Skip to content

Commit 9625234

Browse files
authored
Add redact() function for sensitive data masking (#39)
* add redact * bump version
1 parent 13b0fb0 commit 9625234

File tree

14 files changed

+727
-113
lines changed

14 files changed

+727
-113
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.18.0] - 2025-10-01
11+
12+
### Added
13+
14+
- **New Function: `redact()`** - Redact sensitive information from text for UI/logging purposes
15+
- Built-in pattern support for SSN, credit cards, emails, and phone numbers
16+
- Multiple redaction strategies: `partial` (show last N chars) and `full` (complete masking)
17+
- Selective type redaction - choose which data types to redact
18+
- Custom pattern support with regex and replacement functions
19+
- Configurable partial length (default: 4 characters)
20+
- Smart format preservation for phone numbers (parentheses, dots, dashes)
21+
- Consistent output formatting (e.g., SSNs always use dash format)
22+
- Security notice in documentation emphasizing proper use cases
23+
- 42 comprehensive test cases covering all redaction types and edge cases
24+
- Bundle size: ~1.3KB gzipped
25+
26+
### Changed
27+
28+
- **Bundle Size** - Increased size limit from 9 KB to 9.1 KB to accommodate new redaction function
29+
- **Documentation** - Updated function count from 47 to 48 functions
30+
- **Interactive Playground** - Added `redact()` to documentation site with live examples
31+
1032
## [0.16.0] - 2025-09-22
1133

1234
### Added
@@ -407,6 +429,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
407429
- 100% test coverage for utility functions
408430
- Modern build tooling with tsup and Vitest
409431

432+
[0.18.0]: https://github.com/Zheruel/nano-string-utils/releases/tag/v0.18.0
433+
[0.16.0]: https://github.com/Zheruel/nano-string-utils/releases/tag/v0.16.0
410434
[0.13.0]: https://github.com/Zheruel/nano-string-utils/releases/tag/v0.13.0
411435
[0.12.0]: https://github.com/Zheruel/nano-string-utils/releases/tag/v0.12.0
412436
[0.11.0]: https://github.com/Zheruel/nano-string-utils/releases/tag/v0.11.0

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ nano-string slugify --help
293293

294294
## API Reference
295295

296-
The library provides 47 string utility functions organized by category. Click on any category to explore the available functions.
296+
The library provides 48 string utility functions organized by category. Click on any category to explore the available functions.
297297

298298
<details>
299299
<summary><b>🔤 Case Conversion Functions (10 functions)</b></summary>
@@ -540,7 +540,7 @@ hashString("world"); // 113318802
540540
</details>
541541

542542
<details>
543-
<summary><b>📝 Text Processing (13 functions)</b></summary>
543+
<summary><b>📝 Text Processing (14 functions)</b></summary>
544544

545545
### Text Processing
546546

