@mariozechner/pi-tui 0.7.20 → 0.7.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/markdown.d.ts +4 -3
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +46 -59
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/text.d.ts.map +1 -1
- package/dist/components/text.js +28 -41
- package/dist/components/text.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +12 -2
- package/dist/tui.js.map +1 -1
- package/dist/utils.d.ts +24 -14
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +84 -176
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAU;IACjD,8CAA8C;IAC9C,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC;AAAA,CAC/B;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,GAAW,EAAE,GAAW,EAA2C;IAC3F,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;QAC7D,CAAC,EAAE,CAAC;IACL,CAAC;IAED,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO;YACN,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG;SACnB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AAAA,CACZ;AAED;;GAEG;AACH,MAAM,eAAe;IACZ,eAAe,GAAa,EAAE,CAAC;IAEvC;;OAEG;IACH,OAAO,CAAC,QAAgB,EAAQ;QAC/B,+CAA+C;QAC/C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO;QACR,CAAC;QAED,qCAAqC;QACrC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrD,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACP,sBAAsB;YACtB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;IAAA,CACD;IAED;;OAEG;IACH,cAAc,GAAW;QACxB,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAAA,CACrC;IAED;;OAEG;IACH,cAAc,GAAY;QACzB,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAAA,CACvC;IAED;;OAEG;IACH,YAAY,GAAW;QACtB,OAAO,SAAS,CAAC;IAAA,CACjB;CACD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAa,EAAY;IACvE,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,CAAC,EAAE,CAAC,CAAC;IACb,CAAC;IAED,qDAAqD;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,GAAG,sBAAsB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAAA,CACzC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,IAAY,EAAE,KAAa,EAAY;IACtE,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,CAAC,EAAE,CAAC,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,aAAa,IAAI,KAAK,EAAE,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;IAEtC,gFAAgF;IAChF,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAE7C,0FAA0F;QAC1F,IAAI,iBAAiB,GAAG,KAAK,EAAE,CAAC;YAC/B,4BAA4B;YAC5B,IAAI,WAAW,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC5D,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;gBACvC,oBAAoB,GAAG,CAAC,CAAC;YAC1B,CAAC;YAED,sBAAsB;YACtB,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,oBAAoB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACP,mDAAmD;YACnD,MAAM,WAAW,GAAG,oBAAoB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,yCAAyC;YAC/F,MAAM,WAAW,GAAG,oBAAoB,GAAG,WAAW,GAAG,iBAAiB,CAAC;YAE3E,IAAI,WAAW,GAAG,KAAK,EAAE,CAAC;gBACzB,sCAAsC;gBACtC,IAAI,WAAW,EAAE,CAAC;oBACjB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC7D,CAAC;gBACD,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC;gBAC9C,oBAAoB,GAAG,iBAAiB,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACP,oBAAoB;gBACpB,IAAI,oBAAoB,GAAG,CAAC,EAAE,CAAC;oBAC9B,WAAW,IAAI,GAAG,GAAG,IAAI,CAAC;oBAC1B,oBAAoB,IAAI,CAAC,GAAG,iBAAiB,CAAC;gBAC/C,CAAC;qBAAM,CAAC;oBACP,WAAW,IAAI,IAAI,CAAC;oBACpB,oBAAoB,GAAG,iBAAiB,CAAC;gBAC1C,CAAC;YACF,CAAC;YAED,gDAAgD;YAChD,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtC,CAAC;IACF,CAAC;IAED,iBAAiB;IACjB,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAAA,CAC3C;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,IAAY,EAAE,OAAwB,EAAU;IAChF,IAAI,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;QAC9B,OAAO,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,IAAY,EAAE,OAAwB,EAAQ;IAC5E,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC;QACxB,CAAC;aAAM,CAAC;YACP,CAAC,EAAE,CAAC;QACL,CAAC;IACF,CAAC;AAAA,CACD;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,IAAY,EAAY;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErB,sBAAsB;QACtB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,UAAU,EAAE,CAAC;YAChB,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC;YAC/B,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC;YACvB,SAAS;QACV,CAAC;QAED,kCAAkC;QAClC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAClB,IAAI,WAAW,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACxB,WAAW,GAAG,EAAE,CAAC;YAClB,CAAC;YACD,CAAC,EAAE,CAAC;YACJ,SAAS;QACV,CAAC;QAED,oBAAoB;QACpB,WAAW,IAAI,IAAI,CAAC;QACpB,CAAC,EAAE,CAAC;IACL,CAAC;IAED,iBAAiB;IACjB,IAAI,WAAW,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACb;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,IAAY,EAAE,KAAa,EAAE,OAAwB,EAAY;IAC/F,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAC3C,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACxB,sBAAsB;QACtB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,UAAU,EAAE,CAAC;YAChB,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC;YAC/B,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC;YACvB,SAAS;QACV,CAAC;QAED,yCAAyC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,IAAY,CAAC;QACjB,IAAI,cAAsB,CAAC;QAE3B,IAAI,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACvE,gCAAgC;YAChC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,cAAc,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,oBAAoB;YACpB,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACf,cAAc,GAAG,CAAC,CAAC;QACpB,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAErC,oDAAoD;QACpD,IAAI,oBAAoB,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;YAC9C,eAAe;YACf,IAAI,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;gBACjD,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACxB,WAAW,GAAG,EAAE,CAAC;YAClB,CAAC;YACD,oBAAoB,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,WAAW,IAAI,IAAI,CAAC;QACpB,oBAAoB,IAAI,SAAS,CAAC;QAClC,CAAC,IAAI,cAAc,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACb","sourcesContent":["import stringWidth from \"string-width\";\n\n/**\n * Calculate the visible width of a string in terminal columns.\n * This correctly handles:\n * - ANSI escape codes (ignored)\n * - Emojis and wide characters (counted as 2 columns)\n * - Combining characters (counted correctly)\n * - Tabs (replaced with 3 spaces for consistent width)\n */\nexport function visibleWidth(str: string): number {\n\t// Replace tabs with 3 spaces before measuring\n\tconst normalized = str.replace(/\\t/g, \" \");\n\treturn stringWidth(normalized);\n}\n\n/**\n * Extract ANSI escape sequences from a string at the given position.\n * Returns the ANSI code and the length consumed, or null if no ANSI code found.\n */\nfunction extractAnsiCode(str: string, pos: number): { code: string; length: number } | null {\n\tif (pos >= str.length || str[pos] !== \"\\x1b\" || str[pos + 1] !== \"[\") {\n\t\treturn null;\n\t}\n\n\tlet j = pos + 2;\n\twhile (j < str.length && str[j] && !/[mGKHJ]/.test(str[j]!)) {\n\t\tj++;\n\t}\n\n\tif (j < str.length) {\n\t\treturn {\n\t\t\tcode: str.substring(pos, j + 1),\n\t\t\tlength: j + 1 - pos,\n\t\t};\n\t}\n\n\treturn null;\n}\n\n/**\n * Track and manage active ANSI codes for preserving styling across wrapped lines.\n */\nclass AnsiCodeTracker {\n\tprivate activeAnsiCodes: string[] = [];\n\n\t/**\n\t * Process an ANSI code and update the active codes.\n\t */\n\tprocess(ansiCode: string): void {\n\t\t// Check if it's a styling code (ends with 'm')\n\t\tif (!ansiCode.endsWith(\"m\")) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Reset code clears all active codes\n\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\tthis.activeAnsiCodes.length = 0;\n\t\t} else {\n\t\t\t// Add to active codes\n\t\t\tthis.activeAnsiCodes.push(ansiCode);\n\t\t}\n\t}\n\n\t/**\n\t * Get all active ANSI codes as a single string.\n\t */\n\tgetActiveCodes(): string {\n\t\treturn this.activeAnsiCodes.join(\"\");\n\t}\n\n\t/**\n\t * Check if there are any active codes.\n\t */\n\thasActiveCodes(): boolean {\n\t\treturn this.activeAnsiCodes.length > 0;\n\t}\n\n\t/**\n\t * Get the reset code.\n\t */\n\tgetResetCode(): string {\n\t\treturn \"\\x1b[0m\";\n\t}\n}\n\n/**\n * Wrap text lines with word-based wrapping while preserving ANSI escape codes.\n * This function properly handles:\n * - ANSI escape codes (preserved and tracked across lines)\n * - Word-based wrapping (breaks at spaces when possible)\n * - Multi-byte characters (emoji, surrogate pairs)\n * - Newlines within text\n *\n * @param text - The text to wrap (can contain ANSI codes and newlines)\n * @param width - The maximum width in terminal columns\n * @returns Array of wrapped lines with ANSI codes preserved\n */\nexport function wrapTextWithAnsi(text: string, width: number): string[] {\n\tif (!text) {\n\t\treturn [\"\"];\n\t}\n\n\t// Handle newlines by processing each line separately\n\tconst inputLines = text.split(\"\\n\");\n\tconst result: string[] = [];\n\n\tfor (const inputLine of inputLines) {\n\t\tresult.push(...wrapSingleLineWithAnsi(inputLine, width));\n\t}\n\n\treturn result.length > 0 ? result : [\"\"];\n}\n\n/**\n * Wrap a single line (no newlines) with word-based wrapping while preserving ANSI codes.\n */\nfunction wrapSingleLineWithAnsi(line: string, width: number): string[] {\n\tif (!line) {\n\t\treturn [\"\"];\n\t}\n\n\tconst visibleLength = visibleWidth(line);\n\tif (visibleLength <= width) {\n\t\treturn [line];\n\t}\n\n\tconst wrapped: string[] = [];\n\tconst tracker = new AnsiCodeTracker();\n\n\t// First, split the line into words while preserving ANSI codes with their words\n\tconst words = splitIntoWordsWithAnsi(line);\n\n\tlet currentLine = \"\";\n\tlet currentVisibleLength = 0;\n\n\tfor (const word of words) {\n\t\tconst wordVisibleLength = visibleWidth(word);\n\n\t\t// If the word itself is longer than the width, we need to break it character by character\n\t\tif (wordVisibleLength > width) {\n\t\t\t// Flush current line if any\n\t\t\tif (currentLine) {\n\t\t\t\twrapped.push(closeLineAndPrepareNext(currentLine, tracker));\n\t\t\t\tcurrentLine = tracker.getActiveCodes();\n\t\t\t\tcurrentVisibleLength = 0;\n\t\t\t}\n\n\t\t\t// Break the long word\n\t\t\tconst brokenLines = breakLongWordWithAnsi(word, width, tracker);\n\t\t\twrapped.push(...brokenLines.slice(0, -1));\n\t\t\tcurrentLine = brokenLines[brokenLines.length - 1];\n\t\t\tcurrentVisibleLength = visibleWidth(currentLine);\n\t\t} else {\n\t\t\t// Check if adding this word would exceed the width\n\t\t\tconst spaceNeeded = currentVisibleLength > 0 ? 1 : 0; // Space before word if not at line start\n\t\t\tconst totalNeeded = currentVisibleLength + spaceNeeded + wordVisibleLength;\n\n\t\t\tif (totalNeeded > width) {\n\t\t\t\t// Word doesn't fit, wrap to next line\n\t\t\t\tif (currentLine) {\n\t\t\t\t\twrapped.push(closeLineAndPrepareNext(currentLine, tracker));\n\t\t\t\t}\n\t\t\t\tcurrentLine = tracker.getActiveCodes() + word;\n\t\t\t\tcurrentVisibleLength = wordVisibleLength;\n\t\t\t} else {\n\t\t\t\t// Word fits, add it\n\t\t\t\tif (currentVisibleLength > 0) {\n\t\t\t\t\tcurrentLine += \" \" + word;\n\t\t\t\t\tcurrentVisibleLength += 1 + wordVisibleLength;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += word;\n\t\t\t\t\tcurrentVisibleLength = wordVisibleLength;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update tracker with ANSI codes from this word\n\t\t\tupdateTrackerFromText(word, tracker);\n\t\t}\n\t}\n\n\t// Add final line\n\tif (currentLine) {\n\t\twrapped.push(currentLine);\n\t}\n\n\treturn wrapped.length > 0 ? wrapped : [\"\"];\n}\n\n/**\n * Close current line with reset code if needed, and prepare the next line with active codes.\n */\nfunction closeLineAndPrepareNext(line: string, tracker: AnsiCodeTracker): string {\n\tif (tracker.hasActiveCodes()) {\n\t\treturn line + tracker.getResetCode();\n\t}\n\treturn line;\n}\n\n/**\n * Update the ANSI code tracker by scanning through text.\n */\nfunction updateTrackerFromText(text: string, tracker: AnsiCodeTracker): void {\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\ttracker.process(ansiResult.code);\n\t\t\ti += ansiResult.length;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n}\n\n/**\n * Split text into words while keeping ANSI codes attached to their words.\n */\nfunction splitIntoWordsWithAnsi(text: string): string[] {\n\tconst words: string[] = [];\n\tlet currentWord = \"\";\n\tlet i = 0;\n\n\twhile (i < text.length) {\n\t\tconst char = text[i];\n\n\t\t// Check for ANSI code\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\tcurrentWord += ansiResult.code;\n\t\t\ti += ansiResult.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check for space (word boundary)\n\t\tif (char === \" \") {\n\t\t\tif (currentWord) {\n\t\t\t\twords.push(currentWord);\n\t\t\t\tcurrentWord = \"\";\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Regular character\n\t\tcurrentWord += char;\n\t\ti++;\n\t}\n\n\t// Add final word\n\tif (currentWord) {\n\t\twords.push(currentWord);\n\t}\n\n\treturn words;\n}\n\n/**\n * Break a long word that doesn't fit on a single line, character by character.\n */\nfunction breakLongWordWithAnsi(word: string, width: number, tracker: AnsiCodeTracker): string[] {\n\tconst lines: string[] = [];\n\tlet currentLine = tracker.getActiveCodes();\n\tlet currentVisibleLength = 0;\n\tlet i = 0;\n\n\twhile (i < word.length) {\n\t\t// Check for ANSI code\n\t\tconst ansiResult = extractAnsiCode(word, i);\n\t\tif (ansiResult) {\n\t\t\tcurrentLine += ansiResult.code;\n\t\t\ttracker.process(ansiResult.code);\n\t\t\ti += ansiResult.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Get character (handle surrogate pairs)\n\t\tconst codePoint = word.charCodeAt(i);\n\t\tlet char: string;\n\t\tlet charByteLength: number;\n\n\t\tif (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < word.length) {\n\t\t\t// High surrogate - get the pair\n\t\t\tchar = word.substring(i, i + 2);\n\t\t\tcharByteLength = 2;\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tchar = word[i];\n\t\t\tcharByteLength = 1;\n\t\t}\n\n\t\tconst charWidth = visibleWidth(char);\n\n\t\t// Check if adding this character would exceed width\n\t\tif (currentVisibleLength + charWidth > width) {\n\t\t\t// Need to wrap\n\t\t\tif (tracker.hasActiveCodes()) {\n\t\t\t\tlines.push(currentLine + tracker.getResetCode());\n\t\t\t\tcurrentLine = tracker.getActiveCodes();\n\t\t\t} else {\n\t\t\t\tlines.push(currentLine);\n\t\t\t\tcurrentLine = \"\";\n\t\t\t}\n\t\t\tcurrentVisibleLength = 0;\n\t\t}\n\n\t\tcurrentLine += char;\n\t\tcurrentVisibleLength += charWidth;\n\t\ti += charByteLength;\n\t}\n\n\t// Add final line (don't close it, let the caller handle that)\n\tif (currentLine || lines.length === 0) {\n\t\tlines.push(currentLine);\n\t}\n\n\treturn lines;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chalk } from \"chalk\";\nimport stringWidth from \"string-width\";\n\nconst colorChalk = new Chalk({ level: 3 });\n\n/**\n * Calculate the visible width of a string in terminal columns.\n */\nexport function visibleWidth(str: string): number {\n\tconst normalized = str.replace(/\\t/g, \" \");\n\treturn stringWidth(normalized);\n}\n\n/**\n * Extract ANSI escape sequences from a string at the given position.\n */\nfunction extractAnsiCode(str: string, pos: number): { code: string; length: number } | null {\n\tif (pos >= str.length || str[pos] !== \"\\x1b\" || str[pos + 1] !== \"[\") {\n\t\treturn null;\n\t}\n\n\tlet j = pos + 2;\n\twhile (j < str.length && str[j] && !/[mGKHJ]/.test(str[j]!)) {\n\t\tj++;\n\t}\n\n\tif (j < str.length) {\n\t\treturn {\n\t\t\tcode: str.substring(pos, j + 1),\n\t\t\tlength: j + 1 - pos,\n\t\t};\n\t}\n\n\treturn null;\n}\n\n/**\n * Track active ANSI SGR codes to preserve styling across line breaks.\n */\nclass AnsiCodeTracker {\n\tprivate activeAnsiCodes: string[] = [];\n\n\tprocess(ansiCode: string): void {\n\t\tif (!ansiCode.endsWith(\"m\")) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Full reset clears everything\n\t\tif (ansiCode === \"\\x1b[0m\" || ansiCode === \"\\x1b[m\") {\n\t\t\tthis.activeAnsiCodes.length = 0;\n\t\t} else {\n\t\t\tthis.activeAnsiCodes.push(ansiCode);\n\t\t}\n\t}\n\n\tgetActiveCodes(): string {\n\t\treturn this.activeAnsiCodes.join(\"\");\n\t}\n\n\thasActiveCodes(): boolean {\n\t\treturn this.activeAnsiCodes.length > 0;\n\t}\n}\n\nfunction updateTrackerFromText(text: string, tracker: AnsiCodeTracker): void {\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\ttracker.process(ansiResult.code);\n\t\t\ti += ansiResult.length;\n\t\t} else {\n\t\t\ti++;\n\t\t}\n\t}\n}\n\n/**\n * Split text into words while keeping ANSI codes attached.\n */\nfunction splitIntoWordsWithAnsi(text: string): string[] {\n\tconst words: string[] = [];\n\tlet currentWord = \"\";\n\tlet i = 0;\n\n\twhile (i < text.length) {\n\t\tconst char = text[i];\n\n\t\tconst ansiResult = extractAnsiCode(text, i);\n\t\tif (ansiResult) {\n\t\t\tcurrentWord += ansiResult.code;\n\t\t\ti += ansiResult.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \" \") {\n\t\t\tif (currentWord) {\n\t\t\t\twords.push(currentWord);\n\t\t\t\tcurrentWord = \"\";\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrentWord += char;\n\t\ti++;\n\t}\n\n\tif (currentWord) {\n\t\twords.push(currentWord);\n\t}\n\n\treturn words;\n}\n\n/**\n * Wrap text with ANSI codes preserved.\n *\n * ONLY does word wrapping - NO padding, NO background colors.\n * Returns lines where each line is <= width visible chars.\n * Active ANSI codes are preserved across line breaks.\n *\n * @param text - Text to wrap (may contain ANSI codes and newlines)\n * @param width - Maximum visible width per line\n * @returns Array of wrapped lines (NOT padded to width)\n */\nexport function wrapTextWithAnsi(text: string, width: number): string[] {\n\tif (!text) {\n\t\treturn [\"\"];\n\t}\n\n\t// Handle newlines by processing each line separately\n\tconst inputLines = text.split(\"\\n\");\n\tconst result: string[] = [];\n\n\tfor (const inputLine of inputLines) {\n\t\tresult.push(...wrapSingleLine(inputLine, width));\n\t}\n\n\treturn result.length > 0 ? result : [\"\"];\n}\n\nfunction wrapSingleLine(line: string, width: number): string[] {\n\tif (!line) {\n\t\treturn [\"\"];\n\t}\n\n\tconst visibleLength = visibleWidth(line);\n\tif (visibleLength <= width) {\n\t\treturn [line];\n\t}\n\n\tconst wrapped: string[] = [];\n\tconst tracker = new AnsiCodeTracker();\n\tconst words = splitIntoWordsWithAnsi(line);\n\n\tlet currentLine = \"\";\n\tlet currentVisibleLength = 0;\n\n\tfor (const word of words) {\n\t\tconst wordVisibleLength = visibleWidth(word);\n\n\t\t// Check if adding this word would exceed width\n\t\tconst spaceNeeded = currentVisibleLength > 0 ? 1 : 0;\n\t\tconst totalNeeded = currentVisibleLength + spaceNeeded + wordVisibleLength;\n\n\t\tif (totalNeeded > width && currentVisibleLength > 0) {\n\t\t\t// Wrap to next line\n\t\t\twrapped.push(currentLine);\n\t\t\tcurrentLine = tracker.getActiveCodes() + word;\n\t\t\tcurrentVisibleLength = wordVisibleLength;\n\t\t} else {\n\t\t\t// Add to current line\n\t\t\tif (currentVisibleLength > 0) {\n\t\t\t\tcurrentLine += \" \" + word;\n\t\t\t\tcurrentVisibleLength += 1 + wordVisibleLength;\n\t\t\t} else {\n\t\t\t\tcurrentLine += word;\n\t\t\t\tcurrentVisibleLength = wordVisibleLength;\n\t\t\t}\n\t\t}\n\n\t\tupdateTrackerFromText(word, tracker);\n\t}\n\n\tif (currentLine) {\n\t\twrapped.push(currentLine);\n\t}\n\n\treturn wrapped.length > 0 ? wrapped : [\"\"];\n}\n\n/**\n * Apply background color to a line, padding to full width.\n *\n * Handles the tricky case where content contains \\x1b[0m resets that would\n * kill the background color. We reapply the background after any reset.\n *\n * @param line - Line of text (may contain ANSI codes)\n * @param width - Total width to pad to\n * @param bgRgb - Background RGB color\n * @returns Line with background applied and padded to width\n */\nexport function applyBackgroundToLine(line: string, width: number, bgRgb: { r: number; g: number; b: number }): string {\n\tconst bgStart = `\\x1b[48;2;${bgRgb.r};${bgRgb.g};${bgRgb.b}m`;\n\tconst bgEnd = \"\\x1b[49m\";\n\n\t// Calculate padding needed\n\tconst visibleLen = visibleWidth(line);\n\tconst paddingNeeded = Math.max(0, width - visibleLen);\n\tconst padding = \" \".repeat(paddingNeeded);\n\n\t// Strategy: wrap content + padding in background, then fix any 0m resets\n\tconst withPadding = line + padding;\n\tconst withBg = bgStart + withPadding + bgEnd;\n\n\t// Find all \\x1b[0m or \\x1b[49m that would kill background\n\t// Replace with reset + background reapplication\n\tconst fixedBg = withBg.replace(/\\x1b\\[0m/g, `\\x1b[0m${bgStart}`);\n\n\treturn fixedBg;\n}\n"]}
|
package/package.json
CHANGED