pax_global_header00006660000000000000000000000064152610223300014504gustar00rootroot0000000000000052 comment=45ce15255e0f430ac6d19742b18e316b7539264e handlebars-lang-handlebars.js-0cbc8e4/000077500000000000000000000000001526102233000177345ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/.editorconfig000066400000000000000000000002651526102233000224140ustar00rootroot00000000000000root = true [*.js] indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.yml] indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true handlebars-lang-handlebars.js-0cbc8e4/.eslintignore000066400000000000000000000005331526102233000224400ustar00rootroot00000000000000.rvmrc .DS_Store /tmp/ *.sublime-project *.sublime-workspace npm-debug.log .idea yarn-error.log node_modules /handlebars-release.tgz .nyc_output # Generated files lib/handlebars/compiler/parser.js /coverage/ /dist/ /tests/integration/*/dist/ # Third-party or files that must remain unchanged /spec/expected/ /spec/vendor # JS-Snippets src/*.js handlebars-lang-handlebars.js-0cbc8e4/.eslintrc.js000066400000000000000000000031161526102233000221740ustar00rootroot00000000000000module.exports = { extends: ['eslint:recommended', 'plugin:compat/recommended', 'prettier'], globals: { self: false }, env: { node: true, es6: true }, rules: { 'no-console': 'warn', // temporarily disabled until the violating places are fixed. 'no-func-assign': 'off', 'no-sparse-arrays': 'off', // Best Practices // //----------------// 'default-case': 'warn', 'guard-for-in': 'warn', 'no-alert': 'error', 'no-caller': 'error', 'no-div-regex': 'warn', 'no-eval': 'error', 'no-extend-native': 'error', 'no-extra-bind': 'error', 'no-floating-decimal': 'error', 'no-implied-eval': 'error', 'no-iterator': 'error', 'no-labels': 'error', 'no-lone-blocks': 'error', 'no-loop-func': 'error', 'no-multi-str': 'warn', 'no-global-assign': 'error', 'no-new': 'error', 'no-new-func': 'error', 'no-new-wrappers': 'error', 'no-octal-escape': 'error', 'no-process-env': 'error', 'no-proto': 'error', 'no-return-assign': 'error', 'no-script-url': 'error', 'no-self-compare': 'error', 'no-sequences': 'error', 'no-throw-literal': 'error', 'no-unused-expressions': 'error', 'no-warning-comments': 'warn', 'no-with': 'error', radix: 'error', // Variables // //-----------// 'no-label-var': 'error', 'no-undef-init': 'error', 'no-use-before-define': ['error', 'nofunc'], // ECMAScript 6 // //--------------// 'no-var': 'error' }, parserOptions: { sourceType: 'module', ecmaVersion: 6, ecmaFeatures: {} } }; handlebars-lang-handlebars.js-0cbc8e4/.gitattributes000066400000000000000000000002261526102233000226270ustar00rootroot00000000000000# Handlebars-template fixtures in test cases need deterministic eol *.handlebars text eol=lf *.hbs text eol=lf # Lexer files as well *.l text eol=lf handlebars-lang-handlebars.js-0cbc8e4/.github/000077500000000000000000000000001526102233000212745ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/.github/dependabot.yml000066400000000000000000000002661526102233000241300ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: npm directory: "/" open-pull-requests-limit: 0 schedule: interval: weekly allow: - dependency-type: production handlebars-lang-handlebars.js-0cbc8e4/.github/workflows/000077500000000000000000000000001526102233000233315ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/.github/workflows/ci.yml000066400000000000000000000036441526102233000244560ustar00rootroot00000000000000name: CI on: push: branches: - master pull_request: {} jobs: lint: name: Lint runs-on: 'ubuntu-latest' steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '16' - name: Install dependencies run: npm ci - name: Lint run: npm run lint test: name: Test (Node) runs-on: ${{ matrix.operating-system }} strategy: fail-fast: false matrix: operating-system: ['ubuntu-latest', 'windows-latest'] # https://nodejs.org/en/about/releases/ node-version: ['16', '18', '20', '22'] steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - name: Install dependencies run: npm ci - name: Test run: npm run test - name: Test (Integration) # https://github.com/webpack/webpack/issues/14532 if: ${{ matrix.node-version == '16' }} 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 - browser: name: Test (Browser) runs-on: 'ubuntu-22.04' steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '16' - name: Install dependencies run: npm ci - name: Install Playwright run: | npx playwright install-deps npx playwright install - name: Build run: npx grunt prepare - name: Test run: npm run test:browser handlebars-lang-handlebars.js-0cbc8e4/.github/workflows/release.yml000066400000000000000000000016051526102233000254760ustar00rootroot00000000000000name: Release on: workflow_dispatch: push: branches: - master tags: - '*' jobs: publish-aws-s3: name: Publish to AWS S3 runs-on: 'ubuntu-latest' environment: 'builds.handlebarsjs.com.s3.amazonaws.com' steps: - name: Checkout uses: actions/checkout@v2 with: submodules: true - name: Setup Node.js uses: actions/setup-node@v2 with: node-version: '16' - name: Install dependencies run: npm ci - name: Publish run: | git config --global user.email "release@handlebarsjs.com" git config --global user.name "handlebars-lang" npm run publish:aws env: S3_BUCKET_NAME: "builds.handlebarsjs.com" S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }} S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }} handlebars-lang-handlebars.js-0cbc8e4/.gitignore000066400000000000000000000004321526102233000217230ustar00rootroot00000000000000.rvmrc .DS_Store /tmp/ *.sublime-project *.sublime-workspace npm-debug.log .idea /yarn-error.log /yarn.lock node_modules /handlebars-release.tgz .nyc_output # Generated files lib/handlebars/compiler/parser.js /coverage/ /dist/ /test-results/ /tests/integration/*/dist/ /spec/tmp/* handlebars-lang-handlebars.js-0cbc8e4/.gitmodules000066400000000000000000000001361526102233000221110ustar00rootroot00000000000000[submodule "spec/mustache"] path = spec/mustache url = https://github.com/mustache/spec.git handlebars-lang-handlebars.js-0cbc8e4/.prettierignore000066400000000000000000000005261526102233000230020ustar00rootroot00000000000000.rvmrc .DS_Store /tmp/ *.sublime-project *.sublime-workspace npm-debug.log sauce_connect.log* .idea yarn-error.log node_modules /handlebars-release.tgz .nyc_output # Generated files lib/handlebars/compiler/parser.js /coverage/ /dist/ /tests/integration/*/dist/ # Third-party or files that must remain unchanged /spec/expected/ /spec/vendor handlebars-lang-handlebars.js-0cbc8e4/CONTRIBUTING.md000066400000000000000000000221131526102233000221640ustar00rootroot00000000000000# How to Contribute ## Reporting Issues Please see our [FAQ](https://github.com/handlebars-lang/handlebars.js/blob/master/FAQ.md) for common issues that people run into. Should you run into other issues with the project, please don't hesitate to let us know by filing an [issue][issue]! In general we are going to ask for an example of the problem failing, which can be as simple as a jsfiddle/jsbin/etc. We've put together a jsfiddle [template][jsfiddle] to ease this. (We will keep this link up to date as new releases occur, so feel free to check back here) Pull requests containing only failing tests demonstrating the issue are welcomed and this also helps ensure that your issue won't regress in the future once it's fixed. Documentation issues on the [handlebarsjs.com](https://handlebarsjs.com) site should be reported on [handlebars-lang/docs](https://github.com/handlebars-lang/docs). ## 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. ## Pull Requests We also accept [pull requests][pull-request]! Generally we like to see pull requests that - Maintain the existing code style - Are focused on a single change (i.e. avoid large refactoring or style adjustments in untouched code if not the primary goal of the pull request) - Have [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) - Have tests - Don't significantly decrease the current code coverage (see coverage/lcov-report/index.html) ## Building To build Handlebars.js you'll need a few things installed. - Node.js - [Grunt](http://gruntjs.com/getting-started) 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/`. 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). ## Running Tests To run tests locally, first install all dependencies. ```sh npm install ``` Clone the mustache specs into the spec/mustache folder. ```sh cd spec rm -r mustache git clone https://github.com/mustache/spec.git mustache ``` From the root directory, run the tests. ```sh 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. 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). ## Releasing the latest version Before attempting the release Handlebars, please make sure that you have the following authorizations: - Push-access to [handlebars-lang/handlebars.js](https://github.com/handlebars-lang/handlebars.js/) - Publishing rights on npmjs.com for the [handlebars](https://www.npmjs.com/package/handlebars) package - Publishing rights on rubygems for the [handlebars-source](https://rubygems.org/gems/handlebars-source) package - Push-access to the repo for legacy package managers: [components/handlebars.js](https://github.com/components/handlebars.js) - Push-access to the production-repo of the handlebars site: [handlebars-lang/docs](https://github.com/handlebars-lang/docs) _When releasing a previous version of Handlebars, please look into the CONTRIBUNG.md in the corresponding branch._ A full release via Docker may be completed with the following: 1. Create a `Dockerfile` in this folder for releasing ```Dockerfile FROM node:10-slim ENV EDITOR=vim # Update stretch repositories RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \ -e 's|security.debian.org|archive.debian.org/|g' \ -e '/stretch-updates/d' /etc/apt/sources.list # Install release dependencies RUN apt-get update RUN apt-get install -y git vim # Work around deprecated npm dependency install via unauthenticated git-protocol: # https://github.com/kpdecker/generator-release/blob/87aab9b84c9f083635c3fcc822f18acce1f48736/package.json#L31 RUN git config --system url."https://github.com/".insteadOf git://github.com/ # Configure git RUN git config --system user.email "release@handlebarsjs.com" RUN git config --system user.name "handlebars-lang" RUN mkdir /home/node/.config RUN mkdir /home/node/.ssh RUN mkdir /home/node/tmp # Generate config for yo generator-release: # https://github.com/kpdecker/generator-release#example # You have to add a valid GitHub access token! (Used for reading issues and pull requests.) RUN echo "module.exports = {\n auth: 'oauth',\n token: 'GitHub personal access token'\n};" > /home/node/.config/generator-release RUN chown -R node:node /home/node/.config RUN chown -R node:node /home/node/.ssh RUN chown -R node:node /home/node/tmp # Add the generated key to GitHub: https://github.com/settings/keys RUN ssh-keygen -q -t ed25519 -N '' -f /home/node/.ssh/id_ed25519 -C "release@handlebarsjs.com" RUN chmod 0600 /home/node/.ssh/id_ed25519* RUN chown node:node /home/node/.ssh/id_ed25519* ``` 2. Build and run the Docker image ```bash docker build --tag handlebars:release . docker run --rm --interactive --tty \ --volume $PWD:/app \ --workdir /app \ --user $(id -u):$(id -g) \ --env NPM_CONFIG_PREFIX=/home/node/.npm-global \ handlebars:release bash -c 'export PATH=$PATH:/home/node/.npm-global/bin; bash' ``` * Add SSH key to GitHub: `cat /home/node/.ssh/id_ed25519.pub` (https://github.com/settings/keys) * Add GitHub API token: `vi /home/node/.config/generator-release` * Execute the following steps: ```bash npm install npm install -g yo@1 grunt@1 generator-release npm run release # Warning! This step will collect data from GitHub, bump the version, # create a new commit, create a new tag and push it to GitHub. # https://github.com/kpdecker/generator-release?tab=readme-ov-file#usage yo release npm login npm publish yo release:publish components handlebars.js dist/components/ ``` 6. Publish Ruby `handlebars-source` gem: ```bash docker run --rm --interactive --tty \ --volume $PWD:/app \ --workdir /app \ ruby:3.2-slim bash ``` * Execute the following steps: ```bash cd dist/components/ gem build handlebars-source.gemspec gem push handlebars-source-*.gem ``` ### After the release After the release, you should check that all places have really been updated. Especially verify that the `latest`-tags in those places still point to the latest version - [The npm-package](https://www.npmjs.com/package/handlebars) (check latest-tag) - [The bower package](https://github.com/components/handlebars.js) (check the package.json) - [The AWS S3 Bucket](https://s3.amazonaws.com/builds.handlebarsjs.com) (check latest-tag) - [RubyGems](https://rubygems.org/gems/handlebars-source) When everything is OK, the **handlebars site** needs to be updated. Go to the master branch of the repo [handlebars-lang/docs](https://github.com/handlebars-lang/docs/tree/master) and make a minimal change to the README. This will invoke a github-action that redeploys the site, fetching the latest version-number from the npm-registry. (note that the default-branch of this repo is not the master and regular changes are done in the `handlebars-lang/docs`-repo). [generator-release]: https://github.com/walmartlabs/generator-release [pull-request]: https://github.com/handlebars-lang/handlebars.js/pull/new/master [issue]: https://github.com/handlebars-lang/handlebars.js/issues/new [jsfiddle]: https://jsfiddle.net/9D88g/180/ handlebars-lang-handlebars.js-0cbc8e4/FAQ.md000066400000000000000000000073351526102233000206750ustar00rootroot00000000000000# Frequently Asked Questions 1. How can I file a bug report: See our guidelines on [reporting issues](https://github.com/handlebars-lang/handlebars.js/blob/master/CONTRIBUTING.md#reporting-issues). 1. Why isn't my Mustache template working? Handlebars deviates from Mustache slightly on a few behaviors. These variations are documented in our [readme](https://github.com/handlebars-lang/handlebars.js#differences-between-handlebarsjs-and-mustache). 1. Why is it slower when compiling? The Handlebars compiler must parse the template and construct a JavaScript program which can then be run. Under some environments such as older mobile devices this can have a performance impact which can be avoided by precompiling. Generally it's recommended that precompilation and the runtime library be used on all clients. 1. Why doesn't this work with Content Security Policy restrictions? When not using the precompiler, Handlebars generates a dynamic function for each template which can cause issues with pages that have enabled Content Policy. It's recommended that templates are precompiled or the `unsafe-eval` policy is enabled for sites that must generate dynamic templates at runtime. 1. How can I include script tags in my template? If loading the template via an inlined ` ``` It's generally recommended that templates are served through external, precompiled, files, which do not suffer from this issue. 1. Why are my precompiled scripts throwing exceptions? When using the precompiler, it's important that a supporting version of the Handlebars runtime be loaded on the target page. In version 1.x there were rudimentary checks to compare the version but these did not always work. This is fixed under 2.x but the version checking does not work between these two versions. If you see unexpected errors such as `undefined is not a function` or similar, please verify that the same version is being used for both the precompiler and the client. This can be checked via: ```sh handlebars --version ``` If using the integrated precompiler and ```javascript console.log(Handlebars.VERSION); ``` On the client side. We include the built client libraries in the npm package for those who want to be certain that they are using the same client libraries as the compiler. Should these match, please file an issue with us, per our [issue filing guidelines](https://github.com/handlebars-lang/handlebars.js/blob/master/CONTRIBUTING.md#reporting-issues). 1. Why doesn't IE like the `default` name in the AMD module? Some browsers such as particular versions of IE treat `default` as a reserved word in JavaScript source files. To safely use this you need to reference this via the `Handlebars['default']` lookup method. This is an unfortunate side effect of the shims necessary to backport the Handlebars ES6 code to all current browsers. 1. How do I load the runtime library when using AMD? There are two options for loading under AMD environments. The first is to use the `handlebars.runtime.amd.js` file. This may require a [path mapping](https://github.com/handlebars-lang/handlebars.js/blob/master/spec/amd-runtime.html#L31) as well as access via the `default` field. The other option is to load the `handlebars.runtime.js` UMD build, which might not require path configuration and exposes the library as both the module root and the `default` field for compatibility. If not using ES6 transpilers or accessing submodules in the build the former option should be sufficient for most use cases. handlebars-lang-handlebars.js-0cbc8e4/Gruntfile.js000066400000000000000000000130531526102233000222330ustar00rootroot00000000000000/* eslint-disable no-process-env */ module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), clean: [ 'tmp', 'dist', 'lib/handlebars/compiler/parser.js', '/tests/integration/**/node_modules' ], copy: { dist: { options: { processContent: function(content) { return ( grunt.template.process( '/**!\n\n @license\n <%= pkg.name %> v<%= pkg.version %>\n\n<%= grunt.file.read("LICENSE") %>\n*/\n' ) + content ); } }, files: [{ expand: true, cwd: 'dist/', src: ['*.js'], dest: 'dist/' }] }, cdnjs: { files: [ { expand: true, cwd: 'dist/', src: ['*.js'], dest: 'dist/cdnjs' } ] }, 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' }, amd: { options: { modules: 'amd' }, files: [ { expand: true, cwd: 'lib/', src: '**/!(index).js', dest: 'dist/amd/' } ] }, cjs: { options: { modules: 'common' }, files: [ { cwd: 'lib/', expand: true, src: '**/!(index).js', dest: 'dist/cjs/' } ] } }, webpack: { options: { context: __dirname, module: { loaders: [ // the optional 'runtime' transformer tells babel to require the runtime instead of inlining it. { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader?optional=runtime&loose=es6.modules&auxiliaryCommentBefore=istanbul%20ignore%20next' } ] }, output: { path: 'dist/', library: 'Handlebars', libraryTarget: 'umd' } }, handlebars: { entry: './lib/handlebars.js', output: { filename: 'handlebars.js' } }, runtime: { entry: './lib/handlebars.runtime.js', output: { filename: 'handlebars.runtime.js' } } }, requirejs: { options: { optimize: 'none', baseUrl: 'dist/amd/' }, dist: { options: { name: 'handlebars', out: 'dist/handlebars.amd.js' } }, runtime: { options: { name: 'handlebars.runtime', out: 'dist/handlebars.runtime.amd.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-requirejs'); 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('amd', ['babel:amd', 'requirejs']); grunt.registerTask('globals', ['webpack']); grunt.registerTask('release', 'Build final packages', [ 'uglify', 'test:min', 'copy:dist', 'copy:components', 'copy:cdnjs' ]); // Requires secret properties from .travis.yaml grunt.registerTask('extensive-tests-and-publish-to-aws', [ 'default', 'shell:integrationTests', 'metrics', 'publish-to-aws' ]); grunt.registerTask('on-file-change', ['build', 'concat:tests', 'test']); // === Primary tasks === grunt.registerTask('dev', ['clean', 'connect', 'watch']); grunt.registerTask('default', ['clean', 'build', 'test', 'release']); grunt.registerTask('test', ['test:bin', 'test:cov']); grunt.registerTask('bench', ['metrics']); grunt.registerTask('prepare', ['build', 'concat:tests']); grunt.registerTask( 'build', 'Builds a distributable version of the current project', ['parser', 'node', 'amd', 'globals'] ); grunt.registerTask('integration-tests', [ 'default', 'shell:integrationTests' ]); }; handlebars-lang-handlebars.js-0cbc8e4/LICENSE000066400000000000000000000020471526102233000207440ustar00rootroot00000000000000Copyright (C) 2011-2019 by Yehuda Katz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. handlebars-lang-handlebars.js-0cbc8e4/README.markdown000066400000000000000000000220161526102233000224360ustar00rootroot00000000000000[![CI Build Status](https://github.com/handlebars-lang/handlebars.js/actions/workflows/ci.yml/badge.svg)](https://github.com/handlebars-lang/handlebars.js/actions/workflows/ci.yml) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/handlebars/badge?style=rounded)](https://www.jsdelivr.com/package/npm/handlebars) [![npm downloads](https://badgen.net/npm/dm/handlebars)](https://www.npmjs.com/package/handlebars) [![npm version](https://badgen.net/npm/v/handlebars)](https://www.npmjs.com/package/handlebars) [![Bundle size](https://badgen.net/bundlephobia/minzip/handlebars?label=minified%20%2B%20gzipped)](https://bundlephobia.com/package/handlebars) [![Install size](https://packagephobia.com/badge?p=handlebars)](https://packagephobia.com/result?p=handlebars) Handlebars.js ============= Handlebars provides the power necessary to let you build **semantic templates** effectively with no frustration. Handlebars is largely compatible with Mustache templates. In most cases it is possible to swap out Mustache with Handlebars and continue using your current templates. Checkout the official Handlebars docs site at [handlebarsjs.com](https://handlebarsjs.com) and try our [live demo](https://handlebarsjs.com/playground.html). Installing ---------- See our [installation documentation](https://handlebarsjs.com/installation/). Usage ----- In general, the syntax of Handlebars.js templates is a superset of Mustache templates. For basic syntax, check out the [Mustache manpage](https://mustache.github.io/mustache.5.html). Once you have a template, use the `Handlebars.compile` method to compile the template into a function. The generated function takes a context argument, which will be used to render the template. ```js var source = "

