Discover Web App Manifest in HTML
... and return a hash of the JSON data.
This commit is contained in:
1 parent
ee49c0bfaf
commit
193319945a
6 files changed
+132
-15
No files matched your search
@@ -13,8 +13,25 @@ module Manifique
|
||||
end
|
||||
|
||||
def fetch_web_manifest
|
||||
do_get_request @url
|
||||
# binding.pry
|
||||
res = do_get_request @url
|
||||
links = parse_http_link_header(res)
|
||||
doc = Nokogiri::HTML(res.body)
|
||||
manifest_url = discover_web_manifest_url(links, doc)
|
||||
|
||||
unless manifest_url.match(/^https?\:\/\//)
|
||||
# Link is just the manifest path, not an absolute URL
|
||||
manifest_url = @url + manifest_url
|
||||
end
|
||||
|
||||
res = do_get_request manifest_url
|
||||
|
||||
begin
|
||||
manifest_data = JSON.parse(res.body)
|
||||
rescue
|
||||
manifest_data = false
|
||||
end
|
||||
|
||||
manifest_data
|
||||
end
|
||||
|
||||
private
|
||||
@@ -31,5 +48,20 @@ module Manifique
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
def parse_http_link_header(response)
|
||||
link_parser = Nitlink::Parser.new
|
||||
link_parser.parse(response)
|
||||
end
|
||||
|
||||
def discover_web_manifest_url(links, doc)
|
||||
# TODO implement/test link header discovery
|
||||
# if url = links.by_rel('manifest').target.to_s or
|
||||
if url = doc.at_css("link[rel=manifest]").attributes["href"].value
|
||||
return url
|
||||
else
|
||||
raise "No Web App Manifest found on #{@url}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
{"name":"kosmos.social","short_name":"kosmos.social","description":"A friendly place for tooting. Run by the Kosmos peeps.","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"}],"theme_color":"#282c37","background_color":"#191b22","display":"standalone","start_url":"/web/timelines/home","scope":"https://kosmos.social/","share_target":{"url_template":"share?title={title}\u0026text={text}\u0026url={url}"}}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "kosmos.social",
|
||||
"short_name": "kosmos.social",
|
||||
"description": "A friendly place for tooting. Run by the Kosmos peeps.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#282c37",
|
||||
"background_color": "#191b22",
|
||||
"display": "standalone",
|
||||
"start_url": "/web/timelines/home",
|
||||
"scope": "https://kosmos.social/",
|
||||
"share_target": {
|
||||
"url_template": "share?title={title}&text={text}&url={url}"
|
||||
}
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta content='width=device-width, initial-scale=1' name='viewport'>
|
||||
<link href='/favicon.ico' rel='icon' type='image/x-icon'>
|
||||
<link href='/apple-touch-icon.png' rel='apple-touch-icon' sizes='180x180'>
|
||||
<link color='#2B90D9' href='/mask-icon.svg' rel='mask-icon'>
|
||||
<link href='/mastodon-web-app-manifest.json' rel='manifest'>
|
||||
<meta content='/browserconfig.xml' name='msapplication-config'>
|
||||
<meta content='#282c37' name='theme-color'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<title>kosmos.social</title>
|
||||
<link rel="stylesheet" media="all" href="/packs/common-daadaac9454e7d14470e7954e3143dca.css" />
|
||||
<link rel="stylesheet" media="all" href="/packs/default-cb0ecbe6186a2efd4a161ced507eefe6.css" />
|
||||
<script src="/packs/common-1b7201293887a2c2d284.js" crossorigin="anonymous"></script>
|
||||
<script src="/packs/locale_en-c8065c7bb76863454ac6.js" crossorigin="anonymous"></script>
|
||||
<meta name="csrf-param" content="authenticity_token" />
|
||||
<meta name="csrf-token" content="iCGf+8Jx0lYahbQk2Peua3fJirHNds/gauxKcUniH+xw/KRyrdnJc8rQcR2qQKd4BPfCgJJ7W3yYAMA3Lt5q9g==" />
|
||||
<link rel="preload" href="/packs/features/getting_started-1dd5d55a2eb78554be5f.js" as="script" type="text/javascript" crossorigin="anonymous">
|
||||
<link rel="preload" href="/packs/features/compose-87d8eb2c08790e37389f.js" as="script" type="text/javascript" crossorigin="anonymous">
|
||||
<link rel="preload" href="/packs/features/home_timeline-09ae9683dfa755543815.js" as="script" type="text/javascript" crossorigin="anonymous">
|
||||
<link rel="preload" href="/packs/features/notifications-070ca1d5be465b079719.js" as="script" type="text/javascript" crossorigin="anonymous">
|
||||
<meta content='BLWQ_9tiCpcja4_uJs5avHCm6SUlJMbwcybgIPkJjYzfkdiZ88HpJ1mLNJ26j7Aj0XZd87qWrn0exxplpenSTSc=' name='applicationServerKey'>
|
||||
<script id='initial-state' type='application/json'>{"meta":{"streaming_api_base_url":"wss://kosmos.social","access_token":"34e249632c89759445fc6a1dc7153a22a0d693af3c3c7ab51fa53b1cfe1fd3a7","locale":"en","domain":"kosmos.social","admin":"8","search_enabled":false,"invites_enabled":false,"me":"2","unfollow_modal":false,"boost_modal":false,"delete_modal":true,"auto_play_gif":false,"display_sensitive_media":false,"reduce_motion":false},"compose":{"me":"2","default_privacy":"public","default_sensitive":false},"accounts":{"2":{"id":"2","username":"raucao","acct":"raucao","display_name":"Râu Cao","locked":false,"bot":false,"created_at":"2017-04-06T18:16:03.212Z","note":"\u003cp\u003eMaking web apps awesome with 5apps. Redecentralizing the Web with \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://kosmos.social/@remotestorage\" class=\"u-url mention\"\u003e@\u003cspan\u003eremotestorage\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e and \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://kosmos.social/@kosmos\" class=\"u-url mention\"\u003e@\u003cspan\u003ekosmos\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e. Evading winters with \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://kosmos.social/@hackerbeach\" class=\"u-url mention\"\u003e@\u003cspan\u003ehackerbeach\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e.\u003c/p\u003e","url":"https://kosmos.social/@raucao","avatar":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/avatars/000/000/002/original/571dbe497dc5399a.png","avatar_static":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/avatars/000/000/002/original/571dbe497dc5399a.png","header":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/headers/000/000/002/original/545dc9b61e7c288b.jpg","header_static":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/headers/000/000/002/original/545dc9b61e7c288b.jpg","followers_count":327,"following_count":306,"statuses_count":2090,"emojis":[],"fields":[{"name":"Home page","value":"\u003ca href=\"https://sebastian.kip.pe\" rel=\"me nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003esebastian.kip.pe\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"},{"name":"Toot origin","value":"\u003ca href=\"https://updates.kip.pe\" rel=\"me nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003eupdates.kip.pe\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"}]},"8":{"id":"8","username":"kosmos","acct":"kosmos","display_name":"Kosmos Team","locked":false,"bot":false,"created_at":"2017-04-06T19:45:13.620Z","note":"\u003cp\u003eThe people behind \u003ca href=\"https://kosmos.org\" rel=\"nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003ekosmos.org\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e and \u003ca href=\"https://kosmos.social\" rel=\"nofollow noopener\" target=\"_blank\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003ekosmos.social\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e","url":"https://kosmos.social/@kosmos","avatar":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/avatars/000/000/008/original/1ba9744718783391.png","avatar_static":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/avatars/000/000/008/original/1ba9744718783391.png","header":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/headers/000/000/008/original/cca12d52b4c66532.jpg","header_static":"https://s3-eu-west-1.amazonaws.com/kosmos-social/accounts/headers/000/000/008/original/cca12d52b4c66532.jpg","followers_count":59,"following_count":9,"statuses_count":54,"emojis":[],"fields":[]}},"media_attachments":{"accept_content_types":[".jpg",".jpeg",".png",".gif",".webm",".mp4",".m4v","image/jpeg","image/png","image/gif","video/webm","video/mp4"]},"settings":{"frequentlyUsedEmojis":{"blush":1,"confused":1,"the_horns":1,"beers":1,"grinning":1,"heart":2,"zap":1,"point_up":1,"thinking_face":8,"upside_down_face":1,"fearful":1,"point_right":1,"wink":4,"yum":1,"grimacing":1,"ok_hand":2,"smiling_imp":1,"airplane":1,"face_with_rolling_eyes":9,"rocket":3,"money_mouth_face":1,"joy":2,"clap":1,"wave":1,"pray":2,"computer":1,"sweat_smile":2,"sunglasses":2,"clown_face":2},"onboarded":true,"notifications":{"alerts":{"follow":true,"favourite":true,"reblog":true,"mention":true},"shows":{"follow":true,"favourite":true,"reblog":true,"mention":true},"sounds":{"follow":true,"favourite":true,"reblog":true,"mention":true}},"public":{"regex":{"body":""}},"direct":{"regex":{"body":""}},"community":{"regex":{"body":"@twitter.com"}},"skinTone":1,"trends":{"show":true},"columns":[{"id":"COMPOSE","uuid":"9092b61a-015e-49b8-a511Line truncated
|
||||
<script src="/packs/application-485a7a7977f02013f2fa.js" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body class='app-body no-reduce-motion'>
|
||||
<div class='app-holder' data-props='{"locale":"en"}' id='mastodon'>
|
||||
<noscript>
|
||||
<img alt="Mastodon" src="/packs/logo-fe5141d38a25f50068b4c69b77ca1ec8.svg" />
|
||||
<div>
|
||||
To use the Mastodon web application, please enable JavaScript. Alternatively, try one of the <a href="https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md">native apps</a> for Mastodon for your platform.
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,8 +5,8 @@ RSpec.describe Manifique::Agent do
|
||||
describe "URL validation" do
|
||||
context "with invalid URL" do
|
||||
it "raises an exception" do
|
||||
expect { Manifique::Agent.new }.to raise_error
|
||||
expect { Manifique::Agent.new(url: "htp://example.com") }.to raise_error
|
||||
expect { Manifique::Agent.new }.to raise_error(RuntimeError)
|
||||
expect { Manifique::Agent.new(url: "htp://example.com") }.to raise_error(RuntimeError)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,18 +2,18 @@ require "spec_helper"
|
||||
require "manifique/web_client"
|
||||
|
||||
RSpec.describe Manifique::WebClient do
|
||||
before do
|
||||
stub_request(:get, "http://example.com/200_empty").
|
||||
to_return(body: "", status: 200, headers: {})
|
||||
|
||||
stub_request(:get, "http://example.com/404").
|
||||
to_return(body: "", status: 404, headers: {})
|
||||
|
||||
stub_request(:get, "http://example.com/500").
|
||||
to_return(body: "", status: 500, headers: {})
|
||||
end
|
||||
|
||||
describe "#do_get_request" do
|
||||
before do
|
||||
stub_request(:get, "http://example.com/404").
|
||||
to_return(body: "", status: 404, headers: {})
|
||||
|
||||
stub_request(:get, "http://example.com/500").
|
||||
to_return(body: "", status: 500, headers: {})
|
||||
|
||||
stub_request(:get, "http://example.com/200_empty").
|
||||
to_return(body: "", status: 200, headers: {})
|
||||
end
|
||||
|
||||
context "unsuccessful requests" do
|
||||
describe "404" do
|
||||
let(:client) { Manifique::WebClient.new }
|
||||
@@ -48,4 +48,30 @@ RSpec.describe Manifique::WebClient do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#fetch_web_manifest" do
|
||||
context "link[rel=manifest] present" do
|
||||
before do
|
||||
index_html = File.read(File.join(__dir__, "..", "fixtures", "mastodon.html"));
|
||||
stub_request(:get, "https://kosmos.social/").
|
||||
to_return(body: index_html, status: 200, headers: {
|
||||
"Content-Type": "text/html; charset=utf-8"
|
||||
})
|
||||
manifest = File.read(File.join(__dir__, "..", "fixtures", "mastodon-web-app-manifest.json"));
|
||||
stub_request(:get, "https://kosmos.social/mastodon-web-app-manifest.json").
|
||||
to_return(body: manifest, status: 200, headers: {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
})
|
||||
end
|
||||
|
||||
let(:agent) { Manifique::WebClient.new(url: "https://kosmos.social") }
|
||||
|
||||
subject { agent.fetch_web_manifest }
|
||||
|
||||
it "fetches and returns the manifest" do
|
||||
expect(subject).to be_kind_of(Hash)
|
||||
expect(subject["name"]).to eq("kosmos.social")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user