first commit
This commit is contained in:
180
node_modules/transliteration/dist/node/src/common/transliterate.js
generated
vendored
Normal file
180
node_modules/transliteration/dist/node/src/common/transliterate.js
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Transliterate = exports.defaultOptions = void 0;
|
||||
const charmap_1 = require("../../data/charmap");
|
||||
const utils_1 = require("./utils");
|
||||
exports.defaultOptions = {
|
||||
ignore: [],
|
||||
replace: [],
|
||||
replaceAfter: [],
|
||||
trim: false,
|
||||
unknown: '',
|
||||
fixChineseSpacing: true,
|
||||
};
|
||||
class Transliterate {
|
||||
constructor(confOptions = (0, utils_1.deepClone)(exports.defaultOptions), map = charmap_1.charmap) {
|
||||
this.confOptions = confOptions;
|
||||
this.map = map;
|
||||
}
|
||||
get options() {
|
||||
return (0, utils_1.deepClone)(Object.assign(Object.assign({}, exports.defaultOptions), this.confOptions));
|
||||
}
|
||||
/**
|
||||
* Set default config
|
||||
* @param options
|
||||
*/
|
||||
config(options, reset = false) {
|
||||
if (reset) {
|
||||
this.confOptions = {};
|
||||
}
|
||||
if (options && typeof options === 'object') {
|
||||
this.confOptions = (0, utils_1.deepClone)(options);
|
||||
}
|
||||
return this.confOptions;
|
||||
}
|
||||
/**
|
||||
* Replace the source string using the code map
|
||||
* @param str
|
||||
* @param ignoreRanges
|
||||
* @param unknown
|
||||
*/
|
||||
codeMapReplace(str, ignoreRanges = [], opt) {
|
||||
let index = 0;
|
||||
let result = '';
|
||||
const strContainsChinese = opt.fixChineseSpacing && (0, utils_1.hasChinese)(str);
|
||||
let lastCharHasChinese = false;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
// Get current character, taking surrogates in consideration
|
||||
const char = /[\uD800-\uDBFF]/.test(str[i]) && /[\uDC00-\uDFFF]/.test(str[i + 1])
|
||||
? str[i] + str[i + 1]
|
||||
: str[i];
|
||||
let s;
|
||||
let ignoreFixingChinese = false;
|
||||
switch (true) {
|
||||
// current character is in ignored list
|
||||
case (0, utils_1.inRange)(index, ignoreRanges):
|
||||
// could be UTF-32 with high and low surrogates
|
||||
case char.length === 2 && (0, utils_1.inRange)(index + 1, ignoreRanges):
|
||||
s = char;
|
||||
// if it's the first character of an ignored string, then leave ignoreFixingChinese to true
|
||||
if (!ignoreRanges.find((range) => range[1] >= index && range[0] === index)) {
|
||||
ignoreFixingChinese = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
s = this.map[char] || opt.unknown || '';
|
||||
}
|
||||
// fix Chinese spacing issue
|
||||
if (strContainsChinese) {
|
||||
if (lastCharHasChinese &&
|
||||
!ignoreFixingChinese &&
|
||||
!(0, utils_1.hasPunctuationOrSpace)(s)) {
|
||||
s = ' ' + s;
|
||||
}
|
||||
lastCharHasChinese = !!s && (0, utils_1.hasChinese)(char);
|
||||
}
|
||||
result += s;
|
||||
index += char.length;
|
||||
// If it's UTF-32 then skip next character
|
||||
i += char.length - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Convert the object version of the 'replace' option into tuple array one
|
||||
* @param option replace option to be either an object or tuple array
|
||||
* @return return the paired array version of replace option
|
||||
*/
|
||||
formatReplaceOption(option) {
|
||||
if (option instanceof Array) {
|
||||
// return a new copy of the array
|
||||
return (0, utils_1.deepClone)(option);
|
||||
}
|
||||
// convert object option to array one
|
||||
const replaceArr = [];
|
||||
for (const key in option) {
|
||||
/* istanbul ignore else */
|
||||
if (Object.prototype.hasOwnProperty.call(option, key)) {
|
||||
replaceArr.push([key, option[key]]);
|
||||
}
|
||||
}
|
||||
return replaceArr;
|
||||
}
|
||||
/**
|
||||
* Search and replace a list of strings(regexps) and return the result string
|
||||
* @param source Source string
|
||||
* @param searches Search-replace string(regexp) pairs
|
||||
*/
|
||||
replaceString(source, searches, ignore = []) {
|
||||
const clonedSearches = (0, utils_1.deepClone)(searches);
|
||||
let result = source;
|
||||
for (let i = 0; i < clonedSearches.length; i++) {
|
||||
const item = clonedSearches[i];
|
||||
switch (true) {
|
||||
case item[0] instanceof RegExp:
|
||||
item[0] = RegExp(item[0].source, `${item[0].flags.replace('g', '')}g`);
|
||||
break;
|
||||
case typeof item[0] === 'string' && item[0].length > 0:
|
||||
item[0] = RegExp((0, utils_1.escapeRegExp)(item[0]), 'g');
|
||||
break;
|
||||
default:
|
||||
item[0] = /[^\s\S]/; // Prevent ReDos attack
|
||||
}
|
||||
result = (0, utils_1.regexpReplaceCustom)(result, item[0], item[1], ignore);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Set charmap data
|
||||
* @param {Charmap} [data]
|
||||
* @param {boolean} [reset=false]
|
||||
* @memberof Transliterate
|
||||
*/
|
||||
setData(data, reset = false) {
|
||||
if (reset) {
|
||||
this.map = (0, utils_1.deepClone)(charmap_1.charmap);
|
||||
}
|
||||
if (data && typeof data === 'object' && Object.keys(data).length) {
|
||||
this.map = (0, utils_1.deepClone)(this.map);
|
||||
for (const from in data) {
|
||||
/* istanbul ignore else */
|
||||
if (Object.prototype.hasOwnProperty.call(data, from) &&
|
||||
from.length < 3 &&
|
||||
from <= '\udbff\udfff') {
|
||||
this.map[from] = data[from];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.map;
|
||||
}
|
||||
/**
|
||||
* Main transliterate function
|
||||
* @param source The string which is being transliterated
|
||||
* @param options Options object
|
||||
*/
|
||||
transliterate(source, options) {
|
||||
options = typeof options === 'object' ? options : {};
|
||||
const opt = (0, utils_1.deepClone)(Object.assign(Object.assign({}, this.options), options));
|
||||
// force convert to string
|
||||
let str = typeof source === 'string' ? source : String(source);
|
||||
const replaceOption = this.formatReplaceOption(opt.replace);
|
||||
if (replaceOption.length) {
|
||||
str = this.replaceString(str, replaceOption, opt.ignore);
|
||||
}
|
||||
// ignore
|
||||
const ignoreRanges = opt.ignore && opt.ignore.length > 0
|
||||
? (0, utils_1.findStrOccurrences)(str, opt.ignore)
|
||||
: [];
|
||||
str = this.codeMapReplace(str, ignoreRanges, opt);
|
||||
// trim spaces at the beginning and ending of the string
|
||||
if (opt.trim) {
|
||||
str = str.trim();
|
||||
}
|
||||
const replaceAfterOption = this.formatReplaceOption(opt.replaceAfter);
|
||||
if (replaceAfterOption.length) {
|
||||
str = this.replaceString(str, replaceAfterOption);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
exports.Transliterate = Transliterate;
|
||||
Reference in New Issue
Block a user