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

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.
@@ -346,9 +345,9 @@ export interface PrettyFormatterOptions
346
345
  * levelStyle: null // No additional styling
347
346
  * ```
348
347
  *
349
- * @default `null` (no additional styling)
348
+ * @default `"underline"`
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.
@@ -457,19 +456,9 @@ export interface PrettyFormatterOptions
457
456
  * Controls layout consistency by limiting category width.
458
457
  * Long categories are truncated according to `categoryTruncate` strategy.
459
458
  *
460
- * - Number: Fixed character width limit
461
- * - `"auto"`: No width limit, categories display at full length
462
- *
463
- * @example
464
- * ```typescript
465
- * categoryWidth: 20 // Limit to 20 characters
466
- * categoryWidth: 30 // Limit to 30 characters
467
- * categoryWidth: "auto" // No limit
468
- * ```
469
- *
470
- * @default `20` (20 character limit)
459
+ * @default `20`
471
460
  */
472
- categoryWidth?: number | "auto";
461
+ readonly categoryWidth?: number;
473
462
 
474
463
  /**
475
464
  * Strategy for truncating long category names.
@@ -490,7 +479,7 @@ export interface PrettyFormatterOptions
490
479
  *
491
480
  * @default `"middle"` (smart context-preserving truncation)
492
481
  */
493
- categoryTruncate?: TruncationStrategy;
482
+ readonly categoryTruncate?: TruncationStrategy;
494
483
 
495
484
  /**
496
485
  * Color for log message text content.
@@ -508,7 +497,7 @@ export interface PrettyFormatterOptions
508
497
  *
509
498
  * @default `"rgb(148,163,184)"` (light slate gray)
510
499
  */
511
- messageColor?: Color;
500
+ readonly messageColor?: Color;
512
501
 
513
502
  /**
514
503
  * Visual style applied to log message text.
@@ -528,7 +517,7 @@ export interface PrettyFormatterOptions
528
517
  *
529
518
  * @default `"dim"` (dimmed for subtle readability)
530
519
  */
531
- messageStyle?: Style;
520
+ readonly messageStyle?: Style;
532
521
 
533
522
  /**
534
523
  * Global color control for the entire formatter.
@@ -545,7 +534,7 @@ export interface PrettyFormatterOptions
545
534
  *
546
535
  * @default `true` (colors enabled)
547
536
  */
548
- colors?: boolean;
537
+ readonly colors?: boolean;
549
538
 
550
539
  /**
551
540
  * Column alignment for consistent visual layout.
@@ -562,7 +551,7 @@ export interface PrettyFormatterOptions
562
551
  *
563
552
  * @default `true` (alignment enabled)
564
553
  */
565
- align?: boolean;
554
+ readonly align?: boolean;
566
555
 
567
556
  /**
568
557
  * Configuration for structured value inspection and rendering.
@@ -581,22 +570,24 @@ export interface PrettyFormatterOptions
581
570
  *
582
571
  * @default `{}` (use built-in defaults: depth=unlimited, colors=auto, compact=true)
583
572
  */
584
- inspectOptions?: {
573
+ readonly inspectOptions?: {
585
574
  /**
586
575
  * Maximum depth to traverse when inspecting nested objects.
587
576
  * @default Infinity (no depth limit)
588
577
  */
589
- depth?: number;
578
+ readonly depth?: number;
579
+
590
580
  /**
591
581
  * Whether to use syntax highlighting colors for inspected values.
592
582
  * @default Inherited from global `colors` setting
593
583
  */
594
- colors?: boolean;
584
+ readonly colors?: boolean;
585
+
595
586
  /**
596
587
  * Whether to use compact formatting for objects and arrays.
597
588
  * @default `true` (compact formatting)
598
589
  */
599
- compact?: boolean;
590
+ readonly compact?: boolean;
600
591
  };
601
592
 
602
593
  /**
@@ -622,10 +613,10 @@ export interface PrettyFormatterOptions
622
613
  * wordWrap: false
623
614
  * ```
624
615
  *
625
- * @default `false` (no word wrapping)
616
+ * @default `true` (auto-detect terminal width)
626
617
  * @since 1.0.0
627
618
  */
628
- wordWrap?: boolean | number;
619
+ readonly wordWrap?: boolean | number;
629
620
  }
630
621
 
