mirror of
https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
synced 2025-08-30 01:15:57 +02:00
Revert "permet l'ajout des frameworks et des routes"
This reverts commit 361112699c
This commit is contained in:
4
app/node_modules/express-handlebars/.eslintignore
generated
vendored
4
app/node_modules/express-handlebars/.eslintignore
generated
vendored
@@ -1,4 +0,0 @@
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
coverage/
|
||||
dist/
|
42
app/node_modules/express-handlebars/.eslintrc.js
generated
vendored
42
app/node_modules/express-handlebars/.eslintrc.js
generated
vendored
@@ -1,42 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
extends: [
|
||||
"standard",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
],
|
||||
plugins: [
|
||||
"@typescript-eslint",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
},
|
||||
rules: {
|
||||
quotes: ["error", "double"],
|
||||
semi: ["error", "always"],
|
||||
"no-warning-comments": "warn",
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
indent: ["error", "tab", { SwitchCase: 1 }],
|
||||
"no-tabs": "off",
|
||||
"no-var": "error",
|
||||
"prefer-const": "error",
|
||||
"object-shorthand": "error",
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{
|
||||
name: "fit",
|
||||
message: "Do not commit focused tests.",
|
||||
},
|
||||
{
|
||||
name: "fdescribe",
|
||||
message: "Do not commit focused tests.",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
"@typescript-eslint/no-var-requires": "warn",
|
||||
},
|
||||
};
|
71
app/node_modules/express-handlebars/.github/workflows/codeql-analysis.yml
generated
vendored
71
app/node_modules/express-handlebars/.github/workflows/codeql-analysis.yml
generated
vendored
@@ -1,71 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [master]
|
||||
schedule:
|
||||
- cron: '0 15 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Override automatic language detection by changing the below list
|
||||
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
||||
language: ['javascript']
|
||||
# Learn more...
|
||||
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
115
app/node_modules/express-handlebars/.github/workflows/main.yml
generated
vendored
115
app/node_modules/express-handlebars/.github/workflows/main.yml
generated
vendored
@@ -1,115 +0,0 @@
|
||||
name: "Tests"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
CI: true
|
||||
|
||||
jobs:
|
||||
TestOS:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest]
|
||||
node_version: ['lts/*']
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
check-latest: true
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run tests 👩🏾💻
|
||||
run: npm run test
|
||||
TestNode:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node_version: ['lts/*', '*']
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
check-latest: true
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run tests 👩🏾💻
|
||||
run: npm run test
|
||||
Coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
check-latest: true
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run tests 👩🏾💻
|
||||
run: npm run test:cover
|
||||
Lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
check-latest: true
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
- name: Lint ✨
|
||||
run: npm run lint
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
check-latest: true
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
- name: Build 🧱
|
||||
run: npm run build
|
||||
|
||||
Release:
|
||||
needs: [TestOS, TestNode, Coverage, Lint, Build]
|
||||
if: |
|
||||
github.ref == 'refs/heads/master' &&
|
||||
github.event.repository.fork == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
check-latest: true
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
- name: NPM build
|
||||
run: npm run build
|
||||
- name: Release 🎉
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npx semantic-release
|
259
app/node_modules/express-handlebars/CHANGELOG.md
generated
vendored
259
app/node_modules/express-handlebars/CHANGELOG.md
generated
vendored
@@ -1,259 +0,0 @@
|
||||
## [7.1.2](https://github.com/express-handlebars/express-handlebars/compare/v7.1.1...v7.1.2) (2023-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* use types from handlebars for helpers ([#617](https://github.com/express-handlebars/express-handlebars/issues/617)) ([bc38da4](https://github.com/express-handlebars/express-handlebars/commit/bc38da4199cdc450dd84537c0515da475ef0d6ad))
|
||||
|
||||
## [7.1.1](https://github.com/express-handlebars/express-handlebars/compare/v7.1.0...v7.1.1) (2023-08-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency handlebars to ^4.7.8 ([#616](https://github.com/express-handlebars/express-handlebars/issues/616)) ([54ef900](https://github.com/express-handlebars/express-handlebars/commit/54ef9006ad1dd425a166bd4f1fdd08aa0911dc19))
|
||||
|
||||
# [7.1.0](https://github.com/express-handlebars/express-handlebars/compare/v7.0.7...v7.1.0) (2023-07-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add resetCache ([#554](https://github.com/express-handlebars/express-handlebars/issues/554)) ([868e9b4](https://github.com/express-handlebars/express-handlebars/commit/868e9b4ac9690de5000385c1fecdef858cf8d504))
|
||||
|
||||
## [7.0.7](https://github.com/express-handlebars/express-handlebars/compare/v7.0.6...v7.0.7) (2023-04-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^10.1.0 ([#555](https://github.com/express-handlebars/express-handlebars/issues/555)) ([196c925](https://github.com/express-handlebars/express-handlebars/commit/196c9255716856ae741a9c6672821ff8e2aeb2a9))
|
||||
|
||||
## [7.0.6](https://github.com/express-handlebars/express-handlebars/compare/v7.0.5...v7.0.6) (2023-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* replace backslash in partials with forward slash ([#553](https://github.com/express-handlebars/express-handlebars/issues/553)) ([2ecd784](https://github.com/express-handlebars/express-handlebars/commit/2ecd7840cb16d0e5013469b84183211e02212053))
|
||||
|
||||
## [7.0.5](https://github.com/express-handlebars/express-handlebars/compare/v7.0.4...v7.0.5) (2023-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to v10 ([#551](https://github.com/express-handlebars/express-handlebars/issues/551)) ([7817150](https://github.com/express-handlebars/express-handlebars/commit/7817150a1c06b9cb50826574a2e2127d5730c268))
|
||||
|
||||
## [7.0.4](https://github.com/express-handlebars/express-handlebars/compare/v7.0.3...v7.0.4) (2023-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency graceful-fs to ^4.2.11 ([#531](https://github.com/express-handlebars/express-handlebars/issues/531)) ([570e73d](https://github.com/express-handlebars/express-handlebars/commit/570e73da862694ee3b760c3616eb23ace7b0d4af))
|
||||
|
||||
## [7.0.3](https://github.com/express-handlebars/express-handlebars/compare/v7.0.2...v7.0.3) (2023-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^9.3.2 ([#526](https://github.com/express-handlebars/express-handlebars/issues/526)) ([2aa9c4a](https://github.com/express-handlebars/express-handlebars/commit/2aa9c4aa58cf43d25ae7dd4b21110523451ebaac))
|
||||
|
||||
## [7.0.2](https://github.com/express-handlebars/express-handlebars/compare/v7.0.1...v7.0.2) (2023-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^9.2.1 ([#520](https://github.com/express-handlebars/express-handlebars/issues/520)) ([16a9bc3](https://github.com/express-handlebars/express-handlebars/commit/16a9bc356ba333586bb1626d2402d9aa7df948fd))
|
||||
|
||||
## [7.0.1](https://github.com/express-handlebars/express-handlebars/compare/v7.0.0...v7.0.1) (2023-03-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^9.1.0 ([#518](https://github.com/express-handlebars/express-handlebars/issues/518)) ([635922c](https://github.com/express-handlebars/express-handlebars/commit/635922c746c76b0f36fe7061fcecc7c9f64d3b1b))
|
||||
* fix cannot use import ([0f45477](https://github.com/express-handlebars/express-handlebars/commit/0f45477b822a9d7814e1d05c493e4b827279717c))
|
||||
|
||||
# [7.0.0](https://github.com/express-handlebars/express-handlebars/compare/v6.0.7...v7.0.0) (2023-03-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to v9 ([#514](https://github.com/express-handlebars/express-handlebars/issues/514)) ([3b08bbb](https://github.com/express-handlebars/express-handlebars/commit/3b08bbb05fe195a855a090fadc11fc183f5c2292))
|
||||
* minimum Node v16 ([#516](https://github.com/express-handlebars/express-handlebars/issues/516)) ([86da3b2](https://github.com/express-handlebars/express-handlebars/commit/86da3b229b9c3bdf1c0e5924a796199a861ec260))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* minimum node version is v16
|
||||
|
||||
## [6.0.7](https://github.com/express-handlebars/express-handlebars/compare/v6.0.6...v6.0.7) (2023-01-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^8.1.0 ([#489](https://github.com/express-handlebars/express-handlebars/issues/489)) ([1bb2a2f](https://github.com/express-handlebars/express-handlebars/commit/1bb2a2f3dae7148afc5468bc916f6abe08381937))
|
||||
|
||||
## [6.0.6](https://github.com/express-handlebars/express-handlebars/compare/v6.0.5...v6.0.6) (2022-05-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^8.0.2 ([8202ea1](https://github.com/express-handlebars/express-handlebars/commit/8202ea19fb6e4354edd05dc457d2f3a14a5c29d9))
|
||||
|
||||
## [6.0.5](https://github.com/express-handlebars/express-handlebars/compare/v6.0.4...v6.0.5) (2022-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to v8 ([4025b58](https://github.com/express-handlebars/express-handlebars/commit/4025b58534b794863b2f51dcdc779d347a46c4a6))
|
||||
|
||||
## [6.0.4](https://github.com/express-handlebars/express-handlebars/compare/v6.0.3...v6.0.4) (2022-04-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency graceful-fs to ^4.2.10 ([2d6e89c](https://github.com/express-handlebars/express-handlebars/commit/2d6e89c219b11000125f7bc2630f6ddaf241987d))
|
||||
|
||||
## [6.0.3](https://github.com/express-handlebars/express-handlebars/compare/v6.0.2...v6.0.3) (2022-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow false for defaultLayout ([#303](https://github.com/express-handlebars/express-handlebars/issues/303)) ([d6180fe](https://github.com/express-handlebars/express-handlebars/commit/d6180fe7ad8ab74e60f58b4ced1b6d6af2d68c42))
|
||||
* **deps:** update dependency graceful-fs to ^4.2.9 ([#271](https://github.com/express-handlebars/express-handlebars/issues/271)) ([ea0f1f5](https://github.com/express-handlebars/express-handlebars/commit/ea0f1f563488d67202d7d6067116a4fe67eddf18))
|
||||
|
||||
## [6.0.2](https://github.com/express-handlebars/express-handlebars/compare/v6.0.1...v6.0.2) (2021-11-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix typescript in strict mode ([6833d8d](https://github.com/express-handlebars/express-handlebars/commit/6833d8dd4532e45790e04940b646e33f5fd07429))
|
||||
|
||||
## [6.0.1](https://github.com/express-handlebars/express-handlebars/compare/v6.0.0...v6.0.1) (2021-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix types ([f4de857](https://github.com/express-handlebars/express-handlebars/commit/f4de8577d5ad4510f4c5286cdee300dd27c6abfc))
|
||||
* remove default export ([a7f38a1](https://github.com/express-handlebars/express-handlebars/commit/a7f38a1d3127d63450b10b3f3539e3ce8131b677))
|
||||
* update examples ([1b1f5f7](https://github.com/express-handlebars/express-handlebars/commit/1b1f5f7b818985d433f6dc0398f7866c62b6cdea))
|
||||
|
||||
# [6.0.0](https://github.com/express-handlebars/express-handlebars/compare/v5.3.5...v6.0.0) (2021-11-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* rewrite in typescript ([188d3c4](https://github.com/express-handlebars/express-handlebars/commit/188d3c48526499143b7e1787accd230150a200d3))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* Change minimum node version to 12
|
||||
|
||||
## [5.3.5](https://github.com/express-handlebars/express-handlebars/compare/v5.3.4...v5.3.5) (2021-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* update deps ([b516cff](https://github.com/express-handlebars/express-handlebars/commit/b516cff30ba3de90db02b3a3682c9ffbcfb10091))
|
||||
|
||||
## [5.3.4](https://github.com/express-handlebars/express-handlebars/compare/v5.3.3...v5.3.4) (2021-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^7.2.0 ([15c77f5](https://github.com/express-handlebars/express-handlebars/commit/15c77f5e7cf31168942adaee8d021870719d9cd8))
|
||||
|
||||
## [5.3.3](https://github.com/express-handlebars/express-handlebars/compare/v5.3.2...v5.3.3) (2021-08-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency graceful-fs to ^4.2.7 ([94a4073](https://github.com/express-handlebars/express-handlebars/commit/94a4073bbea4591b57ea5e3cdae03c8fd861d50e))
|
||||
|
||||
## [5.3.2](https://github.com/express-handlebars/express-handlebars/compare/v5.3.1...v5.3.2) (2021-05-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency glob to ^7.1.7 ([8222f00](https://github.com/express-handlebars/express-handlebars/commit/8222f0015805b1287f62a1c66747a7f831a976db))
|
||||
|
||||
## [5.3.1](https://github.com/express-handlebars/express-handlebars/compare/v5.3.0...v5.3.1) (2021-05-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add note about security ([78c47a2](https://github.com/express-handlebars/express-handlebars/commit/78c47a235c4ad7bc2674bddd8ec2721567ed8c72))
|
||||
|
||||
# [5.3.0](https://github.com/express-handlebars/express-handlebars/compare/v5.2.1...v5.3.0) (2021-03-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add partialsDir.rename option ([#151](https://github.com/express-handlebars/express-handlebars/issues/151)) ([1a6771b](https://github.com/express-handlebars/express-handlebars/commit/1a6771b0f9a3db1cbd516faf79cb5e20a779e456))
|
||||
|
||||
## [5.2.1](https://github.com/express-handlebars/express-handlebars/compare/v5.2.0...v5.2.1) (2021-02-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency handlebars to ^4.7.7 ([1930523](https://github.com/express-handlebars/express-handlebars/commit/1930523103e6c97a3f3e41d6e7b5d6dc329c66f9))
|
||||
|
||||
# [5.2.0](https://github.com/express-handlebars/express-handlebars/compare/v5.1.0...v5.2.0) (2020-10-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* allow views to be an array ([a9f4aaa](https://github.com/express-handlebars/express-handlebars/commit/a9f4aaabd657221236b7321a4f87df7c9eb9a1bd))
|
||||
|
||||
# [5.1.0](https://github.com/express-handlebars/express-handlebars/compare/v5.0.0...v5.1.0) (2020-07-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add encoding option ([9e516c3](https://github.com/express-handlebars/express-handlebars/commit/9e516c382269b3ab586a6ab0dbd586b3c23110c4))
|
||||
|
||||
# [5.0.0](https://github.com/express-handlebars/express-handlebars/compare/v4.0.6...v5.0.0) (2020-07-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* update code to es2015+ ([e5a08ee](https://github.com/express-handlebars/express-handlebars/commit/e5a08eed844f177b0f365f882a20c7b229715bdd))
|
||||
* update node support ([ea30d53](https://github.com/express-handlebars/express-handlebars/commit/ea30d531b2f458c37f65b50bddc504180e774f8f))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* Drop support for node versions below v10
|
||||
|
||||
## [4.0.6](https://github.com/express-handlebars/express-handlebars/compare/v4.0.5...v4.0.6) (2020-07-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add runtimeOptions ([b64284f](https://github.com/express-handlebars/express-handlebars/commit/b64284f6f6eab2d184671736c33fc45df5b26246))
|
||||
|
||||
## [4.0.5](https://github.com/express-handlebars/express-handlebars/compare/v4.0.4...v4.0.5) (2020-07-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* overwrite past settings.views ([c27f1b0](https://github.com/express-handlebars/express-handlebars/commit/c27f1b0e8dcf2be974584861433cfb01a10ce1f6))
|
||||
* renderView returns promise when no callback given ([c39ed87](https://github.com/express-handlebars/express-handlebars/commit/c39ed87f2478ed64211821a6ffe1dca7212fb21b))
|
||||
|
||||
## [4.0.4](https://github.com/express-handlebars/express-handlebars/compare/v4.0.3...v4.0.4) (2020-04-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency graceful-fs to ^4.2.4 ([c01661b](https://github.com/express-handlebars/express-handlebars/commit/c01661be5193ea77d9914b71aedcb71d6ad4ab92))
|
||||
|
||||
## [4.0.3](https://github.com/express-handlebars/express-handlebars/compare/v4.0.2...v4.0.3) (2020-04-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency handlebars to ^4.7.6 ([2aa29ab](https://github.com/express-handlebars/express-handlebars/commit/2aa29ab29d5db9becccb5690a6fdef4a46055906))
|
||||
|
||||
## [4.0.2](https://github.com/express-handlebars/express-handlebars/compare/v4.0.1...v4.0.2) (2020-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency handlebars to ^4.7.5 ([#6](https://github.com/express-handlebars/express-handlebars/issues/6)) ([e597254](https://github.com/express-handlebars/express-handlebars/commit/e59725426cd6c6ab261127fd96065f30009ea1e1))
|
402
app/node_modules/express-handlebars/HISTORY.md
generated
vendored
402
app/node_modules/express-handlebars/HISTORY.md
generated
vendored
@@ -1,402 +0,0 @@
|
||||
Express Handlebars Change History
|
||||
=================================
|
||||
|
||||
4.0.1 (2020-04-01)
|
||||
------------------
|
||||
|
||||
* Update handlebars to fix mimist vulnerability.
|
||||
|
||||
4.0.0 (2020-03-25)
|
||||
------------------
|
||||
|
||||
* Move to repo https://github.com/express-handlebars/express-handlebars/
|
||||
* Update all deps.
|
||||
|
||||
3.1.0 (2019-05-14)
|
||||
------------------
|
||||
|
||||
* `defaultLayout` defaults to main ([#249][])
|
||||
* Upgrade Handlebars to v4.1.2 ([#250][])
|
||||
|
||||
[#249]: https://github.com/ericf/express-handlebars/issues/249
|
||||
[#250]: https://github.com/ericf/express-handlebars/issues/250
|
||||
|
||||
3.0.2 (2019-02-24)
|
||||
------------------
|
||||
|
||||
* Fix configuration `layoutsDir` & `partialsDir`. ([#244][])
|
||||
|
||||
[#244]: https://github.com/ericf/express-handlebars/issues/244
|
||||
|
||||
3.0.1 (2019-02-20)
|
||||
------------------
|
||||
|
||||
* Updated dependencies that are long over due
|
||||
|
||||
3.0.0 (2016-01-26)
|
||||
------------------
|
||||
|
||||
* Upgraded to Handlebars 4.0. ([#142][])
|
||||
|
||||
[#142]: https://github.com/ericf/express-handlebars/issues/142
|
||||
|
||||
2.0.1 (2015-04-23)
|
||||
------------------
|
||||
|
||||
* Guarded against unexpected Handlebars API change that was released in a patch.
|
||||
([#125][])
|
||||
|
||||
|
||||
[#125]: https://github.com/ericf/express-handlebars/issues/125
|
||||
|
||||
|
||||
2.0.0 (2015-03-22)
|
||||
------------------
|
||||
|
||||
* __[!]__ Upgraded to Handlebars 3.0 by default, but still works with Handlebars
|
||||
2.x by using the `handlebars` config option. ([#105][])
|
||||
|
||||
* __[!]__ Removed using prototype properties for default config values. The
|
||||
default values are now embedded in the constructor. ([#105][])
|
||||
|
||||
* __[!]__ Removed `handlebarsVersion` instance property and
|
||||
`getHandlebarsSemver()` static function on the `ExpressHandlebars`
|
||||
constructor. ([#105][])
|
||||
|
||||
* __[!]__ Replaced undocumented `compileTemplate()` hook with the protected but
|
||||
supported `_compileTemplate()` and `_precompileTemplate()` hooks. ([#95][])
|
||||
|
||||
* Fixed layout path resolution on Windows. ([#113][] @Tineler)
|
||||
|
||||
* Added `compilerOptions` config property which is passed along to
|
||||
`Handlebars.compile()` and `Handlebars.precompile()`. ([#95][])
|
||||
|
||||
* Exposed Express Handlebars metadata to the data channel during render. This
|
||||
metadata is accessible via `{{@exphbs.*}}` ([#89][], [#101][])
|
||||
|
||||
* Added new "protected" hooks for AOP-ing template compilation and rendering,
|
||||
all of which can optionally return a Promise: ([#105][])
|
||||
|
||||
* `_compileTemplate()`
|
||||
* `_precompileTemplate()`
|
||||
* `_renderTemplate()`
|
||||
|
||||
|
||||
[#89]: https://github.com/ericf/express-handlebars/issues/89
|
||||
[#95]: https://github.com/ericf/express-handlebars/issues/95
|
||||
[#101]: https://github.com/ericf/express-handlebars/issues/101
|
||||
[#105]: https://github.com/ericf/express-handlebars/issues/105
|
||||
[#113]: https://github.com/ericf/express-handlebars/issues/113
|
||||
|
||||
|
||||
1.2.2 (2015-03-06)
|
||||
------------------
|
||||
|
||||
* Upgraded `glob` dependency to v5 which now officially supports symlinks via
|
||||
the new `follow` option. ([#98][])
|
||||
|
||||
|
||||
1.2.1 (2015-02-17)
|
||||
------------------
|
||||
|
||||
* Locked down `glob` dependency to a v4 version range that is known to work with
|
||||
this package _and_ support symlinks. The `glob` version can be updated when
|
||||
[isaacs/node-glob#139](https://github.com/isaacs/node-glob/issues/139) is
|
||||
resolved. ([#98][] @adgad)
|
||||
|
||||
|
||||
[#98]: https://github.com/ericf/express-handlebars/issues/98
|
||||
|
||||
|
||||
1.2.0 (2015-02-17)
|
||||
------------------
|
||||
|
||||
* Added support for render-level `partials` to be specified when calling
|
||||
`renderView()` (which is the method Express calls). The `options.partials`
|
||||
value matches what Handlebars accepts during template rendering: it should
|
||||
have the shape `{partialName: fn}` or be a Promise for such an object.
|
||||
([#82][])
|
||||
|
||||
|
||||
[#82]: https://github.com/ericf/express-handlebars/issues/82
|
||||
|
||||
|
||||
1.1.0 (2014-09-14)
|
||||
------------------
|
||||
|
||||
* __[!]__ Upgraded Handlebars to 2.0.0 final, it was beta before.
|
||||
|
||||
* Added support for `partialsDir` to be configured with a collection (or promise
|
||||
for a collection) of templates, via the new `templates` prop in `partialDir`
|
||||
config objects. This allows developers to hand Express Handlebars the compiled
|
||||
partials templates to use for a specific partials dir.
|
||||
([#81][] @joanniclaborde)
|
||||
|
||||
* Upgraded Promise dependency.
|
||||
|
||||
|
||||
[#81]: https://github.com/ericf/express-handlebars/issues/81
|
||||
|
||||
|
||||
1.0.3 (2014-09-05)
|
||||
------------------
|
||||
|
||||
* Fixed issue with namespaced partials dirs not actually being namespaces.
|
||||
([#76][] @inerte)
|
||||
|
||||
|
||||
[#76]: https://github.com/ericf/express-handlebars/issues/76
|
||||
|
||||
|
||||
1.0.2 (2014-09-05)
|
||||
------------------
|
||||
|
||||
* Fixed `engines` entry in `package.json` to Node `>=0.10` to reflect this
|
||||
package's requirements. ([#78][])
|
||||
|
||||
|
||||
[#78]: https://github.com/ericf/express-handlebars/issues/78
|
||||
|
||||
|
||||
1.0.1 (2014-08-08)
|
||||
------------------
|
||||
|
||||
* Fixed bug where rendered content was only be returned if a layout template was
|
||||
being used. Now a layout-less render will actually return content. ([#73][])
|
||||
|
||||
|
||||
[#73]: https://github.com/ericf/express-handlebars/issues/73
|
||||
|
||||
|
||||
1.0.0 (2014-08-07)
|
||||
------------------
|
||||
|
||||
* __[!]__ Renamed to: `express-handlebars`. ([#65][])
|
||||
|
||||
* __[!]__ Rewritten to use Promises instead of `async` for asynchronous code.
|
||||
([#68][]) This resulted in the following public API changes:
|
||||
|
||||
* `loadPartials()` --> `getPartials()`, returns a Promise.
|
||||
* `loadTemplate()` --> `getTemplate()`, returns a Promise.
|
||||
* `loadTemplates()` --> `getTemplates()`, returns a Promise.
|
||||
* `render(file, context, [options])`, returns a Promise.
|
||||
|
||||
|
||||
* `partialsDir` can now be set with an array of objects in the following form to
|
||||
support namespaced partials: ([#70][] @joanniclaborde)
|
||||
|
||||
{ dir: 'foo/bar/', namespace: 'bar' }
|
||||
|
||||
* Added support for Handlebars' `data` channel via `options.data`. ([#62][])
|
||||
|
||||
* Added `compileTemplate()` hook for the pre/post compile process, this also
|
||||
supports returning a Promise. ([#39][], [#41][])
|
||||
|
||||
* Added `_renderTemplate()` hook that supports returning a Promise.
|
||||
([#39][], [#41][])
|
||||
|
||||
* Upgraded all dependencies, including Handlebars to 2.x. ([#59][])
|
||||
|
||||
* Added `graceful-fs` dependency to support large numbers of files to avoid
|
||||
EMFILE errors.
|
||||
|
||||
* Reduced complexity of cache code.
|
||||
|
||||
* Updated examples to each be self-contained and have `package.json` files.
|
||||
|
||||
|
||||
[#39]: https://github.com/ericf/express-handlebars/issues/39
|
||||
[#41]: https://github.com/ericf/express-handlebars/issues/41
|
||||
[#59]: https://github.com/ericf/express-handlebars/issues/59
|
||||
[#62]: https://github.com/ericf/express-handlebars/issues/62
|
||||
[#65]: https://github.com/ericf/express-handlebars/issues/65
|
||||
[#68]: https://github.com/ericf/express-handlebars/issues/68
|
||||
[#70]: https://github.com/ericf/express-handlebars/issues/70
|
||||
|
||||
|
||||
0.5.1 (2014-08-05)
|
||||
------------------
|
||||
|
||||
* __[!]__ Last release before `v1.0` which will have breaking changes.
|
||||
|
||||
* Improved `extname` docs in README and added example. ([#30][] @Crashthatch)
|
||||
|
||||
* `extname` can now be specified _without_ the leading `"."`.
|
||||
([#51][] @calvinmetcalf)
|
||||
|
||||
|
||||
[#30]: https://github.com/ericf/express-handlebars/issues/30
|
||||
[#51]: https://github.com/ericf/express-handlebars/issues/51
|
||||
|
||||
|
||||
0.5.0 (2013-07-25)
|
||||
------------------
|
||||
|
||||
* Added `loadTemplates()` method which will load all the templates in a
|
||||
specified directory. ([#21][])
|
||||
|
||||
* Added support for multiple partials directories. This enables the
|
||||
`partialsDir` configuration property to be specified as an *array* of
|
||||
directories, and loads all of the templates in each one.
|
||||
|
||||
This feature allows an app's partials to be split up in multiple directories,
|
||||
which is common if an app has some shared partials which will also be exposed
|
||||
to the client, and some server-side-only partials. ([#20][])
|
||||
|
||||
* Added runnable code examples in this package's "examples/" directory.
|
||||
([#22][])
|
||||
|
||||
* Improved optional argument handling in public methods to treat Express
|
||||
`locals` function objects as `options` and not `callback` params to the method
|
||||
being invoked. ([#27][])
|
||||
|
||||
|
||||
[#20]: https://github.com/ericf/express-handlebars/issues/20
|
||||
[#21]: https://github.com/ericf/express-handlebars/issues/21
|
||||
[#22]: https://github.com/ericf/express-handlebars/issues/22
|
||||
[#27]: https://github.com/ericf/express-handlebars/issues/27
|
||||
|
||||
|
||||
0.4.1 (2013-04-06)
|
||||
------------------
|
||||
|
||||
* Updated `async` dependency to the latest stable minor version: "~0.2".
|
||||
|
||||
|
||||
0.4.0 (2013-03-24)
|
||||
------------------
|
||||
|
||||
* __[!]__ Removed the following "get" -> "load" aliases which kept in v0.2.0 for
|
||||
back-compat:
|
||||
|
||||
* `getPartials()` -> `loadPartials()`
|
||||
* `getTemplate()` -> `loadTemplate()`
|
||||
|
||||
This is the future version where these aliases have been removed.
|
||||
|
||||
* __[!]__ Renamed `lib/express3-handlebars.js` -> `lib/express-handlebars.js`.
|
||||
|
||||
* Exposed `getHandlebarsSemver()` function as a static property on the
|
||||
`ExpressHandlebars` constructor.
|
||||
|
||||
* Rearranged module exports by moving the engine factory function to `index.js`,
|
||||
making the `lib/express3-handlebars.js` module only responsible for exporting
|
||||
the `ExpressHandlebars` constructor.
|
||||
|
||||
|
||||
0.3.3 (2013-03-22)
|
||||
------------------
|
||||
|
||||
* Updated internal `_resolveLayoutPath()` method to take the full
|
||||
`options`/locals objects which the view is rendered with. This makes it easier
|
||||
to override. ([#14][])
|
||||
|
||||
|
||||
[#14]: https://github.com/ericf/express-handlebars/issues/14
|
||||
|
||||
|
||||
0.3.2 (2013-02-20)
|
||||
------------------
|
||||
|
||||
* Transfered ownership and copyright to Yahoo! Inc. This software is still free
|
||||
to use, and is now licensed under the Yahoo! Inc. BSD license.
|
||||
|
||||
|
||||
0.3.1 (2013-02-18)
|
||||
------------------
|
||||
|
||||
* Updated README with info about `options.helpers` for `render()` and
|
||||
`renderView()` docs. ([#7][])
|
||||
|
||||
|
||||
[#7]: https://github.com/ericf/express-handlebars/issues/7
|
||||
|
||||
|
||||
0.3.0 (2013-02-18)
|
||||
------------------
|
||||
|
||||
* Added support for render-level helpers, via `options.helpers`, to the
|
||||
`render()` and `renderView()` methods. Handlebars' `registerHelper()` function
|
||||
now works as expected and does not have to be called before the
|
||||
`ExpressHandlebars` instance is created. Helpers are now merged from:
|
||||
`handlebars.helpers` (global), `helpers` (instance), and `options.helpers`
|
||||
(render-level) before a template is rendered; this provides flexibility at
|
||||
all levels. ([#3][], [#11][])
|
||||
|
||||
* Added `handlebarsVersion` property which is the version number of `handlebars`
|
||||
as a semver. This is used internally to branch on certain operations which
|
||||
differ between Handlebars releases.
|
||||
|
||||
|
||||
[#3]: https://github.com/ericf/express-handlebars/issues/3
|
||||
[#11]: https://github.com/ericf/express-handlebars/issues/11
|
||||
|
||||
|
||||
0.2.3 (2013-02-13)
|
||||
------------------
|
||||
|
||||
* Fixed issue with naming nested partials when using the latest version of
|
||||
Handlebars (1.0.rc.2). Previous versions require a hack to replace "/"s with
|
||||
"."s in partial names, and the latest version of Handlebars fixes that bug.
|
||||
This hack will only be applied to old versions of Handlebars. ([#9][])
|
||||
|
||||
|
||||
[#9]: https://github.com/ericf/express-handlebars/issues/9
|
||||
|
||||
|
||||
0.2.2 (2013-02-04)
|
||||
------------------
|
||||
|
||||
* Updated README with the public method renames which happened v0.2.0.
|
||||
|
||||
|
||||
0.2.1 (2013-02-04)
|
||||
------------------
|
||||
|
||||
* `extname`, `layoutsDir`, and `partialsDir` property values will now reference
|
||||
the values on the prototype unless an `ExpressHandlebars` instance is
|
||||
constructed with config values for these properties.
|
||||
|
||||
* Improved clarity of method implementations, and exposed more override "hooks"
|
||||
via new private methods: `_getPartialName()`, `_renderTemplate()`, and
|
||||
`_resolveLayoutPath()`.
|
||||
|
||||
|
||||
0.2.0 (2013-02-01)
|
||||
------------------
|
||||
|
||||
* __[!]__ Renamed methods prefixed with "get" to "load" for clarity:
|
||||
|
||||
* `getPartials()` -> `loadPartials()`
|
||||
* `getTemplate()` -> `loadTemplate()`
|
||||
|
||||
Aliases for these methods have been created to maintain back-compat, but the
|
||||
old method names are now deprecated will be removed in the future. ([#5][])
|
||||
|
||||
* All paths are resolved before checking in or adding to caches. ([#1][])
|
||||
|
||||
* Force `{precompiled: false}` option within `render()` and `renderView()`
|
||||
methods to prevent trying to render with precompiled templates. ([#2][])
|
||||
|
||||
|
||||
[#1]: https://github.com/ericf/express-handlebars/issues/1
|
||||
[#2]: https://github.com/ericf/express-handlebars/issues/2
|
||||
[#5]: https://github.com/ericf/express-handlebars/issues/5
|
||||
|
||||
|
||||
0.1.2 (2013-01-10)
|
||||
------------------
|
||||
|
||||
* Tweaked formatting of README documentation.
|
||||
|
||||
|
||||
0.1.1 (2013-01-10)
|
||||
------------------
|
||||
|
||||
* Added README documentation.
|
||||
|
||||
|
||||
0.1.0 (2013-01-07)
|
||||
------------------
|
||||
|
||||
* Initial release.
|
31
app/node_modules/express-handlebars/LICENSE
generated
vendored
31
app/node_modules/express-handlebars/LICENSE
generated
vendored
@@ -1,31 +0,0 @@
|
||||
Copyright (c) 2014, Yahoo Inc. All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of Yahoo Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of Yahoo Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
611
app/node_modules/express-handlebars/README.md
generated
vendored
611
app/node_modules/express-handlebars/README.md
generated
vendored
@@ -1,611 +0,0 @@
|
||||
Express Handlebars
|
||||
==================
|
||||
|
||||
A [Handlebars][] view engine for [Express][] which doesn't suck.
|
||||
|
||||
[![npm version][npm-badge]][npm]
|
||||
|
||||
**This package used to be named `express3-handlebars`. The previous `express-handlebars` package by @jneen can be found [here][jneen-exphbs].**
|
||||
|
||||
|
||||
[Express]: https://github.com/expressjs/express
|
||||
[Handlebars]: https://github.com/handlebars-lang/handlebars.js
|
||||
[npm]: https://www.npmjs.org/package/express-handlebars
|
||||
[npm-badge]: https://img.shields.io/npm/v/express-handlebars.svg?style=flat-square
|
||||
[jneen-exphbs]: https://github.com/jneen/express-handlebars
|
||||
|
||||
|
||||
## Goals & Design
|
||||
|
||||
I created this project out of frustration with the existing Handlebars view engines for Express. As of version 3.x, Express got out of the business of being a generic view engine — this was a great decision — leaving developers to implement the concepts of layouts, partials, and doing file I/O for their template engines of choice.
|
||||
|
||||
### Goals and Features
|
||||
|
||||
After building a half-dozen Express apps, I developed requirements and opinions about what a Handlebars view engine should provide and how it should be implemented. The following is that list:
|
||||
|
||||
* Add back the concept of "layout", which was removed in Express 3.x.
|
||||
|
||||
* Add back the concept of "partials" via Handlebars' partials mechanism.
|
||||
|
||||
* Support a directory of partials; e.g., `{{> foo/bar}}` which exists on the file system at `views/partials/foo/bar.handlebars`, by default.
|
||||
|
||||
* Smart file system I/O and template caching. When in development, templates are always loaded from disk. In production, raw files and compiled templates are cached, including partials.
|
||||
|
||||
* All async and non-blocking. File system I/O is slow and servers should not be blocked from handling requests while reading from disk. I/O queuing is used to avoid doing unnecessary work.
|
||||
|
||||
* Ability to easily precompile templates and partials for use on the client, enabling template sharing and reuse.
|
||||
|
||||
* Ability to use a different Handlebars module/implementation other than the Handlebars npm package.
|
||||
|
||||
### Package Design
|
||||
|
||||
This package was designed to work great for both the simple and complex use cases. I _intentionally_ made sure the full implementation is exposed and is easily overridable.
|
||||
|
||||
The package exports a function which can be invoked with no arguments or with a `config` object and it will return a function (closed over sensible defaults) which can be registered with an Express app. It's an engine factory function.
|
||||
|
||||
This exported engine factory has two properties which expose the underlying implementation:
|
||||
|
||||
* `ExpressHandlebars()`: The constructor function which holds the internal implementation on its `prototype`. This produces instance objects which store their configuration, `compiled` and `precompiled` templates, and expose an `engine()` function which can be registered with an Express app.
|
||||
|
||||
* `create()`: A convenience factory function for creating `ExpressHandlebars` instances.
|
||||
|
||||
An instance-based approach is used so that multiple `ExpressHandlebars` instances can be created with their own configuration, templates, partials, and helpers.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Install using npm:
|
||||
|
||||
```shell
|
||||
$ npm install express-handlebars
|
||||
```
|
||||
|
||||
## Danger 🔥
|
||||
|
||||
Never put objects on the `req` object straight in as the data, this can allow hackers to run XSS attacks. Always make sure you are destructuring the values on objects like `req.query` and `req.params`. See https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/ for more details.
|
||||
|
||||
## Usage
|
||||
|
||||
This view engine uses sensible defaults that leverage the "Express-way" of structuring an app's views. This makes it trivial to use in basic apps:
|
||||
|
||||
### Basic Usage
|
||||
|
||||
**Directory Structure:**
|
||||
|
||||
```
|
||||
.
|
||||
├── app.js
|
||||
└── views
|
||||
├── home.handlebars
|
||||
└── layouts
|
||||
└── main.handlebars
|
||||
|
||||
2 directories, 3 files
|
||||
```
|
||||
|
||||
**app.js:**
|
||||
|
||||
Creates a super simple Express app which shows the basic way to register a Handlebars view engine using this package.
|
||||
|
||||
```javascript
|
||||
import express from 'express';
|
||||
import { engine } from 'express-handlebars';
|
||||
|
||||
const app = express();
|
||||
|
||||
app.engine('handlebars', engine());
|
||||
app.set('view engine', 'handlebars');
|
||||
app.set('views', './views');
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.render('home');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
```
|
||||
|
||||
**views/layouts/main.handlebars:**
|
||||
|
||||
The main layout is the HTML page wrapper which can be reused for the different views of the app. `{{{body}}}` is used as a placeholder for where the main content should be rendered.
|
||||
|
||||
```handlebars
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example App</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{{body}}}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**views/home.handlebars:**
|
||||
|
||||
The content for the app's home view which will be rendered into the layout's `{{{body}}}`.
|
||||
|
||||
```handlebars
|
||||
<h1>Example App: Home</h1>
|
||||
```
|
||||
|
||||
#### Running the Example
|
||||
|
||||
The above example is bundled in this package's [examples directory][], where it can be run by:
|
||||
|
||||
```shell
|
||||
$ cd examples/basic/
|
||||
$ npm install
|
||||
$ npm start
|
||||
```
|
||||
|
||||
### Using Instances
|
||||
|
||||
Another way to use this view engine is to create an instance(s) of `ExpressHandlebars`, allowing access to the full API:
|
||||
|
||||
```javascript
|
||||
import express from 'express';
|
||||
import { create } from 'express-handlebars';
|
||||
|
||||
const app = express();
|
||||
const hbs = create({ /* config */ });
|
||||
|
||||
// Register `hbs.engine` with the Express app.
|
||||
app.engine('handlebars', hbs.engine);
|
||||
app.set('view engine', 'handlebars');
|
||||
app.set('views', './views');
|
||||
|
||||
// ...still have a reference to `hbs`, on which methods like `getPartials()`
|
||||
// can be called.
|
||||
```
|
||||
|
||||
**Note:** The [Advanced Usage][] example demonstrates how `ExpressHandlebars` instances can be leveraged.
|
||||
|
||||
### Template Caching
|
||||
|
||||
This view engine uses a smart template caching strategy. In development, templates will always be loaded from disk, i.e., no caching. In production, raw files and compiled Handlebars templates are aggressively cached.
|
||||
|
||||
The easiest way to control template/view caching is through Express' [view cache setting][]:
|
||||
|
||||
```javascript
|
||||
app.enable('view cache');
|
||||
```
|
||||
|
||||
Express enables this setting by default when in production mode, i.e.:
|
||||
|
||||
```
|
||||
process.env.NODE_ENV === "production"
|
||||
```
|
||||
|
||||
**Note:** All of the public API methods accept `options.cache`, which gives control over caching when calling these methods directly.
|
||||
|
||||
### Layouts
|
||||
|
||||
A layout is simply a Handlebars template with a `{{{body}}}` placeholder. Usually it will be an HTML page wrapper into which views will be rendered.
|
||||
|
||||
This view engine adds back the concept of "layout", which was removed in Express 3.x. It can be configured with a path to the layouts directory, by default it's set to relative to `express settings.view` + `layouts/`
|
||||
|
||||
There are two ways to set a default layout: configuring the view engine's `defaultLayout` property, or setting [Express locals][] `app.locals.layout`.
|
||||
|
||||
The layout into which a view should be rendered can be overridden per-request by assigning a different value to the `layout` request local. The following will render the "home" view with no layout:
|
||||
|
||||
```javascript
|
||||
app.get('/', (req, res, next) => {
|
||||
res.render('home', {layout: false});
|
||||
});
|
||||
```
|
||||
|
||||
### Helpers
|
||||
|
||||
Helper functions, or "helpers" are functions that can be [registered with Handlebars][] and can be called within a template. Helpers can be used for transforming output, iterating over data, etc. To keep with the spirit of *logic-less* templates, helpers are the place where logic should be defined.
|
||||
|
||||
Handlebars ships with some [built-in helpers][], such as: `with`, `if`, `each`, etc. Most applications will need to extend this set of helpers to include app-specific logic and transformations. Beyond defining global helpers on `Handlebars`, this view engine supports `ExpressHandlebars` instance-level helpers via the `helpers` configuration property, and render-level helpers via `options.helpers` when calling the `render()` and `renderView()` methods.
|
||||
|
||||
The following example shows helpers being specified at each level:
|
||||
|
||||
**app.js:**
|
||||
|
||||
Creates a super simple Express app which shows the basic way to register `ExpressHandlebars` instance-level helpers, and override one at the render-level.
|
||||
|
||||
```javascript
|
||||
import express from 'express';
|
||||
import { create } from 'express-handlebars';
|
||||
|
||||
const app = express();
|
||||
|
||||
const hbs = create({
|
||||
// Specify helpers which are only registered on this instance.
|
||||
helpers: {
|
||||
foo() { return 'FOO!'; },
|
||||
bar() { return 'BAR!'; }
|
||||
}
|
||||
});
|
||||
|
||||
app.engine('handlebars', hbs.engine);
|
||||
app.set('view engine', 'handlebars');
|
||||
app.set('views', './views');
|
||||
|
||||
app.get('/', (req, res, next) => {
|
||||
res.render('home', {
|
||||
showTitle: true,
|
||||
|
||||
// Override `foo` helper only for this rendering.
|
||||
helpers: {
|
||||
foo() { return 'foo.'; }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
```
|
||||
|
||||
**views/home.handlebars:**
|
||||
|
||||
The app's home view which uses helper functions to help render the contents.
|
||||
|
||||
```handlebars
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example App - Home</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Uses built-in `if` helper. -->
|
||||
{{#if showTitle}}
|
||||
<h1>Home</h1>
|
||||
{{/if}}
|
||||
|
||||
<!-- Calls `foo` helper, overridden at render-level. -->
|
||||
<p>{{foo}}</p>
|
||||
|
||||
<!-- Calls `bar` helper, defined at instance-level. -->
|
||||
<p>{{bar}}</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### More on Helpers
|
||||
|
||||
Refer to the [Handlebars website][] for more information on defining helpers:
|
||||
|
||||
* [Expression Helpers][]
|
||||
* [Block Helpers][]
|
||||
|
||||
### Metadata
|
||||
|
||||
Handlebars has a data channel feature that propagates data through all scopes, including helpers and partials. Values in the data channel can be accessed via the `{{@variable}}` syntax. Express Handlebars provides metadata about a template it renders on a `{{@exphbs}}` object allowing access to things like the view name passed to `res.render()` via `{{@exphbs.view}}`.
|
||||
|
||||
The following is the list of metadata that's accessible on the `{{@exphbs}}` data object:
|
||||
|
||||
* `cache`: Boolean whether or not the template is cached.
|
||||
* `encoding`: String name of encoding for files.
|
||||
* `view`: String name of the view passed to `res.render()`.
|
||||
* `layout`: String name of the layout view.
|
||||
* `data`: Original data object passed when rendering the template.
|
||||
* `helpers`: Collection of helpers used when rendering the template.
|
||||
* `partials`: Collection of partials used when rendering the template.
|
||||
* `runtimeOptions`: Runtime Options used to render the template.
|
||||
|
||||
|
||||
[examples directory]: https://github.com/express-handlebars/express-handlebars/tree/master/examples
|
||||
[view cache setting]: https://expressjs.com/en/api.html#app.settings.table
|
||||
[Express locals]: https://expressjs.com/en/api.html#app.locals
|
||||
[registered with Handlebars]: https://github.com/wycats/handlebars.js/#registering-helpers
|
||||
[built-in helpers]: https://handlebarsjs.com/guide/builtin-helpers.html
|
||||
[Handlebars website]: https://handlebarsjs.com/
|
||||
[Expression Helpers]: https://handlebarsjs.com/guide/#custom-helpers
|
||||
[Block Helpers]: https://handlebarsjs.com/guide/#block-helpers
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Configuration and Defaults
|
||||
|
||||
There are two main ways to use this package: via its engine factory function, or creating `ExpressHandlebars` instances; both use the same configuration properties and defaults.
|
||||
|
||||
```javascript
|
||||
import { engine, create, ExpressHandlebars } from 'express-handlebars';
|
||||
|
||||
// Using the engine factory:
|
||||
engine({ /* config */ });
|
||||
|
||||
// Create an instance:
|
||||
create({ /* config */ });
|
||||
|
||||
// Using the class:
|
||||
new ExpressHandlebars({ /* config */})
|
||||
```
|
||||
|
||||
The following is the list of configuration properties and their default values (if any):
|
||||
|
||||
#### `handlebars=require('handlebars')`
|
||||
The Handlebars module/implementation. This allows for the `ExpressHandlebars` instance to use a different Handlebars module/implementation than that provided by the Handlebars npm package.
|
||||
|
||||
#### `extname=".handlebars"`
|
||||
The string name of the file extension used by the templates. This value should correspond with the `extname` under which this view engine is registered with Express when calling `app.engine()`.
|
||||
|
||||
The following example sets up an Express app to use `.hbs` as the file extension for views:
|
||||
|
||||
```javascript
|
||||
import express from 'express';
|
||||
import { engine } from 'express-handlebars';
|
||||
|
||||
const app = express();
|
||||
|
||||
app.engine('.hbs', engine({extname: '.hbs'}));
|
||||
app.set('view engine', '.hbs');
|
||||
app.set('views', './views');
|
||||
```
|
||||
|
||||
**Note:** Setting the app's `"view engine"` setting will make that value the default file extension used for looking up views.
|
||||
|
||||
#### `encoding="utf8"`
|
||||
Default encoding when reading files.
|
||||
|
||||
#### `layoutsDir`
|
||||
Default layouts directory is relative to `express settings.view` + `layouts/`
|
||||
The string path to the directory where the layout templates reside.
|
||||
|
||||
**Note:** If you configure Express to look for views in a custom location (e.g., `app.set('views', 'some/path/')`), and if your `layoutsDir` is not relative to `express settings.view` + `layouts/`, you will need to reflect that by passing an updated path as the `layoutsDir` property in your configuration.
|
||||
|
||||
#### `partialsDir`
|
||||
Default partials directory is relative to `express settings.view` + `partials/`
|
||||
The string path to the directory where the partials templates reside or object with the following properties:
|
||||
|
||||
* `dir`: The string path to the directory where the partials templates reside.
|
||||
* `namespace`: Optional string namespace to prefix the partial names.
|
||||
* `templates`: Optional collection (or promise of a collection) of templates in the form: `{filename: template}`.
|
||||
* `rename(filePath, namespace)`: Optional function to rename the partials. Takes two arguments: `filePath`, e.g., `partials/some/path/template.handlebars` and `namespace`.
|
||||
|
||||
**Note:** If you configure Express to look for views in a custom location (e.g., `app.set('views', 'some/path/')`), and if your `partialsDir` is not relative to `express settings.view` + `partials/`, you will need to reflect that by passing an updated path as the `partialsDir` property in your configuration.
|
||||
|
||||
**Note:** Multiple partials dirs can be used by making `partialsDir` an array of strings, and/or config objects as described above. The namespacing feature is useful if multiple partials dirs are used and their file paths might clash.
|
||||
|
||||
#### `defaultLayout`
|
||||
The string name or path of a template in the `layoutsDir` to use as the default layout. `main` is used as the default. This is overridden by a `layout` specified in the app or response `locals`. **Note:** A falsy value will render without a layout; e.g., `res.render('home', {layout: false});`. You can also use a falsy value when creating the engine to make using no layout a default e.g. `app.engine('.hbs', exphbs({defaultLayout: false}));`.
|
||||
|
||||
#### `helpers`
|
||||
An object which holds the helper functions used when rendering templates with this `ExpressHandlebars` instance. When rendering a template, a collection of helpers will be generated by merging: `handlebars.helpers` (global), `helpers` (instance), and `options.helpers` (render-level). This allows Handlebars' `registerHelper()` function to operate as expected, will providing two extra levels over helper overrides.
|
||||
|
||||
#### `compilerOptions`
|
||||
An object which holds options that will be passed along to the Handlebars compiler functions: `Handlebars.compile()` and `Handlebars.precompile()`.
|
||||
|
||||
#### `runtimeOptions`
|
||||
An object which holds options that will be passed along to the template function in addition to the `data`, `helpers`, and `partials` options. See [Runtime Options][] for a list of available options.
|
||||
|
||||
### Properties
|
||||
|
||||
The public API properties are provided via `ExpressHandlebars` instances. In additional to the properties listed in the **Configuration and Defaults** section, the following are additional public properties:
|
||||
|
||||
#### `engine`
|
||||
A function reference to the `renderView()` method which is bound to `this` `ExpressHandlebars` instance. This bound function should be used when registering this view engine with an Express app.
|
||||
|
||||
#### `extname`
|
||||
The normalized `extname` which will _always_ start with `.` and defaults to `.handlebars`.
|
||||
|
||||
#### `compiled`
|
||||
An object cache which holds compiled Handlebars template functions in the format: `{"path/to/template": [Function]}`.
|
||||
|
||||
#### `precompiled`
|
||||
An object cache which holds precompiled Handlebars template strings in the format: `{"path/to/template": [String]}`.
|
||||
|
||||
### Methods
|
||||
|
||||
The following is the list of public API methods provided via `ExpressHandlebars` instances:
|
||||
|
||||
**Note:** All of the public methods return a [`Promise`][promise] (with the exception of `renderView()` which is the interface with Express.)
|
||||
|
||||
#### `getPartials([options])`
|
||||
Retrieves the partials in the `partialsDir` and returns a Promise for an object mapping the partials in the form `{name: partial}`.
|
||||
|
||||
By default each partial will be a compiled Handlebars template function. Use `options.precompiled` to receive the partials as precompiled templates — this is useful for sharing templates with client code.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `[options]`: Optional object containing any of the following properties:
|
||||
|
||||
* `[cache]`: Whether cached templates can be used if they have already been requested. This is recommended for production to avoid unnecessary file I/O.
|
||||
|
||||
* `[encoding]`: File encoding.
|
||||
|
||||
* `[precompiled=false]`: Whether precompiled templates should be provided, instead of compiled Handlebars template functions.
|
||||
|
||||
The name of each partial corresponds to its location in `partialsDir`. For example, consider the following directory structure:
|
||||
|
||||
```
|
||||
views
|
||||
└── partials
|
||||
├── foo
|
||||
│ └── bar.handlebars
|
||||
└── title.handlebars
|
||||
|
||||
2 directories, 2 files
|
||||
```
|
||||
|
||||
`getPartials()` would produce the following result:
|
||||
|
||||
```javascript
|
||||
import { create } from 'express-handlebars';
|
||||
|
||||
const hbs = create();
|
||||
hbs.getPartials().then(function (partials) {
|
||||
console.log(partials);
|
||||
// => { 'foo/bar': [Function],
|
||||
// => title: [Function] }
|
||||
});
|
||||
```
|
||||
|
||||
#### `getTemplate(filePath, [options])`
|
||||
Retrieves the template at the specified `filePath` and returns a Promise for the compiled Handlebars template function.
|
||||
|
||||
Use `options.precompiled` to receive a precompiled Handlebars template.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `filePath`: String path to the Handlebars template file.
|
||||
|
||||
* `[options]`: Optional object containing any of the following properties:
|
||||
|
||||
* `[cache]`: Whether a cached template can be used if it have already been requested. This is recommended for production to avoid necessary file I/O.
|
||||
|
||||
* `[encoding]`: File encoding.
|
||||
|
||||
* `[precompiled=false]`: Whether a precompiled template should be provided, instead of a compiled Handlebars template function.
|
||||
|
||||
#### `getTemplates(dirPath, [options])`
|
||||
Retrieves all the templates in the specified `dirPath` and returns a Promise for an object mapping the compiled templates in the form `{filename: template}`.
|
||||
|
||||
Use `options.precompiled` to receive precompiled Handlebars templates — this is useful for sharing templates with client code.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `dirPath`: String path to the directory containing Handlebars template files.
|
||||
|
||||
* `[options]`: Optional object containing any of the following properties:
|
||||
|
||||
* `[cache]`: Whether cached templates can be used if it have already been requested. This is recommended for production to avoid necessary file I/O.
|
||||
|
||||
* `[encoding]`: File encoding.
|
||||
|
||||
* `[precompiled=false]`: Whether precompiled templates should be provided, instead of a compiled Handlebars template function.
|
||||
|
||||
#### `resetCache([filePathsOrFilter])`
|
||||
Reset template cache. The cache can be partially reset by providing a filter argument. If no argument is given the whole cache will be reset.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `[filePathsOrFilter]`: Optional filter to reset part of the cache. This can be a file path, an array of file paths, or a filter function based on file path.
|
||||
|
||||
#### `render(filePath, context, [options])`
|
||||
Renders the template at the specified `filePath` with the `context`, using this instance's `helpers` and partials by default, and returns a Promise for the resulting string.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `filePath`: String path to the Handlebars template file.
|
||||
|
||||
* `context`: Object in which the template will be executed. This contains all of the values to fill into the template.
|
||||
|
||||
* `[options]`: Optional object which can contain any of the following properties which affect this view engine's behavior:
|
||||
|
||||
* `[cache]`: Whether a cached template can be used if it have already been requested. This is recommended for production to avoid unnecessary file I/O.
|
||||
|
||||
* `[encoding]`: File encoding.
|
||||
|
||||
* `[data]`: Optional object which can contain any data that Handlebars will pipe through the template, all helpers, and all partials. This is a side data channel.
|
||||
|
||||
* `[helpers]`: Render-level helpers that will be used instead of any instance-level helpers; these will be merged with (and will override) any global Handlebars helper functions.
|
||||
|
||||
* `[partials]`: Render-level partials that will be used instead of any instance-level partials. This is used internally as an optimization to avoid re-loading all the partials.
|
||||
|
||||
* `[runtimeOptions]`: Optional object which can contain options passed to the template function.
|
||||
|
||||
#### `renderView(viewPath, options|callback, [callback])`
|
||||
Renders the template at the specified `viewPath` as the `{{{body}}}` within the layout specified by the `defaultLayout` or `options.layout`. Rendering will use this instance's `helpers` and partials, and passes the resulting string to the `callback`.
|
||||
|
||||
This method is called by Express and is the main entry point into this Express view engine implementation. It adds the concept of a "layout" and delegates rendering to the `render()` method.
|
||||
|
||||
The `options` will be used both as the context in which the Handlebars templates are rendered, and to signal this view engine on how it should behave, e.g., `options.cache=false` will _always_ load the templates from disk.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `viewPath`: String path to the Handlebars template file which should serve as the `{{{body}}}` when using a layout.
|
||||
|
||||
* `[options]`: Optional object which will serve as the context in which the Handlebars templates are rendered. It may also contain any of the following properties which affect this view engine's behavior:
|
||||
|
||||
* `[cache]`: Whether cached templates can be used if they have already been requested. This is recommended for production to avoid unnecessary file I/O.
|
||||
|
||||
* `[encoding]`: File encoding.
|
||||
|
||||
* `[data]`: Optional object which can contain any data that Handlebars will pipe through the template, all helpers, and all partials. This is a side data channel.
|
||||
|
||||
* `[helpers]`: Render-level helpers that will be merged with (and will override) instance and global helper functions.
|
||||
|
||||
* `[partials]`: Render-level partials will be merged with (and will override) instance and global partials. This should be a `{partialName: fn}` hash or a Promise of an object with this shape.
|
||||
|
||||
* `[layout]`: Optional string path to the Handlebars template file to be used as the "layout". This overrides any `defaultLayout` value. Passing a falsy value will render with no layout (even if a `defaultLayout` is defined).
|
||||
|
||||
* `[runtimeOptions]`: Optional object which can contain options passed to the template function.
|
||||
|
||||
* `callback`: Function to call once the template is retrieved.
|
||||
|
||||
### Hooks
|
||||
|
||||
The following is the list of protected methods that are called internally and serve as _hooks_ to override functionality of `ExpressHandlebars` instances. A value or a promise can be returned from these methods which allows them to perform async operations.
|
||||
|
||||
#### `_compileTemplate(template, options)`
|
||||
This hook will be called when a Handlebars template needs to be compiled. This function needs to return a compiled Handlebars template function, or a promise for one.
|
||||
|
||||
By default this hook calls `Handlebars.compile()`, but it can be overridden to preform operations before and/or after Handlebars compiles the template. This is useful if you wanted to first process Markdown within a Handlebars template.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `template`: String Handlebars template that needs to be compiled.
|
||||
|
||||
* `options`: Object `compilerOptions` that were specified when the `ExpressHandlebars` instance as created. This object should be passed along to the `Handlebars.compile()` function.
|
||||
|
||||
#### `_precompileTemplate(template, options)`
|
||||
This hook will be called when a Handlebars template needs to be precompiled. This function needs to return a serialized Handlebars template spec. string, or a promise for one.
|
||||
|
||||
By default this hook calls `Handlebars.precompile()`, but it can be overridden to preform operations before and/or after Handlebars precompiles the template. This is useful if you wanted to first process Markdown within a Handlebars template.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `template`: String Handlebars template that needs to be precompiled.
|
||||
|
||||
* `options`: Object `compilerOptions` that were specified when the `ExpressHandlebars` instance as created. This object should be passed along to the `Handlebars.compile()` function.
|
||||
|
||||
#### `_renderTemplate(template, context, options)`
|
||||
This hook will be called when a compiled Handlebars template needs to be rendered. This function needs to returned the rendered output string, or a promise for one.
|
||||
|
||||
By default this hook simply calls the passed-in `template` with the `context` and `options` arguments, but it can be overridden to perform operations before and/or after rendering the template.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
* `template`: Compiled Handlebars template function to call.
|
||||
|
||||
* `context`: The context object in which to render the `template`.
|
||||
|
||||
* `options`: Object that contains options and metadata for rendering the template:
|
||||
|
||||
* `data`: Object to define custom `@variable` private variables.
|
||||
|
||||
* `helpers`: Object to provide custom helpers in addition to the globally defined helpers.
|
||||
|
||||
* `partials`: Object to provide custom partials in addition to the globally defined partials.
|
||||
|
||||
* `...runtimeOptions`: Other options specified by the `runtimeOptions` value.
|
||||
|
||||
|
||||
[promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
||||
[Runtime Options]: https://handlebarsjs.com/api-reference/runtime-options.html
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### [Basic Usage][]
|
||||
|
||||
This example shows the most basic way to use this view engine.
|
||||
|
||||
### [Advanced Usage][]
|
||||
|
||||
This example is more comprehensive and shows how to use many of the features of this view engine, including helpers, partials, multiple layouts, etc.
|
||||
|
||||
As noted in the **Package Design** section, this view engine's implementation is instance-based, and more advanced usages can take advantage of this. The Advanced Usage example demonstrates how to use an `ExpressHandlebars` instance to share templates with the client, among other features.
|
||||
|
||||
|
||||
[Basic Usage]: https://github.com/express-handlebars/express-handlebars/tree/master/examples/basic
|
||||
[Advanced Usage]: https://github.com/express-handlebars/express-handlebars/tree/master/examples/advanced
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This software is free to use under the Yahoo! Inc. BSD license. See the [LICENSE file][] for license text and copyright information.
|
||||
|
||||
|
||||
[LICENSE file]: https://github.com/express-handlebars/express-handlebars/blob/master/LICENSE
|
37
app/node_modules/express-handlebars/dist/express-handlebars.d.ts
generated
vendored
37
app/node_modules/express-handlebars/dist/express-handlebars.d.ts
generated
vendored
@@ -1,37 +0,0 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="handlebars" />
|
||||
import type { UnknownObject, HelperDelegateObject, ConfigOptions, Engine, TemplateSpecificationObject, TemplateDelegateObject, FsCache, PartialTemplateOptions, PartialsDirObject, RenderOptions, RenderViewOptions, RenderCallback, HandlebarsImport, CompiledCache, PrecompiledCache } from "../types";
|
||||
export default class ExpressHandlebars {
|
||||
config: ConfigOptions;
|
||||
engine: Engine;
|
||||
encoding: BufferEncoding;
|
||||
layoutsDir: string;
|
||||
extname: string;
|
||||
compiled: CompiledCache;
|
||||
precompiled: PrecompiledCache;
|
||||
_fsCache: FsCache;
|
||||
partialsDir: string | PartialsDirObject | (string | PartialsDirObject)[];
|
||||
compilerOptions: CompileOptions;
|
||||
runtimeOptions: RuntimeOptions;
|
||||
helpers: HelperDelegateObject;
|
||||
defaultLayout: string;
|
||||
handlebars: HandlebarsImport;
|
||||
constructor(config?: ConfigOptions);
|
||||
getPartials(options?: PartialTemplateOptions): Promise<TemplateSpecificationObject | TemplateDelegateObject>;
|
||||
getTemplate(filePath: string, options?: PartialTemplateOptions): Promise<HandlebarsTemplateDelegate | TemplateSpecification>;
|
||||
getTemplates(dirPath: string, options?: PartialTemplateOptions): Promise<HandlebarsTemplateDelegate | TemplateSpecification>;
|
||||
render(filePath: string, context?: UnknownObject, options?: RenderOptions): Promise<string>;
|
||||
renderView(viewPath: string): Promise<string>;
|
||||
renderView(viewPath: string, options: RenderViewOptions): Promise<string>;
|
||||
renderView(viewPath: string, callback: RenderCallback): Promise<null>;
|
||||
renderView(viewPath: string, options: RenderViewOptions, callback: RenderCallback): Promise<null>;
|
||||
resetCache(filePathsOrFilter?: string | string[] | ((template: string) => boolean)): void;
|
||||
protected _compileTemplate(template: string, options?: RuntimeOptions): HandlebarsTemplateDelegate;
|
||||
protected _precompileTemplate(template: string, options?: RuntimeOptions): TemplateSpecification;
|
||||
protected _renderTemplate(template: HandlebarsTemplateDelegate, context?: UnknownObject, options?: RuntimeOptions): string;
|
||||
private _getDir;
|
||||
private _getFile;
|
||||
private _getTemplateName;
|
||||
private _resolveViewsPath;
|
||||
private _resolveLayoutPath;
|
||||
}
|
337
app/node_modules/express-handlebars/dist/express-handlebars.js
generated
vendored
337
app/node_modules/express-handlebars/dist/express-handlebars.js
generated
vendored
@@ -1,337 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* Copyright (c) 2015, Yahoo Inc. All rights reserved.
|
||||
* Copyrights licensed under the New BSD License.
|
||||
* See the accompanying LICENSE file for terms.
|
||||
*/
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Handlebars = require("handlebars");
|
||||
const fs = require("graceful-fs");
|
||||
const path = require("node:path");
|
||||
const node_util_1 = require("node:util");
|
||||
const glob_1 = require("glob");
|
||||
const readFile = (0, node_util_1.promisify)(fs.readFile);
|
||||
// -----------------------------------------------------------------------------
|
||||
const defaultConfig = {
|
||||
handlebars: Handlebars,
|
||||
extname: ".handlebars",
|
||||
encoding: "utf8",
|
||||
layoutsDir: undefined,
|
||||
partialsDir: undefined,
|
||||
defaultLayout: "main",
|
||||
helpers: undefined,
|
||||
compilerOptions: undefined,
|
||||
runtimeOptions: undefined,
|
||||
};
|
||||
class ExpressHandlebars {
|
||||
constructor(config = {}) {
|
||||
// Config properties with defaults.
|
||||
Object.assign(this, defaultConfig, config);
|
||||
// save given config to override other settings.
|
||||
this.config = config;
|
||||
// Express view engine integration point.
|
||||
this.engine = this.renderView.bind(this);
|
||||
// Normalize `extname`.
|
||||
if (this.extname.charAt(0) !== ".") {
|
||||
this.extname = "." + this.extname;
|
||||
}
|
||||
// Internal caches of compiled and precompiled templates.
|
||||
this.compiled = {};
|
||||
this.precompiled = {};
|
||||
// Private internal file system cache.
|
||||
this._fsCache = {};
|
||||
}
|
||||
getPartials(options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (typeof this.partialsDir === "undefined") {
|
||||
return {};
|
||||
}
|
||||
const partialsDirs = Array.isArray(this.partialsDir) ? this.partialsDir : [this.partialsDir];
|
||||
const dirs = yield Promise.all(partialsDirs.map((dir) => __awaiter(this, void 0, void 0, function* () {
|
||||
let dirPath;
|
||||
let dirTemplates;
|
||||
let dirNamespace;
|
||||
let dirRename;
|
||||
// Support `partialsDir` collection with object entries that contain a
|
||||
// templates promise and a namespace.
|
||||
if (typeof dir === "string") {
|
||||
dirPath = dir;
|
||||
}
|
||||
else if (typeof dir === "object") {
|
||||
dirTemplates = dir.templates;
|
||||
dirNamespace = dir.namespace;
|
||||
dirRename = dir.rename;
|
||||
dirPath = dir.dir;
|
||||
}
|
||||
// We must have some path to templates, or templates themselves.
|
||||
if (!dirPath && !dirTemplates) {
|
||||
throw new Error("A partials dir must be a string or config object");
|
||||
}
|
||||
const templates = dirTemplates || (yield this.getTemplates(dirPath, options));
|
||||
return {
|
||||
templates: templates,
|
||||
namespace: dirNamespace,
|
||||
rename: dirRename,
|
||||
};
|
||||
})));
|
||||
const partials = {};
|
||||
for (const dir of dirs) {
|
||||
const { templates, namespace, rename } = dir;
|
||||
const filePaths = Object.keys(templates);
|
||||
const getTemplateNameFn = typeof rename === "function"
|
||||
? rename
|
||||
: this._getTemplateName.bind(this);
|
||||
for (const filePath of filePaths) {
|
||||
const partialName = getTemplateNameFn(filePath, namespace);
|
||||
partials[partialName] = templates[filePath];
|
||||
}
|
||||
}
|
||||
return partials;
|
||||
});
|
||||
}
|
||||
getTemplate(filePath, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
filePath = path.resolve(filePath);
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const cache = options.precompiled ? this.precompiled : this.compiled;
|
||||
const template = options.cache && cache[filePath];
|
||||
if (template) {
|
||||
return template;
|
||||
}
|
||||
// Optimistically cache template promise to reduce file system I/O, but
|
||||
// remove from cache if there was a problem.
|
||||
try {
|
||||
cache[filePath] = this._getFile(filePath, { cache: options.cache, encoding })
|
||||
.then((file) => {
|
||||
const compileTemplate = (options.precompiled ? this._precompileTemplate : this._compileTemplate).bind(this);
|
||||
return compileTemplate(file, this.compilerOptions);
|
||||
});
|
||||
return yield cache[filePath];
|
||||
}
|
||||
catch (err) {
|
||||
delete cache[filePath];
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
getTemplates(dirPath, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const cache = options.cache;
|
||||
const filePaths = yield this._getDir(dirPath, { cache });
|
||||
const templates = yield Promise.all(filePaths.map(filePath => {
|
||||
return this.getTemplate(path.join(dirPath, filePath), options);
|
||||
}));
|
||||
const hash = {};
|
||||
for (let i = 0; i < filePaths.length; i++) {
|
||||
hash[filePaths[i]] = templates[i];
|
||||
}
|
||||
return hash;
|
||||
});
|
||||
}
|
||||
render(filePath, context = {}, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const [template, partials] = yield Promise.all([
|
||||
this.getTemplate(filePath, { cache: options.cache, encoding }),
|
||||
(options.partials || this.getPartials({ cache: options.cache, encoding })),
|
||||
]);
|
||||
const helpers = Object.assign(Object.assign({}, this.helpers), options.helpers);
|
||||
const runtimeOptions = Object.assign(Object.assign({}, this.runtimeOptions), options.runtimeOptions);
|
||||
// Add ExpressHandlebars metadata to the data channel so that it's
|
||||
// accessible within the templates and helpers, namespaced under:
|
||||
// `@exphbs.*`
|
||||
const data = Object.assign(Object.assign({}, options.data), { exphbs: Object.assign(Object.assign({}, options), { filePath,
|
||||
helpers,
|
||||
partials,
|
||||
runtimeOptions }) });
|
||||
const html = this._renderTemplate(template, context, Object.assign(Object.assign({}, runtimeOptions), { data,
|
||||
helpers,
|
||||
partials }));
|
||||
return html;
|
||||
});
|
||||
}
|
||||
renderView(viewPath, options = {}, callback = null) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (typeof options === "function") {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
const context = options;
|
||||
let promise = null;
|
||||
if (!callback) {
|
||||
promise = new Promise((resolve, reject) => {
|
||||
callback = (err, value) => { err !== null ? reject(err) : resolve(value); };
|
||||
});
|
||||
}
|
||||
// Express provides `settings.views` which is the path to the views dir that
|
||||
// the developer set on the Express app. When this value exists, it's used
|
||||
// to compute the view's name. Layouts and Partials directories are relative
|
||||
// to `settings.view` path
|
||||
let view;
|
||||
const views = options.settings && options.settings.views;
|
||||
const viewsPath = this._resolveViewsPath(views, viewPath);
|
||||
if (viewsPath) {
|
||||
view = this._getTemplateName(path.relative(viewsPath, viewPath));
|
||||
this.partialsDir = this.config.partialsDir || path.join(viewsPath, "partials/");
|
||||
this.layoutsDir = this.config.layoutsDir || path.join(viewsPath, "layouts/");
|
||||
}
|
||||
const encoding = options.encoding || this.encoding;
|
||||
// Merge render-level and instance-level helpers together.
|
||||
const helpers = Object.assign(Object.assign({}, this.helpers), options.helpers);
|
||||
// Merge render-level and instance-level partials together.
|
||||
const partials = Object.assign(Object.assign({}, yield this.getPartials({ cache: options.cache, encoding })), (options.partials || {}));
|
||||
// Pluck-out ExpressHandlebars-specific options and Handlebars-specific
|
||||
// rendering options.
|
||||
const renderOptions = {
|
||||
cache: options.cache,
|
||||
encoding,
|
||||
view,
|
||||
layout: "layout" in options ? options.layout : this.defaultLayout,
|
||||
data: options.data,
|
||||
helpers,
|
||||
partials,
|
||||
runtimeOptions: options.runtimeOptions,
|
||||
};
|
||||
try {
|
||||
let html = yield this.render(viewPath, context, renderOptions);
|
||||
const layoutPath = this._resolveLayoutPath(renderOptions.layout);
|
||||
if (layoutPath) {
|
||||
html = yield this.render(layoutPath, Object.assign(Object.assign({}, context), { body: html }), Object.assign(Object.assign({}, renderOptions), { layout: undefined }));
|
||||
}
|
||||
callback(null, html);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
resetCache(filePathsOrFilter) {
|
||||
let filePaths = [];
|
||||
if (typeof filePathsOrFilter === "undefined") {
|
||||
filePaths = Object.keys(this._fsCache);
|
||||
}
|
||||
else if (typeof filePathsOrFilter === "string") {
|
||||
filePaths = [filePathsOrFilter];
|
||||
}
|
||||
else if (typeof filePathsOrFilter === "function") {
|
||||
filePaths = Object.keys(this._fsCache).filter(filePathsOrFilter);
|
||||
}
|
||||
else if (Array.isArray(filePathsOrFilter)) {
|
||||
filePaths = filePathsOrFilter;
|
||||
}
|
||||
for (const filePath of filePaths) {
|
||||
delete this._fsCache[filePath];
|
||||
}
|
||||
}
|
||||
// -- Protected Hooks ----------------------------------------------------------
|
||||
_compileTemplate(template, options = {}) {
|
||||
return this.handlebars.compile(template.trim(), options);
|
||||
}
|
||||
_precompileTemplate(template, options = {}) {
|
||||
return this.handlebars.precompile(template.trim(), options);
|
||||
}
|
||||
_renderTemplate(template, context = {}, options = {}) {
|
||||
return template(context, options).trim();
|
||||
}
|
||||
// -- Private ------------------------------------------------------------------
|
||||
_getDir(dirPath, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
dirPath = path.resolve(dirPath);
|
||||
const cache = this._fsCache;
|
||||
let dir = options.cache && cache[dirPath];
|
||||
if (dir) {
|
||||
return [...yield dir];
|
||||
}
|
||||
const pattern = "**/*" + this.extname;
|
||||
// Optimistically cache dir promise to reduce file system I/O, but remove
|
||||
// from cache if there was a problem.
|
||||
try {
|
||||
dir = cache[dirPath] = (0, glob_1.glob)(pattern, {
|
||||
cwd: dirPath,
|
||||
follow: true,
|
||||
posix: true,
|
||||
});
|
||||
// @ts-expect-error FIXME: not sure how to throw error in glob for test coverage
|
||||
if (options._throwTestError) {
|
||||
throw new Error("test");
|
||||
}
|
||||
return [...yield dir];
|
||||
}
|
||||
catch (err) {
|
||||
delete cache[dirPath];
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
_getFile(filePath, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
filePath = path.resolve(filePath);
|
||||
const cache = this._fsCache;
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const file = options.cache && cache[filePath];
|
||||
if (file) {
|
||||
return file;
|
||||
}
|
||||
// Optimistically cache file promise to reduce file system I/O, but remove
|
||||
// from cache if there was a problem.
|
||||
try {
|
||||
cache[filePath] = readFile(filePath, { encoding: encoding || "utf8" });
|
||||
return yield cache[filePath];
|
||||
}
|
||||
catch (err) {
|
||||
delete cache[filePath];
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
_getTemplateName(filePath, namespace = null) {
|
||||
let name = filePath;
|
||||
if (name.endsWith(this.extname)) {
|
||||
name = name.substring(0, name.length - this.extname.length);
|
||||
}
|
||||
if (namespace) {
|
||||
name = namespace + "/" + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
_resolveViewsPath(views, file) {
|
||||
if (!Array.isArray(views)) {
|
||||
return views;
|
||||
}
|
||||
let lastDir = path.resolve(file);
|
||||
let dir = path.dirname(lastDir);
|
||||
const absoluteViews = views.map(v => path.resolve(v));
|
||||
// find the closest parent
|
||||
while (dir !== lastDir) {
|
||||
const index = absoluteViews.indexOf(dir);
|
||||
if (index >= 0) {
|
||||
return views[index];
|
||||
}
|
||||
lastDir = dir;
|
||||
dir = path.dirname(lastDir);
|
||||
}
|
||||
// cannot resolve view
|
||||
return null;
|
||||
}
|
||||
_resolveLayoutPath(layoutPath) {
|
||||
if (!layoutPath) {
|
||||
return null;
|
||||
}
|
||||
if (!path.extname(layoutPath)) {
|
||||
layoutPath += this.extname;
|
||||
}
|
||||
return path.resolve(this.layoutsDir || "", layoutPath);
|
||||
}
|
||||
}
|
||||
exports.default = ExpressHandlebars;
|
||||
//# sourceMappingURL=express-handlebars.js.map
|
1
app/node_modules/express-handlebars/dist/express-handlebars.js.map
generated
vendored
1
app/node_modules/express-handlebars/dist/express-handlebars.js.map
generated
vendored
File diff suppressed because one or more lines are too long
5
app/node_modules/express-handlebars/dist/index.d.ts
generated
vendored
5
app/node_modules/express-handlebars/dist/index.d.ts
generated
vendored
@@ -1,5 +0,0 @@
|
||||
import ExpressHandlebars from "./express-handlebars";
|
||||
import type { ConfigOptions, Engine } from "../types";
|
||||
export { ExpressHandlebars };
|
||||
export declare function create(config?: ConfigOptions): ExpressHandlebars;
|
||||
export declare function engine(config?: ConfigOptions): Engine;
|
19
app/node_modules/express-handlebars/dist/index.js
generated
vendored
19
app/node_modules/express-handlebars/dist/index.js
generated
vendored
@@ -1,19 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
* Copyright (c) 2014, Yahoo Inc. All rights reserved.
|
||||
* Copyrights licensed under the New BSD License.
|
||||
* See the accompanying LICENSE file for terms.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.engine = exports.create = exports.ExpressHandlebars = void 0;
|
||||
const express_handlebars_1 = require("./express-handlebars");
|
||||
exports.ExpressHandlebars = express_handlebars_1.default;
|
||||
function create(config = {}) {
|
||||
return new express_handlebars_1.default(config);
|
||||
}
|
||||
exports.create = create;
|
||||
function engine(config = {}) {
|
||||
return create(config).engine;
|
||||
}
|
||||
exports.engine = engine;
|
||||
//# sourceMappingURL=index.js.map
|
1
app/node_modules/express-handlebars/dist/index.js.map
generated
vendored
1
app/node_modules/express-handlebars/dist/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,6DAAqD;AAM5C,4BANF,4BAAiB,CAME;AAE1B,SAAgB,MAAM,CAAE,SAAwB,EAAE;IACjD,OAAO,IAAI,4BAAiB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAFD,wBAEC;AAED,SAAgB,MAAM,CAAE,SAAwB,EAAE;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;AAC9B,CAAC;AAFD,wBAEC"}
|
27
app/node_modules/express-handlebars/jest.config.js
generated
vendored
27
app/node_modules/express-handlebars/jest.config.js
generated
vendored
@@ -1,27 +0,0 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
restoreMocks: true,
|
||||
clearMocks: true,
|
||||
collectCoverageFrom: [
|
||||
"lib/**/*.ts",
|
||||
],
|
||||
coverageDirectory: "coverage",
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 100,
|
||||
functions: 100,
|
||||
lines: 100,
|
||||
statements: 100,
|
||||
},
|
||||
},
|
||||
testRegex: /\.test\.tsx?/.source,
|
||||
transform: {
|
||||
[/\.test\.tsx?/.source]: [
|
||||
"ts-jest", {
|
||||
diagnostics: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
moduleFileExtensions: ["js", "json", "jsx", "d.ts", "ts", "tsx", "node"],
|
||||
};
|
428
app/node_modules/express-handlebars/lib/express-handlebars.ts
generated
vendored
428
app/node_modules/express-handlebars/lib/express-handlebars.ts
generated
vendored
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Yahoo Inc. All rights reserved.
|
||||
* Copyrights licensed under the New BSD License.
|
||||
* See the accompanying LICENSE file for terms.
|
||||
*/
|
||||
|
||||
import * as Handlebars from "handlebars";
|
||||
import * as fs from "graceful-fs";
|
||||
import * as path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import { glob } from "glob";
|
||||
import type {
|
||||
UnknownObject,
|
||||
HelperDelegateObject,
|
||||
ConfigOptions,
|
||||
Engine,
|
||||
TemplateSpecificationObject,
|
||||
TemplateDelegateObject,
|
||||
FsCache,
|
||||
PartialTemplateOptions,
|
||||
PartialsDirObject,
|
||||
RenderOptions,
|
||||
RenderViewOptions,
|
||||
RenderCallback,
|
||||
HandlebarsImport,
|
||||
CompiledCache,
|
||||
PrecompiledCache,
|
||||
RenameFunction,
|
||||
} from "../types";
|
||||
|
||||
const readFile = promisify(fs.readFile);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const defaultConfig: ConfigOptions = {
|
||||
handlebars: Handlebars,
|
||||
extname: ".handlebars",
|
||||
encoding: "utf8",
|
||||
layoutsDir: undefined, // Default layouts directory is relative to `express settings.view` + `layouts/`
|
||||
partialsDir: undefined, // Default partials directory is relative to `express settings.view` + `partials/`
|
||||
defaultLayout: "main",
|
||||
helpers: undefined,
|
||||
compilerOptions: undefined,
|
||||
runtimeOptions: undefined,
|
||||
};
|
||||
|
||||
export default class ExpressHandlebars {
|
||||
config: ConfigOptions;
|
||||
engine: Engine;
|
||||
encoding: BufferEncoding;
|
||||
layoutsDir: string;
|
||||
extname: string;
|
||||
compiled: CompiledCache;
|
||||
precompiled: PrecompiledCache;
|
||||
_fsCache: FsCache;
|
||||
partialsDir: string|PartialsDirObject|(string|PartialsDirObject)[];
|
||||
compilerOptions: CompileOptions;
|
||||
runtimeOptions: RuntimeOptions;
|
||||
helpers: HelperDelegateObject;
|
||||
defaultLayout: string;
|
||||
handlebars: HandlebarsImport;
|
||||
|
||||
constructor (config: ConfigOptions = {}) {
|
||||
// Config properties with defaults.
|
||||
Object.assign(this, defaultConfig, config);
|
||||
|
||||
// save given config to override other settings.
|
||||
this.config = config;
|
||||
|
||||
// Express view engine integration point.
|
||||
this.engine = this.renderView.bind(this);
|
||||
|
||||
// Normalize `extname`.
|
||||
if (this.extname.charAt(0) !== ".") {
|
||||
this.extname = "." + this.extname;
|
||||
}
|
||||
|
||||
// Internal caches of compiled and precompiled templates.
|
||||
this.compiled = {};
|
||||
this.precompiled = {};
|
||||
|
||||
// Private internal file system cache.
|
||||
this._fsCache = {};
|
||||
}
|
||||
|
||||
async getPartials (options: PartialTemplateOptions = {}): Promise<TemplateSpecificationObject|TemplateDelegateObject> {
|
||||
if (typeof this.partialsDir === "undefined") {
|
||||
return {};
|
||||
}
|
||||
const partialsDirs = Array.isArray(this.partialsDir) ? this.partialsDir : [this.partialsDir];
|
||||
|
||||
const dirs = await Promise.all(partialsDirs.map(async dir => {
|
||||
let dirPath: string;
|
||||
let dirTemplates: TemplateDelegateObject;
|
||||
let dirNamespace: string;
|
||||
let dirRename: RenameFunction;
|
||||
|
||||
// Support `partialsDir` collection with object entries that contain a
|
||||
// templates promise and a namespace.
|
||||
if (typeof dir === "string") {
|
||||
dirPath = dir;
|
||||
} else if (typeof dir === "object") {
|
||||
dirTemplates = dir.templates;
|
||||
dirNamespace = dir.namespace;
|
||||
dirRename = dir.rename;
|
||||
dirPath = dir.dir;
|
||||
}
|
||||
|
||||
// We must have some path to templates, or templates themselves.
|
||||
if (!dirPath && !dirTemplates) {
|
||||
throw new Error("A partials dir must be a string or config object");
|
||||
}
|
||||
|
||||
const templates: HandlebarsTemplateDelegate|TemplateSpecification = dirTemplates || await this.getTemplates(dirPath, options);
|
||||
|
||||
return {
|
||||
templates: templates as HandlebarsTemplateDelegate|TemplateSpecification,
|
||||
namespace: dirNamespace,
|
||||
rename: dirRename,
|
||||
};
|
||||
}));
|
||||
|
||||
const partials: TemplateDelegateObject|TemplateSpecificationObject = {};
|
||||
|
||||
for (const dir of dirs) {
|
||||
const { templates, namespace, rename } = dir;
|
||||
const filePaths = Object.keys(templates);
|
||||
|
||||
const getTemplateNameFn = typeof rename === "function"
|
||||
? rename
|
||||
: this._getTemplateName.bind(this);
|
||||
|
||||
for (const filePath of filePaths) {
|
||||
const partialName = getTemplateNameFn(filePath, namespace);
|
||||
partials[partialName] = templates[filePath];
|
||||
}
|
||||
}
|
||||
|
||||
return partials;
|
||||
}
|
||||
|
||||
async getTemplate (filePath: string, options: PartialTemplateOptions = {}): Promise<HandlebarsTemplateDelegate|TemplateSpecification> {
|
||||
filePath = path.resolve(filePath);
|
||||
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const cache: PrecompiledCache|CompiledCache = options.precompiled ? this.precompiled : this.compiled;
|
||||
const template: Promise<HandlebarsTemplateDelegate|TemplateSpecification> = options.cache && cache[filePath];
|
||||
|
||||
if (template) {
|
||||
return template;
|
||||
}
|
||||
|
||||
// Optimistically cache template promise to reduce file system I/O, but
|
||||
// remove from cache if there was a problem.
|
||||
try {
|
||||
cache[filePath] = this._getFile(filePath, { cache: options.cache, encoding })
|
||||
.then((file: string) => {
|
||||
const compileTemplate: (file: string, options: RuntimeOptions) => TemplateSpecification|HandlebarsTemplateDelegate = (options.precompiled ? this._precompileTemplate : this._compileTemplate).bind(this);
|
||||
return compileTemplate(file, this.compilerOptions);
|
||||
});
|
||||
return await cache[filePath];
|
||||
} catch (err) {
|
||||
delete cache[filePath];
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async getTemplates (dirPath: string, options: PartialTemplateOptions = {}): Promise<HandlebarsTemplateDelegate|TemplateSpecification> {
|
||||
const cache = options.cache;
|
||||
|
||||
const filePaths = await this._getDir(dirPath, { cache });
|
||||
const templates = await Promise.all(filePaths.map(filePath => {
|
||||
return this.getTemplate(path.join(dirPath, filePath), options);
|
||||
}));
|
||||
|
||||
const hash = {};
|
||||
for (let i = 0; i < filePaths.length; i++) {
|
||||
hash[filePaths[i]] = templates[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
async render (filePath: string, context: UnknownObject = {}, options: RenderOptions = {}): Promise<string> {
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const [template, partials] = await Promise.all([
|
||||
this.getTemplate(filePath, { cache: options.cache, encoding }) as Promise<HandlebarsTemplateDelegate>,
|
||||
(options.partials || this.getPartials({ cache: options.cache, encoding })) as Promise<TemplateDelegateObject>,
|
||||
]);
|
||||
const helpers: HelperDelegateObject = { ...this.helpers, ...options.helpers };
|
||||
const runtimeOptions = { ...this.runtimeOptions, ...options.runtimeOptions };
|
||||
|
||||
// Add ExpressHandlebars metadata to the data channel so that it's
|
||||
// accessible within the templates and helpers, namespaced under:
|
||||
// `@exphbs.*`
|
||||
const data = {
|
||||
...options.data,
|
||||
exphbs: {
|
||||
...options,
|
||||
filePath,
|
||||
helpers,
|
||||
partials,
|
||||
runtimeOptions,
|
||||
},
|
||||
};
|
||||
|
||||
const html = this._renderTemplate(template, context, {
|
||||
...runtimeOptions,
|
||||
data,
|
||||
helpers,
|
||||
partials,
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
async renderView (viewPath: string): Promise<string>;
|
||||
async renderView (viewPath: string, options: RenderViewOptions): Promise<string>;
|
||||
async renderView (viewPath: string, callback: RenderCallback): Promise<null>;
|
||||
async renderView (viewPath: string, options: RenderViewOptions, callback: RenderCallback): Promise<null>;
|
||||
async renderView (viewPath: string, options: RenderViewOptions|RenderCallback = {}, callback: RenderCallback|null = null): Promise<string|null> {
|
||||
if (typeof options === "function") {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
const context = options as UnknownObject;
|
||||
|
||||
let promise: Promise<string>|null = null;
|
||||
if (!callback) {
|
||||
promise = new Promise((resolve, reject) => {
|
||||
callback = (err, value) => { err !== null ? reject(err) : resolve(value); };
|
||||
});
|
||||
}
|
||||
|
||||
// Express provides `settings.views` which is the path to the views dir that
|
||||
// the developer set on the Express app. When this value exists, it's used
|
||||
// to compute the view's name. Layouts and Partials directories are relative
|
||||
// to `settings.view` path
|
||||
let view: string;
|
||||
const views = options.settings && options.settings.views;
|
||||
const viewsPath = this._resolveViewsPath(views, viewPath);
|
||||
if (viewsPath) {
|
||||
view = this._getTemplateName(path.relative(viewsPath, viewPath));
|
||||
this.partialsDir = this.config.partialsDir || path.join(viewsPath, "partials/");
|
||||
this.layoutsDir = this.config.layoutsDir || path.join(viewsPath, "layouts/");
|
||||
}
|
||||
|
||||
const encoding = options.encoding || this.encoding;
|
||||
|
||||
// Merge render-level and instance-level helpers together.
|
||||
const helpers = { ...this.helpers, ...options.helpers };
|
||||
|
||||
// Merge render-level and instance-level partials together.
|
||||
const partials: TemplateDelegateObject = {
|
||||
...await this.getPartials({ cache: options.cache, encoding }) as TemplateDelegateObject,
|
||||
...(options.partials || {}),
|
||||
};
|
||||
|
||||
// Pluck-out ExpressHandlebars-specific options and Handlebars-specific
|
||||
// rendering options.
|
||||
const renderOptions = {
|
||||
cache: options.cache,
|
||||
encoding,
|
||||
view,
|
||||
layout: "layout" in options ? options.layout : this.defaultLayout,
|
||||
data: options.data,
|
||||
helpers,
|
||||
partials,
|
||||
runtimeOptions: options.runtimeOptions,
|
||||
};
|
||||
|
||||
try {
|
||||
let html = await this.render(viewPath, context, renderOptions);
|
||||
const layoutPath = this._resolveLayoutPath(renderOptions.layout);
|
||||
|
||||
if (layoutPath) {
|
||||
html = await this.render(
|
||||
layoutPath,
|
||||
{ ...context, body: html },
|
||||
{ ...renderOptions, layout: undefined },
|
||||
);
|
||||
}
|
||||
callback(null, html);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
resetCache (filePathsOrFilter?: string | string[] | ((template: string) => boolean)) {
|
||||
let filePaths: string[] = [];
|
||||
|
||||
if (typeof filePathsOrFilter === "undefined") {
|
||||
filePaths = Object.keys(this._fsCache);
|
||||
} else if (typeof filePathsOrFilter === "string") {
|
||||
filePaths = [filePathsOrFilter];
|
||||
} else if (typeof filePathsOrFilter === "function") {
|
||||
filePaths = Object.keys(this._fsCache).filter(filePathsOrFilter);
|
||||
} else if (Array.isArray(filePathsOrFilter)) {
|
||||
filePaths = filePathsOrFilter;
|
||||
}
|
||||
|
||||
for (const filePath of filePaths) {
|
||||
delete this._fsCache[filePath];
|
||||
}
|
||||
}
|
||||
|
||||
// -- Protected Hooks ----------------------------------------------------------
|
||||
|
||||
protected _compileTemplate (template: string, options: RuntimeOptions = {}): HandlebarsTemplateDelegate {
|
||||
return this.handlebars.compile(template.trim(), options);
|
||||
}
|
||||
|
||||
protected _precompileTemplate (template: string, options: RuntimeOptions = {}): TemplateSpecification {
|
||||
return this.handlebars.precompile(template.trim(), options);
|
||||
}
|
||||
|
||||
protected _renderTemplate (template: HandlebarsTemplateDelegate, context: UnknownObject = {}, options: RuntimeOptions = {}): string {
|
||||
return template(context, options).trim();
|
||||
}
|
||||
|
||||
// -- Private ------------------------------------------------------------------
|
||||
|
||||
private async _getDir (dirPath: string, options: PartialTemplateOptions = {}): Promise<string[]> {
|
||||
dirPath = path.resolve(dirPath);
|
||||
|
||||
const cache = this._fsCache;
|
||||
let dir = options.cache && (cache[dirPath] as Promise<string[]>);
|
||||
|
||||
if (dir) {
|
||||
return [...await dir];
|
||||
}
|
||||
|
||||
const pattern = "**/*" + this.extname;
|
||||
|
||||
// Optimistically cache dir promise to reduce file system I/O, but remove
|
||||
// from cache if there was a problem.
|
||||
|
||||
try {
|
||||
dir = cache[dirPath] = glob(pattern, {
|
||||
cwd: dirPath,
|
||||
follow: true,
|
||||
posix: true,
|
||||
});
|
||||
// @ts-expect-error FIXME: not sure how to throw error in glob for test coverage
|
||||
if (options._throwTestError) {
|
||||
throw new Error("test");
|
||||
}
|
||||
|
||||
return [...await dir];
|
||||
} catch (err) {
|
||||
delete cache[dirPath];
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
private async _getFile (filePath: string, options: PartialTemplateOptions = {}): Promise<string> {
|
||||
filePath = path.resolve(filePath);
|
||||
|
||||
const cache = this._fsCache;
|
||||
const encoding = options.encoding || this.encoding;
|
||||
const file = options.cache && (cache[filePath] as Promise<string>);
|
||||
|
||||
if (file) {
|
||||
return file;
|
||||
}
|
||||
|
||||
// Optimistically cache file promise to reduce file system I/O, but remove
|
||||
// from cache if there was a problem.
|
||||
try {
|
||||
cache[filePath] = readFile(filePath, { encoding: encoding || "utf8" });
|
||||
return await cache[filePath] as string;
|
||||
} catch (err) {
|
||||
delete cache[filePath];
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
private _getTemplateName (filePath: string, namespace: string = null): string {
|
||||
let name = filePath;
|
||||
|
||||
if (name.endsWith(this.extname)) {
|
||||
name = name.substring(0, name.length - this.extname.length);
|
||||
}
|
||||
|
||||
if (namespace) {
|
||||
name = namespace + "/" + name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private _resolveViewsPath (views: string|string[], file: string): string|null {
|
||||
if (!Array.isArray(views)) {
|
||||
return views;
|
||||
}
|
||||
|
||||
let lastDir = path.resolve(file);
|
||||
let dir = path.dirname(lastDir);
|
||||
const absoluteViews = views.map(v => path.resolve(v));
|
||||
|
||||
// find the closest parent
|
||||
while (dir !== lastDir) {
|
||||
const index = absoluteViews.indexOf(dir);
|
||||
if (index >= 0) {
|
||||
return views[index];
|
||||
}
|
||||
lastDir = dir;
|
||||
dir = path.dirname(lastDir);
|
||||
}
|
||||
|
||||
// cannot resolve view
|
||||
return null;
|
||||
}
|
||||
|
||||
private _resolveLayoutPath (layoutPath: string): string|null {
|
||||
if (!layoutPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!path.extname(layoutPath)) {
|
||||
layoutPath += this.extname;
|
||||
}
|
||||
|
||||
return path.resolve(this.layoutsDir || "", layoutPath);
|
||||
}
|
||||
}
|
21
app/node_modules/express-handlebars/lib/index.ts
generated
vendored
21
app/node_modules/express-handlebars/lib/index.ts
generated
vendored
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Yahoo Inc. All rights reserved.
|
||||
* Copyrights licensed under the New BSD License.
|
||||
* See the accompanying LICENSE file for terms.
|
||||
*/
|
||||
|
||||
import ExpressHandlebars from "./express-handlebars";
|
||||
import type {
|
||||
ConfigOptions,
|
||||
Engine,
|
||||
} from "../types";
|
||||
|
||||
export { ExpressHandlebars };
|
||||
|
||||
export function create (config: ConfigOptions = {}): ExpressHandlebars {
|
||||
return new ExpressHandlebars(config);
|
||||
}
|
||||
|
||||
export function engine (config: ConfigOptions = {}): Engine {
|
||||
return create(config).engine;
|
||||
}
|
104
app/node_modules/express-handlebars/package.json
generated
vendored
104
app/node_modules/express-handlebars/package.json
generated
vendored
@@ -1,104 +0,0 @@
|
||||
{
|
||||
"_from": "express-handlebars@^7.1.2",
|
||||
"_id": "express-handlebars@7.1.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-ss9d3mBChOLTEtyfzXCsxlItUxpgS3i4cb/F70G6Q5ohQzmD12XB4x/Y9U6YboeeYBJZt7WQ5yUNu7ZSQ/EGyQ==",
|
||||
"_location": "/express-handlebars",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "express-handlebars@^7.1.2",
|
||||
"name": "express-handlebars",
|
||||
"escapedName": "express-handlebars",
|
||||
"rawSpec": "^7.1.2",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^7.1.2"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-7.1.2.tgz",
|
||||
"_shasum": "2471673d11af46f496cba4098a705f0217232fda",
|
||||
"_spec": "express-handlebars@^7.1.2",
|
||||
"_where": "/mnt/c/Users/docto/Downloads/Rappaurio",
|
||||
"author": {
|
||||
"name": "Eric Ferraiuolo",
|
||||
"email": "eferraiuolo@gmail.com",
|
||||
"url": "http://ericf.me/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/express-handlebars/express-handlebars/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"glob": "^10.3.3",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"handlebars": "^4.7.8"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "A Handlebars view engine for Express which doesn't suck.",
|
||||
"devDependencies": {
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/commit-analyzer": "^10.0.1",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"@semantic-release/github": "^9.0.4",
|
||||
"@semantic-release/npm": "^10.0.4",
|
||||
"@semantic-release/release-notes-generator": "^11.0.4",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.3",
|
||||
"@types/node": "^18.17.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||
"@typescript-eslint/parser": "^6.3.0",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.28.0",
|
||||
"eslint-plugin-n": "^16.0.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"jest-cli": "^29.6.2",
|
||||
"semantic-release": "^21.0.7",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"directories": {
|
||||
"example": "examples"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v16"
|
||||
},
|
||||
"homepage": "https://github.com/express-handlebars/express-handlebars",
|
||||
"keywords": [
|
||||
"express",
|
||||
"express3",
|
||||
"handlebars",
|
||||
"view",
|
||||
"layout",
|
||||
"partials",
|
||||
"templates"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"main": "dist/index.js",
|
||||
"name": "express-handlebars",
|
||||
"release": {
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/changelog",
|
||||
"@semantic-release/npm",
|
||||
"@semantic-release/github",
|
||||
"@semantic-release/git"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/express-handlebars/express-handlebars.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"lint": "eslint .",
|
||||
"test": "jest --verbose",
|
||||
"test:cover": "jest --coverage"
|
||||
},
|
||||
"version": "7.1.2"
|
||||
}
|
10
app/node_modules/express-handlebars/renovate.json
generated
vendored
10
app/node_modules/express-handlebars/renovate.json
generated
vendored
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"devDependencies": {
|
||||
"automerge": true,
|
||||
"commitMessageTopic": "devDependency {{depName}}"
|
||||
},
|
||||
"rangeStrategy": "bump"
|
||||
}
|
880
app/node_modules/express-handlebars/spec/express-handlebars.test.ts
generated
vendored
880
app/node_modules/express-handlebars/spec/express-handlebars.test.ts
generated
vendored
@@ -1,880 +0,0 @@
|
||||
import * as path from "node:path";
|
||||
import * as expressHandlebars from "../lib/index";
|
||||
import type {
|
||||
TemplateDelegateObject,
|
||||
EngineOptions,
|
||||
} from "../types";
|
||||
|
||||
function fixturePath (filePath = "") {
|
||||
return path.resolve(__dirname, "./fixtures", filePath);
|
||||
}
|
||||
|
||||
// allow access to private functions for testing
|
||||
// https://github.com/microsoft/TypeScript/issues/19335
|
||||
/* eslint-disable dot-notation, @typescript-eslint/no-empty-function */
|
||||
|
||||
describe("express-handlebars", () => {
|
||||
test("ExpressHandlebars instance", () => {
|
||||
const exphbs = new expressHandlebars.ExpressHandlebars();
|
||||
expect(exphbs).toBeDefined();
|
||||
});
|
||||
|
||||
test("should nomalize extname", () => {
|
||||
const exphbs1 = expressHandlebars.create({ extname: "ext" });
|
||||
const exphbs2 = expressHandlebars.create({ extname: ".ext" });
|
||||
expect(exphbs1.extname).toBe(".ext");
|
||||
expect(exphbs2.extname).toBe(".ext");
|
||||
});
|
||||
|
||||
describe("getPartials", () => {
|
||||
test("should throw if partialsDir is not correct type", async () => {
|
||||
// @ts-expect-error partialsDir is invalid
|
||||
const exphbs = expressHandlebars.create({ partialsDir: 1 });
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
await exphbs.getPartials();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error).toEqual(expect.any(Error));
|
||||
expect(error?.message).toBe("A partials dir must be a string or config object");
|
||||
});
|
||||
|
||||
test("should return empty object if no partialsDir is defined", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({});
|
||||
});
|
||||
|
||||
test("should return empty object partialsDir does not exist", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: "does-not-exist" });
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({});
|
||||
});
|
||||
|
||||
test("should return partials on string", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: fixturePath("partials") });
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({
|
||||
partial: expect.any(Function),
|
||||
"partial-latin1": expect.any(Function),
|
||||
"subdir/partial-subdir": expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
test("should return partials on array", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: [fixturePath("partials")] });
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({
|
||||
partial: expect.any(Function),
|
||||
"partial-latin1": expect.any(Function),
|
||||
"subdir/partial-subdir": expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
test("should return partials on object", async () => {
|
||||
const fn = jest.fn();
|
||||
const exphbs = expressHandlebars.create({
|
||||
partialsDir: {
|
||||
templates: { "partial template": fn },
|
||||
namespace: "partial namespace",
|
||||
dir: fixturePath("partials"),
|
||||
},
|
||||
});
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({
|
||||
"partial namespace/partial template": fn,
|
||||
});
|
||||
});
|
||||
|
||||
test("should return renamed partials with rename function", async () => {
|
||||
const fn = jest.fn();
|
||||
const exphbs = expressHandlebars.create({
|
||||
partialsDir: {
|
||||
templates: { "partial/template": fn },
|
||||
namespace: "partial namespace",
|
||||
dir: fixturePath("partials"),
|
||||
rename: (filePath, namespace) => {
|
||||
return `${namespace}/${filePath.split("/")[0]}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({
|
||||
"partial namespace/partial": fn,
|
||||
});
|
||||
});
|
||||
|
||||
test("should return partials on path relative to cwd", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: "spec/fixtures/partials" });
|
||||
const partials = await exphbs.getPartials();
|
||||
expect(partials).toEqual({
|
||||
partial: expect.any(Function),
|
||||
"partial-latin1": expect.any(Function),
|
||||
"subdir/partial-subdir": expect.any(Function),
|
||||
});
|
||||
});
|
||||
|
||||
test("should return template function", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: "spec/fixtures/partials" });
|
||||
const partials = await exphbs.getPartials() as TemplateDelegateObject;
|
||||
const html = partials.partial({ text: "test text" });
|
||||
expect(html).toBe("partial test text");
|
||||
});
|
||||
|
||||
test("should return a template with encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({ partialsDir: "spec/fixtures/partials" });
|
||||
const partials = await exphbs.getPartials({ encoding: "latin1" }) as TemplateDelegateObject;
|
||||
const html = partials["partial-latin1"]({});
|
||||
expect(html).toContain("ñáéíóú");
|
||||
});
|
||||
|
||||
test("should return a template with default encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
encoding: "latin1",
|
||||
partialsDir: "spec/fixtures/partials",
|
||||
});
|
||||
const partials = await exphbs.getPartials() as TemplateDelegateObject;
|
||||
const html = partials["partial-latin1"]({});
|
||||
expect(html).toContain("ñáéíóú");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getTemplate", () => {
|
||||
test("should return cached template", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template.handlebars");
|
||||
const compiledCachedFunction = (() => "compiled") as Handlebars.TemplateDelegate;
|
||||
exphbs.compiled[filePath] = Promise.resolve(compiledCachedFunction);
|
||||
const precompiledCachedFunction = (() => "precompiled") as TemplateSpecification;
|
||||
exphbs.precompiled[filePath] = Promise.resolve(precompiledCachedFunction);
|
||||
const template = await exphbs.getTemplate(filePath, { cache: true });
|
||||
expect(template).toBe(compiledCachedFunction);
|
||||
});
|
||||
|
||||
test("should return precompiled cached template", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template.handlebars");
|
||||
const compiledCachedFunction = (() => "compiled") as Handlebars.TemplateDelegate;
|
||||
exphbs.compiled[filePath] = Promise.resolve(compiledCachedFunction);
|
||||
const precompiledCachedFunction = (() => "precompiled") as TemplateSpecification;
|
||||
exphbs.precompiled[filePath] = Promise.resolve(precompiledCachedFunction);
|
||||
const template = await exphbs.getTemplate(filePath, { precompiled: true, cache: true });
|
||||
expect(template).toBe(precompiledCachedFunction);
|
||||
});
|
||||
|
||||
test("should store in precompiled cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template.handlebars");
|
||||
expect(exphbs.compiled[filePath]).toBeUndefined();
|
||||
expect(exphbs.precompiled[filePath]).toBeUndefined();
|
||||
await exphbs.getTemplate(filePath, { precompiled: true });
|
||||
expect(exphbs.compiled[filePath]).toBeUndefined();
|
||||
expect(exphbs.precompiled[filePath]).toBeDefined();
|
||||
});
|
||||
|
||||
test("should store in compiled cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template.handlebars");
|
||||
expect(exphbs.compiled[filePath]).toBeUndefined();
|
||||
expect(exphbs.precompiled[filePath]).toBeUndefined();
|
||||
await exphbs.getTemplate(filePath);
|
||||
expect(exphbs.compiled[filePath]).toBeDefined();
|
||||
expect(exphbs.precompiled[filePath]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should return a template", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template.handlebars");
|
||||
const template = await exphbs.getTemplate(filePath) as HandlebarsTemplateDelegate;
|
||||
const html = template({ text: "test text" });
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should return a template with encoding", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates/template-latin1.handlebars");
|
||||
const template = await exphbs.getTemplate(filePath, { encoding: "latin1" }) as HandlebarsTemplateDelegate;
|
||||
const html = template({});
|
||||
expect(html).toContain("ñáéíóú");
|
||||
});
|
||||
|
||||
test("should return a template with default encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({ encoding: "latin1" });
|
||||
const filePath = fixturePath("templates/template-latin1.handlebars");
|
||||
const template = await exphbs.getTemplate(filePath) as HandlebarsTemplateDelegate;
|
||||
const html = template({});
|
||||
expect(html).toContain("ñáéíóú");
|
||||
});
|
||||
|
||||
test("should not store in cache on error", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = "does-not-exist";
|
||||
expect(exphbs.compiled[filePath]).toBeUndefined();
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
await exphbs.getTemplate(filePath);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error?.message).toEqual(expect.stringContaining("no such file or directory"));
|
||||
expect(exphbs.compiled[filePath]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getTemplates", () => {
|
||||
test("should return cached templates", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const fsCache = Promise.resolve([]);
|
||||
exphbs._fsCache[dirPath] = fsCache;
|
||||
const templates = await exphbs.getTemplates(dirPath, { cache: true });
|
||||
expect(templates).toEqual({});
|
||||
});
|
||||
|
||||
test("should return templates", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const templates = await exphbs.getTemplates(dirPath);
|
||||
const html = templates["template.handlebars"]({ text: "test text" });
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should get templates in sub directories", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const templates = await exphbs.getTemplates(dirPath);
|
||||
const paths = Object.keys(templates);
|
||||
expect(paths).toEqual([
|
||||
"template.handlebars",
|
||||
"template-latin1.handlebars",
|
||||
"subdir/template.handlebars",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("render", () => {
|
||||
test("should return cached templates", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("render-cached.handlebars");
|
||||
exphbs.compiled[filePath] = Promise.resolve(() => "cached");
|
||||
const html = await exphbs.render(filePath, undefined, { cache: true });
|
||||
expect(html).toBe("cached");
|
||||
});
|
||||
|
||||
test("should use helpers", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
helpers: {
|
||||
help: () => "help",
|
||||
},
|
||||
});
|
||||
const filePath = fixturePath("render-helper.handlebars");
|
||||
const html = await exphbs.render(filePath, { text: "test text" });
|
||||
expect(html).toBe("<p>help</p>");
|
||||
});
|
||||
|
||||
test("should override helpers", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
helpers: {
|
||||
help: () => "help",
|
||||
},
|
||||
});
|
||||
const filePath = fixturePath("render-helper.handlebars");
|
||||
const html = await exphbs.render(filePath, { text: "test text" }, {
|
||||
helpers: {
|
||||
help: (text: string) => text,
|
||||
},
|
||||
});
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should return html", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("render-text.handlebars");
|
||||
const html = await exphbs.render(filePath, { text: "test text" });
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should return html with encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
partialsDir: fixturePath("partials"),
|
||||
});
|
||||
const filePath = fixturePath("render-latin1.handlebars");
|
||||
const html = await exphbs.render(filePath, undefined, { encoding: "latin1" });
|
||||
expect(html).toContain("partial ñáéíóú");
|
||||
expect(html).toContain("render ñáéíóú");
|
||||
});
|
||||
|
||||
test("should return html with default encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
encoding: "latin1",
|
||||
partialsDir: fixturePath("partials"),
|
||||
});
|
||||
const filePath = fixturePath("render-latin1.handlebars");
|
||||
const html = await exphbs.render(filePath);
|
||||
expect(html).toContain("partial ñáéíóú");
|
||||
expect(html).toContain("render ñáéíóú");
|
||||
});
|
||||
|
||||
test("should render with partial", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
partialsDir: fixturePath("partials"),
|
||||
});
|
||||
const filePath = fixturePath("render-partial.handlebars");
|
||||
const html = await exphbs.render(filePath, { text: "test text" });
|
||||
expect(html.replace(/\r/g, "")).toBe("<h1>partial test text</h1>\n<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should render with subdir/partial", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
partialsDir: fixturePath("partials"),
|
||||
});
|
||||
const filePath = fixturePath("render-subdir-partial.handlebars");
|
||||
const html = await exphbs.render(filePath, { text: "test text" });
|
||||
expect(html.replace(/\r/g, "")).toBe("<h1>subdir partial test text</h1>\n<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should render with runtimeOptions", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
runtimeOptions: { allowProtoPropertiesByDefault: true },
|
||||
});
|
||||
const filePath = fixturePath("test");
|
||||
const spy = jest.fn(() => { return "test"; }) as Handlebars.TemplateDelegate;
|
||||
exphbs.compiled[filePath] = Promise.resolve(spy);
|
||||
await exphbs.render(filePath, undefined, { cache: true });
|
||||
expect(spy).toHaveBeenCalledWith(expect.any(Object), expect.objectContaining({ allowProtoPropertiesByDefault: true }));
|
||||
});
|
||||
|
||||
test("should override runtimeOptions", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
runtimeOptions: { allowProtoPropertiesByDefault: true },
|
||||
});
|
||||
const filePath = fixturePath("test");
|
||||
const spy = jest.fn(() => { return "test"; }) as Handlebars.TemplateDelegate;
|
||||
exphbs.compiled[filePath] = Promise.resolve(spy);
|
||||
await exphbs.render(filePath, undefined, {
|
||||
cache: true,
|
||||
runtimeOptions: { allowProtoPropertiesByDefault: false },
|
||||
});
|
||||
expect(spy).toHaveBeenCalledWith(expect.any(Object), expect.objectContaining({ allowProtoPropertiesByDefault: false }));
|
||||
});
|
||||
});
|
||||
|
||||
describe("engine", () => {
|
||||
test("should call renderView", async () => {
|
||||
jest.spyOn(expressHandlebars.ExpressHandlebars.prototype, "renderView").mockImplementation(() => Promise.resolve(null));
|
||||
const exphbs = expressHandlebars.create();
|
||||
const cb = () => { /* empty */ };
|
||||
exphbs.engine("view", {}, cb);
|
||||
expect(expressHandlebars.ExpressHandlebars.prototype.renderView).toHaveBeenCalledWith("view", {}, cb);
|
||||
});
|
||||
|
||||
test("should call engine", async () => {
|
||||
jest.spyOn(expressHandlebars.ExpressHandlebars.prototype, "renderView").mockImplementation(() => Promise.resolve(null));
|
||||
const cb = () => { /* empty */ };
|
||||
expressHandlebars.engine()("view", {}, cb);
|
||||
expect(expressHandlebars.ExpressHandlebars.prototype.renderView).toHaveBeenCalledWith("view", {}, cb);
|
||||
});
|
||||
|
||||
test("should render html", async () => {
|
||||
const renderView = expressHandlebars.engine({ defaultLayout: undefined });
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
const html = await renderView(viewPath, { text: "test text" } as EngineOptions);
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("renderView", () => {
|
||||
test("should use settings.views", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewPath = fixturePath("render-partial.handlebars");
|
||||
const viewsPath = fixturePath();
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: viewsPath },
|
||||
});
|
||||
expect(html.replace(/\r/g, "")).toBe("<body>\n<h1>partial test text</h1>\n<p>test text</p>\n</body>");
|
||||
});
|
||||
|
||||
test("should use settings.views array", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewPath = fixturePath("render-partial.handlebars");
|
||||
const viewsPath = fixturePath();
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: [viewsPath] },
|
||||
});
|
||||
expect(html.replace(/\r/g, "")).toBe("<body>\n<h1>partial test text</h1>\n<p>test text</p>\n</body>");
|
||||
});
|
||||
|
||||
test("should not use settings.views array when no parent found", async () => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
const viewsPath = "does-not-exist";
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: [viewsPath] },
|
||||
});
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should use settings.views when it changes", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewPath = fixturePath("render-partial.handlebars");
|
||||
const viewsPath = fixturePath();
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: viewsPath },
|
||||
});
|
||||
expect(html.replace(/\r/g, "")).toBe("<body>\n<h1>partial test text</h1>\n<p>test text</p>\n</body>");
|
||||
const otherViewsPath = fixturePath("other-views");
|
||||
const otherhtml = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: otherViewsPath },
|
||||
});
|
||||
expect(otherhtml.replace(/\r/g, "")).toBe("<body>\nother layout\n<h1>other partial test text</h1>\n<p>test text</p>\n</body>");
|
||||
});
|
||||
|
||||
test("should not overwrite config with settings.views", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
layoutsDir: fixturePath("layouts"),
|
||||
partialsDir: fixturePath("partials"),
|
||||
});
|
||||
const viewPath = fixturePath("render-partial.handlebars");
|
||||
const viewsPath = fixturePath("other-views");
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
settings: { views: viewsPath },
|
||||
});
|
||||
expect(html.replace(/\r/g, "")).toBe("<body>\n<h1>partial test text</h1>\n<p>test text</p>\n</body>");
|
||||
});
|
||||
|
||||
test("should merge helpers", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
defaultLayout: undefined,
|
||||
helpers: {
|
||||
help: () => "help",
|
||||
},
|
||||
});
|
||||
const viewPath = fixturePath("render-helper.handlebars");
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
helpers: {
|
||||
help: (text: string) => text,
|
||||
},
|
||||
});
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should use layout option", async () => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const layoutPath = fixturePath("layouts/main.handlebars");
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
const html = await exphbs.renderView(viewPath, {
|
||||
text: "test text",
|
||||
layout: layoutPath,
|
||||
});
|
||||
expect(html.replace(/\r/g, "")).toBe("<body>\n<p>test text</p>\n</body>");
|
||||
});
|
||||
|
||||
test("should render html", async () => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
const html = await exphbs.renderView(viewPath, { text: "test text" });
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
});
|
||||
|
||||
test("should render html with encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
defaultLayout: "main-latin1",
|
||||
partialsDir: fixturePath("partials"),
|
||||
layoutsDir: fixturePath("layouts"),
|
||||
});
|
||||
const viewPath = fixturePath("render-latin1.handlebars");
|
||||
const html = await exphbs.renderView(viewPath, { encoding: "latin1" });
|
||||
expect(html).toContain("layout ñáéíóú");
|
||||
expect(html).toContain("partial ñáéíóú");
|
||||
expect(html).toContain("render ñáéíóú");
|
||||
});
|
||||
|
||||
test("should render html with default encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({
|
||||
encoding: "latin1",
|
||||
defaultLayout: "main-latin1",
|
||||
partialsDir: fixturePath("partials"),
|
||||
layoutsDir: fixturePath("layouts"),
|
||||
});
|
||||
const viewPath = fixturePath("render-latin1.handlebars");
|
||||
const html = await exphbs.renderView(viewPath);
|
||||
expect(html).toContain("layout ñáéíóú");
|
||||
expect(html).toContain("partial ñáéíóú");
|
||||
expect(html).toContain("render ñáéíóú");
|
||||
});
|
||||
|
||||
test("should call callback with html", (done) => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
exphbs.renderView(viewPath, { text: "test text" }, (err: Error|null, html: string|undefined) => {
|
||||
expect(err).toBe(null);
|
||||
expect(html).toBe("<p>test text</p>");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test("should call callback as second parameter", (done) => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = fixturePath("render-text.handlebars");
|
||||
exphbs.renderView(viewPath, (err: Error|null, html: string|undefined) => {
|
||||
expect(err).toBe(null);
|
||||
expect(html).toBe("<p></p>");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test("should call callback with error", (done) => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = "does-not-exist";
|
||||
exphbs.renderView(viewPath, {}, (err: Error|null, html: string | undefined) => {
|
||||
expect(err?.message).toEqual(expect.stringContaining("no such file or directory"));
|
||||
expect(html).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test("should reject with error", async () => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const viewPath = "does-not-exist";
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
await exphbs.renderView(viewPath);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error?.message).toEqual(expect.stringContaining("no such file or directory"));
|
||||
});
|
||||
|
||||
test("should use runtimeOptions", async () => {
|
||||
const exphbs = expressHandlebars.create({ defaultLayout: undefined });
|
||||
const filePath = fixturePath("test");
|
||||
const spy = jest.fn(() => { return "test"; }) as Handlebars.TemplateDelegate;
|
||||
exphbs.compiled[filePath] = Promise.resolve(spy);
|
||||
await exphbs.renderView(filePath, {
|
||||
cache: true,
|
||||
runtimeOptions: { allowProtoPropertiesByDefault: true },
|
||||
});
|
||||
expect(spy).toHaveBeenCalledWith(expect.any(Object), expect.objectContaining({ allowProtoPropertiesByDefault: true }));
|
||||
});
|
||||
});
|
||||
|
||||
describe("resetCache", () => {
|
||||
test("should reset all cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const template = fixturePath("templates/template.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(exphbs._fsCache[template]).toBeDefined();
|
||||
exphbs.resetCache();
|
||||
expect(exphbs._fsCache).toEqual({});
|
||||
});
|
||||
|
||||
test("should reset all cache with undefined", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const template = fixturePath("templates/template.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(exphbs._fsCache[template]).toBeDefined();
|
||||
let undef: undefined;
|
||||
exphbs.resetCache(undef);
|
||||
expect(exphbs._fsCache).toEqual({});
|
||||
});
|
||||
|
||||
test("should reset cached file path", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const template = fixturePath("templates/template.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(4);
|
||||
expect(exphbs._fsCache[template]).toBeDefined();
|
||||
exphbs.resetCache(template);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(3);
|
||||
expect(exphbs._fsCache[template]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should reset cached file paths", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const template = fixturePath("templates/template.handlebars");
|
||||
const templateLatin1 = fixturePath("templates/template-latin1.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(4);
|
||||
expect(exphbs._fsCache[template]).toBeDefined();
|
||||
expect(exphbs._fsCache[templateLatin1]).toBeDefined();
|
||||
exphbs.resetCache([template, templateLatin1]);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(2);
|
||||
expect(exphbs._fsCache[template]).toBeUndefined();
|
||||
expect(exphbs._fsCache[templateLatin1]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should reset cached file based on filter", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const templateLatin1 = fixturePath("templates/template-latin1.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(4);
|
||||
expect(exphbs._fsCache[templateLatin1]).toBeDefined();
|
||||
exphbs.resetCache((f) => f.includes("latin1"));
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(3);
|
||||
expect(exphbs._fsCache[templateLatin1]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should not error on invalid file path", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const dirPath = fixturePath("templates");
|
||||
const template = fixturePath("templates/invalid.handlebars");
|
||||
await exphbs.getTemplates(dirPath);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(4);
|
||||
expect(exphbs._fsCache[template]).toBeUndefined();
|
||||
exphbs.resetCache(template);
|
||||
expect(Object.keys(exphbs._fsCache).length).toEqual(4);
|
||||
expect(exphbs._fsCache[template]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("hooks", () => {
|
||||
describe("_compileTemplate", () => {
|
||||
test("should call template with context and options", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error empty function
|
||||
jest.spyOn(exphbs.handlebars, "compile").mockImplementation(() => {});
|
||||
const template = "template";
|
||||
const options = {};
|
||||
exphbs["_compileTemplate"](template, options);
|
||||
expect(exphbs.handlebars.compile).toHaveBeenCalledWith(template, options);
|
||||
});
|
||||
|
||||
test("should trim template", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error empty function
|
||||
jest.spyOn(exphbs.handlebars, "compile").mockImplementation(() => {});
|
||||
const template = " template\n";
|
||||
const options = {};
|
||||
exphbs["_compileTemplate"](template, options);
|
||||
expect(exphbs.handlebars.compile).toHaveBeenCalledWith("template", options);
|
||||
});
|
||||
});
|
||||
|
||||
describe("_precompileTemplate", () => {
|
||||
test("should call template with context and options", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error empty function
|
||||
jest.spyOn(exphbs.handlebars, "precompile").mockImplementation(() => {});
|
||||
const template = "template";
|
||||
const options = {};
|
||||
exphbs["_precompileTemplate"](template, options);
|
||||
expect(exphbs.handlebars.precompile).toHaveBeenCalledWith(template, options);
|
||||
});
|
||||
|
||||
test("should trim template", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error empty function
|
||||
jest.spyOn(exphbs.handlebars, "precompile").mockImplementation(() => {});
|
||||
const template = " template\n";
|
||||
const options = {};
|
||||
exphbs["_precompileTemplate"](template, options);
|
||||
expect(exphbs.handlebars.precompile).toHaveBeenCalledWith("template", options);
|
||||
});
|
||||
});
|
||||
|
||||
describe("_renderTemplate", () => {
|
||||
test("should call template with context and options", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const template = jest.fn(() => "");
|
||||
const context = {};
|
||||
const options = {};
|
||||
exphbs["_renderTemplate"](template, context, options);
|
||||
expect(template).toHaveBeenCalledWith(context, options);
|
||||
});
|
||||
|
||||
test("should trim html", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const template = () => " \n";
|
||||
const html = exphbs["_renderTemplate"](template);
|
||||
expect(html).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("_getDir", () => {
|
||||
test("should get from cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("test");
|
||||
exphbs._fsCache[filePath] = Promise.resolve(["test"]);
|
||||
const file = await exphbs["_getDir"](filePath, { cache: true });
|
||||
expect(file).toEqual(["test"]);
|
||||
});
|
||||
|
||||
test("should store in cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("templates");
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
const expected = await exphbs["_getDir"](filePath);
|
||||
expect(exphbs._fsCache[filePath]).toBeInstanceOf(Promise);
|
||||
expect(await exphbs._fsCache[filePath]).toEqual(expected);
|
||||
});
|
||||
|
||||
test("should not store in cache on error", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = "test";
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
await exphbs["_getDir"](filePath, {
|
||||
// @ts-expect-error Add this just for testing
|
||||
_throwTestError: true,
|
||||
});
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error).toBeTruthy();
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("_getFile", () => {
|
||||
test("should get from cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("test");
|
||||
exphbs._fsCache[filePath] = "test";
|
||||
const file = await exphbs["_getFile"](filePath, { cache: true });
|
||||
expect(file).toBe("test");
|
||||
});
|
||||
|
||||
test("should store in cache", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("render-text.handlebars");
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
await exphbs["_getFile"](filePath);
|
||||
expect(exphbs._fsCache[filePath]).toBeDefined();
|
||||
});
|
||||
|
||||
test("should not store in cache on error", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = "does-not-exist";
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
let error: Error | undefined;
|
||||
try {
|
||||
await exphbs["_getFile"](filePath);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error?.message).toEqual(expect.stringContaining("no such file or directory"));
|
||||
expect(exphbs._fsCache[filePath]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should read as utf8", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("render-text.handlebars");
|
||||
const text = await exphbs["_getFile"](filePath);
|
||||
expect(text.trim()).toBe("<p>{{text}}</p>");
|
||||
});
|
||||
|
||||
test("should read as utf8 by default", async () => {
|
||||
const exphbs = expressHandlebars.create({ encoding: undefined });
|
||||
const filePath = fixturePath("render-text.handlebars");
|
||||
const text = await exphbs["_getFile"](filePath);
|
||||
expect(text.trim()).toBe("<p>{{text}}</p>");
|
||||
});
|
||||
|
||||
test("should read as latin1", async () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const filePath = fixturePath("render-latin1.handlebars");
|
||||
const text = await exphbs["_getFile"](filePath, { encoding: "latin1" });
|
||||
expect(text).toContain("ñáéíóú");
|
||||
});
|
||||
|
||||
test("should read as default encoding", async () => {
|
||||
const exphbs = expressHandlebars.create({ encoding: "latin1" });
|
||||
const filePath = fixturePath("render-latin1.handlebars");
|
||||
const text = await exphbs["_getFile"](filePath);
|
||||
expect(text).toContain("ñáéíóú");
|
||||
});
|
||||
});
|
||||
|
||||
describe("_getTemplateName", () => {
|
||||
test("should remove extension", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const name = exphbs["_getTemplateName"]("filePath.handlebars");
|
||||
expect(name).toBe("filePath");
|
||||
});
|
||||
|
||||
test("should leave if no extension", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const name = exphbs["_getTemplateName"]("filePath");
|
||||
expect(name).toBe("filePath");
|
||||
});
|
||||
|
||||
test("should add namespace", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const name = exphbs["_getTemplateName"]("filePath.handlebars", "namespace");
|
||||
expect(name).toBe("namespace/filePath");
|
||||
});
|
||||
});
|
||||
|
||||
describe("_resolveViewsPath", () => {
|
||||
test("should return closest parent", () => {
|
||||
const file = "/root/views/file.hbs";
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewsPath = exphbs["_resolveViewsPath"]([
|
||||
"/root",
|
||||
"/root/views",
|
||||
"/root/views/file",
|
||||
], file);
|
||||
expect(viewsPath).toBe("/root/views");
|
||||
});
|
||||
|
||||
test("should return string views", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewsPath = exphbs["_resolveViewsPath"]("./views", "filePath.hbs");
|
||||
expect(viewsPath).toBe("./views");
|
||||
});
|
||||
|
||||
test("should return null views", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error shouldn't expect null parameter
|
||||
const viewsPath = exphbs["_resolveViewsPath"](null, "filePath.hbs");
|
||||
expect(viewsPath).toBe(null);
|
||||
});
|
||||
|
||||
test("should return null if not found", () => {
|
||||
const file = "/file.hbs";
|
||||
const exphbs = expressHandlebars.create();
|
||||
const viewsPath = exphbs["_resolveViewsPath"]([
|
||||
"/views",
|
||||
], file);
|
||||
expect(viewsPath).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("_resolveLayoutPath", () => {
|
||||
test("should add extension", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
const layoutPath = exphbs["_resolveLayoutPath"]("filePath");
|
||||
expect(layoutPath).toEqual(expect.stringMatching(/filePath\.handlebars$/));
|
||||
});
|
||||
|
||||
test("should use layoutsDir", () => {
|
||||
const layoutsDir = fixturePath("layouts");
|
||||
const filePath = "filePath.handlebars";
|
||||
const exphbs = expressHandlebars.create({ layoutsDir });
|
||||
const layoutPath = exphbs["_resolveLayoutPath"](filePath);
|
||||
expect(layoutPath).toBe(path.resolve(layoutsDir, filePath));
|
||||
});
|
||||
|
||||
test("should return null", () => {
|
||||
const exphbs = expressHandlebars.create();
|
||||
// @ts-expect-error shouldn't expect null parameter
|
||||
const layoutPath = exphbs["_resolveLayoutPath"](null);
|
||||
expect(layoutPath).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
3
app/node_modules/express-handlebars/spec/fixtures/layouts/main-latin1.handlebars
generated
vendored
3
app/node_modules/express-handlebars/spec/fixtures/layouts/main-latin1.handlebars
generated
vendored
@@ -1,3 +0,0 @@
|
||||
file encoding: Windows 1252 (latin1)
|
||||
<p>layout <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD></p>
|
||||
{{{body}}}
|
3
app/node_modules/express-handlebars/spec/fixtures/layouts/main.handlebars
generated
vendored
3
app/node_modules/express-handlebars/spec/fixtures/layouts/main.handlebars
generated
vendored
@@ -1,3 +0,0 @@
|
||||
<body>
|
||||
{{{body}}}
|
||||
</body>
|
@@ -1,4 +0,0 @@
|
||||
<body>
|
||||
other layout
|
||||
{{{body}}}
|
||||
</body>
|
@@ -1 +0,0 @@
|
||||
other partial {{text}}
|
2
app/node_modules/express-handlebars/spec/fixtures/partials/partial-latin1.handlebars
generated
vendored
2
app/node_modules/express-handlebars/spec/fixtures/partials/partial-latin1.handlebars
generated
vendored
@@ -1,2 +0,0 @@
|
||||
file encoding: Windows 1252 (latin1)
|
||||
<p>partial <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD></p>
|
1
app/node_modules/express-handlebars/spec/fixtures/partials/partial.handlebars
generated
vendored
1
app/node_modules/express-handlebars/spec/fixtures/partials/partial.handlebars
generated
vendored
@@ -1 +0,0 @@
|
||||
partial {{text}}
|
@@ -1 +0,0 @@
|
||||
subdir partial {{text}}
|
1
app/node_modules/express-handlebars/spec/fixtures/render-cached.handlebars
generated
vendored
1
app/node_modules/express-handlebars/spec/fixtures/render-cached.handlebars
generated
vendored
@@ -1 +0,0 @@
|
||||
not cached
|
1
app/node_modules/express-handlebars/spec/fixtures/render-helper.handlebars
generated
vendored
1
app/node_modules/express-handlebars/spec/fixtures/render-helper.handlebars
generated
vendored
@@ -1 +0,0 @@
|
||||
<p>{{help text}}</p>
|
3
app/node_modules/express-handlebars/spec/fixtures/render-latin1.handlebars
generated
vendored
3
app/node_modules/express-handlebars/spec/fixtures/render-latin1.handlebars
generated
vendored
@@ -1,3 +0,0 @@
|
||||
{{> partial-latin1}}
|
||||
file encoding: Windows 1252 (latin1)
|
||||
<p>render <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD></p>
|
2
app/node_modules/express-handlebars/spec/fixtures/render-partial.handlebars
generated
vendored
2
app/node_modules/express-handlebars/spec/fixtures/render-partial.handlebars
generated
vendored
@@ -1,2 +0,0 @@
|
||||
<h1>{{> partial}}</h1>
|
||||
<p>{{text}}</p>
|
2
app/node_modules/express-handlebars/spec/fixtures/render-subdir-partial.handlebars
generated
vendored
2
app/node_modules/express-handlebars/spec/fixtures/render-subdir-partial.handlebars
generated
vendored
@@ -1,2 +0,0 @@
|
||||
<h1>{{> subdir/partial-subdir}}</h1>
|
||||
<p>{{text}}</p>
|
1
app/node_modules/express-handlebars/spec/fixtures/render-text.handlebars
generated
vendored
1
app/node_modules/express-handlebars/spec/fixtures/render-text.handlebars
generated
vendored
@@ -1 +0,0 @@
|
||||
<p>{{text}}</p>
|
@@ -1 +0,0 @@
|
||||
<p>{{text}}</p>
|
@@ -1,2 +0,0 @@
|
||||
file encoding: Windows 1252 (latin1)
|
||||
<p><3E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD></p>
|
1
app/node_modules/express-handlebars/spec/fixtures/templates/template.handlebars
generated
vendored
1
app/node_modules/express-handlebars/spec/fixtures/templates/template.handlebars
generated
vendored
@@ -1 +0,0 @@
|
||||
<p>{{text}}</p>
|
12
app/node_modules/express-handlebars/tsconfig.json
generated
vendored
12
app/node_modules/express-handlebars/tsconfig.json
generated
vendored
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"target": "ES2015",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["./lib/**/*"]
|
||||
}
|
92
app/node_modules/express-handlebars/types/index.d.ts
generated
vendored
92
app/node_modules/express-handlebars/types/index.d.ts
generated
vendored
@@ -1,92 +0,0 @@
|
||||
/// <reference types="handlebars" />
|
||||
|
||||
export interface UnknownObject {
|
||||
[index: string]: unknown
|
||||
}
|
||||
|
||||
export interface HelperDelegateObject {
|
||||
[index: string]: Handlebars.HelperDelegate;
|
||||
}
|
||||
|
||||
export interface TemplateDelegateObject {
|
||||
[index: string]: Handlebars.TemplateDelegate;
|
||||
}
|
||||
|
||||
export interface TemplateSpecificationObject {
|
||||
[index: string]: TemplateSpecification;
|
||||
}
|
||||
|
||||
export interface CompiledCache {
|
||||
[index: string]: Promise<Handlebars.TemplateDelegate>;
|
||||
}
|
||||
|
||||
export interface PrecompiledCache {
|
||||
[index: string]: Promise<TemplateSpecification>;
|
||||
}
|
||||
|
||||
export interface FsCache {
|
||||
[index: string]: string|string[]|Promise<string|string[]>;
|
||||
}
|
||||
|
||||
export type RenameFunction = (filePath: string, namespace?: string) => string
|
||||
|
||||
export interface PartialsDirObject {
|
||||
templates: TemplateDelegateObject;
|
||||
namespace: string;
|
||||
dir: string;
|
||||
rename?: RenameFunction | undefined;
|
||||
}
|
||||
|
||||
export interface PartialTemplateOptions {
|
||||
encoding?: BufferEncoding;
|
||||
cache?: boolean;
|
||||
precompiled?: boolean;
|
||||
}
|
||||
|
||||
export interface RenderOptions {
|
||||
cache?: boolean;
|
||||
data?: UnknownObject;
|
||||
encoding?: BufferEncoding;
|
||||
helpers?: HelperDelegateObject;
|
||||
layout?: string;
|
||||
partials?: TemplateDelegateObject;
|
||||
runtimeOptions?: Handlebars.RuntimeOptions;
|
||||
}
|
||||
|
||||
export interface RenderViewOptions extends RenderOptions {
|
||||
[index: string]: unknown;
|
||||
settings?: {
|
||||
views: string|string[]
|
||||
}
|
||||
}
|
||||
|
||||
export type HandlebarsCompile = (input: unknown, options: CompileOptions) => Handlebars.TemplateDelegate;
|
||||
export type HandlebarsPrecompile = (input: unknown, options: PrecompileOptions) => TemplateSpecification;
|
||||
|
||||
export interface HandlebarsImport {
|
||||
[index: string]: unknown;
|
||||
compile: HandlebarsCompile;
|
||||
precompile: HandlebarsPrecompile;
|
||||
}
|
||||
|
||||
export interface ConfigOptions {
|
||||
handlebars?: HandlebarsImport;
|
||||
extname?: string;
|
||||
encoding?: BufferEncoding;
|
||||
layoutsDir?: string;
|
||||
partialsDir?: string|string[]|PartialsDirObject|PartialsDirObject[];
|
||||
defaultLayout?: string|false;
|
||||
helpers?: UnknownObject;
|
||||
compilerOptions?: CompileOptions;
|
||||
runtimeOptions?: Handlebars.RuntimeOptions;
|
||||
}
|
||||
|
||||
export interface EngineOptions extends ConfigOptions {
|
||||
[index: string]: unknown;
|
||||
}
|
||||
|
||||
export interface RenderCallback {
|
||||
(err: Error|null, content?: string): void;
|
||||
}
|
||||
|
||||
export type Engine = (viewPath: string, options: ConfigOptions, callback?: RenderCallback) => Promise<string>
|
Reference in New Issue
Block a user