From 6a435a9f35b8c7254bd7137416789efc35237316 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 12:42:38 +0100 Subject: [PATCH 01/39] Preparatory work --- notebooks/described_markdown.clj | 54 ++++++++++++++++++++++++++++++++ resources/viewer-js-hash | 2 +- src/nextjournal/clerk.clj | 3 +- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 notebooks/described_markdown.clj diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj new file mode 100644 index 000000000..473153b99 --- /dev/null +++ b/notebooks/described_markdown.clj @@ -0,0 +1,54 @@ +;; # ✍️ Described Markdown +^{:nextjournal.clerk/visibility #{:hide-ns}} +(ns ^:nextjournal.clerk/no-cache described-markdown + (:require [nextjournal.clerk :as clerk] + [nextjournal.clerk.viewer :as v] + [nextjournal.markdown :as md] + [nextjournal.markdown.transform :as md.transform])) + +;; This notebook contains preparatory work to make markdown node customizable in clerk. + +;; Due to the recursive nature of [[v/describe]] it is sufficien to wrap a node at a time: + +(defn with-md-viewer [{:as node :keys [type]}] + (v/wrap-value node (keyword "nextjournal.markdown" (name type)))) + +;; We define a generic `fetch-fn` to drill down into the markdown structure. At each depth this produces the desired hiccup representation of the node and delegates to describe the representation of the children nodes: + +(defn into-markup [mkup] + (fn [opts {:keys [text content]}] + (v/fetch-all opts (into mkup (if text [text] (map with-md-viewer content)))))) + +^{::clerk/viewer :hide-result} +(def md-viewers + [{:name :nextjournal.markdown/doc + :fetch-fn (into-markup [:div.viewer-markdown]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/heading + :fetch-fn (into-markup [:h1.foo]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/paragraph + :fetch-fn (into-markup [:p]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/em + :fetch-fn (into-markup [:em]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/strong + :fetch-fn (into-markup [:strong]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/text + :fetch-fn (into-markup [:span.text]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/formula + :fetch-fn #(:text %2) + :render-fn 'v/katex-viewer}]) + +^{::clerk/viewers md-viewers} +(with-md-viewer (md/parse "# Hello +This is _really_ a **strong** formula $\\alpha$.")) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 5a5282208..47f8b3344 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -2aUVWVg14s2z881jVtfSLfQ8XHW7 \ No newline at end of file +3XP2esKpbmLTaAjvjqGV4UQuHNhr \ No newline at end of file diff --git a/src/nextjournal/clerk.clj b/src/nextjournal/clerk.clj index c6027426a..f68eed046 100644 --- a/src/nextjournal/clerk.clj +++ b/src/nextjournal/clerk.clj @@ -360,7 +360,8 @@ (def clerk-docs (into ["notebooks/markdown.md" - "notebooks/onwards.md"] + "notebooks/onwards.md" + "notebooks/described_markdown.clj"] (map #(str "notebooks/" % ".clj")) ["hello" "how_clerk_works" From 70c63057c5f3478157882cef11a6c53b50a1b5e9 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 13:05:31 +0100 Subject: [PATCH 02/39] clearer separation of concerns between fetch-fn and transform-fn --- notebooks/described_markdown.clj | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index 473153b99..b64fa0b2d 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -13,36 +13,43 @@ (defn with-md-viewer [{:as node :keys [type]}] (v/wrap-value node (keyword "nextjournal.markdown" (name type)))) -;; We define a generic `fetch-fn` to drill down into the markdown structure. At each depth this produces the desired hiccup representation of the node and delegates to describe the representation of the children nodes: +;; We define a generic `transform-fn` with 2 purposes: +;; * produces the desired hiccup representation at each node and +;; * delegates to describe the representation of the child nodes: (defn into-markup [mkup] - (fn [opts {:keys [text content]}] - (v/fetch-all opts (into mkup (if text [text] (map with-md-viewer content)))))) + (fn [{:keys [text content]}] (into mkup (if text [text] (map with-md-viewer content))))) ^{::clerk/viewer :hide-result} (def md-viewers [{:name :nextjournal.markdown/doc - :fetch-fn (into-markup [:div.viewer-markdown]) + :transform-fn (into-markup [:div.viewer-markdown]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/heading - :fetch-fn (into-markup [:h1.foo]) + :transform-fn (into-markup [:h1.foo]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/paragraph - :fetch-fn (into-markup [:p]) + :transform-fn (into-markup [:p]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/em - :fetch-fn (into-markup [:em]) + :transform-fn (into-markup [:em]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/strong - :fetch-fn (into-markup [:strong]) + :transform-fn (into-markup [:strong]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/text - :fetch-fn (into-markup [:span.text]) + :transform-fn (into-markup [:span.text]) + :fetch-fn v/fetch-all :render-fn 'v/html} {:name :nextjournal.markdown/formula @@ -51,4 +58,4 @@ ^{::clerk/viewers md-viewers} (with-md-viewer (md/parse "# Hello -This is _really_ a **strong** formula $\\alpha$.")) +This is not _really_ a **strong** formula $\\alpha$.")) From 2e34b9b6cbe8c70ddab4260abf6fb0b87b63c9a2 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 14:48:26 +0100 Subject: [PATCH 03/39] Make `into-markup` a fn of node --- notebooks/described_markdown.clj | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index b64fa0b2d..6a083147c 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -18,7 +18,9 @@ ;; * delegates to describe the representation of the child nodes: (defn into-markup [mkup] - (fn [{:keys [text content]}] (into mkup (if text [text] (map with-md-viewer content))))) + (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] + (fn [{:as node :keys [text content]}] + (into (mkup-fn node) (if text [text] (map with-md-viewer content)))))) ^{::clerk/viewer :hide-result} (def md-viewers @@ -28,7 +30,7 @@ :render-fn 'v/html} {:name :nextjournal.markdown/heading - :transform-fn (into-markup [:h1.foo]) + :transform-fn (into-markup #(vector (str "h" (:heading-level %)))) :fetch-fn v/fetch-all :render-fn 'v/html} @@ -58,4 +60,7 @@ ^{::clerk/viewers md-viewers} (with-md-viewer (md/parse "# Hello + +## Section 2 + This is not _really_ a **strong** formula $\\alpha$.")) From ba985e42aecab4ae617633bfeadae222ede0c13c Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 16:40:14 +0100 Subject: [PATCH 04/39] Sketch of inline eval --- notebooks/described_markdown.clj | 42 +++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index 6a083147c..e60a3c017 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -4,8 +4,16 @@ (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v] [nextjournal.markdown :as md] + [nextjournal.markdown.parser :as md.parser] [nextjournal.markdown.transform :as md.transform])) +^{::clerk/viewer :hide-result} +(defn parse [text] + (md.parser/parse (update md.parser/empty-doc :text-tokenizers conj + {:regexp #"\{\{([^{]+)\}\}" + :handler (fn [m] {:type :inline :text (m 1)})}) + (md/tokenize text))) + ;; This notebook contains preparatory work to make markdown node customizable in clerk. ;; Due to the recursive nature of [[v/describe]] it is sufficien to wrap a node at a time: @@ -22,6 +30,8 @@ (fn [{:as node :keys [text content]}] (into (mkup-fn node) (if text [text] (map with-md-viewer content)))))) +(defn red [text] (v/html [:span {:style {:color "#ef4444"}} text])) + ^{::clerk/viewer :hide-result} (def md-viewers [{:name :nextjournal.markdown/doc @@ -49,18 +59,42 @@ :fetch-fn v/fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/internal-link + :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) + :fetch-fn v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/text + ;; TODO: find a way to drop wrapping [:span] :transform-fn (into-markup [:span.text]) :fetch-fn v/fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/inline + ;; TODO: use clerk/read+eval-cached + :transform-fn (comp eval read-string :text) + :fetch-fn v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/formula :fetch-fn #(:text %2) :render-fn 'v/katex-viewer}]) -^{::clerk/viewers md-viewers} -(with-md-viewer (md/parse "# Hello +(def text "# Hello + +This is not _really_ a **strong** formula $\\alpha$. -## Section 2 +## Section 3 + +with inline wiki [[link]] and inline eval {{ (red \"ahoi\") }} +") + +^{::clerk/viewers md-viewers} +(with-md-viewer (parse text)) -This is not _really_ a **strong** formula $\\alpha$.")) +^{::clerk/visibility :hide} +(comment + (v/describe + (v/with-viewers md-viewers + (with-md-viewer (parse text))) + )) From 55ac94fd96348f452bfdb83beedd56203a76df2d Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 17:28:54 +0100 Subject: [PATCH 05/39] Wire things up: markdown notebook case --- notebooks/described_markdown.clj | 7 ++- notebooks/markdown_mini.md | 0 src/nextjournal/clerk/view.clj | 2 +- src/nextjournal/clerk/viewer.cljc | 74 ++++++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 notebooks/markdown_mini.md diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index e60a3c017..741fd026b 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -28,7 +28,7 @@ (defn into-markup [mkup] (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] (fn [{:as node :keys [text content]}] - (into (mkup-fn node) (if text [text] (map with-md-viewer content)))))) + (into (mkup-fn node) (cond text [text] content (map with-md-viewer content)))))) (defn red [text] (v/html [:span {:style {:color "#ef4444"}} text])) @@ -59,6 +59,11 @@ :fetch-fn v/fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/monospace + :transform-fn (into-markup [:code]) + :fetch-fn v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) :fetch-fn v/fetch-all diff --git a/notebooks/markdown_mini.md b/notebooks/markdown_mini.md new file mode 100644 index 000000000..e69de29bb diff --git a/src/nextjournal/clerk/view.clj b/src/nextjournal/clerk/view.clj index 16d6d4ba7..8a48ef62b 100644 --- a/src/nextjournal/clerk/view.clj +++ b/src/nextjournal/clerk/view.clj @@ -152,7 +152,7 @@ (defn describe-block [{:keys [inline-results?] :or {inline-results? false}} {:keys [ns]} {:as cell :keys [type text doc]}] (case type - :markdown [(v/md (or doc text))] + :markdown [(if doc (v/describe (v/with-md-viewer doc)) (v/md text))] :code (let [{:as cell :keys [result]} (update cell :result apply-viewer-unwrapping-var-from-def) {:keys [code? fold? result?]} (->display cell)] (cond-> [] diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 5658104fe..1098c9102 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -243,8 +243,80 @@ {:pred string? :render-fn (quote v/string-viewer) :fetch-opts {:n 100}} {:pred number? :render-fn '(fn [x] (v/html [:span.tabular-nums (if (js/Number.isNaN x) "NaN" (str x))]))}]) +(defn with-md-viewer [{:as node :keys [type]}] + (wrap-value node (keyword "nextjournal.markdown" (name type)))) + +(defn into-markup [mkup] + (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] + (fn [{:as node :keys [text content]}] + (into (mkup-fn node) (cond text [text] content (map with-md-viewer content)))))) + +(def default-markdown-viewers + [{:name :nextjournal.markdown/doc + :transform-fn (into-markup [:div.viewer-markdown]) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/heading + :transform-fn (into-markup #(vector (str "h" (:heading-level %)))) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/paragraph + :transform-fn (into-markup [:p]) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/em + :transform-fn (into-markup [:em]) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/strong + :transform-fn (into-markup [:strong]) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/monospace + :transform-fn (into-markup [:code]) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/internal-link + :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) + :fetch-fn fetch-all + :render-fn 'v/html} + + {:name :nextjournal.markdown/text + ;; TODO: find a way to drop wrapping [:span] + :transform-fn (into-markup [:span.text]) + :fetch-fn fetch-all + :render-fn 'v/html} + + #?(:clj + {:name :nextjournal.markdown/inline + ;; TODO: use clerk/read+eval-cached + :transform-fn (comp eval read-string :text) + :fetch-fn fetch-all + :render-fn 'v/html}) + + {:name :nextjournal.markdown/formula + :fetch-fn #(:text %2) + :render-fn 'v/katex-viewer} + + {:name :nextjournal.markdown/bullet-list + :fetch-fn fetch-all + :transform-fn (into-markup [:ul]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/list-item + :fetch-fn fetch-all + :transform-fn (into-markup [:li]) + :render-fn 'v/html} + ]) + (defn get-all-viewers [] - {:root default-viewers + {:root (concat default-markdown-viewers default-viewers) :table default-table-cell-viewers}) (defonce From 4fa8d392165bf2db70056c0355fd00f53eaac83d Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 18:02:58 +0100 Subject: [PATCH 06/39] Wire things up for clojure notebooks as well --- notebooks/markdown_mini.md | 0 notebooks/viewers/custom_markdown.clj | 23 +++++++++++++++++++++++ src/nextjournal/clerk.clj | 4 ++-- src/nextjournal/clerk/hashing.clj | 10 ++++++---- src/nextjournal/clerk/view.clj | 4 +++- src/nextjournal/clerk/viewer.cljc | 9 ++++++--- 6 files changed, 40 insertions(+), 10 deletions(-) delete mode 100644 notebooks/markdown_mini.md create mode 100644 notebooks/viewers/custom_markdown.clj diff --git a/notebooks/markdown_mini.md b/notebooks/markdown_mini.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj new file mode 100644 index 000000000..f3095ee33 --- /dev/null +++ b/notebooks/viewers/custom_markdown.clj @@ -0,0 +1,23 @@ +;; # 🎭 Custom Markdown Viewers +(ns viewers.custom-markdown + (:require [nextjournal.clerk :as clerk] + [nextjournal.clerk.viewer :as v])) + +;; **FIXME**: still doesn't apply viewers via set-viewers! + +(clerk/set-viewers! [{:name :nextjournal.markdown/text + :fetch-fn v/fetch-all + :transform-fn (v/into-markup [:span {:style {:color "#f87171"}}]) + :render-fn 'v/html} + + {:name :nextjournal.markdown/ruler + :transform-fn (v/into-markup [:hr {:style {:border-color "#fb923c"}}]) + :fetch-fn v/fetch-all + :render-fn 'v/html}]) + +(+ 39 3) + +;; --- + +(comment + (reset! v/!viewers (v/get-all-viewers))) diff --git a/src/nextjournal/clerk.clj b/src/nextjournal/clerk.clj index f68eed046..e93db9ee8 100644 --- a/src/nextjournal/clerk.clj +++ b/src/nextjournal/clerk.clj @@ -360,8 +360,7 @@ (def clerk-docs (into ["notebooks/markdown.md" - "notebooks/onwards.md" - "notebooks/described_markdown.clj"] + "notebooks/onwards.md"] (map #(str "notebooks/" % ".clj")) ["hello" "how_clerk_works" @@ -375,6 +374,7 @@ "viewer_d3_require" "viewers_nested" "viewer_normalization" + "viewers/custom_markdown" "viewers/html" "viewers/image" "viewers/image_layouts" diff --git a/src/nextjournal/clerk/hashing.clj b/src/nextjournal/clerk/hashing.clj index 6eeb45b7a..d589ab1df 100644 --- a/src/nextjournal/clerk/hashing.clj +++ b/src/nextjournal/clerk/hashing.clj @@ -189,16 +189,18 @@ (and doc? (n/comment? node)) (-> state (assoc :nodes (drop-while n/comment? nodes)) - (update :blocks conj {:type :markdown :text (apply str (map (comp remove-leading-semicolons n/string) - (take-while n/comment? nodes)))})) + (update :blocks conj {:type :markdown + :doc (-> (apply str (map (comp remove-leading-semicolons n/string) + (take-while n/comment? nodes))) + markdown/parse + (select-keys [:type :content]))})) :else (update state :nodes rest))) (merge (select-keys state [:blocks :visibility]) (when doc? (-> {:content (into [] (comp (filter (comp #{:markdown} :type)) - (map (comp markdown/parse :text)) - (mapcat :content)) + (mapcat (comp :content :doc))) blocks)} markdown.parser/add-title+toc (select-keys [:title :toc])))))))) diff --git a/src/nextjournal/clerk/view.clj b/src/nextjournal/clerk/view.clj index 8a48ef62b..91cb42968 100644 --- a/src/nextjournal/clerk/view.clj +++ b/src/nextjournal/clerk/view.clj @@ -152,7 +152,9 @@ (defn describe-block [{:keys [inline-results?] :or {inline-results? false}} {:keys [ns]} {:as cell :keys [type text doc]}] (case type - :markdown [(if doc (v/describe (v/with-md-viewer doc)) (v/md text))] + :markdown [(if doc + (-> doc v/with-md-viewer v/describe) + (v/md text))] :code (let [{:as cell :keys [result]} (update cell :result apply-viewer-unwrapping-var-from-def) {:keys [code? fold? result?]} (->display cell)] (cond-> [] diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 1098c9102..1fa20411f 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -267,21 +267,24 @@ :fetch-fn fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/ruler + :transform-fn (into-markup [:hr]) + :fetch-fn fetch-all + :render-fn 'v/html} + + ;; marks {:name :nextjournal.markdown/em :transform-fn (into-markup [:em]) :fetch-fn fetch-all :render-fn 'v/html} - {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong]) :fetch-fn fetch-all :render-fn 'v/html} - {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code]) :fetch-fn fetch-all :render-fn 'v/html} - {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) :fetch-fn fetch-all From 73bea1545b57cad6d03d4dfb625bd030ee6954a4 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 23 Mar 2022 18:37:05 +0100 Subject: [PATCH 07/39] Implement all markdown nodes --- notebooks/viewers/custom_markdown.clj | 2 - src/nextjournal/clerk/viewer.cljc | 105 ++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj index f3095ee33..d0966a466 100644 --- a/notebooks/viewers/custom_markdown.clj +++ b/notebooks/viewers/custom_markdown.clj @@ -3,8 +3,6 @@ (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v])) -;; **FIXME**: still doesn't apply viewers via set-viewers! - (clerk/set-viewers! [{:name :nextjournal.markdown/text :fetch-fn v/fetch-all :transform-fn (v/into-markup [:span {:style {:color "#f87171"}}]) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 1fa20411f..1423066dc 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -6,7 +6,8 @@ [clojure.walk :as w] #?@(:clj [[clojure.repl :refer [demunge]] [nextjournal.clerk.config :as config]] - :cljs [[reagent.ratom :as ratom]])) + :cljs [[reagent.ratom :as ratom]]) + [nextjournal.markdown.transform :as md.transform]) #?(:clj (:import (java.lang Throwable) (java.awt.image BufferedImage) (javax.imageio ImageIO)))) @@ -285,38 +286,128 @@ :transform-fn (into-markup [:code]) :fetch-fn fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/link + :transform-fn (into-markup #(vector :a (:attrs %))) + :fetch-fn fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/strikethrough + :transform-fn (into-markup [:s]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) :fetch-fn fetch-all :render-fn 'v/html} + {:name :nextjournal.markdown/hashtag + :fetch-fn 'v/fetch-all + :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) + :render-fn 'v/html} + ;; inlines {:name :nextjournal.markdown/text ;; TODO: find a way to drop wrapping [:span] :transform-fn (into-markup [:span.text]) :fetch-fn fetch-all :render-fn 'v/html} - #?(:clj {:name :nextjournal.markdown/inline ;; TODO: use clerk/read+eval-cached :transform-fn (comp eval read-string :text) :fetch-fn fetch-all :render-fn 'v/html}) + {:name :nextjournal.markdown/softbreak + :transform-fn (into-markup [:span]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + + ;; blocks + {:name :nextjournal.markdown/code + ;; TODO: fixme + :transform-fn (into-markup #(vector :div.viewer-code.not-prose (with-viewer :code (md.transform/->text %)))) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/image + :transform-fn (into-markup #(vector :img (:attrs %))) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/blockquote + :transform-fn (into-markup [:blockquote]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + ;; formulas {:name :nextjournal.markdown/formula - :fetch-fn #(:text %2) + :transform-fn :text + :fetch-fn fetch-all + :render-fn 'v/katex-viewer} + {:name :nextjournal.markdown/block-formula + :transform-fn :text + :fetch-fn fetch-all :render-fn 'v/katex-viewer} + ;; lists {:name :nextjournal.markdown/bullet-list - :fetch-fn fetch-all :transform-fn (into-markup [:ul]) + :fetch-fn fetch-all :render-fn 'v/html} - - {:name :nextjournal.markdown/list-item + {:name :nextjournal.markdown/numbered-list + :transform-fn (into-markup [:ol]) :fetch-fn fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/todo-list + :transform-fn (into-markup [:ul.contains-task-list]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/list-item :transform-fn (into-markup [:li]) + :fetch-fn fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/todo-item + :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]])) + :fetch-fn fetch-all + :render-fn 'v/html} + + ;; tables + {:name :nextjournal.markdown/table + :transform-fn (into-markup [:table]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/table-head + :transform-fn (into-markup [:thead]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/table-body + :transform-fn (into-markup [:tbody]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/table-row + :transform-fn (into-markup [:tr]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/table-header + :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))})) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + {:name :nextjournal.markdown/table-data + :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))})) + :fetch-fn 'v/fetch-all + :render-fn 'v/html} + + ;; ToC via [[TOC]] placeholder + {:name :nextjournal.markdown/toc + :fetch-fn 'v/fetch-all + :transform-fn #(throw (ex-info "Not Implemented" {})) + :render-fn 'v/html} + + ;; sidenotes + {:name :nextjournal.markdown/sidenote + :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]])) + :fetch-fn 'v/fetch-all :render-fn 'v/html} - ]) + {:name :nextjournal.markdown/sidenote-ref + :transform-fn (into-markup [:sup.sidenote-ref]) + :fetch-fn 'v/fetch-all + :render-fn 'v/html}]) (defn get-all-viewers [] {:root (concat default-markdown-viewers default-viewers) From 53bd5ea7b29c27a81bb989349dd22cf1222c75b1 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 11:18:28 +0100 Subject: [PATCH 08/39] Show inline eval --- notebooks/viewers/custom_markdown.clj | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj index d0966a466..0908e4961 100644 --- a/notebooks/viewers/custom_markdown.clj +++ b/notebooks/viewers/custom_markdown.clj @@ -1,20 +1,35 @@ ;; # 🎭 Custom Markdown Viewers (ns viewers.custom-markdown (:require [nextjournal.clerk :as clerk] - [nextjournal.clerk.viewer :as v])) + [nextjournal.clerk.viewer :as v] + [nextjournal.markdown.transform :as markdown.transform])) + +(defn slider [min max] + (clerk/with-viewer {:fetch-fn v/fetch-all + :render-fn (list 'fn '[_] + (list 'v/html + [:input {:type :range + :min min :max max + :on-change '(fn [x] (js/console.log (.. x -target -value)))}]))} + nil)) + +;; This allows us to define custom inline `(clerk/tex "\\beta")` evaluation like to build inline controls `(slider 0 100)` to interact with. +;; +;; _**FIXME:** inline formulas!!!_ (clerk/set-viewers! [{:name :nextjournal.markdown/text :fetch-fn v/fetch-all :transform-fn (v/into-markup [:span {:style {:color "#f87171"}}]) :render-fn 'v/html} + {:name :nextjournal.markdown/monospace + :transform-fn (comp eval read-string markdown.transform/->text)} + {:name :nextjournal.markdown/ruler :transform-fn (v/into-markup [:hr {:style {:border-color "#fb923c"}}]) :fetch-fn v/fetch-all :render-fn 'v/html}]) -(+ 39 3) - ;; --- (comment From 1d593c2cc0afff9c158b7e9a87fed7ef386ef2a4 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 11:32:40 +0100 Subject: [PATCH 09/39] Test simplification of viewer spec --- notebooks/described_markdown.clj | 48 ++++++++++---------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index 741fd026b..16e565ecd 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -28,62 +28,44 @@ (defn into-markup [mkup] (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] (fn [{:as node :keys [text content]}] - (into (mkup-fn node) (cond text [text] content (map with-md-viewer content)))))) - -(defn red [text] (v/html [:span {:style {:color "#ef4444"}} text])) + (v/html (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) ^{::clerk/viewer :hide-result} (def md-viewers [{:name :nextjournal.markdown/doc - :transform-fn (into-markup [:div.viewer-markdown]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:div.viewer-markdown])} {:name :nextjournal.markdown/heading - :transform-fn (into-markup #(vector (str "h" (:heading-level %)))) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} {:name :nextjournal.markdown/paragraph - :transform-fn (into-markup [:p]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:p])} {:name :nextjournal.markdown/em - :transform-fn (into-markup [:em]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:em])} {:name :nextjournal.markdown/strong - :transform-fn (into-markup [:strong]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:strong])} {:name :nextjournal.markdown/monospace - :transform-fn (into-markup [:code]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:code])} {:name :nextjournal.markdown/internal-link - :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} {:name :nextjournal.markdown/text ;; TODO: find a way to drop wrapping [:span] - :transform-fn (into-markup [:span.text]) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:span.text])} {:name :nextjournal.markdown/inline ;; TODO: use clerk/read+eval-cached - :transform-fn (comp eval read-string :text) - :fetch-fn v/fetch-all - :render-fn 'v/html} + :transform-fn (comp eval read-string :text)} {:name :nextjournal.markdown/formula - :fetch-fn #(:text %2) - :render-fn 'v/katex-viewer}]) + :transform-fn :text + :render-fn 'v/mathjax-viewer}]) + +(defn marine [text] (clerk/html [:span {:style {:font-weight 800 :color "#0284c7"}} (str "⚓️" text)])) (def text "# Hello @@ -91,7 +73,7 @@ This is not _really_ a **strong** formula $\\alpha$. ## Section 3 -with inline wiki [[link]] and inline eval {{ (red \"ahoi\") }} +with inline wiki [[link]] and inline eval {{ (marine \"Ahoi\") }}. ") ^{::clerk/viewers md-viewers} From 44699a909fcee3f323b7dce46c0ad77366229787 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 12:23:01 +0100 Subject: [PATCH 10/39] Compact markdown viewer spec --- notebooks/described_markdown.clj | 6 +- src/nextjournal/clerk/viewer.cljc | 169 +++++++----------------------- 2 files changed, 43 insertions(+), 132 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index 16e565ecd..976e7ae36 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -83,5 +83,7 @@ with inline wiki [[link]] and inline eval {{ (marine \"Ahoi\") }}. (comment (v/describe (v/with-viewers md-viewers - (with-md-viewer (parse text))) - )) + (with-md-viewer (parse text)))) + + (reset! nextjournal.clerk.webserver/!doc nextjournal.clerk.webserver/help-doc) + (reset! v/!viewers (v/get-all-viewers))) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 1423066dc..729f40303 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -250,164 +250,73 @@ (defn into-markup [mkup] (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] (fn [{:as node :keys [text content]}] - (into (mkup-fn node) (cond text [text] content (map with-md-viewer content)))))) + (with-viewer :html + (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) (def default-markdown-viewers [{:name :nextjournal.markdown/doc - :transform-fn (into-markup [:div.viewer-markdown]) - :fetch-fn fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:div.viewer-markdown])} - {:name :nextjournal.markdown/heading - :transform-fn (into-markup #(vector (str "h" (:heading-level %)))) - :fetch-fn fetch-all - :render-fn 'v/html} - - {:name :nextjournal.markdown/paragraph - :transform-fn (into-markup [:p]) - :fetch-fn fetch-all - :render-fn 'v/html} - - {:name :nextjournal.markdown/ruler - :transform-fn (into-markup [:hr]) - :fetch-fn fetch-all - :render-fn 'v/html} + ;; blocks + {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} + {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} + {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} + {:name :nextjournal.markdown/code + ;; TODO: fixme + :transform-fn (into-markup #(vector :div.viewer-code.not-prose (with-viewer :code (md.transform/->text %))))} + {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} + {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} ;; marks - {:name :nextjournal.markdown/em - :transform-fn (into-markup [:em]) - :fetch-fn fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/strong - :transform-fn (into-markup [:strong]) - :fetch-fn fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/monospace - :transform-fn (into-markup [:code]) - :fetch-fn fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/link - :transform-fn (into-markup #(vector :a (:attrs %))) - :fetch-fn fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/strikethrough - :transform-fn (into-markup [:s]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/internal-link - :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) - :fetch-fn fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/hashtag - :fetch-fn 'v/fetch-all - :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))})) - :render-fn 'v/html} + {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} + {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong])} + {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code])} + {:name :nextjournal.markdown/strikethrough :transform-fn (into-markup [:s])} + {:name :nextjournal.markdown/link :transform-fn (into-markup #(vector :a (:attrs %)))} + {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} + {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} ;; inlines - {:name :nextjournal.markdown/text + {:name :nextjournal.markdown/text :transform-fn (into-markup [:span.text])} ;; TODO: find a way to drop wrapping [:span] - :transform-fn (into-markup [:span.text]) - :fetch-fn fetch-all - :render-fn 'v/html} - #?(:clj - {:name :nextjournal.markdown/inline - ;; TODO: use clerk/read+eval-cached - :transform-fn (comp eval read-string :text) - :fetch-fn fetch-all - :render-fn 'v/html}) - {:name :nextjournal.markdown/softbreak - :transform-fn (into-markup [:span]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - - ;; blocks - {:name :nextjournal.markdown/code - ;; TODO: fixme - :transform-fn (into-markup #(vector :div.viewer-code.not-prose (with-viewer :code (md.transform/->text %)))) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/image - :transform-fn (into-markup #(vector :img (:attrs %))) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/blockquote - :transform-fn (into-markup [:blockquote]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + {:name :nextjournal.markdown/softbreak :transform-fn (into-markup [:span])} + #?(:clj ;; TODO: use clerk/read+eval-cached + {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) ;; formulas - {:name :nextjournal.markdown/formula - :transform-fn :text - :fetch-fn fetch-all - :render-fn 'v/katex-viewer} - {:name :nextjournal.markdown/block-formula - :transform-fn :text - :fetch-fn fetch-all - :render-fn 'v/katex-viewer} + {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} + {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} ;; lists {:name :nextjournal.markdown/bullet-list - :transform-fn (into-markup [:ul]) - :fetch-fn fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:ul])} {:name :nextjournal.markdown/numbered-list - :transform-fn (into-markup [:ol]) - :fetch-fn fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:ol])} {:name :nextjournal.markdown/todo-list - :transform-fn (into-markup [:ul.contains-task-list]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:ul.contains-task-list])} {:name :nextjournal.markdown/list-item - :transform-fn (into-markup [:li]) - :fetch-fn fetch-all - :render-fn 'v/html} + :transform-fn (into-markup [:li])} {:name :nextjournal.markdown/todo-item - :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]])) - :fetch-fn fetch-all - :render-fn 'v/html} + :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} ;; tables - {:name :nextjournal.markdown/table - :transform-fn (into-markup [:table]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/table-head - :transform-fn (into-markup [:thead]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/table-body - :transform-fn (into-markup [:tbody]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} - {:name :nextjournal.markdown/table-row - :transform-fn (into-markup [:tr]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + {:name :nextjournal.markdown/table :transform-fn (into-markup [:table])} + {:name :nextjournal.markdown/table-head :transform-fn (into-markup [:thead])} + {:name :nextjournal.markdown/table-body :transform-fn (into-markup [:tbody])} + {:name :nextjournal.markdown/table-row :transform-fn (into-markup [:tr])} {:name :nextjournal.markdown/table-header - :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))})) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))}))} {:name :nextjournal.markdown/table-data - :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))})) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} ;; ToC via [[TOC]] placeholder - {:name :nextjournal.markdown/toc - :fetch-fn 'v/fetch-all - :transform-fn #(throw (ex-info "Not Implemented" {})) - :render-fn 'v/html} + {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" {}))} ;; sidenotes {:name :nextjournal.markdown/sidenote - :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]])) - :fetch-fn 'v/fetch-all - :render-fn 'v/html} + :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]]))} {:name :nextjournal.markdown/sidenote-ref - :transform-fn (into-markup [:sup.sidenote-ref]) - :fetch-fn 'v/fetch-all - :render-fn 'v/html}]) + :transform-fn (into-markup [:sup.sidenote-ref])}]) (defn get-all-viewers [] {:root (concat default-markdown-viewers default-viewers) From cdc5022695819cca28af853a048d2397ea58533a Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 12:23:16 +0100 Subject: [PATCH 11/39] Fix hashing tests --- test/nextjournal/clerk/hashing_test.clj | 49 ++++++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/test/nextjournal/clerk/hashing_test.clj b/test/nextjournal/clerk/hashing_test.clj index 6f177331e..427f50285 100644 --- a/test/nextjournal/clerk/hashing_test.clj +++ b/test/nextjournal/clerk/hashing_test.clj @@ -37,20 +37,41 @@ (deftest parse-clojure-string (testing "is returning blocks with types and markdown structure attached" - (is (match? (m/equals {:blocks [{:type :code, :text "^:nextjournal.clerk/no-cache (ns example-notebook)", :ns? true} - {:type :markdown, :text " # 📶 Sorting\n"} - {:type :markdown, :text " ## Sorting Sets\n The following set should be sorted upon description\n"} - {:type :code, :text "#{3 1 2}"} - {:type :markdown, :text " ## Sorting Maps\n"} - {:type :code, :text "{2 \"bar\" 1 \"foo\"}"}], - :visibility #{:show}, - :title "📶 Sorting", - :toc {:type :toc, - :children [{:type :toc, - :content [{:type :text, :text "📶 Sorting"}], - :heading-level 1, - :children [{:type :toc, :content [{:type :text, :text "Sorting Sets"}], :heading-level 2} - {:type :toc, :content [{:type :text, :text "Sorting Maps"}], :heading-level 2}]}]}}) + (is (match? (m/equals {:blocks [{:type :code + :text "^:nextjournal.clerk/no-cache (ns example-notebook)" + :ns? true} + {:type :markdown + :doc {:type :doc + :content [{:content [{:text "📶 Sorting" :type :text}] + :heading-level 1 + :type :heading}]}} + {:type :markdown + :doc {:type :doc + :content [{:content [{:text "Sorting Sets" :type :text}] + :heading-level 2 + :type :heading} + {:content [{:text "The following set should be sorted upon description" :type :text}] + :type :paragraph}]}} + {:type :code :text "#{3 1 2}"} + {:type :markdown + :doc {:type :doc + :content [{:content [{:text "Sorting Maps" :type :text}] + :heading-level 2 + :type :heading}]}} + {:type :code :text "{2 \"bar\" 1 \"foo\"}" }] + :title "📶 Sorting" + :toc {:type :toc + :children [{:type :toc + :heading-level 1 + :content [{:text "📶 Sorting" + :type :text}] + :children [{:type :toc + :heading-level 2 + :content [{:text "Sorting Sets" :type :text}]} + {:content [{:text "Sorting Maps" :type :text}] + :heading-level 2 + :type :toc}]}]} + :visibility #{:show}}) (h/parse-clojure-string {:doc? true} notebook))))) (deftest no-cache? From e5de829f114d4069dac71567d3987b390050c7da Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 14:55:37 +0100 Subject: [PATCH 12/39] Fix code viewer --- notebooks/viewers/custom_markdown.clj | 24 +++++++++++++++++++----- src/nextjournal/clerk/viewer.cljc | 13 +++++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj index 0908e4961..b4041763a 100644 --- a/notebooks/viewers/custom_markdown.clj +++ b/notebooks/viewers/custom_markdown.clj @@ -1,5 +1,6 @@ ;; # 🎭 Custom Markdown Viewers -(ns viewers.custom-markdown +^{:nextjournal.clerk/visibility :hide-ns} +(ns ^{:nextjournal.clerk/no-cache true} viewers.custom-markdown (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v] [nextjournal.markdown.transform :as markdown.transform])) @@ -13,7 +14,7 @@ :on-change '(fn [x] (js/console.log (.. x -target -value)))}]))} nil)) -;; This allows us to define custom inline `(clerk/tex "\\beta")` evaluation like to build inline controls `(slider 0 100)` to interact with. +;; Define custom inline `(clerk/tex "\\beta")` evaluation like to build inline controls `(slider 0 100)` to interact with. ;; ;; _**FIXME:** inline formulas!!!_ @@ -26,11 +27,24 @@ :transform-fn (comp eval read-string markdown.transform/->text)} {:name :nextjournal.markdown/ruler - :transform-fn (v/into-markup [:hr {:style {:border-color "#fb923c"}}]) + :transform-fn (v/into-markup [:hr {:style {:border "3px solid #fb923c"}}]) :fetch-fn v/fetch-all :render-fn 'v/html}]) ;; --- +;; Margins in markdown code blocks are still to be fixed, both in fenced blocks +;; ```clojure +;; (+ 1 2) +;; ``` +;; as well as in 2-tab indented +;; +;; this +;; is some +;; code + -(comment - (reset! v/!viewers (v/get-all-viewers))) +^{::clerk/visibility :hide} +(v/with-viewer :hide-result + (comment + (reset! nextjournal.clerk.webserver/!doc nextjournal.clerk.webserver/help-doc) + (reset! v/!viewers (v/get-all-viewers)))) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 729f40303..4f862af14 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -254,18 +254,19 @@ (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) (def default-markdown-viewers - [{:name :nextjournal.markdown/doc - :transform-fn (into-markup [:div.viewer-markdown])} + [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.ahoi.viewer-markdown])} ;; blocks {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} + {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} + {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} {:name :nextjournal.markdown/code - ;; TODO: fixme - :transform-fn (into-markup #(vector :div.viewer-code.not-prose (with-viewer :code (md.transform/->text %))))} - {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} - {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} + :transform-fn #(with-viewer :html + [:div.viewer-code + (with-viewer :code + (md.transform/->text %))])} ;; marks {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} From 1eb958ce2daf4a65bdef001adcf099ca1888e0d8 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 16:03:07 +0100 Subject: [PATCH 13/39] Fix rendering inline katex formulas by defaulting to a element to host reagent dangerously-set inline HTML --- src/nextjournal/clerk/sci_viewer.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/nextjournal/clerk/sci_viewer.cljs b/src/nextjournal/clerk/sci_viewer.cljs index af6a1b2bb..1a8a824ad 100644 --- a/src/nextjournal/clerk/sci_viewer.cljs +++ b/src/nextjournal/clerk/sci_viewer.cljs @@ -923,9 +923,10 @@ black")}]))} (html (katex/to-html-string tex-string))) (defn html-viewer [markup] - (if (string? markup) - (html [:div {:dangerouslySetInnerHTML {:__html markup}}]) - (r/as-element markup))) + (r/as-element + (if (string? markup) + [:span {:dangerouslySetInnerHTML {:__html markup}}] + markup))) (defn reagent-viewer [x] (r/as-element (cond-> x (fn? x) vector))) From 9b3816dd96d389ce01086e4a9d885e30caa1533d Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 18:20:28 +0100 Subject: [PATCH 14/39] Make custom eval a bit more interesting --- notebooks/viewers/custom_markdown.clj | 39 ++++++++++++++++----------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj index b4041763a..8ddb0bf31 100644 --- a/notebooks/viewers/custom_markdown.clj +++ b/notebooks/viewers/custom_markdown.clj @@ -5,32 +5,39 @@ [nextjournal.clerk.viewer :as v] [nextjournal.markdown.transform :as markdown.transform])) +;; This notebook should demostrate how to override markdown nodes and to test how they render by default. + +;; ## Custom Inline Eval (is this margin ok 👇?) + +(defonce slider-state (atom 42)) + (defn slider [min max] - (clerk/with-viewer {:fetch-fn v/fetch-all - :render-fn (list 'fn '[_] - (list 'v/html - [:input {:type :range - :min min :max max - :on-change '(fn [x] (js/console.log (.. x -target -value)))}]))} - nil)) - -;; Define custom inline `(clerk/tex "\\beta")` evaluation like to build inline controls `(slider 0 100)` to interact with. + (clerk/with-viewer + {:fetch-fn (fn [_ x] x) + :render-fn `(fn [val] + (v/html [:input {:type :range + :min ~min + :max ~max + :value val + :on-change #(v/clerk-eval `(reset! slider-state (Integer/parseInt ~(.. % -target -value))))}]))} + @slider-state)) + +;; With overridable markdown nodes we can get inline evaluation for free: `(clerk/tex "\\beta")`. We can build inline controls to interact with. ;; -;; _**FIXME:** inline formulas!!!_ +;; Say you don't like the text color of your notebook: fix it with a slider `(slider 0 256)` and set blue values to `@slider-state`. Unfortunately dragging of the slider isn't smooth at all, because of recomputations. (clerk/set-viewers! [{:name :nextjournal.markdown/text - :fetch-fn v/fetch-all - :transform-fn (v/into-markup [:span {:style {:color "#f87171"}}]) - :render-fn 'v/html} + :transform-fn + (v/into-markup + [:span {:style {:color (str "rgb(130, 130, " @slider-state ")")}}])} {:name :nextjournal.markdown/monospace :transform-fn (comp eval read-string markdown.transform/->text)} {:name :nextjournal.markdown/ruler - :transform-fn (v/into-markup [:hr {:style {:border "3px solid #fb923c"}}]) - :fetch-fn v/fetch-all - :render-fn 'v/html}]) + :transform-fn (v/into-markup [:hr {:style {:border "3px solid #fb923c"}}])}]) +;; # Custom Ruler ;; --- ;; Margins in markdown code blocks are still to be fixed, both in fenced blocks ;; ```clojure From d0f4a233ef060e61bd4cf1b64945f7e1396ae0ee Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 24 Mar 2022 18:51:42 +0100 Subject: [PATCH 15/39] Inline eval in bold --- notebooks/viewers/custom_markdown.clj | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj index 8ddb0bf31..d492f08d3 100644 --- a/notebooks/viewers/custom_markdown.clj +++ b/notebooks/viewers/custom_markdown.clj @@ -7,7 +7,7 @@ ;; This notebook should demostrate how to override markdown nodes and to test how they render by default. -;; ## Custom Inline Eval (is this margin ok 👇?) +;; ## Custom Inline Eval (defonce slider-state (atom 42)) @@ -22,9 +22,10 @@ :on-change #(v/clerk-eval `(reset! slider-state (Integer/parseInt ~(.. % -target -value))))}]))} @slider-state)) +;; --- ;; With overridable markdown nodes we can get inline evaluation for free: `(clerk/tex "\\beta")`. We can build inline controls to interact with. ;; -;; Say you don't like the text color of your notebook: fix it with a slider `(slider 0 256)` and set blue values to `@slider-state`. Unfortunately dragging of the slider isn't smooth at all, because of recomputations. +;; Say you don't like the text color of your notebook: fix it with a slider `(slider 0 256)` and set blue values to **`@slider-state`**. Unfortunately dragging of the slider isn't very smooth yet, because of recomputations, but should be easy to fix. (clerk/set-viewers! [{:name :nextjournal.markdown/text :transform-fn @@ -37,8 +38,6 @@ {:name :nextjournal.markdown/ruler :transform-fn (v/into-markup [:hr {:style {:border "3px solid #fb923c"}}])}]) -;; # Custom Ruler -;; --- ;; Margins in markdown code blocks are still to be fixed, both in fenced blocks ;; ```clojure ;; (+ 1 2) From 987005b6f2049ae003d8ec1328dbfb85755d7ca3 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 10:50:59 +0200 Subject: [PATCH 16/39] Merge markdown viewers in existing var --- src/nextjournal/clerk/viewer.cljc | 155 +++++++++++++++--------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 4f862af14..523fe9efc 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -167,12 +167,88 @@ (defn var-from-def? [x] (and (map? x) (get-safe x :nextjournal.clerk/var-from-def))) +(declare with-viewer) + +(defn with-md-viewer [{:as node :keys [type]}] + (with-viewer (keyword "nextjournal.markdown" (name type)) node)) + +(defn into-markup [mkup] + (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] + (fn [{:as node :keys [text content]}] + (with-viewer :html + (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) + (declare !viewers) ;; keep viewer selection stricly in Clojure (def default-viewers ;; maybe make this a sorted-map - [{:pred char? :render-fn '(fn [c] (v/html [:span.cmt-string.inspected-value "\\" c]))} + [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.ahoi.viewer-markdown])} + + ;; blocks + {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} + {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} + {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} + {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} + {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} + {:name :nextjournal.markdown/code + :transform-fn #(with-viewer :html + [:div.viewer-code + (with-viewer :code + (md.transform/->text %))])} + + ;; marks + {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} + {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong])} + {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code])} + {:name :nextjournal.markdown/strikethrough :transform-fn (into-markup [:s])} + {:name :nextjournal.markdown/link :transform-fn (into-markup #(vector :a (:attrs %)))} + {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} + {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} + + ;; inlines + {:name :nextjournal.markdown/text :transform-fn (into-markup [:span.text])} + ;; TODO: find a way to drop wrapping [:span] + {:name :nextjournal.markdown/softbreak :transform-fn (into-markup [:span])} + #?(:clj ;; TODO: use clerk/read+eval-cached + {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) + + ;; formulas + {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} + {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} + + ;; lists + {:name :nextjournal.markdown/bullet-list + :transform-fn (into-markup [:ul])} + {:name :nextjournal.markdown/numbered-list + :transform-fn (into-markup [:ol])} + {:name :nextjournal.markdown/todo-list + :transform-fn (into-markup [:ul.contains-task-list])} + {:name :nextjournal.markdown/list-item + :transform-fn (into-markup [:li])} + {:name :nextjournal.markdown/todo-item + :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} + + ;; tables + {:name :nextjournal.markdown/table :transform-fn (into-markup [:table])} + {:name :nextjournal.markdown/table-head :transform-fn (into-markup [:thead])} + {:name :nextjournal.markdown/table-body :transform-fn (into-markup [:tbody])} + {:name :nextjournal.markdown/table-row :transform-fn (into-markup [:tr])} + {:name :nextjournal.markdown/table-header + :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))}))} + {:name :nextjournal.markdown/table-data + :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} + + ;; ToC via [[TOC]] placeholder + {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" {}))} + + ;; sidenotes + {:name :nextjournal.markdown/sidenote + :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]]))} + {:name :nextjournal.markdown/sidenote-ref + :transform-fn (into-markup [:sup.sidenote-ref])} + + {:pred char? :render-fn '(fn [c] (v/html [:span.cmt-string.inspected-value "\\" c]))} {:pred string? :render-fn (quote v/quoted-string-viewer) :fetch-opts {:n elide-string-length}} {:pred number? :render-fn '(fn [x] (v/html [:span.cmt-number.inspected-value (if (js/Number.isNaN x) "NaN" (str x))]))} @@ -244,83 +320,8 @@ {:pred string? :render-fn (quote v/string-viewer) :fetch-opts {:n 100}} {:pred number? :render-fn '(fn [x] (v/html [:span.tabular-nums (if (js/Number.isNaN x) "NaN" (str x))]))}]) -(defn with-md-viewer [{:as node :keys [type]}] - (wrap-value node (keyword "nextjournal.markdown" (name type)))) - -(defn into-markup [mkup] - (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] - (fn [{:as node :keys [text content]}] - (with-viewer :html - (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) - -(def default-markdown-viewers - [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.ahoi.viewer-markdown])} - - ;; blocks - {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} - {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} - {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} - {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} - {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} - {:name :nextjournal.markdown/code - :transform-fn #(with-viewer :html - [:div.viewer-code - (with-viewer :code - (md.transform/->text %))])} - - ;; marks - {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} - {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong])} - {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code])} - {:name :nextjournal.markdown/strikethrough :transform-fn (into-markup [:s])} - {:name :nextjournal.markdown/link :transform-fn (into-markup #(vector :a (:attrs %)))} - {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} - {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} - - ;; inlines - {:name :nextjournal.markdown/text :transform-fn (into-markup [:span.text])} - ;; TODO: find a way to drop wrapping [:span] - {:name :nextjournal.markdown/softbreak :transform-fn (into-markup [:span])} - #?(:clj ;; TODO: use clerk/read+eval-cached - {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) - - ;; formulas - {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} - {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} - - ;; lists - {:name :nextjournal.markdown/bullet-list - :transform-fn (into-markup [:ul])} - {:name :nextjournal.markdown/numbered-list - :transform-fn (into-markup [:ol])} - {:name :nextjournal.markdown/todo-list - :transform-fn (into-markup [:ul.contains-task-list])} - {:name :nextjournal.markdown/list-item - :transform-fn (into-markup [:li])} - {:name :nextjournal.markdown/todo-item - :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} - - ;; tables - {:name :nextjournal.markdown/table :transform-fn (into-markup [:table])} - {:name :nextjournal.markdown/table-head :transform-fn (into-markup [:thead])} - {:name :nextjournal.markdown/table-body :transform-fn (into-markup [:tbody])} - {:name :nextjournal.markdown/table-row :transform-fn (into-markup [:tr])} - {:name :nextjournal.markdown/table-header - :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))}))} - {:name :nextjournal.markdown/table-data - :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} - - ;; ToC via [[TOC]] placeholder - {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" {}))} - - ;; sidenotes - {:name :nextjournal.markdown/sidenote - :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]]))} - {:name :nextjournal.markdown/sidenote-ref - :transform-fn (into-markup [:sup.sidenote-ref])}]) - (defn get-all-viewers [] - {:root (concat default-markdown-viewers default-viewers) + {:root default-viewers :table default-table-cell-viewers}) (defonce From 33e67f8cdaed09e2f2c000af7d8b859a10a66e81 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 11:35:52 +0200 Subject: [PATCH 17/39] Fix markdown image viewer --- src/nextjournal/clerk/viewer.cljc | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 523fe9efc..3fda8b0b8 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -187,7 +187,7 @@ ;; blocks {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} - {:name :nextjournal.markdown/image :transform-fn (into-markup #(vector :img (:attrs %)))} + {:name :nextjournal.markdown/image :transform-fn #(with-viewer :html [:img (:attrs %)])} {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} @@ -218,14 +218,10 @@ {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} ;; lists - {:name :nextjournal.markdown/bullet-list - :transform-fn (into-markup [:ul])} - {:name :nextjournal.markdown/numbered-list - :transform-fn (into-markup [:ol])} - {:name :nextjournal.markdown/todo-list - :transform-fn (into-markup [:ul.contains-task-list])} - {:name :nextjournal.markdown/list-item - :transform-fn (into-markup [:li])} + {:name :nextjournal.markdown/bullet-list :transform-fn (into-markup [:ul])} + {:name :nextjournal.markdown/numbered-list :transform-fn (into-markup [:ol])} + {:name :nextjournal.markdown/todo-list :transform-fn (into-markup [:ul.contains-task-list])} + {:name :nextjournal.markdown/list-item :transform-fn (into-markup [:li])} {:name :nextjournal.markdown/todo-item :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} From 8d22dc1c3ff22cac5a9c8272dbb91cb885aad665 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 14:35:37 +0200 Subject: [PATCH 18/39] Remove debug class --- src/nextjournal/clerk/viewer.cljc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 3fda8b0b8..6bcb4a927 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -183,7 +183,7 @@ ;; keep viewer selection stricly in Clojure (def default-viewers ;; maybe make this a sorted-map - [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.ahoi.viewer-markdown])} + [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.viewer-markdown])} ;; blocks {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} @@ -236,7 +236,7 @@ :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} ;; ToC via [[TOC]] placeholder - {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" {}))} + {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" %))} ;; sidenotes {:name :nextjournal.markdown/sidenote From 8ffd8ba5cd945c71e2b52a4c27cb060193769dcf Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 15:18:27 +0200 Subject: [PATCH 19/39] Adjust scope of notebook to in-text eval --- notebooks/viewers/custom_markdown.clj | 56 --------------------------- notebooks/viewers/in_text_eval.clj | 31 +++++++++++++++ 2 files changed, 31 insertions(+), 56 deletions(-) delete mode 100644 notebooks/viewers/custom_markdown.clj create mode 100644 notebooks/viewers/in_text_eval.clj diff --git a/notebooks/viewers/custom_markdown.clj b/notebooks/viewers/custom_markdown.clj deleted file mode 100644 index d492f08d3..000000000 --- a/notebooks/viewers/custom_markdown.clj +++ /dev/null @@ -1,56 +0,0 @@ -;; # 🎭 Custom Markdown Viewers -^{:nextjournal.clerk/visibility :hide-ns} -(ns ^{:nextjournal.clerk/no-cache true} viewers.custom-markdown - (:require [nextjournal.clerk :as clerk] - [nextjournal.clerk.viewer :as v] - [nextjournal.markdown.transform :as markdown.transform])) - -;; This notebook should demostrate how to override markdown nodes and to test how they render by default. - -;; ## Custom Inline Eval - -(defonce slider-state (atom 42)) - -(defn slider [min max] - (clerk/with-viewer - {:fetch-fn (fn [_ x] x) - :render-fn `(fn [val] - (v/html [:input {:type :range - :min ~min - :max ~max - :value val - :on-change #(v/clerk-eval `(reset! slider-state (Integer/parseInt ~(.. % -target -value))))}]))} - @slider-state)) - -;; --- -;; With overridable markdown nodes we can get inline evaluation for free: `(clerk/tex "\\beta")`. We can build inline controls to interact with. -;; -;; Say you don't like the text color of your notebook: fix it with a slider `(slider 0 256)` and set blue values to **`@slider-state`**. Unfortunately dragging of the slider isn't very smooth yet, because of recomputations, but should be easy to fix. - -(clerk/set-viewers! [{:name :nextjournal.markdown/text - :transform-fn - (v/into-markup - [:span {:style {:color (str "rgb(130, 130, " @slider-state ")")}}])} - - {:name :nextjournal.markdown/monospace - :transform-fn (comp eval read-string markdown.transform/->text)} - - {:name :nextjournal.markdown/ruler - :transform-fn (v/into-markup [:hr {:style {:border "3px solid #fb923c"}}])}]) - -;; Margins in markdown code blocks are still to be fixed, both in fenced blocks -;; ```clojure -;; (+ 1 2) -;; ``` -;; as well as in 2-tab indented -;; -;; this -;; is some -;; code - - -^{::clerk/visibility :hide} -(v/with-viewer :hide-result - (comment - (reset! nextjournal.clerk.webserver/!doc nextjournal.clerk.webserver/help-doc) - (reset! v/!viewers (v/get-all-viewers)))) diff --git a/notebooks/viewers/in_text_eval.clj b/notebooks/viewers/in_text_eval.clj new file mode 100644 index 000000000..c8d3ba4c6 --- /dev/null +++ b/notebooks/viewers/in_text_eval.clj @@ -0,0 +1,31 @@ +;; # 📝 In-Text Evaluation +^{:nextjournal.clerk/visibility :hide-ns} +(ns ^{:nextjournal.clerk/no-cache true} viewers.custom-markdown + (:require [nextjournal.clerk :as clerk] + [nextjournal.clerk.viewer :as v] + [nextjournal.markdown.transform :as markdown.transform])) + +;; Being able to override markdown viewers allows we get in-text evaluation for free: + +(defonce N✨ (atom 42)) + +(clerk/set-viewers! [{:name :nextjournal.markdown/monospace + :transform-fn (comp eval read-string markdown.transform/->text)} + {:name :nextjournal.markdown/ruler + :transform-fn (constantly + (v/with-viewer :html [:span (repeat @N✨ "✨")]))}]) +;; --- +(defn slider [var {:keys [min max]}] + (clerk/with-viewer + {:fetch-fn (fn [_ x] x) + :transform-fn (fn [var] {:var-name (symbol var) :value @@var}) + :render-fn `(fn [{:as x :keys [var-name value]}] + (v/html [:input {:type :range + :min ~min :max ~max + :value value + :on-change #(v/clerk-eval `(reset! ~var-name (Integer/parseInt ~(.. % -target -value))))}]))} + var)) + +;; This slider `(slider #'N✨ {:min 10 :max 50})` controls the numebr (**`(deref N✨)`**) of stars in our custom horizontal rules. + +;; --- From afaa3e1b224a4d81627b70327a7a8965e5aeffdb Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 18:06:44 +0200 Subject: [PATCH 20/39] Make custom markdown viewers survive page reload --- src/nextjournal/clerk/view.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nextjournal/clerk/view.clj b/src/nextjournal/clerk/view.clj index 91cb42968..ecb0e7ad2 100644 --- a/src/nextjournal/clerk/view.clj +++ b/src/nextjournal/clerk/view.clj @@ -153,7 +153,7 @@ (defn describe-block [{:keys [inline-results?] :or {inline-results? false}} {:keys [ns]} {:as cell :keys [type text doc]}] (case type :markdown [(if doc - (-> doc v/with-md-viewer v/describe) + (binding [*ns* ns] (-> doc v/with-md-viewer v/describe)) (v/md text))] :code (let [{:as cell :keys [result]} (update cell :result apply-viewer-unwrapping-var-from-def) {:keys [code? fold? result?]} (->display cell)] From b8b56d454554f1f16b0cea8b422a361c268883c1 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 28 Mar 2022 19:11:19 +0200 Subject: [PATCH 21/39] Fix demo notebooks paths and nss --- notebooks/viewers/custom_markdown.md | 53 ++++++++++++++++++++++++++++ notebooks/viewers/in_text_eval.clj | 2 +- src/nextjournal/clerk.clj | 5 +-- 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 notebooks/viewers/custom_markdown.md diff --git a/notebooks/viewers/custom_markdown.md b/notebooks/viewers/custom_markdown.md new file mode 100644 index 000000000..cfc94d703 --- /dev/null +++ b/notebooks/viewers/custom_markdown.md @@ -0,0 +1,53 @@ +# Customizable Markdown + +Playground for overriding markdown nodes + +```clojure +^{:nextjournal.clerk/visibility #{:hide-ns}} +(ns ^:nextjournal.clerk/no-cache viewers.custom-markdown + (:require [nextjournal.clerk :as clerk] + [nextjournal.clerk.viewer :as v])) +``` + +```clojure +(clerk/set-viewers! [{:name :nextjournal.markdown/ruler + :transform-fn (constantly + (v/html [:div {:style {:width "100%" :height "80px" :background-position "center" :background-size "cover" + :background-image "url(https://www.maxpixel.net/static/photo/1x/Ornamental-Separator-Decorative-Line-Art-Divider-4715969.png)"}}]))}]) +``` + +## Sections + +with some more text and a ruler. + +--- + +Clerk parses all _consecutive_ `;;`-led _clojure comment lines_ as [Markdown](https://daringfireball.net/projects/markdown). All of markdown syntax should be supported: + +### Lists + +- one **strong** hashtag like #nomarkdownforoldcountry +- two ~~strikethrough~~ + +and bullet lists + +- [x] what +- [ ] the + +### Code + + (assoc {:this "should get"} :clojure "syntax highlighting") + +--- + +### Tables + +Tables with specific alignment. + +| feature | | +|:-------:|:---| +| One |✅ | +| Two |✅ | +| three |❌ | + +--- diff --git a/notebooks/viewers/in_text_eval.clj b/notebooks/viewers/in_text_eval.clj index c8d3ba4c6..c62c64e03 100644 --- a/notebooks/viewers/in_text_eval.clj +++ b/notebooks/viewers/in_text_eval.clj @@ -1,6 +1,6 @@ ;; # 📝 In-Text Evaluation ^{:nextjournal.clerk/visibility :hide-ns} -(ns ^{:nextjournal.clerk/no-cache true} viewers.custom-markdown +(ns ^{:nextjournal.clerk/no-cache true} viewers.in-text-eval (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v] [nextjournal.markdown.transform :as markdown.transform])) diff --git a/src/nextjournal/clerk.clj b/src/nextjournal/clerk.clj index e93db9ee8..3b897348a 100644 --- a/src/nextjournal/clerk.clj +++ b/src/nextjournal/clerk.clj @@ -360,7 +360,8 @@ (def clerk-docs (into ["notebooks/markdown.md" - "notebooks/onwards.md"] + "notebooks/onwards.md" + "notebooks/viewers/custom_markdown.md"] (map #(str "notebooks/" % ".clj")) ["hello" "how_clerk_works" @@ -374,10 +375,10 @@ "viewer_d3_require" "viewers_nested" "viewer_normalization" - "viewers/custom_markdown" "viewers/html" "viewers/image" "viewers/image_layouts" + "viewers/in_text_eval" "viewers/markdown" "viewers/plotly" "viewers/table" From fe1e9a66e0ff463ef31653522ddc483b1a063e8b Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Tue, 29 Mar 2022 16:36:42 +0200 Subject: [PATCH 22/39] Fix reagent structure for in-text evals not to trigger re-rendering Evaluating the inspect function on edamame read instead of having to deal with ifns seems to make Reagent happier. --- src/nextjournal/clerk/viewer.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 6bcb4a927..32dae29d3 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -154,7 +154,7 @@ (defn inspect-leafs [opts x] (if (wrapped-value? x) - [(->viewer-fn 'v/inspect) (describe x opts)] + [(->viewer-eval 'v/inspect) (describe x opts)] x)) (defn fetch-all [opts xs] From 2bade8915dac4e85db0b7ba7084a25ea6e33c2a9 Mon Sep 17 00:00:00 2001 From: Martin Kavalar Date: Wed, 30 Mar 2022 09:43:17 +0200 Subject: [PATCH 23/39] Tweak in text eval --- notebooks/viewers/in_text_eval.clj | 12 ++++++++---- resources/viewer-js-hash | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/notebooks/viewers/in_text_eval.clj b/notebooks/viewers/in_text_eval.clj index c62c64e03..231dd724d 100644 --- a/notebooks/viewers/in_text_eval.clj +++ b/notebooks/viewers/in_text_eval.clj @@ -1,5 +1,5 @@ ;; # 📝 In-Text Evaluation -^{:nextjournal.clerk/visibility :hide-ns} +^{:nextjournal.clerk/visibility #{:hide-ns :hide}} (ns ^{:nextjournal.clerk/no-cache true} viewers.in-text-eval (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v] @@ -7,14 +7,18 @@ ;; Being able to override markdown viewers allows we get in-text evaluation for free: -(defonce N✨ (atom 42)) +^{::clerk/viewer clerk/hide-result} +(defonce num★ (atom 3)) +#_(reset! num★ 3) +^{::clerk/visibility :show} (clerk/set-viewers! [{:name :nextjournal.markdown/monospace :transform-fn (comp eval read-string markdown.transform/->text)} {:name :nextjournal.markdown/ruler :transform-fn (constantly - (v/with-viewer :html [:span (repeat @N✨ "✨")]))}]) + (v/with-viewer :html [:div.text-center (repeat @num★ "★")]))}]) ;; --- +^{::clerk/viewer clerk/hide-result} (defn slider [var {:keys [min max]}] (clerk/with-viewer {:fetch-fn (fn [_ x] x) @@ -26,6 +30,6 @@ :on-change #(v/clerk-eval `(reset! ~var-name (Integer/parseInt ~(.. % -target -value))))}]))} var)) -;; This slider `(slider #'N✨ {:min 10 :max 50})` controls the numebr (**`(deref N✨)`**) of stars in our custom horizontal rules. +;; Drag the following slider `(slider #'num★ {:min 1 :max 40})` to control the number of stars (currently **`(deref num★)`**) in our custom horizontal rules. ;; --- diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 47f8b3344..30a19b1b6 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -3XP2esKpbmLTaAjvjqGV4UQuHNhr \ No newline at end of file +AxrgPEMZKiDthpt44v61CT3Ff8i \ No newline at end of file From cc24fa20a721a13d7f14832d1debfb53c108ab2a Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 13:18:30 +0200 Subject: [PATCH 24/39] Remove useless class from text spans --- notebooks/viewers/custom_markdown.md | 8 +++++--- src/nextjournal/clerk/viewer.cljc | 6 ++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/notebooks/viewers/custom_markdown.md b/notebooks/viewers/custom_markdown.md index cfc94d703..1d4c0422f 100644 --- a/notebooks/viewers/custom_markdown.md +++ b/notebooks/viewers/custom_markdown.md @@ -10,7 +10,9 @@ Playground for overriding markdown nodes ``` ```clojure -(clerk/set-viewers! [{:name :nextjournal.markdown/ruler +(clerk/set-viewers! [{:name :nextjournal.markdown/text + :transform-fn (v/into-markup [:span {:style {:color "#64748b"}}])} + {:name :nextjournal.markdown/ruler :transform-fn (constantly (v/html [:div {:style {:width "100%" :height "80px" :background-position "center" :background-size "cover" :background-image "url(https://www.maxpixel.net/static/photo/1x/Ornamental-Separator-Decorative-Line-Art-Divider-4715969.png)"}}]))}]) @@ -18,7 +20,7 @@ Playground for overriding markdown nodes ## Sections -with some more text and a ruler. +with some _more_ text and a ruler. --- @@ -48,6 +50,6 @@ Tables with specific alignment. |:-------:|:---| | One |✅ | | Two |✅ | -| three |❌ | +| Three |❌ | --- diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 32dae29d3..4638a39ef 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -207,11 +207,9 @@ {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} ;; inlines - {:name :nextjournal.markdown/text :transform-fn (into-markup [:span.text])} - ;; TODO: find a way to drop wrapping [:span] + {:name :nextjournal.markdown/text :transform-fn (into-markup [:span])} {:name :nextjournal.markdown/softbreak :transform-fn (into-markup [:span])} - #?(:clj ;; TODO: use clerk/read+eval-cached - {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) + #?(:clj {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) ;; formulas {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} From e6138855474f23f4a1528c3357a494daa5b7977c Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 15:54:20 +0200 Subject: [PATCH 25/39] Make clerk/md function consistent with markdown viewers --- notebooks/viewers/markdown.clj | 2 +- src/nextjournal/clerk/sci_viewer.cljs | 10 ---------- src/nextjournal/clerk/viewer.cljc | 4 ++-- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/notebooks/viewers/markdown.clj b/notebooks/viewers/markdown.clj index 842ca34d5..686308488 100644 --- a/notebooks/viewers/markdown.clj +++ b/notebooks/viewers/markdown.clj @@ -1,5 +1,5 @@ ;; # Markdown ✍️ (ns markdown (:require [nextjournal.clerk :as clerk])) -(clerk/md "### Text can be\n * **bold**\n * *italic\n * ~~Strikethrough~~\n +(clerk/md "### Text can be\n * **bold**\n * *italic*\n * ~~Strikethrough~~\n It's [Markdown](https://daringfireball.net/projects/markdown/), like you know it.") diff --git a/src/nextjournal/clerk/sci_viewer.cljs b/src/nextjournal/clerk/sci_viewer.cljs index 1a8a824ad..d02d9e17d 100644 --- a/src/nextjournal/clerk/sci_viewer.cljs +++ b/src/nextjournal/clerk/sci_viewer.cljs @@ -936,15 +936,6 @@ black")}]))} (def plotly-viewer (comp normalize-viewer plotly/viewer)) (def vega-lite-viewer (comp normalize-viewer vega-lite/viewer)) -(defn markdown-viewer - "Accept a markdown string or a structure from parsed markdown." - [data] - (cond - (string? data) - (markdown/viewer data) - (and (map? data) (contains? data :content) (contains? data :type)) - (with-viewer :hiccup (md.transform/->hiccup markdown/default-renderers data)))) - (def expand-icon [:svg {:xmlns "http://www.w3.org/2000/svg" :viewBox "0 0 20 20" :fill "currentColor" :width 12 :height 12} [:path {:fill-rule "evenodd" :d "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" :clip-rule "evenodd"}]]) @@ -998,7 +989,6 @@ black")}]))} 'notebook-viewer notebook 'katex-viewer katex-viewer 'mathjax-viewer mathjax-viewer - 'markdown-viewer markdown-viewer 'code-viewer code-viewer 'foldable-code-viewer foldable-code-viewer 'plotly-viewer plotly-viewer diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 4638a39ef..dd7f9a5de 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -7,6 +7,7 @@ #?@(:clj [[clojure.repl :refer [demunge]] [nextjournal.clerk.config :as config]] :cljs [[reagent.ratom :as ratom]]) + [nextjournal.markdown :as md] [nextjournal.markdown.transform :as md.transform]) #?(:clj (:import (java.lang Throwable) (java.awt.image BufferedImage) @@ -277,10 +278,9 @@ {:name :latex :render-fn (quote v/katex-viewer) :fetch-fn fetch-all} {:name :mathjax :render-fn (quote v/mathjax-viewer) :fetch-fn fetch-all} {:name :html :render-fn (quote v/html) :fetch-fn fetch-all} - {:name :hiccup :render-fn (quote v/html)} ;; TODO: drop once markdown doesn't use it anymore {:name :plotly :render-fn (quote v/plotly-viewer) :fetch-fn fetch-all} {:name :vega-lite :render-fn (quote v/vega-lite-viewer) :fetch-fn fetch-all} - {:name :markdown :render-fn (quote v/markdown-viewer) :fetch-fn fetch-all} + {:name :markdown :transform-fn (comp with-md-viewer md/parse)} {:name :code :render-fn (quote v/code-viewer) :fetch-fn fetch-all :transform-fn #(let [v (value %)] (if (string? v) v (with-out-str (pprint/pprint v))))} {:name :code-folded :render-fn (quote v/foldable-code-viewer) :fetch-fn fetch-all :transform-fn #(let [v (value %)] (if (string? v) v (with-out-str (pprint/pprint v))))} {:name :reagent :render-fn (quote v/reagent-viewer) :fetch-fn fetch-all} From bd6a1a6abac82d1e45edeebe606b4f5fb1f4ffa9 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 16:29:46 +0200 Subject: [PATCH 26/39] Fix describe tests --- test/nextjournal/clerk/viewer_test.clj | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/nextjournal/clerk/viewer_test.clj b/test/nextjournal/clerk/viewer_test.clj index ffd49e669..31ff5a413 100644 --- a/test/nextjournal/clerk/viewer_test.clj +++ b/test/nextjournal/clerk/viewer_test.clj @@ -67,7 +67,26 @@ (deftest describe (testing "only transform-fn can select viewer" - (is (match? {:nextjournal/value "Hello _markdown_!", :nextjournal/viewer {:name :markdown}} + + (is (match? {:nextjournal/viewer {:name :html} + :nextjournal/value [:div.viewer-markdown + [any? + {:nextjournal/viewer {:name :html} + :nextjournal/value [:p + [any? + {:nextjournal/viewer {:name :html} + :nextjournal/value [:span "Hello "]}] + [any? + {:nextjournal/viewer {:name :html} + :nextjournal/value [:em + [any? + {:path [], + :nextjournal/value [:span "markdown"] + :nextjournal/viewer {:name :html}}]]}] + [any? + {:nextjournal/viewer {:name :html} + :nextjournal/value [:span "!"]}]]}]]} + (v/describe (v/with-viewer {:transform-fn (comp v/md :foo)} {:foo "Hello _markdown_!"}))))) From 8f8dabdc8f59a852e0af0a04ff416e16dab86673 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 17:46:47 +0200 Subject: [PATCH 27/39] Fix hashing tests --- test/nextjournal/clerk/hashing_test.clj | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/nextjournal/clerk/hashing_test.clj b/test/nextjournal/clerk/hashing_test.clj index f9c7e4c80..68fec5803 100644 --- a/test/nextjournal/clerk/hashing_test.clj +++ b/test/nextjournal/clerk/hashing_test.clj @@ -38,20 +38,18 @@ (deftest parse-clojure-string (testing "is returning blocks with types and markdown structure attached" (is (match? (m/equals {:blocks [{:type :code, :text "^:nextjournal.clerk/no-cache ^:nextjournal.clerk/toc (ns example-notebook)", :ns? true} - {:type :markdown, :text " # 📶 Sorting\n"} - {:type :markdown, :text " ## Sorting Sets\n The following set should be sorted upon description\n"} + {:type :markdown, :doc {:type :doc :content [{:type :heading}]}} + {:type :markdown, :doc {:type :doc :content [{:type :heading} + {:type :paragraph}]}} {:type :code, :text "#{3 1 2}"} - {:type :markdown, :text " ## Sorting Maps\n"} + {:type :markdown, :doc {:type :doc :content [{:type :heading}]}} {:type :code, :text "{2 \"bar\" 1 \"foo\"}"}], :visibility #{:show}, :title "📶 Sorting", :toc {:type :toc, :mode true, - :children [{:type :toc, - :content [{:type :text, :text "📶 Sorting"}], - :heading-level 1, - :children [{:type :toc, :content [{:type :text, :text "Sorting Sets"}], :heading-level 2} - {:type :toc, :content [{:type :text, :text "Sorting Maps"}], :heading-level 2}]}]}}) + :children [{:type :toc :children [{:type :toc} + {:type :toc}]}]}}) (h/parse-clojure-string {:doc? true} notebook))))) (deftest no-cache? From 1ee6b2c144306b07d0d5aa39eb423e53102fc8b8 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 17:54:04 +0200 Subject: [PATCH 28/39] Bump markdown lib with internal links --- deps.edn | 6 ++++-- resources/viewer-js-hash | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/deps.edn b/deps.edn index e062900fb..714710ed7 100644 --- a/deps.edn +++ b/deps.edn @@ -8,7 +8,7 @@ com.nextjournal/beholder {:mvn/version "1.0.0"} - io.github.nextjournal/markdown {:mvn/version "0.2.44"} + io.github.nextjournal/markdown {:mvn/version "0.3.69"} com.taoensso/nippy {:mvn/version "3.1.1"} mvxcvi/multihash {:mvn/version "2.0.3"} @@ -25,7 +25,9 @@ org.babashka/sci {:mvn/version "0.3.2"} reagent/reagent {:mvn/version "1.1.0"} io.github.babashka/sci-configs {:git/sha "fd6a3332f358e56b96b5a791f75f97573e018580"} - io.github.nextjournal/viewers {:git/sha "d88a9abd1f2bfd28ff2d3983407a9319c6f04501"} + io.github.nextjournal/viewers {:git/sha "d88a9abd1f2bfd28ff2d3983407a9319c6f04501" + :exclusions [io.github.nextjournal/markdown + io.github.nextjournal/clerk]} metosin/reitit-frontend {:mvn/version "0.5.15"}}} :dev {:extra-deps {arrowic/arrowic {:mvn/version "0.1.1"} diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index cbe137023..051595e1b 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -3kU9UUQyoBcteM6RahoiDEbN4pJz +N7BJdQxWFgyeQu7Aki9nnD92AsS \ No newline at end of file From 4173f2c6ccd2f5e00c74760d266aba294caf2c39 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Wed, 30 Mar 2022 18:20:46 +0200 Subject: [PATCH 29/39] Fix showing initial help doc --- notebooks/described_markdown.clj | 2 +- src/nextjournal/clerk/view.clj | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj index 976e7ae36..f2021355d 100644 --- a/notebooks/described_markdown.clj +++ b/notebooks/described_markdown.clj @@ -10,7 +10,7 @@ ^{::clerk/viewer :hide-result} (defn parse [text] (md.parser/parse (update md.parser/empty-doc :text-tokenizers conj - {:regexp #"\{\{([^{]+)\}\}" + {:regex #"\{\{([^{]+)\}\}" :handler (fn [m] {:type :inline :text (m 1)})}) (md/tokenize text))) diff --git a/src/nextjournal/clerk/view.clj b/src/nextjournal/clerk/view.clj index b20db4e30..91c614171 100644 --- a/src/nextjournal/clerk/view.clj +++ b/src/nextjournal/clerk/view.clj @@ -152,9 +152,10 @@ (defn describe-block [{:keys [inline-results?] :or {inline-results? false}} {:keys [ns]} {:as cell :keys [type text doc]}] (case type - :markdown [(if doc - (binding [*ns* ns] (-> doc v/with-md-viewer v/describe)) - (v/md text))] + :markdown [(binding [*ns* ns] + (v/describe (cond + text (v/md text) + doc (v/with-md-viewer doc))))] :code (let [{:as cell :keys [result]} (update cell :result apply-viewer-unwrapping-var-from-def) {:keys [code? fold? result?]} (->display cell)] (cond-> [] From 528c190040c3029899a8a2f5f013da79ed991918 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 31 Mar 2022 11:20:02 +0200 Subject: [PATCH 30/39] Fix TOC text for heading nodes with marks --- notebooks/viewers/in_text_eval.clj | 4 ++-- resources/viewer-js-hash | 2 +- src/nextjournal/clerk/sci_viewer.cljs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/notebooks/viewers/in_text_eval.clj b/notebooks/viewers/in_text_eval.clj index 231dd724d..6c068d4c7 100644 --- a/notebooks/viewers/in_text_eval.clj +++ b/notebooks/viewers/in_text_eval.clj @@ -1,5 +1,5 @@ -;; # 📝 In-Text Evaluation -^{:nextjournal.clerk/visibility #{:hide-ns :hide}} +;; # 📝 _In-Text_ Evaluation +^{:nextjournal.clerk/visibility #{:hide-ns :hide} :nextjournal.clerk/toc true} (ns ^{:nextjournal.clerk/no-cache true} viewers.in-text-eval (:require [nextjournal.clerk :as clerk] [nextjournal.clerk.viewer :as v] diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 051595e1b..485944bc2 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -N7BJdQxWFgyeQu7Aki9nnD92AsS \ No newline at end of file +GgWzAjK8isJtQZVS5vNkJNiJjs2 \ No newline at end of file diff --git a/src/nextjournal/clerk/sci_viewer.cljs b/src/nextjournal/clerk/sci_viewer.cljs index be879d2d1..7f328954a 100644 --- a/src/nextjournal/clerk/sci_viewer.cljs +++ b/src/nextjournal/clerk/sci_viewer.cljs @@ -80,7 +80,7 @@ (reduce (fn [acc {:as item :keys [content children]}] (if content - (let [title (-> content first :text)] + (let [title (md.transform/->text item)] (->> {:title title :path (str "#" (uri.normalize/normalize-fragment title)) :items (toc-items children)} From f911e662e28e4f34919b1dd58b119624952cdab5 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 31 Mar 2022 11:29:59 +0200 Subject: [PATCH 31/39] How Clerk Works ToC --- notebooks/how_clerk_works.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/how_clerk_works.clj b/notebooks/how_clerk_works.clj index 14af0ca6c..d031efb15 100644 --- a/notebooks/how_clerk_works.clj +++ b/notebooks/how_clerk_works.clj @@ -1,5 +1,5 @@ ;; # How Clerk Works 🕵🏻‍♀️ -^{:nextjournal.clerk/toc? true} +^{:nextjournal.clerk/toc true} (ns how-clerk-works (:require [next.jdbc :as jdbc] [nextjournal.clerk :as clerk] From 7ad95648d545d5087b16dc3d02c8900fab2a3564 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Thu, 31 Mar 2022 18:36:15 +0200 Subject: [PATCH 32/39] Ignore [[TOC]] placeholder instead of throwing --- resources/viewer-js-hash | 2 +- src/nextjournal/clerk/viewer.cljc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 485944bc2..00b939f5e 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -GgWzAjK8isJtQZVS5vNkJNiJjs2 \ No newline at end of file +K7azehokxECVXxHTzco7EEuvAwh \ No newline at end of file diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index dd7f9a5de..71c31db3a 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -234,8 +234,8 @@ {:name :nextjournal.markdown/table-data :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} - ;; ToC via [[TOC]] placeholder - {:name :nextjournal.markdown/toc :transform-fn #(throw (ex-info "Not Implemented" %))} + ;; ToC via [[TOC]] placeholder ignored + {:name :nextjournal.markdown/toc :transform-fn (into-markup [:div.toc])} ;; sidenotes {:name :nextjournal.markdown/sidenote From 359761cadd3e669d569081380fb5c5a71ff0745d Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 10:47:27 +0200 Subject: [PATCH 33/39] Fix rendering softbreaks --- resources/viewer-js-hash | 2 +- src/nextjournal/clerk/viewer.cljc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 00b939f5e..2c93cdf9a 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -K7azehokxECVXxHTzco7EEuvAwh \ No newline at end of file +4AGFn7jgi3iH5yL4B71msegs8gjx \ No newline at end of file diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index 71c31db3a..8336ef034 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -209,7 +209,7 @@ ;; inlines {:name :nextjournal.markdown/text :transform-fn (into-markup [:span])} - {:name :nextjournal.markdown/softbreak :transform-fn (into-markup [:span])} + {:name :nextjournal.markdown/softbreak :transform-fn (fn [_] (with-viewer :html [:span " "]))} #?(:clj {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) ;; formulas From a359fe067bd8aef1e944d4ed87971489a8e351cf Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 11:52:20 +0200 Subject: [PATCH 34/39] remove viewers exclusions we'll deal with this by removing clerk and markdown from the root deps of viewers --- deps.edn | 4 +--- resources/viewer-js-hash | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/deps.edn b/deps.edn index 711d86f13..f931a0ace 100644 --- a/deps.edn +++ b/deps.edn @@ -25,9 +25,7 @@ org.babashka/sci {:mvn/version "0.3.2"} reagent/reagent {:mvn/version "1.1.0"} io.github.babashka/sci-configs {:git/sha "fd6a3332f358e56b96b5a791f75f97573e018580"} - io.github.nextjournal/viewers {:git/sha "d88a9abd1f2bfd28ff2d3983407a9319c6f04501" - :exclusions [io.github.nextjournal/markdown - io.github.nextjournal/clerk]} + io.github.nextjournal/viewers {:git/sha "d88a9abd1f2bfd28ff2d3983407a9319c6f04501"} metosin/reitit-frontend {:mvn/version "0.5.15"}}} :dev {:extra-deps {arrowic/arrowic {:mvn/version "0.1.1"} diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index d8f035a86..00fcc0ed1 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -3oPQaaq3te999AVUnqPnMeNwg2jV \ No newline at end of file +3Ui9KcU866k5koHjDzWeik4uKKQr \ No newline at end of file From 284c36e056064bccadf5bd782e6068032e6be71c Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 11:54:13 +0200 Subject: [PATCH 35/39] Remove redundant notebook --- notebooks/described_markdown.clj | 89 -------------------------------- 1 file changed, 89 deletions(-) delete mode 100644 notebooks/described_markdown.clj diff --git a/notebooks/described_markdown.clj b/notebooks/described_markdown.clj deleted file mode 100644 index f2021355d..000000000 --- a/notebooks/described_markdown.clj +++ /dev/null @@ -1,89 +0,0 @@ -;; # ✍️ Described Markdown -^{:nextjournal.clerk/visibility #{:hide-ns}} -(ns ^:nextjournal.clerk/no-cache described-markdown - (:require [nextjournal.clerk :as clerk] - [nextjournal.clerk.viewer :as v] - [nextjournal.markdown :as md] - [nextjournal.markdown.parser :as md.parser] - [nextjournal.markdown.transform :as md.transform])) - -^{::clerk/viewer :hide-result} -(defn parse [text] - (md.parser/parse (update md.parser/empty-doc :text-tokenizers conj - {:regex #"\{\{([^{]+)\}\}" - :handler (fn [m] {:type :inline :text (m 1)})}) - (md/tokenize text))) - -;; This notebook contains preparatory work to make markdown node customizable in clerk. - -;; Due to the recursive nature of [[v/describe]] it is sufficien to wrap a node at a time: - -(defn with-md-viewer [{:as node :keys [type]}] - (v/wrap-value node (keyword "nextjournal.markdown" (name type)))) - -;; We define a generic `transform-fn` with 2 purposes: -;; * produces the desired hiccup representation at each node and -;; * delegates to describe the representation of the child nodes: - -(defn into-markup [mkup] - (let [mkup-fn (if (fn? mkup) mkup (constantly mkup))] - (fn [{:as node :keys [text content]}] - (v/html (into (mkup-fn node) (cond text [text] content (map with-md-viewer content))))))) - -^{::clerk/viewer :hide-result} -(def md-viewers - [{:name :nextjournal.markdown/doc - :transform-fn (into-markup [:div.viewer-markdown])} - - {:name :nextjournal.markdown/heading - :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} - - {:name :nextjournal.markdown/paragraph - :transform-fn (into-markup [:p])} - - {:name :nextjournal.markdown/em - :transform-fn (into-markup [:em])} - - {:name :nextjournal.markdown/strong - :transform-fn (into-markup [:strong])} - - {:name :nextjournal.markdown/monospace - :transform-fn (into-markup [:code])} - - {:name :nextjournal.markdown/internal-link - :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} - - {:name :nextjournal.markdown/text - ;; TODO: find a way to drop wrapping [:span] - :transform-fn (into-markup [:span.text])} - - {:name :nextjournal.markdown/inline - ;; TODO: use clerk/read+eval-cached - :transform-fn (comp eval read-string :text)} - - {:name :nextjournal.markdown/formula - :transform-fn :text - :render-fn 'v/mathjax-viewer}]) - -(defn marine [text] (clerk/html [:span {:style {:font-weight 800 :color "#0284c7"}} (str "⚓️" text)])) - -(def text "# Hello - -This is not _really_ a **strong** formula $\\alpha$. - -## Section 3 - -with inline wiki [[link]] and inline eval {{ (marine \"Ahoi\") }}. -") - -^{::clerk/viewers md-viewers} -(with-md-viewer (parse text)) - -^{::clerk/visibility :hide} -(comment - (v/describe - (v/with-viewers md-viewers - (with-md-viewer (parse text)))) - - (reset! nextjournal.clerk.webserver/!doc nextjournal.clerk.webserver/help-doc) - (reset! v/!viewers (v/get-all-viewers))) From 5bcec410408dba1b3ff45a3451dc62d20891e847 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 11:59:35 +0200 Subject: [PATCH 36/39] Move markdown viewers to a separate var --- resources/viewer-js-hash | 2 +- src/nextjournal/clerk/viewer.cljc | 123 +++++++++++++++--------------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 00fcc0ed1..cc33d9a82 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -3Ui9KcU866k5koHjDzWeik4uKKQr \ No newline at end of file +42VLLsPoiy3BS1BbfhXfPK3Tk8ro \ No newline at end of file diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index cc83a7114..d368904eb 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -184,66 +184,7 @@ ;; keep viewer selection stricly in Clojure (def default-viewers ;; maybe make this a sorted-map - [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.viewer-markdown])} - - ;; blocks - {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} - {:name :nextjournal.markdown/image :transform-fn #(with-viewer :html [:img (:attrs %)])} - {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} - {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} - {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} - {:name :nextjournal.markdown/code - :transform-fn #(with-viewer :html - [:div.viewer-code - (with-viewer :code - (md.transform/->text %))])} - - ;; marks - {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} - {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong])} - {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code])} - {:name :nextjournal.markdown/strikethrough :transform-fn (into-markup [:s])} - {:name :nextjournal.markdown/link :transform-fn (into-markup #(vector :a (:attrs %)))} - {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} - {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} - - ;; inlines - {:name :nextjournal.markdown/text :transform-fn (into-markup [:span])} - {:name :nextjournal.markdown/softbreak :transform-fn (fn [_] (with-viewer :html [:span " "]))} - #?(:clj {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) - - ;; formulas - {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} - {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} - - ;; lists - {:name :nextjournal.markdown/bullet-list :transform-fn (into-markup [:ul])} - {:name :nextjournal.markdown/numbered-list :transform-fn (into-markup [:ol])} - {:name :nextjournal.markdown/todo-list :transform-fn (into-markup [:ul.contains-task-list])} - {:name :nextjournal.markdown/list-item :transform-fn (into-markup [:li])} - {:name :nextjournal.markdown/todo-item - :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} - - ;; tables - {:name :nextjournal.markdown/table :transform-fn (into-markup [:table])} - {:name :nextjournal.markdown/table-head :transform-fn (into-markup [:thead])} - {:name :nextjournal.markdown/table-body :transform-fn (into-markup [:tbody])} - {:name :nextjournal.markdown/table-row :transform-fn (into-markup [:tr])} - {:name :nextjournal.markdown/table-header - :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))}))} - {:name :nextjournal.markdown/table-data - :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} - - ;; ToC via [[TOC]] placeholder ignored - {:name :nextjournal.markdown/toc :transform-fn (into-markup [:div.toc])} - - ;; sidenotes - {:name :nextjournal.markdown/sidenote - :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]]))} - {:name :nextjournal.markdown/sidenote-ref - :transform-fn (into-markup [:sup.sidenote-ref])} - - {:pred char? :render-fn '(fn [c] (v/html [:span.cmt-string.inspected-value "\\" c]))} + [{:pred char? :render-fn '(fn [c] (v/html [:span.cmt-string.inspected-value "\\" c]))} {:pred string? :render-fn (quote v/quoted-string-viewer) :fetch-opts {:n elide-string-length}} {:pred number? :render-fn '(fn [x] (v/html [:span.cmt-number.inspected-value (if (js/Number.isNaN x) "NaN" (str x))]))} @@ -314,8 +255,68 @@ {:pred string? :render-fn (quote v/string-viewer) :fetch-opts {:n 100}} {:pred number? :render-fn '(fn [x] (v/html [:span.tabular-nums (if (js/Number.isNaN x) "NaN" (str x))]))}]) +(def markdown-viewers + [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.viewer-markdown])} + + ;; blocks + {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} + {:name :nextjournal.markdown/image :transform-fn #(with-viewer :html [:img (:attrs %)])} + {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} + {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} + {:name :nextjournal.markdown/ruler :transform-fn (into-markup [:hr])} + {:name :nextjournal.markdown/code + :transform-fn #(with-viewer :html + [:div.viewer-code + (with-viewer :code + (md.transform/->text %))])} + + ;; marks + {:name :nextjournal.markdown/em :transform-fn (into-markup [:em])} + {:name :nextjournal.markdown/strong :transform-fn (into-markup [:strong])} + {:name :nextjournal.markdown/monospace :transform-fn (into-markup [:code])} + {:name :nextjournal.markdown/strikethrough :transform-fn (into-markup [:s])} + {:name :nextjournal.markdown/link :transform-fn (into-markup #(vector :a (:attrs %)))} + {:name :nextjournal.markdown/internal-link :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} + {:name :nextjournal.markdown/hashtag :transform-fn (into-markup #(vector :a {:href (str "#" (:text %))}))} + + ;; inlines + {:name :nextjournal.markdown/text :transform-fn (into-markup [:span])} + {:name :nextjournal.markdown/softbreak :transform-fn (fn [_] (with-viewer :html [:span " "]))} + #?(:clj {:name :nextjournal.markdown/inline :transform-fn (comp eval read-string md.transform/->text)}) + + ;; formulas + {:name :nextjournal.markdown/formula :transform-fn :text :render-fn 'v/katex-viewer} + {:name :nextjournal.markdown/block-formula :transform-fn :text :render-fn 'v/katex-viewer} + + ;; lists + {:name :nextjournal.markdown/bullet-list :transform-fn (into-markup [:ul])} + {:name :nextjournal.markdown/numbered-list :transform-fn (into-markup [:ol])} + {:name :nextjournal.markdown/todo-list :transform-fn (into-markup [:ul.contains-task-list])} + {:name :nextjournal.markdown/list-item :transform-fn (into-markup [:li])} + {:name :nextjournal.markdown/todo-item + :transform-fn (into-markup (fn [{:keys [attrs]}] [:li [:input {:type "checkbox" :default-checked (:checked attrs)}]]))} + + ;; tables + {:name :nextjournal.markdown/table :transform-fn (into-markup [:table])} + {:name :nextjournal.markdown/table-head :transform-fn (into-markup [:thead])} + {:name :nextjournal.markdown/table-body :transform-fn (into-markup [:tbody])} + {:name :nextjournal.markdown/table-row :transform-fn (into-markup [:tr])} + {:name :nextjournal.markdown/table-header + :transform-fn (into-markup #(vector :th {:style (md.transform/table-alignment (:attrs %))}))} + {:name :nextjournal.markdown/table-data + :transform-fn (into-markup #(vector :td {:style (md.transform/table-alignment (:attrs %))}))} + + ;; ToC via [[TOC]] placeholder ignored + {:name :nextjournal.markdown/toc :transform-fn (into-markup [:div.toc])} + + ;; sidenotes + {:name :nextjournal.markdown/sidenote + :transform-fn (into-markup (fn [{:keys [attrs]}] [:span.sidenote [:sup {:style {:margin-right "3px"}} (-> attrs :ref inc)]]))} + {:name :nextjournal.markdown/sidenote-ref + :transform-fn (into-markup [:sup.sidenote-ref])}]) + (defn get-all-viewers [] - {:root default-viewers + {:root (concat default-viewers markdown-viewers) :table default-table-cell-viewers}) (defonce From 50962d17fac765c8e5a447f7d173b82271f0fe12 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 12:55:59 +0200 Subject: [PATCH 37/39] Fix scrolling to section when clicking on ToC items --- resources/viewer-js-hash | 2 +- src/nextjournal/clerk/viewer.cljc | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index 5d3f650a7..dca6d4c69 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -CpD3SeozV1w7zVMFGS6DUgEXUs1 \ No newline at end of file +2HkVLhHi3fmm1gJkAyfW85P9U6aa \ No newline at end of file diff --git a/src/nextjournal/clerk/viewer.cljc b/src/nextjournal/clerk/viewer.cljc index d368904eb..22c13a78b 100644 --- a/src/nextjournal/clerk/viewer.cljc +++ b/src/nextjournal/clerk/viewer.cljc @@ -8,7 +8,8 @@ [nextjournal.clerk.config :as config]] :cljs [[reagent.ratom :as ratom]]) [nextjournal.markdown :as md] - [nextjournal.markdown.transform :as md.transform]) + [nextjournal.markdown.transform :as md.transform] + [lambdaisland.uri.normalize :as uri.normalize]) #?(:clj (:import (java.lang Throwable) (java.awt.image BufferedImage) (javax.imageio ImageIO)))) @@ -259,7 +260,10 @@ [{:name :nextjournal.markdown/doc :transform-fn (into-markup [:div.viewer-markdown])} ;; blocks - {:name :nextjournal.markdown/heading :transform-fn (into-markup #(vector (str "h" (:heading-level %))))} + {:name :nextjournal.markdown/heading + :transform-fn (into-markup + (fn [{:as node :keys [heading-level]}] + [(str "h" heading-level) {:id (uri.normalize/normalize-fragment (md.transform/->text node))}]))} {:name :nextjournal.markdown/image :transform-fn #(with-viewer :html [:img (:attrs %)])} {:name :nextjournal.markdown/blockquote :transform-fn (into-markup [:blockquote])} {:name :nextjournal.markdown/paragraph :transform-fn (into-markup [:p])} From e31fe9e216f43d91b1ab1b5b7e60fd7006df240c Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 16:08:02 +0200 Subject: [PATCH 38/39] Make assertions more precise in describe test --- test/nextjournal/clerk/viewer_test.clj | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/nextjournal/clerk/viewer_test.clj b/test/nextjournal/clerk/viewer_test.clj index 31ff5a413..bdcd50639 100644 --- a/test/nextjournal/clerk/viewer_test.clj +++ b/test/nextjournal/clerk/viewer_test.clj @@ -65,25 +65,26 @@ (is (= :full (:nextjournal/width (v/wrapped-with-viewer (v/table {:nextjournal.clerk/width :full} {:a [1] :b [2] :c [3]}))))))) +(defn viewer-eval-inspect? [x] (= x (v/->viewer-eval 'v/inspect))) + (deftest describe (testing "only transform-fn can select viewer" - (is (match? {:nextjournal/viewer {:name :html} :nextjournal/value [:div.viewer-markdown - [any? + [viewer-eval-inspect? {:nextjournal/viewer {:name :html} :nextjournal/value [:p - [any? + [viewer-eval-inspect? {:nextjournal/viewer {:name :html} :nextjournal/value [:span "Hello "]}] - [any? + [viewer-eval-inspect? {:nextjournal/viewer {:name :html} :nextjournal/value [:em - [any? + [viewer-eval-inspect? {:path [], :nextjournal/value [:span "markdown"] :nextjournal/viewer {:name :html}}]]}] - [any? + [viewer-eval-inspect? {:nextjournal/viewer {:name :html} :nextjournal/value [:span "!"]}]]}]]} From b256c23b78fd60ac11780efe07717a7c6fb288c2 Mon Sep 17 00:00:00 2001 From: Andrea Amantini Date: Mon, 4 Apr 2022 17:49:04 +0200 Subject: [PATCH 39/39] Improve notebook wording --- notebooks/viewers/in_text_eval.clj | 2 +- resources/viewer-js-hash | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/notebooks/viewers/in_text_eval.clj b/notebooks/viewers/in_text_eval.clj index 6c068d4c7..e271f4041 100644 --- a/notebooks/viewers/in_text_eval.clj +++ b/notebooks/viewers/in_text_eval.clj @@ -5,7 +5,7 @@ [nextjournal.clerk.viewer :as v] [nextjournal.markdown.transform :as markdown.transform])) -;; Being able to override markdown viewers allows we get in-text evaluation for free: +;; Being able to override markdown viewers allows us to get in-text evaluation for free: ^{::clerk/viewer clerk/hide-result} (defonce num★ (atom 3)) diff --git a/resources/viewer-js-hash b/resources/viewer-js-hash index dca6d4c69..c8881b92a 100644 --- a/resources/viewer-js-hash +++ b/resources/viewer-js-hash @@ -1 +1 @@ -2HkVLhHi3fmm1gJkAyfW85P9U6aa \ No newline at end of file +3vA1T4ofNtExCV6EKNp2sBuABWoR \ No newline at end of file