index.js
 1  'use strict';
 2  const stripAnsi = require('strip-ansi');
 3  const isFullwidthCodePoint = require('is-fullwidth-code-point');
 4  const emojiRegex = require('emoji-regex');
 5  
 6  const stringWidth = string => {
 7  	if (typeof string !== 'string' || string.length === 0) {
 8  		return 0;
 9  	}
10  
11  	string = stripAnsi(string);
12  
13  	if (string.length === 0) {
14  		return 0;
15  	}
16  
17  	string = string.replace(emojiRegex(), '  ');
18  
19  	let width = 0;
20  
21  	for (let i = 0; i < string.length; i++) {
22  		const code = string.codePointAt(i);
23  
24  		// Ignore control characters
25  		if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) {
26  			continue;
27  		}
28  
29  		// Ignore combining characters
30  		if (code >= 0x300 && code <= 0x36F) {
31  			continue;
32  		}
33  
34  		// Surrogates
35  		if (code > 0xFFFF) {
36  			i++;
37  		}
38  
39  		width += isFullwidthCodePoint(code) ? 2 : 1;
40  	}
41  
42  	return width;
43  };
44  
45  module.exports = stringWidth;
46  // TODO: remove this in the next major version
47  module.exports.default = stringWidth;