887 lines
16 KiB
JavaScript
887 lines
16 KiB
JavaScript
/* global btoa */
|
||
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 is a coherence check. `code` should never be `NaN`.
|
||
/* c8 ignore next 3 */
|
||
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]
|
||
}
|
||
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]
|
||
}
|
||
|
||
// Low surrogate (0xDC00 <= code && code <= 0xDFFF)
|
||
if (i === 0) {
|
||
// Low surrogate without preceding high surrogate
|
||
return [' ', i]
|
||
}
|
||
|
||
const prev = str.charCodeAt(i - 1)
|
||
|
||
/* c8 ignore next */
|
||
if (prev < 0xD800 || prev > 0xDBFF) {
|
||
// Low surrogate without preceding high surrogate
|
||
return [' ', i]
|
||
}
|
||
/* 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') {
|
||
// Browser environment. We don't yet merge coverage with CLI tests.
|
||
/* c8 ignore next 4 */
|
||
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.
|
||
/* c8 ignore next 3 */
|
||
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 {
|
||
base64 = function (input) {
|
||
return Buffer.from(input).toString('base64')
|
||
}
|
||
}
|
||
|
||
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)
|
||
}
|
||
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' }
|
||
}
|
||
|
||
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
|
||
|
||
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) }
|
||
}
|
||
|
||
// 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]/
|
||
|
||
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, '')
|
||
}
|
||
}
|
||
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
|
||
}
|
||
|
||
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',
|
||
θ: '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'
|
||
}
|
||
|
||
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
|
||
}
|
||
},
|
||
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.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)
|
||
}
|
||
|
||
slug.setLocale = function (locale) {
|
||
defaultLocale = locales[locale] || {}
|
||
}
|
||
|
||
export default slug
|