From 0aa530f9445a155ca288854fb5fe167af604dba1 Mon Sep 17 00:00:00 2001 From: s-tanaka Date: Sat, 20 Nov 2021 22:32:41 +0900 Subject: [PATCH 1/7] Add ambiguousIsNarrow option --- index.d.ts | 6 +++++- index.js | 20 +++++++++++++------- package.json | 2 +- test.js | 2 ++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index f595679..3ff42c5 100644 --- a/index.d.ts +++ b/index.d.ts @@ -17,4 +17,8 @@ stringWidth('\u001B[1m古\u001B[22m'); //=> 2 ``` */ -export default function stringWidth(string: string): number; +export interface Options { + ambiguousIsNarrow: boolean; +} + +export default function stringWidth(string: string, options?: Options): number; diff --git a/index.js b/index.js index 155645b..806682e 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,8 @@ import stripAnsi from 'strip-ansi'; -import isFullwidthCodePoint from 'is-fullwidth-code-point'; +import eaw from 'eastasianwidth'; import emojiRegex from 'emoji-regex'; -export default function stringWidth(string) { +export default function stringWidth(string, options = {}) { if (typeof string !== 'string' || string.length === 0) { return 0; } @@ -30,12 +30,18 @@ export default function stringWidth(string) { continue; } - // Surrogates - if (codePoint > 0xFFFF) { - index++; + const code = eaw.eastAsianWidth(string.charAt(index)); + switch (code) { + case 'F': + case 'W': + width += 2; + break; + case 'A': + width += options.ambiguousIsNarrow ? 1 : 2; + break; + default: + width += 1; } - - width += isFullwidthCodePoint(codePoint) ? 2 : 1; } return width; diff --git a/package.json b/package.json index 6d729c3..248b435 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "fixed-width" ], "dependencies": { + "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", - "is-fullwidth-code-point": "^4.0.0", "strip-ansi": "^7.0.1" }, "devDependencies": { diff --git a/test.js b/test.js index cc1f570..c12fa8e 100644 --- a/test.js +++ b/test.js @@ -5,6 +5,8 @@ test('main', t => { t.is(stringWidth('abcde'), 5); t.is(stringWidth('古池や'), 6); t.is(stringWidth('あいうabc'), 9); + t.is(stringWidth('あいう★'), 8); + t.is(stringWidth('あいう★', {ambiguousIsNarrow: true}), 7); t.is(stringWidth('ノード.js'), 9); t.is(stringWidth('你好'), 4); t.is(stringWidth('안녕하세요'), 10); From d128670f311348a58a8d1620ab30ebe0fb7c0617 Mon Sep 17 00:00:00 2001 From: "seito.tanaka" Date: Sat, 8 Jan 2022 07:40:07 +0900 Subject: [PATCH 2/7] Add doc comment --- index.d.ts | 13 +++++++++---- index.test-d.ts | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index 3ff42c5..3c8f101 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,12 @@ +export interface Options { + /** + Count [Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous) as a width of 1, false counts as 2. + + @default false + */ + readonly ambiguousIsNarrow: boolean; +} + /** Get the visual width of a string - the number of columns required to display it. @@ -17,8 +26,4 @@ stringWidth('\u001B[1m古\u001B[22m'); //=> 2 ``` */ -export interface Options { - ambiguousIsNarrow: boolean; -} - export default function stringWidth(string: string, options?: Options): number; diff --git a/index.test-d.ts b/index.test-d.ts index 450ea7c..a713789 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -2,3 +2,5 @@ import {expectType} from 'tsd'; import stringWidth from './index.js'; expectType(stringWidth('古')); + +expectType(stringWidth('★', {ambiguousIsNarrow: true})); From a652998aafc2f3af2eccbc17d39b197b0f6fe8b3 Mon Sep 17 00:00:00 2001 From: "seito.tanaka" Date: Sat, 8 Jan 2022 07:43:31 +0900 Subject: [PATCH 3/7] Rename import --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 806682e..c73ca22 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ import stripAnsi from 'strip-ansi'; -import eaw from 'eastasianwidth'; +import eastAsianWidth from 'eastasianwidth'; import emojiRegex from 'emoji-regex'; export default function stringWidth(string, options = {}) { @@ -30,7 +30,7 @@ export default function stringWidth(string, options = {}) { continue; } - const code = eaw.eastAsianWidth(string.charAt(index)); + const code = eastAsianWidth.eastAsianWidth(string.charAt(index)); switch (code) { case 'F': case 'W': From 49a74832bdd08c7323caa48aee3cd7c44a41585b Mon Sep 17 00:00:00 2001 From: Seito Tanaka Date: Sat, 8 Jan 2022 16:55:22 +0900 Subject: [PATCH 4/7] Update index.d.ts Co-authored-by: Sindre Sorhus --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 3c8f101..6b3dc5d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,6 @@ export interface Options { /** - Count [Ambiguous characters](https://www.unicode.org/reports/tr11/#Ambiguous) as a width of 1, false counts as 2. + Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide (count of 2). @default false */ From 8e5b85edfcef497b729e4352e06bf094f3e8aa33 Mon Sep 17 00:00:00 2001 From: "seito.tanaka" Date: Sat, 8 Jan 2022 17:03:41 +0900 Subject: [PATCH 5/7] Determine the number of ambiguous characters outside the loop --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index c73ca22..35882b0 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,7 @@ export default function stringWidth(string, options = {}) { string = string.replace(emojiRegex(), ' '); + const ambiguousCharWidth = options.ambiguousIsNarrow ? 1 : 2; let width = 0; for (let index = 0; index < string.length; index++) { @@ -37,7 +38,7 @@ export default function stringWidth(string, options = {}) { width += 2; break; case 'A': - width += options.ambiguousIsNarrow ? 1 : 2; + width += ambiguousCharWidth; break; default: width += 1; From ffb6fe309a7ae5b0aece8fb867c66b4f53ba6706 Mon Sep 17 00:00:00 2001 From: "seito.tanaka" Date: Sat, 8 Jan 2022 17:19:56 +0900 Subject: [PATCH 6/7] Add API doc to README.md --- index.d.ts | 2 +- readme.md | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 6b3dc5d..d8da3ce 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,6 @@ export interface Options { /** - Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide (count of 2). + Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide width (count of 2). @default false */ diff --git a/readme.md b/readme.md index 3a15864..4de084b 100644 --- a/readme.md +++ b/readme.md @@ -27,6 +27,27 @@ stringWidth('\u001B[1m古\u001B[22m'); //=> 2 ``` +## API + +### stringWidth(string, options?) + +#### string + +Type: `string` + +The string to be counted. + +#### options + +Type: `object` + +##### ambiguousIsNarrow + +Type: `boolean`\ +Default: `false` + +Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide (count of 2). + ## Related - [string-width-cli](https://github.com/sindresorhus/string-width-cli) - CLI for this module From 901f65a1666c9ea19e2768b720b5525151dea8b0 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 9 Jan 2022 12:57:14 +0700 Subject: [PATCH 7/7] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4de084b..52910df 100644 --- a/readme.md +++ b/readme.md @@ -46,7 +46,7 @@ Type: `object` Type: `boolean`\ Default: `false` -Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide (count of 2). +Count [ambiguous width characters](https://www.unicode.org/reports/tr11/#Ambiguous) as having narrow width (count of 1) instead of wide width (count of 2). ## Related