From b74ce5becc4a1b647732e11ed8fa93a0296cef0d Mon Sep 17 00:00:00 2001 From: Vivswan Shah <58091053+Vivswan@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:11:38 -0400 Subject: [PATCH] refactor(scripts): walk the markdown tree of generated regions with unist-util-visit-parents scanMarkdown in generated-regions.ts walked the mdast tree with a hand-rolled recursive closure that pushed each node's span by type, recorded the headings outside every blockquote through an inQuote flag it threaded down, and recursed into children by hand. unist-util-visit-parents does that walk, preorder with the ancestor list at every node, so the flag becomes a check of the ancestors. It was a transitive dependency of the mdast stack; it is now a direct devDependency at the version bun.lock already held. The differential check ran the old scan against the new over every markdown file in the repository (53 files: 4,628 spans and 400 headings) and over 5,000 seeded generated documents built from 46 block shapes, nested blockquotes, unclosed fences and raw blocks, GFM tables, CRLF endings, and markers in every position the placement check classifies (25,289 spans and 3,879 headings). Every span list and heading agreed. bun run build:check finds all 14 generated files placed as before. --- .github/scripts/lib/generated-regions.ts | 19 +++++++------------ bun.lock | 1 + package.json | 3 ++- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/scripts/lib/generated-regions.ts b/.github/scripts/lib/generated-regions.ts index a4b3c4a3..f9d6bc0e 100644 --- a/.github/scripts/lib/generated-regions.ts +++ b/.github/scripts/lib/generated-regions.ts @@ -8,6 +8,7 @@ import { fromMarkdown } from "mdast-util-from-markdown"; import { gfmTableFromMarkdown } from "mdast-util-gfm-table"; import { gfmTable } from "micromark-extension-gfm-table"; import { err, ok, type Result } from "neverthrow"; +import { visitParents } from "unist-util-visit-parents"; import { Parser } from "yaml"; /** Which comment syntax a file's markers use: a complete `` comment, or a whole-line YAML `#` comment. */ @@ -296,23 +297,17 @@ function scanMarkdown(text: string): MarkdownScan { html, blockquote: quoted, }; - const walk = (node: MarkdownNode, inQuote: boolean): void => { + const tree = fromMarkdown(text, { + extensions: [gfmTable()], + mdastExtensions: [gfmTableFromMarkdown()], + }); + visitParents(tree, (node, ancestors) => { spansByType[node.type]?.push(nodeSpan(node)); - if (node.type === "heading" && !inQuote) { + if (node.type === "heading" && !ancestors.some((ancestor) => ancestor.type === "blockquote")) { const [start, end] = nodeSpan(node); headings.push({ offset: start, text: text.slice(start, end).trim() }); } - if ("children" in node) { - for (const child of node.children) { - walk(child, inQuote || node.type === "blockquote"); - } - } - }; - const tree = fromMarkdown(text, { - extensions: [gfmTable()], - mdastExtensions: [gfmTableFromMarkdown()], }); - walk(tree, false); return { code, codeSpans, html, quoted, headings }; } diff --git a/bun.lock b/bun.lock index c460a796..8b85f93d 100644 --- a/bun.lock +++ b/bun.lock @@ -52,6 +52,7 @@ "publint": "0.3.25", "tsdown": "0.23.0", "typescript": "7.0.2", + "unist-util-visit-parents": "6.0.2", }, }, }, diff --git a/package.json b/package.json index ef324d83..387e0439 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "oxc-parser": "0.152.0", "publint": "0.3.25", "tsdown": "0.23.0", - "typescript": "7.0.2" + "typescript": "7.0.2", + "unist-util-visit-parents": "6.0.2" } }