631
622
  /**
@@ -650,7 +641,7 @@ export interface PrettyFormatterOptions
650
641
  * @example
651
642
  * ```typescript
652
643
  * import { configure } from "@logtape/logtape";
653
- * import { getConsoleSink } from "@logtape/logtape";
644
+ * import { getConsoleSink } from "@logtape/logtape/sink";
654
645
  * import { getPrettyFormatter } from "@logtape/pretty";
655
646
  *
656
647
  * await configure({
@@ -694,7 +685,7 @@ export function getPrettyFormatter(
694
685
  colors: useColors = true,
695
686
  align = true,
696
687
  inspectOptions = {},
697
- wordWrap = false,
688
+ wordWrap = true,
698
689
  } = options;
699
690
 
700
691
  // Resolve icons
@@ -718,103 +709,91 @@ export function getPrettyFormatter(
718
709
  ...levelColors,
719
710
  };
720
711
 
721
- // Level formatter function
712
+ // Level formatter function with optimized mappings
713
+ const levelMappings: Record<string, Record<LogLevel, string>> = {
714
+ "ABBR": {
715
+ trace: "TRC",
716
+ debug: "DBG",
717
+ info: "INF",
718
+ warning: "WRN",
719
+ error: "ERR",
720
+ fatal: "FTL",
721
+ },
722
+ "L": {
723
+ trace: "T",
724
+ debug: "D",
725
+ info: "I",
726
+ warning: "W",
727
+ error: "E",
728
+ fatal: "F",
729
+ },
730
+ "abbr": {
731
+ trace: "trc",
732
+ debug: "dbg",
733
+ info: "inf",
734
+ warning: "wrn",
735
+ error: "err",
736
+ fatal: "ftl",
737
+ },
738
+ "l": {
739
+ trace: "t",
740
+ debug: "d",
741
+ info: "i",
742
+ warning: "w",
743
+ error: "e",
744
+ fatal: "f",
745
+ },
746
+ };
747
+
722
748
  const formatLevel = (level: LogLevel): string => {
723
749
  if (typeof levelFormat === "function") {
724
750
  return levelFormat(level);
725
751
  }
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
- }
752
+
753
+ if (levelFormat === "FULL") return level.toUpperCase();
754
+ if (levelFormat === "full") return level;
755
+
756
+ return levelMappings[levelFormat]?.[level] ?? level;
770
757
  };
771
758
 
772
- // Resolve timestamp formatter - support all TextFormatterOptions formats
759
+ // Timestamp formatters lookup table
760
+ const timestampFormatters: Record<string, (ts: number) => string> = {
761
+ "date-time-timezone": (ts) => {
762
+ const iso = new Date(ts).toISOString();
763
+ return iso.replace("T", " ").replace("Z", " +00:00");
764
+ },
765
+ "date-time-tz": (ts) => {
766
+ const iso = new Date(ts).toISOString();
767
+ return iso.replace("T", " ").replace("Z", " +00");
768
+ },
769
+ "date-time": (ts) => {
770
+ const iso = new Date(ts).toISOString();
771
+ return iso.replace("T", " ").replace("Z", "");
772
+ },
773
+ "time-timezone": (ts) => {
774
+ const iso = new Date(ts).toISOString();
775
+ return iso.replace(/.*T/, "").replace("Z", " +00:00");
776
+ },
777
+ "time-tz": (ts) => {
778
+ const iso = new Date(ts).toISOString();
779
+ return iso.replace(/.*T/, "").replace("Z", " +00");
780
+ },
781
+ "time": (ts) => {
782
+ const iso = new Date(ts).toISOString();
783
+ return iso.replace(/.*T/, "").replace("Z", "");
784
+ },
785
+ "date": (ts) => new Date(ts).toISOString().replace(/T.*/, ""),
786
+ "rfc3339": (ts) => new Date(ts).toISOString(),
787
+ };
788
+
789
+ // Resolve timestamp formatter
773
790
  let timestampFn: ((ts: number) => string | null) | null = null;
774
791
  if (timestamp === "none" || timestamp === "disabled") {
775
792
  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
793
  } else if (typeof timestamp === "function") {
817
794
  timestampFn = timestamp;
795
+ } else {
796
+ timestampFn = timestampFormatters[timestamp as string] ?? null;
818
797
  }
819
798
 
820
799
  // Configure word wrap settings
@@ -850,7 +829,7 @@ export function getPrettyFormatter(
850
829
  const level = formatLevel(record.level);
851
830
  const categoryStr = truncateCategory(
852
831
  record.category,
853
- typeof categoryWidth === "number" ? categoryWidth : 30,
832
+ categoryWidth,
854
833
  categorySeparator,
855
834
  categoryTruncate,
856
835
  );
@@ -965,8 +944,7 @@ export function getPrettyFormatter(
965
944
 
966
945
  const paddedLevel = formattedLevel.padEnd(levelWidth + levelColorLength);
967
946
  const paddedCategory = formattedCategory.padEnd(
968
- (typeof categoryWidth === "number" ? categoryWidth : 30) +
969
- categoryColorLength,
947
+ categoryWidth + categoryColorLength,
970
948
  );
971
949
 
972
950
  let result =
@@ -1020,7 +998,7 @@ export function getPrettyFormatter(
1020
998
  * @example
1021
999
  * ```typescript
1022
1000
  * import { configure } from "@logtape/logtape";
1023
- * import { getConsoleSink } from "@logtape/logtape";
1001
+ * import { getConsoleSink } from "@logtape/logtape/sink";
1024
1002
  * import { prettyFormatter } from "@logtape/pretty";
1025
1003
  *
1026
1004
  * 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.234+3fd3473b",
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.234+3fd3473b"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@alinea/suite": "^0.6.3",