inputs-sanitize 1.0.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joan Lozano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,423 @@
1
+ # inputs-sanitize 🛡️
2
+
3
+ A lightweight, zero-dependency utility to sanitize and filter input strings. Perfect for React, Vue, Angular, Svelte and other JavaScript/TypeScript frameworks.
4
+
5
+ **Supports both CommonJS and ES Modules (ESM)** for maximum compatibility with npm, yarn, and pnpm.
6
+
7
+ ## Features
8
+
9
+ - ✅ **Multiple sanitization modes** (text, numbers, alphanumeric, safe)
10
+ - ✅ **TypeScript support** with full type definitions
11
+ - ✅ **Framework agnostic** - works with React, Vue, Angular, Svelte, etc.
12
+ - ✅ **Dual module support** - CommonJS & ESM
13
+ - ✅ **Zero dependencies**
14
+ - ✅ **Small bundle size** (~1KB minified)
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ # using npm
20
+ npm install inputs-sanitize
21
+
22
+ # using yarn
23
+ yarn add inputs-sanitize
24
+
25
+ # using pnpm
26
+ pnpm add inputs-sanitize
27
+ ```
28
+
29
+ ## API
30
+
31
+ ### `sanitize(value: string, mode?: SanitizeMode, options?: NumberOptions): string`
32
+
33
+ Sanitizes input strings based on the specified mode.
34
+
35
+ #### SanitizeMode Types
36
+
37
+ **`"text"`** - Letras con acentos, espacios, puntos y comas
38
+ - ✓ Permite: `a-z`, `A-Z`, `áéíóúÁÉÍÓÚñÑ`, espacios, `.`, `,`
39
+ - ✗ Elimina: números, caracteres especiales
40
+ - **Uso:** Nombres, direcciones, descripciones
41
+ - **Ejemplo:** `"José María, México."` → `"José María, México."`
42
+
43
+ **`"numbers"`** - Solo números con soporte decimal y negativo opcional
44
+ - ✓ Permite: `0-9`, `.` (decimal si `allowDecimal=true`), `-` (negativo si `allowNegative=true`)
45
+ - ✗ Elimina: letras, caracteres especiales
46
+ - **Opciones:** `allowDecimal` (default: true), `allowNegative` (default: true)
47
+ - **Uso:** Precios, cantidades, edades, códigos numéricos
48
+ - **Ejemplo:**
49
+ - `"$99.99"` → `"99.99"`
50
+ - `"-42.5"` (con opciones) → `"-42.5"`
51
+ - `"-42.5"` (sin negativos) → `"42.5"`
52
+
53
+ **`"alphanumeric"`** - Combinación de TEXT + NUMBERS
54
+ - ✓ Permite: `a-z`, `A-Z`, `áéíóúÁÉÍÓÚñÑ`, `0-9`, espacios, `.`, `,`
55
+ - ✗ Elimina: caracteres especiales (@ ! # $ % etc.)
56
+ - **Uso:** Direcciones con números, nombres con códigos, descripciones con valores
57
+ - **Ejemplo:** `"Calle 123, Apto 45, México."` → `"Calle 123, Apto 45, México."`
58
+
59
+ **`"safe"`** - Solo letras, números y espacios (sin acentos)
60
+ - ✓ Permite: `a-z`, `A-Z`, `0-9`, espacios
61
+ - ✗ Elimina: acentos, puntos, comas, caracteres especiales
62
+ - **Uso:** Usernames, códigos, referencias
63
+ - **Ejemplo:** `"josé_user@123"` → `"jos user123"`
64
+
65
+ **`"all"`** - Sin cambios (valor por defecto)
66
+ - ✓ Permite: Todo
67
+ - **Uso:** Cuando no necesitas filtrado
68
+ - **Ejemplo:** `"José: $123.45!"` → `"José: $123.45!"`
69
+
70
+ #### NumberOptions
71
+
72
+ ```typescript
73
+ interface NumberOptions {
74
+ allowDecimal?: boolean; // default: true
75
+ allowNegative?: boolean; // default: true
76
+ }
77
+ ```
78
+
79
+ Estas opciones **solo aplican al modo `"numbers"`**:
80
+
81
+ - **`allowDecimal`**: Permite caracteres de punto (`.`) para números decimales
82
+ - `true` (default): `"99.99"` es válido
83
+ - `false`: `"99.99"` → `"9999"`
84
+
85
+ - **`allowNegative`**: Permite caracteres de guion (`-`) para números negativos
86
+ - `true` (default): `"-42"` es válido
87
+ - `false`: `"-42"` → `"42"`
88
+
89
+ ### Input Type Handling
90
+
91
+ La función maneja automáticamente diferentes tipos de entrada:
92
+
93
+ | Input | Tipo | Comportamiento |
94
+ |-------|------|----------------|
95
+ | `"José María"` | string | ✅ Se sanitiza normalmente |
96
+ | `123` | number | ✅ Se convierte a string |
97
+ | `null` | null | ✅ Devuelve `""` (vacío) |
98
+ | `undefined` | undefined | ✅ Devuelve `""` (vacío) |
99
+ | `[1, 2, 3]` | array | ✅ Rechaza, devuelve `""` |
100
+ | `{name: 'José'}` | object | ✅ Rechaza, devuelve `""` |
101
+ | `() => {}` | function | ✅ Rechaza, devuelve `""` |
102
+
103
+ **Notas importantes:**
104
+ - ✅ Solo acepta `string` y `number` como valores válidos
105
+ - ✅ Automáticamente trimea espacios en blanco
106
+ - ✅ Rechaza objetos, arrays y funciones (devuelve vacío en lugar de error)
107
+ - ✅ Nunca lanza excepciones
108
+
109
+ ## Usage Examples
110
+
111
+ ### React
112
+
113
+ ```jsx
114
+ import { sanitize } from 'inputs-sanitize';
115
+ import { useState } from 'react';
116
+
117
+ export default function MyComponent() {
118
+ const [email, setEmail] = useState('');
119
+ const [username, setUsername] = useState('');
120
+
121
+ const handleEmailChange = (e) => {
122
+ const sanitized = sanitize(e.target.value, 'safe');
123
+ setEmail(sanitized);
124
+ };
125
+
126
+ const handleUsernameChange = (e) => {
127
+ const sanitized = sanitize(e.target.value, 'alphanumeric');
128
+ setUsername(sanitized);
129
+ };
130
+
131
+ return (
132
+ <div>
133
+ <input
134
+ type="email"
135
+ value={email}
136
+ onChange={handleEmailChange}
137
+ placeholder="Email"
138
+ />
139
+ <input
140
+ type="text"
141
+ value={username}
142
+ onChange={handleUsernameChange}
143
+ placeholder="Username"
144
+ />
145
+ </div>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ### Vue 3
151
+
152
+ ```vue
153
+ <template>
154
+ <div>
155
+ <input
156
+ v-model="email"
157
+ @input="email = sanitize($event.target.value, 'safe')"
158
+ type="email"
159
+ placeholder="Email"
160
+ />
161
+ <input
162
+ v-model="amount"
163
+ @input="amount = sanitize($event.target.value, 'numbers', { allowDecimal: true })"
164
+ type="number"
165
+ placeholder="Amount"
166
+ />
167
+ </div>
168
+ </template>
169
+
170
+ <script setup>
171
+ import { ref } from 'vue';
172
+ import { sanitize } from 'inputs-sanitize';
173
+
174
+ const email = ref('');
175
+ const amount = ref('');
176
+ </script>
177
+ ```
178
+
179
+ ### Vue 2
180
+
181
+ ```vue
182
+ <template>
183
+ <div>
184
+ <input
185
+ v-model="name"
186
+ @input="handleNameChange"
187
+ type="text"
188
+ placeholder="Full Name"
189
+ />
190
+ <input
191
+ v-model="phone"
192
+ @input="handlePhoneChange"
193
+ type="tel"
194
+ placeholder="Phone (numbers only)"
195
+ />
196
+ </div>
197
+ </template>
198
+
199
+ <script>
200
+ import { sanitize } from 'inputs-sanitize';
201
+
202
+ export default {
203
+ data() {
204
+ return {
205
+ name: '',
206
+ phone: ''
207
+ };
208
+ },
209
+ methods: {
210
+ handleNameChange() {
211
+ this.name = sanitize(this.name, 'text');
212
+ },
213
+ handlePhoneChange() {
214
+ this.phone = sanitize(this.phone, 'numbers', { allowNegative: false });
215
+ }
216
+ }
217
+ };
218
+ </script>
219
+ ```
220
+
221
+ ### Vanilla JavaScript
222
+
223
+ ```javascript
224
+ import { sanitize } from 'inputs-sanitize';
225
+
226
+ // CommonJS
227
+ // const { sanitize } = require('inputs-sanitize');
228
+
229
+ const input = document.getElementById('myInput');
230
+ input.addEventListener('input', (e) => {
231
+ e.target.value = sanitize(e.target.value, 'alphanumeric');
232
+ });
233
+ ```
234
+
235
+ ## Examples by Mode
236
+
237
+ ### Text Mode
238
+
239
+ ```typescript
240
+ import { sanitize } from 'inputs-sanitize';
241
+
242
+ // Permitir: letras (acentos), espacios, puntos, comas
243
+ // Eliminar: números, caracteres especiales
244
+
245
+ sanitize('José María, México 123!', 'text');
246
+ // → "José María, México "
247
+
248
+ sanitize('Dr. Juan Pérez, Médico.', 'text');
249
+ // → "Dr. Juan Pérez, Médico."
250
+ ```
251
+
252
+ ### Numbers Mode
253
+
254
+ ```typescript
255
+ // Permitir: números, decimales (opcional), negativos (opcional)
256
+ // Eliminar: letras, caracteres especiales
257
+
258
+ // Con decimales y negativos (default)
259
+ sanitize('Price: $99.99', 'numbers');
260
+ // → "99.99"
261
+
262
+ sanitize('Temperature: -15.5°C', 'numbers');
263
+ // → "-15.5"
264
+
265
+ // Sin decimales
266
+ sanitize('$99.99', 'numbers', { allowDecimal: false });
267
+ // → "9999"
268
+
269
+ // Sin negativos
270
+ sanitize('-42.5', 'numbers', { allowNegative: false });
271
+ // → "42.5"
272
+
273
+ // Sin ambos
274
+ sanitize('-$99.99', 'numbers', { allowDecimal: false, allowNegative: false });
275
+ // → "9999"
276
+ ```
277
+
278
+ ### Alphanumeric Mode
279
+
280
+ ```typescript
281
+ // Permitir: letras (acentos), números, espacios, puntos, comas
282
+ // Eliminar: caracteres especiales (@!#$%^&*)
283
+
284
+ sanitize('Calle Principal 123, Apto 4A.', 'alphanumeric');
285
+ // → "Calle Principal 123, Apto 4A."
286
+
287
+ sanitize('José María: $123.45 @user!', 'alphanumeric');
288
+ // → "José María 123.45 user"
289
+
290
+ sanitize('Order #12345, Amount: $99.99, Client: María-José', 'alphanumeric');
291
+ // → "Order 12345, Amount 99.99, Client MaríaJosé"
292
+ ```
293
+
294
+ ### Safe Mode
295
+
296
+ ```typescript
297
+ // Permitir: letras (sin acentos), números, espacios
298
+ // Eliminar: acentos, puntos, comas, caracteres especiales
299
+
300
+ sanitize('<script>alert("xss")</script>', 'safe');
301
+ // → "scriptalertxssscript"
302
+
303
+ sanitize('user@email.com', 'safe');
304
+ // → "useremailcom"
305
+
306
+ sanitize('José_123@domain', 'safe');
307
+ // → "Jos 123domain"
308
+ ```
309
+
310
+ ### All Mode
311
+
312
+ ```typescript
313
+ // Permitir: todo (sin cambios)
314
+
315
+ sanitize('José María: $123.45 @user!', 'all');
316
+ // → "José María: $123.45 @user!"
317
+
318
+ sanitize('<script>dangerous</script>', 'all');
319
+ // → "<script>dangerous</script>"
320
+ ```
321
+
322
+ ## Comparison Table
323
+
324
+ ### Character Support by Mode
325
+
326
+ | Carácter | text | numbers | alphanumeric | safe | all |
327
+ |----------|------|---------|--------------|------|-----|
328
+ | **Letras** (a-z, A-Z) | ✓ | ✗ | ✓ | ✓ | ✓ |
329
+ | **Acentuadas** (á, é, í, ó, ú, ñ) | ✓ | ✗ | ✓ | ✗ | ✓ |
330
+ | **Números** (0-9) | ✗ | ✓ | ✓ | ✓ | ✓ |
331
+ | **Punto** (.) | ✓ | ✓* | ✓ | ✗ | ✓ |
332
+ | **Coma** (,) | ✓ | ✗ | ✓ | ✗ | ✓ |
333
+ | **Guion** (-) | ✗ | ✓* | ✗ | ✗ | ✓ |
334
+ | **Espacio** | ✓ | ✗ | ✓ | ✓ | ✓ |
335
+ | **Especiales** (@!#$%^&*) | ✗ | ✗ | ✗ | ✗ | ✓ |
336
+
337
+ *`numbers mode`: punto (.) = decimal si `allowDecimal=true`, guion (-) = negativo si `allowNegative=true`
338
+
339
+ ## Framework Integration
340
+
341
+ ### TypeScript with React
342
+
343
+ ```typescript
344
+ import { sanitize, SanitizeMode } from 'inputs-sanitize';
345
+ import { ChangeEvent, useState } from 'react';
346
+
347
+ interface FormData {
348
+ username: string;
349
+ amount: string;
350
+ description: string;
351
+ }
352
+
353
+ export function MyForm() {
354
+ const [data, setData] = useState<FormData>({
355
+ username: '',
356
+ amount: '',
357
+ description: ''
358
+ });
359
+
360
+ const handleChange = (
361
+ e: ChangeEvent<HTMLInputElement>,
362
+ mode: SanitizeMode
363
+ ) => {
364
+ const { name, value } = e.target;
365
+ setData(prev => ({
366
+ ...prev,
367
+ [name]: sanitize(value, mode)
368
+ }));
369
+ };
370
+
371
+ return (
372
+ <form>
373
+ <input
374
+ name="username"
375
+ value={data.username}
376
+ onChange={(e) => handleChange(e, 'alphanumeric')}
377
+ placeholder="Username"
378
+ />
379
+ <input
380
+ name="amount"
381
+ value={data.amount}
382
+ onChange={(e) => handleChange(e, 'numbers')}
383
+ placeholder="Amount"
384
+ />
385
+ <textarea
386
+ name="description"
387
+ value={data.description}
388
+ onChange={(e) =>
389
+ setData(prev => ({
390
+ ...prev,
391
+ description: sanitize(e.target.value, 'safe')
392
+ }))
393
+ }
394
+ placeholder="Description"
395
+ />
396
+ </form>
397
+ );
398
+ }
399
+ ```
400
+
401
+ ## Package Compatibility
402
+
403
+ | Package Manager | Support |
404
+ |-----------------|---------|
405
+ | npm | ✅ Yes |
406
+ | yarn | ✅ Yes |
407
+ | pnpm | ✅ Yes |
408
+ | Node.js | ✅ 14+ |
409
+ | Browser ES2020+ | ✅ Yes |
410
+
411
+ ## Module Formats
412
+
413
+ This package supports both module formats:
414
+
415
+ - **CommonJS** (`dist/cjs/index.js`) - for Node.js and older build tools
416
+ - **ESM** (`dist/esm/index.js`) - for modern applications and bundlers
417
+
418
+ The correct format is automatically selected based on your environment.
419
+
420
+ ## License
421
+
422
+ MIT
423
+
@@ -0,0 +1,3 @@
1
+ export { sanitize } from "./sanitize";
2
+ export type { SanitizeMode, NumberOptions } from "./sanitize";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitize = void 0;
4
+ var sanitize_1 = require("./sanitize");
5
+ Object.defineProperty(exports, "sanitize", { enumerable: true, get: function () { return sanitize_1.sanitize; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA"}
@@ -0,0 +1,7 @@
1
+ export type SanitizeMode = "text" | "numbers" | "alphanumeric" | "safe" | "all";
2
+ export interface NumberOptions {
3
+ allowDecimal?: boolean;
4
+ allowNegative?: boolean;
5
+ }
6
+ export declare function sanitize(value: string | number | null | undefined | any, mode?: SanitizeMode, options?: NumberOptions): string;
7
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAClB,MAAM,GACN,SAAS,GACT,cAAc,GACd,MAAM,GACN,KAAK,CAAC;AAEZ,MAAM,WAAW,aAAa;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,QAAQ,CACpB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,EAC/C,IAAI,GAAE,YAAoB,EAC1B,OAAO,GAAE,aAAkB,GAC5B,MAAM,CA8DR"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitize = sanitize;
4
+ function sanitize(value, mode = "all", options = {}) {
5
+ // Rechazar valores null y undefined
6
+ if (value === null || value === undefined) {
7
+ return "";
8
+ }
9
+ // Solo aceptar string y number
10
+ // Rechazar objetos, arrays, funciones, símbolos, etc.
11
+ if (typeof value !== 'string' && typeof value !== 'number') {
12
+ return "";
13
+ }
14
+ // Convertir a string
15
+ let stringValue = String(value).trim();
16
+ if (!stringValue)
17
+ return "";
18
+ switch (mode) {
19
+ case "text":
20
+ return stringValue.replace(/[^a-zA-ZáéíóúÁÉÍÓÚñÑ\s.,]/g, "");
21
+ case "numbers": {
22
+ const { allowDecimal = true, allowNegative = true } = options;
23
+ let result = stringValue;
24
+ // quitar notación científica
25
+ result = result.replace(/[eE]/g, "");
26
+ // solo números básicos
27
+ result = result.replace(/[^0-9.\-]/g, "");
28
+ if (!allowDecimal) {
29
+ result = result.replace(/\./g, "");
30
+ }
31
+ else {
32
+ const parts = result.split(".");
33
+ if (parts.length > 2) {
34
+ result = parts[0] + "." + parts.slice(1).join("");
35
+ }
36
+ }
37
+ if (!allowNegative) {
38
+ result = result.replace(/-/g, "");
39
+ }
40
+ else {
41
+ result = result.replace(/(?!^)-/g, "");
42
+ }
43
+ return result;
44
+ }
45
+ case "alphanumeric":
46
+ // Combina text + numbers: letras (con acentos), números, espacios, puntos, comas
47
+ return stringValue.replace(/[^a-zA-ZáéíóúÁÉÍÓÚñÑ0-9\s.,]/g, "");
48
+ case "safe":
49
+ // Solo letras, números y espacios
50
+ return stringValue.replace(/[^a-zA-Z0-9\s]/g, "");
51
+ case "all":
52
+ default:
53
+ return stringValue;
54
+ }
55
+ }
56
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":";;AAYA,4BAkEC;AAlED,SAAgB,QAAQ,CACpB,KAA+C,EAC/C,OAAqB,KAAK,EAC1B,UAAyB,EAAE;IAE3B,oCAAoC;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACd,CAAC;IAED,+BAA+B;IAC/B,sDAAsD;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACzD,OAAO,EAAE,CAAC;IACd,CAAC;IAED,qBAAqB;IACrB,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,MAAM;YACP,OAAO,WAAW,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAEjE,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;YAE9D,IAAI,MAAM,GAAG,WAAW,CAAC;YAEzB,6BAA6B;YAC7B,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAErC,uBAAuB;YACvB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAE1C,IAAI,CAAC,YAAY,EAAE,CAAC;gBAChB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnB,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtD,CAAC;YACL,CAAC;YAED,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,KAAK,cAAc;YACf,iFAAiF;YACjF,OAAO,WAAW,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;QAEpE,KAAK,MAAM;YACP,kCAAkC;YAClC,OAAO,WAAW,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAEtD,KAAK,KAAK,CAAC;QACX;YACI,OAAO,WAAW,CAAC;IAC3B,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { sanitize } from "./sanitize";
2
+ export type { SanitizeMode, NumberOptions } from "./sanitize";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { sanitize } from "./sanitize";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type SanitizeMode = "text" | "numbers" | "alphanumeric" | "safe" | "all";
2
+ export interface NumberOptions {
3
+ allowDecimal?: boolean;
4
+ allowNegative?: boolean;
5
+ }
6
+ export declare function sanitize(value: string | number | null | undefined | any, mode?: SanitizeMode, options?: NumberOptions): string;
7
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAClB,MAAM,GACN,SAAS,GACT,cAAc,GACd,MAAM,GACN,KAAK,CAAC;AAEZ,MAAM,WAAW,aAAa;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,QAAQ,CACpB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,EAC/C,IAAI,GAAE,YAAoB,EAC1B,OAAO,GAAE,aAAkB,GAC5B,MAAM,CA8DR"}
@@ -0,0 +1,53 @@
1
+ export function sanitize(value, mode = "all", options = {}) {
2
+ // Rechazar valores null y undefined
3
+ if (value === null || value === undefined) {
4
+ return "";
5
+ }
6
+ // Solo aceptar string y number
7
+ // Rechazar objetos, arrays, funciones, símbolos, etc.
8
+ if (typeof value !== 'string' && typeof value !== 'number') {
9
+ return "";
10
+ }
11
+ // Convertir a string
12
+ let stringValue = String(value).trim();
13
+ if (!stringValue)
14
+ return "";
15
+ switch (mode) {
16
+ case "text":
17
+ return stringValue.replace(/[^a-zA-ZáéíóúÁÉÍÓÚñÑ\s.,]/g, "");
18
+ case "numbers": {
19
+ const { allowDecimal = true, allowNegative = true } = options;
20
+ let result = stringValue;
21
+ // quitar notación científica
22
+ result = result.replace(/[eE]/g, "");
23
+ // solo números básicos
24
+ result = result.replace(/[^0-9.\-]/g, "");
25
+ if (!allowDecimal) {
26
+ result = result.replace(/\./g, "");
27
+ }
28
+ else {
29
+ const parts = result.split(".");
30
+ if (parts.length > 2) {
31
+ result = parts[0] + "." + parts.slice(1).join("");
32
+ }
33
+ }
34
+ if (!allowNegative) {
35
+ result = result.replace(/-/g, "");
36
+ }
37
+ else {
38
+ result = result.replace(/(?!^)-/g, "");
39
+ }
40
+ return result;
41
+ }
42
+ case "alphanumeric":
43
+ // Combina text + numbers: letras (con acentos), números, espacios, puntos, comas
44
+ return stringValue.replace(/[^a-zA-ZáéíóúÁÉÍÓÚñÑ0-9\s.,]/g, "");
45
+ case "safe":
46
+ // Solo letras, números y espacios
47
+ return stringValue.replace(/[^a-zA-Z0-9\s]/g, "");
48
+ case "all":
49
+ default:
50
+ return stringValue;
51
+ }
52
+ }
53
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,QAAQ,CACpB,KAA+C,EAC/C,OAAqB,KAAK,EAC1B,UAAyB,EAAE;IAE3B,oCAAoC;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACd,CAAC;IAED,+BAA+B;IAC/B,sDAAsD;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACzD,OAAO,EAAE,CAAC;IACd,CAAC;IAED,qBAAqB;IACrB,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,MAAM;YACP,OAAO,WAAW,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAEjE,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;YAE9D,IAAI,MAAM,GAAG,WAAW,CAAC;YAEzB,6BAA6B;YAC7B,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAErC,uBAAuB;YACvB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAE1C,IAAI,CAAC,YAAY,EAAE,CAAC;gBAChB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnB,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtD,CAAC;YACL,CAAC;YAED,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC3C,CAAC;YAED,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,KAAK,cAAc;YACf,iFAAiF;YACjF,OAAO,WAAW,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;QAEpE,KAAK,MAAM;YACP,kCAAkC;YAClC,OAAO,WAAW,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAEtD,KAAK,KAAK,CAAC;QACX;YACI,OAAO,WAAW,CAAC;IAC3B,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "inputs-sanitize",
3
+ "version": "1.0.0",
4
+ "description": "Lightweight utility to sanitize and filter input strings for React, Vue and other frameworks",
5
+ "main": "dist/cjs/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.js",
12
+ "types": "./dist/esm/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "npm run build:cjs && npm run build:esm",
20
+ "build:cjs": "tsc --module commonjs --outDir dist/cjs",
21
+ "build:esm": "tsc --module esnext --outDir dist/esm",
22
+ "prepublishOnly": "npm run build",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "keywords": [
26
+ "sanitize",
27
+ "input",
28
+ "validation",
29
+ "filter",
30
+ "react",
31
+ "vue",
32
+ "angular",
33
+ "svelte"
34
+ ],
35
+ "author": "Joan Lozano",
36
+ "license": "MIT",
37
+ "packageManager": "pnpm@10.15.0",
38
+ "devDependencies": {
39
+ "typescript": "^5.5.0"
40
+ }
41
+ }