@logtape/pretty 1.0.0-dev.231
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/LICENSE +20 -0
- package/README.md +236 -0
- package/deno.json +35 -0
- package/dist/_virtual/rolldown_runtime.cjs +30 -0
- package/dist/formatter.cjs +412 -0
- package/dist/formatter.d.cts +488 -0
- package/dist/formatter.d.cts.map +1 -0
- package/dist/formatter.d.ts +488 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +411 -0
- package/dist/formatter.js.map +1 -0
- package/dist/mod.cjs +4 -0
- package/dist/mod.d.cts +2 -0
- package/dist/mod.d.ts +2 -0
- package/dist/mod.js +3 -0
- package/dist/terminal.cjs +66 -0
- package/dist/terminal.js +66 -0
- package/dist/terminal.js.map +1 -0
- package/dist/truncate.cjs +57 -0
- package/dist/truncate.d.cts +47 -0
- package/dist/truncate.d.cts.map +1 -0
- package/dist/truncate.d.ts +47 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +57 -0
- package/dist/truncate.js.map +1 -0
- package/dist/wcwidth.cjs +86 -0
- package/dist/wcwidth.js +85 -0
- package/dist/wcwidth.js.map +1 -0
- package/dist/wordwrap.cjs +98 -0
- package/dist/wordwrap.js +99 -0
- package/dist/wordwrap.js.map +1 -0
- package/formatter.test.ts +782 -0
- package/formatter.ts +1037 -0
- package/mod.ts +17 -0
- package/package.json +66 -0
- package/terminal.test.ts +67 -0
- package/terminal.ts +94 -0
- package/truncate.test.ts +104 -0
- package/truncate.ts +90 -0
- package/tsdown.config.ts +11 -0
- package/wcwidth.test.ts +60 -0
- package/wcwidth.ts +383 -0
- package/wordwrap.test.ts +110 -0
- package/wordwrap.ts +161 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","names":["defaultWidth: number"],"sources":["../terminal.ts"],"sourcesContent":["import process from \"node:process\";\n\n/**\n * @fileoverview\n * Terminal detection and width calculation utilities\n *\n * Provides cross-runtime compatible functions to detect if the process\n * is attached to a terminal and get the terminal width.\n */\n\n/**\n * Detect if the current process is attached to a terminal (TTY).\n *\n * @returns True if stdout is connected to a terminal\n */\nexport function isTerminal(): boolean {\n try {\n // Deno runtime\n if (typeof Deno !== \"undefined\") {\n // Use modern Deno API\n if (Deno.stdout.isTerminal) {\n return Deno.stdout.isTerminal();\n }\n }\n\n // Node.js/Bun runtime\n if (typeof process !== \"undefined\" && process.stdout) {\n return Boolean(process.stdout.isTTY);\n }\n\n // Browser environment - never a terminal\n if (typeof window !== \"undefined\") {\n return false;\n }\n\n // Unknown environment - assume not a terminal\n return false;\n } catch {\n // If any detection method fails, assume not a terminal\n return false;\n }\n}\n\n/**\n * Get the current terminal width in columns.\n *\n * @returns Terminal width in columns, or null if not available\n */\nexport function getTerminalWidth(): number | null {\n try {\n // Deno runtime\n if (typeof Deno !== \"undefined\") {\n // Try to get console size\n if (Deno.consoleSize) {\n const size = Deno.consoleSize();\n return size?.columns || null;\n }\n }\n\n // Node.js/Bun runtime\n if (typeof process !== \"undefined\" && process.stdout) {\n return process.stdout.columns || null;\n }\n\n // Fallback to environment variable\n const envColumns = typeof Deno !== \"undefined\"\n ? Deno.env.get(\"COLUMNS\")\n : process?.env?.COLUMNS;\n\n if (envColumns) {\n const parsed = parseInt(envColumns, 10);\n return isNaN(parsed) ? null : parsed;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the optimal word wrap width based on terminal detection.\n *\n * @param defaultWidth Default width to use when not in a terminal\n * @returns The optimal width\n */\nexport function getOptimalWordWrapWidth(defaultWidth: number = 80): number {\n if (!isTerminal()) {\n return defaultWidth;\n }\n\n const terminalWidth = getTerminalWidth();\n return terminalWidth || defaultWidth;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,aAAsB;AACpC,KAAI;AAEF,aAAW,SAAS,aAElB;OAAI,KAAK,OAAO,WACd,QAAO,KAAK,OAAO,YAAY;EAChC;AAIH,aAAW,YAAY,eAAe,QAAQ,OAC5C,QAAO,QAAQ,QAAQ,OAAO,MAAM;AAItC,aAAW,WAAW,YACpB,QAAO;AAIT,SAAO;CACR,QAAO;AAEN,SAAO;CACR;AACF;;;;;;AAOD,SAAgB,mBAAkC;AAChD,KAAI;AAEF,aAAW,SAAS,aAElB;OAAI,KAAK,aAAa;IACpB,MAAM,OAAO,KAAK,aAAa;AAC/B,WAAO,MAAM,WAAW;GACzB;;AAIH,aAAW,YAAY,eAAe,QAAQ,OAC5C,QAAO,QAAQ,OAAO,WAAW;EAInC,MAAM,oBAAoB,SAAS,cAC/B,KAAK,IAAI,IAAI,UAAU,GACvB,SAAS,KAAK;AAElB,MAAI,YAAY;GACd,MAAM,SAAS,SAAS,YAAY,GAAG;AACvC,UAAO,MAAM,OAAO,GAAG,OAAO;EAC/B;AAED,SAAO;CACR,QAAO;AACN,SAAO;CACR;AACF;;;;;;;AAQD,SAAgB,wBAAwBA,eAAuB,IAAY;AACzE,MAAK,YAAY,CACf,QAAO;CAGT,MAAM,gBAAgB,kBAAkB;AACxC,QAAO,iBAAiB;AACzB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
|
|
2
|
+
//#region truncate.ts
|
|
3
|
+
/**
|
|
4
|
+
* Truncates a category array to fit within a maximum width using the specified strategy.
|
|
5
|
+
*
|
|
6
|
+
* This function intelligently shortens long hierarchical category names while
|
|
7
|
+
* preserving important context. The truncation behavior depends on the chosen
|
|
8
|
+
* strategy:
|
|
9
|
+
*
|
|
10
|
+
* - `"middle"`: Keeps the first and last segments with "…" in between
|
|
11
|
+
* - `"end"`: Truncates at the end with "…" suffix
|
|
12
|
+
* - `false`: No truncation (returns full category string)
|
|
13
|
+
*
|
|
14
|
+
* When the category is too long even for middle truncation (first + "…" + last
|
|
15
|
+
* exceeds maxWidth), it falls back to end truncation.
|
|
16
|
+
*
|
|
17
|
+
* @param category The category segments to truncate.
|
|
18
|
+
* @param maxWidth Maximum width for the category string.
|
|
19
|
+
* @param separator Category separator (default: ".").
|
|
20
|
+
* @param strategy Truncation strategy to use (default: "middle").
|
|
21
|
+
* @returns The truncated category string.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Middle truncation
|
|
26
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "middle");
|
|
27
|
+
* // Returns: "app…auth"
|
|
28
|
+
*
|
|
29
|
+
* // End truncation
|
|
30
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "end");
|
|
31
|
+
* // Returns: "app.server.h…"
|
|
32
|
+
*
|
|
33
|
+
* // No truncation
|
|
34
|
+
* truncateCategory(["app", "auth"], 20, ".", false);
|
|
35
|
+
* // Returns: "app.auth"
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @since 1.0.0
|
|
39
|
+
*/
|
|
40
|
+
function truncateCategory(category, maxWidth, separator = ".", strategy = "middle") {
|
|
41
|
+
if (!strategy || maxWidth <= 0) return category.join(separator);
|
|
42
|
+
const full = category.join(separator);
|
|
43
|
+
if (full.length <= maxWidth) return full;
|
|
44
|
+
const minWidth = 5;
|
|
45
|
+
if (maxWidth < minWidth) return "…";
|
|
46
|
+
if (strategy === "end") return full.substring(0, maxWidth - 1) + "…";
|
|
47
|
+
if (category.length <= 2) return full.substring(0, maxWidth - 1) + "…";
|
|
48
|
+
const first = category[0];
|
|
49
|
+
const last = category[category.length - 1];
|
|
50
|
+
const ellipsis = "…";
|
|
51
|
+
const minimalLength = first.length + ellipsis.length + last.length;
|
|
52
|
+
if (minimalLength > maxWidth) return full.substring(0, maxWidth - 1) + "…";
|
|
53
|
+
return `${first}${ellipsis}${last}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
exports.truncateCategory = truncateCategory;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region truncate.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Truncation strategies for category names.
|
|
4
|
+
*
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
type TruncationStrategy = "middle" | "end" | false;
|
|
8
|
+
/**
|
|
9
|
+
* Truncates a category array to fit within a maximum width using the specified strategy.
|
|
10
|
+
*
|
|
11
|
+
* This function intelligently shortens long hierarchical category names while
|
|
12
|
+
* preserving important context. The truncation behavior depends on the chosen
|
|
13
|
+
* strategy:
|
|
14
|
+
*
|
|
15
|
+
* - `"middle"`: Keeps the first and last segments with "…" in between
|
|
16
|
+
* - `"end"`: Truncates at the end with "…" suffix
|
|
17
|
+
* - `false`: No truncation (returns full category string)
|
|
18
|
+
*
|
|
19
|
+
* When the category is too long even for middle truncation (first + "…" + last
|
|
20
|
+
* exceeds maxWidth), it falls back to end truncation.
|
|
21
|
+
*
|
|
22
|
+
* @param category The category segments to truncate.
|
|
23
|
+
* @param maxWidth Maximum width for the category string.
|
|
24
|
+
* @param separator Category separator (default: ".").
|
|
25
|
+
* @param strategy Truncation strategy to use (default: "middle").
|
|
26
|
+
* @returns The truncated category string.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Middle truncation
|
|
31
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "middle");
|
|
32
|
+
* // Returns: "app…auth"
|
|
33
|
+
*
|
|
34
|
+
* // End truncation
|
|
35
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "end");
|
|
36
|
+
* // Returns: "app.server.h…"
|
|
37
|
+
*
|
|
38
|
+
* // No truncation
|
|
39
|
+
* truncateCategory(["app", "auth"], 20, ".", false);
|
|
40
|
+
* // Returns: "app.auth"
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @since 1.0.0
|
|
44
|
+
*/
|
|
45
|
+
//#endregion
|
|
46
|
+
export { TruncationStrategy };
|
|
47
|
+
//# sourceMappingURL=truncate.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.d.cts","names":[],"sources":["../truncate.ts"],"sourcesContent":[],"mappings":";;AAKA;;;;KAAY,kBAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region truncate.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Truncation strategies for category names.
|
|
4
|
+
*
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
type TruncationStrategy = "middle" | "end" | false;
|
|
8
|
+
/**
|
|
9
|
+
* Truncates a category array to fit within a maximum width using the specified strategy.
|
|
10
|
+
*
|
|
11
|
+
* This function intelligently shortens long hierarchical category names while
|
|
12
|
+
* preserving important context. The truncation behavior depends on the chosen
|
|
13
|
+
* strategy:
|
|
14
|
+
*
|
|
15
|
+
* - `"middle"`: Keeps the first and last segments with "…" in between
|
|
16
|
+
* - `"end"`: Truncates at the end with "…" suffix
|
|
17
|
+
* - `false`: No truncation (returns full category string)
|
|
18
|
+
*
|
|
19
|
+
* When the category is too long even for middle truncation (first + "…" + last
|
|
20
|
+
* exceeds maxWidth), it falls back to end truncation.
|
|
21
|
+
*
|
|
22
|
+
* @param category The category segments to truncate.
|
|
23
|
+
* @param maxWidth Maximum width for the category string.
|
|
24
|
+
* @param separator Category separator (default: ".").
|
|
25
|
+
* @param strategy Truncation strategy to use (default: "middle").
|
|
26
|
+
* @returns The truncated category string.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Middle truncation
|
|
31
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "middle");
|
|
32
|
+
* // Returns: "app…auth"
|
|
33
|
+
*
|
|
34
|
+
* // End truncation
|
|
35
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "end");
|
|
36
|
+
* // Returns: "app.server.h…"
|
|
37
|
+
*
|
|
38
|
+
* // No truncation
|
|
39
|
+
* truncateCategory(["app", "auth"], 20, ".", false);
|
|
40
|
+
* // Returns: "app.auth"
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @since 1.0.0
|
|
44
|
+
*/
|
|
45
|
+
//#endregion
|
|
46
|
+
export { TruncationStrategy };
|
|
47
|
+
//# sourceMappingURL=truncate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.d.ts","names":[],"sources":["../truncate.ts"],"sourcesContent":[],"mappings":";;AAKA;;;;KAAY,kBAAA"}
|
package/dist/truncate.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//#region truncate.ts
|
|
2
|
+
/**
|
|
3
|
+
* Truncates a category array to fit within a maximum width using the specified strategy.
|
|
4
|
+
*
|
|
5
|
+
* This function intelligently shortens long hierarchical category names while
|
|
6
|
+
* preserving important context. The truncation behavior depends on the chosen
|
|
7
|
+
* strategy:
|
|
8
|
+
*
|
|
9
|
+
* - `"middle"`: Keeps the first and last segments with "…" in between
|
|
10
|
+
* - `"end"`: Truncates at the end with "…" suffix
|
|
11
|
+
* - `false`: No truncation (returns full category string)
|
|
12
|
+
*
|
|
13
|
+
* When the category is too long even for middle truncation (first + "…" + last
|
|
14
|
+
* exceeds maxWidth), it falls back to end truncation.
|
|
15
|
+
*
|
|
16
|
+
* @param category The category segments to truncate.
|
|
17
|
+
* @param maxWidth Maximum width for the category string.
|
|
18
|
+
* @param separator Category separator (default: ".").
|
|
19
|
+
* @param strategy Truncation strategy to use (default: "middle").
|
|
20
|
+
* @returns The truncated category string.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Middle truncation
|
|
25
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "middle");
|
|
26
|
+
* // Returns: "app…auth"
|
|
27
|
+
*
|
|
28
|
+
* // End truncation
|
|
29
|
+
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "end");
|
|
30
|
+
* // Returns: "app.server.h…"
|
|
31
|
+
*
|
|
32
|
+
* // No truncation
|
|
33
|
+
* truncateCategory(["app", "auth"], 20, ".", false);
|
|
34
|
+
* // Returns: "app.auth"
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
*/
|
|
39
|
+
function truncateCategory(category, maxWidth, separator = ".", strategy = "middle") {
|
|
40
|
+
if (!strategy || maxWidth <= 0) return category.join(separator);
|
|
41
|
+
const full = category.join(separator);
|
|
42
|
+
if (full.length <= maxWidth) return full;
|
|
43
|
+
const minWidth = 5;
|
|
44
|
+
if (maxWidth < minWidth) return "…";
|
|
45
|
+
if (strategy === "end") return full.substring(0, maxWidth - 1) + "…";
|
|
46
|
+
if (category.length <= 2) return full.substring(0, maxWidth - 1) + "…";
|
|
47
|
+
const first = category[0];
|
|
48
|
+
const last = category[category.length - 1];
|
|
49
|
+
const ellipsis = "…";
|
|
50
|
+
const minimalLength = first.length + ellipsis.length + last.length;
|
|
51
|
+
if (minimalLength > maxWidth) return full.substring(0, maxWidth - 1) + "…";
|
|
52
|
+
return `${first}${ellipsis}${last}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { truncateCategory };
|
|
57
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.js","names":["category: readonly string[]","maxWidth: number","separator: string","strategy: TruncationStrategy"],"sources":["../truncate.ts"],"sourcesContent":["/**\n * Truncation strategies for category names.\n *\n * @since 1.0.0\n */\nexport type TruncationStrategy = \"middle\" | \"end\" | false;\n\n/**\n * Truncates a category array to fit within a maximum width using the specified strategy.\n *\n * This function intelligently shortens long hierarchical category names while\n * preserving important context. The truncation behavior depends on the chosen\n * strategy:\n *\n * - `\"middle\"`: Keeps the first and last segments with \"…\" in between\n * - `\"end\"`: Truncates at the end with \"…\" suffix\n * - `false`: No truncation (returns full category string)\n *\n * When the category is too long even for middle truncation (first + \"…\" + last\n * exceeds maxWidth), it falls back to end truncation.\n *\n * @param category The category segments to truncate.\n * @param maxWidth Maximum width for the category string.\n * @param separator Category separator (default: \".\").\n * @param strategy Truncation strategy to use (default: \"middle\").\n * @returns The truncated category string.\n *\n * @example\n * ```typescript\n * // Middle truncation\n * truncateCategory([\"app\", \"server\", \"http\", \"auth\"], 15, \".\", \"middle\");\n * // Returns: \"app…auth\"\n *\n * // End truncation\n * truncateCategory([\"app\", \"server\", \"http\", \"auth\"], 15, \".\", \"end\");\n * // Returns: \"app.server.h…\"\n *\n * // No truncation\n * truncateCategory([\"app\", \"auth\"], 20, \".\", false);\n * // Returns: \"app.auth\"\n * ```\n *\n * @since 1.0.0\n */\nexport function truncateCategory(\n category: readonly string[],\n maxWidth: number,\n separator: string = \".\",\n strategy: TruncationStrategy = \"middle\",\n): string {\n if (!strategy || maxWidth <= 0) {\n return category.join(separator);\n }\n\n const full = category.join(separator);\n if (full.length <= maxWidth) {\n return full;\n }\n\n // Minimum width needed for truncation with ellipsis\n const minWidth = 5; // e.g., \"a…z\"\n if (maxWidth < minWidth) {\n return \"…\";\n }\n\n if (strategy === \"end\") {\n return full.substring(0, maxWidth - 1) + \"…\";\n }\n\n // Middle truncation strategy\n if (category.length <= 2) {\n // For short categories, just truncate the end\n return full.substring(0, maxWidth - 1) + \"…\";\n }\n\n // Try to keep first and last segments\n const first = category[0];\n const last = category[category.length - 1];\n const ellipsis = \"…\";\n\n // Check if we can at least fit first…last\n const minimalLength = first.length + ellipsis.length + last.length;\n if (minimalLength > maxWidth) {\n // Even minimal format is too long, fallback to end truncation\n return full.substring(0, maxWidth - 1) + \"…\";\n }\n\n // For simple case with limited space, just do first…last\n return `${first}${ellipsis}${last}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,SAAgB,iBACdA,UACAC,UACAC,YAAoB,KACpBC,WAA+B,UACvB;AACR,MAAK,YAAY,YAAY,EAC3B,QAAO,SAAS,KAAK,UAAU;CAGjC,MAAM,OAAO,SAAS,KAAK,UAAU;AACrC,KAAI,KAAK,UAAU,SACjB,QAAO;CAIT,MAAM,WAAW;AACjB,KAAI,WAAW,SACb,QAAO;AAGT,KAAI,aAAa,MACf,QAAO,KAAK,UAAU,GAAG,WAAW,EAAE,GAAG;AAI3C,KAAI,SAAS,UAAU,EAErB,QAAO,KAAK,UAAU,GAAG,WAAW,EAAE,GAAG;CAI3C,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,SAAS,SAAS,SAAS;CACxC,MAAM,WAAW;CAGjB,MAAM,gBAAgB,MAAM,SAAS,SAAS,SAAS,KAAK;AAC5D,KAAI,gBAAgB,SAElB,QAAO,KAAK,UAAU,GAAG,WAAW,EAAE,GAAG;AAI3C,SAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK;AACnC"}
|
package/dist/wcwidth.cjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
//#region wcwidth.ts
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview
|
|
5
|
+
* wcwidth implementation for JavaScript/TypeScript
|
|
6
|
+
*
|
|
7
|
+
* This module provides functions to calculate the display width of Unicode
|
|
8
|
+
* characters and strings in terminal/monospace contexts, compatible with
|
|
9
|
+
* the Python wcwidth library and POSIX wcwidth() standard.
|
|
10
|
+
*
|
|
11
|
+
* Based on Unicode 15.1.0 character width tables.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Remove all ANSI escape sequences from a string.
|
|
15
|
+
*
|
|
16
|
+
* @param text The string to clean
|
|
17
|
+
* @returns String with ANSI escape sequences removed
|
|
18
|
+
*/
|
|
19
|
+
function stripAnsi(text) {
|
|
20
|
+
return text.replace(/\[[0-9;]*m/g, "");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Calculate the display width of a string, ignoring ANSI escape codes
|
|
24
|
+
* and accounting for Unicode character widths using wcwidth-compatible logic.
|
|
25
|
+
*
|
|
26
|
+
* @param text The string to measure
|
|
27
|
+
* @returns The display width in terminal columns
|
|
28
|
+
*/
|
|
29
|
+
function getDisplayWidth(text) {
|
|
30
|
+
const cleanText = stripAnsi(text);
|
|
31
|
+
if (cleanText.length === 0) return 0;
|
|
32
|
+
let width = 0;
|
|
33
|
+
let i = 0;
|
|
34
|
+
while (i < cleanText.length) {
|
|
35
|
+
const code = cleanText.codePointAt(i);
|
|
36
|
+
if (code === void 0) {
|
|
37
|
+
i++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const charWidth = wcwidth(code);
|
|
41
|
+
if (charWidth >= 0) width += charWidth;
|
|
42
|
+
i += code > 65535 ? 2 : 1;
|
|
43
|
+
}
|
|
44
|
+
return width;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the display width of a single Unicode code point.
|
|
48
|
+
* Based on wcwidth implementation - returns:
|
|
49
|
+
* -1: Non-printable/control character
|
|
50
|
+
* 0: Zero-width character (combining marks, etc.)
|
|
51
|
+
* 1: Normal width character
|
|
52
|
+
* 2: Wide character (East Asian, emoji, etc.)
|
|
53
|
+
*
|
|
54
|
+
* @param code Unicode code point
|
|
55
|
+
* @returns Display width (-1, 0, 1, or 2)
|
|
56
|
+
*/
|
|
57
|
+
function wcwidth(code) {
|
|
58
|
+
if (code < 32 || code >= 127 && code < 160) return -1;
|
|
59
|
+
if (isZeroWidth(code)) return 0;
|
|
60
|
+
if (isWideCharacter(code)) return 2;
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if a character is zero-width (combining marks, etc.)
|
|
65
|
+
* Based on wcwidth's zero-width table.
|
|
66
|
+
*
|
|
67
|
+
* @param code Unicode code point
|
|
68
|
+
* @returns True if the character has zero display width
|
|
69
|
+
*/
|
|
70
|
+
function isZeroWidth(code) {
|
|
71
|
+
return code >= 768 && code <= 879 || code >= 1155 && code <= 1161 || code >= 1425 && code <= 1469 || code === 1471 || code >= 1473 && code <= 1474 || code >= 1476 && code <= 1477 || code === 1479 || code >= 1552 && code <= 1562 || code >= 1611 && code <= 1631 || code === 1648 || code >= 1750 && code <= 1756 || code >= 1759 && code <= 1764 || code >= 1767 && code <= 1768 || code >= 1770 && code <= 1773 || code === 1809 || code >= 1840 && code <= 1866 || code >= 1958 && code <= 1968 || code >= 2027 && code <= 2035 || code === 2045 || code >= 2070 && code <= 2073 || code >= 2075 && code <= 2083 || code >= 2085 && code <= 2087 || code >= 2089 && code <= 2093 || code >= 2137 && code <= 2139 || code >= 2259 && code <= 2273 || code >= 2275 && code <= 2306 || code === 2362 || code === 2364 || code >= 2369 && code <= 2376 || code === 2381 || code >= 2385 && code <= 2391 || code >= 2402 && code <= 2403 || code === 2433 || code === 2492 || code >= 2497 && code <= 2500 || code === 2509 || code >= 2530 && code <= 2531 || code >= 2558 && code <= 2558 || code >= 2561 && code <= 2562 || code === 2620 || code >= 2625 && code <= 2626 || code >= 2631 && code <= 2632 || code >= 2635 && code <= 2637 || code === 2641 || code >= 2672 && code <= 2673 || code === 2677 || code >= 2689 && code <= 2690 || code === 2748 || code >= 2753 && code <= 2757 || code >= 2759 && code <= 2760 || code === 2765 || code >= 2786 && code <= 2787 || code >= 2810 && code <= 2815 || code === 2817 || code === 2876 || code === 2879 || code >= 2881 && code <= 2884 || code === 2893 || code >= 2901 && code <= 2902 || code >= 2914 && code <= 2915 || code === 2946 || code === 3008 || code === 3021 || code === 3072 || code === 3076 || code >= 3134 && code <= 3136 || code >= 3142 && code <= 3144 || code >= 3146 && code <= 3149 || code >= 3157 && code <= 3158 || code >= 3170 && code <= 3171 || code === 3201 || code === 3260 || code === 3263 || code === 3270 || code >= 3276 && code <= 3277 || code >= 3298 && code <= 3299 || code >= 3328 && code <= 3329 || code >= 3387 && code <= 3388 || code === 3393 || code >= 3396 && code <= 3396 || code === 3405 || code >= 3426 && code <= 3427 || code === 3457 || code === 3530 || code >= 3538 && code <= 3540 || code === 3542 || code === 3633 || code >= 3636 && code <= 3642 || code >= 3655 && code <= 3662 || code === 3761 || code >= 3764 && code <= 3772 || code >= 3784 && code <= 3789 || code >= 3864 && code <= 3865 || code === 3893 || code === 3895 || code === 3897 || code >= 3953 && code <= 3966 || code >= 3968 && code <= 3972 || code >= 3974 && code <= 3975 || code >= 3981 && code <= 3991 || code >= 3993 && code <= 4028 || code === 4038 || code >= 4141 && code <= 4144 || code >= 4146 && code <= 4151 || code >= 4153 && code <= 4154 || code >= 4157 && code <= 4158 || code >= 4184 && code <= 4185 || code >= 4190 && code <= 4192 || code >= 4209 && code <= 4212 || code === 4226 || code >= 4229 && code <= 4230 || code === 4237 || code === 4253 || code >= 4957 && code <= 4959 || code >= 5906 && code <= 5908 || code >= 5938 && code <= 5940 || code >= 5970 && code <= 5971 || code >= 6002 && code <= 6003 || code >= 6068 && code <= 6069 || code >= 6071 && code <= 6077 || code === 6086 || code >= 6089 && code <= 6099 || code === 6109 || code >= 6155 && code <= 6157 || code >= 6277 && code <= 6278 || code === 6313 || code >= 6432 && code <= 6434 || code >= 6439 && code <= 6440 || code === 6450 || code >= 6457 && code <= 6459 || code >= 6679 && code <= 6680 || code === 6683 || code === 6742 || code >= 6744 && code <= 6750 || code === 6752 || code === 6754 || code >= 6757 && code <= 6764 || code >= 6771 && code <= 6780 || code === 6783 || code >= 6832 && code <= 6846 || code >= 6912 && code <= 6915 || code === 6964 || code >= 6966 && code <= 6970 || code === 6972 || code === 6978 || code >= 7019 && code <= 7027 || code >= 7040 && code <= 7041 || code >= 7074 && code <= 7077 || code >= 7080 && code <= 7081 || code >= 7083 && code <= 7085 || code === 7142 || code >= 7144 && code <= 7145 || code === 7149 || code >= 7151 && code <= 7153 || code >= 7212 && code <= 7219 || code >= 7222 && code <= 7223 || code >= 7376 && code <= 7378 || code >= 7380 && code <= 7392 || code >= 7394 && code <= 7400 || code === 7405 || code === 7412 || code >= 7416 && code <= 7417 || code >= 7616 && code <= 7673 || code >= 7675 && code <= 7679 || code >= 8203 && code <= 8207 || code >= 8234 && code <= 8238 || code >= 8288 && code <= 8292 || code >= 8294 && code <= 8303 || code === 65279 || code >= 65024 && code <= 65039 || code >= 65056 && code <= 65071;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if a character code point represents a wide character.
|
|
75
|
+
* Based on wcwidth's wide character table (selected ranges from Unicode 15.1.0).
|
|
76
|
+
*
|
|
77
|
+
* @param code Unicode code point
|
|
78
|
+
* @returns True if the character has width 2
|
|
79
|
+
*/
|
|
80
|
+
function isWideCharacter(code) {
|
|
81
|
+
return code >= 4352 && code <= 4447 || code >= 8986 && code <= 8987 || code >= 9001 && code <= 9002 || code >= 9193 && code <= 9196 || code === 9200 || code === 9203 || code >= 9725 && code <= 9726 || code >= 9748 && code <= 9749 || code >= 9800 && code <= 9811 || code === 9855 || code === 9875 || code === 9888 || code === 9889 || code === 9898 || code === 9899 || code >= 9917 && code <= 9918 || code >= 9924 && code <= 9925 || code === 9934 || code === 9940 || code >= 9962 && code <= 9962 || code >= 9970 && code <= 9971 || code === 9973 || code === 9978 || code === 9981 || code >= 9989 && code <= 9989 || code >= 9994 && code <= 9995 || code === 10024 || code === 10060 || code === 10062 || code >= 10067 && code <= 10069 || code === 10071 || code >= 10133 && code <= 10135 || code === 10160 || code === 10175 || code >= 11035 && code <= 11036 || code === 11088 || code === 11093 || code >= 11904 && code <= 11929 || code >= 11931 && code <= 12019 || code >= 12032 && code <= 12245 || code >= 12272 && code <= 12283 || code >= 12288 && code <= 12350 || code >= 12353 && code <= 12438 || code >= 12441 && code <= 12543 || code >= 12549 && code <= 12591 || code >= 12593 && code <= 12686 || code >= 12688 && code <= 12771 || code >= 12784 && code <= 12830 || code >= 12832 && code <= 12871 || code >= 12880 && code <= 19903 || code >= 19968 && code <= 40959 || code >= 43360 && code <= 43391 || code >= 44032 && code <= 55203 || code >= 55216 && code <= 55238 || code >= 63744 && code <= 64255 || code >= 65040 && code <= 65049 || code >= 65072 && code <= 65135 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 94176 && code <= 94180 || code >= 94192 && code <= 94193 || code >= 94208 && code <= 100343 || code >= 100352 && code <= 101589 || code >= 101632 && code <= 101640 || code >= 110576 && code <= 110579 || code >= 110581 && code <= 110587 || code >= 110589 && code <= 110590 || code >= 110592 && code <= 110882 || code >= 110928 && code <= 110930 || code >= 110948 && code <= 110951 || code >= 110960 && code <= 111355 || code === 126980 || code === 127183 || code >= 127374 && code <= 127374 || code >= 127377 && code <= 127386 || code >= 127462 && code <= 127487 || code >= 127488 && code <= 127490 || code >= 127504 && code <= 127547 || code >= 127552 && code <= 127560 || code >= 127568 && code <= 127569 || code >= 127584 && code <= 127589 || code >= 127744 && code <= 128727 || code >= 128736 && code <= 128748 || code >= 128752 && code <= 128764 || code >= 128768 && code <= 128883 || code >= 128896 && code <= 128984 || code >= 128992 && code <= 129003 || code >= 129008 && code <= 129008 || code >= 129024 && code <= 129035 || code >= 129040 && code <= 129095 || code >= 129104 && code <= 129113 || code >= 129120 && code <= 129159 || code >= 129168 && code <= 129197 || code >= 129200 && code <= 129201 || code >= 129280 && code <= 129619 || code >= 129632 && code <= 129645 || code >= 129648 && code <= 129660 || code >= 129664 && code <= 129672 || code >= 129680 && code <= 129725 || code >= 129727 && code <= 129733 || code >= 129742 && code <= 129755 || code >= 129760 && code <= 129768 || code >= 129776 && code <= 129784 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
exports.getDisplayWidth = getDisplayWidth;
|
|
86
|
+
exports.stripAnsi = stripAnsi;
|
package/dist/wcwidth.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region wcwidth.ts
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview
|
|
4
|
+
* wcwidth implementation for JavaScript/TypeScript
|
|
5
|
+
*
|
|
6
|
+
* This module provides functions to calculate the display width of Unicode
|
|
7
|
+
* characters and strings in terminal/monospace contexts, compatible with
|
|
8
|
+
* the Python wcwidth library and POSIX wcwidth() standard.
|
|
9
|
+
*
|
|
10
|
+
* Based on Unicode 15.1.0 character width tables.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Remove all ANSI escape sequences from a string.
|
|
14
|
+
*
|
|
15
|
+
* @param text The string to clean
|
|
16
|
+
* @returns String with ANSI escape sequences removed
|
|
17
|
+
*/
|
|
18
|
+
function stripAnsi(text) {
|
|
19
|
+
return text.replace(/\[[0-9;]*m/g, "");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Calculate the display width of a string, ignoring ANSI escape codes
|
|
23
|
+
* and accounting for Unicode character widths using wcwidth-compatible logic.
|
|
24
|
+
*
|
|
25
|
+
* @param text The string to measure
|
|
26
|
+
* @returns The display width in terminal columns
|
|
27
|
+
*/
|
|
28
|
+
function getDisplayWidth(text) {
|
|
29
|
+
const cleanText = stripAnsi(text);
|
|
30
|
+
if (cleanText.length === 0) return 0;
|
|
31
|
+
let width = 0;
|
|
32
|
+
let i = 0;
|
|
33
|
+
while (i < cleanText.length) {
|
|
34
|
+
const code = cleanText.codePointAt(i);
|
|
35
|
+
if (code === void 0) {
|
|
36
|
+
i++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const charWidth = wcwidth(code);
|
|
40
|
+
if (charWidth >= 0) width += charWidth;
|
|
41
|
+
i += code > 65535 ? 2 : 1;
|
|
42
|
+
}
|
|
43
|
+
return width;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the display width of a single Unicode code point.
|
|
47
|
+
* Based on wcwidth implementation - returns:
|
|
48
|
+
* -1: Non-printable/control character
|
|
49
|
+
* 0: Zero-width character (combining marks, etc.)
|
|
50
|
+
* 1: Normal width character
|
|
51
|
+
* 2: Wide character (East Asian, emoji, etc.)
|
|
52
|
+
*
|
|
53
|
+
* @param code Unicode code point
|
|
54
|
+
* @returns Display width (-1, 0, 1, or 2)
|
|
55
|
+
*/
|
|
56
|
+
function wcwidth(code) {
|
|
57
|
+
if (code < 32 || code >= 127 && code < 160) return -1;
|
|
58
|
+
if (isZeroWidth(code)) return 0;
|
|
59
|
+
if (isWideCharacter(code)) return 2;
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if a character is zero-width (combining marks, etc.)
|
|
64
|
+
* Based on wcwidth's zero-width table.
|
|
65
|
+
*
|
|
66
|
+
* @param code Unicode code point
|
|
67
|
+
* @returns True if the character has zero display width
|
|
68
|
+
*/
|
|
69
|
+
function isZeroWidth(code) {
|
|
70
|
+
return code >= 768 && code <= 879 || code >= 1155 && code <= 1161 || code >= 1425 && code <= 1469 || code === 1471 || code >= 1473 && code <= 1474 || code >= 1476 && code <= 1477 || code === 1479 || code >= 1552 && code <= 1562 || code >= 1611 && code <= 1631 || code === 1648 || code >= 1750 && code <= 1756 || code >= 1759 && code <= 1764 || code >= 1767 && code <= 1768 || code >= 1770 && code <= 1773 || code === 1809 || code >= 1840 && code <= 1866 || code >= 1958 && code <= 1968 || code >= 2027 && code <= 2035 || code === 2045 || code >= 2070 && code <= 2073 || code >= 2075 && code <= 2083 || code >= 2085 && code <= 2087 || code >= 2089 && code <= 2093 || code >= 2137 && code <= 2139 || code >= 2259 && code <= 2273 || code >= 2275 && code <= 2306 || code === 2362 || code === 2364 || code >= 2369 && code <= 2376 || code === 2381 || code >= 2385 && code <= 2391 || code >= 2402 && code <= 2403 || code === 2433 || code === 2492 || code >= 2497 && code <= 2500 || code === 2509 || code >= 2530 && code <= 2531 || code >= 2558 && code <= 2558 || code >= 2561 && code <= 2562 || code === 2620 || code >= 2625 && code <= 2626 || code >= 2631 && code <= 2632 || code >= 2635 && code <= 2637 || code === 2641 || code >= 2672 && code <= 2673 || code === 2677 || code >= 2689 && code <= 2690 || code === 2748 || code >= 2753 && code <= 2757 || code >= 2759 && code <= 2760 || code === 2765 || code >= 2786 && code <= 2787 || code >= 2810 && code <= 2815 || code === 2817 || code === 2876 || code === 2879 || code >= 2881 && code <= 2884 || code === 2893 || code >= 2901 && code <= 2902 || code >= 2914 && code <= 2915 || code === 2946 || code === 3008 || code === 3021 || code === 3072 || code === 3076 || code >= 3134 && code <= 3136 || code >= 3142 && code <= 3144 || code >= 3146 && code <= 3149 || code >= 3157 && code <= 3158 || code >= 3170 && code <= 3171 || code === 3201 || code === 3260 || code === 3263 || code === 3270 || code >= 3276 && code <= 3277 || code >= 3298 && code <= 3299 || code >= 3328 && code <= 3329 || code >= 3387 && code <= 3388 || code === 3393 || code >= 3396 && code <= 3396 || code === 3405 || code >= 3426 && code <= 3427 || code === 3457 || code === 3530 || code >= 3538 && code <= 3540 || code === 3542 || code === 3633 || code >= 3636 && code <= 3642 || code >= 3655 && code <= 3662 || code === 3761 || code >= 3764 && code <= 3772 || code >= 3784 && code <= 3789 || code >= 3864 && code <= 3865 || code === 3893 || code === 3895 || code === 3897 || code >= 3953 && code <= 3966 || code >= 3968 && code <= 3972 || code >= 3974 && code <= 3975 || code >= 3981 && code <= 3991 || code >= 3993 && code <= 4028 || code === 4038 || code >= 4141 && code <= 4144 || code >= 4146 && code <= 4151 || code >= 4153 && code <= 4154 || code >= 4157 && code <= 4158 || code >= 4184 && code <= 4185 || code >= 4190 && code <= 4192 || code >= 4209 && code <= 4212 || code === 4226 || code >= 4229 && code <= 4230 || code === 4237 || code === 4253 || code >= 4957 && code <= 4959 || code >= 5906 && code <= 5908 || code >= 5938 && code <= 5940 || code >= 5970 && code <= 5971 || code >= 6002 && code <= 6003 || code >= 6068 && code <= 6069 || code >= 6071 && code <= 6077 || code === 6086 || code >= 6089 && code <= 6099 || code === 6109 || code >= 6155 && code <= 6157 || code >= 6277 && code <= 6278 || code === 6313 || code >= 6432 && code <= 6434 || code >= 6439 && code <= 6440 || code === 6450 || code >= 6457 && code <= 6459 || code >= 6679 && code <= 6680 || code === 6683 || code === 6742 || code >= 6744 && code <= 6750 || code === 6752 || code === 6754 || code >= 6757 && code <= 6764 || code >= 6771 && code <= 6780 || code === 6783 || code >= 6832 && code <= 6846 || code >= 6912 && code <= 6915 || code === 6964 || code >= 6966 && code <= 6970 || code === 6972 || code === 6978 || code >= 7019 && code <= 7027 || code >= 7040 && code <= 7041 || code >= 7074 && code <= 7077 || code >= 7080 && code <= 7081 || code >= 7083 && code <= 7085 || code === 7142 || code >= 7144 && code <= 7145 || code === 7149 || code >= 7151 && code <= 7153 || code >= 7212 && code <= 7219 || code >= 7222 && code <= 7223 || code >= 7376 && code <= 7378 || code >= 7380 && code <= 7392 || code >= 7394 && code <= 7400 || code === 7405 || code === 7412 || code >= 7416 && code <= 7417 || code >= 7616 && code <= 7673 || code >= 7675 && code <= 7679 || code >= 8203 && code <= 8207 || code >= 8234 && code <= 8238 || code >= 8288 && code <= 8292 || code >= 8294 && code <= 8303 || code === 65279 || code >= 65024 && code <= 65039 || code >= 65056 && code <= 65071;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if a character code point represents a wide character.
|
|
74
|
+
* Based on wcwidth's wide character table (selected ranges from Unicode 15.1.0).
|
|
75
|
+
*
|
|
76
|
+
* @param code Unicode code point
|
|
77
|
+
* @returns True if the character has width 2
|
|
78
|
+
*/
|
|
79
|
+
function isWideCharacter(code) {
|
|
80
|
+
return code >= 4352 && code <= 4447 || code >= 8986 && code <= 8987 || code >= 9001 && code <= 9002 || code >= 9193 && code <= 9196 || code === 9200 || code === 9203 || code >= 9725 && code <= 9726 || code >= 9748 && code <= 9749 || code >= 9800 && code <= 9811 || code === 9855 || code === 9875 || code === 9888 || code === 9889 || code === 9898 || code === 9899 || code >= 9917 && code <= 9918 || code >= 9924 && code <= 9925 || code === 9934 || code === 9940 || code >= 9962 && code <= 9962 || code >= 9970 && code <= 9971 || code === 9973 || code === 9978 || code === 9981 || code >= 9989 && code <= 9989 || code >= 9994 && code <= 9995 || code === 10024 || code === 10060 || code === 10062 || code >= 10067 && code <= 10069 || code === 10071 || code >= 10133 && code <= 10135 || code === 10160 || code === 10175 || code >= 11035 && code <= 11036 || code === 11088 || code === 11093 || code >= 11904 && code <= 11929 || code >= 11931 && code <= 12019 || code >= 12032 && code <= 12245 || code >= 12272 && code <= 12283 || code >= 12288 && code <= 12350 || code >= 12353 && code <= 12438 || code >= 12441 && code <= 12543 || code >= 12549 && code <= 12591 || code >= 12593 && code <= 12686 || code >= 12688 && code <= 12771 || code >= 12784 && code <= 12830 || code >= 12832 && code <= 12871 || code >= 12880 && code <= 19903 || code >= 19968 && code <= 40959 || code >= 43360 && code <= 43391 || code >= 44032 && code <= 55203 || code >= 55216 && code <= 55238 || code >= 63744 && code <= 64255 || code >= 65040 && code <= 65049 || code >= 65072 && code <= 65135 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 94176 && code <= 94180 || code >= 94192 && code <= 94193 || code >= 94208 && code <= 100343 || code >= 100352 && code <= 101589 || code >= 101632 && code <= 101640 || code >= 110576 && code <= 110579 || code >= 110581 && code <= 110587 || code >= 110589 && code <= 110590 || code >= 110592 && code <= 110882 || code >= 110928 && code <= 110930 || code >= 110948 && code <= 110951 || code >= 110960 && code <= 111355 || code === 126980 || code === 127183 || code >= 127374 && code <= 127374 || code >= 127377 && code <= 127386 || code >= 127462 && code <= 127487 || code >= 127488 && code <= 127490 || code >= 127504 && code <= 127547 || code >= 127552 && code <= 127560 || code >= 127568 && code <= 127569 || code >= 127584 && code <= 127589 || code >= 127744 && code <= 128727 || code >= 128736 && code <= 128748 || code >= 128752 && code <= 128764 || code >= 128768 && code <= 128883 || code >= 128896 && code <= 128984 || code >= 128992 && code <= 129003 || code >= 129008 && code <= 129008 || code >= 129024 && code <= 129035 || code >= 129040 && code <= 129095 || code >= 129104 && code <= 129113 || code >= 129120 && code <= 129159 || code >= 129168 && code <= 129197 || code >= 129200 && code <= 129201 || code >= 129280 && code <= 129619 || code >= 129632 && code <= 129645 || code >= 129648 && code <= 129660 || code >= 129664 && code <= 129672 || code >= 129680 && code <= 129725 || code >= 129727 && code <= 129733 || code >= 129742 && code <= 129755 || code >= 129760 && code <= 129768 || code >= 129776 && code <= 129784 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
84
|
+
export { getDisplayWidth, stripAnsi };
|
|
85
|
+
//# sourceMappingURL=wcwidth.js.map
|
|
@@ -0,0 +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,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QACT,SAAS,QACR,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,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,QACR,QAAQ,QAAU,QAAQ,QAC1B,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,QAC3B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC3B,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,QAC3B,SAAS,QACR,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,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,SACR,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ;AAE9B;;;;;;;;AASD,SAAS,gBAAgBA,MAAuB;AAC9C,QAEG,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAAU,SAAS,QAC3B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAAU,SAAS,QAC5B,SAAS,QAAU,SAAS,QAAU,SAAS,QAAU,SAAS,QACjE,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAAU,SAAS,QAC3B,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,QAAU,SAAS,QAC5B,SAAS,QACR,QAAQ,QAAU,QAAQ,QAC1B,QAAQ,QAAU,QAAQ,QAC3B,SAAS,SACT,SAAS,SACT,SAAS,SACR,QAAQ,SAAU,QAAQ,SAC3B,SAAS,SACR,QAAQ,SAAU,QAAQ,SAC3B,SAAS,SAAU,SAAS,SAC3B,QAAQ,SAAU,QAAQ,SAC3B,SAAS,SAAU,SAAS,SAC3B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAU,QAAQ,SAC1B,QAAQ,SAAW,QAAQ,SAC3B,QAAQ,SAAW,QAAQ,SAC3B,QAAQ,SAAW,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,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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const require_wcwidth = require('./wcwidth.cjs');
|
|
2
|
+
|
|
3
|
+
//#region wordwrap.ts
|
|
4
|
+
/**
|
|
5
|
+
* Wrap text at specified width with proper indentation for continuation lines.
|
|
6
|
+
* Automatically detects the message start position from the first line.
|
|
7
|
+
*
|
|
8
|
+
* @param text The text to wrap (may contain ANSI escape codes)
|
|
9
|
+
* @param maxWidth Maximum width in terminal columns
|
|
10
|
+
* @param messageContent The plain message content (used to find message start)
|
|
11
|
+
* @returns Wrapped text with proper indentation
|
|
12
|
+
*/
|
|
13
|
+
function wrapText(text, maxWidth, messageContent) {
|
|
14
|
+
if (maxWidth <= 0) return text;
|
|
15
|
+
const displayWidth = require_wcwidth.getDisplayWidth(text);
|
|
16
|
+
if (displayWidth <= maxWidth && !text.includes("\n")) return text;
|
|
17
|
+
const firstLineWords = messageContent.split(" ");
|
|
18
|
+
const firstWord = firstLineWords[0];
|
|
19
|
+
const plainText = require_wcwidth.stripAnsi(text);
|
|
20
|
+
const messageStartIndex = plainText.indexOf(firstWord);
|
|
21
|
+
let indentWidth = 0;
|
|
22
|
+
if (messageStartIndex >= 0) {
|
|
23
|
+
const prefixText = plainText.slice(0, messageStartIndex);
|
|
24
|
+
indentWidth = require_wcwidth.getDisplayWidth(prefixText);
|
|
25
|
+
}
|
|
26
|
+
const indent = " ".repeat(Math.max(0, indentWidth));
|
|
27
|
+
if (text.includes("\n")) {
|
|
28
|
+
const lines = text.split("\n");
|
|
29
|
+
const wrappedLines = [];
|
|
30
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31
|
+
const line = lines[i];
|
|
32
|
+
const lineDisplayWidth = require_wcwidth.getDisplayWidth(line);
|
|
33
|
+
if (lineDisplayWidth <= maxWidth) if (i === 0) wrappedLines.push(line);
|
|
34
|
+
else wrappedLines.push(indent + line);
|
|
35
|
+
else {
|
|
36
|
+
const wrappedLine = wrapSingleLine(line, maxWidth, indent);
|
|
37
|
+
if (i === 0) wrappedLines.push(wrappedLine);
|
|
38
|
+
else {
|
|
39
|
+
const subLines = wrappedLine.split("\n");
|
|
40
|
+
for (let j = 0; j < subLines.length; j++) if (j === 0) wrappedLines.push(indent + subLines[j]);
|
|
41
|
+
else wrappedLines.push(subLines[j]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return wrappedLines.join("\n");
|
|
46
|
+
}
|
|
47
|
+
return wrapSingleLine(text, maxWidth, indent);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Wrap a single line of text (without existing newlines) at word boundaries.
|
|
51
|
+
* Preserves ANSI escape codes and handles Unicode character widths correctly.
|
|
52
|
+
*
|
|
53
|
+
* @param text The text to wrap (single line, may contain ANSI codes)
|
|
54
|
+
* @param maxWidth Maximum width in terminal columns
|
|
55
|
+
* @param indent Indentation string for continuation lines
|
|
56
|
+
* @returns Wrapped text with newlines and proper indentation
|
|
57
|
+
*/
|
|
58
|
+
function wrapSingleLine(text, maxWidth, indent) {
|
|
59
|
+
const lines = [];
|
|
60
|
+
let currentLine = "";
|
|
61
|
+
let currentDisplayWidth = 0;
|
|
62
|
+
let i = 0;
|
|
63
|
+
while (i < text.length) {
|
|
64
|
+
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
65
|
+
let j = i + 2;
|
|
66
|
+
while (j < text.length && text[j] !== "m") j++;
|
|
67
|
+
if (j < text.length) {
|
|
68
|
+
j++;
|
|
69
|
+
currentLine += text.slice(i, j);
|
|
70
|
+
i = j;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const char = text[i];
|
|
75
|
+
if (currentDisplayWidth >= maxWidth && char !== " ") {
|
|
76
|
+
const breakPoint = currentLine.lastIndexOf(" ");
|
|
77
|
+
if (breakPoint > 0) {
|
|
78
|
+
lines.push(currentLine.slice(0, breakPoint));
|
|
79
|
+
currentLine = indent + currentLine.slice(breakPoint + 1) + char;
|
|
80
|
+
currentDisplayWidth = require_wcwidth.getDisplayWidth(currentLine);
|
|
81
|
+
} else {
|
|
82
|
+
lines.push(currentLine);
|
|
83
|
+
currentLine = indent + char;
|
|
84
|
+
currentDisplayWidth = require_wcwidth.getDisplayWidth(currentLine);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
currentLine += char;
|
|
88
|
+
currentDisplayWidth = require_wcwidth.getDisplayWidth(currentLine);
|
|
89
|
+
}
|
|
90
|
+
i++;
|
|
91
|
+
}
|
|
92
|
+
if (currentLine.trim()) lines.push(currentLine);
|
|
93
|
+
const filteredLines = lines.filter((line) => line.trim().length > 0);
|
|
94
|
+
return filteredLines.join("\n");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
exports.wrapText = wrapText;
|