Skip to content
Open
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
20 changes: 20 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,26 @@ Hatch can also be used to serve continuously updating version of the documentati
hatch --env docs run serve
```

#### Sub-package documentation sites

Each sub-package under `packages/` ships its own Material for MkDocs site, built from within the package directory:

```bash
cd packages/zarr-metadata
uv run --group docs mkdocs build --strict
```

Configuration shared by all package sites (theme, plugins, markdown extensions) lives in `packages/mkdocs-base.yml`; each package's `mkdocs.yml` pulls it in via `INHERIT` and defines only the site identity (name, description, repo and site URLs) and nav. The header source widget's version fact is overridden by `packages/source-version.js`, symlinked into each package's `docs/_static/`, which replaces the monorepo's latest release with the latest tag matching the package's `zarr_<name>-v` prefix (both derived from `repo_url` at runtime, so the file needs no per-package edits).

To add a site for a new sub-package, copy `mkdocs.yml`, the `docs/` folder, `.readthedocs.yaml`, and the `docs` dependency group in `pyproject.toml` from an existing package, then adjust the site name, description, URLs, and nav.

Each site is hosted as its own Read the Docs project. To set one up for a new sub-package:

1. Create a new project on [readthedocs.org](https://app.readthedocs.org) importing the `zarr-python` repository, named after the package (e.g. `zarr-metadata`).
2. In the project's admin settings, set the configuration file path to `packages/<name>/.readthedocs.yaml`. That file also cancels pull request builds that don't touch the package.
3. Add an automation rule matching the package's release tags (custom match `^zarr_<name>-v`, note the underscore) with the action "Activate version". Automation rules only apply to versions detected after the rule is created, so activate any earlier release tags manually from the versions list.
4. When activating a version, edit its slug to the bare version number (`0.4.0`, not `v0.4.0`). RTD keeps a version record for every tag in the monorepo, including inactive ones not shown in the dashboard's versions list, and all of zarr-python's own release tags are `v`-prefixed — so a `v`-prefixed slug collides with zarr-python's release history ("A version with that slug already exists"), while bare version numbers cannot collide.
Comment thread
maxrjones marked this conversation as resolved.

#### Adding executable code blocks in the documentation

Zarr uses [Markdown Exec](https://pawamoy.github.io/markdown-exec/usage/) to execute code blocks in Markdown files. Add `exec="true"` to a code block header for it to be executed when the docs are built. For example:
Expand Down
94 changes: 94 additions & 0 deletions packages/mkdocs-base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Shared Material for MkDocs configuration for the sub-package docs sites.
# Each package's mkdocs.yml pulls this in via INHERIT and defines only its
# identity (site_name, repo_*, site_description, site_url) and nav.
# The inventories list below is the superset used by all packages; an
# inventory a package never references is harmless.
site_author: Davis Bennett
use_directory_urls: true

watch:
- src

theme:
language: en
name: material
logo: _static/logo_bw.png
favicon: _static/favicon-96x96.png

palette:
# Light mode
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode

# Dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to light mode

font:
text: Roboto
code: Roboto Mono

features:
- content.code.annotate
- content.code.copy
- navigation.indexes
- navigation.instant
- navigation.tracking
- search.suggest
- search.share

plugins:
- autorefs
- search
- mkdocstrings:
enable_inventory: true
handlers:
python:
paths: [src]
options:
allow_inspection: true
docstring_section_style: list
docstring_style: numpy
inherited_members: true
line_length: 60
separate_signature: true
show_root_heading: true
show_signature_annotations: true
show_source: true
show_symbol_type_toc: true
signature_crossrefs: true
show_if_no_docstring: true
extensions:
- griffe_inherited_docstrings

inventories:
- https://docs.python.org/3/objects.inv
- https://numpy.org/doc/stable/objects.inv
- https://zarr.readthedocs.io/en/stable/objects.inv

# Override the header source widget's version fact (the monorepo's latest
# release) with the latest tag matching the package's prefix.
extra_javascript:
- _static/source-version.js

markdown_extensions:
- admonition
- attr_list
- def_list
- footnotes
- md_in_html
- pymdownx.details
- pymdownx.superfences
- toc:
permalink: true
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
83 changes: 83 additions & 0 deletions packages/source-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* Material's header source widget shows the monorepo's latest release
(e.g. v3.3.0). Replace it with the latest tag for this package, and
patch the theme's sessionStorage cache so instant navigation keeps it.

The GitHub repo and the package's tag prefix (e.g. zarr_metadata-) are
derived from repo_url, whose final path segment is the package directory,
so this file is identical across all sub-package docs sites. */
(() => {
const source = document.querySelector('[data-md-component="source"]')
if (!source || !source.href)
return
const segments = new URL(source.href).pathname.split("/").filter(Boolean)
const REPO = segments.slice(0, 2).join("/")
const PREFIX = segments[segments.length - 1].replace(/-/g, "_") + "-"

const parse = version => version
.replace(/^v/, "")
.split(/[.+-]/)
.map(part => parseInt(part, 10) || 0)

const newestFirst = (a, b) => {
const va = parse(a), vb = parse(b)
for (let i = 0; i < Math.max(va.length, vb.length); i++)
if ((vb[i] || 0) !== (va[i] || 0))
return (vb[i] || 0) - (va[i] || 0)
return 0
}

/* Cache the tag for the tab's lifetime (like the theme's own __source
cache) so navigation doesn't burn GitHub's unauthenticated API rate
limit. Keyed by prefix in case sub-package sites share an origin. */
const CACHE_KEY = `__package_tag/${PREFIX}`

async function latestPackageTag() {
const cached = sessionStorage.getItem(CACHE_KEY)
if (cached)
return cached
const response = await fetch(
Comment thread
maxrjones marked this conversation as resolved.
`https://api.github.com/repos/${REPO}/tags?per_page=100`
)
if (!response.ok)
return undefined
const tags = await response.json()
const versions = tags
.map(tag => tag.name)
.filter(name => name.startsWith(PREFIX))
.map(name => name.slice(PREFIX.length))
.sort(newestFirst)
if (versions[0])
sessionStorage.setItem(CACHE_KEY, versions[0])
return versions[0]
}

