1// Flags: --expose-internals 2'use strict'; 3const common = require('../common'); 4 5const assert = require('assert'); 6const { getStringWidth } = require('internal/util/inspect'); 7 8// Test column width 9 10// Ll (Lowercase Letter): LATIN SMALL LETTER A 11assert.strictEqual(getStringWidth('a'), 1); 12assert.strictEqual(getStringWidth(String.fromCharCode(0x0061)), 1); 13// Lo (Other Letter) 14assert.strictEqual(getStringWidth('丁'), 2); 15assert.strictEqual(getStringWidth(String.fromCharCode(0x4E01)), 2); 16// Surrogate pairs 17assert.strictEqual(getStringWidth('\ud83d\udc78\ud83c\udfff'), 4); 18assert.strictEqual(getStringWidth(''), 2); 19// Cs (Surrogate): High Surrogate 20assert.strictEqual(getStringWidth('\ud83d'), 1); 21// Cs (Surrogate): Low Surrogate 22assert.strictEqual(getStringWidth('\udc78'), 1); 23// Cc (Control): NULL 24assert.strictEqual(getStringWidth('\u0000'), 0); 25// Cc (Control): BELL 26assert.strictEqual(getStringWidth(String.fromCharCode(0x0007)), 0); 27// Cc (Control): LINE FEED 28assert.strictEqual(getStringWidth('\n'), 0); 29// Cf (Format): SOFT HYPHEN 30assert.strictEqual(getStringWidth(String.fromCharCode(0x00AD)), 1); 31// Cf (Format): LEFT-TO-RIGHT MARK 32// Cf (Format): RIGHT-TO-LEFT MARK 33assert.strictEqual(getStringWidth('\u200Ef\u200F'), 1); 34// Cn (Unassigned): Not a character 35assert.strictEqual(getStringWidth(String.fromCharCode(0x10FFEF)), 1); 36// Cn (Unassigned): Not a character (but in a CJK range) 37assert.strictEqual(getStringWidth(String.fromCharCode(0x3FFEF)), 1); 38// Mn (Nonspacing Mark): COMBINING ACUTE ACCENT 39assert.strictEqual(getStringWidth(String.fromCharCode(0x0301)), 0); 40// Mc (Spacing Mark): BALINESE ADEG ADEG 41// Chosen as its Canonical_Combining_Class is not 0, but is not a 0-width 42// character. 43assert.strictEqual(getStringWidth(String.fromCharCode(0x1B44)), 1); 44// Me (Enclosing Mark): COMBINING ENCLOSING CIRCLE 45assert.strictEqual(getStringWidth(String.fromCharCode(0x20DD)), 0); 46 47// The following is an emoji sequence with ZWJ (zero-width-joiner). In some 48// implementations, it is represented as a single glyph, in other 49// implementations as a sequence of individual glyphs. By default, each 50// component will be counted individually, since not a lot of systems support 51// these fully. 52// See https://www.unicode.org/reports/tr51/tr51-16.html#Emoji_ZWJ_Sequences 53assert.strictEqual(getStringWidth(''), 8); 54// TODO(BridgeAR): This should have a width of two and six. The heart contains 55// the \uFE0F variation selector that indicates that it should be displayed as 56// emoji instead of as text. Emojis are all full width characters when not being 57// rendered as text. 58// https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block) 59assert.strictEqual(getStringWidth('❤️'), 1); 60assert.strictEqual(getStringWidth('❤️'), 5); 61// The length of one is correct. It is an emoji treated as text. 62assert.strictEqual(getStringWidth('❤'), 1); 63 64// By default, unicode characters whose width is considered ambiguous will 65// be considered half-width. For these characters, getStringWidth will return 66// 1. In some contexts, however, it is more appropriate to consider them full 67// width. By default, the algorithm will assume half width. 68assert.strictEqual(getStringWidth('\u01d4'), 1); 69 70// Control chars and combining chars are zero 71assert.strictEqual(getStringWidth('\u200E\n\u220A\u20D2'), 1); 72 73// Test that the fast path for ASCII characters yields results consistent 74// with the 'slow' path. 75for (let i = 0; i < 256; i++) { 76 const char = String.fromCharCode(i); 77 assert.strictEqual( 78 getStringWidth(char + ''), 79 getStringWidth(char) + 2); 80 81 if (i < 32 || (i >= 127 && i < 160)) { // Control character 82 assert.strictEqual(getStringWidth(char), 0); 83 } else { // Regular ASCII character 84 assert.strictEqual(getStringWidth(char), 1); 85 } 86} 87 88if (common.hasIntl) { 89 const a = '한글'.normalize('NFD'); // 한글 90 const b = '한글'.normalize('NFC'); // 한글 91 assert.strictEqual(a.length, 6); 92 assert.strictEqual(b.length, 2); 93 assert.strictEqual(getStringWidth(a), 4); 94 assert.strictEqual(getStringWidth(b), 4); 95} 96