Compare commits

...
Author SHA1 Message Date
Yang Jun 8a7791be9e docs: add lambdatest to sponsors 2025-10-26 14:53:32 +08:00
allcontributors[bot]GitHuballcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2858271c8f docs: add skynetigor as a contributor for code (#825)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-10-23 22:23:52 +08:00
semantic-release-bot d22945ed5f chore(release): 10.23.0 [skip ci]
# [10.23.0](https://github.com/harttle/liquidjs/compare/v10.22.0...v10.23.0) (2025-10-23)

### Features

* Export specific tokens as types ([#824](https://github.com/harttle/liquidjs/issues/824)) ([4f7d2fd](https://github.com/harttle/liquidjs/commit/4f7d2fd84a8884e1009b13346d331a99b9721149))
2025-10-23 13:38:41 +00:00
Ihor PanasiukandGitHub 4f7d2fd84a feat: Export specific tokens as types (#824)
* Export specific tokens as types

* Update index.ts
2025-10-23 21:37:20 +08:00
semantic-release-bot 597ce7305f chore(release): 10.22.0 [skip ci]
# [10.22.0](https://github.com/harttle/liquidjs/compare/v10.21.1...v10.22.0) (2025-10-06)

### Bug Fixes

* math filters coerce invalid string to 0, [#813](https://github.com/harttle/liquidjs/issues/813) ([#819](https://github.com/harttle/liquidjs/issues/819)) ([e8e502c](https://github.com/harttle/liquidjs/commit/e8e502c5854c9649bf7611a671a068dc260011d1))

### Features

* allow context access in liquidMethodMissing, [#808](https://github.com/harttle/liquidjs/issues/808) ([#820](https://github.com/harttle/liquidjs/issues/820)) ([e551288](https://github.com/harttle/liquidjs/commit/e55128850e507687f9d85a012fc3a72ac2550f3b))
2025-10-06 14:45:55 +00:00
Yang Jun d7fa8ba5f1 chore: update node version for release workflow 2025-10-06 22:44:24 +08:00
Yang JunandGitHub 1b356d350d chore: fix Github artifact name (#821) 2025-10-06 22:32:34 +08:00
Yang JunandGitHub e55128850e feat: allow context access in liquidMethodMissing, #808 (#820) 2025-10-06 18:34:08 +08:00
Yang JunandGitHub e8e502c585 fix: math filters coerce invalid string to 0, #813 (#819) 2025-10-06 18:31:43 +08:00
allcontributors[bot]GitHuballcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
b8bc4db46c docs: add StreakingMan as a contributor for doc (#812)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-08-13 19:15:43 +08:00
裸奔狂甩丁丁andGitHub 68d500c18a docs: operators.md zh-cn translation (#811) 2025-08-13 19:14:47 +08:00
semantic-release-bot de12359bfd chore(release): 10.21.1 [skip ci]
## [10.21.1](https://github.com/harttle/liquidjs/compare/v10.21.0...v10.21.1) (2025-05-14)

### Bug Fixes

* block.super with strictVariables, [#806](https://github.com/harttle/liquidjs/issues/806) ([#807](https://github.com/harttle/liquidjs/issues/807)) ([025c40f](https://github.com/harttle/liquidjs/commit/025c40f0f2f13efa62193c61d2fa56943917ac3c))
2025-05-14 17:49:27 +00:00
Yang JunandGitHub 025c40f0f2 fix: block.super with strictVariables, #806 (#807) 2025-05-15 01:47:57 +08:00
Vlad GURDIGAandGitHub 2f414f8e40 docs: Fix formatting bug in echo.md (#805)
DISCLAIMER: This may not be the proper way to approach the issue.

Although the Markdown code is proper, on the website itself it is incorrectly rendered as "{{` and `}}".

The reason for the disclaimer above is that I’m imagining this may be an issue at the content rendering level, and my fix here is just a workaround of that issue. — Given this, I’ll not be offended if this PR of mine is rejected and closed. 🙂
2025-05-10 20:35:07 +08:00
Vlad GURDIGAandGitHub 40c52124d7 docs: Fix typo in options.md (#802)
Looks like just a typo.
2025-05-09 21:16:08 +08:00
allcontributors[bot]GitHuballcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
ae0c07e60b docs: add gurdiga as a contributor for doc (#804)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2025-05-09 20:37:59 +08:00
Vlad GURDIGAandGitHub 3b9202465e docs: A lil Markdown fix (#803)
Replaced square brackets with round ones in a link markup.
2025-05-09 20:36:49 +08:00
Harttle fc42ad7548 docs: update financial contributors 2025-04-03 21:27:48 +08:00
allcontributors[bot]andGitHub 050a7fc68e docs: add edh649 as a contributor for doc (#801) 2025-04-02 21:02:42 +08:00
Ed HantonandYang Jun 0fdc5c79da Update register-filters-tags.md
Improve documentation
2025-04-02 21:01:20 +08:00
27 changed files with 8593 additions and 4932 deletions
+36
View File
@@ -721,6 +721,42 @@
"contributions": [
"code"
]
},
{
"login": "edh649",
"name": "Ed Hanton",
"avatar_url": "https://avatars.githubusercontent.com/u/527604?v=4",
"profile": "https://github.com/edh649",
"contributions": [
"doc"
]
},
{
"login": "gurdiga",
"name": "Vlad GURDIGA",
"avatar_url": "https://avatars.githubusercontent.com/u/53922?v=4",
"profile": "https://gurdiga.com",
"contributions": [
"doc"
]
},
{
"login": "StreakingMan",
"name": "裸奔狂甩丁丁",
"avatar_url": "https://avatars.githubusercontent.com/u/30397306?v=4",
"profile": "https://www.streakingman.com",
"contributions": [
"doc"
]
},
{
"login": "skynetigor",
"name": "Ihor Panasiuk",
"avatar_url": "https://avatars.githubusercontent.com/u/20903171?v=4",
"profile": "https://github.com/skynetigor",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '14'
node-version: '22'
- name: Install Dependencies
run: npm ci
- name: Release
+7 -7
View File
@@ -14,13 +14,13 @@ jobs:
node-versoin: 22
- os: ubuntu-latest
timezone: Etc/GMT
node-version: 20
- os: ubuntu-latest
timezone: Asia/Shanghai
node-version: 18
- os: ubuntu-latest
timezone: Asia/Shanghai
node-version: 16
- os: ubuntu-latest
timezone: Asia/Shanghai
node-version: 15
- os: ubuntu-latest
timezone: Asia/Shanghai
node-version: 14
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
@@ -44,7 +44,7 @@ jobs:
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-npm-logs-${{ matrix.os }}-${{ matrix.timezone }}-${{ matrix.node-version }}
name: test-npm-logs-${{ matrix.os }}-${{ matrix.node-version }}
path: ~/.npm/_logs
demo:
name: Demo Check
+26
View File
@@ -1,3 +1,29 @@
# [10.23.0](https://github.com/harttle/liquidjs/compare/v10.22.0...v10.23.0) (2025-10-23)
### Features
* Export specific tokens as types ([#824](https://github.com/harttle/liquidjs/issues/824)) ([4f7d2fd](https://github.com/harttle/liquidjs/commit/4f7d2fd84a8884e1009b13346d331a99b9721149))
# [10.22.0](https://github.com/harttle/liquidjs/compare/v10.21.1...v10.22.0) (2025-10-06)
### Bug Fixes
* math filters coerce invalid string to 0, [#813](https://github.com/harttle/liquidjs/issues/813) ([#819](https://github.com/harttle/liquidjs/issues/819)) ([e8e502c](https://github.com/harttle/liquidjs/commit/e8e502c5854c9649bf7611a671a068dc260011d1))
### Features
* allow context access in liquidMethodMissing, [#808](https://github.com/harttle/liquidjs/issues/808) ([#820](https://github.com/harttle/liquidjs/issues/820)) ([e551288](https://github.com/harttle/liquidjs/commit/e55128850e507687f9d85a012fc3a72ac2550f3b))
## [10.21.1](https://github.com/harttle/liquidjs/compare/v10.21.0...v10.21.1) (2025-05-14)
### Bug Fixes
* block.super with strictVariables, [#806](https://github.com/harttle/liquidjs/issues/806) ([#807](https://github.com/harttle/liquidjs/issues/807)) ([025c40f](https://github.com/harttle/liquidjs/commit/025c40f0f2f13efa62193c61d2fa56943917ac3c))
# [10.21.0](https://github.com/harttle/liquidjs/compare/v10.20.3...v10.21.0) (2025-02-23)
+29 -27
View File
@@ -53,6 +53,7 @@ For more details, refer to the [Setup Guide][setup].
## Who's Using LiquidJS?
- [Eleventy](https://www.11ty.dev/): Eleventy, a simpler static site generator.
- [Github Docs](https://github.com/github/docs): The open-source repo for docs.github.com.
- [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.
@@ -71,33 +72,30 @@ Feel free to create a PR or contact me to add your use case into this list!
If you personally love LiquidJS or it's benefiting your business, please consider financially support us via [GitHub Sponsors](https://github.com/sponsors/harttle). Special thanks to our sponsors!
<!-- FINANCIAL-CONTRIBUTORS-BEGIN -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.opensense.com/"><img src="https://images.opencollective.com/opensense-inc/bf840ae/logo/256.png?height=100" width="100px;" alt="Opensense Inc."/><br /><sub><b>Opensense</b></sub></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></td>
<td align="center" valign="top" width="14.28%"><a href="https://about.me/peterdehaan"><img src="https://avatars2.githubusercontent.com/u/557895?v=4&s=100" width="100px;" alt="Peter deHaan"/><br /><sub><b>Peter deHaan</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://opencollective.com/touchless"><img src="https://images.opencollective.com/touchless/273bc74/logo/256.png?height=100" width="100px;" alt="Touchless"/><br /><sub><b>Touchless</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.dropkiq.com/"><img src="https://images.opencollective.com/1bertlol/43a8ea8/logo/256.png?height=100" width="100px;" alt="Adam Darrah"/><br /><sub><b>Dropkiq</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dailycontributors.com/"><img src="https://images.opencollective.com/dailycontributors/3c2e057/logo/256.png?height=100&width=100" width="100px;" alt="Dailycontributors"/><br /><sub><b>Dailycontributors</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coni2k"><img src="https://avatars0.githubusercontent.com/u/1284601?v=4&s=100" width="100px;" alt="coni2k"/><br /><sub><b>Serkan Holat</b></sub></a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/amit777"><img src="https://avatars0.githubusercontent.com/u/2703309?v=4&s=100" width="100px;" alt="amit777"/><br /><sub><b>amit777</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://opencollective.com/khaled-salem"><img src="https://images.opencollective.com/khaled-salem/avatar/256.png?height=256" width="100px;" alt="Khaled Salem"/><br /><sub><b>Khaled Salem</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sentry.io/"><img src="https://avatars.githubusercontent.com/u/1396951?v=4&s=100" width="100px;" alt="Sentry"/><br /><sub><b>Sentry</b></sub></a></td>
<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></td>
<td align="center" valign="top" width="14.28%"><a href="https://customer.io/"><img src="https://avatars.githubusercontent.com/u/1152079?v=4&s=100" width="100px;" alt="Customer IO"/><br /><sub><b>Customer IO</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/15fathoms"><img src="https://avatars.githubusercontent.com/u/79156039?v=4&s=100" width="100px;" alt="Emmanuel Cartelli"/><br /><sub><b>Emmanuel Cartelli</b></sub></a><br /></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/microsoft"><img src="https://avatars.githubusercontent.com/u/6154722?v=4&s=100" width="100px;" alt="Microsoft"/><br /><sub><b>Microsoft</b></sub></a><br /></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.pakstyle.pk/"><img src="https://images.opencollective.com/pakstyle/2b81605/logo/256.png?height=100" width="100px;" alt="PakStyle.pk"/><br /><sub><b>PakStyle.pk</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://syntax.fm/"><img src="https://avatars.githubusercontent.com/u/130389858?v=4&s=100" width="100px;" alt="Syntax Podcast"/><br /><sub><b>Syntax Podcast</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://opencollective.com/cartelli-emmanuel"><img src="https://images.opencollective.com/cartelli-emmanuel/avatar/256.png?height=100" width="100px;" alt="Cartelli Emmanuel"/><br /><sub><b>Cartelli Emmanuel</b></sub></a></td>
</tr>
</tbody>
</table>
<p align="center" style="line-height: 2.5;">
<a href="https://www.11ty.dev/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/35147177?v=4&s=100" height="80" style="vertical-align: middle;" alt="Eleventy" title="Eleventy"/></a>
<a href="https://www.opensense.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/opensense-inc/bf840ae/logo/256.png?height=100" height="80" style="vertical-align: middle;" alt="Opensense Inc." title="Opensense"/></a>
<a href="https://github.com/microsoft" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/6154722?v=4&s=100" height="80" style="vertical-align: middle;" alt="Microsoft" title="Microsoft"/></a>
<a href="https://sentry.io/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/1396951?v=4&s=100" height="80" style="vertical-align: middle;" alt="Sentry" title="Sentry"/></a>
<a href="https://www.checkoutblocks.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/114603307?v=4&s=100" height="80" style="vertical-align: middle;" alt="Checkout Blocks" title="Checkout Blocks"/></a>
<a href="https://customer.io/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/1152079?v=4&s=100" height="80" style="vertical-align: middle;" alt="Customer IO" title="Customer IO"/></a>
<a href="https://syntax.fm/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/130389858?v=4&s=100" height="80" style="vertical-align: middle;" alt="Syntax Podcast" title="Syntax Podcast"/></a>
<br/>
<a href="https://www.lambdatest.com/?utm_source=liquidjs&utm_medium=sponsor" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://www.lambdatest.com/blue-logo.png" width="240" style="vertical-align: middle;" alt="LambdaTest" title="LambdaTest"/></a>
<a href="https://chudovo.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/Chudovo/avatar/256.png?height=100" width="160" style="vertical-align: middle;background: white;padding: 8px 16px;" alt="Chudovo" title="Chudovo"/></a>
<a href="https://dailycontributors.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/dailycontributors/3c2e057/logo/256.png?height=50&width=100" width="120" style="vertical-align: middle;" alt="Dailycontributors" title="Dailycontributors"/></a>
<a href="https://www.pakstyle.pk/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/pakstyle/2b81605/logo/256.png?height=100" height="80" style="vertical-align: middle;" alt="PakStyle.pk" title="PakStyle.pk"/></a>
<a href="https://www.escorta.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/escortacom/avatar/256.png?height=100" height="45" style="vertical-align: middle;" alt="EscortA.com" title="EscortA.com"/></a>
<br/>
<a href="https://opencollective.com/touchless" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/touchless/273bc74/logo/256.png?height=100" height="80" style="vertical-align: middle;" alt="Touchless" title="Touchless"/></a>
<a href="https://www.dropkiq.com/" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/1bertlol/43a8ea8/logo/256.png?height=100" height="80" style="vertical-align: middle;" alt="Dropkiq" title="Dropkiq"/></a>
<a href="https://about.me/peterdehaan" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars2.githubusercontent.com/u/557895?v=4&s=100" height="80" style="vertical-align: middle;" alt="Peter deHaan" title="Peter deHaan"/></a>
<a href="https://github.com/coni2k" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars0.githubusercontent.com/u/1284601?v=4&s=100" height="80" style="vertical-align: middle;" alt="Serkan Holat" title="Serkan Holat"/></a>
<a href="https://github.com/amit777" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars0.githubusercontent.com/u/2703309?v=4&s=100" height="80" style="vertical-align: middle;" alt="amit777" title="amit777"/></a>
<a href="https://opencollective.com/khaled-salem" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/khaled-salem/avatar/256.png?height=256" height="80" style="vertical-align: middle;" alt="Khaled Salem" title="Khaled Salem"/></a>
<a href="https://github.com/15fathoms" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://avatars.githubusercontent.com/u/79156039?v=4&s=100" height="80" style="vertical-align: middle;" alt="Emmanuel Cartelli" title="Emmanuel Cartelli"/></a>
<a href="https://opencollective.com/cartelli-emmanuel" style="display: inline-block; vertical-align: middle; margin: 8px;"><img src="https://images.opencollective.com/cartelli-emmanuel/avatar/256.png?height=100" height="80" style="vertical-align: middle;" alt="Cartelli Emmanuel" title="Cartelli Emmanuel"/></a>
</p>
<!-- FINANCIAL-CONTRIBUTORS-END -->
## Contributors ✨
@@ -210,6 +208,10 @@ Want to contribute? see [Contribution Guidelines][contribution]. Thanks goes to
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://tovd.dev"><img src="https://avatars.githubusercontent.com/u/35376389?v=4?s=100" width="100px;" alt="Tim van Dam"/><br /><sub><b>Tim van Dam</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=timvandam" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/edh649"><img src="https://avatars.githubusercontent.com/u/527604?v=4?s=100" width="100px;" alt="Ed Hanton"/><br /><sub><b>Ed Hanton</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=edh649" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://gurdiga.com"><img src="https://avatars.githubusercontent.com/u/53922?v=4?s=100" width="100px;" alt="Vlad GURDIGA"/><br /><sub><b>Vlad GURDIGA</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=gurdiga" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.streakingman.com"><img src="https://avatars.githubusercontent.com/u/30397306?v=4?s=100" width="100px;" alt="裸奔狂甩丁丁"/><br /><sub><b>裸奔狂甩丁丁</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=StreakingMan" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/skynetigor"><img src="https://avatars.githubusercontent.com/u/20903171?v=4?s=100" width="100px;" alt="Ihor Panasiuk"/><br /><sub><b>Ihor Panasiuk</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=skynetigor" title="Code">💻</a></td>
</tr>
</tbody>
</table>
-1
View File
@@ -20,7 +20,6 @@ awk '/ALL-CONTRIBUTORS-LIST:START/{flag=1;next}/ALL-CONTRIBUTORS-LIST:END/{flag=
# create docs/themes/navy/layout/partial/financial-contributors.swig
awk '/FINANCIAL-CONTRIBUTORS-BEGIN/{flag=1;next}/FINANCIAL-CONTRIBUTORS-END/{flag=0}flag' README.md | \
sed 's/<br \/>.*<\/td>/<\/a><\/td>/g' | \
sed 's/width="[^"]*"//g' | \
tr -d '\n' | \
sed 's/<\/tr>\s*<tr>//g' \
> docs/themes/navy/layout/partial/financial-contributors.swig
+1 -1
View File
@@ -4,7 +4,7 @@ title: Echo
{% since %}v9.31.0{% endsince %}
Outputs an expression in the rendered HTML. This is identical to wrapping an expression in `{{` and `}}`, but works inside liquid tags and supports filters.
Outputs an expression in the rendered HTML. This is identical to wrapping an expression in <code>{{</code> and <code>}}</code>, but works inside liquid tags and supports filters.
## echo
@@ -20,7 +20,11 @@ Getting started and building is described in [CONTRIBUTING.md](https://github.co
## Financial Support
LiquidJS is Open Source and Free. To help it live and thrive, especially when LiquidJS is benefiting your business, please consider contribute on [GitHub Sponsors](https://github.com/sponsors/harttle) or [Open Collective][oc]. If I'm missing anything, find me via Twitter (harttleharttle) or email (harttleharttle at gmail), to add you into [the contributors table](https://github.com/harttle/liquidjs#contributors-).
LiquidJS is Open Source and Free. To help it live and thrive, especially when LiquidJS is benefiting your business, please consider contribute on [GitHub Sponsors](https://github.com/sponsors/harttle) or [Open Collective][oc].
I'll add all financial contributors into [README.md](https://github.com/harttle/liquidjs#financial-support) and it'll be also shown on https://liquidjs.com after next GitHub Actions build.
If I'm missing anything or you observed it not working, please don't hesitate to file an issue or find me via email (harttleharttle at gmail).
[oc]: https://opencollective.com/liquidjs/contribute/backer-10665/checkout
[shopify/liquid]: https://shopify.github.io/liquid/
+2 -2
View File
@@ -116,7 +116,7 @@ it defaults to false. For example, when set to true, a blank string would evalu
**preserveTimezones** is a boolean effects only literal timestamps. When set to `true`, all literal timestamps will remain the same when output. This is a parser option, so Date objects passed to LiquidJS as data will not be affected. Note that `preserveTimezones` has a higher priority than `timezoneOffset`.
**dateFormat** is used to specify a default format to output dates. `%A, %B %-e, %Y at %-l:%M %P %z` will be used if not specified. For example, set `dateFormat: %Y-%m-%dT%H:%M:%S:%LZ` to output all dates in [JavaScript Date.toJson()][https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON] format.
**dateFormat** is used to specify a default format to output dates. `%A, %B %-e, %Y at %-l:%M %P %z` will be used if not specified. For example, set `dateFormat: %Y-%m-%dT%H:%M:%S:%LZ` to output all dates in [JavaScript Date.toJson()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON) format.
## Trimming
@@ -146,7 +146,7 @@ Nonexistent tags always throw errors during parsing and this behavior cannot be
## Parameter Order
Parameter orders are ignored by default, for ea `{% for i in (1..8) reversed limit:3 %}` will always perform `limit` before `reversed`, even if `reversed` occurs before `limit`. To make parameter order respected, set **orderedFilterParameters** to `true`. Its default value is `false`.
Parameter orders are ignored by default, for example `{% for i in (1..8) reversed limit:3 %}` will always perform `limit` before `reversed`, even if `reversed` occurs before `limit`. To make parameter order respected, set **orderedFilterParameters** to `true`. Its default value is `false`.
[liquid]: /api/classes/Liquid.html
[caching]: ./caching.html
@@ -10,7 +10,7 @@ import { Value, TagToken, Context, Emitter, TopLevelToken } from 'liquidjs'
engine.registerTag('upper', {
parse: function(tagToken: TagToken, remainTokens: TopLevelToken[]) {
this.value = new Value(token.args, liquid)
this.value = new Value(tagToken.args, engine)
},
render: function*(ctx: Context) {
const str = yield this.value.value(ctx); // 'alice'
@@ -80,4 +80,4 @@ function disabledFilter(name) {
}
}
engine.registerFilter('plus', disabledFilter('plus'));
```
```
+1 -1
View File
@@ -16,6 +16,6 @@ LiquidJS 运算符非常简单也很特别,只支持两类运算符:
## 结合性
逻辑运算符是结合的,所以连续的逻辑运算时计算顺序是从右向左,参考 [Shopify][operator-order] 的文档。
逻辑运算符是结合的,所以连续的逻辑运算时计算顺序是从右向左,参考 [Shopify][operator-order] 的文档。
[operator-order]: https://help.shopify.com/en/themes/liquid/basics/operators#order-of-operations
+15 -15
View File
@@ -1,5 +1,5 @@
<header id="banner" class="wrapper">
<div class="inner">
<div class="inner inner-content">
<h2 id="banner-title">{{ page.subtitle }}</h2>
<div id="banner-start">
<code id="banner-start-command">npm install liquidjs</code><a id="banner-start-link" href="./tutorials/setup.html"><i class="icon-arrow-right"></i></a>
@@ -9,7 +9,7 @@
</header>
<div id="intro-news-list">
<div class="wrapper">
<div class="inner">
<div class="inner inner-content">
<div id="intro-news-flex">
{% for news in site.data.news %}
<a href="{{news.url}}" class="intro-news-wrap">
@@ -23,7 +23,7 @@
</div>
<div id="content-wrap">
<div class="wrapper">
<div class="inner">
<div class="inner inner-content">
{{ page.content }}
<div id="intro-cmd-wrap" class="highlight typescript"><pre><span class="line"><span class="keyword">import</span> { Liquid } <span class="keyword">from</span> <span class="string">'liquidjs'</span></span><br><span class="line"><span class="keyword">const</span> engine = <span class="keyword">new</span> Liquid()</span><br><span class="line"><span class="keyword">const</span> tpl = engine.parse(<span class="string">'Welcome to {% raw %}{{v}}{% endraw %}!'</span>)</span><br><span class="line">engine.render(tpl, {<span class="attr">v</span>: <span class="string">"Liquid"</span>}).then(<span class="built_in">console</span>.log)</span><br><span class="line"><span class="comment">// Outputs "Welcome to Liquid!"</span></span><br></pre></div>
<div id="intro-get-started-wrap">
@@ -32,20 +32,9 @@
</div>
</div>
</div>
<div id="contributors-wrap">
<div class="wrapper">
<div class="inner">
<h3>{{__('index.contributors.title')}}</h3>
<p class="description">{{__('index.contributors.description')}}</p>
<div class="contributors">
{{ partial('partial/all-contributors') }}
</div>
</div>
</div>
</div>
<div id="sponsors-wrap">
<div class="wrapper">
<div class="inner">
<div class="inner inner-content">
<h3>{{__('index.sponsors.title')}}</h3>
<p class="description">{{__('index.sponsors.description')}}</p>
<div class="contributors">
@@ -54,3 +43,14 @@
</div>
</div>
</div>
<div id="contributors-wrap">
<div class="wrapper">
<div class="inner inner-content">
<h3>{{__('index.contributors.title')}}</h3>
<p class="description">{{__('index.contributors.description')}}</p>
<div class="contributors">
{{ partial('partial/all-contributors') }}
</div>
</div>
</div>
</div>
+5 -1
View File
@@ -54,7 +54,11 @@ a
.inner
@media screen
padding: 0 gutter-width
margin: 0 gutter-width
.inner.inner-content
margin: 0 32px
@media mq-tablet
margin: 0 48px
#content-wrap
background: var(--color-content-bg)
+21 -17
View File
@@ -66,6 +66,10 @@
.intro-news-wrap
padding: 24px 30px
text-decoration: none
&:first-child
padding-left: 0
&:last-child
padding-right: 0
&:hover
background-color: var(--color-link-hover)
@media mq-normal
@@ -105,7 +109,7 @@
text-align: center
@media mq-normal
text-align: left
padding-left: 70px
padding-left: 48px
.intro-feature-icon
color: var(--color-link)
@@ -116,7 +120,7 @@
margin-bottom: 26px
position: absolute
top: 0
left: 20px
left: 0
font-size: 24px
width: @font-size
@@ -177,9 +181,11 @@
border-bottom: 1px solid #161d24
margin: -1px 0
.inner
margin: 48px 16px
margin-top: 48px
margin-bottom: 48px
@media mq-tablet
margin: 64px 32px
margin-top: 64px
margin-bottom: 64px
h3
color: #fff
font-size: 32px
@@ -192,20 +198,7 @@
text-decoration: none
#contributors-wrap
.description a
color: #fff
&:hover
background: #fff
color: var(--color-navy-lighter)
#sponsors-wrap
border: none
text-align: right
background: var(--color-content-bg)
overflow: hidden;
.contributors
display: flex;
justify-content: right;
.inner
h3
color: var(--color-default)
@@ -227,10 +220,20 @@
background: #fff
color: var(--color-navy-lighter)
#sponsors-wrap
border: none
overflow: hidden;
.description a
color: #fff
&:hover
background: #fff
color: var(--color-navy-lighter)
.contributors
tr
display: flex
flex-wrap: wrap
justify-content: center;
td
margin: 10px 2px 0
a img
@@ -240,3 +243,4 @@
background: var(--color-gray)
border-radius: 50%
margin-bottom: 10px
object-fit: contain
+8340 -4794
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "liquidjs",
"version": "10.21.0",
"version": "10.23.0",
"sideEffects": false,
"description": "A simple, expressive and safe Shopify / Github Pages compatible template engine in pure JavaScript.",
"main": "dist/liquid.node.js",
@@ -12,7 +12,7 @@
},
"types": "dist/index.d.ts",
"engines": {
"node": ">=14"
"node": ">=16"
},
"scripts": {
"lint": "eslint \"**/*.mjs\" \"**/*.ts\" .",
+14 -14
View File
@@ -86,7 +86,7 @@ export class Context {
public * _getFromScope (scope: unknown, paths: (PropertyKey | Drop)[] | string, strictVariables = this.strictVariables): IterableIterator<unknown> {
if (isString(paths)) paths = paths.split('.')
for (let i = 0; i < paths.length; i++) {
scope = yield readProperty(scope as object, paths[i], this.ownPropertyOnly)
scope = yield this.readProperty(scope as object, paths[i])
if (strictVariables && isUndefined(scope)) {
throw new InternalUndefinedVariableError((paths as string[]).slice(0, i + 1).join!('.'))
}
@@ -120,21 +120,21 @@ export class Context {
if (key in this.environments) return this.environments
return this.globals
}
readProperty (obj: Scope, key: (PropertyKey | Drop)) {
obj = toLiquid(obj)
key = toValue(key) as PropertyKey
if (isNil(obj)) return obj
if (isArray(obj) && (key as number) < 0) return obj[obj.length + +key]
const value = readJSProperty(obj, key, this.ownPropertyOnly)
if (value === undefined && obj instanceof Drop) return obj.liquidMethodMissing(key, this)
if (isFunction(value)) return value.call(obj)
if (key === 'size') return readSize(obj)
else if (key === 'first') return readFirst(obj)
else if (key === 'last') return readLast(obj)
return value
}
}
export function readProperty (obj: Scope, key: (PropertyKey | Drop), ownPropertyOnly: boolean) {
obj = toLiquid(obj)
key = toValue(key) as PropertyKey
if (isNil(obj)) return obj
if (isArray(obj) && (key as number) < 0) return obj[obj.length + +key]
const value = readJSProperty(obj, key, ownPropertyOnly)
if (value === undefined && obj instanceof Drop) return obj.liquidMethodMissing(key)
if (isFunction(value)) return value.call(obj)
if (key === 'size') return readSize(obj)
else if (key === 'first') return readFirst(obj)
else if (key === 'last') return readLast(obj)
return value
}
export function readJSProperty (obj: Scope, key: PropertyKey, ownPropertyOnly: boolean) {
if (ownPropertyOnly && !hasOwnProperty.call(obj, key) && !(obj instanceof Drop)) return undefined
return obj[key]
+6 -3
View File
@@ -1,9 +1,10 @@
import { Emitter, SimpleEmitter } from '../emitters'
import { Drop } from './drop'
export class BlockDrop extends Drop {
constructor (
// the block render from layout template
private superBlockRender: () => Iterable<any> = () => ''
private superBlockRender: (emitter: Emitter) => IterableIterator<unknown> | string = () => ''
) {
super()
}
@@ -11,7 +12,9 @@ export class BlockDrop extends Drop {
* Provide parent access in child block by
* {{ block.super }}
*/
public super () {
return this.superBlockRender()
public * super (): IterableIterator<unknown> {
const emitter = new SimpleEmitter()
yield this.superBlockRender(emitter)
return emitter.buffer
}
}
+3 -1
View File
@@ -1,5 +1,7 @@
import { Context } from '../context'
export abstract class Drop {
public liquidMethodMissing (key: string | number): Promise<any> | any {
public liquidMethodMissing (key: string | number, context: Context): Promise<any> | any {
return undefined
}
}
+13 -18
View File
@@ -1,24 +1,19 @@
import { toValue, argumentsToValue } from '../util/underscore'
import { toNumber, argumentsToNumber } from '../util/underscore'
export const abs = argumentsToValue(Math.abs)
export const at_least = argumentsToValue(Math.max)
export const at_most = argumentsToValue(Math.min)
export const ceil = argumentsToValue(Math.ceil)
export const divided_by = argumentsToValue((dividend: number, divisor: number, integerArithmetic = false) => integerArithmetic ? Math.floor(dividend / divisor) : dividend / divisor)
export const floor = argumentsToValue(Math.floor)
export const minus = argumentsToValue((v: number, arg: number) => v - arg)
export const modulo = argumentsToValue((v: number, arg: number) => v % arg)
export const times = argumentsToValue((v: number, arg: number) => v * arg)
export const abs = argumentsToNumber(Math.abs)
export const at_least = argumentsToNumber(Math.max)
export const at_most = argumentsToNumber(Math.min)
export const ceil = argumentsToNumber(Math.ceil)
export const divided_by = argumentsToNumber((dividend: number, divisor: number, integerArithmetic = false) => integerArithmetic ? Math.floor(dividend / divisor) : dividend / divisor)
export const floor = argumentsToNumber(Math.floor)
export const minus = argumentsToNumber((v: number, arg: number) => v - arg)
export const plus = argumentsToNumber((lhs: number, rhs: number) => lhs + rhs)
export const modulo = argumentsToNumber((v: number, arg: number) => v % arg)
export const times = argumentsToNumber((v: number, arg: number) => v * arg)
export function round (v: number, arg = 0) {
v = toValue(v)
arg = toValue(arg)
v = toNumber(v)
arg = toNumber(arg)
const amp = Math.pow(10, arg)
return Math.round(v * amp) / amp
}
export function plus (v: number, arg: number) {
v = toValue(v)
arg = toValue(arg)
return Number(v) + Number(arg)
}
+1
View File
@@ -8,6 +8,7 @@ export { defaultOperators, Operators, evalToken, evalQuotedToken, Expression, is
export { Context, Scope } from './context'
export { Value, Hash, Template, FilterImplOptions, Tag, Filter, Output, Variable, VariableLocation, VariableSegments, Variables, StaticAnalysis, StaticAnalysisOptions, analyze, analyzeSync, Arguments, PartialScope } from './template'
export { Token, TopLevelToken, TagToken, ValueToken } from './tokens'
export type { RangeToken, LiteralToken, QuotedToken, PropertyAccessToken, NumberToken } from './tokens'
export { TokenKind, Tokenizer, ParseStream, Parser } from './parser'
export { filters } from './filters'
export * from './tags'
+5 -1
View File
@@ -39,7 +39,11 @@ export default class extends Tag {
ctx.pop()
}
return renderChild
? (superBlock: BlockDrop, emitter: Emitter) => renderChild(new BlockDrop(() => renderCurrent(superBlock, emitter)), emitter)
? (superBlock: BlockDrop, emitter: Emitter) => renderChild(
new BlockDrop(
(emitter: Emitter) => renderCurrent(superBlock, emitter)
),
emitter)
: renderCurrent
}
+2 -3
View File
@@ -1,5 +1,4 @@
import { assert } from './assert'
import { toNumber } from './underscore'
export class Limiter {
private message: string
@@ -10,12 +9,12 @@ export class Limiter {
this.limit = limit
}
use (count: number) {
count = toNumber(count)
count = +count || 0
assert(this.base + count <= this.limit, this.message)
this.base += count
}
check (count: number) {
count = toNumber(count)
count = +count || 0
assert(count <= this.limit, this.message)
}
}
+5 -2
View File
@@ -67,8 +67,7 @@ export function toValue (value: any): any {
}
export function toNumber (value: any): number {
value = Number(value)
return isNaN(value) ? 0 : value
return +toValue(value) || 0
}
export function isNumber (value: any): value is number {
@@ -191,6 +190,10 @@ export function argumentsToValue<F extends (...args: any) => any, T> (fn: F) {
return function (this: T, ...args: Parameters<F>) { return fn.call(this, ...args.map(toValue)) }
}
export function argumentsToNumber<F extends (...args: any) => any, T> (fn: F) {
return function (this: T, ...args: Parameters<F>) { return fn.call(this, ...args.map(toNumber)) }
}
export function escapeRegExp (text: string) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
+28 -16
View File
@@ -1,25 +1,37 @@
import { Drop, Liquid } from '../..'
class SettingsDrop extends Drop {
public foo = 'FOO'
public bar () {
return 'BAR'
}
public liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
import { Context, Drop, Liquid } from '../..'
describe('drop', function () {
const settings = new SettingsDrop()
let engine: Liquid
beforeEach(function () {
engine = new Liquid()
})
it('should support liquidMethodMissing', async function () {
const src = `{{settings.foo}},{{settings.bar}},{{settings.coo}}`
const html = await engine.parseAndRender(src, { settings })
return expect(html).toBe('FOO,BAR,COO')
describe('liquidMethodMissing', () => {
it('should support liquidMethodMissing', async function () {
class SettingsDrop extends Drop {
public foo = 'FOO'
public bar () {
return 'BAR'
}
public liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
const src = `{{settings.foo}},{{settings.bar}},{{settings.coo}}`
const html = await engine.parseAndRender(src, { settings: new SettingsDrop() })
return expect(html).toBe('FOO,BAR,COO')
})
it('should expose context', async function () {
class SettingsDrop extends Drop {
public liquidMethodMissing (key: string, context: Context) {
return key + ':' + context.getSync([key])
}
}
const src = `{{settings.foo}}`
const html = await engine.parseAndRender(src, { settings: new SettingsDrop(), foo: 'FOO' })
return expect(html).toBe('foo:FOO')
})
})
describe('BlandDrop', function () {
+3 -2
View File
@@ -56,8 +56,9 @@ describe('filters/math', function () {
it('should return "20" for 16,4', () => test('{{ 16 | plus: 4 }}', '20'))
it('should return "195.357" for 183.357,12',
() => test('{{ 183.357 | plus: 12 }}', '195.357'))
it('should convert first arg as number', () => test('{{ "4" | plus: 2 }}', '6'))
it('should convert both args as number', () => test('{{ "4" | plus: "2" }}', '6'))
it('should convert first arg to number', () => test('{{ "4" | plus: 2 }}', '6'))
it('should convert both args to numbers', () => test('{{ "4" | plus: "2" }}', '6'))
it('should convert invalid string to 0', () => test('{{ "abc" | plus: "2" }}', '2'))
it('should support variable', () => test('{{ 4 | plus: b }}', { b: 2 }, '6'))
})
+20
View File
@@ -101,6 +101,26 @@ describe('tags/layout', function () {
const output = '<link href="base.css" rel="stylesheet"><link href="extra.css" rel="stylesheet">'
return expect(html).toBe(output)
})
it('should pass block.super as a string', async function () {
mock({
'/parent.html': '{% block css %}<link href="base.css" rel="stylesheet">{% endblock %}'
})
const src = '{% layout "parent.html" %}' +
'{%block css%}{{block.super}}<meta basesize={{block.super | size}}>{%endblock%}'
const html = await liquid.parseAndRender(src)
const output = '<link href="base.css" rel="stylesheet"><meta basesize=39>'
return expect(html).toBe(output)
})
it('should support block.super while strictVariables', async function () {
mock({
'/parent.html': '{% block css %}<link href="base.css" rel="stylesheet">{% endblock %}'
})
const src = '{% layout "parent.html" %}' +
'{%block css%}{{block.super}}<link href="extra.css" rel="stylesheet">{%endblock%}'
const html = await liquid.parseAndRender(src, undefined, { strictVariables: true })
const output = '<link href="base.css" rel="stylesheet"><link href="extra.css" rel="stylesheet">'
return expect(html).toBe(output)
})
it('should render block.super to empty if no parent exists', async function () {
mock({
'/parent.html': '{% block css %}{{block.super}}<link href="base.css" rel="stylesheet">{% endblock %}'