From 1106e9572ac37e55ea356bdd0efc76c735384231 Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Sun, 26 Jul 2026 12:08:23 +0800 Subject: [PATCH 1/3] fix(type-annotations): space union separators in type values --- .../type-annotations/__tests__/remark.test.mjs | 16 +++++++++++++--- src/utils/type-annotations/mdast.mjs | 6 ++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/utils/type-annotations/__tests__/remark.test.mjs b/src/utils/type-annotations/__tests__/remark.test.mjs index 60070c84..3197166f 100644 --- a/src/utils/type-annotations/__tests__/remark.test.mjs +++ b/src/utils/type-annotations/__tests__/remark.test.mjs @@ -28,11 +28,21 @@ describe('remarkTypeAnnotations', () => { it('parses multiple annotations in one paragraph', () => { assert.deepEqual(valuesIn('{string} and {Buffer|Blob} and {integer}'), [ 'string', - 'Buffer|Blob', + 'Buffer | Blob', 'integer', ]); }); + it('spaces union separators, without touching `||`', () => { + assert.deepEqual(valuesIn('Takes {string|URL} or {string | URL}.'), [ + 'string | URL', + 'string | URL', + ]); + assert.deepEqual(valuesIn("Defaults to {req.url || '/'}."), [ + "req.url || '/'", + ]); + }); + it('supports nested braces (object literal types)', () => { assert.deepEqual(valuesIn('Takes {Record} maps.'), [ 'Record', @@ -62,7 +72,7 @@ describe('remarkTypeAnnotations', () => { '| `flag` | {string\\|number} |', ].join('\n'); - assert.deepEqual(valuesIn(markdown), ['string|number']); + assert.deepEqual(valuesIn(markdown), ['string | number']); }); it('normalizes interior line breaks to spaces', () => { @@ -122,6 +132,6 @@ describe('remarkTypeAnnotations', () => { processor.parse('Returns: {Promise} on success.') ); - assert.match(output, /\{Promise\}/); + assert.match(output, /\{Promise\}/); }); }); diff --git a/src/utils/type-annotations/mdast.mjs b/src/utils/type-annotations/mdast.mjs index 203a6b21..2006560d 100644 --- a/src/utils/type-annotations/mdast.mjs +++ b/src/utils/type-annotations/mdast.mjs @@ -10,7 +10,8 @@ const CHARACTER_ESCAPE = /\\([!-/:-@[-`{-~])/g; * `typeAnnotation` tokens into `{ type: 'typeAnnotation', value }` nodes. * * The stored `value` is the canonical, single-line, unescaped TypeScript type - * text; link offsets computed later are relative to it. + * text with union separators spaced (`A | B`); link offsets computed later + * are relative to it. * * @returns {import('mdast-util-from-markdown').Extension} */ @@ -46,7 +47,8 @@ export const typeAnnotationFromMarkdown = () => ({ node.value = node.value .replace(/\s+/g, ' ') .trim() - .replace(CHARACTER_ESCAPE, '$1'); + .replace(CHARACTER_ESCAPE, '$1') + .replace(/(? Date: Sun, 26 Jul 2026 12:18:40 +0800 Subject: [PATCH 2/3] chore: add changeset for spaced union type annotations --- .changeset/spaced-union-types.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spaced-union-types.md diff --git a/.changeset/spaced-union-types.md b/.changeset/spaced-union-types.md new file mode 100644 index 00000000..6c831a97 --- /dev/null +++ b/.changeset/spaced-union-types.md @@ -0,0 +1,5 @@ +--- +'@node-core/doc-kit': patch +--- + +Space union separators in type annotation values (`{string|URL}` is now rendered as `string | URL`). From 3b7034083d1f44250f2549cccdc6b140f5e315af Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Sun, 26 Jul 2026 12:23:00 +0800 Subject: [PATCH 3/3] refactor(type-annotations): extract union separator regex into a const --- src/utils/type-annotations/mdast.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/type-annotations/mdast.mjs b/src/utils/type-annotations/mdast.mjs index 2006560d..eed7a8ae 100644 --- a/src/utils/type-annotations/mdast.mjs +++ b/src/utils/type-annotations/mdast.mjs @@ -5,6 +5,10 @@ // and the mandatory `\|` inside GFM table cells must be decoded here. const CHARACTER_ESCAPE = /\\([!-/:-@[-`{-~])/g; +// A single union separator, with any surrounding whitespace. Lookarounds +// exclude `||` (logical OR in default-value prose). +const UNION_SEPARATOR = /(? ({ .replace(/\s+/g, ' ') .trim() .replace(CHARACTER_ESCAPE, '$1') - .replace(/(?