| 'use strict'; |
| const stripAnsi = require('strip-ansi'); |
| const isFullwidthCodePoint = require('is-fullwidth-code-point'); |
| const emojiRegex = require('emoji-regex')(); |
| |
| module.exports = input => { |
| input = input.replace(emojiRegex, ' '); |
| |
| if (typeof input !== 'string' || input.length === 0) { |
| return 0; |
| } |
| |
| input = stripAnsi(input); |
| |
| let width = 0; |
| |
| for (let i = 0; i < input.length; i++) { |
| const code = input.codePointAt(i); |
| |
| // Ignore control characters |
| if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) { |
| continue; |
| } |
| |
| // Ignore combining characters |
| if (code >= 0x300 && code <= 0x36F) { |
| continue; |
| } |
| |
| // Surrogates |
| if (code > 0xFFFF) { |
| i++; |
| } |
| |
| width += isFullwidthCodePoint(code) ? 2 : 1; |
| } |
| |
| return width; |
| }; |