@@ -566,6 +566,33 @@ sanitize("javascript:alert(1)"); // ''
566566
sanitize("<div onclick='alert(1)'>Click</div>"); // 'Click'
567567
```
568568

569+
#### `redact(text: string, options?: RedactOptions): string`
570+
571+
Redacts sensitive information from text for UI/logging purposes. Supports SSN, credit cards, emails, and phone numbers with customizable redaction strategies.
572+
573+
**⚠️ Security Notice**: This is for UI/logging purposes to prevent accidental exposure. Not a substitute for proper data security practices or encryption.
574+
575+
```javascript
576+
// Default: redact all types with partial strategy (show last 4)
577+
redact("My SSN is 123-45-6789"); // 'My SSN is ***-**-6789'
578+
redact("Card: 4532-1234-5678-9010"); // 'Card: **** **** **** 9010'
579+
redact("Email: user@example.com"); // 'Email: use***@example.com'
580+
redact("Phone: (555) 123-4567"); // 'Phone: (***) ***-4567'
581+
582+
// Selective type redaction
583+
redact("Email: user@example.com, SSN: 123-45-6789", {
584+
types: ["email"], // Only redact emails
585+
}); // 'Email: use***@example.com, SSN: 123-45-6789'
586+
587+
// Full redaction (no partial reveal)
588+
redact("SSN: 123-45-6789", { strategy: "full" }); // 'SSN: ***-**-****'
589+
590+
// Custom patterns
591+
redact("Secret: ABC-123", {
592+
customPatterns: [{ pattern: /[A-Z]{3}-\d{3}/g, replacement: "[REDACTED]" }],
593+
}); // 'Secret: [REDACTED]'
594+
```
595+
569596
#### `escapeHtml(str: string): string`
570597

571598
Escapes HTML special characters.
@@ -1406,6 +1433,7 @@ Each utility is optimized to be as small as possible:
14061433
| truncate | ~150 bytes |
14071434
| stripHtml | ~120 bytes |
14081435
| sanitize | ~1.2 KB |
1436+
| redact | ~1.3 KB |
14091437
| escapeHtml | ~180 bytes |
14101438
| excerpt | ~220 bytes |
14111439
| randomString | ~200 bytes |

benchmarks/all-functions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[
22
"camelCase",
33
"capitalize",
4+
"classifyText",
45
"codePoints",
56
"constantCase",
67
"deburr",
@@ -30,8 +31,10 @@
3031
"pathCase",
3132
"pluralize",
3233
"randomString",
34+
"redact",
3335
"removeNonPrintable",
3436
"reverse",
37+
"sanitize",
3538
"sentenceCase",
3639
"singularize",
3740
"slugify",

benchmarks/bundle-size-results.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
## Overview
44

5-
- **Total Functions**: 46
6-
- **Nano Wins**: 39/46
7-
- **Average Size Reduction**: -48%
5+
- **Total Functions**: 48
6+
- **Nano Wins**: 41/48
7+
- **Average Size Reduction**: -45%
88

99
## Detailed Comparison
1010

@@ -13,39 +13,41 @@ Sizes shown are minified (gzipped). For nano-string-utils, tree-shaken size is s
1313
| Function | nano-string-utils | lodash | es-toolkit | Winner | Savings |
1414
| --------------------- | ----------------- | ------------- | ----------- | ---------- | ------- |
1515
| camelCase | 1.6KB (827B) | 8.3KB (3.4KB) | 367B (273B) | es-toolkit | -203% |
16-
| capitalize | 1.4KB (696B) | 3.7KB (1.7KB) | 97B (107B) | es-toolkit | -550% |
17-
| classifyText | 2.4KB (986B) | - | - | nano 🏆 | - |
16+
| capitalize | 1.4KB (697B) | 3.7KB (1.7KB) | 97B (107B) | es-toolkit | -551% |
17+
| classifyText | 3.1KB (1.5KB) | - | - | nano 🏆 | - |
1818
| codePoints | 1.4KB (728B) | - | - | nano 🏆 | - |
1919
| constantCase | 1.6KB (805B) | - | - | nano 🏆 | - |
20-
| deburr | 1.6KB (880B) | 4.6KB (1.8KB) | 544B (332B) | es-toolkit | -165% |
20+
| deburr | 1.6KB (879B) | 4.6KB (1.8KB) | 544B (332B) | es-toolkit | -165% |
2121
| detectScript | 2.3KB (1.1KB) | - | - | nano 🏆 | - |
2222
| diff | 1.8KB (863B) | - | - | nano 🏆 | - |
2323
| dotCase | 1.6KB (786B) | - | - | nano 🏆 | - |
2424
| escapeHtml | 1.4KB (741B) | - | - | nano 🏆 | - |
25-
| excerpt | 1.6KB (840B) | - | - | nano 🏆 | - |
25+
| excerpt | 1.6KB (841B) | - | - | nano 🏆 | - |
2626
| extractEntities | 2.3KB (1.1KB) | - | - | nano 🏆 | - |
2727
| fuzzyMatch | 2.4KB (1.2KB) | - | - | nano 🏆 | - |
2828
| graphemes | 1.5KB (759B) | - | - | nano 🏆 | - |
29-
| hashString | 1.5KB (760B) | - | - | nano 🏆 | - |
29+
| hashString | 1.5KB (761B) | - | - | nano 🏆 | - |
3030
| highlight | 1.9KB (1.0KB) | - | - | nano 🏆 | - |
3131
| humanizeList | 1.6KB (857B) | - | - | nano 🏆 | - |
3232
| isASCII | 1.4KB (721B) | - | - | nano 🏆 | - |
3333
| isEmail | 1.3KB (665B) | - | - | nano 🏆 | - |
3434
| isUrl | 1.3KB (665B) | - | - | nano 🏆 | - |
35-
| kebabCase | 1.6KB (792B) | 6.7KB (2.8KB) | 238B (197B) | es-toolkit | -302% |
35+
| kebabCase | 1.6KB (793B) | 6.7KB (2.8KB) | 238B (197B) | es-toolkit | -303% |
3636
| levenshtein | 2.0KB (1.0KB) | - | - | nano 🏆 | - |
3737
| levenshteinNormalized | 2.2KB (1.1KB) | - | - | nano 🏆 | - |
38-
| memoize | 1.8KB (929B) | - | - | nano 🏆 | - |
38+
| memoize | 1.8KB (928B) | - | - | nano 🏆 | - |
3939
| normalizeWhitespace | 1.8KB (860B) | - | - | nano 🏆 | - |
40-
| pad | 1.7KB (895B) | 5.8KB (2.6KB) | 109B (118B) | es-toolkit | -658% |
40+
| pad | 1.7KB (896B) | 5.8KB (2.6KB) | 109B (118B) | es-toolkit | -659% |
4141
| padEnd | 1.5KB (788B) | 5.7KB (2.5KB) | - | nano 🏆 | 70% |
4242
| padStart | 1.5KB (785B) | 5.7KB (2.5KB) | - | nano 🏆 | 70% |
4343
| pascalCase | 1.6KB (821B) | - | 299B (231B) | es-toolkit | -255% |
4444
| pathCase | 1.6KB (785B) | - | - | nano 🏆 | - |
4545
| pluralize | 2.2KB (1.0KB) | - | - | nano 🏆 | - |
4646
| randomString | 1.5KB (821B) | - | - | nano 🏆 | - |
47+
| redact | 2.8KB (1.3KB) | - | - | nano 🏆 | - |
4748
| removeNonPrintable | 1.7KB (918B) | - | - | nano 🏆 | - |
4849
| reverse | 1.4KB (687B) | - | - | nano 🏆 | - |
50+
| sanitize | 3.0KB (1.4KB) | - | - | nano 🏆 | - |
4951
| sentenceCase | 2.1KB (992B) | - | - | nano 🏆 | - |
5052
| singularize | 2.6KB (1.1KB) | - | - | nano 🏆 | - |
5153
| slugify | 1.3KB (667B) | - | - | nano 🏆 | - |

0 commit comments

Comments
 (0)