├── .husky
└── pre-commit
├── .prettierrc
├── src
├── .vitepress
│ ├── components
│ │ ├── playground
│ │ │ ├── lib
│ │ │ │ ├── codemirror-languages
│ │ │ │ │ ├── .gitignore
│ │ │ │ │ ├── readme.md
│ │ │ │ │ ├── js-object.js
│ │ │ │ │ ├── handlebars.js
│ │ │ │ │ └── js-object.grammar
│ │ │ │ ├── prettify.js
│ │ │ │ ├── utils.js
│ │ │ │ ├── in-browser-example-executor
│ │ │ │ │ ├── worker.js
│ │ │ │ │ ├── execute-one-after-another.js
│ │ │ │ │ ├── limit-waiting-time.js
│ │ │ │ │ ├── lazy-get-handlebars.js
│ │ │ │ │ ├── client.js
│ │ │ │ │ ├── worker-with-termination-timeout.js
│ │ │ │ │ ├── execute-one-after-another.test.js
│ │ │ │ │ └── limit-waiting-time.test.js
│ │ │ │ ├── share-utils.js
│ │ │ │ ├── execute-example.js
│ │ │ │ ├── execute-example.test.js
│ │ │ │ └── example-parser.js
│ │ │ ├── WorkspaceError.vue
│ │ │ ├── HandlebarsVersionChooser.vue
│ │ │ ├── ExportYamlModal.vue
│ │ │ ├── WorkspaceElement.vue
│ │ │ ├── HighlightedCode.vue
│ │ │ ├── CodeEditor.vue
│ │ │ ├── WorkspaceElementDecorator.vue
│ │ │ ├── Modal.vue
│ │ │ └── ShareUrlModal.vue
│ │ ├── Flex.vue
│ │ ├── PlaygroundLayout.vue
│ │ ├── TryoutIcon.vue
│ │ └── DownloadHandlebars.vue
│ ├── lib
│ │ ├── handlebars-versions.js
│ │ └── handlebars-cli-help.js
│ └── theme
│ │ └── index.js
├── snippets
│ ├── precompilation
│ │ ├── example.handlebars
│ │ ├── build.sh
│ │ ├── precompile-in-nodejs.js
│ │ ├── index.html
│ │ ├── precompile-in-nodejs.output.js
│ │ └── example.precompiled.js
│ └── compiler-and-runtime
│ │ ├── simple-console-out.html
│ │ └── index.html
├── public
│ ├── favicon.png
│ ├── handlebars-logo.png
│ └── manifest.json
├── examples.data.js
├── examples
│ ├── partials
│ │ ├── failover.md
│ │ ├── basic.md
│ │ ├── partial-block.md
│ │ ├── variable.md
│ │ ├── parameters.md
│ │ ├── other-context.md
│ │ ├── dynamic.md
│ │ ├── inline.md
│ │ ├── partial-block-parameters.md
│ │ ├── register.md
│ │ ├── inline-blocks.md
│ │ ├── parent-context.md
│ │ └── partials.md
│ ├── hook-helper-missing-default-no-param.md
│ ├── simple-expressions.md
│ ├── hook-helper-missing-default-param.md
│ ├── html-escaping.md
│ ├── builtin-helper-log.md
│ ├── path-expressions-dot.md
│ ├── path-expressions-slash.md
│ ├── builtin-helper-eachelse-block.md
│ ├── builtin-helper-with-block.md
│ ├── hook-block-helper-missing-default.md
│ ├── comments.md
│ ├── builtin-helper-unless-block.md
│ ├── builtin-helper-log-multiple-params.md
│ ├── raw-blocks.md
│ ├── builtin-helper-if-block.md
│ ├── path-expressions-dot-dot.md
│ ├── builtin-helper-with-else.md
│ ├── builtin-helper-lookup.md
│ ├── builtin-helper-each-block.md
│ ├── helper-simple.md
│ ├── helper-data-name-conflict.md
│ ├── builtin-helper-ifelse-block.md
│ ├── path-expressions-dot-dot-if.md
│ ├── builtin-helper-if-subexpression.md
│ ├── helper-safestring.md
│ ├── each-with.md
│ ├── hook-block-helper-missing.md
│ ├── helper-this-context.md
│ ├── helper-multiple-parameters.md
│ ├── literal-segments.md
│ ├── builtin-helper-with-block-param.md
│ ├── helper-lookup-property.md
│ ├── hook-helper-missing.md
│ ├── helper-literals.md
│ ├── helper-block.md
│ ├── helper-dynamic-parameters.md
│ ├── builtin-helper-lookup-dynamic-property.md
│ ├── builtin-helper-log-loglevel.md
│ ├── all-features.md
│ ├── helper-hash-arguments.md
│ └── _example-base-data.yaml
├── ko
│ ├── examples
│ │ ├── partials
│ │ │ ├── failover.md
│ │ │ ├── basic.md
│ │ │ ├── partial-block.md
│ │ │ ├── variable.md
│ │ │ ├── parameters.md
│ │ │ ├── other-context.md
│ │ │ ├── dynamic.md
│ │ │ ├── inline.md
│ │ │ ├── partial-block-parameters.md
│ │ │ ├── inline-blocks.md
│ │ │ ├── parent-context.md
│ │ │ ├── register.md
│ │ │ └── partials.md
│ │ ├── hook-helper-missing-default-no-param.md
│ │ ├── simple-expressions.md
│ │ ├── hook-helper-missing-default-param.md
│ │ ├── html-escaping.md
│ │ ├── builtin-helper-log.md
│ │ ├── path-expressions-dot.md
│ │ ├── path-expressions-slash.md
│ │ ├── builtin-helper-eachelse-block.md
│ │ ├── builtin-helper-with-block.md
│ │ ├── hook-block-helper-missing-default.md
│ │ ├── comments.md
│ │ ├── builtin-helper-unless-block.md
│ │ ├── builtin-helper-log-multiple-params.md
│ │ ├── raw-blocks.md
│ │ ├── builtin-helper-if-block.md
│ │ ├── path-expressions-dot-dot.md
│ │ ├── builtin-helper-with-else.md
│ │ ├── builtin-helper-lookup.md
│ │ ├── builtin-helper-each-block.md
│ │ ├── helper-simple.md
│ │ ├── helper-data-name-conflict.md
│ │ ├── builtin-helper-ifelse-block.md
│ │ ├── path-expressions-dot-dot-if.md
│ │ ├── builtin-helper-if-subexpression.md
│ │ ├── helper-safestring.md
│ │ ├── each-with.md
│ │ ├── helper-this-context.md
│ │ ├── literal-segments.md
│ │ ├── hook-block-helper-missing.md
│ │ ├── helper-multiple-parameters.md
│ │ ├── builtin-helper-with-block-param.md
│ │ ├── helper-lookup-property.md
│ │ ├── hook-helper-missing.md
│ │ ├── helper-literals.md
│ │ ├── helper-block.md
│ │ ├── helper-dynamic-parameters.md
│ │ ├── builtin-helper-lookup-dynamic-property.md
│ │ ├── builtin-helper-log-loglevel.md
│ │ ├── all-features.md
│ │ ├── helper-hash-arguments.md
│ │ └── _example-base-data.yaml
│ ├── api-reference
│ │ ├── index.md
│ │ ├── helpers.md
│ │ ├── data-variables.md
│ │ ├── compilation.md
│ │ ├── utilities.md
│ │ └── runtime.md
│ ├── playground.md
│ ├── index.md
│ ├── guide
│ │ ├── installation
│ │ │ ├── when-to-use-handlebars.md
│ │ │ ├── integrations.md
│ │ │ └── precompilation.md
│ │ ├── hooks.md
│ │ └── partials.md
│ └── contributing
│ │ ├── index.md
│ │ └── interactive-examples.md
├── zh
│ ├── examples
│ │ ├── partials
│ │ │ ├── failover.md
│ │ │ ├── basic.md
│ │ │ ├── partial-block.md
│ │ │ ├── variable.md
│ │ │ ├── parameters.md
│ │ │ ├── other-context.md
│ │ │ ├── dynamic.md
│ │ │ ├── inline.md
│ │ │ ├── partial-block-parameters.md
│ │ │ ├── inline-blocks.md
│ │ │ ├── parent-context.md
│ │ │ ├── register.md
│ │ │ └── partials.md
│ │ ├── hook-helper-missing-default-no-param.md
│ │ ├── simple-expressions.md
│ │ ├── hook-helper-missing-default-param.md
│ │ ├── html-escaping.md
│ │ ├── builtin-helper-log.md
│ │ ├── path-expressions-dot.md
│ │ ├── path-expressions-slash.md
│ │ ├── builtin-helper-eachelse-block.md
│ │ ├── builtin-helper-with-block.md
│ │ ├── hook-block-helper-missing-default.md
│ │ ├── comments.md
│ │ ├── builtin-helper-unless-block.md
│ │ ├── builtin-helper-log-multiple-params.md
│ │ ├── raw-blocks.md
│ │ ├── builtin-helper-if-block.md
│ │ ├── path-expressions-dot-dot.md
│ │ ├── builtin-helper-with-else.md
│ │ ├── builtin-helper-lookup.md
│ │ ├── builtin-helper-each-block.md
│ │ ├── helper-simple.md
│ │ ├── helper-data-name-conflict.md
│ │ ├── builtin-helper-ifelse-block.md
│ │ ├── path-expressions-dot-dot-if.md
│ │ ├── builtin-helper-if-subexpression.md
│ │ ├── helper-safestring.md
│ │ ├── each-with.md
│ │ ├── helper-this-context.md
│ │ ├── literal-segments.md
│ │ ├── hook-block-helper-missing.md
│ │ ├── helper-multiple-parameters.md
│ │ ├── builtin-helper-with-block-param.md
│ │ ├── helper-lookup-property.md
│ │ ├── hook-helper-missing.md
│ │ ├── helper-literals.md
│ │ ├── helper-block.md
│ │ ├── helper-dynamic-parameters.md
│ │ ├── builtin-helper-lookup-dynamic-property.md
│ │ ├── builtin-helper-log-loglevel.md
│ │ ├── all-features.md
│ │ ├── helper-hash-arguments.md
│ │ └── _example-base-data.yaml
│ ├── api-reference
│ │ ├── index.md
│ │ ├── helpers.md
│ │ ├── data-variables.md
│ │ ├── compilation.md
│ │ ├── utilities.md
│ │ ├── runtime.md
│ │ └── runtime-options.md
│ ├── playground.md
│ ├── index.md
│ ├── guide
│ │ ├── installation
│ │ │ ├── when-to-use-handlebars.md
│ │ │ ├── integrations.md
│ │ │ └── precompilation.md
│ │ ├── hooks.md
│ │ └── partials.md
│ └── contributing
│ │ ├── index.md
│ │ └── interactive-examples.md
├── handlebars.data.js
├── playground.md
├── api-reference
│ ├── helpers.md
│ ├── index.md
│ ├── data-variables.md
│ ├── compilation.md
│ └── utilities.md
├── index.md
└── guide
│ ├── installation
│ ├── when-to-use-handlebars.md
│ └── integrations.md
│ └── hooks.md
├── .gitignore
├── .prettierignore
├── .github
└── workflows
│ ├── ci.yml
│ └── build-and-deploy.yml
├── README.md
├── LICENSE
└── package.json
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npm run lint-staged
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "proseWrap": "always"
4 | }
5 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/codemirror-languages/.gitignore:
--------------------------------------------------------------------------------
1 | *.terms.js
--------------------------------------------------------------------------------
/src/snippets/precompilation/example.handlebars:
--------------------------------------------------------------------------------
1 | Handlebars {{doesWhat}} precompiled!
--------------------------------------------------------------------------------
/src/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/handlebars-lang/docs/HEAD/src/public/favicon.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /src/.vitepress/.temp
2 | /src/.vitepress/cache
3 | /src/.vitepress/dist
4 | /node_modules
5 | /target
--------------------------------------------------------------------------------
/src/public/handlebars-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/handlebars-lang/docs/HEAD/src/public/handlebars-logo.png
--------------------------------------------------------------------------------
/src/examples.data.js:
--------------------------------------------------------------------------------
1 | import { createContentLoader } from "vitepress";
2 |
3 | export default createContentLoader("**/examples/**/*.md");
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | !.vitepress
2 | /src/snippets/precompilation/example.precompiled.js
3 | /src/snippets/precompilation/precompile-in-nodejs.output.js
4 |
--------------------------------------------------------------------------------
/src/snippets/precompilation/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd "$( dirname "$(readlink -f "$0" )" )" || exit 1
4 |
5 | npx handlebars example.handlebars -f example.precompiled.js
--------------------------------------------------------------------------------
/src/examples/partials/failover.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#> myPartial }}
6 | Failover content
7 | {{/myPartial}}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/failover.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#> myPartial }}
6 | Failover content
7 | {{/myPartial}}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/failover.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#> myPartial }}
6 | Failover content
7 | {{/myPartial}}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/examples/hook-helper-missing-default-no-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | some_{{foo}}mustache
6 | some_{{#foo}}abc{{/foo}}block
7 | input: {}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/examples/simple-expressions.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 |
{{firstname}} {{lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/hook-helper-missing-default-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{foo bar}}
6 | {{#foo bar}}abc{{/foo}}
7 | input: {}
8 | errorExpected: true
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/hook-helper-missing-default-no-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | some_{{foo}}mustache
6 | some_{{#foo}}abc{{/foo}}block
7 | input: {}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/zh/examples/hook-helper-missing-default-no-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | some_{{foo}}mustache
6 | some_{{#foo}}abc{{/foo}}block
7 | input: {}
8 | ---
9 |
--------------------------------------------------------------------------------
/src/examples/html-escaping.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | raw: {{{specialChars}}}
6 | html-escaped: {{specialChars}}
7 | input:
8 | specialChars: '& < > " '' ` ='
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/simple-expressions.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{firstname}} {{lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/simple-expressions.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{firstname}} {{lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-log.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |+
5 | {{log 'this is a simple log output'}}
6 | input:
7 | ---
8 |
9 | Press F12 and open the dev-console to see the log output.
10 |
--------------------------------------------------------------------------------
/src/snippets/precompilation/precompile-in-nodejs.js:
--------------------------------------------------------------------------------
1 | let template = "Handlebars {{doesWhat}} precompiled!";
2 | let Handlebars = require("handlebars");
3 | let compiled = Handlebars.precompile(template);
4 | console.log(compiled);
5 |
--------------------------------------------------------------------------------
/src/ko/examples/hook-helper-missing-default-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{foo bar}}
6 | {{#foo bar}}abc{{/foo}}
7 | input: {}
8 | errorExpected: true
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/hook-helper-missing-default-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{foo bar}}
6 | {{#foo bar}}abc{{/foo}}
7 | input: {}
8 | errorExpected: true
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/partials/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: "{{> myPartial }}"
5 | preparationScript: |
6 | Handlebars.registerPartial('myPartial', '{{prefix}}');
7 | input:
8 | prefix: Hello
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/partials/partial-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#> layout }}
6 | My Content
7 | {{/layout}}
8 | partials:
9 | layout: Site Content {{> @partial-block }}
10 | ---
11 |
--------------------------------------------------------------------------------
/src/examples/partials/variable.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{> (lookup . 'myVariable') }}
6 | partials:
7 | lookupMyPartial: Found!
8 | input:
9 | myVariable: lookupMyPartial
10 | ---
11 |
--------------------------------------------------------------------------------
/src/ko/examples/html-escaping.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | raw: {{{specialChars}}}
6 | html-escaped: {{specialChars}}
7 | input:
8 | specialChars: '& < > " '' ` ='
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/html-escaping.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | raw: {{{specialChars}}}
6 | html-escaped: {{specialChars}}
7 | input:
8 | specialChars: '& < > " '' ` ='
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/partials/parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: "{{> myPartial parameter=favoriteNumber }}"
5 | partials:
6 | myPartial: "The result is {{parameter}}"
7 | input:
8 | favoriteNumber: 123
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-log.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{log 'this is a simple log output'}}
6 | input:
7 | ---
8 |
9 | Press F12 and open the dev-console to see the log output.
10 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-log.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{log 'this is a simple log output'}}
6 | input:
7 | ---
8 |
9 | Press F12 and open the dev-console to see the log output.
10 |
--------------------------------------------------------------------------------
/src/examples/path-expressions-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{person.firstname}} {{person.lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/examples/path-expressions-slash.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{person/firstname}} {{person/lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-eachelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#each paragraphs}}
6 | {{this}}
7 | {{else}}
8 | No content
9 | {{/each}}
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial }}"
5 | preparationScript: |
6 | Handlebars.registerPartial('myPartial', '{{prefix}}');
7 | input:
8 | prefix: Hello
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/partial-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#> layout }}
6 | My Content
7 | {{/layout}}
8 | partials:
9 | layout: Site Content {{> @partial-block }}
10 | ---
11 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/variable.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{> (lookup . 'myVariable') }}
6 | partials:
7 | lookupMyPartial: Found!
8 | input:
9 | myVariable: lookupMyPartial
10 | ---
11 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial }}"
5 | preparationScript: |
6 | Handlebars.registerPartial('myPartial', '{{prefix}}');
7 | input:
8 | prefix: Hello
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/partial-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#> layout }}
6 | My Content
7 | {{/layout}}
8 | partials:
9 | layout: Site Content {{> @partial-block }}
10 | ---
11 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/variable.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{> (lookup . 'myVariable') }}
6 | partials:
7 | lookupMyPartial: Found!
8 | input:
9 | myVariable: lookupMyPartial
10 | ---
11 |
--------------------------------------------------------------------------------
/src/examples/partials/other-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: "{{> myPartial myOtherContext }}"
5 | partials:
6 | myPartial: "{{information}}"
7 | input:
8 | myOtherContext:
9 | information: Interesting!
10 | ---
11 |
--------------------------------------------------------------------------------
/src/ko/api-reference/index.md:
--------------------------------------------------------------------------------
1 | # 인덱스
2 |
3 | - [(사전) 컴파일](compilation.md)
4 | - [런타임](runtime.md)
5 | - [유틸리티](utilities.md)
6 | - [헬퍼 유틸리티](utilities.md#helper-utilities)
7 | - [일반 유틸리티](utilities.md#general-utilities)
8 | - [내장 헬퍼에서 사용하는 `@data` 변수](data-variables.md)
9 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial parameter=favoriteNumber }}"
5 | partials:
6 | myPartial: "The result is {{parameter}}"
7 | input:
8 | favoriteNumber: 123
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial parameter=favoriteNumber }}"
5 | partials:
6 | myPartial: "The result is {{parameter}}"
7 | input:
8 | favoriteNumber: 123
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-with-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |+
5 | {{#with person}}
6 | {{firstname}} {{lastname}}
7 | {{/with}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/ko/examples/path-expressions-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{person.firstname}} {{person.lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/ko/examples/path-expressions-slash.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{person/firstname}} {{person/lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/zh/api-reference/index.md:
--------------------------------------------------------------------------------
1 | # 索引
2 |
3 | - [编译和预编译](compilation.md)
4 | - [运行时](runtime.md)
5 | - [Utilities](utilities.md)
6 | - [Helper utilities](utilities.md#助手代码实用方法)
7 | - [General utilities](utilities.md#general-utilities)
8 | - [内置助手代码使用的 `@data` 变量](data-variables.md)
9 |
--------------------------------------------------------------------------------
/src/zh/examples/path-expressions-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{person.firstname}} {{person.lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/zh/examples/path-expressions-slash.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{person/firstname}} {{person/lastname}}
6 | partials:
7 | input:
8 | person:
9 | firstname: Yehuda
10 | lastname: Katz
11 | ---
12 |
--------------------------------------------------------------------------------
/src/examples/hook-block-helper-missing-default.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-eachelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#each paragraphs}}
6 | {{this}}
7 | {{else}}
8 | No content
9 | {{/each}}
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-eachelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#each paragraphs}}
6 | {{this}}
7 | {{else}}
8 | No content
9 | {{/each}}
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/other-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial myOtherContext }}"
5 | partials:
6 | myPartial: "{{information}}"
7 | input:
8 | myOtherContext:
9 | information: Interesting!
10 | ---
11 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/other-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> myPartial myOtherContext }}"
5 | partials:
6 | myPartial: "{{information}}"
7 | input:
8 | myOtherContext:
9 | information: Interesting!
10 | ---
11 |
--------------------------------------------------------------------------------
/src/examples/comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{! This comment will not show up in the output}}
6 |
7 | {{!-- This comment may contain mustaches like }} --}}
8 | input: {}
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-with-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#with person}}
6 | {{firstname}} {{lastname}}
7 | {{/with}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-with-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#with person}}
6 | {{firstname}} {{lastname}}
7 | {{/with}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-unless-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 |
6 | {{#unless license}}
7 |
WARNING: This entry does not have a license!
8 | {{/unless}}
9 |
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/ko/examples/hook-block-helper-missing-default.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/zh/examples/hook-block-helper-missing-default.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | input:
9 | person:
10 | firstname: Yehuda
11 | lastname: Katz
12 | ---
13 |
--------------------------------------------------------------------------------
/src/examples/partials/dynamic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: "{{> (whichPartial) }}"
5 | preparationScript: |
6 | Handlebars.registerHelper('whichPartial', function(context, options) { return 'dynamicPartial' });
7 | partials:
8 | dynamicPartial: Dynamo!
9 | ---
10 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-log-multiple-params.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |+
5 | {{log 'firstname' firstname 'lastname' lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
11 | Press F12 and open the dev-console to see the log output.
12 |
--------------------------------------------------------------------------------
/src/ko/examples/comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{! This comment will not show up in the output}}
6 |
7 | {{!-- This comment may contain mustaches like }} --}}
8 | input: {}
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{! This comment will not show up in the output}}
6 |
7 | {{!-- This comment may contain mustaches like }} --}}
8 | input: {}
9 | ---
10 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/codemirror-languages/readme.md:
--------------------------------------------------------------------------------
1 | # CodeMirror Languages
2 |
3 | This folder contains custom CodeMirror languages and its parsers.
4 |
5 | If you change the grammar, you have to rebuild the parser:
6 |
7 | - `npm run codemirror:lang-handlebars`
8 | - `npm run codemirror:lang-js-object`
9 |
--------------------------------------------------------------------------------
/src/examples/raw-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{{{raw-loud}}}}
6 | {{bar}}
7 | {{{{/raw-loud}}}}
8 | preparationScript: |
9 | Handlebars.registerHelper('raw-loud', function(options) {
10 | return options.fn().toUpperCase()
11 | });
12 | ---
13 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-unless-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#unless license}}
7 |
WARNING: This entry does not have a license!
8 | {{/unless}}
9 |
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-unless-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#unless license}}
7 |
WARNING: This entry does not have a license!
8 | {{/unless}}
9 |
10 | input: {}
11 | ---
12 |
--------------------------------------------------------------------------------
/src/.vitepress/components/Flex.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
18 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-if-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{/if}}
9 |
10 | input:
11 | author: true
12 | firstName: Yehuda
13 | lastName: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/examples/path-expressions-dot-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{../prefix}} {{firstname}}
7 | {{/each}}
8 | partials:
9 | input:
10 | people:
11 | - firstname: Nils
12 | - firstname: Yehuda
13 | prefix: "Hello"
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/dynamic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> (whichPartial) }}"
5 | preparationScript: |
6 | Handlebars.registerHelper('whichPartial', function(context, options) { return 'dynamicPartial' });
7 | partials:
8 | dynamicPartial: Dynamo!
9 | ---
10 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/dynamic.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: "{{> (whichPartial) }}"
5 | preparationScript: |
6 | Handlebars.registerHelper('whichPartial', function(context, options) { return 'dynamicPartial' });
7 | partials:
8 | dynamicPartial: Dynamo!
9 | ---
10 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-log-multiple-params.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{log 'firstname' firstname 'lastname' lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
11 | Press F12 and open the dev-console to see the log output.
12 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-log-multiple-params.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{log 'firstname' firstname 'lastname' lastname}}
6 | input:
7 | firstname: Yehuda
8 | lastname: Katz
9 | ---
10 |
11 | Press F12 and open the dev-console to see the log output.
12 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-with-else.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |+
5 | {{#with city}}
6 | {{city.name}} (not shown because there is no city)
7 | {{else}}
8 | No city found
9 | {{/with}}
10 | input:
11 | person:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/examples/partials/inline.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#*inline "myPartial"}}
6 | My Content
7 | {{/inline}}
8 | {{#each people}}
9 | {{> myPartial}}
10 | {{/each}}
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | ---
16 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-lookup.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |+
5 | {{#each people}}
6 | {{.}} lives in {{lookup ../cities @index}}
7 | {{/each}}
8 | input:
9 | people:
10 | - Nils
11 | - Yehuda
12 | cities:
13 | - Darmstadt
14 | - San Francisco
15 | ---
16 |
--------------------------------------------------------------------------------
/src/ko/examples/raw-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{{{raw-loud}}}}
6 | {{bar}}
7 | {{{{/raw-loud}}}}
8 | preparationScript: |
9 | Handlebars.registerHelper('raw-loud', function(options) {
10 | return options.fn().toUpperCase()
11 | });
12 | ---
13 |
--------------------------------------------------------------------------------
/src/zh/examples/raw-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{{{raw-loud}}}}
6 | {{bar}}
7 | {{{{/raw-loud}}}}
8 | preparationScript: |
9 | Handlebars.registerHelper('raw-loud', function(options) {
10 | return options.fn().toUpperCase()
11 | });
12 | ---
13 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-each-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 |
6 | {{#each people}}
7 | - {{this}}
8 | {{/each}}
9 |
10 | input:
11 | people:
12 | - Yehuda Katz
13 | - Alan Johnson
14 | - Charles Jolley
15 | ---
16 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-if-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{/if}}
9 |
10 | input:
11 | author: true
12 | firstName: Yehuda
13 | lastName: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/path-expressions-dot-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{../prefix}} {{firstname}}
7 | {{/each}}
8 | partials:
9 | input:
10 | people:
11 | - firstname: Nils
12 | - firstname: Yehuda
13 | prefix: "Hello"
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-if-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{/if}}
9 |
10 | input:
11 | author: true
12 | firstName: Yehuda
13 | lastName: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/path-expressions-dot-dot.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{../prefix}} {{firstname}}
7 | {{/each}}
8 | partials:
9 | input:
10 | people:
11 | - firstname: Nils
12 | - firstname: Yehuda
13 | prefix: "Hello"
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/playground.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: 张
13 | lastname: 三
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/playground.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: Hyunwoo
13 | lastname: Im
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-with-else.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#with city}}
6 | {{city.name}} (not shown because there is no city)
7 | {{else}}
8 | No city found
9 | {{/with}}
10 | input:
11 | person:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/inline.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#*inline "myPartial"}}
6 | My Content
7 | {{/inline}}
8 | {{#each people}}
9 | {{> myPartial}}
10 | {{/each}}
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | ---
16 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-with-else.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#with city}}
6 | {{city.name}} (not shown because there is no city)
7 | {{else}}
8 | No city found
9 | {{/with}}
10 | input:
11 | person:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/inline.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#*inline "myPartial"}}
6 | My Content
7 | {{/inline}}
8 | {{#each people}}
9 | {{> myPartial}}
10 | {{/each}}
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | ---
16 |
--------------------------------------------------------------------------------
/src/examples/helper-simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-lookup.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#each people}}
6 | {{.}} lives in {{lookup ../cities @index}}
7 | {{/each}}
8 | input:
9 | people:
10 | - Nils
11 | - Yehuda
12 | cities:
13 | - Darmstadt
14 | - San Francisco
15 | ---
16 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-lookup.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |+
5 | {{#each people}}
6 | {{.}} lives in {{lookup ../cities @index}}
7 | {{/each}}
8 | input:
9 | people:
10 | - Nils
11 | - Yehuda
12 | cities:
13 | - Darmstadt
14 | - San Francisco
15 | ---
16 |
--------------------------------------------------------------------------------
/src/examples/helper-data-name-conflict.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | helper: {{name}}
6 | data: {{./name}} or {{this/name}} or {{this.name}}
7 | partials:
8 | preparationScript: |
9 | Handlebars.registerHelper('name', function () {
10 | return "Nils"
11 | })
12 | input:
13 | name: Yehuda
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-each-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#each people}}
7 | - {{this}}
8 | {{/each}}
9 |
10 | input:
11 | people:
12 | - Yehuda Katz
13 | - Alan Johnson
14 | - Charles Jolley
15 | ---
16 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-each-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#each people}}
7 | - {{this}}
8 | {{/each}}
9 |
10 | input:
11 | people:
12 | - Yehuda Katz
13 | - Alan Johnson
14 | - Charles Jolley
15 | ---
16 |
--------------------------------------------------------------------------------
/src/snippets/precompilation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/src/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Handlebars.js",
3 | "short_name": "Handlebars",
4 | "start_url": "/",
5 | "display": "standalone",
6 | "background_color": "#f0772b",
7 | "theme_color": "#000000",
8 | "icons": [
9 | {
10 | "src": "/handlebars-icon.svg",
11 | "sizes": "512x512",
12 | "type": "image/svg"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-ifelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{else}}
9 | Unknown Author
10 | {{/if}}
11 |
12 | input:
13 | author: false
14 | firstName: Yehuda
15 | lastName: Katz
16 | ---
17 |
--------------------------------------------------------------------------------
/src/examples/partials/partial-block-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#each people as |person|}}
6 | {{#> childEntry}}
7 | {{person.firstname}}
8 | {{/childEntry}}
9 | {{/each}}
10 | input:
11 | people:
12 | - firstname: Nils
13 | - firstname: Yehuda
14 | - firstname: Carl
15 | ---
16 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-simple.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-data-name-conflict.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | helper: {{name}}
6 | data: {{./name}} or {{this/name}} or {{this.name}}
7 | partials:
8 | preparationScript: |
9 | Handlebars.registerHelper('name', function () {
10 | return "Nils"
11 | })
12 | input:
13 | name: Yehuda
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-data-name-conflict.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | helper: {{name}}
6 | data: {{./name}} or {{this/name}} or {{this.name}}
7 | partials:
8 | preparationScript: |
9 | Handlebars.registerHelper('name', function () {
10 | return "Nils"
11 | })
12 | input:
13 | name: Yehuda
14 | ---
15 |
--------------------------------------------------------------------------------
/src/handlebars.data.js:
--------------------------------------------------------------------------------
1 | import { retrieveHandlebarsVersions } from "./.vitepress/lib/handlebars-versions.js";
2 | import { getHandlebarsCliHelp } from "./.vitepress/lib/handlebars-cli-help.js";
3 |
4 | export default {
5 | async load() {
6 | return {
7 | versions: await retrieveHandlebarsVersions(),
8 | cliHelp: await getHandlebarsCliHelp(),
9 | };
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/src/examples/path-expressions-dot-dot-if.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{#if creator}}
7 | {{../prefix}} {{firstname}}
8 | {{/if}}
9 | {{/each}}
10 | partials:
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | creator: true
16 | prefix: "Hello"
17 | ---
18 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-ifelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{else}}
9 | Unknown Author
10 | {{/if}}
11 |
12 | input:
13 | author: false
14 | firstName: Yehuda
15 | lastName: Katz
16 | ---
17 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/partial-block-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#each people as |person|}}
6 | {{#> childEntry}}
7 | {{person.firstname}}
8 | {{/childEntry}}
9 | {{/each}}
10 | input:
11 | people:
12 | - firstname: Nils
13 | - firstname: Yehuda
14 | - firstname: Carl
15 | ---
16 |
--------------------------------------------------------------------------------
/src/zh/api-reference/helpers.md:
--------------------------------------------------------------------------------
1 | # 助手代码
2 |
3 | ## `options` 参数
4 |
5 | 除了在助手代码调用中运行的参数,`options` 也被作为一个额外的参数传递给助手代码。
6 |
7 | - `lookupProperty(object, propertyName)`: 可以返回对象自身属性的函数。本函数对 `allowedProtoProperties` 与
8 | `allowedProtoMethods` 内的白名单进行参考。例如:
9 |
10 |
11 |
12 | - TODO:对所有传递给助手代码的选项进行解释。
13 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-ifelse-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 |
6 | {{#if author}}
7 |
{{firstName}} {{lastName}}
8 | {{else}}
9 | Unknown Author
10 | {{/if}}
11 |
12 | input:
13 | author: false
14 | firstName: Yehuda
15 | lastName: Katz
16 | ---
17 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/partial-block-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#each people as |person|}}
6 | {{#> childEntry}}
7 | {{person.firstname}}
8 | {{/childEntry}}
9 | {{/each}}
10 | input:
11 | people:
12 | - firstname: Nils
13 | - firstname: Yehuda
14 | - firstname: Carl
15 | ---
16 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-if-subexpression.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#if (isdefined value1)}}true{{else}}false{{/if}}
6 | {{#if (isdefined value2)}}true{{else}}false{{/if}}
7 | preparationScript: |
8 | Handlebars.registerHelper('isdefined', function (value) {
9 | return value !== undefined;
10 | });
11 | input:
12 | value1: {}
13 | ---
14 |
--------------------------------------------------------------------------------
/src/examples/helper-safestring.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{bold text}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper("bold", function(text) {
9 | var result = "" + Handlebars.escapeExpression(text) + "";
10 | return new Handlebars.SafeString(result);
11 | });
12 | input:
13 | text: Isn't this great?
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/examples/path-expressions-dot-dot-if.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{#if creator}}
7 | {{../prefix}} {{firstname}}
8 | {{/if}}
9 | {{/each}}
10 | partials:
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | creator: true
16 | prefix: "Hello"
17 | ---
18 |
--------------------------------------------------------------------------------
/src/zh/examples/path-expressions-dot-dot-if.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{#if creator}}
7 | {{../prefix}} {{firstname}}
8 | {{/if}}
9 | {{/each}}
10 | partials:
11 | input:
12 | people:
13 | - firstname: Nils
14 | - firstname: Yehuda
15 | creator: true
16 | prefix: "Hello"
17 | ---
18 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-if-subexpression.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#if (isdefined value1)}}true{{else}}false{{/if}}
6 | {{#if (isdefined value2)}}true{{else}}false{{/if}}
7 | preparationScript: |
8 | Handlebars.registerHelper('isdefined', function (value) {
9 | return value !== undefined;
10 | });
11 | input:
12 | value1: {}
13 | ---
14 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-safestring.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{bold text}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper("bold", function(text) {
9 | var result = "" + Handlebars.escapeExpression(text) + "";
10 | return new Handlebars.SafeString(result);
11 | });
12 | input:
13 | text: Isn't this great?
14 | ---
15 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-if-subexpression.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#if (isdefined value1)}}true{{else}}false{{/if}}
6 | {{#if (isdefined value2)}}true{{else}}false{{/if}}
7 | preparationScript: |
8 | Handlebars.registerHelper('isdefined', function (value) {
9 | return value !== undefined;
10 | });
11 | input:
12 | value1: {}
13 | ---
14 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-safestring.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{bold text}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper("bold", function(text) {
9 | var result = "" + Handlebars.escapeExpression(text) + "";
10 | return new Handlebars.SafeString(result);
11 | });
12 | input:
13 | text: Isn't this great?
14 | ---
15 |
--------------------------------------------------------------------------------
/src/ko/api-reference/helpers.md:
--------------------------------------------------------------------------------
1 | # 헬퍼(Helpers)
2 |
3 | ## `options` 파라미터
4 |
5 | 헬퍼 호출에 사용되는 파라미터 외에도, options 객체가 추가 파라미터로 헬퍼에 전달됩니다.
6 |
7 | - `lookupProperty(object, propertyName)`: 객체의 "자체 속성"을 반환하는 함수입니다. 이 함수는 `allowedProtoProperties`와
8 | `allowedProtoMethods`에 지정된 화이트리스트를 따릅니다. 예시:
9 |
10 |
11 |
12 | - TODO:헬퍼에 전달되는 모든 옵션을 설명하세요.
13 |
--------------------------------------------------------------------------------
/src/snippets/compiler-and-runtime/simple-console-out.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/prettify.js:
--------------------------------------------------------------------------------
1 | import * as prettier from "prettier";
2 | import prettierPluginBabel from "prettier/plugins/babel";
3 | import prettierPluginESTree from "prettier/plugins/estree";
4 |
5 | export async function prettify(object) {
6 | return prettier.format(JSON.stringify(object || null), {
7 | parser: "json5",
8 | plugins: [prettierPluginBabel, prettierPluginESTree],
9 | printWidth: 40,
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/src/examples/partials/register.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each persons}}
6 | {{>person person=.}}
7 | {{/each}}
8 | preparationScript: >
9 | Handlebars.registerPartial("person", "{{person.name}} is {{person.age}} years old.\n")
10 | input:
11 | persons:
12 | - name: Nils
13 | age: 20
14 | - name: Teddy
15 | age: 10
16 | - name: Nelson
17 | age: 40
18 | ---
19 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/utils.js:
--------------------------------------------------------------------------------
1 | import { ExampleParser } from "./example-parser.js";
2 |
3 | export function deindent(string, ...values) {
4 | const result = String.raw(string, ...values);
5 | return result.replace(/^\s*/gm, "");
6 | }
7 |
8 | export async function parseExample(example) {
9 | if (example == null) {
10 | return;
11 | }
12 |
13 | const exampleParser = new ExampleParser(example);
14 | return exampleParser.parse();
15 | }
16 |
--------------------------------------------------------------------------------
/src/examples/partials/inline-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#> layout}}
6 | {{#*inline "nav"}}
7 | My Nav
8 | {{/inline}}
9 | {{#*inline "content"}}
10 | My Content
11 | {{/inline}}
12 | {{/layout}}
13 | partials:
14 | layout: |-
15 |
16 | {{> nav}}
17 |
18 |
19 | {{> content}}
20 |
21 | ---
22 |
--------------------------------------------------------------------------------
/src/examples/partials/parent-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{> myPartial prefix=../prefix firstname=firstname lastname=lastname}}.
7 | {{/each}}
8 | partials:
9 | myPartial: "{{prefix}}, {{firstname}} {{lastname}}"
10 | input:
11 | people:
12 | - firstname: Nils
13 | lastname: Knappmeier
14 | - firstname: Yehuda
15 | lastname: Katz
16 | prefix: Hello
17 | ---
18 |
--------------------------------------------------------------------------------
/src/examples/each-with.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | Geo-Coordinates :
6 | {{#each cities}}
7 | {{name}} {{#with location}} {{north}}, {{east}} {{/with}}
8 | {{/each}}
9 | partials:
10 | input:
11 | cities:
12 | - name: Darmstadt
13 | location:
14 | north: 49.87
15 | east: 8.64
16 | - name: San Francisco
17 | location:
18 | north: 37.73
19 | east: -122.44
20 | ---
21 |
--------------------------------------------------------------------------------
/src/examples/hook-block-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | preparationScript: |
9 | Handlebars.registerHelper('blockHelperMissing', function(context, options) {
10 | return "Helper '"+options.name+"' not found. Printing block: " + options.fn(context);
11 | });
12 | input:
13 | person:
14 | firstname: Yehuda
15 | lastname: Katz
16 | ---
17 |
--------------------------------------------------------------------------------
/src/examples/helper-this-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{print_person}}
7 | {{/each}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('print_person', function () {
11 | return this.firstname + ' ' + this.lastname
12 | })
13 | input:
14 | people:
15 | - firstname: Nils
16 | lastname: Knappmeier
17 | - firstname: Yehuda
18 | lastname: Katz
19 | ---
20 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/inline-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#> layout}}
6 | {{#*inline "nav"}}
7 | My Nav
8 | {{/inline}}
9 | {{#*inline "content"}}
10 | My Content
11 | {{/inline}}
12 | {{/layout}}
13 | partials:
14 | layout: |-
15 |
16 | {{> nav}}
17 |
18 |
19 | {{> content}}
20 |
21 | ---
22 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/parent-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{> myPartial prefix=../prefix firstname=firstname lastname=lastname}}.
7 | {{/each}}
8 | partials:
9 | myPartial: "{{prefix}}, {{firstname}} {{lastname}}"
10 | input:
11 | people:
12 | - firstname: Nils
13 | lastname: Knappmeier
14 | - firstname: Yehuda
15 | lastname: Katz
16 | prefix: Hello
17 | ---
18 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/inline-blocks.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#> layout}}
6 | {{#*inline "nav"}}
7 | My Nav
8 | {{/inline}}
9 | {{#*inline "content"}}
10 | My Content
11 | {{/inline}}
12 | {{/layout}}
13 | partials:
14 | layout: |-
15 |
16 | {{> nav}}
17 |
18 |
19 | {{> content}}
20 |
21 | ---
22 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/parent-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{> myPartial prefix=../prefix firstname=firstname lastname=lastname}}.
7 | {{/each}}
8 | partials:
9 | myPartial: "{{prefix}}, {{firstname}} {{lastname}}"
10 | input:
11 | people:
12 | - firstname: Nils
13 | lastname: Knappmeier
14 | - firstname: Yehuda
15 | lastname: Katz
16 | prefix: Hello
17 | ---
18 |
--------------------------------------------------------------------------------
/src/examples/helper-multiple-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{link "See Website" url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | url: "https://yehudakatz.com/"
15 | ---
16 |
--------------------------------------------------------------------------------
/src/examples/literal-segments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{!-- wrong: {{array.0.item}} --}}
6 | correct: array.[0].item: {{array.[0].item}}
7 |
8 | {{!-- wrong: {{array.[0].item-class}} --}}
9 | correct: array.[0].[item-class]: {{array.[0].[item-class]}}
10 |
11 | {{!-- wrong: {{./true}}--}}
12 | correct: ./[true]: {{./[true]}}
13 | input:
14 | array:
15 | - item: item1
16 | item-class: class1
17 | true: "yes"
18 | ---
19 |
--------------------------------------------------------------------------------
/src/ko/examples/each-with.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | Geo-Coordinates :
6 | {{#each cities}}
7 | {{name}} {{#with location}} {{north}}, {{east}} {{/with}}
8 | {{/each}}
9 | partials:
10 | input:
11 | cities:
12 | - name: Darmstadt
13 | location:
14 | north: 49.87
15 | east: 8.64
16 | - name: San Francisco
17 | location:
18 | north: 37.73
19 | east: -122.44
20 | ---
21 |
--------------------------------------------------------------------------------
/src/zh/examples/each-with.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | Geo-Coordinates :
6 | {{#each cities}}
7 | {{name}} {{#with location}} {{north}}, {{east}} {{/with}}
8 | {{/each}}
9 | partials:
10 | input:
11 | cities:
12 | - name: Darmstadt
13 | location:
14 | north: 49.87
15 | east: 8.64
16 | - name: San Francisco
17 | location:
18 | north: 37.73
19 | east: -122.44
20 | ---
21 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-this-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{print_person}}
7 | {{/each}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('print_person', function () {
11 | return this.firstname + ' ' + this.lastname
12 | })
13 | input:
14 | people:
15 | - firstname: Nils
16 | lastname: Knappmeier
17 | - firstname: Yehuda
18 | lastname: Katz
19 | ---
20 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-this-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each people}}
6 | {{print_person}}
7 | {{/each}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('print_person', function () {
11 | return this.firstname + ' ' + this.lastname
12 | })
13 | input:
14 | people:
15 | - firstname: Nils
16 | lastname: Knappmeier
17 | - firstname: Yehuda
18 | lastname: Katz
19 | ---
20 |
--------------------------------------------------------------------------------
/src/.vitepress/lib/handlebars-versions.js:
--------------------------------------------------------------------------------
1 | import semver from "semver";
2 |
3 | export async function retrieveHandlebarsVersions() {
4 | const response = await fetch("https://registry.npmjs.org/handlebars/");
5 | const npmMetaData = await response.json();
6 |
7 | const allVersions = Object.keys(npmMetaData.versions).filter((version) => semver.gte(version, "3.0.0"));
8 | allVersions.sort(semver.rcompare);
9 |
10 | return {
11 | latest: npmMetaData["dist-tags"].latest,
12 | allVersions,
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/register.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each persons}}
6 | {{>person person=.}}
7 | {{/each}}
8 | preparationScript: >
9 | Handlebars.registerPartial(
10 | "person",
11 | "{{person.name}} is {{person.age}} years old.\n"
12 | )
13 | input:
14 | persons:
15 | - name: Nils
16 | age: 20
17 | - name: Teddy
18 | age: 10
19 | - name: Nelson
20 | age: 40
21 | ---
22 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/register.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each persons}}
6 | {{>person person=.}}
7 | {{/each}}
8 | preparationScript: >
9 | Handlebars.registerPartial(
10 | "person",
11 | "{{person.name}} is {{person.age}} years old.\n"
12 | )
13 | input:
14 | persons:
15 | - name: Nils
16 | age: 20
17 | - name: Teddy
18 | age: 10
19 | - name: Nelson
20 | age: 40
21 | ---
22 |
--------------------------------------------------------------------------------
/src/ko/examples/literal-segments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{!-- wrong: {{array.0.item}} --}}
6 | correct: array.[0].item: {{array.[0].item}}
7 |
8 | {{!-- wrong: {{array.[0].item-class}} --}}
9 | correct: array.[0].[item-class]: {{array.[0].[item-class]}}
10 |
11 | {{!-- wrong: {{./true}}--}}
12 | correct: ./[true]: {{./[true]}}
13 | input:
14 | array:
15 | - item: item1
16 | item-class: class1
17 | true: "yes"
18 | ---
19 |
--------------------------------------------------------------------------------
/src/zh/examples/literal-segments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{!-- wrong: {{array.0.item}} --}}
6 | correct: array.[0].item: {{array.[0].item}}
7 |
8 | {{!-- wrong: {{array.[0].item-class}} --}}
9 | correct: array.[0].[item-class]: {{array.[0].[item-class]}}
10 |
11 | {{!-- wrong: {{./true}}--}}
12 | correct: ./[true]: {{./[true]}}
13 | input:
14 | array:
15 | - item: item1
16 | item-class: class1
17 | true: "yes"
18 | ---
19 |
--------------------------------------------------------------------------------
/src/ko/examples/hook-block-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | preparationScript: |
9 | Handlebars.registerHelper('blockHelperMissing', function(context, options) {
10 | return "Helper '"+options.name+"' not found. "
11 | + "Printing block: " + options.fn(context);
12 | });
13 | input:
14 | person:
15 | firstname: Yehuda
16 | lastname: Katz
17 | ---
18 |
--------------------------------------------------------------------------------
/src/zh/examples/hook-block-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#person}}
6 | {{firstname}} {{lastname}}
7 | {{/person}}
8 | preparationScript: |
9 | Handlebars.registerHelper('blockHelperMissing', function(context, options) {
10 | return "Helper '"+options.name+"' not found. "
11 | + "Printing block: " + options.fn(context);
12 | });
13 | input:
14 | person:
15 | firstname: Yehuda
16 | lastname: Katz
17 | ---
18 |
--------------------------------------------------------------------------------
/src/playground.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{firstname}} {{loud lastname}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('loud', function (aString) {
9 | return aString.toUpperCase()
10 | })
11 | input:
12 | firstname: Yehuda
13 | lastname: Katz
14 | ---
15 |
16 |
20 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-with-block-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{#with city as | city |}}
6 | {{#with city.location as | loc |}}
7 | {{city.name}}: {{loc.north}} {{loc.east}}
8 | {{/with}}
9 | {{/with}}
10 | input:
11 | city:
12 | name: San Francisco
13 | summary: San Francisco is the cultural center of Northern California
14 | location:
15 | north: "37.73,"
16 | east: -122.44
17 | population: 883305
18 | ---
19 |
--------------------------------------------------------------------------------
/src/examples/helper-lookup-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{lookupOrDefault this 'firstname' 'Name not found'}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('lookupOrDefault', function (object, propertyName, defaultValue, options) {
9 | var result = options.lookupProperty(object, propertyName)
10 | if (result != null) {
11 | return result
12 | }
13 | return defaultValue
14 | })
15 | input:
16 | firstname: Yehuda
17 | ---
18 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-multiple-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link "See Website" url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | url: "https://yehudakatz.com/"
15 | ---
16 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-multiple-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link "See Website" url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | url: "https://yehudakatz.com/"
15 | ---
16 |
--------------------------------------------------------------------------------
/src/.vitepress/lib/handlebars-cli-help.js:
--------------------------------------------------------------------------------
1 | import cp from "child_process";
2 |
3 | export async function getHandlebarsCliHelp() {
4 | const handlebarsCliUrl = await import.meta.resolve("handlebars/bin/handlebars");
5 | const handlebarsCliPath = new URL(handlebarsCliUrl).pathname;
6 | const nodeExecutable = process.argv[0];
7 |
8 | const { stdout } = cp.spawnSync(nodeExecutable, [handlebarsCliPath, "--help"], {
9 | argv0: "handlebars",
10 | stdio: ["pipe", "pipe", "pipe"],
11 | encoding: "utf-8",
12 | });
13 |
14 | return stdout;
15 | }
16 |
--------------------------------------------------------------------------------
/src/examples/hook-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |-
5 | {{foo}}
6 | {{foo true}}
7 | {{foo 2 true}}
8 | {{#foo true}}{{/foo}}
9 | {{#foo}}{{/foo}}
10 | preparationScript: >
11 | Handlebars.registerHelper('helperMissing', function( /* dynamic arguments */) {
12 | var options = arguments[arguments.length-1];
13 | var args = Array.prototype.slice.call(arguments, 0,arguments.length-1)
14 | return new Handlebars.SafeString("Missing: "+options.name+"("+args+")")
15 | })
16 | ---
17 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-with-block-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#with city as | city |}}
6 | {{#with city.location as | loc |}}
7 | {{city.name}}: {{loc.north}} {{loc.east}}
8 | {{/with}}
9 | {{/with}}
10 | input:
11 | city:
12 | name: San Francisco
13 | summary: San Francisco is the cultural center of Northern California
14 | location:
15 | north: "37.73,"
16 | east: -122.44
17 | population: 883305
18 | ---
19 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-with-block-param.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{#with city as | city |}}
6 | {{#with city.location as | loc |}}
7 | {{city.name}}: {{loc.north}} {{loc.east}}
8 | {{/with}}
9 | {{/with}}
10 | input:
11 | city:
12 | name: San Francisco
13 | summary: San Francisco is the cultural center of Northern California
14 | location:
15 | north: "37.73,"
16 | east: -122.44
17 | population: 883305
18 | ---
19 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/worker.js:
--------------------------------------------------------------------------------
1 | import { executeExample } from "../execute-example";
2 | import { lazyGetHandlebars } from "./lazy-get-handlebars";
3 |
4 | onmessage = async function (parsedExampleWithVersion) {
5 | try {
6 | const handlebars = await lazyGetHandlebars(parsedExampleWithVersion.data.handlebarsVersion);
7 | const result = executeExample(handlebars, parsedExampleWithVersion.data);
8 |
9 | postMessage(result);
10 | } catch (e) {
11 | postMessage({ error: e.message });
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/src/examples/helper-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{progress "Search" 10 false}}
6 | {{progress "Upload" 90 true}}
7 | {{progress "Finish" 100 false}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('progress', function (name, percent, stalled) {
11 | var barWidth = percent / 5
12 | var bar = "********************".slice(0,barWidth)
13 | return bar + " " + percent + "% " + name + " " + (stalled ? "stalled" : "")
14 | })
15 | input: {}
16 | ---
17 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-lookup-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{lookupOrDefault this 'firstname' 'Name not found'}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('lookupOrDefault', function (object, propertyName, defaultValue, options) {
9 | var result = options.lookupProperty(object, propertyName)
10 | if (result != null) {
11 | return result
12 | }
13 | return defaultValue
14 | })
15 | input:
16 | firstname: Yehuda
17 | ---
18 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-lookup-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{lookupOrDefault this 'firstname' 'Name not found'}}
6 | partials:
7 | preparationScript: |
8 | Handlebars.registerHelper('lookupOrDefault', function (object, propertyName, defaultValue, options) {
9 | var result = options.lookupProperty(object, propertyName)
10 | if (result != null) {
11 | return result
12 | }
13 | return defaultValue
14 | })
15 | input:
16 | firstname: Yehuda
17 | ---
18 |
--------------------------------------------------------------------------------
/src/examples/partials/partials.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{person.name}} is {{person.age}} years old.
15 | input:
16 | persons:
17 | - name: Nils
18 | age: 20
19 | - name: Teddy
20 | age: 10
21 | - name: Nelson
22 | age: 40
23 | ---
24 |
25 | ```handlebars
26 | test
27 | ```
28 |
--------------------------------------------------------------------------------
/src/ko/examples/hook-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{foo}}
6 | {{foo true}}
7 | {{foo 2 true}}
8 | {{#foo true}}{{/foo}}
9 | {{#foo}}{{/foo}}
10 | preparationScript: >
11 | Handlebars.registerHelper('helperMissing', function( /* dynamic arguments */) {
12 | var options = arguments[arguments.length-1];
13 | var args = Array.prototype.slice.call(arguments, 0,arguments.length-1)
14 | return new Handlebars.SafeString("Missing: "+options.name+"("+args+")")
15 | })
16 | ---
17 |
--------------------------------------------------------------------------------
/src/zh/examples/hook-helper-missing.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |-
5 | {{foo}}
6 | {{foo true}}
7 | {{foo 2 true}}
8 | {{#foo true}}{{/foo}}
9 | {{#foo}}{{/foo}}
10 | preparationScript: >
11 | Handlebars.registerHelper('helperMissing', function( /* dynamic arguments */) {
12 | var options = arguments[arguments.length-1];
13 | var args = Array.prototype.slice.call(arguments, 0,arguments.length-1)
14 | return new Handlebars.SafeString("Missing: "+options.name+"("+args+")")
15 | })
16 | ---
17 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{progress "Search" 10 false}}
6 | {{progress "Upload" 90 true}}
7 | {{progress "Finish" 100 false}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('progress', function (name, percent, stalled) {
11 | var barWidth = percent / 5
12 | var bar = "********************".slice(0,barWidth)
13 | return bar + " " + percent + "% " + name + " " + (stalled ? "stalled" : "")
14 | })
15 | input: {}
16 | ---
17 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{progress "Search" 10 false}}
6 | {{progress "Upload" 90 true}}
7 | {{progress "Finish" 100 false}}
8 | partials:
9 | preparationScript: |
10 | Handlebars.registerHelper('progress', function (name, percent, stalled) {
11 | var barWidth = percent / 5
12 | var bar = "********************".slice(0,barWidth)
13 | return bar + " " + percent + "% " + name + " " + (stalled ? "stalled" : "")
14 | })
15 | input: {}
16 | ---
17 |
--------------------------------------------------------------------------------
/src/snippets/precompilation/precompile-in-nodejs.output.js:
--------------------------------------------------------------------------------
1 | {"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
2 | var helper, alias1=container.propertyIsEnumerable;
3 |
4 | return "Handlebars "
5 | + container.escapeExpression(((helper = (helper = helpers.doesWhat || (depth0 != null ? depth0.doesWhat : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"doesWhat","hash":{},"data":data}) : helper)))
6 | + " precompiled!";
7 | },"useData":true}
--------------------------------------------------------------------------------
/src/api-reference/helpers.md:
--------------------------------------------------------------------------------
1 | # Helpers
2 |
3 | ## The `options`-parameter
4 |
5 | In addition to the parameters used in the helper-call, an `options`-object is passed to the helper as additional
6 | parameter.
7 |
8 | - `lookupProperty(object, propertyName)`: a function that returns an "own property" of an object. Whitelists specified
9 | in `allowedProtoProperties` and `allowedProtoMethods` are respected by this function. Example:
10 |
11 |
12 |
13 | - TODO: Describe all options that are passed to helpers
14 |
--------------------------------------------------------------------------------
/src/ko/examples/partials/partials.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{person.name}} is {{person.age}} years old.
15 | input:
16 | persons:
17 | - name: Nils
18 | age: 20
19 | - name: Teddy
20 | age: 10
21 | - name: Nelson
22 | age: 40
23 | ---
24 |
25 | ```handlebars
26 | test
27 | ```
28 |
--------------------------------------------------------------------------------
/src/zh/examples/partials/partials.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{person.name}} is {{person.age}} years old.
15 | input:
16 | persons:
17 | - name: Nils
18 | age: 20
19 | - name: Teddy
20 | age: 10
21 | - name: Nelson
22 | age: 40
23 | ---
24 |
25 | ```handlebars
26 | test
27 | ```
28 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request: {}
8 |
9 | jobs:
10 | test:
11 | name: Test & Lint
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v2
16 |
17 | - name: Setup Node.js
18 | uses: actions/setup-node@v2
19 | with:
20 | node-version: '22'
21 |
22 | - name: Install dependencies
23 | run: npm ci
24 |
25 | - name: Lint
26 | run: npm run lint
27 |
28 | - name: Test
29 | run: npm run test
30 |
--------------------------------------------------------------------------------
/src/api-reference/index.md:
--------------------------------------------------------------------------------
1 | # Index
2 |
3 |
8 |
9 | - [(Pre-)Compilation](compilation.md)
10 | - [Runtime](runtime.md)
11 | - [Utilities](utilities.md)
12 | - [Helper utilities](utilities.md#helper-utilities)
13 | - [General utilities](utilities.md#general-utilities)
14 | - [`@data`-variables used by built-in helpers](data-variables.md)
15 |
--------------------------------------------------------------------------------
/src/examples/helper-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#list people}}{{firstname}} {{lastname}}{{/list}}
6 | preparationScript: |
7 | Handlebars.registerHelper("list", function(items, options) {
8 | const itemsAsHtml = items.map(item => "" + options.fn(item) + "");
9 | return "\n" + itemsAsHtml.join("\n") + "\n
";
10 | });
11 | input:
12 | people:
13 | - firstname: Yehuda
14 | lastname: Katz
15 | - firstname: Carl
16 | lastname: Lerche
17 | - firstname: Alan
18 | lastname: Johnson
19 | ---
20 |
--------------------------------------------------------------------------------
/src/examples/helper-dynamic-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{link people.text people.url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | people:
15 | firstname: Yehuda
16 | lastname: Katz
17 | url: "https://yehudakatz.com/"
18 | text: "See Website"
19 | ---
20 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#list people}}{{firstname}} {{lastname}}{{/list}}
6 | preparationScript: |
7 | Handlebars.registerHelper("list", function(items, options) {
8 | const itemsAsHtml = items.map(item => "" + options.fn(item) + "");
9 | return "\n" + itemsAsHtml.join("\n") + "\n
";
10 | });
11 | input:
12 | people:
13 | - firstname: Yehuda
14 | lastname: Katz
15 | - firstname: Carl
16 | lastname: Lerche
17 | - firstname: Alan
18 | lastname: Johnson
19 | ---
20 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-block.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#list people}}{{firstname}} {{lastname}}{{/list}}
6 | preparationScript: |
7 | Handlebars.registerHelper("list", function(items, options) {
8 | const itemsAsHtml = items.map(item => "" + options.fn(item) + "");
9 | return "\n" + itemsAsHtml.join("\n") + "\n
";
10 | });
11 | input:
12 | people:
13 | - firstname: Yehuda
14 | lastname: Katz
15 | - firstname: Carl
16 | lastname: Lerche
17 | - firstname: Alan
18 | lastname: Johnson
19 | ---
20 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-lookup-dynamic-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{#each persons as | person |}}
6 | {{name}} lives in {{#with (lookup ../cities [resident-in])~}}
7 | {{name}} ({{country}})
8 | {{/with}}
9 | {{/each}}
10 | input:
11 | persons:
12 | - name: Nils
13 | resident-in: darmstadt
14 | - name: Yehuda
15 | resident-in: san-francisco
16 | cities:
17 | darmstadt:
18 | name: Darmstadt
19 | country: Germany
20 | san-francisco:
21 | name: San Francisco
22 | country: USA
23 | ---
24 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-dynamic-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link people.text people.url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | people:
15 | firstname: Yehuda
16 | lastname: Katz
17 | url: "https://yehudakatz.com/"
18 | text: "See Website"
19 | ---
20 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-dynamic-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link people.text people.url}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, url) {
8 | var url = Handlebars.escapeExpression(url),
9 | text = Handlebars.escapeExpression(text)
10 |
11 | return new Handlebars.SafeString("" + text +"");
12 | });
13 | input:
14 | people:
15 | firstname: Yehuda
16 | lastname: Katz
17 | url: "https://yehudakatz.com/"
18 | text: "See Website"
19 | ---
20 |
--------------------------------------------------------------------------------
/src/examples/builtin-helper-log-loglevel.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{log "debug logging" level="debug"}}
6 | {{log "info logging" level="info"}}
7 | {{log "info logging is the default"}}
8 | {{log "logging a warning" level="warn"}}
9 | {{log "logging an error" level="error"}}
10 | preparationScript: |-
11 | Handlebars.logger.level = 'error'
12 | console.log('Current log level: ', Handlebars.logger.level, '\n---')
13 | input:
14 | ---
15 |
16 | Press F12 and open the dev-console to see the log output. In order to see debug output, you may need to configure your
17 | dev-tools properly.
18 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-lookup-dynamic-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each persons as | person |}}
6 | {{name}} lives in {{#with (lookup ../cities [resident-in])~}}
7 | {{name}} ({{country}})
8 | {{/with}}
9 | {{/each}}
10 | input:
11 | persons:
12 | - name: Nils
13 | resident-in: darmstadt
14 | - name: Yehuda
15 | resident-in: san-francisco
16 | cities:
17 | darmstadt:
18 | name: Darmstadt
19 | country: Germany
20 | san-francisco:
21 | name: San Francisco
22 | country: USA
23 | ---
24 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-lookup-dynamic-property.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{#each persons as | person |}}
6 | {{name}} lives in {{#with (lookup ../cities [resident-in])~}}
7 | {{name}} ({{country}})
8 | {{/with}}
9 | {{/each}}
10 | input:
11 | persons:
12 | - name: Nils
13 | resident-in: darmstadt
14 | - name: Yehuda
15 | resident-in: san-francisco
16 | cities:
17 | darmstadt:
18 | name: Darmstadt
19 | country: Germany
20 | san-francisco:
21 | name: San Francisco
22 | country: USA
23 | ---
24 |
--------------------------------------------------------------------------------
/src/ko/examples/builtin-helper-log-loglevel.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{log "debug logging" level="debug"}}
6 | {{log "info logging" level="info"}}
7 | {{log "info logging is the default"}}
8 | {{log "logging a warning" level="warn"}}
9 | {{log "logging an error" level="error"}}
10 | preparationScript: |-
11 | Handlebars.logger.level = 'error'
12 | console.log('Current log level: ', Handlebars.logger.level, '\n---')
13 | input:
14 | ---
15 |
16 | Press F12 and open the dev-console to see the log output. In order to see debug output, you may need to configure your
17 | dev-tools properly.
18 |
--------------------------------------------------------------------------------
/src/zh/examples/builtin-helper-log-loglevel.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{log "debug logging" level="debug"}}
6 | {{log "info logging" level="info"}}
7 | {{log "info logging is the default"}}
8 | {{log "logging a warning" level="warn"}}
9 | {{log "logging an error" level="error"}}
10 | preparationScript: |-
11 | Handlebars.logger.level = 'error'
12 | console.log('Current log level: ', Handlebars.logger.level, '\n---')
13 | input:
14 | ---
15 |
16 | Press F12 and open the dev-console to see the log output. In order to see debug output, you may need to configure your
17 | dev-tools properly.
18 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/execute-one-after-another.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @param {}asyncFunction
4 | * @returns {function(): Promise<*>}
5 | */
6 | export function executeOneAfterAnother(asyncFunction) {
7 | let lastExecutionDone = Promise.resolve();
8 |
9 | return function (/* same args as asyncFunction */) {
10 | lastExecutionDone = runWhenCompleted(lastExecutionDone, () => asyncFunction.apply(this, [...arguments]));
11 | return lastExecutionDone;
12 | };
13 | }
14 |
15 | async function runWhenCompleted(promiseToBeCompleted, functionToRun) {
16 | return promiseToBeCompleted.then(functionToRun, functionToRun);
17 | }
18 |
--------------------------------------------------------------------------------
/src/examples/all-features.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{loud person.name}} is {{person.age}} years old.
15 | preparationScript: |
16 | Handlebars.registerHelper('loud', function (aString) {
17 | return aString.toUpperCase()
18 | })
19 | input:
20 | persons:
21 | - name: Nils
22 | age: 20
23 | - name: Teddy
24 | age: 10
25 | - name: Nelson
26 | age: 40
27 | ---
28 |
--------------------------------------------------------------------------------
/src/ko/examples/all-features.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{loud person.name}} is {{person.age}} years old.
15 | preparationScript: |
16 | Handlebars.registerHelper('loud', function (aString) {
17 | return aString.toUpperCase()
18 | })
19 | input:
20 | persons:
21 | - name: Nils
22 | age: 20
23 | - name: Teddy
24 | age: 10
25 | - name: Nelson
26 | age: 40
27 | ---
28 |
--------------------------------------------------------------------------------
/src/zh/examples/all-features.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{>header}}
6 |
7 | {{#each persons}}
8 | {{>person person=.}}
9 | {{/each}}
10 | partials:
11 | header: |
12 | {{persons.length}} persons found
13 | person: |
14 | The person {{loud person.name}} is {{person.age}} years old.
15 | preparationScript: |
16 | Handlebars.registerHelper('loud', function (aString) {
17 | return aString.toUpperCase()
18 | })
19 | input:
20 | persons:
21 | - name: Nils
22 | age: 20
23 | - name: Teddy
24 | age: 10
25 | - name: Nelson
26 | age: 40
27 | ---
28 |
--------------------------------------------------------------------------------
/.github/workflows/build-and-deploy.yml:
--------------------------------------------------------------------------------
1 | name: build-and-deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build-and-deploy:
10 | runs-on: ubuntu-latest
11 | env:
12 | TARGET_URL: handlebarsjs.com
13 | steps:
14 | - uses: actions/checkout@v1
15 | - uses: actions/setup-node@v1
16 | with:
17 | node-version: '22'
18 | - run: npm ci
19 | - run: npm run docs:build
20 |
21 | - name: Deploy to ${{ env.TARGET_URL }}
22 | uses: peaceiris/actions-gh-pages@v3
23 | with:
24 | github_token: ${{ secrets.GITHUB_TOKEN }}
25 | publish_dir: ./src/.vitepress/dist
26 | cname: ${{ env.TARGET_URL }}
27 |
--------------------------------------------------------------------------------
/src/snippets/compiler-and-runtime/index.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/src/zh/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # https://vitepress.dev/reference/default-theme-home-page
3 | layout: home
4 |
5 | hero:
6 | name: "Handlebars"
7 | tagline: 轻量的语义化模板
8 | image:
9 | src: /handlebars-icon.svg
10 | alt: Handlebars icon
11 | actions:
12 | - theme: brand
13 | text: 快速上手 →
14 | link: /zh/guide/
15 | - theme: alt
16 | text: 在线演示 →
17 | link: /zh/playground.html
18 |
19 | features:
20 | - title: 语义化模板
21 | details: Handlebars 提供了必要的功能,使你可以高效地构建语义化模板。
22 | - title: 兼容 Mustache
23 | details: Handlebars 与 Mustache 模板基本兼容。大多数情况下,您可以在使用 Handlebars 的同时继续使用您当前的模板。
24 | - title: 高速执行
25 | details: Handlebars 会将模板编译为 JavaScript 函数。这使得 Handlebars 的执行速度比其他大多数模板引擎都要快。
26 | ---
27 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/WorkspaceError.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ error.message }}
5 |
6 | {{ error.stack }}
7 |
8 |
9 |
10 |
11 |
24 |
25 |
32 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/HandlebarsVersionChooser.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
22 |
23 |
30 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/limit-waiting-time.js:
--------------------------------------------------------------------------------
1 | export async function limitWaitingTime(promiseToWaitFor, maxWaitMillis, timeoutCallback) {
2 | try {
3 | return await Promise.race([
4 | promiseToWaitFor,
5 | rejectAfter(maxWaitMillis, () => new TimeoutError(`Timed out after ${maxWaitMillis}ms`)),
6 | ]);
7 | } catch (error) {
8 | if (error instanceof TimeoutError) {
9 | timeoutCallback();
10 | }
11 | throw error;
12 | }
13 | }
14 |
15 | async function rejectAfter(milliseconds, errorProvider) {
16 | return new Promise((resolve, reject) => setTimeout(() => reject(errorProvider()), milliseconds));
17 | }
18 |
19 | export class TimeoutError extends Error {
20 | constructor(message) {
21 | super(message);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/.vitepress/theme/index.js:
--------------------------------------------------------------------------------
1 | // https://vitepress.dev/guide/custom-theme
2 | import { h } from "vue";
3 | import Theme from "vitepress/theme";
4 | import Flex from "../components/Flex.vue";
5 | import Example from "../components/Example.vue";
6 | import PlaygroundLayout from "../components/PlaygroundLayout.vue";
7 | import "./style.css";
8 |
9 | export default {
10 | extends: Theme,
11 | Layout: () => {
12 | return h(Theme.Layout, null, {
13 | // https://vitepress.dev/guide/extending-default-theme#layout-slots
14 | });
15 | },
16 | async enhanceApp({ app, router, siteData }) {
17 | // https://vitepress.dev/guide/custom-theme#theme-interface
18 | app.component("playground", PlaygroundLayout);
19 | app.component("Flex", Flex);
20 | app.component("Example", Example);
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/ExportYamlModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Export YAML
4 | You can copy the yaml-code below and use it as frontmatter for an example page.
5 |
6 |
7 |
8 |
9 |
10 |
25 |
26 |
31 |
--------------------------------------------------------------------------------
/src/ko/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # https://vitepress.dev/reference/default-theme-home-page
3 | layout: home
4 |
5 | hero:
6 | name: "Handlebars"
7 | tagline: 강력한 경량형 템플릿
8 | image:
9 | src: /handlebars-icon.svg
10 | alt: Handlebars icon
11 | actions:
12 | - theme: brand
13 | text: 시작하기 →
14 | link: /ko/guide/
15 | - theme: alt
16 | text: Playground →
17 | link: /ko/playground.html
18 |
19 | features:
20 | - title: Semantic 템플릿
21 | details: Handlebars는 큰 어려움 없이 semantic 템플릿을 효과적으로 구축할 수 있는 필요한 기능을 제공합니다.
22 | - title: Mustache 호환성
23 | details:
24 | Handlebars는 대부분의 경우 Mustache 템플릿과 호환 가능합니다. 대부분의 경우 Mustache를 Handlebars로 대체하고
25 | 현재의 템플릿을 계속 사용할 수 있습니다.
26 | - title: 빠른 실행
27 | details:
28 | Handlebars는 템플릿을 JavaScript 함수로 컴파일하기 때문에 템플릿 실행이 대부분의 다른 템플릿 엔진보다 빠릅니다.
29 | ---
30 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/lazy-get-handlebars.js:
--------------------------------------------------------------------------------
1 | // Cache version -> Promise
2 | const handlebarsCache = {};
3 |
4 | export async function lazyGetHandlebars(version) {
5 | if (handlebarsCache[version] == null) {
6 | handlebarsCache[version] = loadHandlebarsNow(version);
7 | }
8 | return handlebarsCache[version];
9 | }
10 |
11 | async function loadHandlebarsNow(version) {
12 | const response = await fetch(resolveHandlebarsUrl(version));
13 | if (response.ok) {
14 | const exports = {};
15 | const handlebarsUmdCode = await response.text();
16 | Function("", handlebarsUmdCode).call(exports);
17 | return exports["Handlebars"];
18 | }
19 | }
20 |
21 | function resolveHandlebarsUrl(version) {
22 | return `https://unpkg.com/handlebars@${version}/dist/handlebars.min.js`;
23 | }
24 |
--------------------------------------------------------------------------------
/src/examples/helper-hash-arguments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: playground
3 | example:
4 | template: |
5 | {{link "See Website" href=person.url class="person"}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, options) {
8 | var attributes = [];
9 |
10 | Object.keys(options.hash).forEach(key => {
11 | var escapedKey = Handlebars.escapeExpression(key);
12 | var escapedValue = Handlebars.escapeExpression(options.hash[key]);
13 | attributes.push(escapedKey + '="' + escapedValue + '"');
14 | })
15 | var escapedText = Handlebars.escapeExpression(text);
16 |
17 | var escapedOutput ="" + escapedText + "";
18 | return new Handlebars.SafeString(escapedOutput);
19 | });
20 | input:
21 | person:
22 | firstname: Yehuda
23 | lastname: Katz
24 | url: "https://yehudakatz.com/"
25 | ---
26 |
--------------------------------------------------------------------------------
/src/zh/guide/installation/when-to-use-handlebars.md:
--------------------------------------------------------------------------------
1 | # 什么时候使用/不使用 Handlebars?
2 |
3 | 本节概述了 Handlebars 的优缺点。它能够让你了解 Handlebars 是否适合你的实际情况,并使你就是否选择 Handlebars 做出明智的决定。
4 |
5 | ::: info 关于在浏览器中使用 Handlebars 的注意事项
6 |
7 | Handlebars 是一个纯渲染引擎。如果你要允许人们自己编写用于渲染 HTML 页面,电子邮件或者 Markdown 文件的模板,那么使用 Handlebars 效果将会很好。
8 |
9 | Handlebars **没有事件处理**,访问 **后端服务** 或增量 **DOM 更新** 的内置支持。
10 |
11 | 如果你想构建一个 **单页应用程序(SPA)** 并且想要处理用户输入,则可能应该寻找一个前端框架:
12 |
13 | - [Angular](https://angular.io/)
14 | - [Aurelia](https://aurelia.io/)
15 | - [Ember](https://emberjs.com/)
16 | - [Inferno](https://infernojs.org/)
17 | - [Mithril](https://mithril.js.org/)
18 | - [Svelte](https://svelte.dev/)
19 | - [Ractive](https://ractive.js.org/)
20 | - [React](https://reactjs.org/)
21 | - [Vue](https://vuejs.org/)
22 |
23 | :::
24 |
25 | # 高级
26 |
27 | - Handlebars 非常适合在 CLI 应用渲染,非 HTML 文本内容,在服务器端呈现纯内容。
28 | - Handlebars 已移植到许多编程语言上(Java、Rust 等)。
29 | - Handlebars 不利于 DOM 的快速(增量)更新,事件处理和前后端通信。
30 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/client.js:
--------------------------------------------------------------------------------
1 | import ExecuteHandlebarsWorker from "./worker?worker";
2 | import pDebounce from "p-debounce";
3 | import { WorkerWithTerminationTimeout } from "./worker-with-termination-timeout";
4 | import { executeOneAfterAnother } from "./execute-one-after-another";
5 |
6 | const HANDLEBARS_EXECUTION_TIME_LIMIT_MILLIS = 2000;
7 | const DEBOUNCE_DELAY = 200;
8 |
9 | const workerWithTimeout = new WorkerWithTerminationTimeout(
10 | () => new ExecuteHandlebarsWorker(),
11 | HANDLEBARS_EXECUTION_TIME_LIMIT_MILLIS,
12 | );
13 |
14 | async function executeExampleNow(parsedExample) {
15 | return workerWithTimeout.postMessage(parsedExample);
16 | }
17 |
18 | const debouncedSequentialExecuteExample = pDebounce(executeOneAfterAnother(executeExampleNow), DEBOUNCE_DELAY);
19 |
20 | export async function executeExample(parsedExample) {
21 | return debouncedSequentialExecuteExample(parsedExample);
22 | }
23 |
--------------------------------------------------------------------------------
/src/ko/examples/helper-hash-arguments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link "See Website" href=person.url class="person"}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, options) {
8 | var attributes = [];
9 |
10 | Object.keys(options.hash).forEach(key => {
11 | var escapedKey = Handlebars.escapeExpression(key);
12 | var escapedValue = Handlebars.escapeExpression(options.hash[key]);
13 | attributes.push(escapedKey + '="' + escapedValue + '"');
14 | })
15 | var escapedText = Handlebars.escapeExpression(text);
16 |
17 | var escapedOutput ="" + escapedText + "";
18 | return new Handlebars.SafeString(escapedOutput);
19 | });
20 | input:
21 | person:
22 | firstname: Yehuda
23 | lastname: Katz
24 | url: "https://yehudakatz.com/"
25 | ---
26 |
--------------------------------------------------------------------------------
/src/zh/examples/helper-hash-arguments.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: InteractivePlaygroundLayout
3 | example:
4 | template: |
5 | {{link "See Website" href=person.url class="person"}}
6 | preparationScript: |
7 | Handlebars.registerHelper("link", function(text, options) {
8 | var attributes = [];
9 |
10 | Object.keys(options.hash).forEach(key => {
11 | var escapedKey = Handlebars.escapeExpression(key);
12 | var escapedValue = Handlebars.escapeExpression(options.hash[key]);
13 | attributes.push(escapedKey + '="' + escapedValue + '"');
14 | })
15 | var escapedText = Handlebars.escapeExpression(text);
16 |
17 | var escapedOutput ="" + escapedText + "";
18 | return new Handlebars.SafeString(escapedOutput);
19 | });
20 | input:
21 | person:
22 | firstname: Yehuda
23 | lastname: Katz
24 | url: "https://yehudakatz.com/"
25 | ---
26 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/worker-with-termination-timeout.js:
--------------------------------------------------------------------------------
1 | import { limitWaitingTime } from "./limit-waiting-time";
2 |
3 | export class WorkerWithTerminationTimeout {
4 | constructor(workerFactory, timeoutMillis) {
5 | this.workerFactory = workerFactory;
6 | this.timeoutMillis = timeoutMillis;
7 | this._recreateWorker();
8 | }
9 |
10 | async postMessage(message) {
11 | return new Promise((resolve, reject) => {
12 | this.worker.addEventListener("message", (e) => {
13 | if (e.data.error) {
14 | reject(new Error(e.data.error));
15 | } else {
16 | resolve(e.data);
17 | }
18 | });
19 | limitWaitingTime(this.worker.postMessage(message), this.timeoutMillis, () => this._recreateWorker());
20 | });
21 | }
22 |
23 | _recreateWorker() {
24 | if (this.worker != null) {
25 | this.worker.terminate();
26 | }
27 | this.worker = this.workerFactory();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/codemirror-languages/js-object.js:
--------------------------------------------------------------------------------
1 | import { parser } from "./js-object.parser.js";
2 | import { LRLanguage, LanguageSupport } from "@codemirror/language";
3 | import { styleTags, tags as t } from "@lezer/highlight";
4 |
5 | let parserWithMetadata = parser.configure({
6 | props: [
7 | styleTags({
8 | PropertyDefinition: t.propertyName,
9 | BooleanLiteral: t.bool,
10 | Number: t.number,
11 | Escape: t.escape,
12 | String: t.string,
13 | LineComment: t.lineComment,
14 | BlockComment: t.blockComment,
15 | "[ ]": t.squareBracket,
16 | "{ }": t.brace,
17 | }),
18 | ],
19 | });
20 |
21 | const language = LRLanguage.define({
22 | name: "js-object",
23 | parser: parserWithMetadata,
24 | languageData: {
25 | closeBrackets: { brackets: ["(", "[", "{", "'", '"'] },
26 | commentTokens: { line: "//", block: { open: "/*", close: "*/" } },
27 | },
28 | });
29 |
30 | export function jsObject() {
31 | return new LanguageSupport(language, []);
32 | }
33 |
--------------------------------------------------------------------------------
/src/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # https://vitepress.dev/reference/default-theme-home-page
3 | layout: home
4 |
5 | hero:
6 | name: "Handlebars"
7 | tagline: Minimal templating on steroids
8 | image:
9 | src: /handlebars-icon.svg
10 | alt: Handlebars icon
11 | actions:
12 | - theme: brand
13 | text: Get started →
14 | link: /guide/
15 | - theme: alt
16 | text: Live Demo →
17 | link: /playground.html
18 |
19 | features:
20 | - title: Semantic templates
21 | details:
22 | Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.
23 | - title: Mustache-compatible
24 | details:
25 | Handlebars is largely compatible with Mustache templates. In most cases it is possible to swap out Mustache with
26 | Handlebars and continue using your current templates.
27 | - title: Fast execution
28 | details:
29 | Handlebars compiles templates into JavaScript functions. This makes the template execution faster than most other
30 | template engines.
31 | ---
32 |
--------------------------------------------------------------------------------
/src/snippets/precompilation/example.precompiled.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var template = Handlebars.template,
3 | templates = (Handlebars.templates = Handlebars.templates || {});
4 | templates["example"] = template({
5 | compiler: [8, ">= 4.3.0"],
6 | main: function (container, depth0, helpers, partials, data) {
7 | var helper,
8 | alias1 = container.propertyIsEnumerable;
9 |
10 | return (
11 | "Handlebars " +
12 | container.escapeExpression(
13 | ((helper =
14 | (helper = helpers.doesWhat || (depth0 != null ? depth0.doesWhat : depth0)) != null
15 | ? helper
16 | : container.hooks.helperMissing),
17 | typeof helper === "function"
18 | ? helper.call(depth0 != null ? depth0 : container.nullContext || {}, {
19 | name: "doesWhat",
20 | hash: {},
21 | data: data,
22 | })
23 | : helper),
24 | ) +
25 | " precompiled!"
26 | );
27 | },
28 | useData: true,
29 | });
30 | })();
31 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/share-utils.js:
--------------------------------------------------------------------------------
1 | const CURRENT_SHARING_FORMAT = 1;
2 |
3 | export function createSharedUrl(currentExample) {
4 | let currentExampleAsJson = JSON.stringify(currentExample);
5 | const { protocol, host } = document.location;
6 | const hash = "#format=" + CURRENT_SHARING_FORMAT + "¤tExample=" + encodeURIComponent(currentExampleAsJson);
7 | return `${protocol}//${host}/playground.html${hash}`;
8 | }
9 |
10 | export function loadFromSharedUrl() {
11 | const hashMatch = document.location.hash.match(/#format=(\d+)¤tExample=(.*)/);
12 | if (hashMatch) {
13 | const format = Number(hashMatch[1]);
14 | const encodedExampleData = hashMatch[2];
15 | switch (format) {
16 | case 1:
17 | return loadFromFormatVersion1(encodedExampleData);
18 | default:
19 | throw new Error("Unknown example sharing format " + format);
20 | }
21 | }
22 | }
23 |
24 | function loadFromFormatVersion1(encodedExampleData) {
25 | const decodedExampleData = decodeURIComponent(encodedExampleData);
26 | return JSON.parse(decodedExampleData);
27 | }
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/handlebars-lang/docs/actions/workflows/ci.yml)
2 |
3 | This is the repository for the Handlebars documentation site.
4 |
5 | * Target-URL: https://handlebarsjs.com
6 |
7 | # Why VitePress?
8 |
9 | There are a lot of static page generators out there nowadays.
10 | I have chosen [VitePress](https://vitepress.dev/) over other systems for several reasons:
11 |
12 | * I like [vuejs](https://vuejs.org).
13 | * VitePress builds fast loading static sites with modern PWA technologies.
14 | * VitePress is centered around markdown, but leaves the opportunity to inject interactive parts if needed.
15 | * VitePress has a simple predefined way of adapting stylesheets, which makes it easy to adapt colors from the
16 | original site without rewriting the whole css
17 | * The vuejs documentation site is build with VitePress, so it will hopefully be around for a while.
18 |
19 | You can challenge me and propose other solutions, but you might be asked to help out if you do.
20 |
21 | -- Nils
22 |
23 | :rocket: :rocket:
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011-2017 by Yehuda Katz
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/ko/guide/installation/when-to-use-handlebars.md:
--------------------------------------------------------------------------------
1 | # Handlebars를 사용할 때와 사용하지 말아야 할 때?
2 |
3 | 이 섹션은 Handlebars의 강점과 약점에 대한 개요를 제공 합니다. Handlebars가 사용 사례에 적합한지 여부를 파악하고,
4 | Handlebars를 선택할지 여부에 대한 통찰력있는 결정을 내릴 수 있도록 돕습니다.
5 |
6 | ::: info 브라우저에서 Handlebars를 사용하는 데 관한 참고사항입니다.
7 |
8 | Handlebars는 순수한 렌더링 엔진입니다. HTML 페이지, 이메일 또는 마크다운 파일을 렌더링하는 경우에 잘 작동합니다.
9 |
10 | Handlebars에는 **이벤트 처리**, **백엔드 서비스** 접근 또는 **증분 DOM 업데이트**를 위한 내장 지원이 없습니다.
11 |
12 | 사용자 입력을 처리하고 **싱글 페이지 애플리케이션**을 구축하려는 경우, 아마도 Vue.js나 React와 같은 프레임워크를 찾아보
13 | 는 것이 좋습니다.:
14 |
15 | - [Angular](https://angular.io/)
16 | - [Aurelia](https://aurelia.io/)
17 | - [Ember](https://emberjs.com/)
18 | - [Inferno](https://infernojs.org/)
19 | - [Mithril](https://mithril.js.org/)
20 | - [Svelte](https://svelte.dev/)
21 | - [Ractive](https://ractive.js.org/)
22 | - [React](https://reactjs.org/)
23 | - [Vue](https://vuejs.org/)
24 |
25 | :::
26 |
27 | # Handlebars의 장점
28 |
29 | - Handlebars는 CLI 애플리케이션, HTML이 아닌 텍스트 콘텐츠, 순수 콘텐츠의 서버 측 렌더링에 좋습니다.
30 | - Handlebars는 많은 프로그래밍 언어로 이식되었습니다(Java, Rust 등).
31 |
32 | # Handlebars의 단점
33 |
34 | - Handlebars는 DOM의 빠른(증분적) 업데이트, 이벤트 처리, 프론트엔드-백엔드 통신에 적합하지 않습니다.
35 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/execute-example.js:
--------------------------------------------------------------------------------
1 | import json5 from "json5";
2 |
3 | export function executeExample(Handlebars, parsedExample) {
4 | const handlebars = prepareHandlebarsInstance(Handlebars, parsedExample);
5 | return compileAndRun(handlebars, parsedExample);
6 | }
7 |
8 | function prepareHandlebarsInstance(Handlebars, parsedExample) {
9 | const handlebars = Handlebars.create();
10 | registerPartials(handlebars, parsedExample.partials);
11 | runPreparationScript(handlebars, parsedExample.preparationScript);
12 | return handlebars;
13 | }
14 |
15 | function registerPartials(handlebars, partials) {
16 | partials.forEach((partial) => {
17 | handlebars.registerPartial(partial.name, partial.content);
18 | });
19 | }
20 |
21 | function runPreparationScript(handlebars, preparationScript) {
22 | const compiledPreparationScript = Function("Handlebars", preparationScript);
23 | compiledPreparationScript.call(undefined, handlebars);
24 | }
25 |
26 | function compileAndRun(handlebars, parsedExample) {
27 | const template = handlebars.compile(parsedExample.template);
28 | let inputObject = json5.parse(parsedExample.input);
29 | return template(inputObject);
30 | }
31 |
--------------------------------------------------------------------------------
/src/zh/api-reference/data-variables.md:
--------------------------------------------------------------------------------
1 | # `@data` 变量
2 |
3 | 下面的`@data`变量是由 Handlebars 及其内建助手代码实现的。
4 |
5 | ## `@root`
6 |
7 | 初始化模版被执行时的上下文。
8 |
9 | ```handlebars
10 | {{#each array}} {{@root.foo}} {{/each}}
11 | ```
12 |
13 | 除非特意改变,对于页面渲染时的每一部分,本项的值恒定。因此,当深度参数不能够引用它们的父模版时,本项可以在代码片段内使用。
14 |
15 | ## `@first`
16 |
17 | 本项会被 `each` 助手代码在迭代的第一步被设置为 true。
18 |
19 | ```handlebars
20 | {{#each array}} {{#if @first}} First! {{/if}} {{/each}}
21 | ```
22 |
23 | ## `@index`
24 |
25 | 从零开始的编号,表示当前的迭代次数。由 `each` 助手代码设置。
26 |
27 | ```handlebars
28 | {{#each array}} {{@index}} {{/each}}
29 | ```
30 |
31 | ## `@key`
32 |
33 | 当前迭代次数的键。在遍历对象时被 `each` 助手代码设置。
34 |
35 | ```handlebars
36 | {{#each array}} {{@key}} {{/each}}
37 | ```
38 |
39 | ## `@last`
40 |
41 | 在迭代的最后一步被 `each` 助手代码设置为 true。
42 |
43 | ```handlebars
44 | {{#each array}} {{#if @last}} Last :( {{/if}} {{/each}}
45 | ```
46 |
47 | ## `@level`
48 |
49 | 设定 log 的输出级别。
50 |
51 | ```js
52 | template({}, { data: { level: Handlebars.logger.WARN } });
53 | ```
54 |
55 | 可以为以下值:`Handlebars.logger.DEBUG`,`Handlebars.logger.INFO`,`Handlebars.logger.WARN` 或者
56 | `Handlebars.logger.ERROR`
57 |
58 | 当设定时,程序会按照设定的级别选择输出的信息。默认值为 `Handlebars.logger.ERROR`。
59 |
--------------------------------------------------------------------------------
/src/examples/_example-base-data.yaml:
--------------------------------------------------------------------------------
1 | # In order to make the examples in this site recognizable, we generally use this data as their basis.
2 | # If you want to create new example, you can use parts of this data along with your templates, partials and helpers.
3 | # You don't have to use the same JSON structure, but using the same entities (i.e. people, Darmstadt, San Francisco)
4 | # would be nice. If you have to use new data, please add it to this file.
5 | cities:
6 | - name: Darmstadt
7 | summary: Darmstadt is a city in Hesse, Germany
8 | country: Germany
9 | location:
10 | north: 49.87
11 | east: 8.64
12 | population: 158254
13 | - name: San Francisco
14 | summary: San Francisco is the cultural center of Northern California
15 | country: USA
16 | location:
17 | north: 37.73,
18 | east: -122.44
19 | population: 883305
20 | people:
21 | - firstname: Nils
22 | lastname: Knappmeier
23 | url: https://knappi.org
24 | resident-in: Darmstadt
25 | - firstname: Yehuda
26 | lastname: Katz
27 | url: https://yehudakatz.com/
28 | resident-in: San Francisco
29 | - firstname: Carl
30 | lastname: Lerche
31 | - firstname: Alan
32 | lastname: Johnson
33 |
--------------------------------------------------------------------------------
/src/ko/examples/_example-base-data.yaml:
--------------------------------------------------------------------------------
1 | # In order to make the examples in this site recognizable, we generally use this data as their basis.
2 | # If you want to create new example, you can use parts of this data along with your templates, partials and helpers.
3 | # You don't have to use the same JSON structure, but using the same entities (i.e. people, Darmstadt, San Francisco)
4 | # would be nice. If you have to use new data, please add it to this file.
5 | cities:
6 | - name: Darmstadt
7 | summary: Darmstadt is a city in Hesse, Germany
8 | country: Germany
9 | location:
10 | north: 49.87
11 | east: 8.64
12 | population: 158254
13 | - name: San Francisco
14 | summary: San Francisco is the cultural center of Northern California
15 | country: USA
16 | location:
17 | north: 37.73,
18 | east: -122.44
19 | population: 883305
20 | people:
21 | - firstname: Nils
22 | lastname: Knappmeier
23 | url: https://knappi.org
24 | resident-in: Darmstadt
25 | - firstname: Yehuda
26 | lastname: Katz
27 | url: https://yehudakatz.com/
28 | resident-in: San Francisco
29 | - firstname: Carl
30 | lastname: Lerche
31 | - firstname: Alan
32 | lastname: Johnson
33 |
--------------------------------------------------------------------------------
/src/zh/examples/_example-base-data.yaml:
--------------------------------------------------------------------------------
1 | # In order to make the examples in this site recognizable, we generally use this data as their basis.
2 | # If you want to create new example, you can use parts of this data along with your templates, partials and helpers.
3 | # You don't have to use the same JSON structure, but using the same entities (i.e. people, Darmstadt, San Francisco)
4 | # would be nice. If you have to use new data, please add it to this file.
5 | cities:
6 | - name: Darmstadt
7 | summary: Darmstadt is a city in Hesse, Germany
8 | country: Germany
9 | location:
10 | north: 49.87
11 | east: 8.64
12 | population: 158254
13 | - name: San Francisco
14 | summary: San Francisco is the cultural center of Northern California
15 | country: USA
16 | location:
17 | north: 37.73,
18 | east: -122.44
19 | population: 883305
20 | people:
21 | - firstname: Nils
22 | lastname: Knappmeier
23 | url: https://knappi.org
24 | resident-in: Darmstadt
25 | - firstname: Yehuda
26 | lastname: Katz
27 | url: https://yehudakatz.com/
28 | resident-in: San Francisco
29 | - firstname: Carl
30 | lastname: Lerche
31 | - firstname: Alan
32 | lastname: Johnson
33 |
--------------------------------------------------------------------------------
/src/.vitepress/components/PlaygroundLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
43 |
--------------------------------------------------------------------------------
/src/ko/api-reference/data-variables.md:
--------------------------------------------------------------------------------
1 | # `@data` 변수
2 |
3 | 다음 `@data` 변수들은 Handlebars와 내장 헬퍼에 의해 구현됩니다.
4 |
5 | ## `@root`
6 |
7 | 템플릿이 실행된 초기 컨텍스트입니다.
8 |
9 | ```handlebars
10 | {{#each array}} {{@root.foo}} {{/each}}
11 | ```
12 |
13 | 명시적으로 수정되지 않는 한, 이 값은 페이지 렌더링의 모든 부분에서 일관되게 유지되므로, 깊은 매개변수가 상위 템플릿을 참
14 | 조할 수 없는 부분 템플릿 내에서도 사용할 수 있습니다.
15 |
16 | ## `@first`
17 |
18 | 반복의 첫 번째 단계에서 `each` 헬퍼에 의해 true로 설정됩니다.
19 |
20 | ```handlebars
21 | {{#each array}} {{#if @first}} First! {{/if}} {{/each}}
22 | ```
23 |
24 | ## `@index`
25 |
26 | 현재 반복 단계의 0부터 시작하는 인덱스입니다. `each` 헬퍼에 의해 설정됩니다.
27 |
28 | ```handlebars
29 | {{#each array}} {{@index}} {{/each}}
30 | ```
31 |
32 | ## `@key`
33 |
34 | 현재 반복 단계의 키 이름입니다. 객체를 반복할 때 `each` 헬퍼에 의해 설정됩니다.
35 |
36 | ```handlebars
37 | {{#each array}} {{@key}} {{/each}}
38 | ```
39 |
40 | ## `@last`
41 |
42 | 반복의 마지막 단계에서 `each` 헬퍼에 의해 true로 설정됩니다.
43 |
44 | ```handlebars
45 | {{#each array}} {{#if @last}} Last :( {{/if}} {{/each}}
46 | ```
47 |
48 | ## `@level`
49 |
50 | 로그 레벨을 할당합니다.
51 |
52 | ```js
53 | template({}, { data: { level: Handlebars.logger.WARN } });
54 | ```
55 |
56 | `Handlebars.logger.DEBUG`,`Handlebars.logger.INFO`,`Handlebars.logger.WARN` 또는 `Handlebars.logger.ERROR` 중 하나로설
57 | 정할 수 있습니다.
58 |
59 | 설정하게 되면, 로거는 출력에 `Handlebars.logger.level` 이상의 로그 레벨을 가진 메시지만 포함합니다. 기본 값은
60 | `Handlebars.logger.ERROR`입니다.
61 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/WorkspaceElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
45 |
--------------------------------------------------------------------------------
/src/guide/installation/when-to-use-handlebars.md:
--------------------------------------------------------------------------------
1 | # When (not) to use Handlebars?
2 |
3 | This section should give you an overview over the strengths and weaknesses of Handlebars. Ideally, it enables you to see
4 | if handlebars fits your use case and make an informed decision about choosing handlebars or not.
5 |
6 | ::: info A note on using Handlebars in the browser
7 |
8 | Handlebars is a pure rendering engine. It works well if you want to allow people to write templates for rendering
9 | HTML-pages, e-mails or markdown files.
10 |
11 | It has **no** built-in support for **event-handling**, accessing **backend-services** or incremental **DOM updates**.
12 |
13 | If you want to build a **single-page application** and you want to handle user-input, you should probably look for a
14 | framework like
15 |
16 | - [Angular](https://angular.io/)
17 | - [Aurelia](https://aurelia.io/)
18 | - [Ember](https://emberjs.com/)
19 | - [Inferno](https://infernojs.org/)
20 | - [Mithril](https://mithril.js.org/)
21 | - [Svelte](https://svelte.dev/)
22 | - [Ractive](https://ractive.js.org/)
23 | - [React](https://reactjs.org/)
24 | - [Vue](https://vuejs.org/)
25 |
26 | :::
27 |
28 | ## Pro Handlebars
29 |
30 | - Handlebars is good for rendering in CLI-apps, non-HTML text content, server-side rendering of pure contents.
31 | - Handlebars has been ported to many programming languages (Java, Rust etc).
32 |
33 | ## Contra Handlebars
34 |
35 | - Handlebars is not good for fast (incremental) updates of the DOM, event-handling, frontend-backend communication.
36 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/execute-example.test.js:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from "vitest";
2 | import { executeExample } from "./execute-example";
3 | import Handlebars from "handlebars";
4 |
5 | describe("the handlebars runner", () => {
6 | it("should run a simple example", () => {
7 | expect(runWithAppliedDefaultValues({ template: "{{name}}", input: '{ name: "Erwin"}' })).toEqual("Erwin");
8 | });
9 |
10 | it("should register partials", () => {
11 | expect(
12 | runWithAppliedDefaultValues({
13 | template: "template {{>partial}}",
14 | partials: [{ name: "partial", content: "partial {{name}}" }],
15 | input: '{ name: "Erwin"}',
16 | }),
17 | ).toEqual("template partial Erwin");
18 | });
19 |
20 | it("should execute the preparation-script", () => {
21 | expect(
22 | runWithAppliedDefaultValues({
23 | template: "{{loud name}}",
24 | // language=JavaScript
25 | preparationScript: 'Handlebars.registerHelper("loud", function (arg) { return arg.toUpperCase() })',
26 | input: '{ name: "Erwin"}',
27 | }),
28 | ).toEqual("ERWIN");
29 | });
30 |
31 | it("should throw parse errors", () => {
32 | expect(() => runWithAppliedDefaultValues({ template: "{{loud" })).toThrow();
33 | });
34 | });
35 |
36 | function runWithAppliedDefaultValues(incompleteExample) {
37 | const exampleDefaults = { template: "", partials: [], preparationScript: "", input: "{}" };
38 | return executeExample(Handlebars, { ...exampleDefaults, ...incompleteExample });
39 | }
40 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/HighlightedCode.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
43 |
44 |
53 |
54 |
63 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/execute-one-after-another.test.js:
--------------------------------------------------------------------------------
1 | import { describe, it, expect, vi } from "vitest";
2 | import { executeOneAfterAnother } from "./execute-one-after-another";
3 |
4 | describe("oneAfterAnother", () => {
5 | it("without: ensure call order with non-wrapped function", async () => {
6 | const mockFunction = vi.fn();
7 | const promise1 = delay(100).then(() => mockFunction("a"));
8 | const promise2 = delay(50).then(() => mockFunction("b"));
9 | const promise3 = delay(0).then(() => mockFunction("c"));
10 |
11 | await Promise.all([promise1, promise2, promise3]);
12 | expect(mockFunction).toHaveBeenNthCalledWith(1, "c");
13 | expect(mockFunction).toHaveBeenNthCalledWith(2, "b");
14 | expect(mockFunction).toHaveBeenNthCalledWith(3, "a");
15 | });
16 |
17 | it("should resolve promises in sequence", async () => {
18 | const wrappedFunction = executeOneAfterAnother(delay);
19 | const mockFunction = vi.fn();
20 | const promise1 = wrappedFunction(100).then(() => mockFunction("a"));
21 | const promise2 = wrappedFunction(50).then(() => mockFunction("b"));
22 | const promise3 = wrappedFunction(0).then(() => mockFunction("c"));
23 |
24 | await Promise.all([promise1, promise2, promise3]);
25 | expect(mockFunction).toHaveBeenNthCalledWith(1, "a");
26 | expect(mockFunction).toHaveBeenNthCalledWith(2, "b");
27 | expect(mockFunction).toHaveBeenNthCalledWith(3, "c");
28 | });
29 | });
30 |
31 | async function delay(milliseconds) {
32 | return new Promise((resolve) => setTimeout(resolve, milliseconds));
33 | }
34 |
--------------------------------------------------------------------------------
/src/zh/api-reference/compilation.md:
--------------------------------------------------------------------------------
1 | # 编译和预编译
2 |
3 | ## `Handlebars.compile(template, options)`
4 |
5 | 编译一个模版以立即运行。
6 |
7 | ```js
8 | const template = Handlebars.compile("{{foo}}");
9 | template({});
10 | ```
11 |
12 | 支持多种选项以更改模版的执行方式。
13 |
14 | ::: v-pre
15 |
16 | - `data`: 设置为 `false` 以终止 `@data` 跟踪。
17 | - `compat`: 设置为 `true` 以允许递归领域查找。
18 | - `knownHelpers`: 将已知在模版运行时会真实存在的助手代码列表 Hash 化。输入本参数会使编译器在一些情况下优化。内置助手代码已经在本列表里包含,但若设置本项为
19 | `false`,内置的助手代码可能会被忽视。
20 | - `knownHelpersOnly`: 设置为 `true` 以允许基于已知助手代码列表的进一步优化。
21 | - `noEscape`: 设置为 `true` 以避免 HTML 的内容转义。
22 | - `strict`: 在严格模式下运行。在这个模式下,模版将会对缺失参数抛出异常,而非静默忽略。同时,这种模式将会禁止逆操作,比如
23 | `{{^foo}}{{/foo}}`,除非领域被特意包含在源对象中。
24 | - `assumeObjects`: 在遍历路径时,不再检查对象是否存在。这是严格模式的子集,本子集在已知输入安全的情况下会生成最优模版。
25 | - `preventIndent`: 默认情况下,缩进的代码片段调用将会导致代码片段整体全部被缩进。在代码片段写入 `pre`
26 | 标签时,这会造成未预料到的结果。将本项设置成 `true` 可以避免这种自动缩进的功能。
27 | - `ignoreStandalone`: 当设置为 `true`
28 | 时,将不会去除单独的标签。在这种情况下,不在同一行的代码块和代码片段将不会去除本行里的空格。
29 | - `explicitPartialContext`: 对代码片段的上下文进行精确设置。当开启时,没有设置上下文的代码片段将会依托空对象执行。
30 |
31 | :::
32 |
33 | ## `Handlebars.precompile(template, options)`
34 |
35 | 对一个模版进行预编译,这样可以直接将模版送到客户端并执行而不需要再编译。
36 |
37 | ```js
38 | var templateSpec = Handlebars.precompile("{{foo}}");
39 | ```
40 |
41 | 与 `Handlebars.compile` 方法的参数相同,并且额外的参数有:
42 |
43 | - `srcName`: 生成输入文件的源键值表。当运行时,返回的结构为 `{code, map}`。 `code` 包含模版的定义,`map` 包含源键值表。
44 | - `destName`: 可选,本参数可以与 `srcName` 一起使用以在生成源键值表的时候同时提供目标文件的名称。
45 |
46 | ## `Handlebars.template(templateSpec)`
47 |
48 | 设置一个已经被 `Handlebars.precompile` 预编译的模版。
49 |
50 | ```js
51 | var template = Handlebars.template(templateSpec);
52 | template({});
53 | ```
54 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/in-browser-example-executor/limit-waiting-time.test.js:
--------------------------------------------------------------------------------
1 | import { describe, it, expect, vi } from "vitest";
2 | import { limitWaitingTime, TimeoutError } from "./limit-waiting-time";
3 |
4 | describe("limitWaitingTime", () => {
5 | it("should resolve if the given promise resolves", async () => {
6 | const timeoutCallback = vi.fn();
7 | const testPromise = delay(100).then(() => "a");
8 |
9 | const resultPromise = limitWaitingTime(testPromise, 200, timeoutCallback);
10 |
11 | await expect(resultPromise).resolves.toEqual("a");
12 | expect(timeoutCallback).not.toHaveBeenCalled();
13 | });
14 |
15 | it("should reject the promise after a timeout", async () => {
16 | const timeoutCallback = vi.fn();
17 | const testPromise = delay(200).then(() => "a");
18 |
19 | const resultPromise = limitWaitingTime(testPromise, 100, timeoutCallback);
20 |
21 | await expect(resultPromise).rejects.toEqual(new TimeoutError("Timed out after 100ms"));
22 | expect(timeoutCallback).toHaveBeenCalledTimes(1);
23 | });
24 |
25 | it("should reject if the given promise reject before the timeout, without calling the timeoutCallback ", async () => {
26 | const timeoutCallback = vi.fn();
27 | const testPromise = delay(100).then(() => {
28 | throw new Error("b");
29 | });
30 |
31 | const resultPromise = limitWaitingTime(testPromise, 200, timeoutCallback);
32 |
33 | await expect(resultPromise).rejects.toEqual(new Error("b"));
34 | expect(timeoutCallback).not.toHaveBeenCalled();
35 | });
36 | });
37 |
38 | async function delay(milliseconds) {
39 | return new Promise((resolve) => setTimeout(resolve, milliseconds));
40 | }
41 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/codemirror-languages/handlebars.js:
--------------------------------------------------------------------------------
1 | import { parser } from "./handlebars.parser.js";
2 | import { LRLanguage, LanguageSupport } from "@codemirror/language";
3 | import { html, htmlLanguage } from "@codemirror/lang-html";
4 | import { styleTags, tags as t } from "@lezer/highlight";
5 | import { parseMixed } from "@lezer/common";
6 |
7 | let parserWithMetadata = parser.configure({
8 | strict: false,
9 | props: [
10 | styleTags({
11 | Name: t.name,
12 | Prop: t.name,
13 | Array: t.name,
14 | Context: t.name,
15 | BlockParam: t.name,
16 | Bool: t.bool,
17 | Number: t.number,
18 | This: t.className,
19 | "BlockHelper As DataVariable PartialBlock Else BlockHelperClose": t.className,
20 | Partial: t.className,
21 | InlinePartial: t.className,
22 | String: t.string,
23 | Comment1: t.blockComment,
24 | Comment2: t.blockComment,
25 | "# > | @": t.annotation,
26 | '"/"': t.annotation,
27 | "=": t.operator,
28 | "MustacheOpen MustacheClose {{{ }}} {{{{ }}}}": [t.brace, t.bool],
29 | "( ) [ ]": t.bracket,
30 | }),
31 | ],
32 | wrap: parseMixed((node) => {
33 | return node.type.isTop
34 | ? {
35 | parser: htmlLanguage.parser,
36 | overlay: (node) => node.name === "Text",
37 | }
38 | : null;
39 | }),
40 | });
41 |
42 | const language = LRLanguage.define({
43 | name: "handlebars",
44 | parser: parserWithMetadata,
45 | languageData: {
46 | commentTokens: { block: { open: "{{!", close: "}}" } },
47 | },
48 | });
49 |
50 | export function handlebars() {
51 | return new LanguageSupport(language, [html().support]);
52 | }
53 |
--------------------------------------------------------------------------------
/src/api-reference/data-variables.md:
--------------------------------------------------------------------------------
1 | # `@data` variables
2 |
3 | The following `@data` variables are implemented by Handlebars and its builtin helpers.
4 |
5 | ## `@root`
6 |
7 | Initial context with which the template was executed.
8 |
9 | ```handlebars
10 | {{#each array}} {{@root.foo}} {{/each}}
11 | ```
12 |
13 | Unless explicitly modified, this value is consistent across all portions of the page rendering, meaning it can be used
14 | within partials where depthed parameters are unable to reference their parent templates.
15 |
16 | ## `@first`
17 |
18 | Set to true by the `each` helper for the first step of iteration.
19 |
20 | ```handlebars
21 | {{#each array}} {{#if @first}} First! {{/if}} {{/each}}
22 | ```
23 |
24 | ## `@index`
25 |
26 | Zero-based index for the current iteration step. Set by the `each` helper.
27 |
28 | ```handlebars
29 | {{#each array}} {{@index}} {{/each}}
30 | ```
31 |
32 | ## `@key`
33 |
34 | Key name for the current iteration step. Set by the `each` helper when iterating over objects.
35 |
36 | ```handlebars
37 | {{#each array}} {{@key}} {{/each}}
38 | ```
39 |
40 | ## `@last`
41 |
42 | Set to true by the `each` helper for the last step of iteration.
43 |
44 | ```handlebars
45 | {{#each array}} {{#if @last}} Last :( {{/if}} {{/each}}
46 | ```
47 |
48 | ## `@level`
49 |
50 | Assigned log level.
51 |
52 | ```js
53 | template({}, { data: { level: Handlebars.logger.WARN } });
54 | ```
55 |
56 | May be set to one of `Handlebars.logger.DEBUG` , `Handlebars.logger.INFO` , `Handlebars.logger.WARN` , or
57 | `Handlebars.logger.ERROR`
58 |
59 | When set, the logger will include in its output only messages with a log level of `Handlebars.logger.level` or higher.
60 | The default value is `Handlebars.logger.ERROR`.
61 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/CodeEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
57 |
58 |
66 |
--------------------------------------------------------------------------------
/src/zh/guide/hooks.md:
--------------------------------------------------------------------------------
1 | # 钩子
2 |
3 | 你可以在几个地方使用钩子挂接到 Handlebars 的函数调用。
4 |
5 | ## helperMissing
6 |
7 | 当 Mustache 或表达式是如下情况时钩子会被调用:
8 |
9 | - Mustache 表达式不是一个已经注册的助手代码,**并且**
10 | - 不是当前上下文的计算属性。
11 |
12 | 你可以通过注册 `helperMissing` 助手代码为这些情况添加自定义处理:
13 |
14 |
15 |
16 |
17 |
18 | 与任何自定义助手代码或块助手代码一样,该助手代码接收相同的参数和选项(`hash`,`name`等)。 `option.name`
19 | 是被调用的助手代码的名称。
20 |
21 | ### 默认行为
22 |
23 | 如果没有参数传递给 Mustache,则默认行为是不执行任何操作并忽略整个表达式或代码块:
24 |
25 |
26 |
27 |
28 |
29 |
30 | 如果有参数传递给 Mustache,则 Handlebars 将引发异常:
31 |
32 |
33 |
34 |
35 |
36 |
37 | ## blockHelperMissing
38 |
39 | 遇到如下情况时,钩子将会被调用:
40 |
41 | - 代码块表达式尝试调用未注册的助手代码,
42 | - 但是这个助手代码的名称与当前计算上下文中的某个属性相同。
43 |
44 | 你可以通过注册一个名为 `blockHelperMissing` 的助手代码来处理这种情况。
45 |
46 |
47 |
48 |
49 |
50 | ### 默认行为
51 |
52 | 钩子将在当前上下文中使用已解析的属性值作为参数进行调用,并且将 `options.name` 字段设置为属性的名称。
53 |
54 | 如果钩子没有被覆盖,则默认实现将模仿 Mustache 的行为:只调用代码块。
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/.vitepress/components/TryoutIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
30 |
45 |
--------------------------------------------------------------------------------
/src/ko/api-reference/compilation.md:
--------------------------------------------------------------------------------
1 | # (사전) 컴파일
2 |
3 | ## `Handlebars.compile(template, options)`
4 |
5 | 템플릿을 컴파일하여 즉시 실행할 수 있게 합니다.
6 |
7 | ```js
8 | const template = Handlebars.compile("{{foo}}");
9 | template({});
10 | ```
11 |
12 | 템플릿 실행 방식을 변경하는 다양한 옵션을 지원합니다.
13 |
14 | ::: v-pre
15 |
16 | - `data`: `@data` 추적을 비활성화하려면 false로 설정합니다.
17 | - `compat`: 재귀 필드 조회를 활성화하려면 true로 설정합니다.
18 | - `knownHelpers`: 템플릿 실행 시 존재하는 것으로 알려진 헬퍼 목록을 포함하는 해시입니다. 이를 전달하면 컴파일러가 여러
19 | 경우를 최적화할 수 있습니다. 내장 헬퍼는 이 목록에 자동으로 포함되며 값을 `false`로 설정하여 생략할 수 있습니다.
20 | - `knownHelpersOnly`: 알려진 헬퍼 목록을 기반으로 추가 최적화를 허용하려면 true로 설정합니다.
21 | - `noEscape`: HTML 이스케이프를 하지 않으려면 true로 설정합니다.
22 | - `strict`: 엄격 모드에서 실행합니다. 이 모드에서는 누락된 필드를 묵인하지 않고 예외를 발생시킵니다. 이로 인해
23 | `{{^foo}}{{/foo}}`와 같은 역 연산이 데이터 소스 객체에 명시적으로 포함되지 않으면 비활성화됩니다.
24 | - `assumeObjects`: 경로를 탐색할 때 객체 존재 여부 확인을 제거합니다. 이는 데이터 입력이 안전하다고 알려진 경우 최적화된
25 | 템플릿을 생성하는 엄격 모드의 하위 집합입니다.
26 | - `preventIndent`: 기본적으로 들여쓰기된 부분 템플릿 호출은 전체 부분 템플릿 출력이 동일한 양으로 들여쓰기되게 합니다.
27 | 이는 부분 템플릿이 `pre` 태그를 작성할 때 예기치 않은 동작을 초래할 수 있습니다. 이 옵션을 `true`로 설정하면 자동 들여
28 | 쓰기 기능이 비활성화됩니다.
29 | - `ignoreStandalone`: 설정 시 독립 태그 제거를 비활성화합니다. 설정하면 블록과 부분 템플릿이 각자 줄에 있을 때 해당 줄의
30 | 공백을 제거하지 않습니다.
31 | - `explicitPartialContext`: 부분 템플릿의 암시적 컨텍스트를 비활성화합니다. 활성화되면 컨텍스트 값을 전달받지 않은 부분
32 | 템플릿은 빈 객체를 대상으로 실행됩니다.
33 |
34 | :::
35 |
36 | ## `Handlebars.precompile(template, options)`
37 |
38 | 주어진 템플릿을 사전 컴파일하여 클라이언트로 전송한 후 컴파일 없이 실행할 수 있게 합니다.
39 |
40 | ```js
41 | var templateSpec = Handlebars.precompile("{{foo}}");
42 | ```
43 |
44 | `Handlebars.compile` 메서드와 동일한 옵션 매개변수를 지원합니다. 추가적으로 다음을 전달할 수 있습니다:
45 |
46 | - `srcName`: 입력 파일의 소스 맵을 생성하기 위해 전달됩니다. 이렇게 실행되면 반환 구조는 `{code, map}`이며, `code`에는
47 | 템플릿 정의가 포함되고 `map`에는 소스 맵이 포함됩니다.
48 | - `destName`: 소스 맵을 생성할 때 `srcName`과 함께 사용되는 선택적 매개변수로, 대상 파일 이름을 제공합니다.
49 |
50 | ## `Handlebars.template(templateSpec)`
51 |
52 | `Handlebars.precompile`로 사전 컴파일된 템플릿을 설정합니다.
53 |
54 | ```js
55 | var template = Handlebars.template(templateSpec);
56 | template({});
57 | ```
58 |
--------------------------------------------------------------------------------
/src/zh/guide/installation/integrations.md:
--------------------------------------------------------------------------------
1 | # 集成
2 |
3 | 以下软件包在不同的环境中集成了 Handlebars。这些软件包 **并非** 由 Handlebars 团队负责。
4 |
5 | 有多个 Webpack 插件,可让你在 Webpack 环境中使用 Handlebars。
6 |
7 | ## Webpack: handlebars-loader
8 |
9 | [handlebars-loader](https://github.com/pcardune/handlebars-loader) 允许你导入 [预编译](./precompilation.html)
10 | 模板。只需将你的 handlebars-template 写入 `template.handlebars` 文件中,然后使用
11 |
12 | ```js
13 | const compiledTemplate = require("./template.handlebars");
14 | ```
15 |
16 | 或是
17 |
18 | ```js
19 | import compiledTemplate from "./template.handlebars";
20 | ```
21 |
22 | ## Webpack: handlebars-webpack-plugin
23 |
24 | [handlebars-webpack-plugin](https://github.com/sagold/handlebars-webpack-plugin) 使用 Handlebars 构建你的静态 HTML 页面
25 |
26 | ## Webpack: html-bundler-webpack-plugin
27 |
28 | [html-bundler-webpack-plugin](https://github.com/webdiscus/html-bundler-webpack-plugin) 支持使用包括
29 | [Handlebars](https://github.com/webdiscus/html-bundler-webpack-plugin#using-the-handlebars)
30 | 在内的几种模板引擎来渲染模板,并将样式和脚本打包到生成的 HTML 文件中。
31 |
32 | ## Babel: handlebars-inline-precompile
33 |
34 | [babel-plugin-handlebars-inline-precompile](https://github.com/jamiebuilds/babel-plugin-handlebars-inline-precompile)
35 | 提供了预编译的 Handlebars 模板,这些模板在 JavaScript 源代码中作为模板文本提供:
36 |
37 | ```js
38 | import hbs from "handlebars-inline-precompile";
39 | const compiledTemplate = hbs`{{name}}`;
40 | ```
41 |
42 | 请参阅包文档以获取设置说明。
43 |
44 | ## Browserify: hbsfy
45 |
46 | [hbsfy](https://www.npmjs.com/package/hbsfy) 包可让你在浏览器中导入预编译的模板环境:
47 |
48 | ```js
49 | const compiledTemplate = require("./template.handlebars");
50 | ```
51 |
52 | ## 包:parcel-plugin-handlebars
53 |
54 | 这里有一个较老的插件包: https://www.npmjs.com/package/parcel-plugin-handlebars
55 |
56 | 但是你应该使用这些 forks 里面的其中一个,因为它们较新: https://www.npmjs.com/search?q=parcel-plugin-handlebars
57 |
58 | 最新的一个包是: https://www.npmjs.com/package/@inventory/parcel-plugin-handlebars
59 |
60 | ## 包:parcel-plugin-handlebars-precompile
61 |
62 | TODO: 在此填写
63 |
64 | https://www.npmjs.com/package/parcel-plugin-handlebars-precompile
65 |
--------------------------------------------------------------------------------
/src/ko/guide/hooks.md:
--------------------------------------------------------------------------------
1 | # 훅(Hooks)
2 |
3 | Handlebars 함수 호출에 훅을 걸 수 있는 여러 지점이 있습니다.
4 |
5 | ## helperMissing
6 |
7 | 이 훅은 머스태시 또는 블록 문이 아래와 같은 경우 호출됩니다.
8 |
9 | - 단순 머스태시 표현식이 등록된 도우미가 **아닐 때**
10 | - 현재 평가 컨텍스트의 속성이 아닐 때
11 |
12 | 이러한 상황에 대한 사용자 정의 처리를 추가하려면 `helperMissing` 도우미를 등록할 수 있습니다.
13 |
14 |
15 |
16 |
17 |
18 | 이 도우미는 모든 사용자 정의 도우미 또는 블록 도우미와 동일한 인수 및 옵션(`hash`, `name` 등)을 받습니다.
19 | `options.name`은 호출된 도우미의 이름입니다.
20 |
21 | ### 기본 동작
22 |
23 | 머스태시에 매개 변수가 전달되지 않으면 기본 동작은 아무것도 하지 않고 전체 머스태시 표현식 또는 전체 블록을 무시하는 것
24 | 입니다:
25 |
26 |
27 |
28 |
29 |
30 |
31 | 머스태시에 매개 변수가 전달되면 Handlebars는 예외를 발생시킵니다:
32 |
33 |
34 |
35 |
36 |
37 |
38 | ## blockHelperMissing
39 |
40 | 이 훅은 다음과 같은 경우 호출됩니다:
41 |
42 | - 블록 표현식이 등록되지 않은 도우미를 호출하지만
43 | - 그 이름이 현재 평가 컨텍스트의 속성과 일치하는 경우
44 |
45 | 이 상황을 처리하려면 blockHelperMissing이라는 헬퍼를 등록할 수 있습니다.
46 |
47 |
48 |
49 |
50 |
51 | ### 기본 동작
52 |
53 | 훅은 현재 컨텍스트에서 해결된 속성 값과 `options.name` 필드가 속성 이름으로 설정된 상태로 호출됩니다.
54 |
55 | 훅이 재정의되지 않으면 기본 구현은 Mustache의 동작을 모방하여 블록을 호출합니다.
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/zh/api-reference/utilities.md:
--------------------------------------------------------------------------------
1 | ---
2 | outline: [1, 3]
3 | ---
4 |
5 | # 实用方法
6 |
7 | ## 助手代码实用方法
8 |
9 | 这些方法会帮你更轻松地实现自定义助手代码。
10 |
11 | ### `Handlebars.SafeString(string)`
12 |
13 | 防止 `string` 在模版渲染时转义。
14 |
15 | ```js
16 | new Handlebars.SafeString("HTML Content!
");
17 | ```
18 |
19 | 当构建将会被标记为安全的字符串时,为安全起见,任何外部内容都应该使用 `Handlebars.escapeExpression` 方法转义。
20 |
21 | ### `Handlebars.escapeExpression(string)`
22 |
23 | ::: v-pre
24 |
25 | HTML 转义输入的字符串,使得字符串可以安全地在 HTML 内容中渲染为文字。
26 |
27 | ```js
28 | Handlebars.Utils.escapeExpression(string);
29 | ```
30 |
31 | 将字符串值里的`&`, `<`, `>`, `"`, `'`, `` ` ``, `=` 用 HTML 实体的等效值替换。`SafeString` 的值保持不变。
32 |
33 | 除了 `{{{` 表达式之外的表达式都将被本方法处理。为了防止可能的代码注入,帮助函数也应该在返回 HTML 内容时通过一个
34 | `SafeString` 的实例来使用本函数。
35 |
36 | 本函数是 `Handlebars.Utils.escapeExpression` 的别名。
37 |
38 | :::
39 |
40 | ### `Handlebars.createFrame(data)`
41 |
42 | 由块助手代码使用以创建子数据对象。
43 |
44 | ```js
45 | if (options.data) {
46 | var data = Handlebars.createFrame(options.data);
47 | data.foo = "bar";
48 | options.data = data;
49 | }
50 | ```
51 |
52 | 更改数据状态的助手代码应会同时创建一个新的框架以将它们自己隔离并且避免和任何父程序的状态冲突。通常来说,在执行时,对每个助手代码来说只有一个框架需要被创建。比如,`each`
53 | 迭代器创建一个会被所有子执行程序应用的框架。
54 |
55 | ## General Utilities
56 |
57 | Handlebars 提供了一大批由 `Handlebars.Utils` 对象暴露的应用函数。
58 |
59 | ### `Handlebars.Utils.isEmpty(value)`
60 |
61 | 判断给定的值是否为空。
62 |
63 | Handlebars.Utils.isEmpty(value)
64 |
65 | 以上函数被内建的 `if` 与 `with` 助手代码应用以控制执行流。Handlebars 对于「空」的定义如下:
66 |
67 | - 长度为 0 的数组
68 | - 除了 0 以外的虚值
69 |
70 | 以上是为了和 [Mustache behavior](http://mustache.github.io/mustache.5.html#Sections) 匹配。
71 |
72 | ### `Handlebars.Utils.extend(obj, value)`
73 |
74 | 简单的应用函数,用于使用 `value` 里定义的所有键来增强 `obj` 。
75 |
76 | Handlebars.Utils.extend(foo, {bar: true})
77 |
78 | 将会将 `foo` 对象内的键 `bar` 对应的值设定为 `true`。
79 |
80 | ### `Handlebars.Utils.toString(obj)`
81 |
82 | 通用的 `toString` 方法。
83 |
84 | ### `Handlebars.Utils.isArray(obj)`
85 |
86 | 判断对象是否为数组。
87 |
88 | ### `Handlebars.Utils.isFunction(obj)`
89 |
90 | 判断对象是否为函数。
91 |
92 | ### `Handlebars.log(level, message)`
93 |
94 | 被 `log` 助手代码使用的输出程序。
95 |
96 | 可能会在需要时被重载。
97 |
--------------------------------------------------------------------------------
/src/.vitepress/components/playground/lib/example-parser.js:
--------------------------------------------------------------------------------
1 | import { prettify } from "./prettify";
2 | import { executeExample } from "./execute-example";
3 | import Handlebars from "handlebars";
4 |
5 | export class ExampleParser {
6 | constructor({ template, input, partials, preparationScript }) {
7 | this.normalizedExample = {
8 | template: useDefaultValueIfMissing(template, ""),
9 | input: useDefaultValueIfMissing(input, null),
10 | partials: useDefaultValueIfMissing(partials, {}),
11 | preparationScript: useDefaultValueIfMissing(preparationScript, ""),
12 | };
13 | }
14 |
15 | /**
16 | * Entrypoint for parsing
17 | */
18 | async parse() {
19 | const parsedExample = {
20 | template: this.normalizedExample.template,
21 | partials: this._partialsAsNameContentArray(),
22 | preparationScript: this.normalizedExample.preparationScript,
23 | input: (await prettify(this.normalizedExample.input)) || null,
24 | };
25 |
26 | return this._executeAndBuildExample(parsedExample);
27 | }
28 |
29 | _partialsAsNameContentArray() {
30 | return Object.keys(this.normalizedExample.partials).map((partialName) => {
31 | return {
32 | name: partialName,
33 | content: this.normalizedExample.partials[partialName],
34 | };
35 | });
36 | }
37 |
38 | _executeAndBuildExample(parsedExample) {
39 | try {
40 | const output = executeExample(Handlebars, parsedExample);
41 | return { ...parsedExample, output, error: null };
42 | } catch (error) {
43 | const errorWithEnumerableProperties = this._handlebarsExecutionErrorWithEnumerableProperties(error);
44 | return { ...parsedExample, output: null, error: errorWithEnumerableProperties };
45 | }
46 | }
47 |
48 | _handlebarsExecutionErrorWithEnumerableProperties(error) {
49 | if (error == null) {
50 | return null;
51 | }
52 | return {
53 | message: error.message,
54 | stack: error.stack,
55 | };
56 | }
57 | }
58 |
59 | function useDefaultValueIfMissing(value, defaultValue) {
60 | return value == null ? defaultValue : value;
61 | }
62 |
--------------------------------------------------------------------------------
/src/zh/guide/installation/precompilation.md:
--------------------------------------------------------------------------------
1 | # 预编译模板
2 |
3 |
6 |
7 | 使用 Handlebars 预编译器,你可以预编译 Handlebars 模板以节省客户端时间并减少 Handlebars 库所需的运行时大小。
8 |
9 | ## 入门
10 |
11 | 首先,你需要 _Node.js 和 npm_ 。转到 [https://nodejs.org/en/download/](https://nodejs.org/en/download/)
12 | 了解如何在你的操作系统上执行此操作。
13 |
14 | 接下来,安装 Handlebars npm 软件包,其中包含了预编译器。
15 |
16 | ```bash
17 | npm install -g handlebars
18 | ```
19 |
20 | 创建一个文件 `example.handlebars` 来包含模板:
21 |
22 | <<< @/snippets/precompilation/example.handlebars
23 |
24 | 运行预编译器。
25 |
26 | ```bash
27 | handlebars example.handlebars -f example.precompiled.js
28 | ```
29 |
30 | 引用 Handlebars 运行时和预编译的 JavaScript。
31 |
32 | <<< @/snippets/precompilation/index.html
33 |
34 | 也可以在 [安装页面](index.md#downloading-handlebars) 上下载运行时。
35 |
36 | ## 优化
37 |
38 | 因为你在预编译模板,所以你还可以对编译器进行多种优化。首先你可以指定一个已知 helper 的列表:
39 |
40 | ```bash
41 | handlebars -f