Skip to content

Commit

Permalink
More context in viewers
Browse files Browse the repository at this point in the history
  • Loading branch information
mk authored and zampino committed Nov 20, 2023
1 parent b4e201f commit 60afdf9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
44 changes: 44 additions & 0 deletions notebooks/viewers/context.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
;; # 🪬 Viewer Context

(ns viewers.context
(:require [nextjournal.clerk :as clerk]
[nextjournal.clerk.viewer :as viewer]))

;; A viewer's `:pred` function can perform viewer selection based on a value.

;; It would sometimes be useful to have more context available. Examples of this are:
;;
;; * Selecting a viewer based on the originating form
;; * Selecting a different viewer based on additional context like `:path`
;; * Bring Clerk's handling of out-of-band metadata like `::clerk/visibility` and `::clerk/width` into userspace

;; To make this a backwards-compatible change, we can opt into these
;; richer predicate functions using a map with a key:

(def cljc-viewer
{:pred {:wrapped (fn [{:keys [form]}]
(contains? (meta form) :cljc))}
:transform-fn (fn [{:keys [form]}]
(clerk/eval-cljs form))})

;; We should probably use a namespaced keyword to disambiguate it.

;; Also considered letting the pred function opt in using
;; metadata. Rejected this because it's invisible and doesn't work for
;; e.g. keywords.

^::clerk/no-cache
(clerk/add-viewers! [cljc-viewer])


;; Now what can we use this for? We can now, for example, create a
;; viewer in userspace that evalautes a given form in Clojure and sci,
;; allowing us to use it on both sides.

^:cljc
(defn my-greet-fn [x]
(str "Greetings from " x))

(my-greet-fn "Clojure")

(clerk/eval-cljs '(my-greet-fn "ClojureScript"))
12 changes: 8 additions & 4 deletions src/nextjournal/clerk/viewer.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@


(defn transform-result [{:as wrapped-value :keys [path]}]
(let [{:as _cell :keys [form id settings] ::keys [result doc]} (:nextjournal/value wrapped-value)
(let [{:as cell :keys [form id settings] ::keys [result doc]} (:nextjournal/value wrapped-value)
{:keys [static-build? bundle?]} doc
{:nextjournal/keys [value blob-id viewers]} result
blob-mode (cond
Expand All @@ -522,6 +522,7 @@
(select-keys (keys viewer-opts-normalization))
(set/rename-keys viewer-opts-normalization))
{:as to-present :nextjournal/keys [auto-expand-results?]} (merge (dissoc (->opts wrapped-value) :!budget :nextjournal/budget)
(dissoc cell :result)
opts-from-block
(ensure-wrapped-with-viewers (or viewers (get-viewers (get-*ns*))) value))
presented-result (-> (present to-present)
Expand Down Expand Up @@ -1358,9 +1359,12 @@
(throw (ex-info (str "cannot find viewer named " selected-viewer)
{:selected-viewer selected-viewer :viewers viewers})))
selected-viewer))
(find-viewer viewers (let [v (->value x)]
(fn [{:keys [pred]}]
(and (ifn? pred) (pred v)))))
(find-viewer viewers (fn [{:keys [pred]}]
(and (ifn? pred) (if-let [wrapped-pred (and (map? pred)
(ifn? (:wrapped pred))
(:wrapped pred))]
(wrapped-pred x)
(pred (->value x))))))
(throw (ex-info (str "cannot find matching viewer for value")
{:value (->value x) :viewers viewers :x x}))))

Expand Down

0 comments on commit 60afdf9

Please sign in to comment.