locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
64 lines (63 loc) • 2.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.tr = tr;
const expandTrSet = (pattern) => {
const chars = [...pattern];
const expanded = [];
for (let i = 0; i < chars.length; i += 1) {
const startChar = chars[i];
if (startChar === undefined) {
continue;
}
if (i + 2 < chars.length && chars[i + 1] === '-') {
const endChar = chars[i + 2];
if (endChar !== undefined) {
const startCode = startChar.codePointAt(0);
const endCode = endChar.codePointAt(0);
if (startCode !== undefined && endCode !== undefined) {
const step = startCode <= endCode ? 1 : -1;
for (let code = startCode; step > 0 ? code <= endCode : code >= endCode; code += step) {
expanded.push(String.fromCodePoint(code));
}
i += 2;
continue;
}
}
}
expanded.push(startChar);
}
return expanded;
};
function tr(str, from, to) {
// parity verified: Ruby 3.3
// discuss at: https://locutus.io/ruby/String/tr/
// original by: Kevin van Zonneveld (https://kvz.io)
// note 1: Transliterate characters from `from` set to `to` set.
// note 2: Supports basic ranges like `a-z`; complement (`^`) is intentionally not implemented.
// example 1: tr('hello', 'el', 'ip')
// returns 1: 'hippo'
// example 2: tr('abcxyz', 'a-z', 'A-Z')
// returns 2: 'ABCXYZ'
// example 3: tr('banana', 'an', 'o')
// returns 3: 'booooo'
const source = String(str);
const fromChars = expandTrSet(String(from));
if (fromChars.length === 0) {
return source;
}
const toChars = expandTrSet(String(to));
const map = new Map();
for (let index = 0; index < fromChars.length; index += 1) {
const key = fromChars[index];
if (key === undefined) {
continue;
}
const replacement = toChars.length === 0 ? '' : (toChars[Math.min(index, toChars.length - 1)] ?? '');
map.set(key, replacement);
}
let out = '';
for (const char of source) {
out += map.has(char) ? (map.get(char) ?? char) : char;
}
return out;
}