Skip to content

Commit c27943d

Browse files
authored
Server-Side-Rendering: Support rendering formulas with KaTeX (#765)
Closes #761.
1 parent ec84127 commit c27943d

File tree

14 files changed

+118
-108
lines changed

14 files changed

+118
-108
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ jobs:
251251
run: echo $(yarn global dir)/node_modules
252252

253253
- name: 🧪 Build Rule 30 Notebook with SSR
254-
run: NODE_PATH=$(yarn global dir)/node_modules clojure -J-Dclojure.main.report=stdout -X:demo:nextjournal/clerk :git/sha '"${{ github.sha }}"' :git/url '"https://github.com/nextjournal/clerk"' :index '"notebooks/rule_30.clj"' :paths [] :ssr true :compile-css true :exclude-js true
254+
run: NODE_PATH=$(yarn global dir)/node_modules clojure -J-Dclojure.main.report=stdout -X:demo:nextjournal/clerk :git/sha '"${{ github.sha }}"' :git/url '"https://github.com/nextjournal/clerk"' :paths '["notebooks/rule_30.clj" "notebooks/viewers/katex.clj"]' :ssr true :compile-css true :exclude-js true
255255

256256
- name: 🔐 Google Auth
257257
uses: google-github-actions/[email protected]
@@ -318,7 +318,7 @@ jobs:
318318
run: |
319319
bb test:static-app :sha ${{ github.sha }} :skip-install true
320320
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk/book/${{ github.sha }}/book/index.html :index false :selector "h1:has-text(\"Book of Clerk\")"
321-
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk-ssr/build/${{ github.sha }}/index.html :index false :selector "h1:has-text(\"Rule 30\")"
321+
bb test:static-app :skip-install true :url https://snapshots.nextjournal.com/clerk-ssr/build/${{ github.sha }}/index.html :index true
322322
323323
deploy:
324324
needs: [build-and-upload-viewer-resources, test]

bb.edn

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

2121
build:js {:doc "Builds JS"
2222
:depends [yarn-install]
23-
:task (clojure "-M:sci:demo:dev release viewer")}
23+
:task (apply clojure "-M:sci:demo:dev release viewer" *command-line-args*)}
2424

2525
build+upload-viewer-resources {:doc "Refreshes assets stored on CDN (google storage)"
2626
:extra-paths ["src"]

deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
weavejester/dependency {:mvn/version "0.2.1"}
88
com.nextjournal/beholder {:mvn/version "1.0.3"}
99
org.flatland/ordered {:mvn/version "1.15.12"}
10-
io.github.nextjournal/markdown {:mvn/version "0.7.186"}
10+
io.github.nextjournal/markdown {:mvn/version "0.7.189"}
1111
babashka/process {:mvn/version "0.4.16"}
1212
io.github.nextjournal/dejavu {:git/sha "7276cd9cec1bad001d595b52cee9e83a60d43bf0"}
1313
io.github.babashka/sci.nrepl {:mvn/version "0.0.2"}

dev/nextjournal/clerk/ssr.clj

Lines changed: 0 additions & 67 deletions
This file was deleted.

notebooks/viewers/katex.clj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
;; # Katex
2+
3+
(ns katex
4+
(:require [nextjournal.clerk]
5+
[nextjournal.clerk.viewer]))
6+
7+
;; Inline formula: $x^2$
8+
9+
10+
;; Block level formula:
11+
;; $$x^2$$
12+
13+
;; Manual viewer:
14+
(nextjournal.clerk/with-viewer
15+
nextjournal.clerk.viewer/katex-viewer "x^2")
16+

render/deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
io.github.babashka/sci.configs {:git/sha "8253c69a537bcc82e8ff122e5f905fe9d1e303f0"
99
:exclusions [org.babashka/sci]}
1010
io.github.nextjournal/clojure-mode {:git/sha "1f55406087814a0dda6806396aa596dbe13ea302"}
11-
thheller/shadow-cljs {:mvn/version "3.0.4"}
11+
thheller/shadow-cljs {:mvn/version "3.2.0"}
1212
io.github.squint-cljs/cherry {;; :local/root "/Users/borkdude/dev/cherry"
1313
:git/sha "8de9f27"
1414
:git/tag "v0.4.26"

shadow-cljs.edn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
:compiler-options {:source-map true}
99
:dev {:modules {:viewer {:entries [devtools]}}}
1010
:modules {:viewer {:entries [nextjournal.clerk.sci-env
11-
nextjournal.clerk.trim-image]}}
11+
nextjournal.clerk.trim-image]}
12+
:katex {:entries [katex nextjournal.clerk.render.katex]
13+
:depends-on #{:viewer}
14+
:exports {renderToString nextjournal.clerk.render.katex/renderToString}}}
1215
:js-options {:output-feature-set :es8}
1316
:build-hooks [(shadow.cljs.build-report/hook
1417
{:output-to "report.html" :print-table true})]}}}

src/nextjournal/clerk/builder.clj

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -172,28 +172,46 @@
172172
(defn download-text-file [url]
173173
(:body (http/get url)))
174174

