bookspine 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. bookspine-0.1.0/LICENSE +21 -0
  2. bookspine-0.1.0/LICENSES/Python-Markdown.txt +30 -0
  3. bookspine-0.1.0/LICENSES/pymdown-extensions.txt +21 -0
  4. bookspine-0.1.0/LICENSES/rust-crates.txt +55 -0
  5. bookspine-0.1.0/PKG-INFO +350 -0
  6. bookspine-0.1.0/README.md +312 -0
  7. bookspine-0.1.0/pyproject.toml +76 -0
  8. bookspine-0.1.0/rust/Cargo.lock +169 -0
  9. bookspine-0.1.0/rust/Cargo.toml +18 -0
  10. bookspine-0.1.0/rust/src/lib.rs +31 -0
  11. bookspine-0.1.0/src/bookspine/__init__.py +10 -0
  12. bookspine-0.1.0/src/bookspine/__main__.py +7 -0
  13. bookspine-0.1.0/src/bookspine/_markdown.pyi +7 -0
  14. bookspine-0.1.0/src/bookspine/cli.py +71 -0
  15. bookspine-0.1.0/src/bookspine/config.py +395 -0
  16. bookspine-0.1.0/src/bookspine/converter.py +495 -0
  17. bookspine-0.1.0/src/bookspine/equations.py +259 -0
  18. bookspine-0.1.0/src/bookspine/errors.py +5 -0
  19. bookspine-0.1.0/src/bookspine/glossary.py +215 -0
  20. bookspine-0.1.0/src/bookspine/keys.py +308 -0
  21. bookspine-0.1.0/src/bookspine/pages.py +273 -0
  22. bookspine-0.1.0/src/bookspine/passes.py +398 -0
  23. bookspine-0.1.0/src/bookspine/py.typed +0 -0
  24. bookspine-0.1.0/src/bookspine/safe_paths.py +209 -0
  25. bookspine-0.1.0/src/bookspine/site.py +358 -0
  26. bookspine-0.1.0/src/bookspine/static/book.css +850 -0
  27. bookspine-0.1.0/src/bookspine/static/book.js +269 -0
  28. bookspine-0.1.0/src/bookspine/static/export.js +870 -0
  29. bookspine-0.1.0/src/bookspine/static/favicon.svg +5 -0
  30. bookspine-0.1.0/src/bookspine/templates/base.html +203 -0
  31. bookspine-0.1.0/src/bookspine/templates/chapter.html +47 -0
  32. bookspine-0.1.0/src/bookspine/templates/glossary.html +30 -0
  33. bookspine-0.1.0/src/bookspine/templates/help.html +13 -0
  34. bookspine-0.1.0/src/bookspine/templates/home.html +61 -0
  35. bookspine-0.1.0/src/bookspine/templates/part.html +30 -0
  36. bookspine-0.1.0/src/bookspine/templates/section.html +29 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alkaid Cheng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
