From 80e2b5b20982c855feacfe3aabd87fc6fcc3b7be Mon Sep 17 00:00:00 2001 From: hypercross Date: Thu, 3 Sep 2026 10:39:05 +0800 Subject: [PATCH] fix(yaml/tag): prevent yaml role=tag from being stripped & generalize data-config --- src/cli/completions/block-scanner.ts | 4 ++++ src/cli/completions/variable-system.test.ts | 4 ++++ src/markdown/code-block-yaml-tag.ts | 22 ++++++--------------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/cli/completions/block-scanner.ts b/src/cli/completions/block-scanner.ts index 83e335c..800765e 100644 --- a/src/cli/completions/block-scanner.ts +++ b/src/cli/completions/block-scanner.ts @@ -56,12 +56,16 @@ export function parseBlockAttrs(info: string): BlockAttrs { * Defaults: * - role is set, no explicit as → "none" (strip — it's metadata) * - role=spark-table → "md-table" (render as md-table directive) + * - role=tag → "codeblock" (kept for the marked yaml-tag extension) * - no role, no as → "codeblock" (keep as visible code block) */ export function resolveBlockAs(role: string | undefined, as: string | undefined): string { if (as) return as; // spark-table blocks render as md-table by default if (role === "spark-table") return "md-table"; + // yaml-defined tag blocks must survive stripping so the + // code-block-yaml-tag marked extension can render them + if (role === "tag") return "codeblock"; if (role) return "none"; return "codeblock"; } \ No newline at end of file diff --git a/src/cli/completions/variable-system.test.ts b/src/cli/completions/variable-system.test.ts index a11f5cb..f807ed3 100644 --- a/src/cli/completions/variable-system.test.ts +++ b/src/cli/completions/variable-system.test.ts @@ -269,6 +269,10 @@ describe("resolveBlockAs", () => { expect(resolveBlockAs("spark-table", undefined)).toBe("md-table"); }); + test("defaults to codeblock for tag role", () => { + expect(resolveBlockAs("tag", undefined)).toBe("codeblock"); + }); + test("defaults to codeblock when no role and no as", () => { expect(resolveBlockAs(undefined, undefined)).toBe("codeblock"); }); diff --git a/src/markdown/code-block-yaml-tag.ts b/src/markdown/code-block-yaml-tag.ts index 403fc46..b8bfb64 100644 --- a/src/markdown/code-block-yaml-tag.ts +++ b/src/markdown/code-block-yaml-tag.ts @@ -38,21 +38,13 @@ export default function markedCodeBlockYamlTag(): MarkedExtension { delete (rest as Record).body; } - // A structured `data-config` object is serialized to JSON and - // passed as a single attribute (e.g. md-deck layers/templates). - let configAttr = ""; - if ("data-config" in rest) { - const rawConfig = rest["data-config"]; - delete (rest as Record)["data-config"]; - if (rawConfig !== undefined && rawConfig !== null) { - const json = JSON.stringify(rawConfig).replace(/"/g, """); - configAttr = ` data-config="${json}"`; - } - } - + // `data-*` props may hold structured YAML values, so they are + // serialized to JSON strings (e.g. md-deck layers/templates). const propsStr = Object.entries(rest) .map(([key, value]) => { - const strValue = String(value); + const strValue = key.startsWith("data-") + ? JSON.stringify(value) + : String(value); if (strValue.includes(" ") || strValue.includes('"')) { return `${key}="${strValue.replace(/"/g, """)}"`; } @@ -65,15 +57,13 @@ export default function markedCodeBlockYamlTag(): MarkedExtension { raw: match[0], tagName, props: propsStr, - config: configAttr, content, }; } }, renderer(token: any) { const propsAttr = token.props ? ` ${token.props}` : ""; - const configAttr = token.config || ""; - return `<${token.tagName}${propsAttr}${configAttr}>${token.content || ""}\n`; + return `<${token.tagName}${propsAttr}>${token.content || ""}\n`; }, }, ],