@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.
- package/README.md +167 -92
- package/deno.json +1 -1
- package/dist/formatter.cjs +76 -82
- package/dist/formatter.d.cts +23 -23
- package/dist/formatter.d.cts.map +1 -1
- package/dist/formatter.d.ts +23 -23
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +76 -82
- package/dist/formatter.js.map +1 -1
- package/dist/wcwidth.cjs +193 -2
- package/dist/wcwidth.js +193 -2
- package/dist/wcwidth.js.map +1 -1
- package/formatter.test.ts +24 -2
- package/formatter.ts +117 -128
- package/package.json +3 -3
- package/wcwidth.ts +210 -179
package/dist/wcwidth.js.map
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
225
|
+
const entries = Object.entries(iconMap) as Array<[LogLevel, string]>;
|
|
219
226
|
const maxWidth = Math.max(
|
|
220
|
-
...
|
|
227
|
+
...entries.map(([, icon]) => getDisplayWidth(icon)),
|
|
221
228
|
);
|
|
222
229
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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 `
|
|
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 =
|
|
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
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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
|
|
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.
|
|
4
|
-
"description": "Beautiful
|
|
3
|
+
"version": "1.0.0-dev.232+5bb62b49",
|
|
4
|
+
"description": "Beautiful text formatter for LogTape—perfect 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.
|
|
50
|
+
"@logtape/logtape": "1.0.0-dev.232+5bb62b49"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@alinea/suite": "^0.6.3",
|