Skip to content
Permalink
Browse files

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>
  • Loading branch information...
addaleax authored and BridgeAR committed Aug 24, 2019
1 parent f8f3af0 commit 2489682eb54832df00f33d644975cd67af967481
Showing with 22 additions and 10 deletions.
  1. +4 −10 lib/internal/cli_table.js
  2. +18 −0 test/parallel/test-console-table.js
@@ -2,8 +2,7 @@

const { Math, ObjectPrototype } = primordials;

const { Buffer } = require('buffer');
const { removeColors } = require('internal/util');
const { getStringWidth } = require('internal/readline/utils');

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

const countSymbols = (string) => {
const normalized = removeColors(string).normalize('NFC');
return Buffer.from(normalized, 'UCS-2').byteLength / 2;
};

const renderRow = (row, columnWidths) => {
let out = tableChars.left;
for (var i = 0; i < row.length; i++) {
const cell = row[i];
const len = countSymbols(cell);
const len = getStringWidth(cell);
const needed = (columnWidths[i] - len) / 2;
// round(needed) + ceil(needed) will always add up to the amount
// of spaces we need while also left justifying the output.
@@ -52,7 +46,7 @@ const renderRow = (row, columnWidths) => {

const table = (head, columns) => {
const rows = [];
const columnWidths = head.map((h) => countSymbols(h));
const columnWidths = head.map((h) => getStringWidth(h));
const longestColumn = columns.reduce((n, a) => Math.max(n, a.length), 0);

for (var i = 0; i < head.length; i++) {
@@ -63,7 +57,7 @@ const table = (head, columns) => {
const value = rows[j][i] =
ObjectPrototype.hasOwnProperty(column, j) ? column[j] : '';
const width = columnWidths[i] || 0;
const counted = countSymbols(value);
const counted = getStringWidth(value);
columnWidths[i] = Math.max(width, counted);
}
}
@@ -258,3 +258,21 @@ test([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], `
└─────────┴──${line}──┘
`);
}

test({ foo: '', bar: '¥' }, `
┌─────────┬────────┐
│ (index) │ Values │
├─────────┼────────┤
│ foo │ '¥' │
│ bar │ '¥' │
└─────────┴────────┘
`);

test({ foo: '你好', bar: 'hello' }, `
┌─────────┬─────────┐
│ (index) │ Values │
├─────────┼─────────┤
│ foo │ '你好' │
│ bar │ 'hello' │
└─────────┴─────────┘
`);

0 comments on commit 2489682

Please sign in to comment.
You can’t perform that action at this time.