forked from sindresorhus/slugify
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
99 lines (76 loc) · 2.41 KB
/
index.js
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
87
88
89
90
91
92
93
94
95
96
97
98
99
'use strict';
const escapeStringRegexp = require('escape-string-regexp');
const transliterate = require('@sindresorhus/transliterate');
const builtinOverridableReplacements = require('./overridable-replacements');
const decamelize = string => {
return string
// Separate capitalized words.
.replace(/([A-Z]{2,})(\d+)/g, '$1 $2')
.replace(/([a-z\d]+)([A-Z]{2,})/g, '$1 $2')
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
.replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1 $2');
};
const removeMootSeparators = (string, separator) => {
const escapedSeparator = escapeStringRegexp(separator);
return string
.replace(new RegExp(`${escapedSeparator}{2,}`, 'g'), separator)
.replace(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, 'g'), '');
};
const slugify = (string, options) => {
if (typeof string !== 'string') {
throw new TypeError(`Expected a string, got \`${typeof string}\``);
}
options = {
separator: '-',
lowercase: true,
decamelize: true,
customReplacements: [],
preserveLeadingUnderscore: false,
...options
};
const shouldPrependUnderscore = options.preserveLeadingUnderscore && string.startsWith('_');
const customReplacements = new Map([
...builtinOverridableReplacements,
...options.customReplacements
]);
string = transliterate(string, {customReplacements});
if (options.decamelize) {
string = decamelize(string);
}
let patternSlug = /[^a-zA-Z\d]+/g;
if (options.lowercase) {
string = string.toLowerCase();
patternSlug = /[^a-z\d]+/g;
}
string = string.replace(patternSlug, options.separator);
string = string.replace(/\\/g, '');
string = removeMootSeparators(string, options.separator);
if (shouldPrependUnderscore) {
string = `_${string}`;
}
return string;
};
const counter = () => {
const occurrences = new Map();
const countable = (string, options) => {
string = slugify(string, options);
if (!string) {
return '';
}
const stringLower = string.toLowerCase();
const numberless = occurrences.get(stringLower.replace(/(?:-\d+?)+?$/, '')) || 0;
const counter = occurrences.get(stringLower);
occurrences.set(stringLower, typeof counter === 'number' ? counter + 1 : 1);
const newCounter = occurrences.get(stringLower) || 2;
if (newCounter >= 2 || numberless > 2) {
string = `${string}-${newCounter}`;
}
return string;
};
countable.reset = () => {
occurrences.clear();
};
return countable;
};
module.exports = slugify;
module.exports.counter = counter;