Skip to content

Commit aae674d

Browse files
committed
Merge branch 'main' into cljs-deps-perf
2 parents c2fbdfe + cfdcb9f commit aae674d

10 files changed

Lines changed: 96 additions & 130 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Changes can be:
2020

2121
* 🐞 Always analyze doc (but not deps) when no-cache is set, @borkdude, fixes [#781](https://github.com/nextjournal/clerk/issues/781).
2222

23+
* 🐞 Fix browse when using random port by passing 0, fixes [#801](https://github.com/nextjournal/clerk/issues/801)
24+
2325
## 0.18.1158 (2025-11-17)
2426

2527
* ⭐️ Support macros defined in notebooks, @borkdude, fixes [#746](https://github.com/nextjournal/clerk/issues/746)

bb.edn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{:min-bb-version "1.12.206"
22
:paths ["bb"]
3-
:deps {io.github.nextjournal/dejavu {:git/sha "7276cd9cec1bad001d595b52cee9e83a60d43bf0"}
4-
io.github.nextjournal/cas-client {:git/sha "114d3d88d38a2068ec844b0e6c808eaaa6aa64ef"}}
3+
:deps {io.github.nextjournal/cas-client {:git/sha "114d3d88d38a2068ec844b0e6c808eaaa6aa64ef"}
4+
io.github.nextjournal/clerk {:local/root "."}}
55
:tasks
66
{:requires
77
([tasks :as t]

deps.edn

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

2424
rewrite-clj/rewrite-clj {:mvn/version "1.1.45"}
2525

26-
juji/editscript {:mvn/version "0.6.4"}}
26+
juji/editscript {:mvn/version "0.7.0"}}
2727

2828
:aliases {:nextjournal/clerk {:extra-deps {org.clojure/clojure {:mvn/version "1.11.1"} ;; for `:as-alias` support in static build
2929
org.slf4j/slf4j-nop {:mvn/version "2.0.7"}

notebooks/js_import.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@
4242
;; or use `js/import` directly:
4343
(nextjournal.clerk/with-viewer
4444
'(fn [_]
45-
(let [confetti (nextjournal.clerk.render.hooks/use-promise (js/import "https://cdn.skypack.dev/canvas-confetti"))]
45+
(let [confetti (nextjournal.clerk.render.hooks/use-promise (js/import "https://cdn.jsdelivr.net/npm/canvas-confetti/+esm"))]
4646
[:button.bg-teal-500.hover:bg-teal-700.text-white.font-bold.py-2.px-4.rounded.rounded-full.font-sans
4747
(if confetti {:on-click #(.default confetti)} {:class "bg-gray-200"}) "Peng 🎉!"])) {})

src/nextjournal/clerk/always_array_map.clj

Lines changed: 60 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
(ns nextjournal.clerk.always-array-map
22
"A persistent data structure that is based on array-map, but doesn't turn into a hash-map by using assoc etc.
3-
Prints like a normal Clojure map in the order of insertion."
4-
(:require [nextjournal.clerk.utils :as utils]))
3+
Prints like a normal Clojure map in the order of insertion.")
54

65
(set! *warn-on-reflection* true)
76

@@ -10,100 +9,72 @@
109

1110
(declare ->AlwaysArrayMap)
1211

13-
(utils/if-bb
14-
(defn ->AlwaysArrayMap [m]
15-
(proxy [clojure.lang.APersistentMap clojure.lang.IMeta clojure.lang.IObj]
16-
[]
17-
(valAt
18-
([k]
19-
(get m k))
20-
([k default-value]
21-
(get m k default-value)))
22-
(iterator []
23-
(.iterator ^java.lang.Iterable m))
24-
25-
(containsKey [k] (contains? m k))
26-
(entryAt [k] (when (contains? m k)
27-
(get this k)))
28-
(equiv [other] (= m other))
29-
(empty [] (empty m))
30-
(count [] (count m))
31-
(assoc [k v] (if (< (count m) 8)
32-
(->AlwaysArrayMap (assoc m k v))
33-
(->AlwaysArrayMap (assoc-after m k v))))
34-
(without [k] (->AlwaysArrayMap (dissoc m k)))
35-
(seq [] (seq m))
36-
; a lot of map users expect meta to work
37-
(meta [] (meta m))
38-
(withMeta [meta] (->AlwaysArrayMap (with-meta m meta)))))
39-
40-
(deftype AlwaysArrayMap [^clojure.lang.PersistentArrayMap the-map]
41-
clojure.lang.ILookup
42-
(valAt [_ k]
43-
(get the-map k))
44-
45-
clojure.lang.Seqable
46-
(seq [_]
47-
(seq the-map))
48-
49-
clojure.lang.IPersistentMap
50-
(assoc [_ k v]
51-
(if (< (count the-map) 8)
52-
(->AlwaysArrayMap (assoc the-map k v))
53-
(->AlwaysArrayMap (assoc-after the-map k v))))
54-
55-
(assocEx [_ _k _v]
56-
(throw (ex-info "Not implemented" {})))
57-
58-
(without [_ k]
59-
(->AlwaysArrayMap (dissoc the-map k)))
60-
61-
clojure.lang.Associative
62-
(containsKey [_ k]
63-
(contains? the-map k))
64-
65-
clojure.lang.IPersistentCollection
66-
(equiv [_ other]
67-
(= the-map other))
68-
(count [_]
69-
(count the-map))
70-
71-
java.lang.Iterable
72-
(iterator [_]
73-
(.iterator the-map))
74-
75-
clojure.lang.IMeta
76-
(meta [_]
77-
(meta the-map))
78-
79-
clojure.lang.IObj
80-
(withMeta [_ meta]
81-
(->AlwaysArrayMap (with-meta the-map meta)))
82-
83-
Object
84-
(toString [_]
85-
"<always-array-map>")))
12+
(deftype AlwaysArrayMap [^clojure.lang.PersistentArrayMap the-map]
13+
clojure.lang.ILookup
14+
(valAt [_ k]
15+
(get the-map k))
16+
17+
clojure.lang.Seqable
18+
(seq [_]
19+
(seq the-map))
20+
21+
clojure.lang.IPersistentMap
22+
(assoc [_ k v]
23+
(if (< (count the-map) 8)
24+
(->AlwaysArrayMap (assoc the-map k v))
25+
(->AlwaysArrayMap (assoc-after the-map k v))))
26+
27+
(assocEx [_ _k _v]
28+
(throw (ex-info "Not implemented" {})))
29+
30+
(without [_ k]
31+
(->AlwaysArrayMap (dissoc the-map k)))
32+
33+
clojure.lang.Associative
34+
(containsKey [_ k]
35+
(contains? the-map k))
36+
37+
clojure.lang.IPersistentCollection
38+
(equiv [_ other]
39+
(= the-map other))
40+
(count [_]
41+
(count the-map))
42+
43+
java.lang.Iterable
44+
(iterator [_]
45+
(.iterator the-map))
46+
47+
clojure.lang.IMeta
48+
(meta [_]
49+
(meta the-map))
50+
51+
clojure.lang.IObj
52+
(withMeta [_ meta]
53+
(->AlwaysArrayMap (with-meta the-map meta)))
54+
55+
Object
56+
(toString [_]
57+
"<always-array-map>"))
8658

8759
(defn assoc-before [aam k v]
8860
(->AlwaysArrayMap (apply array-map (list* k v (interleave (keys aam) (vals aam))))))
8961

9062
(defn always-array-map [& kvs]
9163
(->AlwaysArrayMap (apply array-map kvs)))
9264

93-
(utils/when-not-bb
94-
(defmethod print-method AlwaysArrayMap
95-
[v ^java.io.Writer writer]
96-
(.write writer "{")
97-
(let [write-kv! (fn [k v]
98-
(.write writer (pr-str k))
99-
(.write writer " ")
100-
(.write writer (pr-str v)))]
101-
(doseq [[k v] (butlast v)]
102-
(write-kv! k v)
103-
(.write writer ", "))
104-
(let [[k v] (last v)]
105-
(write-kv! k v)))
106-
(.write writer "}")))
65+
(defmethod print-method AlwaysArrayMap
66+
[v ^java.io.Writer writer]
67+
(.write writer "{")
68+
(let [write-kv! (fn [k v]
69+
(.write writer (pr-str k))
70+
(.write writer " ")
71+
(.write writer (pr-str v)))]
72+
(doseq [[k v] (butlast v)]
73+
(write-kv! k v)
74+
(.write writer ", "))
75+
(let [[k v] (last v)]
76+
(write-kv! k v)))
77+
(.write writer "}"))
10778

10879
(comment
10980
(pr-str (always-array-map 1 2))

src/nextjournal/clerk/parser.cljc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@
479479
(assoc :add-comment-on-line? true)
480480
(update :nodes rest)
481481
(assoc :block-settings next-block-settings)
482-
(assoc-in [:md-context :opts] md-settings)
482+
(update-in [:md-context :opts] merge md-settings)
483483
(update :blocks conj (add-block-id code-block)))
484484
(not (contains? state :ns))
485485
(assoc :ns *ns*)))

src/nextjournal/clerk/utils.clj

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,6 @@
77
(defmacro if-bb [then else]
88
(if bb? then else))
99

10-
(defmacro if-not-bb-and [conds then else]
11-
(if bb?
12-
else
13-
`(if ~conds
14-
~then
15-
~else)))
16-
17-
(defmacro when-bb [& body]
18-
(when bb?
19-
`(do ~@body)))
20-
2110
(defmacro when-not-bb [& body]
2211
(when (not bb?)
2312
`(do ~@body)))

src/nextjournal/clerk/viewer.cljc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[clojure.pprint :as pprint]
66
[clojure.set :as set]
77
[clojure.string :as str]
8-
[flatland.ordered.map :as omap :refer [ordered-map]]
8+
[flatland.ordered.map :as omap]
99
#?@(:clj [[babashka.fs :as fs]
1010
[clojure.repl :refer [demunge]]
1111
[clojure.tools.reader :as tools.reader]
@@ -18,8 +18,7 @@
1818
[sci.impl.vars]
1919
[sci.lang]
2020
[applied-science.js-interop :as j]])
21-
#?@(:bb []
22-
:clj [[editscript.edit]])
21+
#?@(:clj [[editscript.edit]])
2322
[nextjournal.clerk.parser :as parser]
2423
[nextjournal.clerk.walk :as w]
2524
[nextjournal.markdown :as md]
@@ -45,8 +44,7 @@
4544
(-invoke [_ x y] (@f x y))]))
4645

4746
;; Make sure `RenderFn` is changed atomically
48-
#?(:bb nil
49-
:clj
47+
#?(:clj
5048
(extend-protocol editscript.edit/IType
5149
RenderFn
5250
(get-type [_] :val)))
@@ -739,15 +737,15 @@
739737
#_(update-viewers default-viewers {:page-size #(dissoc % :page-size)})
740738

741739
(defn ^:private ->ordered-map-by-name [viewers]
742-
(into (ordered-map)
740+
(into (omap/ordered-map)
743741
(map (juxt :name identity))
744742
viewers))
745743

746744
(defn ^:private merge-prepending [m1 m2]
747745
(into (apply dissoc m2 (keys m1))
748746
(into m1 m2)))
749747

750-
#_(merge-prepending (ordered-map :bar 1 :baz 2) (ordered-map {:baz 3 :a 1}))
748+
#_(merge-prepending (omap/ordered-map :bar 1 :baz 2) (ordered-map {:baz 3 :a 1}))
751749

752750
(defn ^:private merge-viewers [viewers added-viewers]
753751
(when-let [unnamed-viewers (not-empty (filter (complement :name) (concat viewers added-viewers)))]

src/nextjournal/clerk/webserver.clj

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
[clojure.pprint :as pprint]
88
[clojure.set :as set]
99
[clojure.string :as str]
10+
[editscript.core :as editscript]
1011
[nextjournal.clerk.config :as config]
1112
[nextjournal.clerk.git :as git]
1213
[nextjournal.clerk.paths :as paths]
@@ -17,10 +18,6 @@
1718
[sci.nrepl.browser-server :as sci.nrepl])
1819
(:import (java.nio.file Files)))
1920

20-
(u/if-bb
21-
(require '[editscript.core :as-alias editscript])
22-
(require '[editscript.core :as editscript]))
23-
2421
(defonce !clients (atom #{}))
2522
(defonce !doc (atom nil))
2623
(defonce !last-sender-ch (atom nil))
@@ -160,11 +157,11 @@
160157
presented))
161158

162159
(defn update-doc! [{:as doc :keys [nav-path fragment skip-history?]}]
163-
(broadcast! (u/if-not-bb-and (and (:ns @!doc) (= (:ns @!doc) (:ns doc)))
164-
{:type :patch-state! :patch (editscript/get-edits (editscript/diff (meta @!doc) (present+reset! doc) {:algo :quick}))}
165-
(cond-> {:type :set-state!
166-
:doc (present+reset! doc)}
167-
(and nav-path (not skip-history?))
160+
(broadcast! (if (and (:ns @!doc) (= (:ns @!doc) (:ns doc)))
161+
{:type :patch-state! :patch (editscript/get-edits (editscript/diff (meta @!doc) (present+reset! doc) {:algo :quick}))}
162+
(cond-> {:type :set-state!
163+
:doc (present+reset! doc)}
164+
(and nav-path (not skip-history?))
168165
(assoc :effects [(v/->render-eval (list 'nextjournal.clerk.render/history-push-state
169166
(cond-> {:path nav-path} fragment (assoc :fragment fragment))))])))))
170167

@@ -201,9 +198,7 @@
201198
:sync! (if-let [var (resolve (:var-name msg))]
202199
(try
203200
(binding [*sender-ch* sender-ch]
204-
(u/if-bb
205-
(throw (ex-info "Not implemented" {}))
206-
(swap! @var editscript/patch (editscript/edits->script (:patch msg)))))
201+
(swap! @var editscript/patch (editscript/edits->script (:patch msg))))
207202
(catch Exception ex
208203
(throw (doto (ex-info (str "Clerk cannot update synced var `" (:var-name msg) "`.") msg ex)
209204
update-error!))))
@@ -403,11 +398,13 @@
403398
(defn serve! [{:as opts :keys [host port] :or {host "localhost" port 7777}}]
404399
(halt!)
405400
(try
406-
(reset! !server (assoc opts
407-
:host host
408-
:port port
409-
:instance (httpkit/run-server #'app {:ip host :port port :legacy-return-value? false})))
410-
(println (format "Clerk webserver started on http://%s:%s ..." host port ))
401+
(let [instance (httpkit/run-server #'app {:ip host :port port :legacy-return-value? false})
402+
port (httpkit/server-port instance)]
403+
(reset! !server (assoc opts
404+
:host host
405+
:port port
406+
:instance instance))
407+
(println (format "Clerk webserver started on http://%s:%s ..." host port)))
411408
(when-let [render-nrepl-opts (:render-nrepl opts)]
412409
(serve-sci-nrepl! render-nrepl-opts))
413410
(catch java.net.BindException e

test/nextjournal/clerk/parser_test.clj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,16 @@ line\""}]
6666
(is (match? '([{:type :text, :text "$1 + $2 = $3"}]
6767
[{:type :formula, :text "1 + "} {:type :text, :text "2 = $3"}]
6868
[{:type :text, :text "$1 + $2 = $3"}])
69-
contents)))))
69+
contents))))
70+
71+
(testing "heading ids are preserved in toc (#804)"
72+
(let [parsed (parser/parse-clojure-string "^:nextjournal.clerk/toc (ns example)
73+
74+
;; # Workload Analysis
75+
76+
;; some text")]
77+
(is (match? {:toc {:children [{:type :toc :attrs {:id "workload-analysis"}}]}}
78+
parsed)))))
7079

7180
(deftest parse-inline-comments
7281
(is (match? {:blocks [{:doc {:content [{:content [{:text "text before"}]}]}}

0 commit comments

Comments
 (0)