← Portfolio stringy-core — Architecture
stringy-core / index.js import { maskEmail } from 'stringy-core' import { _s } from 'stringy-core' named exports · tree-shakeable _s namespace · convenience object textCaseManipulation 6 functions camelCase · snakeCase · titleCase invertCase · swapCase · toAlternateCase textCleaning 4 functions trimStart · trimEnd normalizeWhitespace · removeWhitespace textFormatting 6 functions · Intl API only formatNumber · formatCurrency · formatDate formatTime · formatDateTime · formatRelativeTime textMaskingAndSecurity 5 functions maskEmail · maskPhone · maskCreditCard maskString · moderate textMetadataAndExtraction 15 regex extractors URLs · emails · hashtags · mentions · IPs HTML tags · dates · JSON strings · file paths textAnalysisAndValidation 2 functions matchesPattern · isPalindrome known bug: isPalindrome returns string not boolean textTransformations 4 functions shorten · wordWrap shuffle · removeDuplicates textSpecializedOperations 2 functions · algorithmic isBalancedBrackets (stack-based) levenshteinDistance (DP matrix) textGeneration 2 functions generateRandomString generateLoremIpsum
ESM Module "type": "module" 9 module files index.js entry point zero runtime deps Pre-commit Hooks Husky + lint-staged ESLint (code quality) Prettier (formatting) runs on every commit Jest Test Suite Babel (ESM → CJS) 50+ test cases one test per function isPalindrome bug tracked npm publish stringy-core semver versioning package.json exports tree-shakeable ESM Consumer import { maskEmail } from 'stringy-core' commit hooks pass tests pass npm install Contribution Station — stub files mark open contribution points. Each stub has a JSDoc comment describing expected behaviour and a failing Jest test ready for implementation.
Key Design Decisions
Core Philosophy
Zero runtime dependencies
stringy-core has zero runtime dependencies. All formatting (numbers, currencies, dates, relative times) uses the browser's built-in Intl API instead of pulling in date-fns or numeral. All algorithms (Levenshtein, balanced brackets) are self-contained. Nothing to audit, nothing to break.
pure functionsIntl APIzero deps
Export Design
Dual export: named + _s namespace
Two ways to import the library. Named exports (import { maskEmail }) are tree-shakeable — bundlers include only what's used. The _s namespace (import { _s }) gives a single convenience object with all 50+ functions — ideal for REPL use and quick scripts where bundle size doesn't matter.
tree-shaking_s namespaceESM
Quality Gates
Pre-commit hooks on every commit
Husky + lint-staged runs ESLint and Prettier before every commit. No malformed code reaches the repository. This was a deliberate choice over a CI-only approach — catching formatting issues locally is faster and avoids failed CI runs on trivial whitespace or style violations.
Huskylint-stagedESLintPrettier
Testing
Babel bridge — ESM source, CJS test runner
The source is native ESM but Jest runs on CJS. Babel transpiles at test time via a jest.config.js transform. This keeps the published package as clean ESM while letting Jest run without any special experimental flags. The Babel dependency is dev-only and never ships to consumers.
JestBabelESM→CJS bridge
Known Bug
isPalindrome returns string, not boolean
The current implementation returns the cleaned string instead of a boolean. The fix is one line: return cleaned === cleaned.split('').reverse().join('') — but the bug is tracked rather than silently patched, to keep it as a documented contribution opportunity in the Contribution Station.
tracked bugcontribution opportunity
Open Source Design
Contribution Station stubs
Several functions are intentionally left as stubs with detailed JSDoc comments and failing Jest tests. The stubs describe exactly what the function should do, what edge cases to handle, and what the test expects. First-time contributors have a clear task with a definition of done built in.
stubsJSDocfirst-timer friendly