handlebars-lang/handlebars.js
56.7
Adequate · 1 October 2026
4k
lines of production code
JavaScript
with TypeScript
2
measurements over time
What this system is
This system is the Handlebars.js templating library, providing a runtime for compiling and executing Handlebars templates alongside a command-line interface for precompilation. It exposes a modular API for registering helpers, managing partials, and handling data contexts, with specific support for modern JavaScript features like ES modules and TypeScript definitions. The codebase includes comprehensive tooling for building, testing across multiple environments, and publishing distribution artifacts.
How it got here
2010–2013 — ESM migration and tooling modernization
13 changes.
The project underwent a significant architectural shift by converting the Handlebars library from CommonJS to ES modules, enabling better tree-shaking and modern bundler compatibility. This transition was accompanied by a comprehensive overhaul of the development infrastructure, migrating from Grunt and npm to Rspack, pnpm, and Vitest. The period also involved restructuring the compiler into modular components and establishing a robust, modernized test suite to ensure stability during the upgrade.
2015–2021 — ESM refactoring and security hardening
11 changes.
The project refactored Handlebars helpers into separate ES modules and introduced native TypeScript definitions, while implementing prototype access controls to prevent pollution. This period also focused on comprehensive testing infrastructure, adding integration suites for CLI, bundlers, and multiple Node.js versions to ensure stability and compatibility.
2022–2026 — ESM migration and test expansion
5 changes.
The CLI tool was rewritten as an ES module to align with modern Node.js runtime requirements. Comprehensive testing infrastructure was established, including browser execution checks, Rspack build validation, TypeScript definition verification, and performance benchmarking.
Features
New TypeScript definitions for Handlebars
The package now ships with its own TypeScript type definitions (types/index.d.ts) instead of relying on external @types packages. This includes updated types for RuntimeOptions (such as allowCallsToHelperMissing and prototype access controls), HelperOptions (with hash as Record\<string, any\>), and the Exception class, along with support for Map and Set in \#each blocks via new utility type checks.
types · high confidence
New git utility module with ESM exports
A new \tasks/util/git.js\ module has been added, providing asynchronous, promise-based wrappers for common git operations including retrieving remotes, branches, commit information (head/master SHA, tag name), and performing add/commit actions. The module uses ES module syntax (\import\/\export\) and handles specific edge cases, such as ignoring errors when the master branch is not checked out during SHA comparison.
tasks/util · high confidence
Removals
Removal of custom Handlebars implementation and jQuery dependency
The custom Handlebars template engine and its associated test suite have been removed from the project. This change also eliminates the bundled jQuery v1.4.2 library, which was previously used to run the Handlebars tests. Users will no longer have access to the {{}} template syntax provided by this local implementation.
js · high confidence
Architecture
Refactored Handlebars compiler into modular, ESM-based components
The Handlebars compiler has been restructured from a single monolithic file into distinct, modular components (AST, code generation, compiler logic, and JavaScript output) using ES modules. This change introduces a new CodeGen utility for building source code and separates browser and Node.js source-map handling, improving maintainability and enabling better tree-shaking. The public API remains compatible, but the internal architecture now supports more flexible extension and cleaner separation of concerns between parsing, compilation, and code generation.
lib/handlebars/compiler · high confidence
Behavioural changes
CLI tool rewritten as an ES module
The command-line interface for precompiling Handlebars templates has been converted from CommonJS to ES modules. This change updates the underlying runtime requirements for the CLI script, meaning it now relies on Node.js environments that support native ES module syntax (such as using .mjs extensions or setting type: module in package.json). The functional command-line options for compiling templates remain available, but the internal implementation now uses import statements instead of require.
bin · high confidence
Handlebars library restructured into ES modules with version 4.7.7
The Handlebars library has been updated to version 4.7.7 and fully converted to ES modules, replacing the previous CommonJS/browser bundle structure. This change introduces a modular file layout with separate entry points for base environment, runtime, helpers, decorators, and utilities, enabling better tree-shaking and modern bundler compatibility. The core Handlebars environment now registers default helpers (each, if, with, log, lookup) and decorators (inline) via dedicated module files, while the runtime handles template compilation and execution with strict revision checking to ensure compatibility between precompiled templates and the runtime. The SafeString implementation has been simplified to use toHTML checks instead of instanceof, and utility functions like escapeExpression, extend, and createFrame are now exported from a dedicated utils module. The logger module provides a configurable logging interface that falls back to console.log, and a noConflict module is included to prevent global namespace pollution. This restructuring affects how the library is imported and used, requiring module-aware build tools.
lib/handlebars · high confidence
Modernized development tooling and configuration
The project has replaced its previous development toolchain with a modern stack: linting and formatting are now handled by oxlint and oxfmt (configured via .oxlintrc.json and .oxfmtrc.json), the package manager has switched to pnpm (with pnpm-workspace.yaml), and the build system now uses rspack (rspack.config.js) instead of the previous bundler. Additionally, the test runner has been migrated to vitest (vitest.config.js), and the repository now includes standardized configuration files such as .editorconfig, .gitattributes, and .gitignore to enforce consistent code style, line endings, and file management.
(repo-wide) · high confidence
Prototype access control and helper validation improvements
Handlebars now includes built-in protection against prototype pollution by introducing a whitelist-based access control system for prototype properties and methods, which can be configured via runtime options to allow or deny specific accesses. Additionally, the library now safely handles non-function helpers by skipping the wrapper logic instead of crashing, and improves error logging for illegal property access to ensure warnings are logged only once per property using the internal logger.
lib/handlebars/internal · high confidence
Refactored Handlebars helpers into separate ESM modules with enhanced iteration support
The built-in Handlebars helpers (blockHelperMissing, each, helperMissing, if, unless, log, lookup, with) have been extracted from the main bundle into individual ES module files. This refactoring introduces support for iterating over Map, Set, and other iterable objects in the \#each helper, improves the robustness of the \#if and \#unless helpers with better argument validation, and updates the \#lookup helper to use a safer lookupProperty method. Users benefit from more flexible data iteration and stricter error handling in conditional blocks.
lib/handlebars/helpers · high confidence
Replace Grunt build tasks with native ESM scripts
The project's build and release automation has been migrated from Grunt to native Node.js ESM scripts. The new \tasks/publish-to-aws.js\ handles publishing distribution files to AWS S3 using the AWS SDK v3, while \tasks/version.js\ manages version updates across package files and source code. This change removes the Grunt dependency and adopts ES modules for the task runner.
tasks · high confidence
Switch to ES modules and restructure library entry points
The library has migrated from CommonJS to ES modules, replacing the previous single-file distribution with a modular structure. The main entry point (lib/index.js) now re-exports functionality from a new runtime module (lib/handlebars.runtime.js) and a compiler module (lib/handlebars.js), which imports from the external @handlebars/parser package. This change introduces named exports for CommonJS interop to ensure tools like handlebars-loader can still access properties like COMPILER\_REVISION and create() directly via require(). The precompiler (lib/precompiler.js) has also been updated to use ES module imports and the neo-async library for asynchronous template loading.
lib · high confidence
Fixes
Fix Handlebars source gem definition
The Handlebars source gem definition has been corrected to properly locate the bundled JavaScript files. The updated source file now correctly resolves the paths for both the standard handlebars.js and the handlebars.runtime.js files relative to the library's location, ensuring the gem can find its dependencies at runtime.
components/lib · high confidence
Test coverage
Added Playwright browser test configuration and documentation; Added benchmarking and size measurement scripts; Added browser test for Handlebars.js spec execution; Added comprehensive test suite for Handlebars core features; Added debug utility for source code generation; Added integration tests for Handlebars with Webpack; Added integration tests for Rollup ESM bundling with Handlebars; Added multi-node integration tests for Handlebars; Added temporary directory for test artifacts; Added test fixtures for CLI help output and template compilation; Added test fixtures for template rendering; Added test suite for CLI, Git utilities, and S3 publishing; Added tests for Rspack build output and ESM compatibility; Added type tests for Handlebars; New test environment setup files for browser and Node.js specs.
Dependencies
Initial release of Handlebars.js v5.0.0-alpha.1 with package manifests
This change introduces the initial version (5.0.0-alpha.1) of the Handlebars.js library to the components directory. It adds the core JavaScript file along with configuration manifests for Bower, Component, and NuGet, establishing the package structure and metadata for this alpha release.
components · high confidence
Migrate to pnpm and modernize build tooling
The project has switched its package manager from npm to pnpm, introducing a pnpm-lock.yaml and updating the packageManager field. This change is accompanied by a significant upgrade to the build and development infrastructure: the build system has migrated from Grunt to Rspack, and linting/formatting has moved to oxlint and oxfmt. Testing has been updated to use Vitest and Playwright, replacing older tools like Mocha and Saucelabs. Additionally, the package now supports ES modules (type: module) and requires Node.js 20 or higher, while updating core dependencies such as yargs to v18 and neo-async.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 55 → 57 (+1.4)
- Rubric changed (rubric-2026.09.11 → rubric-2026.09.18) — scores are not directly comparable.
Lenses
- Code Health 50 → 50 (+0.0)
- Architecture 98 → 98 (+0.5)
- Maturity 55 → 55 (-0.0)
- Readiness 69 → 67 (-2.2)
- Security 54 → 67 (+12.1)
- Performance 71 (new)
Resolved (3)
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- Off-boarding risk: anonymized user #1
New (2)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- Off-boarding risk: anonymized user #1
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
handlebars-lang/handlebars.js was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 1 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 13a7a679910d2adbfe7f6fad61ce8f98426b0378 — the exact code this score is about.
- Scored under rubric-2026.09.18 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-e569280dd5e2.