Skip to content

Commit 2d96656

Browse files
mkphilippamarkovics
authored andcommitted
👁️ Improve viewer customization (#515)
* Simplify customization of number of rows displayed for table viewer using viewer-opts, e.g. `(clerk/table {::clerk/page-size 7})`. Pass `{::clerk/page-size nil}` to display elisions. Can also be passed a from metadata. Fixes #406. * Change semantics of `clerk/add-viewers!` to perform in-place positional replacement of named added viewers. Anonymous viewers (without a `:name`) or new named viewers will be prepended to the viewer stack. Assign a symbol `:name` to all of `clerk/default-viewers`. * Support first-class `:add-viewers` attribute on viewer map which will do `clerk/add-viewers` before passing viewers down the tree. Use it in `table-viewer` and `markdown-viewer`. Both these viewers can now be customized more easily. For example, you can customize the `table-viewer` to show missing values differently, see [Book of Clerk](https://book.clerk.vision/#tables).
1 parent fbe0b21 commit 2d96656

File tree

8 files changed

+138
-95
lines changed

8 files changed

+138
-95
lines changed

CHANGELOG.md

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

99
## Unreleased
1010

11+
* 👁️ Improve viewer customization
12+
13+
* Simplify customization of number of rows displayed for table viewer using viewer-opts, e.g. `(clerk/table {::clerk/page-size 7})`. Pass `{::clerk/page-size nil}` to display elisions. Can also be passed a form metadata. Fixes [#406](https://github.com/nextjournal/clerk/issues/406).
14+
15+
* Change semantics of `clerk/add-viewers!` to perform in-place positional replacement of named added viewers. Anonymous viewers (without a `:name`) or new named viewers will be prepended to the viewer stack. Assign a symbol `:name` to all of `clerk/default-viewers`.
16+
17+
* Support first-class `:add-viewers` attribute on viewer map which will do `clerk/add-viewers` before passing viewers down the tree. Use it in `table-viewer` and `markdown-viewer`. Both these viewers can now be customized more easily. For example, you can customize the `table-viewer` to show missing values differently, see [Book of Clerk](https://book.clerk.vision/#tables).
18+
1119
* 💫 Assign `:name` to every viewer in `default-viewers`
1220

1321
## 0.14.919 (2023-06-13)

book.clj

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,23 @@
207207
(clerk/table {:head ["odd numbers" "even numbers"]
208208
:rows [[1 2] [3 4]]}) ;; map with `:rows` and optional `:head` keys
209209

210+
;; To customize the number of rows in the table viewer, set
211+
;; `::clerk/page-size`. Use a value of `nil` to show all rows.
212+
(clerk/table {::clerk/page-size 7} (map (comp vector (partial str "Row #")) (range 1 31)))
213+
214+
;; The built-in table viewer adds a number of child-viewers on its
215+
;; `:add-viewers` key. Those sub-viewers control the markup for the
216+
;; table and the display of strings (to turn off quoting inside table
217+
;; cells).
218+
(:add-viewers v/table-viewer)
219+
220+
;; Modifying the `:add-viewers` key allows us to create a custom table
221+
;; viewer that shows missing values differently.
222+
(def table-viewer-custom-missing-values
223+
(update v/table-viewer :add-viewers v/add-viewers [(assoc v/table-missing-viewer :render-fn '(fn [x] [:span.red "N/A"]))]))
224+
225+
^{::clerk/viewer table-viewer-custom-missing-values}
226+
{:A [1 2 3] :B [1 3] :C [1 2]}
210227

211228

212229
;; ### 🧮 TeX
@@ -544,18 +561,11 @@ v/default-viewers
544561

545562
;; **Passing modified viewers down the tree**
546563

547-
#_ "TODO: move this into clerk?"
548-
(defn add-child-viewers [viewer viewers]
549-
(update viewer :transform-fn (fn [transform-fn-orig]
550-
(fn [wrapped-value]
551-
(update (transform-fn-orig wrapped-value) :nextjournal/viewers clerk/add-viewers viewers)))))
552-
553564
v/table-viewer
554565

555566
(def custom-table-viewer
556-
(add-child-viewers v/table-viewer
557-
[(assoc v/table-head-viewer :transform-fn (v/update-val (partial map (comp (partial str "Column: ") str/capitalize name))))
558-
(assoc v/table-missing-viewer :render-fn '(fn [x] [:span.red "N/A"]))]))
567+
(update v/table-viewer :add-viewers v/add-viewers [(assoc v/table-head-viewer :transform-fn (v/update-val (partial map (comp (partial str "Column: ") str/capitalize name))))
568+
(assoc v/table-missing-viewer :render-fn '(fn [x] [:span.red "N/A"]))]))
559569

560570
(clerk/with-viewer custom-table-viewer
561571
{:col/a [1 2 3 4] :col/b [1 2 3] :col/c [1 2 3]})

deps.edn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
borkdude/edamame {:mvn/version "1.0.16"}
88
weavejester/dependency {:mvn/version "0.2.1"}
99
com.nextjournal/beholder {:mvn/version "1.0.2"}
10+
org.flatland/ordered {:mvn/version "1.15.11"}
1011

1112
io.github.nextjournal/markdown {:mvn/version "0.5.144"}
1213
babashka/process {:mvn/version "0.4.16"}

notebooks/viewers/custom_markdown.clj

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,7 @@
66
{:nextjournal.clerk/visibility {:code :hide}}
77
(:require [nextjournal.clerk.viewer :as v]))
88

9-
(defn update-child-viewers [f]
10-
(fn [viewer]
11-
(update viewer :transform-fn (fn [transform-fn]
12-
(fn [wrapped-value]
13-
(-> wrapped-value
14-
transform-fn
15-
(update :nextjournal/viewers f)))))))
16-
17-
(def md-viewers
9+
(def custom-markdown-viewers
1810
[{:name :nextjournal.markdown/text
1911
:transform-fn (v/into-markup [:span {:style {:color "#64748b"}}])}
2012
{:name :nextjournal.markdown/ruler
@@ -24,11 +16,10 @@
2416
{:name :nextjournal.markdown/table
2517
:transform-fn (v/into-markup [:table.monospace])}])
2618

27-
(def viewers-with-pretty-markdown
28-
(v/update-viewers (v/get-default-viewers) {(comp #{`v/markdown-viewer} :name)
29-
(update-child-viewers #(v/add-viewers % md-viewers))}))
19+
(def pretty-markdown-viewer
20+
(update v/markdown-viewer :add-viewers v/add-viewers custom-markdown-viewers))
3021

31-
(v/reset-viewers! viewers-with-pretty-markdown)
22+
(v/add-viewers! [pretty-markdown-viewer])
3223

3324
;; ## Sections
3425
;;

notebooks/viewers/in_text_eval.clj

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,31 @@
33
(ns viewers.in-text-eval
44
{:nextjournal.clerk/no-cache true}
55
(:require [nextjournal.clerk :as clerk]
6+
[nextjournal.clerk.experimental :as cx]
67
[nextjournal.clerk.viewer :as v]
7-
[viewers.custom-markdown :as custom-md]
8-
[nextjournal.markdown.transform :as markdown.transform]))
8+
[nextjournal.markdown.transform :as markdown.transform]
9+
[viewers.custom-markdown :as custom-md]))
910

1011
;; Being able to override markdown viewers allows us to get in-text evaluation for free:
1112

13+
^{::clerk/sync true}
1214
(defonce num★ (atom 20))
1315

14-
(def md-eval-viewers
16+
(def markdown-eval-viewers
1517
[{:name :nextjournal.markdown/monospace
1618
:transform-fn (comp eval read-string markdown.transform/->text v/->value)}
1719
{:name :nextjournal.markdown/ruler
1820
:transform-fn (constantly (v/with-viewer `v/html-viewer [:div.text-center (repeat @num★ "")]))}])
1921

2022
^{::clerk/visibility {:result :hide}}
21-
(def viewers-with-md-eval
22-
(v/update-viewers (v/get-default-viewers) {(comp #{`v/markdown-viewer} :name)
23-
(custom-md/update-child-viewers #(v/add-viewers % md-eval-viewers))}))
23+
(def markdown+eval-viewer
24+
(update v/markdown-viewer :add-viewers v/add-viewers markdown-eval-viewers))
2425

2526
^{::clerk/visibility {:result :hide}}
26-
(clerk/reset-viewers! viewers-with-md-eval) ;; register viewer globally for ns
27+
(clerk/add-viewers! [markdown+eval-viewer]) ;; register viewer globally for ns
2728

2829
;; ---
2930

30-
^{::clerk/visibility {:result :hide}}
31-
(defn slider [var {:keys [min max]}]
32-
(clerk/with-viewer
33-
{:transform-fn (comp v/mark-presented (v/update-val (fn [var] {:var-name (symbol var) :value @@var})))
34-
:render-fn `(fn [data]
35-
[:input {:type :range :min ~min :max ~max :value (:value data)
36-
:on-change #(nextjournal.clerk.render/clerk-eval `(reset! ~(:var-name data) (Integer/parseInt ~(.. % -target -value))))}])}
37-
var))
38-
39-
;; Drag the following slider `(slider #'num★ {:min 1 :max 44})` to control the number of stars (currently **`(deref num★)`**) in our custom horizontal rules.
31+
;; Drag the following slider `(cx/slider {:min 1 :max 44} 'num★)` to control the number of stars (currently **`(deref num★)`**) in our custom horizontal rules.
4032

4133
;; ---

notebooks/viewers/table.clj

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,15 @@
3030
(group-by (comp keyword str/upper-case str first))
3131
(into (sorted-map))))
3232

33-
(clerk/table {:nextjournal/width :full} letter->words)
33+
(clerk/table {::clerk/width :full} letter->words)
34+
35+
;; ## Customize Page Size
36+
(clerk/table {::clerk/page-size 7} (map vector (range 1 26)))
37+
38+
;; Or setting it on the viewer.
39+
(clerk/with-viewer (assoc v/table-viewer :page-size 7)
40+
(map vector (range 1 26)))
41+
3442

3543
;; ## Table Errors
3644
;; The table viewer will perform normalization and show an error in case of failure:
@@ -67,13 +75,9 @@
6775
;; ## Custom Table Viewers
6876
;; override single table components
6977

70-
(defn add-child-viewers [viewer viewers]
71-
(update viewer :transform-fn (partial comp #(update % :nextjournal/viewers clerk/add-viewers viewers))))
72-
7378
(def custom-table-viewer
74-
(add-child-viewers v/table-viewer
75-
[(assoc v/table-head-viewer :transform-fn (v/update-val (partial map (comp (partial str "Column: ") str/capitalize name))))
76-
(assoc v/table-missing-viewer :render-fn '(fn [x] [:span.red "N/A"]))]))
79+
(update v/table-viewer :add-viewers v/add-viewers [(assoc v/table-head-viewer :transform-fn (v/update-val (partial map (comp (partial str "Column: ") str/capitalize name))))
80+
(assoc v/table-missing-viewer :render-fn '(fn [x] [:span.red "N/A"]))]))
7781

7882
(clerk/with-viewer custom-table-viewer
7983
{:col/a [1 2 3 4] :col/b [1 2 3] :col/c [1 2 3]})
@@ -85,7 +89,6 @@
8589
v/normalize-table-data)))
8690
{:a [1 2] :b [3 4]})
8791

88-
8992
;; ## Nesting tables inside html
9093
(clerk/html [:div.bg-amber-100.p-2
9194
(clerk/table [[1 2] [3 4] [5 6]])])

src/nextjournal/clerk/parser.cljc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@
5252
#{:nextjournal.clerk/auto-expand-results?
5353
:nextjournal.clerk/budget
5454
:nextjournal.clerk/css-class
55-
:nextjournal.clerk/visibility
5655
:nextjournal.clerk/opts
57-
:nextjournal.clerk/width
58-
:nextjournal.clerk/render-evaluator})
56+
:nextjournal.clerk/page-size
57+
:nextjournal.clerk/render-evaluator
58+
:nextjournal.clerk/visibility
59+
:nextjournal.clerk/width})
5960

6061
(defn settings-marker? [form]
6162
(boolean (and (map? form)

0 commit comments

Comments
 (0)