Skip to content

Commit 01e5074

Browse files
addaleaxBridgeAR
authored andcommitted
console: use getStringWidth() for character width calculation
This is more accurate for displayed full-width characters (e.g. CJK ones) and makes the calculations match the ones we use in the readline module. Fixes: #29299 PR-URL: #29300 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Tobias NieรŸen <tniessen@tnie.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 0bd6527 commit 01e5074

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

โ€Žlib/internal/cli_table.jsโ€Ž

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
const { Math, ObjectPrototype } = primordials;
44

5-
const { Buffer } = require('buffer');
6-
const { removeColors } = require('internal/util');
5+
const { getStringWidth } = require('internal/readline/utils');
76

87
// The use of Unicode characters below is the only non-comment use of non-ASCII
98
// Unicode characters in Node.js built-in modules. If they are ever removed or
@@ -29,16 +28,11 @@ const tableChars = {
2928
/* eslint-enable node-core/non-ascii-character */
3029
};
3130

32-
const countSymbols = (string) => {
33-
const normalized = removeColors(string).normalize('NFC');
34-
return Buffer.from(normalized, 'UCS-2').byteLength / 2;
35-
};
36-
3731
const renderRow = (row, columnWidths) => {
3832
let out = tableChars.left;
3933
for (var i = 0; i < row.length; i++) {
4034
const cell = row[i];
41-
const len = countSymbols(cell);
35+
const len = getStringWidth(cell);
4236
const needed = (columnWidths[i] - len) / 2;
4337
// round(needed) + ceil(needed) will always add up to the amount
4438
// of spaces we need while also left justifying the output.
@@ -52,7 +46,7 @@ const renderRow = (row, columnWidths) => {
5246

5347
const table = (head, columns) => {
5448
const rows = [];
55-
const columnWidths = head.map((h) => countSymbols(h));
49+
const columnWidths = head.map((h) => getStringWidth(h));
5650
const longestColumn = columns.reduce((n, a) => Math.max(n, a.length), 0);
5751

5852
for (var i = 0; i < head.length; i++) {
@@ -63,7 +57,7 @@ const table = (head, columns) => {
6357
const value = rows[j][i] =
6458
ObjectPrototype.hasOwnProperty(column, j) ? column[j] : '';
6559
const width = columnWidths[i] || 0;
66-
const counted = countSymbols(value);
60+
const counted = getStringWidth(value);
6761
columnWidths[i] = Math.max(width, counted);
6862
}
6963
}

โ€Žtest/parallel/test-console-table.jsโ€Ž

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,21 @@ test([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], `
258258
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€${line}โ”€โ”€โ”˜
259259
`);
260260
}
261+
262+
test({ foo: '๏ฟฅ', bar: 'ยฅ' }, `
263+
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
264+
โ”‚ (index) โ”‚ Values โ”‚
265+
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
266+
โ”‚ foo โ”‚ '๏ฟฅ' โ”‚
267+
โ”‚ bar โ”‚ 'ยฅ' โ”‚
268+
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
269+
`);
270+
271+
test({ foo: 'ไฝ ๅฅฝ', bar: 'hello' }, `
272+
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
273+
โ”‚ (index) โ”‚ Values โ”‚
274+
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
275+
โ”‚ foo โ”‚ 'ไฝ ๅฅฝ' โ”‚
276+
โ”‚ bar โ”‚ 'hello' โ”‚
277+
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
278+
`);

0 commit comments

Comments
ย (0)