Skip to content

Commit 59471a0

Browse files
zampinoborkdude
andauthored
Transform plain containers to hiccup lists (#35)
--------- Co-authored-by: Michiel Borkent <[email protected]>
1 parent 18a7bed commit 59471a0

File tree

6 files changed

+235
-209
lines changed

6 files changed

+235
-209
lines changed

.github/workflows/main.yml

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ jobs:
2525
- name: 🔧 Install clojure
2626
uses: DeLaGuardo/setup-clojure@master
2727
with:
28-
cli: '1.10.3.943'
28+
cli: '1.12.0.1530'
2929

3030
- name: 🗝 maven cache
31-
uses: actions/cache@v2
31+
uses: actions/cache@v4
3232
with:
3333
path: |
3434
~/.m2
@@ -53,11 +53,8 @@ jobs:
5353
with:
5454
babashka-version: 0.7.8
5555

56-
- name: 🗝 Yarn Cache
57-
uses: c-hive/gha-yarn-cache@v2
58-
5956
- name: 🗝 Shadow compiler cache
60-
uses: actions/cache@v2
57+
uses: actions/cache@v4
6158
with:
6259
path: .shadow-cljs
6360
key: ${{ runner.os }}-shadow-cljs-${{ github.sha }}
@@ -101,7 +98,7 @@ jobs:
10198
github-token: ${{ secrets.GITHUB_TOKEN }}
10299

103100
- name: 🗝 maven cache
104-
uses: actions/cache@v2
101+
uses: actions/cache@v4
105102
with:
106103
path: |
107104
~/.m2
@@ -111,16 +108,13 @@ jobs:
111108
${{ runner.os }}-maven-
112109
113110
- name: 🗝 Clerk Cache
114-
uses: actions/cache@v2
111+
uses: actions/cache@v4
115112
with:
116113
path: .clerk
117114
key: ${{ runner.os }}-clerk-cache
118115

119-
- name: 🗝 Yarn Cache
120-
uses: c-hive/gha-yarn-cache@v2
121-
122116
- name: 🗝 Shadow compiler cache
123-
uses: actions/cache@v2
117+
uses: actions/cache@v4
124118
with:
125119
path: .shadow-cljs
126120
key: ${{ runner.os }}-shadow-cljs-${{ github.sha }}
@@ -181,7 +175,7 @@ jobs:
181175
babashka-version: 0.8.156
182176

183177
- name: 🗝 maven cache
184-
uses: actions/cache@v2
178+
uses: actions/cache@v4
185179
with:
186180
path: |
187181
~/.m2

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Unreleased
44

5-
...
5+
* Hiccup JVM compatibiltiy for fragments (see [#34](https://github.com/nextjournal/markdown/issues/34))
66

77
## 0.6.157
88

deps.edn

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
:aliases
1111
{:nextjournal/clerk
1212
{:extra-paths ["notebooks" "dev"]
13-
:extra-deps {io.github.nextjournal/clerk {:git/sha "80b3e0832d08b75e13e3b862bd46660cb1c66d5c"
13+
:extra-deps {io.github.nextjournal/clerk {:git/sha "f4c5488e36c8df11fe352889544e7deb9af73cb7"
1414
:exclusions [io.github.nextjournal/markdown]}}
1515
:jvm-opts ["-Dclojure.main.report=stderr"
1616
#_"-Dclerk.resource_manifest={\"/js/viewer.js\" \"js/viewer.js\"}"] ;;
@@ -29,10 +29,14 @@
2929
{:jvm-opts ["-Dpolyglot.engine.WarnInterpreterOnly=false"]}
3030

3131
:dev
32-
{:extra-paths ["dev"]
32+
{:extra-paths ["dev" "notebooks"]
3333
:extra-deps {org.babashka/http-client {:mvn/version "0.3.11"}
3434
org.clojure/data.json {:mvn/version "2.4.0"}
3535
org.clojure/test.check {:mvn/version "1.1.1"}
36+
io.github.nextjournal/clerk {:git/sha "f4c5488e36c8df11fe352889544e7deb9af73cb7"
37+
:exclusions [io.github.nextjournal/markdown]}
38+
nubank/matcher-combinators {:mvn/version "3.8.3"}
39+
hiccup/hiccup {:mvn/version "2.0.0-RC5"}
3640
org.graalvm.js/js {:mvn/version "21.3.2.1"}}}
3741

3842
:test

notebooks/tight_lists.clj

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
;; # Tight Lists
22
(ns tight-lists
3-
{:nextjournal.clerk/toc :collapsed
4-
:nextjournal.clerk/no-cache true}
3+
{:nextjournal.clerk/no-cache true}
54
(:require [clojure.data.json :as json]
65
[clojure.java.shell :as shell]
76
[nextjournal.clerk :as clerk]
87
[nextjournal.clerk.viewer :as v]
9-
[nextjournal.markdown :as md]))
8+
[nextjournal.markdown :as md]
9+
[hiccup2.core :as h]
10+
[nextjournal.markdown.transform :as md.transform]))
1011

1112
;; Markdown (commonmark) distingushes between [loose and tight lists](https://spec.commonmark.org/0.30/#loose)
1213
;;
@@ -15,40 +16,27 @@
1516
;; > Otherwise a list is tight. (The difference in HTML output is that paragraphs in a loose list are wrapped in `<p>` tags,
1617
;; > while paragraphs in a tight list are not.)
1718
;;
18-
;; We're solving this ambiguity by getting closer to Pandoc types: introduce a `:plain` type, that is a container for
19-
;; inline elemets which is not a paragraph. The advantage will be two-fold:
20-
;;
21-
;; * being able to distinguish among tight and loose lists via markup
22-
;; * get closer to the Pandoc and ease document format conversions
23-
;;
24-
;; ## Markdown-It
25-
;;
26-
;; Markdown-it hides handling of tight/loose behind an [obscure `:hidden` property on the token](https://github.com/markdown-it/markdown-it/blob/8bcc82aa74164a5e13a104f433c26671a92ed872/lib/token.js#L111-L116).
27-
;;
28-
;; * Token#hidden -> Boolean
29-
;; *
30-
;; * If it's true, ignore this element when rendering. Used for tight lists
31-
;; * to hide paragraphs.
32-
;; **/
33-
;; this.hidden = false
34-
3519
;; ## Pandoc to the Rescue
3620
;;
3721
;; To comply with this behaviour [Pandoc uses a `Plain` container type](https://github.com/jgm/pandoc-types/blob/694c383dd674dad97557eb9b97adda17079ebb2c/src/Text/Pandoc/Definition.hs#L275-L278), and I think we should follow their advice
3822

23+
^{::clerk/visibility {:result :hide}}
3924
(defn ->pandoc-ast [text]
40-
(json/read-str
41-
(:out
42-
(shell/sh "pandoc" "-f" "markdown" "-t" "json" :in text))
43-
:key-fn keyword))
25+
(clerk/html [:pre
26+
(with-out-str
27+
(clojure.pprint/pprint
28+
(json/read-str
29+
(:out
30+
(shell/sh "pandoc" "-f" "markdown" "-t" "json" :in text))
31+
:key-fn keyword)))]))
4432

45-
;; Again, tight
33+
;; tight
4634
(->pandoc-ast "
4735
- one
4836
- two
4937
")
5038

51-
;; and loose lists
39+
;; vs loose lists
5240
(->pandoc-ast "
5341
- one
5442
@@ -68,44 +56,48 @@
6856
- two
6957
")
7058

71-
;; ## Adding Plain nodes
72-
;; We're pushing plain nodes into the document when encoutering a paragraph token wiht the `:hidden` flag.
59+
^{::clerk/visibility {:result :hide}}
60+
(defn example [md-string]
61+
(v/html
62+
[:div.flex-col
63+
[:pre.code md-string]
64+
[:pre.code (with-out-str
65+
(clojure.pprint/pprint
66+
(dissoc (md/parse md-string) :toc :title :footnotes)))]
67+
[:pre.code (with-out-str
68+
(clojure.pprint/pprint
69+
(md/->hiccup md-string)))]
70+
(v/html (md/->hiccup md-string))
71+
;; TODO: fix in clerk
72+
#_
73+
(v/html (str (h/html (md/->hiccup md-string))))]))
7374

74-
(md/parse "
75+
(clerk/present!
76+
(example "
7577
* this
7678
* is
77-
* tight!")
79+
* tight!"))
7880

79-
(md/parse "
81+
(example "
8082
* this
8183
* is
8284
> very loose
8385
8486
indeed
8587
* fin")
8688

87-
;; in terms of Clerk support, that amounts to introduce a new viewer, the natural candidate for rendering plain nodes is
88-
;; the empty container `:<>`
89-
(clerk/add-viewers! [(update v/markdown-viewer
90-
:transform-fn (fn [tx-fn]
91-
(fn [wv] (-> wv
92-
tx-fn
93-
(update :nextjournal/viewers
94-
v/add-viewers [{:name ::md/plain
95-
:transform-fn (v/into-markup [:<>])}])))))])
89+
(example "* one \\
90+
hardbreak
91+
* two")
9692

97-
;; ## Rendering
98-
;; ### Tight Lists
99-
;; * one
100-
;; * two
101-
;; * three
102-
;;
103-
;; ### Loose Lists
104-
;; * one
105-
;;
106-
;; one-two
107-
;; * two
108-
;; * three
109-
;; * a tight list
110-
;; * in a loose
111-
;; * one
93+
(example "
94+
* one
95+
softbreak
96+
* two")
97+
98+
;; https://spec.commonmark.org/0.30/#example-314 (loose list)
99+
(example "- a\n- b\n\n- c")
100+
;; https://spec.commonmark.org/0.30/#example-319 (tight with loose sublist inside)
101+
(example "- a\n - b\n\n c\n- d\n")
102+
;; https://spec.commonmark.org/0.30/#example-320 (tight with blockquote inside)
103+
(example "* a\n > b\n >\n* c")

src/nextjournal/markdown/transform.cljc

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ a paragraph
6868
{:doc (partial into-markup [:div])
6969
:heading (fn [ctx {:as node :keys [attrs]}] (-> (heading-markup node) (conj attrs) (into-markup ctx node)))
7070
:paragraph (partial into-markup [:p])
71-
:plain (partial into-markup [:<>])
71+
:plain (fn [ctx {:keys [content]}]
72+
(seq (mapv (partial ->hiccup ctx) content)))
7273
:text (fn [_ {:keys [text]}] text)
7374
:hashtag (fn [_ {:keys [text]}] [:a.tag {:href (str "/tags/" text)} (str "#" text)]) ;; TODO: make it configurable
7475
:blockquote (partial into-markup [:blockquote])
@@ -206,3 +207,41 @@ par two"
206207
;; wrap something around the default
207208
:paragraph (fn [{:as ctx d :default} node] [:div.p-container (d ctx node)]))))
208209
)
210+
211+
(comment
212+
(require '[hiccup2.core :as h])
213+
214+
(-> "
215+
* one
216+
* two"
217+
nextjournal.markdown/parse
218+
->hiccup
219+
h/html str
220+
)
221+
222+
(-> "
223+
* one
224+
225+
* two"
226+
nextjournal.markdown/parse
227+
->hiccup
228+
h/html str
229+
)
230+
231+
(-> "# foo
232+
- one \\
233+
broken
234+
- two"
235+
nextjournal.markdown/parse
236+
->hiccup
237+
h/html str
238+
)
239+
240+
;; https://spec.commonmark.org/0.30/#example-319
241+
(= (str "<div>"
242+
"<ul><li>a<ul><li><p>b</p><p>c</p></li></ul></li><li>d</li></ul>"
243+
"</div>")
244+
(->> "- a\n - b\n\n c\n- d"
245+
nextjournal.markdown/parse
246+
(->hiccup default-hiccup-renderers)
247+
h/html str)))

0 commit comments

Comments
 (0)