mirror of
https://github.com/journeyman-cc/smeagol.git
synced 2026-04-12 18:05:06 +00:00
Still no actual progress.
This commit is contained in:
parent
8032ad60af
commit
37d850d30a
7 changed files with 102 additions and 63 deletions
|
|
@ -32,7 +32,21 @@
|
||||||
:default-locale "en-GB" ;; default language used for messages
|
:default-locale "en-GB" ;; default language used for messages
|
||||||
:formatters ;; formatters for processing markdown
|
:formatters ;; formatters for processing markdown
|
||||||
;; extensions.
|
;; extensions.
|
||||||
{:vega {:formatter "smeagol.extensions.vega/process-vega"
|
{:backticks {:formatter "smeagol.formatting/process-backticks"
|
||||||
|
:scripts {}
|
||||||
|
:styles {}}
|
||||||
|
:mermaid {:formatter "smeagol.extensions.mermaid/process-mermaid"
|
||||||
|
:scripts {:core {:local "vendor/mermaid/dist/mermaid.js"}}
|
||||||
|
: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"}
|
||||||
|
:ui {:local "/vendor/node_modules/photoswipe/dist/photoswipe-ui-default.min.js"
|
||||||
|
: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"}
|
: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"}
|
: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"}
|
:embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"}
|
||||||
|
|
@ -42,19 +56,6 @@
|
||||||
:lite {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.1.1/vega-lite.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"}
|
:embed {:remote "https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.2.2/vega-embed.min.js"}
|
||||||
:styles {}}}
|
: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"}
|
|
||||||
:ui {:local "/vendor/node_modules/photoswipe/dist/photoswipe-ui-default.min.js"
|
|
||||||
: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"}}}
|
|
||||||
}
|
}
|
||||||
:log-level :info ;; the minimum logging level; one of
|
:log-level :info ;; the minimum logging level; one of
|
||||||
;; :trace :debug :info :warn :error :fatal
|
;; :trace :debug :info :warn :error :fatal
|
||||||
|
|
|
||||||
|
|
@ -176,12 +176,8 @@
|
||||||
(defn process-photoswipe
|
(defn process-photoswipe
|
||||||
[^String url-or-pswp-spec ^Integer index]
|
[^String url-or-pswp-spec ^Integer index]
|
||||||
(let [data (resource-url-or-data->data url-or-pswp-spec)
|
(let [data (resource-url-or-data->data url-or-pswp-spec)
|
||||||
spec (cs/trim (:data data))
|
spec (cs/trim (:data data))]
|
||||||
result
|
|
||||||
(if
|
(if
|
||||||
(cs/starts-with? spec "![")
|
(cs/starts-with? spec "![")
|
||||||
(process-simple-photoswipe spec index)
|
(process-simple-photoswipe spec index)
|
||||||
(process-full-photoswipe spec index))]
|
(process-full-photoswipe spec index))))
|
||||||
;; (log/info "process-photoswipe returning `" result "`.")
|
|
||||||
result
|
|
||||||
))
|
|
||||||
|
|
|
||||||
10
src/smeagol/extensions/test.clj
Normal file
10
src/smeagol/extensions/test.clj
Normal file
|
|
@ -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 "<!-- The test extension has run and this is its output -->")
|
||||||
|
|
||||||
|
(defn process-test
|
||||||
|
[^String fragment ^Integer index]
|
||||||
|
process-test-return-value)
|
||||||
|
|
@ -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"}
|
:author "Simon Brooke"}
|
||||||
smeagol.extensions.vega
|
smeagol.extensions.vega
|
||||||
(:require [clojure.data.json :as json]
|
(:require [clojure.data.json :as json]
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,20 @@
|
||||||
fragments
|
fragments
|
||||||
(cons fragment processed)))
|
(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
|
(defn apply-formatter
|
||||||
"Within the context of `process-text`, process a fragment for which an explicit
|
"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:
|
As with `process-text`, this function returns a map with two top-level keys:
|
||||||
`:inclusions`, a map of constructed keywords to inclusion specifications,
|
`:inclusions`, a map of constructed keywords to inclusion specifications,
|
||||||
|
|
@ -104,16 +114,28 @@
|
||||||
corresponding inclusion should be inserted."
|
corresponding inclusion should be inserted."
|
||||||
[index result fragments processed fragment token formatter]
|
[index result fragments processed fragment token formatter]
|
||||||
(let
|
(let
|
||||||
[kw (keyword (str "inclusion-" index))]
|
[ident (keyword (str "inclusion-" index))]
|
||||||
(assoc-in
|
(process-text
|
||||||
(process-text
|
(inc index)
|
||||||
(inc index)
|
(deep-merge
|
||||||
result
|
result
|
||||||
(rest fragments)
|
{:inclusions {ident (apply formatter (list (subs fragment (count token)) index))}
|
||||||
(cons kw processed))
|
:extensions (cons (keyword token) (:extensions result))})
|
||||||
[:inclusions kw]
|
fragments
|
||||||
(apply formatter (list (subs fragment (count token)) index)))))
|
(cons ident processed))))
|
||||||
|
|
||||||
|
(apply-formatter
|
||||||
|
3
|
||||||
|
{:inclusions {}}
|
||||||
|
'()
|
||||||
|
'()
|
||||||
|
"pswp
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
"
|
||||||
|
"pswp"
|
||||||
|
smeagol.extensions.photoswipe/process-photoswipe)
|
||||||
|
|
||||||
(defn process-text
|
(defn process-text
|
||||||
"Process this `text`, assumed to be markdown potentially containing both local links
|
"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
|
inclusion specifications, and `:text`, an HTML text string with the keywords
|
||||||
present where the corresponding inclusion should be inserted."
|
present where the corresponding inclusion should be inserted."
|
||||||
([^String text]
|
([^String text]
|
||||||
(process-text 0 {:inclusions {}} (cs/split (or text "") #"```") '()))
|
(process-text 0 {} (cs/split (or text "") #"```") '()))
|
||||||
([index result fragments processed]
|
([index result fragments processed]
|
||||||
(let [fragment (first fragments)
|
(let [fragment (first fragments)
|
||||||
;; if I didn't find a formatter for a back-tick marked fragment,
|
;; if I didn't find a formatter for a back-tick marked fragment,
|
||||||
|
|
@ -154,24 +176,28 @@
|
||||||
formatter
|
formatter
|
||||||
;; We've found a formatter to apply to the current fragment, and recurse
|
;; We've found a formatter to apply to the current fragment, and recurse
|
||||||
;; on down the list
|
;; on down the list
|
||||||
(let [result (apply-formatter
|
(let
|
||||||
index
|
[ident (keyword (str "inclusion-" index))]
|
||||||
result
|
(deep-merge
|
||||||
fragments
|
(process-text
|
||||||
processed
|
(inc index)
|
||||||
fragment
|
result
|
||||||
first-token
|
(rest fragments)
|
||||||
formatter)]
|
(cons ident processed))
|
||||||
;; TODO: consistency: either these things are `extensions`, or
|
{:inclusions {ident (apply formatter (list (subs fragment (count first-token)) index))}
|
||||||
;; they're `formatters`. I incline to the view that they're
|
:extensions (cons kw (:extensions result))}))
|
||||||
;; `:extensions`
|
|
||||||
(assoc-in result [:extensions kw] (-> config :formatters kw)))
|
|
||||||
:else
|
:else
|
||||||
;; Otherwise process the current fragment as markdown and recurse on
|
;; Otherwise process the current fragment as markdown and recurse on
|
||||||
;; down the list
|
;; down the list
|
||||||
(process-markdown-fragment
|
(process-markdown-fragment
|
||||||
index result remarked (rest fragments) processed)))))
|
index result remarked (rest fragments) processed)))))
|
||||||
|
|
||||||
|
(process-text
|
||||||
|
"pswp
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
" )
|
||||||
|
|
||||||
(defn reintegrate-inclusions
|
(defn reintegrate-inclusions
|
||||||
"Given a map of the form produced by `process-text`, return a string of HTML text
|
"Given a map of the form produced by `process-text`, return a string of HTML text
|
||||||
|
|
|
||||||
|
|
@ -61,33 +61,31 @@
|
||||||
:version (System/getProperty "smeagol.version")}))
|
:version (System/getProperty "smeagol.version")}))
|
||||||
|
|
||||||
|
|
||||||
(defn- raw-get-messages
|
(def get-messages
|
||||||
"Return the most acceptable messages collection we have given the
|
"Return the most acceptable messages collection we have given the
|
||||||
`Accept-Language` header in this `request`."
|
`Accept-Language` header in this `request`."
|
||||||
[request]
|
(memoize
|
||||||
(let [specifier ((:headers request) "accept-language")
|
(fn [request]
|
||||||
messages (try
|
(let [specifier ((:headers request) "accept-language")
|
||||||
(i18n/get-messages specifier "i18n" "en-GB")
|
messages (try
|
||||||
(catch Exception any
|
(i18n/get-messages specifier "i18n" "en-GB")
|
||||||
(log/error
|
(catch Exception any
|
||||||
any
|
(log/error
|
||||||
(str
|
any
|
||||||
"Failed to parse accept-language header '"
|
(str
|
||||||
specifier
|
"Failed to parse accept-language header '"
|
||||||
"'"))
|
specifier
|
||||||
{}))]
|
"'"))
|
||||||
|
{}))]
|
||||||
(merge
|
(merge
|
||||||
messages
|
messages
|
||||||
config)))
|
config)))))
|
||||||
|
|
||||||
|
|
||||||
(def get-messages (memoize raw-get-messages))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-message
|
(defn get-message
|
||||||
"Return the message with this `message-key` from this `request`.
|
"Return the message with this `message-key` from this `request`.
|
||||||
if not found, return this `default`, if provided; else return the
|
if not found, return this `default`, if provided; else return the
|
||||||
`message-key`."
|
`message-key`."
|
||||||
([message-key request]
|
([message-key request]
|
||||||
(get-message message-key message-key request))
|
(get-message message-key message-key request))
|
||||||
([message-key default request]
|
([message-key default request]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
(ns smeagol.test.formatting
|
(ns smeagol.test.formatting
|
||||||
(:require [clojure.test :refer :all]
|
(: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
|
(deftest test-local-links
|
||||||
(testing "Rewriting of local links"
|
(testing "Rewriting of local links"
|
||||||
|
|
@ -10,3 +11,10 @@
|
||||||
(let [text (str "# This is a heading"
|
(let [text (str "# This is a heading"
|
||||||
"[This is a foreign link](http://to.somewhere)")]
|
"[This is a foreign link](http://to.somewhere)")]
|
||||||
(is (= (local-links text) text) "Foreign links should be unchanged"))))
|
(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)))))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue