From 6e8d9e24d645c1431a4ed4c7121ffafb1b15d69f Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sun, 6 Sep 2026 00:20:22 +0530 Subject: [PATCH 1/6] sdk%ci(chore): collapse duplicated workflow path filters --- .github/workflows/pkg_num.yml | 10 ++-------- .github/workflows/pkg_p2p_core.yml | 15 ++------------- .github/workflows/pkg_params.yml | 13 ++----------- .github/workflows/pkg_pkc.yml | 12 ++---------- .github/workflows/pkg_pow.yml | 11 ++--------- .github/workflows/pkg_primitives.yml | 13 ++----------- .github/workflows/pkg_script.yml | 11 ++--------- .github/workflows/pkg_types.yml | 10 ++-------- 8 files changed, 16 insertions(+), 79 deletions(-) diff --git a/.github/workflows/pkg_num.yml b/.github/workflows/pkg_num.yml index a26ff60b..2023c8c3 100644 --- a/.github/workflows/pkg_num.yml +++ b/.github/workflows/pkg_num.yml @@ -3,7 +3,7 @@ name: "dash-num" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/num/** - Cargo.lock - Cargo.toml @@ -11,13 +11,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/num/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_num.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_p2p_core.yml b/.github/workflows/pkg_p2p_core.yml index ad02a128..8bda0071 100644 --- a/.github/workflows/pkg_p2p_core.yml +++ b/.github/workflows/pkg_p2p_core.yml @@ -3,7 +3,7 @@ name: "dash-p2p-core" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/p2p_core/** - pkgs/num/** - pkgs/params/** @@ -16,18 +16,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/p2p_core/** - - pkgs/num/** - - pkgs/params/** - - pkgs/primitives/** - - pkgs/script/** - - pkgs/types/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_p2p_core.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_params.yml b/.github/workflows/pkg_params.yml index f506218d..47f5bd0c 100644 --- a/.github/workflows/pkg_params.yml +++ b/.github/workflows/pkg_params.yml @@ -3,7 +3,7 @@ name: "dash-params" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/params/** - pkgs/num/** - pkgs/primitives/** @@ -14,16 +14,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/params/** - - pkgs/num/** - - pkgs/primitives/** - - pkgs/script/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_params.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_pkc.yml b/.github/workflows/pkg_pkc.yml index 13fc73b7..da71da1d 100644 --- a/.github/workflows/pkg_pkc.yml +++ b/.github/workflows/pkg_pkc.yml @@ -3,7 +3,7 @@ name: "dash-pkc" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/pkc/** - pkgs/num/** - pkgs/types/** @@ -13,15 +13,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/pkc/** - - pkgs/num/** - - pkgs/types/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_pkc.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_pow.yml b/.github/workflows/pkg_pow.yml index 129a93cd..5a95334c 100644 --- a/.github/workflows/pkg_pow.yml +++ b/.github/workflows/pkg_pow.yml @@ -3,7 +3,7 @@ name: "dash-pow" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/pow/** - pkgs/num/** - Cargo.lock @@ -12,14 +12,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/pow/** - - pkgs/num/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_pow.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_primitives.yml b/.github/workflows/pkg_primitives.yml index 2baa8733..56ecdb49 100644 --- a/.github/workflows/pkg_primitives.yml +++ b/.github/workflows/pkg_primitives.yml @@ -3,7 +3,7 @@ name: "dash-primitives" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/primitives/** - pkgs/num/** - pkgs/script/** @@ -14,16 +14,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/primitives/** - - pkgs/num/** - - pkgs/script/** - - pkgs/types/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_primitives.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_script.yml b/.github/workflows/pkg_script.yml index e528e8e6..7b40c41e 100644 --- a/.github/workflows/pkg_script.yml +++ b/.github/workflows/pkg_script.yml @@ -3,7 +3,7 @@ name: "dash-script" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/script/** - pkgs/types/** - Cargo.lock @@ -12,14 +12,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/script/** - - pkgs/types/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_script.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pkg_types.yml b/.github/workflows/pkg_types.yml index 56ce3a75..3b6f8cdb 100644 --- a/.github/workflows/pkg_types.yml +++ b/.github/workflows/pkg_types.yml @@ -3,7 +3,7 @@ name: "dash-types" on: workflow_dispatch: push: - paths: + paths: &paths - pkgs/types/** - Cargo.lock - Cargo.toml @@ -11,13 +11,7 @@ on: - .github/workflows/build_stable.yml - .github/workflows/build_nightly.yml pull_request: - paths: - - pkgs/types/** - - Cargo.lock - - Cargo.toml - - .github/workflows/pkg_types.yml - - .github/workflows/build_stable.yml - - .github/workflows/build_nightly.yml + paths: *paths concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} From a2bb116521f7121d9c2493bcc31b27c19f471116 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sun, 6 Sep 2026 00:20:52 +0530 Subject: [PATCH 2/6] sdk%ci(fix): rebuild docs if Python definitions are updated --- .github/workflows/pages.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 9be1cde0..2afb1ea4 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -8,6 +8,10 @@ on: - pkgs/** - docs/** - .github/workflows/pages.yml + - pyproject.toml + - uv.lock + - README.md + - '**/README.md' workflow_dispatch: concurrency: From 50c5e23ddeb4a510a86afa00a1d49f4a45f60777 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sat, 5 Sep 2026 23:49:09 +0530 Subject: [PATCH 3/6] sdk%ci(fix): define `token` over relying on `CODECOV_TOKEN` envvar --- .github/workflows/build_nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_nightly.yml b/.github/workflows/build_nightly.yml index c93e9a93..3d11fb3a 100644 --- a/.github/workflows/build_nightly.yml +++ b/.github/workflows/build_nightly.yml @@ -100,9 +100,9 @@ jobs: with: files: lcov.info flags: ${{ inputs.package }} + token: ${{ secrets.CODECOV_TOKEN }} env: HAS_CODECOV: ${{ secrets.CODECOV_TOKEN != '' }} - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Sanity check benchmarks run: cargo bench ${{ matrix.config.args }} --package ${{ inputs.package }} --no-run From 3ae446995455760c740768905676273972d55dd1 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sun, 6 Sep 2026 02:24:22 +0530 Subject: [PATCH 4/6] sdk%fix(zen): refuse a spliced segment that leaves a fence open --- docs/preprocess.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/preprocess.py b/docs/preprocess.py index 0da24d90..c08e3638 100644 --- a/docs/preprocess.py +++ b/docs/preprocess.py @@ -151,6 +151,14 @@ def covers(self, line: str) -> bool: return True +def _opens_a_fence(lines: list[str]) -> bool: + """Whether *lines* leave a code fence open at their end.""" + fences = _Fences() + for line in lines: + fences.covers(line) + return fences.opener is not None + + def forge_url(repo_url: str, branch: str, source: Path) -> str: """Return the URL *source* is served from, by its kind.""" kind = "tree" if source.is_dir() else "blob" @@ -275,7 +283,12 @@ def _section(lines: list[str], name: str, spec: str) -> list[str]: finish = next((i for i, text in enumerate(lines) if closer in text), None) if begin is None or finish is None or finish < begin: raise ValueError(f"{spec}: no such section") - return lines[begin + 1 : finish] + found = lines[begin + 1 : finish] + # A fence the segment opens holds over the page it is spliced into, + # which reads there as the segment having swallowed what follows. + if _opens_a_fence(found): + raise ValueError(f"{spec}: segment leaves a fence open") + return found class PreprocessorHost(Extension): @@ -356,6 +369,15 @@ def test_include_refuses_an_unknown_section(self) -> None: with pytest.raises(ValueError, match="no such section"): self._render(f'\n') + def test_section_refuses_an_unclosed_fence(self) -> None: + import pytest + + with self._scratch( + whole="\n```\nsample\n\n", + ) as home: + with pytest.raises(ValueError, match="leaves a fence open"): + self._render(f'\n') + def test_include_rejects_an_absolute_path(self) -> None: import pytest From b0ba186b5cb722e2db3c80e7bce739933c5c999c Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sun, 6 Sep 2026 01:37:32 +0530 Subject: [PATCH 5/6] sdk%feat(zen): add support for omitted segments --- docs/dev/about_docs.md | 21 ++++++++++- docs/preprocess.py | 86 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/docs/dev/about_docs.md b/docs/dev/about_docs.md index d2151c5e..45514310 100644 --- a/docs/dev/about_docs.md +++ b/docs/dev/about_docs.md @@ -77,7 +77,7 @@ outside `docs/` resolve to the forge instead. > [!WARNING] > Zensical treats on-disk `.md` links as documentation and will fail to build if they are located outside `docs/`. -> This does not affect non-Markdown files and directories. +> This does not affect non-Markdown files and directories. [Omitted](#omitting) segments are not processed at all. ### Splicing @@ -99,6 +99,10 @@ To splice in a whole document, or a spliced segment of it (like `setup`), the sy ``` +> [!WARNING] +> `omit` is a reserved label for _stripping_ spliceable regions from the final document. See [Omitting](#omitting) for +> more details. + To create a spliceable segment, wrap the desired text in `start` and `end` markers carrying its label (like `setup`). ```markdown @@ -110,6 +114,21 @@ Carried into the splice. Links in spliced material are resolved against the file that defines them, not the page splicing it in (see [link processing](#link-processing)). Splices may nest, and a directive inside a code fence is inert. +### Omitting + +Due to the dual-audience nature of our documentation, there may exist segments that are meant for GitHub but not +Zensical. The usual pattern for the reverse is to create a new file and then splice in what is required but this creates +situations where most of the file is included _except_ for a small portion. Omissions can take care of that. + +To omit a segment, use the following syntax. Unlike other labels, `omit` can be used repeatedly but typos of `omit` will +be treated as ordinary spliceable segments. + +```markdown + +Rendered on GitHub, absent from the site. + +``` + ## Postprocessing > [!WARNING] diff --git a/docs/preprocess.py b/docs/preprocess.py index c08e3638..e2fccf70 100644 --- a/docs/preprocess.py +++ b/docs/preprocess.py @@ -97,12 +97,18 @@ def run(self, lines: list[str]) -> list[str]: # Matches a splice from another file, or one named section from it. _INCLUDE_RE = re.compile(r"^\s*\s*$") -# Matches any directive-shaped comment, whatever it names. +# Matches any directive-shaped comment, by the verb and label it names. _DIRECTIVE_RE = re.compile(r"^\s*\s*$") # The directives this module answers for. Anything else is a misspelling. _DIRECTIVES = frozenset({"include", "start", "end"}) +# Label reserved for a segment the site does not carry. +_OMIT_LABEL = "omit" + +# Matches a bound of such a segment. +_OMIT_RE = re.compile(rf"^\s*\s*$") + # Matches the target of an inline link, and any title trailing it. _LINK_RE = re.compile( r"\]\(\s*(<[^<>]*>|[^\s()]+)" @@ -119,6 +125,39 @@ def run(self, lines: list[str]) -> list[str]: _DEPTH_LIMIT = 8 +def _strip_omitted(lines: list[str]) -> list[str]: + """Return *lines* without any segment labelled for omission.""" + output: list[str] = [] + fences = _Fences() + begin = None + + for index, line in enumerate(lines): + # An omitted line never reaches the renderer, so it cannot open a fence in + # the stream *fences* models and is not tracked in it. + hidden = begin is not None + found = _OMIT_RE.match(line) if hidden or not fences.covers(line) else None + if found is None: + if not hidden: + # A misspelt verb doesn't match, so the line is passed on and + # refused in `_named_directive`. + output.append(line) + continue + if found.group(1) == "start": + if hidden: + raise ValueError(f"{_OMIT_LABEL}: segments do not nest") + begin = index + continue + if not hidden: + raise ValueError(f"{_OMIT_LABEL}: no segment is open") + if _opens_a_fence(lines[begin + 1 : index]): + raise ValueError(f"{_OMIT_LABEL}: segment leaves a fence open") + begin = None + + if begin is not None: + raise ValueError(f"{_OMIT_LABEL}: segment left open") + return output + + def _named_directive(line: str) -> None: """Raise when *line* holds a directive this module does not answer for.""" found = _DIRECTIVE_RE.match(line) @@ -180,7 +219,7 @@ def __init__(self, md: Markdown, repo_url: str, branch: str) -> None: self.branch = branch def run(self, lines: list[str]) -> list[str]: - return self._expand(lines, _DEPTH_LIMIT, _Fences()) + return self._expand(_strip_omitted(lines), _DEPTH_LIMIT, _Fences()) def _expand( self, lines: list[str], budget: int, fences: _Fences, @@ -218,7 +257,7 @@ def _include(self, spec: str, fences: _Fences) -> list[str]: if not source.is_file(): raise ValueError(f"{spec}: no such file in the repository") - lines = source.read_text(encoding="utf-8").splitlines() + lines = _strip_omitted(source.read_text(encoding="utf-8").splitlines()) if section: lines = _section(lines, section, spec) # `_rebase` walks these same lines, so it takes a copy of the fence @@ -426,6 +465,47 @@ def test_include_refuses_a_cycle(self) -> None: with pytest.raises(ValueError, match="nested past the limit"): self._render(spec) + def test_omit_drops_every_segment_it_labels(self) -> None: + # Unlike a spliceable label, `omit` repeats. A fence or an include a + # segment holds goes with it, and the file named, were it read, does + # not exist and would have been refused. + out = self._render( + "one\n\n```\nhidden\n```\n\n" + "two\n\n" + "\n\nthree\n" + ) + assert "hidden" not in out + assert all(word in out for word in ("one", "two", "three")) + + def test_omit_refuses_a_malformed_segment(self) -> None: + import pytest + + cases = ( + ("\nx\n", "segment left open"), + ("x\n\n", "no segment is open"), + ("\n\n", "do not nest"), + ("\n```\n\n", + "leaves a fence open"), + # The label must not carry a misspelt verb past the directive check. + ("\n", "no such directive"), + ) + for source, message in cases: + with pytest.raises(ValueError, match=message): + self._render(source) + + def test_omit_applies_to_spliced_material(self) -> None: + import pytest + + with self._scratch( + part="carried\n\n" + "[x](./nope.md)\n\n", + ) as home: + out = self._render(f'\n') + with pytest.raises(ValueError, match="no such section"): + self._render(f'\n') + assert "carried" in out + assert "nope.md" not in out + def test_titled_link_is_rebased(self) -> None: with self._scratch(page='[a](../README.md "root")\n') as home: out = self._render(f'\n') From 186bcf9a6975d2cf1a9dcb17b604901ad1d8aba4 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sun, 6 Sep 2026 01:57:23 +0530 Subject: [PATCH 6/6] sdk%doc(zen): omit directory-based tip, add note for GitHub readers --- docs/dev/maintenance.md | 7 +++++++ maint/README.md | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/docs/dev/maintenance.md b/docs/dev/maintenance.md index 7e650eae..724451ef 100644 --- a/docs/dev/maintenance.md +++ b/docs/dev/maintenance.md @@ -1,4 +1,11 @@ # Maintenance + + +> [!NOTE] +> This is a spliced page meant for publication on Zensical. See [`maint`](../../maint/) for available documentation. + + + diff --git a/maint/README.md b/maint/README.md index 4f54f66b..6133d5f4 100644 --- a/maint/README.md +++ b/maint/README.md @@ -1,7 +1,11 @@ + + > [!TIP] > In order to run these scripts, make sure you've set up a development environment as described in > [`contrib`](../contrib/README.md) + + ## Linters All linters available are listed below. The first verb is implied if no verb is specified at runtime. Verbs may accept