text-sanctifier 1.0.17 → 1.0.19
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/ADDITIONAL_TERMS.md +122 -0
- package/LICENSE +694 -0
- package/README.md +163 -163
- package/dist/text-sanctifier.min.js +9 -7
- package/dist/types/index.d.ts +4 -0
- package/dist/types/inspectText.d.ts +38 -0
- package/dist/types/sanctifyText.d.ts +167 -0
- package/package.json +65 -55
- package/robots.txt +79 -0
- package/src/index.d.ts +4 -116
- package/src/index.js +12 -12
- package/src/inspectText.js +175 -171
- package/src/sanctifyText.js +507 -451
- package/LICENSE.md +0 -285
package/README.md
CHANGED
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
# text-sanctifier
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/text-sanctifier)
|
|
4
|
-
[](https://www.npmjs.com/package/text-sanctifier)
|
|
4
|
+
[](https://www.npmjs.com/package/text-sanctifier)
|
|
5
|
+
[](https://bundlephobia.com/package/text-sanctifier)
|
|
6
|
+
[](https://github.com/iWhatty/text-sanctifier/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/iWhatty/text-sanctifier)
|
|
8
|
+
|
|
9
|
+
Brutal text normalizer and invisible Unicode scrubber for modern web projects. ~1.66 KB gzipped.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Purges zero-width Unicode garbage
|
|
14
|
+
- Normalizes line endings (CRLF, CR, LF) to LF
|
|
15
|
+
- Collapses unwanted spaces and paragraphs
|
|
16
|
+
- Nukes control characters (if enabled)
|
|
17
|
+
- Smart normalization of typographic junk (quotes, dashes, bullets, full-width punctuation)
|
|
18
|
+
- Keyboard-only filtering (retain printable ASCII + full emoji sequences)
|
|
19
|
+
- Preserves ZWJ emoji clusters (👨👩👧👦)
|
|
20
|
+
- Preserves VS16 emoji presentation variants (✌️, ‼️)
|
|
21
|
+
- Configurable via fine-grained flags or ready-made presets
|
|
22
|
+
- Includes strict, loose, and keyboard-only modes
|
|
23
|
+
- Deterministic RegExp usage (no global `lastIndex` state leaks)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
pnpm add text-sanctifier
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
**Custom config:**
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import { summonSanctifier } from 'text-sanctifier';
|
|
41
|
+
|
|
42
|
+
const clean = summonSanctifier({
|
|
43
|
+
purgeInvisibleChars: true,
|
|
44
|
+
purgeEmojis: true,
|
|
45
|
+
collapseSpaces: true,
|
|
46
|
+
collapseNewLines: true,
|
|
47
|
+
preserveParagraphs: true,
|
|
48
|
+
finalTrim: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const output = clean(rawText);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Strict preset:**
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
const output = summonSanctifier.strict(rawText);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Loose preset:**
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
const output = summonSanctifier.loose(rawText);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Keyboard-only (no emojis):**
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
const output = summonSanctifier.keyboardOnly(userInput);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Keyboard-only (with emojis):**
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
const output = summonSanctifier.keyboardOnlyEmoji(commentText);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Security notes
|
|
81
|
+
|
|
82
|
+
- **Not an HTML/XSS sanitizer.** This library normalizes and filters plain text.
|
|
83
|
+
- If you need to render **untrusted content**, render it as text (e.g. `textContent`), not HTML (`innerHTML`).
|
|
84
|
+
- If you need to sanitize **HTML**, use a dedicated HTML sanitizer (e.g. DOMPurify / sanitize-html).
|
|
85
|
+
- Like any text-processing library, extremely large untrusted inputs can be used for CPU/DoS pressure; consider input size limits in high-risk environments.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
### `summonSanctifier(options?: SanctifyOptions): (text: string) => string`
|
|
92
|
+
|
|
93
|
+
Creates a reusable sanitizer from an option object.
|
|
94
|
+
|
|
95
|
+
### `summonSanctifier.strict`
|
|
96
|
+
|
|
97
|
+
Aggressively purges: emojis, control characters, extra spacing, and newlines.
|
|
98
|
+
|
|
99
|
+
### `summonSanctifier.loose`
|
|
100
|
+
|
|
101
|
+
Gently normalizes spacing and newlines while preserving emojis and paragraphs.
|
|
102
|
+
|
|
103
|
+
### `summonSanctifier.keyboardOnly`
|
|
104
|
+
|
|
105
|
+
Restricts to printable ASCII only (removes emojis).
|
|
106
|
+
|
|
107
|
+
### `summonSanctifier.keyboardOnlyEmoji`
|
|
108
|
+
|
|
109
|
+
Restricts to printable ASCII + full emoji sequences. Preserves ZWJ emoji clusters and emoji presentation variants.
|
|
110
|
+
|
|
111
|
+
### `inspectText(text: string): UnicodeTrashReport`
|
|
112
|
+
|
|
113
|
+
Returns a structural report of control codes, invisible chars, newline styles, and more.
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { inspectText } from 'text-sanctifier';
|
|
117
|
+
|
|
118
|
+
const report = inspectText(input);
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
{
|
|
122
|
+
hasControlChars: true,
|
|
123
|
+
hasInvisibleChars: true,
|
|
124
|
+
hasMixedNewlines: false,
|
|
125
|
+
newlineStyle: 'LF',
|
|
126
|
+
hasEmojis: true,
|
|
127
|
+
hasNonKeyboardChars: false,
|
|
128
|
+
summary: [
|
|
129
|
+
'Control characters detected.',
|
|
130
|
+
'Invisible Unicode characters detected.',
|
|
131
|
+
'Emojis detected.',
|
|
132
|
+
'Consistent newline style: LF'
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
*/
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Use `inspectText` to preflight text content before rendering, storing, or linting. It's a diagnostic tool to help inform sanitization needs. Pass the report to `getRecommendedSanctifierOptions(report)` to auto-generate config flags for `summonSanctifier()`.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Notes
|
|
143
|
+
|
|
144
|
+
### Runtime requirements
|
|
145
|
+
|
|
146
|
+
Requires a modern JavaScript runtime with ES2020+ support:
|
|
147
|
+
|
|
148
|
+
- Node.js 14+
|
|
149
|
+
- Modern evergreen browsers
|
|
150
|
+
|
|
151
|
+
### Package and build info
|
|
152
|
+
|
|
153
|
+
- **Source (`src/`):** ES2020+ ESM modules with JSDoc
|
|
154
|
+
- **Browser build (`dist/`):** Minified ESM bundle for `<script type="module">`
|
|
155
|
+
- **Tree-shake friendly:** ships `sideEffects: false`
|
|
156
|
+
- **Zero transpilation:** no built-in polyfills or runtime overhead
|
|
157
|
+
- **Bundler ready:** works with Vite, Rollup, Webpack, Parcel, esbuild
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Licensed under AGPL-3.0 with WATT3D Additional Terms. See [LICENSE](./LICENSE) and [ADDITIONAL_TERMS.md](./ADDITIONAL_TERMS.md). Commercial AI/model-training use requires compliance with those terms or a separate WATT3D license. © WATT3D.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
|
|
1
|
+
function g(a={}){const c=!!a.purgeInvisibleChars,b=!!a.purgeEmojis,d=!!a.nukeControls,f=!!a.keyboardOnlyFilter,h=!!a.normalizeNewlines,m=!!a.trimSpacesAroundNewlines,e=!!a.collapseNewLines,r=!!a.preserveParagraphs,t=!!a.collapseSpaces,u=!!a.finalTrim,n=Number.isFinite(a.maxLength)&&0<=a.maxLength?a.maxLength:Infinity,k="truncate"===a.g||"noop"===a.g||"throw"===a.g?a.g:"throw";return z=>l(z,c,b,d,f,h,m,e,r,t,u,n,k)}g.strict=a=>l(a,!0,!0,!0,!1,!0,!0,!0,!1,!0,!0);
|
|
2
|
+
g.loose=a=>l(a,!1,!1,!1,!1,!0,!0,!0,!0,!0,!0);g.keyboardOnlyEmoji=a=>l(a,!1,!1,!1,!0,!0,!0,!1,!1,!1,!0);g.keyboardOnly=a=>l(a,!0,!0,!0,!0,!0,!0,!0,!1,!0,!0);
|
|
3
|
+
function l(a,c=!1,b=!1,d=!1,f=!1,h=!1,m=!1,e=!1,r=!1,t=!1,u=!1,n=Infinity,k="throw"){if("string"!==typeof a)throw new TypeError("sanctifyText expects a string input.");"truncate"!==k&&"noop"!==k&&"throw"!==k&&(k="throw");if(a.length>n)switch(k){case "truncate":a=a.slice(0,n);break;case "noop":return a;default:throw new RangeError(`sanctifyText input length ${a.length} exceeds maxLength ${n}.`);}c&&(a=a.replace(p,""));b&&(a=a.replace(q,""));d&&(a=a.replace(v,""));f&&(a=w(a,b));h&&(a=a.replace(x,"\n"));
|
|
4
|
+
m&&(a=a.replace(y,"$1"));e&&(c=a,a=r?c.replace(A,"\n\n"):c.replace(B,"\n"));t&&(a=a.replace(C," "));return u?a.trim():a}var p=/[\u00A0\u2000-\u200D\u202F\u2060\u3000\uFEFF\u200E\u200F\u202A-\u202E]+/g,D=/[^\x20-\x7E\r\n]+/gu;function w(a,c=!1){a=E(a);return c?a.replace(D,""):a.replace(D,b=>{q.lastIndex=0;if(q.test(b)){q.lastIndex=0;var d="";for(const f of b.matchAll(q))d+=f[0];b=d}else b="";return b})}
|
|
5
|
+
var F=/[\u2018\u2019\u201A\u201B\u2032\u2035]/g,G=/[\u201C\u201D\u201E\u201F\u2033\u2036\u00AB\u00BB]/g,H=/[\u2012\u2013\u2014\u2015\u2212]/g,I=/\u2026/g,J=/[\u2022\u00B7]/g,K=/[\uFF01-\uFF5E]/g;function E(a){return a.replace(F,"'").replace(G,'"').replace(H,"-").replace(I,"...").replace(J,"*").replace(K,c=>String.fromCharCode(c.charCodeAt(0)-65248))}var q;try{q=RegExp("(?:\\p{Extended_Pictographic}(?:\\uFE0F|\\uFE0E)?(?:\\u200D(?:\\p{Extended_Pictographic}|\\w)+)*)","gu")}catch{q=/[\u{2700}-\u{27BF}\u{1F300}-\u{1FAFF}\u{1F3FB}-\u{1F3FF}\u200D\uFE0F\u{1F1E6}-\u{1F1FF}]/gu}
|
|
6
|
+
var x=/\r\n|\r|\n/g,y=/[ \t]*(\n+)[ \t]*/g,B=/\n{2,}/g,A=/\n{3,}/g,C=/ {2,}/g,v=/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F\u0080-\u009F\u200E\u200F\u202A-\u202E]+/g;function L(a,c){a.lastIndex=0;return a.test(c)}
|
|
7
|
+
function M(a){if("string"!==typeof a)throw new TypeError("inspectText expects a string input.");const c=[],b={hasControlChars:!1,hasInvisibleChars:!1,hasMixedNewlines:!1,newlineStyle:null,hasEmojis:!1,hasNonKeyboardChars:!1,summary:c};L(v,a)&&(b.hasControlChars=!0,c.push("Control characters detected."));L(p,a)&&(b.hasInvisibleChars=!0,c.push("Invisible Unicode characters detected."));L(q,a)&&(b.hasEmojis=!0,c.push("Emojis detected."));if("string"!==typeof a)throw new TypeError("getNewlineStats expects a string input.");
|
|
8
|
+
var d=a.replace(/\r\n/g,"");d={i:(a.match(/\r\n/g)||[]).length,h:(d.match(/\r/g)||[]).length,j:(d.match(/\n/g)||[]).length};const f=[];0<d.i&&f.push("CRLF");0<d.h&&f.push("CR");0<d.j&&f.push("LF");const {l:h,types:m}={...d,types:f,l:1<f.length};b.hasMixedNewlines=h;b.newlineStyle=h?"Mixed":m[0]||null;b.newlineStyle&&c.push(h?"Mixed newline styles detected.":`Consistent newline style: ${b.newlineStyle}`);a:{a=E(a);if(L(D,a))for(e of a)if(!("\n"===e||"\r"===e||" "<=e&&"~">=e||L(q,e))){var e=!0;break a}e=
|
|
9
|
+
!1}e&&(b.hasNonKeyboardChars=!0,c.push("Non-keyboard characters detected."));return b}function N(a){return{purgeInvisibleChars:a.hasInvisibleChars,purgeEmojis:a.hasEmojis,nukeControls:a.hasControlChars,keyboardOnlyFilter:a.hasNonKeyboardChars,normalizeNewlines:a.hasMixedNewlines||"CRLF"===a.newlineStyle||"CR"===a.newlineStyle}}export { g as summonSanctifier, M as inspectText, N as getRecommendedSanctifierOptions };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects textual "trash" or anomalies in a given string.
|
|
3
|
+
* @param {string} text @returns {UnicodeTrashReport}
|
|
4
|
+
*/
|
|
5
|
+
export function inspectText(text: string): UnicodeTrashReport;
|
|
6
|
+
/**
|
|
7
|
+
* Counts the number of different newline types in a string.
|
|
8
|
+
* @param {string} text
|
|
9
|
+
* @returns {{
|
|
10
|
+
* crlf: number,
|
|
11
|
+
* cr: number,
|
|
12
|
+
* lf: number,
|
|
13
|
+
* types: string[],
|
|
14
|
+
* mixed: boolean
|
|
15
|
+
* }}
|
|
16
|
+
*/
|
|
17
|
+
export function getNewlineStats(text: string): {
|
|
18
|
+
crlf: number;
|
|
19
|
+
cr: number;
|
|
20
|
+
lf: number;
|
|
21
|
+
types: string[];
|
|
22
|
+
mixed: boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates defaultOptions for summonSanctifier based on inspectText result
|
|
26
|
+
* @param {!UnicodeTrashReport} report
|
|
27
|
+
* @return {!SanctifyOptions}
|
|
28
|
+
*/
|
|
29
|
+
export function getRecommendedSanctifierOptions(report: UnicodeTrashReport): SanctifyOptions;
|
|
30
|
+
export type UnicodeTrashReport = {
|
|
31
|
+
hasControlChars: boolean;
|
|
32
|
+
hasInvisibleChars: boolean;
|
|
33
|
+
hasMixedNewlines: boolean;
|
|
34
|
+
newlineStyle: "LF" | "CRLF" | "CR" | "Mixed" | null;
|
|
35
|
+
hasEmojis: boolean;
|
|
36
|
+
hasNonKeyboardChars: boolean;
|
|
37
|
+
summary: string[];
|
|
38
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} SanctifyOptions
|
|
3
|
+
* @property {boolean} [purgeInvisibleChars]
|
|
4
|
+
* @property {boolean} [purgeEmojis]
|
|
5
|
+
* @property {boolean} [nukeControls]
|
|
6
|
+
* @property {boolean} [keyboardOnlyFilter]
|
|
7
|
+
* @property {boolean} [normalizeNewlines]
|
|
8
|
+
* @property {boolean} [trimSpacesAroundNewlines]
|
|
9
|
+
* @property {boolean} [collapseNewLines]
|
|
10
|
+
* @property {boolean} [preserveParagraphs]
|
|
11
|
+
* @property {boolean} [collapseSpaces]
|
|
12
|
+
* @property {boolean} [finalTrim]
|
|
13
|
+
* @property {number} [maxLength]
|
|
14
|
+
* @property {'throw'|'truncate'|'noop'} [onMaxLength]
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Summons a customized sanctifier function with pre-bound booleans.
|
|
18
|
+
*
|
|
19
|
+
* Accepts full flag names and returns a text-cleaning function.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object} [defaultOptions={}]
|
|
22
|
+
* @param {boolean} [defaultOptions.purgeInvisibleChars]
|
|
23
|
+
* @param {boolean} [defaultOptions.purgeEmojis]
|
|
24
|
+
* @param {boolean} [defaultOptions.nukeControls]
|
|
25
|
+
* @param {boolean} [defaultOptions.keyboardOnlyFilter]
|
|
26
|
+
* @param {boolean} [defaultOptions.normalizeNewlines]
|
|
27
|
+
* @param {boolean} [defaultOptions.trimSpacesAroundNewlines]
|
|
28
|
+
* @param {boolean} [defaultOptions.collapseNewLines]
|
|
29
|
+
* @param {boolean} [defaultOptions.preserveParagraphs]
|
|
30
|
+
* @param {boolean} [defaultOptions.collapseSpaces]
|
|
31
|
+
* @param {boolean} [defaultOptions.finalTrim]
|
|
32
|
+
* @param {number} [defaultOptions.maxLength=Infinity] - Hard input length cap (UTF-16 code units).
|
|
33
|
+
* @param {'throw' | 'truncate' | 'noop'} [defaultOptions.onMaxLength='throw'] - Behavior when input exceeds maxLength.
|
|
34
|
+
* @returns {(text: string) => string}
|
|
35
|
+
*/
|
|
36
|
+
export function summonSanctifier(defaultOptions?: {
|
|
37
|
+
purgeInvisibleChars?: boolean;
|
|
38
|
+
purgeEmojis?: boolean;
|
|
39
|
+
nukeControls?: boolean;
|
|
40
|
+
keyboardOnlyFilter?: boolean;
|
|
41
|
+
normalizeNewlines?: boolean;
|
|
42
|
+
trimSpacesAroundNewlines?: boolean;
|
|
43
|
+
collapseNewLines?: boolean;
|
|
44
|
+
preserveParagraphs?: boolean;
|
|
45
|
+
collapseSpaces?: boolean;
|
|
46
|
+
finalTrim?: boolean;
|
|
47
|
+
maxLength?: number;
|
|
48
|
+
onMaxLength?: "throw" | "truncate" | "noop";
|
|
49
|
+
}): (text: string) => string;
|
|
50
|
+
export namespace summonSanctifier {
|
|
51
|
+
/**
|
|
52
|
+
* Strict sanitizer:
|
|
53
|
+
* - Purge emojis
|
|
54
|
+
* - Collapse all newlines
|
|
55
|
+
* - Collapse spaces
|
|
56
|
+
* - Nuke control characters
|
|
57
|
+
*/
|
|
58
|
+
/** @param {string} text @returns {string} */
|
|
59
|
+
function strict(text: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Loose sanitizer:
|
|
62
|
+
* - Collapse spaces
|
|
63
|
+
* - Preserve paragraphs
|
|
64
|
+
* - Normalize newlines
|
|
65
|
+
*/
|
|
66
|
+
/** @param {string} text @returns {string} */
|
|
67
|
+
function loose(text: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Keyboard-only (with emojis):
|
|
70
|
+
* - Keeps emojis and printable ASCII
|
|
71
|
+
* - Strips non-standard characters
|
|
72
|
+
* - Normalizes typographic trash
|
|
73
|
+
*/
|
|
74
|
+
/** @param {string} text @returns {string} */
|
|
75
|
+
function keyboardOnlyEmoji(text: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Keyboard-only (strict):
|
|
78
|
+
* - Removes emojis
|
|
79
|
+
* - Collapses all whitespace
|
|
80
|
+
* - Restricts to printable ASCII only
|
|
81
|
+
*/
|
|
82
|
+
/** @param {string} text @returns {string} */
|
|
83
|
+
function keyboardOnly(text: string): string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Text Sanctifier
|
|
87
|
+
*
|
|
88
|
+
* Brutal text normalizer and invisible trash scrubber,
|
|
89
|
+
* configurable to kill whatever ghosts you want dead.
|
|
90
|
+
*
|
|
91
|
+
* ⚠️ Note: This is plain-text normalization/filtering — not an HTML/XSS sanitizer.
|
|
92
|
+
*
|
|
93
|
+
* @param {string} text
|
|
94
|
+
* @param {boolean} [purgeInvisibleChars=false] - Remove ZWSP, NBSP, bidi, etc.
|
|
95
|
+
* @param {boolean} [purgeEmojis=false] - Remove emoji characters entirely.
|
|
96
|
+
* @param {boolean} [nukeControls=false] - Remove non-whitespace control characters.
|
|
97
|
+
* @param {boolean} [keyboardOnlyFilter=false] - Keep printable ASCII + full emoji sequences only (drops other Unicode).
|
|
98
|
+
* @param {boolean} [normalizeNewlines=false] - Convert all newlines to `\n`.
|
|
99
|
+
* @param {boolean} [trimSpacesAroundNewlines=false] - Remove spaces/tabs around newlines.
|
|
100
|
+
* @param {boolean} [collapseNewLines=false] - Collapse `\n` runs (optionally preserve paragraphs).
|
|
101
|
+
* @param {boolean} [preserveParagraphs=false] - Preserve paragraph breaks when collapsing newlines.
|
|
102
|
+
* @param {boolean} [collapseSpaces=false] - Collapse multiple spaces into one.
|
|
103
|
+
* @param {boolean} [finalTrim=false] - `.trim()` the final output (head/tail).
|
|
104
|
+
* @param {number} [maxLength=Infinity] - Hard input length cap (UTF-16 code units via `text.length`).
|
|
105
|
+
* @param {'throw'|'truncate'|'noop'} [onMaxLength='throw'] - Behavior when `text.length` exceeds `maxLength`:
|
|
106
|
+
* - `'throw'`: throw a `RangeError`
|
|
107
|
+
* - `'truncate'`: slice to `maxLength` before processing
|
|
108
|
+
* - `'noop'`: return the original input unchanged (skips processing)
|
|
109
|
+
* @returns {string}
|
|
110
|
+
* @throws {TypeError} If `text` is not a string.
|
|
111
|
+
* @throws {RangeError} If input exceeds `maxLength` and `onMaxLength` is `'throw'`.
|
|
112
|
+
*/
|
|
113
|
+
export function sanctifyText(text: string, purgeInvisibleChars?: boolean, purgeEmojis?: boolean, nukeControls?: boolean, keyboardOnlyFilter?: boolean, normalizeNewlines?: boolean, trimSpacesAroundNewlines?: boolean, collapseNewLines?: boolean, preserveParagraphs?: boolean, collapseSpaces?: boolean, finalTrim?: boolean, maxLength?: number, onMaxLength?: "throw" | "truncate" | "noop"): string;
|
|
114
|
+
/**
|
|
115
|
+
* Normalizes typographic Unicode punctuation into ASCII equivalents.
|
|
116
|
+
* @param {string} text
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
export function normalizeTypographicJank(text: string): string;
|
|
120
|
+
/**
|
|
121
|
+
* Purges invisible Unicode "trash" characters and removes them.
|
|
122
|
+
*
|
|
123
|
+
* Targets:
|
|
124
|
+
* - Non-breaking spaces (\u00A0)
|
|
125
|
+
* - Zero-width spaces and miscellaneous Unicode spaces (\u2000–\u200D, \u202F, \u2060, \u3000, \uFEFF)
|
|
126
|
+
* - Left-to-right/right-to-left markers and overrides (\u200E, \u200F, \u202A–\u202E)
|
|
127
|
+
*
|
|
128
|
+
* @param {string} text
|
|
129
|
+
* @returns {string}
|
|
130
|
+
*/
|
|
131
|
+
export const INVISIBLE_TRASH_REGEX: RegExp;
|
|
132
|
+
/**
|
|
133
|
+
* Matches any character that is NOT:
|
|
134
|
+
* - Printable ASCII (U+0020–U+007E)
|
|
135
|
+
* - Newline characters: \n (LF), \r (CR)
|
|
136
|
+
* This allows for \n, \r, and \r\n line endings.
|
|
137
|
+
*/
|
|
138
|
+
export const ASCII_KEYBOARD_SAFE_REGEX: RegExp;
|
|
139
|
+
/** @type {RegExp} */
|
|
140
|
+
export let EMOJI_REGEX: RegExp;
|
|
141
|
+
/**
|
|
142
|
+
* Nukes hidden control characters that are invisible and often dangerous.
|
|
143
|
+
* (Excludes necessary whitespace like \n and \t.)
|
|
144
|
+
*
|
|
145
|
+
* Control characters nuked:
|
|
146
|
+
* - ASCII control range (0x00-0x1F, 0x7F)
|
|
147
|
+
* - Unicode control range (0x80-0x9F)
|
|
148
|
+
* - RTL/LTR markers (U+200E, U+200F, U+202A–U+202E)
|
|
149
|
+
*
|
|
150
|
+
* @param {string} text
|
|
151
|
+
* @returns {string}
|
|
152
|
+
*/
|
|
153
|
+
export const CONTROL_CHARS_REGEX: RegExp;
|
|
154
|
+
export type SanctifyOptions = {
|
|
155
|
+
purgeInvisibleChars?: boolean;
|
|
156
|
+
purgeEmojis?: boolean;
|
|
157
|
+
nukeControls?: boolean;
|
|
158
|
+
keyboardOnlyFilter?: boolean;
|
|
159
|
+
normalizeNewlines?: boolean;
|
|
160
|
+
trimSpacesAroundNewlines?: boolean;
|
|
161
|
+
collapseNewLines?: boolean;
|
|
162
|
+
preserveParagraphs?: boolean;
|
|
163
|
+
collapseSpaces?: boolean;
|
|
164
|
+
finalTrim?: boolean;
|
|
165
|
+
maxLength?: number;
|
|
166
|
+
onMaxLength?: "throw" | "truncate" | "noop";
|
|
167
|
+
};
|