Files
test-repo/src/utils/get-string-width.js
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

61 lines
1.6 KiB
JavaScript
Raw Normal View History

import emojiRegex from "emoji-regex";
import {
// @ts-expect-error -- Private
_isFullWidth as isFullWidth,
// @ts-expect-error -- Private
_isWide as isWide,
} from "get-east-asian-width";
2025-09-18 21:12:26 +09:00
import narrowEmojis from "./narrow-emojis.evaluate.js";
2022-01-27 19:24:11 +09:00
const notAsciiRegex = /[^\x20-\x7F]/u;
2025-09-18 21:12:26 +09:00
const narrowEmojisSet = new Set(narrowEmojis);
2022-01-27 19:24:11 +09:00
// Similar to https://github.com/sindresorhus/string-width
// We don't strip ansi, always treat ambiguous width characters as having narrow width.
2022-01-27 19:24:11 +09:00
/**
* @param {string} text
* @returns {number}
*/
function getStringWidth(text) {
if (!text) {
return 0;
}
// shortcut to avoid needless string `RegExp`s, replacements, and allocations
2022-01-27 19:24:11 +09:00
if (!notAsciiRegex.test(text)) {
return text.length;
}
2025-09-18 21:12:26 +09:00
text = text.replace(emojiRegex(), (match) =>
narrowEmojisSet.has(match) ? " " : " ",
);
let width = 0;
// Use `Intl.Segmenter` when we drop support for Node.js v14
// https://github.com/prettier/prettier/pull/14793#discussion_r1185840038
// https://github.com/sindresorhus/string-width/pull/47
for (const character of text) {
const codePoint = character.codePointAt(0);
// Ignore control characters
if (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f)) {
continue;
}
// Ignore combining characters
if (codePoint >= 0x300 && codePoint <= 0x36f) {
continue;
}
2025-09-18 21:12:26 +09:00
// Ignore Variation Selectors
if (codePoint >= 0xfe00 && codePoint <= 0xfe0f) {
continue;
}
width += isFullWidth(codePoint) || isWide(codePoint) ? 2 : 1;
}
return width;
2022-01-27 19:24:11 +09:00
}
export default getStringWidth;