This commit is contained in:
tatianamac
2019-11-26 14:50:43 -08:00
parent 8a55660ed0
commit 6d5445ecc5
13894 changed files with 2233957 additions and 0 deletions

20
node_modules/liquidjs/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,20 @@
## [6.4.3](https://github.com/harttle/liquidjs/compare/v6.4.2...v6.4.3) (2019-02-13)
### Bug Fixes
* better index.d.ts and a demo ([2015f68](https://github.com/harttle/liquidjs/commit/2015f68)), closes [#98](https://github.com/harttle/liquidjs/issues/98)
## [6.4.2](https://github.com/harttle/liquidjs/compare/v6.4.1...v6.4.2) (2019-01-28)
### Bug Fixes
* **CI:** e2e not building cjs ([dde7b3b](https://github.com/harttle/liquidjs/commit/dde7b3b))
## [6.4.1](https://github.com/harttle/liquidjs/compare/v6.4.0...v6.4.1) (2019-01-28)
### Bug Fixes
* regenerator undefined ([a2caeb5](https://github.com/harttle/liquidjs/commit/a2caeb5))

21
node_modules/liquidjs/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Jun Yang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

276
node_modules/liquidjs/README.md generated vendored Normal file
View File

@@ -0,0 +1,276 @@
# liquidjs
[![npm](https://img.shields.io/npm/v/liquidjs.svg)](https://www.npmjs.org/package/liquidjs)
[![npm](https://img.shields.io/npm/dm/liquidjs.svg)](https://www.npmjs.org/package/liquidjs)
[![Build Status](https://travis-ci.org/harttle/liquidjs.svg?branch=master)](https://travis-ci.org/harttle/liquidjs)
[![Coveralls](https://img.shields.io/coveralls/harttle/liquidjs.svg)](https://coveralls.io/github/harttle/liquidjs?branch=master)
[![GitHub issues](https://img.shields.io/github/issues-closed/harttle/liquidjs.svg)](https://github.com/harttle/liquidjs/issues)
[![GitHub contributors](https://img.shields.io/github/contributors/harttle/liquidjs.svg)](https://github.com/harttle/liquidjs/graphs/contributors)
[![David](https://img.shields.io/david/harttle/liquidjs.svg)](https://david-dm.org/harttle/liquidjs)
[![David Dev](https://img.shields.io/david/dev/harttle/liquidjs.svg)](https://david-dm.org/harttle/liquidjs?type=dev)
[![DUB](https://img.shields.io/dub/l/vibe-d.svg)](https://github.com/harttle/liquidjs/blob/master/LICENSE)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://github.com/harttle/liquidjs)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](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/>
**Features**
* Fully compatible to [shopify][shopify/liquid], with all [tags][tags] and [filters][filters] implemented
* Support layout(extend) and include syntax
* In pure JavaScript with Promise-based API
**Differences**
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:
* 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).
* 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).
* [.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_s()](https://www.rubydoc.info/gems/liquid/Liquid/Drop) uses `JSON.prototype.stringify` as default, rather than Ruby's inspect.
## TOC
* Usage
* [Render from String](#render-from-string)
* [Render from File](#render-from-file)
* [Use with Express.js](#use-with-expressjs)
* [Use in Browser](#use-in-browser)
* [Include Partials](#include-partials)
* [Layout Templates (Extends)](#layout-templates-extends)
* API Spec
* [Constructor Options](#options)
* [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)
* [Operators](https://github.com/harttle/liquidjs/wiki/Operators)
* [Whitespace Control](https://github.com/harttle/liquidjs/wiki/Whitespace-Control)
* [Contribute Guidelines](#contribute-guidelines)
## Render from String
Install as Node.js dependency:
```bash
# You'll need a promise-polyfill for Node.js < 4
npm install --save liquidjs
```
Parse and Render:
```javascript
var Liquid = require('liquidjs');
var engine = Liquid();
engine
.parseAndRender('{{name | capitalize}}', {name: 'alice'})
.then(console.log);
// outputs 'Alice'
```
Caching templates:
```javascript
var tpl = engine.parse('{{name | capitalize}}');
engine
.render(tpl, {name: 'alice'})
.then(console.log);
// outputs 'Alice'
```
## Render from File
```javascript
var engine = Liquid({
root: path.resolve(__dirname, 'views/'), // dirs to lookup layouts/includes
extname: '.liquid' // the extname used for layouts/includes, defaults ""
});
engine.renderFile("hello.liquid", {name: 'alice'})
.then(console.log) // outputs "Alice"
// which is equivalent to:
engine
.renderFile("hello", {name: 'alice'})
.then(console.log) // outputs "Alice"
```
## Use with Express.js
```javascript
// register liquid engine
app.engine('liquid', engine.express());
app.set('views', './views'); // specify the views directory
app.set('view engine', 'liquid'); // set to default
```
[Here](demo/express/)'s an Express demo. When used with Express.js,
Express [`views`][express-views] will be included when looking up
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
```
// file: color.liquid
color: '{{ color }}' shape: '{{ shape }}'
// file: theme.liquid
{% assign shape = 'circle' %}
{% include 'color' %}
{% include 'color' with 'red' %}
{% include 'color', color: 'yellow', shape: 'square' %}
```
The output will be:
```
color: '' shape: 'circle'
color: 'red' shape: 'circle'
color: 'yellow' shape: 'square'
```
## Layout Templates (Extends)
```
// file: default-layout.liquid
Header
{% block content %}My default content{% endblock %}
Footer
// file: page.liquid
{% layout "default-layout" %}
{% block content %}My page content{% endblock %}
```
The output of `page.liquid`:
```
Header
My page content
Footer
```
* It's possible to define multiple blocks.
* block name is optional when there's only one block.
## Options
The full list of options for `Liquid()` is listed as following:
* `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 `["."]`
* `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 `""`.
* `cache` indicates whether or not to cache resolved templates. Defaults to `false`.
* `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`.
* `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`.
* `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_left` is similiar to `trim_tag_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
* `trim_value_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`.
* `trim_value_left` is similiar to `trim_value_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
* `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`.
## Register Filters
```javascript
// Usage: {{ name | uppper }}
engine.registerFilter('upper', v => v.toUpperCase())
```
Filter arguments will be passed to the registered filter function, for example:
```javascript
// Usage: {{ 1 | add: 2, 3 }}
engine.registerFilter('add', (initial, arg1, arg2) => initial + arg1 + arg2)
```
See existing filter implementations here: <https://github.com/harttle/liquidjs/blob/master/filters.js>
## Register Tags
```javascript
// Usage: {% upper name%}
engine.registerTag('upper', {
parse: function(tagToken, remainTokens) {
this.str = tagToken.args; // name
},
render: function(scope, hash) {
var str = Liquid.evalValue(this.str, scope); // 'alice'
return Promise.resolve(str.toUpperCase()); // 'Alice'
}
});
```
* `parse`: Read tokens from `remainTokens` until your end token.
* `render`: Combine scope data with your parsed tokens into HTML string.
See existing tag implementations here: <https://github.com/harttle/liquidjs/blob/master/tags/>
## Plugin API
A pack of tags or filters can be encapsulated into a **plugin**, which will be typically installed via npm.
```javascript
engine.plugin(require('./some-plugin'));
// some-plugin.js
module.exports = function (Liquid) {
// here `this` refers to the engine instance
// `Liquid` provides facilities to implement tags and filters
this.registerFilter('foo', x => x);
}
```
Plugin List:
* To add your plugin, contact me or simply send a PR.
## 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.
* Code Style: <https://github.com/standard/eslint-config-standard>, `npm run lint` to check locally.
* Commit Message: <https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits>
[nunjucks]: http://mozilla.github.io/nunjucks/
[liquid-node]: https://github.com/sirlantis/liquid-node
[shopify/liquid]: https://shopify.github.io/liquid/
[jekyll]: http://jekyllrb.com/
[gh]: https://pages.github.com/
[releases]: https://github.com/harttle/liquidjs/releases
[any-promise]: https://github.com/kevinbeaty/any-promise
[test]: https://github.com/harttle/liquidjs/tree/master/test
[caniuse-promises]: http://caniuse.com/#feat=promises
[whitespace control]: https://github.com/harttle/liquidjs/wiki/Whitespace-Control
[tags]: https://github.com/harttle/liquidjs/wiki/Builtin-Tags
[filters]: https://github.com/harttle/liquidjs/wiki/Builtin-Filters
[express-views]: http://expressjs.com/en/guide/using-template-engines.html
[pp]: https://github.com/taylorhakes/promise-polyfill

1
node_modules/liquidjs/demo/browser/date.html generated vendored Normal file
View File

@@ -0,0 +1 @@
access time: {{date|date: "%Y-%m-%d %H:%M:%S"}}

1
node_modules/liquidjs/demo/browser/hello.html generated vendored Normal file
View File

@@ -0,0 +1 @@
<h2>Welcome to {{ name | capitalize}}, {% include 'date.html' %}</h2>

31
node_modules/liquidjs/demo/browser/index.html generated vendored Normal file
View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>liquidjs for the browser</title>
<script src="../../dist/liquid.js"></script>
</head>
<body>
<script>
var engine = window.Liquid({
extname: '.html',
cache: true
});
var src = '<h2>Welcome to {{ name | capitalize}}, ' +
'access time: {{date|date: "%Y-%m-%d %H:%M:%S"}}&lt;/h2>';
var ctx = {
name: 'Liquid',
date: new Date()
};
engine.parseAndRender(src, ctx)
.then(function(html) {
return engine.renderFile('hello', ctx);
})
.then(function(html) {
document.body.innerHTML += html
});
</script>
</body>
</html>

22
node_modules/liquidjs/demo/express/app.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
const express = require('express')
const Liquid = require('../..')
let app = express()
let engine = Liquid({
root: __dirname, // for layouts and partials
extname: '.liquid'
})
app.engine('liquid', engine.express()) // register liquid engine
app.set('views', ['./partials', './views']) // specify the views directory
app.set('view engine', 'liquid') // set to default
app.get('/', function (req, res) {
let todos = ['fork and clone', 'make it better', 'make a pull request']
res.render('todolist', {
todos: todos,
title: 'Welcome to liquidjs!'
})
})
module.exports = app

5
node_modules/liquidjs/demo/express/index.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
const app = require('./app.js')
app.listen(3000, function () {
console.log('Express running: http://localhost:3000')
})

15
node_modules/liquidjs/demo/express/package.json generated vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "express-demo",
"version": "1.0.0",
"description": "Express Demo Using liquidjs",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "harttle",
"license": "MIT",
"dependencies": {
"express": "^4.14.0"
}
}

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
{% block %}{% endblock %}
<footer> {% block footer %}{% endblock %} </footer>
</body>
</html>

View File

@@ -0,0 +1 @@
{{id}} - {{todo}}

View File

@@ -0,0 +1,11 @@
{% layout 'layout' %}
<ul>
{% for todo in todos %}
<li>{% include 'todo', id:forloop.index %}</li>
{% endfor %}
</ul>
{% block 'footer' %}
Copyright @ 2016, Harttle
{% endblock %}

12
node_modules/liquidjs/demo/nodejs/index.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
const Liquid = require('liquidjs')
const engine = new Liquid({
root: __dirname,
extname: '.liquid'
})
const ctx = {
todos: ['fork and clone', 'make it better', 'make a pull request'],
title: 'Welcome to liquidjs!'
}
engine.renderFile('todolist', ctx).then(console.log)

5
node_modules/liquidjs/demo/nodejs/todolist.liquid generated vendored Normal file
View File

@@ -0,0 +1,5 @@
<ul>
{% for todo in todos %}
<li>{{forloop.index}} - {{todo}}</li>
{% endfor %}
</ul>

2510
node_modules/liquidjs/demo/reactjs/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

30
node_modules/liquidjs/demo/reactjs/package.json generated vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "react-liquidjs",
"version": "0.1.0",
"private": true,
"dependencies": {
"dns": "^0.2.2",
"html-react-parser": "^0.4.7",
"liquidjs": "^6.0.1",
"path": "^0.12.7",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-promise": "^2.0.3",
"react-scripts": "2.0.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}

BIN
node_modules/liquidjs/demo/reactjs/public/favicon.ico generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

41
node_modules/liquidjs/demo/reactjs/public/index.html generated vendored Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="result"></div>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

32
node_modules/liquidjs/demo/reactjs/src/App.css generated vendored Normal file
View File

@@ -0,0 +1,32 @@
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

46
node_modules/liquidjs/demo/reactjs/src/App.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
let path = require('path')
let Liquid = require('liquidjs');
let config = require('./views/demo.liquid');
let pageConfig = config.toString()
let Parser = require('html-react-parser');
class App extends Component {
componentDidMount() {
let engine = Liquid({
root: path.resolve(__dirname, 'views/'), // dirs to lookup layouts/includes
extname: '.liquid' // the extname used for layouts/includes, defaults
});
engine.registerFilter('image', d => {
let img = `<img src="${d}" class="App-logo" alt="logo"></img>`;
return img
})
engine.renderFile(pageConfig, {name: 'alice', logo: logo })
.then((htmlTemp) => {
this.setState({ html: htmlTemp })
}) // outputs "Alice"
}
state = {
html: []
}
render() {
return (
<div className="App">
{Parser(`${this.state.html}`)}
</div>
);
}
}
export default App;

9
node_modules/liquidjs/demo/reactjs/src/App.test.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

14
node_modules/liquidjs/demo/reactjs/src/index.css generated vendored Normal file
View File

@@ -0,0 +1,14 @@
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

12
node_modules/liquidjs/demo/reactjs/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();

7
node_modules/liquidjs/demo/reactjs/src/logo.svg generated vendored Normal file
View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

127
node_modules/liquidjs/demo/reactjs/src/serviceWorker.js generated vendored Normal file
View File

@@ -0,0 +1,127 @@
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
);
});
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
// Execute callback
if (config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}

View File

@@ -0,0 +1,18 @@
<header className="App-header">
{{ logo | image }}
<h2>Welcome {{name | capitalize}}</h2>
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<p>
You are using liquidjs & Reactjs
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>

8521
node_modules/liquidjs/demo/reactjs/yarn.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

13
node_modules/liquidjs/demo/typescript/index.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import Liquid, {isTruthy} from 'liquidjs'
const engine = new Liquid({
root: __dirname,
extname: '.liquid'
})
const ctx = {
todos: ['fork and clone', 'make it better', 'make a pull request'],
title: 'Welcome to liquidjs!'
}
// console.log('isTruthy:', isTruthy('a string here'));
engine.renderFile('todolist', ctx).then(console.log)

View File

@@ -0,0 +1,5 @@
<ul>
{% for todo in todos %}
<li>{{forloop.index}} - {{todo}}</li>
{% endfor %}
</ul>

3645
node_modules/liquidjs/dist/liquid.common.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/liquidjs/dist/liquid.common.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

3593
node_modules/liquidjs/dist/liquid.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/liquidjs/dist/liquid.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

2
node_modules/liquidjs/dist/liquid.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
node_modules/liquidjs/dist/liquid.min.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

153
node_modules/liquidjs/package.json generated vendored Normal file
View File

@@ -0,0 +1,153 @@
{
"_args": [
[
"liquidjs@6.4.3",
"/Users/tatiana/selfdefined"
]
],
"_from": "liquidjs@6.4.3",
"_id": "liquidjs@6.4.3",
"_inBundle": false,
"_integrity": "sha512-m1xSB10Ncu22NR3X0xdaqu/GvP1xadDCFYGqGgd6me8DAWjyA68BKE5DHJmSxw1CGsWPsX+Hj2v/87J2w/LvMQ==",
"_location": "/liquidjs",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "liquidjs@6.4.3",
"name": "liquidjs",
"escapedName": "liquidjs",
"rawSpec": "6.4.3",
"saveSpec": null,
"fetchSpec": "6.4.3"
},
"_requiredBy": [
"/@11ty/eleventy"
],
"_resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-6.4.3.tgz",
"_spec": "6.4.3",
"_where": "/Users/tatiana/selfdefined",
"author": {
"name": "Harttle"
},
"babel": {
"presets": [
"env"
],
"plugins": [
[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]
],
"env": {
"test": {
"plugins": [
"istanbul"
]
}
}
},
"browser": "dist/liquid.js",
"bugs": {
"url": "https://github.com/harttle/liquidjs/issues"
},
"description": "Liquid template engine by pure JavaScript: compatible to shopify, easy to extend.",
"devDependencies": {
"@semantic-release/changelog": "^3.0.2",
"@semantic-release/commit-analyzer": "^6.1.0",
"@semantic-release/git": "^7.0.8",
"@semantic-release/npm": "^5.1.4",
"@semantic-release/release-notes-generator": "^7.1.4",
"babel-core": "^6.26.3",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-istanbul": "^5.1.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-runtime": "^6.26.0",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"coveralls": "^3.0.2",
"cross-env": "^5.2.0",
"eslint": "^5.12.1",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.15.0",
"eslint-plugin-mocha": "^5.2.1",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"express": "^4.16.4",
"http-server": "^0.11.1",
"jsdom": "^13.2.0",
"mocha": "^5.2.0",
"mock-fs": "^4.7.0",
"nyc": "^13.1.0",
"regenerator-runtime": "^0.12.1",
"rollup": "^1.1.2",
"rollup-plugin-alias": "^1.5.1",
"rollup-plugin-babel": "^3.0.7",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-shim": "^1.0.0",
"rollup-plugin-uglify": "^6.0.2",
"semantic-release": "^15.13.3",
"sinon": "^7.2.3",
"sinon-chai": "^3.3.0",
"supertest": "^3.4.2"
},
"engines": {
"node": ">=4.8.7"
},
"homepage": "https://github.com/harttle/liquidjs#readme",
"keywords": [
"liquid",
"template engine",
"express",
"jinja",
"shopify"
],
"license": "MIT",
"main": "dist/liquid.common.js",
"module": "src/index.js",
"name": "liquidjs",
"nyc": {
"require": [
"babel-core/register"
],
"sourceMap": false,
"instrument": false
},
"release": {
"branch": "master",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/harttle/liquidjs.git"
},
"scripts": {
"build": "rollup -c && ls -lh dist",
"coverage": "cross-env NODE_ENV=test nyc --reporter=html npm run unit",
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"demo:browser": "echo open http://localhost:8080/demo/browser && http-server -c-1",
"demo:express": "cd ./demo/express/ && npm start",
"demo:nodejs": "node ./demo/nodejs/index.js",
"e2e": "mocha test/e2e",
"lint": "eslint src/ test/ *.js",
"test": "npm run unit && npm run e2e",
"unit": "mocha test/unit",
"version": "npm run build && git add -A dist"
},
"types": "src/index.d.ts",
"version": "6.4.3"
}

75
node_modules/liquidjs/rollup.config.js generated vendored Normal file
View File

@@ -0,0 +1,75 @@
import shim from 'rollup-plugin-shim'
import alias from 'rollup-plugin-alias'
import babel from 'rollup-plugin-babel'
import { uglify } from 'rollup-plugin-uglify'
import pkg from './package.json'
import nodeResolve from 'rollup-plugin-node-resolve'
const fake = { fs: `export default {}`, path: `export default {}` }
const version = process.env.VERSION || pkg.version
const sourcemap = true
const banner = `/*
* liquidjs@${version}, https://github.com/harttle/liquidjs
* (c) 2016-${new Date().getFullYear()} harttle
* Released under the MIT License.
*/`
const treeshake = {
propertyReadSideEffects: false
}
const input = 'src/index.js'
const babelConf = {
babelrc: false,
'presets': [['env', { 'modules': false }]],
'plugins': ['external-helpers']
}
export default [{
output: [{
file: 'dist/liquid.common.js',
name: 'Liquid',
format: 'cjs',
sourcemap,
banner
}],
external: ['path', 'fs'],
plugins: [
nodeResolve(),
babel(babelConf)
],
treeshake,
input
}, {
output: [{
file: 'dist/liquid.js',
name: 'Liquid',
format: 'umd',
sourcemap,
banner
}],
plugins: [
shim(fake),
alias({
'./template': './template-browser'
}),
nodeResolve(),
babel(babelConf)
],
treeshake,
input
}, {
output: [{
file: 'dist/liquid.min.js',
name: 'Liquid',
format: 'umd',
sourcemap
}],
plugins: [
shim(fake),
nodeResolve(),
babel(babelConf),
uglify()
],
treeshake,
input
}]

68
node_modules/liquidjs/src/filter.js generated vendored Normal file
View File

@@ -0,0 +1,68 @@
import * as lexical from './lexical.js'
import { evalValue } from './syntax.js'
import assert from './util/assert.js'
import { assign, create } from './util/underscore.js'
const valueRE = new RegExp(`${lexical.value.source}`, 'g')
export default function (options) {
options = assign({}, options)
let filters = {}
const _filterInstance = {
render: function (output, scope) {
const args = this.args.map(arg => evalValue(arg, scope))
args.unshift(output)
return this.filter.apply(null, args)
},
parse: function (str) {
let match = lexical.filterLine.exec(str)
assert(match, 'illegal filter: ' + str)
const name = match[1]
const argList = match[2] || ''
const filter = filters[name]
if (typeof filter !== 'function') {
if (options.strict_filters) {
throw new TypeError(`undefined filter: ${name}`)
}
this.name = name
this.filter = x => x
this.args = []
return this
}
const args = []
while ((match = valueRE.exec(argList.trim()))) {
const v = match[0]
const re = new RegExp(`${v}\\s*:`, 'g')
const keyMatch = re.exec(match.input)
const currentMatchIsKey = keyMatch && keyMatch.index === match.index
currentMatchIsKey ? args.push(`'${v}'`) : args.push(v)
}
this.name = name
this.filter = filter
this.args = args
return this
}
}
function construct (str) {
const instance = create(_filterInstance)
return instance.parse(str)
}
function register (name, filter) {
filters[name] = filter
}
function clear () {
filters = {}
}
return {
construct, register, clear
}
}

139
node_modules/liquidjs/src/filters.js generated vendored Normal file
View File

@@ -0,0 +1,139 @@
import strftime from './util/strftime.js'
import * as _ from './util/underscore.js'
import { isTruthy } from './syntax.js'
const escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
"'": '&#39;'
}
const unescapeMap = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&#34;': '"',
'&#39;': "'"
}
const filters = {
'abs': v => Math.abs(v),
'append': (v, arg) => v + arg,
'capitalize': str => stringify(str).charAt(0).toUpperCase() + str.slice(1),
'ceil': v => Math.ceil(v),
'concat': (v, arg) => Array.prototype.concat.call(v, arg),
'date': (v, arg) => {
let date = v
if (v === 'now') {
date = new Date()
} else if (_.isString(v)) {
date = new Date(v)
}
return isValidDate(date) ? strftime(date, arg) : v
},
'default': (v, arg) => isTruthy(v) ? v : arg,
'divided_by': (v, arg) => v / arg,
'downcase': v => v.toLowerCase(),
'escape': escape,
'escape_once': str => escape(unescape(str)),
'first': v => v[0],
'floor': v => Math.floor(v),
'join': (v, arg) => v.join(arg === undefined ? ' ' : arg),
'last': v => _.last(v),
'lstrip': v => stringify(v).replace(/^\s+/, ''),
'map': (arr, arg) => arr.map(v => v[arg]),
'minus': bindFixed((v, arg) => v - arg),
'modulo': bindFixed((v, arg) => v % arg),
'newline_to_br': v => v.replace(/\n/g, '<br />'),
'plus': bindFixed((v, arg) => Number(v) + Number(arg)),
'prepend': (v, arg) => arg + v,
'remove': (v, arg) => v.split(arg).join(''),
'remove_first': (v, l) => v.replace(l, ''),
'replace': (v, pattern, replacement) =>
stringify(v).split(pattern).join(replacement),
'replace_first': (v, arg1, arg2) => stringify(v).replace(arg1, arg2),
'reverse': v => v.reverse(),
'round': (v, arg) => {
const amp = Math.pow(10, arg || 0)
return Math.round(v * amp, arg) / amp
},
'rstrip': str => stringify(str).replace(/\s+$/, ''),
'size': v => v.length,
'slice': (v, begin, length) => {
if (length === undefined) length = 1
return v.slice(begin, begin + length)
},
'sort': (v, arg) => v.sort(arg),
'split': (v, arg) => stringify(v).split(arg),
'strip': (v) => stringify(v).trim(),
'strip_html': v => stringify(v).replace(/<script.*?<\/script>|<!--.*?-->|<style.*?<\/style>|<.*?>/g, ''),
'strip_newlines': v => stringify(v).replace(/\n/g, ''),
'times': (v, arg) => v * arg,
'truncate': (v, l, o) => {
v = stringify(v)
o = (o === undefined) ? '...' : o
l = l || 16
if (v.length <= l) return v
return v.substr(0, l - o.length) + o
},
'truncatewords': (v, l, o) => {
if (o === undefined) o = '...'
const arr = v.split(' ')
let ret = arr.slice(0, l).join(' ')
if (arr.length > l) ret += o
return ret
},
'uniq': function (arr) {
const u = {}
return (arr || []).filter(val => {
if (u.hasOwnProperty(val)) {
return false
}
u[val] = true
return true
})
},
'upcase': str => stringify(str).toUpperCase(),
'url_decode': x => x.split('+').map(decodeURIComponent).join(' '),
'url_encode': x => x.split(' ').map(encodeURIComponent).join('+')
}
function escape (str) {
return stringify(str).replace(/&|<|>|"|'/g, m => escapeMap[m])
}
function unescape (str) {
return stringify(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m])
}
function getFixed (v) {
const p = (v + '').split('.')
return (p.length > 1) ? p[1].length : 0
}
function getMaxFixed (l, r) {
return Math.max(getFixed(l), getFixed(r))
}
function stringify (obj) {
return obj + ''
}
function bindFixed (cb) {
return (l, r) => {
const f = getMaxFixed(l, r)
return cb(l, r).toFixed(f)
}
}
function isValidDate (date) {
return date instanceof Date && !isNaN(date.getTime())
}
export default function registerAll (liquid) {
return _.forOwn(filters, (func, name) => liquid.registerFilter(name, func))
}
registerAll.filters = filters

69
node_modules/liquidjs/src/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,69 @@
export as namespace Liquid;
export function isTruthy(val: any): boolean;
export function isFalsy(val: any): boolean;
export function evalExp(exp: string, scope: any): any;
export function evalValue(str: string, scope: any): any;
export default class Liquid {
constructor(options?: Options);
private init(tag, filter, options): Liquid;
private respectCache(key, getter): Promise<any>
parse(html: string, filepath?: string): Liquid.Template
render(tpl: Template, ctx: any, opts?: Options): Promise<string>
parseAndRender(html: string, ctx: any, opts?: Options): Promise<string>
renderFile(file: string, ctx: any, opts?: Options): Promise<string>
getTemplate(file: string, root: string): Promise<Liquid.Template>
registerFilter(name: string, filter: Filter): void
registerTag(name: string, tag: Tag): void
express(opts: Options): any
}
export interface Options {
/** `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
/** `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_value_right` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`. */
trim_value_right?: boolean
/** `trim_value_left` is similar to `trim_value_right`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
trim_value_left?: boolean
/** `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 Template { }
export interface Tag {
parse(this: any, tagToken: any, remainTokens: any): void
render(this: any, scope: any, hash: any): void
}
export type Filter = (...args: any) => string
declare namespace Types {
class LiquidError extends Error {
input: string
line: number
file: string
}
class ParseError extends LiquidError {
originalError: Error
}
class TokenizationError extends LiquidError {}
class RenderBreakError extends LiquidError {}
class AssertionError extends LiquidError {}
class AssignScope {}
class CaptureScope {}
class IncrementScope {}
class DecrementScope {}
}

134
node_modules/liquidjs/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,134 @@
import 'regenerator-runtime/runtime'
import * as Scope from './scope'
import * as template from './template'
import * as _ from './util/underscore.js'
import assert from './util/assert.js'
import * as tokenizer from './tokenizer.js'
import Render from './render.js'
import Tag from './tag.js'
import Filter from './filter.js'
import Parser from './parser'
import { isTruthy, isFalsy, evalExp, evalValue } from './syntax.js'
import { ParseError, TokenizationError, RenderBreakError, AssertionError } from './util/error.js'
import tags from './tags/index.js'
import filters from './filters.js'
const _engine = {
init: function (tag, filter, options) {
if (options.cache) {
this.cache = {}
}
this.options = options
this.tag = tag
this.filter = filter
this.parser = Parser(tag, filter)
this.renderer = Render()
tags(this, Liquid)
filters(this, Liquid)
return this
},
parse: function (html, filepath) {
const tokens = tokenizer.parse(html, filepath, this.options)
return this.parser.parse(tokens)
},
render: function (tpl, ctx, opts) {
opts = _.assign({}, this.options, opts)
const scope = Scope.factory(ctx, opts)
return this.renderer.renderTemplates(tpl, scope)
},
parseAndRender: async function (html, ctx, opts) {
const tpl = await this.parse(html)
return this.render(tpl, ctx, opts)
},
getTemplate: async function (file, root) {
const filepath = await template.resolve(file, root, this.options)
return this.respectCache(filepath, async () => {
const str = await template.read(filepath)
return this.parse(str, filepath)
})
},
renderFile: async function (file, ctx, opts) {
opts = _.assign({}, opts)
const templates = await this.getTemplate(file, opts.root)
return this.render(templates, ctx, opts)
},
respectCache: async function (key, getter) {
const cacheEnabled = this.options.cache
if (cacheEnabled && this.cache[key]) {
return this.cache[key]
}
const value = await getter()
if (cacheEnabled) {
this.cache[key] = value
}
return value
},
evalValue: function (str, scope) {
const tpl = this.parser.parseValue(str.trim())
return this.renderer.evalValue(tpl, scope)
},
registerFilter: function (name, filter) {
return this.filter.register(name, filter)
},
registerTag: function (name, tag) {
return this.tag.register(name, tag)
},
plugin: function (plugin) {
return plugin.call(this, Liquid)
},
express: function (opts) {
opts = opts || {}
const self = this
return function (filePath, ctx, cb) {
assert(_.isArray(this.root) || _.isString(this.root),
'illegal views root, are you using express.js?')
opts.root = this.root
self.renderFile(filePath, ctx, opts).then(html => cb(null, html), cb)
}
}
}
function normalizeStringArray (value) {
if (_.isArray(value)) return value
if (_.isString(value)) return [value]
throw new TypeError('illegal root: ' + value)
}
export default function Liquid (options) {
options = _.assign({
root: ['.'],
cache: false,
extname: '',
dynamicPartials: true,
trim_tag_right: false,
trim_tag_left: false,
trim_value_right: false,
trim_value_left: false,
greedy: true,
strict_filters: false,
strict_variables: false
}, options)
options.root = normalizeStringArray(options.root)
const engine = _.create(_engine)
engine.init(Tag(), Filter(options), options)
return engine
}
Liquid.default = Liquid
Liquid.isTruthy = isTruthy
Liquid.isFalsy = isFalsy
Liquid.evalExp = evalExp
Liquid.evalValue = evalValue
Liquid.Types = {
ParseError,
TokenizationError,
RenderBreakError,
AssertionError,
AssignScope: {},
CaptureScope: {},
IncrementScope: {},
DecrementScope: {}
}

86
node_modules/liquidjs/src/lexical.js generated vendored Normal file
View File

@@ -0,0 +1,86 @@
// quote related
const singleQuoted = /'[^']*'/
const doubleQuoted = /"[^"]*"/
export const quoted = new RegExp(`${singleQuoted.source}|${doubleQuoted.source}`)
export const quoteBalanced = new RegExp(`(?:${quoted.source}|[^'"])*`)
// basic types
export const integer = /-?\d+/
export const number = /-?\d+\.?\d*|\.?\d+/
export const bool = /true|false/
// property access
export const identifier = /[\w-]+[?]?/
export const subscript = new RegExp(`\\[(?:${quoted.source}|[\\w-\\.]+)\\]`)
export const literal = new RegExp(`(?:${quoted.source}|${bool.source}|${number.source})`)
export const variable = new RegExp(`${identifier.source}(?:\\.${identifier.source}|${subscript.source})*`)
// range related
export const rangeLimit = new RegExp(`(?:${variable.source}|${number.source})`)
export const range = new RegExp(`\\(${rangeLimit.source}\\.\\.${rangeLimit.source}\\)`)
export const rangeCapture = new RegExp(`\\((${rangeLimit.source})\\.\\.(${rangeLimit.source})\\)`)
export const value = new RegExp(`(?:${variable.source}|${literal.source}|${range.source})`)
// hash related
export const hash = new RegExp(`(?:${identifier.source})\\s*:\\s*(?:${value.source})`)
export const hashCapture = new RegExp(`(${identifier.source})\\s*:\\s*(${value.source})`, 'g')
// full match
export const tagLine = new RegExp(`^\\s*(${identifier.source})\\s*([\\s\\S]*)\\s*$`)
export const literalLine = new RegExp(`^${literal.source}$`, 'i')
export const variableLine = new RegExp(`^${variable.source}$`)
export const numberLine = new RegExp(`^${number.source}$`)
export const boolLine = new RegExp(`^${bool.source}$`, 'i')
export const quotedLine = new RegExp(`^${quoted.source}$`)
export const rangeLine = new RegExp(`^${rangeCapture.source}$`)
export const integerLine = new RegExp(`^${integer.source}$`)
// filter related
export const valueDeclaration = new RegExp(`(?:${identifier.source}\\s*:\\s*)?${value.source}`)
export const valueList = new RegExp(`${valueDeclaration.source}(\\s*,\\s*${valueDeclaration.source})*`)
export const filter = new RegExp(`${identifier.source}(?:\\s*:\\s*${valueList.source})?`, 'g')
export const filterCapture = new RegExp(`(${identifier.source})(?:\\s*:\\s*(${valueList.source}))?`)
export const filterLine = new RegExp(`^${filterCapture.source}$`)
export const operators = [
/\s+or\s+/,
/\s+and\s+/,
/==|!=|<=|>=|<|>|\s+contains\s+/
]
export function isInteger (str) {
return integerLine.test(str)
}
export function isLiteral (str) {
return literalLine.test(str)
}
export function isRange (str) {
return rangeLine.test(str)
}
export function isVariable (str) {
return variableLine.test(str)
}
export function matchValue (str) {
return value.exec(str)
}
export function parseLiteral (str) {
let res = str.match(numberLine)
if (res) {
return Number(str)
}
res = str.match(boolLine)
if (res) {
return str.toLowerCase() === 'true'
}
res = str.match(quotedLine)
if (res) {
return str.slice(1, -1)
}
throw new TypeError(`cannot parse '${str}' as literal`)
}

17
node_modules/liquidjs/src/operators.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
export default function (isTruthy) {
return {
'==': (l, r) => l === r,
'!=': (l, r) => l !== r,
'>': (l, r) => l !== null && r !== null && l > r,
'<': (l, r) => l !== null && r !== null && l < r,
'>=': (l, r) => l !== null && r !== null && l >= r,
'<=': (l, r) => l !== null && r !== null && l <= r,
'contains': (l, r) => {
if (!l) return false
if (typeof l.indexOf !== 'function') return false
return l.indexOf(r) > -1
},
'and': (l, r) => isTruthy(l) && isTruthy(r),
'or': (l, r) => isTruthy(l) || isTruthy(r)
}
}

106
node_modules/liquidjs/src/parser.js generated vendored Normal file
View File

@@ -0,0 +1,106 @@
import * as lexical from './lexical.js'
import { create } from './util/underscore.js'
import { ParseError } from './util/error.js'
import assert from './util/assert.js'
export default function (Tag, Filter) {
const stream = {
init: function (tokens) {
this.tokens = tokens
this.handlers = {}
return this
},
on: function (name, cb) {
this.handlers[name] = cb
return this
},
trigger: function (event, arg) {
const h = this.handlers[event]
if (typeof h === 'function') {
h(arg)
return true
}
},
start: function () {
this.trigger('start')
let token
while (!this.stopRequested && (token = this.tokens.shift())) {
if (this.trigger('token', token)) continue
if (token.type === 'tag' &&
this.trigger(`tag:${token.name}`, token)) {
continue
}
const template = parseToken(token, this.tokens)
this.trigger('template', template)
}
if (!this.stopRequested) this.trigger('end')
return this
},
stop: function () {
this.stopRequested = true
return this
}
}
function parse (tokens) {
let token
const templates = []
while ((token = tokens.shift())) {
templates.push(parseToken(token, tokens))
}
return templates
}
function parseToken (token, tokens) {
try {
let tpl = null
if (token.type === 'tag') {
tpl = parseTag(token, tokens)
} else if (token.type === 'value') {
tpl = parseValue(token.value)
} else { // token.type === 'html'
tpl = token
}
tpl.token = token
return tpl
} catch (e) {
throw new ParseError(e, token)
}
}
function parseTag (token, tokens) {
if (token.name === 'continue' || token.name === 'break') return token
return Tag.construct(token, tokens)
}
function parseValue (str) {
let match = lexical.matchValue(str)
assert(match, `illegal value string: ${str}`)
const initial = match[0]
str = str.substr(match.index + match[0].length)
const filters = []
while ((match = lexical.filter.exec(str))) {
filters.push([match[0].trim()])
}
return {
type: 'value',
initial: initial,
filters: filters.map(str => Filter.construct(str))
}
}
function parseStream (tokens) {
const s = create(stream)
return s.init(tokens)
}
return {
parse,
parseTag,
parseStream,
parseValue
}
}

62
node_modules/liquidjs/src/render.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
import { evalExp } from './syntax.js'
import { RenderBreakError, RenderError } from './util/error.js'
import { stringify, create } from './util/underscore.js'
import assert from './util/assert.js'
const render = {
renderTemplates: async function (templates, scope) {
assert(scope, 'unable to evalTemplates: scope undefined')
let html = ''
for (const tpl of templates) {
try {
html += await renderTemplate.call(this, tpl)
} catch (e) {
if (e instanceof RenderBreakError) {
e.resolvedHTML = html
throw e
}
throw new RenderError(e, tpl)
}
}
return html
async function renderTemplate (template) {
if (template.type === 'tag') {
const partial = await this.renderTag(template, scope)
return partial === undefined ? '' : partial
}
if (template.type === 'value') {
return this.renderValue(template, scope)
}
return template.value
}
},
renderTag: async function (template, scope) {
if (template.name === 'continue') {
throw new RenderBreakError('continue')
}
if (template.name === 'break') {
throw new RenderBreakError('break')
}
return template.render(scope)
},
renderValue: async function (template, scope) {
const partial = this.evalValue(template, scope)
return partial === undefined ? '' : stringify(partial)
},
evalValue: function (template, scope) {
assert(scope, 'unable to evalValue: scope undefined')
return template.filters.reduce(
(prev, filter) => filter.render(prev, scope),
evalExp(template.initial, scope))
}
}
export default function () {
const instance = create(render)
return instance
}

179
node_modules/liquidjs/src/scope.js generated vendored Normal file
View File

@@ -0,0 +1,179 @@
import * as _ from './util/underscore.js'
import * as lexical from './lexical.js'
import assert from './util/assert.js'
const Scope = {
getAll: function () {
return this.contexts.reduce((ctx, val) => _.assign(ctx, val), _.create(null))
},
get: function (path) {
const paths = this.propertyAccessSeq(path)
const scope = this.findContextFor(paths[0]) || _.last(this.contexts)
return paths.reduce((value, key) => this.readProperty(value, key), scope)
},
set: function (path, v) {
const paths = this.propertyAccessSeq(path)
let scope = this.findContextFor(paths[0]) || _.last(this.contexts)
paths.some((key, i) => {
if (!_.isObject(scope)) {
return true
}
if (i === paths.length - 1) {
scope[key] = v
return true
}
if (undefined === scope[key]) {
scope[key] = {}
}
scope = scope[key]
})
},
unshift: function (ctx) {
return this.contexts.unshift(ctx)
},
push: function (ctx) {
return this.contexts.push(ctx)
},
pop: function (ctx) {
if (!arguments.length) {
return this.contexts.pop()
}
const i = this.contexts.findIndex(scope => scope === ctx)
if (i === -1) {
throw new TypeError('scope not found, cannot pop')
}
return this.contexts.splice(i, 1)[0]
},
findContextFor: function (key, filter) {
filter = filter || (() => true)
for (let i = this.contexts.length - 1; i >= 0; i--) {
const candidate = this.contexts[i]
if (!filter(candidate)) continue
if (key in candidate) {
return candidate
}
}
return null
},
readProperty: function (obj, key) {
let val
if (_.isNil(obj)) {
val = undefined
} else {
obj = toLiquid(obj)
val = key === 'size' ? readSize(obj) : obj[key]
if (_.isFunction(obj.liquid_method_missing)) {
val = obj.liquid_method_missing(key)
}
}
if (_.isNil(val) && this.opts.strict_variables) {
throw new TypeError(`undefined variable: ${key}`)
}
return val
},
/*
* Parse property access sequence from access string
* @example
* accessSeq("foo.bar") // ['foo', 'bar']
* accessSeq("foo['bar']") // ['foo', 'bar']
* accessSeq("foo['b]r']") // ['foo', 'b]r']
* accessSeq("foo[bar.coo]") // ['foo', 'bar'], for bar.coo == 'bar'
*/
propertyAccessSeq: function (str) {
str = String(str)
const seq = []
let name = ''
let j
let i = 0
while (i < str.length) {
switch (str[i]) {
case '[':
push()
const delemiter = str[i + 1]
if (/['"]/.test(delemiter)) { // foo["bar"]
j = str.indexOf(delemiter, i + 2)
assert(j !== -1, `unbalanced ${delemiter}: ${str}`)
name = str.slice(i + 2, j)
push()
i = j + 2
} else { // foo[bar.coo]
j = matchRightBracket(str, i + 1)
assert(j !== -1, `unbalanced []: ${str}`)
name = str.slice(i + 1, j)
if (!lexical.isInteger(name)) { // foo[bar] vs. foo[1]
name = String(this.get(name))
}
push()
i = j + 1
}
break
case '.':// foo.bar, foo[0].bar
push()
i++
break
default:// foo.bar
name += str[i]
i++
}
}
push()
if (!seq.length) {
throw new TypeError(`invalid path:"${str}"`)
}
return seq
function push () {
if (name.length) seq.push(name)
name = ''
}
}
}
function toLiquid (obj) {
if (_.isFunction(obj.to_liquid)) {
return obj.to_liquid()
}
if (_.isFunction(obj.toLiquid)) {
return obj.toLiquid()
}
return obj
}
function readSize (obj) {
if (!_.isNil(obj.size)) return obj.size
if (_.isArray(obj) || _.isString(obj)) return obj.length
return obj.size
}
function matchRightBracket (str, begin) {
let stack = 1 // count of '[' - count of ']'
for (let i = begin; i < str.length; i++) {
if (str[i] === '[') {
stack++
}
if (str[i] === ']') {
stack--
if (stack === 0) {
return i
}
}
}
return -1
}
export function factory (ctx, opts) {
const defaultOptions = {
dynamicPartials: true,
strict_variables: false,
strict_filters: false,
blocks: {},
root: []
}
const scope = _.create(Scope)
scope.opts = _.assign(defaultOptions, opts)
scope.contexts = [ctx || {}]
return scope
}

54
node_modules/liquidjs/src/syntax.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
import Operators from './operators.js'
import * as lexical from './lexical.js'
import assert from './util/assert.js'
const operators = Operators(isTruthy)
export function evalExp (exp, scope) {
assert(scope, 'unable to evalExp: scope undefined')
const operatorREs = lexical.operators
let match
for (let i = 0; i < operatorREs.length; i++) {
const operatorRE = operatorREs[i]
const expRE = new RegExp(`^(${lexical.quoteBalanced.source})(${operatorRE.source})(${lexical.quoteBalanced.source})$`)
if ((match = exp.match(expRE))) {
const l = evalExp(match[1], scope)
const op = operators[match[2].trim()]
const r = evalExp(match[3], scope)
return op(l, r)
}
}
if ((match = exp.match(lexical.rangeLine))) {
const low = evalValue(match[1], scope)
const high = evalValue(match[2], scope)
const range = []
for (let j = low; j <= high; j++) {
range.push(j)
}
return range
}
return evalValue(exp, scope)
}
export function evalValue (str, scope) {
str = str && str.trim()
if (!str) return undefined
if (lexical.isLiteral(str)) {
return lexical.parseLiteral(str)
}
if (lexical.isVariable(str)) {
return scope.get(str)
}
throw new TypeError(`cannot eval '${str}' as value`)
}
export function isTruthy (val) {
return !isFalsy(val)
}
export function isFalsy (val) {
return val === false || undefined === val || val === null
}

63
node_modules/liquidjs/src/tag.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
import { hashCapture } from './lexical.js'
import { create } from './util/underscore.js'
import { evalValue } from './syntax.js'
import assert from './util/assert.js'
function hash (markup, scope) {
const obj = {}
let match
hashCapture.lastIndex = 0
while ((match = hashCapture.exec(markup))) {
const k = match[1]
const v = match[2]
obj[k] = evalValue(v, scope)
}
return obj
}
export default function () {
let tagImpls = {}
const _tagInstance = {
render: async function (scope) {
const obj = hash(this.token.args, scope)
const impl = this.tagImpl
if (typeof impl.render !== 'function') {
return ''
}
return impl.render(scope, obj)
},
parse: function (token, tokens) {
this.type = 'tag'
this.token = token
this.name = token.name
const tagImpl = tagImpls[this.name]
assert(tagImpl, `tag ${this.name} not found`)
this.tagImpl = create(tagImpl)
if (this.tagImpl.parse) {
this.tagImpl.parse(token, tokens)
}
}
}
function register (name, tag) {
tagImpls[name] = tag
}
function construct (token, tokens) {
const instance = create(_tagInstance)
instance.parse(token, tokens)
return instance
}
function clear () {
tagImpls = {}
}
return {
construct,
register,
clear
}
}

23
node_modules/liquidjs/src/tags/assign.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import assert from '../util/assert.js'
import { identifier } from '../lexical.js'
import { create } from '../util/underscore.js'
export default function (liquid, Liquid) {
const re = new RegExp(`(${identifier.source})\\s*=([^]*)`)
const { AssignScope } = Liquid.Types
liquid.registerTag('assign', {
parse: function (token) {
const match = token.args.match(re)
assert(match, `illegal token ${token.raw}`)
this.key = match[1]
this.value = match[2]
},
render: function (scope) {
const ctx = create(AssignScope)
ctx[this.key] = liquid.evalValue(this.value, scope)
scope.push(ctx)
return Promise.resolve('')
}
})
}

32
node_modules/liquidjs/src/tags/capture.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
import assert from '../util/assert.js'
import { create } from '../util/underscore.js'
import { identifier } from '../lexical.js'
export default function (liquid, Liquid) {
const re = new RegExp(`(${identifier.source})`)
const { CaptureScope } = Liquid.Types
liquid.registerTag('capture', {
parse: function (tagToken, remainTokens) {
const match = tagToken.args.match(re)
assert(match, `${tagToken.args} not valid identifier`)
this.variable = match[1]
this.templates = []
const stream = liquid.parser.parseStream(remainTokens)
stream.on('tag:endcapture', token => stream.stop())
.on('template', tpl => this.templates.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: async function (scope, hash) {
const html = await liquid.renderer.renderTemplates(this.templates, scope)
const ctx = create(CaptureScope)
ctx[this.variable] = html
scope.push(ctx)
}
})
}

39
node_modules/liquidjs/src/tags/case.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
export default function (liquid, Liquid) {
liquid.registerTag('case', {
parse: function (tagToken, remainTokens) {
this.cond = tagToken.args
this.cases = []
this.elseTemplates = []
let p = []
const stream = liquid.parser.parseStream(remainTokens)
.on('tag:when', token => {
this.cases.push({
val: token.args,
templates: p = []
})
})
.on('tag:else', () => (p = this.elseTemplates))
.on('tag:endcase', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: function (scope, hash) {
for (let i = 0; i < this.cases.length; i++) {
const branch = this.cases[i]
const val = Liquid.evalExp(branch.val, scope)
const cond = Liquid.evalExp(this.cond, scope)
if (val === cond) {
return liquid.renderer.renderTemplates(branch.templates, scope)
}
}
return liquid.renderer.renderTemplates(this.elseTemplates, scope)
}
})
}

15
node_modules/liquidjs/src/tags/comment.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
export default function (liquid) {
liquid.registerTag('comment', {
parse: function (tagToken, remainTokens) {
const stream = liquid.parser.parseStream(remainTokens)
stream
.on('token', token => {
if (token.name === 'endcomment') stream.stop()
})
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
}
})
}

43
node_modules/liquidjs/src/tags/cycle.js generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import assert from '../util/assert.js'
import { value as rValue } from '../lexical.js'
export default function (liquid, Liquid) {
const groupRE = new RegExp(`^(?:(${rValue.source})\\s*:\\s*)?(.*)$`)
const candidatesRE = new RegExp(rValue.source, 'g')
liquid.registerTag('cycle', {
parse: function (tagToken, remainTokens) {
let match = groupRE.exec(tagToken.args)
assert(match, `illegal tag: ${tagToken.raw}`)
this.group = match[1] || ''
const candidates = match[2]
this.candidates = []
while ((match = candidatesRE.exec(candidates))) {
this.candidates.push(match[0])
}
assert(this.candidates.length, `empty candidates: ${tagToken.raw}`)
},
render: function (scope, hash) {
const group = Liquid.evalValue(this.group, scope)
const fingerprint = `cycle:${group}:` + this.candidates.join(',')
const groups = scope.opts.groups = scope.opts.groups || {}
let idx = groups[fingerprint]
if (idx === undefined) {
idx = groups[fingerprint] = 0
}
const candidate = this.candidates[idx]
idx = (idx + 1) % this.candidates.length
groups[fingerprint] = idx
return Liquid.evalValue(candidate, scope)
}
})
}

32
node_modules/liquidjs/src/tags/decrement.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
import { create } from '../util/underscore.js'
import assert from '../util/assert.js'
import { identifier } from '../lexical.js'
export default function (liquid, Liquid) {
const { CaptureScope, AssignScope, DecrementScope } = Liquid.Types
liquid.registerTag('decrement', {
parse: function (token) {
const match = token.args.match(identifier)
assert(match, `illegal identifier ${token.args}`)
this.variable = match[0]
},
render: function (scope, hash) {
let context = scope.findContextFor(
this.variable,
ctx => {
const proto = Object.getPrototypeOf(ctx)
return proto !== CaptureScope && proto !== AssignScope
}
)
if (!context) {
context = create(DecrementScope)
scope.unshift(context)
}
if (typeof context[this.variable] !== 'number') {
context[this.variable] = 0
}
return --context[this.variable]
}
})
}

93
node_modules/liquidjs/src/tags/for.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
import { mapSeries } from '../util/promise.js'
import { isString, isObject, isArray } from '../util/underscore.js'
import assert from '../util/assert.js'
import { identifier, value, hash } from '../lexical.js'
export default function (liquid, Liquid) {
const RenderBreakError = Liquid.Types.RenderBreakError
const re = new RegExp(`^(${identifier.source})\\s+in\\s+` +
`(${value.source})` +
`(?:\\s+${hash.source})*` +
`(?:\\s+(reversed))?` +
`(?:\\s+${hash.source})*$`)
liquid.registerTag('for', { parse, render })
function parse (tagToken, remainTokens) {
const match = re.exec(tagToken.args)
assert(match, `illegal tag: ${tagToken.raw}`)
this.variable = match[1]
this.collection = match[2]
this.reversed = !!match[3]
this.templates = []
this.elseTemplates = []
let p
const stream = liquid.parser.parseStream(remainTokens)
.on('start', () => (p = this.templates))
.on('tag:else', () => (p = this.elseTemplates))
.on('tag:endfor', () => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', () => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
}
async function render (scope, hash) {
let collection = Liquid.evalExp(this.collection, scope)
if (!isArray(collection)) {
if (isString(collection) && collection.length > 0) {
collection = [collection]
} else if (isObject(collection)) {
collection = Object.keys(collection).map((key) => [key, collection[key]])
}
}
if (!isArray(collection) || !collection.length) {
return liquid.renderer.renderTemplates(this.elseTemplates, scope)
}
const offset = hash.offset || 0
const limit = (hash.limit === undefined) ? collection.length : hash.limit
collection = collection.slice(offset, offset + limit)
if (this.reversed) collection.reverse()
const contexts = collection.map((item, i) => {
const ctx = {}
ctx[this.variable] = item
ctx.forloop = {
first: i === 0,
index: i + 1,
index0: i,
last: i === collection.length - 1,
length: collection.length,
rindex: collection.length - i,
rindex0: collection.length - i - 1
}
return ctx
})
let html = ''
let finished = false
await mapSeries(contexts, async context => {
if (finished) return
scope.push(context)
try {
html += await liquid.renderer.renderTemplates(this.templates, scope)
} catch (e) {
if (e instanceof RenderBreakError) {
html += e.resolvedHTML
if (e.message === 'break') {
finished = true
}
} else throw e
}
scope.pop(context)
})
return html
}
}

40
node_modules/liquidjs/src/tags/if.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
export default function (liquid, Liquid) {
liquid.registerTag('if', {
parse: function (tagToken, remainTokens) {
this.branches = []
this.elseTemplates = []
let p
const stream = liquid.parser.parseStream(remainTokens)
.on('start', () => this.branches.push({
cond: tagToken.args,
templates: (p = [])
}))
.on('tag:elsif', token => {
this.branches.push({
cond: token.args,
templates: p = []
})
})
.on('tag:else', () => (p = this.elseTemplates))
.on('tag:endif', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: function (scope, hash) {
for (const branch of this.branches) {
const cond = Liquid.evalExp(branch.cond, scope)
if (Liquid.isTruthy(cond)) {
return liquid.renderer.renderTemplates(branch.templates, scope)
}
}
return liquid.renderer.renderTemplates(this.elseTemplates, scope)
}
})
}

57
node_modules/liquidjs/src/tags/include.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
import assert from '../util/assert.js'
import { value, quotedLine } from '../lexical.js'
const staticFileRE = /[^\s,]+/
export default function (liquid, Liquid) {
const withRE = new RegExp(`with\\s+(${value.source})`)
liquid.registerTag('include', {
parse: function (token) {
let match = staticFileRE.exec(token.args)
if (match) {
this.staticValue = match[0]
}
match = value.exec(token.args)
if (match) {
this.value = match[0]
}
match = withRE.exec(token.args)
if (match) {
this.with = match[1]
}
},
render: async function (scope, hash) {
let filepath
if (scope.opts.dynamicPartials) {
if (quotedLine.exec(this.value)) {
const template = this.value.slice(1, -1)
filepath = await liquid.parseAndRender(template, scope.getAll(), scope.opts)
} else {
filepath = Liquid.evalValue(this.value, scope)
}
} else {
filepath = this.staticValue
}
assert(filepath, `cannot include with empty filename`)
const originBlocks = scope.opts.blocks
const originBlockMode = scope.opts.blockMode
scope.opts.blocks = {}
scope.opts.blockMode = 'output'
if (this.with) {
hash[filepath] = Liquid.evalValue(this.with, scope)
}
const templates = await liquid.getTemplate(filepath, scope.opts.root)
scope.push(hash)
const html = await liquid.renderer.renderTemplates(templates, scope)
scope.pop(hash)
scope.opts.blocks = originBlocks
scope.opts.blockMode = originBlockMode
return html
}
})
}

34
node_modules/liquidjs/src/tags/increment.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
import assert from '../util/assert.js'
import { create } from '../util/underscore.js'
import { identifier } from '../lexical.js'
export default function (liquid, Liquid) {
const { CaptureScope, AssignScope, IncrementScope } = Liquid.Types
liquid.registerTag('increment', {
parse: function (token) {
const match = token.args.match(identifier)
assert(match, `illegal identifier ${token.args}`)
this.variable = match[0]
},
render: function (scope, hash) {
let context = scope.findContextFor(
this.variable,
ctx => {
const proto = Object.getPrototypeOf(ctx)
return proto !== CaptureScope && proto !== AssignScope
}
)
if (!context) {
context = create(IncrementScope)
scope.unshift(context)
}
if (typeof context[this.variable] !== 'number') {
context[this.variable] = 0
}
const val = context[this.variable]
context[this.variable]++
return val
}
})
}

31
node_modules/liquidjs/src/tags/index.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import For from './for.js'
import Assign from './assign.js'
import Capture from './capture.js'
import Case from './case.js'
import Comment from './comment.js'
import Include from './include.js'
import Decrement from './decrement.js'
import Cycle from './cycle.js'
import If from './if.js'
import Increment from './increment.js'
import Layout from './layout.js'
import Raw from './raw.js'
import Tablerow from './tablerow.js'
import Unless from './unless.js'
export default function (engine, Liquid) {
Assign(engine, Liquid)
Capture(engine, Liquid)
Case(engine, Liquid)
Comment(engine, Liquid)
Cycle(engine, Liquid)
Decrement(engine, Liquid)
For(engine, Liquid)
If(engine, Liquid)
Include(engine, Liquid)
Increment(engine, Liquid)
Layout(engine, Liquid)
Raw(engine, Liquid)
Tablerow(engine, Liquid)
Unless(engine, Liquid)
}

75
node_modules/liquidjs/src/tags/layout.js generated vendored Normal file
View File

@@ -0,0 +1,75 @@
import assert from '../util/assert.js'
import { value as rValue } from '../lexical.js'
/*
* blockMode:
* * "store": store rendered html into blocks
* * "output": output rendered html
*/
export default function (liquid, Liquid) {
const staticFileRE = /\S+/
liquid.registerTag('layout', {
parse: function (token, remainTokens) {
let match = staticFileRE.exec(token.args)
if (match) {
this.staticLayout = match[0]
}
match = rValue.exec(token.args)
if (match) {
this.layout = match[0]
}
this.tpls = liquid.parser.parse(remainTokens)
},
render: async function (scope, hash) {
const layout = scope.opts.dynamicPartials
? Liquid.evalValue(this.layout, scope)
: this.staticLayout
assert(layout, `cannot apply layout with empty filename`)
// render the remaining tokens immediately
scope.opts.blockMode = 'store'
const html = await liquid.renderer.renderTemplates(this.tpls, scope)
if (scope.opts.blocks[''] === undefined) {
scope.opts.blocks[''] = html
}
const templates = await liquid.getTemplate(layout, scope.opts.root)
scope.push(hash)
scope.opts.blockMode = 'output'
const partial = await liquid.renderer.renderTemplates(templates, scope)
scope.pop(hash)
return partial
}
})
liquid.registerTag('block', {
parse: function (token, remainTokens) {
const match = /\w+/.exec(token.args)
this.block = match ? match[0] : ''
this.tpls = []
const stream = liquid.parser.parseStream(remainTokens)
.on('tag:endblock', () => stream.stop())
.on('template', tpl => this.tpls.push(tpl))
.on('end', () => {
throw new Error(`tag ${token.raw} not closed`)
})
stream.start()
},
render: async function (scope) {
const childDefined = scope.opts.blocks[this.block]
const html = childDefined !== undefined
? childDefined
: await liquid.renderer.renderTemplates(this.tpls, scope)
if (scope.opts.blockMode === 'store') {
scope.opts.blocks[this.block] = html
return ''
}
return html
}
})
}

21
node_modules/liquidjs/src/tags/raw.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
export default function (liquid) {
liquid.registerTag('raw', {
parse: function (tagToken, remainTokens) {
this.tokens = []
const stream = liquid.parser.parseStream(remainTokens)
stream
.on('token', token => {
if (token.name === 'endraw') stream.stop()
else this.tokens.push(token)
})
.on('end', () => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: function (scope, hash) {
return this.tokens.map(token => token.raw).join('')
}
})
}

70
node_modules/liquidjs/src/tags/tablerow.js generated vendored Normal file
View File

@@ -0,0 +1,70 @@
import { mapSeries } from '../util/promise.js'
import assert from '../util/assert.js'
import { identifier, value, hash } from '../lexical.js'
export default function (liquid, Liquid) {
const re = new RegExp(`^(${identifier.source})\\s+in\\s+` +
`(${value.source})` +
`(?:\\s+${hash.source})*$`)
liquid.registerTag('tablerow', {
parse: function (tagToken, remainTokens) {
const match = re.exec(tagToken.args)
assert(match, `illegal tag: ${tagToken.raw}`)
this.variable = match[1]
this.collection = match[2]
this.templates = []
let p
const stream = liquid.parser.parseStream(remainTokens)
.on('start', () => (p = this.templates))
.on('tag:endtablerow', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', () => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: async function (scope, hash) {
let collection = Liquid.evalExp(this.collection, scope) || []
const offset = hash.offset || 0
const limit = (hash.limit === undefined) ? collection.length : hash.limit
collection = collection.slice(offset, offset + limit)
const cols = hash.cols || collection.length
const contexts = collection.map((item, i) => {
const ctx = {}
ctx[this.variable] = item
return ctx
})
let row
let html = ''
await mapSeries(contexts, async (context, idx) => {
row = Math.floor(idx / cols) + 1
const col = (idx % cols) + 1
if (col === 1) {
if (row !== 1) {
html += '</tr>'
}
html += `<tr class="row${row}">`
}
html += `<td class="col${col}">`
scope.push(context)
html += await liquid.renderer.renderTemplates(this.templates, scope)
html += '</td>'
scope.pop(context)
return html
})
if (row > 0) {
html += '</tr>'
}
return html
}
})
}

29
node_modules/liquidjs/src/tags/unless.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
export default function (liquid, Liquid) {
liquid.registerTag('unless', {
parse: function (tagToken, remainTokens) {
this.templates = []
this.elseTemplates = []
let p
const stream = liquid.parser.parseStream(remainTokens)
.on('start', x => {
p = this.templates
this.cond = tagToken.args
})
.on('tag:else', () => (p = this.elseTemplates))
.on('tag:endunless', token => stream.stop())
.on('template', tpl => p.push(tpl))
.on('end', x => {
throw new Error(`tag ${tagToken.raw} not closed`)
})
stream.start()
},
render: function (scope, hash) {
const cond = Liquid.evalExp(this.cond, scope)
return Liquid.isFalsy(cond)
? liquid.renderer.renderTemplates(this.templates, scope)
: liquid.renderer.renderTemplates(this.elseTemplates, scope)
}
})
}

52
node_modules/liquidjs/src/template-browser.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import { last, isArray } from './util/underscore'
function domResolve (root, path) {
const base = document.createElement('base')
base.href = root
const head = document.getElementsByTagName('head')[0]
head.insertBefore(base, head.firstChild)
const a = document.createElement('a')
a.href = path
const resolved = a.href
head.removeChild(base)
return resolved
}
export function resolve (filepath, root, options) {
root = root || options.root
if (isArray(root)) {
root = root[0]
}
if (root.length && last(root) !== '/') {
root += '/'
}
const url = domResolve(root, filepath)
return url.replace(/^(\w+:\/\/[^/]+)(\/[^?]+)/, (str, origin, path) => {
const last = path.split('/').pop()
if (/\.\w+$/.test(last)) {
return str
}
return origin + path + options.extname
})
}
export async function read (url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.responseText)
} else {
reject(new Error(xhr.statusText))
}
}
xhr.onerror = () => {
reject(new Error('An error occurred whilst receiving the response.'))
}
xhr.open('GET', url)
xhr.send()
})
}

29
node_modules/liquidjs/src/template.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import * as _ from './util/underscore.js'
import path from 'path'
import { anySeries } from './util/promise.js'
import fs from 'fs'
const statFileAsync = _.promisify(fs.stat)
const readFileAsync = _.promisify(fs.readFile)
export async function resolve (filepath, root, options) {
if (!path.extname(filepath)) {
filepath += options.extname
}
root = options.root.concat(root || [])
root = _.uniq(root)
const paths = root.map(root => path.resolve(root, filepath))
return anySeries(paths, async path => {
try {
await statFileAsync(path)
return path
} catch (e) {
e.message = `${e.code}: Failed to lookup ${filepath} in: ${root}`
throw e
}
})
}
export async function read (filepath) {
return readFileAsync(filepath, 'utf8')
}

90
node_modules/liquidjs/src/tokenizer.js generated vendored Normal file
View File

@@ -0,0 +1,90 @@
import * as lexical from './lexical.js'
import { TokenizationError } from './util/error.js'
import * as _ from './util/underscore.js'
import assert from './util/assert.js'
import whiteSpaceCtrl from './whitespace-ctrl.js'
export { default as whiteSpaceCtrl } from './whitespace-ctrl.js'
export function parse (input, file, options) {
assert(_.isString(input), 'illegal input')
const rLiquid = /({%-?([\s\S]*?)-?%})|({{-?([\s\S]*?)-?}})/g
let currIndent = 0
const lineNumber = LineNumber(input)
let lastMatchEnd = 0
const tokens = []
for (let match; (match = rLiquid.exec(input)); lastMatchEnd = rLiquid.lastIndex) {
if (match.index > lastMatchEnd) {
tokens.push(parseHTMLToken(lastMatchEnd, match.index))
}
tokens.push(match[1]
? parseTagToken(match[1], match[2].trim(), match.index)
: parseValueToken(match[3], match[4].trim(), match.index))
}
if (input.length > lastMatchEnd) {
tokens.push(parseHTMLToken(lastMatchEnd, input.length))
}
whiteSpaceCtrl(tokens, options)
return tokens
function parseTagToken (raw, value, pos) {
const match = value.match(lexical.tagLine)
const token = {
type: 'tag',
indent: currIndent,
line: lineNumber.get(pos),
trim_left: raw.slice(0, 3) === '{%-',
trim_right: raw.slice(-3) === '-%}',
raw,
value,
input,
file
}
if (!match) {
throw new TokenizationError(`illegal tag syntax`, token)
}
token.name = match[1]
token.args = match[2]
return token
}
function parseValueToken (raw, value, pos) {
return {
type: 'value',
line: lineNumber.get(pos),
trim_left: raw.slice(0, 3) === '{{-',
trim_right: raw.slice(-3) === '-}}',
raw,
value,
input,
file
}
}
function parseHTMLToken (begin, end) {
const htmlFragment = input.slice(begin, end)
currIndent = _.last((htmlFragment).split('\n')).length
return {
type: 'html',
raw: htmlFragment,
value: htmlFragment
}
}
}
function LineNumber (html) {
let parsedLinesCount = 0
let lastMatchBegin = -1
return {
get: function (pos) {
const lines = html.slice(lastMatchBegin + 1, pos).split('\n')
parsedLinesCount += lines.length - 1
lastMatchBegin = pos
return parsedLinesCount + 1
}
}
}

8
node_modules/liquidjs/src/util/assert.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import { AssertionError } from './error.js'
export default function (predicate, message) {
if (!predicate) {
message = message || `expect ${predicate} to be true`
throw new AssertionError(message)
}
}

100
node_modules/liquidjs/src/util/error.js generated vendored Normal file
View File

@@ -0,0 +1,100 @@
import * as _ from './underscore.js'
function initError () {
this.name = this.constructor.name
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor)
}
}
function initLiquidError (err, token) {
initError.call(this)
this.input = token.input
this.line = token.line
this.file = token.file
const context = mkContext(token.input, token.line)
this.message = mkMessage(err.message, token)
this.stack = context +
'\n' + (this.stack || this.message) +
(err.stack ? '\nFrom ' + err.stack : '')
}
export function TokenizationError (message, token) {
initLiquidError.call(this, { message: message }, token)
}
TokenizationError.prototype = _.create(Error.prototype)
TokenizationError.prototype.constructor = TokenizationError
export function ParseError (e, token) {
_.assign(this, e)
this.originalError = e
initLiquidError.call(this, e, token)
}
ParseError.prototype = _.create(Error.prototype)
ParseError.prototype.constructor = ParseError
export function RenderError (e, tpl) {
// return the original render error
if (e instanceof RenderError) {
return e
}
_.assign(this, e)
this.originalError = e
initLiquidError.call(this, e, tpl.token)
}
RenderError.prototype = _.create(Error.prototype)
RenderError.prototype.constructor = RenderError
export function RenderBreakError (message) {
initError.call(this)
this.message = message + ''
}
RenderBreakError.prototype = _.create(Error.prototype)
RenderBreakError.prototype.constructor = RenderBreakError
export function AssertionError (message) {
initError.call(this)
this.message = message + ''
}
AssertionError.prototype = _.create(Error.prototype)
AssertionError.prototype.constructor = AssertionError
function mkContext (input, line) {
const lines = input.split('\n')
const begin = Math.max(line - 2, 1)
const end = Math.min(line + 3, lines.length)
const context = _
.range(begin, end + 1)
.map(l => [
(l === line) ? '>> ' : ' ',
align(l, end),
'| ',
lines[l - 1]
].join(''))
.join('\n')
return context
}
function align (n, max) {
const length = (max + '').length
const str = n + ''
const blank = Array(length - str.length).join(' ')
return blank + str
}
function mkMessage (msg, token) {
msg = msg || ''
if (token.file) {
msg += ', file:' + token.file
}
if (token.line) {
msg += ', line:' + token.line
}
return msg
}

30
node_modules/liquidjs/src/util/promise.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
/*
* Call functions in serial until someone resolved.
* @param {Array} iterable the array to iterate with.
* @param {Array} iteratee returns a new promise.
* The iteratee is invoked with three arguments: (value, index, iterable).
*/
export function anySeries (iterable, iteratee) {
let ret = Promise.reject(new Error('init'))
iterable.forEach(function (item, idx) {
ret = ret.catch(e => iteratee(item, idx, iterable))
})
return ret
}
/*
* Call functions in serial until someone rejected.
* @param {Array} iterable the array to iterate with.
* @param {Array} iteratee returns a new promise.
* The iteratee is invoked with three arguments: (value, index, iterable).
*/
export function mapSeries (iterable, iteratee) {
let ret = Promise.resolve('init')
const result = []
iterable.forEach(function (item, idx) {
ret = ret
.then(() => iteratee(item, idx, iterable))
.then(x => result.push(x))
})
return ret.then(() => result)
}

198
node_modules/liquidjs/src/util/strftime.js generated vendored Normal file
View File

@@ -0,0 +1,198 @@
const monthNames = [
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'
]
const dayNames = [
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
]
const monthNamesShort = monthNames.map(abbr)
const dayNamesShort = dayNames.map(abbr)
const suffixes = {
1: 'st',
2: 'nd',
3: 'rd',
'default': 'th'
}
function abbr (str) {
return str.slice(0, 3)
}
// prototype extensions
const _date = {
daysInMonth: function (d) {
const feb = _date.isLeapYear(d) ? 29 : 28
return [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
},
getDayOfYear: function (d) {
let num = 0
for (let i = 0; i < d.getMonth(); ++i) {
num += _date.daysInMonth(d)[i]
}
return num + d.getDate()
},
// Startday is an integer of which day to start the week measuring from
// TODO: that comment was retarted. fix it.
getWeekOfYear: function (d, startDay) {
// Skip to startDay of this week
const now = this.getDayOfYear(d) + (startDay - d.getDay())
// Find the first startDay of the year
const jan1 = new Date(d.getFullYear(), 0, 1)
const then = (7 - jan1.getDay() + startDay)
return _number.pad(Math.floor((now - then) / 7) + 1, 2)
},
isLeapYear: function (d) {
const year = d.getFullYear()
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
},
getSuffix: function (d) {
const str = d.getDate().toString()
const index = parseInt(str.slice(-1))
return suffixes[index] || suffixes['default']
},
century: function (d) {
return parseInt(d.getFullYear().toString().substring(0, 2), 10)
}
}
const _number = {
pad: function (value, size, ch) {
if (!ch) ch = '0'
let result = value.toString()
let pad = size - result.length
while (pad-- > 0) {
result = ch + result
}
return result
}
}
const formatCodes = {
a: function (d) {
return dayNamesShort[d.getDay()]
},
A: function (d) {
return dayNames[d.getDay()]
},
b: function (d) {
return monthNamesShort[d.getMonth()]
},
B: function (d) {
return monthNames[d.getMonth()]
},
c: function (d) {
return d.toLocaleString()
},
C: function (d) {
return _date.century(d)
},
d: function (d) {
return _number.pad(d.getDate(), 2)
},
e: function (d) {
return _number.pad(d.getDate(), 2, ' ')
},
H: function (d) {
return _number.pad(d.getHours(), 2)
},
I: function (d) {
return _number.pad(d.getHours() % 12 || 12, 2)
},
j: function (d) {
return _number.pad(_date.getDayOfYear(d), 3)
},
k: function (d) {
return _number.pad(d.getHours(), 2, ' ')
},
l: function (d) {
return _number.pad(d.getHours() % 12 || 12, 2, ' ')
},
L: function (d) {
return _number.pad(d.getMilliseconds(), 3)
},
m: function (d) {
return _number.pad(d.getMonth() + 1, 2)
},
M: function (d) {
return _number.pad(d.getMinutes(), 2)
},
p: function (d) {
return (d.getHours() < 12 ? 'AM' : 'PM')
},
P: function (d) {
return (d.getHours() < 12 ? 'am' : 'pm')
},
q: function (d) {
return _date.getSuffix(d)
},
s: function (d) {
return Math.round(d.valueOf() / 1000)
},
S: function (d) {
return _number.pad(d.getSeconds(), 2)
},
u: function (d) {
return d.getDay() || 7
},
U: function (d) {
return _date.getWeekOfYear(d, 0)
},
w: function (d) {
return d.getDay()
},
W: function (d) {
return _date.getWeekOfYear(d, 1)
},
x: function (d) {
return d.toLocaleDateString()
},
X: function (d) {
return d.toLocaleTimeString()
},
y: function (d) {
return d.getFullYear().toString().substring(2, 4)
},
Y: function (d) {
return d.getFullYear()
},
z: function (d) {
const tz = d.getTimezoneOffset() / 60 * 100
return (tz > 0 ? '-' : '+') + _number.pad(Math.abs(tz), 4)
},
'%': function () {
return '%'
}
}
formatCodes.h = formatCodes.b
formatCodes.N = formatCodes.L
export default function (d, format) {
let output = ''
let remaining = format
while (true) {
const r = /%./g
const results = r.exec(remaining)
// No more format codes. Add the remaining text and return
if (!results) {
return output + remaining
}
// Add the preceding text
output += remaining.slice(0, r.lastIndex - 2)
remaining = remaining.slice(r.lastIndex)
// Add the format code
const ch = results[0].charAt(1)
const func = formatCodes[ch]
output += func ? func.call(this, d) : '%' + ch
}
}

154
node_modules/liquidjs/src/util/underscore.js generated vendored Normal file
View File

@@ -0,0 +1,154 @@
const toStr = Object.prototype.toString
const arrToStr = Array.prototype.toString
/*
* Checks if value is classified as a String primitive or object.
* @param {any} value The value to check.
* @return {Boolean} Returns true if value is a string, else false.
*/
export function isString (value) {
return toStr.call(value) === '[object String]'
}
export function isFunction (value) {
return typeof value === 'function'
}
export function promisify (fn) {
return function () {
return new Promise((resolve, reject) => {
fn(...arguments, (err, result) => {
err ? reject(err) : resolve(result)
})
})
}
}
export function stringify (value) {
if (isNil(value)) return String(value)
if (isFunction(value.to_liquid)) return stringify(value.to_liquid())
if (isFunction(value.toLiquid)) return stringify(value.toLiquid())
if (isFunction(value.to_s)) return value.to_s()
if ([toStr, arrToStr].indexOf(value.toString) > -1) return defaultToString(value)
if (isFunction(value.toString)) return value.toString()
return toStr.call(value)
}
function defaultToString (value) {
const cache = []
return JSON.stringify(value, (key, value) => {
if (isObject(value)) {
if (cache.indexOf(value) !== -1) {
return
}
cache.push(value)
}
return value
})
}
export function create (proto) {
return Object.create(proto)
}
export function isNil (value) {
return value === null || value === undefined
}
export function isArray (value) {
// be compatible with IE 8
return toStr.call(value) === '[object Array]'
}
export function isError (value) {
const signature = toStr.call(value)
// [object XXXError]
return signature.substr(-6, 5) === 'Error' ||
(typeof value.message === 'string' && typeof value.name === 'string')
}
/*
* Iterates over own enumerable string keyed properties of an object and invokes iteratee for each property.
* The iteratee is invoked with three arguments: (value, key, object).
* Iteratee functions may exit iteration early by explicitly returning false.
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @return {Object} Returns object.
*/
export function forOwn (object, iteratee) {
object = object || {}
for (const k in object) {
if (object.hasOwnProperty(k)) {
if (iteratee(object[k], k, object) === false) break
}
}
return object
}
/*
* Assigns own enumerable string keyed properties of source objects to the destination object.
* Source objects are applied from left to right.
* Subsequent sources overwrite property assignments of previous sources.
*
* Note: This method mutates object and is loosely based on Object.assign.
*
* @param {Object} object The destination object.
* @param {...Object} sources The source objects.
* @return {Object} Returns object.
*/
export function assign (object) {
object = isObject(object) ? object : {}
const srcs = Array.prototype.slice.call(arguments, 1)
srcs.forEach((src) => Object.assign(object, src))
return object
}
export function last (arr) {
return arr[arr.length - 1]
}
export function uniq (arr) {
const u = {}
const a = []
for (let i = 0, l = arr.length; i < l; ++i) {
if (u.hasOwnProperty(arr[i])) {
continue
}
a.push(arr[i])
u[arr[i]] = 1
}
return a
}
/*
* Checks if value is the language type of Object.
* (e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
* @param {any} value The value to check.
* @return {Boolean} Returns true if value is an object, else false.
*/
export function isObject (value) {
const type = typeof value
return value !== null && (type === 'object' || type === 'function')
}
/*
* A function to create flexibly-numbered lists of integers,
* handy for each and map loops. start, if omitted, defaults to 0; step defaults to 1.
* Returns a list of integers from start (inclusive) to stop (exclusive),
* incremented (or decremented) by step, exclusive.
* Note that ranges that stop before they start are considered to be zero-length instead of
* negative — if you'd like a negative range, use a negative step.
*/
export function range (start, stop, step) {
if (arguments.length === 1) {
stop = start
start = 0
}
step = step || 1
const arr = []
for (let i = start; i < stop; i += step) {
arr.push(i)
}
return arr
}

45
node_modules/liquidjs/src/whitespace-ctrl.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import { assign } from './util/underscore.js'
export default function whiteSpaceCtrl (tokens, options) {
options = assign({ greedy: true }, options)
let inRaw = false
tokens.forEach((token, i) => {
if (shouldTrimLeft(token, inRaw, options)) {
trimLeft(tokens[i - 1], options.greedy)
}
if (token.type === 'tag' && token.name === 'raw') inRaw = true
if (token.type === 'tag' && token.name === 'endraw') inRaw = false
if (shouldTrimRight(token, inRaw, options)) {
trimRight(tokens[i + 1], options.greedy)
}
})
}
function shouldTrimLeft (token, inRaw, options) {
if (inRaw) return false
if (token.type === 'tag') return token.trim_left || options.trim_tag_left
if (token.type === 'value') return token.trim_left || options.trim_value_left
}
function shouldTrimRight (token, inRaw, options) {
if (inRaw) return false
if (token.type === 'tag') return token.trim_right || options.trim_tag_right
if (token.type === 'value') return token.trim_right || options.trim_value_right
}
function trimLeft (token, greedy) {
if (!token || token.type !== 'html') return
const rLeft = greedy ? /\s+$/g : /[\t\r ]*$/g
token.value = token.value.replace(rLeft, '')
}
function trimRight (token, greedy) {
if (!token || token.type !== 'html') return
const rRight = greedy ? /^\s+/g : /^[\t\r ]*\n?/g
token.value = token.value.replace(rRight, '')
}