authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2025-12-25 23:59:02-08:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-14 01:08:16-08:00
logcdbacc656e890b8fccd57bad96a3315cd56635b0
treef8f7f6d9059d4d85a5b3e25c7ded76e948042a67
parentf62bd1c190dd052352816d001adf6cf8c5e274a3
signature Commit is signed but in an unrecognized format.

fix(lib/string/ansi): don't construct `Segmenter` globally

this fixes software like Vite which doesn't apply heavy tree shaking in development, when using it with browsers without the Intl APIs. this hit me when testing my work site in development on a very old Firefox build. resolves #57

1 files changed, 3 insertions(+), 1 deletions(-)

lib/string/ansi.ts+3-1
...@@ -226,6 +226,7 @@ export function debugAnsi(text: string): string {...@@ -226,6 +226,7 @@ export function debugAnsi(text: string): string {
226226
227/** Measure the visible length of a string, ignoring ansi codes. */227/** Measure the visible length of a string, ignoring ansi codes. */
228export function widthInTerminal(str: string): number {228export function widthInTerminal(str: string): number {
229 segmenter ??= new Intl.Segmenter();
229 let width = 0;230 let width = 0;
230 if (str.includes("\x1b")) str = str.replace(ansiEscapes, "");231 if (str.includes("\x1b")) str = str.replace(ansiEscapes, "");
231 for (let i = 0, { length } = str; i < length; i += 1) {232 for (let i = 0, { length } = str; i < length; i += 1) {
...@@ -256,6 +257,7 @@ export function widthInTerminal(str: string): number {...@@ -256,6 +257,7 @@ export function widthInTerminal(str: string): number {
256 */257 */
257// TODO: rename to trimForTerminal258// TODO: rename to trimForTerminal
258export function trimToWidth(str: string, columns: number): string {259export function trimToWidth(str: string, columns: number): string {
260 segmenter ??= new Intl.Segmenter();
259 let width = 0;261 let width = 0;
260 let ansi = false;262 let ansi = false;
261 for (let i = 0, { length } = str; i < length; i += 1) {263 for (let i = 0, { length } = str; i < length; i += 1) {
...@@ -310,7 +312,7 @@ export function trimToWidth(str: string, columns: number): string {...@@ -310,7 +312,7 @@ export function trimToWidth(str: string, columns: number): string {
310// https://github.com/sindresorhus/string-width/blob/42e7b697393a9b9ff732f9bd3ab1db87c3c208b2/index.js312// https://github.com/sindresorhus/string-width/blob/42e7b697393a9b9ff732f9bd3ab1db87c3c208b2/index.js
311// https://github.com/sindresorhus/get-east-asian-width/blob/6aee3824b5e2ade910a38ed93cf9d89b7b5a8e5b/index.js313// https://github.com/sindresorhus/get-east-asian-width/blob/6aee3824b5e2ade910a38ed93cf9d89b7b5a8e5b/index.js
312// MIT license314// MIT license
313const segmenter = /* @__PURE__ */ new Intl.Segmenter();315let segmenter: Intl.Segmenter | null = null;
314const ansiEscapes =316const ansiEscapes =
315 /[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d\/\#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d\/\#&.:=?%@~_]*)*)?(?:\u0007|\u001B\u005C|\u009C))|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;317 /[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d\/\#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d\/\#&.:=?%@~_]*)*)?(?:\u0007|\u001B\u005C|\u009C))|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;
316const zeroWidthClusterRegex =318const zeroWidthClusterRegex =