4
+ Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
5
+ Copyright 2004 Manfred Stienstra (the original version)
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice, this
11
+ list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the name of the copyright holder nor the names of its
18
+ contributors may be used to endorse or promote products derived from
19
+ this software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 - 2025 Isaac Muse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,55 @@
1
+ The compiled module bookspine._markdown contains the Rust standard library and
2
+ the crates listed here. Each is offered under the MIT licence, alone or as one
3
+ of several choices, and is used here under that licence, whose text follows the
4
+ list.
5
+
6
+ Rust standard library <https://github.com/rust-lang/rust>
7
+ Copyright (c) The Rust Project Contributors
8
+
9
+ bitflags <https://github.com/bitflags/bitflags>
10
+ Copyright (c) 2014 The Rust Project Developers
11
+
12
+ libc <https://github.com/rust-lang/libc>
13
+ Copyright (c) The Rust Project Developers
14
+
15
+ memchr <https://github.com/BurntSushi/memchr>
16
+ Copyright (c) 2015 Andrew Gallant
17
+
18
+ once_cell <https://github.com/matklad/once_cell>
19
+ The project's licence file names no copyright holder.
20
+
21
+ portable-atomic <https://github.com/taiki-e/portable-atomic>
22
+ The project's licence file names no copyright holder.
23
+
24
+ pulldown-cmark <https://github.com/pulldown-cmark/pulldown-cmark>
25
+ Copyright 2015 Google Inc. All rights reserved.
26
+
27
+ pulldown-cmark-escape <https://github.com/pulldown-cmark/pulldown-cmark>
28
+ Copyright 2015 Google Inc. All rights reserved.
29
+
30
+ pyo3 <https://github.com/PyO3/pyo3>
31
+ Copyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3
32
+
33
+ pyo3-ffi <https://github.com/PyO3/pyo3>
34
+ Copyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3
35
+
36
+ unicase <https://github.com/seanmonstar/unicase>
37
+ Copyright (c) 2014-2026 Sean McArthur
38
+
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
41
+ this software and associated documentation files (the "Software"), to deal in
42
+ the Software without restriction, including without limitation the rights to
43
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
44
+ the Software, and to permit persons to whom the Software is furnished to do so,
45
+ subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in all
48
+ copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
52
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
53
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
54
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
55
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,350 @@
1
+ Metadata-Version: 2.4
2
+ Name: bookspine
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Environment :: Console
6
+ Classifier: Intended Audience :: Education
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Rust
11
+ Classifier: Topic :: Documentation
12
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
13
+ Classifier: Typing :: Typed
14
+ Requires-Dist: jinja2
15
+ Requires-Dist: pygments
16
+ Requires-Dist: pyyaml
17
+ Requires-Dist: black ; extra == 'dev'
18
+ Requires-Dist: mypy ; extra == 'dev'
19
+ Requires-Dist: pytest ; extra == 'dev'
20
+ Requires-Dist: ruff ; extra == 'dev'
21
+ Requires-Dist: types-pygments ; extra == 'dev'
22
+ Requires-Dist: types-pyyaml ; extra == 'dev'
23
+ Provides-Extra: dev
24
+ License-File: LICENSE
25
+ License-File: LICENSES/Python-Markdown.txt
26
+ License-File: LICENSES/pymdown-extensions.txt
27
+ License-File: LICENSES/rust-crates.txt
28
+ Summary: Build a textbook-style static site from Markdown chapters.
29
+ Keywords: documentation,markdown,static-site,textbook,mathjax
30
+ Author-email: Alkaid Cheng <alkaidc@stanford.edu>
31
+ License-Expression: MIT AND BSD-3-Clause
32
+ Requires-Python: >=3.11
33
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
34
+ Project-URL: Homepage, https://github.com/AlkaidCheng/bookspine
35
+ Project-URL: Issues, https://github.com/AlkaidCheng/bookspine/issues
36
+ Project-URL: Repository, https://github.com/AlkaidCheng/bookspine
37
+
38
+ # bookspine
39
+
40
+ bookspine turns a directory of Markdown chapters into a textbook-style static site,
41
+ with numbered parts, chapters, sections, equations, figures, tables and boxed
42
+ environments, citations, client-side search, and light and dark colour schemes. The
43
+ theme comes with the package, so a book holds only its content and one configuration
44
+ file.
45
+
46
+ ![The build reads book.yaml and the Markdown pages, converts them to HTML, numbers and resolves them, applies the theme and writes the site.](https://raw.githubusercontent.com/AlkaidCheng/bookspine/main/docs/pipeline.svg)
47
+
48
+ | Step | What it does |
49
+ |---|---|
50
+ | Read | Reads `book.yaml` and the Markdown files it lists, in reading order. |
51
+ | Convert | Turns each page's Markdown into HTML. |
52
+ | Number | Numbers sections, figures, captioned tables, boxes and equations, resolves citations and links, and collects the search index. |
53
+ | Theme | Puts each page into its template and gathers the static files. |
54
+ | Write | Replaces what the last build wrote in `site/`. |
55
+
56
+ The build stops on a broken internal link, a missing figure, a citation without a
57
+ reference entry, an `\eqref` to a label no numbered equation carries, or an equation
58
+ label used twice. A failed build leaves `site/` as it was.
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install bookspine
64
+ ```
65
+
66
+ bookspine needs Python 3.11 or later and runs on Linux, macOS and Windows. pip installs a
67
+ prebuilt wheel on x86-64 and ARM Linux with glibc 2.17 or later, on macOS with Apple silicon
68
+ and on 64-bit Windows. Anywhere else it compiles the package, which needs a C compiler and,
69
+ if Rust is not installed, downloads a copy of about 500 MB into the user cache.
70
+
71
+ ## Usage
72
+
73
+ A book is a project directory:
74
+
75
+ ```text
76
+ my-book/
77
+ ├── book.yaml # title, author, parts and chapters
78
+ ├── book/
79
+ │ ├── index.md # the title page
80
+ │ ├── help.md # an optional help page
81
+ │ └── methods/ # a part
82
+ │ ├── index.md # the part's opener
83
+ │ ├── basics.md # a chapter on one page
84
+ │ └── figures/
85
+ └── theme/ # optional overrides
86
+ ```
87
+
88
+ Build it and preview the result:
89
+
90
+ ```bash
91
+ bookspine build my-book
92
+ python -m http.server --directory my-book/site 8000
93
+ ```
94
+
95
+ Then open <http://127.0.0.1:8000/>.
96
+
97
+ ```text
98
+ bookspine build [PROJECT_DIR] [--site-dir DIR] [--allow-warnings]
99
+ ```
100
+
101
+ | Argument | Meaning |
102
+ |---|---|
103
+ | `PROJECT_DIR` | The directory holding `book.yaml`, by default the current one. |
104
+ | `--site-dir DIR` | Where to write the site, by default `site/` in the project directory. |
105
+ | `--allow-warnings` | Do not fail the build on warnings. A reference that is never cited is a warning. |
106
+
107
+ `python -m bookspine` runs the same command. Each build lists any files under `theme/`
108
+ that are in force.
109
+
110
+ ## Writing a book
111
+
112
+ ### Pages
113
+
114
+ Pages follow [CommonMark](https://commonmark.org/), with tables, definition lists,
115
+ footnotes and curly punctuation added, and every page starts with a YAML front matter
116
+ block.
117
+
118
+ | Key | Meaning |
119
+ |---|---|
120
+ | `title` | The page's title. Required. |
121
+ | `summary` | One sentence, shown under the title and in the contents. |
122
+ | `status` | For example `in-preparation`, which puts a badge in the contents and a notice on the page. |
123
+ | `references` | Citation keys mapped to formatted entries, which may use Markdown. |
124
+
125
+ Use `##` for sections and `###` for subsections; the build numbers them. An `##` named
126
+ "References" or "Further reading", or carrying `{: .unnumbered }`, stays unnumbered.
127
+ Section anchors come from the heading text, so renaming a heading changes its link.
128
+ `{: #my-id }` after a heading pins its anchor.
129
+
130
+ A page can also use these forms:
131
+
132
+ | Form | Effect |
133
+ |---|---|
134
+ | `[^note]`, with `[^note]: Text` on a line of its own | A footnote, listed at the end of the page. Indent further paragraphs of the note by four spaces. |
135
+ | `*[HTML]: HyperText Markup Language` on a line of its own | A tooltip on every `HTML` in the page. |
136
+ | `++ctrl+alt+delete++` | Those keys, drawn as keycaps. A name that is not a key leaves the text as written. |
137
+ | `{: .class #id key="value" }` on the line after a paragraph or list item | Those attributes on it. |
138
+
139
+ ### Parts and chapters
140
+
141
+ `book.yaml` lists the parts and their chapters in reading order. Parts take Roman
142
+ numerals, and chapters are numbered continuously through the book.
143
+
144
+ ```yaml
145
+ parts:
146
+ - dir: methods
147
+ title: Methods
148
+ chapters:
149
+ - basics.md
150
+ - dir: inference
151
+ sections:
152
+ - likelihoods.md
153
+ - hypothesis-tests.md
154
+ ```
155
+
156
+ `dir` is the part's directory under `book/`, which needs an `index.md`. A chapter is
157
+ one Markdown file, or a `dir` with an `index.md` opener and one Markdown file per
158
+ section. Each section page is numbered within the chapter (2.1, 2.2) and its `##`
159
+ headings become subsections (2.1.1). Figures, tables, numbered boxes and equations keep
160
+ one running count through a chapter, so splitting a chapter changes none of those
161
+ numbers. Each page has its own `references` and reference list.
162
+
163
+ ### Figures and tables
164
+
165
+ `![caption](figures/name.svg)` on a line of its own becomes a numbered figure. A local
166
+ SVG is copied into the page, so it can use the theme's colours and follow the colour
167
+ scheme. A table followed by a paragraph starting `Table:` becomes a numbered table, and
168
+ a table with no caption takes no number. A button on each figure and table opens it
169
+ enlarged.
170
+
171
+ ### Code
172
+
173
+ A fenced code block takes the colours of the language named after its opening fence,
174
+ which any of these options may follow:
175
+
176
+ | Option | Effect |
177
+ |---|---|
178
+ | `title="app.py"` | A title above the block. |
179
+ | `hl_lines="1 3-4"` | Marks those lines. |
180
+ | `linenums="1"` | Numbers the lines, starting from that number. |
181
+
182
+ Inline code takes a language's colours when it starts with `#!` and the language's name,
183
+ as in `` `#!python x = 1` ``.
184
+
185
+ ### Equations
186
+
187
+ Write inline math as `$…$` or `\(…\)`, and display math as `$$ … $$` on lines of their
188
+ own. `\[…\]` or a `\begin{…}` environment that starts a paragraph is display math too.
189
+ Every display equation is numbered, and `\notag` suppresses a number. `\label{eq:name}` and
190
+ `\eqref{eq:name}` reach any page in the book, so a label must be unique across it.
191
+ Place `\label` after `\end{aligned}` or `\end{split}`, because MathJax discards one
192
+ written inside them. A page with no math does not load MathJax.
193
+
194
+ ### Citations
195
+
196
+ `[@key]` cites an entry of the page's `references`, and `[@a; @b]` cites several. The
197
+ reference list is generated at the end of the page, in order of first citation. A link
198
+ that shows its own address, such as `<https://example.org/a/long/path>`, wraps between
199
+ the address's elements with no hyphen added, so a long one fits a phone's screen.
200
+
201
+ ### Boxes
202
+
203
+ `!!! kind "Title"` sets material apart, and `??? kind "Title"` makes it collapsible.
204
+
205
+ | Kind | Effect |
206
+ |---|---|
207
+ | `definition`, `example`, `remark`, `recipe` | Numbered within the chapter, with a permalink. |
208
+ | `warning`, `caution`, `note`, `tip` | Labelled, with no number. |
209
+ | Any other, such as `summary` | Styled by its own name, with its title as written. |
210
+
211
+ ### Glossary
212
+
213
+ A `\glossary` tag adds a reference to the book's glossary, which follows the last part
214
+ with an opener, a page for terms and a page for equations. The tag prints nothing, as
215
+ LaTeX's `\index` does. Each entry is a name that links to the place it marks, in
216
+ alphabetical order. A page appears once it has an entry, so a book with no tags has no
217
+ glossary.
218
+
219
+ | Where | Tag | Entry |
220
+ |---|---|---|
221
+ | A paragraph or list item | `\glossary{Name}` | A term that links to this place. |
222
+ | The start of a box | `\glossary` | A term named after the box's title, linking to the box. `\glossary{Name}` gives it another name. |
223
+ | A display equation | `\glossary{Name}` | An equation of that name. It needs a `\label` and a number. |
224
+
225
+ ```markdown
226
+ !!! definition "Jet"
227
+ \glossary
228
+ A collimated spray of hadrons.
229
+
230
+ $$
231
+ \sigma = \int f(x) \, \hat\sigma(x) \label{eq:xsec} \glossary{Factorisation formula}
232
+ $$
233
+ ```
234
+
235
+ The build stops on a name used twice on a page, and on a named equation with no label or
236
+ number.
237
+
238
+ ### Help page
239
+
240
+ A book can keep what a reader needs only now and then on a page of its own, such as its
241
+ conventions, its notation, how to cite it and where to report a problem. `help_page` in
242
+ `book.yaml` names a Markdown file in `book/`, and the foot of the sidebar links to it
243
+ from every page, under the page's title. The page takes its address from the file's
244
+ name, so `help.md` is served at `help/`, and the build stops if a part or the glossary
245
+ holds that address. The page has no number, stays out of the contents and of the
246
+ previous and next links, and is covered by the search.
247
+
248
+ ## Exporting
249
+
250
+ Every table, figure, code block and display equation has a button that opens a menu of
251
+ file formats. It appears when the cursor is over that component. On a touch screen it
252
+ stays faintly visible, except on a code block, where a tap shows it. It sits at the end
253
+ of a caption, at the top right of a code block or a table without a caption, and at the
254
+ left of an equation. A code block also has a button that copies its source in one click.
255
+
256
+ | Component | Formats |
257
+ |---|---|
258
+ | Table | Markdown, CSV, LaTeX, PNG, PDF |
259
+ | SVG figure | SVG, PNG, PDF |
260
+ | Other figure | PNG, PDF |
261
+ | Code block | PNG, PDF |
262
+ | Display equation | LaTeX, PNG, PDF |
263
+
264
+ Exports use the light colour scheme on a white background. Markdown and LaTeX keep a
265
+ table's caption, and images and PDFs leave it out. A code block keeps its source's
266
+ lines, however it wraps on the page. Every format except PDF can also be
267
+ copied to the clipboard. LaTeX output defines the book's macros it uses, and states the
268
+ packages it needs.
269
+
270
+ PDF opens the browser's print dialog with the page sized to the component, which keeps
271
+ vectors and fonts: choose "Save as PDF" there. A browser that ignores the page size
272
+ prints on its default paper.
273
+
274
+ ## Configuration
275
+
276
+ `book.yaml` takes the keys below, and an unknown key stops the build.
277
+
278
+ | Key | Default | Meaning |
279
+ |---|---|---|
280
+ | `title`, `author` | required | The book's title and author. |
281
+ | `subtitle`, `kicker` | empty | The lines around the title on the home page. |
282
+ | `url` | empty | The published address. |
283
+ | `repo` | empty | The source repository, linked from the sidebar. |
284
+ | `repo_host` | empty | The name in that link, such as `GitHub`. Required with `repo`. |
285
+ | `edit_url` | empty | The prefix of a page's edit link, followed by its path under `book/`. No link appears when it is empty. |
286
+ | `help_page` | empty | The Markdown file in `book/` [linked from the foot of the sidebar](#help-page). |
287
+ | `parts` | empty | The parts and chapters, as above. |
288
+ | `enlarge_tables` | `true` | Whether a table has a button that opens it enlarged. Figures always do. |
289
+ | `export_menus` | `true` | Whether tables, figures, code blocks and equations offer an [export menu](#exporting). |
290
+ | `glossary` | `true` | Whether `\glossary` tags make [glossary](#glossary) pages. |
291
+ | `wrap_code` | `true` | Whether a long line of code wraps, its continuation indented past the line's own indentation, instead of scrolling sideways. A block with line numbers always scrolls. |
292
+ | `mathjax_macros` | empty | TeX macros, each a definition or `[definition, argument count]`. |
293
+ | `pygments_light`, `pygments_dark` | `friendly`, `github-dark` | The [code colours](https://pygments.org/styles/) of each colour scheme. |
294
+
295
+ ```yaml
296
+ title: A Book of Methods
297
+ author: A. Author
298
+ repo: https://github.com/example/methods
299
+ repo_host: GitHub
300
+ edit_url: https://github.com/example/methods/blob/main/book/
301
+ mathjax_macros:
302
+ dd: \mathrm{d}
303
+ vec: ['\boldsymbol{#1}', 1]
304
+ ```
305
+
306
+ ## Overriding the theme
307
+
308
+ A book changes the theme through its own `theme/` directory, which the build reads
309
+ first.
310
+
311
+ | Path | Effect |
312
+ |---|---|
313
+ | `theme/templates/NAME.html` | Replaces the package's template of that name. The templates are `base`, `home`, `part`, `chapter`, `section`, `glossary` and `help`. |
314
+ | `theme/static/NAME` | Replaces the package's static file of that name, or adds a new one. A `pygments.css` here takes the place of the generated one. |
315
+
316
+ A template replaced whole no longer receives changes from new releases, so extend the
317
+ package's copy instead where a small change is enough. The package's templates stay
318
+ reachable under `bookspine/`, and `base.html` has an empty `extra_head` block for
319
+ additions to the page's head:
320
+
321
+ ```jinja
322
+ {% extends "bookspine/base.html" %}
323
+ {% block extra_head %}
324
+ <link rel="stylesheet" href="{{ page.root }}static/local.css">
325
+ {% endblock %}
326
+ ```
327
+
328
+ ## The site directory
329
+
330
+ The build keeps a list of its top-level entries in `site/.bookspine-stamp.json`. A
331
+ rebuild removes those entries whole and leaves any other top-level file alone. It stops
332
+ if the directory is not empty and has no stamp, as it would for a mistyped `--site-dir`
333
+ or a `site/` written by another program, and it refuses a filesystem root, the home
334
+ directory, the project directory and anything holding them.
335
+
336
+ ## Revision dates
337
+
338
+ The title page and footer show when the book was revised, by default the month of the
339
+ build. A scheduled rebuild would advance that date with nothing changed, so set
340
+ [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/specs/source-date-epoch/) to the
341
+ last commit's time:
342
+
343
+ ```bash
344
+ SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) bookspine build
345
+ ```
346
+
347
+ ## License
348
+
349
+ [MIT](https://github.com/AlkaidCheng/bookspine/blob/main/LICENSE)
350
+