@skeptools/skep-organization-project 0.0.16 → 0.0.17
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 +28 -3
- package/API.md +63 -1
- package/lib/skep-organization-project.js +1 -1
- package/node_modules/liquidjs/README.md +15 -10
- package/node_modules/liquidjs/dist/context/context.d.ts +6 -3
- package/node_modules/liquidjs/dist/drop/blank-drop.d.ts +1 -0
- package/node_modules/liquidjs/dist/drop/empty-drop.d.ts +1 -0
- package/node_modules/liquidjs/dist/index.d.ts +2 -2
- package/node_modules/liquidjs/dist/liquid-options.d.ts +2 -0
- 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 +712 -45
- package/node_modules/liquidjs/dist/liquid.browser.umd.js +1573 -215
- package/node_modules/liquidjs/dist/liquid.browser.umd.js.map +1 -1
- package/node_modules/liquidjs/dist/liquid.d.ts +29 -1
- package/node_modules/liquidjs/dist/liquid.node.js +699 -45
- package/node_modules/liquidjs/dist/liquid.node.mjs +712 -45
- package/node_modules/liquidjs/dist/render/expression.d.ts +1 -1
- package/node_modules/liquidjs/dist/render/operator.d.ts +1 -0
- package/node_modules/liquidjs/dist/tags/assign.d.ts +5 -0
- package/node_modules/liquidjs/dist/tags/block.d.ts +2 -0
- package/node_modules/liquidjs/dist/tags/break.d.ts +1 -1
- package/node_modules/liquidjs/dist/tags/capture.d.ts +5 -1
- package/node_modules/liquidjs/dist/tags/case.d.ts +3 -0
- package/node_modules/liquidjs/dist/tags/continue.d.ts +1 -1
- package/node_modules/liquidjs/dist/tags/cycle.d.ts +2 -0
- package/node_modules/liquidjs/dist/tags/decrement.d.ts +3 -0
- package/node_modules/liquidjs/dist/tags/echo.d.ts +2 -0
- package/node_modules/liquidjs/dist/tags/for.d.ts +4 -0
- package/node_modules/liquidjs/dist/tags/if.d.ts +3 -0
- package/node_modules/liquidjs/dist/tags/include.d.ts +5 -1
- package/node_modules/liquidjs/dist/tags/increment.d.ts +3 -0
- package/node_modules/liquidjs/dist/tags/layout.d.ts +4 -0
- package/node_modules/liquidjs/dist/tags/liquid.d.ts +1 -0
- package/node_modules/liquidjs/dist/tags/render.d.ts +4 -0
- package/node_modules/liquidjs/dist/tags/tablerow.d.ts +4 -0
- package/node_modules/liquidjs/dist/tags/unless.d.ts +3 -0
- package/node_modules/liquidjs/dist/template/analysis.d.ts +85 -0
- package/node_modules/liquidjs/dist/template/analysis.spec.d.ts +1 -0
- package/node_modules/liquidjs/dist/template/hash.d.ts +2 -1
- package/node_modules/liquidjs/dist/template/index.d.ts +1 -0
- package/node_modules/liquidjs/dist/template/output.d.ts +2 -1
- package/node_modules/liquidjs/dist/template/template.d.ts +29 -0
- package/node_modules/liquidjs/dist/tokens/liquid-tag-token.d.ts +1 -1
- package/node_modules/liquidjs/dist/util/type-guards.d.ts +2 -1
- package/node_modules/liquidjs/dist/util/underscore.d.ts +3 -0
- package/node_modules/liquidjs/package.json +2 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* liquidjs@10.
|
|
3
|
-
* (c) 2016-
|
|
2
|
+
* liquidjs@10.20.1, https://github.com/harttle/liquidjs
|
|
3
|
+
* (c) 2016-2025 harttle
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
import { PassThrough } from 'stream';
|
|
@@ -125,6 +125,9 @@ function isArray(value) {
|
|
|
125
125
|
// be compatible with IE 8
|
|
126
126
|
return toString$1.call(value) === '[object Array]';
|
|
127
127
|
}
|
|
128
|
+
function isArrayLike(value) {
|
|
129
|
+
return value && isNumber(value.length);
|
|
130
|
+
}
|
|
128
131
|
function isIterable(value) {
|
|
129
132
|
return isObject(value) && Symbol.iterator in value;
|
|
130
133
|
}
|
|
@@ -210,6 +213,17 @@ function argumentsToValue(fn) {
|
|
|
210
213
|
}
|
|
211
214
|
function escapeRegExp(text) {
|
|
212
215
|
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
216
|
+
}
|
|
217
|
+
/** Return an array containing unique elements from _array_. Works with nested arrays and objects. */
|
|
218
|
+
function* strictUniq(array) {
|
|
219
|
+
const seen = new Set();
|
|
220
|
+
for (const element of array) {
|
|
221
|
+
const key = JSON.stringify(element);
|
|
222
|
+
if (!seen.has(key)) {
|
|
223
|
+
seen.add(key);
|
|
224
|
+
yield element;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
213
227
|
}
|
|
214
228
|
|
|
215
229
|
/**
|
|
@@ -410,6 +424,9 @@ class EmptyDrop extends Drop {
|
|
|
410
424
|
valueOf() {
|
|
411
425
|
return '';
|
|
412
426
|
}
|
|
427
|
+
static is(value) {
|
|
428
|
+
return value instanceof EmptyDrop;
|
|
429
|
+
}
|
|
413
430
|
}
|
|
414
431
|
|
|
415
432
|
class BlankDrop extends EmptyDrop {
|
|
@@ -422,6 +439,9 @@ class BlankDrop extends EmptyDrop {
|
|
|
422
439
|
return /^\s*$/.test(value);
|
|
423
440
|
return super.equals(value);
|
|
424
441
|
}
|
|
442
|
+
static is(value) {
|
|
443
|
+
return value instanceof BlankDrop;
|
|
444
|
+
}
|
|
425
445
|
}
|
|
426
446
|
|
|
427
447
|
class ForloopDrop extends Drop {
|
|
@@ -746,7 +766,11 @@ function getDateTimeFormat() {
|
|
|
746
766
|
|
|
747
767
|
// one minute in milliseconds
|
|
748
768
|
const OneMinute = 60000;
|
|
749
|
-
|
|
769
|
+
/**
|
|
770
|
+
* Need support both ISO8601 and RFC2822 as in major browsers & NodeJS
|
|
771
|
+
* RFC2822: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
|
|
772
|
+
*/
|
|
773
|
+
const TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):?(\d{2}))$/;
|
|
750
774
|
const monthNames = [
|
|
751
775
|
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
|
|
752
776
|
'September', 'October', 'November', 'December'
|
|
@@ -863,7 +887,7 @@ class LiquidDate {
|
|
|
863
887
|
* Given that a template is expected to be parsed fewer times than rendered.
|
|
864
888
|
*/
|
|
865
889
|
static createDateFixedToTimezone(dateString, locale) {
|
|
866
|
-
const m = dateString.match(
|
|
890
|
+
const m = dateString.match(TIMEZONE_PATTERN);
|
|
867
891
|
// representing a UTC timestamp
|
|
868
892
|
if (m && m[1] === 'Z') {
|
|
869
893
|
return new LiquidDate(+new Date(dateString), locale, 0);
|
|
@@ -1149,7 +1173,9 @@ class LiquidTagToken extends DelimitedToken {
|
|
|
1149
1173
|
this.name = this.tokenizer.readTagName();
|
|
1150
1174
|
this.tokenizer.assert(this.name, 'illegal liquid tag syntax');
|
|
1151
1175
|
this.tokenizer.skipBlank();
|
|
1152
|
-
|
|
1176
|
+
}
|
|
1177
|
+
get args() {
|
|
1178
|
+
return this.tokenizer.input.slice(this.tokenizer.p, this.contentRange[1]);
|
|
1153
1179
|
}
|
|
1154
1180
|
}
|
|
1155
1181
|
|
|
@@ -1242,7 +1268,7 @@ class Render {
|
|
|
1242
1268
|
const html = yield tpl.render(ctx, emitter);
|
|
1243
1269
|
// if not, it'll return an `html`, write to the emitter for it
|
|
1244
1270
|
html && emitter.write(html);
|
|
1245
|
-
if (
|
|
1271
|
+
if (ctx.breakCalled || ctx.continueCalled)
|
|
1246
1272
|
break;
|
|
1247
1273
|
}
|
|
1248
1274
|
catch (e) {
|
|
@@ -1326,6 +1352,7 @@ function evalQuotedToken(token) {
|
|
|
1326
1352
|
function* evalRangeToken(token, ctx) {
|
|
1327
1353
|
const low = yield evalToken(token.lhs, ctx);
|
|
1328
1354
|
const high = yield evalToken(token.rhs, ctx);
|
|
1355
|
+
ctx.memoryLimit.use(high - low + 1);
|
|
1329
1356
|
return range(+low, +high + 1);
|
|
1330
1357
|
}
|
|
1331
1358
|
function* toPostfix(tokens) {
|
|
@@ -1417,6 +1444,9 @@ function arrayEquals(lhs, rhs) {
|
|
|
1417
1444
|
if (lhs.length !== rhs.length)
|
|
1418
1445
|
return false;
|
|
1419
1446
|
return !lhs.some((value, i) => !equals(value, rhs[i]));
|
|
1447
|
+
}
|
|
1448
|
+
function arrayIncludes(arr, item) {
|
|
1449
|
+
return arr.some(value => equals(value, item));
|
|
1420
1450
|
}
|
|
1421
1451
|
|
|
1422
1452
|
class Node {
|
|
@@ -2313,9 +2343,9 @@ class Tag extends TemplateImpl {
|
|
|
2313
2343
|
* hash['reversed'] === undefined
|
|
2314
2344
|
*/
|
|
2315
2345
|
class Hash {
|
|
2316
|
-
constructor(
|
|
2346
|
+
constructor(input, jekyllStyle) {
|
|
2317
2347
|
this.hash = {};
|
|
2318
|
-
const tokenizer = new Tokenizer(
|
|
2348
|
+
const tokenizer = input instanceof Tokenizer ? input : new Tokenizer(input, {});
|
|
2319
2349
|
for (const hash of tokenizer.readHashes(jekyllStyle)) {
|
|
2320
2350
|
this.hash[hash.name.content] = hash.value;
|
|
2321
2351
|
}
|
|
@@ -2415,6 +2445,9 @@ class Output extends TemplateImpl {
|
|
|
2415
2445
|
const val = yield this.value.value(ctx, false);
|
|
2416
2446
|
emitter.write(val);
|
|
2417
2447
|
}
|
|
2448
|
+
*arguments() {
|
|
2449
|
+
yield this.value;
|
|
2450
|
+
}
|
|
2418
2451
|
}
|
|
2419
2452
|
|
|
2420
2453
|
class HTML extends TemplateImpl {
|
|
@@ -2427,6 +2460,336 @@ class HTML extends TemplateImpl {
|
|
|
2427
2460
|
}
|
|
2428
2461
|
}
|
|
2429
2462
|
|
|
2463
|
+
/**
|
|
2464
|
+
* A variable's segments and location, which can be coerced to a string.
|
|
2465
|
+
*/
|
|
2466
|
+
class Variable {
|
|
2467
|
+
constructor(segments, location) {
|
|
2468
|
+
this.segments = segments;
|
|
2469
|
+
this.location = location;
|
|
2470
|
+
}
|
|
2471
|
+
toString() {
|
|
2472
|
+
return segmentsString(this.segments, true);
|
|
2473
|
+
}
|
|
2474
|
+
/** Return this variable's segments as an array, possibly with nested arrays for nested paths. */
|
|
2475
|
+
toArray() {
|
|
2476
|
+
function* _visit(...segments) {
|
|
2477
|
+
for (const segment of segments) {
|
|
2478
|
+
if (segment instanceof Variable) {
|
|
2479
|
+
yield Array.from(_visit(...segment.segments));
|
|
2480
|
+
}
|
|
2481
|
+
else {
|
|
2482
|
+
yield segment;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
return Array.from(_visit(...this.segments));
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
/**
|
|
2490
|
+
* Group variables by the string representation of their root segment.
|
|
2491
|
+
*/
|
|
2492
|
+
class VariableMap {
|
|
2493
|
+
constructor() {
|
|
2494
|
+
this.map = new Map();
|
|
2495
|
+
}
|
|
2496
|
+
get(key) {
|
|
2497
|
+
const k = segmentsString([key.segments[0]]);
|
|
2498
|
+
if (!this.map.has(k)) {
|
|
2499
|
+
this.map.set(k, []);
|
|
2500
|
+
}
|
|
2501
|
+
return this.map.get(k);
|
|
2502
|
+
}
|
|
2503
|
+
has(key) {
|
|
2504
|
+
return this.map.has(segmentsString([key.segments[0]]));
|
|
2505
|
+
}
|
|
2506
|
+
push(variable) {
|
|
2507
|
+
this.get(variable).push(variable);
|
|
2508
|
+
}
|
|
2509
|
+
asObject() {
|
|
2510
|
+
return Object.fromEntries(this.map);
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
const defaultStaticAnalysisOptions = {
|
|
2514
|
+
partials: true
|
|
2515
|
+
};
|
|
2516
|
+
function* _analyze(templates, partials, sync) {
|
|
2517
|
+
const variables = new VariableMap();
|
|
2518
|
+
const globals = new VariableMap();
|
|
2519
|
+
const locals = new VariableMap();
|
|
2520
|
+
const rootScope = new DummyScope(new Set());
|
|
2521
|
+
// Names of partial templates that we've already analyzed.
|
|
2522
|
+
const seen = new Set();
|
|
2523
|
+
function updateVariables(variable, scope) {
|
|
2524
|
+
variables.push(variable);
|
|
2525
|
+
const aliased = scope.alias(variable);
|
|
2526
|
+
if (aliased !== undefined) {
|
|
2527
|
+
const root = aliased.segments[0];
|
|
2528
|
+
// TODO: What if a a template renders a rendered template? Do we need scope.parent?
|
|
2529
|
+
if (isString(root) && !rootScope.has(root)) {
|
|
2530
|
+
globals.push(aliased);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
else {
|
|
2534
|
+
const root = variable.segments[0];
|
|
2535
|
+
if (isString(root) && !scope.has(root)) {
|
|
2536
|
+
globals.push(variable);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
// Recurse for nested Variables
|
|
2540
|
+
for (const segment of variable.segments) {
|
|
2541
|
+
if (segment instanceof Variable) {
|
|
2542
|
+
updateVariables(segment, scope);
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
function* visit(template, scope) {
|
|
2547
|
+
if (template.arguments) {
|
|
2548
|
+
for (const arg of template.arguments()) {
|
|
2549
|
+
for (const variable of extractVariables(arg)) {
|
|
2550
|
+
updateVariables(variable, scope);
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
if (template.localScope) {
|
|
2555
|
+
for (const ident of template.localScope()) {
|
|
2556
|
+
scope.add(ident.content);
|
|
2557
|
+
scope.deleteAlias(ident.content);
|
|
2558
|
+
const [row, col] = ident.getPosition();
|
|
2559
|
+
locals.push(new Variable([ident.content], { row, col, file: ident.file }));
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
if (template.children) {
|
|
2563
|
+
if (template.partialScope) {
|
|
2564
|
+
const partial = template.partialScope();
|
|
2565
|
+
if (partial === undefined) {
|
|
2566
|
+
// Layouts, for example, can have children that are not partials.
|
|
2567
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2568
|
+
yield visit(child, scope);
|
|
2569
|
+
}
|
|
2570
|
+
return;
|
|
2571
|
+
}
|
|
2572
|
+
if (seen.has(partial.name))
|
|
2573
|
+
return;
|
|
2574
|
+
const partialScopeNames = new Set();
|
|
2575
|
+
const partialScope = partial.isolated
|
|
2576
|
+
? new DummyScope(partialScopeNames)
|
|
2577
|
+
: scope.push(partialScopeNames);
|
|
2578
|
+
for (const name of partial.scope) {
|
|
2579
|
+
if (isString(name)) {
|
|
2580
|
+
partialScopeNames.add(name);
|
|
2581
|
+
}
|
|
2582
|
+
else {
|
|
2583
|
+
const [alias, argument] = name;
|
|
2584
|
+
partialScopeNames.add(alias);
|
|
2585
|
+
const variables = Array.from(extractVariables(argument));
|
|
2586
|
+
if (variables.length) {
|
|
2587
|
+
partialScope.setAlias(alias, variables[0].segments);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2592
|
+
yield visit(child, partialScope);
|
|
2593
|
+
seen.add(partial.name);
|
|
2594
|
+
}
|
|
2595
|
+
partialScope.pop();
|
|
2596
|
+
}
|
|
2597
|
+
else {
|
|
2598
|
+
if (template.blockScope) {
|
|
2599
|
+
scope.push(new Set(template.blockScope()));
|
|
2600
|
+
}
|
|
2601
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2602
|
+
yield visit(child, scope);
|
|
2603
|
+
}
|
|
2604
|
+
if (template.blockScope) {
|
|
2605
|
+
scope.pop();
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
for (const template of templates) {
|
|
2611
|
+
yield visit(template, rootScope);
|
|
2612
|
+
}
|
|
2613
|
+
return {
|
|
2614
|
+
variables: variables.asObject(),
|
|
2615
|
+
globals: globals.asObject(),
|
|
2616
|
+
locals: locals.asObject()
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Statically analyze a template and report variable usage.
|
|
2621
|
+
*/
|
|
2622
|
+
function analyze(template, options = {}) {
|
|
2623
|
+
const opts = Object.assign(Object.assign({}, defaultStaticAnalysisOptions), options);
|
|
2624
|
+
return toPromise(_analyze(template, opts.partials, false));
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Statically analyze a template and report variable usage.
|
|
2628
|
+
*/
|
|
2629
|
+
function analyzeSync(template, options = {}) {
|
|
2630
|
+
const opts = Object.assign(Object.assign({}, defaultStaticAnalysisOptions), options);
|
|
2631
|
+
return toValueSync(_analyze(template, opts.partials, true));
|
|
2632
|
+
}
|
|
2633
|
+
/**
|
|
2634
|
+
* A stack to manage scopes while traversing templates during static analysis.
|
|
2635
|
+
*/
|
|
2636
|
+
class DummyScope {
|
|
2637
|
+
constructor(globals) {
|
|
2638
|
+
this.stack = [{ names: globals, aliases: new Map() }];
|
|
2639
|
+
}
|
|
2640
|
+
/** Return true if `name` is in scope. */
|
|
2641
|
+
has(name) {
|
|
2642
|
+
for (const scope of this.stack) {
|
|
2643
|
+
if (scope.names.has(name)) {
|
|
2644
|
+
return true;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return false;
|
|
2648
|
+
}
|
|
2649
|
+
push(scope) {
|
|
2650
|
+
this.stack.push({ names: scope, aliases: new Map() });
|
|
2651
|
+
return this;
|
|
2652
|
+
}
|
|
2653
|
+
pop() {
|
|
2654
|
+
var _a;
|
|
2655
|
+
return (_a = this.stack.pop()) === null || _a === void 0 ? void 0 : _a.names;
|
|
2656
|
+
}
|
|
2657
|
+
// Add a name to the template scope.
|
|
2658
|
+
add(name) {
|
|
2659
|
+
this.stack[0].names.add(name);
|
|
2660
|
+
}
|
|
2661
|
+
/** Return the variable that `variable` aliases, or `variable` if it doesn't alias anything. */
|
|
2662
|
+
alias(variable) {
|
|
2663
|
+
const root = variable.segments[0];
|
|
2664
|
+
if (!isString(root))
|
|
2665
|
+
return undefined;
|
|
2666
|
+
const alias = this.getAlias(root);
|
|
2667
|
+
if (alias === undefined)
|
|
2668
|
+
return undefined;
|
|
2669
|
+
return new Variable([...alias, ...variable.segments.slice(1)], variable.location);
|
|
2670
|
+
}
|
|
2671
|
+
// TODO: `from` could be a path with multiple segments, like `include.x`.
|
|
2672
|
+
setAlias(from, to) {
|
|
2673
|
+
this.stack[this.stack.length - 1].aliases.set(from, to);
|
|
2674
|
+
}
|
|
2675
|
+
deleteAlias(name) {
|
|
2676
|
+
this.stack[this.stack.length - 1].aliases.delete(name);
|
|
2677
|
+
}
|
|
2678
|
+
getAlias(name) {
|
|
2679
|
+
for (const scope of this.stack) {
|
|
2680
|
+
if (scope.aliases.has(name)) {
|
|
2681
|
+
return scope.aliases.get(name);
|
|
2682
|
+
}
|
|
2683
|
+
// If a scope has defined `name`, then it masks aliases in parent scopes.
|
|
2684
|
+
if (scope.names.has(name)) {
|
|
2685
|
+
return undefined;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
return undefined;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
function* extractVariables(value) {
|
|
2692
|
+
if (isValueToken(value)) {
|
|
2693
|
+
yield* extractValueTokenVariables(value);
|
|
2694
|
+
}
|
|
2695
|
+
else if (value instanceof Value) {
|
|
2696
|
+
yield* extractFilteredValueVariables(value);
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
function* extractFilteredValueVariables(value) {
|
|
2700
|
+
for (const token of value.initial.postfix) {
|
|
2701
|
+
if (isValueToken(token)) {
|
|
2702
|
+
yield* extractValueTokenVariables(token);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
for (const filter of value.filters) {
|
|
2706
|
+
for (const arg of filter.args) {
|
|
2707
|
+
if (isKeyValuePair(arg) && arg[1]) {
|
|
2708
|
+
yield* extractValueTokenVariables(arg[1]);
|
|
2709
|
+
}
|
|
2710
|
+
else if (isValueToken(arg)) {
|
|
2711
|
+
yield* extractValueTokenVariables(arg);
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
function* extractValueTokenVariables(token) {
|
|
2717
|
+
if (isRangeToken(token)) {
|
|
2718
|
+
yield* extractValueTokenVariables(token.lhs);
|
|
2719
|
+
yield* extractValueTokenVariables(token.rhs);
|
|
2720
|
+
}
|
|
2721
|
+
else if (isPropertyAccessToken(token)) {
|
|
2722
|
+
yield extractPropertyAccessVariable(token);
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
function extractPropertyAccessVariable(token) {
|
|
2726
|
+
const segments = [];
|
|
2727
|
+
// token is not guaranteed to have `file` set. We'll try to get it from a prop if not.
|
|
2728
|
+
let file = token.file;
|
|
2729
|
+
// Here we're flattening the first segment of a path if it is a nested path.
|
|
2730
|
+
const root = token.props[0];
|
|
2731
|
+
file = file || root.file;
|
|
2732
|
+
if (isQuotedToken(root) || isNumberToken(root) || isWordToken(root)) {
|
|
2733
|
+
segments.push(root.content);
|
|
2734
|
+
}
|
|
2735
|
+
else if (isPropertyAccessToken(root)) {
|
|
2736
|
+
// Flatten paths that start with a nested path.
|
|
2737
|
+
segments.push(...extractPropertyAccessVariable(root).segments);
|
|
2738
|
+
}
|
|
2739
|
+
for (const prop of token.props.slice(1)) {
|
|
2740
|
+
file = file || prop.file;
|
|
2741
|
+
if (isQuotedToken(prop) || isNumberToken(prop) || isWordToken(prop)) {
|
|
2742
|
+
segments.push(prop.content);
|
|
2743
|
+
}
|
|
2744
|
+
else if (isPropertyAccessToken(prop)) {
|
|
2745
|
+
segments.push(extractPropertyAccessVariable(prop));
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
const [row, col] = token.getPosition();
|
|
2749
|
+
return new Variable(segments, {
|
|
2750
|
+
row,
|
|
2751
|
+
col,
|
|
2752
|
+
file
|
|
2753
|
+
});
|
|
2754
|
+
}
|
|
2755
|
+
// This is used to detect segments that can be represented with dot notation
|
|
2756
|
+
// when creating a string representation of VariableSegments.
|
|
2757
|
+
const RE_PROPERTY = /^[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*$/;
|
|
2758
|
+
/**
|
|
2759
|
+
* Return a string representation of segments using dot notation where possible.
|
|
2760
|
+
* @param segments - The property names and array indices that make up a path to a variable.
|
|
2761
|
+
* @param bracketedRoot - If false (the default), don't surround the root segment with square brackets.
|
|
2762
|
+
*/
|
|
2763
|
+
function segmentsString(segments, bracketedRoot = false) {
|
|
2764
|
+
const buf = [];
|
|
2765
|
+
const root = segments[0];
|
|
2766
|
+
if (isString(root)) {
|
|
2767
|
+
if (!bracketedRoot || root.match(RE_PROPERTY)) {
|
|
2768
|
+
buf.push(`${root}`);
|
|
2769
|
+
}
|
|
2770
|
+
else {
|
|
2771
|
+
buf.push(`['${root}']`);
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
for (const segment of segments.slice(1)) {
|
|
2775
|
+
if (segment instanceof Variable) {
|
|
2776
|
+
buf.push(`[${segmentsString(segment.segments)}]`);
|
|
2777
|
+
}
|
|
2778
|
+
else if (isString(segment)) {
|
|
2779
|
+
if (segment.match(RE_PROPERTY)) {
|
|
2780
|
+
buf.push(`.${segment}`);
|
|
2781
|
+
}
|
|
2782
|
+
else {
|
|
2783
|
+
buf.push(`['${segment}']`);
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
else {
|
|
2787
|
+
buf.push(`[${segment}]`);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
return buf.join('');
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2430
2793
|
var LookupType;
|
|
2431
2794
|
(function (LookupType) {
|
|
2432
2795
|
LookupType["Partials"] = "partials";
|
|
@@ -2626,6 +2989,10 @@ function isWordToken(val) {
|
|
|
2626
2989
|
function isRangeToken(val) {
|
|
2627
2990
|
return getKind(val) === TokenKind.Range;
|
|
2628
2991
|
}
|
|
2992
|
+
function isValueToken(val) {
|
|
2993
|
+
// valueTokenBitMask = TokenKind.Number | TokenKind.Literal | TokenKind.Quoted | TokenKind.PropertyAccess | TokenKind.Range
|
|
2994
|
+
return (getKind(val) & 1667) > 0;
|
|
2995
|
+
}
|
|
2629
2996
|
function getKind(val) {
|
|
2630
2997
|
return val ? val.kind : -1;
|
|
2631
2998
|
}
|
|
@@ -2642,7 +3009,8 @@ var typeGuards = /*#__PURE__*/Object.freeze({
|
|
|
2642
3009
|
isNumberToken: isNumberToken,
|
|
2643
3010
|
isPropertyAccessToken: isPropertyAccessToken,
|
|
2644
3011
|
isWordToken: isWordToken,
|
|
2645
|
-
isRangeToken: isRangeToken
|
|
3012
|
+
isRangeToken: isRangeToken,
|
|
3013
|
+
isValueToken: isValueToken
|
|
2646
3014
|
});
|
|
2647
3015
|
|
|
2648
3016
|
class Context {
|
|
@@ -2654,6 +3022,8 @@ class Context {
|
|
|
2654
3022
|
*/
|
|
2655
3023
|
this.scopes = [{}];
|
|
2656
3024
|
this.registers = {};
|
|
3025
|
+
this.breakCalled = false;
|
|
3026
|
+
this.continueCalled = false;
|
|
2657
3027
|
this.sync = !!renderOptions.sync;
|
|
2658
3028
|
this.opts = opts;
|
|
2659
3029
|
this.globals = (_a = renderOptions.globals) !== null && _a !== void 0 ? _a : opts.globals;
|
|
@@ -2689,7 +3059,7 @@ class Context {
|
|
|
2689
3059
|
return toValueSync(this._get(paths));
|
|
2690
3060
|
}
|
|
2691
3061
|
*_get(paths) {
|
|
2692
|
-
const scope = this.findScope(paths[0]);
|
|
3062
|
+
const scope = this.findScope(paths[0]); // first prop should always be a string
|
|
2693
3063
|
return yield this._getFromScope(scope, paths);
|
|
2694
3064
|
}
|
|
2695
3065
|
/**
|
|
@@ -2741,6 +3111,7 @@ class Context {
|
|
|
2741
3111
|
}
|
|
2742
3112
|
function readProperty(obj, key, ownPropertyOnly) {
|
|
2743
3113
|
obj = toLiquid(obj);
|
|
3114
|
+
key = toValue(key);
|
|
2744
3115
|
if (isNil(obj))
|
|
2745
3116
|
return obj;
|
|
2746
3117
|
if (isArray(obj) && key < 0)
|
|
@@ -2888,8 +3259,8 @@ const join = argumentsToValue(function (v, arg) {
|
|
|
2888
3259
|
this.context.memoryLimit.use(complexity);
|
|
2889
3260
|
return array.join(sep);
|
|
2890
3261
|
});
|
|
2891
|
-
const last$1 = argumentsToValue((v) =>
|
|
2892
|
-
const first = argumentsToValue((v) =>
|
|
3262
|
+
const last$1 = argumentsToValue((v) => isArrayLike(v) ? last(v) : '');
|
|
3263
|
+
const first = argumentsToValue((v) => isArrayLike(v) ? v[0] : '');
|
|
2893
3264
|
const reverse = argumentsToValue(function (v) {
|
|
2894
3265
|
const array = toArray(v);
|
|
2895
3266
|
this.context.memoryLimit.use(array.length);
|
|
@@ -2990,10 +3361,13 @@ function* where(arr, property, expected) {
|
|
|
2990
3361
|
for (const item of arr) {
|
|
2991
3362
|
values.push(yield evalToken(token, this.context.spawn(item)));
|
|
2992
3363
|
}
|
|
3364
|
+
const matcher = this.context.opts.jekyllWhere
|
|
3365
|
+
? (v) => EmptyDrop.is(expected) ? equals(v, expected) : (isArray(v) ? arrayIncludes(v, expected) : equals(v, expected))
|
|
3366
|
+
: (v) => equals(v, expected);
|
|
2993
3367
|
return arr.filter((_, i) => {
|
|
2994
3368
|
if (expected === undefined)
|
|
2995
3369
|
return isTruthy(values[i], this.context);
|
|
2996
|
-
return
|
|
3370
|
+
return matcher(values[i]);
|
|
2997
3371
|
});
|
|
2998
3372
|
}
|
|
2999
3373
|
function* where_exp(arr, itemName, exp) {
|
|
@@ -3010,7 +3384,7 @@ function* where_exp(arr, itemName, exp) {
|
|
|
3010
3384
|
}
|
|
3011
3385
|
function* group_by(arr, property) {
|
|
3012
3386
|
const map = new Map();
|
|
3013
|
-
arr =
|
|
3387
|
+
arr = toEnumerable(arr);
|
|
3014
3388
|
const token = new Tokenizer(stringify(property)).readScopeValue();
|
|
3015
3389
|
this.context.memoryLimit.use(arr.length);
|
|
3016
3390
|
for (const item of arr) {
|
|
@@ -3024,7 +3398,7 @@ function* group_by(arr, property) {
|
|
|
3024
3398
|
function* group_by_exp(arr, itemName, exp) {
|
|
3025
3399
|
const map = new Map();
|
|
3026
3400
|
const keyTemplate = new Value(stringify(exp), this.liquid);
|
|
3027
|
-
arr =
|
|
3401
|
+
arr = toEnumerable(arr);
|
|
3028
3402
|
this.context.memoryLimit.use(arr.length);
|
|
3029
3403
|
for (const item of arr) {
|
|
3030
3404
|
const key = yield keyTemplate.value(this.context.spawn({ [itemName]: item }));
|
|
@@ -3377,7 +3751,8 @@ const filters = Object.assign(Object.assign(Object.assign(Object.assign(Object.a
|
|
|
3377
3751
|
class AssignTag extends Tag {
|
|
3378
3752
|
constructor(token, remainTokens, liquid) {
|
|
3379
3753
|
super(token, remainTokens, liquid);
|
|
3380
|
-
this.
|
|
3754
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
3755
|
+
this.key = this.identifier.content;
|
|
3381
3756
|
this.tokenizer.assert(this.key, 'expected variable name');
|
|
3382
3757
|
this.tokenizer.skipBlank();
|
|
3383
3758
|
this.tokenizer.assert(this.tokenizer.peek() === '=', 'expected "="');
|
|
@@ -3387,6 +3762,12 @@ class AssignTag extends Tag {
|
|
|
3387
3762
|
*render(ctx) {
|
|
3388
3763
|
ctx.bottom()[this.key] = yield this.value.value(ctx, this.liquid.options.lenientIf);
|
|
3389
3764
|
}
|
|
3765
|
+
*arguments() {
|
|
3766
|
+
yield this.value;
|
|
3767
|
+
}
|
|
3768
|
+
*localScope() {
|
|
3769
|
+
yield this.identifier;
|
|
3770
|
+
}
|
|
3390
3771
|
}
|
|
3391
3772
|
|
|
3392
3773
|
const MODIFIERS = ['offset', 'limit', 'reversed'];
|
|
@@ -3401,7 +3782,7 @@ class ForTag extends Tag {
|
|
|
3401
3782
|
}
|
|
3402
3783
|
this.variable = variable.content;
|
|
3403
3784
|
this.collection = collection;
|
|
3404
|
-
this.hash = new Hash(this.tokenizer
|
|
3785
|
+
this.hash = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3405
3786
|
this.templates = [];
|
|
3406
3787
|
this.elseTemplates = [];
|
|
3407
3788
|
let p;
|
|
@@ -3439,16 +3820,33 @@ class ForTag extends Tag {
|
|
|
3439
3820
|
ctx.push(scope);
|
|
3440
3821
|
for (const item of collection) {
|
|
3441
3822
|
scope[this.variable] = item;
|
|
3823
|
+
ctx.continueCalled = ctx.breakCalled = false;
|
|
3442
3824
|
yield r.renderTemplates(this.templates, ctx, emitter);
|
|
3443
|
-
if (
|
|
3444
|
-
emitter['break'] = false;
|
|
3825
|
+
if (ctx.breakCalled)
|
|
3445
3826
|
break;
|
|
3446
|
-
}
|
|
3447
|
-
emitter['continue'] = false;
|
|
3448
3827
|
scope.forloop.next();
|
|
3449
3828
|
}
|
|
3829
|
+
ctx.continueCalled = ctx.breakCalled = false;
|
|
3450
3830
|
ctx.pop();
|
|
3451
3831
|
}
|
|
3832
|
+
*children() {
|
|
3833
|
+
const templates = this.templates.slice();
|
|
3834
|
+
if (this.elseTemplates) {
|
|
3835
|
+
templates.push(...this.elseTemplates);
|
|
3836
|
+
}
|
|
3837
|
+
return templates;
|
|
3838
|
+
}
|
|
3839
|
+
*arguments() {
|
|
3840
|
+
yield this.collection;
|
|
3841
|
+
for (const v of Object.values(this.hash.hash)) {
|
|
3842
|
+
if (isValueToken(v)) {
|
|
3843
|
+
yield v;
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
blockScope() {
|
|
3848
|
+
return [this.variable, 'forloop'];
|
|
3849
|
+
}
|
|
3452
3850
|
}
|
|
3453
3851
|
function reversed(arr) {
|
|
3454
3852
|
return [...arr].reverse();
|
|
@@ -3464,7 +3862,8 @@ class CaptureTag extends Tag {
|
|
|
3464
3862
|
constructor(tagToken, remainTokens, liquid, parser) {
|
|
3465
3863
|
super(tagToken, remainTokens, liquid);
|
|
3466
3864
|
this.templates = [];
|
|
3467
|
-
this.
|
|
3865
|
+
this.identifier = this.readVariable();
|
|
3866
|
+
this.variable = this.identifier.content;
|
|
3468
3867
|
while (remainTokens.length) {
|
|
3469
3868
|
const token = remainTokens.shift();
|
|
3470
3869
|
if (isTagToken(token) && token.name === 'endcapture')
|
|
@@ -3473,19 +3872,25 @@ class CaptureTag extends Tag {
|
|
|
3473
3872
|
}
|
|
3474
3873
|
throw new Error(`tag ${tagToken.getText()} not closed`);
|
|
3475
3874
|
}
|
|
3875
|
+
readVariable() {
|
|
3876
|
+
let ident = this.tokenizer.readIdentifier();
|
|
3877
|
+
if (ident.content)
|
|
3878
|
+
return ident;
|
|
3879
|
+
ident = this.tokenizer.readQuoted();
|
|
3880
|
+
if (ident)
|
|
3881
|
+
return ident;
|
|
3882
|
+
throw this.tokenizer.error('invalid capture name');
|
|
3883
|
+
}
|
|
3476
3884
|
*render(ctx) {
|
|
3477
3885
|
const r = this.liquid.renderer;
|
|
3478
3886
|
const html = yield r.renderTemplates(this.templates, ctx);
|
|
3479
3887
|
ctx.bottom()[this.variable] = html;
|
|
3480
3888
|
}
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
if (quoted)
|
|
3487
|
-
return evalQuotedToken(quoted);
|
|
3488
|
-
throw this.tokenizer.error('invalid capture name');
|
|
3889
|
+
*children() {
|
|
3890
|
+
return this.templates;
|
|
3891
|
+
}
|
|
3892
|
+
*localScope() {
|
|
3893
|
+
yield this.identifier;
|
|
3489
3894
|
}
|
|
3490
3895
|
}
|
|
3491
3896
|
|
|
@@ -3553,6 +3958,17 @@ class CaseTag extends Tag {
|
|
|
3553
3958
|
yield r.renderTemplates(this.elseTemplates, ctx, emitter);
|
|
3554
3959
|
}
|
|
3555
3960
|
}
|
|
3961
|
+
*arguments() {
|
|
3962
|
+
yield this.value;
|
|
3963
|
+
yield* this.branches.flatMap(b => b.values);
|
|
3964
|
+
}
|
|
3965
|
+
*children() {
|
|
3966
|
+
const templates = this.branches.flatMap(b => b.templates);
|
|
3967
|
+
if (this.elseTemplates) {
|
|
3968
|
+
templates.push(...this.elseTemplates);
|
|
3969
|
+
}
|
|
3970
|
+
return templates;
|
|
3971
|
+
}
|
|
3556
3972
|
}
|
|
3557
3973
|
|
|
3558
3974
|
class CommentTag extends Tag {
|
|
@@ -3606,7 +4022,7 @@ class RenderTag extends Tag {
|
|
|
3606
4022
|
tokenizer.p = begin;
|
|
3607
4023
|
break;
|
|
3608
4024
|
}
|
|
3609
|
-
this.hash = new Hash(tokenizer
|
|
4025
|
+
this.hash = new Hash(tokenizer, liquid.options.keyValueSeparator);
|
|
3610
4026
|
}
|
|
3611
4027
|
*render(ctx, emitter) {
|
|
3612
4028
|
const { liquid, hash } = this;
|
|
@@ -3635,6 +4051,55 @@ class RenderTag extends Tag {
|
|
|
3635
4051
|
yield liquid.renderer.renderTemplates(templates, childCtx, emitter);
|
|
3636
4052
|
}
|
|
3637
4053
|
}
|
|
4054
|
+
*children(partials, sync) {
|
|
4055
|
+
if (partials && isString(this['file'])) {
|
|
4056
|
+
return (yield this.liquid._parsePartialFile(this['file'], sync, this['currentFile']));
|
|
4057
|
+
}
|
|
4058
|
+
return [];
|
|
4059
|
+
}
|
|
4060
|
+
partialScope() {
|
|
4061
|
+
if (isString(this['file'])) {
|
|
4062
|
+
const names = Object.keys(this.hash.hash);
|
|
4063
|
+
if (this['with']) {
|
|
4064
|
+
const { value, alias } = this['with'];
|
|
4065
|
+
if (isString(alias)) {
|
|
4066
|
+
names.push([alias, value]);
|
|
4067
|
+
}
|
|
4068
|
+
else if (isString(this.file)) {
|
|
4069
|
+
names.push([this.file, value]);
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
if (this['for']) {
|
|
4073
|
+
const { value, alias } = this['for'];
|
|
4074
|
+
if (isString(alias)) {
|
|
4075
|
+
names.push([alias, value]);
|
|
4076
|
+
}
|
|
4077
|
+
else if (isString(this.file)) {
|
|
4078
|
+
names.push([this.file, value]);
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
return { name: this['file'], isolated: true, scope: names };
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
*arguments() {
|
|
4085
|
+
for (const v of Object.values(this.hash.hash)) {
|
|
4086
|
+
if (isValueToken(v)) {
|
|
4087
|
+
yield v;
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
if (this['with']) {
|
|
4091
|
+
const { value } = this['with'];
|
|
4092
|
+
if (isValueToken(value)) {
|
|
4093
|
+
yield value;
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
if (this['for']) {
|
|
4097
|
+
const { value } = this['for'];
|
|
4098
|
+
if (isValueToken(value)) {
|
|
4099
|
+
yield value;
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
3638
4103
|
}
|
|
3639
4104
|
/**
|
|
3640
4105
|
* @return null for "none",
|
|
@@ -3691,7 +4156,7 @@ class IncludeTag extends Tag {
|
|
|
3691
4156
|
}
|
|
3692
4157
|
else
|
|
3693
4158
|
tokenizer.p = begin;
|
|
3694
|
-
this.hash = new Hash(tokenizer
|
|
4159
|
+
this.hash = new Hash(tokenizer, liquid.options.jekyllInclude || liquid.options.keyValueSeparator);
|
|
3695
4160
|
}
|
|
3696
4161
|
*render(ctx, emitter) {
|
|
3697
4162
|
const { liquid, hash, withVar } = this;
|
|
@@ -3710,12 +4175,43 @@ class IncludeTag extends Tag {
|
|
|
3710
4175
|
ctx.pop();
|
|
3711
4176
|
ctx.restoreRegister(saved);
|
|
3712
4177
|
}
|
|
4178
|
+
*children(partials, sync) {
|
|
4179
|
+
if (partials && isString(this['file'])) {
|
|
4180
|
+
return (yield this.liquid._parsePartialFile(this['file'], sync, this['currentFile']));
|
|
4181
|
+
}
|
|
4182
|
+
return [];
|
|
4183
|
+
}
|
|
4184
|
+
partialScope() {
|
|
4185
|
+
if (isString(this['file'])) {
|
|
4186
|
+
let names;
|
|
4187
|
+
if (this.liquid.options.jekyllInclude) {
|
|
4188
|
+
names = ['include'];
|
|
4189
|
+
}
|
|
4190
|
+
else {
|
|
4191
|
+
names = Object.keys(this.hash.hash);
|
|
4192
|
+
if (this.withVar) {
|
|
4193
|
+
names.push([this['file'], this.withVar]);
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
return { name: this['file'], isolated: false, scope: names };
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
*arguments() {
|
|
4200
|
+
yield* Object.values(this.hash.hash).filter(isValueToken);
|
|
4201
|
+
if (isValueToken(this['file'])) {
|
|
4202
|
+
yield this['file'];
|
|
4203
|
+
}
|
|
4204
|
+
if (isValueToken(this.withVar)) {
|
|
4205
|
+
yield this.withVar;
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
3713
4208
|
}
|
|
3714
4209
|
|
|
3715
4210
|
class DecrementTag extends Tag {
|
|
3716
4211
|
constructor(token, remainTokens, liquid) {
|
|
3717
4212
|
super(token, remainTokens, liquid);
|
|
3718
|
-
this.
|
|
4213
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
4214
|
+
this.variable = this.identifier.content;
|
|
3719
4215
|
}
|
|
3720
4216
|
render(context, emitter) {
|
|
3721
4217
|
const scope = context.environments;
|
|
@@ -3724,6 +4220,9 @@ class DecrementTag extends Tag {
|
|
|
3724
4220
|
}
|
|
3725
4221
|
emitter.write(stringify(--scope[this.variable]));
|
|
3726
4222
|
}
|
|
4223
|
+
*localScope() {
|
|
4224
|
+
yield this.identifier;
|
|
4225
|
+
}
|
|
3727
4226
|
}
|
|
3728
4227
|
|
|
3729
4228
|
class CycleTag extends Tag {
|
|
@@ -3761,6 +4260,12 @@ class CycleTag extends Tag {
|
|
|
3761
4260
|
groups[fingerprint] = idx;
|
|
3762
4261
|
return yield evalToken(candidate, ctx);
|
|
3763
4262
|
}
|
|
4263
|
+
*arguments() {
|
|
4264
|
+
yield* this.candidates;
|
|
4265
|
+
if (this.group) {
|
|
4266
|
+
yield this.group;
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
3764
4269
|
}
|
|
3765
4270
|
|
|
3766
4271
|
class IfTag extends Tag {
|
|
@@ -3770,13 +4275,13 @@ class IfTag extends Tag {
|
|
|
3770
4275
|
let p = [];
|
|
3771
4276
|
parser.parseStream(remainTokens)
|
|
3772
4277
|
.on('start', () => this.branches.push({
|
|
3773
|
-
value: new Value(tagToken.
|
|
4278
|
+
value: new Value(tagToken.tokenizer.readFilteredValue(), this.liquid),
|
|
3774
4279
|
templates: (p = [])
|
|
3775
4280
|
}))
|
|
3776
4281
|
.on('tag:elsif', (token) => {
|
|
3777
4282
|
assert(!this.elseTemplates, 'unexpected elsif after else');
|
|
3778
4283
|
this.branches.push({
|
|
3779
|
-
value: new Value(token.
|
|
4284
|
+
value: new Value(token.tokenizer.readFilteredValue(), this.liquid),
|
|
3780
4285
|
templates: (p = [])
|
|
3781
4286
|
});
|
|
3782
4287
|
})
|
|
@@ -3801,12 +4306,23 @@ class IfTag extends Tag {
|
|
|
3801
4306
|
}
|
|
3802
4307
|
yield r.renderTemplates(this.elseTemplates || [], ctx, emitter);
|
|
3803
4308
|
}
|
|
4309
|
+
*children() {
|
|
4310
|
+
const templates = this.branches.flatMap(b => b.templates);
|
|
4311
|
+
if (this.elseTemplates) {
|
|
4312
|
+
templates.push(...this.elseTemplates);
|
|
4313
|
+
}
|
|
4314
|
+
return templates;
|
|
4315
|
+
}
|
|
4316
|
+
arguments() {
|
|
4317
|
+
return this.branches.map(b => b.value);
|
|
4318
|
+
}
|
|
3804
4319
|
}
|
|
3805
4320
|
|
|
3806
4321
|
class IncrementTag extends Tag {
|
|
3807
4322
|
constructor(token, remainTokens, liquid) {
|
|
3808
4323
|
super(token, remainTokens, liquid);
|
|
3809
|
-
this.
|
|
4324
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
4325
|
+
this.variable = this.identifier.content;
|
|
3810
4326
|
}
|
|
3811
4327
|
render(context, emitter) {
|
|
3812
4328
|
const scope = context.environments;
|
|
@@ -3817,6 +4333,9 @@ class IncrementTag extends Tag {
|
|
|
3817
4333
|
scope[this.variable]++;
|
|
3818
4334
|
emitter.write(stringify(val));
|
|
3819
4335
|
}
|
|
4336
|
+
*localScope() {
|
|
4337
|
+
yield this.identifier;
|
|
4338
|
+
}
|
|
3820
4339
|
}
|
|
3821
4340
|
|
|
3822
4341
|
class LayoutTag extends Tag {
|
|
@@ -3824,7 +4343,7 @@ class LayoutTag extends Tag {
|
|
|
3824
4343
|
super(token, remainTokens, liquid);
|
|
3825
4344
|
this.file = parseFilePath(this.tokenizer, this.liquid, parser);
|
|
3826
4345
|
this['currentFile'] = token.file;
|
|
3827
|
-
this.args = new Hash(this.tokenizer
|
|
4346
|
+
this.args = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3828
4347
|
this.templates = parser.parseTokens(remainTokens);
|
|
3829
4348
|
}
|
|
3830
4349
|
*render(ctx, emitter) {
|
|
@@ -3851,6 +4370,28 @@ class LayoutTag extends Tag {
|
|
|
3851
4370
|
yield renderer.renderTemplates(templates, ctx, emitter);
|
|
3852
4371
|
ctx.pop();
|
|
3853
4372
|
}
|
|
4373
|
+
*children(partials) {
|
|
4374
|
+
const templates = this.templates.slice();
|
|
4375
|
+
if (partials && isString(this.file)) {
|
|
4376
|
+
templates.push(...(yield this.liquid._parsePartialFile(this.file, true, this['currentFile'])));
|
|
4377
|
+
}
|
|
4378
|
+
return templates;
|
|
4379
|
+
}
|
|
4380
|
+
*arguments() {
|
|
4381
|
+
for (const v of Object.values(this.args.hash)) {
|
|
4382
|
+
if (isValueToken(v)) {
|
|
4383
|
+
yield v;
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
if (isValueToken(this.file)) {
|
|
4387
|
+
yield this.file;
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4390
|
+
partialScope() {
|
|
4391
|
+
if (isString(this.file)) {
|
|
4392
|
+
return { name: this.file, isolated: false, scope: Object.keys(this.args.hash) };
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
3854
4395
|
}
|
|
3855
4396
|
|
|
3856
4397
|
class BlockTag extends Tag {
|
|
@@ -3890,6 +4431,12 @@ class BlockTag extends Tag {
|
|
|
3890
4431
|
? (superBlock, emitter) => renderChild(new BlockDrop(() => renderCurrent(superBlock, emitter)), emitter)
|
|
3891
4432
|
: renderCurrent;
|
|
3892
4433
|
}
|
|
4434
|
+
*children() {
|
|
4435
|
+
return this.templates;
|
|
4436
|
+
}
|
|
4437
|
+
blockScope() {
|
|
4438
|
+
return ['block'];
|
|
4439
|
+
}
|
|
3893
4440
|
}
|
|
3894
4441
|
|
|
3895
4442
|
class RawTag extends Tag {
|
|
@@ -3944,7 +4491,7 @@ class TablerowTag extends Tag {
|
|
|
3944
4491
|
}
|
|
3945
4492
|
this.variable = variable.content;
|
|
3946
4493
|
this.collection = collectionToken;
|
|
3947
|
-
this.args = new Hash(this.tokenizer
|
|
4494
|
+
this.args = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3948
4495
|
this.templates = [];
|
|
3949
4496
|
let p;
|
|
3950
4497
|
const stream = parser.parseStream(remainTokens)
|
|
@@ -3982,6 +4529,20 @@ class TablerowTag extends Tag {
|
|
|
3982
4529
|
emitter.write('</tr>');
|
|
3983
4530
|
ctx.pop();
|
|
3984
4531
|
}
|
|
4532
|
+
*children() {
|
|
4533
|
+
return this.templates;
|
|
4534
|
+
}
|
|
4535
|
+
*arguments() {
|
|
4536
|
+
yield this.collection;
|
|
4537
|
+
for (const v of Object.values(this.args.hash)) {
|
|
4538
|
+
if (isValueToken(v)) {
|
|
4539
|
+
yield v;
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
blockScope() {
|
|
4544
|
+
return [this.variable, 'tablerowloop'];
|
|
4545
|
+
}
|
|
3985
4546
|
}
|
|
3986
4547
|
|
|
3987
4548
|
class UnlessTag extends Tag {
|
|
@@ -3993,7 +4554,7 @@ class UnlessTag extends Tag {
|
|
|
3993
4554
|
let elseCount = 0;
|
|
3994
4555
|
parser.parseStream(remainTokens)
|
|
3995
4556
|
.on('start', () => this.branches.push({
|
|
3996
|
-
value: new Value(tagToken.
|
|
4557
|
+
value: new Value(tagToken.tokenizer.readFilteredValue(), this.liquid),
|
|
3997
4558
|
test: isFalsy,
|
|
3998
4559
|
templates: (p = [])
|
|
3999
4560
|
}))
|
|
@@ -4003,7 +4564,7 @@ class UnlessTag extends Tag {
|
|
|
4003
4564
|
return;
|
|
4004
4565
|
}
|
|
4005
4566
|
this.branches.push({
|
|
4006
|
-
value: new Value(token.
|
|
4567
|
+
value: new Value(token.tokenizer.readFilteredValue(), this.liquid),
|
|
4007
4568
|
test: isTruthy,
|
|
4008
4569
|
templates: (p = [])
|
|
4009
4570
|
});
|
|
@@ -4032,17 +4593,27 @@ class UnlessTag extends Tag {
|
|
|
4032
4593
|
}
|
|
4033
4594
|
yield r.renderTemplates(this.elseTemplates, ctx, emitter);
|
|
4034
4595
|
}
|
|
4596
|
+
*children() {
|
|
4597
|
+
const children = this.branches.flatMap(b => b.templates);
|
|
4598
|
+
if (this.elseTemplates) {
|
|
4599
|
+
children.push(...this.elseTemplates);
|
|
4600
|
+
}
|
|
4601
|
+
return children;
|
|
4602
|
+
}
|
|
4603
|
+
arguments() {
|
|
4604
|
+
return this.branches.map(b => b.value);
|
|
4605
|
+
}
|
|
4035
4606
|
}
|
|
4036
4607
|
|
|
4037
4608
|
class BreakTag extends Tag {
|
|
4038
|
-
render(ctx,
|
|
4039
|
-
|
|
4609
|
+
render(ctx, _emitter) {
|
|
4610
|
+
ctx.breakCalled = true;
|
|
4040
4611
|
}
|
|
4041
4612
|
}
|
|
4042
4613
|
|
|
4043
4614
|
class ContinueTag extends Tag {
|
|
4044
|
-
render(ctx,
|
|
4045
|
-
|
|
4615
|
+
render(ctx, _emitter) {
|
|
4616
|
+
ctx.continueCalled = true;
|
|
4046
4617
|
}
|
|
4047
4618
|
}
|
|
4048
4619
|
|
|
@@ -4060,6 +4631,11 @@ class EchoTag extends Tag {
|
|
|
4060
4631
|
const val = yield this.value.value(ctx, false);
|
|
4061
4632
|
emitter.write(val);
|
|
4062
4633
|
}
|
|
4634
|
+
*arguments() {
|
|
4635
|
+
if (this.value) {
|
|
4636
|
+
yield this.value;
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4063
4639
|
}
|
|
4064
4640
|
|
|
4065
4641
|
class LiquidTag extends Tag {
|
|
@@ -4071,6 +4647,9 @@ class LiquidTag extends Tag {
|
|
|
4071
4647
|
*render(ctx, emitter) {
|
|
4072
4648
|
yield this.liquid.renderer.renderTemplates(this.templates, ctx, emitter);
|
|
4073
4649
|
}
|
|
4650
|
+
*children() {
|
|
4651
|
+
return this.templates;
|
|
4652
|
+
}
|
|
4074
4653
|
}
|
|
4075
4654
|
|
|
4076
4655
|
class InlineCommentTag extends Tag {
|
|
@@ -4221,9 +4800,97 @@ class Liquid {
|
|
|
4221
4800
|
self.renderFile(filePath, ctx).then(html => callback(null, html), callback);
|
|
4222
4801
|
};
|
|
4223
4802
|
}
|
|
4803
|
+
analyze(template, options = {}) {
|
|
4804
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4805
|
+
return analyze(template, options);
|
|
4806
|
+
});
|
|
4807
|
+
}
|
|
4808
|
+
analyzeSync(template, options = {}) {
|
|
4809
|
+
return analyzeSync(template, options);
|
|
4810
|
+
}
|
|
4811
|
+
parseAndAnalyze(html, filename, options = {}) {
|
|
4812
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4813
|
+
return analyze(this.parse(html, filename), options);
|
|
4814
|
+
});
|
|
4815
|
+
}
|
|
4816
|
+
parseAndAnalyzeSync(html, filename, options = {}) {
|
|
4817
|
+
return analyzeSync(this.parse(html, filename), options);
|
|
4818
|
+
}
|
|
4819
|
+
/** Return an array of all variables without their properties. */
|
|
4820
|
+
variables(template, options = {}) {
|
|
4821
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4822
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4823
|
+
return Object.keys(analysis.variables);
|
|
4824
|
+
});
|
|
4825
|
+
}
|
|
4826
|
+
/** Return an array of all variables without their properties. */
|
|
4827
|
+
variablesSync(template, options = {}) {
|
|
4828
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4829
|
+
return Object.keys(analysis.variables);
|
|
4830
|
+
}
|
|
4831
|
+
/** Return an array of all variables including their properties/paths. */
|
|
4832
|
+
fullVariables(template, options = {}) {
|
|
4833
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4834
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4835
|
+
return Array.from(new Set(Object.values(analysis.variables).flatMap((a) => a.map((v) => String(v)))));
|
|
4836
|
+
});
|
|
4837
|
+
}
|
|
4838
|
+
/** Return an array of all variables including their properties/paths. */
|
|
4839
|
+
fullVariablesSync(template, options = {}) {
|
|
4840
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4841
|
+
return Array.from(new Set(Object.values(analysis.variables).flatMap((a) => a.map((v) => String(v)))));
|
|
4842
|
+
}
|
|
4843
|
+
/** Return an array of all variables, each as an array of properties/segments. */
|
|
4844
|
+
variableSegments(template, options = {}) {
|
|
4845
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4846
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4847
|
+
return Array.from(strictUniq(Object.values(analysis.variables).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4848
|
+
});
|
|
4849
|
+
}
|
|
4850
|
+
/** Return an array of all variables, each as an array of properties/segments. */
|
|
4851
|
+
variableSegmentsSync(template, options = {}) {
|
|
4852
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4853
|
+
return Array.from(strictUniq(Object.values(analysis.variables).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4854
|
+
}
|
|
4855
|
+
/** Return an array of all expected context variables without their properties. */
|
|
4856
|
+
globalVariables(template, options = {}) {
|
|
4857
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4858
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4859
|
+
return Object.keys(analysis.globals);
|
|
4860
|
+
});
|
|
4861
|
+
}
|
|
4862
|
+
/** Return an array of all expected context variables without their properties. */
|
|
4863
|
+
globalVariablesSync(template, options = {}) {
|
|
4864
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4865
|
+
return Object.keys(analysis.globals);
|
|
4866
|
+
}
|
|
4867
|
+
/** Return an array of all expected context variables including their properties/paths. */
|
|
4868
|
+
globalFullVariables(template, options = {}) {
|
|
4869
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4870
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4871
|
+
return Array.from(new Set(Object.values(analysis.globals).flatMap((a) => a.map((v) => String(v)))));
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
/** Return an array of all expected context variables including their properties/paths. */
|
|
4875
|
+
globalFullVariablesSync(template, options = {}) {
|
|
4876
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4877
|
+
return Array.from(new Set(Object.values(analysis.globals).flatMap((a) => a.map((v) => String(v)))));
|
|
4878
|
+
}
|
|
4879
|
+
/** Return an array of all expected context variables, each as an array of properties/segments. */
|
|
4880
|
+
globalVariableSegments(template, options = {}) {
|
|
4881
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4882
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4883
|
+
return Array.from(strictUniq(Object.values(analysis.globals).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4884
|
+
});
|
|
4885
|
+
}
|
|
4886
|
+
/** Return an array of all expected context variables, each as an array of properties/segments. */
|
|
4887
|
+
globalVariableSegmentsSync(template, options = {}) {
|
|
4888
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4889
|
+
return Array.from(strictUniq(Object.values(analysis.globals).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4890
|
+
}
|
|
4224
4891
|
}
|
|
4225
4892
|
|
|
4226
4893
|
/* istanbul ignore file */
|
|
4227
4894
|
const version = '[VI]{version}[/VI]';
|
|
4228
4895
|
|
|
4229
|
-
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, RawTag, RenderError, RenderTag, TablerowTag, Tag, TagToken, Token, TokenKind, TokenizationError, Tokenizer, typeGuards as TypeGuards, UndefinedVariableError, UnlessTag, Value, assert, createTrie, defaultOperators, defaultOptions, evalQuotedToken, evalToken, filters, isFalsy, isTruthy, tags, toPromise, toValue, toValueSync, version };
|
|
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 };
|