Skip to content

Commit baebfbd

Browse files
fix: derive heading anchors from plain text, not rendered HTML (#314)
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 <code><span style="..."> 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) <noreply@anthropic.com>
1 parent 3eb4789 commit baebfbd

1 file changed

Lines changed: 15 additions & 1 deletion

File tree

scripts/render_document.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ import {
3939
import { DocumentPosition, DocumentRange, ModelDef } from "@malloydata/malloy";
4040
import { DocsError } from "./errors.js";
4141

42+
function plainTextFromMarkdown(nodes: Markdown[]): string {
43+
return nodes
44+
.map((node) => {
45+
if ("value" in node && typeof node.value === "string") {
46+
return node.type === "html" ? "" : node.value;
47+
}
48+
if ("children" in node && Array.isArray(node.children)) {
49+
return plainTextFromMarkdown(node.children as Markdown[]);
50+
}
51+
return "";
52+
})
53+
.join("");
54+
}
55+
4256
/*
4357
* A Renderer is capable of converting a parsed `Markdown` document into HTML,
4458
* given that it exists at a given `path`.
@@ -202,7 +216,7 @@ class Renderer {
202216
protected async heading(content: Markdown[], level: 1 | 2 | 3 | 4 | 5 | 6) {
203217
const text = await this.children(content);
204218
this.registerTitle(text, level);
205-
const escapedText = hashForHeading(text);
219+
const escapedText = hashForHeading(plainTextFromMarkdown(content));
206220
this.hashes.push(escapedText);
207221
// TODO handle ambiguous hashes?
208222

0 commit comments

Comments
 (0)