unicode-shaper
Version:
Shape unicode text so that renderers like WebGL and WebGPU can properly display the glyphs.
569 lines • 12.7 kB
JavaScript
/// If a RTL set is reversed, but surounded by (), [], {}, or <>, then mirror the sets.
/// This also tracks other special characters that need to be mirrored. Some examples:
/// '«', '»', '∕', '∟', '∠', '∡', '∢', '∤', '≃', '≅', '≌', '⊘', '⊦', '⊨',
export const MIRROR_CHAR = [
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
];
// 192 bytes
/**
* Mirror adjust string (things like parens, brackets, quotes, etc.)
* @param s - input string
*/
export function mirrorAdjustString(s) {
for (let i = 0, sl = s.length; i < sl; i++) {
const c = s[i];
for (const from_to of MIRROR_CHAR) {
if (c === from_to[0]) {
s[i] = from_to[1];
break;
}
}
}
}
/// A RandALCat character is a character with unambiguously right-to-left directionality.
export const RAND_AL_CAT = [
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
];
// 168 bytes
/**
* Check if a character is a "right-to-left" unicode character
* @param c - input unicode character
* @returns - True if right-to-left
*/
export function isRTL(c) {
for (const arr of RAND_AL_CAT) {
if (c >= arr[0] && c <= arr[1])
return true;
}
return false;
}
/// NEUTRAL characters are those with no inherent directionality, which can be
/// treated as being part of any adjacent runs of text with other directionality.
export const NEUTRAL = [
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
];
// 536 bytes
/**
* Check if character is neutral
* @param c - input unicode character
* @returns - True if neutral
*/
export function isNeutral(c) {
for (const arr of NEUTRAL) {
if (c >= arr[0] && c <= arr[1])
return true;
}
return false;
}
export const WEAK = [
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
];
// 900 bytes
/**
* Check if a character is a "weak" unicode character
* @param c - input unicode character
* @returns - True if weak
*/
export function isWeak(c) {
for (const arr of WEAK) {
if (c >= arr[0] && c <= arr[1])
return true;
}
return false;
}
/** Unicode character types */
export const Type = {
/** Right to Left */
Rtl: 0,
/** Weak */
Weak: 1,
/** Neutral */
Neutral: 2,
/** Left to Right */
Ltr: 3,
};
/**
* Get the type of a unicode character
* @param c - input unicode character
* @returns - The type
*/
export function getType(c) {
if (isRTL(c)) {
return Type.Rtl;
}
else if (isNeutral(c)) {
return Type.Neutral;
}
else if (isWeak(c)) {
return Type.Weak;
}
return Type.Ltr;
}
/**
* Find the dominant type in the string. skip past CtrChar until RTL or LTR is found.
* @param str - Array of unicode characters
* @returns - The dominant type
*/
export function findDominantType(str) {
for (const c of str) {
const t = getType(c);
if (t === Type.Rtl || t === Type.Ltr)
return t;
}
return Type.Ltr;
}
//# sourceMappingURL=internal.js.map