You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

39 lines
751 B

3 years ago
  1. 'use strict';
  2. const stripAnsi = require('strip-ansi');
  3. const isFullwidthCodePoint = require('is-fullwidth-code-point');
  4. const emojiRegex = require('emoji-regex')();
  5. module.exports = input => {
  6. input = input.replace(emojiRegex, ' ');
  7. if (typeof input !== 'string' || input.length === 0) {
  8. return 0;
  9. }
  10. input = stripAnsi(input);
  11. let width = 0;
  12. for (let i = 0; i < input.length; i++) {
  13. const code = input.codePointAt(i);
  14. // Ignore control characters
  15. if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) {
  16. continue;
  17. }
  18. // Ignore combining characters
  19. if (code >= 0x300 && code <= 0x36F) {
  20. continue;
  21. }
  22. // Surrogates
  23. if (code > 0xFFFF) {
  24. i++;
  25. }
  26. width += isFullwidthCodePoint(code) ? 2 : 1;
  27. }
  28. return width;
  29. };