14. Page text is Markdown, parsed by a library on both sides#
Date: 2026-10-20 (#71, #102)
Status#
Accepted
Context#
Early rendering and importing used hand-written regexes. They mis-handled tables, code, nested brackets and pathological inputs, and the client and server disagreed about what a link or image was. Search needed plain text from the same parse.
Decision#
Both sides use the same grammar: CommonMark plus tables, strikethrough, footnotes,
[[slug|label]]page links, raw HTML as text, and a line break kept as one.The PWA renders with markdown-it in a lazy chunk (
render.ts); a post-parse pass allows only http(s), mailto, page and in-page links (rel=noopener) and only this server’s images.```mermaidblocks are drawn by a bundled, separately loaded Mermaid withsecurityLevel: 'strict', so the CSP does not change.The server uses markdown-it-py (
scrap/markdown.py) to produce search text (link/image text, not addresses; code as typed) and for link rewriting, which rewrites links, images and wiki links found by the parse and mapped back to source positions, so code is never touched.Parsers must be linear in the text. Migration 0004 re-indexed every page this way.
Search deliberately does not index addresses.
Consequences#
Rendering offline works once the chunk is cached; before that, text shows as typed.
Two parser implementations must be kept in step, covered by tests and docs.
A hand-written URL is found by its link text, not its domain, by choice.