diff --git a/packages/widgets/src/data/LineChart.test.ts b/packages/widgets/src/data/LineChart.test.ts index 3357529c4..ea6d53c88 100644 --- a/packages/widgets/src/data/LineChart.test.ts +++ b/packages/widgets/src/data/LineChart.test.ts @@ -406,5 +406,41 @@ describe('LineChart', () => { expect(hasBraille).toBe(true); }); }); + + describe('ASCII fallback for axes', () => { + it('uses ASCII pipe for Y-axis separator when caps.unicode is false', async () => { + vi.stubEnv('NO_UNICODE', '1'); + vi.stubEnv('TERM', ''); + vi.resetModules(); + + const lines = await renderLineChart([10, 50, 90], { showYAxis: true }, 20, 5); + const asciiPipeCount = countCharInGrid(lines, '|'); + const unicodePipeCount = countCharInGrid(lines, '│'); + expect(asciiPipeCount).toBeGreaterThan(0); + expect(unicodePipeCount).toBe(0); + }); + + it('uses ASCII dash for X-axis line when caps.unicode is false', async () => { + vi.stubEnv('NO_UNICODE', '1'); + vi.stubEnv('TERM', ''); + vi.resetModules(); + + const lines = await renderLineChart([10, 50, 90], { showXAxis: true }, 20, 5); + const asciiDashCount = countCharInGrid(lines, '-'); + const unicodeDashCount = countCharInGrid(lines, '─'); + expect(asciiDashCount).toBeGreaterThan(0); + expect(unicodeDashCount).toBe(0); + }); + + it('uses ASCII chars for Y-axis tick marks when caps.unicode is false', async () => { + vi.stubEnv('NO_UNICODE', '1'); + vi.stubEnv('TERM', ''); + vi.resetModules(); + + const lines = await renderLineChart([0, 100], { showYAxis: true }, 20, 5); + expect(lines[0]).not.toContain('┤'); + expect(lines[0]).toContain('+'); + }); + }); }); diff --git a/packages/widgets/src/data/LineChart.ts b/packages/widgets/src/data/LineChart.ts index 82ccb721f..772db4520 100644 --- a/packages/widgets/src/data/LineChart.ts +++ b/packages/widgets/src/data/LineChart.ts @@ -105,9 +105,9 @@ export class LineChart extends Widget { const v = plotHeight > 1 ? max - (row / (plotHeight - 1)) * range : max; if (row === 0 || row === plotHeight - 1) { const label = v.toFixed(0).padStart(yAxisWidth - 1, ' '); - screen.writeString(x, y + row, label + '┤', { ...attrs, dim: true }); + screen.writeString(x, y + row, label + (caps.unicode ? '┤' : '+'), { ...attrs, dim: true }); } else { - screen.writeString(x + yAxisWidth - 1, y + row, '│', { ...attrs, dim: true }); + screen.writeString(x + yAxisWidth - 1, y + row, caps.unicode ? '│' : '|', { ...attrs, dim: true }); } } } @@ -157,7 +157,7 @@ export class LineChart extends Widget { const top = Math.min(prevRow, row) + 1; const bottom = Math.max(prevRow, row); for (let r = top; r < bottom; r++) { - screen.setCell(plotX + col, y + r, { char: '│', fg: this._color, dim: true }); + screen.setCell(plotX + col, y + r, { char: caps.unicode ? '│' : '|', fg: this._color, dim: true }); } } @@ -172,10 +172,10 @@ export class LineChart extends Widget { if (this._showXAxis) { const axisY = y + height - 1; for (let col = 0; col < plotWidth; col++) { - screen.setCell(plotX + col, axisY, { char: '─', ...attrs, dim: true }); + screen.setCell(plotX + col, axisY, { char: caps.unicode ? '─' : '-', ...attrs, dim: true }); } if (yAxisWidth > 0) { - screen.setCell(plotX - 1, axisY, { char: '└', ...attrs, dim: true }); + screen.setCell(plotX - 1, axisY, { char: caps.unicode ? '└' : '+', ...attrs, dim: true }); } } } diff --git a/packages/widgets/src/display/Code.test.ts b/packages/widgets/src/display/Code.test.ts index 76a9a5039..c9244efa2 100644 --- a/packages/widgets/src/display/Code.test.ts +++ b/packages/widgets/src/display/Code.test.ts @@ -2,8 +2,8 @@ // @termuijs/widgets — Tests for Code widget // ───────────────────────────────────────────────────── -import { describe, it, expect } from 'vitest'; -import { Screen } from '@termuijs/core'; +import { describe, it, expect, vi } from 'vitest'; +import { Screen, caps } from '@termuijs/core'; import { Code } from './Code.js'; describe('Code', () => { @@ -73,4 +73,13 @@ describe('Code', () => { expect(screen.back[0][3].char).toBe('t'); expect(screen.back[0][4].char).toBe('╮'); // topRight corner (width-1 index) }); + + it('uses ASCII pipe for gutter separator when caps.unicode is false', () => { + vi.spyOn(caps, 'unicode', 'get').mockReturnValue(false); + const code = new Code('hello'); + code.updateRect({ x: 0, y: 0, width: 12, height: 4 }); + const screen = new Screen(12, 4); + code.render(screen); + expect(screen.back[1][2].char).toBe('|'); + }); }); diff --git a/packages/widgets/src/display/Code.ts b/packages/widgets/src/display/Code.ts index 673a1067e..be4d75c81 100644 --- a/packages/widgets/src/display/Code.ts +++ b/packages/widgets/src/display/Code.ts @@ -49,7 +49,7 @@ export class Code extends Widget { screen.writeString(x, y, lineNum, { dim: true }); x += lineNumWidth; - screen.setCell(x, y, { char: '│', dim: true }); + screen.setCell(x, y, { char: caps.unicode ? '│' : '|', dim: true }); x++; screen.setCell(x, y, { char: ' ' }); diff --git a/packages/widgets/src/layout/SplitPane.test.ts b/packages/widgets/src/layout/SplitPane.test.ts index 7bf873652..a270c06d4 100644 --- a/packages/widgets/src/layout/SplitPane.test.ts +++ b/packages/widgets/src/layout/SplitPane.test.ts @@ -119,6 +119,24 @@ describe('SplitPane layout', () => { expect(markDirtySpy).toHaveBeenCalled(); }); + it('vertical split uses ASCII dash for divider when caps.unicode is false', () => { + vi.spyOn(caps, 'unicode', 'get').mockReturnValue(false); + + const left = new Box(); + const right = new Box(); + const pane = new SplitPane(left, right, { width: 10, height: 6 }, { ratio: 0.5, direction: 'vertical' }); + + const node = pane.getLayoutNode(); + computeLayout(node, 10, 6); + pane.syncLayout(); + + const screen = new Screen(10, 6); + pane.render(screen); + + const dividerRow = screen.back[3].map(c => c.char).join(''); + expect(dividerRow).toContain('-'); + }); + describe('mouse drag', () => { function makePane(opts: { ratio?: number; minSize?: number } = {}) { const left = new Box(); diff --git a/packages/widgets/src/layout/SplitPane.ts b/packages/widgets/src/layout/SplitPane.ts index 013f2d1f1..981b4c624 100644 --- a/packages/widgets/src/layout/SplitPane.ts +++ b/packages/widgets/src/layout/SplitPane.ts @@ -219,7 +219,7 @@ export class SplitPane extends Widget { for (let col = 0; col < width; col++) { screen.setCell(col + x, dividerY, { - char: '─', + char: caps.unicode ? '─' : '-', ...attrs, }); }