Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move remaining inlined :render-fn forms to render.cljs #705

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 86 additions & 4 deletions src/nextjournal/clerk/render.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@
(defn render-unreadable-edn [edn]
[:span.inspected-value.whitespace-nowrap.cmt-default edn])

(def !read-string-without-tag-table
(delay (eval 'nextjournal.clerk.viewer/read-string-without-tag-table)))

(defn render-read+inspect
[x] (try [inspect @!read-string-without-tag-table]
(catch js/Error _e
(render-unreadable-edn x))))

(defn error-badge [& content]
[:div.bg-red-50.rounded-sm.text-xs.text-red-400.px-2.py-1.items-center.sans-serif.inline-flex
[:svg.h-4.w-4.text-red-400 {:xmlns "http://www.w3.org/2000/svg" :viewBox "0 0 20 20" :fill "currentColor" :aria-hidden "true"}
Expand Down Expand Up @@ -333,6 +341,9 @@
(get-in x [:nextjournal/render-opts :id])
(with-meta {:key (str (get-in x [:nextjournal/render-opts :id]) "@" @!eval-counter)})))))

(defn render-children [xs opts]
(into [:<>] (nextjournal.clerk.render/inspect-children opts) xs))

(def expand-style
["cursor-pointer"
"bg-indigo-50"
Expand Down Expand Up @@ -435,6 +446,18 @@
[:span.cmt-number.inspected-value
(if (js/Number.isNaN num) "NaN" (str num))])

(defn render-hex-number [num] (render-number (str "0x" (.toString (js/Number. num) 16))))

(defn render-map-entry [xs opts]
(into [:<>] (comp (nextjournal.clerk.render/inspect-children opts) (interpose " ")) xs))

(defn render-symbol [x] [:span.cmt-keyword.inspected-value (str x)])
(defn render-keyword [x] [:span.cmt-atom.inspected-value (str x)])
(defn render-nil [_] [:span.cmt-default.inspected-value "nil"])
(defn render-boolean [x] [:span.cmt-bool.inspected-value (str x)])
(defn render-char [c] [:span.cmt-string.inspected-value "\\" c])
(defn render-var [x] [:span.inspected-value [:span.cmt-meta "#'" (str x)]])

(defn sort! [!sort i k]
(let [{:keys [sort-key sort-order]} @!sort]
(reset! !sort {:sort-index i
Expand Down Expand Up @@ -526,12 +549,30 @@
[:div.rounded.border.border-red-200.border-t-0.overflow-hidden
[throwable-view ex opts]]))

(defn render-tagged-value
([tag value] (render-tagged-value {:space? true} tag value))
(defn render-tagged-value*
([tag value] (render-tagged-value* {:space? true} tag value))
([{:keys [space?]} tag value]
[:span.inspected-value.whitespace-nowrap
[:span.cmt-meta tag] (when space? nbsp) value]))


(defn render-tagged-value [{:keys [tag value space?]} opts]
[render-tagged-value
{:space? (:nextjournal/value space?)}
(str "#" (:nextjournal/value tag))
[nextjournal.clerk.render/inspect-presented value]])

(defn render-js-object [v opts]
[render-tagged-value* {:space? true}
"#js"
[nextjournal.clerk.render/render-map v opts]])

(defn render-js-array [v opts]
[render-tagged-value* {:space? true}
"#js"
[nextjournal.clerk.render/render-coll v opts]])


(defn set-viewers! [scope viewers]
#_(js/console.log :set-viewers! {:scope scope :viewers viewers})
(swap! !viewers assoc scope (vec viewers))
Expand Down Expand Up @@ -695,12 +736,16 @@
(let [re-eval (fn [{:keys [form]}] (viewer/->viewer-fn form))]
(w/postwalk (fn [x] (cond-> x (viewer/viewer-fn? x) re-eval)) doc)))

(defn replace-viewer-fns [{:as doc :keys [name->viewer]}]
(assoc (w/postwalk-replace name->viewer doc)
:name->viewer name->viewer))

(defn ^:export set-state! [{:as state :keys [doc]}]
(when (contains? state :doc)
(when (exists? js/window)
;; TODO: can we restore the scroll position when navigating back?
(.scrollTo js/window #js {:top 0}))
(reset! !doc doc))
(reset! !doc (replace-viewer-fns doc)))
;; (when (and error (contains? @!doc :status))
;; (swap! !doc dissoc :status))
(when (remount? doc)
Expand All @@ -713,7 +758,7 @@

(defn patch-state! [{:keys [patch]}]
(if (remount? patch)
(do (swap! !doc #(re-eval-viewer-fns (apply-patch % patch)))
(do (swap! !doc #(re-eval-viewer-fns (replace-viewer-fns (apply-patch % patch))))
;; TODO: figure out why it doesn't work without `js/setTimeout`
(js/setTimeout #(swap! !eval-counter inc) 10))
(swap! !doc apply-patch patch)))
Expand Down Expand Up @@ -967,6 +1012,9 @@
[:span {:dangerouslySetInnerHTML {:__html (.renderToString katex tex-string (j/obj :displayMode (not inline?) :throwOnError false))}}]
default-loading-view)))

(defn render-katex-inline [tex opts]
(nextjournal.clerk.render/render-katex tex (assoc opts :inline? true)))

(defn render-mathjax [value]
(let [mathjax (hooks/use-d3-require "https://run.nextjournalusercontent.com/data/QmQadTUYtF4JjbwhUFzQy9BQiK52ace3KqVHreUqL7ohoZ?filename=es5/tex-svg-full.js&content-type=application/javascript")
ref-fn (react/useCallback (fn [el]
Expand Down Expand Up @@ -1027,10 +1075,44 @@
[render-code code-string (assoc opts :language "clojure")]]])))


(defn render-example [{:keys [form val]} opts]
[:div.mb-3.last:mb-0
[:div.bg-slate-100.dark:bg-slate-800.px-4.py-2.border-l-2.border-slate-200.dark:border-slate-700
(inspect-presented opts form)]
[:div.pt-2.px-4.border-l-2.border-transparent
(inspect-presented opts val)]])

(defn render-examples [examples opts]
[:div
[:div.uppercase.tracking-wider.text-xs.font-sans.font-bold.text-slate-500.dark:text-white.mb-2.mt-3 "Examples"]
(into [:div] (inspect-children opts) examples)])

(defn render-row [items opts]
(into [:div {:class "md:flex md:flex-row md:gap-4 not-prose"
:style opts}]
(map (fn [item]
[:div.flex.items-center.justify-center.flex-auto
[inspect-presented opts item]]))
items))

(defn render-col [items opts]
(into [:div {:class "md:flex md:flex-col md:gap-4 clerk-grid not-prose"
:style opts}]
(map (fn [item]
[:div.flex.items-center.justify-center
[inspect-presented opts item]]))
items))

(defn render-empty-fragment [_ _] [:<>])

(defn url-for [{:as src :keys [blob-id]}]
(if (string? src)
src
(str "/_blob/" blob-id (when-let [opts (seq (dissoc src :blob-id))]
(str "?" (opts->query opts))))))

(defn render-image [blob-or-url]
[:div.flex.flex-col.items-center.not-prose
[:img {:src (url-for blob-or-url)}]])

(def consume-view-context view-context/consume)
76 changes: 21 additions & 55 deletions src/nextjournal/clerk/viewer.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@
(->> (mapv (partial with-viewer
(cond-> result-viewer
(hidden-viewer-eval-result? cell)
(assoc :render-fn '(fn [_ _] [:<>]))))))))
(assoc :render-fn 'nextjournal.clerk.render/render-empty-fragment)))))))

(defn transform-cell [cell]
(let [{:keys [code? result?]} (->visibility cell)]
Expand All @@ -677,7 +677,7 @@
(def cell-viewer
{:name `cell-viewer
:transform-fn (update-val transform-cell)
:render-fn '(fn [xs opts] (into [:<>] (nextjournal.clerk.render/inspect-children opts) xs))})
:render-fn 'nextjournal.clerk.render/render-children})

(defn lift-block-images
"Lift an image node to top-level when it is the only child of a paragraph."
Expand Down Expand Up @@ -750,7 +750,7 @@
(def table-missing-viewer
{:name `table-missing-viewer
:pred #{:nextjournal/missing}
:render-fn '(fn [x] [:<>])})
:render-fn 'nextjournal.clerk.render/render-empty-fragment})

(def table-markup-viewer
{:name `table-markup-viewer
Expand Down Expand Up @@ -809,7 +809,7 @@
;; formulas
{:name :nextjournal.markdown/formula
:transform-fn (comp :text ->value)
:render-fn '(fn [tex] (nextjournal.clerk.render/render-katex tex {:inline? true}))}
:render-fn 'nextjournal.clerk.render/render-katex-inline}
{:name :nextjournal.markdown/block-formula
:transform-fn (comp :text ->value)
:render-fn 'nextjournal.clerk.render/render-katex}
Expand Down Expand Up @@ -855,7 +855,7 @@
:transform-fn (fn [wrapped-value] (with-viewer `html-viewer [:sup.sidenote-ref (-> wrapped-value ->value :ref inc)]))}])

(def char-viewer
{:name `char-viewer :pred char? :render-fn '(fn [c] [:span.cmt-string.inspected-value "\\" c])})
{:name `char-viewer :pred char? :render-fn 'nextjournal.clerk.render/char-viewer})

(def string-viewer
{:name `string-viewer
Expand All @@ -874,27 +874,25 @@
(instance? clojure.lang.BigInt %)) pr-str))])})

(def number-hex-viewer
{:name `number-hex-viewer :render-fn '(fn [num] (nextjournal.clerk.render/render-number (str "0x" (.toString (js/Number. num) 16))))})
{:name `number-hex-viewer :render-fn 'nextjournal.clerk.render/render-hex-number})

(def symbol-viewer
{:name `symbol-viewer :pred symbol? :render-fn '(fn [x] [:span.cmt-keyword.inspected-value (str x)])})
{:name `symbol-viewer :pred symbol? :render-fn 'nextjournal.clerk.render/render-symbol})

(def keyword-viewer
{:name `keyword-viewer :pred keyword? :render-fn '(fn [x] [:span.cmt-atom.inspected-value (str x)])})
{:name `keyword-viewer :pred keyword? :render-fn 'nextjournal.clerk.render/render-keyword})

(def nil-viewer
{:name `nil-viewer :pred nil? :render-fn '(fn [_] [:span.cmt-default.inspected-value "nil"])})
{:name `nil-viewer :pred nil? :render-fn 'nextjournal.clerk.render/render-nil})

(def boolean-viewer
{:name `boolean-viewer :pred boolean? :render-fn '(fn [x] [:span.cmt-bool.inspected-value (str x)])})
{:name `boolean-viewer :pred boolean? :render-fn 'nextjournal.clerk.render/render-boolean})

(def map-entry-viewer
{:name `map-entry-viewer :pred map-entry? :render-fn '(fn [xs opts] (into [:<>] (comp (nextjournal.clerk.render/inspect-children opts) (interpose " ")) xs)) :page-size 2})
{:name `map-entry-viewer :pred map-entry? :render-fn 'nextjournal.clerk.render/render-map-entry :page-size 2})

(def read+inspect-viewer
{:name `read+inspect-viewer :render-fn '(fn [x] (try [nextjournal.clerk.render/inspect (nextjournal.clerk.viewer/read-string-without-tag-table x)]
(catch js/Error _e
(nextjournal.clerk.render/render-unreadable-edn x))))})
{:name `read+inspect-viewer :render-fn 'nextjournal.clerk.render/render-read+inspect})

(def vector-viewer
{:name `vector-viewer :pred vector? :render-fn 'nextjournal.clerk.render/render-coll :opening-paren "[" :closing-paren "]" :page-size 20})
Expand All @@ -914,7 +912,7 @@
{:name `var-viewer
:pred var?
:transform-fn (comp #?(:cljs var->symbol :clj symbol) ->value)
:render-fn '(fn [x] [:span.inspected-value [:span.cmt-meta "#'" (str x)]])})
:render-fn 'nextjournal.clerk.render/render-var})

(defn ->opts [wrapped-value]
(select-keys wrapped-value [:nextjournal/budget :nextjournal/css-class :nextjournal/width :nextjournal/render-opts
Expand Down Expand Up @@ -961,9 +959,7 @@
:nextjournal/width (image-width image)}
mark-presented))])
:name `image-viewer
:render-fn '(fn [blob-or-url] [:div.flex.flex-col.items-center.not-prose
[:img {:src #?(:clj (nextjournal.clerk.render/url-for blob-or-url)
:cljs blob-or-url)}]])})
:render-fn 'nextjournal.clerk.render/render-image})

(def ideref-viewer
{:name `ideref-viewer
Expand Down Expand Up @@ -1038,21 +1034,10 @@
(update-val (fn [v] (if (string? v) v (str/trim (with-out-str (pprint/pprint v)))))))})

(def row-viewer
{:name `row-viewer :render-fn '(fn [items opts]
(let [item-count (count items)]
(into [:div {:class "md:flex md:flex-row md:gap-4 not-prose"
:style opts}]
(map (fn [item]
[:div.flex.items-center.justify-center.flex-auto
(nextjournal.clerk.render/inspect-presented opts item)])) items)))})
{:name `row-viewer :render-fn 'nextjournal.clerk.render/render-row})

(def col-viewer
{:name `col-viewer :render-fn '(fn [items opts]
(into [:div {:class "md:flex md:flex-col md:gap-4 clerk-grid not-prose"
:style opts}]
(map (fn [item]
[:div.flex.items-center.justify-center
(nextjournal.clerk.render/inspect-presented opts item)])) items))})
{:name `col-viewer :render-fn 'nextjournal.clerk.render/render-col})

(def table-viewers
[(-> string-viewer
Expand Down Expand Up @@ -1111,14 +1096,9 @@

(def tagged-value-viewer
{:name `tagged-value-viewer
:render-fn '(fn [{:keys [tag value space?]} opts]
(nextjournal.clerk.render/render-tagged-value
{:space? (:nextjournal/value space?)}
(str "#" (:nextjournal/value tag))
[nextjournal.clerk.render/inspect-presented value]))
:render-fn 'nextjournal.clerk.render/render-tagged-value
:transform-fn mark-preserve-keys})


#?(:cljs
(def js-promise-viewer
{:name `js-promise-viewer :pred #(instance? js/Promise %) :render-fn 'nextjournal.clerk.render/render-promise}))
Expand All @@ -1129,9 +1109,7 @@
:pred goog/isObject
:page-size 20
:opening-paren "{" :closing-paren "}"
:render-fn '(fn [v opts] (nextjournal.clerk.render/render-tagged-value {:space? true}
"#js"
(nextjournal.clerk.render/render-map v opts)))
:render-fn 'nextjournal.clerk.render/render-js-object
:transform-fn (update-val (fn [^js o]
(into {}
(comp (remove (fn [k] (identical? "function" (goog/typeOf (j/get o k)))))
Expand All @@ -1148,10 +1126,7 @@
{:name `js-array-viewer
:pred js-iterable?
:transform-fn (update-val seq)
:render-fn '(fn [v opts]
(nextjournal.clerk.render/render-tagged-value {:space? true}
"#js"
(nextjournal.clerk.render/render-coll v opts)))
:render-fn 'nextjournal.clerk.render/render-js-array
:opening-paren "[" :closing-paren "]"
:page-size 20}))

Expand Down Expand Up @@ -1977,21 +1952,12 @@
:transform-fn (fn [wrapped-value]
(-> wrapped-value
mark-preserve-keys
(assoc :nextjournal/viewer {:render-fn '(fn [{:keys [form val]} opts]
[:div.mb-3.last:mb-0
[:div.bg-slate-100.dark:bg-slate-800.px-4.py-2.border-l-2.border-slate-200.dark:border-slate-700
(nextjournal.clerk.render/inspect-presented opts form)]
[:div.pt-2.px-4.border-l-2.border-transparent
(nextjournal.clerk.render/inspect-presented opts val)]])})
(assoc :nextjournal/viewer {:render-fn 'nextjournal.clerk.render/render-example})
(update-in [:nextjournal/value :val] maybe-wrap-var-from-def (get-in wrapped-value [:nextjournal/value :form]))
(update-in [:nextjournal/value :form] code)))})

(def examples-viewer
{:name `examples-viewer
:transform-fn (update-val (fn [examples]
(mapv (partial with-viewer example-viewer) examples)))
:render-fn '(fn [examples opts]
[:div
[:div.uppercase.tracking-wider.text-xs.font-sans.font-bold.text-slate-500.dark:text-white.mb-2.mt-3 "Examples"]
(into [:div]
(nextjournal.clerk.render/inspect-children opts) examples)])})
:render-fn 'nextjournal.clerk.render/render-examples})
Loading