clerk

Jeremy 2025-01-19T09:16:20.155439Z

Does the method for including cljs code at https://clerk-utils.mentat.org/#custom-clojurescript-builds still work? I've been at it for a while now, but keep encountering one error after another.

(build/serve! {:browse? true :port 7779
               :paths ["src/lab/nb/*"]
               :index "src/lab/nb/index.clj"
               :cljs-namespaces ['lab.nb.viewers.custom 'lab.sci]})
The browser opens up, but no index page loads. I get this error on during build):
Encountered error when macroexpanding sci.impl.copy-vars/copy-var.
NullPointerException: Cannot invoke "clojure.lang.IFn.invoke(Object, Object)" because the return value of "clojure.lang.Var.getRawRoot()" is null
	sci.impl.copy-vars/var-meta (copy_vars.cljc:66)
Clearing :cljs-namespaces makes serve work just fine

Jeremy 2025-01-25T20:57:19.559049Z

I used the very basic template lab.nb.viewers.custom:

(ns lab.nb.viewers.custom)

(defn sum [x y]
  (+ x y))
lab.sci:
(ns lab.sci
  (:require #_[nextjournal.clerk.sci-env]
            [lab.nb.viewers.custom]
            [sci.ctx-store]
            [sci.core :as sci]))

(def custom-namespace
  (sci/copy-ns lab.nb.viewers.custom
               (sci/create-ns 'lab.nb.viewers.custom)))

(sci.ctx-store/swap-ctx!
  sci/merge-opts
  {:classes {'Math js/Math}
   ;; :aliases    {'cust 'lab.nb.viewers.custom}
   :namespaces
   {'lab.nb.viewers.custom custom-namespace}})

Nguyen Hoai Nam 2025-01-22T00:56:36.264299Z

It still works for me. Can you show your lab.nb.viewers.custom and lab.sci namespaces?

Nguyen Hoai Nam 2025-01-27T05:19:38.589819Z

Can you try replacing + with vector? + is both a macro and a function, so I’m guessing it’s interfering with the macroexpansion somehow. (I might be very wrong.)

peterh 2025-01-19T15:21:46.650389Z

I want to share some global state between render functions that is available in the static build of my notebook (which is why I can’t use Clerk Sync), so I can add some interactivity for “explorable explanations”. Of course, it can only stay in cljs-land, which is not a problem for me. My approach is to use clerk/eval-cljs to define a ratom and deref/mutate that within custom render functions. It work fine so far, but I just want to ask if there is a different approach that you recommend instead or if this is the way to do it. Example:

(clerk/eval-cljs '(def !state (reagent.core/atom 0)))

(clerk/with-viewer
    {:render-fn
     `(fn []
        [:div
         [:input
          {:type "button"
           :value "increment"
           :on-click #(swap! !state inc)}]
         [:p (str @!state)]])}
    {})
And then you can also use that state elsewhere:
(clerk/with-viewer
    {:render-fn
     `(fn []
        [:p "The value of the counter is " (str @!state) "!"])}
    {})

mkvlr 2025-01-19T20:21:05.660259Z

looks good, it’s how I’d do it as well

👍 1