diff --git a/lib/manifique/web_client.rb b/lib/manifique/web_client.rb
index 9e52208..704168b 100644
--- a/lib/manifique/web_client.rb
+++ b/lib/manifique/web_client.rb
@@ -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
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..013026c
--- /dev/null
+++ b/manifest.json
@@ -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}"}}
\ No newline at end of file
diff --git a/spec/fixtures/mastodon-web-app-manifest.json b/spec/fixtures/mastodon-web-app-manifest.json
new file mode 100644
index 0000000..8fa7253
--- /dev/null
+++ b/spec/fixtures/mastodon-web-app-manifest.json
@@ -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}"
+ }
+}
diff --git a/spec/fixtures/mastodon.html b/spec/fixtures/mastodon.html
new file mode 100644
index 0000000..a2e3631
--- /dev/null
+++ b/spec/fixtures/mastodon.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ kosmos.social
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spec/manifique/agent_spec.rb b/spec/manifique/agent_spec.rb
index f217004..a2ec219 100644
--- a/spec/manifique/agent_spec.rb
+++ b/spec/manifique/agent_spec.rb
@@ -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
diff --git a/spec/manifique/web_client_spec.rb b/spec/manifique/web_client_spec.rb
index c4487b2..515e0f6 100644
--- a/spec/manifique/web_client_spec.rb
+++ b/spec/manifique/web_client_spec.rb
@@ -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