text-aligner
Version:
Align text by adding spaces to each string so that all strings have the same number of English and Chinese characters.
142 lines (141 loc) • 4.11 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
alignText: () => alignText
});
module.exports = __toCommonJS(index_exports);
var FallbackKey = "@@fallback";
var FallbackPlaceholder = "\u2007";
var DefaultPaddingMap = {
cjk: {
test: (char) => isCJK(char),
placeholder: "\u2001"
},
[FallbackKey]: {
test: FallbackKey,
placeholder: FallbackPlaceholder
}
};
function isCJK(char) {
const cjkRanges = [
// Chinese (Hanzi) ranges
[19968, 40959],
// CJK Unified Ideographs
[13312, 19903],
// CJK Unified Ideographs Extension A
[131072, 173791],
// CJK Unified Ideographs Extension B
[173824, 177983],
// CJK Unified Ideographs Extension C
[177984, 178207],
// CJK Unified Ideographs Extension D
[178208, 183983],
// CJK Unified Ideographs Extension E
[63744, 64255],
// CJK Compatibility Ideographs
[194560, 195103],
// CJK Compatibility Ideographs Supplement
// Japanese ranges
[12352, 12447],
// Hiragana
[12448, 12543],
// Katakana
[12784, 12799],
// Katakana Phonetic Extensions
// Korean ranges
[44032, 55203],
// Hangul Syllables
[4352, 4607],
// Hangul Jamo
[12592, 12687]
// Hangul Compatibility Jamo
];
const charCode = char.codePointAt(0);
return cjkRanges.some(([start, end]) => charCode >= start && charCode <= end);
}
function countChars(str, rules) {
const counts = {
[FallbackKey]: 0
};
Object.keys(rules).forEach((key) => counts[key] = 0);
for (const char of str) {
let matched = false;
for (const [key, rule] of Object.entries(rules)) {
if (key === FallbackKey || rule.test === FallbackKey) {
continue;
}
if (typeof rule.test === "function" ? rule.test(char) : rule.test.test(char)) {
counts[key]++;
matched = true;
break;
}
}
if (!matched) {
counts[FallbackKey]++;
}
}
return counts;
}
function findMaxCounts(counts) {
const maxCounts = {};
for (const count of counts) {
Object.keys(count).forEach((key) => {
maxCounts[key] = Math.max(maxCounts[key] || 0, count[key]);
});
}
return maxCounts;
}
function alignText(strings, paddingMap = DefaultPaddingMap) {
const normalizedPaddingMap = {};
for (const [key, value] of Object.entries(paddingMap)) {
if (typeof value === "string") {
if (!DefaultPaddingMap[key]) {
continue;
}
normalizedPaddingMap[key] = {
test: DefaultPaddingMap[key]?.test,
placeholder: value
};
continue;
}
normalizedPaddingMap[key] = value;
}
normalizedPaddingMap[FallbackKey] ??= {
test: FallbackKey,
placeholder: FallbackPlaceholder
};
const counts = strings.map((str) => countChars(str, normalizedPaddingMap));
const maxCounts = findMaxCounts(counts);
return strings.map((str, index) => {
const currentCounts = counts[index];
let result = str;
for (const [key, count] of Object.entries(maxCounts)) {
const diff = count - currentCounts[key];
result += normalizedPaddingMap[key].placeholder.repeat(diff);
}
return result;
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
alignText
});
//# sourceMappingURL=index.cjs.map