he

A robust, spec-compliant HTML entity encoder and decoder for JavaScript with full Unicode support.

Library
npm
v2.0.0
3,612 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
56 /100 Fair
Development Activity 52
Maintenance 12
Community 60
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
73 /100 Good
Architecture 70
Code Quality 75
Innovation 80
Learning Curve 65

he is a robust HTML entity encoder and decoder for JavaScript, implementing the WHATWG HTML specification’s character-reference tokenizing algorithm exactly as a browser would. It correctly handles every standardized named character reference, resolves ambiguous ampersands, and supports astral Unicode code points beyond the basic multilingual plane — edge cases that trip up many simpler entity libraries built on ad-hoc regex tables.

Beyond encode/decode, it exposes lightweight escape/unescape helpers for the narrower set of HTML-unsafe characters, plus a command-line binary for encoding or decoding text directly from the shell. With tens of millions of weekly downloads, it is widely relied upon as a dependency inside larger HTML-processing, scraping, and templating tools rather than used directly by most application authors.

What You Get

  • Spec-accurate encode()/decode() functions covering every named HTML5 character reference
  • Support for astral Unicode symbols (surrogate pairs) that many alternatives mishandle
  • Lightweight escape()/unescape() helpers for the minimal HTML-unsafe character set
  • A he command-line binary for encoding/decoding text from the shell

Common Use Cases

  • Decoding HTML entities scraped or parsed from web pages before further text processing
  • Encoding user-supplied text for safe inclusion in HTML templates
  • Building HTML parsers or validators that need strict, spec-conformant character-reference handling
  • Converting between named and numeric character references in build tooling

Under The Hood

Architecture

he.js is a single-file UMD module (built from src/he.js via Grunt’s template task) exposing encode, decode, escape, unescape, and version on one flat he namespace object — there is no internal layering. The core data tables (encode/decode maps, ASCII/BMP/astral regexes) are generated at build time from JSON files under data/, sourced from the WHATWG entities spec and a scraped copy of the tokenizer states, via scripts/process-data.js, then inlined into the built he.js as literal regex and object definitions. The runtime module itself ships with zero external dependencies; changing the core mapping tables means re-running the Grunt build pipeline rather than editing the generated file directly.

Tech Stack

Plain JavaScript with a UMD wrapper that detects CommonJS, AMD, and browser globals — no transpilation and no runtime dependencies. Build tooling is Grunt, using grunt-template to inject generated data into src/he.js and grunt-shell to fetch the WHATWG entities.json spec, scrape supplementary spec pages with PhantomJS, and regenerate the astral/BMP/ASCII regexes via regenerate/regexgen. Tests run under QUnit (qunitjs/qunit-extras) across Node, PhantomJS, Rhino, Narwhal, and RingoJS. The package is published to npm, Bower, and Component, and ships a bin/he CLI plus a man/he.1 man page.

Code Quality

tests/tests.js is a single ~6,700-line QUnit suite exercising every entity, edge case (ambiguous ampersands, astral symbols, invalid code points), and option combination across encode/decode/escape/unescape. Historical CI (Travis) ran the suite across multiple JS engines via dedicated Gruntfile targets (test-node, test-phantomjs, test-rhino, test-narwhal, test-ringo), with Istanbul/Codecov coverage reporting. There is no TypeScript and no linter config; the code is pre-ES6, prototype-style JavaScript with manual hasOwnProperty checks and hand-written iteration helpers rather than native array/object methods, reflecting both its 2013 origins and its goal of running in older or exotic JS runtimes.

API Design The public surface is deliberately tiny — four functions (encode, decode, escape, unescape) plus a version string — with safe-by-default behavior and a documented global-override pattern (he.encode.options.x = ...) for callers who don’t want to pass an options object on every call. Every option (useNamedReferences, allowUnsafeSymbols, isAttributeValue, strict, decimal, encodeEverything) is descriptively named and documented in the README with runnable before/after examples. Getting started requires zero configuration: require('he') and call he.encode() or he.decode() immediately.

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