traxxx-common/slugify.cjs

137 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const accentMap = {
à: 'a',
á: 'a',
ä: 'a',
å: 'a',
ã: 'a',
â: 'a',
æ: 'ae',
ç: 'c',
è: 'e',
é: 'e',
ë: 'e',
: 'e',
ê: 'e',
ì: 'i',
í: 'i',
ï: 'i',
ĩ: 'i',
î: 'i',
ǹ: 'n',
ń: 'n',
ñ: 'n',
ò: 'o',
ó: 'o',
ö: 'o',
õ: 'o',
ô: 'o',
ø: 'o',
œ: 'oe',
ß: 'ss',
ù: 'u',
ú: 'u',
ü: 'u',
ũ: 'u',
û: 'u',
: 'y',
ý: 'y',
ÿ: 'y',
: 'y',
};
const plainCharRegex = /[a-zA-Z0-9]/;
const defaultPunctuationRegex = /[.,?!:;&'"“”…()[]{}<>\/*—-]/;
const defaultSymbolRegex = /[@$€£#%^+=\\~]/;
module.exports = function slugify(strings, delimiter = '-', {
limit = 1000,
lower = true,
encode = false,
accents: keepAccents = false,
punctuation: keepPunctuation = false,
punctuationRegex = defaultPunctuationRegex,
symbols: keepSymbols = false,
symbolRegex = defaultSymbolRegex,
} = {}) {
if (!strings || (typeof strings !== 'string' && !Array.isArray(strings))) {
return strings;
}
const string = [].concat(strings).join(' ');
const casedString = lower
? string.toLowerCase()
: string;
const normalized = casedString
.split('')
.map((char) => {
if (char === ' ') {
return char;
}
const lowChar = char.toLowerCase();
if (accentMap[lowChar]) {
if (keepAccents) {
return char;
}
// match original case after mapping
if (char === lowChar) {
return accentMap[lowChar];
}
return accentMap[lowChar].toUpperCase();
}
if (plainCharRegex.test(char)) {
return char;
}
if (punctuationRegex.test(char)) {
if (keepPunctuation === 'split') {
return ' ';
}
if (keepPunctuation) {
return char;
}
}
if (symbolRegex.test(char)) {
if (keepSymbols === 'split') {
return ' ';
}
if (keepSymbols) {
return char;
}
}
return '';
}).join('');
const components = normalized.trim().split(/\s+/).filter(Boolean);
if (components.length === 0) {
return '';
}
const slug = components.reduce((acc, component, index) => {
const accSlug = `${acc}${index > 0 ? delimiter : ''}${component}`;
if (accSlug.length < limit) {
return accSlug;
}
return acc;
}).slice(0, limit); // in case first word exceeds limit
if (encode) {
return encodeURI(slug);
}
return slug;
}