From 969696b327823f5a7c05ff31a0602a2f1dfbbfdc Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Wed, 16 Sep 2026 09:05:09 +0800 Subject: [PATCH 1/2] fix(react): avoid empty label segments and duplicate keys --- .changeset/fix-render-label-empty-segments.md | 5 ++ .../ui/utils/__tests__/renderLabel.test.mjs | 63 +++++++++++++++++++ .../react/src/html/ui/utils/renderLabel.jsx | 23 +++++-- 3 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 .changeset/fix-render-label-empty-segments.md create mode 100644 packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs diff --git a/.changeset/fix-render-label-empty-segments.md b/.changeset/fix-render-label-empty-segments.md new file mode 100644 index 000000000..28716a88c --- /dev/null +++ b/.changeset/fix-render-label-empty-segments.md @@ -0,0 +1,5 @@ +--- +'@doc-kit/generator-react': patch +--- + +Avoid rendering empty label segments and ensure repeated label segments use unique keys. diff --git a/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs b/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs new file mode 100644 index 000000000..76dfac560 --- /dev/null +++ b/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs @@ -0,0 +1,63 @@ +import assert from 'node:assert/strict'; +import { mkdtemp, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { describe, it } from 'node:test'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +import { + setConfig, + default as getConfig, +} from '@doc-kit/core/utils/configuration/index.mjs'; + +import { buildServer } from '../../../bundlers/vite.mjs'; + +const output = await mkdtemp(join(tmpdir(), 'doc-kit-render-label-test-')); +const renderLabelModule = await buildServer({ + entry: `export { renderLabel } from ${JSON.stringify( + pathToFileURL(fileURLToPath(new URL('../renderLabel.jsx', import.meta.url))) + .href + )};`, + virtualImports: {}, + outDir: output, + config: await setConfig({ + target: ['html'], + output, + version: 'v22.0.0', + changelog: [], + generators: { + html: {}, + }, + }).then(() => getConfig('html')), +}); +const { renderLabel } = await import(renderLabelModule); + +process.once('exit', () => rm(output, { recursive: true, force: true })); + +describe('renderLabel', () => { + it('does not render elements for empty segments', () => { + const result = renderLabel('`value`'); + + assert.equal(result.length, 3); + assert.equal(result[0], null); + assert.equal(result[1].type, 'code'); + assert.equal(result[2], null); + }); + + it('uses unique keys when segments have the same content', () => { + const result = renderLabel('text `value` text `value`'); + const elements = result.filter(Boolean); + const keys = elements.map(segment => segment.key); + + assert.equal(new Set(keys).size, keys.length); + assert.deepEqual( + elements.map(segment => [segment.type, segment.props.children]), + [ + ['span', 'text '], + ['code', 'value'], + ['span', ' text '], + ['code', 'value'], + ] + ); + }); +}); diff --git a/packages/react/src/html/ui/utils/renderLabel.jsx b/packages/react/src/html/ui/utils/renderLabel.jsx index a7390bc29..38b8f1143 100644 --- a/packages/react/src/html/ui/utils/renderLabel.jsx +++ b/packages/react/src/html/ui/utils/renderLabel.jsx @@ -16,11 +16,22 @@ export const renderLabel = label => { } // Odd-indexed segments sat between a pair of backticks. - return segments.map((segment, index) => - index % 2 ? ( - {segment} + const segmentCounts = new Map(); + + return segments.map((segment, index) => { + if (!segment) { + return null; + } + + const type = index % 2 ? 'code' : 'text'; + const count = (segmentCounts.get(`${type}:${segment}`) ?? 0) + 1; + + segmentCounts.set(`${type}:${segment}`, count); + + return index % 2 ? ( + {segment} ) : ( - {segment} - ) - ); + {segment} + ); + }); }; From 5a052268ee6b0063f79102cca863432d081e3a53 Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Wed, 16 Sep 2026 22:25:11 +0800 Subject: [PATCH 2/2] fix: update --- .../src/html/ui/utils/__tests__/renderLabel.test.mjs | 2 +- packages/react/src/html/ui/utils/renderLabel.jsx | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs b/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs index 76dfac560..e95b890cc 100644 --- a/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs +++ b/packages/react/src/html/ui/utils/__tests__/renderLabel.test.mjs @@ -49,7 +49,7 @@ describe('renderLabel', () => { const elements = result.filter(Boolean); const keys = elements.map(segment => segment.key); - assert.equal(new Set(keys).size, keys.length); + assert.deepEqual(keys, [0, 1, 2, 3]); assert.deepEqual( elements.map(segment => [segment.type, segment.props.children]), [ diff --git a/packages/react/src/html/ui/utils/renderLabel.jsx b/packages/react/src/html/ui/utils/renderLabel.jsx index 38b8f1143..1d3f6bc25 100644 --- a/packages/react/src/html/ui/utils/renderLabel.jsx +++ b/packages/react/src/html/ui/utils/renderLabel.jsx @@ -16,22 +16,15 @@ export const renderLabel = label => { } // Odd-indexed segments sat between a pair of backticks. - const segmentCounts = new Map(); - return segments.map((segment, index) => { if (!segment) { return null; } - const type = index % 2 ? 'code' : 'text'; - const count = (segmentCounts.get(`${type}:${segment}`) ?? 0) + 1; - - segmentCounts.set(`${type}:${segment}`, count); - return index % 2 ? ( - {segment} + {segment} ) : ( - {segment} + {segment} ); }); };