fix(markdown): keep summary block boundaries outside bold text

This commit is contained in:
Mohamed Boudra
2026-10-15 20:26:35 +02:00
parent 904fc10d89
commit 35592a26f8
2 changed files with 20 additions and 2 deletions
+12 -2
View File
@@ -6,7 +6,7 @@ import type { Nodes } from "mdast";
const ATTRIBUTE = String.raw`\s+[A-Za-z_:][\w.:-]*(?:\s*=\s*(?:[^\s"'=<>\x60]+|'[^']*'|"[^"]*"))?`;
const TAG = String.raw`<(?:[A-Za-z][A-Za-z0-9-]*(?:${ATTRIBUTE})*\s*\/?|\/[A-Za-z][A-Za-z0-9-]*\s*)>`;
const HTML = new RegExp(
String.raw`(?<!\\)(?:<!--[\s\S]*?-->|<code\b[^>]*>[\s\S]*?<\/code\s*>|${TAG})`,
String.raw`(?<!\\)(?:<!--[\s\S]*?-->|<code\b[^>]*>[\s\S]*?<\/code\s*>|<summary\b[^>]*>[\s\S]*?<\/summary\s*>|${TAG})`,
"gi",
);
const BLOCK_TAGS = new Set([
@@ -57,6 +57,16 @@ export function normalizeMarkdownHtml(source: string): string {
const convert = (raw: string, offset: number): string => {
if (codeRanges.some(({ start, end }) => offset >= start && offset < end)) return raw;
if (raw.startsWith("<!--")) return "";
const summary = /^<summary\b[^>]*>([\s\S]*?)<\/summary\s*>$/i.exec(raw);
if (summary) {
const title = normalizeMarkdownHtml(summary[1]).trim();
// A summary is one bold paragraph, even when its HTML title uses headings
// or several block wrappers. Slice AST blocks so inline code stays literal.
const inline = fromMarkdown(title)
.children.map(({ position }) => title.slice(position!.start.offset!, position!.end.offset!))
.join(" ");
return `**${inline}**\n\n`;
}
const code = /^<code\b[^>]*>([\s\S]*?)<\/code\s*>$/i.exec(raw);
if (code)
return inlineCode(
@@ -83,7 +93,7 @@ export function normalizeMarkdownHtml(source: string): string {
result += source.slice(cursor, range.start);
// Inline HTML code has separate opening/closing AST nodes. Convert the pair
// together so its contents keep backslashes and get a safe backtick delimiter.
const code = /^<code\b[^>]*>[\s\S]*?<\/code\s*>/i.exec(source.slice(range.start));
const code = /^<(code|summary)\b[^>]*>[\s\S]*?<\/\1\s*>/i.exec(source.slice(range.start));
const end = code ? Math.max(range.end, range.start + code[0].length) : range.end;
result += source
.slice(range.start, end)
@@ -222,6 +222,14 @@ describe("GitHub comment HTML normalization", () => {
"**Review details**\n\nBody **stays**.",
],
["Before<!-- private -->After", "BeforeAfter"],
[
"<details><summary><h3>Important Files Changed</h3></summary>Body</details>",
"**Important Files Changed**\n\nBody",
],
[
"<details><summary><p>First</p><p>Second</p></summary>Body</details>",
"**First Second**\n\nBody",
],
["<span>file.</span>ts", "file.ts"],
['<a href="https://example.com">Git</a>Hub', "[Git](<https://example.com>)Hub"],
["<span>Git</span><span>Hub</span>", "GitHub"],