|
| 1 | +# Stratum Notebooks |
| 2 | + |
| 3 | +Literate documentation and tests for Stratum, rendered as a |
| 4 | +[Quarto](https://quarto.org/) book via [Clay](https://scicloj.github.io/clay/). |
| 5 | + |
| 6 | +## Structure |
| 7 | + |
| 8 | +``` |
| 9 | +notebooks/ |
| 10 | +├── chapters.edn # book outline — parts and chapter filenames |
| 11 | +├── index.clj # landing page (renders README.md) |
| 12 | +├── dev.clj # build helpers (make-book!, make-gfm!) |
| 13 | +├── custom.scss # Quarto styling (Fira Code, table tweaks) |
| 14 | +└── stratum_book/ # chapters live here |
| 15 | + ├── quickstart.clj |
| 16 | + ├── csv_import.clj |
| 17 | + ├── columnar_internals.clj |
| 18 | + ├── dataset_persistence.clj |
| 19 | + ├── tablecloth_interop.clj |
| 20 | + └── api_reference.clj |
| 21 | +
|
| 22 | +test/stratum_book/ # generated by Clay from kind/test-last |
| 23 | +├── quickstart_generated_test.clj |
| 24 | +├── csv_import_generated_test.clj |
| 25 | +├── columnar_internals_generated_test.clj |
| 26 | +├── dataset_persistence_generated_test.clj |
| 27 | +├── tablecloth_interop_generated_test.clj |
| 28 | +└── api_reference_generated_test.clj |
| 29 | +
|
| 30 | +clay.edn # Clay config (Quarto theme, target paths) |
| 31 | +``` |
| 32 | + |
| 33 | +## Requirements |
| 34 | + |
| 35 | +The Quarto CLI needs to be [installed](https://quarto.org/docs/get-started/). |
| 36 | + |
| 37 | +## How it works |
| 38 | + |
| 39 | +Each `.clj` file under `stratum_book/` is a regular Clojure namespace |
| 40 | +that doubles as a notebook. Prose goes in `;;` comments (rendered as |
| 41 | +Markdown), and top-level expressions become evaluated code cells. |
| 42 | + |
| 43 | +Assertions use `kind/test-last`: |
| 44 | + |
| 45 | +```clojure |
| 46 | +(st/q {:from data :agg [[:count]]}) |
| 47 | + |
| 48 | +(kind/test-last |
| 49 | + [(fn [result] (= 1 (count result)))]) |
| 50 | +``` |
| 51 | +notebooks/ |
| 52 | +├── chapters.edn # book outline — parts and chapter filenames |
| 53 | +├── index.clj # landing page (renders README.md) |
| 54 | +├── dev.clj # build helpers (make-book!, make-gfm!) |
| 55 | +├── custom.scss # Quarto styling (Fira Code, table tweaks) |
| 56 | +└── stratum_book/ # chapters live here |
| 57 | + ├── quickstart.clj |
| 58 | + ├── csv_import.clj |
| 59 | + ├── columnar_internals.clj |
| 60 | + ├── dataset_persistence.clj |
| 61 | + ├── tablecloth_interop.clj |
| 62 | + └── api_reference.clj |
| 63 | + |
| 64 | +test/stratum_book/ # generated by Clay from kind/test-last |
| 65 | +├── quickstart_generated_test.clj |
| 66 | +├── csv_import_generated_test.clj |
| 67 | +├── columnar_internals_generated_test.clj |
| 68 | +├── dataset_persistence_generated_test.clj |
| 69 | +├── tablecloth_interop_generated_test.clj |
| 70 | +└── api_reference_generated_test.clj |
| 71 | + |
| 72 | +clay.edn # Clay config (Quarto theme, target paths) |
| 73 | +``` |
| 74 | +
|
| 75 | +Then, instead of writing manual `### heading` comments, call |
| 76 | +`kind/doc` on the var: |
| 77 | +
|
| 78 | +```clojure |
| 79 | +(kind/doc #'st/q) |
| 80 | +
|
| 81 | +;; Free-form prose and examples follow as usual. |
| 82 | +
|
| 83 | +(st/q {:from data :agg [[:sum :qty]]}) |
| 84 | +
|
| 85 | +(kind/test-last |
| 86 | + [(fn [result] (= 1 (count result)))]) |
| 87 | +``` |
| 88 | +notebooks/ |
| 89 | +├── chapters.edn # book outline — parts and chapter filenames |
| 90 | +├── index.clj # landing page (renders README.md) |
| 91 | +├── dev.clj # build helpers (make-book!, make-gfm!) |
| 92 | +├── custom.scss # Quarto styling (Fira Code, table tweaks) |
| 93 | +└── stratum_book/ # chapters live here |
| 94 | + ├── quickstart.clj |
| 95 | + ├── csv_import.clj |
| 96 | + ├── columnar_internals.clj |
| 97 | + ├── dataset_persistence.clj |
| 98 | + ├── tablecloth_interop.clj |
| 99 | + └── api_reference.clj |
| 100 | + |
| 101 | +test/stratum_book/ # generated by Clay from kind/test-last |
| 102 | +├── quickstart_generated_test.clj |
| 103 | +├── csv_import_generated_test.clj |
| 104 | +├── columnar_internals_generated_test.clj |
| 105 | +├── dataset_persistence_generated_test.clj |
| 106 | +├── tablecloth_interop_generated_test.clj |
| 107 | +└── api_reference_generated_test.clj |
| 108 | + |
| 109 | +clay.edn # Clay config (Quarto theme, target paths) |
| 110 | +``` |
| 111 | +
|
| 112 | +`make-book!` reads `chapters.edn` to assemble the book structure, |
| 113 | +then calls Clay which: |
| 114 | +
|
| 115 | +1. Evaluates each `.clj` file top-to-bottom |
| 116 | +2. Converts the output to `.qmd` (Quarto Markdown) |
| 117 | +3. Runs Quarto to produce the HTML site in `docs/` |
| 118 | +
|
| 119 | +## Adding a chapter |
| 120 | +
|
| 121 | +1. Create `notebooks/stratum_book/my_chapter.clj` with an `(ns stratum-book.my-chapter ...)` form |
| 122 | +2. Add `"my_chapter"` to the appropriate part in `chapters.edn` |
| 123 | +3. Run `(make-book!)` to verify |
| 124 | +
|
| 125 | +## Running tests |
| 126 | +
|
| 127 | +The notebooks are on the `:test` classpath. `kind/test-last` |
| 128 | +annotations [generate](https://scicloj.github.io/clay/clay_book.test_generation.html) |
| 129 | +`deftest` forms that the test runner picks up |
| 130 | +alongside traditional `deftest` tests. |
| 131 | +
|
0 commit comments