fix: make overlay() ANSI-aware using visible character positions
This commit is contained in:
29
render.ts
29
render.ts
@@ -34,10 +34,33 @@ export function joinText(parts: string[], separator: string): string {
|
|||||||
return parts.filter(Boolean).join(` ${separator} `);
|
return parts.filter(Boolean).join(` ${separator} `);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ANSI-Aware Slice - Extract a substring by visible character positions,
|
||||||
|
// preserving ANSI escape codes that precede visible characters.
|
||||||
|
function ansiSlice(text: string, start: number, end: number): string {
|
||||||
|
let output = "";
|
||||||
|
let visible = 0;
|
||||||
|
for (let i = 0; i < text.length; i++) {
|
||||||
|
if (text[i] === "\x1b") {
|
||||||
|
const match = text.slice(i).match(ANSI_PREFIX_RE);
|
||||||
|
if (match) {
|
||||||
|
if (visible >= start && visible < end) output += match[0];
|
||||||
|
i += match[0].length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (visible >= start && visible < end) output += text[i];
|
||||||
|
visible++;
|
||||||
|
if (visible >= end) break;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
export function overlay(base: string, text: string): string {
|
export function overlay(base: string, text: string): string {
|
||||||
if (visibleWidth(text) >= visibleWidth(base)) return truncate(text, visibleWidth(base));
|
const baseWidth = visibleWidth(base);
|
||||||
const start = Math.max(0, Math.floor((visibleWidth(base) - visibleWidth(text)) / 2));
|
const textWidth = visibleWidth(text);
|
||||||
return `${base.slice(0, start)}${text}${base.slice(start + visibleWidth(text))}`;
|
if (textWidth >= baseWidth) return truncate(text, baseWidth);
|
||||||
|
const start = Math.max(0, Math.floor((baseWidth - textWidth) / 2));
|
||||||
|
return `${ansiSlice(base, 0, start)}${text}${ansiSlice(base, start + textWidth, baseWidth)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dimText(text: string, theme?: any): string {
|
function dimText(text: string, theme?: any): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user