function patchDom(version) {
for (const el of document.querySelectorAll(".md-source__fact--version"))
el.textContent = version
}

function patchCache(version) {
const facts = __md_get("__source", sessionStorage)
Comment thread
maxrjones marked this conversation as resolved.
if (!facts)
return false
facts.version = version
__md_set("__source", facts, sessionStorage)
return true
}

latestPackageTag().then(version => {
if (!version)
return
patchDom(version)
if (patchCache(version))
return
/* The theme's own API request hasn't resolved yet — patch both the
cache and the DOM once it renders the facts list. */
new MutationObserver((_, observer) => {
if (patchCache(version)) {
patchDom(version)
observer.disconnect()
}
}).observe(source, { childList: true, subtree: true })
})
})()
1 change: 1 addition & 0 deletions packages/zarr-indexing/docs/_static/source-version.js
87 changes: 2 additions & 85 deletions packages/zarr-indexing/mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
INHERIT: ../mkdocs-base.yml

site_name: zarr-indexing
# The package lives in the zarr-python monorepo; point the header source
# widget at the package directory rather than the repository root.
Expand All @@ -6,10 +8,7 @@ repo_url: https://github.com/zarr-developers/zarr-python/tree/main/packages/zarr
# Absolute because mkdocs would otherwise append this to repo_url's subpath.
edit_uri: https://github.com/zarr-developers/zarr-python/edit/main/packages/zarr-indexing/docs/
site_description: Composable, lazy coordinate transforms for Zarr array indexing.
site_author: Davis Bennett
site_url: !ENV [READTHEDOCS_CANONICAL_URL, 'https://zarr-indexing.readthedocs.io/']
docs_dir: docs
use_directory_urls: true

nav:
- index.md
Expand All @@ -26,85 +25,3 @@ nav:
- '<code class="doc-symbol doc-symbol-toc doc-symbol-module"></code> <code>zarr_indexing.messages</code>': api/messages.md
- '<code class="doc-symbol doc-symbol-toc doc-symbol-module"></code> <code>zarr_indexing.errors</code>': api/errors.md
- Changelog: https://github.com/zarr-developers/zarr-python/blob/main/packages/zarr-indexing/CHANGELOG.md

watch:
- src

theme:
language: en
name: material
logo: _static/logo_bw.png
favicon: _static/favicon-96x96.png

palette:
# Light mode
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode

# Dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to light mode

font:
text: Roboto
code: Roboto Mono

features:
- content.code.annotate
- content.code.copy
- navigation.indexes
- navigation.instant
- navigation.tracking
- search.suggest
- search.share

plugins:
- autorefs
- search
- mkdocstrings:
enable_inventory: true
handlers:
python:
paths: [src]
options:
allow_inspection: true
docstring_section_style: list
docstring_style: numpy
inherited_members: true
line_length: 60
separate_signature: true
show_root_heading: true
show_signature_annotations: true
show_source: true
show_symbol_type_toc: true
signature_crossrefs: true
show_if_no_docstring: true
extensions:
- griffe_inherited_docstrings

inventories:
- https://docs.python.org/3/objects.inv
- https://numpy.org/doc/stable/objects.inv
- https://zarr.readthedocs.io/en/stable/objects.inv

markdown_extensions:
- admonition
- attr_list
- def_list
- footnotes
- md_in_html
- pymdownx.details
- pymdownx.superfences
- toc:
permalink: true
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
Loading
Loading