he
A robust, spec-compliant HTML entity encoder and decoder for JavaScript with full Unicode support.
Repository Health
Technical Analysis
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
hecommand-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.
Used by 11 apps in this directory
AnythingLLM
Developer Tools · Automation · AI Assistants
The all-in-one AI platform for private document chat, no-code agents, and local LLMs with zero setup friction.
ClearFlask
Product Management · Community
Open-source feedback management and roadmap tool that lets product teams collect, prioritize, and respond to user input — with AI-powered summarization and full self-hosting control.
Dub
Marketing · Analytics
The open-source link attribution platform for short links, conversion tracking, and affiliate programs — powering 100M+ clicks monthly.
Firecrawl
AI Development · Developer Tools
Turn any website into clean, LLM-ready data with a single API call — no proxy headaches, no scraping complexity.
Forem
Community · Blogging
Open source Ruby on Rails platform for building developer communities with articles, discussions, and social profiles—the same software that powers dev.to.
Kibana
Analytics · Monitoring
Your open source window into the Elastic Stack — query, visualize, and act on data stored in Elasticsearch with real-time dashboards, AI-assisted search, and automated alerting.
nango
Developer Tools · Automation · Authentication
Build product integrations with AI using 800+ APIs — auth, proxy, and TypeScript functions on production-grade infrastructure.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Rocket.Chat
Team Chat
The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.