mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65b30e7464 | ||
|
|
5facd99a27 | ||
|
|
3f4f328572 | ||
|
|
a7c94eeeb5 | ||
|
|
2222a1be87 | ||
|
|
bf425c3adb | ||
|
|
c0bc2de76e | ||
|
|
4759371102 | ||
|
|
e03e053362 | ||
|
|
d8691421b4 | ||
|
|
0b4e2a9979 | ||
|
|
e401a30972 | ||
|
|
495bef2d0c | ||
|
|
fcb930f0dd | ||
|
|
b4e12232be | ||
|
|
3a67eb7f1c | ||
|
|
fc42438283 | ||
|
|
8acf405949 | ||
|
|
e9da7f39de | ||
|
|
87e83b63fc | ||
|
|
e347e603d7 | ||
|
|
0480d3317d | ||
|
|
82ba54845f | ||
|
|
05c478c322 | ||
|
|
87d4cc7e14 | ||
|
|
202556115f | ||
|
|
db67118a75 | ||
|
|
ba8b842452 | ||
|
|
dca9ab52b8 | ||
|
|
7ceff17fcb | ||
|
|
648b158dbd | ||
|
|
33b3c010af | ||
|
|
21ee27b575 |
+48
-1
@@ -567,8 +567,55 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "TomasHubelbauer",
|
||||
"name": "Tomáš Hübelbauer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6831144?v=4",
|
||||
"profile": "https://hubelbauer.net/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jgarber623",
|
||||
"name": "Jason Garber",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/73866?v=4",
|
||||
"profile": "https://sixtwothree.org",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Checkout-Blocks",
|
||||
"name": "Checkout Blocks",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/114603307?v=4",
|
||||
"profile": "https://www.checkoutblocks.com/",
|
||||
"contributions": [
|
||||
"financial"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "akdarrah",
|
||||
"name": "Adam Darrah",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/69064?v=4",
|
||||
"profile": "https://www.dropkiq.com/",
|
||||
"contributions": [
|
||||
"financial"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "11ty",
|
||||
"name": "Eleventy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/35147177?v=4",
|
||||
"profile": "https://www.11ty.dev/",
|
||||
"contributions": [
|
||||
"financial"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"skipCi": true
|
||||
"skipCi": true,
|
||||
"commitType": "docs"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Build
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
os:
|
||||
required: true
|
||||
type: string
|
||||
bundles:
|
||||
required: false
|
||||
type: string
|
||||
env:
|
||||
BUNDLES: ${{ inputs.bundles }}
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ${{ inputs.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Build
|
||||
run: npm run build
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dist-${{ inputs.os }}
|
||||
path: dist
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
@@ -1,36 +0,0 @@
|
||||
name: Check
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
- name: Test
|
||||
run: |
|
||||
npm run lint
|
||||
npm run test
|
||||
- name: Coverage
|
||||
uses: coverallsapp/[email protected]
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Performance
|
||||
run: |
|
||||
npm run perf:diff
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
@@ -0,0 +1,28 @@
|
||||
name: CI Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'test'
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
lint:
|
||||
uses: ./.github/workflows/lint.yml
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/test.yml
|
||||
coverage:
|
||||
uses: ./.github/workflows/coverage.yml
|
||||
performance:
|
||||
needs: build
|
||||
uses: ./.github/workflows/performance.yml
|
||||
with:
|
||||
os: ubuntu-latest
|
||||
docs:
|
||||
uses: ./.github/workflows/docs.yml
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Test Coverage
|
||||
on: [workflow_dispatch, workflow_call]
|
||||
jobs:
|
||||
coverage:
|
||||
name: Test Coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Test
|
||||
run: npm run test:coverage
|
||||
- name: Coverage
|
||||
uses: coverallsapp/[email protected]
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
@@ -1,32 +1,30 @@
|
||||
name: Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
on: [workflow_dispatch, workflow_call]
|
||||
jobs:
|
||||
docs:
|
||||
name: Docs
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
npm run build:docs
|
||||
- name: Publish
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: JamesIves/[email protected]
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: docs/public
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Lint
|
||||
on: [workflow_dispatch, workflow_call]
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Performance Check
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
os:
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
performance:
|
||||
name: Performance
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist-${{ inputs.os }}
|
||||
path: dist
|
||||
- name: Check Performance
|
||||
run: npm run perf:diff
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
@@ -0,0 +1,22 @@
|
||||
name: PR Build
|
||||
on: pull_request
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
lint:
|
||||
uses: ./.github/workflows/lint.yml
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/test.yml
|
||||
coverage:
|
||||
uses: ./.github/workflows/coverage.yml
|
||||
performance:
|
||||
needs: build
|
||||
uses: ./.github/workflows/performance.yml
|
||||
with:
|
||||
os: ubuntu-latest
|
||||
@@ -1,15 +1,12 @@
|
||||
name: "PR Title Checker"
|
||||
|
||||
name: PR Check
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR title
|
||||
title:
|
||||
name: Check PR title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
@@ -1,37 +1,48 @@
|
||||
name: Release
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
uses: ./.github/workflows/build.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/test.yml
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build, test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:dist
|
||||
- name: Test
|
||||
run: |
|
||||
npm run lint
|
||||
npm run test
|
||||
- name: Coverage
|
||||
uses: coverallsapp/[email protected]
|
||||
node-version: '18'
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: dist-ubuntu-latest
|
||||
path: dist
|
||||
- name: Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: npx semantic-release
|
||||
run: |
|
||||
if [ ${{ github.ref == 'refs/heads/master' }} ]; then
|
||||
npx semantic-release
|
||||
else
|
||||
npx semantic-release --dry-run
|
||||
fi
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Test
|
||||
on: [workflow_dispatch, workflow_call]
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
timezone: [Etc/GMT, Asia/Shanghai, America/New_York]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist-${{ matrix.os }}
|
||||
path: dist
|
||||
- name: Run Test
|
||||
run: TZ=${{ matrix.timezone }} npm test
|
||||
- name: Archive npm failure logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: npm-logs
|
||||
path: ~/.npm/_logs
|
||||
+3
-1
@@ -9,8 +9,10 @@ coverage/
|
||||
|
||||
# modules
|
||||
node_modules/
|
||||
|
||||
# tmp
|
||||
docs/public/js/liquid.browser.min.js
|
||||
dist/
|
||||
demo/*/package-lock.json
|
||||
demo/*/yarn.json
|
||||
|
||||
# editors
|
||||
|
||||
@@ -1,3 +1,55 @@
|
||||
## [10.8.4](https://github.com/harttle/liquidjs/compare/v10.8.3...v10.8.4) (2023-07-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow quotes in inline comment tag, fixes [#628](https://github.com/harttle/liquidjs/issues/628) ([bf425c3](https://github.com/harttle/liquidjs/commit/bf425c3adb929e68fa234bee8397560a436595bb))
|
||||
|
||||
## [10.8.3](https://github.com/harttle/liquidjs/compare/v10.8.2...v10.8.3) (2023-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* strftime getSuffix works for all dates ([0b4e2a9](https://github.com/harttle/liquidjs/commit/0b4e2a99790347bea0ab5f7d651f2330e3054601))
|
||||
|
||||
## [10.8.2](https://github.com/harttle/liquidjs/compare/v10.8.1...v10.8.2) (2023-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* sample filter randomness and count=1 case ([fcb930f](https://github.com/harttle/liquidjs/commit/fcb930f0ddf2489fa74cd323f24398d7e9f7717f))
|
||||
|
||||
## [10.8.1](https://github.com/harttle/liquidjs/compare/v10.8.0...v10.8.1) (2023-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* incorrect error message for browser UMD bundle ([3a67eb7](https://github.com/harttle/liquidjs/commit/3a67eb7f1cc7e54d2ec94a985eca4c1f147cdd61))
|
||||
|
||||
# [10.8.0](https://github.com/harttle/liquidjs/compare/v10.7.1...v10.8.0) (2023-06-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* proper error message for filter syntax error, [#610](https://github.com/harttle/liquidjs/issues/610) ([0480d33](https://github.com/harttle/liquidjs/commit/0480d3317d0e46519ad2adf4ac43f53cddf467c6))
|
||||
* sed invocations to work out of the box on macOS ([#615](https://github.com/harttle/liquidjs/issues/615)) ([87d4cc7](https://github.com/harttle/liquidjs/commit/87d4cc7e14ece14161285a740be63afc8a88b63c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add support for the Jekyll sample filter ([#612](https://github.com/harttle/liquidjs/issues/612)) ([ba8b842](https://github.com/harttle/liquidjs/commit/ba8b84245266589e43c0e70d99e12b981d349809))
|
||||
* Add support for the Jekyll push filter ([#611](https://github.com/harttle/liquidjs/issues/611))
|
||||
* introduce a matrix with latest Ubuntu and macOS to test the build on macOS as well ([82ba548](https://github.com/harttle/liquidjs/commit/82ba54845f4cd4e1e7660c1557e3cfaa22d68924)), closes [#615](https://github.com/harttle/liquidjs/issues/615)
|
||||
* precise line/col for tokenization Error, [#613](https://github.com/harttle/liquidjs/issues/613) ([e347e60](https://github.com/harttle/liquidjs/commit/e347e603d76c039cec191d417deab34e7ef1f9a7))
|
||||
|
||||
## [10.7.1](https://github.com/harttle/liquidjs/compare/v10.7.0...v10.7.1) (2023-04-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* incorrect timezone correction for DST dates, fixes [#604](https://github.com/harttle/liquidjs/issues/604) ([33b3c01](https://github.com/harttle/liquidjs/commit/33b3c010af0cd17a303621331feab0119ca840ce))
|
||||
* timezoneOffset ignored in date when preserveTimezones is enabled, fixes [#605](https://github.com/harttle/liquidjs/issues/605) ([21ee27b](https://github.com/harttle/liquidjs/commit/21ee27b57503f9d57f228973e1699972484e6089))
|
||||
|
||||
# [10.7.0](https://github.com/harttle/liquidjs/compare/v10.6.2...v10.7.0) (2023-03-21)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Contributing
|
||||
|
||||
1. Build everything and run tests to learn how to do both:
|
||||
- `npm run build`
|
||||
- `npm run test`
|
||||
|
||||
Tests won't at first unless you've done a build at least once.
|
||||
Subsequent changes to tests do not need re-builds but changes to the code and
|
||||
then tests need a build to pick up the new code by the tests.
|
||||
|
||||
2. Make your changes and add a test for them
|
||||
- Build after you've made your changes
|
||||
- Run tests as per the above to validate your changes
|
||||
|
||||
3. Create a pull request
|
||||
- Ensure the build runs because the Husky pre-commit hook checks it
|
||||
- `npm run check` checks runs the build, tests, lint and perf tests
|
||||
- `commitlint` checks the commit message format
|
||||
|
||||
If there is a problem you will see it in the pre-commit hook output.
|
||||
In VS Code, this output will be shown in a new file in a new tab if the
|
||||
pre-commit hook fails.
|
||||
If you want to check the commit message without using the VS Code Source
|
||||
Control UI, you can run `echo "feat: my commit message" > npx commitlint`
|
||||
directly.
|
||||
|
||||
- `git switch -c your_branch_name` (do this in your fork not the main repo)
|
||||
- `git add .`
|
||||
- `git commit -m "feat: Adding my change"`
|
||||
- `git push`
|
||||
- Go to GitHub and find your fork, open a PR against the upstream from it
|
||||
|
||||
## Playground
|
||||
|
||||
The Playground runs off the `docs` directory.
|
||||
`npm run build:docs` is used to build it.
|
||||
|
||||
Then, to start the site locally, go to `docs` and run `npm start`, then visit
|
||||
http://localhost:4000/playground.html.
|
||||
|
||||
The Playground uses a local built LiquidJS, which is created during `npm run build:docs`.
|
||||
To update that, you'll need to run `./bin/build-docs-liquid.sh` each time after making changes.
|
||||
Then refresh the Playground site for the changes to take effect.
|
||||
|
||||
## Performance
|
||||
|
||||
If your change can have a performance impact, you can update and run performance cases under `benchmark/`.
|
||||
|
||||
1. `npm run build:cjs` to build a CommonJS bundle for the perf test.
|
||||
2. `npm run perf:diff` to check whether there's a regression compared against `liquidjs@latest`
|
||||
|
||||
Further more, `benchmark/` contains different cases to check its ops/sec. Useful when debugging perf regressions, to use it:
|
||||
|
||||
- `cd benchmark` go into benchmark project
|
||||
- `npm ci` install dependencies
|
||||
- `npm start` run the cases
|
||||
@@ -11,7 +11,7 @@ A simple, expressive and safe [Shopify][shopify/liquid] / Github Pages compatibl
|
||||
|
||||
* [Documentation][doc]
|
||||
* Please star [LiquidJS on GitHub][github]!
|
||||
* Support [LiquidJS on Open Collective][oc] or [Patreon][patreon]
|
||||
* Financial support via [LiquidJS on Open Collective][oc], or [Github Sponsors](https://github.com/sponsors/harttle)
|
||||
|
||||
<p align="center"><a href="https://liquidjs.com"><img height="155px" width="155px" src="https://liquidjs.com/icon/mstile-310x310.png" alt="logo"></a></p>
|
||||
|
||||
@@ -50,19 +50,27 @@ npx liquidjs --template 'Hello, {{ name }}!' --context '{"name": "Snake"}'
|
||||
|
||||
For more details, refer to the [Setup Guide][setup].
|
||||
|
||||
## Related Projects
|
||||
## Who's Using LiquidJS?
|
||||
|
||||
* [@11ty/eleventy](https://www.npmjs.com/package/@11ty/eleventy): A simpler static site generator. An alternative to Jekyll. Written in JavaScript. Transforms a directory of templates (of varying types) into HTML.
|
||||
* [gulp-liquidjs](https://www.npmjs.com/package/@tuanpham-dev/gulp-liquidjs): A shopify compatible Liquid template engine for Gulp using liquidjs.
|
||||
* [grunt-liquify](https://www.npmjs.com/package/grunt-liquify): A Grunt task to process Liquid using liquidjs. Use it to add Liquid magic to your scripts and css assets.
|
||||
* [react-liquid](https://github.com/aquibm/react-liquid#readme): Liquid templating language component for React
|
||||
- [Eleventy](https://www.11ty.dev/): Eleventy, a simpler static site generator.
|
||||
- [Opensense](https://www.opensense.com/): The smarter way to send email.
|
||||
- [Directus](https://docs.directus.io/): an instant REST+GraphQL API and intuitive no-code data collaboration app for any SQL database.
|
||||
- [Semgrep](https://github.com/returntocorp/semgrep): Lightweight static analysis for many languages.
|
||||
- [Rock](https://www.rockrms.com/): An open source CMS, Relationship Management System (RMS) and Church Management System (ChMS) all rolled into one.
|
||||
- [Mitosis](https://github.com/BuilderIO/mitosis): Write components once, run everywhere. Compiles to React, Vue, Qwik, Solid, Angular, Svelte, and more.
|
||||
- [Pattern Lab](https://patternlab.io/): a frontend workshop environment that helps you build, view, test, and showcase your design system's UI components.
|
||||
- [Builder.io](https://www.builder.io/m/developers): the first and only headless CMS with a visual editor that lets you drag and drop with your components, directly within your current site or app. Completely API-driven, for cleaner code and simpler workflows.
|
||||
- [Microsoft Power Pages](https://learn.microsoft.com/en-us/power-pages/introduction): a secure, enterprise-grade, low-code software as a service (SaaS) platform for creating, hosting, and administering modern external-facing business websites.
|
||||
- [Azure API Management developer portal](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-developer-portal): an automatically generated, fully customizable website with the documentation of your APIs.
|
||||
|
||||
Feel free to create a PR or contact me to add your use case into this list!
|
||||
|
||||
## Financial Support
|
||||
|
||||
If you love LiquidJS or your company is using LiquidJS? Please consider [support us on Open Collective or Patreon][financial-support].
|
||||
If you love LiquidJS or your company is using LiquidJS, please consider [financial support][financial-support].
|
||||
|
||||
### Backers
|
||||
If you personally like LiquidJS and find it useful to you, you can buy me a coffee!
|
||||
If you personally like LiquidJS and find it useful to you, buy me a coffee!💖
|
||||
|
||||
<img src="https://opencollective.com/liquidjs/backers.svg?avatarHeight=72">
|
||||
|
||||
@@ -158,6 +166,13 @@ Want to contribute? see [Contribution Guidelines][contribution]. Thanks goes to
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bobgubko"><img src="https://avatars.githubusercontent.com/u/733312?v=4?s=100" width="100px;" alt="bobgubko"/><br /><sub><b>bobgubko</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=bobgubko" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bangank36"><img src="https://avatars.githubusercontent.com/u/10071857?v=4?s=100" width="100px;" alt="BaNgan"/><br /><sub><b>BaNgan</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=bangank36" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mahyar-pasarzangene"><img src="https://avatars.githubusercontent.com/u/16485039?v=4?s=100" width="100px;" alt="Mahyar Pasarzangene"/><br /><sub><b>Mahyar Pasarzangene</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=mahyar-pasarzangene" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://hubelbauer.net/"><img src="https://avatars.githubusercontent.com/u/6831144?v=4?s=100" width="100px;" alt="Tomáš Hübelbauer"/><br /><sub><b>Tomáš Hübelbauer</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=TomasHubelbauer" title="Code">💻</a> <a href="https://github.com/harttle/liquidjs/commits?author=TomasHubelbauer" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://sixtwothree.org"><img src="https://avatars.githubusercontent.com/u/73866?v=4?s=100" width="100px;" alt="Jason Garber"/><br /><sub><b>Jason Garber</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=jgarber623" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.checkoutblocks.com/"><img src="https://avatars.githubusercontent.com/u/114603307?v=4?s=100" width="100px;" alt="Checkout Blocks"/><br /><sub><b>Checkout Blocks</b></sub></a><br /><a href="#financial-Checkout-Blocks" title="Financial">💵</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.dropkiq.com/"><img src="https://avatars.githubusercontent.com/u/69064?v=4?s=100" width="100px;" alt="Adam Darrah"/><br /><sub><b>Adam Darrah</b></sub></a><br /><a href="#financial-akdarrah" title="Financial">💵</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.11ty.dev/"><img src="https://avatars.githubusercontent.com/u/35147177?v=4?s=100" width="100px;" alt="Eleventy"/><br /><sub><b>Eleventy</b></sub></a><br /><a href="#financial-11ty" title="Financial">💵</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -172,7 +187,6 @@ Want to contribute? see [Contribution Guidelines][contribution]. Thanks goes to
|
||||
[setup]: https://liquidjs.com/tutorials/setup.html
|
||||
[doc]: https://liquidjs.com
|
||||
[github]: https://github.com/harttle/liquidjs
|
||||
[patreon]: https://www.patreon.com/harttle
|
||||
[oc]: https://opencollective.com/liquidjs/
|
||||
[contribution]: https://liquidjs.com/tutorials/contribution-guidelines.html
|
||||
[financial-support]: https://liquidjs.com/tutorials/contribution-guidelines.html#Financial-Support
|
||||
|
||||
+14
-3
@@ -1,8 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Run `sed` in a way that's compatible with both macOS (BSD) and Linux (GNU)
|
||||
sedi() {
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "$@"
|
||||
else
|
||||
sed -i "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
cd docs
|
||||
cp ../CHANGELOG.md source/tutorials/changelog.md
|
||||
sed -i \
|
||||
sedi \
|
||||
-e 's/{%/{% raw %}{%{% endraw %}/g' \
|
||||
-e 's/{{/{% raw %}{{{% endraw %}/g' \
|
||||
-e '1 s/"/\"/g' \
|
||||
@@ -11,5 +20,7 @@ sed -i \
|
||||
source/tutorials/changelog.md
|
||||
cp source/tutorials/changelog.md source/zh-cn/tutorials/changelog.md
|
||||
|
||||
sed -i '1i ---\ntitle: Changelog\nauto: true\n---\n' source/tutorials/changelog.md
|
||||
sed -i '1i ---\ntitle: 更新日志\nauto: true\n---\n' source/zh-cn/tutorials/changelog.md
|
||||
sedi -e '1i\
|
||||
---\ntitle: Changelog\nauto: true\n---\n' source/tutorials/changelog.md
|
||||
sedi -e '1i\
|
||||
---\ntitle: 更新日志\nauto: true\n---\n' source/zh-cn/tutorials/changelog.md
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Run `sed` in a way that's compatible with both macOS (BSD) and Linux (GNU)
|
||||
sedi() {
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' "$@"
|
||||
else
|
||||
sed -i "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
cp .all-contributorsrc docs/.all-contributorsrc
|
||||
sed -i \
|
||||
-e 's/README.md/docs\/themes\/navy\/layout\/partial\/all-contributors.swig/g' \
|
||||
-e 's/"contributorsPerLine": 7/"contributorsPerLine": 65535/g' \
|
||||
docs/.all-contributorsrc
|
||||
sedi \
|
||||
-e 's/README.md/docs\/themes\/navy\/layout\/partial\/all-contributors.swig/g' \
|
||||
-e 's/"contributorsPerLine": 7/"contributorsPerLine": 65535/g' \
|
||||
docs/.all-contributorsrc
|
||||
|
||||
all-contributors --config docs/.all-contributorsrc generate
|
||||
sed -i 's/<br \/>.*<\/td>/<\/a><\/td>/g' docs/themes/navy/layout/partial/all-contributors.swig
|
||||
sedi 's/<br \/>.*<\/td>/<\/a><\/td>/g' docs/themes/navy/layout/partial/all-contributors.swig
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUNDLES=min npm run build
|
||||
mkdir -p docs/public/js/
|
||||
cp dist/liquid.browser.min.js docs/public/js/
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
set -ex
|
||||
|
||||
./bin/build-docs-liquid.sh
|
||||
./bin/build-contributors.sh
|
||||
./bin/build-apidoc.sh
|
||||
./bin/build-changelog.sh
|
||||
|
||||
@@ -9,8 +9,4 @@ if [ ! -f $FILE_LATEST ]; then
|
||||
curl $URL_LATEST > $FILE_LATEST
|
||||
fi
|
||||
|
||||
# if [ ! -f $FILE_LOCAL ]; then
|
||||
BUNDLES=cjs npm run build:dist
|
||||
# fi
|
||||
|
||||
exec node benchmark/diff.js $FILE_LOCAL $FILE_LATEST
|
||||
|
||||
Generated
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "liquidjs-demo-nodejs",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"hello-liquid": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hello-liquid/-/hello-liquid-1.0.0.tgz",
|
||||
"integrity": "sha512-WNmZp5s647BN2WHPq4FHVH85CcqNVet5DXIVw1UtVMaV+MJHFA+ylge0hqHSw0iOI/Ojrx8KEKZurYZix5PekQ=="
|
||||
},
|
||||
"liquidjs": {
|
||||
"version": "9.42.0",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.42.0.tgz",
|
||||
"integrity": "sha512-krvhwGFrMCMGhybGkxJIvlWVVnoCSpYCn7NhEN43+uvlg2vOkYWpq8be+L3NMlOfwe4ZrKQ7hCh1EmS4yhLKow=="
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "liquidjs-demo-nodejs",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"liquidjs": {
|
||||
"version": "9.32.1",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.32.1.tgz",
|
||||
"integrity": "sha512-U/ymmm4M3sNJszHlF0Gzneky17qk+vWmu3nFkWKdniQhqaZNk6eZQdbcKkFGFPN4I9ijrBRjDsLBLysu292j8w=="
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+16737
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"html-react-parser": "^0.4.7",
|
||||
"liquidjs": "^9.1.0",
|
||||
"liquidjs": "^10.8.3",
|
||||
"react": "^16.5.2",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-promise": "^2.0.3",
|
||||
|
||||
Generated
+82
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"name": "liquidjs-demo-typescript",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.18.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.34.tgz",
|
||||
"integrity": "sha512-hcU9AIQVHmPnmjRK+XUUYlILlr9pQrsqSrwov/JK1pnf3GTQowVBhx54FbvM0AU/VXGH4i3+vgXS5EguR7fysA==",
|
||||
"dev": true
|
||||
},
|
||||
"arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
||||
},
|
||||
"diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
|
||||
},
|
||||
"liquidjs": {
|
||||
"version": "10.8.3",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.8.3.tgz",
|
||||
"integrity": "sha512-LqHLYtH3vrkT3LyfOhPU0FJX5KPO4aB6SzGa4HRI29yz8pS0ZxqIe/fWtic8qiust1+qrHI92J67tdt92V4WOA==",
|
||||
"requires": {
|
||||
"commander": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "8.10.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
|
||||
"integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
|
||||
"requires": {
|
||||
"arg": "^4.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"source-map-support": "^0.5.17",
|
||||
"yn": "3.1.1"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.9.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
|
||||
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg=="
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
"start": "ts-node index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"liquidjs": "*",
|
||||
"liquidjs": "^10.8.3",
|
||||
"ts-node": "^8.10.2",
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
|
||||
Generated
+979
@@ -0,0 +1,979 @@
|
||||
{
|
||||
"name": "liquidjs-demo-nodejs",
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/gen-mapping": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
|
||||
"integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/set-array": "^1.0.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
}
|
||||
},
|
||||
"@jridgewell/resolve-uri": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
|
||||
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/set-array": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/source-map": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
|
||||
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/gen-mapping": "^0.3.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
}
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.14",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
||||
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/trace-mapping": {
|
||||
"version": "0.3.17",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
|
||||
"integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/resolve-uri": "3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "8.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz",
|
||||
"integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint-scope": {
|
||||
"version": "3.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
|
||||
"integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint": "*",
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "0.0.51",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
|
||||
"integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
|
||||
"integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
|
||||
"integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/helper-numbers": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/floating-point-hex-parser": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
|
||||
"integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/helper-api-error": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
|
||||
"integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/helper-buffer": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
|
||||
"integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/helper-numbers": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
|
||||
"integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.11.1",
|
||||
"@webassemblyjs/helper-api-error": "1.11.1",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/helper-wasm-bytecode": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
|
||||
"integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/helper-wasm-section": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
|
||||
"integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/helper-buffer": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
|
||||
"@webassemblyjs/wasm-gen": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/ieee754": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
|
||||
"integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@xtuc/ieee754": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/leb128": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
|
||||
"integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/utf8": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
|
||||
"integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@webassemblyjs/wasm-edit": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
|
||||
"integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/helper-buffer": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-section": "1.11.1",
|
||||
"@webassemblyjs/wasm-gen": "1.11.1",
|
||||
"@webassemblyjs/wasm-opt": "1.11.1",
|
||||
"@webassemblyjs/wasm-parser": "1.11.1",
|
||||
"@webassemblyjs/wast-printer": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/wasm-gen": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
|
||||
"integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
|
||||
"@webassemblyjs/ieee754": "1.11.1",
|
||||
"@webassemblyjs/leb128": "1.11.1",
|
||||
"@webassemblyjs/utf8": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/wasm-opt": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
|
||||
"integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/helper-buffer": "1.11.1",
|
||||
"@webassemblyjs/wasm-gen": "1.11.1",
|
||||
"@webassemblyjs/wasm-parser": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/wasm-parser": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
|
||||
"integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/helper-api-error": "1.11.1",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.1",
|
||||
"@webassemblyjs/ieee754": "1.11.1",
|
||||
"@webassemblyjs/leb128": "1.11.1",
|
||||
"@webassemblyjs/utf8": "1.11.1"
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/wast-printer": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
|
||||
"integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"@webpack-cli/configtest": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
|
||||
"integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
|
||||
"dev": true
|
||||
},
|
||||
"@webpack-cli/info": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
|
||||
"integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"envinfo": "^7.7.3"
|
||||
}
|
||||
},
|
||||
"@webpack-cli/serve": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
|
||||
"integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
|
||||
"dev": true
|
||||
},
|
||||
"@xtuc/long": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
|
||||
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-import-assertions": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
|
||||
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
"node-releases": "^2.0.6",
|
||||
"update-browserslist-db": "^1.0.9"
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001423",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz",
|
||||
"integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==",
|
||||
"dev": true
|
||||
},
|
||||
"chrome-trace-event": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||
"dev": true
|
||||
},
|
||||
"clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
|
||||
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-plain-object": "^2.0.4",
|
||||
"kind-of": "^6.0.2",
|
||||
"shallow-clone": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"colorette": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
|
||||
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.284",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
|
||||
"integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"envinfo": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
|
||||
"integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
|
||||
"dev": true
|
||||
},
|
||||
"es-module-lexer": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
|
||||
"integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
|
||||
"dev": true
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"esrecurse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true
|
||||
},
|
||||
"events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
|
||||
"integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"dev": true
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"hello-liquid": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hello-liquid/-/hello-liquid-1.0.0.tgz",
|
||||
"integrity": "sha512-WNmZp5s647BN2WHPq4FHVH85CcqNVet5DXIVw1UtVMaV+MJHFA+ylge0hqHSw0iOI/Ojrx8KEKZurYZix5PekQ=="
|
||||
},
|
||||
"import-local": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
|
||||
"integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pkg-dir": "^4.2.0",
|
||||
"resolve-cwd": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"interpret": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
|
||||
"integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
|
||||
"dev": true
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
|
||||
"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
},
|
||||
"isobject": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
|
||||
"dev": true
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||
"dev": true
|
||||
},
|
||||
"liquidjs": {
|
||||
"version": "9.42.0",
|
||||
"resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-9.42.0.tgz",
|
||||
"integrity": "sha512-krvhwGFrMCMGhybGkxJIvlWVVnoCSpYCn7NhEN43+uvlg2vOkYWpq8be+L3NMlOfwe4ZrKQ7hCh1EmS4yhLKow=="
|
||||
},
|
||||
"loader-runner": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
||||
"dev": true
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
|
||||
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
||||
"integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.9.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"resolve-cwd": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
|
||||
"integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve-from": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
|
||||
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
|
||||
"dev": true
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
|
||||
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"shallow-clone": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
|
||||
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"kind-of": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true
|
||||
},
|
||||
"tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.15.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
|
||||
"integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "5.3.6",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz",
|
||||
"integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/trace-mapping": "^0.3.14",
|
||||
"jest-worker": "^27.4.5",
|
||||
"schema-utils": "^3.1.1",
|
||||
"serialize-javascript": "^6.0.0",
|
||||
"terser": "^5.14.1"
|
||||
}
|
||||
},
|
||||
"update-browserslist-db": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escalade": "^3.1.1",
|
||||
"picocolors": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.74.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
|
||||
"integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^0.0.51",
|
||||
"@webassemblyjs/ast": "1.11.1",
|
||||
"@webassemblyjs/wasm-edit": "1.11.1",
|
||||
"@webassemblyjs/wasm-parser": "1.11.1",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.7.6",
|
||||
"browserslist": "^4.14.5",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.10.0",
|
||||
"es-module-lexer": "^0.9.0",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"json-parse-even-better-errors": "^2.3.1",
|
||||
"loader-runner": "^4.2.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"neo-async": "^2.6.2",
|
||||
"schema-utils": "^3.1.0",
|
||||
"tapable": "^2.1.1",
|
||||
"terser-webpack-plugin": "^5.1.3",
|
||||
"watchpack": "^2.4.0",
|
||||
"webpack-sources": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"webpack-cli": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
|
||||
"integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@discoveryjs/json-ext": "^0.5.0",
|
||||
"@webpack-cli/configtest": "^1.2.0",
|
||||
"@webpack-cli/info": "^1.5.0",
|
||||
"@webpack-cli/serve": "^1.7.0",
|
||||
"colorette": "^2.0.14",
|
||||
"commander": "^7.0.0",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"fastest-levenshtein": "^1.0.12",
|
||||
"import-local": "^3.0.2",
|
||||
"interpret": "^2.2.0",
|
||||
"rechoir": "^0.7.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webpack-merge": {
|
||||
"version": "5.8.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
|
||||
"integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clone-deep": "^4.0.1",
|
||||
"wildcard": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||
"dev": true
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wildcard": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
|
||||
"integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,5 +34,4 @@ algolia:
|
||||
indexName: liquidjs
|
||||
twitter: harttleharttle
|
||||
github: harttle/liquidjs
|
||||
patreon: harttle
|
||||
oc: liquidjs
|
||||
|
||||
@@ -8,17 +8,11 @@ Starring LiquidJS is the most important and easiest way to support us: boost its
|
||||
|
||||
## Show Me Your Code
|
||||
|
||||
**Code Style**: LiquidJS applies [standard](https://github.com/standard/eslint-config-standard) and [@typescript-eslint/recommended](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json) rules, make sure it's still valid before commit:
|
||||
Getting started and building is described in [CONTRIBUTING.md](https://github.com/harttle/liquidjs/blob/master/CONTRIBUTING.md).
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
**Code Style**: LiquidJS applies [standard](https://github.com/standard/eslint-config-standard) and [@typescript-eslint/recommended](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json) rules.
|
||||
|
||||
**Testing**: Make sure test cases pass with your patch merged:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
**Testing**: Make sure test cases pass with your patch merged by running `npm test`
|
||||
|
||||
**Commit Message**: Please align to [the Angular Commit Message Guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits), especially note the [type identifier](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type), on which semantic-release bot depends.
|
||||
|
||||
@@ -26,7 +20,7 @@ npm test
|
||||
|
||||
## Financial Support
|
||||
|
||||
LiquidJS is Open Source and Free. To help it live and thrive, please consider contribute on [Open Collective][oc] or [Patreon][pt]. To acknowledge your contribution, your name and avatar will be listed here, on LiquidJS [homepage](https://liquidjs.com/) and on [Github README][liquidjs]. Please provide your Github ID by openning an issue or contacting me through Twitter (harttleharttle), I can help add you into [the contributors table](https://github.com/harttle/liquidjs#contributors-).
|
||||
LiquidJS is Open Source and Free. To help it live and thrive, you can contribute on [Open Collective][oc] or [Github Sponsors](https://github.com/sponsors/harttle). Please find me via Twitter (harttleharttle) or email (harttleharttle at gmail), to add you into [the contributors table](https://github.com/harttle/liquidjs#contributors-).
|
||||
|
||||
### Backers
|
||||
If you personally like LiquidJS and find it's useful to you, you can become a backer!
|
||||
@@ -38,8 +32,7 @@ If LiquidJS is benefiting your business/company, please sponsor us to make it be
|
||||
|
||||
<object type="image/svg+xml" data="https://opencollective.com/liquidjs/sponsors.svg?avatarHeight=72"></object>
|
||||
|
||||
[oc]: https://opencollective.com/liquidjs/contribute/backer-ii-10666/checkout
|
||||
[pt]: https://www.patreon.com/harttle
|
||||
[oc]: https://opencollective.com/liquidjs/contribute/backer-10665/checkout
|
||||
[shopify/liquid]: https://shopify.github.io/liquid/
|
||||
[caniuse-promises]: http://caniuse.com/#feat=promises
|
||||
[pp]: https://github.com/taylorhakes/promise-polyfill
|
||||
|
||||
@@ -8,17 +8,11 @@ Star 是支持 LiquidJS 最重要的方式,也是最简单的方式:通过
|
||||
|
||||
## 发起 Pull Request
|
||||
|
||||
**代码风格**:LiquidJS 采用 [standard](https://github.com/standard/eslint-config-standard) 和 [@typescript-eslint/recommended](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json) 规则,提交前确保可以通过风格检查:
|
||||
开发和构建描述在这篇文档里 [CONTRIBUTING.md](https://github.com/harttle/liquidjs/blob/master/CONTRIBUTING.md)。
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
**代码风格**:LiquidJS 采用 [standard](https://github.com/standard/eslint-config-standard) 和 [@typescript-eslint/recommended](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.json) 规则。
|
||||
|
||||
**测试**:确保你改动之后测试仍然可以通过:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
**测试**:确保你改动之后测试仍然可以通过 `npm test`
|
||||
|
||||
**提交消息**:请遵守 [Angular 提交消息规范](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits),尤其注意 [type 标识](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type),semantic-release 机器人依赖这个标识自动发布。
|
||||
|
||||
@@ -26,7 +20,7 @@ npm test
|
||||
|
||||
## 资金支持
|
||||
|
||||
LiquidJS 是开源和免费的,但支持 [Open Collective][oc] 或 [Patreon][pt] 赞助,作为感谢你的名字和头像(或 Logo)会展示在这里,[LiquidJS 首页](https://liquidjs.com/)和 [Github README][liquidjs]。
|
||||
LiquidJS 是开源和免费的,但支持 [Open Collective][oc] 和 [Github Sponsors](https://github.com/sponsors/harttle) 赞助,请通过 Twitter (harttleharttle) 或邮件 (harttleharttle at gmail) 联系我,把您加到 [贡献者列表](https://github.com/harttle/liquidjs#contributors-) 中。
|
||||
|
||||
### 支持者
|
||||
如果你喜欢 LiquidJS,希望支持我们,你可以成为 Open Collective Backer!
|
||||
@@ -39,7 +33,6 @@ LiquidJS 是开源和免费的,但支持 [Open Collective][oc] 或 [Patreon][p
|
||||
<object type="image/svg+xml" data="https://opencollective.com/liquidjs/sponsors.svg?avatarHeight=72"></object>
|
||||
|
||||
[oc]: https://opencollective.com/liquidjs/
|
||||
[pt]: https://www.patreon.com/harttle
|
||||
[shopify/liquid]: https://shopify.github.io/liquid/
|
||||
[caniuse-promises]: http://caniuse.com/#feat=promises
|
||||
[pp]: https://github.com/taylorhakes/promise-polyfill
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{% if page.layout === 'playground' %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.8/src-min/ace.js"></script>
|
||||
{{ js('js/liquid.browser.min.js') }}
|
||||
<script src="https://cdn.jsdelivr.net/npm/ace-builds@1.22.0/src-min/ace.js"></script>
|
||||
{% endif %}
|
||||
|
||||
{{ js('js/main') }}
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
<td align="center" valign="top" width="0%"><a href="http://slavv.com/"><img src="https://avatars.githubusercontent.com/u/713329?v=4?s=100" width="100px;" alt="Slav Ivanov"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="http://www.orgflow.io/"><img src="https://avatars.githubusercontent.com/u/3889090?v=4?s=100" width="100px;" alt="Daniel Rosenberg"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="https://github.com/bobgubko"><img src="https://avatars.githubusercontent.com/u/733312?v=4?s=100" width="100px;" alt="bobgubko"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="https://github.com/bangank36"><img src="https://avatars.githubusercontent.com/u/10071857?v=4?s=100" width="100px;" alt="BaNgan"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="https://github.com/mahyar-pasarzangene"><img src="https://avatars.githubusercontent.com/u/16485039?v=4?s=100" width="100px;" alt="Mahyar Pasarzangene"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="https://hubelbauer.net/"><img src="https://avatars.githubusercontent.com/u/6831144?v=4?s=100" width="100px;" alt="Tomáš Hübelbauer"/></a></td>
|
||||
<td align="center" valign="top" width="0%"><a href="https://sixtwothree.org"><img src="https://avatars.githubusercontent.com/u/73866?v=4?s=100" width="100px;" alt="Jason Garber"/></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
-1
@@ -6,7 +6,6 @@
|
||||
</div>
|
||||
<div id="footer-links">
|
||||
<a href="https://twitter.com/{{ config.twitter }}" class="footer-link" target="_blank"><i class="icon-twitter"></i></a>
|
||||
<a href="https://www.patreon.com/{{ config.patreon }}" class="footer-link" target="_blank"><i class="icon-patreon"></i></a>
|
||||
<a href="https://opencollective.com/{{ config.oc }}" class="footer-link" target="_blank"><i class="icon-opencollective"></i></a>
|
||||
<a href="https://github.com/{{ config.github }}" class="footer-link" target="_blank"><i class="icon-github"></i></a>
|
||||
</div>
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
color: #fff
|
||||
.icon-twitter:hover
|
||||
color: #1da1f2
|
||||
.icon-patreon:hover
|
||||
color: #f96854
|
||||
.icon-opencollective:hover
|
||||
color: #3384ff
|
||||
|
||||
|
||||
@@ -34,9 +34,6 @@ i {
|
||||
.icon-opencollective:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-patreon:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-search:before {
|
||||
content: "\f002";
|
||||
}
|
||||
|
||||
-1
@@ -11,7 +11,6 @@
|
||||
<glyph unicode="" glyph-name="chat-bubble-dots" d="M512 182.857l-204.8-204.8v204.8h-204.8c-56.554 0-102.4 45.846-102.4 102.4v0 512c0 56.32 46.080 102.4 102.4 102.4h819.2c56.554 0 102.4-45.846 102.4-102.4v0-512c0-56.554-45.846-102.4-102.4-102.4v0h-409.6zM256 592.457v-102.4h102.4v102.4h-102.4zM460.8 592.457v-102.4h102.4v102.4h-102.4zM665.6 592.457v-102.4h102.4v102.4h-102.4z" />
|
||||
<glyph unicode="" glyph-name="network" d="M512-73.143c-282.77 0-512 229.23-512 512s229.23 512 512 512v0c282.77 0 512-229.23 512-512s-229.23-512-512-512v0zM908.8 336.457c8.251 30.73 12.99 66.012 12.99 102.4s-4.739 71.67-13.634 105.261l0.644-2.861h-195.584c2.267-30.637 3.559-66.368 3.559-102.4s-1.292-71.763-3.832-107.148l0.273 4.748h195.584zM866.816 234.057h-164.864c-9.503-67.086-26.518-127.646-50.456-184.579l1.816 4.867c91.262 34.305 165.167 97.283 212.455 177.781l1.049 1.931zM413.696 336.457h196.608c2.654 30.668 4.168 66.357 4.168 102.4s-1.513 71.734-4.48 107.010l0.312-4.61h-196.608c-2.654-30.668-4.168-66.357-4.168-102.4s1.513-71.734 4.48-107.010l-0.312 4.61zM426.496 234.057c20.992-122.88 57.856-204.8 85.504-204.8s64.512 81.92 85.504 204.8h-171.008zM115.2 336.457h195.584c-2.267 30.637-3.559 66.368-3.559 102.4s1.292 71.763 3.832 107.148l-0.273-4.748h-195.584c-8.251-30.73-12.99-66.012-12.99-102.4s4.739-71.67 13.634-105.261l-0.644 2.861zM157.184 234.057c48.337-82.429 122.242-145.407 210.673-178.775l2.831-0.937c-21.504 49.152-37.888 110.592-48.64 179.712h-164.864zM866.816 643.657c-48.337 82.429-122.242 145.407-210.673 178.775l-2.831 0.937c21.504-49.152 37.888-110.592 48.64-179.712h164.864zM426.496 643.657h171.008c-20.992 122.88-57.856 204.8-85.504 204.8s-64.512-81.92-85.504-204.8zM157.184 643.657h164.864c10.24 69.12 27.136 130.56 48.64 179.712-91.262-34.305-165.167-97.283-212.455-177.781l-1.049-1.931z" />
|
||||
<glyph unicode="" glyph-name="opencollective" d="M932.693 730.27c57.298-81.265 91.58-182.336 91.58-291.413s-34.281-210.149-92.657-293.026l1.077 1.613-132.267 132.267c25.95 45.863 41.242 100.719 41.242 159.147s-15.292 113.284-42.092 160.785l0.85-1.638zM803.413 859.55l-132.267-132.267c-45.751 25.644-100.402 40.747-158.58 40.747-181.68 0-328.96-147.28-328.96-328.96s147.28-328.96 328.96-328.96c58.179 0 112.83 15.103 160.247 41.602l-1.666-0.855 132.267-132.693c-81.392-57.006-182.473-91.093-291.516-91.093-282.77 0-512 229.23-512 512s229.23 512 512 512c109.043 0 210.124-34.088 293.168-92.188l-1.652 1.095zM932.693 730.27c57.298-81.265 91.58-182.336 91.58-291.413s-34.281-210.149-92.657-293.026l1.077 1.613-132.267 132.267c25.95 45.863 41.242 100.719 41.242 159.147s-15.292 113.284-42.092 160.785l0.85-1.638z" />
|
||||
<glyph unicode="" glyph-name="patreon" d="M656.469 928.5c-203.264 0-368.64-165.376-368.64-368.64 0-202.667 165.376-367.488 368.64-367.488 202.667 0 367.531 164.864 367.531 367.488 0 203.264-164.864 368.64-367.531 368.64zM0.128-53.388h180.053v981.888h-180.053z" />
|
||||
<glyph unicode="" glyph-name="shopify" d="M654.379-72.247l307.883 66.603c0 0-111.104 751.488-112 756.48-0.768 4.949-4.864 8.192-9.003 8.192s-82.304 5.803-82.304 5.803-54.4 54.357-61.397 60.203c-1.92 1.579-3.2 2.432-5.163 3.157l-38.997-900.437zM499.627 468.51c0 0-34.56 18.091-75.691 18.091-61.739 0-64.171-38.656-64.171-48.683 0-52.565 138.24-73.173 138.24-197.504 0-97.92-61.44-160.427-145.323-160.427-100.437 0-151.040 62.507-151.040 62.507l27.563 89.003c0 0 53.12-45.483 97.28-45.483 28.8 0 41.6 23.253 41.6 39.765 0 69.077-113.237 72.277-113.237 185.984-1.451 95.445 67.029 188.416 205.952 188.416 53.632 0 80-15.403 80-15.403l-40.32-115.84zM476.587 915.444c5.803 0 11.563-1.621 17.28-5.76-41.984-19.84-88.064-69.931-107.008-170.325-27.989-9.088-55.168-17.28-80.597-24.661 22.144 76.16 75.648 200.32 170.325 200.32zM529.28 789.62v-5.76c-32.171-9.899-67.541-20.651-102.144-31.403 19.883 75.819 56.875 112.853 88.96 126.763 8.235-21.376 13.184-50.176 13.184-89.6zM552.277 884.937c29.611-3.157 48.683-36.992 60.971-74.88-14.891-4.864-31.36-9.856-49.408-15.616v10.752c0 32.085-4.096 58.496-11.563 79.829zM679.936 829.94c-0.853 0-2.56-0.896-3.328-0.896s-12.331-3.2-30.464-8.96c-18.048 52.608-50.176 101.12-107.008 101.12h-4.907c-16.469 20.736-36.352 29.653-53.589 29.653-132.523 0-195.84-165.419-215.68-249.429-50.944-15.573-88.021-27.136-92.16-28.757-28.8-9.088-29.611-9.899-32.939-37.12-3.2-19.712-78.080-600.021-78.080-600.021l578.603-108.672z" />
|
||||
<glyph unicode="" glyph-name="rocket" d="M704 886.857l-320-320h-192l-192-256c0 0 203.416 56.652 322.066 30.084l-322.066-414.084 421.902 328.144c58.838-134.654-37.902-328.144-37.902-328.144l256 192v192l320 320 64 320-320-64z" />
|
||||
<glyph unicode="" glyph-name="search" horiz-adv-x="951" d="M658.286 475.428c0 141.143-114.857 256-256 256s-256-114.857-256-256 114.857-256 256-256 256 114.857 256 256zM950.857 0c0-40-33.143-73.143-73.143-73.143-19.429 0-38.286 8-51.429 21.714l-196 195.429c-66.857-46.286-146.857-70.857-228-70.857-222.286 0-402.286 180-402.286 402.286s180 402.286 402.286 402.286 402.286-180 402.286-402.286c0-81.143-24.571-161.143-70.857-228l196-196c13.143-13.143 21.143-32 21.143-51.429z" />
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "liquidjs",
|
||||
"version": "10.7.0",
|
||||
"version": "10.8.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
+8
-7
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "liquidjs",
|
||||
"version": "10.7.0",
|
||||
"version": "10.8.4",
|
||||
"description": "A simple, expressive and safe Shopify / Github Pages compatible template engine in pure JavaScript.",
|
||||
"main": "dist/liquid.node.cjs.js",
|
||||
"module": "dist/liquid.node.esm.js",
|
||||
@@ -15,15 +15,16 @@
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"**/*.mjs\" \"**/*.ts\" .",
|
||||
"check": "npm run build && npm test && npm run lint && npm run perf:diff",
|
||||
"test": "jest --coverage",
|
||||
"check": "npm run build && npm run build:docs && npm test && npm run lint && npm run perf:diff",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --coverage src test/integration",
|
||||
"test:e2e": "jest test/e2e",
|
||||
"perf": "cd benchmark && npm ci && npm start",
|
||||
"perf:diff": "bin/perf-diff.sh",
|
||||
"perf:engines": "cd benchmark && npm run engines",
|
||||
"postversion": "npm run build:dist",
|
||||
"build": "npm run build:dist && npm run build:docs",
|
||||
"build:dist": "rollup -c rollup.config.mjs",
|
||||
"build": "rollup -c rollup.config.mjs",
|
||||
"build:cjs": "BUNDLES=cjs rollup -c rollup.config.mjs",
|
||||
"build:min": "BUNDLES=min rollup -c rollup.config.mjs",
|
||||
"build:umd": "BUNDLES=umd rollup -c rollup.config.mjs",
|
||||
"build:docs": "bin/build-docs.sh"
|
||||
},
|
||||
"bin": {
|
||||
|
||||
@@ -54,6 +54,10 @@ export function concat<T1, T2> (v: T1[], arg: T2[] = []): (T1 | T2)[] {
|
||||
return toArray(v).concat(arg)
|
||||
}
|
||||
|
||||
export function push<T> (v: T[], arg: T): T[] {
|
||||
return concat(v, [arg])
|
||||
}
|
||||
|
||||
export function slice<T> (v: T[] | string, begin: number, length = 1): T[] | string {
|
||||
v = toValue(v)
|
||||
if (isNil(v)) return []
|
||||
@@ -84,3 +88,12 @@ export function uniq<T> (arr: T[]): T[] {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
export function sample<T> (v: T[] | string, count = 1): T | string | (T | string)[] {
|
||||
v = toValue(v)
|
||||
if (isNil(v)) return []
|
||||
if (!isArray(v)) v = stringify(v)
|
||||
const shuffled = [...v].sort(() => Math.random() - 0.5)
|
||||
if (count === 1) return shuffled[0]
|
||||
return shuffled.slice(0, count)
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ export function date (this: FilterImpl, v: string | Date, format?: string, timez
|
||||
if (!isValidDate(date)) return v
|
||||
if (timezoneOffset !== undefined) {
|
||||
date = new TimezoneDate(date, parseTimezoneOffset(date, timezoneOffset))
|
||||
} else if (opts.timezoneOffset !== undefined) {
|
||||
} else if (!(date instanceof TimezoneDate) && opts.timezoneOffset !== undefined) {
|
||||
date = new TimezoneDate(date, parseTimezoneOffset(date, opts.timezoneOffset))
|
||||
}
|
||||
return strftime(date, format)
|
||||
|
||||
@@ -5,6 +5,7 @@ import { TopLevelToken, OutputToken } from '../tokens'
|
||||
import { Template, Output, HTML } from '../template'
|
||||
import { LiquidCache } from '../cache'
|
||||
import { FS, Loader, LookupType } from '../fs'
|
||||
import { LiquidError } from '../util/error'
|
||||
import type { Liquid } from '../liquid'
|
||||
|
||||
export class Parser {
|
||||
@@ -47,6 +48,7 @@ export class Parser {
|
||||
}
|
||||
return new HTML(token)
|
||||
} catch (e) {
|
||||
if (e instanceof LiquidError) throw e
|
||||
throw new ParseError(e as Error, token)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@ export enum TokenKind {
|
||||
Range = 512,
|
||||
Quoted = 1024,
|
||||
Operator = 2048,
|
||||
FilteredValue = 4096,
|
||||
Delimited = Tag | Output
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ describe('Tokenizer', function () {
|
||||
it('should throw when {% raw %} not closed', function () {
|
||||
const html = '{%raw%} {%endraw {%raw%}'
|
||||
const tokenizer = new Tokenizer(html)
|
||||
expect(() => tokenizer.readTopLevelTokens()).toThrow('raw "{%raw%} {%end..." not closed, line:1, col:8')
|
||||
expect(() => tokenizer.readTopLevelTokens()).toThrow('raw "{%raw%} {%endraw {%raw%}" not closed, line:1, col:8')
|
||||
})
|
||||
it('should read output token', function () {
|
||||
const html = '<p>{{foo | date: "%Y-%m-%d"}}</p>'
|
||||
@@ -191,7 +191,7 @@ describe('Tokenizer', function () {
|
||||
it('should throw if tag not closed', function () {
|
||||
const html = '{% assign foo = bar {{foo}}'
|
||||
const tokenizer = new Tokenizer(html)
|
||||
expect(() => tokenizer.readTopLevelTokens()).toThrow(/tag "{% assign foo..." not closed/)
|
||||
expect(() => tokenizer.readTopLevelTokens()).toThrow('tag "{% assign foo = bar {{foo}}" not closed, line:1, col:1')
|
||||
})
|
||||
it('should throw if output not closed', function () {
|
||||
const tokenizer = new Tokenizer('{{name}')
|
||||
@@ -199,15 +199,6 @@ describe('Tokenizer', function () {
|
||||
})
|
||||
})
|
||||
describe('#readTagToken()', () => {
|
||||
it('should skip quoted delimiters', function () {
|
||||
const html = '{% assign a = "%} {% }} {{" %}'
|
||||
const tokenizer = new Tokenizer(html)
|
||||
const token = tokenizer.readTagToken()
|
||||
|
||||
expect(token).toBeInstanceOf(TagToken)
|
||||
expect(token.name).toBe('assign')
|
||||
expect(token.args).toBe('a = "%} {% }} {{"')
|
||||
})
|
||||
})
|
||||
describe('#readOutputToken()', () => {
|
||||
it('should skip quoted delimiters', function () {
|
||||
|
||||
+51
-28
@@ -1,5 +1,5 @@
|
||||
import { TagToken, HTMLToken, HashToken, QuotedToken, LiquidTagToken, OutputToken, ValueToken, Token, RangeToken, FilterToken, TopLevelToken, PropertyAccessToken, OperatorToken, LiteralToken, IdentifierToken, NumberToken } from '../tokens'
|
||||
import { Trie, createTrie, ellipsis, literalValues, assert, TokenizationError, TYPES, QUOTE, BLANK, IDENTIFIER } from '../util'
|
||||
import { FilteredValueToken, TagToken, HTMLToken, HashToken, QuotedToken, LiquidTagToken, OutputToken, ValueToken, Token, RangeToken, FilterToken, TopLevelToken, PropertyAccessToken, OperatorToken, LiteralToken, IdentifierToken, NumberToken } from '../tokens'
|
||||
import { Trie, createTrie, ellipsis, literalValues, TokenizationError, TYPES, QUOTE, BLANK, IDENTIFIER } from '../util'
|
||||
import { Operators, Expression } from '../render'
|
||||
import { NormalizedFullOptions, defaultOptions } from '../liquid-options'
|
||||
import { FilterArg } from './filter-arg'
|
||||
@@ -7,7 +7,7 @@ import { matchOperator } from './match-operator'
|
||||
import { whiteSpaceCtrl } from './whitespace-ctrl'
|
||||
|
||||
export class Tokenizer {
|
||||
p = 0
|
||||
p: number
|
||||
N: number
|
||||
private rawBeginAt = -1
|
||||
private opTrie: Trie
|
||||
@@ -15,9 +15,11 @@ export class Tokenizer {
|
||||
constructor (
|
||||
public input: string,
|
||||
operators: Operators = defaultOptions.operators,
|
||||
public file?: string
|
||||
public file?: string,
|
||||
private range?: [number, number]
|
||||
) {
|
||||
this.N = input.length
|
||||
this.p = range ? range[0] : 0
|
||||
this.N = range ? range[1] : input.length
|
||||
this.opTrie = createTrie(operators)
|
||||
}
|
||||
|
||||
@@ -46,6 +48,13 @@ export class Tokenizer {
|
||||
if (end === -1) return
|
||||
return new OperatorToken(this.input, this.p, (this.p = end), this.file)
|
||||
}
|
||||
readFilteredValue (): FilteredValueToken {
|
||||
const begin = this.p
|
||||
const initial = this.readExpression()
|
||||
this.assert(initial.valid(), `invalid value expression: ${this.snapshot()}`)
|
||||
const filters = this.readFilters()
|
||||
return new FilteredValueToken(initial, filters, this.input, begin, this.p, this.file)
|
||||
}
|
||||
readFilters (): FilterToken[] {
|
||||
const filters = []
|
||||
while (true) {
|
||||
@@ -57,11 +66,14 @@ export class Tokenizer {
|
||||
readFilter (): FilterToken | null {
|
||||
this.skipBlank()
|
||||
if (this.end()) return null
|
||||
assert(this.peek() === '|', () => `unexpected token at ${this.snapshot()}`)
|
||||
this.assert(this.peek() === '|', `expected "|" before filter`)
|
||||
this.p++
|
||||
const begin = this.p
|
||||
const name = this.readIdentifier()
|
||||
if (!name.size()) return null
|
||||
if (!name.size()) {
|
||||
this.assert(this.end(), `expected filter name`)
|
||||
return null
|
||||
}
|
||||
const args = []
|
||||
this.skipBlank()
|
||||
if (this.peek() === ':') {
|
||||
@@ -70,8 +82,12 @@ export class Tokenizer {
|
||||
const arg = this.readFilterArg()
|
||||
arg && args.push(arg)
|
||||
this.skipBlank()
|
||||
assert(this.end() || this.peek() === ',' || this.peek() === '|', () => `unexpected character ${this.snapshot()}`)
|
||||
this.assert(this.end() || this.peek() === ',' || this.peek() === '|', () => `unexpected character ${this.snapshot()}`)
|
||||
} while (this.peek() === ',')
|
||||
} else if (this.peek() === '|' || this.end()) {
|
||||
// do nothing
|
||||
} else {
|
||||
throw this.error('expected ":" after filter name')
|
||||
}
|
||||
return new FilterToken(name.getText(), args, this.input, begin, this.p, this.file)
|
||||
}
|
||||
@@ -117,16 +133,17 @@ export class Tokenizer {
|
||||
const { file, input } = this
|
||||
const begin = this.p
|
||||
if (this.readToDelimiter(options.tagDelimiterRight) === -1) {
|
||||
throw this.mkError(`tag ${this.snapshot(begin)} not closed`, begin)
|
||||
throw this.error(`tag ${this.snapshot(begin)} not closed`, begin)
|
||||
}
|
||||
const token = new TagToken(input, begin, this.p, options, file)
|
||||
if (token.name === 'raw') this.rawBeginAt = begin
|
||||
return token
|
||||
}
|
||||
|
||||
readToDelimiter (delimiter: string) {
|
||||
readToDelimiter (delimiter: string, respectQuoted = false) {
|
||||
this.skipBlank()
|
||||
while (this.p < this.N) {
|
||||
if ((this.peekType() & QUOTE)) {
|
||||
if (respectQuoted && (this.peekType() & QUOTE)) {
|
||||
this.readQuoted()
|
||||
continue
|
||||
}
|
||||
@@ -140,8 +157,8 @@ export class Tokenizer {
|
||||
const { file, input } = this
|
||||
const { outputDelimiterRight } = options
|
||||
const begin = this.p
|
||||
if (this.readToDelimiter(outputDelimiterRight) === -1) {
|
||||
throw this.mkError(`output ${this.snapshot(begin)} not closed`, begin)
|
||||
if (this.readToDelimiter(outputDelimiterRight, true) === -1) {
|
||||
throw this.error(`output ${this.snapshot(begin)} not closed`, begin)
|
||||
}
|
||||
return new OutputToken(input, begin, this.p, options, file)
|
||||
}
|
||||
@@ -170,32 +187,38 @@ export class Tokenizer {
|
||||
this.p++
|
||||
}
|
||||
}
|
||||
throw this.mkError(`raw ${this.snapshot(this.rawBeginAt)} not closed`, begin)
|
||||
throw this.error(`raw ${this.snapshot(this.rawBeginAt)} not closed`, begin)
|
||||
}
|
||||
|
||||
readLiquidTagTokens (options: NormalizedFullOptions = defaultOptions): LiquidTagToken[] {
|
||||
const tokens: LiquidTagToken[] = []
|
||||
while (this.p < this.N) {
|
||||
const token = this.readLiquidTagToken(options)
|
||||
if (token.name) tokens.push(token)
|
||||
token && tokens.push(token)
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
readLiquidTagToken (options: NormalizedFullOptions): LiquidTagToken {
|
||||
const { file, input } = this
|
||||
readLiquidTagToken (options: NormalizedFullOptions): LiquidTagToken | undefined {
|
||||
this.skipBlank()
|
||||
if (this.end()) return
|
||||
|
||||
const begin = this.p
|
||||
let end = this.N
|
||||
if (this.readToDelimiter('\n') !== -1) end = this.p
|
||||
return new LiquidTagToken(input, begin, end, options, file)
|
||||
this.readToDelimiter('\n')
|
||||
const end = this.p
|
||||
return new LiquidTagToken(this.input, begin, end, options, this.file)
|
||||
}
|
||||
|
||||
mkError (msg: string, begin: number) {
|
||||
return new TokenizationError(msg, new IdentifierToken(this.input, begin, this.N, this.file))
|
||||
error (msg: string, pos: number = this.p) {
|
||||
return new TokenizationError(msg, new IdentifierToken(this.input, pos, this.N, this.file))
|
||||
}
|
||||
|
||||
assert (pred: unknown, msg: string | (() => string), pos?: number) {
|
||||
if (!pred) throw this.error(typeof msg === 'function' ? msg() : msg, pos)
|
||||
}
|
||||
|
||||
snapshot (begin: number = this.p) {
|
||||
return JSON.stringify(ellipsis(this.input.slice(begin), 16))
|
||||
return JSON.stringify(ellipsis(this.input.slice(begin, this.N), 32))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +231,7 @@ export class Tokenizer {
|
||||
readIdentifier (): IdentifierToken {
|
||||
this.skipBlank()
|
||||
const begin = this.p
|
||||
while (this.peekType() & IDENTIFIER) ++this.p
|
||||
while (!this.end() && this.peekType() & IDENTIFIER) ++this.p
|
||||
return new IdentifierToken(this.input, begin, this.p, this.file)
|
||||
}
|
||||
|
||||
@@ -246,7 +269,7 @@ export class Tokenizer {
|
||||
}
|
||||
|
||||
remaining () {
|
||||
return this.input.slice(this.p)
|
||||
return this.input.slice(this.p, this.N)
|
||||
}
|
||||
|
||||
advance (i = 1) {
|
||||
@@ -319,7 +342,7 @@ export class Tokenizer {
|
||||
|
||||
readValueOrThrow (): ValueToken {
|
||||
const value = this.readValue()
|
||||
assert(value, () => `unexpected token ${this.snapshot()}, value expected`)
|
||||
this.assert(value, () => `unexpected token ${this.snapshot()}, value expected`)
|
||||
return value!
|
||||
}
|
||||
|
||||
@@ -368,8 +391,8 @@ export class Tokenizer {
|
||||
return TYPES[this.input.charCodeAt(this.p + n)]
|
||||
}
|
||||
|
||||
peek (n = 0) {
|
||||
return this.input[this.p + n]
|
||||
peek (n = 0): string {
|
||||
return this.p + n >= this.N ? '' : this.input[this.p + n]
|
||||
}
|
||||
|
||||
skipBlank () {
|
||||
|
||||
@@ -30,6 +30,9 @@ export class Expression {
|
||||
}
|
||||
return operands[0]
|
||||
}
|
||||
public valid () {
|
||||
return !!this.postfix.length
|
||||
}
|
||||
}
|
||||
|
||||
export function * evalToken (token: Token | undefined, ctx: Context, lenient = false): IterableIterator<unknown> {
|
||||
|
||||
+9
-7
@@ -1,16 +1,18 @@
|
||||
import { Value, assert, Tokenizer, Liquid, TopLevelToken, TagToken, Context, Tag } from '..'
|
||||
import { Value, Liquid, TopLevelToken, TagToken, Context, Tag } from '..'
|
||||
export default class extends Tag {
|
||||
private key: string
|
||||
private value: Value
|
||||
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, liquid.options.operators)
|
||||
this.key = tokenizer.readIdentifier().content
|
||||
tokenizer.skipBlank()
|
||||
assert(tokenizer.peek() === '=', () => `illegal token ${token.getText()}`)
|
||||
tokenizer.advance()
|
||||
this.value = new Value(tokenizer.remaining(), this.liquid)
|
||||
this.key = this.tokenizer.readIdentifier().content
|
||||
this.tokenizer.assert(this.key, 'expected variable name')
|
||||
|
||||
this.tokenizer.skipBlank()
|
||||
this.tokenizer.assert(this.tokenizer.peek() === '=', 'expected "="')
|
||||
|
||||
this.tokenizer.advance()
|
||||
this.value = new Value(this.tokenizer.readFilteredValue(), this.liquid)
|
||||
}
|
||||
* render (ctx: Context): Generator<unknown, void, unknown> {
|
||||
ctx.bottom()[this.key] = yield this.value.value(ctx, this.liquid.options.lenientIf)
|
||||
|
||||
+9
-11
@@ -1,4 +1,4 @@
|
||||
import { Liquid, Tag, Tokenizer, assert, Template, Context, TagToken, TopLevelToken } from '..'
|
||||
import { Liquid, Tag, Template, Context, TagToken, TopLevelToken } from '..'
|
||||
import { evalQuotedToken } from '../render'
|
||||
import { isTagToken } from '../util'
|
||||
|
||||
@@ -7,9 +7,7 @@ export default class extends Tag {
|
||||
templates: Template[] = []
|
||||
constructor (tagToken: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(tagToken, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(tagToken.args, this.liquid.options.operators)
|
||||
this.variable = readVariableName(tokenizer)!
|
||||
assert(this.variable, () => `${tagToken.args} not valid identifier`)
|
||||
this.variable = this.readVariableName()
|
||||
|
||||
while (remainTokens.length) {
|
||||
const token = remainTokens.shift()!
|
||||
@@ -23,11 +21,11 @@ export default class extends Tag {
|
||||
const html = yield r.renderTemplates(this.templates, ctx)
|
||||
ctx.bottom()[this.variable] = html
|
||||
}
|
||||
}
|
||||
|
||||
function readVariableName (tokenizer: Tokenizer) {
|
||||
const word = tokenizer.readIdentifier().content
|
||||
if (word) return word
|
||||
const quoted = tokenizer.readQuoted()
|
||||
if (quoted) return evalQuotedToken(quoted)
|
||||
private readVariableName () {
|
||||
const word = this.tokenizer.readIdentifier().content
|
||||
if (word) return word
|
||||
const quoted = this.tokenizer.readQuoted()
|
||||
if (quoted) return evalQuotedToken(quoted)
|
||||
throw this.tokenizer.error('invalid capture name')
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
import { ValueToken, Liquid, Tokenizer, toValue, evalToken, Value, Emitter, TagToken, TopLevelToken, Context, Template, Tag, ParseStream } from '..'
|
||||
import { ValueToken, Liquid, toValue, evalToken, Value, Emitter, TagToken, TopLevelToken, Context, Template, Tag, ParseStream } from '..'
|
||||
|
||||
export default class extends Tag {
|
||||
value: Value
|
||||
@@ -6,7 +6,7 @@ export default class extends Tag {
|
||||
elseTemplates: Template[] = []
|
||||
constructor (tagToken: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(tagToken, remainTokens, liquid)
|
||||
this.value = new Value(tagToken.args, this.liquid)
|
||||
this.value = new Value(this.tokenizer.readFilteredValue(), this.liquid)
|
||||
this.elseTemplates = []
|
||||
|
||||
let p: Template[] = []
|
||||
@@ -14,11 +14,10 @@ export default class extends Tag {
|
||||
.on('tag:when', (token: TagToken) => {
|
||||
p = []
|
||||
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
const values: ValueToken[] = []
|
||||
while (!tokenizer.end()) {
|
||||
values.push(tokenizer.readValueOrThrow())
|
||||
tokenizer.readTo(',')
|
||||
while (!token.tokenizer.end()) {
|
||||
values.push(token.tokenizer.readValueOrThrow())
|
||||
token.tokenizer.readTo(',')
|
||||
}
|
||||
this.branches.push({
|
||||
values,
|
||||
|
||||
+11
-12
@@ -1,27 +1,26 @@
|
||||
import { Tokenizer, assert, TopLevelToken, Liquid, ValueToken, evalToken, Emitter, TagToken, Context, Tag } from '..'
|
||||
import { TopLevelToken, Liquid, ValueToken, evalToken, Emitter, TagToken, Context, Tag } from '..'
|
||||
|
||||
export default class extends Tag {
|
||||
private candidates: ValueToken[] = []
|
||||
private group?: ValueToken
|
||||
constructor (tagToken: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(tagToken, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(tagToken.args, this.liquid.options.operators)
|
||||
const group = tokenizer.readValue()
|
||||
tokenizer.skipBlank()
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const group = this.tokenizer.readValue()
|
||||
this.tokenizer.skipBlank()
|
||||
|
||||
if (group) {
|
||||
if (tokenizer.peek() === ':') {
|
||||
if (this.tokenizer.peek() === ':') {
|
||||
this.group = group
|
||||
tokenizer.advance()
|
||||
this.tokenizer.advance()
|
||||
} else this.candidates.push(group)
|
||||
}
|
||||
|
||||
while (!tokenizer.end()) {
|
||||
const value = tokenizer.readValue()
|
||||
while (!this.tokenizer.end()) {
|
||||
const value = this.tokenizer.readValue()
|
||||
if (value) this.candidates.push(value)
|
||||
tokenizer.readTo(',')
|
||||
this.tokenizer.readTo(',')
|
||||
}
|
||||
assert(this.candidates.length, () => `empty candidates: ${tagToken.getText()}`)
|
||||
this.tokenizer.assert(this.candidates.length, () => `empty candidates: "${token.getText()}"`)
|
||||
}
|
||||
|
||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Tag, Liquid, TopLevelToken, Tokenizer, Emitter, TagToken, Context } from '..'
|
||||
import { Tag, Liquid, TopLevelToken, Emitter, TagToken, Context } from '..'
|
||||
import { isNumber, stringify } from '../util'
|
||||
|
||||
export default class extends Tag {
|
||||
private variable: string
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
this.variable = tokenizer.readIdentifier().content
|
||||
this.variable = this.tokenizer.readIdentifier().content
|
||||
}
|
||||
render (context: Context, emitter: Emitter) {
|
||||
const scope = context.environments
|
||||
|
||||
+7
-2
@@ -1,12 +1,17 @@
|
||||
import { Liquid, TopLevelToken, Emitter, Value, TagToken, Context, Tag } from '..'
|
||||
|
||||
export default class extends Tag {
|
||||
private value: Value
|
||||
private value?: Value
|
||||
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
this.value = new Value(token.args, this.liquid)
|
||||
this.tokenizer.skipBlank()
|
||||
if (!this.tokenizer.end()) {
|
||||
this.value = new Value(this.tokenizer.readFilteredValue(), this.liquid)
|
||||
}
|
||||
}
|
||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
||||
if (!this.value) return
|
||||
const val = yield this.value.value(ctx, false)
|
||||
emitter.write(val)
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
import { Hash, ValueToken, Liquid, Tag, Tokenizer, evalToken, Emitter, TagToken, TopLevelToken, Context, Template, ParseStream } from '..'
|
||||
import { Hash, ValueToken, Liquid, Tag, evalToken, Emitter, TagToken, TopLevelToken, Context, Template, ParseStream } from '..'
|
||||
import { toEnumerable } from '../util/collection'
|
||||
import { ForloopDrop } from '../drop/forloop-drop'
|
||||
|
||||
@@ -15,17 +15,16 @@ export default class extends Tag {
|
||||
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
const variable = tokenizer.readIdentifier()
|
||||
const inStr = tokenizer.readIdentifier()
|
||||
const collection = tokenizer.readValue()
|
||||
const variable = this.tokenizer.readIdentifier()
|
||||
const inStr = this.tokenizer.readIdentifier()
|
||||
const collection = this.tokenizer.readValue()
|
||||
if (!variable.size() || inStr.content !== 'in' || !collection) {
|
||||
throw new Error(`illegal tag: ${token.getText()}`)
|
||||
}
|
||||
|
||||
this.variable = variable.content
|
||||
this.collection = collection
|
||||
this.hash = new Hash(tokenizer.remaining())
|
||||
this.hash = new Hash(this.tokenizer.remaining())
|
||||
this.templates = []
|
||||
this.elseTemplates = []
|
||||
|
||||
|
||||
+3
-4
@@ -1,4 +1,4 @@
|
||||
import { Template, ValueToken, TopLevelToken, Liquid, Tag, assert, Tokenizer, evalToken, Hash, Emitter, TagToken, Context } from '..'
|
||||
import { Template, ValueToken, TopLevelToken, Liquid, Tag, assert, evalToken, Hash, Emitter, TagToken, Context } from '..'
|
||||
import { BlockMode, Scope } from '../context'
|
||||
import { parseFilePath, renderFilePath } from './render'
|
||||
|
||||
@@ -7,8 +7,7 @@ export default class extends Tag {
|
||||
private hash: Hash
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const args = token.args
|
||||
const tokenizer = new Tokenizer(args, this.liquid.options.operators)
|
||||
const { tokenizer } = token
|
||||
this['file'] = parseFilePath(tokenizer, this.liquid)
|
||||
this['currentFile'] = token.file
|
||||
|
||||
@@ -27,7 +26,7 @@ export default class extends Tag {
|
||||
const { liquid, hash, withVar } = this
|
||||
const { renderer } = liquid
|
||||
const filepath = (yield renderFilePath(this['file'], ctx, liquid)) as string
|
||||
assert(filepath, () => `illegal filename "${filepath}"`)
|
||||
assert(filepath, () => `illegal file path "${filepath}"`)
|
||||
|
||||
const saved = ctx.saveRegister('blocks', 'blockMode')
|
||||
ctx.setRegister('blocks', {})
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { isNumber, stringify } from '../util'
|
||||
import { Tag, Liquid, TopLevelToken, Tokenizer, Emitter, TagToken, Context } from '..'
|
||||
import { Tag, Liquid, TopLevelToken, Emitter, TagToken, Context } from '..'
|
||||
|
||||
export default class extends Tag {
|
||||
private variable: string
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
this.variable = tokenizer.readIdentifier().content
|
||||
this.variable = this.tokenizer.readIdentifier().content
|
||||
}
|
||||
render (context: Context, emitter: Emitter) {
|
||||
const scope = context.environments
|
||||
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
import { Scope, Template, Liquid, Tag, assert, Tokenizer, Emitter, Hash, TagToken, TopLevelToken, Context } from '..'
|
||||
import { Scope, Template, Liquid, Tag, assert, Emitter, Hash, TagToken, TopLevelToken, Context } from '..'
|
||||
import { BlockMode } from '../context'
|
||||
import { parseFilePath, renderFilePath, ParsedFileName } from './render'
|
||||
import { BlankDrop } from '../drop'
|
||||
@@ -9,10 +9,9 @@ export default class extends Tag {
|
||||
file?: ParsedFileName
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
this.file = parseFilePath(tokenizer, this.liquid)
|
||||
this.file = parseFilePath(this.tokenizer, this.liquid)
|
||||
this['currentFile'] = token.file
|
||||
this.args = new Hash(tokenizer.remaining())
|
||||
this.args = new Hash(this.tokenizer.remaining())
|
||||
this.templates = this.liquid.parser.parseTokens(remainTokens)
|
||||
}
|
||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {
|
||||
@@ -24,7 +23,7 @@ export default class extends Tag {
|
||||
return
|
||||
}
|
||||
const filepath = (yield renderFilePath(this.file, ctx, liquid)) as string
|
||||
assert(filepath, () => `illegal filename "${filepath}"`)
|
||||
assert(filepath, () => `illegal file path "${filepath}"`)
|
||||
const templates = (yield liquid._parseLayoutFile(filepath, ctx.sync, this['currentFile'])) as Template[]
|
||||
|
||||
// render remaining contents and store rendered results
|
||||
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
import { Template, Tokenizer, Emitter, Liquid, TopLevelToken, TagToken, Context, Tag } from '..'
|
||||
import { Template, Emitter, Liquid, TopLevelToken, TagToken, Context, Tag } from '..'
|
||||
|
||||
export default class extends Tag {
|
||||
templates: Template[]
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(token.args, this.liquid.options.operators)
|
||||
const tokens = tokenizer.readLiquidTagTokens(this.liquid.options)
|
||||
const tokens = this.tokenizer.readLiquidTagTokens(this.liquid.options)
|
||||
this.templates = this.liquid.parser.parseTokens(tokens)
|
||||
}
|
||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
||||
|
||||
+4
-5
@@ -11,8 +11,7 @@ export default class extends Tag {
|
||||
private hash: Hash
|
||||
constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token, remainTokens, liquid)
|
||||
const args = token.args
|
||||
const tokenizer = new Tokenizer(args, this.liquid.options.operators)
|
||||
const tokenizer = this.tokenizer
|
||||
this.file = parseFilePath(tokenizer, this.liquid)
|
||||
this.currentFile = token.file
|
||||
while (!tokenizer.end()) {
|
||||
@@ -50,7 +49,7 @@ export default class extends Tag {
|
||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
||||
const { liquid, hash } = this
|
||||
const filepath = (yield renderFilePath(this['file'], ctx, liquid)) as string
|
||||
assert(filepath, () => `illegal filename "${filepath}"`)
|
||||
assert(filepath, () => `illegal file path "${filepath}"`)
|
||||
|
||||
const childCtx = new Context({}, ctx.opts, { sync: ctx.sync, globals: ctx.globals, strictVariables: ctx.strictVariables })
|
||||
const scope = childCtx.bottom()
|
||||
@@ -86,8 +85,8 @@ export default class extends Tag {
|
||||
export function parseFilePath (tokenizer: Tokenizer, liquid: Liquid): ParsedFileName {
|
||||
if (liquid.options.dynamicPartials) {
|
||||
const file = tokenizer.readValue()
|
||||
if (file === undefined) throw new TypeError(`illegal argument "${tokenizer.input}"`)
|
||||
if (file.getText() === 'none') return
|
||||
tokenizer.assert(file, 'illegal file path')
|
||||
if (file!.getText() === 'none') return
|
||||
if (TypeGuards.isQuotedToken(file)) {
|
||||
// for filenames like "files/{{file}}", eval as liquid template
|
||||
const templates = liquid.parse(evalQuotedToken(file))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { toEnumerable } from '../util/collection'
|
||||
import { ValueToken, Liquid, Tag, evalToken, Emitter, Hash, TagToken, TopLevelToken, Context, Template, ParseStream } from '..'
|
||||
import { TablerowloopDrop } from '../drop/tablerowloop-drop'
|
||||
import { Tokenizer } from '../parser/tokenizer'
|
||||
|
||||
export default class extends Tag {
|
||||
variable: string
|
||||
@@ -10,20 +9,18 @@ export default class extends Tag {
|
||||
collection: ValueToken
|
||||
constructor (tagToken: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(tagToken, remainTokens, liquid)
|
||||
const tokenizer = new Tokenizer(tagToken.args, this.liquid.options.operators)
|
||||
const variable = this.tokenizer.readIdentifier()
|
||||
this.tokenizer.skipBlank()
|
||||
|
||||
const variable = tokenizer.readIdentifier()
|
||||
tokenizer.skipBlank()
|
||||
|
||||
const predicate = tokenizer.readIdentifier()
|
||||
const collectionToken = tokenizer.readValue()
|
||||
const predicate = this.tokenizer.readIdentifier()
|
||||
const collectionToken = this.tokenizer.readValue()
|
||||
if (predicate.content !== 'in' || !collectionToken) {
|
||||
throw new Error(`illegal tag: ${tagToken.getText()}`)
|
||||
}
|
||||
|
||||
this.variable = variable.content
|
||||
this.collection = collectionToken
|
||||
this.args = new Hash(tokenizer.remaining())
|
||||
this.args = new Hash(this.tokenizer.remaining())
|
||||
this.templates = []
|
||||
|
||||
let p
|
||||
|
||||
@@ -7,31 +7,32 @@ import { defaultOptions } from '../liquid-options'
|
||||
describe('Output', function () {
|
||||
const emitter: any = { write: (html: string) => (emitter.html += html), html: '' }
|
||||
const liquid = { options: {} } as any
|
||||
const token = { content: 'obj', input: 'obj' } as OutputToken
|
||||
beforeEach(() => { emitter.html = '' })
|
||||
|
||||
it('should stringify objects', async function () {
|
||||
const scope = new Context({
|
||||
foo: { obj: { arr: ['a', 2] } }
|
||||
obj: { foo: { arr: ['a', 2] } }
|
||||
})
|
||||
const output = new Output({ content: 'foo' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe('[object Object]')
|
||||
})
|
||||
it('should skip function property', async function () {
|
||||
const scope = new Context({ obj: { foo: 'foo', bar: (x: any) => x } })
|
||||
const output = new Output({ content: 'obj' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe('[object Object]')
|
||||
})
|
||||
it('should respect to .toString()', async () => {
|
||||
const scope = new Context({ obj: { toString: () => 'FOO' } })
|
||||
const output = new Output({ content: 'obj' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe('FOO')
|
||||
})
|
||||
it('should respect to .toString()', async () => {
|
||||
const scope = new Context({ obj: { toString: () => 'FOO' } })
|
||||
const output = new Output({ content: 'obj' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe('FOO')
|
||||
})
|
||||
@@ -47,6 +48,7 @@ describe('Output', function () {
|
||||
html: '',
|
||||
keepOutputType: true
|
||||
}
|
||||
const token = { content: 'foo', input: 'foo' } as OutputToken
|
||||
|
||||
beforeEach(() => { emitter.html = '' })
|
||||
|
||||
@@ -54,7 +56,7 @@ describe('Output', function () {
|
||||
const scope = new Context({
|
||||
foo: 42
|
||||
}, { ...defaultOptions, keepOutputType: true })
|
||||
const output = new Output({ content: 'foo' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe(42)
|
||||
})
|
||||
@@ -62,7 +64,7 @@ describe('Output', function () {
|
||||
const scope = new Context({
|
||||
foo: true
|
||||
}, { ...defaultOptions, keepOutputType: true })
|
||||
const output = new Output({ content: 'foo' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe(true)
|
||||
})
|
||||
@@ -70,7 +72,7 @@ describe('Output', function () {
|
||||
const scope = new Context({
|
||||
foo: 'test'
|
||||
}, { ...defaultOptions, keepOutputType: true })
|
||||
const output = new Output({ content: 'foo' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toBe('test')
|
||||
})
|
||||
@@ -78,7 +80,7 @@ describe('Output', function () {
|
||||
const scope = new Context({
|
||||
foo: { a: { b: 42 } }
|
||||
}, { ...defaultOptions, keepOutputType: true })
|
||||
const output = new Output({ content: 'foo' } as OutputToken, liquid)
|
||||
const output = new Output(token, liquid)
|
||||
await toPromise(output.render(scope, emitter))
|
||||
return expect(emitter.html).toEqual({ a: { b: 42 } })
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Template, TemplateImpl } from '../template'
|
||||
import { Context } from '../context/context'
|
||||
import { Emitter } from '../emitters/emitter'
|
||||
import { OutputToken } from '../tokens/output-token'
|
||||
import { Tokenizer } from '../parser'
|
||||
import { Liquid } from '../liquid'
|
||||
import { Filter } from './filter'
|
||||
|
||||
@@ -10,7 +11,8 @@ export class Output extends TemplateImpl<OutputToken> implements Template {
|
||||
value: Value
|
||||
public constructor (token: OutputToken, liquid: Liquid) {
|
||||
super(token)
|
||||
this.value = new Value(token.content, liquid)
|
||||
const tokenizer = new Tokenizer(token.input, liquid.options.operators, token.file, token.contentRange)
|
||||
this.value = new Value(tokenizer.readFilteredValue(), liquid)
|
||||
const filters = this.value.filters
|
||||
const outputEscape = liquid.options.outputEscape
|
||||
if (!filters[filters.length - 1]?.raw && outputEscape) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { TemplateImpl } from './template-impl'
|
||||
import type { Emitter } from '../emitters/emitter'
|
||||
import type { Tokenizer } from '../parser'
|
||||
import type { Context } from '../context/context'
|
||||
import type { TopLevelToken, TagToken } from '../tokens'
|
||||
import type { Template } from './template'
|
||||
@@ -10,11 +11,13 @@ export type TagRenderReturn = Generator<unknown, unknown, unknown> | Promise<unk
|
||||
export abstract class Tag extends TemplateImpl<TagToken> implements Template {
|
||||
public name: string
|
||||
public liquid: Liquid
|
||||
protected tokenizer: Tokenizer
|
||||
|
||||
public constructor (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) {
|
||||
super(token)
|
||||
this.name = token.name
|
||||
this.liquid = liquid
|
||||
this.tokenizer = token.tokenizer
|
||||
}
|
||||
public abstract render (ctx: Context, emitter: Emitter): TagRenderReturn;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Filter } from './filter'
|
||||
import { Expression } from '../render'
|
||||
import { Tokenizer } from '../parser'
|
||||
import { assert } from '../util'
|
||||
import type { FilteredValueToken } from '../tokens'
|
||||
import type { Liquid } from '../liquid'
|
||||
import type { Context } from '../context'
|
||||
|
||||
@@ -12,10 +13,12 @@ export class Value {
|
||||
/**
|
||||
* @param str the value to be valuated, eg.: "foobar" | truncate: 3
|
||||
*/
|
||||
public constructor (str: string, liquid: Liquid) {
|
||||
const tokenizer = new Tokenizer(str, liquid.options.operators)
|
||||
this.initial = tokenizer.readExpression()
|
||||
this.filters = tokenizer.readFilters().map(({ name, args }) => new Filter(name, this.getFilter(liquid, name), args, liquid))
|
||||
public constructor (input: string | FilteredValueToken, liquid: Liquid) {
|
||||
const token: FilteredValueToken = typeof input === 'string'
|
||||
? new Tokenizer(input, liquid.options.operators).readFilteredValue()
|
||||
: input
|
||||
this.initial = token.initial
|
||||
this.filters = token.filters.map(({ name, args }) => new Filter(name, this.getFilter(liquid, name), args, liquid))
|
||||
}
|
||||
public * value (ctx: Context, lenient?: boolean): Generator<unknown, unknown, unknown> {
|
||||
lenient = lenient || (ctx.opts.lenientIf && this.filters.length > 0 && this.filters[0].name === 'default')
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Token } from './token'
|
||||
import { TokenKind } from '../parser'
|
||||
import { last } from '../util'
|
||||
import { TYPES, BLANK } from '../util'
|
||||
|
||||
export abstract class DelimitedToken extends Token {
|
||||
public trimLeft = false
|
||||
public trimRight = false
|
||||
public content: string
|
||||
public contentRange: [number, number]
|
||||
public constructor (
|
||||
kind: TokenKind,
|
||||
content: string,
|
||||
[contentBegin, contentEnd]: [number, number],
|
||||
input: string,
|
||||
begin: number,
|
||||
end: number,
|
||||
@@ -17,16 +17,19 @@ export abstract class DelimitedToken extends Token {
|
||||
file?: string
|
||||
) {
|
||||
super(kind, input, begin, end, file)
|
||||
this.content = this.getText()
|
||||
const tl = content[0] === '-'
|
||||
const tr = last(content) === '-'
|
||||
this.content = content
|
||||
.slice(
|
||||
tl ? 1 : 0,
|
||||
tr ? -1 : content.length
|
||||
)
|
||||
.trim()
|
||||
const tl = input[contentBegin] === '-'
|
||||
const tr = input[contentEnd - 1] === '-'
|
||||
|
||||
let l = tl ? contentBegin + 1 : contentBegin
|
||||
let r = tr ? contentEnd - 1 : contentEnd
|
||||
while (l < r && (TYPES[input.charCodeAt(l)] & BLANK)) l++
|
||||
while (r > l && (TYPES[input.charCodeAt(r - 1)] & BLANK)) r--
|
||||
|
||||
this.contentRange = [l, r]
|
||||
this.trimLeft = tl || trimLeft
|
||||
this.trimRight = tr || trimRight
|
||||
}
|
||||
get content () {
|
||||
return this.input.slice(this.contentRange[0], this.contentRange[1])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Token } from './token'
|
||||
import { FilterToken } from './filter-token'
|
||||
import { TokenKind } from '../parser'
|
||||
import { Expression } from '../render'
|
||||
|
||||
/**
|
||||
* value expression with optional filters
|
||||
* e.g.
|
||||
* {% assign foo="bar" | append: "coo" %}
|
||||
*/
|
||||
export class FilteredValueToken extends Token {
|
||||
constructor (
|
||||
public initial: Expression,
|
||||
public filters: FilterToken[],
|
||||
public input: string,
|
||||
public begin: number,
|
||||
public end: number,
|
||||
public file?: string
|
||||
) {
|
||||
super(TokenKind.FilteredValue, input, begin, end, file)
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,4 @@ export * from './range-token'
|
||||
export * from './value-token'
|
||||
export * from './liquid-tag-token'
|
||||
export * from './delimited-token'
|
||||
export * from './filtered-value-token'
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { DelimitedToken } from './delimited-token'
|
||||
import { TokenizationError } from '../util'
|
||||
import { NormalizedFullOptions } from '../liquid-options'
|
||||
import { Tokenizer, TokenKind } from '../parser'
|
||||
|
||||
/**
|
||||
* LiquidTagToken is different from TagToken by not having delimiters `{%` or `%}`
|
||||
*/
|
||||
export class LiquidTagToken extends DelimitedToken {
|
||||
public name: string
|
||||
public args: string
|
||||
public tokenizer: Tokenizer
|
||||
public constructor (
|
||||
input: string,
|
||||
begin: number,
|
||||
@@ -13,20 +16,13 @@ export class LiquidTagToken extends DelimitedToken {
|
||||
options: NormalizedFullOptions,
|
||||
file?: string
|
||||
) {
|
||||
const value = input.slice(begin, end)
|
||||
super(TokenKind.Tag, value, input, begin, end, false, false, file)
|
||||
super(TokenKind.Tag, [begin, end], input, begin, end, false, false, file)
|
||||
|
||||
if (!/\S/.test(value)) {
|
||||
// A line that contains only whitespace.
|
||||
this.name = ''
|
||||
this.args = ''
|
||||
} else {
|
||||
const tokenizer = new Tokenizer(this.content, options.operators)
|
||||
this.name = tokenizer.readTagName()
|
||||
if (!this.name) throw new TokenizationError(`illegal liquid tag syntax`, this)
|
||||
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange)
|
||||
this.name = this.tokenizer.readTagName()
|
||||
this.tokenizer.assert(this.name, 'illegal liquid tag syntax')
|
||||
|
||||
tokenizer.skipBlank()
|
||||
this.args = tokenizer.remaining()
|
||||
}
|
||||
this.tokenizer.skipBlank()
|
||||
this.args = this.tokenizer.remaining()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export class OutputToken extends DelimitedToken {
|
||||
file?: string
|
||||
) {
|
||||
const { trimOutputLeft, trimOutputRight, outputDelimiterLeft, outputDelimiterRight } = options
|
||||
const value = input.slice(begin + outputDelimiterLeft.length, end - outputDelimiterRight.length)
|
||||
super(TokenKind.Output, value, input, begin, end, trimOutputLeft, trimOutputRight, file)
|
||||
const valueRange: [number, number] = [begin + outputDelimiterLeft.length, end - outputDelimiterRight.length]
|
||||
super(TokenKind.Output, valueRange, input, begin, end, trimOutputLeft, trimOutputRight, file)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,11 +1,10 @@
|
||||
import { DelimitedToken } from './delimited-token'
|
||||
import { TokenizationError } from '../util/error'
|
||||
import { Tokenizer, TokenKind } from '../parser'
|
||||
import type { NormalizedFullOptions } from '../liquid-options'
|
||||
|
||||
export class TagToken extends DelimitedToken {
|
||||
public name: string
|
||||
public args: string
|
||||
public tokenizer: Tokenizer
|
||||
public constructor (
|
||||
input: string,
|
||||
begin: number,
|
||||
@@ -14,14 +13,15 @@ export class TagToken extends DelimitedToken {
|
||||
file?: string
|
||||
) {
|
||||
const { trimTagLeft, trimTagRight, tagDelimiterLeft, tagDelimiterRight } = options
|
||||
const value = input.slice(begin + tagDelimiterLeft.length, end - tagDelimiterRight.length)
|
||||
super(TokenKind.Tag, value, input, begin, end, trimTagLeft, trimTagRight, file)
|
||||
const [valueBegin, valueEnd] = [begin + tagDelimiterLeft.length, end - tagDelimiterRight.length]
|
||||
super(TokenKind.Tag, [valueBegin, valueEnd], input, begin, end, trimTagLeft, trimTagRight, file)
|
||||
|
||||
const tokenizer = new Tokenizer(this.content, options.operators)
|
||||
this.name = tokenizer.readTagName()
|
||||
if (!this.name) throw new TokenizationError(`illegal tag syntax`, this)
|
||||
|
||||
tokenizer.skipBlank()
|
||||
this.args = tokenizer.remaining()
|
||||
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange)
|
||||
this.name = this.tokenizer.readTagName()
|
||||
this.tokenizer.assert(this.name, `illegal tag syntax, tag name expected`)
|
||||
this.tokenizer.skipBlank()
|
||||
}
|
||||
get args (): string {
|
||||
return this.tokenizer.input.slice(this.tokenizer.p, this.contentRange[1])
|
||||
}
|
||||
}
|
||||
|
||||
+27
-17
@@ -3,27 +3,30 @@ import { Token } from '../tokens/token'
|
||||
import { Template } from '../template/template'
|
||||
|
||||
export abstract class LiquidError extends Error {
|
||||
private token: Token
|
||||
public context: string
|
||||
private originalError: Error
|
||||
public constructor (err: Error, token: Token) {
|
||||
super(err.message)
|
||||
this.originalError = err
|
||||
this.token = token
|
||||
this.context = ''
|
||||
private token!: Token
|
||||
public context = ''
|
||||
private originalError?: Error
|
||||
public constructor (err: Error | string, token: Token) {
|
||||
/**
|
||||
* note: for ES5 targeting, `this` will be replaced by return value of Error(),
|
||||
* thus everything on `this` will be lost, avoid calling `LiquidError` methods here
|
||||
*/
|
||||
super(typeof err === 'string' ? err : err.message)
|
||||
if (typeof err !== 'string') Object.defineProperty(this, 'originalError', { value: err, enumerable: false })
|
||||
Object.defineProperty(this, 'token', { value: token, enumerable: false })
|
||||
}
|
||||
protected update () {
|
||||
const err = this.originalError
|
||||
this.context = mkContext(this.token)
|
||||
this.message = mkMessage(err.message, this.token)
|
||||
Object.defineProperty(this, 'context', { value: mkContext(this.token), enumerable: false })
|
||||
this.message = mkMessage(this.message, this.token)
|
||||
this.stack = this.message + '\n' + this.context +
|
||||
'\n' + this.stack + '\nFrom ' + err.stack
|
||||
'\n' + this.stack
|
||||
if (this.originalError) this.stack += '\nFrom ' + this.originalError.stack
|
||||
}
|
||||
}
|
||||
|
||||
export class TokenizationError extends LiquidError {
|
||||
public constructor (message: string, token: Token) {
|
||||
super(new Error(message), token)
|
||||
super(message, token)
|
||||
this.name = 'TokenizationError'
|
||||
super.update()
|
||||
}
|
||||
@@ -80,7 +83,7 @@ export class AssertionError extends Error {
|
||||
}
|
||||
|
||||
function mkContext (token: Token) {
|
||||
const [line] = token.getPosition()
|
||||
const [line, col] = token.getPosition()
|
||||
const lines = token.input.split('\n')
|
||||
const begin = Math.max(line - 2, 1)
|
||||
const end = Math.min(line + 3, lines.length)
|
||||
@@ -88,10 +91,17 @@ function mkContext (token: Token) {
|
||||
const context = _
|
||||
.range(begin, end + 1)
|
||||
.map(lineNumber => {
|
||||
const indicator = (lineNumber === line) ? '>> ' : ' '
|
||||
const rowIndicator = (lineNumber === line) ? '>> ' : ' '
|
||||
const num = _.padStart(String(lineNumber), String(end).length)
|
||||
const text = lines[lineNumber - 1]
|
||||
return `${indicator}${num}| ${text}`
|
||||
let text = `${rowIndicator}${num}| `
|
||||
|
||||
const colIndicator = lineNumber === line
|
||||
? '\n' + _.padStart('^', col + text.length)
|
||||
: ''
|
||||
|
||||
text += lines[lineNumber - 1]
|
||||
text += colIndicator
|
||||
return text
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
|
||||
@@ -32,13 +32,30 @@ describe('util/strftime', function () {
|
||||
})
|
||||
})
|
||||
it('should format %q as date suffix', function () {
|
||||
const st = new Date('2016-03-01 03:05:03')
|
||||
const nd = new Date('2016-03-02 03:05:03')
|
||||
const rd = new Date('2016-03-03 03:05:03')
|
||||
expect(t(st, '%q')).toBe('st')
|
||||
expect(t(nd, '%q')).toBe('nd')
|
||||
expect(t(rd, '%q')).toBe('rd')
|
||||
const first = new Date('2016-03-01 03:05:03')
|
||||
const second = new Date('2016-03-02 03:05:03')
|
||||
const third = new Date('2016-03-03 03:05:03')
|
||||
|
||||
const eleventh = new Date('2016-03-11 03:05:03')
|
||||
const twelfth = new Date('2016-03-12 03:05:03')
|
||||
const thirteenth = new Date('2016-03-13 03:05:03')
|
||||
|
||||
const twentyfirst = new Date('2016-03-21 03:05:03')
|
||||
const twentysecond = new Date('2016-03-22 03:05:03')
|
||||
const twentythird = new Date('2016-03-23 03:05:03')
|
||||
|
||||
expect(t(first, '%q')).toBe('st')
|
||||
expect(t(second, '%q')).toBe('nd')
|
||||
expect(t(third, '%q')).toBe('rd')
|
||||
expect(t(now, '%q')).toBe('th')
|
||||
|
||||
expect(t(eleventh, '%q')).toBe('th')
|
||||
expect(t(twelfth, '%q')).toBe('th')
|
||||
expect(t(thirteenth, '%q')).toBe('th')
|
||||
|
||||
expect(t(twentyfirst, '%q')).toBe('st')
|
||||
expect(t(twentysecond, '%q')).toBe('nd')
|
||||
expect(t(twentythird, '%q')).toBe('rd')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
+24
-9
@@ -11,12 +11,6 @@ const dayNames = [
|
||||
]
|
||||
const monthNamesShort = monthNames.map(abbr)
|
||||
const dayNamesShort = dayNames.map(abbr)
|
||||
const suffixes = {
|
||||
1: 'st',
|
||||
2: 'nd',
|
||||
3: 'rd',
|
||||
'default': 'th'
|
||||
}
|
||||
interface FormatOptions {
|
||||
flags: object;
|
||||
width?: string;
|
||||
@@ -52,9 +46,30 @@ function isLeapYear (d: LiquidDate) {
|
||||
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
|
||||
}
|
||||
function getSuffix (d: LiquidDate) {
|
||||
const str = d.getDate().toString()
|
||||
const index = parseInt(str.slice(-1))
|
||||
return suffixes[index] || suffixes['default']
|
||||
const date = d.getDate()
|
||||
|
||||
let suffix = 'th'
|
||||
|
||||
switch (date) {
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
break
|
||||
default:
|
||||
switch (date % 10) {
|
||||
case 1:
|
||||
suffix = 'st'
|
||||
break
|
||||
case 2:
|
||||
suffix = 'nd'
|
||||
break
|
||||
case 3:
|
||||
suffix = 'rd'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return suffix
|
||||
}
|
||||
function century (d: LiquidDate) {
|
||||
return parseInt(d.getFullYear().toString().substring(0, 2), 10)
|
||||
|
||||
@@ -24,6 +24,12 @@ describe('TimezoneDate', () => {
|
||||
const date = new TimezoneDate('2021-12-07T00:00:00.001+08:00', -480)
|
||||
expect(date.getDay()).toBe(2)
|
||||
})
|
||||
it('should support .toLocaleString()', () => {
|
||||
const date = new TimezoneDate('2021-10-06T00:00:00.001+00:00', -480)
|
||||
expect(date.toLocaleString('en-US')).toMatch(/8:00:00\sAM$/)
|
||||
expect(date.toLocaleString('en-US', { timeZone: 'America/New_York' })).toMatch(/8:00:00\sPM$/)
|
||||
expect(() => date.toLocaleString()).not.toThrow()
|
||||
})
|
||||
it('should support .toLocaleTimeString()', () => {
|
||||
const date = new TimezoneDate('2021-10-06T00:00:00.001+00:00', -480)
|
||||
expect(date.toLocaleTimeString('en-US')).toMatch(/^8:00:00\sAM$/)
|
||||
|
||||
+27
-22
@@ -2,7 +2,6 @@ import { LiquidDate } from './liquid-date'
|
||||
|
||||
// one minute in milliseconds
|
||||
const OneMinute = 60000
|
||||
const hostTimezoneOffset = new Date().getTimezoneOffset()
|
||||
const ISO8601_TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):(\d{2}))$/
|
||||
|
||||
/**
|
||||
@@ -15,51 +14,57 @@ const ISO8601_TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):(\d{2}))$/
|
||||
export class TimezoneDate implements LiquidDate {
|
||||
private timezoneOffset: number
|
||||
private date: Date
|
||||
private displayDate: Date
|
||||
constructor (init: string | number | Date | TimezoneDate, timezoneOffset: number) {
|
||||
if (init instanceof TimezoneDate) {
|
||||
this.date = init.date
|
||||
timezoneOffset = init.timezoneOffset
|
||||
} else {
|
||||
const diff = (hostTimezoneOffset - timezoneOffset) * OneMinute
|
||||
const time = new Date(init).getTime() + diff
|
||||
this.date = new Date(time)
|
||||
}
|
||||
this.date = init instanceof TimezoneDate
|
||||
? init.date
|
||||
: new Date(init)
|
||||
this.timezoneOffset = timezoneOffset
|
||||
|
||||
const diff = (this.date.getTimezoneOffset() - this.timezoneOffset) * OneMinute
|
||||
const time = this.date.getTime() + diff
|
||||
this.displayDate = new Date(time)
|
||||
}
|
||||
|
||||
getTime () {
|
||||
return this.date.getTime()
|
||||
return this.displayDate.getTime()
|
||||
}
|
||||
|
||||
getMilliseconds () {
|
||||
return this.date.getMilliseconds()
|
||||
return this.displayDate.getMilliseconds()
|
||||
}
|
||||
getSeconds () {
|
||||
return this.date.getSeconds()
|
||||
return this.displayDate.getSeconds()
|
||||
}
|
||||
getMinutes () {
|
||||
return this.date.getMinutes()
|
||||
return this.displayDate.getMinutes()
|
||||
}
|
||||
getHours () {
|
||||
return this.date.getHours()
|
||||
return this.displayDate.getHours()
|
||||
}
|
||||
getDay () {
|
||||
return this.date.getDay()
|
||||
return this.displayDate.getDay()
|
||||
}
|
||||
getDate () {
|
||||
return this.date.getDate()
|
||||
return this.displayDate.getDate()
|
||||
}
|
||||
getMonth () {
|
||||
return this.date.getMonth()
|
||||
return this.displayDate.getMonth()
|
||||
}
|
||||
getFullYear () {
|
||||
return this.date.getFullYear()
|
||||
return this.displayDate.getFullYear()
|
||||
}
|
||||
toLocaleString (locale?: string, init?: any) {
|
||||
if (init?.timeZone) {
|
||||
return this.date.toLocaleString(locale, init)
|
||||
}
|
||||
return this.displayDate.toLocaleString(locale, init)
|
||||
}
|
||||
toLocaleTimeString (locale?: string) {
|
||||
return this.date.toLocaleTimeString(locale)
|
||||
return this.displayDate.toLocaleTimeString(locale)
|
||||
}
|
||||
toLocaleDateString (locale?: string) {
|
||||
return this.date.toLocaleDateString(locale)
|
||||
return this.displayDate.toLocaleDateString(locale)
|
||||
}
|
||||
getTimezoneOffset () {
|
||||
return this.timezoneOffset!
|
||||
@@ -87,8 +92,8 @@ export class TimezoneDate implements LiquidDate {
|
||||
// has a timezone specified
|
||||
if (m && m[2] && m[3] && m[4]) {
|
||||
const [, , sign, hours, minutes] = m
|
||||
const delta = (sign === '+' ? -1 : 1) * (parseInt(hours, 10) * 60 + parseInt(minutes, 10))
|
||||
return new TimezoneDate(+new Date(dateString), delta)
|
||||
const offset = (sign === '+' ? -1 : 1) * (parseInt(hours, 10) * 60 + parseInt(minutes, 10))
|
||||
return new TimezoneDate(+new Date(dateString), offset)
|
||||
}
|
||||
return new Date(dateString)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
{
|
||||
"extends": ["../.eslintrc.json"],
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"plugins": [
|
||||
"mocha"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": "test/tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"deprecation/deprecation": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-new": "off"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
const LiquidUMD = require('../../dist/liquid.browser.umd.js').Liquid
|
||||
|
||||
describe('browser', function () {
|
||||
it('should yield unclosed output error', () => {
|
||||
const engine = new LiquidUMD()
|
||||
return expect(engine.parseAndRender('{{huh')).rejects.toMatchObject({
|
||||
message: 'output "{{huh" not closed, line:1, col:1'
|
||||
})
|
||||
})
|
||||
})
|
||||
+49
-1
@@ -254,7 +254,7 @@ describe('Issues', function () {
|
||||
})
|
||||
it('#519 should throw parse error for invalid assign expression', () => {
|
||||
const engine = new Liquid()
|
||||
expect(() => engine.parse('{% assign headshot = https://testurl.com/not_enclosed_in_quotes.jpg %}')).toThrow(/unexpected token at ":/)
|
||||
expect(() => engine.parse('{% assign headshot = https://testurl.com/not_enclosed_in_quotes.jpg %}')).toThrow(/expected "|" before filter, line:1, col:27/)
|
||||
})
|
||||
it('#527 export Liquid Expression', () => {
|
||||
const tokenizer = new Tokenizer('a > b')
|
||||
@@ -406,4 +406,52 @@ describe('Issues', function () {
|
||||
const html = await engine.parseAndRender(template)
|
||||
expect(html).toContain('true')
|
||||
})
|
||||
it('#604 date filter appears to add DST correction to UTC dates', () => {
|
||||
const engine = new Liquid({
|
||||
timezoneOffset: 'Etc/GMT'
|
||||
})
|
||||
|
||||
const html = engine.parseAndRenderSync(
|
||||
'{{ "2023-04-05T12:00:00Z" | date: "%Y-%m-%dT%H:%M:%S%z", "Etc/GMT" }}' +
|
||||
'{{ "2023-01-05T12:00:00Z" | date: "%Y-%m-%dT%H:%M:%S%z", 0 }}' +
|
||||
'{{ "2023-01-05T12:00:00Z" | date: "%Y-%m-%dT%H:%M:%S%z", "Etc/GMT" }}' +
|
||||
'{{ "2023-01-05T12:00:00Z" | date: "%Y-%m-%dT%H:%M:%S%z" }}' +
|
||||
'{{ "2023-01-05T12:00:00+0000" | date: "%Y-%m-%dT%H:%M:%S%z", 0 }}'
|
||||
)
|
||||
const expected =
|
||||
'2023-04-05T12:00:00+0000' +
|
||||
'2023-01-05T12:00:00+0000' +
|
||||
'2023-01-05T12:00:00+0000' +
|
||||
'2023-01-05T12:00:00+0000' +
|
||||
'2023-01-05T12:00:00+0000'
|
||||
expect(html).toEqual(expected)
|
||||
})
|
||||
it('#610 should throw missing ":" after filter name', () => {
|
||||
const engine = new Liquid()
|
||||
const fn = () => engine.parseAndRenderSync("{%- assign module = '' | split '' -%}")
|
||||
expect(fn).toThrow(/expected ":" after filter name/)
|
||||
})
|
||||
it('#628 Single or double quote breaks comments', () => {
|
||||
const template = `{%- liquid
|
||||
# Show a message that's customized to the product type
|
||||
|
||||
assign product_type = product.type | downcase
|
||||
assign message = ''
|
||||
|
||||
case product_type
|
||||
when 'health'
|
||||
assign message = 'This is a health potion!'
|
||||
when 'love'
|
||||
assign message = 'This is a love potion!'
|
||||
else
|
||||
assign message = 'This is a potion!'
|
||||
endcase
|
||||
|
||||
echo message
|
||||
-%}`
|
||||
const engine = new Liquid()
|
||||
const product = { type: 'love' }
|
||||
const result = engine.parseAndRenderSync(template, { product })
|
||||
expect(result).toEqual('This is a love potion!')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { test, render } from '../../stub/render'
|
||||
import { Liquid } from '../../../src/liquid'
|
||||
|
||||
describe('filters/array', function () {
|
||||
const engine = new Liquid()
|
||||
describe('index', function () {
|
||||
it('should support index', function () {
|
||||
const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
@@ -22,7 +24,7 @@ describe('filters/array', function () {
|
||||
it('should throw when comma missing', async () => {
|
||||
const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
'{{ beatles | join " and " }}'
|
||||
return expect(render(src)).rejects.toThrow('unexpected token at "\\" and \\"", line:1, col:65')
|
||||
return expect(render(src)).rejects.toThrow('expected ":" after filter name, line:1, col:83')
|
||||
})
|
||||
})
|
||||
describe('last', () => {
|
||||
@@ -92,6 +94,31 @@ describe('filters/array', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('push', () => {
|
||||
it('should push arg value', async () => {
|
||||
const scope = { val: ['hey'], arg: 'foo' }
|
||||
await test('{{ val | push: arg | join: "," }}', scope, 'hey,foo')
|
||||
})
|
||||
it('should not change original array', async () => {
|
||||
const scope = { val: ['hey'], arg: 'foo' }
|
||||
await test('{{ val | push: arg | join: "," }} {{ val | push: arg | join: "," }}', scope, 'hey,foo hey,foo')
|
||||
})
|
||||
it('should support undefined left value', async () => {
|
||||
const scope = { arg: 'foo' }
|
||||
await test('{{ notDefined | push: arg | join: "," }}', scope, 'foo')
|
||||
})
|
||||
it('should ignore nil left value', async () => {
|
||||
const scope = { undefinedValue: undefined, nullValue: null, arg: 'foo' }
|
||||
await test('{{ undefinedValue | push: arg | join: "," }}', scope, 'foo')
|
||||
await test('{{ nullValue | push: arg | join: "," }}', scope, 'foo')
|
||||
})
|
||||
it('should ignore nil right value', async () => {
|
||||
const scope = { nullValue: null }
|
||||
await test('{{ nullValue | push | join: "," }}', scope, '')
|
||||
await test('{{ nullValue | push: nil | join: "," }}', scope, '')
|
||||
})
|
||||
})
|
||||
|
||||
describe('reverse', function () {
|
||||
it('should support reverse', () => test(
|
||||
'{{ "Ground control to Major Tom." | split: "" | reverse | join: "" }}',
|
||||
@@ -104,6 +131,29 @@ describe('filters/array', function () {
|
||||
expect(html).toBe('abc')
|
||||
})
|
||||
})
|
||||
describe('sample', function () {
|
||||
it('should return one item if count not specified', async () => {
|
||||
const template = '{{ "hello,world" | split: "," | sample }}'
|
||||
const result = await engine.parseAndRender(template)
|
||||
expect(result).toMatch(/hello|world/)
|
||||
})
|
||||
it('should return full array sample even if excess count', () => test(
|
||||
'{{ "hello,world" | split: "," | sample: 10 | size }}',
|
||||
'2'
|
||||
))
|
||||
it('should return partial array sample', () => test(
|
||||
'{{ "hello,world" | split: "," | sample: 1 | size }}',
|
||||
'5'
|
||||
))
|
||||
it('should sample nil value', () => test(
|
||||
'{{ nil | sample: 2 }}',
|
||||
''
|
||||
))
|
||||
it('should sample string characters', () => test(
|
||||
'{{ "aaa" | sample: 2 }}',
|
||||
'aa'
|
||||
))
|
||||
})
|
||||
describe('size', function () {
|
||||
it('should return string length', () => test(
|
||||
'{{ "Ground control to Major Tom." | size }}',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { LiquidOptions } from '../../../src/liquid-options'
|
||||
import { Liquid } from '.././../../src/liquid'
|
||||
import { test } from '../../stub/render'
|
||||
|
||||
describe('filters/date', function () {
|
||||
@@ -98,10 +99,15 @@ describe('filters/date', function () {
|
||||
const scope = { date: new Date('1990-12-31T23:00:00Z') }
|
||||
return test('{{ date | date: "%z"}}', scope, '-0600', opts)
|
||||
})
|
||||
it('should work with `preserveTimezones`', function () {
|
||||
it('opts.timezoneOffset should work with `preserveTimezones`', function () {
|
||||
const opts: LiquidOptions = { timezoneOffset: 600, preserveTimezones: true }
|
||||
return test('{{ "1990-12-31T23:00:00+02:30" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T23:00:00', undefined, opts)
|
||||
})
|
||||
it('timezoneOffset should work with `preserveTimezones`', async () => {
|
||||
const liquid = new Liquid({ preserveTimezones: true })
|
||||
const html = liquid.parseAndRenderSync('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }}')
|
||||
expect(html).toEqual('1991-01-01T04:30:00')
|
||||
})
|
||||
})
|
||||
describe('dateFormat', function () {
|
||||
const optsWithoutDateFormat: LiquidOptions = { timezoneOffset: 360 } // -06:00
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Liquid } from '../../../src/liquid'
|
||||
import { ParseError } from '../../../src'
|
||||
import { TokenizationError } from '../../../src'
|
||||
|
||||
describe('tags/assign', function () {
|
||||
const liquid = new Liquid()
|
||||
it('should throw when variable name illegal', function () {
|
||||
const src = '{% assign / %}'
|
||||
const ctx = {}
|
||||
return expect(liquid.parseAndRender(src, ctx)).rejects.toThrow(/illegal/)
|
||||
return expect(liquid.parseAndRender(src, ctx)).rejects.toThrow(/expected variable name/)
|
||||
})
|
||||
it('should support assign to a string', async function () {
|
||||
const src = '{% assign foo="bar" %}{{foo}}'
|
||||
@@ -15,8 +15,8 @@ describe('tags/assign', function () {
|
||||
})
|
||||
it('should throw when variable value illegal', function () {
|
||||
const src = '{% assign foo = “bar” %}'
|
||||
expect(() => liquid.parse(src)).toThrow(/unexpected token at "“bar”"/)
|
||||
expect(() => liquid.parse(src)).toThrow(ParseError)
|
||||
expect(() => liquid.parse(src)).toThrow(/invalid value expression: "“bar”"/)
|
||||
expect(() => liquid.parse(src)).toThrow(TokenizationError)
|
||||
})
|
||||
it('should support assign to a number', async function () {
|
||||
const src = '{% assign foo=10086 %}{{foo}}'
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('tags/capture', function () {
|
||||
it('should throw on invalid identifier', function () {
|
||||
const src = '{% capture = %}{%endcapture%}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.rejects.toThrow(/= not valid identifier/)
|
||||
.rejects.toThrow('invalid capture name, line:1, col:12')
|
||||
})
|
||||
|
||||
it('should throw when capture not closed', function () {
|
||||
|
||||
@@ -11,7 +11,7 @@ describe('tags/cycle', function () {
|
||||
|
||||
it('should throw when cycle candidates empty', function () {
|
||||
return expect(liquid.parseAndRender('{%cycle%}'))
|
||||
.rejects.toThrow(/empty candidates/)
|
||||
.rejects.toThrow('empty candidates: "{%cycle%}", line:1, col:8')
|
||||
})
|
||||
|
||||
it('should support cycle in for block', async function () {
|
||||
|
||||
@@ -49,8 +49,8 @@ describe('tags/include', function () {
|
||||
'/parent.html': '{%include , %}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('ParseError')
|
||||
expect(e.message).toMatch(/illegal argument ","/)
|
||||
expect(e.name).toBe('TokenizationError')
|
||||
expect(e.message).toMatch('illegal file path, file:/parent.html, line:1, col:11')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('tags/include', function () {
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('RenderError')
|
||||
expect(e.message).toMatch(/illegal filename "undefined"/)
|
||||
expect(e.message).toMatch(/illegal file path "undefined"/)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -17,6 +17,16 @@ describe('tags/inline-comment', function () {
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).toBe('foo')
|
||||
})
|
||||
it('should allow single quotes', async function () {
|
||||
const src = "B{% # that's %}A"
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).toBe('BA')
|
||||
})
|
||||
it('should allow double quotes', async function () {
|
||||
const src = 'B{% # that"s %}A'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).toBe('BA')
|
||||
})
|
||||
it('should handle hash without trailing whitespace', async function () {
|
||||
const src = '{% #some comment %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
|
||||
@@ -23,8 +23,8 @@ describe('tags/layout', function () {
|
||||
'/parent.html': '{%layout%}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('ParseError')
|
||||
expect(e.message).toMatch(/illegal argument ""/)
|
||||
expect(e.name).toBe('TokenizationError')
|
||||
expect(e.message).toMatch(/illegal file path/)
|
||||
})
|
||||
})
|
||||
it('should throw when filename resolved to falsy', function () {
|
||||
@@ -33,7 +33,7 @@ describe('tags/layout', function () {
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('RenderError')
|
||||
expect(e.message).toContain('illegal filename "undefined"')
|
||||
expect(e.message).toContain('illegal file path')
|
||||
})
|
||||
})
|
||||
it('should handle layout none', async function () {
|
||||
|
||||
@@ -42,8 +42,8 @@ describe('tags/render', function () {
|
||||
'/parent.html': '{%render%}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('ParseError')
|
||||
expect(e.message).toMatch(/illegal argument ""/)
|
||||
expect(e.name).toBe('TokenizationError')
|
||||
expect(e.message).toMatch(/illegal file path/)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('tags/render', function () {
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).toBe('RenderError')
|
||||
expect(e.message).toMatch(/illegal filename "undefined"/)
|
||||
expect(e.message).toMatch(/illegal file path/)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -25,11 +25,12 @@ describe('error', function () {
|
||||
' 1| 1st',
|
||||
' 2| 2nd',
|
||||
'>> 3| X{% . a %} Y',
|
||||
' ^',
|
||||
' 4| 4th',
|
||||
'TokenizationError'
|
||||
]
|
||||
await expect(engine.parseAndRender(html.join('\n'))).rejects.toMatchObject({
|
||||
message: 'illegal tag syntax, line:3, col:2',
|
||||
message: 'illegal tag syntax, tag name expected, line:3, col:5',
|
||||
stack: expect.stringContaining(message.join('\n')),
|
||||
name: 'TokenizationError'
|
||||
})
|
||||
@@ -61,7 +62,7 @@ describe('error', function () {
|
||||
it('should throw error with [line, col] if tag unmatched', async function () {
|
||||
await expect(engine.parseAndRender('1\n2\nfoo{% assign a = 4 }\n4')).rejects.toMatchObject({
|
||||
name: 'TokenizationError',
|
||||
message: 'tag "{% assign a =..." not closed, line:3, col:4'
|
||||
message: 'tag "{% assign a = 4 }\\n4" not closed, line:3, col:4'
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -122,6 +123,7 @@ describe('error', function () {
|
||||
' 2| 2nd',
|
||||
' 3| 3rd',
|
||||
'>> 4| X{%throwingTag%} Y',
|
||||
' ^',
|
||||
' 5| 5th',
|
||||
' 6| 6th',
|
||||
' 7| 7th',
|
||||
@@ -150,6 +152,7 @@ describe('error', function () {
|
||||
' 2| 2nd',
|
||||
' 3| 3rd',
|
||||
'>> 4| X{%throwingTag%} Y',
|
||||
' ^',
|
||||
' 5| 5th',
|
||||
' 6| {%block%}{%endblock%}',
|
||||
' 7| 7th',
|
||||
@@ -171,6 +174,7 @@ describe('error', function () {
|
||||
' 2| 2nd',
|
||||
' 3| 3rd',
|
||||
'>> 4| X{%throwingTag%} Y',
|
||||
' ^',
|
||||
' 5| 5th',
|
||||
' 6| 6th',
|
||||
' 7| 7th',
|
||||
@@ -207,9 +211,15 @@ describe('error', function () {
|
||||
})
|
||||
})
|
||||
it('should throw ParseError when tag not closed', async function () {
|
||||
await expect(engine.parseAndRender('{% if %}')).rejects.toMatchObject({
|
||||
await expect(engine.parseAndRender('{% if true %}')).rejects.toMatchObject({
|
||||
name: 'ParseError',
|
||||
message: expect.stringContaining('tag {% if %} not closed')
|
||||
message: expect.stringContaining('tag {% if true %} not closed')
|
||||
})
|
||||
})
|
||||
it('should throw ParseError when tag value not specified', async function () {
|
||||
await expect(engine.parseAndRender('{% if %}{% endif %}')).rejects.toMatchObject({
|
||||
name: 'TokenizationError',
|
||||
message: 'invalid value expression: "", line:1, col:1'
|
||||
})
|
||||
})
|
||||
it('should throw ParseError when tag parse throws', async function () {
|
||||
@@ -238,6 +248,7 @@ describe('error', function () {
|
||||
' 2| 2nd',
|
||||
' 3| 3rd',
|
||||
'>> 4| X{% a %} {% enda %} Y',
|
||||
' ^',
|
||||
' 5| 5th',
|
||||
' 6| 6th',
|
||||
' 7| 7th',
|
||||
@@ -255,6 +266,7 @@ describe('error', function () {
|
||||
const message = [
|
||||
' 1| 1st',
|
||||
'>> 2| X{% a %} {% enda %} Y',
|
||||
' ^',
|
||||
' 3| 3rd',
|
||||
' 4| 4th',
|
||||
'ParseError: tag "a" not found'
|
||||
@@ -300,6 +312,7 @@ describe('error', function () {
|
||||
' 2| 2nd',
|
||||
' 3| 3rd',
|
||||
'>> 4| X{%throwingTag%} Y',
|
||||
' ^',
|
||||
' 5| 5th',
|
||||
' 6| 6th',
|
||||
' 7| 7th',
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module":"CommonJS",
|
||||
"lib": ["es2015", "es2016", "es2017", "dom"],
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"downlevelIteration": true,
|
||||
"strict": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"all": true
|
||||
}
|
||||
+1
-1
@@ -14,5 +14,5 @@
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"all": true,
|
||||
"exclude": [ "node_modules", "dist", "demo" ]
|
||||
"exclude": [ "node_modules", "dist", "demo", "test" ]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user