diff --git a/resources/config.edn b/resources/config.edn index 7c462b3..87d1361 100644 --- a/resources/config.edn +++ b/resources/config.edn @@ -32,22 +32,12 @@ :default-locale "en-GB" ;; default language used for messages :formatters ;; formatters for processing markdown ;; extensions. - {:vega {:formatter "smeagol.extensions.vega/process-vega" - :scripts {:core {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega/5.9.1/vega.min.js"} - :lite {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.1.1/vega-lite.min.js"} - :embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"} - :styles {}}} - :vis {:formatter "smeagol.extensions.vega/process-vega" - :scripts {:core {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega/5.9.1/vega.min.js"} - :lite {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.1.1/vega-lite.min.js"} - :embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"} - :styles {}}} + {:backticks {:formatter "smeagol.formatting/process-backticks" + :scripts {} + :styles {}} :mermaid {:formatter "smeagol.extensions.mermaid/process-mermaid" :scripts {:core {:local "vendor/mermaid/dist/mermaid.js"}} :styles {}} - :backticks {:formatter "smeagol.formatting/process-backticks" - :scripts {} - :styles {}} :pswp {:formatter "smeagol.extensions.photoswipe/process-photoswipe" :scripts {:core {:local "/vendor/node_modules/photoswipe/dist/photoswipe.min.js" :remote "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"} @@ -55,6 +45,17 @@ :remote "https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"}} :styles {:core {:local "/vendor/node_modules/photoswipe/dist/photoswipe.css" :remote "/vendor/node_modules/photoswipe/dist/default-skin/default-skin.css"}}} + :test {:formatter "smeagol.extensions.test/process-test" } + :vega {:formatter "smeagol.extensions.vega/process-vega" + :scripts {:core {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega/5.9.1/vega.min.js"} + :lite {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.1.1/vega-lite.min.js"} + :embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"} + :styles {}}} + :vis {:formatter "smeagol.extensions.vega/process-vega" + :scripts {:core {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega/5.9.1/vega.min.js"} + :lite {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.1.1/vega-lite.min.js"} + :embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"} + :styles {}}} } :log-level :info ;; the minimum logging level; one of ;; :trace :debug :info :warn :error :fatal diff --git a/src/smeagol/extensions/photoswipe.clj b/src/smeagol/extensions/photoswipe.clj index ee80792..7b16a09 100644 --- a/src/smeagol/extensions/photoswipe.clj +++ b/src/smeagol/extensions/photoswipe.clj @@ -176,12 +176,8 @@ (defn process-photoswipe [^String url-or-pswp-spec ^Integer index] (let [data (resource-url-or-data->data url-or-pswp-spec) - spec (cs/trim (:data data)) - result + spec (cs/trim (:data data))] (if (cs/starts-with? spec "![") (process-simple-photoswipe spec index) - (process-full-photoswipe spec index))] -;; (log/info "process-photoswipe returning `" result "`.") - result - )) + (process-full-photoswipe spec index)))) diff --git a/src/smeagol/extensions/test.clj b/src/smeagol/extensions/test.clj new file mode 100644 index 0000000..ffe5c1a --- /dev/null +++ b/src/smeagol/extensions/test.clj @@ -0,0 +1,10 @@ +(ns ^{:doc "Very simple extension for testing the extension processing flow." + :author "Simon Brooke"} + smeagol.extensions.test) + + +(def process-test-return-value "") + +(defn process-test + [^String fragment ^Integer index] + process-test-return-value) diff --git a/src/smeagol/extensions/vega.clj b/src/smeagol/extensions/vega.clj index 1b9e2de..49edea0 100644 --- a/src/smeagol/extensions/vega.clj +++ b/src/smeagol/extensions/vega.clj @@ -1,4 +1,4 @@ -(ns ^{:doc "Format Semagol's extended markdown format." +(ns ^{:doc "Format vega/vis extensions to Semagol's extended markdown format." :author "Simon Brooke"} smeagol.extensions.vega (:require [clojure.data.json :as json] diff --git a/src/smeagol/formatting.clj b/src/smeagol/formatting.clj index 3bb0d63..bbcaaa7 100644 --- a/src/smeagol/formatting.clj +++ b/src/smeagol/formatting.clj @@ -93,10 +93,20 @@ fragments (cons fragment processed))) +(defn deep-merge [v & vs] + "Cripped in its entirety from https://clojuredocs.org/clojure.core/merge." + (letfn [(rec-merge [v1 v2] + (if (and (map? v1) (map? v2)) + (merge-with deep-merge v1 v2) + v2))] + (if (some identity vs) + (reduce #(rec-merge %1 %2) v vs) + (last vs)))) + (defn apply-formatter "Within the context of `process-text`, process a fragment for which an explicit - §formatter has been identified. + `formatter` has been identified. As with `process-text`, this function returns a map with two top-level keys: `:inclusions`, a map of constructed keywords to inclusion specifications, @@ -104,16 +114,28 @@ corresponding inclusion should be inserted." [index result fragments processed fragment token formatter] (let - [kw (keyword (str "inclusion-" index))] - (assoc-in - (process-text - (inc index) + [ident (keyword (str "inclusion-" index))] + (process-text + (inc index) + (deep-merge result - (rest fragments) - (cons kw processed)) - [:inclusions kw] - (apply formatter (list (subs fragment (count token)) index))))) - + {:inclusions {ident (apply formatter (list (subs fragment (count token)) index))} + :extensions (cons (keyword token) (:extensions result))}) + fragments + (cons ident processed)))) + +(apply-formatter + 3 + {:inclusions {}} + '() + '() + "pswp + ![Frost on a gate, Laurieston](content/uploads/g1.jpg) + ![Feathered crystals on snow surface, Taliesin](content/uploads/g2.jpg) + ![Feathered snow on log, Taliesin](content/uploads/g3.jpg) + ![Crystaline growth on seed head, Taliesin](content/uploads/g4.jpg)" + "pswp" + smeagol.extensions.photoswipe/process-photoswipe) (defn process-text "Process this `text`, assumed to be markdown potentially containing both local links @@ -124,7 +146,7 @@ inclusion specifications, and `:text`, an HTML text string with the keywords present where the corresponding inclusion should be inserted." ([^String text] - (process-text 0 {:inclusions {}} (cs/split (or text "") #"```") '())) + (process-text 0 {} (cs/split (or text "") #"```") '())) ([index result fragments processed] (let [fragment (first fragments) ;; if I didn't find a formatter for a back-tick marked fragment, @@ -154,24 +176,28 @@ formatter ;; We've found a formatter to apply to the current fragment, and recurse ;; on down the list - (let [result (apply-formatter - index - result - fragments - processed - fragment - first-token - formatter)] - ;; TODO: consistency: either these things are `extensions`, or - ;; they're `formatters`. I incline to the view that they're - ;; `:extensions` - (assoc-in result [:extensions kw] (-> config :formatters kw))) + (let + [ident (keyword (str "inclusion-" index))] + (deep-merge + (process-text + (inc index) + result + (rest fragments) + (cons ident processed)) + {:inclusions {ident (apply formatter (list (subs fragment (count first-token)) index))} + :extensions (cons kw (:extensions result))})) :else ;; Otherwise process the current fragment as markdown and recurse on ;; down the list (process-markdown-fragment index result remarked (rest fragments) processed))))) +(process-text + "pswp + ![Frost on a gate, Laurieston](content/uploads/g1.jpg) + ![Feathered crystals on snow surface, Taliesin](content/uploads/g2.jpg) + ![Feathered snow on log, Taliesin](content/uploads/g3.jpg) + ![Crystaline growth on seed head, Taliesin](content/uploads/g4.jpg)" ) (defn reintegrate-inclusions "Given a map of the form produced by `process-text`, return a string of HTML text diff --git a/src/smeagol/util.clj b/src/smeagol/util.clj index 972a0a7..9e0a6ba 100644 --- a/src/smeagol/util.clj +++ b/src/smeagol/util.clj @@ -61,33 +61,31 @@ :version (System/getProperty "smeagol.version")})) -(defn- raw-get-messages +(def get-messages "Return the most acceptable messages collection we have given the `Accept-Language` header in this `request`." - [request] - (let [specifier ((:headers request) "accept-language") - messages (try - (i18n/get-messages specifier "i18n" "en-GB") - (catch Exception any - (log/error - any - (str - "Failed to parse accept-language header '" - specifier - "'")) - {}))] + (memoize + (fn [request] + (let [specifier ((:headers request) "accept-language") + messages (try + (i18n/get-messages specifier "i18n" "en-GB") + (catch Exception any + (log/error + any + (str + "Failed to parse accept-language header '" + specifier + "'")) + {}))] (merge messages - config))) - - -(def get-messages (memoize raw-get-messages)) + config))))) (defn get-message "Return the message with this `message-key` from this `request`. - if not found, return this `default`, if provided; else return the - `message-key`." + if not found, return this `default`, if provided; else return the + `message-key`." ([message-key request] (get-message message-key message-key request)) ([message-key default request] diff --git a/test/smeagol/test/formatting.clj b/test/smeagol/test/formatting.clj index 2887047..9cb4956 100644 --- a/test/smeagol/test/formatting.clj +++ b/test/smeagol/test/formatting.clj @@ -1,6 +1,7 @@ (ns smeagol.test.formatting (:require [clojure.test :refer :all] - [smeagol.formatting :refer [local-links no-text-error]])) + [smeagol.formatting :refer [local-links no-text-error]] + [smeagol.extensions.test :refer :all])) (deftest test-local-links (testing "Rewriting of local links" @@ -10,3 +11,10 @@ (let [text (str "# This is a heading" "[This is a foreign link](http://to.somewhere)")] (is (= (local-links text) text) "Foreign links should be unchanged")))) + +(deftest test-process-text + (testing "The process-text flow" + (let [expected process-test-return-value + actual (process-text "```test + ```")] + (is (= actual expected)))))