Hello, my name is {{name}}. I am from {{hometown}}. I have " + "{{kids.length}} kids:

" + ""; var template = Handlebars.compile(source); var data = { "name": "Alan", "hometown": "Somewhere, TX", "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]}; var result = template(data); // Would render: //

Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:

// ``` Full documentation and more examples are at [handlebarsjs.com](https://handlebarsjs.com/). Precompiling Templates ---------------------- Handlebars allows templates to be precompiled and included as javascript code rather than the handlebars template allowing for faster startup time. Full details are located [here](https://handlebarsjs.com/installation/precompilation.html). Differences Between Handlebars.js and Mustache ---------------------------------------------- Handlebars.js adds a couple of additional features to make writing templates easier and also changes a tiny detail of how partials work. - [Nested Paths](https://handlebarsjs.com/guide/expressions.html#path-expressions) - [Helpers](https://handlebarsjs.com/guide/expressions.html#helpers) - [Block Expressions](https://handlebarsjs.com/guide/block-helpers.html#basic-blocks) - [Literal Values](https://handlebarsjs.com/guide/expressions.html#literal-segments) - [Delimited Comments](https://handlebarsjs.com/guide/#template-comments) Block expressions have the same syntax as mustache sections but should not be confused with one another. Sections are akin to an implicit `each` or `with` statement depending on the input data and helpers are explicit pieces of code that are free to implement whatever behavior they like. The [mustache spec](https://mustache.github.io/mustache.5.html) defines the exact behavior of sections. In the case of name conflicts, helpers are given priority. ### Compatibility There are a few Mustache behaviors that Handlebars does not implement. - Handlebars deviates from Mustache slightly in that it does not perform recursive lookup by default. The compile time `compat` flag must be set to enable this functionality. Users should note that there is a performance cost for enabling this flag. The exact cost varies by template, but it's recommended that performance sensitive operations should avoid this mode and instead opt for explicit path references. - The optional Mustache-style lambdas are not supported. Instead Handlebars provides its own lambda resolution that follows the behaviors of helpers. - Alternative delimiters are not supported. Supported Environments ---------------------- Handlebars has been designed to work in any ECMAScript 3 environment. This includes - Node.js - Chrome - Firefox - Safari 5+ - Opera 11+ - IE 6+ Older versions and other runtimes are likely to work but have not been formally tested. The compiler requires `JSON.stringify` to be implemented natively or via a polyfill. If using the precompiler this is not necessary. Performance ----------- In a rough performance test, precompiled Handlebars.js templates (in the original version of Handlebars.js) rendered in about half the time of Mustache templates. It would be a shame if it were any other way, since they were precompiled, but the difference in architecture does have some big performance advantages. Justin Marney, a.k.a. [gotascii](http://github.com/gotascii), confirmed that with an [independent test](http://sorescode.com/2010/09/12/benchmarks.html). The rewritten Handlebars (current version) is faster than the old version, with many performance tests being 5 to 7 times faster than the Mustache equivalent. Upgrading --------- See [release-notes.md](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md) for upgrade notes. Known Issues ------------ See [FAQ.md](https://github.com/handlebars-lang/handlebars.js/blob/master/FAQ.md) for known issues and common pitfalls. Handlebars in the Wild ---------------------- * [Assemble](http://assemble.io), by [@jonschlinkert](https://github.com/jonschlinkert) and [@doowb](https://github.com/doowb), is a static site generator that uses Handlebars.js as its template engine. * [Cory](https://github.com/leo/cory), by [@leo](https://github.com/leo), is another tiny static site generator * [CoSchedule](http://coschedule.com) An editorial calendar for WordPress that uses Handlebars.js * [dashbars](https://github.com/pismute/dashbars) A modern helper library for Handlebars.js. * [Ember.js](http://www.emberjs.com) makes Handlebars.js the primary way to structure your views, also with automatic data binding support. * [Ghost](https://ghost.org/) Just a blogging platform. * [handlebars_assets](http://github.com/leshill/handlebars_assets): A Rails Asset Pipeline gem from Les Hill (@leshill). * [handlebars-helpers](https://github.com/assemble/handlebars-helpers) is an extensive library with 100+ handlebars helpers. * [handlebars-layouts](https://github.com/shannonmoeller/handlebars-layouts) is a set of helpers which implement extendible and embeddable layout blocks as seen in other popular templating languages. * [hbs](http://github.com/donpark/hbs): An Express.js view engine adapter for Handlebars.js, from Don Park. * [koa-hbs](https://github.com/jwilm/koa-hbs): [koa](https://github.com/koajs/koa) generator based renderer for Handlebars.js. * [jblotus](http://github.com/jblotus) created [http://tryhandlebarsjs.com](http://tryhandlebarsjs.com) for anyone who would like to try out Handlebars.js in their browser. * [jQuery plugin](http://71104.github.io/jquery-handlebars/): allows you to use Handlebars.js with [jQuery](http://jquery.com/). * [Lumbar](http://walmartlabs.github.io/lumbar) provides easy module-based template management for handlebars projects. * [Marionette.Handlebars](https://github.com/hashchange/marionette.handlebars) adds support for Handlebars and Mustache templates to Marionette. * [sammy.js](http://github.com/quirkey/sammy) by Aaron Quint, a.k.a. quirkey, supports Handlebars.js as one of its template plugins. * [SproutCore](http://www.sproutcore.com) uses Handlebars.js as its main templating engine, extending it with automatic data binding support. * [YUI](http://yuilibrary.com/yui/docs/handlebars/) implements a port of handlebars * [Swag](https://github.com/elving/swag) by [@elving](https://github.com/elving) is a growing collection of helpers for handlebars.js. Give your handlebars.js templates some swag son! * [DOMBars](https://github.com/blakeembrey/dombars) is a DOM-based templating engine built on the Handlebars parser and runtime **DEPRECATED** * [promised-handlebars](https://github.com/nknapp/promised-handlebars) is a wrapper for Handlebars that allows helpers to return Promises. * [just-handlebars-helpers](https://github.com/leapfrogtechnology/just-handlebars-helpers) A fully tested lightweight package with common Handlebars helpers. External Resources ------------------ * [Gist about Synchronous and asynchronous loading of external handlebars templates](https://gist.github.com/2287070) Have a project using Handlebars? Send us a [pull request][pull-request]! License ------- Handlebars.js is released under the MIT license. [pull-request]: https://github.com/handlebars-lang/handlebars.js/pull/new/master handlebars-lang-handlebars.js-0cbc8e4/bin/000077500000000000000000000000001526102233000205045ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/bin/.eslintrc.js000066400000000000000000000001121526102233000227350ustar00rootroot00000000000000module.exports = { rules: { 'no-console': 0, 'no-var': 0 } }; handlebars-lang-handlebars.js-0cbc8e4/bin/handlebars000077500000000000000000000102741526102233000225410ustar00rootroot00000000000000#!/usr/bin/env node var argv = parseArgs({ 'f': { 'type': 'string', 'description': 'Output File', 'alias': 'output' }, 'map': { 'type': 'string', 'description': 'Source Map File' }, 'a': { 'type': 'boolean', 'description': 'Exports amd style (require.js)', 'alias': 'amd' }, 'c': { 'type': 'string', 'description': 'Exports CommonJS style, path to Handlebars module', 'alias': 'commonjs', 'default': null }, 'h': { 'type': 'string', 'description': 'Path to handlebar.js (only valid for amd-style)', 'alias': 'handlebarPath', 'default': '' }, 'k': { 'type': 'string', 'description': 'Known helpers', 'alias': 'known' }, 'o': { 'type': 'boolean', 'description': 'Known helpers only', 'alias': 'knownOnly' }, 'm': { 'type': 'boolean', 'description': 'Minimize output', 'alias': 'min' }, 'n': { 'type': 'string', 'description': 'Template namespace', 'alias': 'namespace', 'default': 'Handlebars.templates' }, 's': { 'type': 'boolean', 'description': 'Output template function only.', 'alias': 'simple' }, 'N': { 'type': 'string', 'description': 'Name of passed string templates. Optional if running in a simple mode. Required when operating on multiple templates.', 'alias': 'name' }, 'i': { 'type': 'string', 'description': 'Generates a template from the passed CLI argument.\n"-" is treated as a special value and causes stdin to be read for the template value.', 'alias': 'string' }, 'r': { 'type': 'string', 'description': 'Template root. Base value that will be stripped from template names; it does not restrict filesystem access.', 'alias': 'root' }, 'p': { 'type': 'boolean', 'description': 'Compiling a partial template', 'alias': 'partial' }, 'd': { 'type': 'boolean', 'description': 'Include data when compiling', 'alias': 'data' }, 'e': { 'type': 'string', 'description': 'Template extension.', 'alias': 'extension', 'default': 'handlebars' }, 'b': { 'type': 'boolean', 'description': 'Removes the BOM (Byte Order Mark) from the beginning of the templates.', 'alias': 'bom' }, 'v': { 'type': 'boolean', 'description': 'Prints the current compiler version', 'alias': 'version' }, 'help': { 'type': 'boolean', 'description': 'Outputs this message' } }); argv.files = argv._; delete argv._; var Precompiler = require('../dist/cjs/precompiler'); Precompiler.loadTemplates(argv, function(err, opts) { if (err) { throw err; } if (opts.help || (!opts.templates.length && !opts.version)) { printUsage(argv._spec, 120); } else { Precompiler.cli(opts); } }); function pad(n) { var str = ''; while (str.length < n) { str += ' '; } return str; } function parseArgs(spec) { var opts = { alias: {}, boolean: [], default: {}, string: [] }; Object.keys(spec).forEach(function (arg) { var opt = spec[arg]; opts[opt.type].push(arg); if ('alias' in opt) opts.alias[arg] = opt.alias; if ('default' in opt) opts.default[arg] = opt.default; }); var argv = require('minimist')(process.argv.slice(2), opts); argv._spec = spec; return argv; } function printUsage(spec, wrap) { var wordwrap = require('wordwrap'); console.log('Precompile handlebar templates.'); console.log('Usage: handlebars [template|directory]...'); var opts = []; var width = 0; Object.keys(spec).forEach(function (arg) { var opt = spec[arg]; var name = (arg.length === 1 ? '-' : '--') + arg; if ('alias' in opt) name += ', --' + opt.alias; var meta = '[' + opt.type + ']'; if ('default' in opt) meta += ' [default: ' + JSON.stringify(opt.default) + ']'; opts.push({ name: name, desc: opt.description, meta: meta }); if (name.length > width) width = name.length; }); console.log('Options:'); opts.forEach(function (opt) { var desc = wordwrap(width + 4, wrap + 1)(opt.desc); console.log(' %s%s%s%s%s', opt.name, pad(width - opt.name.length + 2), desc.slice(width + 4), pad(wrap - opt.meta.length - desc.split(/\n/).pop().length), opt.meta ); }); } handlebars-lang-handlebars.js-0cbc8e4/components/000077500000000000000000000000001526102233000221215ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/components/bower.json000066400000000000000000000001671526102233000241360ustar00rootroot00000000000000{ "name": "handlebars", "version": "4.7.10", "main": "handlebars.js", "license": "MIT", "dependencies": {} } handlebars-lang-handlebars.js-0cbc8e4/components/component.json000066400000000000000000000002321526102233000250130ustar00rootroot00000000000000{ "name": "handlebars", "repo": "components/handlebars.js", "version": "1.0.0", "main": "handlebars.js", "scripts": [ "handlebars.js" ] } handlebars-lang-handlebars.js-0cbc8e4/components/composer.json000066400000000000000000000014111526102233000246400ustar00rootroot00000000000000{ "name": "components/handlebars.js", "description": "Handlebars.js and Mustache are both logicless templating languages that keep the view and the code separated like we all know they should be.", "homepage": "https://handlebarsjs.com", "license": "MIT", "type": "component", "keywords": [ "handlebars", "mustache", "html" ], "authors": [ { "name": "Chris Wanstrath" } ], "extra": { "component": { "name": "handlebars", "scripts": [ "handlebars.js" ], "files": [ "handlebars.runtime.js" ], "shim": { "exports": "Handlebars" } } } } handlebars-lang-handlebars.js-0cbc8e4/components/handlebars-source.gemspec000066400000000000000000000013011526102233000270620ustar00rootroot00000000000000# -*- encoding: utf-8 -*- require 'json' package = JSON.parse(File.read('bower.json')) Gem::Specification.new do |gem| gem.name = "handlebars-source" gem.authors = ["Yehuda Katz"] gem.email = ["wycats@gmail.com"] gem.date = Time.now.strftime("%Y-%m-%d") gem.description = %q{Handlebars.js source code wrapper for (pre)compilation gems.} gem.summary = %q{Handlebars.js source code wrapper} gem.homepage = "https://github.com/handlebars-lang/handlebars.js/" gem.version = package["version"].sub "-", "." gem.license = "MIT" gem.files = [ 'handlebars.js', 'handlebars.runtime.js', 'lib/handlebars/source.rb' ] end handlebars-lang-handlebars.js-0cbc8e4/components/handlebars.js.nuspec000066400000000000000000000011751526102233000260620ustar00rootroot00000000000000 handlebars.js 4.7.10 handlebars.js Authors https://github.com/handlebars-lang/handlebars.js/blob/master/LICENSE https://github.com/handlebars-lang/handlebars.js/ false Extension of the Mustache logicless template language handlebars mustache template html handlebars-lang-handlebars.js-0cbc8e4/components/lib/000077500000000000000000000000001526102233000226675ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/components/lib/handlebars/000077500000000000000000000000001526102233000247725ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/components/lib/handlebars/source.rb000066400000000000000000000003671526102233000266250ustar00rootroot00000000000000module Handlebars module Source def self.bundled_path File.expand_path("../../../handlebars.js", __FILE__) end def self.runtime_bundled_path File.expand_path("../../../handlebars.runtime.js", __FILE__) end end end handlebars-lang-handlebars.js-0cbc8e4/components/package.json000066400000000000000000000004771526102233000244170ustar00rootroot00000000000000{ "name": "handlebars", "version": "4.7.10", "license": "MIT", "jspm": { "main": "handlebars", "shim": { "handlebars": { "exports": "Handlebars" } }, "files": [ "handlebars.js", "handlebars.runtime.js" ], "buildConfig": { "minify": true } } } handlebars-lang-handlebars.js-0cbc8e4/docs/000077500000000000000000000000001526102233000206645ustar00rootroot00000000000000handlebars-lang-handlebars.js-0cbc8e4/docs/compiler-api.md000066400000000000000000000260241526102233000235730ustar00rootroot00000000000000# Handlebars Compiler APIs There are a number of formal APIs that tool implementors may interact with. ## AST Other tools may interact with the formal AST as defined below. An AST built by your application that matches this pattern may be passed into the `compile` and `precompile` methods in the same way as the text for a template. AST structures may be generated either with the `Handlebars.parse` method and then manipulated, via the `Handlebars.AST` objects of the same name, or constructed manually as a generic JavaScript object matching the structure defined below. **Security:** `compile` and `precompile` turn an AST into JavaScript, so treat it like code. Only pass ASTs that your application built itself. Never pass an AST that comes from untrusted input, such as JSON from a request body or from storage that users can write to. The compiler hardens the values it writes into generated code, but that is defense in depth, not a guarantee. To cache or transfer templates, store the template source and parse it where it is compiled. ```javascript var ast = Handlebars.parse(myTemplate); // Modify ast Handlebars.precompile(ast); ``` ### Parsing There are two primary APIs that are used to parse an existing template into the AST: #### parseWithoutProcessing `Handlebars.parseWithoutProcessing` is the primary mechanism to turn a raw template string into the Handlebars AST described in this document. No processing is done on the resulting AST which makes this ideal for codemod (for source to source transformation) tooling. Example: ```js let ast = Handlebars.parseWithoutProcessing(myTemplate); ``` #### parse `Handlebars.parse` will parse the template with `parseWithoutProcessing` (see above) then it will update the AST to strip extraneous whitespace. The whitespace stripping functionality handles two distinct situations: * Removes whitespace around dynamic statements that are on a line by themselves (aka "stand alone") * Applies "whitespace control" characters (i.e. `~`) by truncating the `ContentStatement` `value` property appropriately (e.g. `\n\n{{~foo}}` would have a `ContentStatement` with a `value` of `''`) `Handlebars.parse` is used internally by `Handlebars.precompile` and `Handlebars.compile`. Example: ```js let ast = Handlebars.parse(myTemplate); ``` ### Basic ```java interface Node { type: string; loc: SourceLocation | null; } interface SourceLocation { source: string | null; start: Position; end: Position; } interface Position { line: uint >= 1; column: uint >= 0; } ``` ### Programs ```java interface Program <: Node { type: "Program"; body: [ Statement ]; blockParams: [ string ]; } ``` ### Statements ```java interface Statement <: Node { } interface MustacheStatement <: Statement { type: "MustacheStatement"; path: PathExpression | Literal; params: [ Expression ]; hash: Hash; escaped: boolean; strip: StripFlags | null; } interface BlockStatement <: Statement { type: "BlockStatement"; path: PathExpression | Literal; params: [ Expression ]; hash: Hash; program: Program | null; inverse: Program | null; openStrip: StripFlags | null; inverseStrip: StripFlags | null; closeStrip: StripFlags | null; } interface PartialStatement <: Statement { type: "PartialStatement"; name: PathExpression | SubExpression; params: [ Expression ]; hash: Hash; indent: string; strip: StripFlags | null; } interface PartialBlockStatement <: Statement { type: "PartialBlockStatement"; name: PathExpression | SubExpression; params: [ Expression ]; hash: Hash; program: Program | null; indent: string; openStrip: StripFlags | null; closeStrip: StripFlags | null; } ``` `name` will be a `SubExpression` when tied to a dynamic partial, i.e. `{{> (foo) }}`, otherwise this is a path or literal whose `original` value is used to lookup the desired partial. ```java interface ContentStatement <: Statement { type: "ContentStatement"; value: string; original: string; } interface CommentStatement <: Statement { type: "CommentStatement"; value: string; strip: StripFlags | null; } ``` ```java interface Decorator <: Statement { type: "Decorator"; path: PathExpression | Literal; params: [ Expression ]; hash: Hash; strip: StripFlags | null; } interface DecoratorBlock <: Statement { type: "DecoratorBlock"; path: PathExpression | Literal; params: [ Expression ]; hash: Hash; program: Program | null; openStrip: StripFlags | null; closeStrip: StripFlags | null; } ``` Decorator paths only utilize the `path.original` value and as a consequence do not support depthed evaluation. ### Expressions ```java interface Expression <: Node { } ``` ##### SubExpressions ```java interface SubExpression <: Expression { type: "SubExpression"; path: PathExpression; params: [ Expression ]; hash: Hash; } ``` ##### Paths ```java interface PathExpression <: Expression { type: "PathExpression"; data: boolean; depth: uint >= 0; parts: [ string ]; original: string; } ``` - `data` is true when the given expression is a `@data` reference. - `depth` is an integer representation of which context the expression references. `0` represents the current context, `1` would be `../`, etc. - `parts` is an array of the names in the path. `foo.bar` would be `['foo', 'bar']`. Scope references, `.`, `..`, and `this` should be omitted from this array. - `original` is the path as entered by the user. Separator and scope references are left untouched. ##### Literals ```java interface Literal <: Expression { } interface StringLiteral <: Literal { type: "StringLiteral"; value: string; original: string; } interface BooleanLiteral <: Literal { type: "BooleanLiteral"; value: boolean; original: boolean; } interface NumberLiteral <: Literal { type: "NumberLiteral"; value: number; original: number; } interface UndefinedLiteral <: Literal { type: "UndefinedLiteral"; } interface NullLiteral <: Literal { type: "NullLiteral"; } ``` ### Miscellaneous ```java interface Hash <: Node { type: "Hash"; pairs: [ HashPair ]; } interface HashPair <: Node { type: "HashPair"; key: string; value: Expression; } interface StripFlags { open: boolean; close: boolean; } ``` `StripFlags` are used to signify whitespace control character that may have been entered on a given statement. ## AST Visitor `Handlebars.Visitor` is available as a base class for general interaction with AST structures. This will by default traverse the entire tree and individual methods may be overridden to provide specific responses to particular nodes. Recording all referenced partial names: ```javascript var Visitor = Handlebars.Visitor; function ImportScanner() { this.partials = []; } ImportScanner.prototype = new Visitor(); ImportScanner.prototype.PartialStatement = function(partial) { this.partials.push({request: partial.name.original}); Visitor.prototype.PartialStatement.call(this, partial); }; var scanner = new ImportScanner(); scanner.accept(ast); ``` The current node's ancestors will be maintained in the `parents` array, with the most recent parent listed first. A visitor only dispatches on the node types produced by the parser, plus any additional types for which it defines a handler method of its own. Nodes of any other type, including types that collide with `Visitor` methods such as `accept`, cause an `Unknown type` exception. The visitor may also be configured to operate in mutation mode by setting the `mutation` field to true. When in this mode, handler methods may return any valid AST node and it will replace the one they are currently operating on. Returning `false` will remove the given value (if valid) and returning `undefined` will leave the node in tact. This return structure only apply to mutation mode and non-mutation mode visitors are free to return whatever values they wish. Implementors that may need to support mutation mode are encouraged to utilize the `acceptKey`, `acceptRequired` and `acceptArray` helpers which provide the conditional overwrite behavior as well as implement sanity checks where pertinent. ## JavaScript Compiler The `Handlebars.JavaScriptCompiler` object has a number of methods that may be customized to alter the output of the compiler: - `nameLookup(parent, name, type)` Used to generate the code to resolve a give path component. - `parent` is the existing code in the path resolution - `name` is the current path component - `type` is the type of name being evaluated. May be one of `context`, `data`, `helper`, `decorator`, or `partial`. Note that this does not impact dynamic partials, which implementors need to be aware of. Overriding `VM.resolvePartial` may be required to support dynamic cases. - `depthedLookup(name)` Used to generate code that resolves parameters within any context in the stack. Is only used in `compat` mode. - `compilerInfo()` Allows for custom compiler flags used in the runtime version checking logic. - `appendToBuffer(source, location, explicit)` Allows for code buffer emitting code. Defaults behavior is string concatenation. - `source` is the source code whose result is to be appending - `location` is the location of the source in the source map. - `explicit` is a flag signaling that the emit operation must occur, vs. the lazy evaled options otherwise. - `initializeBuffer()` Allows for buffers other than the default string buffer to be used. Generally needs to be paired with a custom `appendToBuffer` implementation. ### Example for the compiler api. This example changes all lookups of properties are performed by a helper (`lookupLowerCase`) which looks for `test` if `{{Test}}` occurs in the template. This is just to illustrate how compiler behavior can be change. Names and other strings from the template must be written into the generated code with `this.quotedString()`, as in the example. It escapes them so that the code stays safe to inline in a `