Summary
Add an opt-in capability to the markdown bundle action that rewrites local .md links to .html in the rendered output, so that converting a Markdown doc to HTML also fixes its intra-doc links in a single action.
Motivation
Today the markdown action only renders Markdown to HTML — it does not touch links. To make links work in the rendered HTML, bundle authors must follow every markdown action with a separate move/copy action carrying a regex replace like:
replace:
from: "((\./|(?:\.\./)+).+)\.md"
to: "\g<1>.html"
In the gist repo's bundle.yaml this exact block is copy-pasted 6 times (docs, docs/models, migration v11–v14). That duplication is error-prone: a real bug shipped in the gist 14.1.0 web-download bundle because the replace block got attached to the wrong action (the *.md move instead of the *.html move), simultaneously skipping the conversion where it was needed and applying it where it was wrong. See gist issues semanticarts/gist#1443 (redesign request) and semanticarts/gist#1467 (the narrow bug fix).
Pushing the .md→.html relink into the markdown action itself eliminates all six duplicated blocks downstream and removes the entire class of "wrong action" bugs, because there is no longer a separate, mis-attachable step. This is "Option A" from semanticarts/gist#1443.
Proposed change
Add an opt-in boolean option to the markdown action (proposed name: relinkHtml, matching the existing camelCase options like versionedDefinedBy, retainDefinedBy). When true, after rendering Markdown to HTML, rewrite local relative links ending in .md to .html.
- action: markdown
source: "{output}/docs/"
target: "{output}/docs/html/"
includes: ["*.md"]
relinkHtml: true # NEW: render AND fix .md -> .html links
Rewrite semantics (must get these right)
- Only rewrite local relative link targets — skip absolute URLs (
http:, https:, mailto:, protocol-relative //, and root-absolute /...).
- Operate on
href/src attribute values of the rendered HTML, not arbitrary text — so .md mentioned in prose or code spans is not touched. (This is stricter/safer than the current regex, which matched anywhere in the file.)
- Preserve any
#fragment or ?query suffix: ./Foo.md#section → ./Foo.html#section.
- More general than the current regex (which required an explicit
./ or ../ prefix): bare relative targets like Foo.md should also be relinked.
Implementation pointers (branch already created)
A branch feature/markdown-relink-html is already checked out off develop.
onto_tool/bundle.py:292 — __bundle_markdown__ (the markdown action). Currently renders via md2html and writes output; ignores replace. Read the option here (use the existing __boolean_option__ helper at onto_tool/bundle.py:849) and pass it through to the renderer.
onto_tool/mdutils.py:44 — md2html(md). Add an optional relink=False parameter; when set, post-process the rendered HTML to rewrite local .md links in href/src attributes to .html. A focused regex on attribute values (with the scheme/anchor handling above) is acceptable for the prototype; a real HTML parser is the robust version if needed.
onto_tool/bundle_schema.yaml — the markdown action validates against #/definitions/bulk_file_operation (def at line 32; markdown wired at lines 394–396). Add the new relinkHtml property so the option passes schema validation. (Confirm whether additionalProperties is restricted — this was the last unchecked item before the session paused.)
Tests
There is an existing markdown test harness to extend:
tests/bundle/test_markdown.py, tests/bundle/markdown.yaml, tests/bundle/bulk_md.yaml, tests/bundle/Table.md
- Add a fixture Markdown file containing a mix of links: a local
./foo.md, a bare foo.md, a ../bar.md#frag, an external https://example.com/x.md, and a .md reference inside a code span. Assert that only the local relative ones are rewritten to .html, fragments preserved, external and code-span untouched.
- Runner is
pytest (see setup.py tests_require).
Acceptance criteria
Out of scope
The relative-path depth fixes (e.g. ../docs/ → ./, ../migration/ → ../../migration/) are a separate concern ("Option B" in semanticarts/gist#1443) and are not part of this issue.
Summary
Add an opt-in capability to the
markdownbundle action that rewrites local.mdlinks to.htmlin the rendered output, so that converting a Markdown doc to HTML also fixes its intra-doc links in a single action.Motivation
Today the
markdownaction only renders Markdown to HTML — it does not touch links. To make links work in the rendered HTML, bundle authors must follow everymarkdownaction with a separatemove/copyaction carrying a regexreplacelike:In the gist repo's
bundle.yamlthis exact block is copy-pasted 6 times (docs, docs/models, migration v11–v14). That duplication is error-prone: a real bug shipped in the gist 14.1.0 web-download bundle because thereplaceblock got attached to the wrong action (the*.mdmove instead of the*.htmlmove), simultaneously skipping the conversion where it was needed and applying it where it was wrong. See gist issues semanticarts/gist#1443 (redesign request) and semanticarts/gist#1467 (the narrow bug fix).Pushing the
.md→.htmlrelink into themarkdownaction itself eliminates all six duplicated blocks downstream and removes the entire class of "wrong action" bugs, because there is no longer a separate, mis-attachable step. This is "Option A" from semanticarts/gist#1443.Proposed change
Add an opt-in boolean option to the
markdownaction (proposed name:relinkHtml, matching the existing camelCase options likeversionedDefinedBy,retainDefinedBy). When true, after rendering Markdown to HTML, rewrite local relative links ending in.mdto.html.Rewrite semantics (must get these right)
http:,https:,mailto:, protocol-relative//, and root-absolute/...).href/srcattribute values of the rendered HTML, not arbitrary text — so.mdmentioned in prose or code spans is not touched. (This is stricter/safer than the current regex, which matched anywhere in the file.)#fragmentor?querysuffix:./Foo.md#section→./Foo.html#section../or../prefix): bare relative targets likeFoo.mdshould also be relinked.Implementation pointers (branch already created)
A branch
feature/markdown-relink-htmlis already checked out offdevelop.onto_tool/bundle.py:292—__bundle_markdown__(themarkdownaction). Currently renders viamd2htmland writes output; ignoresreplace. Read the option here (use the existing__boolean_option__helper atonto_tool/bundle.py:849) and pass it through to the renderer.onto_tool/mdutils.py:44—md2html(md). Add an optionalrelink=Falseparameter; when set, post-process the rendered HTML to rewrite local.mdlinks inhref/srcattributes to.html. A focused regex on attribute values (with the scheme/anchor handling above) is acceptable for the prototype; a real HTML parser is the robust version if needed.onto_tool/bundle_schema.yaml— themarkdownaction validates against#/definitions/bulk_file_operation(def at line 32; markdown wired at lines 394–396). Add the newrelinkHtmlproperty so the option passes schema validation. (Confirm whetheradditionalPropertiesis restricted — this was the last unchecked item before the session paused.)Tests
There is an existing markdown test harness to extend:
tests/bundle/test_markdown.py,tests/bundle/markdown.yaml,tests/bundle/bulk_md.yaml,tests/bundle/Table.md./foo.md, a barefoo.md, a../bar.md#frag, an externalhttps://example.com/x.md, and a.mdreference inside a code span. Assert that only the local relative ones are rewritten to.html, fragments preserved, external and code-span untouched.pytest(seesetup.pytests_require).Acceptance criteria
markdownaction acceptsrelinkHtml: trueand rewrites local.mdlinks to.htmlin rendered output.bundle.yamlto userelinkHtmland delete the six duplicatedmove … replaceblocks — tracked in gist, not here.Out of scope
The relative-path depth fixes (e.g.
../docs/→./,../migration/→../../migration/) are a separate concern ("Option B" in semanticarts/gist#1443) and are not part of this issue.