Fork me on GitHub

Is there a way to render Clojure datastructure expanded?


I mean the following (also see the unexpected } marked by green question mark)


does that do what you want?


it seems there’s a bug related to out parens alignment in clerk/example , could you file an issue with that screenshot?


hmmm... it doesn't work...


on "0.13.842"


is it only namespace related?


maybe it doesn’t work in clerk/example?


when I include it at the namespace level: it doesn't work in clerk/example indeed. Also, it expands only first level.


It would be great to have ability to annotate each form individually and expansion should be full (or configurable)


it should work at individual level as well


@U1EP3BZ3Q agreed! all of these kinds of tunables are meant to be cascading


hrm, seems like it doesn’t yet and I misremembered. Agree it should work like this, issue welcome

👍 2

^{:nextjournal.clerk/opts {:auto-expand-results? true}}
{:hello "world 👋" :tacos (map (comp #(map (constantly '🌮) %) range) (range 1 100)) :zeta {:chars [\w \a \v \e] :set (set (range 100))}}


it does work like this but maybe that’s not the ideal api


Cool! I don't know how many options are possible to set via ::clerk/opts but maybe it's good to have them at top level?

Jakub Holý (HolyJak)16:04:17

It would be great to have one place in the Book documenting these options 🙏


I had no chance to test it yesterday. I've tested today and it still doesn't work for me. Maybe it's not available in the latest version (842)?


made this consistent


^{:nextjournal.clerk/auto-expand-results? true}
{:hello "world 👋" :tacos (map (comp #(map (constantly '🌮) %) range) (range 1 100)) :zeta {:chars [\w \a \v \e] :set (set (range 100))}}


so this works now

❤️ 2

also documented it in the book (still needs a deploy)

🙌 2

Hey guys! First of all love the project, even though I was skeptical at first. Got a question though regarding defining user input. Not sure why my solution is not working as intended and thought that maybe you may help. I just wanted to make an input that would update the state only when the user submitted it (on enter). However it's not updating the local state atom and don't know whether I got rusty with frontend or there's a reason why it shouldn't work. In the message thread I'm posting a code sample that is heavily based on


(def text-input
  (assoc v/viewer-eval-viewer
         '(fn [text-state]
            (let [input-state (atom "")]
              [:input {:type :text :placeholder "Domain name" :value @input-state
                       :class "px-3 py-3 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-sm border border-blueGray-300 outline-none focus:outline-none focus:ring w-full"
                       :on-change #(reset! input-state (.. % -target -value))
                       :on-key-down #(when (= :enter (.-key %))
                                       (reset! text-state @input-state))}]))))

^{::clerk/sync true ::clerk/viewer text-input}
(defonce text-state (atom ""))


Ok, so I got it sorted. Here's how for the future generations: Instead of

(let [input-state (atom "")]
I should've used
(reagent.core/with-let [input-state (reagent.core/atom "")]
Here's the served as an inspiration

Charles Comstock20:04:04

Is there a nice example somewhere for rendering SVG or png output from an external source that requires shelling out like PlantUML or Graphviz? I found the mermaid example that parses in the browser, but curious if there is a quick example somewhere for importing Graphviz or PlantUML. I'm sure I can figure it out myself if not, but seemed worth checking if there was prior art to crib from as I suspect the caching might be a little tricky.


I do something similar for the Basically, I hash the input arguments to produce a filename and only regenerate the output if the file doesn't already exist. It's a little clunky since you still end up with a temp folder, but maybe it gives you a starting point. Also, graphviz doesn't technically require shelling out if you call the underlying c library 😛.

Charles Comstock21:04:18

Cool, thanks, that looks very helpful


You might also be able to find some prior art at

Charles Comstock21:04:38

Thanks, not seeing any shell out examples in that set, but looks like there are some other useful tricks in it


clerk/html can display svg (via hiccup or an html string), and you can shell out to however you like


and depending on your use case you will also want to disable caching for that form using ^:nextjournal.clerk/no-cache

Charles Comstock19:04:16

Thanks, I also tracked down an earlier example using mermaid and a couple other examples that do shell out so I think have that covered, unfortunately as mentioned in the next question, slide show mode is not rendering BufferedImage examples. Not sure if that's only a limitation for png/gif or svg as well, but I think that's a larger blocker.


looking into that…

Charles Comstock19:04:50

Thanks! I just posted a minimal example there if that helps at all.

Charles Comstock21:04:56

Another question about images. I assumed that they should be visible in the live notebook viewer, but I'm getting a broken image picture in chrome. I'm seeing this result using ImageIO/read, clerk/image for both local files and the remote URLs shown in the example notebook on images. If I eval (clerk/image "") in cider, it spits out both the BufferedImage and corresponding clerk image viewer, but the blob url listed in the img tag chrome doesn't appear to exist. It's in the form _blob/sha-cache?path=[1 0] , and visiting directly gives a 404. From within the notebook if I inspect the file using (.exists (io/file "path")) it appears to have found the file, but somehow it's getting lost between clerk and the browser. I am using clerk version ef2828d20a9fe039e693487f8d1fce4637109fc2. Is this a bug, or are images only visible after publishing, or am I doing something else wrong?

Charles Comstock21:04:50

I'm also attempting to do this inside of a clerk slideshow if somehow that is relevant.

Charles Comstock22:04:36

Hmm. Tried same example outside of the slide viewer and it worked so will try and determine why it doesn't like nested images.

Charles Comstock22:04:59

So I guess the reframed question is does anyone know why slideshow might break the image viewer? Does it perhaps need a custom block in: ?


The slideshow viewer is very much a proof of concept thing at the moment. It would need a good bit more work to be feature complete. PRs welcome! 🙂

Charles Comstock17:04:47

Happy to take a look, but I guess was more asking if there was any idea where to start? I've tracked down the image-viewer where I can see it encoding a :nextjournal/value for the png, and I've tracked down the serve-blob method in the webserver, but I haven't tracked down where the blob is uploaded to the blob cache? I was hoping by tracing that I could determine if the blob was actually uploaded, or if it's just mangling the hash somewhere? Similarly, I'm guessing that manual unwrapping of the markdown-viewer and code-block-viewer for the slideshow is relevant, but I'm not clear on what should be unwrapped there for images so that it actually uploads or renders correctly?

Charles Comstock19:04:35

btw the minimal example to show this is:

(ns example-talk
  #:nextjournal.clerk{:visibility {:code :hide}}
   [ :as io]
   [nextjournal.clerk :as clerk]
   [nextjournal.clerk-slideshow :as slideshow])
   (javax.imageio ImageIO)))

;; ---
;; # Testing

^{::clerk/visibility {:result :hide}}
  (clerk/add-viewers! [slideshow/viewer])
  (clerk/reset-viewers! clerk/default-viewers))

(ImageIO/read (io/file "test-image.png"))
First render that works, but evaluating the add-viewers in the comment breaks the image, and then resetting to default viewer brings it back.


yep can repro


filed as I don’t have time to fix it now, we should get around to it next week

Charles Comstock20:04:01

Thanks, I'll add my example there then.

Charles Comstock20:04:49

hmm, I tried updating my deps sha for clerk to point at that revision, but unfortunately still isn't working for me with slideshow. Really appreciate you taking a look though.

Charles Comstock20:04:29

Oh wait, problem might be on my end, sorry give me a minute

Charles Comstock20:04:03

yep that's working! Thank you! For some reason it still broke if I evaluated the add-viewers! line but once I added back to the top level it worked great!.

🙌 2

cool, thanks for the report!