Files
vue-tui/packages/runtime-tests/integration/paint/output-emoji.test.tsx
T
Yunfei He 957d30f43a feat: rewrite Output class with StyledChar[][] grid for correct emoji/wide char handling
Port Ink's output character model using @alcalzone/ansi-tokenize. Each cell is now a
StyledChar with proper grapheme clustering. Fixes emoji alignment, wide char boundaries,
and changes clipping to top-only (matching Ink). Upgraded ansi-tokenize to ^0.3.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:19:50 +08:00

50 lines
1.8 KiB
TypeScript

import { defineComponent } from "vue";
import { describe, test, expect } from "vite-plus/test";
import { render } from "@vue-tui/testing";
import { Box, Text } from "@vue-tui/runtime";
describe("Output character model", () => {
test("variation selector emoji characters align correctly within borders", async () => {
const App = defineComponent(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
<Text>🌡️⚠️✅</Text>
</Box>
));
const { lastFrame } = await render(App, { columns: 100 });
const frame = lastFrame()!;
const lines = frame.split("\n");
// The text line (line 1) must have a closing right border "│"
// With the old placeLine implementation, variation selector emojis
// miscount visual width and the right border is lost.
expect(lines[1]).toContain("│");
expect(lines[1]!.endsWith("│")).toBe(true);
});
test("wide CJK characters occupy two cells", async () => {
const App = defineComponent(() => () => (
<Box borderStyle="single" width={8}>
<Text>你好世</Text>
</Box>
));
const { lastFrame } = await render(App, { columns: 100 });
const frame = lastFrame()!;
const lines = frame.split("\n");
expect(lines[1]!.endsWith("│")).toBe(true);
});
test("simple emoji characters align within borders", async () => {
const App = defineComponent(() => () => (
<Box borderStyle="round" alignSelf="flex-start">
<Text>🦾🌏😋</Text>
</Box>
));
const { lastFrame } = await render(App, { columns: 100 });
const frame = lastFrame()!;
const lines = frame.split("\n");
// All lines must end with the right border character
expect(lines[0]!.endsWith("╮")).toBe(true);
expect(lines[1]!.endsWith("│")).toBe(true);
expect(lines[2]!.endsWith("╯")).toBe(true);
});
});