-
Notifications
You must be signed in to change notification settings - Fork 4
/
markdown.clj
85 lines (71 loc) · 2.83 KB
/
markdown.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
(ns nextjournal.markdown
"Facility functions for handling markdown conversions"
(:require [clojure.java.io :as io]
[clojure.data.json :as json]
[nextjournal.markdown.parser :as markdown.parser]
[nextjournal.markdown.transform :as markdown.transform])
(:import (org.graalvm.polyglot Context Context$Builder Source Value)
(java.io Reader)))
(set! *warn-on-reflection* true)
(def ^Context$Builder context-builder
(doto (Context/newBuilder (into-array String ["js"]))
(.option "js.timer-resolution" "1")
(.option "js.java-package-globals" "false")
(.option "js.esm-eval-returns-exports", "true")
;; ⬆ returns module exports when evaling an esm module file, note this will only work on stock JVM or on GraalJVM
;; matching the poliglot library versions specified in deps.edn
(.out System/out)
(.err System/err)
(.allowIO true)
(.allowExperimentalOptions true)
(.allowAllAccess true)
(.allowNativeAccess true)
(.option "engine.WarnInterpreterOnly" "false")))
(def ^Context ctx (.build context-builder))
(def ^Value MD-imports
;; Contructing a `java.io.Reader` first to work around a bug with graal on windows
;; see https://github.com/oracle/graaljs/issues/534 and https://github.com/nextjournal/viewers/pull/33
(let [source (-> (io/resource "js/markdown.mjs")
io/input-stream
io/reader
(as-> r (Source/newBuilder "js" ^Reader r "markdown.mjs")))]
(locking ctx
(.. ctx
(eval (.build source))
(getMember "default")))))
(def ^Value tokenize-fn (.getMember MD-imports "tokenizeJSON"))
(defn tokenize [markdown-text]
(let [^Value tokens-json (locking ctx
(.execute tokenize-fn (to-array [markdown-text])))]
(json/read-str (.asString tokens-json) :key-fn keyword)))
(defn parse
"Turns a markdown string into a nested clojure structure."
([markdown-text] (parse markdown.parser/empty-doc markdown-text))
([doc markdown-text] (markdown.parser/parse doc (tokenize markdown-text))))
(defn ->hiccup
"Turns a markdown string into hiccup."
([markdown-text] (->hiccup markdown.transform/default-hiccup-renderers markdown-text))
([ctx markdown-text] (->> markdown-text parse (markdown.transform/->hiccup ctx))))
(comment
(tokenize "# Title
- [ ] one
- [x] two
")
(parse "# Hello Markdown
- [ ] what
- [ ] [nice](very/nice/thing)
- [x] ~~thing~~
")
(->hiccup "# Hello Markdown
* What's _going_ on?
")
(->hiccup
(assoc markdown.transform/default-hiccup-renderers
:heading (fn [ctx node]
[:h1.some-extra.class
(markdown.transform/into-markup [:span.some-other-class] ctx node)]))
"# Hello Markdown
* What's _going_ on?
")
;; launch shadow cljs repl
(shadow.cljs.devtools.api/repl :sci))