smalldocs 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 (78) hide show
  1. smalldocs-0.1.0/.github/workflows/pages.yml +32 -0
  2. smalldocs-0.1.0/.gitignore +9 -0
  3. smalldocs-0.1.0/CLAUDE.md +88 -0
  4. smalldocs-0.1.0/LICENSE +21 -0
  5. smalldocs-0.1.0/PKG-INFO +63 -0
  6. smalldocs-0.1.0/PLAN.md +175 -0
  7. smalldocs-0.1.0/README.md +39 -0
  8. smalldocs-0.1.0/docs/_quarto.yml +48 -0
  9. smalldocs-0.1.0/docs/guide/api.qmd +81 -0
  10. smalldocs-0.1.0/docs/guide/commands.qmd +66 -0
  11. smalldocs-0.1.0/docs/guide/config.qmd +99 -0
  12. smalldocs-0.1.0/docs/guide/from-quarto.qmd +47 -0
  13. smalldocs-0.1.0/docs/guide/get-started.qmd +105 -0
  14. smalldocs-0.1.0/docs/guide/listings.qmd +65 -0
  15. smalldocs-0.1.0/docs/guide/markdown.qmd +195 -0
  16. smalldocs-0.1.0/docs/guide/notebooks.ipynb +132 -0
  17. smalldocs-0.1.0/docs/guide/themes.qmd +61 -0
  18. smalldocs-0.1.0/docs/images/mark.svg +7 -0
  19. smalldocs-0.1.0/docs/index.qmd +40 -0
  20. smalldocs-0.1.0/docs/news/first-release.qmd +16 -0
  21. smalldocs-0.1.0/docs/news/index.qmd +9 -0
  22. smalldocs-0.1.0/docs/news/why.qmd +15 -0
  23. smalldocs-0.1.0/justfile +27 -0
  24. smalldocs-0.1.0/pyproject.toml +39 -0
  25. smalldocs-0.1.0/ruff.toml +7 -0
  26. smalldocs-0.1.0/src/smalldocs/__init__.py +3 -0
  27. smalldocs-0.1.0/src/smalldocs/api.py +675 -0
  28. smalldocs-0.1.0/src/smalldocs/assets/smalldocs.css +380 -0
  29. smalldocs-0.1.0/src/smalldocs/assets/smalldocs.js +242 -0
  30. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap/LICENSE +21 -0
  31. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap/bootstrap.bundle.min.js +7 -0
  32. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap/bootstrap.min.css +6 -0
  33. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap-icons/LICENSE +21 -0
  34. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap-icons/bootstrap-icons.min.css +5 -0
  35. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
  36. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
  37. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/LICENSE +21 -0
  38. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/cerulean.min.css +12 -0
  39. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/cosmo.min.css +12 -0
  40. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/cyborg.min.css +12 -0
  41. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/darkly.min.css +12 -0
  42. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/flatly.min.css +12 -0
  43. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/journal.min.css +12 -0
  44. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/litera.min.css +12 -0
  45. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/lumen.min.css +12 -0
  46. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/lux.min.css +12 -0
  47. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/materia.min.css +12 -0
  48. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/minty.min.css +12 -0
  49. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/morph.min.css +12 -0
  50. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/pulse.min.css +12 -0
  51. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/quartz.min.css +12 -0
  52. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/sandstone.min.css +12 -0
  53. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/simplex.min.css +12 -0
  54. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/sketchy.min.css +12 -0
  55. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/slate.min.css +12 -0
  56. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/solar.min.css +12 -0
  57. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/spacelab.min.css +12 -0
  58. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/superhero.min.css +12 -0
  59. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/united.min.css +12 -0
  60. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/vapor.min.css +12 -0
  61. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/yeti.min.css +12 -0
  62. smalldocs-0.1.0/src/smalldocs/assets/vendor/bootswatch/zephyr.min.css +12 -0
  63. smalldocs-0.1.0/src/smalldocs/assets/vendor/fuse/LICENSE +201 -0
  64. smalldocs-0.1.0/src/smalldocs/assets/vendor/fuse/fuse.min.js +9 -0
  65. smalldocs-0.1.0/src/smalldocs/check.py +60 -0
  66. smalldocs-0.1.0/src/smalldocs/cli.py +118 -0
  67. smalldocs-0.1.0/src/smalldocs/config.py +250 -0
  68. smalldocs-0.1.0/src/smalldocs/highlight.py +76 -0
  69. smalldocs-0.1.0/src/smalldocs/layout.py +826 -0
  70. smalldocs-0.1.0/src/smalldocs/listing.py +406 -0
  71. smalldocs-0.1.0/src/smalldocs/markdown.py +793 -0
  72. smalldocs-0.1.0/src/smalldocs/notebook.py +134 -0
  73. smalldocs-0.1.0/src/smalldocs/publish.py +91 -0
  74. smalldocs-0.1.0/src/smalldocs/serve.py +125 -0
  75. smalldocs-0.1.0/src/smalldocs/shortcodes.py +81 -0
  76. smalldocs-0.1.0/src/smalldocs/site.py +520 -0
  77. smalldocs-0.1.0/tests/test_smalldocs.py +931 -0
  78. smalldocs-0.1.0/uv.lock +233 -0
