mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-13 19:30:39 -07:00
perf: add cross-engines benchmark
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
require: "ts-node/register/transpile-only",
|
||||
reporter: "spec"
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const Benchmark = require('benchmark')
|
||||
const data = require('./data/todolist.json')
|
||||
const path = require('path')
|
||||
|
||||
const engines = {
|
||||
liquid: require('./engines/liquid'),
|
||||
handlebars: require('./engines/handlebars'),
|
||||
react: require('./engines/react'),
|
||||
swig: require('./engines/swig')
|
||||
}
|
||||
|
||||
function crossEngines () {
|
||||
console.log(' cross engines')
|
||||
console.log('------------------------')
|
||||
return new Promise(resolve => {
|
||||
const suit = new Benchmark.Suite('cross engines')
|
||||
|
||||
for (const [name, { load, render }] of Object.entries(engines)) {
|
||||
const tpl = load(path.resolve(__dirname, `templates/todolist`))
|
||||
suit.add(name, () => render(tpl, data))
|
||||
}
|
||||
|
||||
suit.on('cycle', event => console.log(String(event.target)))
|
||||
suit.on('complete', resolve)
|
||||
suit.run({ async: true })
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { crossEngines }
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
{
|
||||
"categories": [{
|
||||
"color": "red",
|
||||
"id": "CAT1",
|
||||
"title": "work"
|
||||
}, {
|
||||
"color": "red",
|
||||
"id": "CAT2",
|
||||
"title": "emergency"
|
||||
}, {
|
||||
"color": "green",
|
||||
"id": "CAT3",
|
||||
"title": "sport"
|
||||
}],
|
||||
"todos": [{
|
||||
"title": "fork and clone",
|
||||
"id": "TODO1",
|
||||
"category": "work"
|
||||
}, {
|
||||
"title": "make it better",
|
||||
"id": "TODO2",
|
||||
"category": "sport"
|
||||
}, {
|
||||
"title": "make a pull request",
|
||||
"id": "TODO3",
|
||||
"category": "work"
|
||||
}]
|
||||
}
|
||||
Regular → Executable
+6
-18
@@ -1,8 +1,10 @@
|
||||
const Benchmark = require('benchmark')
|
||||
const { Liquid } = require('..')
|
||||
const ctx = require('./data/todolist.json')
|
||||
const { resolve } = require('path')
|
||||
|
||||
const engine = new Liquid({
|
||||
root: __dirname,
|
||||
root: resolve(__dirname, 'templates'),
|
||||
extname: '.liquid'
|
||||
})
|
||||
|
||||
@@ -17,28 +19,14 @@ engine.registerTag('header', {
|
||||
}
|
||||
})
|
||||
|
||||
const ctx = {
|
||||
todos: ['fork and clone', 'make it better', 'make a pull request'],
|
||||
title: 'Welcome to liquidjs!'
|
||||
}
|
||||
|
||||
const template = `
|
||||
{%header content: "welcome to liquid" | capitalize%}
|
||||
|
||||
<ul>
|
||||
{% for todo in todos %}
|
||||
<li>{{forloop.index}} - {{todo}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
`
|
||||
|
||||
function demo () {
|
||||
console.log('--- demo ---')
|
||||
console.log(' demo')
|
||||
console.log('------------------------')
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite('demo')
|
||||
.add('demo', {
|
||||
defer: true,
|
||||
fn: d => engine.parseAndRender(template, ctx).then(x => d.resolve(x))
|
||||
fn: d => engine.renderFile('todolist', ctx).then(x => d.resolve(x))
|
||||
})
|
||||
.on('cycle', event => console.log(String(event.target)))
|
||||
.on('complete', resolve)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
const handlebars = require('handlebars')
|
||||
const { readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
|
||||
handlebars.registerPartial(
|
||||
'todo-icon',
|
||||
readFileSync(join(__dirname, '../templates/todo-icon.hbs'), 'utf8')
|
||||
)
|
||||
|
||||
handlebars.registerHelper('concat', function (...args) {
|
||||
return args.filter(x => typeof x === 'string').join('')
|
||||
})
|
||||
|
||||
handlebars.registerHelper('url', function (path) {
|
||||
return `http://example.com${path}`
|
||||
})
|
||||
|
||||
handlebars.registerHelper('inc', function (num) {
|
||||
return Number(num) + 1
|
||||
})
|
||||
|
||||
handlebars.registerHelper('capitalize', function (str) {
|
||||
return str[0].toUpperCase() + str.slice(1).toLowerCase()
|
||||
})
|
||||
|
||||
handlebars.registerHelper('upcase', function (str) {
|
||||
return str.toUpperCase()
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
load: path => handlebars.compile(readFileSync(path + '.hbs', 'utf8')),
|
||||
render: (tpl, data) => tpl(data)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const { Liquid } = require('../..')
|
||||
const { readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
|
||||
const liquid = new Liquid({
|
||||
root: join(__dirname, '../templates'),
|
||||
extname: '.liquid'
|
||||
})
|
||||
|
||||
liquid.registerFilter('url', path => `http://example.com${path}`)
|
||||
|
||||
module.exports = {
|
||||
load: path => liquid.parse(readFileSync(path + '.liquid', 'utf8')),
|
||||
render: (tpl, data) => liquid.renderSync(tpl, data)
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
const { readFileSync } = require('fs')
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const babel = require('@babel/core')
|
||||
const requireFromString = require('require-from-string')
|
||||
|
||||
const babelConfig = {
|
||||
presets: ['@babel/preset-react', '@babel/preset-env']
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
load: path => {
|
||||
const src = readFileSync(path + '.jsx', 'utf8')
|
||||
const transformed = babel.transform(src, babelConfig)
|
||||
return requireFromString(transformed.code)
|
||||
},
|
||||
render: (Component, data) => {
|
||||
return ReactDOMServer.renderToString(React.createElement(Component, data))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
const swig = require('swig')
|
||||
|
||||
swig.setFilter('url', function (path) {
|
||||
return `http://example.com${path}`
|
||||
})
|
||||
|
||||
swig.setFilter('prepend', function (input, arg) {
|
||||
return arg + input
|
||||
})
|
||||
|
||||
swig.setFilter('append', function (input, arg) {
|
||||
return input + arg
|
||||
})
|
||||
|
||||
swig.setFilter('inc', function (num) {
|
||||
return Number(num) + 1
|
||||
})
|
||||
|
||||
swig.setFilter('capitalize', function (str) {
|
||||
return str[0].toUpperCase() + str.slice(1).toLowerCase()
|
||||
})
|
||||
|
||||
swig.setFilter('upcase', function (str) {
|
||||
return str.toUpperCase()
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
load: path => swig.compileFile(path + '.swig'),
|
||||
render: (tpl, data) => tpl(data)
|
||||
}
|
||||
Regular → Executable
+2
@@ -3,6 +3,7 @@ const { tag } = require('./tag')
|
||||
const { demo } = require('./demo')
|
||||
const { layout } = require('./layout')
|
||||
const { memory } = require('./memory')
|
||||
const { crossEngines } = require('./cross-engines')
|
||||
|
||||
async function main () {
|
||||
await output()
|
||||
@@ -10,6 +11,7 @@ async function main () {
|
||||
await demo()
|
||||
await layout()
|
||||
await memory()
|
||||
await crossEngines()
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
Regular → Executable
+2
-1
@@ -18,7 +18,8 @@ const template = `
|
||||
`
|
||||
|
||||
function layout () {
|
||||
console.log('--- layout ---')
|
||||
console.log(' layout')
|
||||
console.log('------------------------')
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite('layout')
|
||||
.add('cache=false', {
|
||||
|
||||
Regular → Executable
+7
-6
@@ -13,7 +13,8 @@ const engine = new Liquid(engineOptions)
|
||||
const SAMPLE_COUNT = 1024
|
||||
|
||||
function memory () {
|
||||
console.log('--- memory ---')
|
||||
console.log(' memory')
|
||||
console.log('------------------------')
|
||||
html()
|
||||
todolist()
|
||||
}
|
||||
@@ -29,11 +30,11 @@ function html () {
|
||||
templates.push(engine.parse(str))
|
||||
}
|
||||
const diff1 = (getHeapStatistics().used_heap_size - base) / SAMPLE_COUNT
|
||||
console.log(`${h(str.length)} lorem-html before GC x ${h(diff1)}/tpl (${SAMPLE_COUNT} instances sampled)`)
|
||||
console.log(`[lorem-html ${h(str.length)}][before GC] ${h(diff1)}/tpl (${SAMPLE_COUNT} runs sampled)`)
|
||||
|
||||
global.gc()
|
||||
const diff2 = (getHeapStatistics().used_heap_size - base) / SAMPLE_COUNT
|
||||
console.log(`${h(str.length)} lorem-html after GC x ${h(diff2)}/tpl (${SAMPLE_COUNT} instances sampled)`)
|
||||
console.log(`[lorem-html ${h(str.length)}][after GC] ${h(diff2)}/tpl (${SAMPLE_COUNT} runs sampled)`)
|
||||
}
|
||||
|
||||
function todolist () {
|
||||
@@ -47,15 +48,15 @@ function todolist () {
|
||||
templates.push(engine.parse(str))
|
||||
}
|
||||
const diff1 = (getHeapStatistics().used_heap_size - base) / SAMPLE_COUNT
|
||||
console.log(`${h(str.length)} todolist before GC x ${h(diff1)}/tpl (${SAMPLE_COUNT} instances sampled)`)
|
||||
console.log(`[todolist ${h(str.length)}][before GC] ${h(diff1)}/tpl (${SAMPLE_COUNT} runs sampled)`)
|
||||
|
||||
global.gc()
|
||||
const diff2 = (getHeapStatistics().used_heap_size - base) / SAMPLE_COUNT
|
||||
console.log(`${h(str.length)} todolist after GC x ${h(diff2)}/tpl (${SAMPLE_COUNT} instances sampled)`)
|
||||
console.log(`[todolist ${h(str.length)}][after GC] ${h(diff2)}/tpl (${SAMPLE_COUNT} runs sampled)`)
|
||||
}
|
||||
|
||||
function h (size) {
|
||||
return (size / 1024).toFixed(3) + ' kB'
|
||||
return (size / 1024).toFixed(3) + ' KB'
|
||||
}
|
||||
|
||||
module.exports = { memory }
|
||||
|
||||
Regular → Executable
+2
-1
@@ -4,7 +4,8 @@ const { Liquid } = require('..')
|
||||
const liquid = new Liquid()
|
||||
|
||||
function output () {
|
||||
console.log('--- output ---')
|
||||
console.log(' output')
|
||||
console.log('------------------------')
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite('output')
|
||||
.add('literal', test('{{false}}{{"foo"}}{{32.322}}'))
|
||||
|
||||
Generated
+3380
File diff suppressed because it is too large
Load Diff
Executable
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "benchmark",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node --expose-gc index",
|
||||
"engines": "node -e 'require(\"./cross-engines\").crossEngines()'"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.13.14",
|
||||
"@babel/preset-env": "^7.13.12",
|
||||
"@babel/preset-react": "^7.13.13",
|
||||
"handlebars": "^4.7.7",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"require-from-string": "^2.0.2",
|
||||
"swig": "^1.4.2"
|
||||
}
|
||||
}
|
||||
Regular → Executable
+2
-1
@@ -4,7 +4,8 @@ const { Liquid } = require('..')
|
||||
const liquid = new Liquid()
|
||||
|
||||
function tag () {
|
||||
console.log('--- tag ---')
|
||||
console.log(' tag')
|
||||
console.log('------------------------')
|
||||
return new Promise(resolve => {
|
||||
new Benchmark.Suite('tag')
|
||||
.add('if', test('{% if "foobar" %}foo{% endif %}'))
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<img title="risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices" src="http://images.example.com/{{id}}.png">
|
||||
@@ -0,0 +1 @@
|
||||
<img title="risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices" src="http://images.example.com/{{id}}.png">
|
||||
@@ -0,0 +1 @@
|
||||
<img title="risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices" src="http://images.example.com/{{todo.id}}.png">
|
||||
@@ -0,0 +1,44 @@
|
||||
<section class="todo-list">
|
||||
<h1>
|
||||
posuere cubilia Curae; Vestibulum hendrerit malesuada odio. Fusce ut elit
|
||||
ut augue sollicitudin blandit. Phasellus volutpat lorem. Duis non pede et
|
||||
neque luctus tincidunt. Duis interdum tempus elit.
|
||||
<small>Aenean metus. Vestibulum ac lacus. Vivamus porttitor, massa ut.</small>
|
||||
</h1>
|
||||
<a href={{url "/add"}} class="todo-add"><i class="fa fa-plus-square"></i>Add Todo</a>
|
||||
<ul class="filter-category">
|
||||
{{#each categories }}
|
||||
<li style="background: {{ color }}">
|
||||
<a href="/todos/category/{{ id }}">{{ title }}</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#each todos }}
|
||||
<div>
|
||||
<h2>
|
||||
Todo {{inc @index}}:
|
||||
<span class="todo-item content" data-todo-index="{{@index}}">
|
||||
{{ upcase (concat 'TODO: ' title) }}
|
||||
</span>
|
||||
</h2>
|
||||
{{> todo-icon id=id }}
|
||||
|
||||
<p class="description">
|
||||
Purus eu mi. Proin commodo, massa commodo dapibus elementum,
|
||||
libero lacus pulvinar eros, ut tincidunt nisl elit ut velit. Cras rutrum
|
||||
porta purus. Vivamus lorem. Sed turpis enim, faucibus quis, pharetra in,
|
||||
sagittis sed, magna. Curabitur ultricies felis ut libero. Nullam tincidunt
|
||||
enim eu nibh. Nunc eget ipsum in sem facilisis convallis. Proin fermentum
|
||||
</p>
|
||||
|
||||
<div class="todo-meta">
|
||||
{{# if category }}
|
||||
<span>{{ capitalize category }}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<a class="btn btn-primary" href={{ url (concat "/edit/" id) }}><i class="fa fa-pencil"></i> Edit</a>
|
||||
<a class="btn btn-default"><i class="fa fa-check"></i> Check</a>
|
||||
<a class="btn ben-danger" href={{ url (concat "/delete/" id) }}><i class="fa fa-trash-o"</i> Trash</a>
|
||||
</div>
|
||||
{{/each}}
|
||||
</section>
|
||||
@@ -0,0 +1,57 @@
|
||||
// eslint-disable-next-line
|
||||
const React = require('react')
|
||||
|
||||
function capitalize (str) {
|
||||
return str[0].toUpperCase() + str.slice(1).toLowerCase()
|
||||
}
|
||||
function url (path) {
|
||||
return `http://example.com${path}`
|
||||
}
|
||||
function renderTodoIcon (id) {
|
||||
return <img title="risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices" src="http://images.example.com/{id}.png"/>
|
||||
}
|
||||
|
||||
module.exports = ({ categories, todos }) => {
|
||||
return <section className="todo-list">
|
||||
<h1>
|
||||
posuere cubilia Curae; Vestibulum hendrerit malesuada odio. Fusce ut elit
|
||||
ut augue sollicitudin blandit. Phasellus volutpat lorem. Duis non pede et
|
||||
neque luctus tincidunt. Duis interdum tempus elit.
|
||||
<small>Aenean metus. Vestibulum ac lacus. Vivamus porttitor, massa ut.</small>
|
||||
</h1>
|
||||
<a href={url('/add')} className="todo-add"><i className="fa fa-plus-square"></i>Add Todo</a>
|
||||
<ul className="filter-category">
|
||||
{categories.map((item, i) => {
|
||||
return <li key={i} style={{ background: item.color }}>
|
||||
<a href={'/todos/category/' + item.id }>{ item.title }</a>
|
||||
</li>
|
||||
})}
|
||||
</ul>
|
||||
{todos.map((todo, index0) => {
|
||||
return <div key={index0}>
|
||||
<h2>
|
||||
Todo { index0 + 1 }:
|
||||
<span className="todo-item content" data-todo-index="{{ forloop.index0 }}">
|
||||
{ ('TODO: ' + todo.title).toUpperCase() }
|
||||
</span>
|
||||
</h2>
|
||||
{ renderTodoIcon(todo.id) }
|
||||
|
||||
<p className="description">
|
||||
Purus eu mi. Proin commodo, massa commodo dapibus elementum,
|
||||
libero lacus pulvinar eros, ut tincidunt nisl elit ut velit. Cras rutrum
|
||||
porta purus. Vivamus lorem. Sed turpis enim, faucibus quis, pharetra in,
|
||||
sagittis sed, magna. Curabitur ultricies felis ut libero. Nullam tincidunt
|
||||
enim eu nibh. Nunc eget ipsum in sem facilisis convallis. Proin fermentum
|
||||
</p>
|
||||
|
||||
<div className="todo-meta">
|
||||
{ todo.category ? <span>{capitalize(todo.category)}</span> : '' }
|
||||
</div>
|
||||
<a className="btn btn-primary" href={url('/edit/' + todo.id)}><i className="fa fa-pencil"></i> Edit</a>
|
||||
<a className="btn btn-default"><i className="fa fa-check"></i> Check</a>
|
||||
<a className="btn ben-danger" href={url('/delete/' + todo.id)}><i className="fa fa-trash-o"></i> Trash</a>
|
||||
</div>
|
||||
})}
|
||||
</section>
|
||||
}
|
||||
@@ -7,8 +7,7 @@
|
||||
</h1>
|
||||
<a href={{"/add" | url}} class="todo-add"><i class="fa fa-plus-square"></i>Add Todo</a>
|
||||
<ul class="filter-category">
|
||||
{% for i in (0..categories.length) %}
|
||||
{% assign item=categories[i] %}
|
||||
{% for item in categories %}
|
||||
<li style="background: {{ item.color }}">
|
||||
<a href="/todos/category/{{ item.id }}">{{ item.title }}</a>
|
||||
</li>
|
||||
@@ -22,11 +21,7 @@
|
||||
{{ todo.title | prepend: 'TODO: ' | upcase }}
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
<img
|
||||
title="risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices"
|
||||
src="{% include "todo-icon", id=todo.id }} %}"
|
||||
>
|
||||
{% render "todo-icon", id:todo.id %}
|
||||
|
||||
<p class="description">
|
||||
Purus eu mi. Proin commodo, massa commodo dapibus elementum,
|
||||
@@ -38,12 +33,12 @@
|
||||
|
||||
<div class="todo-meta">
|
||||
{% if todo.category %}
|
||||
<span>{{ todo.category.title | capitalize }}</span>
|
||||
<span>{{ todo.category | capitalize }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a class="btn btn-primary" href={{"/edit/" | append todo.id | url }}><i class="fa fa-pencil"></i> Edit</a>
|
||||
<a class="btn btn-primary" href={{"/edit/" | append: todo.id | url }}><i class="fa fa-pencil"></i> Edit</a>
|
||||
<a class="btn btn-default"><i class="fa fa-check"></i> Check</a>
|
||||
<a class="btn ben-danger" href={{"/delete/" | append todo.id | url }}><i class="fa fa-trash-o"</i> Trash</a>
|
||||
<a class="btn ben-danger" href={{"/delete/" | append: todo.id | url }}><i class="fa fa-trash-o"</i> Trash</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<section class="todo-list">
|
||||
<h1>
|
||||
posuere cubilia Curae; Vestibulum hendrerit malesuada odio. Fusce ut elit
|
||||
ut augue sollicitudin blandit. Phasellus volutpat lorem. Duis non pede et
|
||||
neque luctus tincidunt. Duis interdum tempus elit.
|
||||
<small>Aenean metus. Vestibulum ac lacus. Vivamus porttitor, massa ut.</small>
|
||||
</h1>
|
||||
<a href={{"/add" | url}} class="todo-add"><i class="fa fa-plus-square"></i>Add Todo</a>
|
||||
<ul class="filter-category">
|
||||
{% for item in categories %}
|
||||
<li style="background: {{ item.color }}">
|
||||
<a href="/todos/category/{{ item.id }}">{{ item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% for todo in todos %}
|
||||
<div>
|
||||
<h2>
|
||||
Todo {{ loop.index }}:
|
||||
<span class="todo-item content" data-todo-index="{{ loop.index0 }}">
|
||||
{{ todo.title | prepend('TODO: ') | upcase }}
|
||||
</span>
|
||||
</h2>
|
||||
{% include "todo-icon.swig" %}
|
||||
|
||||
<p class="description">
|
||||
Purus eu mi. Proin commodo, massa commodo dapibus elementum,
|
||||
libero lacus pulvinar eros, ut tincidunt nisl elit ut velit. Cras rutrum
|
||||
porta purus. Vivamus lorem. Sed turpis enim, faucibus quis, pharetra in,
|
||||
sagittis sed, magna. Curabitur ultricies felis ut libero. Nullam tincidunt
|
||||
enim eu nibh. Nunc eget ipsum in sem facilisis convallis. Proin fermentum
|
||||
</p>
|
||||
|
||||
<div class="todo-meta">
|
||||
{% if todo.category %}
|
||||
<span>{{ todo.category | capitalize }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a class="btn btn-primary" href={{"/edit/" | append(todo.id) | url }}><i class="fa fa-pencil"></i> Edit</a>
|
||||
<a class="btn btn-default"><i class="fa fa-check"></i> Check</a>
|
||||
<a class="btn ben-danger" href={{"/delete/" | append(todo.id) | url }}><i class="fa fa-trash-o"</i> Trash</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
Generated
+28343
-1529
File diff suppressed because it is too large
Load Diff
+12
-10
@@ -15,14 +15,15 @@
|
||||
"check": "npm test && npm run lint",
|
||||
"unit": "mocha \"test/unit/**/*.ts\"",
|
||||
"integration": "mocha \"test/integration/**/*.ts\"",
|
||||
"e2e": "npm run build && mocha \"test/e2e/**/*.ts\"",
|
||||
"e2e": "mocha \"test/e2e/**/*.ts\"",
|
||||
"test": "cross-env BUNDLES=cjs,umd npm run build && mocha \"test/**/*.ts\"",
|
||||
"benchmark": "node --expose-gc benchmark/index",
|
||||
"benchmark:prepare": "cd benchmark && npm ci",
|
||||
"benchmark": "cd benchmark && npm start",
|
||||
"benchmark:engines": "cd benchmark && npm run engines",
|
||||
"coverage": "nyc --reporter=html mocha \"test/{unit,integration}/**/*.ts\"",
|
||||
"coverage-coveralls": "nyc mocha \"test/{unit,integration}/**/*.ts\" && nyc report --reporter=text-lcov | coveralls",
|
||||
"build": "rm -rf dist && rollup -c rollup.config.ts && ls -lh dist",
|
||||
"build-docs": "bin/build-docs.sh",
|
||||
"watch": "tsc --watch"
|
||||
"build-docs": "bin/build-docs.sh"
|
||||
},
|
||||
"bin": {
|
||||
"liquidjs": "./bin/liquid.js",
|
||||
@@ -59,7 +60,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/harttle/liquidjs#readme",
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^8.2.0",
|
||||
"@commitlint/cli": "^12.1.4",
|
||||
"@commitlint/config-conventional": "^8.2.0",
|
||||
"@semantic-release/changelog": "^3.0.2",
|
||||
"@semantic-release/commit-analyzer": "^6.1.0",
|
||||
@@ -93,13 +94,13 @@
|
||||
"express": "^4.16.4",
|
||||
"husky": "^4.2.5",
|
||||
"jsdom": "^13.2.0",
|
||||
"mocha": "^5.2.0",
|
||||
"nyc": "^13.1.0",
|
||||
"mocha": "^9.0.1",
|
||||
"nyc": "^15.1.0",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"rollup": "^1.1.2",
|
||||
"rollup-plugin-replace": "^2.1.0",
|
||||
"rollup-plugin-typescript2": "^0.21.1",
|
||||
"rollup-plugin-uglify": "^6.0.2",
|
||||
"rollup-plugin-uglify": "^5.0.2",
|
||||
"semantic-release": "^17.2.3",
|
||||
"sinon": "^7.5.0",
|
||||
"sinon-chai": "^3.3.0",
|
||||
@@ -141,6 +142,7 @@
|
||||
"pre-commit": "npm run check",
|
||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ import { stringify } from '../../util/underscore'
|
||||
import { assert } from '../../util/assert'
|
||||
|
||||
export function append (v: string, arg: string) {
|
||||
assert(arg !== undefined, () => 'append expect 2 arguments')
|
||||
assert(arguments.length === 2, () => 'append expect 2 arguments')
|
||||
return stringify(v) + stringify(arg)
|
||||
}
|
||||
|
||||
export function prepend (v: string, arg: string) {
|
||||
assert(arg !== undefined, () => 'prepend expect 2 arguments')
|
||||
assert(arguments.length === 2, () => 'prepend expect 2 arguments')
|
||||
return stringify(arg) + stringify(v)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export default {
|
||||
render: function * (ctx: Context, emitter: Emitter) {
|
||||
const { liquid, hash, withVar, file } = this
|
||||
const { renderer } = liquid
|
||||
// TODO try move all liquid.parse calls into parse() section
|
||||
const filepath = ctx.opts.dynamicPartials
|
||||
? (TypeGuards.isQuotedToken(file)
|
||||
? yield renderer.renderTemplates(liquid.parse(evalQuotedToken(file)), ctx)
|
||||
|
||||
@@ -9,9 +9,6 @@ describe('filters/string', function () {
|
||||
it('should return "-3abc" for -3, "abc"',
|
||||
() => test('{{ -3 | append: "abc" }}', '-3abc'))
|
||||
it('should return "abar" for "a", foo', () => test('{{ "a" | append: foo }}', { foo: 'bar' }, 'abar'))
|
||||
it('should throw if second argument undefined', () => {
|
||||
return expect(test('{{ "abc" | append: undefinedVar }}', 'abc')).to.be.rejectedWith(/2 arguments/)
|
||||
})
|
||||
it('should throw if second argument not set', () => {
|
||||
return expect(test('{{ "abc" | append }}', 'abc')).to.be.rejectedWith(/2 arguments/)
|
||||
})
|
||||
@@ -21,9 +18,6 @@ describe('filters/string', function () {
|
||||
it('should return "-3abc" for -3, "abc"',
|
||||
() => test('{{ -3 | prepend: "abc" }}', 'abc-3'))
|
||||
it('should return "abar" for "a", foo', () => test('{{ "a" | prepend: foo }}', { foo: 'bar' }, 'bara'))
|
||||
it('should throw if second argument undefined', () => {
|
||||
return expect(test('{{ "abc" | prepend: undefinedVar }}', 'abc')).to.be.rejectedWith(/2 arguments/)
|
||||
})
|
||||
it('should throw if second argument not set', () => {
|
||||
return expect(test('{{ "abc" | prepend }}', 'abc')).to.be.rejectedWith(/2 arguments/)
|
||||
})
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
--require ts-node/register/transpile-only --strict false
|
||||
Reference in New Issue
Block a user