html-escaper
A tiny, zero-dependency utility that safely escapes and unescapes HTML entities in JavaScript strings.
Repository Health
Technical Analysis
html-escaper is a minimal JavaScript module for converting the five HTML-sensitive characters (&, <, >, ', ") to and from their entity forms. Rather than chaining multiple .replace() calls character-by-character — a common anti-pattern that can produce double-encoding bugs and even reopen XSS holes when unescaping — it performs a single regex pass paired with a plain-object lookup map, so every character is matched and replaced in one traversal of the string.
The package ships as ESM-only from version 3 onward, with a generated CommonJS build for compatibility and a minified UMD bundle for direct browser use via <script> tags. It has no runtime dependencies, a tiny footprint, and an API surface of exactly two functions: escape and unescape.
What You Get
- An
escape(string)function that converts&,<,>,', and"to their HTML entity equivalents in one pass - An
unescape(string)function that reverses the process, correctly handling both named (&) and numeric (&) entity forms - Zero runtime dependencies and a sub-1KB minified footprint
- Dual ESM/CJS builds plus a UMD
min.jsbundle for direct browser<script>usage
Common Use Cases
- Escaping user-supplied text before injecting it into HTML templates to prevent XSS
- Sanitizing values before setting
innerHTMLor building HTML strings on the server - Round-tripping content that was previously escaped for storage or transport, via
unescape - Lightweight alternative to larger sanitization libraries when only entity escaping is needed, not full HTML parsing
Under The Hood
Architecture
The entire module lives in a single index.js file (mirrored as esm/index.js for the ESM build) with no internal layering: two plain lookup objects (esca for escaping, unes for unescaping) map each character or entity to its counterpart, and String.prototype.replace is invoked once per direction with a replacer function that looks up the match in the corresponding object. This single-pass design is the module’s entire reason for existing — the README explicitly documents the double-encoding bug that results from chaining separate .replace(/&/g,...).replace(/</g,...) calls, and the architecture is built specifically to avoid it by matching all target characters with one combined regex (/[&<>'"]/g for escaping, an alternation of entity patterns for unescaping) before any substitution happens.
Tech Stack
The package has zero runtime dependencies. Its source is authored as a native ES module (type: module in package.json) and is transformed into a CommonJS build via the ascjs dev dependency, with rollup producing a UMD bundle that uglify-es then minifies for the unpkg-served min.js. Tests run under c8 for coverage reporting, invoked via a plain node ./test/index.js — no test framework is used. CI historically ran on Travis (.travis.yml, targeting a single “stable” Node version).
Code Quality
The test suite is a single file (test/index.js) containing four console.assert calls that check escape/unescape correctness in both normal and “inverted” character order — there is no assertion library, no test runner, and console.assert does not throw or fail the process on a failed assertion, so a regression could pass silently in some environments. There are no TypeScript types shipped in the repository itself, no ESLint or Prettier configuration, and the Travis CI badge points at an integration that is no longer actively used by most projects. The source itself, however, is small, readable, and thoroughly commented with JSDoc describing exact behavior and edge cases.
What Makes It Unique
The module isn’t notable for new functionality — escaping HTML entities is a well-worn problem — but for the specific correctness argument it makes and enforces in its own implementation: the README walks through exactly how naive chained .replace() escaping and unescaping can produce double-encoded output or reopen an XSS vector, and the single-combined-regex design exists purely to close that gap. It intentionally stays minimal, referring users elsewhere (html-sloppy-escaper, he, lodash) if they need broader character coverage or more permissive input handling.
Used by 2 apps in this directory
Dub
Marketing · Analytics
The open-source link attribution platform for short links, conversion tracking, and affiliate programs — powering 100M+ clicks monthly.
Uptime Kuma
Monitoring
Self-hosted monitoring for every service you run — 23 monitor types, 95 notification channels, live dashboards, and public status pages with no vendor lock-in.