mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49c45a463b | ||
|
|
cef5d1aa1a | ||
|
|
6e6ea0ae58 | ||
|
|
dc9a6e019e | ||
|
|
5adebaa710 | ||
|
|
34d5af25a4 | ||
|
|
88c89fe3b3 | ||
|
|
e6f5f1cd85 | ||
|
|
570400ebcc | ||
|
|
3f5e23c42b | ||
|
|
96c061bee0 | ||
|
|
edb2cc1f37 | ||
|
|
2ae8c37a4f | ||
|
|
0bc5908f17 | ||
|
|
1ffba2bc76 | ||
|
|
bbebb5515c | ||
|
|
b14430a161 | ||
|
|
505c408a85 | ||
|
|
224679a7d7 | ||
|
|
2cb4bffd3e | ||
|
|
c940e6c997 | ||
|
|
d8ba009773 | ||
|
|
fdf0043b9c | ||
|
|
bef290923c | ||
|
|
4282accaa2 | ||
|
|
6075c0a54f | ||
|
|
87489f6098 | ||
|
|
6c5dc336e7 | ||
|
|
00bc1efe6a | ||
|
|
6fb4796202 | ||
|
|
7483613b23 | ||
|
|
7762dd9612 | ||
|
|
daa0b574fc | ||
|
|
a084183246 | ||
|
|
eadb6f3711 | ||
|
|
dba26f24e6 | ||
|
|
722da6a7ee | ||
|
|
82d7673554 | ||
|
|
64dd057552 | ||
|
|
45e3c2bb8e | ||
|
|
76345a64c3 | ||
|
|
9e69652655 | ||
|
|
defbb58e66 | ||
|
|
b7b92c63cf | ||
|
|
265534b7b7 | ||
|
|
84ea2c7488 | ||
|
|
64e0c876e9 | ||
|
|
4a8088d4e4 | ||
|
|
ad0930f152 | ||
|
|
998832c772 | ||
|
|
4ba224043b | ||
|
|
5ffc904f80 | ||
|
|
08646f75b0 | ||
|
|
3647305dcf | ||
|
|
cca0306f5b | ||
|
|
eeeacc4492 | ||
|
|
d44e1d727a | ||
|
|
f960904df4 | ||
|
|
b4acdb463a | ||
|
|
21d674e22b | ||
|
|
7bee9fc92d | ||
|
|
b69c3a3203 | ||
|
|
d5b9916b2f | ||
|
|
d0118402e4 | ||
|
|
31bc71d472 | ||
|
|
53a835ab54 | ||
|
|
75b3e15ca9 | ||
|
|
f34573ee21 | ||
|
|
875f71d5f2 | ||
|
|
407ac6d0a4 | ||
|
|
f9f35ebd6c | ||
|
|
88c9e96392 | ||
|
|
54b2adce12 | ||
|
|
542968e133 | ||
|
|
3b7351d9a0 | ||
|
|
e977669118 | ||
|
|
279458c670 | ||
|
|
37d12a14eb | ||
|
|
3cf01603e8 | ||
|
|
56c7992b76 | ||
|
|
5b6100d12b | ||
|
|
51f7e66f60 | ||
|
|
952ab6e73b |
+11
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "standard",
|
"extends": ["standard", "plugin:@typescript-eslint/recommended"],
|
||||||
"env": {
|
"env": {
|
||||||
"mocha": true,
|
"mocha": true,
|
||||||
"es6": true,
|
"es6": true,
|
||||||
@@ -17,6 +17,15 @@
|
|||||||
"no-var": 2,
|
"no-var": 2,
|
||||||
"prefer-const": 2,
|
"prefer-const": 2,
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }]
|
"indent": "off",
|
||||||
|
"@typescript-eslint/indent": ["error", 2],
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-object-literal-type-assertion": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"import/export": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ coverage/
|
|||||||
|
|
||||||
# modules
|
# modules
|
||||||
node_modules/
|
node_modules/
|
||||||
build/
|
dist/
|
||||||
|
|
||||||
# editors
|
# editors
|
||||||
.*.swp
|
.*.swp
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ language: node_js
|
|||||||
node_js:
|
node_js:
|
||||||
- "10"
|
- "10"
|
||||||
- "8"
|
- "8"
|
||||||
- "6"
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: test
|
- stage: test
|
||||||
|
|||||||
+160
@@ -1,3 +1,159 @@
|
|||||||
|
## [8.4.1](https://github.com/harttle/liquidjs/compare/v8.4.0...v8.4.1) (2019-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* some filters on undefined variable throws, [#140](https://github.com/harttle/liquidjs/issues/140) ([6e6ea0a](https://github.com/harttle/liquidjs/commit/6e6ea0a))
|
||||||
|
|
||||||
|
# [8.4.0](https://github.com/harttle/liquidjs/compare/v8.3.0...v8.4.0) (2019-07-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* at_least, at_most, sort_naturual for [#132](https://github.com/harttle/liquidjs/issues/132) ([e6f5f1c](https://github.com/harttle/liquidjs/commit/e6f5f1c))
|
||||||
|
|
||||||
|
# [8.3.0](https://github.com/harttle/liquidjs/compare/v8.2.4...v8.3.0) (2019-06-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* fs option implemented by [#138](https://github.com/harttle/liquidjs/issues/138) ([3f5e23c](https://github.com/harttle/liquidjs/commit/3f5e23c))
|
||||||
|
|
||||||
|
## [8.2.4](https://github.com/harttle/liquidjs/compare/v8.2.3...v8.2.4) (2019-06-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* improve getTemplate() when cache is enabled ([1ffba2b](https://github.com/harttle/liquidjs/commit/1ffba2b))
|
||||||
|
|
||||||
|
## [8.2.3](https://github.com/harttle/liquidjs/compare/v8.2.2...v8.2.3) (2019-05-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* reverse filter not pure, see [#126](https://github.com/harttle/liquidjs/issues/126) ([505c408](https://github.com/harttle/liquidjs/commit/505c408))
|
||||||
|
|
||||||
|
## [8.2.2](https://github.com/harttle/liquidjs/compare/v8.2.1...v8.2.2) (2019-05-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* date from integer, [#125](https://github.com/harttle/liquidjs/issues/125) ([fdf0043](https://github.com/harttle/liquidjs/commit/fdf0043))
|
||||||
|
* pass drops directly to filters/tags ([bef2909](https://github.com/harttle/liquidjs/commit/bef2909))
|
||||||
|
|
||||||
|
## [8.2.1](https://github.com/harttle/liquidjs/compare/v8.2.0...v8.2.1) (2019-04-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* `default` filter is not working with an empty string, [#122](https://github.com/harttle/liquidjs/issues/122) ([6075c0a](https://github.com/harttle/liquidjs/commit/6075c0a))
|
||||||
|
|
||||||
|
# [8.2.0](https://github.com/harttle/liquidjs/compare/v8.1.0...v8.2.0) (2019-04-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* pass context to filters ([00bc1ef](https://github.com/harttle/liquidjs/commit/00bc1ef))
|
||||||
|
|
||||||
|
# [8.1.0](https://github.com/harttle/liquidjs/compare/v8.0.3...v8.1.0) (2019-04-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* where filter, working on [#118](https://github.com/harttle/liquidjs/issues/118) ([daa0b57](https://github.com/harttle/liquidjs/commit/daa0b57))
|
||||||
|
|
||||||
|
## [8.0.3](https://github.com/harttle/liquidjs/compare/v8.0.2...v8.0.3) (2019-04-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* slice filter on negative `begin`, [#117](https://github.com/harttle/liquidjs/issues/117) ([eadb6f3](https://github.com/harttle/liquidjs/commit/eadb6f3))
|
||||||
|
|
||||||
|
## [8.0.2](https://github.com/harttle/liquidjs/compare/v8.0.1...v8.0.2) (2019-03-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* use polymophism instead duck test ([82d7673](https://github.com/harttle/liquidjs/commit/82d7673))
|
||||||
|
|
||||||
|
## [8.0.1](https://github.com/harttle/liquidjs/compare/v8.0.0...v8.0.1) (2019-03-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* incorrect scope when using assign with for, fixes [#115](https://github.com/harttle/liquidjs/issues/115) ([defbb58](https://github.com/harttle/liquidjs/commit/defbb58))
|
||||||
|
|
||||||
|
# [8.0.0](https://github.com/harttle/liquidjs/compare/v7.5.1...v8.0.0) (2019-03-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* use camelCase for JavaScript APIs ([64e0c87](https://github.com/harttle/liquidjs/commit/64e0c87))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* promise support for drops, working on [#65](https://github.com/harttle/liquidjs/issues/65) ([4a8088d](https://github.com/harttle/liquidjs/commit/4a8088d))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* Options and method names in JavaScript API are now renamed to cammelCase, for a complete list see #109
|
||||||
|
|
||||||
|
## [7.5.1](https://github.com/harttle/liquidjs/compare/v7.5.0...v7.5.1) (2019-03-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* named params for filters, working on [#113](https://github.com/harttle/liquidjs/issues/113) ([5ffc904](https://github.com/harttle/liquidjs/commit/5ffc904))
|
||||||
|
|
||||||
|
# [7.5.0](https://github.com/harttle/liquidjs/compare/v7.4.0...v7.5.0) (2019-03-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* tablerowloop object ([3647305](https://github.com/harttle/liquidjs/commit/3647305))
|
||||||
|
|
||||||
|
# [7.4.0](https://github.com/harttle/liquidjs/compare/v7.3.1...v7.4.0) (2019-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* math filters now return number, resolves [#110](https://github.com/harttle/liquidjs/issues/110) ([b4acdb4](https://github.com/harttle/liquidjs/commit/b4acdb4))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* exported Drop interface for [#107](https://github.com/harttle/liquidjs/issues/107) ([7bee9fc](https://github.com/harttle/liquidjs/commit/7bee9fc)), closes [#109](https://github.com/harttle/liquidjs/issues/109)
|
||||||
|
|
||||||
|
## [7.3.1](https://github.com/harttle/liquidjs/compare/v7.3.0...v7.3.1) (2019-02-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **#108:** remove absolute path in emitted d.ts ([53a835a](https://github.com/harttle/liquidjs/commit/53a835a)), closes [#108](https://github.com/harttle/liquidjs/issues/108)
|
||||||
|
|
||||||
|
# [7.3.0](https://github.com/harttle/liquidjs/compare/v7.2.2...v7.3.0) (2019-02-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* nil/null/empty/blank literals, resolves [#102](https://github.com/harttle/liquidjs/issues/102) ([88c9e96](https://github.com/harttle/liquidjs/commit/88c9e96))
|
||||||
|
|
||||||
|
## [7.2.2](https://github.com/harttle/liquidjs/compare/v7.2.1...v7.2.2) (2019-02-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* filters break when argument contains [()|, fixes [#89](https://github.com/harttle/liquidjs/issues/89) ([e977669](https://github.com/harttle/liquidjs/commit/e977669))
|
||||||
|
|
||||||
|
## [7.2.1](https://github.com/harttle/liquidjs/compare/v7.2.0...v7.2.1) (2019-02-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* default length for truncate and truncatewords ([56c7992](https://github.com/harttle/liquidjs/commit/56c7992))
|
||||||
|
|
||||||
# [7.2.0](https://github.com/harttle/liquidjs/compare/v7.1.0...v7.2.0) (2019-02-20)
|
# [7.2.0](https://github.com/harttle/liquidjs/compare/v7.1.0...v7.2.0) (2019-02-20)
|
||||||
|
|
||||||
|
|
||||||
@@ -5,6 +161,10 @@
|
|||||||
|
|
||||||
* override output/tag delimiter, fixes [#54](https://github.com/harttle/liquidjs/issues/54) ([d20a043](https://github.com/harttle/liquidjs/commit/d20a043))
|
* override output/tag delimiter, fixes [#54](https://github.com/harttle/liquidjs/issues/54) ([d20a043](https://github.com/harttle/liquidjs/commit/d20a043))
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* `trim_value_left` option renamed to `trim_output_left`, `trim_value_right` option renamed to `trim_output_right`
|
||||||
|
|
||||||
# [7.1.0](https://github.com/harttle/liquidjs/compare/v7.0.2...v7.1.0) (2019-02-20)
|
# [7.1.0](https://github.com/harttle/liquidjs/compare/v7.0.2...v7.1.0) (2019-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,51 +12,61 @@
|
|||||||
[](http://github.com/harttle/liquidjs)
|
[](http://github.com/harttle/liquidjs)
|
||||||
[](https://github.com/harttle/liquidjs)
|
[](https://github.com/harttle/liquidjs)
|
||||||
|
|
||||||
This is a liquid implementation for both Node.js and browsers. Website: <http://harttle.github.io/liquidjs/>, Live Demo: <https://jsfiddle.net/6u40xbzs/>
|
A [shopify][shopify/liquid] compatible [Liquid][tutorial] template engine in pure JavaScript. Install via npm:
|
||||||
|
|
||||||
**Features**
|
```bash
|
||||||
|
npm install --save liquidjs
|
||||||
|
```
|
||||||
|
|
||||||
* Fully compatible to [shopify][shopify/liquid], with all [tags][tags] and [filters][filters] implemented
|
Or include the UMD build (You may need a [Promise polyfill][pp] for Node.js < 4 and ES5 browsers like [IE and Android UC][caniuse-promises]):
|
||||||
* Support layout(extend) and include syntax
|
|
||||||
* In pure JavaScript with Promise-based API
|
|
||||||
|
|
||||||
**Differences**
|
```html
|
||||||
|
<script src="//unpkg.com/liquidjs/dist/liquid.min.js"></script> <!--for production-->
|
||||||
|
<script src="//unpkg.com/liquidjs/dist/liquid.js"></script> <!--for development-->
|
||||||
|
```
|
||||||
|
|
||||||
Though being compatible with [Ruby Liquid](https://github.com/shopify/liquid) is one of our priorities, there're still certain differences. You may need some configuration to get it compatible in these senarios:
|
**The purpose of this repo** is to provide a standard Liquid implementation for the JavaScript community.
|
||||||
|
All features, filters and tags in [shopify/liquid](https://github.com/Shopify/liquid) are supposed to be supported here,
|
||||||
|
though there are still some differences:
|
||||||
|
|
||||||
* Dynamic file locating (enabled by default), which means layout/partial name can be an variable in liquidjs. See [#51](https://github.com/harttle/liquidjs/issues/51).
|
* Dynamic file locating (enabled by default), that means layout/partial names are treated as variables in liquidjs. See [#51](https://github.com/harttle/liquidjs/issues/51).
|
||||||
* Truthy and Falsy. All values except `undefined`, `null`, `false` are truthy, whereas in Ruby Liquid all except `nil` and `false` are truthy. See [#26](https://github.com/harttle/liquidjs/pull/26).
|
* Truthy and Falsy. All values except `undefined`, `null`, `false` are truthy, whereas in Ruby Liquid all except `nil` and `false` are truthy. See [#26](https://github.com/harttle/liquidjs/pull/26).
|
||||||
* Number Rendering. Since JavaScript do not distinguish `float` and `integer`, we cannot either convert between them nor render regarding to their type. See [#59](https://github.com/harttle/liquidjs/issues/59).
|
* Number. In JavaScript we cannot distinguish or convert between `float` and `integer`, see [#59](https://github.com/harttle/liquidjs/issues/59). And when applied `size` filter, numbers always return 0, which is 8 for integer in ruby, cause they do not have a `length` property.
|
||||||
* [.to_liquid()](https://github.com/Shopify/liquid/wiki/Introduction-to-Drops) has a `.toLiquid()` alias and and the JavaScript `.toString()` is aliased to `.to_s()`.
|
* [.to_liquid()](https://github.com/Shopify/liquid/wiki/Introduction-to-Drops) is replaced by `.toLiquid()`
|
||||||
* [.to_s()](https://www.rubydoc.info/gems/liquid/Liquid/Drop) uses `JSON.prototype.stringify` as default, rather than Ruby's inspect.
|
* [.to_s()](https://www.rubydoc.info/gems/liquid/Liquid/Drop) is replaced by JavaScript `.toString()`
|
||||||
|
|
||||||
|
Features that available on shopify website but not on shopify/liquid repo will not be implemented in this repo,
|
||||||
|
but there're some plugins available (feel free to add yours):
|
||||||
|
|
||||||
|
* color filters: https://github.com/harttle/liquidjs-color-filters
|
||||||
|
* sections tags (WIP): https://github.com/harttle/liquidjs-section-tags
|
||||||
|
|
||||||
## TOC
|
## TOC
|
||||||
|
|
||||||
* Usage
|
* Get Started
|
||||||
* [Render from String](#render-from-string)
|
* [Render from String](#render-from-string)
|
||||||
* [Render from File](#render-from-file)
|
* [Render from File](#render-from-file)
|
||||||
* [Use with Express.js](#use-with-expressjs)
|
* [Use with Express.js](#use-with-expressjs)
|
||||||
* [Use in Browser](#use-in-browser)
|
|
||||||
* [Include Partials](#include-partials)
|
* [Include Partials](#include-partials)
|
||||||
* [Layout Templates (Extends)](#layout-templates-extends)
|
* [Layout Templates (Extends)](#layout-templates-extends)
|
||||||
* API Spec
|
* Demos
|
||||||
* [Constructor Options](#options)
|
* Node.js: [/demo/node/](demo/node/)
|
||||||
|
* Browser: <https://jsfiddle.net/6u40xbzs/>, [/demo/browser/](demo/browser/).
|
||||||
|
* Express.js: [/demo/express/](demo/express/)
|
||||||
|
* TypeScript: [/demo/typescript/](demo/typescript/)
|
||||||
|
* React JS: [/demo/reactjs/](demo/reactjs/)
|
||||||
|
* Advanced
|
||||||
|
* [Options](#options)
|
||||||
* [Register Filters](#register-filters), [Builtin Filters](https://github.com/harttle/liquidjs/wiki/Builtin-Filters)
|
* [Register Filters](#register-filters), [Builtin Filters](https://github.com/harttle/liquidjs/wiki/Builtin-Filters)
|
||||||
* [Register Tags](#register-tags), [Builtin Tags](https://github.com/harttle/liquidjs/wiki/Builtin-Tags)
|
* [Register Tags](#register-tags), [Builtin Tags](https://github.com/harttle/liquidjs/wiki/Builtin-Tags)
|
||||||
* [Operators](https://github.com/harttle/liquidjs/wiki/Operators)
|
* [Operators](https://github.com/harttle/liquidjs/wiki/Operators)
|
||||||
* [Whitespace Control](https://github.com/harttle/liquidjs/wiki/Whitespace-Control)
|
* [Whitespace Control](https://github.com/harttle/liquidjs/wiki/Whitespace-Control)
|
||||||
|
* [Plugin API](#plugin-api)
|
||||||
* [Contribute Guidelines](#contribute-guidelines)
|
* [Contribute Guidelines](#contribute-guidelines)
|
||||||
|
|
||||||
## Render from String
|
## Render from String
|
||||||
|
|
||||||
Install as Node.js dependency:
|
Just render a template string with a context:
|
||||||
|
|
||||||
```bash
|
|
||||||
# You'll need a promise-polyfill for Node.js < 4
|
|
||||||
npm install --save liquidjs
|
|
||||||
```
|
|
||||||
|
|
||||||
Parse and Render:
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var Liquid = require('liquidjs');
|
var Liquid = require('liquidjs');
|
||||||
@@ -64,35 +74,27 @@ var engine = new Liquid();
|
|||||||
|
|
||||||
engine
|
engine
|
||||||
.parseAndRender('{{name | capitalize}}', {name: 'alice'})
|
.parseAndRender('{{name | capitalize}}', {name: 'alice'})
|
||||||
.then(console.log);
|
.then(console.log); // outputs 'Alice'
|
||||||
|
|
||||||
// outputs 'Alice'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Caching templates:
|
Caching parsed templates:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var tpl = engine.parse('{{name | capitalize}}');
|
var tpl = engine.parse('{{name | capitalize}}');
|
||||||
engine
|
engine
|
||||||
.render(tpl, {name: 'alice'})
|
.render(tpl, {name: 'alice'})
|
||||||
.then(console.log);
|
.then(console.log); // outputs 'Alice'
|
||||||
|
|
||||||
// outputs 'Alice'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Render from File
|
## Render from File
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var engine = new Liquid({
|
var engine = new Liquid({
|
||||||
root: path.resolve(__dirname, 'views/'), // dirs to lookup layouts/includes
|
root: path.resolve(__dirname, 'views/'), // root for layouts/includes lookup
|
||||||
extname: '.liquid' // the extname used for layouts/includes, defaults ""
|
extname: '.liquid' // used for layouts/includes, defaults ""
|
||||||
});
|
});
|
||||||
engine.renderFile("hello.liquid", {name: 'alice'})
|
|
||||||
.then(console.log) // outputs "Alice"
|
|
||||||
|
|
||||||
// which is equivalent to:
|
|
||||||
engine
|
engine
|
||||||
.renderFile("hello", {name: 'alice'})
|
.renderFile("hello", {name: 'alice'}) // will read and render `views/hello.liquid`
|
||||||
.then(console.log) // outputs "Alice"
|
.then(console.log) // outputs "Alice"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -105,24 +107,9 @@ app.set('views', './views'); // specify the views directory
|
|||||||
app.set('view engine', 'liquid'); // set to default
|
app.set('view engine', 'liquid'); // set to default
|
||||||
```
|
```
|
||||||
|
|
||||||
[Here](demo/express/)'s an Express demo. When used with Express.js,
|
[`views`][express-views] in express.js will be included when looking up
|
||||||
Express [`views`][express-views] will be included when looking up
|
|
||||||
partials(includes and layouts).
|
partials(includes and layouts).
|
||||||
|
|
||||||
## Use in Browser
|
|
||||||
|
|
||||||
You can get a dist file for browsers from
|
|
||||||
|
|
||||||
* [Releases][releases] page for liquidjs, or
|
|
||||||
* unpkg.com: <https://unpkg.com/liquidjs/dist/liquid.min.js>
|
|
||||||
|
|
||||||
Here's the demo:
|
|
||||||
|
|
||||||
* JSFiddle: <https://jsfiddle.net/6u40xbzs/>
|
|
||||||
* Demo directory: [/demo/browser/](demo/browser/).
|
|
||||||
|
|
||||||
Note: For [IE and Android UC][caniuse-promises] browser, you will need a [Promise polyfill][pp].
|
|
||||||
|
|
||||||
## Include Partials
|
## Include Partials
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -182,25 +169,27 @@ Defaults to `["."]`
|
|||||||
|
|
||||||
* `dynamicPartials`: if set, treat `<filepath>` parameter in `{%include filepath %}`, `{%layout filepath%}` as a variable, otherwise as a literal value. Defaults to `true`.
|
* `dynamicPartials`: if set, treat `<filepath>` parameter in `{%include filepath %}`, `{%layout filepath%}` as a variable, otherwise as a literal value. Defaults to `true`.
|
||||||
|
|
||||||
* `strict_filters` is used to enable strict filter existence. If set to `false`, undefined filters will be rendered as empty string. Otherwise, undefined filters will cause an exception. Defaults to `false`.
|
* `strictFilters` is used to enable strict filter existence. If set to `false`, undefined filters will be rendered as empty string. Otherwise, undefined filters will cause an exception. Defaults to `false`.
|
||||||
|
|
||||||
* `strict_variables` is used to enable strict variable derivation.
|
* `strictVariables` is used to enable strict variable derivation.
|
||||||
If set to `false`, undefined variables will be rendered as empty string.
|
If set to `false`, undefined variables will be rendered as empty string.
|
||||||
Otherwise, undefined variables will cause an exception. Defaults to `false`.
|
Otherwise, undefined variables will cause an exception. Defaults to `false`.
|
||||||
|
|
||||||
* `trim_tag_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`.
|
* `trimTagRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`.
|
||||||
|
|
||||||
* `trim_tag_left` is similiar to `trim_tag_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
* `trimTagLeft` is similiar to `trimTagRight`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
||||||
|
|
||||||
* `trim_output_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`.
|
* `trimOutputRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`.
|
||||||
|
|
||||||
* `trim_output_left` is similiar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
* `trimOutputLeft` is similiar to `trimOutputRight`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
||||||
|
|
||||||
* `tag_delimiter_left` and `tag_delimiter_right` are used to override the delimiter for liquid tags.
|
* `tagDelimiterLeft` and `tagDelimiterRight` are used to override the delimiter for liquid tags.
|
||||||
|
|
||||||
* `output_delimiter_left` and `output_delimiter_right` are used to override the delimiter for liquid outputs.
|
* `outputDelimiterLeft` and `outputDelimiterRight` are used to override the delimiter for liquid outputs.
|
||||||
|
|
||||||
* `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`.
|
* `greedy` is used to specify whether `trim*Left`/`trim*Right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`.
|
||||||
|
|
||||||
|
* `fs` is used to override the default file-system module with a custom implementation.
|
||||||
|
|
||||||
## Register Filters
|
## Register Filters
|
||||||
|
|
||||||
@@ -226,9 +215,9 @@ engine.registerTag('upper', {
|
|||||||
parse: function(tagToken, remainTokens) {
|
parse: function(tagToken, remainTokens) {
|
||||||
this.str = tagToken.args; // name
|
this.str = tagToken.args; // name
|
||||||
},
|
},
|
||||||
render: function(scope, hash) {
|
render: async function(scope, hash) {
|
||||||
var str = Liquid.evalValue(this.str, scope); // 'alice'
|
var str = await Liquid.evalValue(this.str, scope); // 'alice'
|
||||||
return Promise.resolve(str.toUpperCase()); // 'Alice'
|
return str.toUpperCase() // 'Alice'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -253,10 +242,6 @@ module.exports = function (Liquid) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Plugin List:
|
|
||||||
|
|
||||||
* To add your plugin, contact me or simply send a PR.
|
|
||||||
|
|
||||||
## Contribute Guidelines
|
## Contribute Guidelines
|
||||||
|
|
||||||
This repo uses [eslint](https://eslint.org/) to check code style, [semantic-release](https://github.com/semantic-release/semantic-release) to generate changelog and publish to npm and Github Releases.
|
This repo uses [eslint](https://eslint.org/) to check code style, [semantic-release](https://github.com/semantic-release/semantic-release) to generate changelog and publish to npm and Github Releases.
|
||||||
@@ -269,7 +254,6 @@ This repo uses [eslint](https://eslint.org/) to check code style, [semantic-rele
|
|||||||
[shopify/liquid]: https://shopify.github.io/liquid/
|
[shopify/liquid]: https://shopify.github.io/liquid/
|
||||||
[jekyll]: http://jekyllrb.com/
|
[jekyll]: http://jekyllrb.com/
|
||||||
[gh]: https://pages.github.com/
|
[gh]: https://pages.github.com/
|
||||||
[releases]: https://github.com/harttle/liquidjs/releases
|
|
||||||
[any-promise]: https://github.com/kevinbeaty/any-promise
|
[any-promise]: https://github.com/kevinbeaty/any-promise
|
||||||
[test]: https://github.com/harttle/liquidjs/tree/master/test
|
[test]: https://github.com/harttle/liquidjs/tree/master/test
|
||||||
[caniuse-promises]: http://caniuse.com/#feat=promises
|
[caniuse-promises]: http://caniuse.com/#feat=promises
|
||||||
@@ -278,3 +262,4 @@ This repo uses [eslint](https://eslint.org/) to check code style, [semantic-rele
|
|||||||
[filters]: https://github.com/harttle/liquidjs/wiki/Builtin-Filters
|
[filters]: https://github.com/harttle/liquidjs/wiki/Builtin-Filters
|
||||||
[express-views]: http://expressjs.com/en/guide/using-template-engines.html
|
[express-views]: http://expressjs.com/en/guide/using-template-engines.html
|
||||||
[pp]: https://github.com/taylorhakes/promise-polyfill
|
[pp]: https://github.com/taylorhakes/promise-polyfill
|
||||||
|
[tutorial]: https://shopify.github.io/liquid/basics/introduction/
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"no-unused-expressions": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import * as Benchmark from 'benchmark'
|
||||||
|
import Liquid from '../src/liquid'
|
||||||
|
import TagToken from '../src/parser/tag-token'
|
||||||
|
import Context from '../src/context/context'
|
||||||
|
|
||||||
|
const engine = new Liquid({
|
||||||
|
root: __dirname,
|
||||||
|
extname: '.liquid'
|
||||||
|
})
|
||||||
|
|
||||||
|
engine.registerTag('header', {
|
||||||
|
parse: function (token: TagToken) {
|
||||||
|
const [key, val] = token.args.split(':')
|
||||||
|
this[key] = val
|
||||||
|
},
|
||||||
|
render: function (ctx: Context) {
|
||||||
|
const title = this.liquid.evalValue(this.content, ctx)
|
||||||
|
return `<h1>${title}</h1>`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const ctx = {
|
||||||
|
todos: ['fork and clone', 'make it better', 'make a pull request'],
|
||||||
|
title: 'Welcome to liquidjs!'
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = `
|
||||||
|
{%header content: "welcome to liquid" | capitalize%}
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for todo in todos %}
|
||||||
|
<li>{{forloop.index}} - {{todo}}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
console.log('--- demo ---')
|
||||||
|
return new Promise(resolve => {
|
||||||
|
new Benchmark.Suite('demo')
|
||||||
|
.add('demo', {
|
||||||
|
defer: true,
|
||||||
|
fn: (d: any) => engine.parseAndRender(template, ctx).then(x => d.resolve(x))
|
||||||
|
})
|
||||||
|
.on('cycle', (event: any) => console.log(String(event.target)))
|
||||||
|
.on('complete', resolve)
|
||||||
|
.run({ 'async': true })
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import output from './output'
|
||||||
|
import tag from './tag'
|
||||||
|
import demo from './demo'
|
||||||
|
import layout from './layout'
|
||||||
|
|
||||||
|
async function main () {
|
||||||
|
await output()
|
||||||
|
await tag()
|
||||||
|
await demo()
|
||||||
|
await layout()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import * as Benchmark from 'benchmark'
|
||||||
|
import Liquid from '../src/liquid'
|
||||||
|
|
||||||
|
const engineOptions = {
|
||||||
|
root: __dirname,
|
||||||
|
extname: '.liquid'
|
||||||
|
}
|
||||||
|
|
||||||
|
const engine = new Liquid(engineOptions)
|
||||||
|
const cachingEngine = new Liquid({
|
||||||
|
...engineOptions,
|
||||||
|
cache: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const template = `
|
||||||
|
{% layout "./templates/layout.liquid" %}
|
||||||
|
{% block body %}a small body{% endblock %}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
console.log('--- layout ---')
|
||||||
|
return new Promise(resolve => {
|
||||||
|
new Benchmark.Suite('layout')
|
||||||
|
.add('cache=false', {
|
||||||
|
defer: true,
|
||||||
|
fn: (d: any) => engine.parseAndRender(template, {}).then(x => d.resolve(x))
|
||||||
|
})
|
||||||
|
.add('cache=true', {
|
||||||
|
defer: true,
|
||||||
|
fn: (d: any) => cachingEngine.parseAndRender(template, {}).then(x => d.resolve(x))
|
||||||
|
})
|
||||||
|
.on('cycle', (event: any) => console.log(String(event.target)))
|
||||||
|
.on('complete', resolve)
|
||||||
|
.run({ 'async': true })
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import * as Benchmark from 'benchmark'
|
||||||
|
import Liquid from '../src/liquid'
|
||||||
|
|
||||||
|
const liquid = new Liquid()
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
console.log('--- output ---')
|
||||||
|
return new Promise(resolve => {
|
||||||
|
new Benchmark.Suite('output')
|
||||||
|
.add('literal', test('{{false}}{{"foo"}}{{32.322}}'))
|
||||||
|
.add('truncate', test('{{"foobar" | truncate: 3}}'))
|
||||||
|
.add('date', test('{{"now" | date: "%d%Y%m"}}'))
|
||||||
|
.add('escape', test('{{"1<2" | escape}}'))
|
||||||
|
.add('default', test('{{"" | default: 3}}'))
|
||||||
|
.on('cycle', (event: any) => console.log(String(event.target)))
|
||||||
|
.on('complete', resolve)
|
||||||
|
.run({ 'async': true })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function test (str: string) {
|
||||||
|
return {
|
||||||
|
defer: true,
|
||||||
|
fn: (d: any) => liquid.parseAndRender(str).then(x => d.resolve(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import * as Benchmark from 'benchmark'
|
||||||
|
import Liquid from '../src/liquid'
|
||||||
|
|
||||||
|
const liquid = new Liquid()
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
console.log('--- tag ---')
|
||||||
|
return new Promise(resolve => {
|
||||||
|
new Benchmark.Suite('tag')
|
||||||
|
.add('if', test('{% if "foobar" %}foo{% endif %}'))
|
||||||
|
.add('unless', test('{%unless "foo"%}true{%else%}false{%endunless%}'))
|
||||||
|
.add('for', test('{% for i in (1..3) %}{{fooloop.index}}{% endfor %}'))
|
||||||
|
.add('switch', test('{%case 3%}{% when 1 %}1{% when 2 %}2{% when 3 %}3{%endcase%}'))
|
||||||
|
.add('assign', test('{%assign a="foo bar"%}'))
|
||||||
|
.add('capture', test('{%capture foo%}what is this{%endcapture%}'))
|
||||||
|
.add('increment', test('{%increment a%}'))
|
||||||
|
.add('decrement', test('{%decrement a%}'))
|
||||||
|
.add('tablerow', test('{%tablerow i in (1..10) cols:3%}{%endtablerow%}'))
|
||||||
|
.on('cycle', (event: any) => console.log(String(event.target)))
|
||||||
|
.on('complete', resolve)
|
||||||
|
.run({ 'async': true })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function test (str: string) {
|
||||||
|
return {
|
||||||
|
defer: true,
|
||||||
|
fn: (d: any) => liquid.parseAndRender(str).then(x => d.resolve(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
This is a barely empty layout with a body:
|
||||||
|
{% block body %}{% endblock %}
|
||||||
Vendored
-12
@@ -1,12 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'join': (v: any, arg: any) => any;
|
|
||||||
'last': (v: any) => any;
|
|
||||||
'first': (v: any) => any;
|
|
||||||
'map': (arr: any, arg: any) => any;
|
|
||||||
'reverse': (v: any) => any;
|
|
||||||
'sort': (v: any, arg: any) => any;
|
|
||||||
'size': (v: any) => any;
|
|
||||||
'slice': (v: any, begin: any, length: any) => any;
|
|
||||||
'uniq': (arr: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'date': (v: any, arg: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
declare function escape(str: any): string;
|
|
||||||
declare const _default: {
|
|
||||||
'escape': typeof escape;
|
|
||||||
'escape_once': (str: any) => string;
|
|
||||||
'newline_to_br': (v: any) => any;
|
|
||||||
'strip_html': (v: any) => string;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-46
@@ -1,46 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'join': (v: any, arg: any) => any;
|
|
||||||
'last': (v: any) => any;
|
|
||||||
'first': (v: any) => any;
|
|
||||||
'map': (arr: any, arg: any) => any;
|
|
||||||
'reverse': (v: any) => any;
|
|
||||||
'sort': (v: any, arg: any) => any;
|
|
||||||
'size': (v: any) => any;
|
|
||||||
'slice': (v: any, begin: any, length: any) => any;
|
|
||||||
'uniq': (arr: any) => any;
|
|
||||||
'default': (v: any, arg: any) => any;
|
|
||||||
'date': (v: any, arg: any) => any;
|
|
||||||
'url_decode': (x: any) => any;
|
|
||||||
'url_encode': (x: any) => any;
|
|
||||||
'abs': (v: any) => number;
|
|
||||||
'ceil': (v: any) => number;
|
|
||||||
'divided_by': (v: any, arg: any) => number;
|
|
||||||
'floor': (v: any) => number;
|
|
||||||
'minus': (l: any, r: any) => any;
|
|
||||||
'modulo': (l: any, r: any) => any;
|
|
||||||
'round': (v: any, arg: any) => number;
|
|
||||||
'plus': (l: any, r: any) => any;
|
|
||||||
'times': (v: any, arg: any) => number;
|
|
||||||
'append': (v: any, arg: any) => any;
|
|
||||||
'prepend': (v: any, arg: any) => any;
|
|
||||||
'capitalize': (str: any) => string;
|
|
||||||
'concat': (v: any, arg: any) => any;
|
|
||||||
'lstrip': (v: any) => string;
|
|
||||||
'downcase': (v: any) => any;
|
|
||||||
'upcase': (str: any) => string;
|
|
||||||
'remove': (v: any, arg: any) => any;
|
|
||||||
'remove_first': (v: any, l: any) => any;
|
|
||||||
'replace': (v: any, pattern: any, replacement: any) => string;
|
|
||||||
'replace_first': (v: any, arg1: any, arg2: any) => string;
|
|
||||||
'rstrip': (str: any) => string;
|
|
||||||
'split': (v: any, arg: any) => string[];
|
|
||||||
'strip': (v: any) => string;
|
|
||||||
'strip_newlines': (v: any) => string;
|
|
||||||
'truncate': (v: any, l: any, o: any) => any;
|
|
||||||
'truncatewords': (v: any, l: any, o: any) => any;
|
|
||||||
'escape': (str: any) => string;
|
|
||||||
'escape_once': (str: any) => string;
|
|
||||||
'newline_to_br': (v: any) => any;
|
|
||||||
'strip_html': (v: any) => string;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-12
@@ -1,12 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'abs': (v: any) => number;
|
|
||||||
'ceil': (v: any) => number;
|
|
||||||
'divided_by': (v: any, arg: any) => number;
|
|
||||||
'floor': (v: any) => number;
|
|
||||||
'minus': (l: any, r: any) => any;
|
|
||||||
'modulo': (l: any, r: any) => any;
|
|
||||||
'round': (v: any, arg: any) => number;
|
|
||||||
'plus': (l: any, r: any) => any;
|
|
||||||
'times': (v: any, arg: any) => number;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'default': (v: any, arg: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'append': (v: any, arg: any) => any;
|
|
||||||
'prepend': (v: any, arg: any) => any;
|
|
||||||
'capitalize': (str: any) => string;
|
|
||||||
'concat': (v: any, arg: any) => any;
|
|
||||||
'lstrip': (v: any) => string;
|
|
||||||
'downcase': (v: any) => any;
|
|
||||||
'upcase': (str: any) => string;
|
|
||||||
'remove': (v: any, arg: any) => any;
|
|
||||||
'remove_first': (v: any, l: any) => any;
|
|
||||||
'replace': (v: any, pattern: any, replacement: any) => string;
|
|
||||||
'replace_first': (v: any, arg1: any, arg2: any) => string;
|
|
||||||
'rstrip': (str: any) => string;
|
|
||||||
'split': (v: any, arg: any) => string[];
|
|
||||||
'strip': (v: any) => string;
|
|
||||||
'strip_newlines': (v: any) => string;
|
|
||||||
'truncate': (v: any, l: any, o: any) => any;
|
|
||||||
'truncatewords': (v: any, l: any, o: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
'url_decode': (x: any) => any;
|
|
||||||
'url_encode': (x: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (token: any) => void;
|
|
||||||
render: (scope: any) => Promise<string>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (token: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any) => Promise<any>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
render: () => Promise<never>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
import TagToken from 'src/parser/tag-token';
|
|
||||||
import Token from 'src/parser/token';
|
|
||||||
import Scope from 'src/scope/scope';
|
|
||||||
declare const _default: {
|
|
||||||
parse: (tagToken: TagToken, remainTokens: Token[]) => void;
|
|
||||||
render: (scope: Scope) => Promise<void>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
render: () => Promise<never>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any) => void;
|
|
||||||
render: (scope: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
import TagToken from 'src/parser/tag-token';
|
|
||||||
import Scope from 'src/scope/scope';
|
|
||||||
declare const _default: {
|
|
||||||
parse: (token: TagToken) => void;
|
|
||||||
render: (scope: Scope) => number;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
declare function parse(tagToken: any, remainTokens: any): void;
|
|
||||||
declare function render(scope: any, hash: any): Promise<any>;
|
|
||||||
declare const _default: {
|
|
||||||
parse: typeof parse;
|
|
||||||
render: typeof render;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (token: any) => void;
|
|
||||||
render: (scope: any, hash: any) => Promise<any>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (token: any) => void;
|
|
||||||
render: (scope: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
import ITagImplOptions from 'src/template/tag/itag-impl-options';
|
|
||||||
declare const tags: {
|
|
||||||
[key: string]: ITagImplOptions;
|
|
||||||
};
|
|
||||||
export default tags;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (token: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any, hash: any) => Promise<any>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
render: () => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any, hash: any) => Promise<string>;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare const _default: {
|
|
||||||
parse: (tagToken: any, remainTokens: any) => void;
|
|
||||||
render: (scope: any) => any;
|
|
||||||
};
|
|
||||||
export default _default;
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
import IFS from './ifs';
|
|
||||||
declare const _default: IFS;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
export default interface IFS {
|
|
||||||
exists: (filepath?: string) => Promise<boolean>;
|
|
||||||
readFile: (filepath: string) => Promise<string>;
|
|
||||||
resolve: (root: string, file: string, ext: string) => string;
|
|
||||||
}
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
import IFS from './ifs';
|
|
||||||
declare const fs: IFS;
|
|
||||||
export default fs;
|
|
||||||
Vendored
-48
@@ -1,48 +0,0 @@
|
|||||||
export interface LiquidOptions {
|
|
||||||
/** `root` is a directory or an array of directories to resolve layouts and includes, as well as the filename passed in when calling `.renderFile()`. If an array, the files are looked up in the order they occur in the array. Defaults to `["."]` */
|
|
||||||
root?: string | string[];
|
|
||||||
/** `extname` is used to lookup the template file when filepath doesn't include an extension name. Eg: setting to `".html"` will allow including file by basename. Defaults to `""`. */
|
|
||||||
extname?: string;
|
|
||||||
/** `cache` indicates whether or not to cache resolved templates. Defaults to `false`. */
|
|
||||||
cache?: boolean;
|
|
||||||
/** `dynamicPartials`: if set, treat `<filepath>` parameter in `{%include filepath %}`, `{%layout filepath%}` as a variable, otherwise as a literal value. Defaults to `true`. */
|
|
||||||
dynamicPartials?: boolean;
|
|
||||||
/** `strict_filters` is used to enable strict filter existence. If set to `false`, undefined filters will be rendered as empty string. Otherwise, undefined filters will cause an exception. Defaults to `false`. */
|
|
||||||
strict_filters?: boolean;
|
|
||||||
/** `strict_variables` is used to enable strict variable derivation. If set to `false`, undefined variables will be rendered as empty string. Otherwise, undefined variables will cause an exception. Defaults to `false`. */
|
|
||||||
strict_variables?: boolean;
|
|
||||||
/** `trim_tag_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`. */
|
|
||||||
trim_tag_right?: boolean;
|
|
||||||
/** `trim_tag_left` is similar to `trim_tag_right`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
|
|
||||||
trim_tag_left?: boolean;
|
|
||||||
/** ``trim_output_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`. */
|
|
||||||
trim_output_right?: boolean;
|
|
||||||
/** `trim_output_left` is similar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
|
|
||||||
trim_output_left?: boolean;
|
|
||||||
/** `tag_delimiter_left` and `tag_delimiter_right` are used to override the delimiter for liquid tags **/
|
|
||||||
tag_delimiter_left?: string;
|
|
||||||
tag_delimiter_right?: string;
|
|
||||||
/** `output_delimiter_left` and `output_delimiter_right` are used to override the delimiter for liquid outputs **/
|
|
||||||
output_delimiter_left?: string;
|
|
||||||
output_delimiter_right?: string;
|
|
||||||
/** `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`. */
|
|
||||||
greedy?: boolean;
|
|
||||||
}
|
|
||||||
export interface NormalizedOptions extends LiquidOptions {
|
|
||||||
root?: string[];
|
|
||||||
}
|
|
||||||
export interface NormalizedFullOptions extends NormalizedOptions {
|
|
||||||
root: string[];
|
|
||||||
extname: string;
|
|
||||||
cache: boolean;
|
|
||||||
dynamicPartials: boolean;
|
|
||||||
strict_filters: boolean;
|
|
||||||
strict_variables: boolean;
|
|
||||||
trim_tag_right: boolean;
|
|
||||||
trim_tag_left: boolean;
|
|
||||||
trim_output_right: boolean;
|
|
||||||
trim_output_left: boolean;
|
|
||||||
greedy: boolean;
|
|
||||||
}
|
|
||||||
export declare function normalize(options: LiquidOptions): NormalizedOptions;
|
|
||||||
export declare function applyDefault(options: NormalizedOptions): NormalizedFullOptions;
|
|
||||||
Vendored
-2291
File diff suppressed because it is too large
Load Diff
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-30
@@ -1,30 +0,0 @@
|
|||||||
import Scope from './scope/scope';
|
|
||||||
import * as Types from './types';
|
|
||||||
import ITemplate from './template/itemplate';
|
|
||||||
import ITagImplOptions from './template/tag/itag-impl-options';
|
|
||||||
import { isTruthy, isFalsy, evalExp, evalValue } from './render/syntax';
|
|
||||||
import { LiquidOptions, NormalizedFullOptions } from './liquid-options';
|
|
||||||
export default class Liquid {
|
|
||||||
options: NormalizedFullOptions;
|
|
||||||
private cache;
|
|
||||||
private parser;
|
|
||||||
private renderer;
|
|
||||||
private tokenizer;
|
|
||||||
constructor(opts?: LiquidOptions);
|
|
||||||
parse(html: string, filepath?: string): any[];
|
|
||||||
render(tpl: Array<ITemplate>, ctx?: object, opts?: LiquidOptions): Promise<string>;
|
|
||||||
parseAndRender(html: string, ctx?: object, opts?: LiquidOptions): Promise<string>;
|
|
||||||
getTemplate(file: any, opts?: LiquidOptions): Promise<any>;
|
|
||||||
renderFile(file: any, ctx?: object, opts?: LiquidOptions): Promise<string>;
|
|
||||||
evalValue(str: string, scope: Scope): any;
|
|
||||||
registerFilter(name: any, filter: any): void;
|
|
||||||
registerTag(name: string, tag: ITagImplOptions): void;
|
|
||||||
plugin(plugin: any): any;
|
|
||||||
express(): (filePath: string, ctx: object, cb: (err: Error, html?: string) => void) => void;
|
|
||||||
static default: typeof Liquid;
|
|
||||||
static isTruthy: typeof isTruthy;
|
|
||||||
static isFalsy: typeof isFalsy;
|
|
||||||
static evalExp: typeof evalExp;
|
|
||||||
static evalValue: typeof evalValue;
|
|
||||||
static Types: typeof Types;
|
|
||||||
}
|
|
||||||
Vendored
-2318
File diff suppressed because it is too large
Load Diff
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-2
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import Token from './token';
|
|
||||||
export default class DelimitedToken extends Token {
|
|
||||||
trimLeft: boolean;
|
|
||||||
trimRight: boolean;
|
|
||||||
constructor(raw: any, value: any, pos: any, input: any, file: any, line: any);
|
|
||||||
}
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
import Token from './token';
|
|
||||||
export default class HTMLToken extends Token {
|
|
||||||
constructor(str: any, begin: any, input: any, file: any, line: any);
|
|
||||||
}
|
|
||||||
Vendored
-35
@@ -1,35 +0,0 @@
|
|||||||
export declare const quoted: RegExp;
|
|
||||||
export declare const quoteBalanced: RegExp;
|
|
||||||
export declare const integer: RegExp;
|
|
||||||
export declare const number: RegExp;
|
|
||||||
export declare const bool: RegExp;
|
|
||||||
export declare const identifier: RegExp;
|
|
||||||
export declare const subscript: RegExp;
|
|
||||||
export declare const literal: RegExp;
|
|
||||||
export declare const variable: RegExp;
|
|
||||||
export declare const rangeLimit: RegExp;
|
|
||||||
export declare const range: RegExp;
|
|
||||||
export declare const rangeCapture: RegExp;
|
|
||||||
export declare const value: RegExp;
|
|
||||||
export declare const hash: RegExp;
|
|
||||||
export declare const hashCapture: RegExp;
|
|
||||||
export declare const tagLine: RegExp;
|
|
||||||
export declare const literalLine: RegExp;
|
|
||||||
export declare const variableLine: RegExp;
|
|
||||||
export declare const numberLine: RegExp;
|
|
||||||
export declare const boolLine: RegExp;
|
|
||||||
export declare const quotedLine: RegExp;
|
|
||||||
export declare const rangeLine: RegExp;
|
|
||||||
export declare const integerLine: RegExp;
|
|
||||||
export declare const valueDeclaration: RegExp;
|
|
||||||
export declare const valueList: RegExp;
|
|
||||||
export declare const filter: RegExp;
|
|
||||||
export declare const filterCapture: RegExp;
|
|
||||||
export declare const filterLine: RegExp;
|
|
||||||
export declare const operators: RegExp[];
|
|
||||||
export declare function isInteger(str: any): boolean;
|
|
||||||
export declare function isLiteral(str: any): boolean;
|
|
||||||
export declare function isRange(str: any): boolean;
|
|
||||||
export declare function isVariable(str: any): boolean;
|
|
||||||
export declare function matchValue(str: any): RegExpExecArray;
|
|
||||||
export declare function parseLiteral(str: any): any;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
import DelimitedToken from './delimited-token';
|
|
||||||
export default class OutputToken extends DelimitedToken {
|
|
||||||
constructor(raw: any, value: any, pos: any, input: any, file: any, line: any);
|
|
||||||
}
|
|
||||||
Vendored
-16
@@ -1,16 +0,0 @@
|
|||||||
import Token from 'src/parser/token';
|
|
||||||
import ITemplate from 'src/template/itemplate';
|
|
||||||
declare type parseToken = (token: Token, remainTokens: Array<Token>) => ITemplate;
|
|
||||||
declare type eventHandler = ((arg?: Token | ITemplate) => void);
|
|
||||||
export default class ParseStream {
|
|
||||||
private tokens;
|
|
||||||
private handlers;
|
|
||||||
private stopRequested;
|
|
||||||
private parseToken;
|
|
||||||
constructor(tokens: Array<Token>, parseToken: parseToken);
|
|
||||||
on(name: string, cb: eventHandler): this;
|
|
||||||
trigger(event: string, arg?: Token | ITemplate): boolean;
|
|
||||||
start(): this;
|
|
||||||
stop(): this;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
import Liquid from 'src/liquid';
|
|
||||||
import ParseStream from './parse-stream';
|
|
||||||
import Token from './token';
|
|
||||||
import Tag from 'src/template/tag/tag';
|
|
||||||
import Output from 'src/template/output';
|
|
||||||
import HTML from 'src/template/html';
|
|
||||||
export default class Parser {
|
|
||||||
liquid: Liquid;
|
|
||||||
constructor(liquid: Liquid);
|
|
||||||
parse(tokens: Array<Token>): any[];
|
|
||||||
parseToken(token: Token, remainTokens: Array<Token>): Tag | Output | HTML;
|
|
||||||
parseStream(tokens: Array<Token>): ParseStream;
|
|
||||||
}
|
|
||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import DelimitedToken from './delimited-token';
|
|
||||||
export default class TagToken extends DelimitedToken {
|
|
||||||
name: string;
|
|
||||||
args: string;
|
|
||||||
constructor(raw: any, value: any, pos: any, input: any, file: any, line: any);
|
|
||||||
}
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
export default class Token {
|
|
||||||
type: string;
|
|
||||||
line: number;
|
|
||||||
col: number;
|
|
||||||
raw: string;
|
|
||||||
input: string;
|
|
||||||
file: string;
|
|
||||||
value: string;
|
|
||||||
constructor(raw: any, col: any, input: any, file: any, line: any);
|
|
||||||
}
|
|
||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import { NormalizedFullOptions } from '../liquid-options';
|
|
||||||
export default class Tokenizer {
|
|
||||||
options: NormalizedFullOptions;
|
|
||||||
constructor(options?: NormalizedFullOptions);
|
|
||||||
tokenize(input: string, file?: string): any[];
|
|
||||||
}
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
import Token from 'src/parser/token';
|
|
||||||
import { NormalizedFullOptions } from 'src/liquid-options';
|
|
||||||
export default function whiteSpaceCtrl(tokens: Token[], options: NormalizedFullOptions): void;
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
export default class Render {
|
|
||||||
renderTemplates(templates: any, scope: any): Promise<string>;
|
|
||||||
}
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
export declare function evalExp(exp: any, scope: any): any;
|
|
||||||
export declare function evalValue(str: any, scope: any): any;
|
|
||||||
export declare function isTruthy(val: any): boolean;
|
|
||||||
export declare function isFalsy(val: any): boolean;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
declare enum BlockMode {
|
|
||||||
OUTPUT = 0,
|
|
||||||
STORE = 1
|
|
||||||
}
|
|
||||||
export default BlockMode;
|
|
||||||
Vendored
-18
@@ -1,18 +0,0 @@
|
|||||||
import { NormalizedFullOptions } from '../liquid-options';
|
|
||||||
import BlockMode from './block-mode';
|
|
||||||
export default class Scope {
|
|
||||||
opts: NormalizedFullOptions;
|
|
||||||
contexts: Array<object>;
|
|
||||||
blocks: object;
|
|
||||||
blockMode: BlockMode;
|
|
||||||
constructor(ctx?: object, opts?: NormalizedFullOptions);
|
|
||||||
getAll(): object;
|
|
||||||
get(path: string): any;
|
|
||||||
set(path: string, v: any): void;
|
|
||||||
unshift(ctx: object): number;
|
|
||||||
push(ctx: object): number;
|
|
||||||
pop(ctx?: object): object;
|
|
||||||
findContextFor(key: string, filter?: ((conttext: object) => boolean)): object;
|
|
||||||
readProperty(obj: any, key: any): any;
|
|
||||||
propertyAccessSeq(str: any): any[];
|
|
||||||
}
|
|
||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
export declare class CaptureScope {
|
|
||||||
}
|
|
||||||
export declare class AssignScope {
|
|
||||||
}
|
|
||||||
export declare class IncrementScope {
|
|
||||||
}
|
|
||||||
export declare class DecrementScope {
|
|
||||||
}
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
import Scope from 'src/scope/scope';
|
|
||||||
declare type impl = (value: any, ...args: any[]) => any;
|
|
||||||
export default class Filter {
|
|
||||||
name: string;
|
|
||||||
impl: impl;
|
|
||||||
args: string[];
|
|
||||||
private static impls;
|
|
||||||
constructor(str: string, strictFilters?: boolean);
|
|
||||||
parseArgs(argList: string): string[];
|
|
||||||
render(value: any, scope: Scope): any;
|
|
||||||
static register(name: any, filter: any): void;
|
|
||||||
static clear(): void;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
import Template from 'src/template/template';
|
|
||||||
import ITemplate from 'src/template/itemplate';
|
|
||||||
import Token from 'src/parser/token';
|
|
||||||
export default class extends Template implements ITemplate {
|
|
||||||
str: string;
|
|
||||||
constructor(token: Token);
|
|
||||||
render(): Promise<string>;
|
|
||||||
}
|
|
||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import Scope from 'src/scope/scope';
|
|
||||||
import Token from 'src/parser/token';
|
|
||||||
export default interface ITemplate {
|
|
||||||
token: Token;
|
|
||||||
render(scope: Scope): Promise<string>;
|
|
||||||
}
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
import Value from './value';
|
|
||||||
import Template from 'src/template/template';
|
|
||||||
import ITemplate from 'src/template/itemplate';
|
|
||||||
import Scope from 'src/scope/scope';
|
|
||||||
import OutputToken from 'src/parser/output-token';
|
|
||||||
export default class Output extends Template implements ITemplate {
|
|
||||||
value: Value;
|
|
||||||
constructor(token: OutputToken, strictFilters?: boolean);
|
|
||||||
render(scope: Scope): Promise<string>;
|
|
||||||
}
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
* Key-Value Pairs Representing Tag Arguments
|
|
||||||
* Example:
|
|
||||||
* For the markup `{% include 'head.html' foo='bar' %}`,
|
|
||||||
* hash['foo'] === 'bar'
|
|
||||||
*/
|
|
||||||
export default class Hash {
|
|
||||||
[key: string]: any;
|
|
||||||
constructor(markup: any, scope: any);
|
|
||||||
}
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
import Scope from 'src/scope/scope';
|
|
||||||
import TagToken from 'src/parser/tag-token';
|
|
||||||
import Token from 'src/parser/token';
|
|
||||||
import Hash from 'src/template/tag/hash';
|
|
||||||
import ITagImpl from './itag-impl';
|
|
||||||
export default interface ITagImplOptions {
|
|
||||||
parse?: (this: ITagImpl, token: TagToken, remainingTokens: Array<Token>) => void;
|
|
||||||
render?: (this: ITagImpl, scope: Scope, hash: Hash) => any | Promise<any>;
|
|
||||||
}
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
import Liquid from 'src/liquid';
|
|
||||||
import ITagImplOptions from './itag-impl-options';
|
|
||||||
export default interface ITagImpl extends ITagImplOptions {
|
|
||||||
liquid: Liquid;
|
|
||||||
}
|
|
||||||
Vendored
-19
@@ -1,19 +0,0 @@
|
|||||||
import Scope from 'src/scope/scope';
|
|
||||||
import ITagImplOptions from './itag-impl-options';
|
|
||||||
import Liquid from 'src/liquid';
|
|
||||||
import Template from 'src/template/template';
|
|
||||||
import ITemplate from 'src/template/itemplate';
|
|
||||||
import TagToken from 'src/parser/tag-token';
|
|
||||||
import Token from 'src/parser/token';
|
|
||||||
export default class Tag extends Template implements ITemplate {
|
|
||||||
name: string;
|
|
||||||
token: TagToken;
|
|
||||||
private impl;
|
|
||||||
static impls: {
|
|
||||||
[key: string]: ITagImplOptions;
|
|
||||||
};
|
|
||||||
constructor(token: TagToken, tokens: Token[], liquid: Liquid);
|
|
||||||
render(scope: Scope): Promise<string>;
|
|
||||||
static register(name: string, tag: ITagImplOptions): void;
|
|
||||||
static clear(): void;
|
|
||||||
}
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
import Token from 'src/parser/token';
|
|
||||||
export default class Template {
|
|
||||||
token: Token;
|
|
||||||
constructor(token: any);
|
|
||||||
}
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
import Scope from 'src/scope/scope';
|
|
||||||
export default class {
|
|
||||||
initial: any;
|
|
||||||
filters: Array<any>;
|
|
||||||
constructor(str: string, strictFilters?: boolean);
|
|
||||||
value(scope: Scope): any;
|
|
||||||
}
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
export { AssignScope, CaptureScope, IncrementScope, DecrementScope } from './scope/scopes';
|
|
||||||
export { ParseError, TokenizationError, RenderBreakError, AssertionError } from './util/error';
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export default function (predicate: any, message?: string): void;
|
|
||||||
Vendored
-30
@@ -1,30 +0,0 @@
|
|||||||
declare abstract class LiquidError {
|
|
||||||
name: string;
|
|
||||||
message: string;
|
|
||||||
stack: string;
|
|
||||||
private file;
|
|
||||||
private input;
|
|
||||||
private token;
|
|
||||||
private originalError;
|
|
||||||
constructor(err: any, token: any);
|
|
||||||
captureStackTrace(obj: any): void;
|
|
||||||
}
|
|
||||||
export declare class TokenizationError extends LiquidError {
|
|
||||||
constructor(message: any, token: any);
|
|
||||||
}
|
|
||||||
export declare class ParseError extends LiquidError {
|
|
||||||
constructor(err: any, token: any);
|
|
||||||
}
|
|
||||||
export declare class RenderError extends LiquidError {
|
|
||||||
constructor(err: any, tpl: any);
|
|
||||||
}
|
|
||||||
export declare class RenderBreakError {
|
|
||||||
message: string;
|
|
||||||
resolvedHTML: string;
|
|
||||||
constructor(message: any);
|
|
||||||
}
|
|
||||||
export declare class AssertionError {
|
|
||||||
message: string;
|
|
||||||
constructor(message: any);
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
export declare function anySeries(iterable: any, iteratee: any): Promise<any>;
|
|
||||||
export declare function mapSeries(iterable: any, iteratee: any): Promise<any[]>;
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
export default function (d: any, format: any): string;
|
|
||||||
Vendored
-15
@@ -1,15 +0,0 @@
|
|||||||
export declare function isString(value: any): boolean;
|
|
||||||
export declare function isFunction(value: any): boolean;
|
|
||||||
export declare function promisify(fn: any): (...args: any[]) => Promise<{}>;
|
|
||||||
export declare function stringify(value: any): string;
|
|
||||||
export declare function create<T1 extends object, T2 extends T1 = T1>(proto: T1): T2;
|
|
||||||
export declare function isNil(value: any): boolean;
|
|
||||||
export declare function isArray(value: any): boolean;
|
|
||||||
export declare function isError(value: any): boolean;
|
|
||||||
export declare function forOwn(object: any, iteratee: ((val: any, key: string, obj: object) => boolean | void)): any;
|
|
||||||
export declare function assign(obj: object, ...srcs: object[]): object;
|
|
||||||
export declare function last(arr: any[]): any;
|
|
||||||
export declare function uniq(arr: any[]): any[];
|
|
||||||
export declare function isObject(value: any): boolean;
|
|
||||||
export declare function range(start: number, stop?: number, step?: number): any[];
|
|
||||||
export declare function padStart(str: any, length: number, ch?: string): any;
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
declare module 'rollup-plugin-uglify' {
|
||||||
|
export function uglify (): any
|
||||||
|
}
|
||||||
|
declare module 'rollup-plugin-replace' {
|
||||||
|
export default function replace(options: any): any
|
||||||
|
}
|
||||||
Generated
+2944
-2574
File diff suppressed because it is too large
Load Diff
+31
-18
@@ -1,19 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "liquidjs",
|
"name": "liquidjs",
|
||||||
"version": "7.2.0",
|
"version": "8.4.1",
|
||||||
"description": "Liquid template engine by pure JavaScript: compatible to shopify, easy to extend.",
|
"description": "Liquid template engine by pure JavaScript: compatible to shopify, easy to extend.",
|
||||||
"main": "dist/liquid.common.js",
|
"main": "dist/liquid.common.js",
|
||||||
"types": "dist/liquid.d.ts",
|
"types": "dist/liquid.d.ts",
|
||||||
"browser": "dist/liquid.js",
|
"browser": "dist/liquid.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint . --ext .ts --ext .js",
|
"lint": "eslint . --ext .ts",
|
||||||
"unit": "mocha 'test/unit/**/*.ts'",
|
"unit": "mocha \"test/unit/**/*.ts\"",
|
||||||
"e2e": "npm run build && mocha 'test/e2e/**/*.ts'",
|
"integration": "mocha \"test/integration/**/*.ts\"",
|
||||||
"test": "npm run unit && npm run e2e",
|
"e2e": "npm run build && mocha \"test/e2e/**/*.ts\"",
|
||||||
"coverage-html": "nyc npm run unit && nyc report --reporter=html",
|
"test": "cross-env BUNDLES=cjs,umd npm run build && mocha \"test/**/*.ts\"",
|
||||||
"coverage-coveralls": "nyc npm run unit && nyc report --reporter=text-lcov | coveralls",
|
"benchmark": "ts-node benchmark",
|
||||||
"build": "rollup -c && ls -lh dist",
|
"coverage-html": "nyc --reporter=html mocha \"test/{unit,integration}/**/*.ts\"",
|
||||||
"version": "npm run build && git add -A dist"
|
"coverage-coveralls": "nyc mocha \"test/{unit,integration}/**/*.ts\" && nyc report --reporter=text-lcov | coveralls",
|
||||||
|
"build": "rollup -c rollup.config.ts && ls -lh dist",
|
||||||
|
"version": "npm run build"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -44,11 +46,20 @@
|
|||||||
"@semantic-release/changelog": "^3.0.2",
|
"@semantic-release/changelog": "^3.0.2",
|
||||||
"@semantic-release/commit-analyzer": "^6.1.0",
|
"@semantic-release/commit-analyzer": "^6.1.0",
|
||||||
"@semantic-release/git": "^7.0.8",
|
"@semantic-release/git": "^7.0.8",
|
||||||
"@semantic-release/npm": "^5.1.4",
|
"@semantic-release/npm": "^5.1.8",
|
||||||
"@semantic-release/release-notes-generator": "^7.1.4",
|
"@semantic-release/release-notes-generator": "^7.1.4",
|
||||||
|
"@types/benchmark": "^1.0.31",
|
||||||
|
"@types/chai": "^4.1.7",
|
||||||
|
"@types/chai-as-promised": "^7.1.0",
|
||||||
|
"@types/express": "^4.16.1",
|
||||||
"@types/jsdom": "^12.2.2",
|
"@types/jsdom": "^12.2.2",
|
||||||
"@types/mocha": "^5.2.6",
|
"@types/mocha": "^5.2.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^1.3.0",
|
"@types/sinon": "^7.0.6",
|
||||||
|
"@types/sinon-chai": "^3.2.2",
|
||||||
|
"@types/supertest": "^2.0.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^1.11.0",
|
||||||
|
"@typescript-eslint/parser": "^1.11.0",
|
||||||
|
"benchmark": "^2.1.4",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"coveralls": "^3.0.2",
|
"coveralls": "^3.0.2",
|
||||||
@@ -56,7 +67,7 @@
|
|||||||
"eslint": "^5.12.1",
|
"eslint": "^5.12.1",
|
||||||
"eslint-config-standard": "^12.0.0",
|
"eslint-config-standard": "^12.0.0",
|
||||||
"eslint-plugin-import": "^2.15.0",
|
"eslint-plugin-import": "^2.15.0",
|
||||||
"eslint-plugin-mocha": "^5.2.1",
|
"eslint-plugin-mocha": "^5.3.0",
|
||||||
"eslint-plugin-node": "^8.0.1",
|
"eslint-plugin-node": "^8.0.1",
|
||||||
"eslint-plugin-promise": "^4.0.1",
|
"eslint-plugin-promise": "^4.0.1",
|
||||||
"eslint-plugin-standard": "^4.0.0",
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
@@ -66,15 +77,15 @@
|
|||||||
"nyc": "^13.1.0",
|
"nyc": "^13.1.0",
|
||||||
"regenerator-runtime": "^0.12.1",
|
"regenerator-runtime": "^0.12.1",
|
||||||
"rollup": "^1.1.2",
|
"rollup": "^1.1.2",
|
||||||
"rollup-plugin-shim": "^1.0.0",
|
"rollup-plugin-replace": "^2.1.0",
|
||||||
"rollup-plugin-typescript2": "^0.19.2",
|
"rollup-plugin-typescript2": "^0.21.1",
|
||||||
"rollup-plugin-uglify": "^6.0.2",
|
"rollup-plugin-uglify": "^6.0.2",
|
||||||
"semantic-release": "^15.13.3",
|
"semantic-release": "^15.13.14",
|
||||||
"sinon": "^7.2.3",
|
"sinon": "^7.2.3",
|
||||||
"sinon-chai": "^3.3.0",
|
"sinon-chai": "^3.3.0",
|
||||||
"supertest": "^3.4.2",
|
"supertest": "^3.4.2",
|
||||||
"ts-node": "^8.0.2",
|
"ts-node": "^8.0.2",
|
||||||
"tsconfig-paths": "^3.8.0",
|
"tslib": "^1.9.3",
|
||||||
"typescript": "^3.3.3"
|
"typescript": "^3.3.3"
|
||||||
},
|
},
|
||||||
"release": {
|
"release": {
|
||||||
@@ -84,12 +95,14 @@
|
|||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
"@semantic-release/npm",
|
"@semantic-release/npm",
|
||||||
"@semantic-release/git"
|
"@semantic-release/git",
|
||||||
|
"@semantic-release/github"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nyc": {
|
"nyc": {
|
||||||
"extension": [
|
"extension": [
|
||||||
".ts"
|
".ts"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import shim from 'rollup-plugin-shim'
|
|
||||||
import { uglify } from 'rollup-plugin-uglify'
|
import { uglify } from 'rollup-plugin-uglify'
|
||||||
import pkg from './package.json'
|
import pkg from './package.json'
|
||||||
import typescript from 'rollup-plugin-typescript2'
|
import typescript from 'rollup-plugin-typescript2'
|
||||||
|
import replace from 'rollup-plugin-replace'
|
||||||
|
|
||||||
const fake = { fs: `export default {}`, path: `export default {}` }
|
|
||||||
const version = process.env.VERSION || pkg.version
|
const version = process.env.VERSION || pkg.version
|
||||||
const sourcemap = true
|
const sourcemap = true
|
||||||
const banner = `/*
|
const banner = `/*
|
||||||
@@ -14,9 +13,9 @@ const banner = `/*
|
|||||||
const treeshake = {
|
const treeshake = {
|
||||||
propertyReadSideEffects: false
|
propertyReadSideEffects: false
|
||||||
}
|
}
|
||||||
const input = 'src/liquid.ts'
|
const input = './src/liquid.ts'
|
||||||
|
|
||||||
export default [{
|
const cjs = {
|
||||||
output: [{
|
output: [{
|
||||||
file: 'dist/liquid.common.js',
|
file: 'dist/liquid.common.js',
|
||||||
name: 'Liquid',
|
name: 'Liquid',
|
||||||
@@ -27,15 +26,19 @@ export default [{
|
|||||||
external: ['path', 'fs'],
|
external: ['path', 'fs'],
|
||||||
plugins: [typescript({
|
plugins: [typescript({
|
||||||
tsconfigOverride: {
|
tsconfigOverride: {
|
||||||
exclude: [ 'test' ],
|
include: [ 'src' ],
|
||||||
|
exclude: [ 'test', 'benchmark' ],
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
|
target: 'es5',
|
||||||
module: 'ES2015'
|
module: 'ES2015'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})],
|
})],
|
||||||
treeshake,
|
treeshake,
|
||||||
input
|
input
|
||||||
}, {
|
}
|
||||||
|
|
||||||
|
const umd = {
|
||||||
output: [{
|
output: [{
|
||||||
file: 'dist/liquid.js',
|
file: 'dist/liquid.js',
|
||||||
name: 'Liquid',
|
name: 'Liquid',
|
||||||
@@ -44,20 +47,27 @@ export default [{
|
|||||||
banner
|
banner
|
||||||
}],
|
}],
|
||||||
plugins: [
|
plugins: [
|
||||||
shim(fake),
|
replace({
|
||||||
|
include: './src/liquid.ts',
|
||||||
|
delimiters: ['', ''],
|
||||||
|
'./fs/node': './fs/browser'
|
||||||
|
}),
|
||||||
typescript({
|
typescript({
|
||||||
tsconfigOverride: {
|
tsconfigOverride: {
|
||||||
exclude: [ 'test' ],
|
include: [ 'src' ],
|
||||||
|
exclude: [ 'test', 'benchmark' ],
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
module: 'ES2015',
|
target: 'es5',
|
||||||
paths: { 'src/fs': ['src/fs/browser'] }
|
module: 'ES2015'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
treeshake,
|
treeshake,
|
||||||
input
|
input
|
||||||
}, {
|
}
|
||||||
|
|
||||||
|
const min = {
|
||||||
output: [{
|
output: [{
|
||||||
file: 'dist/liquid.min.js',
|
file: 'dist/liquid.min.js',
|
||||||
name: 'Liquid',
|
name: 'Liquid',
|
||||||
@@ -65,13 +75,18 @@ export default [{
|
|||||||
sourcemap
|
sourcemap
|
||||||
}],
|
}],
|
||||||
plugins: [
|
plugins: [
|
||||||
shim(fake),
|
replace({
|
||||||
|
include: './src/liquid.ts',
|
||||||
|
delimiters: ['', ''],
|
||||||
|
'./fs/node': './fs/browser'
|
||||||
|
}),
|
||||||
typescript({
|
typescript({
|
||||||
tsconfigOverride: {
|
tsconfigOverride: {
|
||||||
exclude: [ 'test' ],
|
include: [ 'src' ],
|
||||||
|
exclude: [ 'test', 'benchmark' ],
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
module: 'ES2015',
|
target: 'es5',
|
||||||
paths: { 'src/fs': ['src/fs/browser'] }
|
module: 'ES2015'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -79,4 +94,13 @@ export default [{
|
|||||||
],
|
],
|
||||||
treeshake,
|
treeshake,
|
||||||
input
|
input
|
||||||
}]
|
}
|
||||||
|
|
||||||
|
const bundles = []
|
||||||
|
const env = process.env.BUNDLES || ''
|
||||||
|
if (env.includes('cjs')) bundles.push(cjs)
|
||||||
|
if (env.includes('umd')) bundles.push(umd)
|
||||||
|
if (env.includes('min')) bundles.push(min)
|
||||||
|
if (bundles.length === 0) bundles.push(cjs, umd, min)
|
||||||
|
|
||||||
|
export default bundles
|
||||||
@@ -1,25 +1,42 @@
|
|||||||
import { last } from 'src/util/underscore'
|
import { isArray, last } from '../../util/underscore'
|
||||||
|
import { isTruthy } from '../../render/syntax'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'join': (v, arg) => v.join(arg === undefined ? ' ' : arg),
|
'join': (v: any[], arg: string) => v.join(arg === undefined ? ' ' : arg),
|
||||||
'last': v => last(v),
|
'last': (v: any) => isArray(v) ? last(v) : '',
|
||||||
'first': v => v[0],
|
'first': (v: any) => isArray(v) ? v[0] : '',
|
||||||
'map': (arr, arg) => arr.map(v => v[arg]),
|
'map': map,
|
||||||
'reverse': v => v.reverse(),
|
'reverse': (v: any[]) => [...v].reverse(),
|
||||||
'sort': (v, arg) => v.sort(arg),
|
'sort': <T>(v: T[], arg: (lhs: T, rhs: T) => number) => v.sort(arg),
|
||||||
'size': v => v.length,
|
'size': (v: string | any[]) => (v && v.length) || 0,
|
||||||
'slice': (v, begin, length) => {
|
'concat': concat,
|
||||||
if (length === undefined) length = 1
|
'slice': slice,
|
||||||
return v.slice(begin, begin + length)
|
'uniq': uniq,
|
||||||
},
|
'where': where
|
||||||
'uniq': function (arr) {
|
}
|
||||||
const u = {}
|
|
||||||
return (arr || []).filter(val => {
|
function map<T1, T2> (arr: {[key: string]: T1}[], arg: string): T1[] {
|
||||||
if (u.hasOwnProperty(val)) {
|
return arr.map(v => v[arg])
|
||||||
return false
|
}
|
||||||
}
|
|
||||||
u[val] = true
|
function concat<T1, T2> (v: T1[], arg: T2[] | T2): (T1 | T2)[] {
|
||||||
return true
|
return Array.prototype.concat.call(v, arg)
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
function slice<T> (v: T[], begin: number, length: number = 1): T[] {
|
||||||
|
begin = begin < 0 ? v.length + begin : begin
|
||||||
|
return v.slice(begin, begin + length)
|
||||||
|
}
|
||||||
|
|
||||||
|
function where<T> (arr: T[], property: string, value?: any): T[] {
|
||||||
|
return arr.filter(obj => value === undefined ? isTruthy(obj[property]) : obj[property] === value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniq<T> (arr: T[]): T[] {
|
||||||
|
const u = {}
|
||||||
|
return (arr || []).filter(val => {
|
||||||
|
if (u.hasOwnProperty(String(val))) return false
|
||||||
|
u[String(val)] = true
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
import strftime from 'src/util/strftime'
|
import strftime from '../../util/strftime'
|
||||||
import { isString } from 'src/util/underscore'
|
import { isString, isNumber } from '../../util/underscore'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'date': (v, arg) => {
|
'date': (v: string | Date, arg: string) => {
|
||||||
let date = v
|
let date = v
|
||||||
if (v === 'now') {
|
if (v === 'now') {
|
||||||
date = new Date()
|
date = new Date()
|
||||||
|
} else if (isNumber(v)) {
|
||||||
|
date = new Date(v * 1000)
|
||||||
} else if (isString(v)) {
|
} else if (isString(v)) {
|
||||||
date = new Date(v)
|
date = /^\d+$/.test(v) ? new Date(+v * 1000) : new Date(v)
|
||||||
}
|
}
|
||||||
return isValidDate(date) ? strftime(date, arg) : v
|
return isValidDate(date) ? strftime(date, arg) : v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidDate (date) {
|
function isValidDate (date: any): date is Date {
|
||||||
return date instanceof Date && !isNaN(date.getTime())
|
return date instanceof Date && !isNaN(date.getTime())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ const unescapeMap = {
|
|||||||
''': "'"
|
''': "'"
|
||||||
}
|
}
|
||||||
|
|
||||||
function escape (str) {
|
function escape (str: string) {
|
||||||
return String(str).replace(/&|<|>|"|'/g, m => escapeMap[m])
|
return String(str).replace(/&|<|>|"|'/g, m => escapeMap[m])
|
||||||
}
|
}
|
||||||
|
|
||||||
function unescape (str) {
|
function unescape (str: string) {
|
||||||
return String(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m])
|
return String(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m])
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'escape': escape,
|
'escape': escape,
|
||||||
'escape_once': str => escape(unescape(str)),
|
'escape_once': (str: string) => escape(unescape(str)),
|
||||||
'newline_to_br': v => v.replace(/\n/g, '<br />'),
|
'newline_to_br': (v: string) => v.replace(/\n/g, '<br />'),
|
||||||
'strip_html': v => String(v).replace(/<script.*?<\/script>|<!--.*?-->|<style.*?<\/style>|<.*?>/g, '')
|
'strip_html': (v: string) => v.replace(/<script.*?<\/script>|<!--.*?-->|<style.*?<\/style>|<.*?>/g, '')
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-17
@@ -1,26 +1,39 @@
|
|||||||
|
const toLowerCase = String.prototype.toLowerCase
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'abs': v => Math.abs(v),
|
'abs': (v: number) => Math.abs(v),
|
||||||
'ceil': v => Math.ceil(v),
|
'at_least': (v: number, n: number) => Math.max(v, n),
|
||||||
'divided_by': (v, arg) => v / arg,
|
'at_most': (v: number, n: number) => Math.min(v, n),
|
||||||
'floor': v => Math.floor(v),
|
'ceil': (v: number) => Math.ceil(v),
|
||||||
'minus': bindFixed((v, arg) => v - arg),
|
'divided_by': (v: number, arg: number) => v / arg,
|
||||||
'modulo': bindFixed((v, arg) => v % arg),
|
'floor': (v: number) => Math.floor(v),
|
||||||
'round': (v, arg) => {
|
'minus': (v: number, arg: number) => v - arg,
|
||||||
const amp = Math.pow(10, arg || 0)
|
'modulo': (v: number, arg: number) => v % arg,
|
||||||
|
'round': (v: number, arg: number = 0) => {
|
||||||
|
const amp = Math.pow(10, arg)
|
||||||
return Math.round(v * amp) / amp
|
return Math.round(v * amp) / amp
|
||||||
},
|
},
|
||||||
'plus': bindFixed((v, arg) => Number(v) + Number(arg)),
|
'plus': (v: number, arg: number) => Number(v) + Number(arg),
|
||||||
'times': (v, arg) => v * arg
|
'sort_natural': sortNatural,
|
||||||
|
'times': (v: number, arg: number) => v * arg
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFixed (v) {
|
function caseInsensitiveCmp (a: any, b: any) {
|
||||||
const p = String(v).split('.')
|
if (!b) return -1
|
||||||
return (p.length > 1) ? p[1].length : 0
|
if (!a) return 1
|
||||||
|
a = toLowerCase.call(a)
|
||||||
|
b = toLowerCase.call(b)
|
||||||
|
if (a < b) return -1
|
||||||
|
if (a > b) return 1
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindFixed (cb) {
|
function sortNatural (input: any[], property?: string) {
|
||||||
return (l, r) => {
|
if (!input || !input.sort) return []
|
||||||
const f = Math.max(getFixed(l), getFixed(r))
|
if (property !== undefined) {
|
||||||
return cb(l, r).toFixed(f)
|
return [...input].sort(
|
||||||
|
(lhs, rhs) => caseInsensitiveCmp(lhs[property], rhs[property])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
return [...input].sort(caseInsensitiveCmp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { isTruthy } from 'src/render/syntax'
|
import { isFalsy } from '../../render/syntax'
|
||||||
|
import { toValue } from '../../util/underscore'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'default': (v, arg) => isTruthy(v) ? v : arg
|
'default': function<T1, T2> (v: string | T1, arg: T2): string | T1 | T2 {
|
||||||
|
return isFalsy(toValue(v)) || v === '' ? arg : v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* String related filters
|
||||||
|
*
|
||||||
|
* * prefer stringify() to String() since `undefined`, `null` should eval ''
|
||||||
|
*/
|
||||||
|
import { stringify } from '../../util/underscore'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
'append': (v, arg) => v + arg,
|
'append': (v: string, arg: string) => stringify(v) + arg,
|
||||||
'prepend': (v, arg) => arg + v,
|
'prepend': (v: string, arg: string) => arg + stringify(v),
|
||||||
'capitalize': str => String(str).charAt(0).toUpperCase() + str.slice(1),
|
'capitalize': capitalize,
|
||||||
'concat': (v, arg) => Array.prototype.concat.call(v, arg),
|
'lstrip': (v: string) => stringify(v).replace(/^\s+/, ''),
|
||||||
'lstrip': v => String(v).replace(/^\s+/, ''),
|
'downcase': (v: string) => stringify(v).toLowerCase(),
|
||||||
'downcase': v => v.toLowerCase(),
|
'upcase': (str: string) => stringify(str).toUpperCase(),
|
||||||
'upcase': str => String(str).toUpperCase(),
|
'remove': (v: string, arg: string) => stringify(v).split(arg).join(''),
|
||||||
'remove': (v, arg) => v.split(arg).join(''),
|
'remove_first': (v: string, l: string) => stringify(v).replace(l, ''),
|
||||||
'remove_first': (v, l) => v.replace(l, ''),
|
'replace': replace,
|
||||||
'replace': (v, pattern, replacement) =>
|
'replace_first': replaceFirst,
|
||||||
String(v).split(pattern).join(replacement),
|
'rstrip': (str: string) => stringify(str).replace(/\s+$/, ''),
|
||||||
'replace_first': (v, arg1, arg2) => String(v).replace(arg1, arg2),
|
'split': (v: string, arg: string) => stringify(v).split(arg),
|
||||||
'rstrip': str => String(str).replace(/\s+$/, ''),
|
'strip': (v: string) => stringify(v).trim(),
|
||||||
'split': (v, arg) => String(v).split(arg),
|
'strip_newlines': (v: string) => stringify(v).replace(/\n/g, ''),
|
||||||
'strip': (v) => String(v).trim(),
|
'truncate': truncate,
|
||||||
'strip_newlines': v => String(v).replace(/\n/g, ''),
|
'truncatewords': truncateWords
|
||||||
'truncate': (v, l, o) => {
|
}
|
||||||
v = String(v)
|
|
||||||
o = (o === undefined) ? '...' : o
|
function capitalize (str: string) {
|
||||||
l = l || 16
|
str = stringify(str)
|
||||||
if (v.length <= l) return v
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
return v.substr(0, l - o.length) + o
|
}
|
||||||
},
|
|
||||||
'truncatewords': (v, l, o) => {
|
function replace (v: string, pattern: string, replacement: string) {
|
||||||
if (o === undefined) o = '...'
|
return stringify(v).split(pattern).join(replacement)
|
||||||
const arr = v.split(' ')
|
}
|
||||||
let ret = arr.slice(0, l).join(' ')
|
|
||||||
if (arr.length > l) ret += o
|
function replaceFirst (v: string, arg1: string, arg2: string) {
|
||||||
return ret
|
return stringify(v).replace(arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function truncate (v: string, l: number = 50, o: string = '...') {
|
||||||
|
v = stringify(v)
|
||||||
|
if (v.length <= l) return v
|
||||||
|
return v.substr(0, l - o.length) + o
|
||||||
|
}
|
||||||
|
|
||||||
|
function truncateWords (v: string, l: number = 15, o: string = '...') {
|
||||||
|
const arr = v.split(/\s+/)
|
||||||
|
let ret = arr.slice(0, l).join(' ')
|
||||||
|
if (arr.length >= l) ret += o
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default {
|
export default {
|
||||||
'url_decode': x => x.split('+').map(decodeURIComponent).join(' '),
|
'url_decode': (x: string) => x.split('+').map(decodeURIComponent).join(' '),
|
||||||
'url_encode': x => x.split(' ').map(encodeURIComponent).join('+')
|
'url_encode': (x: string) => x.split(' ').map(encodeURIComponent).join('+')
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-11
@@ -1,20 +1,19 @@
|
|||||||
import assert from 'src/util/assert'
|
import assert from '../../util/assert'
|
||||||
import { identifier } from 'src/parser/lexical'
|
import { identifier } from '../../parser/lexical'
|
||||||
import { AssignScope } from 'src/scope/scopes'
|
import TagToken from '../../parser/tag-token'
|
||||||
|
import Context from '../../context/context'
|
||||||
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
|
||||||
const re = new RegExp(`(${identifier.source})\\s*=([^]*)`)
|
const re = new RegExp(`(${identifier.source})\\s*=([^]*)`)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (token) {
|
parse: function (token: TagToken) {
|
||||||
const match = token.args.match(re)
|
const match = token.args.match(re) as RegExpMatchArray
|
||||||
assert(match, `illegal token ${token.raw}`)
|
assert(match, `illegal token ${token.raw}`)
|
||||||
this.key = match[1]
|
this.key = match[1]
|
||||||
this.value = match[2]
|
this.value = match[2]
|
||||||
},
|
},
|
||||||
render: function (scope) {
|
render: async function (ctx: Context) {
|
||||||
const ctx = new AssignScope()
|
ctx.front()[this.key] = await this.liquid.evalValue(this.value, ctx)
|
||||||
ctx[this.key] = this.liquid.evalValue(this.value, scope)
|
|
||||||
scope.push(ctx)
|
|
||||||
return Promise.resolve('')
|
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
+18
-12
@@ -1,29 +1,35 @@
|
|||||||
import BlockMode from 'src/scope/block-mode'
|
import BlockMode from '../../context/block-mode'
|
||||||
|
import TagToken from '../../parser/tag-token'
|
||||||
|
import Token from '../../parser/token'
|
||||||
|
import ITemplate from '../../template/itemplate'
|
||||||
|
import Context from '../../context/context'
|
||||||
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
import ParseStream from '../../parser/parse-stream'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (token, remainTokens) {
|
parse: function (token: TagToken, remainTokens: Token[]) {
|
||||||
const match = /\w+/.exec(token.args)
|
const match = /\w+/.exec(token.args)
|
||||||
this.block = match ? match[0] : ''
|
this.block = match ? match[0] : ''
|
||||||
|
this.tpls = [] as ITemplate[]
|
||||||
this.tpls = []
|
const stream: ParseStream = this.liquid.parser.parseStream(remainTokens)
|
||||||
const stream = this.liquid.parser.parseStream(remainTokens)
|
|
||||||
.on('tag:endblock', () => stream.stop())
|
.on('tag:endblock', () => stream.stop())
|
||||||
.on('template', tpl => this.tpls.push(tpl))
|
.on('template', (tpl: ITemplate) => this.tpls.push(tpl))
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
throw new Error(`tag ${token.raw} not closed`)
|
throw new Error(`tag ${token.raw} not closed`)
|
||||||
})
|
})
|
||||||
stream.start()
|
stream.start()
|
||||||
},
|
},
|
||||||
render: async function (scope) {
|
render: async function (ctx: Context) {
|
||||||
const childDefined = scope.blocks[this.block]
|
const blocks = ctx.getRegister('blocks')
|
||||||
|
const childDefined = blocks[this.block]
|
||||||
const html = childDefined !== undefined
|
const html = childDefined !== undefined
|
||||||
? childDefined
|
? childDefined
|
||||||
: await this.liquid.renderer.renderTemplates(this.tpls, scope)
|
: await this.liquid.renderer.renderTemplates(this.tpls, ctx)
|
||||||
|
|
||||||
if (scope.blockMode === BlockMode.STORE) {
|
if (ctx.getRegister('blockMode', BlockMode.OUTPUT) === BlockMode.STORE) {
|
||||||
scope.blocks[this.block] = html
|
blocks[this.block] = html
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RenderBreakError } from 'src/util/error'
|
import { RenderBreakError } from '../../util/error'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
render: async function () {
|
render: async function () {
|
||||||
|
|||||||
+12
-14
@@ -1,15 +1,15 @@
|
|||||||
import assert from 'src/util/assert'
|
import assert from '../../util/assert'
|
||||||
import { identifier } from 'src/parser/lexical'
|
import { identifier } from '../../parser/lexical'
|
||||||
import { CaptureScope } from 'src/scope/scopes'
|
import TagToken from '../../parser/tag-token'
|
||||||
import TagToken from 'src/parser/tag-token'
|
import Token from '../../parser/token'
|
||||||
import Token from 'src/parser/token'
|
import Context from '../../context/context'
|
||||||
import Scope from 'src/scope/scope'
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
|
||||||
const re = new RegExp(`(${identifier.source})`)
|
const re = new RegExp(`(${identifier.source})`)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (tagToken: TagToken, remainTokens: Token[]) {
|
parse: function (tagToken: TagToken, remainTokens: Token[]) {
|
||||||
const match = tagToken.args.match(re)
|
const match = tagToken.args.match(re) as RegExpMatchArray
|
||||||
assert(match, `${tagToken.args} not valid identifier`)
|
assert(match, `${tagToken.args} not valid identifier`)
|
||||||
|
|
||||||
this.variable = match[1]
|
this.variable = match[1]
|
||||||
@@ -17,16 +17,14 @@ export default {
|
|||||||
|
|
||||||
const stream = this.liquid.parser.parseStream(remainTokens)
|
const stream = this.liquid.parser.parseStream(remainTokens)
|
||||||
stream.on('tag:endcapture', () => stream.stop())
|
stream.on('tag:endcapture', () => stream.stop())
|
||||||
.on('template', tpl => this.templates.push(tpl))
|
.on('template', (tpl) => this.templates.push(tpl))
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
throw new Error(`tag ${tagToken.raw} not closed`)
|
throw new Error(`tag ${tagToken.raw} not closed`)
|
||||||
})
|
})
|
||||||
stream.start()
|
stream.start()
|
||||||
},
|
},
|
||||||
render: async function (scope: Scope) {
|
render: async function (ctx: Context) {
|
||||||
const html = await this.liquid.renderer.renderTemplates(this.templates, scope)
|
const html = await this.liquid.renderer.renderTemplates(this.templates, ctx)
|
||||||
const ctx = new CaptureScope()
|
ctx.front()[this.variable] = html
|
||||||
ctx[this.variable] = html
|
|
||||||
scope.push(ctx)
|
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
+18
-12
@@ -1,14 +1,20 @@
|
|||||||
import { evalExp } from 'src/render/syntax'
|
import { evalExp } from '../../render/syntax'
|
||||||
|
import TagToken from '../../parser/tag-token'
|
||||||
|
import Token from '../../parser/token'
|
||||||
|
import Context from '../../context/context'
|
||||||
|
import ITemplate from '../../template/itemplate'
|
||||||
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
import ParseStream from '../../parser/parse-stream'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (tagToken, remainTokens) {
|
parse: function (tagToken: TagToken, remainTokens: Token[]) {
|
||||||
this.cond = tagToken.args
|
this.cond = tagToken.args
|
||||||
this.cases = []
|
this.cases = []
|
||||||
this.elseTemplates = []
|
this.elseTemplates = []
|
||||||
|
|
||||||
let p = []
|
let p: ITemplate[] = []
|
||||||
const stream = this.liquid.parser.parseStream(remainTokens)
|
const stream: ParseStream = this.liquid.parser.parseStream(remainTokens)
|
||||||
.on('tag:when', token => {
|
.on('tag:when', (token: TagToken) => {
|
||||||
this.cases.push({
|
this.cases.push({
|
||||||
val: token.args,
|
val: token.args,
|
||||||
templates: p = []
|
templates: p = []
|
||||||
@@ -16,7 +22,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.on('tag:else', () => (p = this.elseTemplates))
|
.on('tag:else', () => (p = this.elseTemplates))
|
||||||
.on('tag:endcase', () => stream.stop())
|
.on('tag:endcase', () => stream.stop())
|
||||||
.on('template', tpl => p.push(tpl))
|
.on('template', (tpl: ITemplate) => p.push(tpl))
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
throw new Error(`tag ${tagToken.raw} not closed`)
|
throw new Error(`tag ${tagToken.raw} not closed`)
|
||||||
})
|
})
|
||||||
@@ -24,15 +30,15 @@ export default {
|
|||||||
stream.start()
|
stream.start()
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function (scope) {
|
render: async function (ctx: Context) {
|
||||||
for (let i = 0; i < this.cases.length; i++) {
|
for (let i = 0; i < this.cases.length; i++) {
|
||||||
const branch = this.cases[i]
|
const branch = this.cases[i]
|
||||||
const val = evalExp(branch.val, scope)
|
const val = await evalExp(branch.val, ctx)
|
||||||
const cond = evalExp(this.cond, scope)
|
const cond = await evalExp(this.cond, ctx)
|
||||||
if (val === cond) {
|
if (val === cond) {
|
||||||
return this.liquid.renderer.renderTemplates(branch.templates, scope)
|
return this.liquid.renderer.renderTemplates(branch.templates, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.liquid.renderer.renderTemplates(this.elseTemplates, scope)
|
return this.liquid.renderer.renderTemplates(this.elseTemplates, ctx)
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import TagToken from '../../parser/tag-token'
|
||||||
|
import Token from '../../parser/token'
|
||||||
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (tagToken, remainTokens) {
|
parse: function (tagToken: TagToken, remainTokens: Token[]) {
|
||||||
const stream = this.liquid.parser.parseStream(remainTokens)
|
const stream = this.liquid.parser.parseStream(remainTokens)
|
||||||
stream
|
stream
|
||||||
.on('token', token => {
|
.on('token', (token: TagToken) => {
|
||||||
if (token.name === 'endcomment') stream.stop()
|
if (token.name === 'endcomment') stream.stop()
|
||||||
})
|
})
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
@@ -10,4 +14,4 @@ export default {
|
|||||||
})
|
})
|
||||||
stream.start()
|
stream.start()
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RenderBreakError } from 'src/util/error'
|
import { RenderBreakError } from '../../util/error'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
render: async function () {
|
render: async function () {
|
||||||
|
|||||||
+13
-11
@@ -1,13 +1,16 @@
|
|||||||
import assert from 'src/util/assert'
|
import assert from '../../util/assert'
|
||||||
import { value as rValue } from 'src/parser/lexical'
|
import { value as rValue } from '../../parser/lexical'
|
||||||
import { evalValue } from 'src/render/syntax'
|
import { evalValue } from '../../render/syntax'
|
||||||
|
import TagToken from '../../parser/tag-token'
|
||||||
|
import Context from '../../context/context'
|
||||||
|
import ITagImplOptions from '../../template/tag/itag-impl-options'
|
||||||
|
|
||||||
const groupRE = new RegExp(`^(?:(${rValue.source})\\s*:\\s*)?(.*)$`)
|
const groupRE = new RegExp(`^(?:(${rValue.source})\\s*:\\s*)?(.*)$`)
|
||||||
const candidatesRE = new RegExp(rValue.source, 'g')
|
const candidatesRE = new RegExp(rValue.source, 'g')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parse: function (tagToken) {
|
parse: function (tagToken: TagToken) {
|
||||||
let match = groupRE.exec(tagToken.args)
|
let match: RegExpExecArray | null = groupRE.exec(tagToken.args) as RegExpExecArray
|
||||||
assert(match, `illegal tag: ${tagToken.raw}`)
|
assert(match, `illegal tag: ${tagToken.raw}`)
|
||||||
|
|
||||||
this.group = match[1] || ''
|
this.group = match[1] || ''
|
||||||
@@ -21,11 +24,10 @@ export default {
|
|||||||
assert(this.candidates.length, `empty candidates: ${tagToken.raw}`)
|
assert(this.candidates.length, `empty candidates: ${tagToken.raw}`)
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function (scope) {
|
render: async function (ctx: Context) {
|
||||||
const group = evalValue(this.group, scope)
|
const group = await evalValue(this.group, ctx)
|
||||||
const fingerprint = `cycle:${group}:` + this.candidates.join(',')
|
const fingerprint = `cycle:${group}:` + this.candidates.join(',')
|
||||||
|
const groups = ctx.getRegister('cycle')
|
||||||
const groups = scope.opts.groups = scope.opts.groups || {}
|
|
||||||
let idx = groups[fingerprint]
|
let idx = groups[fingerprint]
|
||||||
|
|
||||||
if (idx === undefined) {
|
if (idx === undefined) {
|
||||||
@@ -36,6 +38,6 @@ export default {
|
|||||||
idx = (idx + 1) % this.candidates.length
|
idx = (idx + 1) % this.candidates.length
|
||||||
groups[fingerprint] = idx
|
groups[fingerprint] = idx
|
||||||
|
|
||||||
return evalValue(candidate, scope)
|
return evalValue(candidate, ctx)
|
||||||
}
|
}
|
||||||
}
|
} as ITagImplOptions
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user