parse-entities

Spec-compliant HTML character reference decoder with positional warnings for building linters and parsers.

Library
npm
v4.0.2
52stars
MIT License

Repository Health

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

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture78
Code Quality88
Innovation82
Learning Curve65

parse-entities is a small, dependency-light library that decodes HTML character references (entities) exactly according to the WHATWG HTML parsing spec. It exports a single parseEntities function that takes a string and returns the decoded text, correctly handling named references (like &), decimal and hexadecimal numeric references, legacy unterminated references (like &copy without a semicolon), and the full set of edge cases the spec defines for disallowed and prohibited code points.

Beyond simple decoding, the library exposes optional reference, text, and warning callbacks that fire during parsing with precise line/column/offset position information for every decoded reference and every warning condition. This makes it especially useful for building linters, syntax highlighters, or Markdown/HTML processors that need to report exactly where in the source a malformed or suspicious character reference occurred, rather than just returning a decoded string. It underlies entity-handling across the unified/remark/rehype ecosystem.

What You Get

  • Spec-compliant decoding - Handles named, decimal, and hexadecimal character references exactly as the WHATWG HTML parsing algorithm specifies.
  • Positional warning system - Emits machine-readable warning codes (1-7) with line/column/offset info for malformed or unknown references.
  • Reference and text callbacks - Optional reference and text handlers let you track exactly which spans of output came from decoded entities versus plain text.
  • Attribute-aware parsing - An attribute option changes parsing behavior to match how browsers decode entities inside HTML attribute values specifically.
  • Zero-config defaults - Works out of the box with sensible defaults (like allowing nonterminated legacy references) while remaining fully configurable.

Common Use Cases

  • Building a Markdown or HTML parser - Parser authors use parse-entities to correctly unescape &, {, and similar sequences found in source text.
  • Writing a linter for HTML/Markdown content - Linters use the warning callback to flag missing semicolons or unknown entity names with precise positions for editor diagnostics.
  • Processing user-submitted HTML fragments - Applications sanitizing or rendering untrusted HTML use it to safely decode entities before further processing.
  • Powering the unified/remark/rehype toolchain - Downstream packages in the unified ecosystem rely on parse-entities as the entity-decoding primitive for Markdown-to-HTML pipelines.

Under The Hood

Architecture lib/index.js implements a single-file, monolithic character-by-character state machine: one exported parseEntities function runs a manual scanning loop over char codes, using inner closures (now, warning, flush) for position tracking and callback dispatch. Rather than pulling in a parser generator or class hierarchy, the design composes six small sibling packages (character-entities-legacy, character-reference-invalid, decode-named-character-reference, is-alphanumerical, is-decimal, is-hexadecimal) each responsible for one lookup table or predicate, so the risk of an entity-table format change is isolated to a single import rather than spread through the scanning logic. Data flows linearly: input string, character-code scan, queue accumulation, flush on reference boundaries, joined result array.

Tech Stack The package is pure ESM (type: module) with zero runtime framework dependencies beyond its small sibling packages by the same author. TypeScript is used only for type-checking via JSDoc annotations and a hand-authored index.d.ts, not compiled from .ts source; tsc --build plus type-coverage enforce full type coverage as part of the build. Linting and formatting run through xo (a prettier-wrapped ESLint preset) and remark-preset-wooorm for the README’s own markdown linting. Tests run on Node’s built-in node:test and node:assert/strict with no external test framework, and c8 enforces coverage.

Code Quality A single comprehensive test file exercises dozens of assertions covering named, decimal, and hexadecimal references, warning codes, position tracking, and edge cases like surrogate pairs and prohibited/disallowed code points, with coverage enforced at a strict threshold. JSDoc type annotations throughout the implementation provide type safety without a separate compile step, checked via the project’s type-coverage tooling. Naming conventions are terse but consistent with the author’s other unist/remark-ecosystem packages.

API Design The public surface is a single function, parseEntities(value, options), with no classes or config objects to instantiate — the zero-config case is a one-line call. Optional callback-based extensibility (reference, text, warning handlers) lets consumers opt into rich positional data only when they need it. Full TypeScript types are shipped for editor autocomplete, and the README documents every option and every warning code in a reference table.

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