From 264038e27cb8252aebeed32ce68b8be02e28c11e Mon Sep 17 00:00:00 2001 From: hyper Date: Sat, 12 Sep 2026 23:44:43 +0800 Subject: [PATCH] fix(markdown): keep hyphenated block attribute keys The key pattern \w+ could not cross a hyphen, so data-config=foo was parsed as config=foo and the data- prefix was lost. Allow hyphens in keys, matching parseDirectiveAttrs. --- src/cli/completions/variable-system.test.ts | 10 ++++++++++ src/markdown/block-attrs.ts | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/cli/completions/variable-system.test.ts b/src/cli/completions/variable-system.test.ts index 97bcfbf..d637a87 100644 --- a/src/cli/completions/variable-system.test.ts +++ b/src/cli/completions/variable-system.test.ts @@ -239,6 +239,16 @@ describe("parseBlockAttrs", () => { expect(attrs.extra).toEqual({ foo: "bar", baz: "42" }); }); + test("keeps hyphenated attribute names intact", () => { + const attrs = parseBlockAttrs("yaml role=tag data-config=foo data-src=./x"); + expect(attrs.extra).toEqual({ "data-config": "foo", "data-src": "./x" }); + }); + + test("keeps hyphenated attribute names with quoted values", () => { + const attrs = parseBlockAttrs('yaml role=tag data-config="my config"'); + expect(attrs.extra).toEqual({ "data-config": "my config" }); + }); + test("handles empty info string", () => { const attrs = parseBlockAttrs(""); expect(attrs.lang).toBe(""); diff --git a/src/markdown/block-attrs.ts b/src/markdown/block-attrs.ts index ad434cb..4a3b67f 100644 --- a/src/markdown/block-attrs.ts +++ b/src/markdown/block-attrs.ts @@ -14,10 +14,16 @@ export interface BlockAttrs { extra: Record; } -/** Parse key="value" and key=value pairs from an attribute string. */ +/** + * Parse key="value" and key=value pairs from an attribute string. + * + * Keys may contain hyphens (e.g. `data-config=...`); the key must start with a + * letter or underscore so a leading `-` is treated as part of a value, not a + * key. + */ export function parseBlockAttrs(info: string): BlockAttrs { const attrs: Record = {}; - const re = /(\w+)\s*=\s*("[^"]*"|\S+)/g; + const re = /([A-Za-z_][\w-]*)\s*=\s*("[^"]*"|\S+)/g; let m: RegExpExecArray | null; while ((m = re.exec(info)) !== null) { attrs[m[1]] = m[2].replace(/^"|"$/g, "");