Skip to content

Include Markdown and notebook files with scoped references - #65

Open
PiotrCzapla wants to merge 13 commits into
mainfrom
board-consent-packet
Open

Include Markdown and notebook files with scoped references#65
PiotrCzapla wants to merge 13 commits into
mainfrom
board-consent-packet

Conversation

@PiotrCzapla

@PiotrCzapla PiotrCzapla commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

We needed a way to include Markdown in Markdown. Code blocks were perfect for that, but the included documents sometimes had clashing section names. We could fix all the clashes, but I thought it would be better to do it programmatically in mdhtml, as clashes in reference IDs are hard to notice when an include is added during DOCX generation.

This PR contains both the include function and the ability to scope references in included sections.
It feels that scope could be more generic and apply, for say, headers instead of a wrapping div.
But the generic version is harder to specify correctly.

LLM authored PR desc, but reads well:

include(path) loads Markdown files or exported notebook notes. During Markdown conversion, each include appends its scope to local IDs and links.

from mdhtml.fill import include

source = f'{include("camera.md")}\n\n<br type="page">\n\n{include("mic.ipynb")}'

The caller places page breaks. Ordinary placeholders are blank by default. keep=["port"] preserves a field; keep={"port": "camera_port"} also renames it. Code literals stay literal. Notebook loading excludes code and stored outputs.

Markdown and MDHTML

The blocks can also be written directly:

::: {.include scope="__camera"}
# Camera
## Setup {#sec-setup}
See [@sec-setup].
:::

::: {.include scope="__mic"}
# Microphone
## Setup {#sec-setup}
See [@sec-setup].
:::

md2mdhtml(source) produces:

<div class="include">
<h1>Camera</h1>
<h2 id="sec-setup__camera">Setup</h2>
<p>See <a href="#sec-setup__camera" data-ref=""></a>.</p>
</div>
<div class="include">
<h1>Microphone</h1>
<h2 id="sec-setup__mic">Setup</h2>
<p>See <a href="#sec-setup__mic" data-ref=""></a>.</p>
</div>

scope is the complete suffix. scope="__mic" produces sec-setup__mic by concatenation. The converter inserts no punctuation. The file helper defaults to __ followed by the filename stem.

The sec-, fig- and tbl- prefixes remain intact. Reference lookup uses its existing rules without stripping namespaces or adding reference syntax.

Inside the include, use [@sec-setup]. Outside, use [@sec-setup__mic]. An unqualified outside reference reports a missing target. Links to outside targets stay unchanged. Nested scopes append in order: sec-setup__lens__camera.

HTML export adds numbers and reference text. Each h1 resets the normal heading counter. Nested divs use the same ::: delimiter.

Implementation and checks

Include handling runs with the div renderer and processes include contents without reparsing the whole document. Invalid scope attributes produce parser warnings. Rust render and wiki2mdhtml return strings. The helper reuses the notebook conversion functions and Md return type.

Independent review approved the changes. All 963 Python tests and 42 Rust tests passed; the WASM target compiled. The combined converter suite passed 40 tests and 16 downstream integration tests passed. The default Python suite excludes one slow test.

PiotrCzapla and others added 5 commits September 3, 2026 23:01
… numbers on request

A document's frontmatter `number_headings: legal` (or `decimal`) now drives every
exporter when the call gives no scheme: `mdhtml2html` and `mdhtml2typst` read it
from the `Mdhtml` result's `meta`, `md2gfm` extracts it from the raw source by the
dialect's own rule (new native `frontmatter_meta`), and `viewmd` reads a notebook's
frontmatter message through fastcore's `nb_frontmatter` since `dlg2md` fences that
raw cell as code. The call argument still wins when both are present.

`refs='ids'` (the live-preview mode Solveit renders in) used to skip numbering
entirely; a requested scheme now numbers the fragment's headings there too, while
nothing numbers automatically without a registry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Namespace include-local IDs and links while preserving reference types.
Give each include its own HTML heading counter and honor unnumbered forms.
This prevents repeated exhibit names and numbering schemes from leaking
between the consent and its attached forms.

Validated with the assembled stock-plan packet and renderer suites:
73 tests passed; 2 checkout-asset tests deselected. The coordinated
mdhtml2docx, virgil-templates, and fasttract changes are on branches
named board-consent-packet.
@jph00

jph00 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

I deleted the private links from this PR - be careful please.

I don't understand the jargon being used here. Please try to explain in simple concise terms.

@PiotrCzapla
PiotrCzapla changed the base branch from frontmatter-numbering to main September 9, 2026 09:36
@PiotrCzapla PiotrCzapla changed the title Scope included document references and heading numbering Prefix included document IDs and local links Sep 9, 2026
@PiotrCzapla PiotrCzapla changed the title Prefix included document IDs and local links Prefix included IDs during Markdown conversion Sep 9, 2026
@PiotrCzapla PiotrCzapla changed the title Prefix included IDs during Markdown conversion Include Markdown and notebook files with scoped references Sep 9, 2026
Comment thread py/src/lib.rs Outdated
Comment thread python/mdhtml/fill.py
Comment thread python/mdhtml/fill.py Outdated
Comment thread python/mdhtml/fill.py Outdated
Comment thread python/mdhtml/fill.py Outdated
Comment thread python/mdhtml/md.py Outdated
Comment thread python/mdhtml/typst.py Outdated
Comment thread src/scopes.rs Outdated
@PiotrCzapla

PiotrCzapla commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

I deleted the private links from this PR - be careful please.

I don't understand the jargon being used here. Please try to explain in simple concise terms.

LLm didn't have instructions to watch out when publishing to a public repo; you got to the PR before I did. I need to find a better way to review the changes before they go to the public repo. Sorry about that. Thank you for catching that.

@PiotrCzapla
PiotrCzapla marked this pull request as ready for review September 9, 2026 21:24
@PiotrCzapla
PiotrCzapla requested a review from jph00 September 9, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants