This is an attempt to rewrite Handlebars cleanly and with modern tools, and a the same time provide a reliable specification of its language.
In the best of all cases, this repo replaces Handlebars completely when all the original features are implemented.
This project is a mono-repo. The directory packages/@handlebars-ng contains the following modules:
- specification - builds a specification site and exports testcases and AST types
- parser - a TypeScript-based parser for the Handlebars language
- runner - a TypeScript-based compiler/executor for Handlebars ASTs
- benchmark - measures the performance of the new parser/executor compared to the original Handlebars
And some auxillary modules
- playground - The SolidJS components for the HandlebarsNG playground
- common-dev - project configuration files shared by multiple sub-repositories
- eslint-plugin - eslint-rules and configuration shared by multiple sub-repositories
I use Visual Studio Code to work in this repository. The following extensions are helpful:
You can contribute by adding new sections to the specification and fixing the resulting failing tests in the parser and runner.
I use the following workflow for this:
All the yarn-commands in the following description are run in the main directory.
- In general, it is helpful to run
yarn site dev:server
while editing the spec. It shows the current website instantly, including live-reload on content changes. - In the directory src/spec, add a new chapter-directory or use an existing chapter, if it fits semantically.
- Create a file
index.md
and describe the feature. Use existing chapters as a template.
Grammar is written in grammarkdown which allows to use a language grammar as defined the ECMA 262 Specification.
- Adjust the file handlebars.grammar by adding more statements and extending existing ones.
- If you want to include parts of the grammar into your text, add a
// @section:MySectionName
comment to the grammar file - Add a link
[My FeatureName](../handlebars.grammer#MySectionName)
to the text, linking to the grammar file.
The part of the grammar starting with the linked section, up to the next section marker (or end-of-file) will be inlined instead of the link.
- Add one file named
[feature-name].hb-spec.json
, give it a$schema
,description
,template
andinput
(and possible more relevant data that is NOTast
oroutput
) - Create a link from the markdown-file to the test-file using markdown-syntax.
- Run
yarn spec generate:auto-complete-tests
. This will run Handlebars 4.x and addast
andoutput
to the test-file - Validate output and ast. If the AST does not match your expectations, correct it and run
yarn spec generate:auto-complete-tests
again. This will add theoriginalAst
feature. - The output should match your expectation, because handlebars-ng ist supposed to be compatible to Handlebars 4.x at least in that respect. If you really think it is a bug, you can add a description of the bug to the field
possibleBug
. We can discuss this later. - If the generated AST does not match, the JSON schema, you add the correct TypeScript-types to the file
packages/@handlebars-ng/abstract-syntax-tree/index.d.ts
and runyarn spec generate
to update the JSON schema. The Handlebars 4.x types are intypes/handlebars/index.d.ts
. You can use them as hints. - Only add as many types as necessary to represent the generated AST. We want to build up the model incrementally.
- Run
yarn spec test-and-build
to make sure all the dist-files are updated correctly.
Go to "packages/@handlebars-ng/parser"
- Run
yarn parser dev:unit
to run unit-tests in watch mode. Your specification-test should be run as well and fail, so you can try to fix. - Add values to the
TokenType
and new tokens in src/model/lexer.ts if necessary. - Add a new plugin to src/plugins
- Have a look at the existing plugins for reference. In general, a plugin uses registers rules and lexer-states and parse-functions associates with those rules. It's all in one place now.
- Add your plugin to the default parser
- When the test is green, cleanup your code.
- You can run
yarn parser perf
to run the performance tests, but performance optimizations can also be done later on. - Finally, run
yarn parser test-and-build
to update thedist
-folder
Go to "packages/@handlebars-ng/runner"
- Run
yarn runner dev:unit
to run unit-tests in watch mode. Your specification-test should be run as well and fail, so you can try to fix. - Add a new renderer to src/renderer if necessary.
- Register the new renderer in src/index.ts
- Adjust renders and needed
- Cleanup your code afterwards.
- You can run
yarn runner perf
to run the performance tests, but performance optimizations can also be done later on. - Finally, run
yarn runner test-and-build
to update thedist
-folder
- We need to set up a publishing progress and maybe some browser tests.
- Should we put this unter the
@handlebars
-scope in npm? And move it to thenhandlebars-lang
org? I am reluctant doing that unless I know that this project will get some drive from other people as well.