@@ -0,0 +1,32 @@
1
+ name: docs
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ pages: write
9
+ id-token: write
10
+ concurrency:
11
+ group: pages
12
+ cancel-in-progress: true
13
+ jobs:
14
+ build:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v6
19
+ - run: uv sync
20
+ - run: uv run smalldocs render docs --strict
21
+ - uses: actions/upload-pages-artifact@v3
22
+ with:
23
+ path: docs/_site
24
+ deploy:
25
+ needs: build
26
+ runs-on: ubuntu-latest
27
+ environment:
28
+ name: github-pages
29
+ url: ${{ steps.deployment.outputs.page_url }}
30
+ steps:
31
+ - id: deployment
32
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,9 @@
1
+ .venv/
2
+ __pycache__/
3
+ _site/
4
+ dist/
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ docs/api/
9
+ docs/_symbols.json
@@ -0,0 +1,88 @@
1
+ # smalldocs
2
+
3
+ smalldocs builds a Quarto-like website from a `_quarto.yml` project, in pure Python, and is published on
4
+ PyPI as `smalldocs`. It exists so that Rahul's projects (babykev, smallwikiapp, nbinlineai, ProblemSolving,
5
+ the timewalk class kits) can build their docs sites without Quarto, which is 600 MB of Pandoc, Deno, Sass
6
+ and Typst. It makes websites only: no PDF, Word, slides or books, and it runs no code.
7
+
8
+ The user documentation is the site in `docs/`, built by smalldocs itself. Keep it true when the behaviour
9
+ changes. The README is a short front page.
10
+
11
+ ## Rules the tool must keep
12
+
13
+ - **A project that builds with Quarto builds with smalldocs, with the same pages, the same anchors and the
14
+ same links.** Heading ids follow Pandoc's algorithm (`markdown.pandoc_id`); links to `.qmd`/`.md`/`.ipynb`
15
+ become `.html`; links from `/` start at the root. Check a change against real sites (below).
16
+ - **Read `_quarto.yml` unchanged.** smalldocs' own settings live under `smalldocs:`, which Quarto ignores. A
17
+ key smalldocs does not read is a warning, never silent.
18
+ - **Any Bootswatch theme, with no Sass.** `assets/smalldocs.css` uses only Bootstrap's `--bs-*` variables
19
+ and its own `--sd-*` ones. Never hard-code a colour that a theme should set (the Quarto highlight colours
20
+ and the inline-code purple are the exceptions, with dark variants under `html.quarto-dark`).
21
+ - **The output folder is emptied at each build**, so `Site.check_output` refuses an output folder that is
22
+ the project or above it, holds `.git`, or is not empty and has no `site_libs`. The API build deletes only
23
+ pages listed in its manifest, `api/.smalldocs-api`, and `api.out` must be inside the site. Keep these
24
+ guards; each has a test.
25
+ - **Never publish a source.** A link to a page that is not built is reported, and its `.qmd` is never
26
+ copied. `resources` and `render` take one glob or a list (`config.as_list`); globs use `config.glob_match`
27
+ (as Quarto: with a `/`, `*` stays in one folder; with no `/`, the glob matches at any depth).
28
+ - **`publish` never touches the working tree or the current branch.** It works in a temporary worktree,
29
+ removes it in `finally`, deletes only a branch it made (a uuid name), skips hooks, and refuses to
30
+ publish onto the current branch, the remote's default branch, `main` or `master`.
31
+ - **`smalldocs api` must import only fastcore and PyYAML**, because it runs in the documented project's
32
+ environment. Keep the imports in `cli.py` lazy.
33
+ - **The API pages are byte-for-byte what babykev's `apidocs.py` made.** `api.module_markdown` and `api.page`
34
+ are ported from `babykev/src/babykev/docs.py` and `babykev/docs/apidocs.py`.
35
+
36
+ ## Layout
37
+
38
+ | File | What it is |
39
+ |---|---|
40
+ | `src/smalldocs/config.py` | `_quarto.yml`: load, merge (`merge`, `dir_metadata`), the known keys, `ConfigError`, `BuildError` |
41
+ | `src/smalldocs/markdown.py` | markdown-it-py with mdit-py-plugins, and Pandoc's rules: heading attributes and ids, fenced divs, callouts, tabsets, figures, sections, typography, code, maths |
42
+ | `src/smalldocs/highlight.py` | Pygments tokens to Pandoc's classes (`kw`, `st`, `co`, ...) |
43
+ | `src/smalldocs/notebook.py` | `.ipynb` to Markdown with raw HTML outputs; nothing runs |
44
+ | `src/smalldocs/shortcodes.py` | `include`, `meta`, `var`, `env`, `pagebreak` |
45
+ | `src/smalldocs/site.py` | `Site`: discovery, pages, link rewriting (`resolve`), scripts, assets, resources, search.json, sitemap |
46
+ | `src/smalldocs/layout.py` | `SiteNav` (sidebars, navbar, order, breadcrumbs) and `Layout` (the page, in Quarto's markup, with `fastcore.xml`) |
47
+ | `src/smalldocs/listing.py` | Listings (default, grid, table), categories, RSS |
48
+ | `src/smalldocs/api.py` | The API reference: inventory, Markdown, pages, `_symbols.json`, `check` |
49
+ | `src/smalldocs/serve.py`, `publish.py`, `check.py`, `cli.py` | The commands |
50
+ | `src/smalldocs/assets/` | `smalldocs.css`, `smalldocs.js`, and `vendor/` (Bootswatch 5.3.8, Bootstrap 5.3.8, Bootstrap Icons 1.11.3, Fuse.js 7.0.0). Vendored: do not edit |
51
+ | `tests/test_smalldocs.py` | One test per feature |
52
+ | `docs/` | smalldocs' own site; it uses every feature, and its Reference is made by `smalldocs.api` from this package |
53
+
54
+ ## Commands
55
+
56
+ ```
57
+ just test # pytest; extra arguments go to pytest
58
+ just lint # ruff
59
+ just render DIR # build a site
60
+ just docs # preview smalldocs' own site with reload
61
+ just build # the wheel and sdist into dist/
62
+ ```
63
+
64
+ ## Checking a change
65
+
66
+ 1. `just test` and `just lint`, as separate commands; read each result.
67
+ 2. `uv run smalldocs api check --dir docs`: every function typed and documented.
68
+ 3. For anything in `layout.py`, `markdown.py` or `assets/`: build `docs/` and drive it in headless Chrome
69
+ (Playwright, `channel="chrome"`): tabs, callouts, search, the dark toggle, listings, a phone width.
70
+ 4. Against real sites: copy a site into the scratchpad (never build in place: ProblemSolving's
71
+ `output-dir` is `../docs`, a folder of its repository), render it with Quarto and with smalldocs, and
72
+ compare the pages, the ids and the links. babykev needs its own Python for the API; run smalldocs
73
+ with `PYTHONPATH` set to `src` and to this project's site-packages.
74
+ 5. An adversarial review by an Opus subagent before each commit.
75
+
76
+ ## Conventions
77
+
78
+ - Python 3.11+, ruff with line length 150. Dependencies: fastcore, markdown-it-py, mdit-py-plugins,
79
+ PyYAML, Pygments. Nothing else at run time.
80
+ - Type and document every function in the docments style: one comment per parameter, one on the return,
81
+ a one-line docstring.
82
+ - Plain, short sentences in docs, docstrings and messages.
83
+ - Ask Rahul before every commit. End each commit message with the line `Coded using Claude`.
84
+
85
+ ## Releasing
86
+
87
+ Raise `version` in `pyproject.toml` and `__version__` in `src/smalldocs/__init__.py`, run the checks,
88
+ `just build`, then `uv publish` (the token is in `~/.pypirc`; pass it with `--token`). Tag `vX.Y.Z`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rahul Dave
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,63 @@
1
+ Metadata-Version: 2.5
2
+ Name: smalldocs
3
+ Version: 0.1.0
4
+ Summary: Quarto-like websites from a _quarto.yml project, in pure Python: pages, API reference and listings
5
+ Project-URL: Homepage, https://github.com/rahuldave/smalldocs
6
+ Author-email: Rahul Dave <rahuldave@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ License-File: src/smalldocs/assets/vendor/bootstrap-icons/LICENSE
10
+ License-File: src/smalldocs/assets/vendor/bootstrap/LICENSE
11
+ License-File: src/smalldocs/assets/vendor/bootswatch/LICENSE
12
+ License-File: src/smalldocs/assets/vendor/fuse/LICENSE
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Documentation
15
+ Classifier: Topic :: Software Development :: Documentation
16
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: fastcore>=1.8
19
+ Requires-Dist: markdown-it-py>=3.0
20
+ Requires-Dist: mdit-py-plugins>=0.4
21
+ Requires-Dist: pygments>=2.17
22
+ Requires-Dist: pyyaml>=6.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # smalldocs
26
+
27
+ smalldocs builds a website from a [Quarto](https://quarto.org) project, in pure Python. It reads the same
28
+ `_quarto.yml` and the same Markdown, and writes the same kind of site into `_site`: pages with a navbar, a
29
+ sidebar and a table of contents, notebooks with their saved outputs, reference pages made from your code,
30
+ and listings of posts with categories and a feed. The site takes any [Bootswatch](https://bootswatch.com)
31
+ theme, in light and dark.
32
+
33
+ It makes websites only: no PDF, Word, slides or books, and it runs no code. In return it is one package
34
+ from PyPI, with no Pandoc, Deno, Sass or TeX.
35
+
36
+ ```bash
37
+ pip install smalldocs
38
+
39
+ smalldocs render docs # build docs/_site
40
+ smalldocs preview docs # serve it at http://127.0.0.1:4200, rebuild and reload on each change
41
+ smalldocs check docs # what smalldocs ignores, broken links, Markdown only Pandoc reads
42
+ smalldocs api build --dir docs # the API reference, from docstrings, types and docments
43
+ smalldocs publish gh-pages docs # push the site to the gh-pages branch
44
+ ```
45
+
46
+ The documentation is in [`docs/`](docs/), built with smalldocs.
47
+
48
+ ## What it reads
49
+
50
+ - `_quarto.yml`, `_metadata.yml` and front matter, merged as Quarto merges them: `project`
51
+ (`output-dir`, `render`, `resources`, `pre-render`, `post-render`), `website` (navbar, sidebar, page
52
+ navigation, footer, search, site URL, repository links) and `format.html` (theme, CSS, table of contents,
53
+ numbered sections, includes).
54
+ - Markdown: CommonMark, tables, footnotes, definition lists, task lists, `{#id .class}` attributes,
55
+ fenced divs, callouts, tabsets, `$` maths (KaTeX), mermaid, raw HTML, and the shortcodes `include`,
56
+ `meta`, `var` and `env`. Heading ids follow Pandoc's rules, so links written for Quarto keep working.
57
+ - Notebooks, with the outputs they were saved with, and Quarto's `#|` cell options.
58
+ - Listings: `default`, `grid` and `table`, with sorting, filtering, categories, pages and RSS.
59
+
60
+ ## Licence
61
+
62
+ MIT. smalldocs ships Bootstrap, Bootswatch and Bootstrap Icons (MIT) and Fuse.js (Apache-2.0), each with
63
+ its licence in `src/smalldocs/assets/vendor/`.
@@ -0,0 +1,175 @@
1
+ # smalldocs: a plan
2
+
3
+ A small, pure-Python tool that builds a Quarto-like website from a `_quarto.yml` project: regular pages,
4
+ API reference pages, and listing (blog/collection) pages, into `_site`. No PDF, Word, slides, books,
5
+ code execution, Lua, Sass or Pandoc.
6
+
7
+ ## 1. What we use Quarto for today (surveyed 2026-10-10)
8
+
9
+ 18 `_quarto.yml` sites under `~/Projects` (babykev and its copies, smallwikiapp, nbinlineai and its
10
+ copies, ProblemSolving, smallwikiapp-walk, babykev-class prototype). timewalk-test has none: its tags
11
+ hold no `docs/`. All are `type: website` except `playing_with_quarto` (a book, with pdf and docx).
12
+
13
+ Config keys in use, and nothing else:
14
+
15
+ | Area | Keys |
16
+ |---|---|
17
+ | project | `type: website`, `output-dir`, `pre-render`, `render` (globs), `resources` (globs) |
18
+ | website | `title`, `description`, `site-url`, `repo-url`, `navbar.left` (text/href), `sidebar` (`style: docked`, `search`, `contents` with files, globs like `api/*`, `section:`, `text`/`href`), `page-navigation`, `search` |
19
+ | format.html | `theme: cosmo` (every site), `css`, `toc`, `toc-depth`, `code-copy`, `from: markdown-tex_math_dollars-smart` |
20
+ | filters | `linkify.lua` only: a backticked name becomes a link to its API entry, from `_symbols.json` |
21
+
22
+ Markdown in the 71 pages: pipe tables (43 pages), images, `{#id}` on headings, `{.source-link}` on
23
+ links, inline `$` (dollars, not maths). No callouts, tabsets, listings, shortcodes, cross-refs, footnotes
24
+ or executed code. One notebook (`babykev/docs/guide/01_mask.ipynb`), rendered from stored outputs.
25
+
26
+ The API pages come from a per-project `docs/apidocs.py` (86 lines) over a per-project `docs.py`
27
+ (babykev: 451 lines; fastcore `docments`, dataclasses, pydantic). The copies have drifted
28
+ (smallwikiapp's has `check` and `module`; babykev's does not).
29
+
30
+ Quarto 1.8.26 is 638 MB: Deno, Pandoc, dart-sass, esbuild and Typst.
31
+
32
+ ## 2. Feasibility: yes
33
+
34
+ - **Themes without Sass.** Quarto compiles Bootswatch Sass with its own layer. We do not need to:
35
+ Bootswatch 5.3.8 ships each of its 25 themes as a plain `bootstrap.min.css` (about 30 KB gzipped), and
36
+ Bootstrap 5.3 exposes the theme as CSS variables (`--bs-primary`, `--bs-body-bg`, `--bs-border-color`,
37
+ `--bs-secondary-bg`, `--bs-link-color`, `--bs-font-sans-serif`, ...). One hand-written `smalldocs.css`
38
+ that uses only these variables, plus Bootstrap's own classes (`navbar`, `card`, `nav-tabs`, `table`,
39
+ `alert`), looks right under every theme. All 25 vendored add about 750 KB to the wheel; a build copies
40
+ only the chosen one into `_site/site_libs/`.
41
+ - **Markdown.** markdown-it-py (the parser behind MyST) with mdit-py-plugins covers front matter,
42
+ tables, footnotes, definition lists, `$` maths, task lists and inline `{.class}` attributes. We add
43
+ small rules for what Pandoc has and it lacks: `{#id .class}` after a heading, fenced divs
44
+ `::: {.class}`, raw `{=html}` blocks, and Pandoc's heading-id algorithm, so anchors stay the same.
45
+ - **HTML.** We copy the shape of Quarto's markup (its class and id names: `#quarto-header`,
46
+ `#quarto-sidebar`, `#TOC`, `.quarto-title-block`, `.quarto-grid-item`, `callout-*`, `panel-tabset`),
47
+ not its files, and write it with `fastcore.xml` (FT components), so templating adds no dependency.
48
+ - **Notebooks.** `.ipynb` is JSON: markdown cells, code cells, and stored outputs (stream, text/plain,
49
+ text/html, image/png, image/svg+xml, error with ANSI stripped), with `#| echo: false` and
50
+ `#| output: false`. No kernel, as Quarto by default.
51
+ - **API docs.** Generalise babykev's `docs.py` and `apidocs.py` into `smalldocs.api`, and build
52
+ `linkify.lua` in. This removes the drifting copies.
53
+
54
+ Dependencies: `fastcore`, `markdown-it-py`, `mdit-py-plugins`, `PyYAML`, `Pygments`. All pure Python.
55
+ Vendored: Bootswatch and Bootstrap (MIT), Fuse.js (Apache-2.0) for search.
56
+
57
+ Estimate: 3,000 to 4,000 lines of Python, about 600 of CSS and JS.
58
+
59
+ ## 3. Risks, and what we do about them
60
+
61
+ | Risk | Answer |
62
+ |---|---|
63
+ | markdown-it is not Pandoc: grid tables, citations `[@key]`, raw LaTeX, `{.class}` on spans | Out of scope; `smalldocs check` names each one with file and line. None of our sites uses them |
64
+ | Anchors change and links break | Pandoc's id algorithm, tested against Quarto's output; a link checker in `render` |
65
+ | `.qmd` links | Rewrite `.qmd`/`.md`/`.ipynb` to `.html` and root `/` links to relative ones, as Quarto does (`_symbols.json` targets are `/api/api.qmd#Noul`) |
66
+ | Looks almost like Quarto, not exactly | Screenshot comparisons against Quarto under cosmo, flatly, darkly and sketchy |
67
+ | `theme: [cosmo, custom.scss]` | Refused with a message: use `css:` and `--bs-*` variables. No site of ours uses `.scss` |
68
+ | Lua filters | Ignored with a warning; the only one we use (linkify) is built in. Later: Python filters |
69
+ | `{python}` cells in `.qmd` | Shown as code, not run, with a warning |
70
+
71
+ ## 4. What smalldocs does
72
+
73
+ **Commands**
74
+
75
+ ```
76
+ smalldocs render [DIR] build DIR (default .) into its output-dir, default _site
77
+ smalldocs preview [DIR] [--port] render, serve, rebuild on change, reload the browser
78
+ smalldocs check [DIR] config keys we ignore, Pandoc-only syntax, broken links
79
+ smalldocs api build|check|module NAME the reference pages; the gaps in the docments; one module as Markdown
80
+ smalldocs publish gh-pages [DIR] push the output-dir to the gh-pages branch (as quarto publish gh-pages)
81
+ ```
82
+
83
+ **Config.** Read `_quarto.yml` unchanged, so one site builds with either tool. Our own settings go
84
+ under a `smalldocs:` key, which Quarto ignores:
85
+
86
+ ```yaml
87
+ smalldocs:
88
+ api:
89
+ packages: [babykev] # importable packages to document
90
+ out: api # pages go to docs/api/
91
+ source: https://github.com/rahuldave/babykev/blob/main
92
+ linkify: true # `render` in prose links to its entry
93
+ ```
94
+
95
+ Unknown keys get a warning that names them; `--strict` makes it an error.
96
+
97
+ **Supported, by area**
98
+
99
+ - project: `type: website`, `output-dir`, `render`, `resources`, `pre-render`, `post-render` (run with
100
+ Quarto's `QUARTO_PROJECT_*` environment variables).
101
+ - website: `title`, `description`, `site-url` (sitemap.xml), `repo-url` (link and repo actions),
102
+ `favicon`, `navbar` (left/right, menus, `search`), `sidebar` (docked/floating, files, globs, sections,
103
+ `auto`), `page-navigation`, `page-footer`, `search` (search.json and a Fuse.js box), `open-graph` (basic).
104
+ - format.html: `theme` (any Bootswatch name, or `light:`/`dark:` with a toggle), `css`, `toc`,
105
+ `toc-depth`, `toc-title`, `number-sections`, `code-copy`, `highlight-style` (Pygments),
106
+ `from: ...-tex_math_dollars-smart`, `page-layout` (article, full), `anchor-sections`.
107
+ - page front matter: `title`, `subtitle`, `description`, `author`, `date`, `categories`, `image`,
108
+ `draft`, `toc`, `listing`, `page-layout`, `search: false`.
109
+ - Markdown: CommonMark, pipe tables, footnotes, definition lists, task lists, `{#id .class key=val}`,
110
+ fenced divs, callouts (note, tip, warning, important, caution; collapse; title), `panel-tabset`,
111
+ raw HTML, `$`/`$$` maths with KaTeX, mermaid blocks (mermaid.js from a CDN).
112
+ - Listings (`listing:` in front matter): `contents` (globs), `type: default|grid|table`, `sort`,
113
+ `fields`, `categories` (with filter), `sort-ui`, `filter-ui`, `page-size`, `max-items`,
114
+ `grid-columns`, `image-height`, `feed: true` (RSS). Item data from each page's front matter; when it
115
+ is missing, the first paragraph for the description and the first image for the picture. Several
116
+ listings per page, by `id`.
117
+ - API: the generic `smalldocs.api` from babykev's `docs.py`. Modules, classes, methods, functions;
118
+ signatures with types; docment tables; dataclass fields; pydantic fields (detected, not imported);
119
+ TypedDict keys with comments; a source link per entry; the `check` of docments; and the name index
120
+ that the built-in linkify uses.
121
+
122
+ ## 5. Layout of the repository
123
+
124
+ ```
125
+ smalldocs/
126
+ pyproject.toml justfile ruff.toml CLAUDE.md README.md
127
+ src/smalldocs/
128
+ config.py # _quarto.yml: load, defaults, unknown keys, globs
129
+ markdown.py # markdown-it setup and the Pandoc-like rules (ids, divs, callouts, tabsets, raw)
130
+ notebook.py # .ipynb to the same tokens
131
+ pages.py # discovery, front matter, link rewriting, the page model
132
+ layout.py # fastcore.xml: navbar, sidebar, title block, TOC, page nav, footer
133
+ listing.py # listings and RSS
134
+ search.py # search.json, sitemap.xml
135
+ api.py # the API reference (from babykev docs.py and apidocs.py)
136
+ serve.py # preview: http.server, watch, reload
137
+ publish.py # gh-pages
138
+ cli.py # the commands, with fastcore.script
139
+ assets/ # smalldocs.css, smalldocs.js, vendor/{bootswatch/*, bootstrap, fuse, katex?}
140
+ tests/ # one test per feature, and a kitchen-sink site
141
+ docs/ # smalldocs' own site, built by smalldocs: it uses every feature
142
+ ```
143
+
144
+ ## 6. Phases
145
+
146
+ Each phase ends with its tests green and an Opus adversarial review, as in timewalk.
147
+
148
+ 1. **Skeleton.** pyproject (hatchling, uv), justfile, ruff, CLAUDE.md, vendored assets with licences.
149
+ 2. **Core render.** Config, discovery, the Markdown pipeline, link rewriting, navbar, sidebar, TOC,
150
+ title block, themes, `css`, `resources`, `pre-render`. Test: babykev/docs, smallwikiapp-walk/site,
151
+ nbinlineai/docs and ProblemSolving/site build with no Quarto, and every link resolves.
152
+ 3. **Pages in full.** Notebooks, Pygments highlighting, code-copy, callouts, tabsets, maths, mermaid,
153
+ page navigation, footer, light/dark.
154
+ 4. **API.** `smalldocs.api` and the built-in linkify. Test: babykev's reference pages and
155
+ `_symbols.json` match what `apidocs.py` makes today.
156
+ 5. **Listings and search.** Default, grid and table; categories; sorting; pages; RSS; search.json and
157
+ the search box; sitemap.
158
+ 6. **Preview and publish.** `smalldocs preview` with reload; `publish gh-pages`.
159
+ 7. **Compare with Quarto.** Render each surveyed site with both into the scratchpad. Compare pages,
160
+ anchors and links mechanically, and screenshots by eye under four themes. Write smalldocs' own docs.
161
+ 8. **Release.** GitHub repo `rahuldave/smalldocs`, PyPI via trusted publishing from a GitHub Action,
162
+ `v0.1.0`.
163
+
164
+ Only after that, and when you say so: move babykev, timewalk-test and the kits from Quarto to
165
+ smalldocs.
166
+
167
+ ## 7. Decisions for you
168
+
169
+ 1. **Name.** `smalldoc` is taken on PyPI (a 2012 SmallTalk-style API documenter by sebastien).
170
+ `smalldocs` is free. I recommend it.
171
+ 2. **Templates in `fastcore.xml`, not Jinja2.** One dependency fewer, and in Python. The cost: a user
172
+ cannot override a template file; they override with CSS, or with a Python hook later.
173
+ 3. **Vendor all 25 Bootswatch themes** in the wheel (about 750 KB), so that a build works offline. The
174
+ other choice is links to a CDN.
175
+ 4. **PyPI.** Publishing needs a trusted publisher set up on your PyPI account for the GitHub repository.
@@ -0,0 +1,39 @@
1
+ # smalldocs
2
+
3
+ smalldocs builds a website from a [Quarto](https://quarto.org) project, in pure Python. It reads the same
4
+ `_quarto.yml` and the same Markdown, and writes the same kind of site into `_site`: pages with a navbar, a
5
+ sidebar and a table of contents, notebooks with their saved outputs, reference pages made from your code,
6
+ and listings of posts with categories and a feed. The site takes any [Bootswatch](https://bootswatch.com)
7
+ theme, in light and dark.
8
+
9
+ It makes websites only: no PDF, Word, slides or books, and it runs no code. In return it is one package
10
+ from PyPI, with no Pandoc, Deno, Sass or TeX.
11
+
12
+ ```bash
13
+ pip install smalldocs
14
+
15
+ smalldocs render docs # build docs/_site
16
+ smalldocs preview docs # serve it at http://127.0.0.1:4200, rebuild and reload on each change
17
+ smalldocs check docs # what smalldocs ignores, broken links, Markdown only Pandoc reads
18
+ smalldocs api build --dir docs # the API reference, from docstrings, types and docments
19
+ smalldocs publish gh-pages docs # push the site to the gh-pages branch
20
+ ```
21
+
22
+ The documentation is in [`docs/`](docs/), built with smalldocs.
23
+
24
+ ## What it reads
25
+
26
+ - `_quarto.yml`, `_metadata.yml` and front matter, merged as Quarto merges them: `project`
27
+ (`output-dir`, `render`, `resources`, `pre-render`, `post-render`), `website` (navbar, sidebar, page
28
+ navigation, footer, search, site URL, repository links) and `format.html` (theme, CSS, table of contents,
29
+ numbered sections, includes).
30
+ - Markdown: CommonMark, tables, footnotes, definition lists, task lists, `{#id .class}` attributes,
31
+ fenced divs, callouts, tabsets, `$` maths (KaTeX), mermaid, raw HTML, and the shortcodes `include`,
32
+ `meta`, `var` and `env`. Heading ids follow Pandoc's rules, so links written for Quarto keep working.
33
+ - Notebooks, with the outputs they were saved with, and Quarto's `#|` cell options.
34
+ - Listings: `default`, `grid` and `table`, with sorting, filtering, categories, pages and RSS.
35
+
36
+ ## Licence
37
+
38
+ MIT. smalldocs ships Bootstrap, Bootswatch and Bootstrap Icons (MIT) and Fuse.js (Apache-2.0), each with
39
+ its licence in `src/smalldocs/assets/vendor/`.
@@ -0,0 +1,48 @@
1
+ project:
2
+ type: website
3
+ output-dir: _site
4
+
5
+ website:
6
+ title: smalldocs
7
+ description: Quarto-like websites from a _quarto.yml project, in pure Python
8
+ site-url: https://rahuldave.com/smalldocs/
9
+ repo-url: https://github.com/rahuldave/smalldocs
10
+ repo-actions: [source, issue]
11
+ page-navigation: true
12
+ navbar:
13
+ left:
14
+ - href: index.qmd
15
+ text: Home
16
+ - href: guide/get-started.qmd
17
+ text: Guide
18
+ - href: api/site.qmd
19
+ text: Reference
20
+ - href: news/index.qmd
21
+ text: News
22
+ tools:
23
+ - icon: github
24
+ href: https://github.com/rahuldave/smalldocs
25
+ sidebar:
26
+ style: floating
27
+ contents:
28
+ - section: Guide
29
+ contents: guide/*
30
+ - section: Reference
31
+ contents: api/*
32
+ page-footer:
33
+ left: "smalldocs is MIT-licensed."
34
+ right: "Built with [smalldocs](https://github.com/rahuldave/smalldocs)."
35
+
36
+ format:
37
+ html:
38
+ theme:
39
+ light: cosmo
40
+ dark: darkly
41
+ toc: true
42
+ code-copy: true
43
+
44
+ smalldocs:
45
+ api:
46
+ packages: [smalldocs]
47
+ root: ..
48
+ source: https://github.com/rahuldave/smalldocs/blob/main
@@ -0,0 +1,81 @@
1
+ ---
2
+ title: The API reference
3
+ description: Reference pages made from your code, and names in backticks that link to them.
4
+ order: 5
5
+ ---
6
+
7
+ smalldocs writes a reference page for each module of your package. It reads what the code already
8
+ says: the types from the annotations, the description of each parameter from the comment beside it,
9
+ and the summary from the docstring. Nothing is written twice. The [Reference](../api/site.qmd) of this
10
+ site is made this way, from smalldocs' own code.
11
+
12
+ ## Write the code
13
+
14
+ Put one parameter on each line, with its comment beside it, and the return's comment after the
15
+ colon of the `def` line. [fastcore](https://fastcore.fast.ai) calls these comments *docments*.
16
+
17
+ ```python
18
+ def add(
19
+ a: int, # The first number
20
+ b: int = 2, # The second number
21
+ ) -> int: # Their sum
22
+ "Add two numbers."
23
+ return a + b
24
+ ```
25
+
26
+ A dataclass shows its constructor, with the comment beside each field. A pydantic model shows its
27
+ fields, with their descriptions. A `TypedDict` shows its keys, with the comment beside each.
28
+
29
+ ## Turn it on
30
+
31
+ ```yaml
32
+ smalldocs:
33
+ api:
34
+ packages: [mypkg] # the importable packages to document
35
+ out: api # the folder of pages, inside the site; `api` by default
36
+ root: .. # the repository's root, from the site's folder; `..`, or `.` when the site's folder holds pyproject.toml
37
+ source: https://github.com/me/mypkg/blob/main # each entry links to its line here
38
+ check: ["*.py", "tests/**/*.py"] # more files that `smalldocs api check` holds to the convention
39
+ ```
40
+
41
+ Then every build writes `api/<module>.qmd`, one page for each public module, and `_symbols.json`,
42
+ the index of names. `out` must be a folder inside the site. smalldocs notes the pages it writes in
43
+ `api/.smalldocs-api`, and deletes a page only when an earlier build wrote it and this one did not, so a
44
+ page of your own in that folder, such as `api/index.qmd`, is safe. List the pages in the sidebar with
45
+ a glob:
46
+
47
+ ```yaml
48
+ website:
49
+ sidebar:
50
+ contents:
51
+ - section: Reference
52
+ contents: api/*
53
+ ```
54
+
55
+ smalldocs imports your package, so install it in the same environment as the package. If it cannot
56
+ import the package, it also looks in the repository's root and in its `src` folder.
57
+
58
+ ## Links from the prose
59
+
60
+ With the API on, a name in backticks that the reference documents becomes a link to its entry,
61
+ anywhere on the site: `Site`, `inventory`, `smalldocs.markdown.render`. A name in a link stays as it is, and a name
62
+ that the reference does not know stays as code.
63
+
64
+ ## At the terminal
65
+
66
+ ```bash
67
+ smalldocs api build --dir docs # write the pages and the index
68
+ smalldocs api module site --dir docs # print one module as plain Markdown, for people and agents
69
+ smalldocs api list --dir docs # every module, class, method and function, one line each
70
+ smalldocs api check --dir docs # what is typed and documented, and every gap; exit 1 if any
71
+ ```
72
+
73
+ `check` reports each function without a docstring, each parameter without a type or a docment, and
74
+ each return without one. Run it in your tests or before each commit.
75
+
76
+ ## Coming from apidocs.py
77
+
78
+ A project that made its reference with its own `apidocs.py` and `linkify.lua` keeps working: smalldocs
79
+ runs the `pre-render` script, and linkify is on when `filters` lists `linkify.lua`. To move to
80
+ `smalldocs.api`, add the section above, then drop `pre-render`, `apidocs.py`, the filter and
81
+ `linkify.lua`. The pages that it writes are the same, byte for byte.
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: The commands
3
+ description: Every command of smalldocs and its options.
4
+ order: 9
5
+ ---
6
+
7
+ Each command takes the project's folder, the one with `_quarto.yml`. It is the folder you are in
8
+ when you give none.
9
+
10
+ ## render
11
+
12
+ ```bash
13
+ smalldocs render [DIR] [--quiet] [--strict]
14
+ ```
15
+
16
+ Build the site. `--quiet` prints only warnings and errors. `--strict` exits with 1 when there is a
17
+ warning, such as a broken link or a key that smalldocs ignores.
18
+
19
+ ## preview
20
+
21
+ ```bash
22
+ smalldocs preview [DIR] [--port 4200] [--host 127.0.0.1] [--no-browser]
23
+ ```
24
+
25
+ Build the site, serve it, and open a browser. On each change to a file of the project, build it
26
+ again; the browser reloads. A failed build prints its error and keeps the last good site. It
27
+ listens on this machine only, unless you give `--host`.
28
+
29
+ ## check
30
+
31
+ ```bash
32
+ smalldocs check [DIR]
33
+ ```
34
+
35
+ Build the site into a scratch folder, and list what to look at before you move from Quarto: keys
36
+ that smalldocs ignores, broken links, and Markdown that only Pandoc reads. Exit with 1 if there is
37
+ anything.
38
+
39
+ ## api
40
+
41
+ ```bash
42
+ smalldocs api build|check|list [--dir DIR]
43
+ smalldocs api module NAME [--dir DIR]
44
+ ```
45
+
46
+ Make the reference pages, check the docments, list the symbols, or print one module as Markdown. See
47
+ [The API reference](api.qmd).
48
+
49
+ ## publish
50
+
51
+ ```bash
52
+ smalldocs publish gh-pages [DIR] [--branch gh-pages] [--remote origin] [--no-render] [-m MESSAGE]
53
+ ```
54
+
55
+ Build the site and push it to the branch, through a temporary worktree. Your working tree and your
56
+ branch do not change, and your git hooks do not run on the site's commit. It refuses to publish onto
57
+ your current branch, the remote's default branch, `main` or `master`, which hold your sources.
58
+ `--no-render` publishes the output folder as it is.
59
+
60
+ ## Exit codes
61
+
62
+ | Code | Means |
63
+ |---|---|
64
+ | 0 | Done |
65
+ | 1 | Done, with something to fix: `--strict` with warnings, or `check` and `api check` with findings |
66
+ | 2 | Stopped: no `_quarto.yml`, a bad option, a failed script, or a port in use |