From 8550b0f3d6af9ed46b6b24fe00df09ad9b6c1fdb Mon Sep 17 00:00:00 2001 From: Michael Toy <66150587+mtoy-googly-moogly@users.noreply.github.com> Date: Tue, 12 May 2026 21:24:02 -0700 Subject: [PATCH] fix: derive heading anchors from plain text, not rendered HTML The heading() renderer was hashing the already-HTML-rendered heading content to produce its anchor id. For headings containing inline code, the syntax highlighter wraps the code in markup, which then got slugified into anchor ids like #array-givens-and-code-class-language-malloy-style-...-span- Walk the Markdown AST to extract plain text first, then slug it. The displayed heading still uses the full rendered HTML; only the anchor id and in-page href use the plain-text slug. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/render_document.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/render_document.ts b/scripts/render_document.ts index 9a237582..d2735e26 100644 --- a/scripts/render_document.ts +++ b/scripts/render_document.ts @@ -39,6 +39,20 @@ import { import { DocumentPosition, DocumentRange, ModelDef } from "@malloydata/malloy"; import { DocsError } from "./errors.js"; +function plainTextFromMarkdown(nodes: Markdown[]): string { + return nodes + .map((node) => { + if ("value" in node && typeof node.value === "string") { + return node.type === "html" ? "" : node.value; + } + if ("children" in node && Array.isArray(node.children)) { + return plainTextFromMarkdown(node.children as Markdown[]); + } + return ""; + }) + .join(""); +} + /* * A Renderer is capable of converting a parsed `Markdown` document into HTML, * given that it exists at a given `path`. @@ -202,7 +216,7 @@ class Renderer { protected async heading(content: Markdown[], level: 1 | 2 | 3 | 4 | 5 | 6) { const text = await this.children(content); this.registerTitle(text, level); - const escapedText = hashForHeading(text); + const escapedText = hashForHeading(plainTextFromMarkdown(content)); this.hashes.push(escapedText); // TODO handle ambiguous hashes?