stringify-entities

A small, spec-compliant encoder that serializes HTML character references, with fine-grained control over named, decimal, and hexadecimal output formats.

Library
npm
v4.0.4
20stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
27/100Needs Attention
Development Activity0
Maintenance20
Community16
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture78
Code Quality90
Innovation48
Learning Curve45

stringify-entities is a focused JavaScript library for encoding (serializing) HTML character references — the inverse of parsing entities like & back into raw characters. It exports two functions: stringifyEntities, which supports the full range of formatting options (named vs. numeric references, shortest-output selection, semicolon omission, attribute-safe output), and stringifyEntitiesLight, a smaller build that always emits hexadecimal references for consumers who don’t need the extra formatting logic.

The library underlies entity-encoding needs across the unified/remark/rehype ecosystem, where consistent, spec-correct escaping of HTML text and attribute values is required when serializing ASTs back into markup. It explicitly handles surrogate pairs, control characters, and legacy named references (including the historical backtick-in-Internet-Explorer quirk), and ships with full TypeScript types with 100% type coverage enforced in CI.

What You Get

  • Two entry points — stringifyEntities for full control over reference formatting, and stringifyEntitiesLight for a smaller, hexadecimal-only build
  • Named, decimal, and hexadecimal character reference output, selectable per call via options
  • A useShortestReferences mode that compares candidate encodings and picks whichever produces the fewest bytes
  • Subset and escape-only modes for narrowly scoped escaping (e.g. just the five dangerous HTML characters)
  • Full TypeScript types generated from JSDoc, with 100% type coverage enforced via type-coverage in CI

Common Use Cases

  • HTML/XML serializers - AST-to-HTML tooling (e.g. rehype-based pipelines) uses stringify-entities to safely encode text and attribute values before writing final markup
  • HTML minifiers - Minifier authors use useShortestReferences and omitOptionalSemicolons to squeeze character references down to the smallest valid byte count
  • Markdown-to-HTML converters - remark/rehype-based static site generators rely on it to escape user content safely during compilation
  • Spec-compliant dangerous-character escaping - Applications needing correct escaping of ", &, ', <, >, and ` use escapeOnly mode instead of hand-rolled replace calls

Under The Hood

Architecture The library is a small, layered strategy-pattern design: lib/index.js exposes the two public functions, both of which delegate to a single shared traversal engine in lib/core.js, passing in a different format callback (format-smart.js for the full-featured encoder, format-basic.js for the light hexadecimal-only one). core.js owns the actual string-walking logic — matching either a default dangerous-character regex or a cached, dynamically-built subset regex, then invoking the injected format strategy per matched character (with surrogate pairs handled as a special case). Below that sit small, pure helper modules (to-decimal.js, to-hexadecimal.js, to-named.js) that each encode a single reference type, plus a generated constant/dangerous.js data file (produced by build.js from character-entities-legacy and character-entities, kept out of hand-written source). If core.js’s signature changed, both public entry points would break identically, since they’re thin wrappers around the same traversal function.

Tech Stack A dependency-light, ESM-only ("type": "module") Node.js library with exactly two runtime dependencies — character-entities-html4 and character-entities-legacy — both small pure-data lookup packages. Types are authored as JSDoc comments and compiled to .d.ts via tsc --build, with type-coverage enforcing complete coverage rather than relying on hand-written .ts source. Linting and formatting run through xo (an opinionated ESLint preset) and prettier, with remark-cli plus remark-preset-wooorm linting the README itself. Tests run on Node’s built-in node:test/node:assert runner with coverage measured by c8. CI is a single GitHub Actions workflow running the full test/build/lint pipeline across two Node LTS versions and uploading coverage to Codecov. There is no bundler — the package ships its ESM source directly to npm.

Code Quality A single root-level test.js (232 lines) exercises the public API as black-box behavioral tests — default encoding, named references, shortest-reference selection, semicolon omission, subset scoping, and escape-only mode are each asserted against exact expected output strings. Coverage is enforced at 100% via c8 --check-coverage --100, and type coverage is separately enforced at 100% via type-coverage, so neither untested code paths nor untyped values are tolerated in CI. Naming is terse but consistent with the wider wooorm/unified ecosystem (one narrow concern per file). There’s little explicit error-handling to assess, since the library is a pure string transform with no I/O, but the strict coverage gates substitute for that concern here.

What Makes It Unique HTML character-reference encoding is a solved, spec-defined problem, so this library isn’t attempting anything conceptually new — its one genuinely specific technical contribution is the useShortestReferences algorithm in format-smart.js, which computes named, decimal, and hexadecimal candidate encodings for each character and picks whichever is shortest, accounting for how a following character interacts with optional semicolon omission. That’s a narrow, well-scoped optimization aimed squarely at HTML minifier authors rather than a broader architectural innovation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search