@stacksjs/strings 0.70.56 → 0.70.58
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/case.js +133 -0
- package/dist/detect-indent.js +72 -0
- package/dist/detect-newline.js +16 -0
- package/dist/helpers.js +15 -0
- package/dist/index.js +2 -1317
- package/dist/is.d.ts +5 -0
- package/dist/is.js +1 -0
- package/dist/macro.js +95 -0
- package/dist/pluralize.js +310 -0
- package/dist/slug.js +21 -0
- package/dist/sponge-case.js +6 -0
- package/dist/string.js +7 -0
- package/dist/swap-case.js +8 -0
- package/dist/title-case.js +108 -0
- package/dist/utils.js +46 -0
- package/dist/validators.js +272 -0
- package/package.json +3 -3
package/dist/case.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export function capitalize(str) {
|
|
2
|
+
return str[0] ? str[0].toUpperCase() + str.slice(1).toLowerCase() : "";
|
|
3
|
+
}
|
|
4
|
+
export function lowercase(str) {
|
|
5
|
+
return str.toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu, SPLIT_UPPER_UPPER_RE = /(\p{Lu})(\p{Lu}\p{Ll})/gu, SPLIT_SEPARATE_NUMBER_RE = /(\d)\p{Ll}|(\p{L})\d/u, DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu, SPLIT_REPLACE_VALUE = "$1\x00$2", DEFAULT_PREFIX_SUFFIX_CHARACTERS = "";
|
|
8
|
+
export function split(value) {
|
|
9
|
+
let result = value.trim();
|
|
10
|
+
result = result.replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE).replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE);
|
|
11
|
+
result = result.replace(DEFAULT_STRIP_REGEXP, "\x00");
|
|
12
|
+
let start = 0, end = result.length;
|
|
13
|
+
while (result.charAt(start) === "\x00")
|
|
14
|
+
start++;
|
|
15
|
+
if (start === end)
|
|
16
|
+
return [];
|
|
17
|
+
while (result.charAt(end - 1) === "\x00")
|
|
18
|
+
end--;
|
|
19
|
+
return result.slice(start, end).split(/\0/g);
|
|
20
|
+
}
|
|
21
|
+
export function splitSeparateNumbers(value) {
|
|
22
|
+
const words = split(value);
|
|
23
|
+
for (let i = 0;i < words.length; i++) {
|
|
24
|
+
const word = words[i];
|
|
25
|
+
if (word === void 0)
|
|
26
|
+
continue;
|
|
27
|
+
const match = SPLIT_SEPARATE_NUMBER_RE.exec(word);
|
|
28
|
+
if (match) {
|
|
29
|
+
const offset = match.index + (match[1] ?? match[2] ?? "").length;
|
|
30
|
+
words.splice(i, 1, word.slice(0, offset), word.slice(offset));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return words;
|
|
34
|
+
}
|
|
35
|
+
export function noCase(input, options) {
|
|
36
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options);
|
|
37
|
+
return prefix + words.map(lowerFactory(options?.locale)).join(options?.delimiter ?? " ") + suffix;
|
|
38
|
+
}
|
|
39
|
+
export function camelCase(input, options) {
|
|
40
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options), lower = lowerFactory(options?.locale), upper = upperFactory(options?.locale), transform = options?.mergeAmbiguousCharacters ? capitalCaseTransformFactory(lower, upper) : pascalCaseTransformFactory(lower, upper);
|
|
41
|
+
return prefix + words.map((word, index) => {
|
|
42
|
+
if (index === 0)
|
|
43
|
+
return lower(word);
|
|
44
|
+
return transform(word, index);
|
|
45
|
+
}).join(options?.delimiter ?? "") + suffix;
|
|
46
|
+
}
|
|
47
|
+
export function pascalCase(input, options) {
|
|
48
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options), lower = lowerFactory(options?.locale), upper = upperFactory(options?.locale), transform = options?.mergeAmbiguousCharacters ? capitalCaseTransformFactory(lower, upper) : pascalCaseTransformFactory(lower, upper);
|
|
49
|
+
return prefix + words.map(transform).join(options?.delimiter ?? "") + suffix;
|
|
50
|
+
}
|
|
51
|
+
export function pascalSnakeCase(input, options) {
|
|
52
|
+
return capitalCase(input, { delimiter: "_", ...options });
|
|
53
|
+
}
|
|
54
|
+
export function capitalCase(input, options) {
|
|
55
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options), lower = lowerFactory(options?.locale), upper = upperFactory(options?.locale);
|
|
56
|
+
return prefix + words.map(capitalCaseTransformFactory(lower, upper)).join(options?.delimiter ?? " ") + suffix;
|
|
57
|
+
}
|
|
58
|
+
export function constantCase(input, options) {
|
|
59
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options);
|
|
60
|
+
return prefix + words.map(upperFactory(options?.locale)).join(options?.delimiter ?? "_") + suffix;
|
|
61
|
+
}
|
|
62
|
+
export function dotCase(input, options) {
|
|
63
|
+
return noCase(input, { delimiter: ".", ...options });
|
|
64
|
+
}
|
|
65
|
+
export function kebabCase(input, options) {
|
|
66
|
+
return noCase(input, { delimiter: "-", ...options });
|
|
67
|
+
}
|
|
68
|
+
export function pathCase(input, options) {
|
|
69
|
+
return noCase(input, { delimiter: "/", ...options });
|
|
70
|
+
}
|
|
71
|
+
export function sentenceCase(input, options) {
|
|
72
|
+
const [prefix, words, suffix] = splitPrefixSuffix(input, options), lower = lowerFactory(options?.locale), upper = upperFactory(options?.locale), transform = capitalCaseTransformFactory(lower, upper);
|
|
73
|
+
return prefix + words.map((word, index) => {
|
|
74
|
+
if (index === 0)
|
|
75
|
+
return transform(word);
|
|
76
|
+
return lower(word);
|
|
77
|
+
}).join(options?.delimiter ?? " ") + suffix;
|
|
78
|
+
}
|
|
79
|
+
export function snakeCase(input, options) {
|
|
80
|
+
return noCase(input, { delimiter: "_", ...options });
|
|
81
|
+
}
|
|
82
|
+
export function trainCase(input, options) {
|
|
83
|
+
return capitalCase(input, { delimiter: "-", ...options });
|
|
84
|
+
}
|
|
85
|
+
export function paramCase(input, options) {
|
|
86
|
+
return kebabCase(input, options);
|
|
87
|
+
}
|
|
88
|
+
function lowerFactory(locale) {
|
|
89
|
+
return locale === !1 ? (input) => input.toLowerCase() : (input) => input.toLocaleLowerCase(locale);
|
|
90
|
+
}
|
|
91
|
+
function upperFactory(locale) {
|
|
92
|
+
return locale === !1 ? (input) => input.toUpperCase() : (input) => input.toLocaleUpperCase(locale);
|
|
93
|
+
}
|
|
94
|
+
function capitalCaseTransformFactory(lower, upper) {
|
|
95
|
+
return (word) => {
|
|
96
|
+
if (!word)
|
|
97
|
+
return word;
|
|
98
|
+
return `${upper(word[0] ?? "")}${lower(word.slice(1))}`;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function pascalCaseTransformFactory(lower, upper) {
|
|
102
|
+
return (word, index) => {
|
|
103
|
+
if (!word)
|
|
104
|
+
return word;
|
|
105
|
+
const char0 = word[0] ?? "";
|
|
106
|
+
return (index > 0 && char0 >= "0" && char0 <= "9" ? `_${char0}` : upper(char0)) + lower(word.slice(1));
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function splitPrefixSuffix(input, options = {}) {
|
|
110
|
+
const splitFn = options.split ?? split, prefixCharacters = options.prefixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS, suffixCharacters = options.suffixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
|
|
111
|
+
let prefixIndex = 0, suffixIndex = input.length;
|
|
112
|
+
while (prefixIndex < input.length) {
|
|
113
|
+
const char = input.charAt(prefixIndex);
|
|
114
|
+
if (!prefixCharacters.includes(char))
|
|
115
|
+
break;
|
|
116
|
+
prefixIndex++;
|
|
117
|
+
}
|
|
118
|
+
while (suffixIndex > prefixIndex) {
|
|
119
|
+
const index = suffixIndex - 1, char = input.charAt(index);
|
|
120
|
+
if (!suffixCharacters.includes(char))
|
|
121
|
+
break;
|
|
122
|
+
suffixIndex = index;
|
|
123
|
+
}
|
|
124
|
+
return [
|
|
125
|
+
input.slice(0, prefixIndex),
|
|
126
|
+
splitFn(input.slice(prefixIndex, suffixIndex)),
|
|
127
|
+
input.slice(suffixIndex)
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export * from "./sponge-case";
|
|
132
|
+
export * from "./swap-case";
|
|
133
|
+
export * from "./title-case";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const INDENT_REGEX = /^(?:( )+|\t+)/, INDENT_TYPE_SPACE = "space", INDENT_TYPE_TAB = "tab";
|
|
2
|
+
function makeIndentsMap(string, ignoreSingleSpaces = !0) {
|
|
3
|
+
const indents = new Map;
|
|
4
|
+
let previousSize = 0, previousIndentType, key = "";
|
|
5
|
+
for (const line of string.split(/\n/g)) {
|
|
6
|
+
if (!line)
|
|
7
|
+
continue;
|
|
8
|
+
let indent, indentType, use, weight, entry;
|
|
9
|
+
const matches = line.match(INDENT_REGEX);
|
|
10
|
+
if (matches === null) {
|
|
11
|
+
previousSize = 0;
|
|
12
|
+
previousIndentType = "";
|
|
13
|
+
} else {
|
|
14
|
+
indent = matches[0].length;
|
|
15
|
+
indentType = matches[1] ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB;
|
|
16
|
+
if (ignoreSingleSpaces && indentType === INDENT_TYPE_SPACE && indent === 1)
|
|
17
|
+
continue;
|
|
18
|
+
if (indentType !== previousIndentType)
|
|
19
|
+
previousSize = 0;
|
|
20
|
+
previousIndentType = indentType;
|
|
21
|
+
use = 1;
|
|
22
|
+
weight = 0;
|
|
23
|
+
const indentDifference = indent - previousSize;
|
|
24
|
+
previousSize = indent;
|
|
25
|
+
if (indentDifference === 0) {
|
|
26
|
+
use = 0;
|
|
27
|
+
weight = 1;
|
|
28
|
+
} else {
|
|
29
|
+
const absoluteIndentDifference = indentDifference > 0 ? indentDifference : -indentDifference;
|
|
30
|
+
key = encodeIndentsKey(indentType, absoluteIndentDifference);
|
|
31
|
+
}
|
|
32
|
+
entry = indents.get(key);
|
|
33
|
+
entry = entry === void 0 ? [1, 0] : [entry[0] + use, entry[1] + weight];
|
|
34
|
+
indents.set(key, entry);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return indents;
|
|
38
|
+
}
|
|
39
|
+
function encodeIndentsKey(indentType, indentAmount) {
|
|
40
|
+
return (indentType === INDENT_TYPE_SPACE ? "s" : "t") + String(indentAmount);
|
|
41
|
+
}
|
|
42
|
+
function decodeIndentsKey(indentsKey) {
|
|
43
|
+
const type = indentsKey[0] === "s" ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB, amount = Number(indentsKey.slice(1));
|
|
44
|
+
return { type, amount };
|
|
45
|
+
}
|
|
46
|
+
function getMostUsedKey(indents) {
|
|
47
|
+
let result, maxUsed = 0, maxWeight = 0;
|
|
48
|
+
for (const [key, [usedCount, weight]] of indents)
|
|
49
|
+
if (usedCount > maxUsed || usedCount === maxUsed && weight > maxWeight) {
|
|
50
|
+
maxUsed = usedCount;
|
|
51
|
+
maxWeight = weight;
|
|
52
|
+
result = key;
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function makeIndentString(type, amount) {
|
|
57
|
+
return (type === INDENT_TYPE_SPACE ? " " : "\t").repeat(amount);
|
|
58
|
+
}
|
|
59
|
+
export function detectIndent(string) {
|
|
60
|
+
if (typeof string !== "string")
|
|
61
|
+
throw TypeError("Expected a string");
|
|
62
|
+
let indents = makeIndentsMap(string, !0);
|
|
63
|
+
if (indents.size === 0)
|
|
64
|
+
indents = makeIndentsMap(string, !1);
|
|
65
|
+
const keyOfMostUsedIndent = getMostUsedKey(indents), decoded = keyOfMostUsedIndent !== void 0 ? decodeIndentsKey(keyOfMostUsedIndent) : void 0, type = decoded?.type, amount = decoded?.amount ?? 0, indent = decoded ? makeIndentString(type, amount) : "";
|
|
66
|
+
return {
|
|
67
|
+
amount,
|
|
68
|
+
type,
|
|
69
|
+
indent
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export default detectIndent;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function detectNewline(string) {
|
|
2
|
+
if (typeof string !== "string")
|
|
3
|
+
throw TypeError("Expected a string");
|
|
4
|
+
const newlines = string.match(/\r?\n/g) || [];
|
|
5
|
+
if (newlines.length === 0)
|
|
6
|
+
return;
|
|
7
|
+
const crlf = newlines.filter((newline) => newline === `\r
|
|
8
|
+
`).length, lf = newlines.length - crlf;
|
|
9
|
+
return crlf > lf ? `\r
|
|
10
|
+
` : `
|
|
11
|
+
`;
|
|
12
|
+
}
|
|
13
|
+
export function detectNewlineGraceful(string) {
|
|
14
|
+
return typeof string === "string" && detectNewline(string) || `
|
|
15
|
+
`;
|
|
16
|
+
}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function toString(v) {
|
|
2
|
+
return Object.prototype.toString.call(v);
|
|
3
|
+
}
|
|
4
|
+
export function mask(value, character, index, length) {
|
|
5
|
+
if (character === "")
|
|
6
|
+
return value;
|
|
7
|
+
const len = value.length, start = index < 0 ? Math.max(0, len + index) : index;
|
|
8
|
+
if (start >= len)
|
|
9
|
+
return value;
|
|
10
|
+
const maskLen = length === void 0 ? len - start : Math.max(0, length);
|
|
11
|
+
if (maskLen === 0)
|
|
12
|
+
return value;
|
|
13
|
+
const end = Math.min(len, start + maskLen), fill = character.charAt(0).repeat(end - start);
|
|
14
|
+
return value.slice(0, start) + fill + value.slice(end);
|
|
15
|
+
}
|