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)