-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
slugifier.ts
86 lines (69 loc) 路 1.88 KB
/
slugifier.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { unidecode } from "../deps/unidecode.ts";
import { merge } from "./utils/object.ts";
export interface Options {
/** Convert the paths to lower case */
lowercase?: boolean;
/** Remove all non-alphanumeric characters */
alphanumeric?: boolean;
/** Character used as word separator */
separator?: string;
/** Characters to replace */
replace?: {
[index: string]: string;
};
/** Words to remove */
stopWords?: string[];
}
export const defaults: Options = {
lowercase: true,
alphanumeric: true,
separator: "-",
replace: {
"脨": "D", // eth
"冒": "d",
"膼": "D", // crossed D
"膽": "d",
"酶": "o",
"脽": "ss",
"忙": "ae",
"艙": "oe",
},
stopWords: [],
};
export default function createSlugifier(
userOptions?: Options,
): (string: string) => string {
const options = merge(defaults, userOptions);
const { lowercase, alphanumeric, separator, replace, stopWords } = options;
return function (string) {
string = decodeURI(string);
if (lowercase) {
string = string.toLowerCase();
}
string = string.replaceAll(/[^a-z\d/.-]/giu, (char) => {
if (char in replace) {
return replace[char];
}
if (alphanumeric) {
char = char.normalize("NFKD").replaceAll(/[\u0300-\u036F]/g, "");
char = unidecode(char).trim();
}
char = /[\p{L}\u0300-\u036F]+/u.test(char) ? char : "-";
return alphanumeric && /[^\w-]+/.test(char) ? "" : char;
});
if (lowercase) {
string = string.toLowerCase();
}
// remove stop words
string = string.trim().split(/-+/).filter((word) =>
stopWords.indexOf(word) === -1
).join("-");
// clean url
string = string.replaceAll(
/(?<=^|[/.])-+(?=[^/.-])|(?<=[^/.-])-+(?=$|[/.])/g,
"",
);
// replace dash with separator
return encodeURI(string.replaceAll("-", separator));
};
}