175+
(defn local-js [url tmp-dir]
176+
(if (str/starts-with? url "http")
177+
(let [tmp (-> tmp-dir
178+
(fs/file (-> (fs/file-name url)
179+
(str/split #"\?")
180+
(first)
181+
(str/replace #".js$" ".mjs")))
182+
(fs/delete-on-exit)
183+
str)
184+
src (download-text-file url)
185+
src (str/replace src "viewer.js" "viewer.mjs")]
186+
(spit tmp src)
187+
tmp)
188+
url))
189+
175190
(defn- node-ssr!
176191
[{:keys [viewer-js state]
177192
:or {viewer-js
178193
;; for local REPL testing
179194
"./public/js/viewer.js"}}]
180-
(let [viewer-js (if (str/starts-with? viewer-js "http")
181-
(let [tmp (-> (fs/create-temp-file {:suffix ".mjs"})
182-
(fs/file)
183-
(fs/delete-on-exit)
184-
str)
185-
src (download-text-file viewer-js)]
186-
(spit tmp src)
187-
tmp)
188-
viewer-js)
195+
(let [tmp-dir (fs/create-temp-dir)
196+
katex? (-> state :doc :katex?)
197+
[viewer-js katex-js] [(local-js viewer-js tmp-dir)
198+
(when katex?
199+
(local-js (str/replace viewer-js "viewer.js" "katex.js") tmp-dir))]
189200
in (str "import '" viewer-js "';"
190-
"globalThis.CLERK_SSR = true;"
191-
"console.log(nextjournal.clerk.sci_env.ssr(" (pr-str (pr-str state)) "))")]
192-
(sh {:in in}
193-
"node"
194-
"--abort-on-uncaught-exception"
195-
"--input-type=module"
196-
"--trace-warnings")))
201+
(when katex?
202+
(format (str "import * as katex from \"%s\";"
203+
"globalThis.clerk$katex = katex;")
204+
katex-js))
205+
"globalThis.CLERK_SSR = true;
206+
new Promise((resolve) => { setTimeout(resolve, 2000)});\n"
207+
"console.log(nextjournal.clerk.sci_env.ssr(" (pr-str (pr-str state )) "))")]
208+
#_(spit "in.mjs" in)
209+
(sh
210+
{:out :string :in in :err :inherit}
211+
"node"
212+
"--abort-on-uncaught-exception"
213+
"--input-type=module"
214+
"--trace-warnings")))
197215

198216
(comment
199217
(declare so) ;; captured in REPL in ssr! function
@@ -219,8 +237,10 @@
219237
(throw (ex-info (str "Clerk ssr! failed\n" out "\n" err) result)))))
220238

221239
(defn cleanup [build-opts]
222-
(select-keys build-opts
223-
[:package :render-router :path->doc :current-path :resource->url :exclude-js? :index :html]))
240+
(cond-> (select-keys build-opts
241+
[:package :render-router :path->doc :current-path :resource->url :exclude-js? :index :html])
242+
(-> build-opts :doc :katex?)
243+
(assoc :katex? true)))
224244

225245
(defn write-static-app!
226246
[opts docs]
@@ -244,7 +264,7 @@
244264
(dissoc :path->doc)
245265
cleanup))))))
246266
(when browse?
247-
(browse/browse-url (if-let [server-url (and (= out-path "public/build") (webserver/server-url))]
267+
(browse/browse-url (if-let [server-url (and (= "public/build" out-path) (webserver/server-url))]
248268
(str server-url "/build/")
249269
(-> index-html fs/absolutize .toString path-to-url-canonicalize))))
250270
{:docs docs
@@ -386,11 +406,12 @@
386406
(build-static-app! {:index "notebooks/document_linking.clj"
387407
:paths ["notebooks/viewers/html.clj" "notebooks/rule_30.clj"]})
388408

409+
;; document is not defined
389410
(build-static-app! {:ssr? true
390411
:exclude-js? true
391412
;; test against cljs release `bb build:js`
392413
:resource->url {"/js/viewer.js" "./build/viewer.js"}
393-
:index "notebooks/rule_30.clj"})
414+
:index "notebooks/viewers/katex.clj"})
394415

395416
(build-static-app! {:ssr? true
396417
:exclude-js? true

src/nextjournal/clerk/render.cljs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,9 +981,14 @@
981981
default-loading-view))))
982982

983983
(defn render-katex [tex-string {:keys [inline?]}]
984-
(let [katex (hooks/use-d3-require "[email protected]")]
984+
(let [katex (if (some-> (unchecked-get js/globalThis "process")
985+
(unchecked-get "versions")
986+
(unchecked-get "node"))
987+
(unchecked-get js/globalThis "clerk$katex")
988+
(hooks/use-d3-require "[email protected]"))]
985989
(if katex
986-
[:span {:dangerouslySetInnerHTML (r/unsafe-html (.renderToString katex tex-string (j/obj :displayMode (not inline?) :throwOnError false)))}]
990+
(let [html (.renderToString katex tex-string (j/obj :displayMode (not inline?) :throwOnError false))]
991+
[:span {:dangerouslySetInnerHTML (r/unsafe-html html)}])
987992
default-loading-view)))
988993

989994
(defn render-mathjax [value]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(ns nextjournal.clerk.render.katex
2+
(:require ["katex" :as katex]))
3+
4+
(defn renderToString [s]
5+
(katex/renderToString s))

0 commit comments

Comments
 (0)