string-width
Advanced tools
+33
-3
@@ -10,3 +10,4 @@ import stripAnsi from 'strip-ansi'; | ||
| 2. RGI emoji clusters (\p{RGI_Emoji}) are double-width. | ||
| 3. Otherwise use East Asian Width of the cluster’s first visible code point, and add widths for trailing Halfwidth/Fullwidth Forms within the same cluster (e.g., dakuten/handakuten/prolonged sound mark). | ||
| 3. Minimally-qualified/unqualified emoji clusters (ZWJ sequences with 2+ Extended_Pictographic, or keycap sequences) are double-width. | ||
| 4. Otherwise use East Asian Width of the cluster's first visible code point, and add widths for trailing Halfwidth/Fullwidth Forms within the same cluster (e.g., dakuten/handakuten/prolonged sound mark). | ||
| */ | ||
@@ -25,2 +26,25 @@ | ||
| // Detect minimally-qualified/unqualified emoji sequences (missing VS16 but still render as double-width) | ||
| const unqualifiedKeycapRegex = /^[\d#*]\u20E3$/; | ||
| const extendedPictographicRegex = /\p{Extended_Pictographic}/gu; | ||
| function isDoubleWidthNonRgiEmojiSequence(segment) { | ||
| // Real emoji clusters are < 30 chars; guard against pathological input | ||
| if (segment.length > 50) { | ||
| return false; | ||
| } | ||
| if (unqualifiedKeycapRegex.test(segment)) { | ||
| return true; | ||
| } | ||
| // ZWJ sequences with 2+ Extended_Pictographic | ||
| if (segment.includes('\u200D')) { | ||
| const pictographics = segment.match(extendedPictographicRegex); | ||
| return pictographics !== null && pictographics.length >= 2; | ||
| } | ||
| return false; | ||
| } | ||
| function baseVisible(segment) { | ||
@@ -59,3 +83,4 @@ return segment.replace(leadingNonPrintingRegex, ''); | ||
| if (!countAnsiEscapeCodes) { | ||
| // Avoid calling stripAnsi when there are no ANSI escape sequences (ESC = 0x1B, CSI = 0x9B) | ||
| if (!countAnsiEscapeCodes && (string.includes('\u001B') || string.includes('\u009B'))) { | ||
| string = stripAnsi(string); | ||
@@ -68,2 +93,7 @@ } | ||
| // Fast path: printable ASCII (0x20–0x7E) needs no segmenter, regex, or EAW lookup — width equals length. | ||
| if (/^[\u0020-\u007E]*$/.test(string)) { | ||
| return string.length; | ||
| } | ||
| let width = 0; | ||
@@ -79,3 +109,3 @@ const eastAsianWidthOptions = {ambiguousAsWide: !ambiguousIsNarrow}; | ||
| // Emoji width logic | ||
| if (rgiEmojiRegex.test(segment)) { | ||
| if (rgiEmojiRegex.test(segment) || isDoubleWidthNonRgiEmojiSequence(segment)) { | ||
| width += 2; | ||
@@ -82,0 +112,0 @@ continue; |
+4
-4
| { | ||
| "name": "string-width", | ||
| "version": "8.1.1", | ||
| "version": "8.2.0", | ||
| "description": "Get the visual width of a string - the number of columns required to display it", | ||
@@ -57,4 +57,4 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "get-east-asian-width": "^1.3.0", | ||
| "strip-ansi": "^7.1.0" | ||
| "get-east-asian-width": "^1.5.0", | ||
| "strip-ansi": "^7.1.2" | ||
| }, | ||
@@ -64,4 +64,4 @@ "devDependencies": { | ||
| "tsd": "^0.33.0", | ||
| "xo": "^1.2.2" | ||
| "xo": "^1.2.3" | ||
| } | ||
| } |
+1
-1
@@ -5,3 +5,3 @@ # string-width | ||
| Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width. | ||
| Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and do not affect the width. | ||
@@ -8,0 +8,0 @@ Useful to be able to measure the actual width of command-line output. |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
9253
14.96%123
24.24%2
100%Updated
Updated