@skeptools/skep-organization-project 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +22 -2139
- package/API.md +533 -418
- package/lib/skep-organization-project.js +36 -5
- package/node_modules/liquidjs/README.md +110 -67
- package/node_modules/liquidjs/dist/build/base64-impl-browser.d.ts +2 -0
- package/node_modules/liquidjs/dist/build/base64-impl-browser.spec.d.ts +1 -0
- package/node_modules/liquidjs/dist/build/crypto-impl-browser.d.ts +2 -0
- package/node_modules/liquidjs/dist/build/crypto-impl-browser.spec.d.ts +1 -0
- package/node_modules/liquidjs/dist/context/context.d.ts +10 -4
- package/node_modules/liquidjs/dist/context/scope.d.ts +2 -2
- package/node_modules/liquidjs/dist/drop/blank-drop.d.ts +1 -1
- package/node_modules/liquidjs/dist/drop/block-drop.d.ts +3 -2
- package/node_modules/liquidjs/dist/drop/comparable.d.ts +11 -5
- package/node_modules/liquidjs/dist/drop/drop.d.ts +3 -1
- package/node_modules/liquidjs/dist/drop/empty-drop.d.ts +1 -1
- package/node_modules/liquidjs/dist/drop/null-drop.d.ts +1 -1
- package/node_modules/liquidjs/dist/filters/array.d.ts +9 -3
- package/node_modules/liquidjs/dist/filters/base64-impl.d.ts +2 -0
- package/node_modules/liquidjs/dist/filters/base64.d.ts +9 -0
- package/node_modules/liquidjs/dist/filters/crypto-impl.d.ts +2 -0
- package/node_modules/liquidjs/dist/filters/crypto.d.ts +8 -0
- package/node_modules/liquidjs/dist/filters/math.d.ts +1 -1
- package/node_modules/liquidjs/dist/filters/misc.d.ts +2 -2
- package/node_modules/liquidjs/dist/filters/string.d.ts +2 -1
- package/node_modules/liquidjs/dist/fs/fs-impl.d.ts +2 -1
- package/node_modules/liquidjs/dist/fs/fs.d.ts +4 -2
- package/node_modules/liquidjs/dist/fs/loader.d.ts +2 -1
- package/node_modules/liquidjs/dist/index.d.ts +8 -3
- package/node_modules/liquidjs/dist/liquid-options.d.ts +8 -2
- package/node_modules/liquidjs/dist/liquid.browser.min.js +1 -1
- package/node_modules/liquidjs/dist/liquid.browser.min.js.map +1 -1
- package/node_modules/liquidjs/dist/liquid.browser.mjs +836 -406
- package/node_modules/liquidjs/dist/liquid.browser.umd.js +1683 -788
- package/node_modules/liquidjs/dist/liquid.browser.umd.js.map +1 -1
- package/node_modules/liquidjs/dist/liquid.d.ts +1 -0
- package/node_modules/liquidjs/dist/liquid.node.js +848 -426
- package/node_modules/liquidjs/dist/liquid.node.mjs +849 -422
- package/node_modules/liquidjs/dist/parser/parser.d.ts +1 -0
- package/node_modules/liquidjs/dist/parser/token-kind.d.ts +1 -0
- package/node_modules/liquidjs/dist/parser/tokenizer.d.ts +4 -3
- package/node_modules/liquidjs/dist/render/expression.d.ts +11 -1
- package/node_modules/liquidjs/dist/render/operator.d.ts +11 -4
- package/node_modules/liquidjs/dist/tags/case.d.ts +2 -2
- package/node_modules/liquidjs/dist/tags/for.d.ts +2 -2
- package/node_modules/liquidjs/dist/tags/include.d.ts +2 -0
- package/node_modules/liquidjs/dist/tags/layout.d.ts +1 -0
- package/node_modules/liquidjs/dist/tags/render.d.ts +2 -0
- package/node_modules/liquidjs/dist/tags/tablerow.d.ts +2 -2
- package/node_modules/liquidjs/dist/tokens/literal-token.d.ts +2 -2
- package/node_modules/liquidjs/dist/tokens/operator-token.d.ts +3 -2
- package/node_modules/liquidjs/dist/tokens/property-access-token.d.ts +3 -2
- package/node_modules/liquidjs/dist/tokens/tag-token.d.ts +1 -1
- package/node_modules/liquidjs/dist/tokens/value-token.d.ts +2 -1
- package/node_modules/liquidjs/dist/util/async.d.ts +2 -0
- package/node_modules/liquidjs/dist/util/liquid-date.d.ts +7 -0
- package/node_modules/liquidjs/dist/util/operator-trie.d.ts +4 -8
- package/node_modules/liquidjs/dist/util/strftime.d.ts +2 -1
- package/node_modules/liquidjs/dist/util/type-guards.d.ts +2 -1
- package/node_modules/liquidjs/dist/util/underscore.d.ts +5 -1
- package/node_modules/liquidjs/package.json +20 -14
- package/package.json +47 -41
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* liquidjs@10.
|
|
3
|
-
* (c) 2016-
|
|
2
|
+
* liquidjs@10.30.1, https://github.com/harttle/liquidjs
|
|
3
|
+
* (c) 2016-2026 harttle
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
import { PassThrough } from 'stream';
|
|
7
7
|
import { sep, extname, resolve as resolve$1, dirname as dirname$1 } from 'path';
|
|
8
|
-
import { statSync, readFileSync as readFileSync$1, stat, readFile as readFile$1 } from 'fs';
|
|
8
|
+
import { statSync, readFileSync as readFileSync$1, realpathSync, stat, readFile as readFile$1, realpath } from 'fs';
|
|
9
9
|
import { createRequire } from 'module';
|
|
10
|
+
import { createHash, createHmac } from 'crypto';
|
|
10
11
|
|
|
11
12
|
class Token {
|
|
12
13
|
constructor(kind, input, begin, end, file) {
|
|
@@ -37,7 +38,7 @@ class Token {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
class Drop {
|
|
40
|
-
liquidMethodMissing(key) {
|
|
41
|
+
liquidMethodMissing(key, context) {
|
|
41
42
|
return undefined;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
@@ -58,9 +59,6 @@ function isPromise(val) {
|
|
|
58
59
|
function isIterator(val) {
|
|
59
60
|
return val && isFunction(val.next) && isFunction(val.throw) && isFunction(val.return);
|
|
60
61
|
}
|
|
61
|
-
function escapeRegex(str) {
|
|
62
|
-
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
63
|
-
}
|
|
64
62
|
function promisify(fn) {
|
|
65
63
|
return function (...args) {
|
|
66
64
|
return new Promise((resolve, reject) => {
|
|
@@ -80,6 +78,25 @@ function stringify(value) {
|
|
|
80
78
|
return value.map(x => stringify(x)).join('');
|
|
81
79
|
return String(value);
|
|
82
80
|
}
|
|
81
|
+
function advanceCodePoints(str, from, count) {
|
|
82
|
+
let index = from;
|
|
83
|
+
for (let i = 0; i < count && index < str.length; i++)
|
|
84
|
+
index += str.codePointAt(index) > 0xFFFF ? 2 : 1;
|
|
85
|
+
return index;
|
|
86
|
+
}
|
|
87
|
+
function codePointLength(str) {
|
|
88
|
+
let length = 0;
|
|
89
|
+
for (let index = 0; index < str.length; index = advanceCodePoints(str, index, 1))
|
|
90
|
+
length++;
|
|
91
|
+
return length;
|
|
92
|
+
}
|
|
93
|
+
function readArrayElement(arr, index, ownPropertyOnly) {
|
|
94
|
+
if (index < 0)
|
|
95
|
+
index = arr.length + index;
|
|
96
|
+
if (ownPropertyOnly && !hasOwnProperty.call(arr, index))
|
|
97
|
+
return undefined;
|
|
98
|
+
return arr[index];
|
|
99
|
+
}
|
|
83
100
|
function toEnumerable(val) {
|
|
84
101
|
val = toValue(val);
|
|
85
102
|
if (isArray(val))
|
|
@@ -104,8 +121,7 @@ function toValue(value) {
|
|
|
104
121
|
return (value instanceof Drop && isFunction(value.valueOf)) ? value.valueOf() : value;
|
|
105
122
|
}
|
|
106
123
|
function toNumber(value) {
|
|
107
|
-
|
|
108
|
-
return isNaN(value) ? 0 : value;
|
|
124
|
+
return +toValue(value) || 0;
|
|
109
125
|
}
|
|
110
126
|
function isNumber(value) {
|
|
111
127
|
return typeof value === 'number';
|
|
@@ -149,9 +165,6 @@ function forOwn(obj, iteratee) {
|
|
|
149
165
|
}
|
|
150
166
|
return obj;
|
|
151
167
|
}
|
|
152
|
-
function last(arr) {
|
|
153
|
-
return arr[arr.length - 1];
|
|
154
|
-
}
|
|
155
168
|
/*
|
|
156
169
|
* Checks if value is the language type of Object.
|
|
157
170
|
* (e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
|
|
@@ -177,10 +190,10 @@ function padEnd(str, length, ch = ' ') {
|
|
|
177
190
|
}
|
|
178
191
|
function pad(str, length, ch, add) {
|
|
179
192
|
str = String(str);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return str;
|
|
193
|
+
const n = length - str.length;
|
|
194
|
+
if (n <= 0)
|
|
195
|
+
return str;
|
|
196
|
+
return add(str, ch.repeat(n));
|
|
184
197
|
}
|
|
185
198
|
function identify(val) {
|
|
186
199
|
return val;
|
|
@@ -192,13 +205,26 @@ function changeCase(str) {
|
|
|
192
205
|
function ellipsis(str, N) {
|
|
193
206
|
return str.length > N ? str.slice(0, N - 3) + '...' : str;
|
|
194
207
|
}
|
|
208
|
+
function orderedCompare(a, b) {
|
|
209
|
+
if (isNil(a) && isNil(b))
|
|
210
|
+
return 0;
|
|
211
|
+
if (isNil(a))
|
|
212
|
+
return 1;
|
|
213
|
+
if (isNil(b))
|
|
214
|
+
return -1;
|
|
215
|
+
if (a < b)
|
|
216
|
+
return -1;
|
|
217
|
+
if (a > b)
|
|
218
|
+
return 1;
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
195
221
|
// compare string in case-insensitive way, undefined values to the tail
|
|
196
222
|
function caseInsensitiveCompare(a, b) {
|
|
197
|
-
if (a
|
|
223
|
+
if (isNil(a) && isNil(b))
|
|
198
224
|
return 0;
|
|
199
|
-
if (a
|
|
225
|
+
if (isNil(a))
|
|
200
226
|
return 1;
|
|
201
|
-
if (b
|
|
227
|
+
if (isNil(b))
|
|
202
228
|
return -1;
|
|
203
229
|
a = toLowerCase.call(a);
|
|
204
230
|
b = toLowerCase.call(b);
|
|
@@ -211,8 +237,8 @@ function caseInsensitiveCompare(a, b) {
|
|
|
211
237
|
function argumentsToValue(fn) {
|
|
212
238
|
return function (...args) { return fn.call(this, ...args.map(toValue)); };
|
|
213
239
|
}
|
|
214
|
-
function
|
|
215
|
-
return
|
|
240
|
+
function argumentsToNumber(fn) {
|
|
241
|
+
return function (...args) { return fn.call(this, ...args.map(toNumber)); };
|
|
216
242
|
}
|
|
217
243
|
/** Return an array containing unique elements from _array_. Works with nested arrays and objects. */
|
|
218
244
|
function* strictUniq(array) {
|
|
@@ -378,8 +404,8 @@ function assertEmpty(predicate, message = `unexpected ${JSON.stringify(predicate
|
|
|
378
404
|
}
|
|
379
405
|
|
|
380
406
|
class NullDrop extends Drop {
|
|
381
|
-
equals(value) {
|
|
382
|
-
return isNil(toValue(value));
|
|
407
|
+
*equals(value) {
|
|
408
|
+
return isNil(yield toValue(value));
|
|
383
409
|
}
|
|
384
410
|
gt() {
|
|
385
411
|
return false;
|
|
@@ -399,10 +425,10 @@ class NullDrop extends Drop {
|
|
|
399
425
|
}
|
|
400
426
|
|
|
401
427
|
class EmptyDrop extends Drop {
|
|
402
|
-
equals(value) {
|
|
428
|
+
*equals(value) {
|
|
403
429
|
if (value instanceof EmptyDrop)
|
|
404
430
|
return false;
|
|
405
|
-
value = toValue(value);
|
|
431
|
+
value = yield toValue(value);
|
|
406
432
|
if (isString(value) || isArray(value))
|
|
407
433
|
return value.length === 0;
|
|
408
434
|
if (isObject(value))
|
|
@@ -430,14 +456,14 @@ class EmptyDrop extends Drop {
|
|
|
430
456
|
}
|
|
431
457
|
|
|
432
458
|
class BlankDrop extends EmptyDrop {
|
|
433
|
-
equals(value) {
|
|
459
|
+
*equals(value) {
|
|
434
460
|
if (value === false)
|
|
435
461
|
return true;
|
|
436
|
-
if (isNil(toValue(value)))
|
|
462
|
+
if (isNil(yield toValue(value)))
|
|
437
463
|
return true;
|
|
438
464
|
if (isString(value))
|
|
439
465
|
return /^\s*$/.test(value);
|
|
440
|
-
return super.equals(value);
|
|
466
|
+
return yield super.equals(value);
|
|
441
467
|
}
|
|
442
468
|
static is(value) {
|
|
443
469
|
return value instanceof BlankDrop;
|
|
@@ -477,6 +503,50 @@ class ForloopDrop extends Drop {
|
|
|
477
503
|
}
|
|
478
504
|
}
|
|
479
505
|
|
|
506
|
+
class SimpleEmitter {
|
|
507
|
+
constructor() {
|
|
508
|
+
this.buffer = '';
|
|
509
|
+
}
|
|
510
|
+
write(html) {
|
|
511
|
+
this.buffer += stringify(html);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
class StreamedEmitter {
|
|
516
|
+
constructor() {
|
|
517
|
+
this.buffer = '';
|
|
518
|
+
this.stream = new PassThrough();
|
|
519
|
+
}
|
|
520
|
+
write(html) {
|
|
521
|
+
this.stream.write(stringify(html));
|
|
522
|
+
}
|
|
523
|
+
error(err) {
|
|
524
|
+
this.stream.emit('error', err);
|
|
525
|
+
}
|
|
526
|
+
end() {
|
|
527
|
+
this.stream.end();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
class KeepingTypeEmitter {
|
|
532
|
+
constructor() {
|
|
533
|
+
this.buffer = '';
|
|
534
|
+
}
|
|
535
|
+
write(html) {
|
|
536
|
+
html = toValue(html);
|
|
537
|
+
// This will only preserve the type if the value is isolated.
|
|
538
|
+
// I.E:
|
|
539
|
+
// {{ my-port }} -> 42
|
|
540
|
+
// {{ my-host }}:{{ my-port }} -> 'host:42'
|
|
541
|
+
if (typeof html !== 'string' && this.buffer === '') {
|
|
542
|
+
this.buffer = html;
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
this.buffer = stringify(this.buffer) + stringify(html);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
480
550
|
class BlockDrop extends Drop {
|
|
481
551
|
constructor(
|
|
482
552
|
// the block render from layout template
|
|
@@ -488,8 +558,10 @@ class BlockDrop extends Drop {
|
|
|
488
558
|
* Provide parent access in child block by
|
|
489
559
|
* {{ block.super }}
|
|
490
560
|
*/
|
|
491
|
-
super() {
|
|
492
|
-
|
|
561
|
+
*super() {
|
|
562
|
+
const emitter = new SimpleEmitter();
|
|
563
|
+
yield this.superBlockRender(emitter);
|
|
564
|
+
return emitter.buffer;
|
|
493
565
|
}
|
|
494
566
|
}
|
|
495
567
|
|
|
@@ -512,7 +584,16 @@ const literalValues = {
|
|
|
512
584
|
'blank': new BlankDrop()
|
|
513
585
|
};
|
|
514
586
|
|
|
587
|
+
// Tries are built once per input object and reused: the Tokenizer rebuilds them
|
|
588
|
+
// on every instantiation, but `input` (operators/literalValues) is a stable
|
|
589
|
+
// reference. WeakMap-keying by `input` lets short-lived operator objects (and
|
|
590
|
+
// their tries) be garbage collected. The returned trie is treated as read-only
|
|
591
|
+
// by callers (matchTrie only reads it); do not mutate it.
|
|
592
|
+
const trieCache = new WeakMap();
|
|
515
593
|
function createTrie(input) {
|
|
594
|
+
const cached = trieCache.get(input);
|
|
595
|
+
if (cached)
|
|
596
|
+
return cached;
|
|
516
597
|
const trie = {};
|
|
517
598
|
for (const [name, data] of Object.entries(input)) {
|
|
518
599
|
let node = trie;
|
|
@@ -527,6 +608,7 @@ function createTrie(input) {
|
|
|
527
608
|
node.data = data;
|
|
528
609
|
node.end = true;
|
|
529
610
|
}
|
|
611
|
+
trieCache.set(input, trie);
|
|
530
612
|
return trie;
|
|
531
613
|
}
|
|
532
614
|
|
|
@@ -566,6 +648,12 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
566
648
|
});
|
|
567
649
|
}
|
|
568
650
|
|
|
651
|
+
function toLiquidAsync(asyncFn, syncFn) {
|
|
652
|
+
const syncImpl = syncFn || asyncFn;
|
|
653
|
+
return (sync, ...args) => {
|
|
654
|
+
return sync ? syncImpl(...args) : asyncFn(...args);
|
|
655
|
+
};
|
|
656
|
+
}
|
|
569
657
|
// convert an async iterator to a Promise
|
|
570
658
|
function toPromise(val) {
|
|
571
659
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -576,7 +664,7 @@ function toPromise(val) {
|
|
|
576
664
|
let next = 'next';
|
|
577
665
|
do {
|
|
578
666
|
const state = val[next](value);
|
|
579
|
-
done = state.done;
|
|
667
|
+
done = !!state.done;
|
|
580
668
|
value = state.value;
|
|
581
669
|
next = 'next';
|
|
582
670
|
try {
|
|
@@ -602,7 +690,7 @@ function toValueSync(val) {
|
|
|
602
690
|
let next = 'next';
|
|
603
691
|
do {
|
|
604
692
|
const state = val[next](value);
|
|
605
|
-
done = state.done;
|
|
693
|
+
done = !!state.done;
|
|
606
694
|
value = state.value;
|
|
607
695
|
next = 'next';
|
|
608
696
|
if (isIterator(value)) {
|
|
@@ -632,12 +720,9 @@ function getDayOfYear(d) {
|
|
|
632
720
|
return num + d.getDate();
|
|
633
721
|
}
|
|
634
722
|
function getWeekOfYear(d, startDay) {
|
|
635
|
-
//
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
const jan1 = new Date(d.getFullYear(), 0, 1);
|
|
639
|
-
const then = (7 - jan1.getDay() + startDay);
|
|
640
|
-
return String(Math.floor((now - then) / 7) + 1);
|
|
723
|
+
// Days before the first startDay of the year belong to week 0
|
|
724
|
+
const daysSinceStartDay = (d.getDay() - startDay + 7) % 7;
|
|
725
|
+
return String(Math.floor((getDayOfYear(d) - 1 - daysSinceStartDay + 7) / 7));
|
|
641
726
|
}
|
|
642
727
|
function isLeapYear(d) {
|
|
643
728
|
const year = d.getFullYear();
|
|
@@ -655,10 +740,11 @@ function ordinal(d) {
|
|
|
655
740
|
}
|
|
656
741
|
}
|
|
657
742
|
function century(d) {
|
|
658
|
-
return
|
|
743
|
+
return Math.floor(d.getFullYear() / 100);
|
|
659
744
|
}
|
|
660
745
|
// default to 0
|
|
661
746
|
const padWidths = {
|
|
747
|
+
C: 2,
|
|
662
748
|
d: 2,
|
|
663
749
|
e: 2,
|
|
664
750
|
H: 2,
|
|
@@ -671,7 +757,9 @@ const padWidths = {
|
|
|
671
757
|
M: 2,
|
|
672
758
|
S: 2,
|
|
673
759
|
U: 2,
|
|
674
|
-
W: 2
|
|
760
|
+
W: 2,
|
|
761
|
+
y: 2,
|
|
762
|
+
Y: 4
|
|
675
763
|
};
|
|
676
764
|
const padSpaceChars = new Set('aAbBceklpP');
|
|
677
765
|
function getTimezoneOffset(d, opts) {
|
|
@@ -701,14 +789,16 @@ const formatCodes = {
|
|
|
701
789
|
m: (d) => d.getMonth() + 1,
|
|
702
790
|
M: (d) => d.getMinutes(),
|
|
703
791
|
N: (d, opts) => {
|
|
792
|
+
var _a;
|
|
704
793
|
const width = Number(opts.width) || 9;
|
|
705
|
-
const str = String(d.getMilliseconds()).slice(0, width);
|
|
794
|
+
const str = padStart(String(d.getMilliseconds()), 3, '0').slice(0, width);
|
|
795
|
+
(_a = opts.memoryLimit) === null || _a === void 0 ? void 0 : _a.use(width - str.length);
|
|
706
796
|
return padEnd(str, width, '0');
|
|
707
797
|
},
|
|
708
798
|
p: (d) => (d.getHours() < 12 ? 'AM' : 'PM'),
|
|
709
799
|
P: (d) => (d.getHours() < 12 ? 'am' : 'pm'),
|
|
710
800
|
q: (d) => ordinal(d),
|
|
711
|
-
s: (d) => Math.
|
|
801
|
+
s: (d) => Math.floor(d.dateValue() / 1000),
|
|
712
802
|
S: (d) => d.getSeconds(),
|
|
713
803
|
u: (d) => d.getDay() || 7,
|
|
714
804
|
U: (d) => getWeekOfYear(d, 0),
|
|
@@ -716,7 +806,7 @@ const formatCodes = {
|
|
|
716
806
|
W: (d) => getWeekOfYear(d, 1),
|
|
717
807
|
x: (d) => d.toLocaleDateString(),
|
|
718
808
|
X: (d) => d.toLocaleTimeString(),
|
|
719
|
-
y: (d) => d.getFullYear()
|
|
809
|
+
y: (d) => (d.getFullYear() % 100 + 100) % 100,
|
|
720
810
|
Y: (d) => d.getFullYear(),
|
|
721
811
|
z: getTimezoneOffset,
|
|
722
812
|
Z: (d, opts) => d.getTimeZoneName() || getTimezoneOffset(d, opts),
|
|
@@ -725,18 +815,18 @@ const formatCodes = {
|
|
|
725
815
|
'%': () => '%'
|
|
726
816
|
};
|
|
727
817
|
formatCodes.h = formatCodes.b;
|
|
728
|
-
function strftime(d, formatStr) {
|
|
818
|
+
function strftime(d, formatStr, memoryLimit) {
|
|
729
819
|
let output = '';
|
|
730
820
|
let remaining = formatStr;
|
|
731
821
|
let match;
|
|
732
822
|
while ((match = rFormat.exec(remaining))) {
|
|
733
823
|
output += remaining.slice(0, match.index);
|
|
734
824
|
remaining = remaining.slice(match.index + match[0].length);
|
|
735
|
-
output += format(d, match);
|
|
825
|
+
output += format(d, match, memoryLimit);
|
|
736
826
|
}
|
|
737
827
|
return output + remaining;
|
|
738
828
|
}
|
|
739
|
-
function format(d, match) {
|
|
829
|
+
function format(d, match, memoryLimit) {
|
|
740
830
|
const [input, flagStr = '', width, modifier, conversion] = match;
|
|
741
831
|
const convert = formatCodes[conversion];
|
|
742
832
|
if (!convert)
|
|
@@ -744,9 +834,9 @@ function format(d, match) {
|
|
|
744
834
|
const flags = {};
|
|
745
835
|
for (const flag of flagStr)
|
|
746
836
|
flags[flag] = true;
|
|
747
|
-
let ret = String(convert(d, { flags, width, modifier }));
|
|
837
|
+
let ret = String(convert(d, { flags, width, modifier, memoryLimit }));
|
|
748
838
|
let padChar = padSpaceChars.has(conversion) ? ' ' : '0';
|
|
749
|
-
let padWidth = width || padWidths[conversion] || 0;
|
|
839
|
+
let padWidth = Number(width) || padWidths[conversion] || 0;
|
|
750
840
|
if (flags['^'])
|
|
751
841
|
ret = ret.toUpperCase();
|
|
752
842
|
else if (flags['#'])
|
|
@@ -757,6 +847,9 @@ function format(d, match) {
|
|
|
757
847
|
padChar = '0';
|
|
758
848
|
if (flags['-'])
|
|
759
849
|
padWidth = 0;
|
|
850
|
+
memoryLimit === null || memoryLimit === void 0 ? void 0 : memoryLimit.use(Number(padWidth) - ret.length);
|
|
851
|
+
if (padChar === '0' && ret[0] === '-')
|
|
852
|
+
return '-' + padStart(ret.slice(1), padWidth - 1, padChar);
|
|
760
853
|
return padStart(ret, padWidth, padChar);
|
|
761
854
|
}
|
|
762
855
|
|
|
@@ -805,6 +898,15 @@ class LiquidDate {
|
|
|
805
898
|
getTime() {
|
|
806
899
|
return this.displayDate.getTime();
|
|
807
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* The underlying UTC timestamp in milliseconds, unaffected by the display
|
|
903
|
+
* timezone. Use this (not `getTime()`) for timezone-invariant values like
|
|
904
|
+
* `%s`: `getTime()` reads `displayDate`, which is deliberately shifted by
|
|
905
|
+
* the display timezone offset so wall-clock getters can delegate to Date.
|
|
906
|
+
*/
|
|
907
|
+
dateValue() {
|
|
908
|
+
return this.date.getTime();
|
|
909
|
+
}
|
|
808
910
|
getMilliseconds() {
|
|
809
911
|
return this.displayDate.getMilliseconds();
|
|
810
912
|
}
|
|
@@ -916,13 +1018,15 @@ class Limiter {
|
|
|
916
1018
|
this.limit = limit;
|
|
917
1019
|
}
|
|
918
1020
|
use(count) {
|
|
919
|
-
count
|
|
920
|
-
|
|
921
|
-
|
|
1021
|
+
if (+count > 0) {
|
|
1022
|
+
assert(this.base + +count <= this.limit, this.message);
|
|
1023
|
+
this.base += +count;
|
|
1024
|
+
}
|
|
922
1025
|
}
|
|
923
1026
|
check(count) {
|
|
924
|
-
count
|
|
925
|
-
|
|
1027
|
+
if (+count > 0) {
|
|
1028
|
+
assert(+count <= this.limit, this.message);
|
|
1029
|
+
}
|
|
926
1030
|
}
|
|
927
1031
|
}
|
|
928
1032
|
|
|
@@ -953,13 +1057,11 @@ class TagToken extends DelimitedToken {
|
|
|
953
1057
|
const { trimTagLeft, trimTagRight, tagDelimiterLeft, tagDelimiterRight } = options;
|
|
954
1058
|
const [valueBegin, valueEnd] = [begin + tagDelimiterLeft.length, end - tagDelimiterRight.length];
|
|
955
1059
|
super(TokenKind.Tag, [valueBegin, valueEnd], input, begin, end, trimTagLeft, trimTagRight, file);
|
|
956
|
-
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange);
|
|
1060
|
+
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange, options.groupedExpressions);
|
|
957
1061
|
this.name = this.tokenizer.readTagName();
|
|
958
1062
|
this.tokenizer.assert(this.name, `illegal tag syntax, tag name expected`);
|
|
959
1063
|
this.tokenizer.skipBlank();
|
|
960
|
-
|
|
961
|
-
get args() {
|
|
962
|
-
return this.tokenizer.input.slice(this.tokenizer.p, this.contentRange[1]);
|
|
1064
|
+
this.args = this.tokenizer.input.slice(this.tokenizer.p, this.contentRange[1]);
|
|
963
1065
|
}
|
|
964
1066
|
}
|
|
965
1067
|
|
|
@@ -1054,8 +1156,7 @@ class OperatorToken extends Token {
|
|
|
1054
1156
|
this.operator = this.getText();
|
|
1055
1157
|
}
|
|
1056
1158
|
getPrecedence() {
|
|
1057
|
-
|
|
1058
|
-
return key in operatorPrecedences ? operatorPrecedences[key] : 1;
|
|
1159
|
+
return this.operator in operatorPrecedences ? operatorPrecedences[this.operator] : 1;
|
|
1059
1160
|
}
|
|
1060
1161
|
}
|
|
1061
1162
|
|
|
@@ -1169,7 +1270,7 @@ class RangeToken extends Token {
|
|
|
1169
1270
|
class LiquidTagToken extends DelimitedToken {
|
|
1170
1271
|
constructor(input, begin, end, options, file) {
|
|
1171
1272
|
super(TokenKind.Tag, [begin, end], input, begin, end, false, false, file);
|
|
1172
|
-
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange);
|
|
1273
|
+
this.tokenizer = new Tokenizer(input, options.operators, file, this.contentRange, options.groupedExpressions);
|
|
1173
1274
|
this.name = this.tokenizer.readTagName();
|
|
1174
1275
|
this.tokenizer.assert(this.name, 'illegal liquid tag syntax');
|
|
1175
1276
|
this.tokenizer.skipBlank();
|
|
@@ -1205,50 +1306,6 @@ function getPerformance() {
|
|
|
1205
1306
|
polyfill;
|
|
1206
1307
|
}
|
|
1207
1308
|
|
|
1208
|
-
class SimpleEmitter {
|
|
1209
|
-
constructor() {
|
|
1210
|
-
this.buffer = '';
|
|
1211
|
-
}
|
|
1212
|
-
write(html) {
|
|
1213
|
-
this.buffer += stringify(html);
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
class StreamedEmitter {
|
|
1218
|
-
constructor() {
|
|
1219
|
-
this.buffer = '';
|
|
1220
|
-
this.stream = new PassThrough();
|
|
1221
|
-
}
|
|
1222
|
-
write(html) {
|
|
1223
|
-
this.stream.write(stringify(html));
|
|
1224
|
-
}
|
|
1225
|
-
error(err) {
|
|
1226
|
-
this.stream.emit('error', err);
|
|
1227
|
-
}
|
|
1228
|
-
end() {
|
|
1229
|
-
this.stream.end();
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
class KeepingTypeEmitter {
|
|
1234
|
-
constructor() {
|
|
1235
|
-
this.buffer = '';
|
|
1236
|
-
}
|
|
1237
|
-
write(html) {
|
|
1238
|
-
html = toValue(html);
|
|
1239
|
-
// This will only preserve the type if the value is isolated.
|
|
1240
|
-
// I.E:
|
|
1241
|
-
// {{ my-port }} -> 42
|
|
1242
|
-
// {{ my-host }}:{{ my-port }} -> 'host:42'
|
|
1243
|
-
if (typeof html !== 'string' && this.buffer === '') {
|
|
1244
|
-
this.buffer = html;
|
|
1245
|
-
}
|
|
1246
|
-
else {
|
|
1247
|
-
this.buffer = stringify(this.buffer) + stringify(html);
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
1309
|
class Render {
|
|
1253
1310
|
renderTemplatesToNodeStream(templates, ctx) {
|
|
1254
1311
|
const emitter = new StreamedEmitter();
|
|
@@ -1260,6 +1317,7 @@ class Render {
|
|
|
1260
1317
|
if (!emitter) {
|
|
1261
1318
|
emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter();
|
|
1262
1319
|
}
|
|
1320
|
+
ctx.renderLimit.check(getPerformance().now());
|
|
1263
1321
|
const errors = [];
|
|
1264
1322
|
for (const tpl of templates) {
|
|
1265
1323
|
ctx.renderLimit.check(getPerformance().now());
|
|
@@ -1286,6 +1344,33 @@ class Render {
|
|
|
1286
1344
|
}
|
|
1287
1345
|
}
|
|
1288
1346
|
|
|
1347
|
+
function isKeyValuePair(arr) {
|
|
1348
|
+
return isArray(arr);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
class Filter {
|
|
1352
|
+
constructor(token, options, liquid) {
|
|
1353
|
+
this.token = token;
|
|
1354
|
+
this.name = token.name;
|
|
1355
|
+
this.handler = isFunction(options)
|
|
1356
|
+
? options
|
|
1357
|
+
: (isFunction(options === null || options === void 0 ? void 0 : options.handler) ? options.handler : identify);
|
|
1358
|
+
this.raw = !isFunction(options) && !!(options === null || options === void 0 ? void 0 : options.raw);
|
|
1359
|
+
this.args = token.args;
|
|
1360
|
+
this.liquid = liquid;
|
|
1361
|
+
}
|
|
1362
|
+
*render(value, context) {
|
|
1363
|
+
const argv = [];
|
|
1364
|
+
for (const arg of this.args) {
|
|
1365
|
+
if (isKeyValuePair(arg))
|
|
1366
|
+
argv.push([arg[0], yield evalToken(arg[1], context)]);
|
|
1367
|
+
else
|
|
1368
|
+
argv.push(yield evalToken(arg, context));
|
|
1369
|
+
}
|
|
1370
|
+
return yield this.handler.apply({ context, token: this.token, liquid: this.liquid }, [value, ...argv]);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1289
1374
|
class Expression {
|
|
1290
1375
|
constructor(tokens) {
|
|
1291
1376
|
this.postfix = [...toPostfix(tokens)];
|
|
@@ -1316,6 +1401,11 @@ class Expression {
|
|
|
1316
1401
|
return !!this.postfix.length;
|
|
1317
1402
|
}
|
|
1318
1403
|
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Evaluate `token`, preserving Drops.
|
|
1406
|
+
* Operators use this so `Comparable` drops (`empty`, `nil`, `blank`) and custom drops
|
|
1407
|
+
* are compared as drops rather than as their `valueOf()` result.
|
|
1408
|
+
*/
|
|
1319
1409
|
function* evalToken(token, ctx, lenient = false) {
|
|
1320
1410
|
if (!token)
|
|
1321
1411
|
return;
|
|
@@ -1325,11 +1415,32 @@ function* evalToken(token, ctx, lenient = false) {
|
|
|
1325
1415
|
return yield evalPropertyAccessToken(token, ctx, lenient);
|
|
1326
1416
|
if (isRangeToken(token))
|
|
1327
1417
|
return yield evalRangeToken(token, ctx);
|
|
1418
|
+
if (isFilteredValueToken(token))
|
|
1419
|
+
return yield evalFilteredValueToken(token, ctx, lenient);
|
|
1420
|
+
}
|
|
1421
|
+
function* evalFilteredValueToken(token, ctx, lenient) {
|
|
1422
|
+
assert(ctx.liquid, 'FilteredValueToken evaluation requires liquid instance in context');
|
|
1423
|
+
lenient = lenient || (ctx.opts.lenientIf && token.filters.length > 0 && token.filters[0].name === 'default');
|
|
1424
|
+
let val = yield token.initial.evaluate(ctx, lenient);
|
|
1425
|
+
for (const filterToken of token.filters) {
|
|
1426
|
+
const filterImpl = ctx.liquid.filters[filterToken.name];
|
|
1427
|
+
assert(filterImpl || !ctx.liquid.options.strictFilters, () => `undefined filter: ${filterToken.name}`);
|
|
1428
|
+
const filter = new Filter(filterToken, filterImpl, ctx.liquid);
|
|
1429
|
+
val = yield filter.render(val, ctx);
|
|
1430
|
+
}
|
|
1431
|
+
return val;
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Evaluate `token` to the value filters and tags consume.
|
|
1435
|
+
* Awaits a promise returned by `Drop.valueOf()`.
|
|
1436
|
+
*/
|
|
1437
|
+
function* evalTokenValue(token, ctx, lenient = false) {
|
|
1438
|
+
return yield toValue(yield evalToken(token, ctx, lenient));
|
|
1328
1439
|
}
|
|
1329
1440
|
function* evalPropertyAccessToken(token, ctx, lenient) {
|
|
1330
1441
|
const props = [];
|
|
1331
1442
|
for (const prop of token.props) {
|
|
1332
|
-
props.push((yield
|
|
1443
|
+
props.push((yield evalTokenValue(prop, ctx, false)));
|
|
1333
1444
|
}
|
|
1334
1445
|
try {
|
|
1335
1446
|
if (token.variable) {
|
|
@@ -1350,8 +1461,8 @@ function evalQuotedToken(token) {
|
|
|
1350
1461
|
return token.content;
|
|
1351
1462
|
}
|
|
1352
1463
|
function* evalRangeToken(token, ctx) {
|
|
1353
|
-
const low = yield
|
|
1354
|
-
const high = yield
|
|
1464
|
+
const low = (yield evalTokenValue(token.lhs, ctx));
|
|
1465
|
+
const high = (yield evalTokenValue(token.rhs, ctx));
|
|
1355
1466
|
ctx.memoryLimit.use(high - low + 1);
|
|
1356
1467
|
return range(+low, +high + 1);
|
|
1357
1468
|
}
|
|
@@ -1386,67 +1497,75 @@ function isFalsy(val, ctx) {
|
|
|
1386
1497
|
}
|
|
1387
1498
|
|
|
1388
1499
|
const defaultOperators = {
|
|
1389
|
-
'==': equals,
|
|
1390
|
-
'!=': (l, r)
|
|
1391
|
-
'>': (l, r)
|
|
1500
|
+
'==': function* (l, r) { return yield equals(l, r); },
|
|
1501
|
+
'!=': function* (l, r) { return !(yield equals(l, r)); },
|
|
1502
|
+
'>': function* (l, r) {
|
|
1392
1503
|
if (isComparable(l))
|
|
1393
|
-
return l.gt(r);
|
|
1504
|
+
return yield l.gt(r);
|
|
1394
1505
|
if (isComparable(r))
|
|
1395
|
-
return r.lt(l);
|
|
1396
|
-
return toValue(l) > toValue(r);
|
|
1506
|
+
return yield r.lt(l);
|
|
1507
|
+
return (yield toValue(l)) > (yield toValue(r));
|
|
1397
1508
|
},
|
|
1398
|
-
'<': (l, r)
|
|
1509
|
+
'<': function* (l, r) {
|
|
1399
1510
|
if (isComparable(l))
|
|
1400
|
-
return l.lt(r);
|
|
1511
|
+
return yield l.lt(r);
|
|
1401
1512
|
if (isComparable(r))
|
|
1402
|
-
return r.gt(l);
|
|
1403
|
-
return toValue(l) < toValue(r);
|
|
1513
|
+
return yield r.gt(l);
|
|
1514
|
+
return (yield toValue(l)) < (yield toValue(r));
|
|
1404
1515
|
},
|
|
1405
|
-
'>=': (l, r)
|
|
1516
|
+
'>=': function* (l, r) {
|
|
1406
1517
|
if (isComparable(l))
|
|
1407
|
-
return l.geq(r);
|
|
1518
|
+
return yield l.geq(r);
|
|
1408
1519
|
if (isComparable(r))
|
|
1409
|
-
return r.leq(l);
|
|
1410
|
-
return toValue(l) >= toValue(r);
|
|
1520
|
+
return yield r.leq(l);
|
|
1521
|
+
return (yield toValue(l)) >= (yield toValue(r));
|
|
1411
1522
|
},
|
|
1412
|
-
'<=': (l, r)
|
|
1523
|
+
'<=': function* (l, r) {
|
|
1413
1524
|
if (isComparable(l))
|
|
1414
|
-
return l.leq(r);
|
|
1525
|
+
return yield l.leq(r);
|
|
1415
1526
|
if (isComparable(r))
|
|
1416
|
-
return r.geq(l);
|
|
1417
|
-
return toValue(l) <= toValue(r);
|
|
1527
|
+
return yield r.geq(l);
|
|
1528
|
+
return (yield toValue(l)) <= (yield toValue(r));
|
|
1418
1529
|
},
|
|
1419
|
-
'contains': (l, r)
|
|
1420
|
-
l = toValue(l);
|
|
1530
|
+
'contains': function* (l, r) {
|
|
1531
|
+
l = yield toValue(l);
|
|
1421
1532
|
if (isArray(l))
|
|
1422
|
-
return
|
|
1533
|
+
return yield arrayIncludes(l, r);
|
|
1423
1534
|
if (isFunction(l === null || l === void 0 ? void 0 : l.indexOf))
|
|
1424
|
-
return l.indexOf(toValue(r)) > -1;
|
|
1535
|
+
return l.indexOf(yield toValue(r)) > -1;
|
|
1425
1536
|
return false;
|
|
1426
1537
|
},
|
|
1427
|
-
'not': (v, ctx)
|
|
1428
|
-
'and': (l, r, ctx)
|
|
1429
|
-
'or': (l, r, ctx)
|
|
1538
|
+
'not': function* (v, ctx) { return isFalsy(yield toValue(v), ctx); },
|
|
1539
|
+
'and': function* (l, r, ctx) { return isTruthy(yield toValue(l), ctx) && isTruthy(yield toValue(r), ctx); },
|
|
1540
|
+
'or': function* (l, r, ctx) { return isTruthy(yield toValue(l), ctx) || isTruthy(yield toValue(r), ctx); }
|
|
1430
1541
|
};
|
|
1431
|
-
function equals(lhs, rhs) {
|
|
1542
|
+
function* equals(lhs, rhs) {
|
|
1432
1543
|
if (isComparable(lhs))
|
|
1433
|
-
return lhs.equals(rhs);
|
|
1544
|
+
return yield lhs.equals(rhs);
|
|
1434
1545
|
if (isComparable(rhs))
|
|
1435
|
-
return rhs.equals(lhs);
|
|
1436
|
-
lhs = toValue(lhs);
|
|
1437
|
-
rhs = toValue(rhs);
|
|
1546
|
+
return yield rhs.equals(lhs);
|
|
1547
|
+
lhs = yield toValue(lhs);
|
|
1548
|
+
rhs = yield toValue(rhs);
|
|
1438
1549
|
if (isArray(lhs)) {
|
|
1439
|
-
return isArray(rhs) && arrayEquals(lhs, rhs);
|
|
1550
|
+
return isArray(rhs) && (yield arrayEquals(lhs, rhs));
|
|
1440
1551
|
}
|
|
1441
1552
|
return lhs === rhs;
|
|
1442
1553
|
}
|
|
1443
|
-
function arrayEquals(lhs, rhs) {
|
|
1554
|
+
function* arrayEquals(lhs, rhs) {
|
|
1444
1555
|
if (lhs.length !== rhs.length)
|
|
1445
1556
|
return false;
|
|
1446
|
-
|
|
1557
|
+
for (let i = 0; i < lhs.length; i++) {
|
|
1558
|
+
if (!(yield equals(lhs[i], rhs[i])))
|
|
1559
|
+
return false;
|
|
1560
|
+
}
|
|
1561
|
+
return true;
|
|
1447
1562
|
}
|
|
1448
|
-
function arrayIncludes(arr, item) {
|
|
1449
|
-
|
|
1563
|
+
function* arrayIncludes(arr, item) {
|
|
1564
|
+
for (const value of arr) {
|
|
1565
|
+
if (yield equals(value, item))
|
|
1566
|
+
return true;
|
|
1567
|
+
}
|
|
1568
|
+
return false;
|
|
1450
1569
|
}
|
|
1451
1570
|
|
|
1452
1571
|
class Node {
|
|
@@ -1554,10 +1673,30 @@ function fallback(file) {
|
|
|
1554
1673
|
function dirname(filepath) {
|
|
1555
1674
|
return dirname$1(filepath);
|
|
1556
1675
|
}
|
|
1676
|
+
const realpathAsync = promisify(realpath);
|
|
1557
1677
|
function contains(root, file) {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1678
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1679
|
+
try {
|
|
1680
|
+
const realRoot = yield realpathAsync(root);
|
|
1681
|
+
const realFile = yield realpathAsync(file);
|
|
1682
|
+
const prefix = realRoot.endsWith(sep) ? realRoot : realRoot + sep;
|
|
1683
|
+
return realFile.startsWith(prefix);
|
|
1684
|
+
}
|
|
1685
|
+
catch (_a) {
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
function containsSync(root, file) {
|
|
1691
|
+
try {
|
|
1692
|
+
const realRoot = realpathSync(root);
|
|
1693
|
+
const realFile = realpathSync(file);
|
|
1694
|
+
const prefix = realRoot.endsWith(sep) ? realRoot : realRoot + sep;
|
|
1695
|
+
return realFile.startsWith(prefix);
|
|
1696
|
+
}
|
|
1697
|
+
catch (_a) {
|
|
1698
|
+
return false;
|
|
1699
|
+
}
|
|
1561
1700
|
}
|
|
1562
1701
|
|
|
1563
1702
|
var fs = /*#__PURE__*/Object.freeze({
|
|
@@ -1570,9 +1709,24 @@ var fs = /*#__PURE__*/Object.freeze({
|
|
|
1570
1709
|
fallback: fallback,
|
|
1571
1710
|
dirname: dirname,
|
|
1572
1711
|
contains: contains,
|
|
1712
|
+
containsSync: containsSync,
|
|
1573
1713
|
sep: sep
|
|
1574
1714
|
});
|
|
1575
1715
|
|
|
1716
|
+
function chargeJsonReplacerValue(memoryLimit, val) {
|
|
1717
|
+
if (typeof val === 'string') {
|
|
1718
|
+
memoryLimit.use(val.length);
|
|
1719
|
+
}
|
|
1720
|
+
else if (val === null || typeof val === 'number' || typeof val === 'boolean') {
|
|
1721
|
+
memoryLimit.use(JSON.stringify(val).length);
|
|
1722
|
+
}
|
|
1723
|
+
else if (Array.isArray(val)) {
|
|
1724
|
+
memoryLimit.use(val.length + 1);
|
|
1725
|
+
}
|
|
1726
|
+
else if (typeof val === 'object') {
|
|
1727
|
+
memoryLimit.use(2);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1576
1730
|
function defaultFilter(value, defaultValue, ...args) {
|
|
1577
1731
|
value = toValue(value);
|
|
1578
1732
|
if (isArray(value) || isString(value))
|
|
@@ -1582,19 +1736,29 @@ function defaultFilter(value, defaultValue, ...args) {
|
|
|
1582
1736
|
return isFalsy(value, this.context) ? defaultValue : value;
|
|
1583
1737
|
}
|
|
1584
1738
|
function json(value, space = 0) {
|
|
1585
|
-
|
|
1739
|
+
const memoryLimit = this.context.memoryLimit;
|
|
1740
|
+
return JSON.stringify(value, (_key, val) => {
|
|
1741
|
+
chargeJsonReplacerValue(memoryLimit, val);
|
|
1742
|
+
return val;
|
|
1743
|
+
}, space);
|
|
1586
1744
|
}
|
|
1587
1745
|
function inspect(value, space = 0) {
|
|
1746
|
+
const memoryLimit = this.context.memoryLimit;
|
|
1588
1747
|
const ancestors = [];
|
|
1589
1748
|
return JSON.stringify(value, function (_key, value) {
|
|
1590
|
-
if (typeof value !== 'object' || value === null)
|
|
1749
|
+
if (typeof value !== 'object' || value === null) {
|
|
1750
|
+
chargeJsonReplacerValue(memoryLimit, value);
|
|
1591
1751
|
return value;
|
|
1752
|
+
}
|
|
1592
1753
|
// `this` is the object that value is contained in, i.e., its direct parent.
|
|
1593
1754
|
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)
|
|
1594
1755
|
ancestors.pop();
|
|
1595
|
-
if (ancestors.includes(value))
|
|
1756
|
+
if (ancestors.includes(value)) {
|
|
1757
|
+
memoryLimit.use('[Circular]'.length);
|
|
1596
1758
|
return '[Circular]';
|
|
1759
|
+
}
|
|
1597
1760
|
ancestors.push(value);
|
|
1761
|
+
chargeJsonReplacerValue(memoryLimit, value);
|
|
1598
1762
|
return value;
|
|
1599
1763
|
}, space);
|
|
1600
1764
|
}
|
|
@@ -1649,10 +1813,33 @@ function newline_to_br(v) {
|
|
|
1649
1813
|
this.context.memoryLimit.use(str.length);
|
|
1650
1814
|
return str.replace(/\r?\n/gm, '<br />\n');
|
|
1651
1815
|
}
|
|
1816
|
+
// Raw-text blocks (HTML5) plus '<...>' as the catch-all kind; a regex
|
|
1817
|
+
// equivalent is O(n^2) in V8 on unclosed openers.
|
|
1652
1818
|
function strip_html(v) {
|
|
1653
1819
|
const str = stringify(v);
|
|
1654
1820
|
this.context.memoryLimit.use(str.length);
|
|
1655
|
-
|
|
1821
|
+
const blocks = new Map([['<script', '</script>'], ['<style', '</style>'], ['<!--', '-->'], ['<', '>']]);
|
|
1822
|
+
let out = '';
|
|
1823
|
+
let i = 0;
|
|
1824
|
+
while (i < str.length) {
|
|
1825
|
+
const lt = str.indexOf('<', i);
|
|
1826
|
+
if (lt < 0)
|
|
1827
|
+
return out + str.slice(i);
|
|
1828
|
+
out += str.slice(i, lt);
|
|
1829
|
+
for (const [opener, closer] of blocks) {
|
|
1830
|
+
if (!str.startsWith(opener, lt))
|
|
1831
|
+
continue;
|
|
1832
|
+
const e = str.indexOf(closer, lt + opener.length);
|
|
1833
|
+
if (e >= 0) {
|
|
1834
|
+
i = e + closer.length;
|
|
1835
|
+
break;
|
|
1836
|
+
}
|
|
1837
|
+
blocks.delete(opener);
|
|
1838
|
+
}
|
|
1839
|
+
if (i <= lt)
|
|
1840
|
+
return out + str.slice(lt);
|
|
1841
|
+
}
|
|
1842
|
+
return out;
|
|
1656
1843
|
}
|
|
1657
1844
|
|
|
1658
1845
|
var htmlFilters = /*#__PURE__*/Object.freeze({
|
|
@@ -1743,6 +1930,7 @@ const defaultOptions = {
|
|
|
1743
1930
|
globals: {},
|
|
1744
1931
|
keepOutputType: false,
|
|
1745
1932
|
operators: defaultOperators,
|
|
1933
|
+
groupedExpressions: false,
|
|
1746
1934
|
memoryLimit: Infinity,
|
|
1747
1935
|
parseLimit: Infinity,
|
|
1748
1936
|
renderLimit: Infinity
|
|
@@ -1839,7 +2027,7 @@ function trimRight(token, greedy) {
|
|
|
1839
2027
|
}
|
|
1840
2028
|
|
|
1841
2029
|
class Tokenizer {
|
|
1842
|
-
constructor(input, operators = defaultOptions.operators, file, range) {
|
|
2030
|
+
constructor(input, operators = defaultOptions.operators, file, range, groupedExpressions = false) {
|
|
1843
2031
|
this.input = input;
|
|
1844
2032
|
this.file = file;
|
|
1845
2033
|
this.rawBeginAt = -1;
|
|
@@ -1847,6 +2035,7 @@ class Tokenizer {
|
|
|
1847
2035
|
this.N = range ? range[1] : input.length;
|
|
1848
2036
|
this.opTrie = createTrie(operators);
|
|
1849
2037
|
this.literalTrie = createTrie(literalValues);
|
|
2038
|
+
this.groupedExpressions = groupedExpressions;
|
|
1850
2039
|
}
|
|
1851
2040
|
readExpression() {
|
|
1852
2041
|
return new Expression(this.readExpressionTokens());
|
|
@@ -1908,6 +2097,8 @@ class Tokenizer {
|
|
|
1908
2097
|
this.skipBlank();
|
|
1909
2098
|
if (this.end())
|
|
1910
2099
|
return null;
|
|
2100
|
+
if (this.peek() === ')' || this.peek() === ',')
|
|
2101
|
+
return null;
|
|
1911
2102
|
this.assert(this.read() === '|', `expected "|" before filter`);
|
|
1912
2103
|
const name = this.readIdentifier();
|
|
1913
2104
|
if (!name.size()) {
|
|
@@ -1922,10 +2113,10 @@ class Tokenizer {
|
|
|
1922
2113
|
const arg = this.readFilterArg();
|
|
1923
2114
|
arg && args.push(arg);
|
|
1924
2115
|
this.skipBlank();
|
|
1925
|
-
this.assert(this.end() || this.peek() === ',' || this.peek() === '|', () => `unexpected character ${this.snapshot()}`);
|
|
2116
|
+
this.assert(this.end() || this.peek() === ',' || this.peek() === '|' || this.peek() === ')', () => `unexpected character ${this.snapshot()}`);
|
|
1926
2117
|
} while (this.peek() === ',');
|
|
1927
2118
|
}
|
|
1928
|
-
else if (this.peek() === '|' || this.end()) ;
|
|
2119
|
+
else if (this.peek() === '|' || this.peek() === ')' || this.peek() === ',' || this.end()) ;
|
|
1929
2120
|
else {
|
|
1930
2121
|
throw this.error('expected ":" after filter name');
|
|
1931
2122
|
}
|
|
@@ -2131,7 +2322,10 @@ class Tokenizer {
|
|
|
2131
2322
|
readValue() {
|
|
2132
2323
|
this.skipBlank();
|
|
2133
2324
|
const begin = this.p;
|
|
2134
|
-
|
|
2325
|
+
let variable = this.readLiteral() || this.readQuoted() || this.readNumber();
|
|
2326
|
+
if (!variable && this.peek() === '(') {
|
|
2327
|
+
variable = this.readGroupOrRange();
|
|
2328
|
+
}
|
|
2135
2329
|
const props = this.readProperties(!variable);
|
|
2136
2330
|
if (!props.length)
|
|
2137
2331
|
return variable;
|
|
@@ -2210,17 +2404,30 @@ class Tokenizer {
|
|
|
2210
2404
|
this.p = end;
|
|
2211
2405
|
return literal;
|
|
2212
2406
|
}
|
|
2213
|
-
|
|
2407
|
+
readGroupOrRange() {
|
|
2214
2408
|
this.skipBlank();
|
|
2215
2409
|
const begin = this.p;
|
|
2216
2410
|
if (this.peek() !== '(')
|
|
2217
2411
|
return;
|
|
2218
2412
|
++this.p;
|
|
2219
2413
|
const lhs = this.readValueOrThrow();
|
|
2220
|
-
this.
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2414
|
+
this.skipBlank();
|
|
2415
|
+
if (this.peek() === '.' && this.peek(1) === '.') {
|
|
2416
|
+
this.p += 2;
|
|
2417
|
+
const rhs = this.readValueOrThrow();
|
|
2418
|
+
this.skipBlank();
|
|
2419
|
+
this.assert(this.read() === ')', 'invalid range syntax');
|
|
2420
|
+
return new RangeToken(this.input, begin, this.p, lhs, rhs, this.file);
|
|
2421
|
+
}
|
|
2422
|
+
if (this.groupedExpressions) {
|
|
2423
|
+
const initial = new Expression([lhs, ...this.readExpressionTokens()]);
|
|
2424
|
+
this.assert(initial.valid(), () => `invalid value expression: ${this.snapshot()}`);
|
|
2425
|
+
const filters = this.readFilters();
|
|
2426
|
+
this.skipBlank();
|
|
2427
|
+
this.assert(this.read() === ')', 'unbalanced parentheses');
|
|
2428
|
+
return new FilteredValueToken(initial, filters, this.input, begin, this.p, this.file);
|
|
2429
|
+
}
|
|
2430
|
+
throw this.error('invalid range syntax');
|
|
2224
2431
|
}
|
|
2225
2432
|
readValueOrThrow() {
|
|
2226
2433
|
const value = this.readValue();
|
|
@@ -2247,7 +2454,7 @@ class Tokenizer {
|
|
|
2247
2454
|
}
|
|
2248
2455
|
*readFileNameTemplate(options) {
|
|
2249
2456
|
const { outputDelimiterLeft } = options;
|
|
2250
|
-
const htmlStopStrings = [',', ' ', outputDelimiterLeft];
|
|
2457
|
+
const htmlStopStrings = [',', ' ', '\r', '\n', '\t', outputDelimiterLeft];
|
|
2251
2458
|
const htmlStopStringSet = new Set(htmlStopStrings);
|
|
2252
2459
|
// break on ',' and ' ', outputDelimiterLeft only stops HTML token
|
|
2253
2460
|
while (this.p < this.N && !htmlStopStringSet.has(this.peek())) {
|
|
@@ -2374,33 +2581,6 @@ function createTagClass(options) {
|
|
|
2374
2581
|
};
|
|
2375
2582
|
}
|
|
2376
2583
|
|
|
2377
|
-
function isKeyValuePair(arr) {
|
|
2378
|
-
return isArray(arr);
|
|
2379
|
-
}
|
|
2380
|
-
|
|
2381
|
-
class Filter {
|
|
2382
|
-
constructor(token, options, liquid) {
|
|
2383
|
-
this.token = token;
|
|
2384
|
-
this.name = token.name;
|
|
2385
|
-
this.handler = isFunction(options)
|
|
2386
|
-
? options
|
|
2387
|
-
: (isFunction(options === null || options === void 0 ? void 0 : options.handler) ? options.handler : identify);
|
|
2388
|
-
this.raw = !isFunction(options) && !!(options === null || options === void 0 ? void 0 : options.raw);
|
|
2389
|
-
this.args = token.args;
|
|
2390
|
-
this.liquid = liquid;
|
|
2391
|
-
}
|
|
2392
|
-
*render(value, context) {
|
|
2393
|
-
const argv = [];
|
|
2394
|
-
for (const arg of this.args) {
|
|
2395
|
-
if (isKeyValuePair(arg))
|
|
2396
|
-
argv.push([arg[0], yield evalToken(arg[1], context)]);
|
|
2397
|
-
else
|
|
2398
|
-
argv.push(yield evalToken(arg, context));
|
|
2399
|
-
}
|
|
2400
|
-
return yield this.handler.apply({ context, token: this.token, liquid: this.liquid }, [value, ...argv]);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
2584
|
class Value {
|
|
2405
2585
|
/**
|
|
2406
2586
|
* @param str the value to be valuated, eg.: "foobar" | truncate: 3
|
|
@@ -2408,7 +2588,7 @@ class Value {
|
|
|
2408
2588
|
constructor(input, liquid) {
|
|
2409
2589
|
this.filters = [];
|
|
2410
2590
|
const token = typeof input === 'string'
|
|
2411
|
-
? new Tokenizer(input, liquid.options.operators).readFilteredValue()
|
|
2591
|
+
? new Tokenizer(input, liquid.options.operators, undefined, undefined, liquid.options.groupedExpressions).readFilteredValue()
|
|
2412
2592
|
: input;
|
|
2413
2593
|
this.initial = token.initial;
|
|
2414
2594
|
this.filters = token.filters.map(token => new Filter(token, this.getFilter(liquid, token.name), liquid));
|
|
@@ -2432,7 +2612,7 @@ class Output extends TemplateImpl {
|
|
|
2432
2612
|
constructor(token, liquid) {
|
|
2433
2613
|
var _a;
|
|
2434
2614
|
super(token);
|
|
2435
|
-
const tokenizer = new Tokenizer(token.input, liquid.options.operators, token.file, token.contentRange);
|
|
2615
|
+
const tokenizer = new Tokenizer(token.input, liquid.options.operators, token.file, token.contentRange, liquid.options.groupedExpressions);
|
|
2436
2616
|
this.value = new Value(tokenizer.readFilteredValue(), liquid);
|
|
2437
2617
|
const filters = this.value.filters;
|
|
2438
2618
|
const outputEscape = liquid.options.outputEscape;
|
|
@@ -2442,7 +2622,7 @@ class Output extends TemplateImpl {
|
|
|
2442
2622
|
}
|
|
2443
2623
|
}
|
|
2444
2624
|
*render(ctx, emitter) {
|
|
2445
|
-
const val = yield this.value.value(ctx, false);
|
|
2625
|
+
const val = yield toValue(yield this.value.value(ctx, false));
|
|
2446
2626
|
emitter.write(val);
|
|
2447
2627
|
}
|
|
2448
2628
|
*arguments() {
|
|
@@ -2718,10 +2898,31 @@ function* extractValueTokenVariables(token) {
|
|
|
2718
2898
|
yield* extractValueTokenVariables(token.lhs);
|
|
2719
2899
|
yield* extractValueTokenVariables(token.rhs);
|
|
2720
2900
|
}
|
|
2901
|
+
else if (isFilteredValueToken(token)) {
|
|
2902
|
+
yield* extractGroupedExpressionTokenVariables(token);
|
|
2903
|
+
}
|
|
2721
2904
|
else if (isPropertyAccessToken(token)) {
|
|
2722
2905
|
yield extractPropertyAccessVariable(token);
|
|
2723
2906
|
}
|
|
2724
2907
|
}
|
|
2908
|
+
function* extractGroupedExpressionTokenVariables(token) {
|
|
2909
|
+
if (!isFilteredValueToken(token))
|
|
2910
|
+
return;
|
|
2911
|
+
for (const t of token.initial.postfix) {
|
|
2912
|
+
if (isValueToken(t))
|
|
2913
|
+
yield* extractValueTokenVariables(t);
|
|
2914
|
+
}
|
|
2915
|
+
for (const filter of token.filters) {
|
|
2916
|
+
for (const arg of filter.args) {
|
|
2917
|
+
if (isKeyValuePair(arg) && arg[1]) {
|
|
2918
|
+
yield* extractValueTokenVariables(arg[1]);
|
|
2919
|
+
}
|
|
2920
|
+
else if (isValueToken(arg)) {
|
|
2921
|
+
yield* extractValueTokenVariables(arg);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2725
2926
|
function extractPropertyAccessVariable(token) {
|
|
2726
2927
|
const segments = [];
|
|
2727
2928
|
// token is not guaranteed to have `file` set. We'll try to get it from a prop if not.
|
|
@@ -2798,44 +2999,47 @@ var LookupType;
|
|
|
2798
2999
|
})(LookupType || (LookupType = {}));
|
|
2799
3000
|
class Loader {
|
|
2800
3001
|
constructor(options) {
|
|
3002
|
+
var _a, _b, _c, _d;
|
|
2801
3003
|
this.options = options;
|
|
2802
3004
|
if (options.relativeReference) {
|
|
2803
3005
|
const sep = options.fs.sep;
|
|
2804
3006
|
assert(sep, '`fs.sep` is required for relative reference');
|
|
2805
|
-
const
|
|
2806
|
-
this.shouldLoadRelative = (referencedFile) =>
|
|
3007
|
+
const prefixes = ['.' + sep, '..' + sep, './', '../'];
|
|
3008
|
+
this.shouldLoadRelative = (referencedFile) => prefixes.some(prefix => referencedFile.startsWith(prefix));
|
|
2807
3009
|
}
|
|
2808
3010
|
else {
|
|
2809
3011
|
this.shouldLoadRelative = (_referencedFile) => false;
|
|
2810
3012
|
}
|
|
2811
|
-
|
|
3013
|
+
const fs = options.fs;
|
|
3014
|
+
this.contains = toLiquidAsync(((_a = fs.contains) === null || _a === void 0 ? void 0 : _a.bind(fs)) || (() => __awaiter(this, void 0, void 0, function* () { return true; })), ((_b = fs.containsSync) === null || _b === void 0 ? void 0 : _b.bind(fs)) || (() => true));
|
|
3015
|
+
this.exists = toLiquidAsync(((_c = fs.exists) === null || _c === void 0 ? void 0 : _c.bind(fs)) || (() => __awaiter(this, void 0, void 0, function* () { return false; })), (_d = fs.existsSync) === null || _d === void 0 ? void 0 : _d.bind(fs));
|
|
2812
3016
|
}
|
|
2813
3017
|
*lookup(file, type, sync, currentFile) {
|
|
2814
|
-
const { fs } = this.options;
|
|
2815
3018
|
const dirs = this.options[type];
|
|
2816
|
-
for (const filepath of this.candidates(file, dirs, currentFile
|
|
2817
|
-
|
|
3019
|
+
for (const filepath of this.candidates(file, dirs, currentFile)) {
|
|
3020
|
+
let allowed = false;
|
|
3021
|
+
for (const dir of dirs) {
|
|
3022
|
+
if (yield this.contains(!!sync, dir, filepath)) {
|
|
3023
|
+
allowed = true;
|
|
3024
|
+
break;
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
if (!allowed)
|
|
3028
|
+
continue;
|
|
3029
|
+
if (yield this.exists(!!sync, filepath))
|
|
2818
3030
|
return filepath;
|
|
2819
3031
|
}
|
|
2820
3032
|
throw this.lookupError(file, dirs);
|
|
2821
3033
|
}
|
|
2822
|
-
*candidates(file, dirs, currentFile
|
|
3034
|
+
*candidates(file, dirs, currentFile) {
|
|
2823
3035
|
const { fs, extname } = this.options;
|
|
2824
3036
|
if (this.shouldLoadRelative(file) && currentFile) {
|
|
2825
3037
|
const referenced = fs.resolve(this.dirname(currentFile), file, extname);
|
|
2826
|
-
|
|
2827
|
-
if (!enforceRoot || this.contains(dir, referenced)) {
|
|
2828
|
-
// the relatively referenced file is within one of root dirs
|
|
2829
|
-
yield referenced;
|
|
2830
|
-
break;
|
|
2831
|
-
}
|
|
2832
|
-
}
|
|
3038
|
+
yield referenced;
|
|
2833
3039
|
}
|
|
2834
3040
|
for (const dir of dirs) {
|
|
2835
3041
|
const referenced = fs.resolve(dir, file, extname);
|
|
2836
|
-
|
|
2837
|
-
yield referenced;
|
|
2838
|
-
}
|
|
3042
|
+
yield referenced;
|
|
2839
3043
|
}
|
|
2840
3044
|
if (fs.fallback !== undefined) {
|
|
2841
3045
|
const filepath = fs.fallback(file);
|
|
@@ -2858,17 +3062,19 @@ class Loader {
|
|
|
2858
3062
|
|
|
2859
3063
|
class Parser {
|
|
2860
3064
|
constructor(liquid) {
|
|
3065
|
+
var _a, _b;
|
|
2861
3066
|
this.liquid = liquid;
|
|
2862
3067
|
this.cache = this.liquid.options.cache;
|
|
2863
3068
|
this.fs = this.liquid.options.fs;
|
|
2864
3069
|
this.parseFile = this.cache ? this._parseFileCached : this._parseFile;
|
|
2865
3070
|
this.loader = new Loader(this.liquid.options);
|
|
2866
3071
|
this.parseLimit = new Limiter('parse length', liquid.options.parseLimit);
|
|
3072
|
+
this.readFile = toLiquidAsync(((_a = this.fs.readFile) === null || _a === void 0 ? void 0 : _a.bind(this.fs)) || (() => __awaiter(this, void 0, void 0, function* () { throw new Error('readFile not implemented'); })), (_b = this.fs.readFileSync) === null || _b === void 0 ? void 0 : _b.bind(this.fs));
|
|
2867
3073
|
}
|
|
2868
3074
|
parse(html, filepath) {
|
|
2869
3075
|
html = String(html);
|
|
2870
3076
|
this.parseLimit.use(html.length);
|
|
2871
|
-
const tokenizer = new Tokenizer(html, this.liquid.options.operators, filepath);
|
|
3077
|
+
const tokenizer = new Tokenizer(html, this.liquid.options.operators, filepath, undefined, this.liquid.options.groupedExpressions);
|
|
2872
3078
|
const tokens = tokenizer.readTopLevelTokens(this.liquid.options);
|
|
2873
3079
|
return this.parseTokens(tokens);
|
|
2874
3080
|
}
|
|
@@ -2934,7 +3140,7 @@ class Parser {
|
|
|
2934
3140
|
}
|
|
2935
3141
|
*_parseFile(file, sync, type = LookupType.Root, currentFile) {
|
|
2936
3142
|
const filepath = yield this.loader.lookup(file, type, sync, currentFile);
|
|
2937
|
-
return this.parse(
|
|
3143
|
+
return this.parse(yield this.readFile(!!sync, filepath), filepath);
|
|
2938
3144
|
}
|
|
2939
3145
|
}
|
|
2940
3146
|
|
|
@@ -2953,6 +3159,7 @@ var TokenKind;
|
|
|
2953
3159
|
TokenKind[TokenKind["Quoted"] = 1024] = "Quoted";
|
|
2954
3160
|
TokenKind[TokenKind["Operator"] = 2048] = "Operator";
|
|
2955
3161
|
TokenKind[TokenKind["FilteredValue"] = 4096] = "FilteredValue";
|
|
3162
|
+
TokenKind[TokenKind["GroupedExpression"] = 8192] = "GroupedExpression";
|
|
2956
3163
|
TokenKind[TokenKind["Delimited"] = 12] = "Delimited";
|
|
2957
3164
|
})(TokenKind || (TokenKind = {}));
|
|
2958
3165
|
|
|
@@ -2989,9 +3196,12 @@ function isWordToken(val) {
|
|
|
2989
3196
|
function isRangeToken(val) {
|
|
2990
3197
|
return getKind(val) === TokenKind.Range;
|
|
2991
3198
|
}
|
|
3199
|
+
function isFilteredValueToken(val) {
|
|
3200
|
+
return getKind(val) === TokenKind.FilteredValue;
|
|
3201
|
+
}
|
|
2992
3202
|
function isValueToken(val) {
|
|
2993
|
-
// valueTokenBitMask = TokenKind.Number | TokenKind.Literal | TokenKind.Quoted | TokenKind.PropertyAccess | TokenKind.Range
|
|
2994
|
-
return (getKind(val) &
|
|
3203
|
+
// valueTokenBitMask = TokenKind.Number | TokenKind.Literal | TokenKind.Quoted | TokenKind.PropertyAccess | TokenKind.Range | TokenKind.FilteredValue
|
|
3204
|
+
return (getKind(val) & 5763) > 0;
|
|
2995
3205
|
}
|
|
2996
3206
|
function getKind(val) {
|
|
2997
3207
|
return val ? val.kind : -1;
|
|
@@ -3010,17 +3220,25 @@ var typeGuards = /*#__PURE__*/Object.freeze({
|
|
|
3010
3220
|
isPropertyAccessToken: isPropertyAccessToken,
|
|
3011
3221
|
isWordToken: isWordToken,
|
|
3012
3222
|
isRangeToken: isRangeToken,
|
|
3223
|
+
isFilteredValueToken: isFilteredValueToken,
|
|
3013
3224
|
isValueToken: isValueToken
|
|
3014
3225
|
});
|
|
3015
3226
|
|
|
3227
|
+
function createScope(from) {
|
|
3228
|
+
const scope = Object.create(null);
|
|
3229
|
+
if (from)
|
|
3230
|
+
Object.assign(scope, from);
|
|
3231
|
+
return scope;
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3016
3234
|
class Context {
|
|
3017
|
-
constructor(env = {}, opts = defaultOptions, renderOptions = {}, { memoryLimit, renderLimit } = {}) {
|
|
3235
|
+
constructor(env = {}, opts = defaultOptions, renderOptions = {}, { memoryLimit, renderLimit, liquid } = {}) {
|
|
3018
3236
|
var _a, _b, _c, _d, _e;
|
|
3019
3237
|
/**
|
|
3020
3238
|
* insert a Context-level empty scope,
|
|
3021
3239
|
* for tags like `{% capture %}` `{% assign %}` to operate
|
|
3022
3240
|
*/
|
|
3023
|
-
this.scopes = [
|
|
3241
|
+
this.scopes = [createScope()];
|
|
3024
3242
|
this.registers = {};
|
|
3025
3243
|
this.breakCalled = false;
|
|
3026
3244
|
this.continueCalled = false;
|
|
@@ -3032,9 +3250,10 @@ class Context {
|
|
|
3032
3250
|
this.ownPropertyOnly = (_c = renderOptions.ownPropertyOnly) !== null && _c !== void 0 ? _c : opts.ownPropertyOnly;
|
|
3033
3251
|
this.memoryLimit = memoryLimit !== null && memoryLimit !== void 0 ? memoryLimit : new Limiter('memory alloc', (_d = renderOptions.memoryLimit) !== null && _d !== void 0 ? _d : opts.memoryLimit);
|
|
3034
3252
|
this.renderLimit = renderLimit !== null && renderLimit !== void 0 ? renderLimit : new Limiter('template render', getPerformance().now() + ((_e = renderOptions.renderLimit) !== null && _e !== void 0 ? _e : opts.renderLimit));
|
|
3253
|
+
this.liquid = liquid;
|
|
3035
3254
|
}
|
|
3036
|
-
getRegister(key) {
|
|
3037
|
-
return (this.registers[key] = this.registers[key] ||
|
|
3255
|
+
getRegister(key, defaultValue = undefined) {
|
|
3256
|
+
return (this.registers[key] = this.registers[key] || defaultValue);
|
|
3038
3257
|
}
|
|
3039
3258
|
setRegister(key, value) {
|
|
3040
3259
|
return (this.registers[key] = value);
|
|
@@ -3072,7 +3291,7 @@ class Context {
|
|
|
3072
3291
|
if (isString(paths))
|
|
3073
3292
|
paths = paths.split('.');
|
|
3074
3293
|
for (let i = 0; i < paths.length; i++) {
|
|
3075
|
-
scope = yield readProperty(scope, paths[i]
|
|
3294
|
+
scope = yield this.readProperty(scope, paths[i]);
|
|
3076
3295
|
if (strictVariables && isUndefined(scope)) {
|
|
3077
3296
|
throw new InternalUndefinedVariableError(paths.slice(0, i + 1).join('.'));
|
|
3078
3297
|
}
|
|
@@ -3092,10 +3311,12 @@ class Context {
|
|
|
3092
3311
|
return new Context(scope, this.opts, {
|
|
3093
3312
|
sync: this.sync,
|
|
3094
3313
|
globals: this.globals,
|
|
3095
|
-
strictVariables: this.strictVariables
|
|
3314
|
+
strictVariables: this.strictVariables,
|
|
3315
|
+
ownPropertyOnly: this.ownPropertyOnly
|
|
3096
3316
|
}, {
|
|
3097
3317
|
renderLimit: this.renderLimit,
|
|
3098
|
-
memoryLimit: this.memoryLimit
|
|
3318
|
+
memoryLimit: this.memoryLimit,
|
|
3319
|
+
liquid: this.liquid
|
|
3099
3320
|
});
|
|
3100
3321
|
}
|
|
3101
3322
|
findScope(key) {
|
|
@@ -3108,41 +3329,41 @@ class Context {
|
|
|
3108
3329
|
return this.environments;
|
|
3109
3330
|
return this.globals;
|
|
3110
3331
|
}
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
return
|
|
3130
|
-
|
|
3332
|
+
readProperty(obj, key) {
|
|
3333
|
+
obj = toLiquid(obj);
|
|
3334
|
+
key = toValue(key);
|
|
3335
|
+
if (isNil(obj))
|
|
3336
|
+
return obj;
|
|
3337
|
+
if (isArray(obj) && isNumber(key))
|
|
3338
|
+
return readArrayElement(obj, key, this.ownPropertyOnly);
|
|
3339
|
+
const value = readJSProperty(obj, key, this.ownPropertyOnly);
|
|
3340
|
+
if (value === undefined && obj instanceof Drop)
|
|
3341
|
+
return obj.liquidMethodMissing(key, this);
|
|
3342
|
+
if (isFunction(value))
|
|
3343
|
+
return value.call(obj);
|
|
3344
|
+
if (key === 'size')
|
|
3345
|
+
return readSize(obj);
|
|
3346
|
+
else if (key === 'first')
|
|
3347
|
+
return readFirst(obj, this.ownPropertyOnly);
|
|
3348
|
+
else if (key === 'last')
|
|
3349
|
+
return readLast(obj, this.ownPropertyOnly);
|
|
3350
|
+
return value;
|
|
3351
|
+
}
|
|
3131
3352
|
}
|
|
3132
3353
|
function readJSProperty(obj, key, ownPropertyOnly) {
|
|
3133
3354
|
if (ownPropertyOnly && !hasOwnProperty.call(obj, key) && !(obj instanceof Drop))
|
|
3134
3355
|
return undefined;
|
|
3135
3356
|
return obj[key];
|
|
3136
3357
|
}
|
|
3137
|
-
function readFirst(obj) {
|
|
3358
|
+
function readFirst(obj, ownPropertyOnly) {
|
|
3138
3359
|
if (isArray(obj))
|
|
3139
|
-
return obj
|
|
3140
|
-
return obj
|
|
3360
|
+
return readArrayElement(obj, 0, ownPropertyOnly);
|
|
3361
|
+
return readJSProperty(obj, 'first', ownPropertyOnly);
|
|
3141
3362
|
}
|
|
3142
|
-
function readLast(obj) {
|
|
3363
|
+
function readLast(obj, ownPropertyOnly) {
|
|
3143
3364
|
if (isArray(obj))
|
|
3144
|
-
return obj
|
|
3145
|
-
return obj
|
|
3365
|
+
return readArrayElement(obj, -1, ownPropertyOnly);
|
|
3366
|
+
return readJSProperty(obj, 'last', ownPropertyOnly);
|
|
3146
3367
|
}
|
|
3147
3368
|
function readSize(obj) {
|
|
3148
3369
|
if (hasOwnProperty.call(obj, 'size') || obj['size'] !== undefined)
|
|
@@ -3161,25 +3382,28 @@ var BlockMode;
|
|
|
3161
3382
|
BlockMode[BlockMode["STORE"] = 1] = "STORE";
|
|
3162
3383
|
})(BlockMode || (BlockMode = {}));
|
|
3163
3384
|
|
|
3164
|
-
const abs =
|
|
3165
|
-
const at_least =
|
|
3166
|
-
const at_most =
|
|
3167
|
-
const ceil =
|
|
3168
|
-
const divided_by =
|
|
3169
|
-
const floor =
|
|
3170
|
-
const minus =
|
|
3171
|
-
const
|
|
3172
|
-
const
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
return Math.round(v * amp) / amp;
|
|
3385
|
+
const abs = argumentsToNumber(Math.abs);
|
|
3386
|
+
const at_least = argumentsToNumber(Math.max);
|
|
3387
|
+
const at_most = argumentsToNumber(Math.min);
|
|
3388
|
+
const ceil = argumentsToNumber(Math.ceil);
|
|
3389
|
+
const divided_by = argumentsToNumber((dividend, divisor, integerArithmetic = false) => integerArithmetic ? Math.floor(dividend / divisor) : dividend / divisor);
|
|
3390
|
+
const floor = argumentsToNumber(Math.floor);
|
|
3391
|
+
const minus = argumentsToNumber((v, arg) => v - arg);
|
|
3392
|
+
const plus = argumentsToNumber((lhs, rhs) => lhs + rhs);
|
|
3393
|
+
const modulo = argumentsToNumber((v, arg) => ((v % arg) + arg) % arg);
|
|
3394
|
+
const times = argumentsToNumber((v, arg) => v * arg);
|
|
3395
|
+
function shiftDecimal(n, exponent) {
|
|
3396
|
+
const [mantissa, power = '0'] = String(n).split('e');
|
|
3397
|
+
return Number(`${mantissa}e${Number(power) + exponent}`);
|
|
3178
3398
|
}
|
|
3179
|
-
function
|
|
3180
|
-
v =
|
|
3181
|
-
arg =
|
|
3182
|
-
|
|
3399
|
+
function round(v, arg = 0) {
|
|
3400
|
+
v = toNumber(v);
|
|
3401
|
+
arg = toNumber(arg);
|
|
3402
|
+
const scaled = shiftDecimal(Math.abs(v), arg);
|
|
3403
|
+
if (!(scaled <= Number.MAX_SAFE_INTEGER))
|
|
3404
|
+
return v;
|
|
3405
|
+
const rounded = shiftDecimal(Math.round(scaled), -arg);
|
|
3406
|
+
return v < 0 ? -rounded : rounded;
|
|
3183
3407
|
}
|
|
3184
3408
|
|
|
3185
3409
|
var mathFilters = /*#__PURE__*/Object.freeze({
|
|
@@ -3191,13 +3415,13 @@ var mathFilters = /*#__PURE__*/Object.freeze({
|
|
|
3191
3415
|
divided_by: divided_by,
|
|
3192
3416
|
floor: floor,
|
|
3193
3417
|
minus: minus,
|
|
3418
|
+
plus: plus,
|
|
3194
3419
|
modulo: modulo,
|
|
3195
3420
|
times: times,
|
|
3196
|
-
round: round
|
|
3197
|
-
plus: plus
|
|
3421
|
+
round: round
|
|
3198
3422
|
});
|
|
3199
3423
|
|
|
3200
|
-
const url_decode = (x) => decodeURIComponent(stringify(x)
|
|
3424
|
+
const url_decode = (x) => decodeURIComponent(stringify(x).replace(/\+/g, ' '));
|
|
3201
3425
|
const url_encode = (x) => encodeURIComponent(stringify(x)).replace(/%20/g, '+');
|
|
3202
3426
|
const cgi_escape = (x) => encodeURIComponent(stringify(x))
|
|
3203
3427
|
.replace(/%20/g, '+')
|
|
@@ -3255,18 +3479,24 @@ var urlFilters = /*#__PURE__*/Object.freeze({
|
|
|
3255
3479
|
const join = argumentsToValue(function (v, arg) {
|
|
3256
3480
|
const array = toArray(v);
|
|
3257
3481
|
const sep = isNil(arg) ? ' ' : stringify(arg);
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3482
|
+
let outputSize = sep.length * Math.max(array.length - 1, 0);
|
|
3483
|
+
for (let i = 0; i < array.length; i++)
|
|
3484
|
+
outputSize += String(array[i]).length;
|
|
3485
|
+
this.context.memoryLimit.use(outputSize);
|
|
3486
|
+
return Array.prototype.join.call(array, sep);
|
|
3487
|
+
});
|
|
3488
|
+
const last = argumentsToValue(function (v) {
|
|
3489
|
+
return isArrayLike(v) ? readArrayElement(v, -1, this.context.ownPropertyOnly) : '';
|
|
3490
|
+
});
|
|
3491
|
+
const first = argumentsToValue(function (v) {
|
|
3492
|
+
return isArrayLike(v) ? readArrayElement(v, 0, this.context.ownPropertyOnly) : '';
|
|
3261
3493
|
});
|
|
3262
|
-
const last$1 = argumentsToValue((v) => isArrayLike(v) ? last(v) : '');
|
|
3263
|
-
const first = argumentsToValue((v) => isArrayLike(v) ? v[0] : '');
|
|
3264
3494
|
const reverse = argumentsToValue(function (v) {
|
|
3265
3495
|
const array = toArray(v);
|
|
3266
3496
|
this.context.memoryLimit.use(array.length);
|
|
3267
3497
|
return [...array].reverse();
|
|
3268
3498
|
});
|
|
3269
|
-
function*
|
|
3499
|
+
function* sortBy(arr, property, comparator) {
|
|
3270
3500
|
const values = [];
|
|
3271
3501
|
const array = toArray(arr);
|
|
3272
3502
|
this.context.memoryLimit.use(array.length);
|
|
@@ -3276,20 +3506,13 @@ function* sort(arr, property) {
|
|
|
3276
3506
|
property ? yield this.context._getFromScope(item, stringify(property).split('.'), false) : item
|
|
3277
3507
|
]);
|
|
3278
3508
|
}
|
|
3279
|
-
return values.sort((lhs, rhs) =>
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
const propertyString = stringify(property);
|
|
3287
|
-
const compare = property === undefined
|
|
3288
|
-
? caseInsensitiveCompare
|
|
3289
|
-
: (lhs, rhs) => caseInsensitiveCompare(lhs[propertyString], rhs[propertyString]);
|
|
3290
|
-
const array = toArray(input);
|
|
3291
|
-
this.context.memoryLimit.use(array.length);
|
|
3292
|
-
return [...array].sort(compare);
|
|
3509
|
+
return values.sort((lhs, rhs) => comparator(lhs[1], rhs[1])).map(tuple => tuple[0]);
|
|
3510
|
+
}
|
|
3511
|
+
function* sort(arr, property) {
|
|
3512
|
+
return yield* sortBy.call(this, arr, property, orderedCompare);
|
|
3513
|
+
}
|
|
3514
|
+
function* sort_natural(arr, property) {
|
|
3515
|
+
return yield* sortBy.call(this, arr, property, caseInsensitiveCompare);
|
|
3293
3516
|
}
|
|
3294
3517
|
const size = (v) => (v && v.length) || 0;
|
|
3295
3518
|
function* map(arr, property) {
|
|
@@ -3313,13 +3536,13 @@ function* sum(arr, property) {
|
|
|
3313
3536
|
function compact(arr) {
|
|
3314
3537
|
const array = toArray(arr);
|
|
3315
3538
|
this.context.memoryLimit.use(array.length);
|
|
3316
|
-
return
|
|
3539
|
+
return Array.prototype.filter.call(array, x => !isNil(toValue(x)));
|
|
3317
3540
|
}
|
|
3318
3541
|
function concat(v, arg = []) {
|
|
3319
3542
|
const lhs = toArray(v);
|
|
3320
3543
|
const rhs = toArray(arg);
|
|
3321
3544
|
this.context.memoryLimit.use(lhs.length + rhs.length);
|
|
3322
|
-
return
|
|
3545
|
+
return Array.prototype.concat.call(lhs, rhs);
|
|
3323
3546
|
}
|
|
3324
3547
|
function push(v, arg) {
|
|
3325
3548
|
return concat.call(this, v, [arg]);
|
|
@@ -3332,7 +3555,9 @@ function unshift(v, arg) {
|
|
|
3332
3555
|
return clone;
|
|
3333
3556
|
}
|
|
3334
3557
|
function pop(v) {
|
|
3335
|
-
const
|
|
3558
|
+
const array = toArray(v);
|
|
3559
|
+
this.context.memoryLimit.use(array.length);
|
|
3560
|
+
const clone = [...array];
|
|
3336
3561
|
clone.pop();
|
|
3337
3562
|
return clone;
|
|
3338
3563
|
}
|
|
@@ -3349,39 +3574,65 @@ function slice(v, begin, length = 1) {
|
|
|
3349
3574
|
return [];
|
|
3350
3575
|
if (!isArray(v))
|
|
3351
3576
|
v = stringify(v);
|
|
3352
|
-
begin = begin < 0 ? v.length + begin : begin;
|
|
3577
|
+
begin = begin < 0 ? (isArray(v) ? v.length : codePointLength(v)) + begin : begin;
|
|
3578
|
+
if (begin < 0 || length < 0)
|
|
3579
|
+
return isArray(v) ? [] : '';
|
|
3353
3580
|
this.context.memoryLimit.use(length);
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3581
|
+
if (isArray(v))
|
|
3582
|
+
return Array.prototype.slice.call(v, begin, begin + length);
|
|
3583
|
+
const start = advanceCodePoints(v, 0, begin);
|
|
3584
|
+
return v.slice(start, advanceCodePoints(v, start, length));
|
|
3585
|
+
}
|
|
3586
|
+
function* matches(value, expected) {
|
|
3587
|
+
if (this.context.opts.jekyllWhere) {
|
|
3588
|
+
if (EmptyDrop.is(expected))
|
|
3589
|
+
return yield equals(value, expected);
|
|
3590
|
+
if (isArray(value))
|
|
3591
|
+
return yield arrayIncludes(value, expected);
|
|
3592
|
+
return yield equals(value, expected);
|
|
3593
|
+
}
|
|
3594
|
+
if (expected === undefined)
|
|
3595
|
+
return isTruthy(value, this.context);
|
|
3596
|
+
return yield equals(value, expected);
|
|
3597
|
+
}
|
|
3598
|
+
function* filter(include, arr, property, expected) {
|
|
3358
3599
|
arr = toArray(arr);
|
|
3359
3600
|
this.context.memoryLimit.use(arr.length);
|
|
3360
3601
|
const token = new Tokenizer(stringify(property)).readScopeValue();
|
|
3602
|
+
const result = [];
|
|
3361
3603
|
for (const item of arr) {
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
return arr.filter((_, i) => {
|
|
3368
|
-
if (expected === undefined)
|
|
3369
|
-
return isTruthy(values[i], this.context);
|
|
3370
|
-
return matcher(values[i]);
|
|
3371
|
-
});
|
|
3604
|
+
const value = yield evalToken(token, this.context.spawn(item));
|
|
3605
|
+
if ((yield matches.call(this, value, expected)) === include)
|
|
3606
|
+
result.push(item);
|
|
3607
|
+
}
|
|
3608
|
+
return result;
|
|
3372
3609
|
}
|
|
3373
|
-
function*
|
|
3610
|
+
function* filter_exp(include, arr, itemName, exp) {
|
|
3374
3611
|
const filtered = [];
|
|
3375
3612
|
const keyTemplate = new Value(stringify(exp), this.liquid);
|
|
3376
3613
|
const array = toArray(arr);
|
|
3377
3614
|
this.context.memoryLimit.use(array.length);
|
|
3378
3615
|
for (const item of array) {
|
|
3379
|
-
|
|
3380
|
-
|
|
3616
|
+
this.context.push({ [itemName]: item });
|
|
3617
|
+
const value = yield keyTemplate.value(this.context);
|
|
3618
|
+
this.context.pop();
|
|
3619
|
+
if (value === include)
|
|
3381
3620
|
filtered.push(item);
|
|
3382
3621
|
}
|
|
3383
3622
|
return filtered;
|
|
3384
3623
|
}
|
|
3624
|
+
function* where(arr, property, expected) {
|
|
3625
|
+
return yield* filter.call(this, true, arr, property, expected);
|
|
3626
|
+
}
|
|
3627
|
+
function* reject(arr, property, expected) {
|
|
3628
|
+
return yield* filter.call(this, false, arr, property, expected);
|
|
3629
|
+
}
|
|
3630
|
+
function* where_exp(arr, itemName, exp) {
|
|
3631
|
+
return yield* filter_exp.call(this, true, arr, itemName, exp);
|
|
3632
|
+
}
|
|
3633
|
+
function* reject_exp(arr, itemName, exp) {
|
|
3634
|
+
return yield* filter_exp.call(this, false, arr, itemName, exp);
|
|
3635
|
+
}
|
|
3385
3636
|
function* group_by(arr, property) {
|
|
3386
3637
|
const map = new Map();
|
|
3387
3638
|
arr = toEnumerable(arr);
|
|
@@ -3401,31 +3652,59 @@ function* group_by_exp(arr, itemName, exp) {
|
|
|
3401
3652
|
arr = toEnumerable(arr);
|
|
3402
3653
|
this.context.memoryLimit.use(arr.length);
|
|
3403
3654
|
for (const item of arr) {
|
|
3404
|
-
|
|
3655
|
+
this.context.push({ [itemName]: item });
|
|
3656
|
+
const key = yield keyTemplate.value(this.context);
|
|
3657
|
+
this.context.pop();
|
|
3405
3658
|
if (!map.has(key))
|
|
3406
3659
|
map.set(key, []);
|
|
3407
3660
|
map.get(key).push(item);
|
|
3408
3661
|
}
|
|
3409
3662
|
return [...map.entries()].map(([name, items]) => ({ name, items }));
|
|
3410
3663
|
}
|
|
3411
|
-
function*
|
|
3664
|
+
function* search(arr, property, expected) {
|
|
3412
3665
|
const token = new Tokenizer(stringify(property)).readScopeValue();
|
|
3413
3666
|
const array = toArray(arr);
|
|
3414
|
-
for (
|
|
3415
|
-
const value = yield evalToken(token, this.context.spawn(
|
|
3416
|
-
if (
|
|
3417
|
-
return
|
|
3667
|
+
for (let index = 0; index < array.length; index++) {
|
|
3668
|
+
const value = yield evalToken(token, this.context.spawn(array[index]));
|
|
3669
|
+
if (yield matches.call(this, value, expected))
|
|
3670
|
+
return [index, array[index]];
|
|
3418
3671
|
}
|
|
3419
3672
|
}
|
|
3420
|
-
function*
|
|
3673
|
+
function* search_exp(arr, itemName, exp) {
|
|
3421
3674
|
const predicate = new Value(stringify(exp), this.liquid);
|
|
3422
3675
|
const array = toArray(arr);
|
|
3423
|
-
for (
|
|
3424
|
-
|
|
3676
|
+
for (let index = 0; index < array.length; index++) {
|
|
3677
|
+
this.context.push({ [itemName]: array[index] });
|
|
3678
|
+
const value = yield predicate.value(this.context);
|
|
3679
|
+
this.context.pop();
|
|
3425
3680
|
if (value)
|
|
3426
|
-
return
|
|
3681
|
+
return [index, array[index]];
|
|
3427
3682
|
}
|
|
3428
3683
|
}
|
|
3684
|
+
function* has(arr, property, expected) {
|
|
3685
|
+
const result = yield* search.call(this, arr, property, expected);
|
|
3686
|
+
return !!result;
|
|
3687
|
+
}
|
|
3688
|
+
function* has_exp(arr, itemName, exp) {
|
|
3689
|
+
const result = yield* search_exp.call(this, arr, itemName, exp);
|
|
3690
|
+
return !!result;
|
|
3691
|
+
}
|
|
3692
|
+
function* find_index(arr, property, expected) {
|
|
3693
|
+
const result = yield* search.call(this, arr, property, expected);
|
|
3694
|
+
return result ? result[0] : undefined;
|
|
3695
|
+
}
|
|
3696
|
+
function* find_index_exp(arr, itemName, exp) {
|
|
3697
|
+
const result = yield* search_exp.call(this, arr, itemName, exp);
|
|
3698
|
+
return result ? result[0] : undefined;
|
|
3699
|
+
}
|
|
3700
|
+
function* find(arr, property, expected) {
|
|
3701
|
+
const result = yield* search.call(this, arr, property, expected);
|
|
3702
|
+
return result ? result[1] : undefined;
|
|
3703
|
+
}
|
|
3704
|
+
function* find_exp(arr, itemName, exp) {
|
|
3705
|
+
const result = yield* search_exp.call(this, arr, itemName, exp);
|
|
3706
|
+
return result ? result[1] : undefined;
|
|
3707
|
+
}
|
|
3429
3708
|
function uniq(arr) {
|
|
3430
3709
|
arr = toArray(arr);
|
|
3431
3710
|
this.context.memoryLimit.use(arr.length);
|
|
@@ -3437,7 +3716,7 @@ function sample(v, count = 1) {
|
|
|
3437
3716
|
return [];
|
|
3438
3717
|
if (!isArray(v))
|
|
3439
3718
|
v = stringify(v);
|
|
3440
|
-
this.context.memoryLimit.use(
|
|
3719
|
+
this.context.memoryLimit.use(v.length);
|
|
3441
3720
|
const shuffled = [...v].sort(() => Math.random() - 0.5);
|
|
3442
3721
|
if (count === 1)
|
|
3443
3722
|
return shuffled[0];
|
|
@@ -3447,7 +3726,7 @@ function sample(v, count = 1) {
|
|
|
3447
3726
|
var arrayFilters = /*#__PURE__*/Object.freeze({
|
|
3448
3727
|
__proto__: null,
|
|
3449
3728
|
join: join,
|
|
3450
|
-
last: last
|
|
3729
|
+
last: last,
|
|
3451
3730
|
first: first,
|
|
3452
3731
|
reverse: reverse,
|
|
3453
3732
|
sort: sort,
|
|
@@ -3463,9 +3742,15 @@ var arrayFilters = /*#__PURE__*/Object.freeze({
|
|
|
3463
3742
|
shift: shift,
|
|
3464
3743
|
slice: slice,
|
|
3465
3744
|
where: where,
|
|
3745
|
+
reject: reject,
|
|
3466
3746
|
where_exp: where_exp,
|
|
3747
|
+
reject_exp: reject_exp,
|
|
3467
3748
|
group_by: group_by,
|
|
3468
3749
|
group_by_exp: group_by_exp,
|
|
3750
|
+
has: has,
|
|
3751
|
+
has_exp: has_exp,
|
|
3752
|
+
find_index: find_index,
|
|
3753
|
+
find_index_exp: find_index_exp,
|
|
3469
3754
|
find: find,
|
|
3470
3755
|
find_exp: find_exp,
|
|
3471
3756
|
uniq: uniq,
|
|
@@ -3473,21 +3758,25 @@ var arrayFilters = /*#__PURE__*/Object.freeze({
|
|
|
3473
3758
|
});
|
|
3474
3759
|
|
|
3475
3760
|
function date(v, format, timezoneOffset) {
|
|
3476
|
-
var _a, _b
|
|
3477
|
-
const size = ((_a = v === null || v === void 0 ? void 0 : v.length) !== null && _a !== void 0 ? _a : 0) + ((_b =
|
|
3761
|
+
var _a, _b;
|
|
3762
|
+
const size = ((_a = v === null || v === void 0 ? void 0 : v.length) !== null && _a !== void 0 ? _a : 0) + ((_b = timezoneOffset === null || timezoneOffset === void 0 ? void 0 : timezoneOffset.length) !== null && _b !== void 0 ? _b : 0);
|
|
3478
3763
|
this.context.memoryLimit.use(size);
|
|
3479
3764
|
const date = parseDate(v, this.context.opts, timezoneOffset);
|
|
3480
3765
|
if (!date)
|
|
3481
3766
|
return v;
|
|
3482
3767
|
format = toValue(format);
|
|
3483
3768
|
format = isNil(format) ? this.context.opts.dateFormat : stringify(format);
|
|
3484
|
-
|
|
3769
|
+
this.context.memoryLimit.use(format.length);
|
|
3770
|
+
return strftime(date, format, this.context.memoryLimit);
|
|
3485
3771
|
}
|
|
3486
3772
|
function date_to_xmlschema(v) {
|
|
3487
3773
|
return date.call(this, v, '%Y-%m-%dT%H:%M:%S%:z');
|
|
3488
3774
|
}
|
|
3489
3775
|
function date_to_rfc822(v) {
|
|
3490
|
-
|
|
3776
|
+
const date = parseDate(v, this.context.opts, undefined, 'en-US');
|
|
3777
|
+
if (!date)
|
|
3778
|
+
return v;
|
|
3779
|
+
return strftime(date, '%a, %d %b %Y %H:%M:%S %z', this.context.memoryLimit);
|
|
3491
3780
|
}
|
|
3492
3781
|
function date_to_string(v, type, style) {
|
|
3493
3782
|
return stringify_date.call(this, v, '%b', type, style);
|
|
@@ -3499,20 +3788,23 @@ function stringify_date(v, month_type, type, style) {
|
|
|
3499
3788
|
const date = parseDate(v, this.context.opts);
|
|
3500
3789
|
if (!date)
|
|
3501
3790
|
return v;
|
|
3791
|
+
const ml = this.context.memoryLimit;
|
|
3502
3792
|
if (type === 'ordinal') {
|
|
3503
3793
|
const d = date.getDate();
|
|
3504
3794
|
return style === 'US'
|
|
3505
|
-
? strftime(date, `${month_type} ${d}%q, %Y
|
|
3506
|
-
: strftime(date, `${d}%q ${month_type} %Y
|
|
3795
|
+
? strftime(date, `${month_type} ${d}%q, %Y`, ml)
|
|
3796
|
+
: strftime(date, `${d}%q ${month_type} %Y`, ml);
|
|
3507
3797
|
}
|
|
3508
|
-
return strftime(date, `%d ${month_type} %Y
|
|
3798
|
+
return strftime(date, `%d ${month_type} %Y`, ml);
|
|
3509
3799
|
}
|
|
3510
|
-
function parseDate(v, opts, timezoneOffset) {
|
|
3800
|
+
function parseDate(v, opts, timezoneOffset, locale = opts.locale) {
|
|
3511
3801
|
let date;
|
|
3512
3802
|
const defaultTimezoneOffset = timezoneOffset !== null && timezoneOffset !== void 0 ? timezoneOffset : opts.timezoneOffset;
|
|
3513
|
-
const locale = opts.locale;
|
|
3514
3803
|
v = toValue(v);
|
|
3515
|
-
if (v
|
|
3804
|
+
if (isNil(v)) {
|
|
3805
|
+
return undefined;
|
|
3806
|
+
}
|
|
3807
|
+
else if (v === 'now' || v === 'today') {
|
|
3516
3808
|
date = new LiquidDate(Date.now(), locale, defaultTimezoneOffset);
|
|
3517
3809
|
}
|
|
3518
3810
|
else if (isNumber(v)) {
|
|
@@ -3566,14 +3858,34 @@ function prepend(v, arg) {
|
|
|
3566
3858
|
this.context.memoryLimit.use(lhs.length + rhs.length);
|
|
3567
3859
|
return rhs + lhs;
|
|
3568
3860
|
}
|
|
3861
|
+
function getTrimStart(str, chars) {
|
|
3862
|
+
let start = 0;
|
|
3863
|
+
for (const char of str) {
|
|
3864
|
+
if (!chars.has(char))
|
|
3865
|
+
break;
|
|
3866
|
+
start += char.length;
|
|
3867
|
+
}
|
|
3868
|
+
return start;
|
|
3869
|
+
}
|
|
3870
|
+
function getTrimEnd(str, chars, start = 0) {
|
|
3871
|
+
let end = str.length;
|
|
3872
|
+
while (end > start) {
|
|
3873
|
+
const size = end - start >= 2 && str.codePointAt(end - 2) > 0xFFFF ? 2 : 1;
|
|
3874
|
+
if (!chars.has(str.slice(end - size, end)))
|
|
3875
|
+
break;
|
|
3876
|
+
end -= size;
|
|
3877
|
+
}
|
|
3878
|
+
return end;
|
|
3879
|
+
}
|
|
3569
3880
|
function lstrip(v, chars) {
|
|
3570
3881
|
const str = stringify(v);
|
|
3571
3882
|
this.context.memoryLimit.use(str.length);
|
|
3572
3883
|
if (chars) {
|
|
3573
|
-
chars =
|
|
3574
|
-
|
|
3884
|
+
chars = stringify(chars);
|
|
3885
|
+
this.context.memoryLimit.use(chars.length);
|
|
3886
|
+
return str.slice(getTrimStart(str, new Set(chars)));
|
|
3575
3887
|
}
|
|
3576
|
-
return str.
|
|
3888
|
+
return str.trimStart();
|
|
3577
3889
|
}
|
|
3578
3890
|
function downcase(v) {
|
|
3579
3891
|
const str = stringify(v);
|
|
@@ -3587,18 +3899,20 @@ function upcase(v) {
|
|
|
3587
3899
|
}
|
|
3588
3900
|
function remove(v, arg) {
|
|
3589
3901
|
const str = stringify(v);
|
|
3590
|
-
|
|
3591
|
-
|
|
3902
|
+
arg = stringify(arg);
|
|
3903
|
+
this.context.memoryLimit.use(str.length + arg.length);
|
|
3904
|
+
return str.split(arg).join('');
|
|
3592
3905
|
}
|
|
3593
3906
|
function remove_first(v, l) {
|
|
3594
3907
|
const str = stringify(v);
|
|
3595
|
-
|
|
3596
|
-
|
|
3908
|
+
l = stringify(l);
|
|
3909
|
+
this.context.memoryLimit.use(str.length + l.length);
|
|
3910
|
+
return str.replace(l, '');
|
|
3597
3911
|
}
|
|
3598
3912
|
function remove_last(v, l) {
|
|
3599
3913
|
const str = stringify(v);
|
|
3600
|
-
this.context.memoryLimit.use(str.length);
|
|
3601
3914
|
const pattern = stringify(l);
|
|
3915
|
+
this.context.memoryLimit.use(str.length + pattern.length);
|
|
3602
3916
|
const index = str.lastIndexOf(pattern);
|
|
3603
3917
|
if (index === -1)
|
|
3604
3918
|
return str;
|
|
@@ -3608,10 +3922,11 @@ function rstrip(str, chars) {
|
|
|
3608
3922
|
str = stringify(str);
|
|
3609
3923
|
this.context.memoryLimit.use(str.length);
|
|
3610
3924
|
if (chars) {
|
|
3611
|
-
chars =
|
|
3612
|
-
|
|
3925
|
+
chars = stringify(chars);
|
|
3926
|
+
this.context.memoryLimit.use(chars.length);
|
|
3927
|
+
return str.slice(0, getTrimEnd(str, new Set(chars)));
|
|
3613
3928
|
}
|
|
3614
|
-
return str.
|
|
3929
|
+
return str.trimEnd();
|
|
3615
3930
|
}
|
|
3616
3931
|
function split(v, arg) {
|
|
3617
3932
|
const str = stringify(v);
|
|
@@ -3627,10 +3942,10 @@ function strip(v, chars) {
|
|
|
3627
3942
|
const str = stringify(v);
|
|
3628
3943
|
this.context.memoryLimit.use(str.length);
|
|
3629
3944
|
if (chars) {
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3945
|
+
const set = new Set(stringify(chars));
|
|
3946
|
+
this.context.memoryLimit.use(set.size);
|
|
3947
|
+
const start = getTrimStart(str, set);
|
|
3948
|
+
return str.slice(start, getTrimEnd(str, set, start));
|
|
3634
3949
|
}
|
|
3635
3950
|
return str.trim();
|
|
3636
3951
|
}
|
|
@@ -3639,6 +3954,11 @@ function strip_newlines(v) {
|
|
|
3639
3954
|
this.context.memoryLimit.use(str.length);
|
|
3640
3955
|
return str.replace(/\r?\n/gm, '');
|
|
3641
3956
|
}
|
|
3957
|
+
function squish(v) {
|
|
3958
|
+
const str = stringify(v);
|
|
3959
|
+
this.context.memoryLimit.use(str.length);
|
|
3960
|
+
return str.replace(/\s+/g, ' ').trim();
|
|
3961
|
+
}
|
|
3642
3962
|
function capitalize(str) {
|
|
3643
3963
|
str = stringify(str);
|
|
3644
3964
|
this.context.memoryLimit.use(str.length);
|
|
@@ -3646,35 +3966,43 @@ function capitalize(str) {
|
|
|
3646
3966
|
}
|
|
3647
3967
|
function replace(v, pattern, replacement) {
|
|
3648
3968
|
const str = stringify(v);
|
|
3649
|
-
|
|
3650
|
-
|
|
3969
|
+
pattern = stringify(pattern);
|
|
3970
|
+
replacement = stringify(replacement);
|
|
3971
|
+
const parts = str.split(pattern);
|
|
3972
|
+
const outputSize = str.length + (parts.length - 1) * (replacement.length - pattern.length);
|
|
3973
|
+
this.context.memoryLimit.use(outputSize);
|
|
3974
|
+
return parts.join(replacement);
|
|
3651
3975
|
}
|
|
3652
3976
|
function replace_first(v, arg1, arg2) {
|
|
3653
3977
|
const str = stringify(v);
|
|
3654
|
-
|
|
3655
|
-
|
|
3978
|
+
arg1 = stringify(arg1);
|
|
3979
|
+
arg2 = stringify(arg2);
|
|
3980
|
+
this.context.memoryLimit.use(str.length + arg1.length + arg2.length);
|
|
3981
|
+
return str.replace(arg1, () => arg2);
|
|
3656
3982
|
}
|
|
3657
3983
|
function replace_last(v, arg1, arg2) {
|
|
3658
3984
|
const str = stringify(v);
|
|
3659
|
-
this.context.memoryLimit.use(str.length);
|
|
3660
3985
|
const pattern = stringify(arg1);
|
|
3986
|
+
const replacement = stringify(arg2);
|
|
3987
|
+
this.context.memoryLimit.use(str.length + pattern.length + replacement.length);
|
|
3661
3988
|
const index = str.lastIndexOf(pattern);
|
|
3662
3989
|
if (index === -1)
|
|
3663
3990
|
return str;
|
|
3664
|
-
const replacement = stringify(arg2);
|
|
3665
3991
|
return str.substring(0, index) + replacement + str.substring(index + pattern.length);
|
|
3666
3992
|
}
|
|
3667
3993
|
function truncate(v, l = 50, o = '...') {
|
|
3668
3994
|
const str = stringify(v);
|
|
3669
|
-
|
|
3670
|
-
|
|
3995
|
+
o = stringify(o);
|
|
3996
|
+
this.context.memoryLimit.use(str.length + o.length);
|
|
3997
|
+
if (str.length <= l || advanceCodePoints(str, 0, l) >= str.length)
|
|
3671
3998
|
return v;
|
|
3672
|
-
return str.
|
|
3999
|
+
return str.slice(0, advanceCodePoints(str, 0, Math.max(l - codePointLength(o), 0))) + o;
|
|
3673
4000
|
}
|
|
3674
4001
|
function truncatewords(v, words = 15, o = '...') {
|
|
3675
4002
|
const str = stringify(v);
|
|
3676
|
-
|
|
3677
|
-
|
|
4003
|
+
o = stringify(o);
|
|
4004
|
+
this.context.memoryLimit.use(str.length + o.length);
|
|
4005
|
+
const arr = str.trimStart().split(/\s+/);
|
|
3678
4006
|
if (words <= 0)
|
|
3679
4007
|
words = 1;
|
|
3680
4008
|
let ret = arr.slice(0, words).join(' ');
|
|
@@ -3707,8 +4035,13 @@ function number_of_words(input, mode) {
|
|
|
3707
4035
|
return input.split(/\s+/).length;
|
|
3708
4036
|
}
|
|
3709
4037
|
}
|
|
3710
|
-
function array_to_sentence_string(
|
|
3711
|
-
|
|
4038
|
+
function array_to_sentence_string(input, connector = 'and') {
|
|
4039
|
+
const array = toArray(input);
|
|
4040
|
+
connector = stringify(connector);
|
|
4041
|
+
let outputSize = connector.length + array.length * 2;
|
|
4042
|
+
for (let i = 0; i < array.length; i++)
|
|
4043
|
+
outputSize += stringify(array[i]).length;
|
|
4044
|
+
this.context.memoryLimit.use(outputSize);
|
|
3712
4045
|
switch (array.length) {
|
|
3713
4046
|
case 0:
|
|
3714
4047
|
return '';
|
|
@@ -3735,6 +4068,7 @@ var stringFilters = /*#__PURE__*/Object.freeze({
|
|
|
3735
4068
|
split: split,
|
|
3736
4069
|
strip: strip,
|
|
3737
4070
|
strip_newlines: strip_newlines,
|
|
4071
|
+
squish: squish,
|
|
3738
4072
|
capitalize: capitalize,
|
|
3739
4073
|
replace: replace,
|
|
3740
4074
|
replace_first: replace_first,
|
|
@@ -3746,7 +4080,77 @@ var stringFilters = /*#__PURE__*/Object.freeze({
|
|
|
3746
4080
|
array_to_sentence_string: array_to_sentence_string
|
|
3747
4081
|
});
|
|
3748
4082
|
|
|
3749
|
-
|
|
4083
|
+
function base64Encode(str) {
|
|
4084
|
+
return Buffer.from(str, 'utf8').toString('base64');
|
|
4085
|
+
}
|
|
4086
|
+
function base64Decode(str) {
|
|
4087
|
+
return Buffer.from(str, 'base64').toString('utf8');
|
|
4088
|
+
}
|
|
4089
|
+
|
|
4090
|
+
/**
|
|
4091
|
+
* Base64 related filters
|
|
4092
|
+
*
|
|
4093
|
+
* Implements base64_encode and base64_decode filters for Shopify compatibility
|
|
4094
|
+
*/
|
|
4095
|
+
function base64_encode(value) {
|
|
4096
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
|
|
4097
|
+
this.context.memoryLimit.use(value.byteLength);
|
|
4098
|
+
return value.toString('base64');
|
|
4099
|
+
}
|
|
4100
|
+
const str = stringify(value);
|
|
4101
|
+
this.context.memoryLimit.use(str.length);
|
|
4102
|
+
return base64Encode(str);
|
|
4103
|
+
}
|
|
4104
|
+
function base64_decode(value) {
|
|
4105
|
+
const str = stringify(value);
|
|
4106
|
+
this.context.memoryLimit.use(str.length);
|
|
4107
|
+
assert(isBase64(str), 'invalid base64 provided to base64_decode');
|
|
4108
|
+
return base64Decode(str);
|
|
4109
|
+
}
|
|
4110
|
+
function isBase64(str) {
|
|
4111
|
+
str = str.replace(/[\t\n\f\r ]/g, '');
|
|
4112
|
+
if (str.length % 4 === 0)
|
|
4113
|
+
str = str.replace(/==?$/, '');
|
|
4114
|
+
return str.length % 4 !== 1 && /^[A-Za-z0-9+/]*$/.test(str);
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
var base64Filters = /*#__PURE__*/Object.freeze({
|
|
4118
|
+
__proto__: null,
|
|
4119
|
+
base64_encode: base64_encode,
|
|
4120
|
+
base64_decode: base64_decode
|
|
4121
|
+
});
|
|
4122
|
+
|
|
4123
|
+
function sha256(str) {
|
|
4124
|
+
return createHash('sha256').update(str, 'utf8').digest('hex');
|
|
4125
|
+
}
|
|
4126
|
+
function hmacSha256(str, key) {
|
|
4127
|
+
return createHmac('sha256', key).update(str, 'utf8').digest('hex');
|
|
4128
|
+
}
|
|
4129
|
+
|
|
4130
|
+
/**
|
|
4131
|
+
* Crypto related filters
|
|
4132
|
+
*
|
|
4133
|
+
* Implements sha256 and hmac_sha256 filters for Shopify compatibility
|
|
4134
|
+
*/
|
|
4135
|
+
function sha256$1(value) {
|
|
4136
|
+
const str = stringify(value);
|
|
4137
|
+
this.context.memoryLimit.use(str.length);
|
|
4138
|
+
return sha256(str);
|
|
4139
|
+
}
|
|
4140
|
+
function hmac_sha256(value, key) {
|
|
4141
|
+
const str = stringify(value);
|
|
4142
|
+
const keyStr = stringify(key);
|
|
4143
|
+
this.context.memoryLimit.use(str.length + keyStr.length);
|
|
4144
|
+
return hmacSha256(str, keyStr);
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4147
|
+
var cryptoFilters = /*#__PURE__*/Object.freeze({
|
|
4148
|
+
__proto__: null,
|
|
4149
|
+
sha256: sha256$1,
|
|
4150
|
+
hmac_sha256: hmac_sha256
|
|
4151
|
+
});
|
|
4152
|
+
|
|
4153
|
+
const filters = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, htmlFilters), mathFilters), urlFilters), arrayFilters), dateFilters), stringFilters), base64Filters), cryptoFilters), misc);
|
|
3750
4154
|
|
|
3751
4155
|
class AssignTag extends Tag {
|
|
3752
4156
|
constructor(token, remainTokens, liquid) {
|
|
@@ -3802,8 +4206,8 @@ class ForTag extends Tag {
|
|
|
3802
4206
|
return;
|
|
3803
4207
|
}
|
|
3804
4208
|
const continueKey = 'continue-' + this.variable + '-' + this.collection.getText();
|
|
3805
|
-
ctx.push({ continue: ctx.getRegister(continueKey) });
|
|
3806
|
-
const hash = yield this.hash.render(ctx);
|
|
4209
|
+
ctx.push(createScope({ continue: ctx.getRegister(continueKey, {}) }));
|
|
4210
|
+
const hash = (yield this.hash.render(ctx));
|
|
3807
4211
|
ctx.pop();
|
|
3808
4212
|
const modifiers = this.liquid.options.orderedFilterParameters
|
|
3809
4213
|
? Object.keys(hash).filter(x => MODIFIERS.includes(x))
|
|
@@ -3816,7 +4220,7 @@ class ForTag extends Tag {
|
|
|
3816
4220
|
return reversed(collection);
|
|
3817
4221
|
}, collection);
|
|
3818
4222
|
ctx.setRegister(continueKey, (hash['offset'] || 0) + collection.length);
|
|
3819
|
-
const scope = { forloop: new ForloopDrop(collection.length, this.collection.getText(), this.variable) };
|
|
4223
|
+
const scope = createScope({ forloop: new ForloopDrop(collection.length, this.collection.getText(), this.variable) });
|
|
3820
4224
|
ctx.push(scope);
|
|
3821
4225
|
for (const item of collection) {
|
|
3822
4226
|
scope[this.variable] = item;
|
|
@@ -3942,12 +4346,12 @@ class CaseTag extends Tag {
|
|
|
3942
4346
|
}
|
|
3943
4347
|
*render(ctx, emitter) {
|
|
3944
4348
|
const r = this.liquid.renderer;
|
|
3945
|
-
const target = toValue(yield this.value.value(ctx, ctx.opts.lenientIf));
|
|
4349
|
+
const target = yield toValue(yield this.value.value(ctx, ctx.opts.lenientIf));
|
|
3946
4350
|
let branchHit = false;
|
|
3947
4351
|
for (const branch of this.branches) {
|
|
3948
4352
|
for (const valueToken of branch.values) {
|
|
3949
4353
|
const value = yield evalToken(valueToken, ctx, ctx.opts.lenientIf);
|
|
3950
|
-
if (equals(target, value)) {
|
|
4354
|
+
if (yield equals(target, value)) {
|
|
3951
4355
|
yield r.renderTemplates(branch.templates, ctx, emitter);
|
|
3952
4356
|
branchHit = true;
|
|
3953
4357
|
break;
|
|
@@ -4008,7 +4412,11 @@ class RenderTag extends Tag {
|
|
|
4008
4412
|
alias = tokenizer.readIdentifier();
|
|
4009
4413
|
else
|
|
4010
4414
|
tokenizer.p = beforeAs;
|
|
4011
|
-
|
|
4415
|
+
const binding = { value, alias: alias && alias.content };
|
|
4416
|
+
if (keyword.content === 'with')
|
|
4417
|
+
this.with = binding;
|
|
4418
|
+
else
|
|
4419
|
+
this.forBinding = binding;
|
|
4012
4420
|
tokenizer.skipBlank();
|
|
4013
4421
|
if (tokenizer.peek() === ',')
|
|
4014
4422
|
tokenizer.advance();
|
|
@@ -4026,42 +4434,42 @@ class RenderTag extends Tag {
|
|
|
4026
4434
|
}
|
|
4027
4435
|
*render(ctx, emitter) {
|
|
4028
4436
|
const { liquid, hash } = this;
|
|
4029
|
-
const filepath = (yield renderFilePath(this
|
|
4437
|
+
const filepath = (yield renderFilePath(this.file, ctx, liquid));
|
|
4030
4438
|
assert(filepath, () => `illegal file path "${filepath}"`);
|
|
4031
4439
|
const childCtx = ctx.spawn();
|
|
4032
4440
|
const scope = childCtx.bottom();
|
|
4033
4441
|
__assign(scope, yield hash.render(ctx));
|
|
4034
|
-
if (this
|
|
4035
|
-
const { value, alias } = this
|
|
4442
|
+
if (this.with) {
|
|
4443
|
+
const { value, alias } = this.with;
|
|
4036
4444
|
scope[alias || filepath] = yield evalToken(value, ctx);
|
|
4037
4445
|
}
|
|
4038
|
-
if (this
|
|
4039
|
-
const { value, alias } = this
|
|
4446
|
+
if (this.forBinding) {
|
|
4447
|
+
const { value, alias } = this.forBinding;
|
|
4040
4448
|
const collection = toEnumerable(yield evalToken(value, ctx));
|
|
4041
4449
|
scope['forloop'] = new ForloopDrop(collection.length, value.getText(), alias);
|
|
4042
4450
|
for (const item of collection) {
|
|
4043
4451
|
scope[alias] = item;
|
|
4044
|
-
const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this
|
|
4452
|
+
const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this.currentFile));
|
|
4045
4453
|
yield liquid.renderer.renderTemplates(templates, childCtx, emitter);
|
|
4046
4454
|
scope['forloop'].next();
|
|
4047
4455
|
}
|
|
4048
4456
|
}
|
|
4049
4457
|
else {
|
|
4050
|
-
const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this
|
|
4458
|
+
const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this.currentFile));
|
|
4051
4459
|
yield liquid.renderer.renderTemplates(templates, childCtx, emitter);
|
|
4052
4460
|
}
|
|
4053
4461
|
}
|
|
4054
4462
|
*children(partials, sync) {
|
|
4055
|
-
if (partials && isString(this
|
|
4056
|
-
return (yield this.liquid._parsePartialFile(this
|
|
4463
|
+
if (partials && isString(this.file)) {
|
|
4464
|
+
return (yield this.liquid._parsePartialFile(this.file, sync, this.currentFile));
|
|
4057
4465
|
}
|
|
4058
4466
|
return [];
|
|
4059
4467
|
}
|
|
4060
4468
|
partialScope() {
|
|
4061
|
-
if (isString(this
|
|
4469
|
+
if (isString(this.file)) {
|
|
4062
4470
|
const names = Object.keys(this.hash.hash);
|
|
4063
|
-
if (this
|
|
4064
|
-
const { value, alias } = this
|
|
4471
|
+
if (this.with) {
|
|
4472
|
+
const { value, alias } = this.with;
|
|
4065
4473
|
if (isString(alias)) {
|
|
4066
4474
|
names.push([alias, value]);
|
|
4067
4475
|
}
|
|
@@ -4069,8 +4477,8 @@ class RenderTag extends Tag {
|
|
|
4069
4477
|
names.push([this.file, value]);
|
|
4070
4478
|
}
|
|
4071
4479
|
}
|
|
4072
|
-
if (this
|
|
4073
|
-
const { value, alias } = this
|
|
4480
|
+
if (this.forBinding) {
|
|
4481
|
+
const { value, alias } = this.forBinding;
|
|
4074
4482
|
if (isString(alias)) {
|
|
4075
4483
|
names.push([alias, value]);
|
|
4076
4484
|
}
|
|
@@ -4078,7 +4486,7 @@ class RenderTag extends Tag {
|
|
|
4078
4486
|
names.push([this.file, value]);
|
|
4079
4487
|
}
|
|
4080
4488
|
}
|
|
4081
|
-
return { name: this
|
|
4489
|
+
return { name: this.file, isolated: true, scope: names };
|
|
4082
4490
|
}
|
|
4083
4491
|
}
|
|
4084
4492
|
*arguments() {
|
|
@@ -4087,14 +4495,14 @@ class RenderTag extends Tag {
|
|
|
4087
4495
|
yield v;
|
|
4088
4496
|
}
|
|
4089
4497
|
}
|
|
4090
|
-
if (this
|
|
4091
|
-
const { value } = this
|
|
4498
|
+
if (this.with) {
|
|
4499
|
+
const { value } = this.with;
|
|
4092
4500
|
if (isValueToken(value)) {
|
|
4093
4501
|
yield value;
|
|
4094
4502
|
}
|
|
4095
4503
|
}
|
|
4096
|
-
if (this
|
|
4097
|
-
const { value } = this
|
|
4504
|
+
if (this.forBinding) {
|
|
4505
|
+
const { value } = this.forBinding;
|
|
4098
4506
|
if (isValueToken(value)) {
|
|
4099
4507
|
yield value;
|
|
4100
4508
|
}
|
|
@@ -4142,8 +4550,8 @@ class IncludeTag extends Tag {
|
|
|
4142
4550
|
constructor(token, remainTokens, liquid, parser) {
|
|
4143
4551
|
super(token, remainTokens, liquid);
|
|
4144
4552
|
const { tokenizer } = token;
|
|
4145
|
-
this
|
|
4146
|
-
this
|
|
4553
|
+
this.file = parseFilePath(tokenizer, this.liquid, parser);
|
|
4554
|
+
this.currentFile = token.file;
|
|
4147
4555
|
const begin = tokenizer.p;
|
|
4148
4556
|
const withStr = tokenizer.readIdentifier();
|
|
4149
4557
|
if (withStr.content === 'with') {
|
|
@@ -4161,28 +4569,28 @@ class IncludeTag extends Tag {
|
|
|
4161
4569
|
*render(ctx, emitter) {
|
|
4162
4570
|
const { liquid, hash, withVar } = this;
|
|
4163
4571
|
const { renderer } = liquid;
|
|
4164
|
-
const filepath = (yield renderFilePath(this
|
|
4572
|
+
const filepath = (yield renderFilePath(this.file, ctx, liquid));
|
|
4165
4573
|
assert(filepath, () => `illegal file path "${filepath}"`);
|
|
4166
4574
|
const saved = ctx.saveRegister('blocks', 'blockMode');
|
|
4167
4575
|
ctx.setRegister('blocks', {});
|
|
4168
4576
|
ctx.setRegister('blockMode', BlockMode.OUTPUT);
|
|
4169
|
-
const scope = (yield hash.render(ctx));
|
|
4577
|
+
const scope = createScope((yield hash.render(ctx)));
|
|
4170
4578
|
if (withVar)
|
|
4171
4579
|
scope[filepath] = yield evalToken(withVar, ctx);
|
|
4172
|
-
const templates = (yield liquid._parsePartialFile(filepath, ctx.sync, this
|
|
4173
|
-
ctx.push(ctx.opts.jekyllInclude ? { include: scope } : scope);
|
|
4580
|
+
const templates = (yield liquid._parsePartialFile(filepath, ctx.sync, this.currentFile));
|
|
4581
|
+
ctx.push(ctx.opts.jekyllInclude ? createScope({ include: scope }) : scope);
|
|
4174
4582
|
yield renderer.renderTemplates(templates, ctx, emitter);
|
|
4175
4583
|
ctx.pop();
|
|
4176
4584
|
ctx.restoreRegister(saved);
|
|
4177
4585
|
}
|
|
4178
4586
|
*children(partials, sync) {
|
|
4179
|
-
if (partials && isString(this
|
|
4180
|
-
return (yield this.liquid._parsePartialFile(this
|
|
4587
|
+
if (partials && isString(this.file)) {
|
|
4588
|
+
return (yield this.liquid._parsePartialFile(this.file, sync, this.currentFile));
|
|
4181
4589
|
}
|
|
4182
4590
|
return [];
|
|
4183
4591
|
}
|
|
4184
4592
|
partialScope() {
|
|
4185
|
-
if (isString(this
|
|
4593
|
+
if (isString(this.file)) {
|
|
4186
4594
|
let names;
|
|
4187
4595
|
if (this.liquid.options.jekyllInclude) {
|
|
4188
4596
|
names = ['include'];
|
|
@@ -4190,16 +4598,16 @@ class IncludeTag extends Tag {
|
|
|
4190
4598
|
else {
|
|
4191
4599
|
names = Object.keys(this.hash.hash);
|
|
4192
4600
|
if (this.withVar) {
|
|
4193
|
-
names.push([this
|
|
4601
|
+
names.push([this.file, this.withVar]);
|
|
4194
4602
|
}
|
|
4195
4603
|
}
|
|
4196
|
-
return { name: this
|
|
4604
|
+
return { name: this.file, isolated: false, scope: names };
|
|
4197
4605
|
}
|
|
4198
4606
|
}
|
|
4199
4607
|
*arguments() {
|
|
4200
4608
|
yield* Object.values(this.hash.hash).filter(isValueToken);
|
|
4201
|
-
if (isValueToken(this
|
|
4202
|
-
yield this
|
|
4609
|
+
if (isValueToken(this.file)) {
|
|
4610
|
+
yield this.file;
|
|
4203
4611
|
}
|
|
4204
4612
|
if (isValueToken(this.withVar)) {
|
|
4205
4613
|
yield this.withVar;
|
|
@@ -4229,6 +4637,7 @@ class CycleTag extends Tag {
|
|
|
4229
4637
|
constructor(token, remainTokens, liquid) {
|
|
4230
4638
|
super(token, remainTokens, liquid);
|
|
4231
4639
|
this.candidates = [];
|
|
4640
|
+
const begin = this.tokenizer.p;
|
|
4232
4641
|
const group = this.tokenizer.readValue();
|
|
4233
4642
|
this.tokenizer.skipBlank();
|
|
4234
4643
|
if (group) {
|
|
@@ -4237,28 +4646,33 @@ class CycleTag extends Tag {
|
|
|
4237
4646
|
this.tokenizer.advance();
|
|
4238
4647
|
}
|
|
4239
4648
|
else
|
|
4240
|
-
this.
|
|
4649
|
+
this.tokenizer.p = begin;
|
|
4241
4650
|
}
|
|
4242
4651
|
while (!this.tokenizer.end()) {
|
|
4243
|
-
const value = this.tokenizer.
|
|
4244
|
-
|
|
4245
|
-
this.candidates.push(value);
|
|
4652
|
+
const value = this.tokenizer.readFilteredValue();
|
|
4653
|
+
this.candidates.push(value);
|
|
4246
4654
|
this.tokenizer.readTo(',');
|
|
4247
4655
|
}
|
|
4248
4656
|
this.tokenizer.assert(this.candidates.length, () => `empty candidates: "${token.getText()}"`);
|
|
4249
4657
|
}
|
|
4250
4658
|
*render(ctx, emitter) {
|
|
4659
|
+
var _a;
|
|
4251
4660
|
const group = (yield evalToken(this.group, ctx));
|
|
4252
|
-
const fingerprint = `cycle:${group}:` + this.candidates.join(',');
|
|
4253
|
-
const groups = ctx.getRegister('cycle');
|
|
4661
|
+
const fingerprint = `cycle:${group}:` + this.candidates.map(c => c.getText()).join(',');
|
|
4662
|
+
const groups = ctx.getRegister('cycle', {});
|
|
4254
4663
|
let idx = groups[fingerprint];
|
|
4255
4664
|
if (idx === undefined) {
|
|
4256
4665
|
idx = groups[fingerprint] = 0;
|
|
4257
4666
|
}
|
|
4258
|
-
const candidate = this.candidates[idx];
|
|
4667
|
+
const candidate = new Value(this.candidates[idx], this.liquid);
|
|
4259
4668
|
idx = (idx + 1) % this.candidates.length;
|
|
4260
4669
|
groups[fingerprint] = idx;
|
|
4261
|
-
|
|
4670
|
+
let val = yield toValue(yield candidate.value(ctx, false));
|
|
4671
|
+
const outputEscape = this.liquid.options.outputEscape;
|
|
4672
|
+
if (outputEscape && !((_a = candidate.filters[candidate.filters.length - 1]) === null || _a === void 0 ? void 0 : _a.raw)) {
|
|
4673
|
+
val = yield outputEscape.call({ context: ctx, token: this.token, liquid: this.liquid }, val);
|
|
4674
|
+
}
|
|
4675
|
+
return val;
|
|
4262
4676
|
}
|
|
4263
4677
|
*arguments() {
|
|
4264
4678
|
yield* this.candidates;
|
|
@@ -4298,7 +4712,7 @@ class IfTag extends Tag {
|
|
|
4298
4712
|
*render(ctx, emitter) {
|
|
4299
4713
|
const r = this.liquid.renderer;
|
|
4300
4714
|
for (const { value, templates } of this.branches) {
|
|
4301
|
-
const v = yield value.value(ctx, ctx.opts.lenientIf);
|
|
4715
|
+
const v = yield toValue(yield value.value(ctx, ctx.opts.lenientIf));
|
|
4302
4716
|
if (isTruthy(v, ctx)) {
|
|
4303
4717
|
yield r.renderTemplates(templates, ctx, emitter);
|
|
4304
4718
|
return;
|
|
@@ -4342,7 +4756,7 @@ class LayoutTag extends Tag {
|
|
|
4342
4756
|
constructor(token, remainTokens, liquid, parser) {
|
|
4343
4757
|
super(token, remainTokens, liquid);
|
|
4344
4758
|
this.file = parseFilePath(this.tokenizer, this.liquid, parser);
|
|
4345
|
-
this
|
|
4759
|
+
this.currentFile = token.file;
|
|
4346
4760
|
this.args = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
4347
4761
|
this.templates = parser.parseTokens(remainTokens);
|
|
4348
4762
|
}
|
|
@@ -4356,24 +4770,24 @@ class LayoutTag extends Tag {
|
|
|
4356
4770
|
}
|
|
4357
4771
|
const filepath = (yield renderFilePath(this.file, ctx, liquid));
|
|
4358
4772
|
assert(filepath, () => `illegal file path "${filepath}"`);
|
|
4359
|
-
const templates = (yield liquid._parseLayoutFile(filepath, ctx.sync, this
|
|
4773
|
+
const templates = (yield liquid._parseLayoutFile(filepath, ctx.sync, this.currentFile));
|
|
4360
4774
|
// render remaining contents and store rendered results
|
|
4361
4775
|
ctx.setRegister('blockMode', BlockMode.STORE);
|
|
4362
4776
|
const html = yield renderer.renderTemplates(this.templates, ctx);
|
|
4363
|
-
const blocks = ctx.getRegister('blocks');
|
|
4777
|
+
const blocks = ctx.getRegister('blocks', {});
|
|
4364
4778
|
// set whole content to anonymous block if anonymous doesn't specified
|
|
4365
4779
|
if (blocks[''] === undefined)
|
|
4366
4780
|
blocks[''] = (parent, emitter) => emitter.write(html);
|
|
4367
4781
|
ctx.setRegister('blockMode', BlockMode.OUTPUT);
|
|
4368
4782
|
// render the layout file use stored blocks
|
|
4369
|
-
ctx.push((yield args.render(ctx)));
|
|
4783
|
+
ctx.push(createScope((yield args.render(ctx))));
|
|
4370
4784
|
yield renderer.renderTemplates(templates, ctx, emitter);
|
|
4371
4785
|
ctx.pop();
|
|
4372
4786
|
}
|
|
4373
4787
|
*children(partials) {
|
|
4374
4788
|
const templates = this.templates.slice();
|
|
4375
4789
|
if (partials && isString(this.file)) {
|
|
4376
|
-
templates.push(...(yield this.liquid._parsePartialFile(this.file, true, this
|
|
4790
|
+
templates.push(...(yield this.liquid._parsePartialFile(this.file, true, this.currentFile)));
|
|
4377
4791
|
}
|
|
4378
4792
|
return templates;
|
|
4379
4793
|
}
|
|
@@ -4412,23 +4826,28 @@ class BlockTag extends Tag {
|
|
|
4412
4826
|
*render(ctx, emitter) {
|
|
4413
4827
|
const blockRender = this.getBlockRender(ctx);
|
|
4414
4828
|
if (ctx.getRegister('blockMode') === BlockMode.STORE) {
|
|
4415
|
-
ctx.getRegister('blocks')[this.block] = blockRender;
|
|
4829
|
+
ctx.getRegister('blocks', {})[this.block] = blockRender;
|
|
4416
4830
|
}
|
|
4417
4831
|
else {
|
|
4418
4832
|
yield blockRender(new BlockDrop(), emitter);
|
|
4419
4833
|
}
|
|
4420
4834
|
}
|
|
4421
4835
|
getBlockRender(ctx) {
|
|
4836
|
+
const self = this;
|
|
4422
4837
|
const { liquid, templates } = this;
|
|
4423
|
-
const renderChild = ctx.getRegister('blocks')[this.block];
|
|
4838
|
+
const renderChild = ctx.getRegister('blocks', {})[this.block];
|
|
4424
4839
|
const renderCurrent = function* (superBlock, emitter) {
|
|
4425
|
-
|
|
4426
|
-
|
|
4840
|
+
const stack = ctx.getRegister('blockStack', []);
|
|
4841
|
+
if (stack.includes(self))
|
|
4842
|
+
throw new Error('block tag cannot be nested');
|
|
4843
|
+
stack.push(self);
|
|
4844
|
+
ctx.push(createScope({ block: superBlock }));
|
|
4427
4845
|
yield liquid.renderer.renderTemplates(templates, ctx, emitter);
|
|
4428
4846
|
ctx.pop();
|
|
4847
|
+
stack.pop();
|
|
4429
4848
|
};
|
|
4430
4849
|
return renderChild
|
|
4431
|
-
? (superBlock, emitter) => renderChild(new BlockDrop(() => renderCurrent(superBlock, emitter)), emitter)
|
|
4850
|
+
? (superBlock, emitter) => renderChild(new BlockDrop((emitter) => renderCurrent(superBlock, emitter)), emitter)
|
|
4432
4851
|
: renderCurrent;
|
|
4433
4852
|
}
|
|
4434
4853
|
*children() {
|
|
@@ -4512,7 +4931,7 @@ class TablerowTag extends Tag {
|
|
|
4512
4931
|
const cols = args.cols || collection.length;
|
|
4513
4932
|
const r = this.liquid.renderer;
|
|
4514
4933
|
const tablerowloop = new TablerowloopDrop(collection.length, cols, this.collection.getText(), this.variable);
|
|
4515
|
-
const scope = { tablerowloop };
|
|
4934
|
+
const scope = createScope({ tablerowloop });
|
|
4516
4935
|
ctx.push(scope);
|
|
4517
4936
|
for (let idx = 0; idx < collection.length; idx++, tablerowloop.next()) {
|
|
4518
4937
|
scope[this.variable] = collection[idx];
|
|
@@ -4585,7 +5004,7 @@ class UnlessTag extends Tag {
|
|
|
4585
5004
|
*render(ctx, emitter) {
|
|
4586
5005
|
const r = this.liquid.renderer;
|
|
4587
5006
|
for (const { value, test, templates } of this.branches) {
|
|
4588
|
-
const v = yield value.value(ctx, ctx.opts.lenientIf);
|
|
5007
|
+
const v = yield toValue(yield value.value(ctx, ctx.opts.lenientIf));
|
|
4589
5008
|
if (test(v, ctx)) {
|
|
4590
5009
|
yield r.renderTemplates(templates, ctx, emitter);
|
|
4591
5010
|
return;
|
|
@@ -4626,9 +5045,14 @@ class EchoTag extends Tag {
|
|
|
4626
5045
|
}
|
|
4627
5046
|
}
|
|
4628
5047
|
*render(ctx, emitter) {
|
|
5048
|
+
var _a;
|
|
4629
5049
|
if (!this.value)
|
|
4630
5050
|
return;
|
|
4631
|
-
|
|
5051
|
+
let val = yield toValue(yield this.value.value(ctx, false));
|
|
5052
|
+
const outputEscape = this.liquid.options.outputEscape;
|
|
5053
|
+
if (outputEscape && !((_a = this.value.filters[this.value.filters.length - 1]) === null || _a === void 0 ? void 0 : _a.raw)) {
|
|
5054
|
+
val = yield outputEscape.call({ context: ctx, token: this.token, liquid: this.liquid }, val);
|
|
5055
|
+
}
|
|
4632
5056
|
emitter.write(val);
|
|
4633
5057
|
}
|
|
4634
5058
|
*arguments() {
|
|
@@ -4689,8 +5113,8 @@ const tags = {
|
|
|
4689
5113
|
class Liquid {
|
|
4690
5114
|
constructor(opts = {}) {
|
|
4691
5115
|
this.renderer = new Render();
|
|
4692
|
-
this.filters =
|
|
4693
|
-
this.tags =
|
|
5116
|
+
this.filters = Object.create(null);
|
|
5117
|
+
this.tags = Object.create(null);
|
|
4694
5118
|
this.options = normalize(opts);
|
|
4695
5119
|
// eslint-disable-next-line deprecation/deprecation
|
|
4696
5120
|
this.parser = new Parser(this);
|
|
@@ -4702,7 +5126,7 @@ class Liquid {
|
|
|
4702
5126
|
return parser.parse(html, filepath);
|
|
4703
5127
|
}
|
|
4704
5128
|
_render(tpl, scope, renderOptions) {
|
|
4705
|
-
const ctx = scope instanceof Context ? scope : new Context(scope, this.options, renderOptions);
|
|
5129
|
+
const ctx = scope instanceof Context ? scope : new Context(scope, this.options, renderOptions, { liquid: this });
|
|
4706
5130
|
return this.renderer.renderTemplates(tpl, ctx);
|
|
4707
5131
|
}
|
|
4708
5132
|
render(tpl, scope, renderOptions) {
|
|
@@ -4714,7 +5138,7 @@ class Liquid {
|
|
|
4714
5138
|
return toValueSync(this._render(tpl, scope, Object.assign(Object.assign({}, renderOptions), { sync: true })));
|
|
4715
5139
|
}
|
|
4716
5140
|
renderToNodeStream(tpl, scope, renderOptions = {}) {
|
|
4717
|
-
const ctx = new Context(scope, this.options, renderOptions);
|
|
5141
|
+
const ctx = new Context(scope, this.options, renderOptions, { liquid: this });
|
|
4718
5142
|
return this.renderer.renderTemplatesToNodeStream(tpl, ctx);
|
|
4719
5143
|
}
|
|
4720
5144
|
_parseAndRender(html, scope, renderOptions) {
|
|
@@ -4766,7 +5190,7 @@ class Liquid {
|
|
|
4766
5190
|
}
|
|
4767
5191
|
_evalValue(str, scope) {
|
|
4768
5192
|
const value = new Value(str, this);
|
|
4769
|
-
const ctx = scope instanceof Context ? scope : new Context(scope, this.options);
|
|
5193
|
+
const ctx = scope instanceof Context ? scope : new Context(scope, this.options, {}, { liquid: this });
|
|
4770
5194
|
return value.value(ctx);
|
|
4771
5195
|
}
|
|
4772
5196
|
evalValue(str, scope) {
|
|
@@ -4780,6 +5204,9 @@ class Liquid {
|
|
|
4780
5204
|
registerFilter(name, filter) {
|
|
4781
5205
|
this.filters[name] = filter;
|
|
4782
5206
|
}
|
|
5207
|
+
unregisterFilter(name) {
|
|
5208
|
+
delete this.filters[name];
|
|
5209
|
+
}
|
|
4783
5210
|
registerTag(name, tag) {
|
|
4784
5211
|
this.tags[name] = isFunction(tag) ? tag : createTagClass(tag);
|
|
4785
5212
|
}
|
|
@@ -4893,4 +5320,4 @@ class Liquid {
|
|
|
4893
5320
|
/* istanbul ignore file */
|
|
4894
5321
|
const version = '[VI]{version}[/VI]';
|
|
4895
5322
|
|
|
4896
|
-
export { AssertionError, AssignTag, BlockTag, BreakTag, CaptureTag, CaseTag, CommentTag, Context, ContinueTag, CycleTag, DecrementTag, Drop, EchoTag, Expression, Filter, ForTag, Hash, IfTag, IncludeTag, IncrementTag, InlineCommentTag, LayoutTag, Liquid, LiquidError, LiquidTag, Output, ParseError, ParseStream, Parser, RawTag, RenderError, RenderTag, TablerowTag, Tag, TagToken, Token, TokenKind, TokenizationError, Tokenizer, typeGuards as TypeGuards, UndefinedVariableError, UnlessTag, Value, Variable, analyze, analyzeSync, assert, createTrie, defaultOperators, defaultOptions, evalQuotedToken, evalToken, filters, isFalsy, isTruthy, tags, toPromise, toValue, toValueSync, version };
|
|
5323
|
+
export { AssertionError, AssignTag, BlockTag, BreakTag, CaptureTag, CaseTag, CommentTag, Context, ContinueTag, CycleTag, DecrementTag, Drop, EchoTag, Expression, Filter, ForTag, Hash, IfTag, IncludeTag, IncrementTag, InlineCommentTag, LayoutTag, Liquid, LiquidError, LiquidTag, LookupType, Output, ParseError, ParseStream, Parser, RawTag, RenderError, RenderTag, TablerowTag, Tag, TagToken, Token, TokenKind, TokenizationError, Tokenizer, typeGuards as TypeGuards, UndefinedVariableError, UnlessTag, Value, Variable, analyze, analyzeSync, assert, createTrie, defaultOperators, defaultOptions, evalQuotedToken, evalToken, evalTokenValue, filters, isFalsy, isTruthy, tags, toPromise, toValue, toValueSync, version };
|