From 9b1b638e8a57e975511f93f041789576af5eefe6 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 11:30:01 +0100 Subject: [PATCH 1/8] Add MkDocs skeleton and update related files --- TODO.md | 2 +- docs/guides/using-the-template.md | 5 +- src/scene_repo_template/cli.py | 14 ++++ .../skeleton/mkdocs/docs/images/favicon.png | Bin 0 -> 7277 bytes .../mkdocs/docs/images/scene-logo.png | Bin 0 -> 62237 bytes .../skeleton/mkdocs/docs/index.md.tmpl | 5 ++ .../mkdocs/docs/stylesheets/scene.css | 32 +++++++ .../mkdocs/dot-github/workflows/docs.yml | 46 +++++++++++ .../skeleton/mkdocs/mkdocs.yml.tmpl | 78 ++++++++++++++++++ tests/test_cli.py | 77 +++++++++++------ 10 files changed, 233 insertions(+), 26 deletions(-) create mode 100644 src/scene_repo_template/skeleton/mkdocs/docs/images/favicon.png create mode 100644 src/scene_repo_template/skeleton/mkdocs/docs/images/scene-logo.png create mode 100644 src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl create mode 100644 src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css create mode 100644 src/scene_repo_template/skeleton/mkdocs/dot-github/workflows/docs.yml create mode 100644 src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl diff --git a/TODO.md b/TODO.md index b3eca77..d4d7919 100644 --- a/TODO.md +++ b/TODO.md @@ -4,9 +4,9 @@ Open work and open decisions for this repository. ## Work -- **MkDocs backend for the generator:** `src/scene_repo_template/skeleton/mkdocs/`, from the prototype on `cy/scene-docs-mkdocs` (worktree `../CodeAndDocsTemplate-mkdocs`, `api-docs/` uncommitted). It writes `docs/`, with its own docs extra (`docs_dependencies`), docs workflow and SCENE stylesheet from `scene-palette.json`; add it to `BACKENDS` in `cli.py` and to the end-to-end docs test. The logo and favicon are in `skeleton/jupyter-book/docs/images/` because `footer.md` links them relatively; move them to `common/` only if both backends can reach them there. - **CI on this repository:** its workflows skip private repositories, like those of generated projects. If the new repository is private, delete the `if:` lines in `.github/workflows/` here; the skeleton's keep them. - **Review and test pass:** `pytest` on Windows and Linux with `SCENE_TEMPLATE_E2E=1`, `pre-commit run --all-files --hook-stage manual`, a strict book build with link checking, `actionlint` and `zizmor` on `.github/` and the skeleton's `dot-github/`, the interactive prompts by hand, and every page checked in light and dark mode. +- **Landing page typo:** "for more other repositories" in `docs/index.md`. ## Decisions diff --git a/docs/guides/using-the-template.md b/docs/guides/using-the-template.md index a9242e2..0eefdab 100644 --- a/docs/guides/using-the-template.md +++ b/docs/guides/using-the-template.md @@ -48,6 +48,7 @@ You will need to enter: - A one-line description - The author - The GitHub URL +- The documentation: Jupyter Book (guides and notebooks) or MkDocs (API reference from docstrings) This will show a summary, and wait for confirmation. @@ -60,7 +61,7 @@ The project then contains: - `pyproject.toml`, the package folder and a first test example in `tests/`; - `.pre-commit-config.yaml` and three GitHub Actions workflows: lint, tests and docs; -- `docs/`, a Jupyter Book with SCENE's logo, colours and footer; +- `docs/`, a Jupyter Book, or an MkDocs site with `mkdocs.yml; - `LICENSE` (Apache-2.0) and a short `README.md`. ## 2. Set up your environment @@ -144,5 +145,5 @@ Commit `uv.lock` with the change. - To publish the docs, enable GitHub Pages once: see [Documentation with Jupyter Book](jupyter-book.md#publish). ```{important} -No docs needed? Delete `docs/` and `.github/workflows/docs.yml`. +No docs needed? Delete `docs/`, `.github/workflows/docs.yml`, and `mkdocs.yml` if present. ``` diff --git a/src/scene_repo_template/cli.py b/src/scene_repo_template/cli.py index 176b283..9e3c3a9 100644 --- a/src/scene_repo_template/cli.py +++ b/src/scene_repo_template/cli.py @@ -27,6 +27,20 @@ "`.github/workflows/docs.yml` publishes it to GitHub Pages once Pages is enabled with GitHub Actions as its source." ), }, + "mkdocs": { + "label": "MkDocs: API reference from docstrings", + # MkDocs 2.0 drops the plugin system mkdocstrings relies on. + "docs_dependencies": ( + '"mkdocs>=1.6,<2", "mkdocs-api-autonav>=0.1", "mkdocs-autorefs>=1.2", "mkdocs-material>=9.5", ' + '"mkdocstrings[python]>=0.27"' + ), + "docs_readme": ( + "Built from `docs/` and `mkdocs.yml` with [MkDocs](https://www.mkdocs.org) and Material, " + "the API reference generated from docstrings: " + 'after `pip install -e ".[docs]"` (or `uv sync --extra docs`), `mkdocs serve` serves it locally. ' + "`.github/workflows/docs.yml` publishes it to GitHub Pages once Pages is enabled with GitHub Actions as its source." + ), + }, } TEMPLATE_SUFFIX = ".tmpl" diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/images/favicon.png b/src/scene_repo_template/skeleton/mkdocs/docs/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..a0de517d8a6eab7eaf289701634201be41c70697 GIT binary patch literal 7277 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 Hu0mjfg)~%b literal 0 HcmV?d00001 diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/images/scene-logo.png b/src/scene_repo_template/skeleton/mkdocs/docs/images/scene-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..de8ba5d1321f233c6be7d83f2380517029189485 GIT binary patch literal 62237 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 @SsluUhwF-QLY_TD^9s_VKI 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 LNkvXXu0mjf9D6#V literal 0 HcmV?d00001 diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl b/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl new file mode 100644 index 0000000..3dee4e6 --- /dev/null +++ b/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl @@ -0,0 +1,5 @@ +# $title + +$description + +The API reference is generated from the docstrings of `$package`. Add pages next to this one and list them under `nav:` in `mkdocs.yml`. diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css b/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css new file mode 100644 index 0000000..7cdb870 --- /dev/null +++ b/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css @@ -0,0 +1,32 @@ +/* SCENE theme for MkDocs Material, in the colours of the SCENE logo. */ + +:root { + --md-primary-fg-color: #125069; /* petrol blue */ + --md-primary-fg-color--light: #12638e; /* ocean blue */ + --md-primary-fg-color--dark: #0d3a4c; + --md-accent-fg-color: #41cfdb; /* cyan */ + --md-typeset-a-color: #12638e; +} + +[data-md-color-scheme="slate"] { + --md-primary-fg-color: #1f2d36; /* ink */ + --md-typeset-a-color: #41cfdb; +} + +/* Brand stripe above the header, in the logo's colours. */ +.md-header::before { + content: ""; + display: block; + height: 4px; + background: linear-gradient(90deg, #41cfdb, #31c5a1, #80c848, #edb71f, #e98724, #d76c26); +} + +.md-typeset h2 { + padding-bottom: 0.25em; + border-bottom: 2px solid var(--md-accent-fg-color); +} + +.md-copyright { + width: 100%; + text-align: center; +} diff --git a/src/scene_repo_template/skeleton/mkdocs/dot-github/workflows/docs.yml b/src/scene_repo_template/skeleton/mkdocs/dot-github/workflows/docs.yml new file mode 100644 index 0000000..9a2fb4c --- /dev/null +++ b/src/scene_repo_template/skeleton/mkdocs/dot-github/workflows/docs.yml @@ -0,0 +1,46 @@ +name: Docs + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + build: + # CI runs on public repositories only: private ones draw on the org's Actions quota, which can be billed. Delete this line to opt in. + if: ${{ !github.event.repository.private }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2 + with: + python-version: "3.13" + - run: uv sync --extra docs + - run: uv run mkdocs build --strict + - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 + with: + path: site + + deploy: + # Pull requests only check that the site builds. + if: ${{ github.event_name == 'push' && !github.event.repository.private }} + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + concurrency: + group: pages + cancel-in-progress: false + steps: + - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 + - id: deployment + uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1 diff --git a/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl new file mode 100644 index 0000000..a0818f6 --- /dev/null +++ b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl @@ -0,0 +1,78 @@ +# MkDocs configuration: https://www.mkdocs.org, theme https://squidfunk.github.io/mkdocs-material/ +# Preview locally with `mkdocs serve`; build with `mkdocs build --strict`. Pages are in docs/. +site_name: "$title" +site_description: "$description" +repo_url: $github_url + +theme: + name: material + logo: images/scene-logo.png + favicon: images/favicon.png + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: custom + accent: custom + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: custom + accent: custom + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - content.code.copy + - navigation.indexes + - navigation.path + - navigation.sections + - navigation.top + - search.highlight + - search.suggest + - toc.follow + +extra_css: + - stylesheets/scene.css + +plugins: + - search + - autorefs + # One page per module of the package, under "API reference". + - api-autonav: + modules: ["$package"] + nav_section_title: "API reference" + exclude_private: true + - mkdocstrings: + default_handler: python + handlers: + python: + options: + show_root_heading: true + show_symbol_type_heading: true + separate_signature: true + show_signature_annotations: true + docstring_style: google + line_length: 120 + inventories: + - url: https://docs.python.org/3/objects.inv + domains: [py, std] + +markdown_extensions: + - attr_list + - admonition + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.superfences + +extra: + generator: false + +copyright: "Simons Collaboration on Ecological NEuroscience · Simons Foundation" + +nav: + - Home: index.md + - API reference diff --git a/tests/test_cli.py b/tests/test_cli.py index 7b2b874..6e5d511 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -37,27 +37,50 @@ def refused(tmp_path, *options, folder="my-project"): return exit_info.value.code == 2 -def test_a_project_gets_the_common_files_and_its_docs_backend(tmp_path): - expected = { - ".github/workflows/docs.yml", - ".github/workflows/lint.yml", - ".github/workflows/tests.yml", - ".gitignore", - ".pre-commit-config.yaml", - "LICENSE", - "README.md", - "docs/_static/footer.md", - "docs/_static/scene.css", - "docs/images/favicon.png", - "docs/images/scene-logo.png", - "docs/index.md", - "docs/myst.yml", - "my_project/__init__.py", - "my_project/version.py", - "pyproject.toml", - "tests/test_version.py", - } - assert expected <= files_of(generate(tmp_path)) +COMMON_FILES = { + ".github/workflows/docs.yml", + ".github/workflows/lint.yml", + ".github/workflows/tests.yml", + ".gitignore", + ".pre-commit-config.yaml", + "LICENSE", + "README.md", + "docs/images/favicon.png", + "docs/images/scene-logo.png", + "docs/index.md", + "my_project/__init__.py", + "my_project/version.py", + "pyproject.toml", + "tests/test_version.py", +} +BACKEND_FILES = { + "jupyter-book": {"docs/myst.yml", "docs/_static/footer.md", "docs/_static/scene.css"}, + "mkdocs": {"mkdocs.yml", "docs/stylesheets/scene.css"}, +} + + +def test_every_backend_is_tested(): + assert set(BACKEND_FILES) == set(cli.BACKENDS) + + +@pytest.mark.parametrize("backend", BACKEND_FILES) +def test_a_project_gets_the_common_files_and_only_its_own_docs_backend(tmp_path, backend): + project = files_of(generate(tmp_path, f"--docs={backend}")) + assert COMMON_FILES | BACKEND_FILES[backend] <= project + other_backends = set().union(*(files for name, files in BACKEND_FILES.items() if name != backend)) + assert project & other_backends == set() + + +def test_the_backends_ship_the_same_logo_and_favicon(): + for image in ("scene-logo.png", "favicon.png"): + copies = {(cli.SKELETON / backend / "docs" / "images" / image).read_bytes() for backend in cli.BACKENDS} + assert len(copies) == 1, image + + +def test_the_docs_extra_follows_the_backend(tmp_path): + pyproject = (generate(tmp_path, "--docs=mkdocs") / "pyproject.toml").read_text(encoding="utf-8") + assert '"mkdocstrings[python]>=0.27"' in pyproject + assert "jupyter-book" not in pyproject def test_no_skeleton_naming_is_left_in_a_project(tmp_path): @@ -303,7 +326,15 @@ def test_a_generated_project_installs_lints_and_passes_its_tests(tmp_path): @E2E @pytest.mark.skipif(shutil.which("node") is None, reason="Jupyter Book needs Node.js") -def test_a_generated_project_builds_its_docs(tmp_path): - dest = generate(tmp_path) +def test_a_generated_jupyter_book_builds(tmp_path): + dest = generate(tmp_path, "--docs=jupyter-book") run(dest, "uv", "sync", "--extra", "docs") run(dest / "docs", "uv", "run", "jupyter", "book", "build", "--html", "--strict") + + +@E2E +def test_a_generated_mkdocs_site_builds_with_an_api_page_per_module(tmp_path): + dest = generate(tmp_path, "--docs=mkdocs") + run(dest, "uv", "sync", "--extra", "docs") + run(dest, "uv", "run", "mkdocs", "build", "--strict") + assert (dest / "site" / "reference" / "my_project" / "version" / "index.html").is_file() From 3cf6d084ed1df27617da28ad52381920ec67d495 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 11:41:12 +0100 Subject: [PATCH 2/8] Enhance documentation and styling for MkDocs setup; fix typos and improve footer design --- TODO.md | 10 +++++---- docs/guides/using-the-template.md | 15 +++++++++++-- docs/index.md | 2 +- .../mkdocs/docs/stylesheets/scene.css | 22 +++++++++++++++++++ .../skeleton/mkdocs/mkdocs.yml.tmpl | 3 ++- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index d4d7919..e23db41 100644 --- a/TODO.md +++ b/TODO.md @@ -5,11 +5,13 @@ Open work and open decisions for this repository. ## Work - **CI on this repository:** its workflows skip private repositories, like those of generated projects. If the new repository is private, delete the `if:` lines in `.github/workflows/` here; the skeleton's keep them. -- **Review and test pass:** `pytest` on Windows and Linux with `SCENE_TEMPLATE_E2E=1`, `pre-commit run --all-files --hook-stage manual`, a strict book build with link checking, `actionlint` and `zizmor` on `.github/` and the skeleton's `dot-github/`, the interactive prompts by hand, and every page checked in light and dark mode. -- **Landing page typo:** "for more other repositories" in `docs/index.md`. +- **Review and test pass, what is left:** the interactive prompts by hand (the `questionary` path has no tests), and every page of the book and of a generated MkDocs site checked in light and dark mode. Done on 2026-10-28: `pytest` with `SCENE_TEMPLATE_E2E=1` on Windows and the Linux break cases in WSL, `pre-commit run --hook-stage manual`, a strict book build, `actionlint` and `zizmor` (no findings) on `.github/` and the skeleton's `dot-github/`. ## Decisions -- **New repository:** this work moves to a new SCENE repository; its name and visibility are open. After the move, update the repository links in `pyproject.toml` (`urls`), `docs/myst.yml` (`github`) and the `uvx --from` command in `docs/guides/using-the-template.md`. `uvx --from git+https://…` works without credentials only on a public repository. Do not mark it as a GitHub template repository: projects come from the generator. -- **Footer funder line:** "Simons Foundation" now; SCENE's own wording is "supported by a Simons Foundation International grant administered by the Simons Foundation". +- **New repository:** this work moves to a new SCENE repository; its name and visibility are open. After the move, update the repository links in `pyproject.toml` (`urls`), `docs/myst.yml` (`github`) and `docs/guides/using-the-template.md` (uv, pip and conda tabs). Installing from `git+https://…` works without credentials only on a public repository. Do not mark it as a GitHub template repository: projects come from the generator. +- **Broken links** (`jupyter book build --strict --check-links` fails on them): + - `guides/guidelines.md`: the DataCamp docstrings tutorial returns 403 to the link checker; `SCENE-Collaboration/SCENE-pipelines` returns 404 (private, or not created yet). + - `contributed-examples/MLAI/datajoint-architecture.md`: `https://docs.datajoint.org/` does not resolve and `github.com/datajoint/datajoint` returns 404. The page is kept as published, so a fix belongs in its "Changes" field. +- **Footer funder line:** "Simons Foundation" now, in the skeleton's `jupyter-book/docs/_static/footer.md` and in the `copyright` of `mkdocs/mkdocs.yml.tmpl`; SCENE's own wording is "supported by a Simons Foundation International grant administered by the Simons Foundation". - **MLAI example headers:** authors are given as initials (C. Benquet, T. Sainsbury); the permission line has no date. diff --git a/docs/guides/using-the-template.md b/docs/guides/using-the-template.md index 0eefdab..e05272f 100644 --- a/docs/guides/using-the-template.md +++ b/docs/guides/using-the-template.md @@ -61,9 +61,20 @@ The project then contains: - `pyproject.toml`, the package folder and a first test example in `tests/`; - `.pre-commit-config.yaml` and three GitHub Actions workflows: lint, tests and docs; -- `docs/`, a Jupyter Book, or an MkDocs site with `mkdocs.yml; +- `docs/`, a Jupyter Book, or an MkDocs site with `mkdocs.yml`; - `LICENSE` (Apache-2.0) and a short `README.md`. +### Which documentation backend? + +| | Jupyter Book | MkDocs | +| --- | --- | --- | +| Best for | Guides, tutorials and analyses shown as notebooks | A package with an API | +| Needed | Markdown and notebooks (`.ipynb`), shown with their saved outputs | Markdown for the documentation, plus docstrings on the code | +| Configuration | `docs/myst.yml` | `mkdocs.yml` | +| Preview | `jupyter book start` in `docs/` (needs [Node.js](https://nodejs.org)) | `mkdocs serve` | + +A project can only have one. To switch later, generate a project with the other backend and copy its `docs/`, `.github/workflows/docs.yml`, `mkdocs.yml` if any, and the `docs` extra of `pyproject.toml`. + ## 2. Set up your environment In the new project, with your preferred package manager: @@ -142,7 +153,7 @@ Commit `uv.lock` with the change. - Create the repository on GitHub at the URL you decided, then commit and push. - CI runs as soon as you push, if the repository is public and Actions is enabled (**Settings → Actions**): see *Continuous Integration* in the [Project standards](guidelines.md). -- To publish the docs, enable GitHub Pages once: see [Documentation with Jupyter Book](jupyter-book.md#publish). +- To publish the docs, enable GitHub Pages once: in **Settings → Pages**, set **Source** to **GitHub Actions**. The docs workflow then publishes on every push to `main`, for either backend. More on Jupyter Book: [Documentation with Jupyter Book](jupyter-book.md#publish). ```{important} No docs needed? Delete `docs/`, `.github/workflows/docs.yml`, and `mkdocs.yml` if present. diff --git a/docs/index.md b/docs/index.md index 96b91f1..476fabe 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ title: SCENE Code & Data Guidelines Shared practices for code and data in [SCENE](https://www.project-scene.org/), the Simons Collaboration on Ecological Neuroscience, and a template repository for quick project setup. -See the [SCENE-Collaboration](https://github.com/SCENE-Collaboration) GitHub organisation for more other repositories and resources. +See the [SCENE-Collaboration](https://github.com/SCENE-Collaboration) GitHub organisation for other repositories and resources. ::::{grid} 1 1 2 2 diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css b/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css index 7cdb870..33e1176 100644 --- a/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css +++ b/src/scene_repo_template/skeleton/mkdocs/docs/stylesheets/scene.css @@ -30,3 +30,25 @@ width: 100%; text-align: center; } + +/* Footer line: the name with its initials in stripe order (golden yellow skipped), as in the SCENE Jupyter Book, + the logo, then the funder. Markup: `copyright` in mkdocs.yml. */ +.scene-logo { + display: inline-block; + width: 1.4em; + height: 1.4em; + margin: 0 0.6em; + vertical-align: middle; + /* A background image, not an : its URL is relative to this file, so it holds on every page. */ + background: url("../images/scene-logo.png") center / contain no-repeat; +} + +.scene-footer strong { + color: #fff; +} + +.scene-footer em b:nth-of-type(1) { color: #41cfdb; } +.scene-footer em b:nth-of-type(2) { color: #31c5a1; } +.scene-footer em b:nth-of-type(3) { color: #80c848; } +.scene-footer em b:nth-of-type(4) { color: #e98724; } +.scene-footer em b:nth-of-type(5) { color: #d76c26; } diff --git a/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl index a0818f6..e69cb29 100644 --- a/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl +++ b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl @@ -71,7 +71,8 @@ markdown_extensions: extra: generator: false -copyright: "Simons Collaboration on Ecological NEuroscience · Simons Foundation" +# The SCENE name with coloured initials, styled in docs/stylesheets/scene.css. +copyright: "Simons Collaboration on Ecological NEuroscienceSimons Foundation" nav: - Home: index.md From 632053a92862dda3fd17359f18a18e0b1321815e Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 11:51:28 +0100 Subject: [PATCH 3/8] update TODO --- TODO.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/TODO.md b/TODO.md index e23db41..92d80f5 100644 --- a/TODO.md +++ b/TODO.md @@ -2,16 +2,6 @@ Open work and open decisions for this repository. -## Work - -- **CI on this repository:** its workflows skip private repositories, like those of generated projects. If the new repository is private, delete the `if:` lines in `.github/workflows/` here; the skeleton's keep them. -- **Review and test pass, what is left:** the interactive prompts by hand (the `questionary` path has no tests), and every page of the book and of a generated MkDocs site checked in light and dark mode. Done on 2026-10-28: `pytest` with `SCENE_TEMPLATE_E2E=1` on Windows and the Linux break cases in WSL, `pre-commit run --hook-stage manual`, a strict book build, `actionlint` and `zizmor` (no findings) on `.github/` and the skeleton's `dot-github/`. - ## Decisions - **New repository:** this work moves to a new SCENE repository; its name and visibility are open. After the move, update the repository links in `pyproject.toml` (`urls`), `docs/myst.yml` (`github`) and `docs/guides/using-the-template.md` (uv, pip and conda tabs). Installing from `git+https://…` works without credentials only on a public repository. Do not mark it as a GitHub template repository: projects come from the generator. -- **Broken links** (`jupyter book build --strict --check-links` fails on them): - - `guides/guidelines.md`: the DataCamp docstrings tutorial returns 403 to the link checker; `SCENE-Collaboration/SCENE-pipelines` returns 404 (private, or not created yet). - - `contributed-examples/MLAI/datajoint-architecture.md`: `https://docs.datajoint.org/` does not resolve and `github.com/datajoint/datajoint` returns 404. The page is kept as published, so a fix belongs in its "Changes" field. -- **Footer funder line:** "Simons Foundation" now, in the skeleton's `jupyter-book/docs/_static/footer.md` and in the `copyright` of `mkdocs/mkdocs.yml.tmpl`; SCENE's own wording is "supported by a Simons Foundation International grant administered by the Simons Foundation". -- **MLAI example headers:** authors are given as initials (C. Benquet, T. Sainsbury); the permission line has no date. From 0b704cc23f73a8e4fa8334b6573e58e587dfcc4b Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 12:07:19 +0100 Subject: [PATCH 4/8] Link Using this template to Project standards by its new title --- docs/guides/development-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/development-guide.md b/docs/guides/development-guide.md index 0727eda..1909efb 100644 --- a/docs/guides/development-guide.md +++ b/docs/guides/development-guide.md @@ -1,4 +1,4 @@ -# Development Guide +# Development guide Each project sets its own rules, such as who reviews what and how decisions are made. The guidelines below are a suggested common starting point. From 4e874e45cc85248478fc7f606071567564479688 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 12:09:36 +0100 Subject: [PATCH 5/8] Retitle the Working together page heading --- docs/guides/development-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/development-guide.md b/docs/guides/development-guide.md index 1909efb..473b3e3 100644 --- a/docs/guides/development-guide.md +++ b/docs/guides/development-guide.md @@ -1,4 +1,4 @@ -# Development guide +# Working together Each project sets its own rules, such as who reviews what and how decisions are made. The guidelines below are a suggested common starting point. From e42d937e0ca1432c4af0993abdc55e5a44154ec2 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Oct 2026 12:10:34 +0100 Subject: [PATCH 6/8] Retitle the Collaborating on code page heading --- docs/guides/development-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/development-guide.md b/docs/guides/development-guide.md index 473b3e3..ac57d4f 100644 --- a/docs/guides/development-guide.md +++ b/docs/guides/development-guide.md @@ -1,4 +1,4 @@ -# Working together +# Collaborating on code Each project sets its own rules, such as who reviews what and how decisions are made. The guidelines below are a suggested common starting point. From 681e31f00f1f85902a05da6f89860ac7fe3820c9 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Tue, 3 Nov 2026 16:47:23 +0100 Subject: [PATCH 7/8] On Python 3.10, mkdocstrings stops at 1.0.6, which breaks on pymdown-extensions 12.2+ (Highlight now requires `md`). --- src/scene_repo_template/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scene_repo_template/cli.py b/src/scene_repo_template/cli.py index 9e3c3a9..91d3cf6 100644 --- a/src/scene_repo_template/cli.py +++ b/src/scene_repo_template/cli.py @@ -32,7 +32,7 @@ # MkDocs 2.0 drops the plugin system mkdocstrings relies on. "docs_dependencies": ( '"mkdocs>=1.6,<2", "mkdocs-api-autonav>=0.1", "mkdocs-autorefs>=1.2", "mkdocs-material>=9.5", ' - '"mkdocstrings[python]>=0.27"' + '"mkdocstrings[python]>=0.27", "pymdown-extensions<12.2; python_version < \'3.11\'"' ), "docs_readme": ( "Built from `docs/` and `mkdocs.yml` with [MkDocs](https://www.mkdocs.org) and Material, " From dc241d62aaf4b8cea605d2a74cabe252e327a6d5 Mon Sep 17 00:00:00 2001 From: C-Achard Date: Wed, 4 Nov 2026 11:37:22 +0100 Subject: [PATCH 8/8] Include MkDocs notebooks support in documentation --- docs/guides/using-the-template.md | 2 +- src/scene_repo_template/cli.py | 8 ++++---- .../skeleton/mkdocs/docs/index.md.tmpl | 2 +- .../skeleton/mkdocs/mkdocs.yml.tmpl | 4 ++++ tests/test_cli.py | 10 +++++++++- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/guides/using-the-template.md b/docs/guides/using-the-template.md index e05272f..fd30061 100644 --- a/docs/guides/using-the-template.md +++ b/docs/guides/using-the-template.md @@ -48,7 +48,7 @@ You will need to enter: - A one-line description - The author - The GitHub URL -- The documentation: Jupyter Book (guides and notebooks) or MkDocs (API reference from docstrings) +- The documentation: Jupyter Book (guides and notebooks) or MkDocs (API reference from docstrings and notebooks) This will show a summary, and wait for confirmation. diff --git a/src/scene_repo_template/cli.py b/src/scene_repo_template/cli.py index 91d3cf6..893acf8 100644 --- a/src/scene_repo_template/cli.py +++ b/src/scene_repo_template/cli.py @@ -28,15 +28,15 @@ ), }, "mkdocs": { - "label": "MkDocs: API reference from docstrings", + "label": "MkDocs: API reference from docstrings, and notebooks", # MkDocs 2.0 drops the plugin system mkdocstrings relies on. "docs_dependencies": ( - '"mkdocs>=1.6,<2", "mkdocs-api-autonav>=0.1", "mkdocs-autorefs>=1.2", "mkdocs-material>=9.5", ' - '"mkdocstrings[python]>=0.27", "pymdown-extensions<12.2; python_version < \'3.11\'"' + '"mkdocs>=1.6,<2", "mkdocs-api-autonav>=0.1", "mkdocs-autorefs>=1.2", "mkdocs-jupyter>=0.25", ' + '"mkdocs-material>=9.5", "mkdocstrings[python]>=0.27", "pymdown-extensions<12.2; python_version < \'3.11\'"' ), "docs_readme": ( "Built from `docs/` and `mkdocs.yml` with [MkDocs](https://www.mkdocs.org) and Material, " - "the API reference generated from docstrings: " + "the API reference generated from docstrings and notebooks shown as pages: " 'after `pip install -e ".[docs]"` (or `uv sync --extra docs`), `mkdocs serve` serves it locally. ' "`.github/workflows/docs.yml` publishes it to GitHub Pages once Pages is enabled with GitHub Actions as its source." ), diff --git a/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl b/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl index 3dee4e6..03ea926 100644 --- a/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl +++ b/src/scene_repo_template/skeleton/mkdocs/docs/index.md.tmpl @@ -2,4 +2,4 @@ $description -The API reference is generated from the docstrings of `$package`. Add pages next to this one and list them under `nav:` in `mkdocs.yml`. +The API reference is generated from the docstrings of `$package`. Add pages, Markdown files or notebooks, next to this one and list them under `nav:` in `mkdocs.yml`. diff --git a/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl index e69cb29..c2daae5 100644 --- a/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl +++ b/src/scene_repo_template/skeleton/mkdocs/mkdocs.yml.tmpl @@ -58,6 +58,10 @@ plugins: inventories: - url: https://docs.python.org/3/objects.inv domains: [py, std] + # Notebooks (.ipynb) are pages, shown with the outputs saved in them, not re-executed. + # Only notebooks: by default, .py files in docs/ would become pages too. + - mkdocs-jupyter: + include: ["*.ipynb"] markdown_extensions: - attr_list diff --git a/tests/test_cli.py b/tests/test_cli.py index 6e5d511..7dc1941 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,5 +1,6 @@ import importlib import importlib.metadata +import json import os import shutil import subprocess @@ -80,6 +81,7 @@ def test_the_backends_ship_the_same_logo_and_favicon(): def test_the_docs_extra_follows_the_backend(tmp_path): pyproject = (generate(tmp_path, "--docs=mkdocs") / "pyproject.toml").read_text(encoding="utf-8") assert '"mkdocstrings[python]>=0.27"' in pyproject + assert '"mkdocs-jupyter>=0.25"' in pyproject assert "jupyter-book" not in pyproject @@ -333,8 +335,14 @@ def test_a_generated_jupyter_book_builds(tmp_path): @E2E -def test_a_generated_mkdocs_site_builds_with_an_api_page_per_module(tmp_path): +def test_a_generated_mkdocs_site_builds_with_an_api_page_per_module_and_a_notebook(tmp_path): dest = generate(tmp_path, "--docs=mkdocs") + notebook = {"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# Analysis"]}], "metadata": {}} + notebook |= {"nbformat": 4, "nbformat_minor": 5} + (dest / "docs" / "analysis.ipynb").write_text(json.dumps(notebook), encoding="utf-8") + mkdocs_yml = dest / "mkdocs.yml" + mkdocs_yml.write_text(mkdocs_yml.read_text(encoding="utf-8") + " - analysis.ipynb\n", encoding="utf-8") run(dest, "uv", "sync", "--extra", "docs") run(dest, "uv", "run", "mkdocs", "build", "--strict") assert (dest / "site" / "reference" / "my_project" / "version" / "index.html").is_file() + assert (dest / "site" / "analysis" / "index.html").is_file()