@naturalcycles/js-lib 14.252.1 → 14.253.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/string/slugify.d.ts +19 -0
- package/dist/string/slugify.js +69 -0
- package/dist-esm/index.js +1 -0
- package/dist-esm/string/slugify.js +66 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/string/slugify.ts +107 -0
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,7 @@ export * from './string/pupa';
|
|
|
74
74
|
export * from './string/readingTime';
|
|
75
75
|
export * from './string/regex';
|
|
76
76
|
export * from './string/safeJsonStringify';
|
|
77
|
+
export * from './string/slugify';
|
|
77
78
|
export * from './string/string.util';
|
|
78
79
|
export * from './string/stringify';
|
|
79
80
|
export * from './string/url.util';
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ tslib_1.__exportStar(require("./string/pupa"), exports);
|
|
|
78
78
|
tslib_1.__exportStar(require("./string/readingTime"), exports);
|
|
79
79
|
tslib_1.__exportStar(require("./string/regex"), exports);
|
|
80
80
|
tslib_1.__exportStar(require("./string/safeJsonStringify"), exports);
|
|
81
|
+
tslib_1.__exportStar(require("./string/slugify"), exports);
|
|
81
82
|
tslib_1.__exportStar(require("./string/string.util"), exports);
|
|
82
83
|
tslib_1.__exportStar(require("./string/stringify"), exports);
|
|
83
84
|
tslib_1.__exportStar(require("./string/url.util"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface SlugifyOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Default: `-`
|
|
4
|
+
*/
|
|
5
|
+
separator?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Default: true
|
|
8
|
+
*/
|
|
9
|
+
lowercase?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Default: true
|
|
12
|
+
*/
|
|
13
|
+
decamelize?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Default: []
|
|
16
|
+
*/
|
|
17
|
+
preserveCharacters?: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function _slugify(s: string, opt?: SlugifyOptions): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Credit to (adopted from): https://github.com/sindresorhus/slugify/
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports._slugify = _slugify;
|
|
5
|
+
function _slugify(s, opt = {}) {
|
|
6
|
+
opt = {
|
|
7
|
+
separator: '-',
|
|
8
|
+
lowercase: true,
|
|
9
|
+
decamelize: true,
|
|
10
|
+
preserveCharacters: [],
|
|
11
|
+
...opt,
|
|
12
|
+
};
|
|
13
|
+
if (opt.decamelize) {
|
|
14
|
+
s = decamelize(s);
|
|
15
|
+
}
|
|
16
|
+
const patternSlug = buildPatternSlug(opt);
|
|
17
|
+
if (opt.lowercase) {
|
|
18
|
+
s = s.toLowerCase();
|
|
19
|
+
}
|
|
20
|
+
// based on https://stackoverflow.com/a/23633850/4919972
|
|
21
|
+
// Combining Diacritical Marks
|
|
22
|
+
// https://www.unicode.org/charts/PDF/U0300.pdf
|
|
23
|
+
// biome-ignore lint/suspicious/noMisleadingCharacterClass: ok
|
|
24
|
+
s = s.normalize('NFKD').replaceAll(/[\u0300-\u036F]/g, '');
|
|
25
|
+
// Detect contractions/possessives by looking for any word followed by a `'t`
|
|
26
|
+
// or `'s` in isolation and then remove it.
|
|
27
|
+
s = s.replaceAll(/([a-zA-Z\d]+)'([ts])(\s|$)/g, '$1$2$3');
|
|
28
|
+
s = s.replace(patternSlug, opt.separator);
|
|
29
|
+
s = s.replaceAll('\\', '');
|
|
30
|
+
if (opt.separator) {
|
|
31
|
+
s = removeMootSeparators(s, opt.separator);
|
|
32
|
+
}
|
|
33
|
+
return s;
|
|
34
|
+
}
|
|
35
|
+
function buildPatternSlug(options) {
|
|
36
|
+
let negationSetPattern = String.raw `a-z\d`;
|
|
37
|
+
negationSetPattern += options.lowercase ? '' : 'A-Z';
|
|
38
|
+
if (options.preserveCharacters.length > 0) {
|
|
39
|
+
for (const character of options.preserveCharacters) {
|
|
40
|
+
if (character === options.separator) {
|
|
41
|
+
throw new Error(`The separator character \`${options.separator}\` cannot be included in preserved characters: ${options.preserveCharacters}`);
|
|
42
|
+
}
|
|
43
|
+
negationSetPattern += escapeStringRegexp(character);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return new RegExp(`[^${negationSetPattern}]+`, 'g');
|
|
47
|
+
}
|
|
48
|
+
function removeMootSeparators(s, separator) {
|
|
49
|
+
const escapedSeparator = escapeStringRegexp(separator);
|
|
50
|
+
return s
|
|
51
|
+
.replaceAll(new RegExp(`${escapedSeparator}{2,}`, 'g'), separator)
|
|
52
|
+
.replaceAll(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, 'g'), '');
|
|
53
|
+
}
|
|
54
|
+
function decamelize(s) {
|
|
55
|
+
return (s
|
|
56
|
+
// Separate capitalized words.
|
|
57
|
+
.replaceAll(/([A-Z]{2,})(\d+)/g, '$1 $2')
|
|
58
|
+
.replaceAll(/([a-z\d]+)([A-Z]{2,})/g, '$1 $2')
|
|
59
|
+
.replaceAll(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
60
|
+
// `[a-rt-z]` matches all lowercase characters except `s`.
|
|
61
|
+
// This avoids matching plural acronyms like `APIs`.
|
|
62
|
+
.replaceAll(/([A-Z]+)([A-Z][a-rt-z\d]+)/g, '$1 $2'));
|
|
63
|
+
}
|
|
64
|
+
// based on: https://github.com/sindresorhus/escape-string-regexp/
|
|
65
|
+
function escapeStringRegexp(s) {
|
|
66
|
+
// Escape characters with special meaning either inside or outside character sets.
|
|
67
|
+
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
68
|
+
return s.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw `\$&`).replaceAll('-', String.raw `\x2d`);
|
|
69
|
+
}
|
package/dist-esm/index.js
CHANGED
|
@@ -74,6 +74,7 @@ export * from './string/pupa';
|
|
|
74
74
|
export * from './string/readingTime';
|
|
75
75
|
export * from './string/regex';
|
|
76
76
|
export * from './string/safeJsonStringify';
|
|
77
|
+
export * from './string/slugify';
|
|
77
78
|
export * from './string/string.util';
|
|
78
79
|
export * from './string/stringify';
|
|
79
80
|
export * from './string/url.util';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Credit to (adopted from): https://github.com/sindresorhus/slugify/
|
|
2
|
+
export function _slugify(s, opt = {}) {
|
|
3
|
+
opt = {
|
|
4
|
+
separator: '-',
|
|
5
|
+
lowercase: true,
|
|
6
|
+
decamelize: true,
|
|
7
|
+
preserveCharacters: [],
|
|
8
|
+
...opt,
|
|
9
|
+
};
|
|
10
|
+
if (opt.decamelize) {
|
|
11
|
+
s = decamelize(s);
|
|
12
|
+
}
|
|
13
|
+
const patternSlug = buildPatternSlug(opt);
|
|
14
|
+
if (opt.lowercase) {
|
|
15
|
+
s = s.toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
// based on https://stackoverflow.com/a/23633850/4919972
|
|
18
|
+
// Combining Diacritical Marks
|
|
19
|
+
// https://www.unicode.org/charts/PDF/U0300.pdf
|
|
20
|
+
// biome-ignore lint/suspicious/noMisleadingCharacterClass: ok
|
|
21
|
+
s = s.normalize('NFKD').replaceAll(/[\u0300-\u036F]/g, '');
|
|
22
|
+
// Detect contractions/possessives by looking for any word followed by a `'t`
|
|
23
|
+
// or `'s` in isolation and then remove it.
|
|
24
|
+
s = s.replaceAll(/([a-zA-Z\d]+)'([ts])(\s|$)/g, '$1$2$3');
|
|
25
|
+
s = s.replace(patternSlug, opt.separator);
|
|
26
|
+
s = s.replaceAll('\\', '');
|
|
27
|
+
if (opt.separator) {
|
|
28
|
+
s = removeMootSeparators(s, opt.separator);
|
|
29
|
+
}
|
|
30
|
+
return s;
|
|
31
|
+
}
|
|
32
|
+
function buildPatternSlug(options) {
|
|
33
|
+
let negationSetPattern = String.raw `a-z\d`;
|
|
34
|
+
negationSetPattern += options.lowercase ? '' : 'A-Z';
|
|
35
|
+
if (options.preserveCharacters.length > 0) {
|
|
36
|
+
for (const character of options.preserveCharacters) {
|
|
37
|
+
if (character === options.separator) {
|
|
38
|
+
throw new Error(`The separator character \`${options.separator}\` cannot be included in preserved characters: ${options.preserveCharacters}`);
|
|
39
|
+
}
|
|
40
|
+
negationSetPattern += escapeStringRegexp(character);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return new RegExp(`[^${negationSetPattern}]+`, 'g');
|
|
44
|
+
}
|
|
45
|
+
function removeMootSeparators(s, separator) {
|
|
46
|
+
const escapedSeparator = escapeStringRegexp(separator);
|
|
47
|
+
return s
|
|
48
|
+
.replaceAll(new RegExp(`${escapedSeparator}{2,}`, 'g'), separator)
|
|
49
|
+
.replaceAll(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, 'g'), '');
|
|
50
|
+
}
|
|
51
|
+
function decamelize(s) {
|
|
52
|
+
return (s
|
|
53
|
+
// Separate capitalized words.
|
|
54
|
+
.replaceAll(/([A-Z]{2,})(\d+)/g, '$1 $2')
|
|
55
|
+
.replaceAll(/([a-z\d]+)([A-Z]{2,})/g, '$1 $2')
|
|
56
|
+
.replaceAll(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
57
|
+
// `[a-rt-z]` matches all lowercase characters except `s`.
|
|
58
|
+
// This avoids matching plural acronyms like `APIs`.
|
|
59
|
+
.replaceAll(/([A-Z]+)([A-Z][a-rt-z\d]+)/g, '$1 $2'));
|
|
60
|
+
}
|
|
61
|
+
// based on: https://github.com/sindresorhus/escape-string-regexp/
|
|
62
|
+
function escapeStringRegexp(s) {
|
|
63
|
+
// Escape characters with special meaning either inside or outside character sets.
|
|
64
|
+
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
65
|
+
return s.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw `\$&`).replaceAll('-', String.raw `\x2d`);
|
|
66
|
+
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -74,6 +74,7 @@ export * from './string/pupa'
|
|
|
74
74
|
export * from './string/readingTime'
|
|
75
75
|
export * from './string/regex'
|
|
76
76
|
export * from './string/safeJsonStringify'
|
|
77
|
+
export * from './string/slugify'
|
|
77
78
|
export * from './string/string.util'
|
|
78
79
|
export * from './string/stringify'
|
|
79
80
|
export * from './string/url.util'
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Credit to (adopted from): https://github.com/sindresorhus/slugify/
|
|
2
|
+
|
|
3
|
+
export interface SlugifyOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Default: `-`
|
|
6
|
+
*/
|
|
7
|
+
separator?: string
|
|
8
|
+
/**
|
|
9
|
+
* Default: true
|
|
10
|
+
*/
|
|
11
|
+
lowercase?: boolean
|
|
12
|
+
/**
|
|
13
|
+
* Default: true
|
|
14
|
+
*/
|
|
15
|
+
decamelize?: boolean
|
|
16
|
+
/**
|
|
17
|
+
* Default: []
|
|
18
|
+
*/
|
|
19
|
+
preserveCharacters?: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function _slugify(s: string, opt: SlugifyOptions = {}): string {
|
|
23
|
+
opt = {
|
|
24
|
+
separator: '-',
|
|
25
|
+
lowercase: true,
|
|
26
|
+
decamelize: true,
|
|
27
|
+
preserveCharacters: [],
|
|
28
|
+
...opt,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (opt.decamelize) {
|
|
32
|
+
s = decamelize(s)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const patternSlug = buildPatternSlug(opt)
|
|
36
|
+
|
|
37
|
+
if (opt.lowercase) {
|
|
38
|
+
s = s.toLowerCase()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// based on https://stackoverflow.com/a/23633850/4919972
|
|
42
|
+
// Combining Diacritical Marks
|
|
43
|
+
// https://www.unicode.org/charts/PDF/U0300.pdf
|
|
44
|
+
// biome-ignore lint/suspicious/noMisleadingCharacterClass: ok
|
|
45
|
+
s = s.normalize('NFKD').replaceAll(/[\u0300-\u036F]/g, '')
|
|
46
|
+
|
|
47
|
+
// Detect contractions/possessives by looking for any word followed by a `'t`
|
|
48
|
+
// or `'s` in isolation and then remove it.
|
|
49
|
+
s = s.replaceAll(/([a-zA-Z\d]+)'([ts])(\s|$)/g, '$1$2$3')
|
|
50
|
+
|
|
51
|
+
s = s.replace(patternSlug, opt.separator!)
|
|
52
|
+
s = s.replaceAll('\\', '')
|
|
53
|
+
|
|
54
|
+
if (opt.separator) {
|
|
55
|
+
s = removeMootSeparators(s, opt.separator)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return s
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildPatternSlug(options: any): RegExp {
|
|
62
|
+
let negationSetPattern = String.raw`a-z\d`
|
|
63
|
+
negationSetPattern += options.lowercase ? '' : 'A-Z'
|
|
64
|
+
|
|
65
|
+
if (options.preserveCharacters.length > 0) {
|
|
66
|
+
for (const character of options.preserveCharacters) {
|
|
67
|
+
if (character === options.separator) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`The separator character \`${options.separator}\` cannot be included in preserved characters: ${options.preserveCharacters}`,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
negationSetPattern += escapeStringRegexp(character)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return new RegExp(`[^${negationSetPattern}]+`, 'g')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function removeMootSeparators(s: string, separator: string): string {
|
|
81
|
+
const escapedSeparator = escapeStringRegexp(separator)
|
|
82
|
+
|
|
83
|
+
return s
|
|
84
|
+
.replaceAll(new RegExp(`${escapedSeparator}{2,}`, 'g'), separator)
|
|
85
|
+
.replaceAll(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, 'g'), '')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function decamelize(s: string): string {
|
|
89
|
+
return (
|
|
90
|
+
s
|
|
91
|
+
// Separate capitalized words.
|
|
92
|
+
.replaceAll(/([A-Z]{2,})(\d+)/g, '$1 $2')
|
|
93
|
+
.replaceAll(/([a-z\d]+)([A-Z]{2,})/g, '$1 $2')
|
|
94
|
+
|
|
95
|
+
.replaceAll(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
96
|
+
// `[a-rt-z]` matches all lowercase characters except `s`.
|
|
97
|
+
// This avoids matching plural acronyms like `APIs`.
|
|
98
|
+
.replaceAll(/([A-Z]+)([A-Z][a-rt-z\d]+)/g, '$1 $2')
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// based on: https://github.com/sindresorhus/escape-string-regexp/
|
|
103
|
+
function escapeStringRegexp(s: string): string {
|
|
104
|
+
// Escape characters with special meaning either inside or outside character sets.
|
|
105
|
+
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
106
|
+
return s.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`).replaceAll('-', String.raw`\x2d`)
|
|
107
|
+
}
|