@logtape/pretty 1.0.0-dev.231 → 1.0.0-dev.232

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.
@@ -1 +1 @@
1
- {"version":3,"file":"wcwidth.js","names":["text: string","code: number"],"sources":["../wcwidth.ts"],"sourcesContent":["/**\n * @fileoverview\n * wcwidth implementation for JavaScript/TypeScript\n *\n * This module provides functions to calculate the display width of Unicode\n * characters and strings in terminal/monospace contexts, compatible with\n * the Python wcwidth library and POSIX wcwidth() standard.\n *\n * Based on Unicode 15.1.0 character width tables.\n */\n\n/**\n * Remove all ANSI escape sequences from a string.\n *\n * @param text The string to clean\n * @returns String with ANSI escape sequences removed\n */\nexport function stripAnsi(text: string): string {\n return text.replace(/\\[[0-9;]*m/g, \"\");\n}\n\n/**\n * Calculate the display width of a string, ignoring ANSI escape codes\n * and accounting for Unicode character widths using wcwidth-compatible logic.\n *\n * @param text The string to measure\n * @returns The display width in terminal columns\n */\nexport function getDisplayWidth(text: string): number {\n // Remove all ANSI escape sequences first\n const cleanText = stripAnsi(text);\n\n if (cleanText.length === 0) return 0;\n\n let width = 0;\n let i = 0;\n\n // Process character by character, handling surrogate pairs and combining characters\n while (i < cleanText.length) {\n const code = cleanText.codePointAt(i);\n if (code === undefined) {\n i++;\n continue;\n }\n\n const charWidth = wcwidth(code);\n if (charWidth >= 0) {\n width += charWidth;\n }\n\n // Move to next code point (handles surrogate pairs)\n i += (code > 0xFFFF) ? 2 : 1;\n }\n\n return width;\n}\n\n/**\n * Get the display width of a single Unicode code point.\n * Based on wcwidth implementation - returns:\n * -1: Non-printable/control character\n * 0: Zero-width character (combining marks, etc.)\n * 1: Normal width character\n * 2: Wide character (East Asian, emoji, etc.)\n *\n * @param code Unicode code point\n * @returns Display width (-1, 0, 1, or 2)\n */\nexport function wcwidth(code: number): number {\n // C0 and C1 control characters\n if (code < 32 || (code >= 0x7F && code < 0xA0)) {\n return -1;\n }\n\n // Zero-width characters (based on wcwidth table_zero.py)\n if (isZeroWidth(code)) {\n return 0;\n }\n\n // Wide characters (based on wcwidth table_wide.py)\n if (isWideCharacter(code)) {\n return 2;\n }\n\n return 1;\n}\n\n/**\n * Check if a character is zero-width (combining marks, etc.)\n * Based on wcwidth's zero-width table.\n *\n * @param code Unicode code point\n * @returns True if the character has zero display width\n */\nfunction isZeroWidth(code: number): boolean {\n return (\n // Combining Diacritical Marks\n (code >= 0x0300 && code <= 0x036F) ||\n // Hebrew combining marks\n (code >= 0x0483 && code <= 0x0489) ||\n // Arabic combining marks\n (code >= 0x0591 && code <= 0x05BD) ||\n code === 0x05BF ||\n (code >= 0x05C1 && code <= 0x05C2) ||\n (code >= 0x05C4 && code <= 0x05C5) ||\n code === 0x05C7 ||\n // More Arabic combining marks\n (code >= 0x0610 && code <= 0x061A) ||\n (code >= 0x064B && code <= 0x065F) ||\n code === 0x0670 ||\n (code >= 0x06D6 && code <= 0x06DC) ||\n (code >= 0x06DF && code <= 0x06E4) ||\n (code >= 0x06E7 && code <= 0x06E8) ||\n (code >= 0x06EA && code <= 0x06ED) ||\n code === 0x0711 ||\n (code >= 0x0730 && code <= 0x074A) ||\n (code >= 0x07A6 && code <= 0x07B0) ||\n (code >= 0x07EB && code <= 0x07F3) ||\n code === 0x07FD ||\n // Various other combining marks\n (code >= 0x0816 && code <= 0x0819) ||\n (code >= 0x081B && code <= 0x0823) ||\n (code >= 0x0825 && code <= 0x0827) ||\n (code >= 0x0829 && code <= 0x082D) ||\n (code >= 0x0859 && code <= 0x085B) ||\n (code >= 0x08D3 && code <= 0x08E1) ||\n (code >= 0x08E3 && code <= 0x0902) ||\n code === 0x093A ||\n code === 0x093C ||\n (code >= 0x0941 && code <= 0x0948) ||\n code === 0x094D ||\n (code >= 0x0951 && code <= 0x0957) ||\n (code >= 0x0962 && code <= 0x0963) ||\n code === 0x0981 ||\n code === 0x09BC ||\n (code >= 0x09C1 && code <= 0x09C4) ||\n code === 0x09CD ||\n (code >= 0x09E2 && code <= 0x09E3) ||\n (code >= 0x09FE && code <= 0x09FE) ||\n (code >= 0x0A01 && code <= 0x0A02) ||\n code === 0x0A3C ||\n (code >= 0x0A41 && code <= 0x0A42) ||\n (code >= 0x0A47 && code <= 0x0A48) ||\n (code >= 0x0A4B && code <= 0x0A4D) ||\n code === 0x0A51 ||\n (code >= 0x0A70 && code <= 0x0A71) ||\n code === 0x0A75 ||\n (code >= 0x0A81 && code <= 0x0A82) ||\n code === 0x0ABC ||\n (code >= 0x0AC1 && code <= 0x0AC5) ||\n (code >= 0x0AC7 && code <= 0x0AC8) ||\n code === 0x0ACD ||\n (code >= 0x0AE2 && code <= 0x0AE3) ||\n (code >= 0x0AFA && code <= 0x0AFF) ||\n code === 0x0B01 ||\n code === 0x0B3C ||\n code === 0x0B3F ||\n (code >= 0x0B41 && code <= 0x0B44) ||\n code === 0x0B4D ||\n (code >= 0x0B55 && code <= 0x0B56) ||\n (code >= 0x0B62 && code <= 0x0B63) ||\n code === 0x0B82 ||\n code === 0x0BC0 ||\n code === 0x0BCD ||\n code === 0x0C00 ||\n code === 0x0C04 ||\n (code >= 0x0C3E && code <= 0x0C40) ||\n (code >= 0x0C46 && code <= 0x0C48) ||\n (code >= 0x0C4A && code <= 0x0C4D) ||\n (code >= 0x0C55 && code <= 0x0C56) ||\n (code >= 0x0C62 && code <= 0x0C63) ||\n code === 0x0C81 ||\n code === 0x0CBC ||\n code === 0x0CBF ||\n code === 0x0CC6 ||\n (code >= 0x0CCC && code <= 0x0CCD) ||\n (code >= 0x0CE2 && code <= 0x0CE3) ||\n (code >= 0x0D00 && code <= 0x0D01) ||\n (code >= 0x0D3B && code <= 0x0D3C) ||\n code === 0x0D41 ||\n (code >= 0x0D44 && code <= 0x0D44) ||\n code === 0x0D4D ||\n (code >= 0x0D62 && code <= 0x0D63) ||\n code === 0x0D81 ||\n code === 0x0DCA ||\n (code >= 0x0DD2 && code <= 0x0DD4) ||\n code === 0x0DD6 ||\n code === 0x0E31 ||\n (code >= 0x0E34 && code <= 0x0E3A) ||\n (code >= 0x0E47 && code <= 0x0E4E) ||\n code === 0x0EB1 ||\n (code >= 0x0EB4 && code <= 0x0EBC) ||\n (code >= 0x0EC8 && code <= 0x0ECD) ||\n (code >= 0x0F18 && code <= 0x0F19) ||\n code === 0x0F35 ||\n code === 0x0F37 ||\n code === 0x0F39 ||\n (code >= 0x0F71 && code <= 0x0F7E) ||\n (code >= 0x0F80 && code <= 0x0F84) ||\n (code >= 0x0F86 && code <= 0x0F87) ||\n (code >= 0x0F8D && code <= 0x0F97) ||\n (code >= 0x0F99 && code <= 0x0FBC) ||\n code === 0x0FC6 ||\n (code >= 0x102D && code <= 0x1030) ||\n (code >= 0x1032 && code <= 0x1037) ||\n (code >= 0x1039 && code <= 0x103A) ||\n (code >= 0x103D && code <= 0x103E) ||\n (code >= 0x1058 && code <= 0x1059) ||\n (code >= 0x105E && code <= 0x1060) ||\n (code >= 0x1071 && code <= 0x1074) ||\n code === 0x1082 ||\n (code >= 0x1085 && code <= 0x1086) ||\n code === 0x108D ||\n code === 0x109D ||\n (code >= 0x135D && code <= 0x135F) ||\n (code >= 0x1712 && code <= 0x1714) ||\n (code >= 0x1732 && code <= 0x1734) ||\n (code >= 0x1752 && code <= 0x1753) ||\n (code >= 0x1772 && code <= 0x1773) ||\n (code >= 0x17B4 && code <= 0x17B5) ||\n (code >= 0x17B7 && code <= 0x17BD) ||\n code === 0x17C6 ||\n (code >= 0x17C9 && code <= 0x17D3) ||\n code === 0x17DD ||\n (code >= 0x180B && code <= 0x180D) ||\n (code >= 0x1885 && code <= 0x1886) ||\n code === 0x18A9 ||\n (code >= 0x1920 && code <= 0x1922) ||\n (code >= 0x1927 && code <= 0x1928) ||\n code === 0x1932 ||\n (code >= 0x1939 && code <= 0x193B) ||\n (code >= 0x1A17 && code <= 0x1A18) ||\n code === 0x1A1B ||\n code === 0x1A56 ||\n (code >= 0x1A58 && code <= 0x1A5E) ||\n code === 0x1A60 ||\n code === 0x1A62 ||\n (code >= 0x1A65 && code <= 0x1A6C) ||\n (code >= 0x1A73 && code <= 0x1A7C) ||\n code === 0x1A7F ||\n (code >= 0x1AB0 && code <= 0x1ABE) ||\n (code >= 0x1B00 && code <= 0x1B03) ||\n code === 0x1B34 ||\n (code >= 0x1B36 && code <= 0x1B3A) ||\n code === 0x1B3C ||\n code === 0x1B42 ||\n (code >= 0x1B6B && code <= 0x1B73) ||\n (code >= 0x1B80 && code <= 0x1B81) ||\n (code >= 0x1BA2 && code <= 0x1BA5) ||\n (code >= 0x1BA8 && code <= 0x1BA9) ||\n (code >= 0x1BAB && code <= 0x1BAD) ||\n code === 0x1BE6 ||\n (code >= 0x1BE8 && code <= 0x1BE9) ||\n code === 0x1BED ||\n (code >= 0x1BEF && code <= 0x1BF1) ||\n (code >= 0x1C2C && code <= 0x1C33) ||\n (code >= 0x1C36 && code <= 0x1C37) ||\n (code >= 0x1CD0 && code <= 0x1CD2) ||\n (code >= 0x1CD4 && code <= 0x1CE0) ||\n (code >= 0x1CE2 && code <= 0x1CE8) ||\n code === 0x1CED ||\n code === 0x1CF4 ||\n (code >= 0x1CF8 && code <= 0x1CF9) ||\n (code >= 0x1DC0 && code <= 0x1DF9) ||\n (code >= 0x1DFB && code <= 0x1DFF) ||\n (code >= 0x200B && code <= 0x200F) || // Zero-width spaces\n (code >= 0x202A && code <= 0x202E) || // Bidirectional format characters\n (code >= 0x2060 && code <= 0x2064) || // Word joiner, etc.\n (code >= 0x2066 && code <= 0x206F) || // More bidirectional\n code === 0xFEFF || // Zero-width no-break space\n (code >= 0xFE00 && code <= 0xFE0F) || // Variation selectors\n (code >= 0xFE20 && code <= 0xFE2F) // Combining half marks\n );\n}\n\n/**\n * Check if a character code point represents a wide character.\n * Based on wcwidth's wide character table (selected ranges from Unicode 15.1.0).\n *\n * @param code Unicode code point\n * @returns True if the character has width 2\n */\nfunction isWideCharacter(code: number): boolean {\n return (\n // Based on wcwidth table_wide.py for Unicode 15.1.0\n (code >= 0x1100 && code <= 0x115F) || // Hangul Jamo\n (code >= 0x231A && code <= 0x231B) || // Watch, Hourglass\n (code >= 0x2329 && code <= 0x232A) || // Angle brackets\n (code >= 0x23E9 && code <= 0x23EC) || // Media controls\n code === 0x23F0 || code === 0x23F3 || // Alarm clock, hourglass\n (code >= 0x25FD && code <= 0x25FE) || // Small squares\n (code >= 0x2614 && code <= 0x2615) || // Umbrella, coffee\n (code >= 0x2648 && code <= 0x2653) || // Zodiac signs\n code === 0x267F || code === 0x2693 || // Wheelchair, anchor\n code === 0x26A0 || code === 0x26A1 || code === 0x26AA || code === 0x26AB || // Warning, lightning, circles\n (code >= 0x26BD && code <= 0x26BE) || // Sports balls\n (code >= 0x26C4 && code <= 0x26C5) || // Weather\n code === 0x26CE || code === 0x26D4 || // Ophiuchus, no entry\n (code >= 0x26EA && code <= 0x26EA) || // Church\n (code >= 0x26F2 && code <= 0x26F3) || // Fountain, golf\n code === 0x26F5 || code === 0x26FA || // Sailboat, tent\n code === 0x26FD || // Gas pump\n (code >= 0x2705 && code <= 0x2705) || // Check mark\n (code >= 0x270A && code <= 0x270B) || // Raised fists\n code === 0x2728 || // Sparkles (✨)\n code === 0x274C || // Cross mark (❌)\n code === 0x274E || // Cross mark button\n (code >= 0x2753 && code <= 0x2755) || // Question marks\n code === 0x2757 || // Exclamation\n (code >= 0x2795 && code <= 0x2797) || // Plus signs\n code === 0x27B0 || code === 0x27BF || // Curly loop, double curly loop\n (code >= 0x2B1B && code <= 0x2B1C) || // Large squares\n code === 0x2B50 || code === 0x2B55 || // Star, circle\n (code >= 0x2E80 && code <= 0x2E99) || // CJK Radicals Supplement\n (code >= 0x2E9B && code <= 0x2EF3) ||\n (code >= 0x2F00 && code <= 0x2FD5) || // Kangxi Radicals\n (code >= 0x2FF0 && code <= 0x2FFB) || // Ideographic Description Characters\n (code >= 0x3000 && code <= 0x303E) || // CJK Symbols and Punctuation\n (code >= 0x3041 && code <= 0x3096) || // Hiragana\n (code >= 0x3099 && code <= 0x30FF) || // Katakana\n (code >= 0x3105 && code <= 0x312F) || // Bopomofo\n (code >= 0x3131 && code <= 0x318E) || // Hangul Compatibility Jamo\n (code >= 0x3190 && code <= 0x31E3) || // Various CJK\n (code >= 0x31F0 && code <= 0x321E) || // Katakana Phonetic Extensions\n (code >= 0x3220 && code <= 0x3247) || // Enclosed CJK Letters and Months\n (code >= 0x3250 && code <= 0x4DBF) || // Various CJK\n (code >= 0x4E00 && code <= 0x9FFF) || // CJK Unified Ideographs\n (code >= 0xA960 && code <= 0xA97F) || // Hangul Jamo Extended-A\n (code >= 0xAC00 && code <= 0xD7A3) || // Hangul Syllables\n (code >= 0xD7B0 && code <= 0xD7C6) || // Hangul Jamo Extended-B\n (code >= 0xF900 && code <= 0xFAFF) || // CJK Compatibility Ideographs\n (code >= 0xFE10 && code <= 0xFE19) || // Vertical Forms\n (code >= 0xFE30 && code <= 0xFE6F) || // CJK Compatibility Forms\n (code >= 0xFF00 && code <= 0xFF60) || // Fullwidth Forms\n (code >= 0xFFE0 && code <= 0xFFE6) || // Fullwidth Forms\n (code >= 0x16FE0 && code <= 0x16FE4) || // Tangut\n (code >= 0x16FF0 && code <= 0x16FF1) ||\n (code >= 0x17000 && code <= 0x187F7) || // Tangut\n (code >= 0x18800 && code <= 0x18CD5) || // Tangut Components\n (code >= 0x18D00 && code <= 0x18D08) || // Tangut Supplement\n (code >= 0x1AFF0 && code <= 0x1AFF3) ||\n (code >= 0x1AFF5 && code <= 0x1AFFB) ||\n (code >= 0x1AFFD && code <= 0x1AFFE) ||\n (code >= 0x1B000 && code <= 0x1B122) || // Kana Extended-A/Supplement\n (code >= 0x1B150 && code <= 0x1B152) ||\n (code >= 0x1B164 && code <= 0x1B167) ||\n (code >= 0x1B170 && code <= 0x1B2FB) ||\n code === 0x1F004 || // Mahjong Red Dragon\n code === 0x1F0CF || // Playing Card Black Joker\n (code >= 0x1F18E && code <= 0x1F18E) || // AB Button\n (code >= 0x1F191 && code <= 0x1F19A) || // Various squared symbols\n (code >= 0x1F1E6 && code <= 0x1F1FF) || // Regional Indicator Symbols (flags)\n (code >= 0x1F200 && code <= 0x1F202) || // Squared symbols\n (code >= 0x1F210 && code <= 0x1F23B) || // Squared CJK\n (code >= 0x1F240 && code <= 0x1F248) || // Tortoise shell bracketed\n (code >= 0x1F250 && code <= 0x1F251) || // Circled ideographs\n (code >= 0x1F260 && code <= 0x1F265) ||\n (code >= 0x1F300 && code <= 0x1F6D7) || // Large emoji block\n (code >= 0x1F6E0 && code <= 0x1F6EC) ||\n (code >= 0x1F6F0 && code <= 0x1F6FC) ||\n (code >= 0x1F700 && code <= 0x1F773) ||\n (code >= 0x1F780 && code <= 0x1F7D8) ||\n (code >= 0x1F7E0 && code <= 0x1F7EB) ||\n (code >= 0x1F7F0 && code <= 0x1F7F0) ||\n (code >= 0x1F800 && code <= 0x1F80B) ||\n (code >= 0x1F810 && code <= 0x1F847) ||\n (code >= 0x1F850 && code <= 0x1F859) ||\n (code >= 0x1F860 && code <= 0x1F887) ||\n (code >= 0x1F890 && code <= 0x1F8AD) ||\n (code >= 0x1F8B0 && code <= 0x1F8B1) ||\n (code >= 0x1F900 && code <= 0x1FA53) || // Supplemental symbols and pictographs\n (code >= 0x1FA60 && code <= 0x1FA6D) ||\n (code >= 0x1FA70 && code <= 0x1FA7C) ||\n (code >= 0x1FA80 && code <= 0x1FA88) ||\n (code >= 0x1FA90 && code <= 0x1FABD) ||\n (code >= 0x1FABF && code <= 0x1FAC5) ||\n (code >= 0x1FACE && code <= 0x1FADB) ||\n (code >= 0x1FAE0 && code <= 0x1FAE8) ||\n (code >= 0x1FAF0 && code <= 0x1FAF8) ||\n (code >= 0x20000 && code <= 0x2FFFD) || // CJK Extension B\n (code >= 0x30000 && code <= 0x3FFFD) // CJK Extension C\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,UAAUA,MAAsB;AAC9C,QAAO,KAAK,QAAQ,eAAe,GAAG;AACvC;;;;;;;;AASD,SAAgB,gBAAgBA,MAAsB;CAEpD,MAAM,YAAY,UAAU,KAAK;AAEjC,KAAI,UAAU,WAAW,EAAG,QAAO;CAEnC,IAAI,QAAQ;CACZ,IAAI,IAAI;AAGR,QAAO,IAAI,UAAU,QAAQ;EAC3B,MAAM,OAAO,UAAU,YAAY,EAAE;AACrC,MAAI,iBAAoB;AACtB;AACA;EACD;EAED,MAAM,YAAY,QAAQ,KAAK;AAC/B,MAAI,aAAa,EACf,UAAS;AAIX,OAAM,OAAO,QAAU,IAAI;CAC5B;AAED,QAAO;AACR;;;;;;;;;;;;AAaD,SAAgB,QAAQC,MAAsB;AAE5C,KAAI,OAAO,MAAO,QAAQ,OAAQ,OAAO,IACvC,QAAO;AAIT,KAAI,YAAY,KAAK,CACnB,QAAO;AAIT,KAAI,gBAAgB,KAAK,CACvB,QAAO;AAGT,QAAO;AACR;;;;;;;;AASD,SAAS,YAAYA,MAAuB;AAC1C,QAEG,QAAQ,OAAU,QAAQ,OAE1B,QAAQ,QAAU,QAAQ,QAE1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAER,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAER,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACT,SAAS,QACT,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACT,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACT,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAA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C3B,QAAQ,UAAW,QAAQ,UAC5B,SAAS,UACT,SAAS,UACR,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ;AAE/B"}
1
+ {"version":3,"file":"wcwidth.js","names":["text: string","code: number","ZERO_WIDTH_RANGES: Array<[number, number]>","ranges: Array<[number, number]>"],"sources":["../wcwidth.ts"],"sourcesContent":["/**\n * @fileoverview\n * wcwidth implementation for JavaScript/TypeScript\n *\n * This module provides functions to calculate the display width of Unicode\n * characters and strings in terminal/monospace contexts, compatible with\n * the Python wcwidth library and POSIX wcwidth() standard.\n *\n * Based on Unicode 15.1.0 character width tables.\n */\n\n// Pre-compiled regex for ANSI escape sequences\n// deno-lint-ignore no-control-regex\nconst ANSI_PATTERN = /\\x1b\\[[0-9;]*m/g;\n\n/**\n * Remove all ANSI escape sequences from a string.\n *\n * @param text The string to clean\n * @returns String with ANSI escape sequences removed\n */\nexport function stripAnsi(text: string): string {\n return text.replace(ANSI_PATTERN, \"\");\n}\n\n/**\n * Calculate the display width of a string, ignoring ANSI escape codes\n * and accounting for Unicode character widths using wcwidth-compatible logic.\n *\n * @param text The string to measure\n * @returns The display width in terminal columns\n */\nexport function getDisplayWidth(text: string): number {\n // Remove all ANSI escape sequences first\n const cleanText = stripAnsi(text);\n\n if (cleanText.length === 0) return 0;\n\n let width = 0;\n let i = 0;\n\n // Process character by character, handling surrogate pairs and combining characters\n while (i < cleanText.length) {\n const code = cleanText.codePointAt(i);\n if (code === undefined) {\n i++;\n continue;\n }\n\n const charWidth = wcwidth(code);\n if (charWidth >= 0) {\n width += charWidth;\n }\n\n // Move to next code point (handles surrogate pairs)\n i += (code > 0xFFFF) ? 2 : 1;\n }\n\n return width;\n}\n\n/**\n * Get the display width of a single Unicode code point.\n * Based on wcwidth implementation - returns:\n * -1: Non-printable/control character\n * 0: Zero-width character (combining marks, etc.)\n * 1: Normal width character\n * 2: Wide character (East Asian, emoji, etc.)\n *\n * @param code Unicode code point\n * @returns Display width (-1, 0, 1, or 2)\n */\nexport function wcwidth(code: number): number {\n // C0 and C1 control characters\n if (code < 32 || (code >= 0x7F && code < 0xA0)) {\n return -1;\n }\n\n // Zero-width characters (based on wcwidth table_zero.py)\n if (isZeroWidth(code)) {\n return 0;\n }\n\n // Wide characters (based on wcwidth table_wide.py)\n if (isWideCharacter(code)) {\n return 2;\n }\n\n return 1;\n}\n\n// Zero-width character ranges (sorted for binary search)\nconst ZERO_WIDTH_RANGES: Array<[number, number]> = [\n [0x0300, 0x036F], // Combining Diacritical Marks\n [0x0483, 0x0489], // Hebrew combining marks\n [0x0591, 0x05BD], // Arabic combining marks\n [0x05C1, 0x05C2],\n [0x05C4, 0x05C5],\n [0x0610, 0x061A], // More Arabic combining marks\n [0x064B, 0x065F],\n [0x06D6, 0x06DC],\n [0x06DF, 0x06E4],\n [0x06E7, 0x06E8],\n [0x06EA, 0x06ED],\n [0x0730, 0x074A],\n [0x07A6, 0x07B0],\n [0x07EB, 0x07F3],\n [0x0816, 0x0819],\n [0x081B, 0x0823],\n [0x0825, 0x0827],\n [0x0829, 0x082D],\n [0x0859, 0x085B],\n [0x08D3, 0x08E1],\n [0x08E3, 0x0902],\n [0x0941, 0x0948],\n [0x0951, 0x0957],\n [0x0962, 0x0963],\n [0x09C1, 0x09C4],\n [0x09E2, 0x09E3],\n [0x0A01, 0x0A02],\n [0x0A41, 0x0A42],\n [0x0A47, 0x0A48],\n [0x0A4B, 0x0A4D],\n [0x0A70, 0x0A71],\n [0x0A81, 0x0A82],\n [0x0AC1, 0x0AC5],\n [0x0AC7, 0x0AC8],\n [0x0AE2, 0x0AE3],\n [0x0AFA, 0x0AFF],\n [0x0B41, 0x0B44],\n [0x0B55, 0x0B56],\n [0x0B62, 0x0B63],\n [0x0C3E, 0x0C40],\n [0x0C46, 0x0C48],\n [0x0C4A, 0x0C4D],\n [0x0C55, 0x0C56],\n [0x0C62, 0x0C63],\n [0x0CCC, 0x0CCD],\n [0x0CE2, 0x0CE3],\n [0x0D00, 0x0D01],\n [0x0D3B, 0x0D3C],\n [0x0D62, 0x0D63],\n [0x0DD2, 0x0DD4],\n [0x0E34, 0x0E3A],\n [0x0E47, 0x0E4E],\n [0x0EB4, 0x0EBC],\n [0x0EC8, 0x0ECD],\n [0x0F18, 0x0F19],\n [0x0F71, 0x0F7E],\n [0x0F80, 0x0F84],\n [0x0F86, 0x0F87],\n [0x0F8D, 0x0F97],\n [0x0F99, 0x0FBC],\n [0x102D, 0x1030],\n [0x1032, 0x1037],\n [0x1039, 0x103A],\n [0x103D, 0x103E],\n [0x1058, 0x1059],\n [0x105E, 0x1060],\n [0x1071, 0x1074],\n [0x1085, 0x1086],\n [0x135D, 0x135F],\n [0x1712, 0x1714],\n [0x1732, 0x1734],\n [0x1752, 0x1753],\n [0x1772, 0x1773],\n [0x17B4, 0x17B5],\n [0x17B7, 0x17BD],\n [0x17C9, 0x17D3],\n [0x180B, 0x180D],\n [0x1885, 0x1886],\n [0x1920, 0x1922],\n [0x1927, 0x1928],\n [0x1939, 0x193B],\n [0x1A17, 0x1A18],\n [0x1A58, 0x1A5E],\n [0x1A65, 0x1A6C],\n [0x1A73, 0x1A7C],\n [0x1AB0, 0x1ABE],\n [0x1B00, 0x1B03],\n [0x1B36, 0x1B3A],\n [0x1B6B, 0x1B73],\n [0x1B80, 0x1B81],\n [0x1BA2, 0x1BA5],\n [0x1BA8, 0x1BA9],\n [0x1BAB, 0x1BAD],\n [0x1BE8, 0x1BE9],\n [0x1BEF, 0x1BF1],\n [0x1C2C, 0x1C33],\n [0x1C36, 0x1C37],\n [0x1CD0, 0x1CD2],\n [0x1CD4, 0x1CE0],\n [0x1CE2, 0x1CE8],\n [0x1CF8, 0x1CF9],\n [0x1DC0, 0x1DF9],\n [0x1DFB, 0x1DFF],\n [0x200B, 0x200F], // Zero-width spaces\n [0x202A, 0x202E], // Bidirectional format characters\n [0x2060, 0x2064], // Word joiner, etc.\n [0x2066, 0x206F], // More bidirectional\n [0xFE00, 0xFE0F], // Variation selectors\n [0xFE20, 0xFE2F], // Combining half marks\n];\n\n// Single zero-width characters\nconst ZERO_WIDTH_SINGLES = new Set([\n 0x05BF,\n 0x05C7,\n 0x0670,\n 0x0711,\n 0x07FD,\n 0x093A,\n 0x093C,\n 0x094D,\n 0x0981,\n 0x09BC,\n 0x09CD,\n 0x09FE,\n 0x0A3C,\n 0x0A51,\n 0x0A75,\n 0x0ABC,\n 0x0ACD,\n 0x0B01,\n 0x0B3C,\n 0x0B3F,\n 0x0B4D,\n 0x0B82,\n 0x0BC0,\n 0x0BCD,\n 0x0C00,\n 0x0C04,\n 0x0C81,\n 0x0CBC,\n 0x0CBF,\n 0x0CC6,\n 0x0D41,\n 0x0D44,\n 0x0D4D,\n 0x0D81,\n 0x0DCA,\n 0x0DD6,\n 0x0E31,\n 0x0EB1,\n 0x0F35,\n 0x0F37,\n 0x0F39,\n 0x0FC6,\n 0x1082,\n 0x108D,\n 0x109D,\n 0x17C6,\n 0x17DD,\n 0x18A9,\n 0x1932,\n 0x1A1B,\n 0x1A56,\n 0x1A60,\n 0x1A62,\n 0x1A7F,\n 0x1B34,\n 0x1B3C,\n 0x1B42,\n 0x1BE6,\n 0x1BED,\n 0x1CED,\n 0x1CF4,\n 0xFEFF,\n]);\n\n/**\n * Binary search to check if a value is within any range\n */\nfunction isInRanges(code: number, ranges: Array<[number, number]>): boolean {\n let left = 0;\n let right = ranges.length - 1;\n\n while (left <= right) {\n const mid = Math.floor((left + right) / 2);\n const [start, end] = ranges[mid];\n\n if (code >= start && code <= end) {\n return true;\n } else if (code < start) {\n right = mid - 1;\n } else {\n left = mid + 1;\n }\n }\n\n return false;\n}\n\n/**\n * Check if a character is zero-width (combining marks, etc.)\n * Based on wcwidth's zero-width table.\n *\n * @param code Unicode code point\n * @returns True if the character has zero display width\n */\nfunction isZeroWidth(code: number): boolean {\n return ZERO_WIDTH_SINGLES.has(code) || isInRanges(code, ZERO_WIDTH_RANGES);\n}\n\n/**\n * Check if a character code point represents a wide character.\n * Based on wcwidth's wide character table (selected ranges from Unicode 15.1.0).\n *\n * @param code Unicode code point\n * @returns True if the character has width 2\n */\nfunction isWideCharacter(code: number): boolean {\n // cSpell: disable\n return (\n // Based on wcwidth table_wide.py for Unicode 15.1.0\n (code >= 0x1100 && code <= 0x115F) || // Hangul Jamo\n (code >= 0x231A && code <= 0x231B) || // Watch, Hourglass\n (code >= 0x2329 && code <= 0x232A) || // Angle brackets\n (code >= 0x23E9 && code <= 0x23EC) || // Media controls\n code === 0x23F0 || code === 0x23F3 || // Alarm clock, hourglass\n (code >= 0x25FD && code <= 0x25FE) || // Small squares\n (code >= 0x2614 && code <= 0x2615) || // Umbrella, coffee\n (code >= 0x2648 && code <= 0x2653) || // Zodiac signs\n code === 0x267F || code === 0x2693 || // Wheelchair, anchor\n code === 0x26A0 || code === 0x26A1 || code === 0x26AA || code === 0x26AB || // Warning, lightning, circles\n (code >= 0x26BD && code <= 0x26BE) || // Sports balls\n (code >= 0x26C4 && code <= 0x26C5) || // Weather\n code === 0x26CE || code === 0x26D4 || // Ophiuchus, no entry\n (code >= 0x26EA && code <= 0x26EA) || // Church\n (code >= 0x26F2 && code <= 0x26F3) || // Fountain, golf\n code === 0x26F5 || code === 0x26FA || // Sailboat, tent\n code === 0x26FD || // Gas pump\n (code >= 0x2705 && code <= 0x2705) || // Check mark\n (code >= 0x270A && code <= 0x270B) || // Raised fists\n code === 0x2728 || // Sparkles (✨)\n code === 0x274C || // Cross mark (❌)\n code === 0x274E || // Cross mark button\n (code >= 0x2753 && code <= 0x2755) || // Question marks\n code === 0x2757 || // Exclamation\n (code >= 0x2795 && code <= 0x2797) || // Plus signs\n code === 0x27B0 || code === 0x27BF || // Curly loop, double curly loop\n (code >= 0x2B1B && code <= 0x2B1C) || // Large squares\n code === 0x2B50 || code === 0x2B55 || // Star, circle\n (code >= 0x2E80 && code <= 0x2E99) || // CJK Radicals Supplement\n (code >= 0x2E9B && code <= 0x2EF3) ||\n (code >= 0x2F00 && code <= 0x2FD5) || // Kangxi Radicals\n (code >= 0x2FF0 && code <= 0x2FFB) || // Ideographic Description Characters\n (code >= 0x3000 && code <= 0x303E) || // CJK Symbols and Punctuation\n (code >= 0x3041 && code <= 0x3096) || // Hiragana\n (code >= 0x3099 && code <= 0x30FF) || // Katakana\n (code >= 0x3105 && code <= 0x312F) || // Bopomofo\n (code >= 0x3131 && code <= 0x318E) || // Hangul Compatibility Jamo\n (code >= 0x3190 && code <= 0x31E3) || // Various CJK\n (code >= 0x31F0 && code <= 0x321E) || // Katakana Phonetic Extensions\n (code >= 0x3220 && code <= 0x3247) || // Enclosed CJK Letters and Months\n (code >= 0x3250 && code <= 0x4DBF) || // Various CJK\n (code >= 0x4E00 && code <= 0x9FFF) || // CJK Unified Ideographs\n (code >= 0xA960 && code <= 0xA97F) || // Hangul Jamo Extended-A\n (code >= 0xAC00 && code <= 0xD7A3) || // Hangul Syllables\n (code >= 0xD7B0 && code <= 0xD7C6) || // Hangul Jamo Extended-B\n (code >= 0xF900 && code <= 0xFAFF) || // CJK Compatibility Ideographs\n (code >= 0xFE10 && code <= 0xFE19) || // Vertical Forms\n (code >= 0xFE30 && code <= 0xFE6F) || // CJK Compatibility Forms\n (code >= 0xFF00 && code <= 0xFF60) || // Fullwidth Forms\n (code >= 0xFFE0 && code <= 0xFFE6) || // Fullwidth Forms\n (code >= 0x16FE0 && code <= 0x16FE4) || // Tangut\n (code >= 0x16FF0 && code <= 0x16FF1) ||\n (code >= 0x17000 && code <= 0x187F7) || // Tangut\n (code >= 0x18800 && code <= 0x18CD5) || // Tangut Components\n (code >= 0x18D00 && code <= 0x18D08) || // Tangut Supplement\n (code >= 0x1AFF0 && code <= 0x1AFF3) ||\n (code >= 0x1AFF5 && code <= 0x1AFFB) ||\n (code >= 0x1AFFD && code <= 0x1AFFE) ||\n (code >= 0x1B000 && code <= 0x1B122) || // Kana Extended-A/Supplement\n (code >= 0x1B150 && code <= 0x1B152) ||\n (code >= 0x1B164 && code <= 0x1B167) ||\n (code >= 0x1B170 && code <= 0x1B2FB) ||\n code === 0x1F004 || // Mahjong Red Dragon\n code === 0x1F0CF || // Playing Card Black Joker\n (code >= 0x1F18E && code <= 0x1F18E) || // AB Button\n (code >= 0x1F191 && code <= 0x1F19A) || // Various squared symbols\n (code >= 0x1F1E6 && code <= 0x1F1FF) || // Regional Indicator Symbols (flags)\n (code >= 0x1F200 && code <= 0x1F202) || // Squared symbols\n (code >= 0x1F210 && code <= 0x1F23B) || // Squared CJK\n (code >= 0x1F240 && code <= 0x1F248) || // Tortoise shell bracketed\n (code >= 0x1F250 && code <= 0x1F251) || // Circled ideographs\n (code >= 0x1F260 && code <= 0x1F265) ||\n (code >= 0x1F300 && code <= 0x1F6D7) || // Large emoji block\n (code >= 0x1F6E0 && code <= 0x1F6EC) ||\n (code >= 0x1F6F0 && code <= 0x1F6FC) ||\n (code >= 0x1F700 && code <= 0x1F773) ||\n (code >= 0x1F780 && code <= 0x1F7D8) ||\n (code >= 0x1F7E0 && code <= 0x1F7EB) ||\n (code >= 0x1F7F0 && code <= 0x1F7F0) ||\n (code >= 0x1F800 && code <= 0x1F80B) ||\n (code >= 0x1F810 && code <= 0x1F847) ||\n (code >= 0x1F850 && code <= 0x1F859) ||\n (code >= 0x1F860 && code <= 0x1F887) ||\n (code >= 0x1F890 && code <= 0x1F8AD) ||\n (code >= 0x1F8B0 && code <= 0x1F8B1) ||\n (code >= 0x1F900 && code <= 0x1FA53) || // Supplemental symbols and pictographs\n (code >= 0x1FA60 && code <= 0x1FA6D) ||\n (code >= 0x1FA70 && code <= 0x1FA7C) ||\n (code >= 0x1FA80 && code <= 0x1FA88) ||\n (code >= 0x1FA90 && code <= 0x1FABD) ||\n (code >= 0x1FABF && code <= 0x1FAC5) ||\n (code >= 0x1FACE && code <= 0x1FADB) ||\n (code >= 0x1FAE0 && code <= 0x1FAE8) ||\n (code >= 0x1FAF0 && code <= 0x1FAF8) ||\n (code >= 0x20000 && code <= 0x2FFFD) || // CJK Extension B\n (code >= 0x30000 && code <= 0x3FFFD) // CJK Extension C\n );\n // cSpell: enable\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,eAAe;;;;;;;AAQrB,SAAgB,UAAUA,MAAsB;AAC9C,QAAO,KAAK,QAAQ,cAAc,GAAG;AACtC;;;;;;;;AASD,SAAgB,gBAAgBA,MAAsB;CAEpD,MAAM,YAAY,UAAU,KAAK;AAEjC,KAAI,UAAU,WAAW,EAAG,QAAO;CAEnC,IAAI,QAAQ;CACZ,IAAI,IAAI;AAGR,QAAO,IAAI,UAAU,QAAQ;EAC3B,MAAM,OAAO,UAAU,YAAY,EAAE;AACrC,MAAI,iBAAoB;AACtB;AACA;EACD;EAED,MAAM,YAAY,QAAQ,KAAK;AAC/B,MAAI,aAAa,EACf,UAAS;AAIX,OAAM,OAAO,QAAU,IAAI;CAC5B;AAED,QAAO;AACR;;;;;;;;;;;;AAaD,SAAgB,QAAQC,MAAsB;AAE5C,KAAI,OAAO,MAAO,QAAQ,OAAQ,OAAO,IACvC,QAAO;AAIT,KAAI,YAAY,KAAK,CACnB,QAAO;AAIT,KAAI,gBAAgB,KAAK,CACvB,QAAO;AAGT,QAAO;AACR;AAGD,MAAMC,oBAA6C;CACjD,CAAC,KAAQ,GAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,IAAO;CAChB,CAAC,MAAQ,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UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC5B,SAAS,UACT,SAAS,UACR,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ,UAC3B,QAAQ,UAAW,QAAQ;AAG/B"}
package/formatter.test.ts CHANGED
@@ -509,13 +509,35 @@ test("Multiple styles combination", () => {
509
509
  assertStringIncludes(result, "\x1b[9m"); // strikethrough
510
510
  });
511
511
 
512
- test("Word wrapping disabled by default", () => {
512
+ ("Bun" in globalThis ? test.skip : test)(
513
+ "Word wrapping enabled by default",
514
+ () => {
515
+ const formatter = getPrettyFormatter({
516
+ colors: false,
517
+ });
518
+
519
+ const longMessage =
520
+ "This is a very long message that would normally exceed the typical console width and should be wrapped when word wrapping is enabled by default.";
521
+ const record = createLogRecord("info", ["test"], [longMessage]);
522
+ const result = formatter(record);
523
+
524
+ // Should contain multiple line breaks due to wrapping
525
+ const lines = result.split("\n");
526
+ assert(lines.length > 2); // More than just content + trailing newline due to wrapping
527
+
528
+ // First line should contain the beginning of the message
529
+ assert(lines[0].includes("This is a very long message"));
530
+ },
531
+ );
532
+
533
+ test("Word wrapping can be disabled", () => {
513
534
  const formatter = getPrettyFormatter({
514
535
  colors: false,
536
+ wordWrap: false,
515
537
  });
516
538
 
517
539
  const longMessage =
518
- "This is a very long message that would normally exceed the typical console width and should not be wrapped when word wrapping is disabled by default.";
540
+ "This is a very long message that would normally exceed the typical console width but should not be wrapped when word wrapping is explicitly disabled.";
519
541
  const record = createLogRecord("info", ["test"], [longMessage]);
520
542
  const result = formatter(record);
521
543
 
package/formatter.ts CHANGED
@@ -96,6 +96,10 @@ type CategoryPattern = {
96
96
  */
97
97
  export type Style = keyof typeof styles | (keyof typeof styles)[] | null;
98
98
 
99
+ // Pre-compiled regex patterns for color parsing
100
+ const RGB_PATTERN = /^rgb\((\d+),(\d+),(\d+)\)$/;
101
+ const HEX_PATTERN = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
102
+
99
103
  /**
100
104
  * Helper function to convert color to ANSI escape code
101
105
  */
@@ -104,14 +108,16 @@ function colorToAnsi(color: Color): string {
104
108
  if (color in ansiColors) {
105
109
  return ansiColors[color as keyof typeof ansiColors];
106
110
  }
111
+
107
112
  // Handle rgb() format
108
- const rgbMatch = color.match(/^rgb\((\d+),(\d+),(\d+)\)$/);
113
+ const rgbMatch = color.match(RGB_PATTERN);
109
114
  if (rgbMatch) {
110
115
  const [, r, g, b] = rgbMatch;
111
116
  return `\x1b[38;2;${r};${g};${b}m`;
112
117
  }
118
+
113
119
  // Handle hex format (#rrggbb or #rgb)
114
- const hexMatch = color.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
120
+ const hexMatch = color.match(HEX_PATTERN);
115
121
  if (hexMatch) {
116
122
  let hex = hexMatch[1];
117
123
  // Convert 3-digit hex to 6-digit
@@ -123,6 +129,7 @@ function colorToAnsi(color: Color): string {
123
129
  const b = parseInt(hex.substr(4, 2), 16);
124
130
  return `\x1b[38;2;${r};${g};${b}m`;
125
131
  }
132
+
126
133
  return "";
127
134
  }
128
135
 
@@ -215,25 +222,17 @@ const defaultIcons: Record<LogLevel, string> = {
215
222
  function normalizeIconSpacing(
216
223
  iconMap: Record<LogLevel, string>,
217
224
  ): Record<LogLevel, string> {
218
- // Calculate the maximum display width among all icons
225
+ const entries = Object.entries(iconMap) as Array<[LogLevel, string]>;
219
226
  const maxWidth = Math.max(
220
- ...Object.values(iconMap).map((icon) => getDisplayWidth(icon)),
227
+ ...entries.map(([, icon]) => getDisplayWidth(icon)),
221
228
  );
222
229
 
223
- // Normalize each icon to the maximum width by adding spaces
224
- const normalizedMap: Record<LogLevel, string> = {} as Record<
225
- LogLevel,
226
- string
227
- >;
228
- for (
229
- const [level, icon] of Object.entries(iconMap) as Array<[LogLevel, string]>
230
- ) {
231
- const currentWidth = getDisplayWidth(icon);
232
- const spacesToAdd = maxWidth - currentWidth;
233
- normalizedMap[level] = icon + " ".repeat(spacesToAdd);
234
- }
235
-
236
- return normalizedMap;
230
+ return Object.fromEntries(
231
+ entries.map(([level, icon]) => [
232
+ level,
233
+ icon + " ".repeat(maxWidth - getDisplayWidth(icon)),
234
+ ]),
235
+ ) as Record<LogLevel, string>;
237
236
  }
238
237
 
239
238
  /**
@@ -287,7 +286,7 @@ export interface PrettyFormatterOptions
287
286
  *
288
287
  * @default `"rgb(100,116,139)"` (slate gray)
289
288
  */
290
- timestampColor?: Color;
289
+ readonly timestampColor?: Color;
291
290
 
292
291
  /**
293
292
  * Visual style applied to timestamp text.
@@ -307,7 +306,7 @@ export interface PrettyFormatterOptions
307
306
  *
308
307
  * @default `"dim"`
309
308
  */
310
- timestampStyle?: Style;
309
+ readonly timestampStyle?: Style;
311
310
 
312
311
  /**
313
312
  * Custom colors for each log level.
@@ -328,7 +327,7 @@ export interface PrettyFormatterOptions
328
327
  *
329
328
  * @default Built-in color scheme (purple trace, blue debug, green info, amber warning, red error, dark red fatal)
330
329
  */
331
- levelColors?: Partial<Record<LogLevel, Color>>;
330
+ readonly levelColors?: Partial<Record<LogLevel, Color>>;
332
331
 
333
332
  /**
334
333
  * Visual style applied to log level text.
@@ -348,7 +347,7 @@ export interface PrettyFormatterOptions
348
347
  *
349
348
  * @default `null` (no additional styling)
350
349
  */
351
- levelStyle?: Style;
350
+ readonly levelStyle?: Style;
352
351
 
353
352
  /**
354
353
  * Icon configuration for each log level.
@@ -373,7 +372,7 @@ export interface PrettyFormatterOptions
373
372
  *
374
373
  * @default `true` (use default emoji icons)
375
374
  */
376
- icons?: boolean | Partial<Record<LogLevel, string>>;
375
+ readonly icons?: boolean | Partial<Record<LogLevel, string>>;
377
376
 
378
377
  /**
379
378
  * Character(s) used to separate category hierarchy levels.
@@ -392,7 +391,7 @@ export interface PrettyFormatterOptions
392
391
  *
393
392
  * @default `"·"` (interpunct)
394
393
  */
395
- categorySeparator?: string;
394
+ readonly categorySeparator?: string;
396
395
 
397
396
  /**
398
397
  * Default color for category display.
@@ -410,7 +409,7 @@ export interface PrettyFormatterOptions
410
409
  *
411
410
  * @default `"rgb(100,116,139)"` (slate gray)
412
411
  */
413
- categoryColor?: Color;
412
+ readonly categoryColor?: Color;
414
413
 
415
414
  /**
416
415
  * Category-specific color mapping based on prefixes.
@@ -429,7 +428,7 @@ export interface PrettyFormatterOptions
429
428
  * ])
430
429
  * ```
431
430
  */
432
- categoryColorMap?: CategoryColorMap;
431
+ readonly categoryColorMap?: CategoryColorMap;
433
432
 
434
433
  /**
435
434
  * Visual style applied to category text.
@@ -449,7 +448,7 @@ export interface PrettyFormatterOptions
449
448
  *
450
449
  * @default `["dim", "italic"]` (dimmed for subtle appearance)
451
450
  */
452
- categoryStyle?: Style;
451
+ readonly categoryStyle?: Style;
453
452
 
454
453
  /**
455
454
  * Maximum display width for category names.
@@ -469,7 +468,7 @@ export interface PrettyFormatterOptions
469
468
  *
470
469
  * @default `20` (20 character limit)
471
470
  */
472
- categoryWidth?: number | "auto";
471
+ readonly categoryWidth?: number | "auto";
473
472
 
474
473
  /**
475
474
  * Strategy for truncating long category names.
@@ -490,7 +489,7 @@ export interface PrettyFormatterOptions
490
489
  *
491
490
  * @default `"middle"` (smart context-preserving truncation)
492
491
  */
493
- categoryTruncate?: TruncationStrategy;
492
+ readonly categoryTruncate?: TruncationStrategy;
494
493
 
495
494
  /**
496
495
  * Color for log message text content.
@@ -508,7 +507,7 @@ export interface PrettyFormatterOptions
508
507
  *
509
508
  * @default `"rgb(148,163,184)"` (light slate gray)
510
509
  */
511
- messageColor?: Color;
510
+ readonly messageColor?: Color;
512
511
 
513
512
  /**
514
513
  * Visual style applied to log message text.
@@ -528,7 +527,7 @@ export interface PrettyFormatterOptions
528
527
  *
529
528
  * @default `"dim"` (dimmed for subtle readability)
530
529
  */
531
- messageStyle?: Style;
530
+ readonly messageStyle?: Style;
532
531
 
533
532
  /**
534
533
  * Global color control for the entire formatter.
@@ -545,7 +544,7 @@ export interface PrettyFormatterOptions
545
544
  *
546
545
  * @default `true` (colors enabled)
547
546
  */
548
- colors?: boolean;
547
+ readonly colors?: boolean;
549
548
 
550
549
  /**
551
550
  * Column alignment for consistent visual layout.
@@ -562,7 +561,7 @@ export interface PrettyFormatterOptions
562
561
  *
563
562
  * @default `true` (alignment enabled)
564
563
  */
565
- align?: boolean;
564
+ readonly align?: boolean;
566
565
 
567
566
  /**
568
567
  * Configuration for structured value inspection and rendering.
@@ -581,22 +580,24 @@ export interface PrettyFormatterOptions
581
580
  *
582
581
  * @default `{}` (use built-in defaults: depth=unlimited, colors=auto, compact=true)
583
582
  */
584
- inspectOptions?: {
583
+ readonly inspectOptions?: {
585
584
  /**
586
585
  * Maximum depth to traverse when inspecting nested objects.
587
586
  * @default Infinity (no depth limit)
588
587
  */
589
- depth?: number;
588
+ readonly depth?: number;
589
+
590
590
  /**
591
591
  * Whether to use syntax highlighting colors for inspected values.
592
592
  * @default Inherited from global `colors` setting
593
593
  */
594
- colors?: boolean;
594
+ readonly colors?: boolean;
595
+
595
596
  /**
596
597
  * Whether to use compact formatting for objects and arrays.
597
598
  * @default `true` (compact formatting)
598
599
  */
599
- compact?: boolean;
600
+ readonly compact?: boolean;
600
601
  };
601
602
 
602
603
  /**
@@ -622,10 +623,10 @@ export interface PrettyFormatterOptions
622
623
  * wordWrap: false
623
624
  * ```
624
625
  *
625
- * @default `false` (no word wrapping)
626
+ * @default `true` (auto-detect terminal width)
626
627
  * @since 1.0.0
627
628
  */
628
- wordWrap?: boolean | number;
629
+ readonly wordWrap?: boolean | number;
629
630
  }
630
631
 
631
632
  /**
@@ -650,7 +651,7 @@ export interface PrettyFormatterOptions
650
651
  * @example
651
652
  * ```typescript
652
653
  * import { configure } from "@logtape/logtape";
653
- * import { getConsoleSink } from "@logtape/logtape";
654
+ * import { getConsoleSink } from "@logtape/logtape/sink";
654
655
  * import { getPrettyFormatter } from "@logtape/pretty";
655
656
  *
656
657
  * await configure({
@@ -694,7 +695,7 @@ export function getPrettyFormatter(
694
695
  colors: useColors = true,
695
696
  align = true,
696
697
  inspectOptions = {},
697
- wordWrap = false,
698
+ wordWrap = true,
698
699
  } = options;
699
700
 
700
701
  // Resolve icons
@@ -718,103 +719,91 @@ export function getPrettyFormatter(
718
719
  ...levelColors,
719
720
  };
720
721
 
721
- // Level formatter function
722
+ // Level formatter function with optimized mappings
723
+ const levelMappings: Record<string, Record<LogLevel, string>> = {
724
+ "ABBR": {
725
+ trace: "TRC",
726
+ debug: "DBG",
727
+ info: "INF",
728
+ warning: "WRN",
729
+ error: "ERR",
730
+ fatal: "FTL",
731
+ },
732
+ "L": {
733
+ trace: "T",
734
+ debug: "D",
735
+ info: "I",
736
+ warning: "W",
737
+ error: "E",
738
+ fatal: "F",
739
+ },
740
+ "abbr": {
741
+ trace: "trc",
742
+ debug: "dbg",
743
+ info: "inf",
744
+ warning: "wrn",
745
+ error: "err",
746
+ fatal: "ftl",
747
+ },
748
+ "l": {
749
+ trace: "t",
750
+ debug: "d",
751
+ info: "i",
752
+ warning: "w",
753
+ error: "e",
754
+ fatal: "f",
755
+ },
756
+ };
757
+
722
758
  const formatLevel = (level: LogLevel): string => {
723
759
  if (typeof levelFormat === "function") {
724
760
  return levelFormat(level);
725
761
  }
726
- switch (levelFormat) {
727
- case "ABBR":
728
- return {
729
- trace: "TRC",
730
- debug: "DBG",
731
- info: "INF",
732
- warning: "WRN",
733
- error: "ERR",
734
- fatal: "FTL",
735
- }[level];
736
- case "FULL":
737
- return level.toUpperCase();
738
- case "L":
739
- return {
740
- trace: "T",
741
- debug: "D",
742
- info: "I",
743
- warning: "W",
744
- error: "E",
745
- fatal: "F",
746
- }[level];
747
- case "abbr":
748
- return {
749
- trace: "trc",
750
- debug: "dbg",
751
- info: "inf",
752
- warning: "wrn",
753
- error: "err",
754
- fatal: "ftl",
755
- }[level];
756
- case "full":
757
- return level;
758
- case "l":
759
- return {
760
- trace: "t",
761
- debug: "d",
762
- info: "i",
763
- warning: "w",
764
- error: "e",
765
- fatal: "f",
766
- }[level];
767
- default:
768
- return level;
769
- }
762
+
763
+ if (levelFormat === "FULL") return level.toUpperCase();
764
+ if (levelFormat === "full") return level;
765
+
766
+ return levelMappings[levelFormat]?.[level] ?? level;
767
+ };
768
+
769
+ // Timestamp formatters lookup table
770
+ const timestampFormatters: Record<string, (ts: number) => string> = {
771
+ "date-time-timezone": (ts) => {
772
+ const iso = new Date(ts).toISOString();
773
+ return iso.replace("T", " ").replace("Z", " +00:00");
774
+ },
775
+ "date-time-tz": (ts) => {
776
+ const iso = new Date(ts).toISOString();
777
+ return iso.replace("T", " ").replace("Z", " +00");
778
+ },
779
+ "date-time": (ts) => {
780
+ const iso = new Date(ts).toISOString();
781
+ return iso.replace("T", " ").replace("Z", "");
782
+ },
783
+ "time-timezone": (ts) => {
784
+ const iso = new Date(ts).toISOString();
785
+ return iso.replace(/.*T/, "").replace("Z", " +00:00");
786
+ },
787
+ "time-tz": (ts) => {
788
+ const iso = new Date(ts).toISOString();
789
+ return iso.replace(/.*T/, "").replace("Z", " +00");
790
+ },
791
+ "time": (ts) => {
792
+ const iso = new Date(ts).toISOString();
793
+ return iso.replace(/.*T/, "").replace("Z", "");
794
+ },
795
+ "date": (ts) => new Date(ts).toISOString().replace(/T.*/, ""),
796
+ "rfc3339": (ts) => new Date(ts).toISOString(),
770
797
  };
771
798
 
772
- // Resolve timestamp formatter - support all TextFormatterOptions formats
799
+ // Resolve timestamp formatter
773
800
  let timestampFn: ((ts: number) => string | null) | null = null;
774
801
  if (timestamp === "none" || timestamp === "disabled") {
775
802
  timestampFn = null;
776
- } else if (timestamp === "date-time-timezone") {
777
- timestampFn = (ts: number) => {
778
- const date = new Date(ts);
779
- return date.toISOString().replace("T", " ").replace("Z", " +00:00");
780
- };
781
- } else if (timestamp === "date-time-tz") {
782
- timestampFn = (ts: number) => {
783
- const date = new Date(ts);
784
- return date.toISOString().replace("T", " ").replace("Z", " +00");
785
- };
786
- } else if (timestamp === "date-time") {
787
- timestampFn = (ts: number) => {
788
- const date = new Date(ts);
789
- return date.toISOString().replace("T", " ").replace("Z", "");
790
- };
791
- } else if (timestamp === "time-timezone") {
792
- timestampFn = (ts: number) => {
793
- const date = new Date(ts);
794
- return date.toISOString().replace(/.*T/, "").replace("Z", " +00:00");
795
- };
796
- } else if (timestamp === "time-tz") {
797
- timestampFn = (ts: number) => {
798
- const date = new Date(ts);
799
- return date.toISOString().replace(/.*T/, "").replace("Z", " +00");
800
- };
801
- } else if (timestamp === "time") {
802
- timestampFn = (ts: number) => {
803
- const date = new Date(ts);
804
- return date.toISOString().replace(/.*T/, "").replace("Z", "");
805
- };
806
- } else if (timestamp === "date") {
807
- timestampFn = (ts: number) => {
808
- const date = new Date(ts);
809
- return date.toISOString().replace(/T.*/, "");
810
- };
811
- } else if (timestamp === "rfc3339") {
812
- timestampFn = (ts: number) => {
813
- const date = new Date(ts);
814
- return date.toISOString();
815
- };
816
803
  } else if (typeof timestamp === "function") {
817
804
  timestampFn = timestamp;
805
+ } else {
806
+ timestampFn = timestampFormatters[timestamp as string] ?? null;
818
807
  }
819
808
 
820
809
  // Configure word wrap settings
@@ -1020,7 +1009,7 @@ export function getPrettyFormatter(
1020
1009
  * @example
1021
1010
  * ```typescript
1022
1011
  * import { configure } from "@logtape/logtape";
1023
- * import { getConsoleSink } from "@logtape/logtape";
1012
+ * import { getConsoleSink } from "@logtape/logtape/sink";
1024
1013
  * import { prettyFormatter } from "@logtape/pretty";
1025
1014
  *
1026
1015
  * await configure({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@logtape/pretty",
3
- "version": "1.0.0-dev.231+227a7dc5",
4
- "description": "Beautiful console formatter for LogTape - perfect for local development",
3
+ "version": "1.0.0-dev.232+5bb62b49",
4
+ "description": "Beautiful text formatter for LogTapeperfect for local development",
5
5
  "keywords": [
6
6
  "logging",
7
7
  "log",
@@ -47,7 +47,7 @@
47
47
  "./package.json": "./package.json"
48
48
  },
49
49
  "peerDependencies": {
50
- "@logtape/logtape": "1.0.0-dev.231+227a7dc5"
50
+ "@logtape/logtape": "1.0.0-dev.232+5bb62b49"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@alinea/suite": "^0.6.3",