From cfbd567628e2a9dbbf3f89f85fc445a5ff4590ad Mon Sep 17 00:00:00 2001 From: Shawn Koh Date: Tue, 11 Aug 2026 01:19:54 +0800 Subject: [PATCH] fix: preserve punctuation label colors --- .../test/modes/theme/mermaid-rendering.test.ts | 4 ++++ .../utils/src/vendor/mermaid-ascii/ascii/draw.ts | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/test/modes/theme/mermaid-rendering.test.ts b/packages/coding-agent/test/modes/theme/mermaid-rendering.test.ts index 25173ab3e..d86bb48f5 100644 --- a/packages/coding-agent/test/modes/theme/mermaid-rendering.test.ts +++ b/packages/coding-agent/test/modes/theme/mermaid-rendering.test.ts @@ -76,6 +76,10 @@ describe("Mermaid rendering setting", () => { expect(rendered).not.toMatch(/\x1b\[38;2;229;229;231m[╔═╗║╚╝]/); expect(rendered).not.toContain("\x1b[38;2;42;48;56m"); expect(rendered).not.toContain("\x1b[38;2;31;37;45m"); + const labels = renderer("flowchart TD\n A[x=y]\n B[status=#1]", 80); + const text = "\x1b[38;2;229;229;231m"; + expect(labels).toContain(`${text}x=y`); + expect(labels).toContain(`${text}status=#1`); } finally { setThemeInstance(dark); } diff --git a/packages/utils/src/vendor/mermaid-ascii/ascii/draw.ts b/packages/utils/src/vendor/mermaid-ascii/ascii/draw.ts index d849d3670..1cefc6c49 100644 --- a/packages/utils/src/vendor/mermaid-ascii/ascii/draw.ts +++ b/packages/utils/src/vendor/mermaid-ascii/ascii/draw.ts @@ -1225,15 +1225,18 @@ function fillRolesFromCanvases( /** * Special handling for node boxes: border chars get 'border' role, text gets 'text' role. - * Detects text by checking if character is alphanumeric or common punctuation. + * Common final-state border characters (`#` and `=`) count only on the outer edge, + * so identical characters inside ordinary node labels retain the text role. */ function fillRolesForNodeBox( roleCanvas: RoleCanvas, canvas: Canvas, offset: DrawingCoord, ): void { - const isBorderChar = (c: string) => /^[┌┐└┘├┤┬┴┼│─╭╮╰╯╔╗╚╝═║+\-|.':#=‖]$/.test(c) - + const isBorderChar = (c: string) => /^[┌┐└┘├┤┬┴┼│─╭╮╰╯+\-|.':]$/.test(c) + const isStateEndBorderChar = (c: string) => /^[╔╗╚╝═║#=‖]$/.test(c) + const maxX = canvas.length - 1 + const maxY = (canvas[0]?.length ?? 1) - 1 for (let x = 0; x < canvas.length; x++) { for (let y = 0; y < (canvas[0]?.length ?? 0); y++) { const char = canvas[x]?.[y] @@ -1242,7 +1245,9 @@ function fillRolesForNodeBox( const ry = y + offset.y // Use setRole which auto-expands the role canvas if needed if (rx >= 0 && ry >= 0) { - setRole(roleCanvas, rx, ry, isBorderChar(char) ? 'border' : 'text') + const isOuterEdge = x === 0 || x === maxX || y === 0 || y === maxY + const role = isBorderChar(char) || (isOuterEdge && isStateEndBorderChar(char)) ? 'border' : 'text' + setRole(roleCanvas, rx, ry, role) } } }