Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Generally we like to see pull requests that
- [ ] Have tests
- [ ] Have the [typings](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html) (types/index.d.ts) updated on every API change. If you need help, updating those, please mention that in the PR description.
- [ ] Don't significantly decrease the current code coverage (see coverage/lcov-report/index.html)
- [ ] Currently, the `4.x`-branch contains the latest version. Please target that branch in the PR.
- [ ] Please target the `master` branch in the PR.
11 changes: 4 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,9 @@ jobs:
- name: Test
run: npm run test

# TODO: Re-enable integration tests once webpack/rollup compatibility is resolved
# - name: Test (Integration)
# run: |
# cd ./tests/integration/rollup-test && ./test.sh && cd -
# cd ./tests/integration/webpack-babel-test && ./test.sh && cd -
# cd ./tests/integration/webpack-test && ./test.sh && cd -
- name: Test (Integration)
if: matrix.operating-system == 'ubuntu-latest'
run: npm run test:integration

browser:
name: Test (Browser)
Expand All @@ -82,7 +79,7 @@ jobs:
npx playwright install

- name: Build
run: npx grunt prepare
run: npm run build

- name: Test
run: |
Expand Down
8 changes: 8 additions & 0 deletions .swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://swc.rs/schema.json",
"module": {
"type": "commonjs",
"importInterop": "swc"
},
"sourceMaps": "inline"
}
44 changes: 12 additions & 32 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ Documentation issues on the [handlebarsjs.com](https://handlebarsjs.com) site sh

## Branches

- The branch `4.x` contains the currently released version. Bugfixes should be made in this branch.
- The branch `master` contains the next version. A release date is not yet specified. Maintainers
should merge the branch `4.x` into the master branch regularly.
- The branch `3.x` contains the legacy version `3.x`. Bugfixes are applied separately (if needed). The branch will not
be merged with any of the other branches.
- The branch `master` contains the current development version (v5).
- The branch `4.x` contains the previous stable version. Only critical bugfixes are backported there.

## Pull Requests

Expand All @@ -38,21 +35,13 @@ Generally we like to see pull requests that

## Building

To build Handlebars.js you'll need a few things installed.

- Node.js
- [Grunt](http://gruntjs.com/getting-started)
To build Handlebars.js you'll need Node.js installed.

Before building, you need to make sure that the Git submodule `spec/mustache` is included (i.e. the directory `spec/mustache` should not be empty). To include it, if using Git version 1.6.5 or newer, use `git clone --recursive` rather than `git clone`. Or, if you already cloned without `--recursive`, use `git submodule update --init`.

Project dependencies may be installed via `npm install`.

To build Handlebars.js from scratch, you'll want to run `grunt`
in the root of the project. That will build Handlebars and output the
results to the dist/ folder. To re-run tests, run `grunt test` or `npm test`.
You can also run our set of benchmarks with `grunt bench`.

The `grunt dev` implements watching for tests and allows for in browser testing at `http://localhost:9999/spec/`.
To build Handlebars.js from scratch, run `npm run build` in the root of the project. That will compile CJS modules via SWC and bundle UMD distributions via rspack, outputting results to the dist/ folder. To run tests, use `npm test`.

If you notice any problems, please report them to the GitHub issue tracker at
[http://github.com/handlebars-lang/handlebars.js/issues](http://github.com/handlebars-lang/handlebars.js/issues).
Expand Down Expand Up @@ -81,21 +70,16 @@ npm test

## Linting and Formatting

Handlebars uses `eslint` to enforce best-practices and `prettier` to auto-format files.
We do linting and formatting in two phases:

- Committed files are linted and formatted in a pre-commit hook. In this stage eslint-errors are forbidden,
while warnings are allowed.
- The GitHub CI job also lints all files and checks if they are formatted correctly. In this stage, warnings
are forbidden.
Handlebars uses `oxlint` for linting, `oxfmt` for formatting, and `eslint` (with `eslint-plugin-compat`) for browser API compatibility checks.
Committed files are linted and formatted in a pre-commit hook.

You can use the following scripts to make sure that the CI job does not fail:

- **npm run lint** will run `eslint` and fail on warnings
- **npm run format** will run `prettier` on all files
- **npm run check-before-pull-request** will perform all most checks that our CI job does in its build-job, excluding the "integration-test".
- **npm run test:integration** will run integration tests (using old NodeJS versions and integrations with webpack, babel and so on)
These tests only work on a Linux-machine with `nvm` installed (for running tests in multiple versions of NodeJS).
- **npm run lint** will run all linters and fail on warnings
- **npm run format** will format all files
- **npm run check-before-pull-request** will perform all checks that our CI job does, excluding integration tests.
- **npm run test:integration** will run integration tests (bundler compatibility with webpack, rollup, etc.)
These tests only work on Linux.

## Releasing the latest version

Expand All @@ -113,12 +97,8 @@ A full release may be completed with the following:

```
npm ci
npx grunt
npm run build
npm publish

cd dist/components/
gem build handlebars-source.gemspec
gem push handlebars-source-*.gem
```

After the release, you should check that all places have really been updated. Especially verify that the `latest`-tags
Expand Down
169 changes: 2 additions & 167 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -1,174 +1,9 @@
/* eslint-disable no-process-env */
// Legacy Gruntfile — kept only for the 'metrics' and 'version' tasks.
// The main build pipeline uses rspack + swc (see rspack.config.js and .swcrc).
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

clean: ['tmp', 'dist', 'tests/integration/**/node_modules'],

copy: {
dist: {
options: {
processContent: function (content) {
return (
grunt.template.process(
'/**!\n\n @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat\n <%= pkg.name %> v<%= pkg.version %>\n\n<%= grunt.file.read("LICENSE") %>\n*/\n'
) +
content +
'\n// @license-end\n'
);
},
},
files: [{ expand: true, cwd: 'dist/', src: ['*.js'], dest: 'dist/' }],
},
components: {
files: [
{
expand: true,
cwd: 'components/',
src: ['**'],
dest: 'dist/components',
},
{
expand: true,
cwd: 'dist/',
src: ['*.js'],
dest: 'dist/components',
},
],
},
},

babel: {
options: {
sourceMaps: 'inline',
loose: ['es6.modules'],
auxiliaryCommentBefore: 'istanbul ignore next',
},
cjs: {
files: [
{
cwd: 'lib/',
expand: true,
src: '**/!(index).js',
dest: 'dist/cjs/',
},
],
},
},
webpack: {
options: {
context: __dirname,
output: {
path: 'dist/',
library: 'Handlebars',
libraryTarget: 'umd',
},
},
handlebars: {
entry: './dist/cjs/handlebars.js',
output: {
filename: 'handlebars.js',
},
},
runtime: {
entry: './dist/cjs/handlebars.runtime.js',
output: {
filename: 'handlebars.runtime.js',
},
},
},

uglify: {
options: {
mangle: true,
compress: true,
preserveComments: /(?:^!|@(?:license|preserve|cc_on))/,
},
dist: {
files: [
{
cwd: 'dist/',
expand: true,
src: ['handlebars*.js', '!*.min.js'],
dest: 'dist/',
rename: function (dest, src) {
return dest + src.replace(/\.js$/, '.min.js');
},
},
],
},
},

concat: {
tests: {
src: ['spec/!(require).js'],
dest: 'tmp/tests.js',
},
},

connect: {
server: {
options: {
base: '.',
hostname: '*',
port: 9999,
},
},
},

shell: {
integrationTests: {
command: './tests/integration/run-integration-tests.sh',
},
},

watch: {
scripts: {
options: {
atBegin: true,
},

files: ['src/*', 'lib/**/*.js', 'spec/**/*.js'],
tasks: ['on-file-change'],
},
},
});

// Load tasks from npm
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-webpack');

grunt.task.loadTasks('tasks');

grunt.registerTask('node', ['babel:cjs']);
grunt.registerTask('globals', ['webpack']);
grunt.registerTask('release', 'Build final packages', [
'uglify',
'copy:dist',
'copy:components',
]);

grunt.registerTask('on-file-change', ['build', 'concat:tests']);

// === Primary tasks ===
grunt.registerTask('dev', ['clean', 'connect', 'watch']);
grunt.registerTask('default', ['clean', 'build', 'release']);
grunt.registerTask('bench', ['metrics']);
grunt.registerTask('prepare', ['build', 'concat:tests']);
grunt.registerTask(
'build',
'Builds a distributable version of the current project',
['node', 'globals']
);
grunt.registerTask('integration-tests', [
'default',
'shell:integrationTests',
]);
};
5 changes: 4 additions & 1 deletion lib/handlebars.runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ function create() {
hb.Utils = Utils;
hb.escapeExpression = Utils.escapeExpression;

hb.VM = runtime;
// Spread into a plain object so that runtime functions (e.g. checkRevision)
// can be overridden by consumers. ES module namespace objects are sealed with
// getter-only properties per spec, which would prevent monkey-patching.
hb.VM = { ...runtime };
hb.template = function (spec) {
return runtime.template(spec, hb);
};
Expand Down
2 changes: 1 addition & 1 deletion lib/precompiler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
import Async from 'neo-async';
import fs from 'fs';
import * as Handlebars from './handlebars';
import Handlebars from './handlebars';
import { basename } from 'path';
import { SourceMapConsumer, SourceNode } from 'source-map';

Expand Down
Loading