@itshackers/utilix 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +304 -3
- package/dist/common/index.cjs +102 -0
- package/dist/common/index.cjs.map +1 -0
- package/dist/common/index.d.cts +58 -0
- package/dist/common/index.d.ts +58 -0
- package/dist/common/index.js +93 -0
- package/dist/common/index.js.map +1 -0
- package/dist/date/index.cjs +154 -0
- package/dist/date/index.cjs.map +1 -0
- package/dist/date/index.d.cts +65 -0
- package/dist/date/index.d.ts +65 -0
- package/dist/date/index.js +146 -0
- package/dist/date/index.js.map +1 -0
- package/dist/format/index.cjs +136 -0
- package/dist/format/index.cjs.map +1 -0
- package/dist/format/index.d.cts +56 -0
- package/dist/format/index.d.ts +56 -0
- package/dist/format/index.js +130 -0
- package/dist/format/index.js.map +1 -0
- package/dist/id/index.cjs +66 -0
- package/dist/id/index.cjs.map +1 -0
- package/dist/id/index.d.cts +19 -0
- package/dist/id/index.d.ts +19 -0
- package/dist/id/index.js +64 -0
- package/dist/id/index.js.map +1 -0
- package/dist/index.cjs +906 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +853 -0
- package/dist/index.js.map +1 -0
- package/dist/number/index.cjs +107 -0
- package/dist/number/index.cjs.map +1 -0
- package/dist/number/index.d.cts +90 -0
- package/dist/number/index.d.ts +90 -0
- package/dist/number/index.js +99 -0
- package/dist/number/index.js.map +1 -0
- package/dist/password/index.cjs +71 -0
- package/dist/password/index.cjs.map +1 -0
- package/dist/password/index.d.cts +15 -0
- package/dist/password/index.d.ts +15 -0
- package/dist/password/index.js +69 -0
- package/dist/password/index.js.map +1 -0
- package/dist/phone/index.cjs +19 -0
- package/dist/phone/index.cjs.map +1 -0
- package/dist/phone/index.d.cts +12 -0
- package/dist/phone/index.d.ts +12 -0
- package/dist/phone/index.js +17 -0
- package/dist/phone/index.js.map +1 -0
- package/dist/regex/index.cjs +73 -0
- package/dist/regex/index.cjs.map +1 -0
- package/dist/regex/index.d.cts +65 -0
- package/dist/regex/index.d.ts +65 -0
- package/dist/regex/index.js +67 -0
- package/dist/regex/index.js.map +1 -0
- package/dist/response/index.cjs +43 -0
- package/dist/response/index.cjs.map +1 -0
- package/dist/response/index.d.cts +41 -0
- package/dist/response/index.d.ts +41 -0
- package/dist/response/index.js +40 -0
- package/dist/response/index.js.map +1 -0
- package/dist/sanitize/index.cjs +83 -0
- package/dist/sanitize/index.cjs.map +1 -0
- package/dist/sanitize/index.d.cts +20 -0
- package/dist/sanitize/index.d.ts +20 -0
- package/dist/sanitize/index.js +80 -0
- package/dist/sanitize/index.js.map +1 -0
- package/dist/slug/index.cjs +33 -0
- package/dist/slug/index.cjs.map +1 -0
- package/dist/slug/index.d.cts +38 -0
- package/dist/slug/index.d.ts +38 -0
- package/dist/slug/index.js +31 -0
- package/dist/slug/index.js.map +1 -0
- package/dist/string/index.cjs +130 -0
- package/dist/string/index.cjs.map +1 -0
- package/dist/string/index.d.cts +112 -0
- package/dist/string/index.d.ts +112 -0
- package/dist/string/index.js +115 -0
- package/dist/string/index.js.map +1 -0
- package/package.json +187 -3
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/internal/validation.ts
|
|
4
|
+
function escapeRegExp(value) {
|
|
5
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/string/index.ts
|
|
9
|
+
var HTML_ESCAPE_MAP = {
|
|
10
|
+
"&": "&",
|
|
11
|
+
"<": "<",
|
|
12
|
+
">": ">",
|
|
13
|
+
'"': """,
|
|
14
|
+
"'": "'"
|
|
15
|
+
};
|
|
16
|
+
function splitWords(value) {
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (trimmed.length === 0) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return trimmed.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s._-]+/u).filter((word) => word.length > 0);
|
|
22
|
+
}
|
|
23
|
+
function toLowerWords(value) {
|
|
24
|
+
return splitWords(value).map((word) => word.toLowerCase());
|
|
25
|
+
}
|
|
26
|
+
function capitalizeWord(word) {
|
|
27
|
+
const [first = "", ...rest] = [...word];
|
|
28
|
+
return `${first.toUpperCase()}${rest.join("").toLowerCase()}`;
|
|
29
|
+
}
|
|
30
|
+
function toCamelCase(value) {
|
|
31
|
+
const words = toLowerWords(value);
|
|
32
|
+
if (words.length === 0) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
const [first = "", ...rest] = words;
|
|
36
|
+
return `${first}${rest.map(capitalizeWord).join("")}`;
|
|
37
|
+
}
|
|
38
|
+
function toPascalCase(value) {
|
|
39
|
+
return toLowerWords(value).map(capitalizeWord).join("");
|
|
40
|
+
}
|
|
41
|
+
function toSnakeCase(value) {
|
|
42
|
+
return toLowerWords(value).join("_");
|
|
43
|
+
}
|
|
44
|
+
function toKebabCase(value) {
|
|
45
|
+
return toLowerWords(value).join("-");
|
|
46
|
+
}
|
|
47
|
+
function capitalize(value) {
|
|
48
|
+
const trimmed = value.trim();
|
|
49
|
+
if (trimmed.length === 0) {
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
const [first = "", ...rest] = [...trimmed];
|
|
53
|
+
return `${first.toUpperCase()}${rest.join("")}`;
|
|
54
|
+
}
|
|
55
|
+
function normalizeWhitespace(value) {
|
|
56
|
+
return value.trim().replace(/\s+/gu, " ");
|
|
57
|
+
}
|
|
58
|
+
function escapeHtml(value) {
|
|
59
|
+
return value.replace(/[&<>"']/g, (character) => HTML_ESCAPE_MAP[character] ?? character);
|
|
60
|
+
}
|
|
61
|
+
function escapeRegex(value) {
|
|
62
|
+
return escapeRegExp(value);
|
|
63
|
+
}
|
|
64
|
+
function toTitleCase(value) {
|
|
65
|
+
const trimmed = value.trim();
|
|
66
|
+
if (trimmed.length === 0) {
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
return trimmed.toLowerCase().replace(/\b\w/g, (character) => character.toUpperCase());
|
|
70
|
+
}
|
|
71
|
+
function convertCase(value, casing = "title") {
|
|
72
|
+
switch (casing.toLowerCase()) {
|
|
73
|
+
case "title":
|
|
74
|
+
case "titlecase":
|
|
75
|
+
return toTitleCase(value);
|
|
76
|
+
case "lower":
|
|
77
|
+
case "lowercase":
|
|
78
|
+
return value.trim().toLowerCase();
|
|
79
|
+
case "upper":
|
|
80
|
+
case "uppercase":
|
|
81
|
+
return value.trim().toUpperCase();
|
|
82
|
+
case "camel":
|
|
83
|
+
case "camelcase":
|
|
84
|
+
return toCamelCase(value);
|
|
85
|
+
case "pascal":
|
|
86
|
+
case "pascalcase":
|
|
87
|
+
return toPascalCase(value);
|
|
88
|
+
case "snake":
|
|
89
|
+
case "snakecase":
|
|
90
|
+
return toSnakeCase(value);
|
|
91
|
+
case "kebab":
|
|
92
|
+
case "kebabcase":
|
|
93
|
+
return toKebabCase(value);
|
|
94
|
+
default:
|
|
95
|
+
throw new TypeError(`Unsupported case style: ${casing}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function replaceSeparatorsWithSpace(value) {
|
|
99
|
+
return toTitleCase(value.replace(/[-_]+/g, " ").replace(/\s+/g, " "));
|
|
100
|
+
}
|
|
101
|
+
function htmlToPlainText(value) {
|
|
102
|
+
if (value.trim().length === 0) {
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
105
|
+
return value.replace(/<(br|\/p|\/div|\/pre|\/li)\b[^>]*>/gi, " ").replace(/<[^>]*>/g, " ").replace(/[\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
106
|
+
}
|
|
107
|
+
function nonEmptyString(value) {
|
|
108
|
+
if (typeof value !== "string") {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const trimmed = value.trim();
|
|
112
|
+
return trimmed.length === 0 ? null : trimmed;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.capitalize = capitalize;
|
|
116
|
+
exports.convertCase = convertCase;
|
|
117
|
+
exports.escapeHtml = escapeHtml;
|
|
118
|
+
exports.escapeRegExp = escapeRegex;
|
|
119
|
+
exports.escapeRegex = escapeRegex;
|
|
120
|
+
exports.htmlToPlainText = htmlToPlainText;
|
|
121
|
+
exports.nonEmptyString = nonEmptyString;
|
|
122
|
+
exports.normalizeWhitespace = normalizeWhitespace;
|
|
123
|
+
exports.replaceSeparatorsWithSpace = replaceSeparatorsWithSpace;
|
|
124
|
+
exports.toCamelCase = toCamelCase;
|
|
125
|
+
exports.toKebabCase = toKebabCase;
|
|
126
|
+
exports.toPascalCase = toPascalCase;
|
|
127
|
+
exports.toSnakeCase = toSnakeCase;
|
|
128
|
+
exports.toTitleCase = toTitleCase;
|
|
129
|
+
//# sourceMappingURL=index.cjs.map
|
|
130
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/validation.ts","../../src/string/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export function assertFiniteNumber(\r\n value: unknown,\r\n name: string,\r\n): asserts value is number {\r\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\r\n throw new TypeError(`${name} must be a finite number`);\r\n }\r\n}\r\n\r\nexport function escapeRegExp(value: string): string {\r\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n","import { escapeRegExp } from \"../internal/validation.js\";\r\n\r\nexport type TextCase =\r\n | \"title\"\r\n | \"titlecase\"\r\n | \"lower\"\r\n | \"lowercase\"\r\n | \"upper\"\r\n | \"uppercase\"\r\n | \"camel\"\r\n | \"camelcase\"\r\n | \"pascal\"\r\n | \"pascalcase\"\r\n | \"snake\"\r\n | \"snakecase\"\r\n | \"kebab\"\r\n | \"kebabcase\";\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n \"&\": \"&\",\r\n \"<\": \"<\",\r\n \">\": \">\",\r\n '\"': \""\",\r\n \"'\": \"'\",\r\n};\r\n\r\n/**\r\n * Splits mixed naming conventions into discrete words.\r\n * Handles spaces, hyphens, underscores, dots, and camel/PascalCase boundaries.\r\n */\r\nfunction splitWords(value: string): string[] {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return [];\r\n }\r\n\r\n return trimmed\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\r\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\r\n .split(/[\\s._-]+/u)\r\n .filter((word) => word.length > 0);\r\n}\r\n\r\nfunction toLowerWords(value: string): string[] {\r\n return splitWords(value).map((word) => word.toLowerCase());\r\n}\r\n\r\nfunction capitalizeWord(word: string): string {\r\n const [first = \"\", ...rest] = [...word];\r\n return `${first.toUpperCase()}${rest.join(\"\").toLowerCase()}`;\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n *\r\n * @example\r\n * toCamelCase(\"hello-world\") // \"helloWorld\"\r\n * toCamelCase(\"XMLHttpRequest\") // \"xmlHttpRequest\"\r\n */\r\nexport function toCamelCase(value: string): string {\r\n const words = toLowerWords(value);\r\n if (words.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = words;\r\n return `${first}${rest.map(capitalizeWord).join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n *\r\n * @example\r\n * toPascalCase(\"hello_world\") // \"HelloWorld\"\r\n */\r\nexport function toPascalCase(value: string): string {\r\n return toLowerWords(value).map(capitalizeWord).join(\"\");\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n *\r\n * @example\r\n * toSnakeCase(\"Hello World\") // \"hello_world\"\r\n */\r\nexport function toSnakeCase(value: string): string {\r\n return toLowerWords(value).join(\"_\");\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n *\r\n * @example\r\n * toKebabCase(\"HelloWorld\") // \"hello-world\"\r\n */\r\nexport function toKebabCase(value: string): string {\r\n return toLowerWords(value).join(\"-\");\r\n}\r\n\r\n/**\r\n * Trims the string and uppercases its first Unicode character.\r\n * The remaining characters are left unchanged.\r\n *\r\n * @example\r\n * capitalize(\" hello world\") // \"Hello world\"\r\n */\r\nexport function capitalize(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = [...trimmed];\r\n return `${first.toUpperCase()}${rest.join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Trims leading and trailing whitespace and collapses internal\r\n * whitespace runs to a single space.\r\n *\r\n * @example\r\n * normalizeWhitespace(\" hello \\t\\n world \") // \"hello world\"\r\n */\r\nexport function normalizeWhitespace(value: string): string {\r\n return value.trim().replace(/\\s+/gu, \" \");\r\n}\r\n\r\n/**\r\n * Escapes `&`, `<`, `>`, `\"`, and `'` for safe interpolation into HTML text\r\n * or quoted attributes.\r\n *\r\n * This is not an HTML sanitizer. It does not parse markup, remove scripts,\r\n * or make untrusted HTML safe to render.\r\n *\r\n * @example\r\n * escapeHtml(`<img alt=\"O'Reilly & Co\">`)\r\n * // \"<img alt="O'Reilly & Co">\"\r\n */\r\nexport function escapeHtml(value: string): string {\r\n return value.replace(/[&<>\"']/g, (character) => HTML_ESCAPE_MAP[character] ?? character);\r\n}\r\n\r\n/**\r\n * Escapes special regular-expression characters in a string.\r\n *\r\n * @example\r\n * escapeRegex(\"file.name.txt\") // \"file\\\\.name\\\\.txt\"\r\n */\r\nexport function escapeRegex(value: string): string {\r\n return escapeRegExp(value);\r\n}\r\n\r\nexport { escapeRegex as escapeRegExp };\r\n\r\n/**\r\n * Converts a string to Title Case using word boundaries.\r\n *\r\n * @example\r\n * toTitleCase(\"hello world\") // \"Hello World\"\r\n * toTitleCase(\"used-truck\") // \"Used-Truck\"\r\n */\r\nexport function toTitleCase(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n return trimmed.toLowerCase().replace(/\\b\\w/g, (character) => character.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to one of the supported case styles.\r\n * Unknown styles throw rather than silently falling back.\r\n *\r\n * @example\r\n * convertCase(\"hello world\", \"title\") // \"Hello World\"\r\n * convertCase(\"hello-world\", \"camel\") // \"helloWorld\"\r\n */\r\nexport function convertCase(value: string, casing: TextCase = \"title\"): string {\r\n switch (casing.toLowerCase() as TextCase) {\r\n case \"title\":\r\n case \"titlecase\":\r\n return toTitleCase(value);\r\n case \"lower\":\r\n case \"lowercase\":\r\n return value.trim().toLowerCase();\r\n case \"upper\":\r\n case \"uppercase\":\r\n return value.trim().toUpperCase();\r\n case \"camel\":\r\n case \"camelcase\":\r\n return toCamelCase(value);\r\n case \"pascal\":\r\n case \"pascalcase\":\r\n return toPascalCase(value);\r\n case \"snake\":\r\n case \"snakecase\":\r\n return toSnakeCase(value);\r\n case \"kebab\":\r\n case \"kebabcase\":\r\n return toKebabCase(value);\r\n default:\r\n throw new TypeError(`Unsupported case style: ${casing}`);\r\n }\r\n}\r\n\r\n/**\r\n * Replaces hyphens and underscores with spaces, then title-cases the result.\r\n *\r\n * @example\r\n * replaceSeparatorsWithSpace(\"used-truck\") // \"Used Truck\"\r\n * replaceSeparatorsWithSpace(\"hello_world\") // \"Hello World\"\r\n */\r\nexport function replaceSeparatorsWithSpace(value: string): string {\r\n return toTitleCase(value.replace(/[-_]+/g, \" \").replace(/\\s+/g, \" \"));\r\n}\r\n\r\n/**\r\n * Strips HTML tags and collapses whitespace into a single-line plain-text string.\r\n *\r\n * This is not an HTML sanitizer or a complete HTML parser. It does not decode\r\n * all entities or preserve document structure.\r\n *\r\n * @example\r\n * htmlToPlainText(\"<p>Hello<br>World</p>\") // \"Hello World\"\r\n */\r\nexport function htmlToPlainText(value: string): string {\r\n if (value.trim().length === 0) {\r\n return \"\";\r\n }\r\n\r\n return value\r\n .replace(/<(br|\\/p|\\/div|\\/pre|\\/li)\\b[^>]*>/gi, \" \")\r\n .replace(/<[^>]*>/g, \" \")\r\n .replace(/[\\n\\t]+/g, \" \")\r\n .replace(/\\s+/g, \" \")\r\n .trim();\r\n}\r\n\r\n/**\r\n * Returns a trimmed string, or `null` when the value is not a non-empty string.\r\n *\r\n * @example\r\n * nonEmptyString(\" Gold \") // \"Gold\"\r\n * nonEmptyString(\" \") // null\r\n */\r\nexport function nonEmptyString(value: unknown): string | null {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n return trimmed.length === 0 ? null : trimmed;\r\n}\r\n"]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
type TextCase = "title" | "titlecase" | "lower" | "lowercase" | "upper" | "uppercase" | "camel" | "camelcase" | "pascal" | "pascalcase" | "snake" | "snakecase" | "kebab" | "kebabcase";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a string to camelCase.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* toCamelCase("hello-world") // "helloWorld"
|
|
7
|
+
* toCamelCase("XMLHttpRequest") // "xmlHttpRequest"
|
|
8
|
+
*/
|
|
9
|
+
declare function toCamelCase(value: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Converts a string to PascalCase.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* toPascalCase("hello_world") // "HelloWorld"
|
|
15
|
+
*/
|
|
16
|
+
declare function toPascalCase(value: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Converts a string to snake_case.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* toSnakeCase("Hello World") // "hello_world"
|
|
22
|
+
*/
|
|
23
|
+
declare function toSnakeCase(value: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Converts a string to kebab-case.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* toKebabCase("HelloWorld") // "hello-world"
|
|
29
|
+
*/
|
|
30
|
+
declare function toKebabCase(value: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Trims the string and uppercases its first Unicode character.
|
|
33
|
+
* The remaining characters are left unchanged.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* capitalize(" hello world") // "Hello world"
|
|
37
|
+
*/
|
|
38
|
+
declare function capitalize(value: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Trims leading and trailing whitespace and collapses internal
|
|
41
|
+
* whitespace runs to a single space.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* normalizeWhitespace(" hello \t\n world ") // "hello world"
|
|
45
|
+
*/
|
|
46
|
+
declare function normalizeWhitespace(value: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Escapes `&`, `<`, `>`, `"`, and `'` for safe interpolation into HTML text
|
|
49
|
+
* or quoted attributes.
|
|
50
|
+
*
|
|
51
|
+
* This is not an HTML sanitizer. It does not parse markup, remove scripts,
|
|
52
|
+
* or make untrusted HTML safe to render.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* escapeHtml(`<img alt="O'Reilly & Co">`)
|
|
56
|
+
* // "<img alt="O'Reilly & Co">"
|
|
57
|
+
*/
|
|
58
|
+
declare function escapeHtml(value: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Escapes special regular-expression characters in a string.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* escapeRegex("file.name.txt") // "file\\.name\\.txt"
|
|
64
|
+
*/
|
|
65
|
+
declare function escapeRegex(value: string): string;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Converts a string to Title Case using word boundaries.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* toTitleCase("hello world") // "Hello World"
|
|
72
|
+
* toTitleCase("used-truck") // "Used-Truck"
|
|
73
|
+
*/
|
|
74
|
+
declare function toTitleCase(value: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Converts a string to one of the supported case styles.
|
|
77
|
+
* Unknown styles throw rather than silently falling back.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* convertCase("hello world", "title") // "Hello World"
|
|
81
|
+
* convertCase("hello-world", "camel") // "helloWorld"
|
|
82
|
+
*/
|
|
83
|
+
declare function convertCase(value: string, casing?: TextCase): string;
|
|
84
|
+
/**
|
|
85
|
+
* Replaces hyphens and underscores with spaces, then title-cases the result.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* replaceSeparatorsWithSpace("used-truck") // "Used Truck"
|
|
89
|
+
* replaceSeparatorsWithSpace("hello_world") // "Hello World"
|
|
90
|
+
*/
|
|
91
|
+
declare function replaceSeparatorsWithSpace(value: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Strips HTML tags and collapses whitespace into a single-line plain-text string.
|
|
94
|
+
*
|
|
95
|
+
* This is not an HTML sanitizer or a complete HTML parser. It does not decode
|
|
96
|
+
* all entities or preserve document structure.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* htmlToPlainText("<p>Hello<br>World</p>") // "Hello World"
|
|
100
|
+
*/
|
|
101
|
+
declare function htmlToPlainText(value: string): string;
|
|
102
|
+
/**
|
|
103
|
+
* Returns a trimmed string, or `null` when the value is not a non-empty string.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* nonEmptyString(" Gold ") // "Gold"
|
|
107
|
+
* nonEmptyString(" ") // null
|
|
108
|
+
*/
|
|
109
|
+
declare function nonEmptyString(value: unknown): string | null;
|
|
110
|
+
|
|
111
|
+
export { capitalize, convertCase, escapeHtml, escapeRegex as escapeRegExp, escapeRegex, htmlToPlainText, nonEmptyString, normalizeWhitespace, replaceSeparatorsWithSpace, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toTitleCase };
|
|
112
|
+
export type { TextCase };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
type TextCase = "title" | "titlecase" | "lower" | "lowercase" | "upper" | "uppercase" | "camel" | "camelcase" | "pascal" | "pascalcase" | "snake" | "snakecase" | "kebab" | "kebabcase";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a string to camelCase.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* toCamelCase("hello-world") // "helloWorld"
|
|
7
|
+
* toCamelCase("XMLHttpRequest") // "xmlHttpRequest"
|
|
8
|
+
*/
|
|
9
|
+
declare function toCamelCase(value: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Converts a string to PascalCase.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* toPascalCase("hello_world") // "HelloWorld"
|
|
15
|
+
*/
|
|
16
|
+
declare function toPascalCase(value: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Converts a string to snake_case.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* toSnakeCase("Hello World") // "hello_world"
|
|
22
|
+
*/
|
|
23
|
+
declare function toSnakeCase(value: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Converts a string to kebab-case.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* toKebabCase("HelloWorld") // "hello-world"
|
|
29
|
+
*/
|
|
30
|
+
declare function toKebabCase(value: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Trims the string and uppercases its first Unicode character.
|
|
33
|
+
* The remaining characters are left unchanged.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* capitalize(" hello world") // "Hello world"
|
|
37
|
+
*/
|
|
38
|
+
declare function capitalize(value: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Trims leading and trailing whitespace and collapses internal
|
|
41
|
+
* whitespace runs to a single space.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* normalizeWhitespace(" hello \t\n world ") // "hello world"
|
|
45
|
+
*/
|
|
46
|
+
declare function normalizeWhitespace(value: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Escapes `&`, `<`, `>`, `"`, and `'` for safe interpolation into HTML text
|
|
49
|
+
* or quoted attributes.
|
|
50
|
+
*
|
|
51
|
+
* This is not an HTML sanitizer. It does not parse markup, remove scripts,
|
|
52
|
+
* or make untrusted HTML safe to render.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* escapeHtml(`<img alt="O'Reilly & Co">`)
|
|
56
|
+
* // "<img alt="O'Reilly & Co">"
|
|
57
|
+
*/
|
|
58
|
+
declare function escapeHtml(value: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Escapes special regular-expression characters in a string.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* escapeRegex("file.name.txt") // "file\\.name\\.txt"
|
|
64
|
+
*/
|
|
65
|
+
declare function escapeRegex(value: string): string;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Converts a string to Title Case using word boundaries.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* toTitleCase("hello world") // "Hello World"
|
|
72
|
+
* toTitleCase("used-truck") // "Used-Truck"
|
|
73
|
+
*/
|
|
74
|
+
declare function toTitleCase(value: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Converts a string to one of the supported case styles.
|
|
77
|
+
* Unknown styles throw rather than silently falling back.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* convertCase("hello world", "title") // "Hello World"
|
|
81
|
+
* convertCase("hello-world", "camel") // "helloWorld"
|
|
82
|
+
*/
|
|
83
|
+
declare function convertCase(value: string, casing?: TextCase): string;
|
|
84
|
+
/**
|
|
85
|
+
* Replaces hyphens and underscores with spaces, then title-cases the result.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* replaceSeparatorsWithSpace("used-truck") // "Used Truck"
|
|
89
|
+
* replaceSeparatorsWithSpace("hello_world") // "Hello World"
|
|
90
|
+
*/
|
|
91
|
+
declare function replaceSeparatorsWithSpace(value: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Strips HTML tags and collapses whitespace into a single-line plain-text string.
|
|
94
|
+
*
|
|
95
|
+
* This is not an HTML sanitizer or a complete HTML parser. It does not decode
|
|
96
|
+
* all entities or preserve document structure.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* htmlToPlainText("<p>Hello<br>World</p>") // "Hello World"
|
|
100
|
+
*/
|
|
101
|
+
declare function htmlToPlainText(value: string): string;
|
|
102
|
+
/**
|
|
103
|
+
* Returns a trimmed string, or `null` when the value is not a non-empty string.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* nonEmptyString(" Gold ") // "Gold"
|
|
107
|
+
* nonEmptyString(" ") // null
|
|
108
|
+
*/
|
|
109
|
+
declare function nonEmptyString(value: unknown): string | null;
|
|
110
|
+
|
|
111
|
+
export { capitalize, convertCase, escapeHtml, escapeRegex as escapeRegExp, escapeRegex, htmlToPlainText, nonEmptyString, normalizeWhitespace, replaceSeparatorsWithSpace, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toTitleCase };
|
|
112
|
+
export type { TextCase };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// src/internal/validation.ts
|
|
2
|
+
function escapeRegExp(value) {
|
|
3
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/string/index.ts
|
|
7
|
+
var HTML_ESCAPE_MAP = {
|
|
8
|
+
"&": "&",
|
|
9
|
+
"<": "<",
|
|
10
|
+
">": ">",
|
|
11
|
+
'"': """,
|
|
12
|
+
"'": "'"
|
|
13
|
+
};
|
|
14
|
+
function splitWords(value) {
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
if (trimmed.length === 0) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
return trimmed.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s._-]+/u).filter((word) => word.length > 0);
|
|
20
|
+
}
|
|
21
|
+
function toLowerWords(value) {
|
|
22
|
+
return splitWords(value).map((word) => word.toLowerCase());
|
|
23
|
+
}
|
|
24
|
+
function capitalizeWord(word) {
|
|
25
|
+
const [first = "", ...rest] = [...word];
|
|
26
|
+
return `${first.toUpperCase()}${rest.join("").toLowerCase()}`;
|
|
27
|
+
}
|
|
28
|
+
function toCamelCase(value) {
|
|
29
|
+
const words = toLowerWords(value);
|
|
30
|
+
if (words.length === 0) {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
const [first = "", ...rest] = words;
|
|
34
|
+
return `${first}${rest.map(capitalizeWord).join("")}`;
|
|
35
|
+
}
|
|
36
|
+
function toPascalCase(value) {
|
|
37
|
+
return toLowerWords(value).map(capitalizeWord).join("");
|
|
38
|
+
}
|
|
39
|
+
function toSnakeCase(value) {
|
|
40
|
+
return toLowerWords(value).join("_");
|
|
41
|
+
}
|
|
42
|
+
function toKebabCase(value) {
|
|
43
|
+
return toLowerWords(value).join("-");
|
|
44
|
+
}
|
|
45
|
+
function capitalize(value) {
|
|
46
|
+
const trimmed = value.trim();
|
|
47
|
+
if (trimmed.length === 0) {
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
const [first = "", ...rest] = [...trimmed];
|
|
51
|
+
return `${first.toUpperCase()}${rest.join("")}`;
|
|
52
|
+
}
|
|
53
|
+
function normalizeWhitespace(value) {
|
|
54
|
+
return value.trim().replace(/\s+/gu, " ");
|
|
55
|
+
}
|
|
56
|
+
function escapeHtml(value) {
|
|
57
|
+
return value.replace(/[&<>"']/g, (character) => HTML_ESCAPE_MAP[character] ?? character);
|
|
58
|
+
}
|
|
59
|
+
function escapeRegex(value) {
|
|
60
|
+
return escapeRegExp(value);
|
|
61
|
+
}
|
|
62
|
+
function toTitleCase(value) {
|
|
63
|
+
const trimmed = value.trim();
|
|
64
|
+
if (trimmed.length === 0) {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
return trimmed.toLowerCase().replace(/\b\w/g, (character) => character.toUpperCase());
|
|
68
|
+
}
|
|
69
|
+
function convertCase(value, casing = "title") {
|
|
70
|
+
switch (casing.toLowerCase()) {
|
|
71
|
+
case "title":
|
|
72
|
+
case "titlecase":
|
|
73
|
+
return toTitleCase(value);
|
|
74
|
+
case "lower":
|
|
75
|
+
case "lowercase":
|
|
76
|
+
return value.trim().toLowerCase();
|
|
77
|
+
case "upper":
|
|
78
|
+
case "uppercase":
|
|
79
|
+
return value.trim().toUpperCase();
|
|
80
|
+
case "camel":
|
|
81
|
+
case "camelcase":
|
|
82
|
+
return toCamelCase(value);
|
|
83
|
+
case "pascal":
|
|
84
|
+
case "pascalcase":
|
|
85
|
+
return toPascalCase(value);
|
|
86
|
+
case "snake":
|
|
87
|
+
case "snakecase":
|
|
88
|
+
return toSnakeCase(value);
|
|
89
|
+
case "kebab":
|
|
90
|
+
case "kebabcase":
|
|
91
|
+
return toKebabCase(value);
|
|
92
|
+
default:
|
|
93
|
+
throw new TypeError(`Unsupported case style: ${casing}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function replaceSeparatorsWithSpace(value) {
|
|
97
|
+
return toTitleCase(value.replace(/[-_]+/g, " ").replace(/\s+/g, " "));
|
|
98
|
+
}
|
|
99
|
+
function htmlToPlainText(value) {
|
|
100
|
+
if (value.trim().length === 0) {
|
|
101
|
+
return "";
|
|
102
|
+
}
|
|
103
|
+
return value.replace(/<(br|\/p|\/div|\/pre|\/li)\b[^>]*>/gi, " ").replace(/<[^>]*>/g, " ").replace(/[\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
104
|
+
}
|
|
105
|
+
function nonEmptyString(value) {
|
|
106
|
+
if (typeof value !== "string") {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const trimmed = value.trim();
|
|
110
|
+
return trimmed.length === 0 ? null : trimmed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export { capitalize, convertCase, escapeHtml, escapeRegex as escapeRegExp, escapeRegex, htmlToPlainText, nonEmptyString, normalizeWhitespace, replaceSeparatorsWithSpace, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toTitleCase };
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/validation.ts","../../src/string/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export function assertFiniteNumber(\r\n value: unknown,\r\n name: string,\r\n): asserts value is number {\r\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\r\n throw new TypeError(`${name} must be a finite number`);\r\n }\r\n}\r\n\r\nexport function escapeRegExp(value: string): string {\r\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n","import { escapeRegExp } from \"../internal/validation.js\";\r\n\r\nexport type TextCase =\r\n | \"title\"\r\n | \"titlecase\"\r\n | \"lower\"\r\n | \"lowercase\"\r\n | \"upper\"\r\n | \"uppercase\"\r\n | \"camel\"\r\n | \"camelcase\"\r\n | \"pascal\"\r\n | \"pascalcase\"\r\n | \"snake\"\r\n | \"snakecase\"\r\n | \"kebab\"\r\n | \"kebabcase\";\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n \"&\": \"&\",\r\n \"<\": \"<\",\r\n \">\": \">\",\r\n '\"': \""\",\r\n \"'\": \"'\",\r\n};\r\n\r\n/**\r\n * Splits mixed naming conventions into discrete words.\r\n * Handles spaces, hyphens, underscores, dots, and camel/PascalCase boundaries.\r\n */\r\nfunction splitWords(value: string): string[] {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return [];\r\n }\r\n\r\n return trimmed\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\r\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\r\n .split(/[\\s._-]+/u)\r\n .filter((word) => word.length > 0);\r\n}\r\n\r\nfunction toLowerWords(value: string): string[] {\r\n return splitWords(value).map((word) => word.toLowerCase());\r\n}\r\n\r\nfunction capitalizeWord(word: string): string {\r\n const [first = \"\", ...rest] = [...word];\r\n return `${first.toUpperCase()}${rest.join(\"\").toLowerCase()}`;\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n *\r\n * @example\r\n * toCamelCase(\"hello-world\") // \"helloWorld\"\r\n * toCamelCase(\"XMLHttpRequest\") // \"xmlHttpRequest\"\r\n */\r\nexport function toCamelCase(value: string): string {\r\n const words = toLowerWords(value);\r\n if (words.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = words;\r\n return `${first}${rest.map(capitalizeWord).join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n *\r\n * @example\r\n * toPascalCase(\"hello_world\") // \"HelloWorld\"\r\n */\r\nexport function toPascalCase(value: string): string {\r\n return toLowerWords(value).map(capitalizeWord).join(\"\");\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n *\r\n * @example\r\n * toSnakeCase(\"Hello World\") // \"hello_world\"\r\n */\r\nexport function toSnakeCase(value: string): string {\r\n return toLowerWords(value).join(\"_\");\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n *\r\n * @example\r\n * toKebabCase(\"HelloWorld\") // \"hello-world\"\r\n */\r\nexport function toKebabCase(value: string): string {\r\n return toLowerWords(value).join(\"-\");\r\n}\r\n\r\n/**\r\n * Trims the string and uppercases its first Unicode character.\r\n * The remaining characters are left unchanged.\r\n *\r\n * @example\r\n * capitalize(\" hello world\") // \"Hello world\"\r\n */\r\nexport function capitalize(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = [...trimmed];\r\n return `${first.toUpperCase()}${rest.join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Trims leading and trailing whitespace and collapses internal\r\n * whitespace runs to a single space.\r\n *\r\n * @example\r\n * normalizeWhitespace(\" hello \\t\\n world \") // \"hello world\"\r\n */\r\nexport function normalizeWhitespace(value: string): string {\r\n return value.trim().replace(/\\s+/gu, \" \");\r\n}\r\n\r\n/**\r\n * Escapes `&`, `<`, `>`, `\"`, and `'` for safe interpolation into HTML text\r\n * or quoted attributes.\r\n *\r\n * This is not an HTML sanitizer. It does not parse markup, remove scripts,\r\n * or make untrusted HTML safe to render.\r\n *\r\n * @example\r\n * escapeHtml(`<img alt=\"O'Reilly & Co\">`)\r\n * // \"<img alt="O'Reilly & Co">\"\r\n */\r\nexport function escapeHtml(value: string): string {\r\n return value.replace(/[&<>\"']/g, (character) => HTML_ESCAPE_MAP[character] ?? character);\r\n}\r\n\r\n/**\r\n * Escapes special regular-expression characters in a string.\r\n *\r\n * @example\r\n * escapeRegex(\"file.name.txt\") // \"file\\\\.name\\\\.txt\"\r\n */\r\nexport function escapeRegex(value: string): string {\r\n return escapeRegExp(value);\r\n}\r\n\r\nexport { escapeRegex as escapeRegExp };\r\n\r\n/**\r\n * Converts a string to Title Case using word boundaries.\r\n *\r\n * @example\r\n * toTitleCase(\"hello world\") // \"Hello World\"\r\n * toTitleCase(\"used-truck\") // \"Used-Truck\"\r\n */\r\nexport function toTitleCase(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n return trimmed.toLowerCase().replace(/\\b\\w/g, (character) => character.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to one of the supported case styles.\r\n * Unknown styles throw rather than silently falling back.\r\n *\r\n * @example\r\n * convertCase(\"hello world\", \"title\") // \"Hello World\"\r\n * convertCase(\"hello-world\", \"camel\") // \"helloWorld\"\r\n */\r\nexport function convertCase(value: string, casing: TextCase = \"title\"): string {\r\n switch (casing.toLowerCase() as TextCase) {\r\n case \"title\":\r\n case \"titlecase\":\r\n return toTitleCase(value);\r\n case \"lower\":\r\n case \"lowercase\":\r\n return value.trim().toLowerCase();\r\n case \"upper\":\r\n case \"uppercase\":\r\n return value.trim().toUpperCase();\r\n case \"camel\":\r\n case \"camelcase\":\r\n return toCamelCase(value);\r\n case \"pascal\":\r\n case \"pascalcase\":\r\n return toPascalCase(value);\r\n case \"snake\":\r\n case \"snakecase\":\r\n return toSnakeCase(value);\r\n case \"kebab\":\r\n case \"kebabcase\":\r\n return toKebabCase(value);\r\n default:\r\n throw new TypeError(`Unsupported case style: ${casing}`);\r\n }\r\n}\r\n\r\n/**\r\n * Replaces hyphens and underscores with spaces, then title-cases the result.\r\n *\r\n * @example\r\n * replaceSeparatorsWithSpace(\"used-truck\") // \"Used Truck\"\r\n * replaceSeparatorsWithSpace(\"hello_world\") // \"Hello World\"\r\n */\r\nexport function replaceSeparatorsWithSpace(value: string): string {\r\n return toTitleCase(value.replace(/[-_]+/g, \" \").replace(/\\s+/g, \" \"));\r\n}\r\n\r\n/**\r\n * Strips HTML tags and collapses whitespace into a single-line plain-text string.\r\n *\r\n * This is not an HTML sanitizer or a complete HTML parser. It does not decode\r\n * all entities or preserve document structure.\r\n *\r\n * @example\r\n * htmlToPlainText(\"<p>Hello<br>World</p>\") // \"Hello World\"\r\n */\r\nexport function htmlToPlainText(value: string): string {\r\n if (value.trim().length === 0) {\r\n return \"\";\r\n }\r\n\r\n return value\r\n .replace(/<(br|\\/p|\\/div|\\/pre|\\/li)\\b[^>]*>/gi, \" \")\r\n .replace(/<[^>]*>/g, \" \")\r\n .replace(/[\\n\\t]+/g, \" \")\r\n .replace(/\\s+/g, \" \")\r\n .trim();\r\n}\r\n\r\n/**\r\n * Returns a trimmed string, or `null` when the value is not a non-empty string.\r\n *\r\n * @example\r\n * nonEmptyString(\" Gold \") // \"Gold\"\r\n * nonEmptyString(\" \") // null\r\n */\r\nexport function nonEmptyString(value: unknown): string | null {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n return trimmed.length === 0 ? null : trimmed;\r\n}\r\n"]}
|