Comparing version 9.0.0-beta.1 to 9.0.0
{ | ||
"name": "slug", | ||
"description": "slugifies even utf-8 chars!", | ||
"version": "9.0.0-beta.1", | ||
"version": "9.0.0", | ||
"homepage": "https://github.com/Trott/slug", | ||
"author": "dodo (https://github.com/dodo)", | ||
"type": "module", | ||
"repository": { | ||
@@ -14,5 +13,5 @@ "type": "git", | ||
"main": "slug.js", | ||
"files": [ | ||
"slug.js" | ||
], | ||
"bin": { | ||
"slug": "cli.js" | ||
}, | ||
"keywords": [ | ||
@@ -28,3 +27,3 @@ "slugify", | ||
"scripts": { | ||
"test": "standard && c8 --100 mocha test/**/*.js && karma start --single-run --browsers ChromeHeadless,FirefoxHeadless .karma.config.cjs", | ||
"test": "standard && mocha test/*.mjs && nyc --reporter none mocha test/**/*.js && karma start --single-run --browsers ChromeHeadless .karma.config.js && nyc report --reporter=text --reporter=html && nyc check-coverage --lines 100 --branches 100 --statements 100 --functions 100", | ||
"benchmark": "node benchmark/benchmark.js" | ||
@@ -35,4 +34,3 @@ }, | ||
"@semantic-release/git": "^10.0.1", | ||
"c8": "^7.11.2", | ||
"chai": "^4.2.0", | ||
"chai": "^4.4.0", | ||
"karma": "^6.3.19", | ||
@@ -42,8 +40,8 @@ "karma-chai": "^0.1.0", | ||
"karma-coverage": "^2.1.1", | ||
"karma-firefox-launcher": "^2.0.0", | ||
"karma-jasmine": "^5.0.0", | ||
"karma-mocha": "^2.0.1", | ||
"mocha": "^10.0.0", | ||
"semantic-release": "^19.0.1", | ||
"standard": "^17.0.0" | ||
"nyc": "^15.0.1", | ||
"semantic-release": "^23.0.0", | ||
"standard": "^17.1.0" | ||
}, | ||
@@ -50,0 +48,0 @@ "license": "MIT", |
@@ -9,3 +9,3 @@ # [slug](https://github.com/Trott/slug) | ||
- No dependencies | ||
- Works in the browser or in Node.js | ||
- Works in browser (`window.slug`) and AMD/CommonJS-flavoured module loaders | ||
@@ -22,21 +22,6 @@ ``` | ||
## Differences between `slug` and `slugify` packages | ||
Here are some key differences between this package and [`slugify`](https://github.com/simov/slugify). | ||
- **Defaults:** `slug` has the `lower` option enabled by default, lowercasing all slugs | ||
(`'On SALE'` becomes `'on-sale'`). | ||
`slugify` has the `lower` option disabled by default (`'On SALE'` becomes `'On-SALE'`). | ||
- **Symbols:** `slug` removes unrecognized symbols (`'$100'` becomes `'100'`, `'<5'` becomes `'5'`, etc.). | ||
`slugify` maps them to words (`'$100'` becomes `'dollar100'`, `'<5'` becomes `'less5'`, etc.). | ||
- **Empty Output:** `slug` will return a short, predictable hash (`' '` becomes `'icag'` and `'🎉'` becomes `'8joiq'`). | ||
`slugify` will return an empty string (`' '` and `'🎉'` become `''`). | ||
- **Stability:** `slug` is planning [a new release](https://github.com/Trott/slug/blob/beta/CHANGELOG.md) that will drop support for CommonJS | ||
and only support ESM modules. | ||
`slugify` will continue to support CommonJS and is likely to remain stable for the foreseeable future. | ||
## Example | ||
```javascript | ||
import slug from 'slug' | ||
var slug = require('slug') | ||
var print = console.log.bind(console, '>') | ||
@@ -57,3 +42,3 @@ | ||
print(slug('I ♥ UNICODE')) | ||
// > i_unicode | ||
// > i-unicode | ||
@@ -130,1 +115,26 @@ print(slug('Telephone-Number')) // lower case by default | ||
``` | ||
## Differences between `slug` and `slugify` packages | ||
Here are some key differences between this package and [`slugify`](https://github.com/simov/slugify). | ||
- **Defaults:** `slug` has the `lower` option enabled by default, lowercasing all slugs | ||
(`'On SALE'` becomes `'on-sale'`). | ||
`slugify` has the `lower` option disabled by default (`'On SALE'` becomes `'On-SALE'`). | ||
- **Symbols:** `slug` removes unrecognized symbols (`'$100'` becomes `'100'`, `'<5'` becomes `'5'`, etc.). | ||
`slugify` maps them to words (`'$100'` becomes `'dollar100'`, `'<5'` becomes `'less5'`, etc.). | ||
- **Empty Output:** `slug` will return a short, predictable hash (`' '` becomes `'icag'` and `'🎉'` becomes `'8joiq'`). | ||
`slugify` will return an empty string (`' '` and `'🎉'` become `''`). | ||
- **Stability:** `slug` is planning [a new release](https://github.com/Trott/slug/blob/beta/CHANGELOG.md) that will drop support for CommonJS | ||
and only support ESM modules. | ||
`slugify` will continue to support CommonJS and is likely to remain stable for the foreseeable future. | ||
## Playground | ||
A (painfully minimal) web playground is available at | ||
https://trott.github.io/slug/. It doesn't allow you to specify options, so it's utility is minimal. Pull requests welcome to add the ability to | ||
specify options. | ||
There is also a (similarly minimal) CLI tool available via `npx slug`. | ||
As with the web playground, it doesn't allow you to specify options, so | ||
it's utility is minimal. |
1698
slug.js
/* global btoa */ | ||
let base64 | ||
(function (root) { | ||
let base64 | ||
// This function's sole purpose is to help us ignore lone surrogates so that | ||
// malformed strings don't throw in the browser while being processed | ||
// permissively in Node.js. If we didn't care about parity, we could get rid | ||
// of it. | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt | ||
function getWholeCharAndI (str, i) { | ||
const code = str.charCodeAt(i) | ||
// This function's sole purpose is to help us ignore lone surrogates so that | ||
// malformed strings don't throw in the browser while being processed | ||
// permissively in Node.js. If we didn't care about parity, we could get rid | ||
// of it. | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt | ||
function getWholeCharAndI (str, i) { | ||
const code = str.charCodeAt(i) | ||
// This is a coherence check. `code` should never be `NaN`. | ||
/* c8 ignore start */ | ||
if (isNaN(code)) { | ||
throw new RangeError('Index ' + i + ' out of range for string "' + str + '"; please open an issue at https://github.com/Trott/slug/issues/new') | ||
} | ||
/* c8 ignore stop */ | ||
if (code < 0xD800 || code > 0xDFFF) { | ||
return [str.charAt(i), i] // Non-surrogate character, keeping 'i' the same | ||
} | ||
// This is a coherence check. `code` should never be `NaN`. | ||
/* istanbul ignore if */ | ||
if (isNaN(code)) { | ||
throw new RangeError('Index ' + i + ' out of range for string "' + str + '"; please open an issue at https://github.com/Trott/slug/issues/new') | ||
} | ||
if (code < 0xD800 || code > 0xDFFF) { | ||
return [str.charAt(i), i] // Non-surrogate character, keeping 'i' the same | ||
} | ||
// High surrogate | ||
if (code >= 0xD800 && code <= 0xDBFF) { | ||
if (str.length <= (i + 1)) { | ||
// High surrogate without following low surrogate | ||
return [' ', i] | ||
// High surrogate | ||
if (code >= 0xD800 && code <= 0xDBFF) { | ||
if (str.length <= (i + 1)) { | ||
// High surrogate without following low surrogate | ||
return [' ', i] | ||
} | ||
const next = str.charCodeAt(i + 1) | ||
if (next < 0xDC00 || next > 0xDFFF) { | ||
// High surrogate without following low surrogate | ||
return [' ', i] | ||
} | ||
return [str.charAt(i) + str.charAt(i + 1), i + 1] | ||
} | ||
const next = str.charCodeAt(i + 1) | ||
if (next < 0xDC00 || next > 0xDFFF) { | ||
// High surrogate without following low surrogate | ||
// Low surrogate (0xDC00 <= code && code <= 0xDFFF) | ||
if (i === 0) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
} | ||
return [str.charAt(i) + str.charAt(i + 1), i + 1] | ||
} | ||
// Low surrogate (0xDC00 <= code && code <= 0xDFFF) | ||
if (i === 0) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
} | ||
const prev = str.charCodeAt(i - 1) | ||
const prev = str.charCodeAt(i - 1) | ||
/* istanbul ignore else */ | ||
if (prev < 0xD800 || prev > 0xDBFF) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
} | ||
if (prev < 0xD800 || prev > 0xDBFF) { | ||
// Low surrogate without preceding high surrogate | ||
return [' ', i] | ||
/* istanbul ignore next */ | ||
throw new Error('String "' + str + '" reaches code believed to be unreachable; please open an issue at https://github.com/Trott/slug/issues/new') | ||
} | ||
/* c8 ignore next */ | ||
throw new Error('String "' + str + '" reaches code believed to be unreachable; please open an issue at https://github.com/Trott/slug/issues/new') | ||
} | ||
if (typeof window !== 'undefined') { | ||
if (window.btoa) { | ||
base64 = function (input) { | ||
return btoa(unescape(encodeURIComponent(input))) | ||
if (typeof window !== 'undefined') { | ||
if (window.btoa) { | ||
base64 = function (input) { | ||
return btoa(unescape(encodeURIComponent(input))) | ||
} | ||
} else { | ||
// Polyfill for environments that don't have btoa or Buffer class (notably, React Native). | ||
// Based on https://github.com/davidchambers/Base64.js/blob/a121f75bb10c8dd5d557886c4b1069b31258d230/base64.js | ||
base64 = function (input) { | ||
const str = unescape(encodeURIComponent(input + '')) | ||
let output = '' | ||
for ( | ||
let block, charCode, idx = 0, map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | ||
str.charAt(idx | 0) || (map = '=', idx % 1); | ||
output += map.charAt(63 & block >> 8 - idx % 1 * 8) | ||
) { | ||
charCode = str.charCodeAt(idx += 3 / 4) | ||
// This is a coherence check. The result of unescape(encodeURIComponent()) should always be | ||
// characters with code points that fit into two bytes. | ||
/* istanbul ignore next */ | ||
if (charCode > 0xFF) { | ||
throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.") | ||
} | ||
block = block << 8 | charCode | ||
} | ||
return output | ||
} | ||
} | ||
} else { | ||
// Polyfill for environments that don't have btoa or Buffer class (notably, React Native). | ||
// Based on https://github.com/davidchambers/Base64.js/blob/a121f75bb10c8dd5d557886c4b1069b31258d230/base64.js | ||
base64 = function (input) { | ||
const str = unescape(encodeURIComponent(input + '')) | ||
let output = '' | ||
for ( | ||
let block, charCode, idx = 0, map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | ||
str.charAt(idx | 0) || (map = '=', idx % 1); | ||
output += map.charAt(63 & block >> 8 - idx % 1 * 8) | ||
) { | ||
charCode = str.charCodeAt(idx += 3 / 4) | ||
// TODO: The if condition may be guaranteed to be false. Verify and | ||
// remove or otherwise write a test to cover it. | ||
/* c8 ignore start */ | ||
if (charCode > 0xFF) { | ||
throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.") | ||
} | ||
/* c8 ignore stop */ | ||
block = block << 8 | charCode | ||
} | ||
return output | ||
return Buffer.from(input).toString('base64') | ||
} | ||
} | ||
} else { | ||
base64 = function (input) { | ||
return Buffer.from(input).toString('base64') | ||
} | ||
} | ||
/* c8 ignore start */ | ||
if (typeof Object.assign !== 'function') { | ||
throw new Error('Runtime environment does not support Object.assign()') | ||
} | ||
/* c8 ignore stop */ | ||
function slug (string, opts) { | ||
let result = slugify(string, opts) | ||
const fallback = opts && opts.fallback !== undefined ? opts.fallback : slug.defaults.fallback | ||
// If output is an empty string, try slug for base64 of string. | ||
if (fallback === true && result === '') { | ||
// Get rid of lone surrogates. | ||
let input = '' | ||
for (let i = 0; i < string.length; i++) { | ||
const charAndI = getWholeCharAndI(string, i) | ||
i = charAndI[1] | ||
input += charAndI[0] | ||
function slug (string, opts) { | ||
let result = slugify(string, opts) | ||
const fallback = opts && opts.fallback !== undefined ? opts.fallback : slug.defaults.fallback | ||
// If output is an empty string, try slug for base64 of string. | ||
if (fallback === true && result === '') { | ||
// Get rid of lone surrogates. | ||
let input = '' | ||
for (let i = 0; i < string.length; i++) { | ||
const charAndI = getWholeCharAndI(string, i) | ||
i = charAndI[1] | ||
input += charAndI[0] | ||
} | ||
result = slugify(base64(input), opts) | ||
} | ||
result = slugify(base64(input), opts) | ||
return result | ||
} | ||
return result | ||
} | ||
const locales = { | ||
// http://www.eki.ee/wgrs/rom1_bg.pdf | ||
bg: { Й: 'Y', й: 'y', X: 'H', x: 'h', Ц: 'Ts', ц: 'ts', Щ: 'Sht', щ: 'sht', Ъ: 'A', ъ: 'a', Ь: 'Y', ь: 'y' }, | ||
// Need a reference URL for German, although this is pretty well-known. | ||
de: { Ä: 'AE', ä: 'ae', Ö: 'OE', ö: 'oe', Ü: 'UE', ü: 'ue' }, | ||
// Need a reference URL for Serbian. | ||
sr: { đ: 'dj', Đ: 'DJ' }, | ||
// https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/864314/ROMANIZATION_OF_UKRAINIAN.pdf | ||
uk: { И: 'Y', и: 'y', Й: 'Y', й: 'y', Ц: 'Ts', ц: 'ts', Х: 'Kh', х: 'kh', Щ: 'Shch', щ: 'shch', Г: 'H', г: 'h' } | ||
} | ||
const locales = { | ||
// http://www.eki.ee/wgrs/rom1_bg.pdf | ||
bg: { Й: 'Y', й: 'y', X: 'H', x: 'h', Ц: 'Ts', ц: 'ts', Щ: 'Sht', щ: 'sht', Ъ: 'A', ъ: 'a', Ь: 'Y', ь: 'y' }, | ||
// Need a reference URL for German, although this is pretty well-known. | ||
de: { Ä: 'AE', ä: 'ae', Ö: 'OE', ö: 'oe', Ü: 'UE', ü: 'ue' }, | ||
// Need a reference URL for Serbian. | ||
sr: { đ: 'dj', Đ: 'DJ' }, | ||
// https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/864314/ROMANIZATION_OF_UKRAINIAN.pdf | ||
uk: { И: 'Y', и: 'y', Й: 'Y', й: 'y', Ц: 'Ts', ц: 'ts', Х: 'Kh', х: 'kh', Щ: 'Shch', щ: 'shch', Г: 'H', г: 'h' } | ||
} | ||
let defaultLocale = {} | ||
let defaultLocale = {} | ||
function slugify (string, opts) { | ||
if (typeof string !== 'string') { | ||
throw new Error('slug() requires a string argument, received ' + typeof string) | ||
} | ||
if (typeof opts === 'string') { opts = { replacement: opts } } | ||
opts = opts ? Object.assign({}, opts) : {} | ||
opts.mode = opts.mode || slug.defaults.mode | ||
const defaults = slug.defaults.modes[opts.mode] | ||
const keys = ['replacement', 'multicharmap', 'charmap', 'remove', 'lower', 'trim'] | ||
for (let key, i = 0, l = keys.length; i < l; i++) { | ||
key = keys[i] | ||
opts[key] = (key in opts) ? opts[key] : defaults[key] | ||
} | ||
const localeMap = locales[opts.locale] || defaultLocale | ||
function slugify (string, opts) { | ||
if (typeof string !== 'string') { | ||
throw new Error('slug() requires a string argument, received ' + typeof string) | ||
} | ||
if (typeof opts === 'string') { opts = { replacement: opts } } | ||
opts = opts ? Object.assign({}, opts) : {} | ||
opts.mode = opts.mode || slug.defaults.mode | ||
const defaults = slug.defaults.modes[opts.mode] | ||
const keys = ['replacement', 'multicharmap', 'charmap', 'remove', 'lower', 'trim'] | ||
for (let key, i = 0, l = keys.length; i < l; i++) { | ||
key = keys[i] | ||
opts[key] = (key in opts) ? opts[key] : defaults[key] | ||
} | ||
const localeMap = locales[opts.locale] || defaultLocale | ||
let lengths = [] | ||
for (const key in opts.multicharmap) { | ||
if (!Object.prototype.hasOwnProperty.call(opts.multicharmap, key)) { continue } | ||
let lengths = [] | ||
for (const key in opts.multicharmap) { | ||
if (!Object.prototype.hasOwnProperty.call(opts.multicharmap, key)) { continue } | ||
const len = key.length | ||
if (lengths.indexOf(len) === -1) { lengths.push(len) } | ||
} | ||
const len = key.length | ||
if (lengths.indexOf(len) === -1) { lengths.push(len) } | ||
} | ||
// We want to match the longest string if there are multiple matches, so | ||
// sort lengths in descending order. | ||
lengths = lengths.sort(function (a, b) { return b - a }) | ||
// We want to match the longest string if there are multiple matches, so | ||
// sort lengths in descending order. | ||
lengths = lengths.sort(function (a, b) { return b - a }) | ||
const disallowedChars = opts.mode === 'rfc3986' ? /[^\w\s\-.~]/ : /[^A-Za-z0-9\s]/ | ||
const disallowedChars = opts.mode === 'rfc3986' ? /[^\w\s\-.~]/ : /[^A-Za-z0-9\s]/ | ||
let result = '' | ||
for (let char, i = 0, l = string.length; i < l; i++) { | ||
char = string[i] | ||
let matchedMultichar = false | ||
for (let j = 0; j < lengths.length; j++) { | ||
const len = lengths[j] | ||
const str = string.substr(i, len) | ||
if (opts.multicharmap[str]) { | ||
i += len - 1 | ||
char = opts.multicharmap[str] | ||
matchedMultichar = true | ||
break | ||
let result = '' | ||
for (let char, i = 0, l = string.length; i < l; i++) { | ||
char = string[i] | ||
let matchedMultichar = false | ||
for (let j = 0; j < lengths.length; j++) { | ||
const len = lengths[j] | ||
const str = string.substr(i, len) | ||
if (opts.multicharmap[str]) { | ||
i += len - 1 | ||
char = opts.multicharmap[str] | ||
matchedMultichar = true | ||
break | ||
} | ||
} | ||
} | ||
if (!matchedMultichar) { | ||
if (localeMap[char]) { | ||
char = localeMap[char] | ||
} else if (opts.charmap[char]) { | ||
char = opts.charmap[char].replace(opts.replacement, ' ') | ||
} else if (char.includes(opts.replacement)) { | ||
// preserve the replacement character in case it is excluded by disallowedChars | ||
char = char.replace(opts.replacement, ' ') | ||
} else { | ||
char = char.replace(disallowedChars, '') | ||
if (!matchedMultichar) { | ||
if (localeMap[char]) { | ||
char = localeMap[char] | ||
} else if (opts.charmap[char]) { | ||
char = opts.charmap[char].replace(opts.replacement, ' ') | ||
} else if (char.includes(opts.replacement)) { | ||
// preserve the replacement character in case it is excluded by disallowedChars | ||
char = char.replace(opts.replacement, ' ') | ||
} else { | ||
char = char.replace(disallowedChars, '') | ||
} | ||
} | ||
result += char | ||
} | ||
result += char | ||
if (opts.remove) { | ||
result = result.replace(opts.remove, '') | ||
} | ||
if (opts.trim) { | ||
result = result.trim() | ||
} | ||
result = result.replace(/\s+/g, opts.replacement) // convert spaces | ||
if (opts.lower) { | ||
result = result.toLowerCase() | ||
} | ||
return result | ||
} | ||
if (opts.remove) { | ||
result = result.replace(opts.remove, '') | ||
const initialMulticharmap = { | ||
// multibyte devanagari characters (hindi, sanskrit, etc.) | ||
फ़: 'Fi', | ||
ग़: 'Ghi', | ||
ख़: 'Khi', | ||
क़: 'Qi', | ||
ड़: 'ugDha', | ||
ढ़: 'ugDhha', | ||
य़: 'Yi', | ||
ज़: 'Za', | ||
// hebrew | ||
// Refs: http://www.eki.ee/wgrs/rom1_he.pdf | ||
// Refs: https://en.wikipedia.org/wiki/Niqqud | ||
בִי: 'i', | ||
בֵ: 'e', | ||
בֵי: 'e', | ||
בֶ: 'e', | ||
בַ: 'a', | ||
בָ: 'a', | ||
בֹ: 'o', | ||
וֹ: 'o', | ||
בֻ: 'u', | ||
וּ: 'u', | ||
בּ: 'b', | ||
כּ: 'k', | ||
ךּ: 'k', | ||
פּ: 'p', | ||
שׁ: 'sh', | ||
שׂ: 's', | ||
בְ: 'e', | ||
חֱ: 'e', | ||
חֲ: 'a', | ||
חֳ: 'o', | ||
בִ: 'i' | ||
} | ||
if (opts.trim) { | ||
result = result.trim() | ||
// https://github.com/django/django/blob/master/django/contrib/admin/static/admin/js/urlify.js | ||
const initialCharmap = { | ||
// latin | ||
À: 'A', | ||
Á: 'A', | ||
Â: 'A', | ||
Ã: 'A', | ||
Ä: 'A', | ||
Å: 'A', | ||
Æ: 'AE', | ||
Ç: 'C', | ||
È: 'E', | ||
É: 'E', | ||
Ê: 'E', | ||
Ë: 'E', | ||
Ì: 'I', | ||
Í: 'I', | ||
Î: 'I', | ||
Ï: 'I', | ||
Ð: 'D', | ||
Ñ: 'N', | ||
Ò: 'O', | ||
Ó: 'O', | ||
Ô: 'O', | ||
Õ: 'O', | ||
Ö: 'O', | ||
Ő: 'O', | ||
Ø: 'O', | ||
Ō: 'O', | ||
Ù: 'U', | ||
Ú: 'U', | ||
Û: 'U', | ||
Ü: 'U', | ||
Ű: 'U', | ||
Ý: 'Y', | ||
Þ: 'TH', | ||
ß: 'ss', | ||
à: 'a', | ||
á: 'a', | ||
â: 'a', | ||
ã: 'a', | ||
ä: 'a', | ||
å: 'a', | ||
æ: 'ae', | ||
ç: 'c', | ||
è: 'e', | ||
é: 'e', | ||
ê: 'e', | ||
ë: 'e', | ||
ì: 'i', | ||
í: 'i', | ||
î: 'i', | ||
ï: 'i', | ||
ð: 'd', | ||
ñ: 'n', | ||
ò: 'o', | ||
ó: 'o', | ||
ô: 'o', | ||
õ: 'o', | ||
ö: 'o', | ||
ő: 'o', | ||
ø: 'o', | ||
ō: 'o', | ||
Œ: 'OE', | ||
œ: 'oe', | ||
ù: 'u', | ||
ú: 'u', | ||
û: 'u', | ||
ü: 'u', | ||
ű: 'u', | ||
ý: 'y', | ||
þ: 'th', | ||
ÿ: 'y', | ||
ẞ: 'SS', | ||
// greek | ||
α: 'a', | ||
β: 'b', | ||
γ: 'g', | ||
δ: 'd', | ||
ε: 'e', | ||
ζ: 'z', | ||
η: 'h', | ||
θ: 'th', | ||
ι: 'i', | ||
κ: 'k', | ||
λ: 'l', | ||
μ: 'm', | ||
ν: 'n', | ||
ξ: '3', | ||
ο: 'o', | ||
π: 'p', | ||
ρ: 'r', | ||
σ: 's', | ||
τ: 't', | ||
υ: 'y', | ||
φ: 'f', | ||
χ: 'x', | ||
ψ: 'ps', | ||
ω: 'w', | ||
ά: 'a', | ||
έ: 'e', | ||
ί: 'i', | ||
ό: 'o', | ||
ύ: 'y', | ||
ή: 'h', | ||
ώ: 'w', | ||
ς: 's', | ||
ϊ: 'i', | ||
ΰ: 'y', | ||
ϋ: 'y', | ||
ΐ: 'i', | ||
Α: 'A', | ||
Β: 'B', | ||
Γ: 'G', | ||
Δ: 'D', | ||
Ε: 'E', | ||
Ζ: 'Z', | ||
Η: 'H', | ||
Θ: 'Th', | ||
Ι: 'I', | ||
Κ: 'K', | ||
Λ: 'L', | ||
Μ: 'M', | ||
Ν: 'N', | ||
Ξ: '3', | ||
Ο: 'O', | ||
Π: 'P', | ||
Ρ: 'R', | ||
Σ: 'S', | ||
Τ: 'T', | ||
Υ: 'Y', | ||
Φ: 'F', | ||
Χ: 'X', | ||
Ψ: 'PS', | ||
Ω: 'W', | ||
Ά: 'A', | ||
Έ: 'E', | ||
Ί: 'I', | ||
Ό: 'O', | ||
Ύ: 'Y', | ||
Ή: 'H', | ||
Ώ: 'W', | ||
Ϊ: 'I', | ||
Ϋ: 'Y', | ||
// turkish | ||
ş: 's', | ||
Ş: 'S', | ||
ı: 'i', | ||
İ: 'I', | ||
ğ: 'g', | ||
Ğ: 'G', | ||
// russian | ||
а: 'a', | ||
б: 'b', | ||
в: 'v', | ||
г: 'g', | ||
д: 'd', | ||
е: 'e', | ||
ё: 'yo', | ||
ж: 'zh', | ||
з: 'z', | ||
и: 'i', | ||
й: 'j', | ||
к: 'k', | ||
л: 'l', | ||
м: 'm', | ||
н: 'n', | ||
о: 'o', | ||
п: 'p', | ||
р: 'r', | ||
с: 's', | ||
т: 't', | ||
у: 'u', | ||
ф: 'f', | ||
х: 'h', | ||
ц: 'c', | ||
ч: 'ch', | ||
ш: 'sh', | ||
щ: 'sh', | ||
ъ: 'u', | ||
ы: 'y', | ||
ь: '', | ||
э: 'e', | ||
ю: 'yu', | ||
я: 'ya', | ||
А: 'A', | ||
Б: 'B', | ||
В: 'V', | ||
Г: 'G', | ||
Д: 'D', | ||
Е: 'E', | ||
Ё: 'Yo', | ||
Ж: 'Zh', | ||
З: 'Z', | ||
И: 'I', | ||
Й: 'J', | ||
К: 'K', | ||
Л: 'L', | ||
М: 'M', | ||
Н: 'N', | ||
О: 'O', | ||
П: 'P', | ||
Р: 'R', | ||
С: 'S', | ||
Т: 'T', | ||
У: 'U', | ||
Ф: 'F', | ||
Х: 'H', | ||
Ц: 'C', | ||
Ч: 'Ch', | ||
Ш: 'Sh', | ||
Щ: 'Sh', | ||
Ъ: 'U', | ||
Ы: 'Y', | ||
Ь: '', | ||
Э: 'E', | ||
Ю: 'Yu', | ||
Я: 'Ya', | ||
// ukranian | ||
Є: 'Ye', | ||
І: 'I', | ||
Ї: 'Yi', | ||
Ґ: 'G', | ||
є: 'ye', | ||
і: 'i', | ||
ї: 'yi', | ||
ґ: 'g', | ||
// czech | ||
č: 'c', | ||
ď: 'd', | ||
ě: 'e', | ||
ň: 'n', | ||
ř: 'r', | ||
š: 's', | ||
ť: 't', | ||
ů: 'u', | ||
ž: 'z', | ||
Č: 'C', | ||
Ď: 'D', | ||
Ě: 'E', | ||
Ň: 'N', | ||
Ř: 'R', | ||
Š: 'S', | ||
Ť: 'T', | ||
Ů: 'U', | ||
Ž: 'Z', | ||
// slovak | ||
ľ: 'l', | ||
ĺ: 'l', | ||
ŕ: 'r', | ||
Ľ: 'L', | ||
Ĺ: 'L', | ||
Ŕ: 'R', | ||
// polish | ||
ą: 'a', | ||
ć: 'c', | ||
ę: 'e', | ||
ł: 'l', | ||
ń: 'n', | ||
ś: 's', | ||
ź: 'z', | ||
ż: 'z', | ||
Ą: 'A', | ||
Ć: 'C', | ||
Ę: 'E', | ||
Ł: 'L', | ||
Ń: 'N', | ||
Ś: 'S', | ||
Ź: 'Z', | ||
Ż: 'Z', | ||
// latvian | ||
ā: 'a', | ||
ē: 'e', | ||
ģ: 'g', | ||
ī: 'i', | ||
ķ: 'k', | ||
ļ: 'l', | ||
ņ: 'n', | ||
ū: 'u', | ||
Ā: 'A', | ||
Ē: 'E', | ||
Ģ: 'G', | ||
Ī: 'I', | ||
Ķ: 'K', | ||
Ļ: 'L', | ||
Ņ: 'N', | ||
Ū: 'U', | ||
// arabic | ||
أ: 'a', | ||
إ: 'i', | ||
ب: 'b', | ||
ت: 't', | ||
ث: 'th', | ||
ج: 'g', | ||
ح: 'h', | ||
خ: 'kh', | ||
د: 'd', | ||
ذ: 'th', | ||
ر: 'r', | ||
ز: 'z', | ||
س: 's', | ||
ش: 'sh', | ||
ص: 's', | ||
ض: 'd', | ||
ط: 't', | ||
ظ: 'th', | ||
ع: 'aa', | ||
غ: 'gh', | ||
ف: 'f', | ||
ق: 'k', | ||
ك: 'k', | ||
ل: 'l', | ||
م: 'm', | ||
ن: 'n', | ||
ه: 'h', | ||
و: 'o', | ||
ي: 'y', | ||
ء: 'aa', | ||
ة: 'a', | ||
// farsi | ||
آ: 'a', | ||
ا: 'a', | ||
پ: 'p', | ||
ژ: 'zh', | ||
گ: 'g', | ||
چ: 'ch', | ||
ک: 'k', | ||
ی: 'i', | ||
// lithuanian | ||
ė: 'e', | ||
į: 'i', | ||
ų: 'u', | ||
Ė: 'E', | ||
Į: 'I', | ||
Ų: 'U', | ||
// romanian | ||
ț: 't', | ||
Ț: 'T', | ||
ţ: 't', | ||
Ţ: 'T', | ||
ș: 's', | ||
Ș: 'S', | ||
ă: 'a', | ||
Ă: 'A', | ||
// vietnamese | ||
Ạ: 'A', | ||
Ả: 'A', | ||
Ầ: 'A', | ||
Ấ: 'A', | ||
Ậ: 'A', | ||
Ẩ: 'A', | ||
Ẫ: 'A', | ||
Ằ: 'A', | ||
Ắ: 'A', | ||
Ặ: 'A', | ||
Ẳ: 'A', | ||
Ẵ: 'A', | ||
Ẹ: 'E', | ||
Ẻ: 'E', | ||
Ẽ: 'E', | ||
Ề: 'E', | ||
Ế: 'E', | ||
Ệ: 'E', | ||
Ể: 'E', | ||
Ễ: 'E', | ||
Ị: 'I', | ||
Ỉ: 'I', | ||
Ĩ: 'I', | ||
Ọ: 'O', | ||
Ỏ: 'O', | ||
Ồ: 'O', | ||
Ố: 'O', | ||
Ộ: 'O', | ||
Ổ: 'O', | ||
Ỗ: 'O', | ||
Ơ: 'O', | ||
Ờ: 'O', | ||
Ớ: 'O', | ||
Ợ: 'O', | ||
Ở: 'O', | ||
Ỡ: 'O', | ||
Ụ: 'U', | ||
Ủ: 'U', | ||
Ũ: 'U', | ||
Ư: 'U', | ||
Ừ: 'U', | ||
Ứ: 'U', | ||
Ự: 'U', | ||
Ử: 'U', | ||
Ữ: 'U', | ||
Ỳ: 'Y', | ||
Ỵ: 'Y', | ||
Ỷ: 'Y', | ||
Ỹ: 'Y', | ||
Đ: 'D', | ||
ạ: 'a', | ||
ả: 'a', | ||
ầ: 'a', | ||
ấ: 'a', | ||
ậ: 'a', | ||
ẩ: 'a', | ||
ẫ: 'a', | ||
ằ: 'a', | ||
ắ: 'a', | ||
ặ: 'a', | ||
ẳ: 'a', | ||
ẵ: 'a', | ||
ẹ: 'e', | ||
ẻ: 'e', | ||
ẽ: 'e', | ||
ề: 'e', | ||
ế: 'e', | ||
ệ: 'e', | ||
ể: 'e', | ||
ễ: 'e', | ||
ị: 'i', | ||
ỉ: 'i', | ||
ĩ: 'i', | ||
ọ: 'o', | ||
ỏ: 'o', | ||
ồ: 'o', | ||
ố: 'o', | ||
ộ: 'o', | ||
ổ: 'o', | ||
ỗ: 'o', | ||
ơ: 'o', | ||
ờ: 'o', | ||
ớ: 'o', | ||
ợ: 'o', | ||
ở: 'o', | ||
ỡ: 'o', | ||
ụ: 'u', | ||
ủ: 'u', | ||
ũ: 'u', | ||
ư: 'u', | ||
ừ: 'u', | ||
ứ: 'u', | ||
ự: 'u', | ||
ử: 'u', | ||
ữ: 'u', | ||
ỳ: 'y', | ||
ỵ: 'y', | ||
ỷ: 'y', | ||
ỹ: 'y', | ||
đ: 'd', | ||
// kazakh | ||
Ә: 'AE', | ||
ә: 'ae', | ||
Ғ: 'GH', | ||
ғ: 'gh', | ||
Қ: 'KH', | ||
қ: 'kh', | ||
Ң: 'NG', | ||
ң: 'ng', | ||
Ү: 'UE', | ||
ү: 'ue', | ||
Ұ: 'U', | ||
ұ: 'u', | ||
Һ: 'H', | ||
һ: 'h', | ||
Ө: 'OE', | ||
ө: 'oe', | ||
// serbian | ||
ђ: 'dj', | ||
ј: 'j', | ||
љ: 'lj', | ||
њ: 'nj', | ||
ћ: 'c', | ||
џ: 'dz', | ||
Ђ: 'Dj', | ||
Ј: 'j', | ||
Љ: 'Lj', | ||
Њ: 'Nj', | ||
Ћ: 'C', | ||
Џ: 'Dz', | ||
nj: 'nj', | ||
lj: 'lj', | ||
Nj: 'NJ', | ||
Lj: 'LJ', | ||
// hindi | ||
अ: 'a', | ||
आ: 'aa', | ||
ए: 'e', | ||
ई: 'ii', | ||
ऍ: 'ei', | ||
ऎ: 'ae', | ||
ऐ: 'ai', | ||
इ: 'i', | ||
ओ: 'o', | ||
ऑ: 'oi', | ||
ऒ: 'oii', | ||
ऊ: 'uu', | ||
औ: 'ou', | ||
उ: 'u', | ||
ब: 'B', | ||
भ: 'Bha', | ||
च: 'Ca', | ||
छ: 'Chha', | ||
ड: 'Da', | ||
ढ: 'Dha', | ||
फ: 'Fa', | ||
ग: 'Ga', | ||
घ: 'Gha', | ||
ग़: 'Ghi', | ||
ह: 'Ha', | ||
ज: 'Ja', | ||
झ: 'Jha', | ||
क: 'Ka', | ||
ख: 'Kha', | ||
ख़: 'Khi', | ||
ल: 'L', | ||
ळ: 'Li', | ||
ऌ: 'Li', | ||
ऴ: 'Lii', | ||
ॡ: 'Lii', | ||
म: 'Ma', | ||
न: 'Na', | ||
ङ: 'Na', | ||
ञ: 'Nia', | ||
ण: 'Nae', | ||
ऩ: 'Ni', | ||
ॐ: 'oms', | ||
प: 'Pa', | ||
क़: 'Qi', | ||
र: 'Ra', | ||
ऋ: 'Ri', | ||
ॠ: 'Ri', | ||
ऱ: 'Ri', | ||
स: 'Sa', | ||
श: 'Sha', | ||
ष: 'Shha', | ||
ट: 'Ta', | ||
त: 'Ta', | ||
ठ: 'Tha', | ||
द: 'Tha', | ||
थ: 'Tha', | ||
ध: 'Thha', | ||
ड़: 'ugDha', | ||
ढ़: 'ugDhha', | ||
व: 'Va', | ||
य: 'Ya', | ||
य़: 'Yi', | ||
ज़: 'Za', | ||
// azerbaijani | ||
ə: 'e', | ||
Ə: 'E', | ||
// georgian | ||
ა: 'a', | ||
ბ: 'b', | ||
გ: 'g', | ||
დ: 'd', | ||
ე: 'e', | ||
ვ: 'v', | ||
ზ: 'z', | ||
თ: 't', | ||
ი: 'i', | ||
კ: 'k', | ||
ლ: 'l', | ||
მ: 'm', | ||
ნ: 'n', | ||
ო: 'o', | ||
პ: 'p', | ||
ჟ: 'zh', | ||
რ: 'r', | ||
ს: 's', | ||
ტ: 't', | ||
უ: 'u', | ||
ფ: 'p', | ||
ქ: 'k', | ||
ღ: 'gh', | ||
ყ: 'q', | ||
შ: 'sh', | ||
ჩ: 'ch', | ||
ც: 'ts', | ||
ძ: 'dz', | ||
წ: 'ts', | ||
ჭ: 'ch', | ||
ხ: 'kh', | ||
ჯ: 'j', | ||
ჰ: 'h', | ||
// hebrew | ||
ב: 'v', | ||
גּ: 'g', | ||
ג: 'g', | ||
ד: 'd', | ||
דּ: 'd', | ||
ה: 'h', | ||
ו: 'v', | ||
ז: 'z', | ||
ח: 'h', | ||
ט: 't', | ||
י: 'y', | ||
כ: 'kh', | ||
ך: 'kh', | ||
ל: 'l', | ||
מ: 'm', | ||
ם: 'm', | ||
נ: 'n', | ||
ן: 'n', | ||
ס: 's', | ||
פ: 'f', | ||
ף: 'f', | ||
ץ: 'ts', | ||
צ: 'ts', | ||
ק: 'k', | ||
ר: 'r', | ||
תּ: 't', | ||
ת: 't' | ||
} | ||
result = result.replace(/\s+/g, opts.replacement) // convert spaces | ||
if (opts.lower) { | ||
result = result.toLowerCase() | ||
} | ||
return result | ||
} | ||
const initialMulticharmap = { | ||
// multibyte devanagari characters (hindi, sanskrit, etc.) | ||
फ़: 'Fi', | ||
ग़: 'Ghi', | ||
ख़: 'Khi', | ||
क़: 'Qi', | ||
ड़: 'ugDha', | ||
ढ़: 'ugDhha', | ||
य़: 'Yi', | ||
ज़: 'Za', | ||
// hebrew | ||
// Refs: http://www.eki.ee/wgrs/rom1_he.pdf | ||
// Refs: https://en.wikipedia.org/wiki/Niqqud | ||
בִי: 'i', | ||
בֵ: 'e', | ||
בֵי: 'e', | ||
בֶ: 'e', | ||
בַ: 'a', | ||
בָ: 'a', | ||
בֹ: 'o', | ||
וֹ: 'o', | ||
בֻ: 'u', | ||
וּ: 'u', | ||
בּ: 'b', | ||
כּ: 'k', | ||
ךּ: 'k', | ||
פּ: 'p', | ||
שׁ: 'sh', | ||
שׂ: 's', | ||
בְ: 'e', | ||
חֱ: 'e', | ||
חֲ: 'a', | ||
חֳ: 'o', | ||
בִ: 'i' | ||
} | ||
// https://github.com/django/django/blob/master/django/contrib/admin/static/admin/js/urlify.js | ||
const initialCharmap = { | ||
// latin | ||
À: 'A', | ||
Á: 'A', | ||
Â: 'A', | ||
Ã: 'A', | ||
Ä: 'A', | ||
Å: 'A', | ||
Æ: 'AE', | ||
Ç: 'C', | ||
È: 'E', | ||
É: 'E', | ||
Ê: 'E', | ||
Ë: 'E', | ||
Ì: 'I', | ||
Í: 'I', | ||
Î: 'I', | ||
Ï: 'I', | ||
Ð: 'D', | ||
Ñ: 'N', | ||
Ò: 'O', | ||
Ó: 'O', | ||
Ô: 'O', | ||
Õ: 'O', | ||
Ö: 'O', | ||
Ő: 'O', | ||
Ø: 'O', | ||
Ō: 'O', | ||
Ù: 'U', | ||
Ú: 'U', | ||
Û: 'U', | ||
Ü: 'U', | ||
Ű: 'U', | ||
Ý: 'Y', | ||
Þ: 'TH', | ||
ß: 'ss', | ||
à: 'a', | ||
á: 'a', | ||
â: 'a', | ||
ã: 'a', | ||
ä: 'a', | ||
å: 'a', | ||
æ: 'ae', | ||
ç: 'c', | ||
è: 'e', | ||
é: 'e', | ||
ê: 'e', | ||
ë: 'e', | ||
ì: 'i', | ||
í: 'i', | ||
î: 'i', | ||
ï: 'i', | ||
ð: 'd', | ||
ñ: 'n', | ||
ò: 'o', | ||
ó: 'o', | ||
ô: 'o', | ||
õ: 'o', | ||
ö: 'o', | ||
ő: 'o', | ||
ø: 'o', | ||
ō: 'o', | ||
Œ: 'OE', | ||
œ: 'oe', | ||
ù: 'u', | ||
ú: 'u', | ||
û: 'u', | ||
ü: 'u', | ||
ű: 'u', | ||
ý: 'y', | ||
þ: 'th', | ||
ÿ: 'y', | ||
ẞ: 'SS', | ||
// greek | ||
α: 'a', | ||
β: 'b', | ||
γ: 'g', | ||
δ: 'd', | ||
ε: 'e', | ||
ζ: 'z', | ||
η: 'h', | ||
θ: '8', | ||
ι: 'i', | ||
κ: 'k', | ||
λ: 'l', | ||
μ: 'm', | ||
ν: 'n', | ||
ξ: '3', | ||
ο: 'o', | ||
π: 'p', | ||
ρ: 'r', | ||
σ: 's', | ||
τ: 't', | ||
υ: 'y', | ||
φ: 'f', | ||
χ: 'x', | ||
ψ: 'ps', | ||
ω: 'w', | ||
ά: 'a', | ||
έ: 'e', | ||
ί: 'i', | ||
ό: 'o', | ||
ύ: 'y', | ||
ή: 'h', | ||
ώ: 'w', | ||
ς: 's', | ||
ϊ: 'i', | ||
ΰ: 'y', | ||
ϋ: 'y', | ||
ΐ: 'i', | ||
Α: 'A', | ||
Β: 'B', | ||
Γ: 'G', | ||
Δ: 'D', | ||
Ε: 'E', | ||
Ζ: 'Z', | ||
Η: 'H', | ||
Θ: '8', | ||
Ι: 'I', | ||
Κ: 'K', | ||
Λ: 'L', | ||
Μ: 'M', | ||
Ν: 'N', | ||
Ξ: '3', | ||
Ο: 'O', | ||
Π: 'P', | ||
Ρ: 'R', | ||
Σ: 'S', | ||
Τ: 'T', | ||
Υ: 'Y', | ||
Φ: 'F', | ||
Χ: 'X', | ||
Ψ: 'PS', | ||
Ω: 'W', | ||
Ά: 'A', | ||
Έ: 'E', | ||
Ί: 'I', | ||
Ό: 'O', | ||
Ύ: 'Y', | ||
Ή: 'H', | ||
Ώ: 'W', | ||
Ϊ: 'I', | ||
Ϋ: 'Y', | ||
// turkish | ||
ş: 's', | ||
Ş: 'S', | ||
ı: 'i', | ||
İ: 'I', | ||
ğ: 'g', | ||
Ğ: 'G', | ||
// russian | ||
а: 'a', | ||
б: 'b', | ||
в: 'v', | ||
г: 'g', | ||
д: 'd', | ||
е: 'e', | ||
ё: 'yo', | ||
ж: 'zh', | ||
з: 'z', | ||
и: 'i', | ||
й: 'j', | ||
к: 'k', | ||
л: 'l', | ||
м: 'm', | ||
н: 'n', | ||
о: 'o', | ||
п: 'p', | ||
р: 'r', | ||
с: 's', | ||
т: 't', | ||
у: 'u', | ||
ф: 'f', | ||
х: 'h', | ||
ц: 'c', | ||
ч: 'ch', | ||
ш: 'sh', | ||
щ: 'sh', | ||
ъ: 'u', | ||
ы: 'y', | ||
ь: '', | ||
э: 'e', | ||
ю: 'yu', | ||
я: 'ya', | ||
А: 'A', | ||
Б: 'B', | ||
В: 'V', | ||
Г: 'G', | ||
Д: 'D', | ||
Е: 'E', | ||
Ё: 'Yo', | ||
Ж: 'Zh', | ||
З: 'Z', | ||
И: 'I', | ||
Й: 'J', | ||
К: 'K', | ||
Л: 'L', | ||
М: 'M', | ||
Н: 'N', | ||
О: 'O', | ||
П: 'P', | ||
Р: 'R', | ||
С: 'S', | ||
Т: 'T', | ||
У: 'U', | ||
Ф: 'F', | ||
Х: 'H', | ||
Ц: 'C', | ||
Ч: 'Ch', | ||
Ш: 'Sh', | ||
Щ: 'Sh', | ||
Ъ: 'U', | ||
Ы: 'Y', | ||
Ь: '', | ||
Э: 'E', | ||
Ю: 'Yu', | ||
Я: 'Ya', | ||
// ukranian | ||
Є: 'Ye', | ||
І: 'I', | ||
Ї: 'Yi', | ||
Ґ: 'G', | ||
є: 'ye', | ||
і: 'i', | ||
ї: 'yi', | ||
ґ: 'g', | ||
// czech | ||
č: 'c', | ||
ď: 'd', | ||
ě: 'e', | ||
ň: 'n', | ||
ř: 'r', | ||
š: 's', | ||
ť: 't', | ||
ů: 'u', | ||
ž: 'z', | ||
Č: 'C', | ||
Ď: 'D', | ||
Ě: 'E', | ||
Ň: 'N', | ||
Ř: 'R', | ||
Š: 'S', | ||
Ť: 'T', | ||
Ů: 'U', | ||
Ž: 'Z', | ||
// slovak | ||
ľ: 'l', | ||
ĺ: 'l', | ||
ŕ: 'r', | ||
Ľ: 'L', | ||
Ĺ: 'L', | ||
Ŕ: 'R', | ||
// polish | ||
ą: 'a', | ||
ć: 'c', | ||
ę: 'e', | ||
ł: 'l', | ||
ń: 'n', | ||
ś: 's', | ||
ź: 'z', | ||
ż: 'z', | ||
Ą: 'A', | ||
Ć: 'C', | ||
Ę: 'E', | ||
Ł: 'L', | ||
Ń: 'N', | ||
Ś: 'S', | ||
Ź: 'Z', | ||
Ż: 'Z', | ||
// latvian | ||
ā: 'a', | ||
ē: 'e', | ||
ģ: 'g', | ||
ī: 'i', | ||
ķ: 'k', | ||
ļ: 'l', | ||
ņ: 'n', | ||
ū: 'u', | ||
Ā: 'A', | ||
Ē: 'E', | ||
Ģ: 'G', | ||
Ī: 'I', | ||
Ķ: 'K', | ||
Ļ: 'L', | ||
Ņ: 'N', | ||
Ū: 'U', | ||
// arabic | ||
أ: 'a', | ||
إ: 'i', | ||
ب: 'b', | ||
ت: 't', | ||
ث: 'th', | ||
ج: 'g', | ||
ح: 'h', | ||
خ: 'kh', | ||
د: 'd', | ||
ذ: 'th', | ||
ر: 'r', | ||
ز: 'z', | ||
س: 's', | ||
ش: 'sh', | ||
ص: 's', | ||
ض: 'd', | ||
ط: 't', | ||
ظ: 'th', | ||
ع: 'aa', | ||
غ: 'gh', | ||
ف: 'f', | ||
ق: 'k', | ||
ك: 'k', | ||
ل: 'l', | ||
م: 'm', | ||
ن: 'n', | ||
ه: 'h', | ||
و: 'o', | ||
ي: 'y', | ||
ء: 'aa', | ||
ة: 'a', | ||
// farsi | ||
آ: 'a', | ||
ا: 'a', | ||
پ: 'p', | ||
ژ: 'zh', | ||
گ: 'g', | ||
چ: 'ch', | ||
ک: 'k', | ||
ی: 'i', | ||
// lithuanian | ||
ė: 'e', | ||
į: 'i', | ||
ų: 'u', | ||
Ė: 'E', | ||
Į: 'I', | ||
Ų: 'U', | ||
// romanian | ||
ț: 't', | ||
Ț: 'T', | ||
ţ: 't', | ||
Ţ: 'T', | ||
ș: 's', | ||
Ș: 'S', | ||
ă: 'a', | ||
Ă: 'A', | ||
// vietnamese | ||
Ạ: 'A', | ||
Ả: 'A', | ||
Ầ: 'A', | ||
Ấ: 'A', | ||
Ậ: 'A', | ||
Ẩ: 'A', | ||
Ẫ: 'A', | ||
Ằ: 'A', | ||
Ắ: 'A', | ||
Ặ: 'A', | ||
Ẳ: 'A', | ||
Ẵ: 'A', | ||
Ẹ: 'E', | ||
Ẻ: 'E', | ||
Ẽ: 'E', | ||
Ề: 'E', | ||
Ế: 'E', | ||
Ệ: 'E', | ||
Ể: 'E', | ||
Ễ: 'E', | ||
Ị: 'I', | ||
Ỉ: 'I', | ||
Ĩ: 'I', | ||
Ọ: 'O', | ||
Ỏ: 'O', | ||
Ồ: 'O', | ||
Ố: 'O', | ||
Ộ: 'O', | ||
Ổ: 'O', | ||
Ỗ: 'O', | ||
Ơ: 'O', | ||
Ờ: 'O', | ||
Ớ: 'O', | ||
Ợ: 'O', | ||
Ở: 'O', | ||
Ỡ: 'O', | ||
Ụ: 'U', | ||
Ủ: 'U', | ||
Ũ: 'U', | ||
Ư: 'U', | ||
Ừ: 'U', | ||
Ứ: 'U', | ||
Ự: 'U', | ||
Ử: 'U', | ||
Ữ: 'U', | ||
Ỳ: 'Y', | ||
Ỵ: 'Y', | ||
Ỷ: 'Y', | ||
Ỹ: 'Y', | ||
Đ: 'D', | ||
ạ: 'a', | ||
ả: 'a', | ||
ầ: 'a', | ||
ấ: 'a', | ||
ậ: 'a', | ||
ẩ: 'a', | ||
ẫ: 'a', | ||
ằ: 'a', | ||
ắ: 'a', | ||
ặ: 'a', | ||
ẳ: 'a', | ||
ẵ: 'a', | ||
ẹ: 'e', | ||
ẻ: 'e', | ||
ẽ: 'e', | ||
ề: 'e', | ||
ế: 'e', | ||
ệ: 'e', | ||
ể: 'e', | ||
ễ: 'e', | ||
ị: 'i', | ||
ỉ: 'i', | ||
ĩ: 'i', | ||
ọ: 'o', | ||
ỏ: 'o', | ||
ồ: 'o', | ||
ố: 'o', | ||
ộ: 'o', | ||
ổ: 'o', | ||
ỗ: 'o', | ||
ơ: 'o', | ||
ờ: 'o', | ||
ớ: 'o', | ||
ợ: 'o', | ||
ở: 'o', | ||
ỡ: 'o', | ||
ụ: 'u', | ||
ủ: 'u', | ||
ũ: 'u', | ||
ư: 'u', | ||
ừ: 'u', | ||
ứ: 'u', | ||
ự: 'u', | ||
ử: 'u', | ||
ữ: 'u', | ||
ỳ: 'y', | ||
ỵ: 'y', | ||
ỷ: 'y', | ||
ỹ: 'y', | ||
đ: 'd', | ||
// kazakh | ||
Ә: 'AE', | ||
ә: 'ae', | ||
Ғ: 'GH', | ||
ғ: 'gh', | ||
Қ: 'KH', | ||
қ: 'kh', | ||
Ң: 'NG', | ||
ң: 'ng', | ||
Ү: 'UE', | ||
ү: 'ue', | ||
Ұ: 'U', | ||
ұ: 'u', | ||
Һ: 'H', | ||
һ: 'h', | ||
Ө: 'OE', | ||
ө: 'oe', | ||
// serbian | ||
ђ: 'dj', | ||
ј: 'j', | ||
љ: 'lj', | ||
њ: 'nj', | ||
ћ: 'c', | ||
џ: 'dz', | ||
Ђ: 'Dj', | ||
Ј: 'j', | ||
Љ: 'Lj', | ||
Њ: 'Nj', | ||
Ћ: 'C', | ||
Џ: 'Dz', | ||
nj: 'nj', | ||
lj: 'lj', | ||
Nj: 'NJ', | ||
Lj: 'LJ', | ||
// hindi | ||
अ: 'a', | ||
आ: 'aa', | ||
ए: 'e', | ||
ई: 'ii', | ||
ऍ: 'ei', | ||
ऎ: 'ae', | ||
ऐ: 'ai', | ||
इ: 'i', | ||
ओ: 'o', | ||
ऑ: 'oi', | ||
ऒ: 'oii', | ||
ऊ: 'uu', | ||
औ: 'ou', | ||
उ: 'u', | ||
ब: 'B', | ||
भ: 'Bha', | ||
च: 'Ca', | ||
छ: 'Chha', | ||
ड: 'Da', | ||
ढ: 'Dha', | ||
फ: 'Fa', | ||
ग: 'Ga', | ||
घ: 'Gha', | ||
ग़: 'Ghi', | ||
ह: 'Ha', | ||
ज: 'Ja', | ||
झ: 'Jha', | ||
क: 'Ka', | ||
ख: 'Kha', | ||
ख़: 'Khi', | ||
ल: 'L', | ||
ळ: 'Li', | ||
ऌ: 'Li', | ||
ऴ: 'Lii', | ||
ॡ: 'Lii', | ||
म: 'Ma', | ||
न: 'Na', | ||
ङ: 'Na', | ||
ञ: 'Nia', | ||
ण: 'Nae', | ||
ऩ: 'Ni', | ||
ॐ: 'oms', | ||
प: 'Pa', | ||
क़: 'Qi', | ||
र: 'Ra', | ||
ऋ: 'Ri', | ||
ॠ: 'Ri', | ||
ऱ: 'Ri', | ||
स: 'Sa', | ||
श: 'Sha', | ||
ष: 'Shha', | ||
ट: 'Ta', | ||
त: 'Ta', | ||
ठ: 'Tha', | ||
द: 'Tha', | ||
थ: 'Tha', | ||
ध: 'Thha', | ||
ड़: 'ugDha', | ||
ढ़: 'ugDhha', | ||
व: 'Va', | ||
य: 'Ya', | ||
य़: 'Yi', | ||
ज़: 'Za', | ||
// azerbaijani | ||
ə: 'e', | ||
Ə: 'E', | ||
// georgian | ||
ა: 'a', | ||
ბ: 'b', | ||
გ: 'g', | ||
დ: 'd', | ||
ე: 'e', | ||
ვ: 'v', | ||
ზ: 'z', | ||
თ: 't', | ||
ი: 'i', | ||
კ: 'k', | ||
ლ: 'l', | ||
მ: 'm', | ||
ნ: 'n', | ||
ო: 'o', | ||
პ: 'p', | ||
ჟ: 'zh', | ||
რ: 'r', | ||
ს: 's', | ||
ტ: 't', | ||
უ: 'u', | ||
ფ: 'p', | ||
ქ: 'k', | ||
ღ: 'gh', | ||
ყ: 'q', | ||
შ: 'sh', | ||
ჩ: 'ch', | ||
ც: 'ts', | ||
ძ: 'dz', | ||
წ: 'ts', | ||
ჭ: 'ch', | ||
ხ: 'kh', | ||
ჯ: 'j', | ||
ჰ: 'h', | ||
// hebrew | ||
ב: 'v', | ||
גּ: 'g', | ||
ג: 'g', | ||
ד: 'd', | ||
דּ: 'd', | ||
ה: 'h', | ||
ו: 'v', | ||
ז: 'z', | ||
ח: 'h', | ||
ט: 't', | ||
י: 'y', | ||
כ: 'kh', | ||
ך: 'kh', | ||
ל: 'l', | ||
מ: 'm', | ||
ם: 'm', | ||
נ: 'n', | ||
ן: 'n', | ||
ס: 's', | ||
פ: 'f', | ||
ף: 'f', | ||
ץ: 'ts', | ||
צ: 'ts', | ||
ק: 'k', | ||
ר: 'r', | ||
תּ: 't', | ||
ת: 't' | ||
} | ||
slug.charmap = Object.assign({}, initialCharmap) | ||
slug.multicharmap = Object.assign({}, initialMulticharmap) | ||
slug.defaults = { | ||
charmap: slug.charmap, | ||
mode: 'pretty', | ||
modes: { | ||
rfc3986: { | ||
replacement: '-', | ||
remove: null, | ||
lower: true, | ||
charmap: slug.charmap, | ||
multicharmap: slug.multicharmap, | ||
trim: true | ||
slug.charmap = Object.assign({}, initialCharmap) | ||
slug.multicharmap = Object.assign({}, initialMulticharmap) | ||
slug.defaults = { | ||
charmap: slug.charmap, | ||
mode: 'pretty', | ||
modes: { | ||
rfc3986: { | ||
replacement: '-', | ||
remove: null, | ||
lower: true, | ||
charmap: slug.charmap, | ||
multicharmap: slug.multicharmap, | ||
trim: true | ||
}, | ||
pretty: { | ||
replacement: '-', | ||
remove: null, | ||
lower: true, | ||
charmap: slug.charmap, | ||
multicharmap: slug.multicharmap, | ||
trim: true | ||
} | ||
}, | ||
pretty: { | ||
replacement: '-', | ||
remove: null, | ||
lower: true, | ||
charmap: slug.charmap, | ||
multicharmap: slug.multicharmap, | ||
trim: true | ||
} | ||
}, | ||
multicharmap: slug.multicharmap, | ||
fallback: true | ||
} | ||
multicharmap: slug.multicharmap, | ||
fallback: true | ||
} | ||
slug.reset = function () { | ||
slug.defaults.modes.rfc3986.charmap = slug.defaults.modes.pretty.charmap = slug.charmap = slug.defaults.charmap = Object.assign({}, initialCharmap) | ||
slug.defaults.modes.rfc3986.multicharmap = slug.defaults.modes.pretty.multicharmap = slug.multicharmap = slug.defaults.multicharmap = Object.assign({}, initialMulticharmap) | ||
defaultLocale = '' | ||
} | ||
slug.reset = function () { | ||
slug.defaults.modes.rfc3986.charmap = slug.defaults.modes.pretty.charmap = slug.charmap = slug.defaults.charmap = Object.assign({}, initialCharmap) | ||
slug.defaults.modes.rfc3986.multicharmap = slug.defaults.modes.pretty.multicharmap = slug.multicharmap = slug.defaults.multicharmap = Object.assign({}, initialMulticharmap) | ||
defaultLocale = '' | ||
} | ||
slug.extend = function (customMap) { | ||
const keys = Object.keys(customMap) | ||
const multi = {} | ||
const single = {} | ||
for (let i = 0; i < keys.length; i++) { | ||
if (keys[i].length > 1) { | ||
multi[keys[i]] = customMap[keys[i]] | ||
} else { | ||
single[keys[i]] = customMap[keys[i]] | ||
slug.extend = function (customMap) { | ||
const keys = Object.keys(customMap) | ||
const multi = {} | ||
const single = {} | ||
for (let i = 0; i < keys.length; i++) { | ||
if (keys[i].length > 1) { | ||
multi[keys[i]] = customMap[keys[i]] | ||
} else { | ||
single[keys[i]] = customMap[keys[i]] | ||
} | ||
} | ||
Object.assign(slug.charmap, single) | ||
Object.assign(slug.multicharmap, multi) | ||
} | ||
Object.assign(slug.charmap, single) | ||
Object.assign(slug.multicharmap, multi) | ||
} | ||
slug.setLocale = function (locale) { | ||
defaultLocale = locales[locale] || {} | ||
} | ||
slug.setLocale = function (locale) { | ||
defaultLocale = locales[locale] || {} | ||
} | ||
export default slug | ||
if (typeof module !== 'undefined' && module.exports) { // CommonJS | ||
module.exports = slug | ||
} else { // Script tag | ||
root.slug = slug | ||
} | ||
}(this)) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
35047
13
6
874
0
137
No