Skip to content

Commit

Permalink
Merge branch 'harttle:master' into static-analysis-alternate
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp authored Dec 28, 2024
2 parents e9b11f4 + 35a8442 commit d1f7bea
Show file tree
Hide file tree
Showing 18 changed files with 80 additions and 26 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,15 @@
"contributions": [
"doc"
]
},
{
"login": "timvandam",
"name": "Tim van Dam",
"avatar_url": "https://avatars.githubusercontent.com/u/35376389?v=4",
"profile": "https://tovd.dev",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## [10.19.1](https://github.com/harttle/liquidjs/compare/v10.19.0...v10.19.1) (2024-12-22)


### Bug Fixes

* add sideEffects=false to package.json ([734eb52](https://github.com/harttle/liquidjs/commit/734eb52b987d46d33cf8f03281a3773a0f1f0e4a))
* inconsistent continue behaviour, fixes [#779](https://github.com/harttle/liquidjs/issues/779) ([e3ef574](https://github.com/harttle/liquidjs/commit/e3ef574674c5a21a37b3ffc929f514c8a3d0b866))
* memoryLimit doesn't work in for tag, [#776](https://github.com/harttle/liquidjs/issues/776) ([2af297f](https://github.com/harttle/liquidjs/commit/2af297f81ac465feb3277ba7b92f7236409370b0))

# [10.19.0](https://github.com/harttle/liquidjs/compare/v10.18.0...v10.19.0) (2024-11-17)


Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ Want to contribute? see [Contribution Guidelines][contribution]. Thanks goes to
<td align="center" valign="top" width="14.28%"><a href="https://vrugtehagel.nl"><img src="https://avatars.githubusercontent.com/u/41021050?v=4?s=100" width="100px;" alt="Koen"/><br /><sub><b>Koen</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=vrugtehagel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://neamar.fr"><img src="https://avatars.githubusercontent.com/u/536844?v=4?s=100" width="100px;" alt="Matthieu Bacconnier"/><br /><sub><b>Matthieu Bacconnier</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=Neamar" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://tovd.dev"><img src="https://avatars.githubusercontent.com/u/35376389?v=4?s=100" width="100px;" alt="Tim van Dam"/><br /><sub><b>Tim van Dam</b></sub></a><br /><a href="https://github.com/harttle/liquidjs/commits?author=timvandam" title="Code">💻</a></td>
</tr>
</tbody>
</table>

Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"private": true,
"hexo": {
"version": "5.4.0"
"version": "7.3.0"
},
"scripts": {
"build": "hexo generate",
Expand Down
5 changes: 4 additions & 1 deletion docs/themes/navy/source/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@
/* global liquidjs, ace */
if (!location.pathname.match(/playground.html$/)) return;
updateVersion(liquidjs.version);
const engine = new liquidjs.Liquid();
const engine = new liquidjs.Liquid({
memoryLimit: 1e5,
renderLimit: 1e5
});
const editor = createEditor('editorEl', 'liquid');
const dataEditor = createEditor('dataEl', 'json');
const preview = createEditor('previewEl', 'html');
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "liquidjs",
"version": "10.19.0",
"version": "10.19.1",
"sideEffects": false,
"description": "A simple, expressive and safe Shopify / Github Pages compatible template engine in pure JavaScript.",
"main": "dist/liquid.node.js",
"module": "dist/liquid.node.mjs",
Expand Down
2 changes: 2 additions & 0 deletions src/context/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export class Context {
*/
public globals: Scope
public sync: boolean
public breakCalled = false
public continueCalled = false
/**
* The normalized liquid options object
*/
Expand Down
6 changes: 3 additions & 3 deletions src/filters/array.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast } from '../util'
import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast, isArrayLike } from '../util'
import { arrayIncludes, equals, evalToken, isTruthy } from '../render'
import { Value, FilterImpl } from '../template'
import { Tokenizer } from '../parser'
Expand All @@ -12,8 +12,8 @@ export const join = argumentsToValue(function (this: FilterImpl, v: any[], arg:
this.context.memoryLimit.use(complexity)
return array.join(sep)
})
export const last = argumentsToValue((v: any) => isArray(v) ? arrayLast(v) : '')
export const first = argumentsToValue((v: any) => isArray(v) ? v[0] : '')
export const last = argumentsToValue((v: any) => isArrayLike(v) ? arrayLast(v) : '')
export const first = argumentsToValue((v: any) => isArrayLike(v) ? v[0] : '')
export const reverse = argumentsToValue(function (this: FilterImpl, v: any[]) {
const array = toArray(v)
this.context.memoryLimit.use(array.length)
Expand Down
1 change: 1 addition & 0 deletions src/render/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function evalQuotedToken (token: QuotedToken) {
function * evalRangeToken (token: RangeToken, ctx: Context) {
const low: number = yield evalToken(token.lhs, ctx)
const high: number = yield evalToken(token.rhs, ctx)
ctx.memoryLimit.use(high - low + 1)
return range(+low, +high + 1)
}

Expand Down
2 changes: 1 addition & 1 deletion src/render/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class Render {
const html = yield tpl.render(ctx, emitter)
// if not, it'll return an `html`, write to the emitter for it
html && emitter.write(html)
if (emitter['break'] || emitter['continue']) break
if (ctx.breakCalled || ctx.continueCalled) break
} catch (e) {
const err = LiquidError.is(e) ? e : new RenderError(e as Error, tpl)
if (ctx.opts.catchAllErrors) errors.push(err)
Expand Down
4 changes: 2 additions & 2 deletions src/tags/break.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Context, Emitter, Tag } from '..'

export default class extends Tag {
render (ctx: Context, emitter: Emitter) {
emitter['break'] = true
render (ctx: Context, _emitter: Emitter) {
ctx.breakCalled = true
}
}
4 changes: 2 additions & 2 deletions src/tags/continue.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Tag, Emitter, Context } from '..'

export default class extends Tag {
render (ctx: Context, emitter: Emitter) {
emitter['continue'] = true
render (ctx: Context, _emitter: Emitter) {
ctx.continueCalled = true
}
}
7 changes: 2 additions & 5 deletions src/tags/for.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,9 @@ export default class extends Tag {
ctx.push(scope)
for (const item of collection) {
scope[this.variable] = item
ctx.continueCalled = ctx.breakCalled = false
yield r.renderTemplates(this.templates, ctx, emitter)
if (emitter['break']) {
emitter['break'] = false
break
}
emitter['continue'] = false
if (ctx.breakCalled) break
scope.forloop.next()
}
ctx.pop()
Expand Down
4 changes: 4 additions & 0 deletions src/util/underscore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export function isArray (value: any): value is any[] {
return toString.call(value) === '[object Array]'
}

export function isArrayLike (value: any): value is any[] {
return value && isNumber(value.length)
}

export function isIterable (value: any): value is Iterable<any> {
return isObject(value) && Symbol.iterator in value
}
Expand Down
7 changes: 7 additions & 0 deletions test/e2e/issues.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,4 +524,11 @@ describe('Issues', function () {
const result = engine.parseAndRenderSync(`\n{{ "foo" | pos }}`)
expect(result).toEqual('\n[2,12] foo')
})
it("memoryLimit doesn't work in for tag #776", () => {
const engine = new Liquid({
memoryLimit: 1e5
})
const tpl = `{% for i in (1..1000000000) %} {{'a'}} {% endfor %}`
expect(() => engine.parseAndRenderSync(tpl)).toThrow('memory alloc limit exceeded, line:1, col:1')
})
})
12 changes: 3 additions & 9 deletions test/integration/filters/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ describe('filters/array', function () {
return expect(render(src)).rejects.toThrow('expected ":" after filter name, line:1, col:83')
})
})
describe('last', () => {
it('should support last', function () {
const src = '{{ arr | last }}'
const scope = { arr: ['zebra', 'octopus', 'giraffe', 'tiger'] }
return test(src, scope, 'tiger')
})
})
describe('split', () => {
it('should support split', function () {
const src = '{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %}' +
Expand Down Expand Up @@ -263,6 +256,7 @@ describe('filters/array', function () {
it('should return 0 for false', () => test('{{ false | size }}', '0'))
it('should return 0 for nil', () => test('{{ nil | size }}', '0'))
it('should return 0 for undefined', () => test('{{ foo | size }}', '0'))
it('should work for string', () => test('{{ "foo" | size }}', {}, '3'))
})
describe('first', function () {
it('should support first', () => test(
Expand All @@ -273,7 +267,7 @@ describe('filters/array', function () {
it('should return empty for nil', () => test('{{nil | first}}', ''))
it('should return empty for undefined', () => test('{{foo | first}}', ''))
it('should return empty for false', () => test('{{false | first}}', ''))
it('should return empty for string', () => test('{{"zebra" | first}}', ''))
it('should work for string', () => test('{{ "foo" | first }}', 'f'))
})
describe('last', function () {
it('should support last', () => test(
Expand All @@ -284,7 +278,7 @@ describe('filters/array', function () {
it('should return empty for nil', () => test('{{nil | last}}', ''))
it('should return empty for undefined', () => test('{{foo | last}}', ''))
it('should return empty for false', () => test('{{false | last}}', ''))
it('should return empty for string', () => test('{{"zebra" | last}}', ''))
it('should work for string', () => test('{{ "foo" | last }}', {}, 'o'))
})
describe('slice', function () {
it('should slice first char by 0', () => test('{{ "Liquid" | slice: 0 }}', 'L'))
Expand Down
24 changes: 24 additions & 0 deletions test/integration/tags/for.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Liquid } from '../../../src/liquid'
import { Drop } from '../../../src/drop/drop'
import { Scope } from '../../../src/context/scope'
import { mock, restore } from '../../stub/mockfs'

describe('tags/for', function () {
let liquid: Liquid, scope: Scope
Expand Down Expand Up @@ -139,6 +140,7 @@ describe('tags/for', function () {
})

describe('continue', function () {
afterEach(restore)
it('should support for with continue', async function () {
const src = '{% for i in (1..5) %}' +
'{% if i == 4 %}continue{% continue %}{% endif %}{{i}}' +
Expand All @@ -154,6 +156,28 @@ describe('tags/for', function () {
const html = await liquid.parseAndRender(src, scope)
return expect(html).toBe('123continue5')
})
it('should skip snippet for rendered continue', async function () {
mock({
'snippet.liquid': ' before{% continue %}skipped'
})
const src = '{% for i in (1..2) %}' +
'{% render "snippet.liquid" %}' +
' after' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, scope)
return expect(html).toBe(' before after before after')
})
it('should skip `for` body for included continue', async function () {
mock({
'snippet.liquid': ' before{% continue %}skipped'
})
const src = '{% for i in (1..2) %}' +
'{% include "snippet.liquid" %}' +
' after' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, scope)
return expect(html).toBe(' before before')
})
})
describe('break', function () {
it('should support break', async function () {
Expand Down

0 comments on commit d1f7bea

Please sign in to comment.