Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ body:
attributes:
label: DocSprout version
description: Output of `docsprout --version`.
placeholder: docsprout 1.2.1
placeholder: docsprout 1.2.2
validations:
required: true
- type: input
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: '3.11'
- run: python -m pip install "git+https://github.com/ikelaiah/docsprout.git@v1.2.1"
- run: python -m pip install "git+https://github.com/ikelaiah/docsprout.git@v1.2.2"
- run: docsprout check
- if: inputs.versioned
run: docsprout check-release
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## 1.2.2

A reading and link-validation patch. No configuration, route, machine-format,
public CSS token or dependency change is required. Update package and workflow
pins to `v1.2.2`, then rebuild.

### Changed

- Add a keyboard skip link to every generated page. On phones, the sticky
header reduces its brand row after scrolling while keeping search and
settings available.
- Measure reading progress against article content instead of the whole page.
- Lead the qualification guide with current support information and clarify
the maintainer architecture path.

### Fixed

- Reject broken same-page heading fragments during `check` and `build`.
- Reject links to missing or unpublished Markdown instead of copying a private
Markdown file into the output as an asset.

## 1.2.1

A reading-layout patch. No configuration, route, theme-specific CSS or public
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🌱 DocSprout

[![CI](https://github.com/ikelaiah/docsprout/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ikelaiah/docsprout/actions/workflows/ci.yml?query=branch%3Amain) [![Docs](https://img.shields.io/website?url=https%3A%2F%2Fikelaiah.github.io%2Fdocsprout%2F1.2.1%2F&label=docs)](https://ikelaiah.github.io/docsprout/1.2.1/) [![Latest release](https://img.shields.io/github/v/release/ikelaiah/docsprout?display_name=tag&sort=semver)](https://github.com/ikelaiah/docsprout/releases/latest) [![Python 3.10–3.14](https://img.shields.io/badge/python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://github.com/ikelaiah/docsprout/blob/main/docs/qualification.md#supported-python-versions) [![License: MIT](https://img.shields.io/github/license/ikelaiah/docsprout)](https://github.com/ikelaiah/docsprout/blob/main/LICENSE)
[![CI](https://github.com/ikelaiah/docsprout/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ikelaiah/docsprout/actions/workflows/ci.yml?query=branch%3Amain) [![Docs](https://img.shields.io/website?url=https%3A%2F%2Fikelaiah.github.io%2Fdocsprout%2F1.2.2%2F&label=docs)](https://ikelaiah.github.io/docsprout/1.2.2/) [![Latest release](https://img.shields.io/github/v/release/ikelaiah/docsprout?display_name=tag&sort=semver)](https://github.com/ikelaiah/docsprout/releases/latest) [![Python 3.10–3.14](https://img.shields.io/badge/python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://github.com/ikelaiah/docsprout/blob/main/docs/qualification.md#supported-python-versions) [![License: MIT](https://img.shields.io/github/license/ikelaiah/docsprout)](https://github.com/ikelaiah/docsprout/blob/main/LICENSE)

![DocSprout banner — Build documentation people can use.](docs/assets/docsprout-banner.svg)

Expand All @@ -23,7 +23,7 @@ Open a terminal in your project's top-level folder—the folder that normally
contains files such as `README.md`, `src/` or `.git/`—and run:

```bash
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.1.zip"
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.2.zip"
docsprout init
docsprout serve
```
Expand Down
40 changes: 32 additions & 8 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
# Architecture

DocSprout has six small layers: configuration discovery, validation, safe
Markdown rendering, static-site generation, brand and contrast derivation
(`palette.py` proves link and focus colours against every reading surface), and
immutable-version orchestration.
The package carries the CSS and browser code so consuming projects do not copy
the implementation. `build` renders a working tree for preview; `build-all`
archives every declared Git tag or full SHA into an isolated temporary tree.
DocSprout is a command-line application that turns project-owned Markdown and
navigation into static files. A consuming project owns its content and visual
identity; the installed package supplies the renderer, CSS and browser code.

## Follow one build

1. `cli.py` chooses a command and project root. `check` calls the same builder
as `build`, but writes into a temporary directory.
2. `config.py` loads `docsprout.json` and the navigation layout, validates
paths and fields, and returns a `SiteConfig`. `layout_markdown.py` parses
`layout.md` into the same navigation shape as `layout.json`.
3. `palette.py` derives colours and checks contrast against the reading
surfaces. `build.py` assigns routes and rejects route collisions.
4. `markdown.py` renders the supported Markdown subset and assigns heading
IDs. `build.py` resolves links against published pages, validates heading
fragments and copies linked local assets.
5. `build.py` writes each page in the shared HTML shell, then writes the search
index and release metadata. `assets.py` supplies the site CSS and JavaScript;
the package also carries local KaTeX assets.

`serve` rebuilds that same site when source files change. `audit.py` adds
publication diagnostics, including warnings about image descriptions and
heading structure. `versions.py` checks immutable release references and
builds historical releases from isolated Git archives. `safety.py` limits
replacement of existing output to DocSprout-owned directories.

For a first code change, start with the command in `cli.py`, follow its call
into the owning module above, and read the corresponding tests listed in the
repository's `CONTRIBUTING.md` code map. Run the focused test while editing,
then the full suite. Changes to routes, configuration, generated formats or
command behavior also need a review of the contract below.

## Compatibility surface

Expand Down Expand Up @@ -53,6 +77,6 @@ needs no custom CSS; the custom stylesheet mechanism is a deliberately bounded
escape hatch whose inclusion mechanics DocSprout owns and whose accessibility
the author owns.

Downstream projects should pin released tags such as `v1.2.1`, never the main
Downstream projects should pin released tags such as `v1.2.2`, never the main
branch. The stable boundary and deprecation policy are in [Machine-readable
contracts](machine-contracts.md).
4 changes: 2 additions & 2 deletions docs/beginners-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ that normally contains `README.md` or `src/`.
Open a terminal in your project folder and run:

```bash
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.1.zip"
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.2.zip"
```

Then check that the command is available:
Expand Down Expand Up @@ -254,7 +254,7 @@ appear in the navigation.
in [How DocSprout renders Markdown](markdown-showcase.md).
- Learn the three configuration files in [Configuration](configuration.md).
- Copy a small working project from the
[minimal example](https://github.com/ikelaiah/docsprout/tree/v1.2.1/examples/minimal).
[minimal example](https://github.com/ikelaiah/docsprout/tree/v1.2.2/examples/minimal).
- When you truly want a public site, choose the simpler or historical path in
[GitHub Pages](github-pages.md).
- Look up unfamiliar words in the [glossary](glossary.md).
2 changes: 1 addition & 1 deletion docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ asset is local, and `index.html` opens directly in a browser.
## Ship a ZIP

```bash
docsprout build --release 1.2.1 --offline-archive dist/docsprout-docs-1.2.1.zip
docsprout build --release 1.2.2 --offline-archive dist/docsprout-docs-1.2.2.zip
```

The release label used for an offline archive must start with a letter or
Expand Down
6 changes: 3 additions & 3 deletions docs/ci-cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
with:
python-version: "3.12"
- name: Install DocSprout
run: python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.1.zip"
run: python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.2.zip"
- name: Validate the site
run: docsprout check
- name: Audit publications
Expand All @@ -52,7 +52,7 @@ jobs:
path: audit.json
```

Pin a released tag (`v1.2.1` above), never a branch. `--format json` writes the
Pin a released tag (`v1.2.2` above), never a branch. `--format json` writes the
machine-readable report; the artifact keeps it after the job, including when
the audit fails.

Expand All @@ -76,7 +76,7 @@ is yours. The same checks in GitLab CI:
docs-checks:
image: python:3.12
script:
- python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.1.zip"
- python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.2.zip"
- docsprout check
- docsprout audit --strict
```
Expand Down
4 changes: 2 additions & 2 deletions docs/customisation.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ identity asset:

Fields that are not relevant here, such as `banner` and `homepage`, are
omitted for brevity. You can inspect the complete maintained
[`docs/docsprout.json`](https://github.com/ikelaiah/docsprout/blob/v1.2.1/docs/docsprout.json)
and its [local SVG asset](https://github.com/ikelaiah/docsprout/blob/v1.2.1/docs/assets/docsprout-mark.svg).
[`docs/docsprout.json`](https://github.com/ikelaiah/docsprout/blob/v1.2.2/docs/docsprout.json)
and its [local SVG asset](https://github.com/ikelaiah/docsprout/blob/v1.2.2/docs/assets/docsprout-mark.svg).
On generated DocSprout pages, purple is the accent and highlight colour; the
potted sprout mark (green leaves, brown soil and a beige pot) appears immediately
before the project name in the top header;
Expand Down
2 changes: 1 addition & 1 deletion docs/existing-repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Run both commands from the repository's top-level folder—the one that contains
`README.md` or `.git/`:

```bash
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.1.zip"
python -m pip install "https://github.com/ikelaiah/docsprout/archive/refs/tags/v1.2.2.zip"
docsprout init
```

Expand Down
10 changes: 5 additions & 5 deletions docs/github-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ from feature branches do not deploy Pages.
workflow are current, it makes no repository changes.

The generated workflow carries a DocSprout ownership marker and pins the reusable
workflow to the installed release, such as `@v1.2.1`. It never follows
workflow to the installed release, such as `@v1.2.2`. It never follows
`@main`. If a recognised managed workflow is older, ordinary setup reports the
version and leaves it unchanged. Update only that workflow deliberately:

Expand Down Expand Up @@ -101,13 +101,13 @@ jobs:
contents: read
pages: write
id-token: write
uses: ikelaiah/docsprout/.github/workflows/publish-docs.yml@v1.2.1
uses: ikelaiah/docsprout/.github/workflows/publish-docs.yml@v1.2.2
with:
versioned: false
release: latest
```

The maintained [single-version example](https://github.com/ikelaiah/docsprout/tree/v1.2.1/examples/single-version)
The maintained [single-version example](https://github.com/ikelaiah/docsprout/tree/v1.2.2/examples/single-version)
uses this form.

## Historical site for versioned projects
Expand All @@ -129,7 +129,7 @@ jobs:
contents: read
pages: write
id-token: write
uses: ikelaiah/docsprout/.github/workflows/publish-docs.yml@v1.2.1
uses: ikelaiah/docsprout/.github/workflows/publish-docs.yml@v1.2.2
```

Check a historical release locally after creating its tag and before pushing:
Expand All @@ -140,7 +140,7 @@ docsprout check-release
docsprout build-all --output build/docs-site
```

The maintained [historical example](https://github.com/ikelaiah/docsprout/tree/v1.2.1/examples/historical)
The maintained [historical example](https://github.com/ikelaiah/docsprout/tree/v1.2.2/examples/historical)
uses this form. Follow the [pre-publish checklist](pre-publish-checklist.md)
for the exact release order.

Expand Down
2 changes: 1 addition & 1 deletion docs/historical-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ the release check and full build, then push the tag. Use the exact commands in t
[pre-publish checklist](pre-publish-checklist.md).

The maintained
[historical example](https://github.com/ikelaiah/docsprout/tree/v1.2.1/examples/historical)
[historical example](https://github.com/ikelaiah/docsprout/tree/v1.2.2/examples/historical)
demonstrates two small releases. Its automated test builds the same Git history
twice and compares every generated byte.
2 changes: 1 addition & 1 deletion docs/homepage-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ which is a top-level setting, are `homepage` values.
## See it in DocSprout

DocSprout uses the same configuration on this site. Its
[`docs/docsprout.json`](https://github.com/ikelaiah/docsprout/blob/v1.2.1/docs/docsprout.json)
[`docs/docsprout.json`](https://github.com/ikelaiah/docsprout/blob/v1.2.2/docs/docsprout.json)
uses these exact values for its home-page banner and capability cards:

```json
Expand Down
19 changes: 14 additions & 5 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The 1.x upgrades are deliberately boring: v1.0.0 froze the qualified v0.18.1
surface, and every later 1.x release adds no configuration schema change. Pin
the released package and workflow, then run the same checks you already use.
Current guidance targets `v1.2.1`; each section below remains authoritative for
Current guidance targets `v1.2.2`; each section below remains authoritative for
its own step.

## DocKit to DocSprout (1.x rebrand)
Expand Down Expand Up @@ -64,7 +64,7 @@ each published release manifest on immutable tags while upgrading.
## Upgrade directly from any supported 0.x release

All released 0.x configurations use schema version 1. Upgrade the pinned package
and workflow to the latest 1.x release (`v1.2.1`), then use this table before
and workflow to the latest 1.x release (`v1.2.2`), then use this table before
running `doctor`, `check`, and the appropriate publish build.

| Starting release | Required compatibility work |
Expand Down Expand Up @@ -96,6 +96,15 @@ segments and option-like refs, requires the current source to match `HEAD`, and
requires documentation changes to be committed. These checks make existing
valid manifests more dependable; they do not change generated routes.

## v1.2.1 to v1.2.2

No configuration or content migration is required. Update package and workflow
pins to `v1.2.2`, then rebuild. Reading pages gain a keyboard skip link, a
smaller phone header after scrolling, and article-based reading progress.
`check` and `build` now report missing same-page heading fragments and links to
unpublished Markdown. Fix the link or publish the target page in the navigation
layout before upgrading.

## v1.2.0 to v1.2.1

No configuration or content migration is required. Update the package and
Expand Down Expand Up @@ -275,7 +284,7 @@ the contract qualified by v0.18.1:

1. Pin the package archive or source installation to `v1.0.0` and pin the
reusable Pages workflow to `@v1.0.0`; never use `main`. For a new upgrade
today, pin the latest 1.x release (`v1.2.1`) instead.
today, pin the latest 1.x release (`v1.2.2`) instead.
2. Keep `"schema_version": 1` in `docsprout.json`, `layout.json` and
`versions.json`. There is no schema rewrite or generated-route migration.
3. If custom CSS still uses pre-v0.18 generic names such as `--bg`, `--text`
Expand Down Expand Up @@ -407,9 +416,9 @@ safe, readable plain code.

Version 1.0 is the formal commitment point for the contracts that v0.18.1
qualified, and later 1.x releases keep that contract. There is no schema change.
Before adopting the latest 1.x release (`v1.2.1`):
Before adopting the latest 1.x release (`v1.2.2`):

1. Upgrade the pinned package and Pages workflow to `v1.2.1` following this
1. Upgrade the pinned package and Pages workflow to `v1.2.2` following this
guide's patterns (config-compatible, then rebuild).
2. Remove references to any pre-v0.18 generic theme token names
(`--bg`, `--text`, `--interactive`, …) in custom CSS; the `--dk-*` names
Expand Down
16 changes: 8 additions & 8 deletions docs/pre-publish-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ This path updates the public site from a branch such as `main`.
## Historical site

This path publishes an immutable site for every listed release. In the example
below, replace `1.2.1` with your version.
below, replace `1.2.2` with your version.

1. Add release `1.2.1` and source ref `v1.2.1` to `docs/versions.json`. Set
`current` to `1.2.1`.
1. Add release `1.2.2` and source ref `v1.2.2` to `docs/versions.json`. Set
`current` to `1.2.2`.
2. Run `docsprout check`.
3. Commit all release files, including package metadata, documentation,
examples and workflows, on a branch named `release/vX.Y.Z`:

```bash
git add pyproject.toml src/docsprout/__init__.py README.md CHANGELOG.md docs .github examples tests
git diff --cached --check
git commit -m "Prepare v1.2.1 documentation"
git commit -m "Prepare v1.2.2 documentation"
```

4. Push the qualified branch and open a PR against `main`. Wait for every
Expand All @@ -83,7 +83,7 @@ below, replace `1.2.1` with your version.
5. Check out the merged `main` commit and create the tag on that exact commit:

```bash
git tag -a v1.2.1 -m "v1.2.1"
git tag -a v1.2.2 -m "v1.2.2"
```

6. Run the release checks and historical build:
Expand All @@ -100,7 +100,7 @@ below, replace `1.2.1` with your version.
8. Push the annotated tag (the merge commit is already on `main`):

```bash
git push origin v1.2.1
git push origin v1.2.2
```

9. Create the GitHub Release from the tag. Confirm both CI and the Documentation
Expand All @@ -111,9 +111,9 @@ below, replace `1.2.1` with your version.
## If you find a mistake

If the tag exists only on your computer, correct and commit the files, delete
the local tag with `git tag -d v1.2.1`, then create it again on the corrected
the local tag with `git tag -d v1.2.2`, then create it again on the corrected
commit.

If the tag has been pushed, do not move or replace it. Publish the correction
as a new patch release, such as `v1.2.2`, so links and historical documentation
as a new patch release, such as `v1.2.3`, so links and historical documentation
remain trustworthy.
Loading
Loading