I was debugging a very strange case with one of my Node.js projects recently. It prints my output formatted (with the as-table module) into a nicely-looking ASCII table layout:

For the sake of even greater niceness, I tried replacing that “time” title with the 🕑 symbol from Unicode…

Whoa. Something wrong happened, obviously. Quite quickly I discovered that the computed length of symbol 🕑 turned out to be 2!

Initially, I suspected a bug in the module that incorrectly determined the true optical length of a string (it’s the printable-characters that does the job, BTW). WTF? Looks like you can’t rely on str.length to get its rendered length: you have to strip zero-width characters and ANSI escape sequences first, otherwise your string might end up being wider than it actually is!

So, I thought that 🕑 .length could be erroneously computed as 2 , and that miscalculation lead to an observed disruption of the table’s layout. That happens because the “clock”-symbol occupies multiple Unicode code points or something, and the built-in .length just isn’t smart enough to manage it. Here’s a thorough explanation of the issue and I highly recommend reading it:

…but then, suddenly, I realized one more thing. The actual visible width of 🕑 might be “2” indeed, from VSCode:

A screenshot from the VSCode editor

But not quite… As you can see, it is not exactly 2 nor 1(and that puts things out of alignment). But how do various console terminals render it? Check it out in VSCode’s Integrated Terminal:

I’ve highlighted the “🕑” with the text selection

…and the built-in terminal app from MacOS:

I put my cursor at “🕑” to highlight it’s location.

It seems that popular terminals render everything strictly monospaced, and it’s up to the user himself to put an empty space after each of those new fancy Unicode glyphs, to make room for them in a monospaced grid, manually:

Same thing with a whitespace added after the “🕑”

Thus, our initial suggestion must have been true, and we should’ve patched printable-characters , enabling it to comprehend those symbols. The article referenced above helped me a lot with that task. So all essential bits required for a proper ASCII layout now work like a charm without breaking on zero-width characters, Emojis and ANSI escape codes:

// determining the real length of a string

strlen ('💩') === 1 // getting first N visible symbols

first ('💩23456789', 3) === '💩23' // filling with whitespace

blank ('\t💩foo') === '\t '

Yay! Now the as-table is capable of rendering those fancy characters nicely:

About the Author

I’m a member of the developer team behind the open-source cross-language CCXT Library (available for JavaScript, Python or PHP). The library is used to connect and trade with more than 85 cryptocurrency exchanges worldwide.