@skeptools/skep-organization-project 0.0.16 → 0.0.18
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 +29 -4
- 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 +4 -4
|
@@ -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
|
class Token {
|
|
@@ -111,6 +111,9 @@ function isArray(value) {
|
|
|
111
111
|
// be compatible with IE 8
|
|
112
112
|
return toString$1.call(value) === '[object Array]';
|
|
113
113
|
}
|
|
114
|
+
function isArrayLike(value) {
|
|
115
|
+
return value && isNumber(value.length);
|
|
116
|
+
}
|
|
114
117
|
function isIterable(value) {
|
|
115
118
|
return isObject(value) && Symbol.iterator in value;
|
|
116
119
|
}
|
|
@@ -196,6 +199,17 @@ function argumentsToValue(fn) {
|
|
|
196
199
|
}
|
|
197
200
|
function escapeRegExp(text) {
|
|
198
201
|
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
202
|
+
}
|
|
203
|
+
/** Return an array containing unique elements from _array_. Works with nested arrays and objects. */
|
|
204
|
+
function* strictUniq(array) {
|
|
205
|
+
const seen = new Set();
|
|
206
|
+
for (const element of array) {
|
|
207
|
+
const key = JSON.stringify(element);
|
|
208
|
+
if (!seen.has(key)) {
|
|
209
|
+
seen.add(key);
|
|
210
|
+
yield element;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
/**
|
|
@@ -396,6 +410,9 @@ class EmptyDrop extends Drop {
|
|
|
396
410
|
valueOf() {
|
|
397
411
|
return '';
|
|
398
412
|
}
|
|
413
|
+
static is(value) {
|
|
414
|
+
return value instanceof EmptyDrop;
|
|
415
|
+
}
|
|
399
416
|
}
|
|
400
417
|
|
|
401
418
|
class BlankDrop extends EmptyDrop {
|
|
@@ -408,6 +425,9 @@ class BlankDrop extends EmptyDrop {
|
|
|
408
425
|
return /^\s*$/.test(value);
|
|
409
426
|
return super.equals(value);
|
|
410
427
|
}
|
|
428
|
+
static is(value) {
|
|
429
|
+
return value instanceof BlankDrop;
|
|
430
|
+
}
|
|
411
431
|
}
|
|
412
432
|
|
|
413
433
|
class ForloopDrop extends Drop {
|
|
@@ -732,7 +752,11 @@ function getDateTimeFormat() {
|
|
|
732
752
|
|
|
733
753
|
// one minute in milliseconds
|
|
734
754
|
const OneMinute = 60000;
|
|
735
|
-
|
|
755
|
+
/**
|
|
756
|
+
* Need support both ISO8601 and RFC2822 as in major browsers & NodeJS
|
|
757
|
+
* RFC2822: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
|
|
758
|
+
*/
|
|
759
|
+
const TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):?(\d{2}))$/;
|
|
736
760
|
const monthNames = [
|
|
737
761
|
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
|
|
738
762
|
'September', 'October', 'November', 'December'
|
|
@@ -849,7 +873,7 @@ class LiquidDate {
|
|
|
849
873
|
* Given that a template is expected to be parsed fewer times than rendered.
|
|
850
874
|
*/
|
|
851
875
|
static createDateFixedToTimezone(dateString, locale) {
|
|
852
|
-
const m = dateString.match(
|
|
876
|
+
const m = dateString.match(TIMEZONE_PATTERN);
|
|
853
877
|
// representing a UTC timestamp
|
|
854
878
|
if (m && m[1] === 'Z') {
|
|
855
879
|
return new LiquidDate(+new Date(dateString), locale, 0);
|
|
@@ -1135,7 +1159,9 @@ class LiquidTagToken extends DelimitedToken {
|
|
|
1135
1159
|
this.name = this.tokenizer.readTagName();
|
|
1136
1160
|
this.tokenizer.assert(this.name, 'illegal liquid tag syntax');
|
|
1137
1161
|
this.tokenizer.skipBlank();
|
|
1138
|
-
|
|
1162
|
+
}
|
|
1163
|
+
get args() {
|
|
1164
|
+
return this.tokenizer.input.slice(this.tokenizer.p, this.contentRange[1]);
|
|
1139
1165
|
}
|
|
1140
1166
|
}
|
|
1141
1167
|
|
|
@@ -1220,7 +1246,7 @@ class Render {
|
|
|
1220
1246
|
const html = yield tpl.render(ctx, emitter);
|
|
1221
1247
|
// if not, it'll return an `html`, write to the emitter for it
|
|
1222
1248
|
html && emitter.write(html);
|
|
1223
|
-
if (
|
|
1249
|
+
if (ctx.breakCalled || ctx.continueCalled)
|
|
1224
1250
|
break;
|
|
1225
1251
|
}
|
|
1226
1252
|
catch (e) {
|
|
@@ -1304,6 +1330,7 @@ function evalQuotedToken(token) {
|
|
|
1304
1330
|
function* evalRangeToken(token, ctx) {
|
|
1305
1331
|
const low = yield evalToken(token.lhs, ctx);
|
|
1306
1332
|
const high = yield evalToken(token.rhs, ctx);
|
|
1333
|
+
ctx.memoryLimit.use(high - low + 1);
|
|
1307
1334
|
return range(+low, +high + 1);
|
|
1308
1335
|
}
|
|
1309
1336
|
function* toPostfix(tokens) {
|
|
@@ -1395,6 +1422,9 @@ function arrayEquals(lhs, rhs) {
|
|
|
1395
1422
|
if (lhs.length !== rhs.length)
|
|
1396
1423
|
return false;
|
|
1397
1424
|
return !lhs.some((value, i) => !equals(value, rhs[i]));
|
|
1425
|
+
}
|
|
1426
|
+
function arrayIncludes(arr, item) {
|
|
1427
|
+
return arr.some(value => equals(value, item));
|
|
1398
1428
|
}
|
|
1399
1429
|
|
|
1400
1430
|
class Node {
|
|
@@ -2300,9 +2330,9 @@ class Tag extends TemplateImpl {
|
|
|
2300
2330
|
* hash['reversed'] === undefined
|
|
2301
2331
|
*/
|
|
2302
2332
|
class Hash {
|
|
2303
|
-
constructor(
|
|
2333
|
+
constructor(input, jekyllStyle) {
|
|
2304
2334
|
this.hash = {};
|
|
2305
|
-
const tokenizer = new Tokenizer(
|
|
2335
|
+
const tokenizer = input instanceof Tokenizer ? input : new Tokenizer(input, {});
|
|
2306
2336
|
for (const hash of tokenizer.readHashes(jekyllStyle)) {
|
|
2307
2337
|
this.hash[hash.name.content] = hash.value;
|
|
2308
2338
|
}
|
|
@@ -2402,6 +2432,9 @@ class Output extends TemplateImpl {
|
|
|
2402
2432
|
const val = yield this.value.value(ctx, false);
|
|
2403
2433
|
emitter.write(val);
|
|
2404
2434
|
}
|
|
2435
|
+
*arguments() {
|
|
2436
|
+
yield this.value;
|
|
2437
|
+
}
|
|
2405
2438
|
}
|
|
2406
2439
|
|
|
2407
2440
|
class HTML extends TemplateImpl {
|
|
@@ -2414,6 +2447,336 @@ class HTML extends TemplateImpl {
|
|
|
2414
2447
|
}
|
|
2415
2448
|
}
|
|
2416
2449
|
|
|
2450
|
+
/**
|
|
2451
|
+
* A variable's segments and location, which can be coerced to a string.
|
|
2452
|
+
*/
|
|
2453
|
+
class Variable {
|
|
2454
|
+
constructor(segments, location) {
|
|
2455
|
+
this.segments = segments;
|
|
2456
|
+
this.location = location;
|
|
2457
|
+
}
|
|
2458
|
+
toString() {
|
|
2459
|
+
return segmentsString(this.segments, true);
|
|
2460
|
+
}
|
|
2461
|
+
/** Return this variable's segments as an array, possibly with nested arrays for nested paths. */
|
|
2462
|
+
toArray() {
|
|
2463
|
+
function* _visit(...segments) {
|
|
2464
|
+
for (const segment of segments) {
|
|
2465
|
+
if (segment instanceof Variable) {
|
|
2466
|
+
yield Array.from(_visit(...segment.segments));
|
|
2467
|
+
}
|
|
2468
|
+
else {
|
|
2469
|
+
yield segment;
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
return Array.from(_visit(...this.segments));
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
/**
|
|
2477
|
+
* Group variables by the string representation of their root segment.
|
|
2478
|
+
*/
|
|
2479
|
+
class VariableMap {
|
|
2480
|
+
constructor() {
|
|
2481
|
+
this.map = new Map();
|
|
2482
|
+
}
|
|
2483
|
+
get(key) {
|
|
2484
|
+
const k = segmentsString([key.segments[0]]);
|
|
2485
|
+
if (!this.map.has(k)) {
|
|
2486
|
+
this.map.set(k, []);
|
|
2487
|
+
}
|
|
2488
|
+
return this.map.get(k);
|
|
2489
|
+
}
|
|
2490
|
+
has(key) {
|
|
2491
|
+
return this.map.has(segmentsString([key.segments[0]]));
|
|
2492
|
+
}
|
|
2493
|
+
push(variable) {
|
|
2494
|
+
this.get(variable).push(variable);
|
|
2495
|
+
}
|
|
2496
|
+
asObject() {
|
|
2497
|
+
return Object.fromEntries(this.map);
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
const defaultStaticAnalysisOptions = {
|
|
2501
|
+
partials: true
|
|
2502
|
+
};
|
|
2503
|
+
function* _analyze(templates, partials, sync) {
|
|
2504
|
+
const variables = new VariableMap();
|
|
2505
|
+
const globals = new VariableMap();
|
|
2506
|
+
const locals = new VariableMap();
|
|
2507
|
+
const rootScope = new DummyScope(new Set());
|
|
2508
|
+
// Names of partial templates that we've already analyzed.
|
|
2509
|
+
const seen = new Set();
|
|
2510
|
+
function updateVariables(variable, scope) {
|
|
2511
|
+
variables.push(variable);
|
|
2512
|
+
const aliased = scope.alias(variable);
|
|
2513
|
+
if (aliased !== undefined) {
|
|
2514
|
+
const root = aliased.segments[0];
|
|
2515
|
+
// TODO: What if a a template renders a rendered template? Do we need scope.parent?
|
|
2516
|
+
if (isString(root) && !rootScope.has(root)) {
|
|
2517
|
+
globals.push(aliased);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
else {
|
|
2521
|
+
const root = variable.segments[0];
|
|
2522
|
+
if (isString(root) && !scope.has(root)) {
|
|
2523
|
+
globals.push(variable);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
// Recurse for nested Variables
|
|
2527
|
+
for (const segment of variable.segments) {
|
|
2528
|
+
if (segment instanceof Variable) {
|
|
2529
|
+
updateVariables(segment, scope);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
function* visit(template, scope) {
|
|
2534
|
+
if (template.arguments) {
|
|
2535
|
+
for (const arg of template.arguments()) {
|
|
2536
|
+
for (const variable of extractVariables(arg)) {
|
|
2537
|
+
updateVariables(variable, scope);
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
if (template.localScope) {
|
|
2542
|
+
for (const ident of template.localScope()) {
|
|
2543
|
+
scope.add(ident.content);
|
|
2544
|
+
scope.deleteAlias(ident.content);
|
|
2545
|
+
const [row, col] = ident.getPosition();
|
|
2546
|
+
locals.push(new Variable([ident.content], { row, col, file: ident.file }));
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
if (template.children) {
|
|
2550
|
+
if (template.partialScope) {
|
|
2551
|
+
const partial = template.partialScope();
|
|
2552
|
+
if (partial === undefined) {
|
|
2553
|
+
// Layouts, for example, can have children that are not partials.
|
|
2554
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2555
|
+
yield visit(child, scope);
|
|
2556
|
+
}
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
if (seen.has(partial.name))
|
|
2560
|
+
return;
|
|
2561
|
+
const partialScopeNames = new Set();
|
|
2562
|
+
const partialScope = partial.isolated
|
|
2563
|
+
? new DummyScope(partialScopeNames)
|
|
2564
|
+
: scope.push(partialScopeNames);
|
|
2565
|
+
for (const name of partial.scope) {
|
|
2566
|
+
if (isString(name)) {
|
|
2567
|
+
partialScopeNames.add(name);
|
|
2568
|
+
}
|
|
2569
|
+
else {
|
|
2570
|
+
const [alias, argument] = name;
|
|
2571
|
+
partialScopeNames.add(alias);
|
|
2572
|
+
const variables = Array.from(extractVariables(argument));
|
|
2573
|
+
if (variables.length) {
|
|
2574
|
+
partialScope.setAlias(alias, variables[0].segments);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2579
|
+
yield visit(child, partialScope);
|
|
2580
|
+
seen.add(partial.name);
|
|
2581
|
+
}
|
|
2582
|
+
partialScope.pop();
|
|
2583
|
+
}
|
|
2584
|
+
else {
|
|
2585
|
+
if (template.blockScope) {
|
|
2586
|
+
scope.push(new Set(template.blockScope()));
|
|
2587
|
+
}
|
|
2588
|
+
for (const child of (yield template.children(partials, sync))) {
|
|
2589
|
+
yield visit(child, scope);
|
|
2590
|
+
}
|
|
2591
|
+
if (template.blockScope) {
|
|
2592
|
+
scope.pop();
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
for (const template of templates) {
|
|
2598
|
+
yield visit(template, rootScope);
|
|
2599
|
+
}
|
|
2600
|
+
return {
|
|
2601
|
+
variables: variables.asObject(),
|
|
2602
|
+
globals: globals.asObject(),
|
|
2603
|
+
locals: locals.asObject()
|
|
2604
|
+
};
|
|
2605
|
+
}
|
|
2606
|
+
/**
|
|
2607
|
+
* Statically analyze a template and report variable usage.
|
|
2608
|
+
*/
|
|
2609
|
+
function analyze(template, options = {}) {
|
|
2610
|
+
const opts = Object.assign(Object.assign({}, defaultStaticAnalysisOptions), options);
|
|
2611
|
+
return toPromise(_analyze(template, opts.partials, false));
|
|
2612
|
+
}
|
|
2613
|
+
/**
|
|
2614
|
+
* Statically analyze a template and report variable usage.
|
|
2615
|
+
*/
|
|
2616
|
+
function analyzeSync(template, options = {}) {
|
|
2617
|
+
const opts = Object.assign(Object.assign({}, defaultStaticAnalysisOptions), options);
|
|
2618
|
+
return toValueSync(_analyze(template, opts.partials, true));
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* A stack to manage scopes while traversing templates during static analysis.
|
|
2622
|
+
*/
|
|
2623
|
+
class DummyScope {
|
|
2624
|
+
constructor(globals) {
|
|
2625
|
+
this.stack = [{ names: globals, aliases: new Map() }];
|
|
2626
|
+
}
|
|
2627
|
+
/** Return true if `name` is in scope. */
|
|
2628
|
+
has(name) {
|
|
2629
|
+
for (const scope of this.stack) {
|
|
2630
|
+
if (scope.names.has(name)) {
|
|
2631
|
+
return true;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
return false;
|
|
2635
|
+
}
|
|
2636
|
+
push(scope) {
|
|
2637
|
+
this.stack.push({ names: scope, aliases: new Map() });
|
|
2638
|
+
return this;
|
|
2639
|
+
}
|
|
2640
|
+
pop() {
|
|
2641
|
+
var _a;
|
|
2642
|
+
return (_a = this.stack.pop()) === null || _a === void 0 ? void 0 : _a.names;
|
|
2643
|
+
}
|
|
2644
|
+
// Add a name to the template scope.
|
|
2645
|
+
add(name) {
|
|
2646
|
+
this.stack[0].names.add(name);
|
|
2647
|
+
}
|
|
2648
|
+
/** Return the variable that `variable` aliases, or `variable` if it doesn't alias anything. */
|
|
2649
|
+
alias(variable) {
|
|
2650
|
+
const root = variable.segments[0];
|
|
2651
|
+
if (!isString(root))
|
|
2652
|
+
return undefined;
|
|
2653
|
+
const alias = this.getAlias(root);
|
|
2654
|
+
if (alias === undefined)
|
|
2655
|
+
return undefined;
|
|
2656
|
+
return new Variable([...alias, ...variable.segments.slice(1)], variable.location);
|
|
2657
|
+
}
|
|
2658
|
+
// TODO: `from` could be a path with multiple segments, like `include.x`.
|
|
2659
|
+
setAlias(from, to) {
|
|
2660
|
+
this.stack[this.stack.length - 1].aliases.set(from, to);
|
|
2661
|
+
}
|
|
2662
|
+
deleteAlias(name) {
|
|
2663
|
+
this.stack[this.stack.length - 1].aliases.delete(name);
|
|
2664
|
+
}
|
|
2665
|
+
getAlias(name) {
|
|
2666
|
+
for (const scope of this.stack) {
|
|
2667
|
+
if (scope.aliases.has(name)) {
|
|
2668
|
+
return scope.aliases.get(name);
|
|
2669
|
+
}
|
|
2670
|
+
// If a scope has defined `name`, then it masks aliases in parent scopes.
|
|
2671
|
+
if (scope.names.has(name)) {
|
|
2672
|
+
return undefined;
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
return undefined;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
function* extractVariables(value) {
|
|
2679
|
+
if (isValueToken(value)) {
|
|
2680
|
+
yield* extractValueTokenVariables(value);
|
|
2681
|
+
}
|
|
2682
|
+
else if (value instanceof Value) {
|
|
2683
|
+
yield* extractFilteredValueVariables(value);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
function* extractFilteredValueVariables(value) {
|
|
2687
|
+
for (const token of value.initial.postfix) {
|
|
2688
|
+
if (isValueToken(token)) {
|
|
2689
|
+
yield* extractValueTokenVariables(token);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
for (const filter of value.filters) {
|
|
2693
|
+
for (const arg of filter.args) {
|
|
2694
|
+
if (isKeyValuePair(arg) && arg[1]) {
|
|
2695
|
+
yield* extractValueTokenVariables(arg[1]);
|
|
2696
|
+
}
|
|
2697
|
+
else if (isValueToken(arg)) {
|
|
2698
|
+
yield* extractValueTokenVariables(arg);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
function* extractValueTokenVariables(token) {
|
|
2704
|
+
if (isRangeToken(token)) {
|
|
2705
|
+
yield* extractValueTokenVariables(token.lhs);
|
|
2706
|
+
yield* extractValueTokenVariables(token.rhs);
|
|
2707
|
+
}
|
|
2708
|
+
else if (isPropertyAccessToken(token)) {
|
|
2709
|
+
yield extractPropertyAccessVariable(token);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
function extractPropertyAccessVariable(token) {
|
|
2713
|
+
const segments = [];
|
|
2714
|
+
// token is not guaranteed to have `file` set. We'll try to get it from a prop if not.
|
|
2715
|
+
let file = token.file;
|
|
2716
|
+
// Here we're flattening the first segment of a path if it is a nested path.
|
|
2717
|
+
const root = token.props[0];
|
|
2718
|
+
file = file || root.file;
|
|
2719
|
+
if (isQuotedToken(root) || isNumberToken(root) || isWordToken(root)) {
|
|
2720
|
+
segments.push(root.content);
|
|
2721
|
+
}
|
|
2722
|
+
else if (isPropertyAccessToken(root)) {
|
|
2723
|
+
// Flatten paths that start with a nested path.
|
|
2724
|
+
segments.push(...extractPropertyAccessVariable(root).segments);
|
|
2725
|
+
}
|
|
2726
|
+
for (const prop of token.props.slice(1)) {
|
|
2727
|
+
file = file || prop.file;
|
|
2728
|
+
if (isQuotedToken(prop) || isNumberToken(prop) || isWordToken(prop)) {
|
|
2729
|
+
segments.push(prop.content);
|
|
2730
|
+
}
|
|
2731
|
+
else if (isPropertyAccessToken(prop)) {
|
|
2732
|
+
segments.push(extractPropertyAccessVariable(prop));
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
const [row, col] = token.getPosition();
|
|
2736
|
+
return new Variable(segments, {
|
|
2737
|
+
row,
|
|
2738
|
+
col,
|
|
2739
|
+
file
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2742
|
+
// This is used to detect segments that can be represented with dot notation
|
|
2743
|
+
// when creating a string representation of VariableSegments.
|
|
2744
|
+
const RE_PROPERTY = /^[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*$/;
|
|
2745
|
+
/**
|
|
2746
|
+
* Return a string representation of segments using dot notation where possible.
|
|
2747
|
+
* @param segments - The property names and array indices that make up a path to a variable.
|
|
2748
|
+
* @param bracketedRoot - If false (the default), don't surround the root segment with square brackets.
|
|
2749
|
+
*/
|
|
2750
|
+
function segmentsString(segments, bracketedRoot = false) {
|
|
2751
|
+
const buf = [];
|
|
2752
|
+
const root = segments[0];
|
|
2753
|
+
if (isString(root)) {
|
|
2754
|
+
if (!bracketedRoot || root.match(RE_PROPERTY)) {
|
|
2755
|
+
buf.push(`${root}`);
|
|
2756
|
+
}
|
|
2757
|
+
else {
|
|
2758
|
+
buf.push(`['${root}']`);
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
for (const segment of segments.slice(1)) {
|
|
2762
|
+
if (segment instanceof Variable) {
|
|
2763
|
+
buf.push(`[${segmentsString(segment.segments)}]`);
|
|
2764
|
+
}
|
|
2765
|
+
else if (isString(segment)) {
|
|
2766
|
+
if (segment.match(RE_PROPERTY)) {
|
|
2767
|
+
buf.push(`.${segment}`);
|
|
2768
|
+
}
|
|
2769
|
+
else {
|
|
2770
|
+
buf.push(`['${segment}']`);
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
else {
|
|
2774
|
+
buf.push(`[${segment}]`);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
return buf.join('');
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2417
2780
|
var LookupType;
|
|
2418
2781
|
(function (LookupType) {
|
|
2419
2782
|
LookupType["Partials"] = "partials";
|
|
@@ -2613,6 +2976,10 @@ function isWordToken(val) {
|
|
|
2613
2976
|
function isRangeToken(val) {
|
|
2614
2977
|
return getKind(val) === TokenKind.Range;
|
|
2615
2978
|
}
|
|
2979
|
+
function isValueToken(val) {
|
|
2980
|
+
// valueTokenBitMask = TokenKind.Number | TokenKind.Literal | TokenKind.Quoted | TokenKind.PropertyAccess | TokenKind.Range
|
|
2981
|
+
return (getKind(val) & 1667) > 0;
|
|
2982
|
+
}
|
|
2616
2983
|
function getKind(val) {
|
|
2617
2984
|
return val ? val.kind : -1;
|
|
2618
2985
|
}
|
|
@@ -2629,7 +2996,8 @@ var typeGuards = /*#__PURE__*/Object.freeze({
|
|
|
2629
2996
|
isNumberToken: isNumberToken,
|
|
2630
2997
|
isPropertyAccessToken: isPropertyAccessToken,
|
|
2631
2998
|
isWordToken: isWordToken,
|
|
2632
|
-
isRangeToken: isRangeToken
|
|
2999
|
+
isRangeToken: isRangeToken,
|
|
3000
|
+
isValueToken: isValueToken
|
|
2633
3001
|
});
|
|
2634
3002
|
|
|
2635
3003
|
class Context {
|
|
@@ -2641,6 +3009,8 @@ class Context {
|
|
|
2641
3009
|
*/
|
|
2642
3010
|
this.scopes = [{}];
|
|
2643
3011
|
this.registers = {};
|
|
3012
|
+
this.breakCalled = false;
|
|
3013
|
+
this.continueCalled = false;
|
|
2644
3014
|
this.sync = !!renderOptions.sync;
|
|
2645
3015
|
this.opts = opts;
|
|
2646
3016
|
this.globals = (_a = renderOptions.globals) !== null && _a !== void 0 ? _a : opts.globals;
|
|
@@ -2676,7 +3046,7 @@ class Context {
|
|
|
2676
3046
|
return toValueSync(this._get(paths));
|
|
2677
3047
|
}
|
|
2678
3048
|
*_get(paths) {
|
|
2679
|
-
const scope = this.findScope(paths[0]);
|
|
3049
|
+
const scope = this.findScope(paths[0]); // first prop should always be a string
|
|
2680
3050
|
return yield this._getFromScope(scope, paths);
|
|
2681
3051
|
}
|
|
2682
3052
|
/**
|
|
@@ -2728,6 +3098,7 @@ class Context {
|
|
|
2728
3098
|
}
|
|
2729
3099
|
function readProperty(obj, key, ownPropertyOnly) {
|
|
2730
3100
|
obj = toLiquid(obj);
|
|
3101
|
+
key = toValue(key);
|
|
2731
3102
|
if (isNil(obj))
|
|
2732
3103
|
return obj;
|
|
2733
3104
|
if (isArray(obj) && key < 0)
|
|
@@ -2875,8 +3246,8 @@ const join = argumentsToValue(function (v, arg) {
|
|
|
2875
3246
|
this.context.memoryLimit.use(complexity);
|
|
2876
3247
|
return array.join(sep);
|
|
2877
3248
|
});
|
|
2878
|
-
const last$1 = argumentsToValue((v) =>
|
|
2879
|
-
const first = argumentsToValue((v) =>
|
|
3249
|
+
const last$1 = argumentsToValue((v) => isArrayLike(v) ? last(v) : '');
|
|
3250
|
+
const first = argumentsToValue((v) => isArrayLike(v) ? v[0] : '');
|
|
2880
3251
|
const reverse = argumentsToValue(function (v) {
|
|
2881
3252
|
const array = toArray(v);
|
|
2882
3253
|
this.context.memoryLimit.use(array.length);
|
|
@@ -2977,10 +3348,13 @@ function* where(arr, property, expected) {
|
|
|
2977
3348
|
for (const item of arr) {
|
|
2978
3349
|
values.push(yield evalToken(token, this.context.spawn(item)));
|
|
2979
3350
|
}
|
|
3351
|
+
const matcher = this.context.opts.jekyllWhere
|
|
3352
|
+
? (v) => EmptyDrop.is(expected) ? equals(v, expected) : (isArray(v) ? arrayIncludes(v, expected) : equals(v, expected))
|
|
3353
|
+
: (v) => equals(v, expected);
|
|
2980
3354
|
return arr.filter((_, i) => {
|
|
2981
3355
|
if (expected === undefined)
|
|
2982
3356
|
return isTruthy(values[i], this.context);
|
|
2983
|
-
return
|
|
3357
|
+
return matcher(values[i]);
|
|
2984
3358
|
});
|
|
2985
3359
|
}
|
|
2986
3360
|
function* where_exp(arr, itemName, exp) {
|
|
@@ -2997,7 +3371,7 @@ function* where_exp(arr, itemName, exp) {
|
|
|
2997
3371
|
}
|
|
2998
3372
|
function* group_by(arr, property) {
|
|
2999
3373
|
const map = new Map();
|
|
3000
|
-
arr =
|
|
3374
|
+
arr = toEnumerable(arr);
|
|
3001
3375
|
const token = new Tokenizer(stringify(property)).readScopeValue();
|
|
3002
3376
|
this.context.memoryLimit.use(arr.length);
|
|
3003
3377
|
for (const item of arr) {
|
|
@@ -3011,7 +3385,7 @@ function* group_by(arr, property) {
|
|
|
3011
3385
|
function* group_by_exp(arr, itemName, exp) {
|
|
3012
3386
|
const map = new Map();
|
|
3013
3387
|
const keyTemplate = new Value(stringify(exp), this.liquid);
|
|
3014
|
-
arr =
|
|
3388
|
+
arr = toEnumerable(arr);
|
|
3015
3389
|
this.context.memoryLimit.use(arr.length);
|
|
3016
3390
|
for (const item of arr) {
|
|
3017
3391
|
const key = yield keyTemplate.value(this.context.spawn({ [itemName]: item }));
|
|
@@ -3364,7 +3738,8 @@ const filters = Object.assign(Object.assign(Object.assign(Object.assign(Object.a
|
|
|
3364
3738
|
class AssignTag extends Tag {
|
|
3365
3739
|
constructor(token, remainTokens, liquid) {
|
|
3366
3740
|
super(token, remainTokens, liquid);
|
|
3367
|
-
this.
|
|
3741
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
3742
|
+
this.key = this.identifier.content;
|
|
3368
3743
|
this.tokenizer.assert(this.key, 'expected variable name');
|
|
3369
3744
|
this.tokenizer.skipBlank();
|
|
3370
3745
|
this.tokenizer.assert(this.tokenizer.peek() === '=', 'expected "="');
|
|
@@ -3374,6 +3749,12 @@ class AssignTag extends Tag {
|
|
|
3374
3749
|
*render(ctx) {
|
|
3375
3750
|
ctx.bottom()[this.key] = yield this.value.value(ctx, this.liquid.options.lenientIf);
|
|
3376
3751
|
}
|
|
3752
|
+
*arguments() {
|
|
3753
|
+
yield this.value;
|
|
3754
|
+
}
|
|
3755
|
+
*localScope() {
|
|
3756
|
+
yield this.identifier;
|
|
3757
|
+
}
|
|
3377
3758
|
}
|
|
3378
3759
|
|
|
3379
3760
|
const MODIFIERS = ['offset', 'limit', 'reversed'];
|
|
@@ -3388,7 +3769,7 @@ class ForTag extends Tag {
|
|
|
3388
3769
|
}
|
|
3389
3770
|
this.variable = variable.content;
|
|
3390
3771
|
this.collection = collection;
|
|
3391
|
-
this.hash = new Hash(this.tokenizer
|
|
3772
|
+
this.hash = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3392
3773
|
this.templates = [];
|
|
3393
3774
|
this.elseTemplates = [];
|
|
3394
3775
|
let p;
|
|
@@ -3426,16 +3807,33 @@ class ForTag extends Tag {
|
|
|
3426
3807
|
ctx.push(scope);
|
|
3427
3808
|
for (const item of collection) {
|
|
3428
3809
|
scope[this.variable] = item;
|
|
3810
|
+
ctx.continueCalled = ctx.breakCalled = false;
|
|
3429
3811
|
yield r.renderTemplates(this.templates, ctx, emitter);
|
|
3430
|
-
if (
|
|
3431
|
-
emitter['break'] = false;
|
|
3812
|
+
if (ctx.breakCalled)
|
|
3432
3813
|
break;
|
|
3433
|
-
}
|
|
3434
|
-
emitter['continue'] = false;
|
|
3435
3814
|
scope.forloop.next();
|
|
3436
3815
|
}
|
|
3816
|
+
ctx.continueCalled = ctx.breakCalled = false;
|
|
3437
3817
|
ctx.pop();
|
|
3438
3818
|
}
|
|
3819
|
+
*children() {
|
|
3820
|
+
const templates = this.templates.slice();
|
|
3821
|
+
if (this.elseTemplates) {
|
|
3822
|
+
templates.push(...this.elseTemplates);
|
|
3823
|
+
}
|
|
3824
|
+
return templates;
|
|
3825
|
+
}
|
|
3826
|
+
*arguments() {
|
|
3827
|
+
yield this.collection;
|
|
3828
|
+
for (const v of Object.values(this.hash.hash)) {
|
|
3829
|
+
if (isValueToken(v)) {
|
|
3830
|
+
yield v;
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
blockScope() {
|
|
3835
|
+
return [this.variable, 'forloop'];
|
|
3836
|
+
}
|
|
3439
3837
|
}
|
|
3440
3838
|
function reversed(arr) {
|
|
3441
3839
|
return [...arr].reverse();
|
|
@@ -3451,7 +3849,8 @@ class CaptureTag extends Tag {
|
|
|
3451
3849
|
constructor(tagToken, remainTokens, liquid, parser) {
|
|
3452
3850
|
super(tagToken, remainTokens, liquid);
|
|
3453
3851
|
this.templates = [];
|
|
3454
|
-
this.
|
|
3852
|
+
this.identifier = this.readVariable();
|
|
3853
|
+
this.variable = this.identifier.content;
|
|
3455
3854
|
while (remainTokens.length) {
|
|
3456
3855
|
const token = remainTokens.shift();
|
|
3457
3856
|
if (isTagToken(token) && token.name === 'endcapture')
|
|
@@ -3460,19 +3859,25 @@ class CaptureTag extends Tag {
|
|
|
3460
3859
|
}
|
|
3461
3860
|
throw new Error(`tag ${tagToken.getText()} not closed`);
|
|
3462
3861
|
}
|
|
3862
|
+
readVariable() {
|
|
3863
|
+
let ident = this.tokenizer.readIdentifier();
|
|
3864
|
+
if (ident.content)
|
|
3865
|
+
return ident;
|
|
3866
|
+
ident = this.tokenizer.readQuoted();
|
|
3867
|
+
if (ident)
|
|
3868
|
+
return ident;
|
|
3869
|
+
throw this.tokenizer.error('invalid capture name');
|
|
3870
|
+
}
|
|
3463
3871
|
*render(ctx) {
|
|
3464
3872
|
const r = this.liquid.renderer;
|
|
3465
3873
|
const html = yield r.renderTemplates(this.templates, ctx);
|
|
3466
3874
|
ctx.bottom()[this.variable] = html;
|
|
3467
3875
|
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
if (quoted)
|
|
3474
|
-
return evalQuotedToken(quoted);
|
|
3475
|
-
throw this.tokenizer.error('invalid capture name');
|
|
3876
|
+
*children() {
|
|
3877
|
+
return this.templates;
|
|
3878
|
+
}
|
|
3879
|
+
*localScope() {
|
|
3880
|
+
yield this.identifier;
|
|
3476
3881
|
}
|
|
3477
3882
|
}
|
|
3478
3883
|
|
|
@@ -3540,6 +3945,17 @@ class CaseTag extends Tag {
|
|
|
3540
3945
|
yield r.renderTemplates(this.elseTemplates, ctx, emitter);
|
|
3541
3946
|
}
|
|
3542
3947
|
}
|
|
3948
|
+
*arguments() {
|
|
3949
|
+
yield this.value;
|
|
3950
|
+
yield* this.branches.flatMap(b => b.values);
|
|
3951
|
+
}
|
|
3952
|
+
*children() {
|
|
3953
|
+
const templates = this.branches.flatMap(b => b.templates);
|
|
3954
|
+
if (this.elseTemplates) {
|
|
3955
|
+
templates.push(...this.elseTemplates);
|
|
3956
|
+
}
|
|
3957
|
+
return templates;
|
|
3958
|
+
}
|
|
3543
3959
|
}
|
|
3544
3960
|
|
|
3545
3961
|
class CommentTag extends Tag {
|
|
@@ -3593,7 +4009,7 @@ class RenderTag extends Tag {
|
|
|
3593
4009
|
tokenizer.p = begin;
|
|
3594
4010
|
break;
|
|
3595
4011
|
}
|
|
3596
|
-
this.hash = new Hash(tokenizer
|
|
4012
|
+
this.hash = new Hash(tokenizer, liquid.options.keyValueSeparator);
|
|
3597
4013
|
}
|
|
3598
4014
|
*render(ctx, emitter) {
|
|
3599
4015
|
const { liquid, hash } = this;
|
|
@@ -3622,6 +4038,55 @@ class RenderTag extends Tag {
|
|
|
3622
4038
|
yield liquid.renderer.renderTemplates(templates, childCtx, emitter);
|
|
3623
4039
|
}
|
|
3624
4040
|
}
|
|
4041
|
+
*children(partials, sync) {
|
|
4042
|
+
if (partials && isString(this['file'])) {
|
|
4043
|
+
return (yield this.liquid._parsePartialFile(this['file'], sync, this['currentFile']));
|
|
4044
|
+
}
|
|
4045
|
+
return [];
|
|
4046
|
+
}
|
|
4047
|
+
partialScope() {
|
|
4048
|
+
if (isString(this['file'])) {
|
|
4049
|
+
const names = Object.keys(this.hash.hash);
|
|
4050
|
+
if (this['with']) {
|
|
4051
|
+
const { value, alias } = this['with'];
|
|
4052
|
+
if (isString(alias)) {
|
|
4053
|
+
names.push([alias, value]);
|
|
4054
|
+
}
|
|
4055
|
+
else if (isString(this.file)) {
|
|
4056
|
+
names.push([this.file, value]);
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
if (this['for']) {
|
|
4060
|
+
const { value, alias } = this['for'];
|
|
4061
|
+
if (isString(alias)) {
|
|
4062
|
+
names.push([alias, value]);
|
|
4063
|
+
}
|
|
4064
|
+
else if (isString(this.file)) {
|
|
4065
|
+
names.push([this.file, value]);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
return { name: this['file'], isolated: true, scope: names };
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
*arguments() {
|
|
4072
|
+
for (const v of Object.values(this.hash.hash)) {
|
|
4073
|
+
if (isValueToken(v)) {
|
|
4074
|
+
yield v;
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
if (this['with']) {
|
|
4078
|
+
const { value } = this['with'];
|
|
4079
|
+
if (isValueToken(value)) {
|
|
4080
|
+
yield value;
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
if (this['for']) {
|
|
4084
|
+
const { value } = this['for'];
|
|
4085
|
+
if (isValueToken(value)) {
|
|
4086
|
+
yield value;
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
3625
4090
|
}
|
|
3626
4091
|
/**
|
|
3627
4092
|
* @return null for "none",
|
|
@@ -3678,7 +4143,7 @@ class IncludeTag extends Tag {
|
|
|
3678
4143
|
}
|
|
3679
4144
|
else
|
|
3680
4145
|
tokenizer.p = begin;
|
|
3681
|
-
this.hash = new Hash(tokenizer
|
|
4146
|
+
this.hash = new Hash(tokenizer, liquid.options.jekyllInclude || liquid.options.keyValueSeparator);
|
|
3682
4147
|
}
|
|
3683
4148
|
*render(ctx, emitter) {
|
|
3684
4149
|
const { liquid, hash, withVar } = this;
|
|
@@ -3697,12 +4162,43 @@ class IncludeTag extends Tag {
|
|
|
3697
4162
|
ctx.pop();
|
|
3698
4163
|
ctx.restoreRegister(saved);
|
|
3699
4164
|
}
|
|
4165
|
+
*children(partials, sync) {
|
|
4166
|
+
if (partials && isString(this['file'])) {
|
|
4167
|
+
return (yield this.liquid._parsePartialFile(this['file'], sync, this['currentFile']));
|
|
4168
|
+
}
|
|
4169
|
+
return [];
|
|
4170
|
+
}
|
|
4171
|
+
partialScope() {
|
|
4172
|
+
if (isString(this['file'])) {
|
|
4173
|
+
let names;
|
|
4174
|
+
if (this.liquid.options.jekyllInclude) {
|
|
4175
|
+
names = ['include'];
|
|
4176
|
+
}
|
|
4177
|
+
else {
|
|
4178
|
+
names = Object.keys(this.hash.hash);
|
|
4179
|
+
if (this.withVar) {
|
|
4180
|
+
names.push([this['file'], this.withVar]);
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
return { name: this['file'], isolated: false, scope: names };
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
*arguments() {
|
|
4187
|
+
yield* Object.values(this.hash.hash).filter(isValueToken);
|
|
4188
|
+
if (isValueToken(this['file'])) {
|
|
4189
|
+
yield this['file'];
|
|
4190
|
+
}
|
|
4191
|
+
if (isValueToken(this.withVar)) {
|
|
4192
|
+
yield this.withVar;
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
3700
4195
|
}
|
|
3701
4196
|
|
|
3702
4197
|
class DecrementTag extends Tag {
|
|
3703
4198
|
constructor(token, remainTokens, liquid) {
|
|
3704
4199
|
super(token, remainTokens, liquid);
|
|
3705
|
-
this.
|
|
4200
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
4201
|
+
this.variable = this.identifier.content;
|
|
3706
4202
|
}
|
|
3707
4203
|
render(context, emitter) {
|
|
3708
4204
|
const scope = context.environments;
|
|
@@ -3711,6 +4207,9 @@ class DecrementTag extends Tag {
|
|
|
3711
4207
|
}
|
|
3712
4208
|
emitter.write(stringify(--scope[this.variable]));
|
|
3713
4209
|
}
|
|
4210
|
+
*localScope() {
|
|
4211
|
+
yield this.identifier;
|
|
4212
|
+
}
|
|
3714
4213
|
}
|
|
3715
4214
|
|
|
3716
4215
|
class CycleTag extends Tag {
|
|
@@ -3748,6 +4247,12 @@ class CycleTag extends Tag {
|
|
|
3748
4247
|
groups[fingerprint] = idx;
|
|
3749
4248
|
return yield evalToken(candidate, ctx);
|
|
3750
4249
|
}
|
|
4250
|
+
*arguments() {
|
|
4251
|
+
yield* this.candidates;
|
|
4252
|
+
if (this.group) {
|
|
4253
|
+
yield this.group;
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
3751
4256
|
}
|
|
3752
4257
|
|
|
3753
4258
|
class IfTag extends Tag {
|
|
@@ -3757,13 +4262,13 @@ class IfTag extends Tag {
|
|
|
3757
4262
|
let p = [];
|
|
3758
4263
|
parser.parseStream(remainTokens)
|
|
3759
4264
|
.on('start', () => this.branches.push({
|
|
3760
|
-
value: new Value(tagToken.
|
|
4265
|
+
value: new Value(tagToken.tokenizer.readFilteredValue(), this.liquid),
|
|
3761
4266
|
templates: (p = [])
|
|
3762
4267
|
}))
|
|
3763
4268
|
.on('tag:elsif', (token) => {
|
|
3764
4269
|
assert(!this.elseTemplates, 'unexpected elsif after else');
|
|
3765
4270
|
this.branches.push({
|
|
3766
|
-
value: new Value(token.
|
|
4271
|
+
value: new Value(token.tokenizer.readFilteredValue(), this.liquid),
|
|
3767
4272
|
templates: (p = [])
|
|
3768
4273
|
});
|
|
3769
4274
|
})
|
|
@@ -3788,12 +4293,23 @@ class IfTag extends Tag {
|
|
|
3788
4293
|
}
|
|
3789
4294
|
yield r.renderTemplates(this.elseTemplates || [], ctx, emitter);
|
|
3790
4295
|
}
|
|
4296
|
+
*children() {
|
|
4297
|
+
const templates = this.branches.flatMap(b => b.templates);
|
|
4298
|
+
if (this.elseTemplates) {
|
|
4299
|
+
templates.push(...this.elseTemplates);
|
|
4300
|
+
}
|
|
4301
|
+
return templates;
|
|
4302
|
+
}
|
|
4303
|
+
arguments() {
|
|
4304
|
+
return this.branches.map(b => b.value);
|
|
4305
|
+
}
|
|
3791
4306
|
}
|
|
3792
4307
|
|
|
3793
4308
|
class IncrementTag extends Tag {
|
|
3794
4309
|
constructor(token, remainTokens, liquid) {
|
|
3795
4310
|
super(token, remainTokens, liquid);
|
|
3796
|
-
this.
|
|
4311
|
+
this.identifier = this.tokenizer.readIdentifier();
|
|
4312
|
+
this.variable = this.identifier.content;
|
|
3797
4313
|
}
|
|
3798
4314
|
render(context, emitter) {
|
|
3799
4315
|
const scope = context.environments;
|
|
@@ -3804,6 +4320,9 @@ class IncrementTag extends Tag {
|
|
|
3804
4320
|
scope[this.variable]++;
|
|
3805
4321
|
emitter.write(stringify(val));
|
|
3806
4322
|
}
|
|
4323
|
+
*localScope() {
|
|
4324
|
+
yield this.identifier;
|
|
4325
|
+
}
|
|
3807
4326
|
}
|
|
3808
4327
|
|
|
3809
4328
|
class LayoutTag extends Tag {
|
|
@@ -3811,7 +4330,7 @@ class LayoutTag extends Tag {
|
|
|
3811
4330
|
super(token, remainTokens, liquid);
|
|
3812
4331
|
this.file = parseFilePath(this.tokenizer, this.liquid, parser);
|
|
3813
4332
|
this['currentFile'] = token.file;
|
|
3814
|
-
this.args = new Hash(this.tokenizer
|
|
4333
|
+
this.args = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3815
4334
|
this.templates = parser.parseTokens(remainTokens);
|
|
3816
4335
|
}
|
|
3817
4336
|
*render(ctx, emitter) {
|
|
@@ -3838,6 +4357,28 @@ class LayoutTag extends Tag {
|
|
|
3838
4357
|
yield renderer.renderTemplates(templates, ctx, emitter);
|
|
3839
4358
|
ctx.pop();
|
|
3840
4359
|
}
|
|
4360
|
+
*children(partials) {
|
|
4361
|
+
const templates = this.templates.slice();
|
|
4362
|
+
if (partials && isString(this.file)) {
|
|
4363
|
+
templates.push(...(yield this.liquid._parsePartialFile(this.file, true, this['currentFile'])));
|
|
4364
|
+
}
|
|
4365
|
+
return templates;
|
|
4366
|
+
}
|
|
4367
|
+
*arguments() {
|
|
4368
|
+
for (const v of Object.values(this.args.hash)) {
|
|
4369
|
+
if (isValueToken(v)) {
|
|
4370
|
+
yield v;
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
if (isValueToken(this.file)) {
|
|
4374
|
+
yield this.file;
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
4377
|
+
partialScope() {
|
|
4378
|
+
if (isString(this.file)) {
|
|
4379
|
+
return { name: this.file, isolated: false, scope: Object.keys(this.args.hash) };
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
3841
4382
|
}
|
|
3842
4383
|
|
|
3843
4384
|
class BlockTag extends Tag {
|
|
@@ -3877,6 +4418,12 @@ class BlockTag extends Tag {
|
|
|
3877
4418
|
? (superBlock, emitter) => renderChild(new BlockDrop(() => renderCurrent(superBlock, emitter)), emitter)
|
|
3878
4419
|
: renderCurrent;
|
|
3879
4420
|
}
|
|
4421
|
+
*children() {
|
|
4422
|
+
return this.templates;
|
|
4423
|
+
}
|
|
4424
|
+
blockScope() {
|
|
4425
|
+
return ['block'];
|
|
4426
|
+
}
|
|
3880
4427
|
}
|
|
3881
4428
|
|
|
3882
4429
|
class RawTag extends Tag {
|
|
@@ -3931,7 +4478,7 @@ class TablerowTag extends Tag {
|
|
|
3931
4478
|
}
|
|
3932
4479
|
this.variable = variable.content;
|
|
3933
4480
|
this.collection = collectionToken;
|
|
3934
|
-
this.args = new Hash(this.tokenizer
|
|
4481
|
+
this.args = new Hash(this.tokenizer, liquid.options.keyValueSeparator);
|
|
3935
4482
|
this.templates = [];
|
|
3936
4483
|
let p;
|
|
3937
4484
|
const stream = parser.parseStream(remainTokens)
|
|
@@ -3969,6 +4516,20 @@ class TablerowTag extends Tag {
|
|
|
3969
4516
|
emitter.write('</tr>');
|
|
3970
4517
|
ctx.pop();
|
|
3971
4518
|
}
|
|
4519
|
+
*children() {
|
|
4520
|
+
return this.templates;
|
|
4521
|
+
}
|
|
4522
|
+
*arguments() {
|
|
4523
|
+
yield this.collection;
|
|
4524
|
+
for (const v of Object.values(this.args.hash)) {
|
|
4525
|
+
if (isValueToken(v)) {
|
|
4526
|
+
yield v;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
blockScope() {
|
|
4531
|
+
return [this.variable, 'tablerowloop'];
|
|
4532
|
+
}
|
|
3972
4533
|
}
|
|
3973
4534
|
|
|
3974
4535
|
class UnlessTag extends Tag {
|
|
@@ -3980,7 +4541,7 @@ class UnlessTag extends Tag {
|
|
|
3980
4541
|
let elseCount = 0;
|
|
3981
4542
|
parser.parseStream(remainTokens)
|
|
3982
4543
|
.on('start', () => this.branches.push({
|
|
3983
|
-
value: new Value(tagToken.
|
|
4544
|
+
value: new Value(tagToken.tokenizer.readFilteredValue(), this.liquid),
|
|
3984
4545
|
test: isFalsy,
|
|
3985
4546
|
templates: (p = [])
|
|
3986
4547
|
}))
|
|
@@ -3990,7 +4551,7 @@ class UnlessTag extends Tag {
|
|
|
3990
4551
|
return;
|
|
3991
4552
|
}
|
|
3992
4553
|
this.branches.push({
|
|
3993
|
-
value: new Value(token.
|
|
4554
|
+
value: new Value(token.tokenizer.readFilteredValue(), this.liquid),
|
|
3994
4555
|
test: isTruthy,
|
|
3995
4556
|
templates: (p = [])
|
|
3996
4557
|
});
|
|
@@ -4019,17 +4580,27 @@ class UnlessTag extends Tag {
|
|
|
4019
4580
|
}
|
|
4020
4581
|
yield r.renderTemplates(this.elseTemplates, ctx, emitter);
|
|
4021
4582
|
}
|
|
4583
|
+
*children() {
|
|
4584
|
+
const children = this.branches.flatMap(b => b.templates);
|
|
4585
|
+
if (this.elseTemplates) {
|
|
4586
|
+
children.push(...this.elseTemplates);
|
|
4587
|
+
}
|
|
4588
|
+
return children;
|
|
4589
|
+
}
|
|
4590
|
+
arguments() {
|
|
4591
|
+
return this.branches.map(b => b.value);
|
|
4592
|
+
}
|
|
4022
4593
|
}
|
|
4023
4594
|
|
|
4024
4595
|
class BreakTag extends Tag {
|
|
4025
|
-
render(ctx,
|
|
4026
|
-
|
|
4596
|
+
render(ctx, _emitter) {
|
|
4597
|
+
ctx.breakCalled = true;
|
|
4027
4598
|
}
|
|
4028
4599
|
}
|
|
4029
4600
|
|
|
4030
4601
|
class ContinueTag extends Tag {
|
|
4031
|
-
render(ctx,
|
|
4032
|
-
|
|
4602
|
+
render(ctx, _emitter) {
|
|
4603
|
+
ctx.continueCalled = true;
|
|
4033
4604
|
}
|
|
4034
4605
|
}
|
|
4035
4606
|
|
|
@@ -4047,6 +4618,11 @@ class EchoTag extends Tag {
|
|
|
4047
4618
|
const val = yield this.value.value(ctx, false);
|
|
4048
4619
|
emitter.write(val);
|
|
4049
4620
|
}
|
|
4621
|
+
*arguments() {
|
|
4622
|
+
if (this.value) {
|
|
4623
|
+
yield this.value;
|
|
4624
|
+
}
|
|
4625
|
+
}
|
|
4050
4626
|
}
|
|
4051
4627
|
|
|
4052
4628
|
class LiquidTag extends Tag {
|
|
@@ -4058,6 +4634,9 @@ class LiquidTag extends Tag {
|
|
|
4058
4634
|
*render(ctx, emitter) {
|
|
4059
4635
|
yield this.liquid.renderer.renderTemplates(this.templates, ctx, emitter);
|
|
4060
4636
|
}
|
|
4637
|
+
*children() {
|
|
4638
|
+
return this.templates;
|
|
4639
|
+
}
|
|
4061
4640
|
}
|
|
4062
4641
|
|
|
4063
4642
|
class InlineCommentTag extends Tag {
|
|
@@ -4208,9 +4787,97 @@ class Liquid {
|
|
|
4208
4787
|
self.renderFile(filePath, ctx).then(html => callback(null, html), callback);
|
|
4209
4788
|
};
|
|
4210
4789
|
}
|
|
4790
|
+
analyze(template, options = {}) {
|
|
4791
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4792
|
+
return analyze(template, options);
|
|
4793
|
+
});
|
|
4794
|
+
}
|
|
4795
|
+
analyzeSync(template, options = {}) {
|
|
4796
|
+
return analyzeSync(template, options);
|
|
4797
|
+
}
|
|
4798
|
+
parseAndAnalyze(html, filename, options = {}) {
|
|
4799
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4800
|
+
return analyze(this.parse(html, filename), options);
|
|
4801
|
+
});
|
|
4802
|
+
}
|
|
4803
|
+
parseAndAnalyzeSync(html, filename, options = {}) {
|
|
4804
|
+
return analyzeSync(this.parse(html, filename), options);
|
|
4805
|
+
}
|
|
4806
|
+
/** Return an array of all variables without their properties. */
|
|
4807
|
+
variables(template, options = {}) {
|
|
4808
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4809
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4810
|
+
return Object.keys(analysis.variables);
|
|
4811
|
+
});
|
|
4812
|
+
}
|
|
4813
|
+
/** Return an array of all variables without their properties. */
|
|
4814
|
+
variablesSync(template, options = {}) {
|
|
4815
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4816
|
+
return Object.keys(analysis.variables);
|
|
4817
|
+
}
|
|
4818
|
+
/** Return an array of all variables including their properties/paths. */
|
|
4819
|
+
fullVariables(template, options = {}) {
|
|
4820
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4821
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4822
|
+
return Array.from(new Set(Object.values(analysis.variables).flatMap((a) => a.map((v) => String(v)))));
|
|
4823
|
+
});
|
|
4824
|
+
}
|
|
4825
|
+
/** Return an array of all variables including their properties/paths. */
|
|
4826
|
+
fullVariablesSync(template, options = {}) {
|
|
4827
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4828
|
+
return Array.from(new Set(Object.values(analysis.variables).flatMap((a) => a.map((v) => String(v)))));
|
|
4829
|
+
}
|
|
4830
|
+
/** Return an array of all variables, each as an array of properties/segments. */
|
|
4831
|
+
variableSegments(template, options = {}) {
|
|
4832
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4833
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4834
|
+
return Array.from(strictUniq(Object.values(analysis.variables).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4835
|
+
});
|
|
4836
|
+
}
|
|
4837
|
+
/** Return an array of all variables, each as an array of properties/segments. */
|
|
4838
|
+
variableSegmentsSync(template, options = {}) {
|
|
4839
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4840
|
+
return Array.from(strictUniq(Object.values(analysis.variables).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4841
|
+
}
|
|
4842
|
+
/** Return an array of all expected context variables without their properties. */
|
|
4843
|
+
globalVariables(template, options = {}) {
|
|
4844
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4845
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4846
|
+
return Object.keys(analysis.globals);
|
|
4847
|
+
});
|
|
4848
|
+
}
|
|
4849
|
+
/** Return an array of all expected context variables without their properties. */
|
|
4850
|
+
globalVariablesSync(template, options = {}) {
|
|
4851
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4852
|
+
return Object.keys(analysis.globals);
|
|
4853
|
+
}
|
|
4854
|
+
/** Return an array of all expected context variables including their properties/paths. */
|
|
4855
|
+
globalFullVariables(template, options = {}) {
|
|
4856
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4857
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4858
|
+
return Array.from(new Set(Object.values(analysis.globals).flatMap((a) => a.map((v) => String(v)))));
|
|
4859
|
+
});
|
|
4860
|
+
}
|
|
4861
|
+
/** Return an array of all expected context variables including their properties/paths. */
|
|
4862
|
+
globalFullVariablesSync(template, options = {}) {
|
|
4863
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4864
|
+
return Array.from(new Set(Object.values(analysis.globals).flatMap((a) => a.map((v) => String(v)))));
|
|
4865
|
+
}
|
|
4866
|
+
/** Return an array of all expected context variables, each as an array of properties/segments. */
|
|
4867
|
+
globalVariableSegments(template, options = {}) {
|
|
4868
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4869
|
+
const analysis = yield analyze(isString(template) ? this.parse(template) : template, options);
|
|
4870
|
+
return Array.from(strictUniq(Object.values(analysis.globals).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4871
|
+
});
|
|
4872
|
+
}
|
|
4873
|
+
/** Return an array of all expected context variables, each as an array of properties/segments. */
|
|
4874
|
+
globalVariableSegmentsSync(template, options = {}) {
|
|
4875
|
+
const analysis = analyzeSync(isString(template) ? this.parse(template) : template, options);
|
|
4876
|
+
return Array.from(strictUniq(Object.values(analysis.globals).flatMap((a) => a.map((v) => v.toArray()))));
|
|
4877
|
+
}
|
|
4211
4878
|
}
|
|
4212
4879
|
|
|
4213
4880
|
/* istanbul ignore file */
|
|
4214
4881
|
const version = '[VI]{version}[/VI]';
|
|
4215
4882
|
|
|
4216
|
-
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 };
|
|
4883
|
+
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 };
|