diff --git a/src/io/perun.clj b/src/io/perun.clj index a965482d..996117a7 100644 --- a/src/io/perun.clj +++ b/src/io/perun.clj @@ -1285,3 +1285,61 @@ :passthru-fn content-passthru :task-name "inject-scripts" :tracer :io.perun/inject-scripts})))) + +(def ^:private ^:deps manifest-deps + '[[org.clojure/tools.namespace "0.3.0-alpha3"] + [cheshire "5.7.0"]]) + +(def +manifest-defaults+ + {:out-dir "public" + :icon-path "icon.png" + :resolutions #{192 512} + :theme-color "#ffffff" + :display "standalone" + :scope "/"}) + +(deftask manifest* + [o out-dir OUTDIR str "the output directory" + t site-title TITLE str "name for the installable web application" + c theme-color COLOR str "background color theme for icon (default \"#ffffff\")" + d display DISPLAY str "display mode for browser (default \"standalone\")" + s scope SCOPE str "the scope to which the manifest applies (default \"/\")"] + (let [{:keys [site-title] :as opts} (merge +manifest-defaults+ *opts*) + pod (create-pod manifest-deps)] + (letfn [(manifest-path [fileset] + (let [icon-metas (filter-meta-by-ext fileset {:filterer :manifest-icon}) + path (perun/create-filepath out-dir "manifest.json") + global-meta (pm/get-global-meta fileset) + args (merge opts + {:icons icon-metas + :input-paths (into #{} (map :path icon-metas)) + :site-title (or site-title (:site-title global-meta))})] + {path args}))] + (content-task + {:render-form-fn (fn [data] `(io.perun.manifest/manifest ~data)) + :paths-fn manifest-path + :task-name "manifest" + :tracer :io.perun/manifest + :pod pod})))) + +(deftask manifest + "Creates a manifest.json for Android (currently)" + [o out-dir OUTDIR str "the output directory" + i icon-path PATH str "The input icon to be resized (default \"icon.png\"" + r resolutions RESOLUTIONS #{int} "resolutions to which images should be resized (default #{192 512})" + t site-title TITLE str "name for the installable web application" + c theme-color COLOR str "background color theme for icon (default \"#ffffff\")" + d display DISPLAY str "display mode for browser (default \"standalone\")" + s scope SCOPE str "the scope to which the manifest applies (default \"/\")"] + (let [{:keys [out-dir icon-path resolutions site-title theme-color display scope]} + (merge +manifest-defaults+ *opts*)] + (comp (images-resize :out-dir out-dir + :resolutions resolutions + :filterer #(= (:path %) icon-path) + :meta {:manifest-icon true}) + (mime-type :filterer :manifest-icon) + (manifest* :out-dir out-dir + :site-title site-title + :theme-color theme-color + :display display + :scope scope)))) diff --git a/src/io/perun/manifest.clj b/src/io/perun/manifest.clj new file mode 100644 index 00000000..78082710 --- /dev/null +++ b/src/io/perun/manifest.clj @@ -0,0 +1,15 @@ +(ns io.perun.manifest + (:require [cheshire.core :refer [generate-string]])) + +(defn manifest + [{:keys [icons site-title theme-color display scope input-paths] :as data}] + (let [manifest {:name site-title + :icons (for [{:keys [permalink width height mime-type]} icons] + {:src permalink + :sizes (str width "x" height) + :type mime-type}) + :theme_color theme-color + :display display + :scope scope}] + {:rendered (generate-string manifest) + :input-paths input-paths})) diff --git a/test/io/perun_test.clj b/test/io/perun_test.clj index 8d3a34bc..fa5d30e0 100644 --- a/test/io/perun_test.clj +++ b/test/io/perun_test.clj @@ -444,7 +444,17 @@ This --- be _asciidoc_.") (testing "draft" (file-exists? :path (perun/url-to-path "public/test/index.html") :negate? true - :msg "`draft` should remove files")))) + :msg "`draft` should remove files")) + + (add-image :path "icon.png" :type "PNG" :width 10 :height 10) + (p/manifest) + (testing "manifest" + (file-exists? :path (perun/url-to-path "public/manifest.json") + :msg "`manifest` should write manifest.json") + (file-exists? :path (perun/url-to-path "public/icon_192.png") + :msg "`manifest` should write icon resized to 192px") + (file-exists? :path (perun/url-to-path "public/icon_512.png") + :msg "`manifest` should write icon resized to 512px")))) (deftesttask with-arguments-test [] (comp (boot/with-pre-wrap fileset @@ -757,7 +767,21 @@ This --- be _asciidoc_.") (content-check :path "baz.htm" :content (str "") :negate? true - :msg "`inject-scripts` should not alter the contents of a removed file"))))) + :msg "`inject-scripts` should not alter the contents of a removed file"))) + + (add-image :path "an-icon.png" :type "PNG" :width 10 :height 10) + (p/manifest :out-dir "foop" + :icon-path "an-icon.png" + :resolutions #{20} + :site-title "Blarg" + :theme-color "#f0987d" + :display "fullscreen" + :scope "/blarp") + (testing "manifest" + (file-exists? :path (perun/url-to-path "foop/manifest.json") + :msg "`manifest` should write manifest.json") + (file-exists? :path (perun/url-to-path "foop/an-icon_20.png") + :msg "`manifest` should write icon resized to 20px")))) (deftesttask content-tests [] (comp (testing "Collection works without input files" ;; #77