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}
);
});
};