feat(publish): replace publishing system with Quarto#33
Merged
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #33 +/- ##
==========================================
- Coverage 91.84% 90.92% -0.93%
==========================================
Files 27 31 +4
Lines 3852 3770 -82
Branches 867 857 -10
==========================================
- Hits 3538 3428 -110
- Misses 198 221 +23
- Partials 116 121 +5 ☔ View full report in Codecov by Harness. |
vanandrew
added a commit
that referenced
this pull request
Jun 16, 2026
…34) ## Summary Aligns jamb's ruff configuration with the **median** project's, which uses a curated lint rule set instead of jamb's defaults-only config. ### Config changes (`pyproject.toml`) - **`[tool.ruff.lint]`** — select `N` (pep8-naming), `UP` (pyupgrade), `B` (bugbear), `SIM` (simplify), and `RUF` on top of the existing `E`/`W`/`F`/`I`; ignore `E501` (the formatter handles line length). - **`[tool.ruff.format]`** — explicit `quote-style = "double"`, `indent-style = "space"`, `docstring-code-format = true`. ### Adapted, not copied verbatim These median values are project-specific, so I kept jamb's: - **`target-version`** stays `py310` (median is `py311`). jamb's `requires-python` is `>=3.10`; copying `py311` would let `pyupgrade` rewrite code with 3.11-only syntax and break 3.10 support. - **`line-length`** stays `120` (median is `88`) — keeping it avoids reformatting the entire codebase in this change. - median's `craniotrace`/`tissunet`/`clinseg` per-file-ignores are not relevant to jamb and were not copied. ### Code fixes The new rules surfaced **223 violations**, all resolved: - **Auto-fixed** (safe + unsafe): import sorting, `pyupgrade` modernizations, `contextlib.suppress`, ternaries, `next(iter(...))`, sorted `__all__`, etc. - **143 `RUF002`** — EN DASH (`–`) in docstrings (almost all in `test_comprehensive.py` titles) replaced with ASCII hyphens. - **Manual** — combined nested `with`/`if` statements, lowercased in-function constants (e.g. DFS `WHITE/GRAY/BLACK` → `white/gray/black`), and escaped/raw-stringed regex metacharacters in `pytest.raises(match=...)`. Behavior is unchanged: ruff check, ruff format, `ty`, and the full test suite (**1478 passed, 1 skipped**) are all green. > **Merge note:** this branch is off `main` and lightly edits `src/jamb/publish/formats/docx.py` and `html.py`, which PR #33 (Quarto publishing) deletes. Whichever PR merges second will hit a trivial modify/delete conflict on those two files — resolve by taking the deletion. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the publishing system with a single Quarto-based pipeline. Items are assembled into a document model, rendered to Quarto markdown (.qmd), then rendered to HTML, DOCX, and PDF by the bundled Quarto binary; Markdown and raw .qmd are written directly. - Output formats: HTML, DOCX, PDF (new), Markdown, and raw .qmd - Cross-references between items resolve to HTML anchors, DOCX bookmarks, and PDF links; every format gets a table of contents - Styling is data-driven: a bundled SCSS theme for HTML and a Word reference document, both overridable via --template; `jamb template` scaffolds them - quarto-cli is a core dependency so publishing works out of the box - The publish package splits a pure layer (document model + .qmd generation, unit-tested without the binary) from a render layer that invokes Quarto Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0371983 to
b98d6e3
Compare
…items - heading items map their level field to heading depth (h1-h6, clamped) - info items render as an anchored heading plus a Quarto note callout, giving them a distinct boxed style; the anchor lives on the heading so cross- references into an info item resolve in PDF/Typst (a callout id alone breaks the Typst render) - requirement items remain a level-2 heading plus body text Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b98d6e3 to
a3cc413
Compare
- Rework the default HTML theme: refined typography, prominent document-section banners, UID cross-references styled as monospace chips, tuned note callouts, and table/print styles. - Add [tool.jamb] settings to apply styling on every publish without repeating --template: publish_html_theme, publish_docx_reference, publish_pdf_template. An explicit --template still overrides. Missing configured files error clearly. - Make `jamb template` scaffold only the HTML theme by default; the Word reference document (which styles DOCX — SCSS does not) is now opt-in via --docx. The command also prints the pyproject.toml snippet to wire it up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make PDF and DOCX match the HTML theme as closely as each format allows, so a published document looks the same regardless of format: near-black text, a single blue accent, and a clean sans-serif typeface. - Rework the default HTML theme (theme.scss): clean modern look — SF/system type, hairline dividers, pill-shaped UID cross-references, soft note callouts. - PDF: bundle a Typst preamble (typst-theme.typ) included in the header, mapping the same palette/font/margins; applied by default, overridable via --template. - DOCX: generate the Word reference document at runtime by restyling Pandoc's default to the same palette and typeface (docx_reference.py) — applied by default, overridable via --template. No binary asset is committed. - `jamb template` scaffolds the HTML and PDF text themes by default; --docx adds the Word reference. Refresh docs/_static/publish-example.png to the new look. Format-specific HTML touches (pill chips, rounded cards) do not carry to PDF/DOCX. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render published documents as a formal specification, consistently across HTML, PDF, and DOCX: - Title block with a metadata line (document id, version, date, status). Version comes from project/config, date from the render, status from a new [tool.jamb].publish_status setting. - Numbered sections (1, 1.1, 1.1.1) and a "Contents" table of contents; HTML renders the TOC inline as a contents section rather than a sidebar. - Serif body with sans-serif headings and a conservative blue accent: theme.scss (HTML), typst-theme.typ with a "Page X of Y" footer (PDF), and the runtime Word reference document (DOCX, Georgia body / Helvetica Neue headings). Threads an optional subtitle through PublishDocument and build_publish_document; the CLI composes it from config plus the render date. Refresh docs/_static/publish-example.png and the publishing/configuration docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When publishing every document, the subtitle now starts with the version/date rather than a redundant "All documents" label. Single-document output keeps its "Document <PREFIX>" label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces jamb's document publishing system with a single, Quarto-based pipeline. The previous design had two independently hand-maintained renderers —
publish/formats/html.py(raw string concatenation) andpublish/formats/docx.py(manualpython-docxOXML) — with Markdown handled separately in the CLI. This is a ground-up replacement: the oldpublish/formats/package is deleted and the new code stands on its own.Requirement items now flow through one model → Quarto markdown (
.qmd) → Quarto, which renders HTML, DOCX, and PDF. Markdown and raw.qmdare written directly without invoking the binary.What's new
--template.jamb templatenow scaffolds these editable assets into./jamb-assets/.Architecture
src/jamb/publish/is split into a pure layer and a render layer:formats.py—OutputFormatenum + extension mappingdocument.py—build_publish_document()→ orderedPublishDocument(pure)qmd.py—PublishDocument→.qmdsource via Jinja2 (pure, unit-tested without the binary)quarto.py— locate/run the Quarto binary; typed errorsrender.py— generate.qmdin a temp dir and invoke Quartoassets/— bundleddocument.qmd.j2andtheme.scssCLI
jamb publish PREFIX [PATH]gains--pdf;--templateis now format-aware (SCSS / reference.docx/ Typst template)..pdfand.qmdare auto-detected from the extension.jamb templatescaffolds the styling assets instead of generating a.docx.Dependencies
python-docx.quarto-clias a core dependency (per design decision — publishing works out of the box).jinja2is now actually used (previously declared but unused).quarto-cliPyPI package downloads the ~150 MB Quarto binary at install time and hard-depends onjupyter/nbclient(jamb never executes notebooks, but the tree installs regardless). This meaningfully increases install size anduv synctime for every install, including pytest-plugin-only users. CI now enables uv caching so the build isn't repeated each run. Flagging in case we'd prefer an optionaljamb[publish]extra instead — easy to switch.Tests
tests/unit/test_publish_qmd.py— pure tests for the document model,.qmdgeneration, markdown escaping, format mapping, and binary resolution (no Quarto needed).tests/integration/test_publish_render.py— real renders asserting magic bytes and surviving anchors, marked@pytest.mark.quarto.quartoand auto-skip when the binary is absent (conftest hook).Docs
Updated the publishing guide, command reference, tutorial, installation, design, FAQ, troubleshooting, API reference, README, and CONTRIBUTING to describe the Quarto pipeline and PDF output.
Verification
uv sync && uv run quarto --version→ resolvesuv build --wheel→ bundlespublish/assets/*jamb publish all out.{html,docx,pdf,md,qmd}all render;jamb templatescaffolds theme + reference doc;--templateoverrides apply.🤖 Generated with Claude Code