first commit

This commit is contained in:
2025-10-26 23:10:15 +08:00
commit 8f0345b7be
14961 changed files with 2356381 additions and 0 deletions

36
node_modules/transliteration/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,36 @@
### 2.2.0
- Fix #229 data issue
- Add an option `fixChineseSpacing` option for improving performance for none-Chinese languages
- Fix #202 replace related issues.
- Update dependencies
### 2.1.0
- Add `transliterate` as a global variable for browser builds. Keep `transl` for backward compatibility.
### 2.0.0
- **CDN file structure changed**: [https://www.jsdelivr.com/package/npm/transliteration](https://www.jsdelivr.com/package/npm/transliteration)
- The entire module had been refactored in Typescript, with big performance improvements as well as a reduced package size.
- Better code quality. 100% unit tested.
- `bower` support was dropped. Please use CDN or `webpack`/`rollup`.
- As according to RFC 3986, more characters(`/a-zA-Z0-9-_.~/`) are kept as allowed characters in the result for `slugify`, and it is configurable.
- Added `uppercase` as an option for `slugify`, if is set to `true` then the generated slug will be converted to uppercase letters.
- Unknown characters will be transliterated as empty string by default, instead of a meaningless `[?]`.
### 1.6.6
- Added support for `TypeScript`. #77
### 1.5.0
- Minimum node requirement: 6.0+
### 1.0.0
- Code had been entirely refactored since version 1.0.0. Be careful when you plan to upgrade from v0.1.x or v0.2.x to v1.0.x
- The `options` parameter of `transliterate` now is an `Object` (In 0.1.x it's a string `unknown`).
- Added `transliterate.config` and `slugify.config`.
- Unknown string will be transliterated as `[?]` instead of `?`.
- In the browser, global variables have been changed to `window.transl` and `windnow.slugify`. Other global variables are removed.

20
node_modules/transliteration/LICENSE.txt generated vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright http://github.com/dzcpy/transliteration
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Software), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, andor sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

318
node_modules/transliteration/README.md generated vendored Normal file
View File

@@ -0,0 +1,318 @@
<p align="center"><img src="http://dzcpy.github.io/transliteration/transliteration.png" alt="Transliteration"></p>
[![Build Status](https://img.shields.io/circleci/project/github/dzcpy/transliteration/master.svg)](https://circleci.com/gh/dzcpy/transliteration)
[![Coverage Status](https://coveralls.io/repos/github/dzcpy/transliteration/badge.svg?branch=master)](https://coveralls.io/github/dzcpy/transliteration?branch=master)
[![NPM Version](https://img.shields.io/npm/v/transliteration.svg)](https://www.npmjs.com/package/transliteration)
[![NPM Download](https://img.shields.io/npm/dm/transliteration.svg)](https://www.npmjs.com/package/transliteration)
[![](https://data.jsdelivr.com/v1/package/npm/transliteration/badge)](https://www.jsdelivr.com/package/npm/transliteration)
[![License](https://img.shields.io/npm/l/transliteration.svg)](https://github.com/dzcpy/transliteration/blob/master/LICENSE.txt)\
Universal Unicode to Latin transliteration + slugify module. Works on all platforms and with all major languages.
## Demo
[Try it out](http://dzcpy.github.io/transliteration)
## Compatibility / Browser support
IE 9+ and all modern browsers, Node.js, Web Worker, React Native and CLI
## Installation
### Node.js / React Native
```bash
npm install transliteration --save
```
If you are using Typescript, please do not install `@types/transliteration`. Since in verson `2.x`, type definition files are built-in within this project.
```javascript
import { transliterate as tr, slugify } from 'transliteration';
tr('你好, world!');
// Ni Hao , world!
slugify('你好, world!');
// ni-hao-world
```
### Browser (CDN):
```html
<!-- UMD build -->
<script
async
defer
src="https://cdn.jsdelivr.net/npm/transliteration@2.1.8/dist/browser/bundle.umd.min.js"
></script>
<script>
console.log(transliterate('你好'));
</script>
```
```html
<!-- ESM build -->
<script type="module">
import { transliterate } from 'https://cdn.jsdelivr.net/npm/transliteration@2.1.8/dist/browser/bundle.esm.min.js';
console.log(transliterate('你好'));
</script>
```
`transliteration` can be loaded as an AMD / CommonJS module, or as global variables (UMD).
When you use it in the browser, by default it creates three global variables under `window` object:
```javascript
transliterate('你好, World');
// window.transliterate
slugify('Hello, 世界');
// window.slugify
transl('Hola, mundo'); // For backward compatibility only, will be removed in next major version
// window.transl
```
### CLI
```bash
npm install transliteration -g
transliterate 你好 # Ni Hao
slugify 你好 # ni-hao
echo 你好 | slugify -S # ni-hao
```
## Usage
### transliterate(str, [options])
Transliterate the string `str` and return the result. Characters which this module can't handle will default to the placeholder character(s) given in the `unknown` option. If it's not provided, they will be removed.
**Options:** (optional)
```javascript
{
/**
* Ignore a list of strings untouched
* @example tr('你好,世界', { ignore: ['你'] }) // 你 Hao , Shi Jie
*/
ignore?: string[];
/**
* Replace a list of string / regex in the source string with the provided target string before transliteration
* The option can either be an array or an object
* @example tr('你好,世界', { replace: {你: 'You'} }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [['你', 'You']] }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [[/你/g, 'You']] }) // You Hao , Shi Jie
*/
replace?: OptionReplaceCombined;
/**
* Same as `replace` but after transliteration
*/
replaceAfter?: OptionReplaceCombined;
/**
* Decides whether or not to trim the result string after transliteration
* @default false
*/
trim?: boolean;
/**
* Any characters not known by this library will be replaced by a specific string `unknown`
* @default ''
*/
unknown?: string;
/**
* Fix Chinese spacing. For example, `你好` is transliterated to `Ni Hao` instead of `NiHao`. If you don't need to transliterate Chinese characters, set it to false to false to improve performance.
* @default true
*/
fixChineseSpacing?: boolean;
}
```
### transliterate.config([optionsObj], [reset = false])
Bind option object globally so any following calls will use `optionsObj` by default. If `optionsObj` is not given, it will return current default option object.
```javascript
import { transliterate as tr } from 'transliteration';
tr('你好,世界');
// Ni Hao , Shi Jie
tr('Γεια σας, τον κόσμο');
// Geia sas, ton kosmo
tr('안녕하세요, 세계');
// annyeonghaseyo, segye
tr('你好,世界', { replace: { : 'You' }, ignore: ['好'] });
// You 好,Shi Jie
tr('你好,世界', { replace: [['你', 'You']], ignore: ['好'] });
// You 好,Shi Jie (option in array form)
tr.config({ replace: [['你', 'You']], ignore: ['好'] });
tr('你好,世界'); // You 好,Shi Jie
console.log(tr.config());
// { replace: [['你', 'You']], ignore: ['好'] }
tr.config(undefined, true);
console.log(tr.config());
// {}
```
### slugify(str, [options])
Convert Unicode `str` into a slug string, making sure it is safe to be used in an URL or in a file name.
**Options:** (optional)
```javascript
/**
* Ignore a list of strings untouched
* @example tr('你好,世界', { ignore: ['你'] }) // 你 Hao , Shi Jie
*/
ignore?: string[];
/**
* Replace a list of string / regex in the source string with the provided target string before transliteration
* The option can either be an array or an object
* @example tr('你好,世界', { replace: {你: 'You'} }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [['你', 'You']] }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [[/你/g, 'You']] }) // You Hao , Shi Jie
*/
replace?: OptionReplaceCombined;
/**
* Same as `replace` but after transliteration
*/
replaceAfter?: OptionReplaceCombined;
/**
* Decides whether or not to trim the result string after transliteration
* @default false
*/
trim?: boolean;
/**
* Any characters not known by this library will be replaced by a specific string `unknown`
* @default ''
*/
unknown?: string;
/**
* Whether the result need to be converted into lowercase
* @default true
*/
lowercase?: boolean;
/**
* Whether the result need to be converted into uppercase
* @default false
*/
uppercase?: boolean;
/**
* Custom separator string
* @default '-'
*/
separator?: string;
/**
* Allowed characters.
* When `allowedChars` is set to `'abc'`, only characters which match `/[abc]/g` will be preserved.
* Other characters will all be converted to `separator`
* @default 'a-zA-Z0-9-_.~''
*/
allowedChars?: string;
/**
* Fix Chinese spacing. For example, `你好` is transliterated to `Ni Hao` instead of `NiHao`. If you don't need to transliterate Chinese characters, set it to false to false to improve performance.
*/
fixChineseSpacing?: boolean;
```
```javascript
slugify('你好,世界');
// ni-hao-shi-jie
slugify('你好,世界', { lowercase: false, separator: '_' });
// Ni_Hao_Shi_Jie
slugify('你好,世界', {
replace: { 你好: 'Hello', 世界: 'world' },
separator: '_',
});
// hello_world
slugify('你好,世界', {
replace: [
['你好', 'Hello'],
['世界', 'world'],
],
separator: '_',
}); // replace option in array form)
// hello_world
slugify('你好,世界', { ignore: ['你好'] });
// 你好shi-jie
```
### slugify.config([optionsObj], [reset = false])
Bind option object globally so any following calls will use `optionsObj` by default. If `optionsObj` is not given, it will return current default option object.
```javascript
slugify.config({ lowercase: false, separator: '_' });
slugify('你好,世界');
// Ni_Hao_Shi_Jie
console.log(slugify.config());
// { lowercase: false, separator: "_" }
slugify.config({ replace: [['你好', 'Hello']] });
slugify('你好, world!');
// This equals slugify('你好, world!', { replace: [['你好', 'Hello']] });
console.log(slugify.config());
// { replace: [['你好', 'Hello']] }
slugify.config(undefined, true);
console.log(slugify.config());
// {}
```
### CLI Usage
```
➜ ~ transliterate --help
Usage: transliterate <unicode> [options]
Options:
--version Show version number [boolean]
-u, --unknown Placeholder for unknown characters [string] [default: ""]
-r, --replace Custom string replacement [array] [default: []]
-i, --ignore String list to ignore [array] [default: []]
-S, --stdin Use stdin as input [boolean] [default: false]
-h, --help [boolean]
Examples:
transliterate "你好, world!" -r 好=good -r Replace `,` with `!`, `world` with `shijie`.
"world=Shi Jie" Result: Ni good, Shi Jie!
transliterate "你好,世界!" -i 你好 -i Ignore `你好` and ``.
Result: 你好Shi Jie !
```
```
➜ ~ slugify --help
Usage: slugify <unicode> [options]
Options:
--version Show version number [boolean]
-U, --unknown Placeholder for unknown characters [string] [default: ""]
-l, --lowercase Returns result in lowercase [boolean] [default: true]
-u, --uppercase Returns result in uppercase [boolean] [default: false]
-s, --separator Separator of the slug [string] [default: "-"]
-r, --replace Custom string replacement [array] [default: []]
-i, --ignore String list to ignore [array] [default: []]
-S, --stdin Use stdin as input [boolean] [default: false]
-h, --help [boolean]
Examples:
slugify "你好, world!" -r 好=good -r "world=Shi Replace `,` with `!` and `world` with
Jie" `shijie`.
Result: ni-good-shi-jie
slugify "你好,世界!" -i 你好 -i Ignore `你好` and ``.
Result: 你好shi-jie
```
## Caveats
Currently, `transliteration` only supports 1 to 1 code map (from Unicode to Latin). It is the simplest way to implement, but there are some limitations when dealing with polyphonic characters. It does not work well with all languages, please test all possible situations before using it. Some known issues are:
- **Chinese:** Polyphonic characters are not always transliterated correctly. Alternative: `pinyin`.
- **Japanese:** Most Japanese Kanji characters are transliterated into Chinese Pinyin because of the overlapped code map in Unicode. Also there are many polyphonic characters in Japanese which makes it impossible to transliterate Japanese Kanji correctly without tokenizing the sentence. Consider using `kuroshiro` for a better Kanji -> Romaji conversion.
- **Thai:** Currently it is not working. If you know how to fix it, please comment on [this](https://github.com/dzcpy/transliteration/issues/67) issue.
- **Cyrillic:** Cyrillic characters are overlapped between a few languages. The result might be inaccurate in some specific languages, for example Bulgarian.
If you find any other issues, please raise a ticket.
### License
MIT

2
node_modules/transliteration/dist/bin/slugify generated vendored Executable file

File diff suppressed because one or more lines are too long

2
node_modules/transliteration/dist/bin/transliterate generated vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"bundle.esm.min.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
export interface Charmap {
[key: string]: string;
}
export declare const charmap: Charmap;

18
node_modules/transliteration/dist/node/data/charmap.js generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
import { OptionsSlugify } from '../types';
import { Transliterate } from './transliterate';
export declare const defaultOptions: OptionsSlugify;
export declare class Slugify extends Transliterate {
get options(): OptionsSlugify;
/**
* Set default config
* @param options
*/
config(options?: OptionsSlugify, reset?: boolean): OptionsSlugify;
/**
* Slugify
* @param str
* @param options
*/
slugify(str: string, options?: OptionsSlugify): string;
}

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Slugify = exports.defaultOptions = void 0;
const transliterate_1 = require("./transliterate");
const utils_1 = require("./utils");
// Slugify
exports.defaultOptions = Object.assign(Object.assign({}, (0, utils_1.deepClone)(transliterate_1.defaultOptions)), { allowedChars: 'a-zA-Z0-9-_.~', lowercase: true, separator: '-', uppercase: false, fixChineseSpacing: true });
class Slugify extends transliterate_1.Transliterate {
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;
}
/**
* Slugify
* @param str
* @param options
*/
slugify(str, options) {
options = typeof options === 'object' ? options : {};
const opt = (0, utils_1.deepClone)(Object.assign(Object.assign({}, this.options), options));
// remove leading and trailing separators
const sep = opt.separator ? (0, utils_1.escapeRegExp)(opt.separator) : '';
let slug = this.transliterate(str, opt);
slug = (0, utils_1.regexpReplaceCustom)(slug, RegExp(`[^${opt.allowedChars}]+`, 'g'), opt.separator, opt.ignore);
if (sep) {
slug = slug.replace(RegExp(`^${sep}+|${sep}$`, 'g'), '');
}
if (opt.lowercase) {
slug = slug.toLowerCase();
}
if (opt.uppercase) {
slug = slug.toUpperCase();
}
return slug;
}
}
exports.Slugify = Slugify;

View File

@@ -0,0 +1,46 @@
import { IntervalArray, OptionReplaceArray, OptionReplaceCombined, OptionsTransliterate } from '../types';
import { Charmap } from '../../data/charmap';
export declare const defaultOptions: OptionsTransliterate;
export declare class Transliterate {
protected confOptions: OptionsTransliterate;
protected map: Charmap;
get options(): OptionsTransliterate;
constructor(confOptions?: OptionsTransliterate, map?: Charmap);
/**
* Set default config
* @param options
*/
config(options?: OptionsTransliterate, reset?: boolean): OptionsTransliterate;
/**
* Replace the source string using the code map
* @param str
* @param ignoreRanges
* @param unknown
*/
codeMapReplace(str: string, ignoreRanges: IntervalArray | undefined, opt: OptionsTransliterate): string;
/**
* 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: OptionReplaceCombined): OptionReplaceArray;
/**
* 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: string, searches: OptionReplaceArray, ignore?: string[]): string;
/**
* Set charmap data
* @param {Charmap} [data]
* @param {boolean} [reset=false]
* @memberof Transliterate
*/
setData(data?: Charmap, reset?: boolean): Charmap;
/**
* Main transliterate function
* @param source The string which is being transliterated
* @param options Options object
*/
transliterate(source: string, options?: OptionsTransliterate): string;
}

View 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;

View File

@@ -0,0 +1,42 @@
import { IntervalArray } from '../types';
/**
* Escape regular expression string
* @see https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex/6969486#6969486
*/
export declare function escapeRegExp(str?: string): string;
/**
* Check if a character is Chinese
*/
export declare function hasChinese(char: string): boolean;
/**
* Check if a character is a punctuation
*/
export declare function hasPunctuationOrSpace(char: string): boolean;
/**
* Deep clone a variable
* @param obj Object to clone
* @returns The cloned object
*/
export declare function deepClone(obj: any): any;
/**
* Find all occurrences of a list of strings and merge the result in an interval array
* @see: https://stackoverflow.com/questions/26390938/merge-arrays-with-overlapping-values#answer-26391774
* @param source Source string
* @param searches Strings to search
* @returns A list of occurrences in the format of [[from, to], [from, to]]
*/
export declare function findStrOccurrences(source: string, searches: string[]): IntervalArray;
/**
* Check if the given `num` is in the `rangeArr` interval array using Binary Search algorithm
* @param num
* @param rangeArr
*/
export declare function inRange(num: number, rangeArr: IntervalArray): boolean;
/**
* Custom RegExp replace function to replace all unnecessary strings into target replacement string
* @param source Source string
* @param regexp Used to search through the source string
* @param replacement Replace matched RegExp with replacement value
* @param ignored Ignore certain string values within the matched strings
*/
export declare function regexpReplaceCustom(source: string, regexp: RegExp, replacement: string, ignored?: string[]): string;

View File

@@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.regexpReplaceCustom = exports.inRange = exports.findStrOccurrences = exports.deepClone = exports.hasPunctuationOrSpace = exports.hasChinese = exports.escapeRegExp = void 0;
/**
* Escape regular expression string
* @see https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex/6969486#6969486
*/
function escapeRegExp(str) {
return (str || '').replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}
exports.escapeRegExp = escapeRegExp;
/**
* Check if a character is Chinese
*/
function hasChinese(char) {
return /[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DBF\u4E00-\u9FFC\uF900-\uFA6D\uFA70-\uFAD9]|\uD81B[\uDFF0\uDFF1]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]/.test(char);
}
exports.hasChinese = hasChinese;
/**
* Check if a character is a punctuation
*/
function hasPunctuationOrSpace(char) {
return /[\s!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDEAD\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDFFF]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/.test(char);
}
exports.hasPunctuationOrSpace = hasPunctuationOrSpace;
/**
* Deep clone a variable
* @param obj Object to clone
* @returns The cloned object
*/
function deepClone(obj) {
switch (true) {
case obj instanceof Array:
const clonedArr = [];
for (let i = 0; i < obj.length; i++) {
clonedArr[i] = deepClone(obj[i]);
}
return clonedArr;
case obj instanceof Date:
return new Date(obj.valueOf());
case obj instanceof RegExp:
return new RegExp(obj.source, obj.flags);
case obj instanceof Object:
const clonedObj = {};
for (const key in obj) {
/* istanbul ignore else */
if (Object.prototype.hasOwnProperty.call(obj, key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
default:
return obj;
}
}
exports.deepClone = deepClone;
/**
* Find all occurrences of a list of strings and merge the result in an interval array
* @see: https://stackoverflow.com/questions/26390938/merge-arrays-with-overlapping-values#answer-26391774
* @param source Source string
* @param searches Strings to search
* @returns A list of occurrences in the format of [[from, to], [from, to]]
*/
function findStrOccurrences(source, searches) {
let result = [];
for (let i = 0; i < searches.length; i++) {
const str = searches[i];
let index = -1;
while ((index = source.indexOf(str, index + 1)) > -1) {
result.push([index, index + str.length - 1]);
}
}
// sort the interval array
const sortedResult = result.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
result = [];
let last;
// merge overlapped ranges
sortedResult.forEach((r) => !last || r[0] > last[1] + 1
? result.push((last = r))
: r[1] > last[1] && (last[1] = r[1]));
return result;
}
exports.findStrOccurrences = findStrOccurrences;
/**
* Check the position of the number of a specific range
* @param num
* @param range
*/
function getPosition(num, range) {
switch (true) {
case num < range[0]:
return -1 /* Position.Left */;
case num > range[1]:
return 1 /* Position.Right */;
}
return 0 /* Position.Middle */;
}
/**
* Check if the given `num` is in the `rangeArr` interval array using Binary Search algorithm
* @param num
* @param rangeArr
*/
function inRange(num, rangeArr) {
if (rangeArr.length === 0) {
return false;
}
const testIndex = Math.floor(rangeArr.length / 2);
switch (getPosition(num, rangeArr[testIndex])) {
case -1 /* Position.Left */:
return inRange(num, rangeArr.slice(0, testIndex));
case 1 /* Position.Right */:
return inRange(num, rangeArr.slice(testIndex + 1));
}
return true;
}
exports.inRange = inRange;
/**
* Custom RegExp replace function to replace all unnecessary strings into target replacement string
* @param source Source string
* @param regexp Used to search through the source string
* @param replacement Replace matched RegExp with replacement value
* @param ignored Ignore certain string values within the matched strings
*/
function regexpReplaceCustom(source, regexp, replacement, ignored = []) {
// RegExp version of ignored
const ignoredRegexp = ignored.length
? RegExp(ignored.map(escapeRegExp).join('|'), 'g')
: null;
// clones regex and with g flag
const rule = RegExp(regexp.source, regexp.flags.replace('g', '') + 'g');
// final result
let result = '';
// used to count where
let lastIndex = 0;
while (true) {
const matchMain = rule.exec(source);
let ignoreResult = '';
let ignoreLastIndex = 0;
if (matchMain) {
while (true) {
const matchIgnore = ignoredRegexp
? ignoredRegexp.exec(matchMain[0])
: null;
if (matchIgnore) {
ignoreResult +=
matchIgnore.index > ignoreLastIndex ? replacement : '';
ignoreResult += matchIgnore[0];
ignoreLastIndex = ignoredRegexp.lastIndex;
}
else {
ignoreResult +=
matchMain[0].length > ignoreLastIndex ? replacement : '';
break;
}
}
result += source.substring(lastIndex, matchMain.index) + ignoreResult;
lastIndex = rule.lastIndex;
}
else {
result += source.substring(lastIndex, source.length);
break;
}
}
return result;
}
exports.regexpReplaceCustom = regexpReplaceCustom;

View File

@@ -0,0 +1,4 @@
import { SlugifyFunction, TransliterateFunction } from '../types';
export declare const transliterate: TransliterateFunction;
export declare const slugify: SlugifyFunction;
export * from '../types';

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.slugify = exports.transliterate = void 0;
const slugify_1 = require("../common/slugify");
const transliterate_1 = require("../common/transliterate");
const t = new transliterate_1.Transliterate();
exports.transliterate = t.transliterate.bind(t);
exports.transliterate.config = t.config.bind(t);
exports.transliterate.setData = t.setData.bind(t);
const s = new slugify_1.Slugify();
exports.slugify = s.slugify.bind(s);
exports.slugify.config = s.config.bind(s);
exports.slugify.setData = s.setData.bind(s);

View File

@@ -0,0 +1,99 @@
import { Charmap } from '../../data/charmap';
export declare type OptionReplaceArrayItem = [string | RegExp, string];
export declare type OptionReplaceArray = OptionReplaceArrayItem[];
export interface OptionReplaceObject {
[from: string]: string;
}
export declare type OptionReplaceCombined = OptionReplaceArray | OptionReplaceObject;
export interface OptionsTransliterate {
/**
* Ignore a list of strings untouched
* @example tr('你好,世界', { ignore: ['你'] }) // 你 Hao , Shi Jie
*/
ignore?: string[];
/**
* Replace a list of string / regex in the source string into the provided target string before transliteration
* The option can either be an array or an object
* @example tr('你好,世界', { replace: {你: 'You'} }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [['你', 'You']] }) // You Hao , Shi Jie
* @example tr('你好,世界', { replace: [[/你/g, 'You']] }) // You Hao , Shi Jie
*/
replace?: OptionReplaceCombined;
/**
* Same as `replace` but after transliteration
*/
replaceAfter?: OptionReplaceCombined;
/**
* Decides whether or not to trim the result string after transliteration
* @default false
*/
trim?: boolean;
/**
* Any characters not known by this library will be replaced by a specific string `unknown`
* @default ''
*/
unknown?: string;
/**
* Fix Chinese spacing. For example, `你好` is transliterated to `Ni Hao` instead of `NiHao`. If you don't need to transliterate Chinese characters, set it to false to false to improve performance.
* @default true
*/
fixChineseSpacing?: boolean;
}
export interface OptionsSlugify extends OptionsTransliterate {
/**
* Whether the result need to be converted into lowercase
* @default true
*/
lowercase?: boolean;
/**
* Whether the result need to be converted into uppercase
* @default false
*/
uppercase?: boolean;
/**
* Custom separator string
* @default '-'
*/
separator?: string;
/**
* Allowed characters.
* When `allowedChars` is set to `'abc'`, then only characters match `/[abc]/g` will be preserved.
* Other characters will all be converted to `separator`
* @default 'a-zA-Z0-9-_.~''
*/
allowedChars?: string;
/**
* Fix Chinese spacing. For example, `你好` is transliterated to `Ni Hao` instead of `NiHao`. If you don't need to transliterate Chinese characters, set it to false to false to improve performance.
*/
fixChineseSpacing?: boolean;
}
export declare type Options = OptionsTransliterate | OptionsSlugify;
export declare type IntervalArray = [number, number][];
interface TransliterationFunction<T> {
(source: string, options?: T): string;
/**
* Set default config
* @param options
* @param reset
*/
config: (options?: T, reset?: boolean) => T;
/**
* Set charmap data
* @param data
* @param reset
* @memberof Transliterate
*/
setData: (data?: Charmap, reset?: boolean) => Charmap;
/**
* Used by browser
*/
noConflict?: () => TransliterationFunction<T>;
}
export declare type TransliterateFunction = TransliterationFunction<OptionsTransliterate>;
export declare type SlugifyFunction = TransliterationFunction<OptionsSlugify>;
export interface BrowserGlobalObject {
transl: TransliterateFunction;
transliterate: TransliterateFunction;
slugify: SlugifyFunction;
}
export {};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

90
node_modules/transliteration/package.json generated vendored Normal file
View File

@@ -0,0 +1,90 @@
{
"name": "transliteration",
"version": "2.3.5",
"description": "Unicode to ACSII transliteration / slugify module for node.js, browser, Web Worker, ReactNative and CLI.",
"main": "dist/node/src/node/index.js",
"module": "dist/browser/bundle.esm.min.js",
"jsnext": "dist/browser/bundle.esm.min.js",
"browser": "dist/browser/bundle.umd.min.js",
"bin": {
"transliterate": "dist/bin/transliterate",
"slugify": "dist/bin/slugify"
},
"types": "dist/node/src/node/index.d.ts",
"scripts": {
"generate:data": "node scripts/generate_data.js",
"lint": "tslint -c tslint.json src/**/*.ts test/**/*.ts",
"pretest": "npm run lint",
"test": "npm run test:node && npm run test:cli",
"test:node": "ts-node node_modules/tape/bin/tape test/common/*.ts | tap-spec",
"test:cli": "ts-node node_modules/tape/bin/tape test/cli/*.ts | tap-spec",
"prebuild": "npm run generate:data && rimraf dist",
"build": "rollup -c rollup.config.js && rimraf .rpt2_cache && tsc",
"postbuild": "(ver && (echo export * from '../types';>> dist/node/src/node/index.d.ts)) || (echo \"export * from '../types';\">> dist/node/src/node/index.d.ts)",
"coverage": "nyc npm test",
"coveralls": "nyc npm test && nyc report -r=text-lcov | coveralls",
"prepublish": "npm run lint && npm test && npm run build"
},
"nyc": {
"extension": [
".ts"
]
},
"repository": {
"type": "git",
"url": "https://github.com/dzcpy/transliteration.git"
},
"keywords": [
"transliterate",
"transliteration",
"utf8",
"slug",
"slugify",
"romanization",
"unicode",
"unidecode"
],
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/dzcpy/transliteration/issues"
},
"engines": {
"node": ">=6.0.0"
},
"devDependencies": {
"@babel/core": "7.18.6",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-object-rest-spread": "7.18.6",
"@babel/preset-env": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@types/tape": "4.13.2",
"@types/yargs": "17.0.10",
"codecov": "3.8.3",
"core-js": "3.23.3",
"coveralls": "3.1.1",
"eslint-config-prettier": "^8.5.0",
"json5": "2.2.1",
"nyc": "15.1.0",
"prettier": "^2.7.1",
"rimraf": "3.0.2",
"rollup": "2.75.7",
"rollup-plugin-babel": "5.0.0-alpha.2",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-hashbang": "3.0.0",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-typescript2": "0.32.1",
"rollup-plugin-uglify": "6.0.4",
"tap-spec": "5.0.0",
"tape": "5.5.3",
"ts-loader": "9.3.1",
"ts-node": "10.8.2",
"tslint": "6.1.3",
"tslint-config-prettier": "1.18.0",
"typescript": "4.7.4"
},
"dependencies": {
"yargs": "^17.5.1"
}
}