@platformos/liquid-html-parser 0.0.8 → 0.0.10

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.
@@ -62,6 +62,7 @@ export declare enum ConcreteNodeTypes {
62
62
  Comparison = "Comparison",
63
63
  Condition = "Condition",
64
64
  AssignMarkup = "AssignMarkup",
65
+ AssignPushRhs = "AssignPushRhs",
65
66
  HashAssignMarkup = "HashAssignMarkup",
66
67
  ContentForMarkup = "ContentForMarkup",
67
68
  CycleMarkup = "CycleMarkup",
@@ -262,11 +263,15 @@ export interface ConcreteLiquidTagLiquid extends ConcreteLiquidTagNode<NamedTags
262
263
  export type ConcreteLiquidLiquidTagNode = ConcreteLiquidTagOpen | ConcreteLiquidTagClose | ConcreteLiquidTag | ConcreteLiquidRawTag;
263
264
  export interface ConcreteLiquidTagAssign extends ConcreteLiquidTagNode<NamedTags.assign, ConcreteLiquidTagAssignMarkup> {
264
265
  }
266
+ export interface ConcreteLiquidTagAssignPushRhs extends ConcreteBasicNode<ConcreteNodeTypes.AssignPushRhs> {
267
+ pushSource: ConcreteLiquidVariable;
268
+ pushValue: ConcreteLiquidVariable;
269
+ }
265
270
  export interface ConcreteLiquidTagAssignMarkup extends ConcreteBasicNode<ConcreteNodeTypes.AssignMarkup> {
266
271
  name: string;
267
272
  target: ConcreteLiquidVariableLookup;
268
273
  operator: string;
269
- value: ConcreteLiquidVariable;
274
+ value: ConcreteLiquidVariable | ConcreteLiquidTagAssignPushRhs;
270
275
  }
271
276
  export interface ConcreteLiquidTagHashAssign extends ConcreteLiquidTagNode<NamedTags.hash_assign, ConcreteLiquidTagHashAssignMarkup> {
272
277
  }
@@ -338,7 +343,7 @@ export interface ConcreteLiquidTagContentForMarkup extends ConcreteBasicNode<Con
338
343
  contentForType: ConcreteStringLiteral;
339
344
  }
340
345
  export interface ConcreteLiquidTagRenderMarkup extends ConcreteBasicNode<ConcreteNodeTypes.RenderMarkup> {
341
- snippet: ConcreteStringLiteral | ConcreteLiquidVariableLookup;
346
+ partial: ConcreteStringLiteral | ConcreteLiquidVariableLookup;
342
347
  variable: ConcreteRenderVariableExpression | null;
343
348
  alias: ConcreteRenderAliasExpression | null;
344
349
  renderArguments: ConcreteLiquidNamedArgument[];
@@ -416,7 +421,7 @@ export interface ConcreteLiquidFilter extends ConcreteBasicNode<ConcreteNodeType
416
421
  export type ConcreteLiquidArgument = ConcreteLiquidExpression | ConcreteLiquidNamedArgument;
417
422
  export interface ConcreteLiquidNamedArgument extends ConcreteBasicNode<ConcreteNodeTypes.NamedArgument> {
418
423
  name: string;
419
- value: ConcreteLiquidExpression;
424
+ value: ConcreteLiquidExpression | ConcreteLiquidVariable;
420
425
  }
421
426
  export type ConcreteLiquidExpression = ConcreteStringLiteral | ConcreteNumberLiteral | ConcreteLiquidLiteral | ConcreteLiquidRange | ConcreteLiquidVariableLookup | ConcreteJsonHashLiteral | ConcreteJsonArrayLiteral;
422
427
  export type ConcreteComplexLiquidExpression = ConcreteLiquidBooleanExpression | ConcreteLiquidExpression;
@@ -452,7 +457,7 @@ export interface ConcreteJsonKeyValuePair extends ConcreteBasicNode<ConcreteNode
452
457
  export interface ConcreteJsonArrayLiteral extends ConcreteBasicNode<ConcreteNodeTypes.JsonArrayLiteral> {
453
458
  elements: ConcreteJsonValue[];
454
459
  }
455
- export type ConcreteJsonValue = ConcreteJsonHashLiteral | ConcreteJsonArrayLiteral | ConcreteLiquidExpression;
460
+ export type ConcreteJsonValue = ConcreteJsonHashLiteral | ConcreteJsonArrayLiteral | ConcreteLiquidVariable | ConcreteLiquidExpression;
456
461
  export type ConcreteHtmlNode = ConcreteHtmlDoctype | ConcreteHtmlComment | ConcreteHtmlRawTag | ConcreteHtmlVoidElement | ConcreteHtmlSelfClosingElement | ConcreteHtmlTagOpen | ConcreteHtmlTagClose;
457
462
  export interface ConcreteTextNode extends ConcreteBasicNode<ConcreteNodeTypes.TextNode> {
458
463
  value: string;
@@ -70,6 +70,7 @@ var ConcreteNodeTypes;
70
70
  ConcreteNodeTypes["Comparison"] = "Comparison";
71
71
  ConcreteNodeTypes["Condition"] = "Condition";
72
72
  ConcreteNodeTypes["AssignMarkup"] = "AssignMarkup";
73
+ ConcreteNodeTypes["AssignPushRhs"] = "AssignPushRhs";
73
74
  ConcreteNodeTypes["HashAssignMarkup"] = "HashAssignMarkup";
74
75
  ConcreteNodeTypes["ContentForMarkup"] = "ContentForMarkup";
75
76
  ConcreteNodeTypes["CycleMarkup"] = "CycleMarkup";
@@ -365,6 +366,26 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
365
366
  source,
366
367
  },
367
368
  assignOperator: (node) => node.sourceString,
369
+ liquidAssignValue: 0,
370
+ liquidAssignPushExpr: {
371
+ type: ConcreteNodeTypes.AssignPushRhs,
372
+ // tokens: [pushSource, space*, "<<", space*, pushValue]
373
+ pushSource: 0,
374
+ pushValue: 4,
375
+ locStart,
376
+ locEnd,
377
+ source,
378
+ },
379
+ liquidAssignPushSource: {
380
+ type: ConcreteNodeTypes.LiquidVariable,
381
+ expression: 0,
382
+ filters: 1,
383
+ // No &delim lookahead at end (unlike liquidAssignVariable), so last token is space*
384
+ rawSource: (tokens) => source.slice(locStart(tokens), tokens[tokens.length - 1].source.endIdx).trimEnd(),
385
+ locStart,
386
+ locEnd,
387
+ source,
388
+ },
368
389
  liquidAssignVariable: {
369
390
  type: ConcreteNodeTypes.LiquidVariable,
370
391
  expression: 0,
@@ -407,6 +428,16 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
407
428
  source,
408
429
  },
409
430
  liquidJsonValue: 0,
431
+ liquidJsonItemVariable: {
432
+ type: ConcreteNodeTypes.LiquidVariable,
433
+ expression: 0,
434
+ filters: 1,
435
+ // No &delim lookahead at end (unlike liquidVariable), so last token is space*
436
+ rawSource: (tokens) => source.slice(locStart(tokens), tokens[tokens.length - 1].source.endIdx).trimEnd(),
437
+ locStart,
438
+ locEnd,
439
+ source,
440
+ },
410
441
  liquidJsonSep: 1,
411
442
  liquidTagHashAssignMarkup: {
412
443
  type: ConcreteNodeTypes.HashAssignMarkup,
@@ -435,7 +466,7 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
435
466
  contentForType: 0,
436
467
  liquidTagRenderMarkup: {
437
468
  type: ConcreteNodeTypes.RenderMarkup,
438
- snippet: 0,
469
+ partial: 0,
439
470
  variable: 1,
440
471
  alias: 2,
441
472
  renderArguments: 3,
@@ -580,7 +611,7 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
580
611
  .toAST(self.args.mapping)
581
612
  .concat(variableLookup.sourceString === '' ? [] : variableLookup.toAST(self.args.mapping));
582
613
  },
583
- snippetExpression: 0,
614
+ partialExpression: 0,
584
615
  renderVariableExpression: {
585
616
  type: ConcreteNodeTypes.RenderVariableExpression,
586
617
  kind: 1,
@@ -637,6 +668,23 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
637
668
  }
638
669
  },
639
670
  },
671
+ // Same as liquidFilter but without trailing comma — used inside JSON values to avoid
672
+ // consuming JSON entry separator commas as trailing filter argument commas.
673
+ liquidJsonFilter: {
674
+ type: ConcreteNodeTypes.LiquidFilter,
675
+ name: 3,
676
+ locStart,
677
+ locEnd,
678
+ source,
679
+ args(nodes) {
680
+ if (nodes[7].sourceString === '') {
681
+ return [];
682
+ }
683
+ else {
684
+ return nodes[7].toAST(this.args.mapping);
685
+ }
686
+ },
687
+ },
640
688
  filterArguments: 0,
641
689
  arguments: 0,
642
690
  complexArguments: function (completeParams, _space1, _comma, _space2, incompleteParam) {
@@ -647,6 +695,8 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
647
695
  },
648
696
  simpleArgument: 0,
649
697
  tagArguments: 0,
698
+ graphqlArguments: 0,
699
+ graphqlRenderArguments: 1,
650
700
  positionalArgument: 0,
651
701
  namedArgument: {
652
702
  type: ConcreteNodeTypes.NamedArgument,
@@ -656,6 +706,23 @@ function toCST(source /* the original file */, grammars, grammar, cstMappings, m
656
706
  locEnd,
657
707
  source,
658
708
  },
709
+ graphqlNamedArgument: {
710
+ type: ConcreteNodeTypes.NamedArgument,
711
+ name: 0,
712
+ value: 4,
713
+ locStart,
714
+ locEnd,
715
+ source,
716
+ },
717
+ graphqlNamedArgumentValue: {
718
+ type: ConcreteNodeTypes.LiquidVariable,
719
+ expression: 0,
720
+ filters: 1,
721
+ rawSource: (tokens) => source.slice(locStart(tokens), locEnd(tokens)),
722
+ locStart,
723
+ locEnd,
724
+ source,
725
+ },
659
726
  liquidBooleanExpression(initialCondition, subsequentConditions) {
660
727
  const initialConditionAst = initialCondition.toAST(this.args.mapping);
661
728
  const subsequentConditionAsts = subsequentConditions.toAST(this.args.mapping);
@@ -35,7 +35,7 @@
35
35
  import { ConcreteAttributeNode, ConcreteHtmlTagClose, ConcreteLiquidTagClose, LiquidCST, LiquidHtmlCST, ConcreteLiquidLiteral } from './stage-1-cst';
36
36
  import { Comparators, NamedTags, NodeTypes, Position } from './types';
37
37
  /** The union type of all possible node types inside a LiquidHTML AST. */
38
- export type LiquidHtmlNode = DocumentNode | YAMLFrontmatter | LiquidNode | HtmlDoctype | HtmlNode | AttributeNode | LiquidVariable | ComplexLiquidExpression | LiquidFilter | LiquidNamedArgument | AssignMarkup | HashAssignMarkup | ContentForMarkup | CycleMarkup | ForMarkup | RenderMarkup | FunctionMarkup | GraphQLMarkup | GraphQLInlineMarkup | RawMarkup | RenderVariableExpression | RenderAliasExpression | LiquidLogicalExpression | LiquidComparison | TextNode | LiquidDocParamNode | LiquidDocExampleNode | LiquidDocPromptNode | LiquidDocDescriptionNode | JsonHashLiteral | JsonArrayLiteral | JsonKeyValuePair | BackgroundMarkup | BackgroundInlineMarkup | CacheMarkup | LogMarkup | SessionMarkup | ExportMarkup | RedirectToMarkup | IncludeFormMarkup | SpamProtectionMarkup;
38
+ export type LiquidHtmlNode = DocumentNode | YAMLFrontmatter | LiquidNode | HtmlDoctype | HtmlNode | AttributeNode | LiquidVariable | ComplexLiquidExpression | LiquidFilter | LiquidNamedArgument | AssignMarkup | AssignPushRhs | HashAssignMarkup | ContentForMarkup | CycleMarkup | ForMarkup | RenderMarkup | FunctionMarkup | GraphQLMarkup | GraphQLInlineMarkup | RawMarkup | RenderVariableExpression | RenderAliasExpression | LiquidLogicalExpression | LiquidComparison | TextNode | LiquidDocParamNode | LiquidDocExampleNode | LiquidDocPromptNode | LiquidDocDescriptionNode | JsonHashLiteral | JsonArrayLiteral | JsonKeyValuePair | BackgroundMarkup | BackgroundInlineMarkup | CacheMarkup | LogMarkup | SessionMarkup | ExportMarkup | RedirectToMarkup | IncludeFormMarkup | SpamProtectionMarkup;
39
39
  /** The root node of all LiquidHTML ASTs. */
40
40
  export interface DocumentNode extends ASTNode<NodeTypes.Document> {
41
41
  children: LiquidHtmlNode[];
@@ -143,8 +143,15 @@ export interface AssignMarkup extends ASTNode<NodeTypes.AssignMarkup> {
143
143
  lookups: LiquidExpression[];
144
144
  /** '=' for assignment, '<<' for array append */
145
145
  operator: '=' | '<<';
146
- /** the value of the variable that is being assigned */
147
- value: LiquidVariable;
146
+ /** the value of the variable that is being assigned, or a push expression */
147
+ value: LiquidVariable | AssignPushRhs;
148
+ }
149
+ /** The RHS of an explicit push assign: `assign a = source << value` */
150
+ export interface AssignPushRhs extends ASTNode<NodeTypes.AssignPushRhs> {
151
+ /** the source array to push into */
152
+ pushSource: LiquidVariable;
153
+ /** the value being pushed */
154
+ pushValue: LiquidVariable;
148
155
  }
149
156
  export interface LiquidTagHashAssign extends LiquidTagNode<NamedTags.hash_assign, HashAssignMarkup> {
150
157
  }
@@ -257,8 +264,8 @@ export interface ContentForMarkup extends ASTNode<NodeTypes.ContentForMarkup> {
257
264
  }
258
265
  /** {% render 'partial' [(with|for) variable [as alias]], [...namedArguments] %} */
259
266
  export interface RenderMarkup extends ASTNode<NodeTypes.RenderMarkup> {
260
- /** {% render snippet %} */
261
- snippet: LiquidString | LiquidVariableLookup;
267
+ /** {% render 'partial' %} */
268
+ partial: LiquidString | LiquidVariableLookup;
262
269
  /** {% render 'partial' with thing as alias %} */
263
270
  alias: RenderAliasExpression | null;
264
271
  /** {% render 'partial' [with variable] %} */
@@ -274,7 +281,7 @@ export interface RenderMarkup extends ASTNode<NodeTypes.RenderMarkup> {
274
281
  }
275
282
  /** {% function res = 'partial', [...namedArguments] %} */
276
283
  export interface FunctionMarkup extends ASTNode<NodeTypes.FunctionMarkup> {
277
- /** {% render res = snippet %} */
284
+ /** {% function res = 'partial' %} */
278
285
  name: string;
279
286
  partial: LiquidString | LiquidVariableLookup;
280
287
  /**
@@ -288,7 +295,7 @@ export interface FunctionMarkup extends ASTNode<NodeTypes.FunctionMarkup> {
288
295
  }
289
296
  /** {% graphql res = 'path/to/graphql/file', [...namedArguments] %} (file-based) */
290
297
  export interface GraphQLMarkup extends ASTNode<NodeTypes.GraphQLMarkup> {
291
- /** {% graphql res = snippet %} */
298
+ /** {% graphql res = 'path/to/graphql/file' %} */
292
299
  name: string;
293
300
  graphql: LiquidString | LiquidVariableLookup;
294
301
  /**
@@ -410,7 +417,7 @@ export interface RenderVariableExpression extends ASTNode<NodeTypes.RenderVariab
410
417
  }
411
418
  /** Represents the `as name` expressions in render nodes */
412
419
  export interface RenderAliasExpression extends ASTNode<NodeTypes.RenderAliasExpression> {
413
- /** {% render 'partial' for array as name %}` or `{% render 'snippet' with object as name %} */
420
+ /** {% render 'partial' for array as name %}` or `{% render 'partial' with object as name %} */
414
421
  value: string;
415
422
  }
416
423
  /** The union type of the strictly and loosely typed LiquidBranch nodes */
@@ -498,12 +505,15 @@ export interface LiquidFilter extends ASTNode<NodeTypes.LiquidFilter> {
498
505
  }
499
506
  /** Represents the union type of positional and named arguments */
500
507
  export type LiquidArgument = LiquidExpression | LiquidNamedArgument;
501
- /** Named arguments are the ones used in kwargs, such as `name: value` */
508
+ /** Named arguments are the ones used in kwargs, such as `name: value` or `name: value | filter` */
502
509
  export interface LiquidNamedArgument extends ASTNode<NodeTypes.NamedArgument> {
503
510
  /** name: value */
504
511
  name: string;
505
- /** name: value */
506
- value: LiquidExpression;
512
+ /**
513
+ * For regular tags (render, function, for, etc.): a plain LiquidExpression (no filters).
514
+ * For graphql tags: a LiquidVariable which may include filters (e.g. `name: val | fetch: "key"`).
515
+ */
516
+ value: LiquidExpression | LiquidVariable;
507
517
  }
508
518
  export interface LiquidBooleanExpression extends ASTNode<NodeTypes.BooleanExpression> {
509
519
  condition: LiquidConditionalExpression;
@@ -553,11 +563,11 @@ export interface JsonHashLiteral extends ASTNode<NodeTypes.JsonHashLiteral> {
553
563
  /** Represents a key-value pair in a JSON hash literal */
554
564
  export interface JsonKeyValuePair extends ASTNode<NodeTypes.JsonKeyValuePair> {
555
565
  key: LiquidExpression;
556
- value: LiquidExpression;
566
+ value: LiquidExpression | LiquidVariable;
557
567
  }
558
568
  /** Represents a JSON array literal [el1, el2, ...] */
559
569
  export interface JsonArrayLiteral extends ASTNode<NodeTypes.JsonArrayLiteral> {
560
- elements: LiquidExpression[];
570
+ elements: (LiquidExpression | LiquidVariable)[];
561
571
  }
562
572
  /** The union type of all HTML nodes */
563
573
  export type HtmlNode = HtmlComment | HtmlElement | HtmlDanglingMarkerClose | HtmlVoidElement | HtmlSelfClosingElement | HtmlRawNode;
@@ -898,12 +898,24 @@ function toUnnamedLiquidBranch(parentNode) {
898
898
  };
899
899
  }
900
900
  function toAssignMarkup(node) {
901
+ const value = node.value.type === stage_1_cst_1.ConcreteNodeTypes.AssignPushRhs
902
+ ? toAssignPushRhs(node.value)
903
+ : toLiquidVariable(node.value);
901
904
  return {
902
905
  type: types_1.NodeTypes.AssignMarkup,
903
906
  name: node.name,
904
907
  lookups: node.target.lookups.map(toExpression),
905
908
  operator: node.operator,
906
- value: toLiquidVariable(node.value),
909
+ value,
910
+ position: position(node),
911
+ source: node.source,
912
+ };
913
+ }
914
+ function toAssignPushRhs(node) {
915
+ return {
916
+ type: types_1.NodeTypes.AssignPushRhs,
917
+ pushSource: toLiquidVariable(node.pushSource),
918
+ pushValue: toLiquidVariable(node.pushValue),
907
919
  position: position(node),
908
920
  source: node.source,
909
921
  };
@@ -1014,14 +1026,14 @@ function toContentForMarkup(node) {
1014
1026
  function toRenderMarkup(node) {
1015
1027
  return {
1016
1028
  type: types_1.NodeTypes.RenderMarkup,
1017
- snippet: toExpression(node.snippet),
1029
+ partial: toExpression(node.partial),
1018
1030
  alias: toRenderAliasExpression(node.alias),
1019
1031
  variable: toRenderVariableExpression(node.variable),
1020
1032
  /**
1021
1033
  * When we're in completion mode we won't necessarily have valid named
1022
1034
  * arguments so we need to call toLiquidArgument instead of toNamedArgument.
1023
1035
  * We cast using `as` so that this doesn't affect the type system used in
1024
- * other areas (like theme check) for a scenario that only occurs in
1036
+ * other areas (like platformos-check) for a scenario that only occurs in
1025
1037
  * completion mode. This means that our types are *wrong* in completion mode
1026
1038
  * but this is the compromise we're making to get completions to work.
1027
1039
  */
@@ -1039,7 +1051,7 @@ function toFunctionMarkup(node) {
1039
1051
  * When we're in completion mode we won't necessarily have valid named
1040
1052
  * arguments so we need to call toLiquidArgument instead of toNamedArgument.
1041
1053
  * We cast using `as` so that this doesn't affect the type system used in
1042
- * other areas (like theme check) for a scenario that only occurs in
1054
+ * other areas (like platformos-check) for a scenario that only occurs in
1043
1055
  * completion mode. This means that our types are *wrong* in completion mode
1044
1056
  * but this is the compromise we're making to get completions to work.
1045
1057
  */
@@ -1057,7 +1069,7 @@ function toGraphQLMarkup(node) {
1057
1069
  * When we're in completion mode we won't necessarily have valid named
1058
1070
  * arguments so we need to call toLiquidArgument instead of toNamedArgument.
1059
1071
  * We cast using `as` so that this doesn't affect the type system used in
1060
- * other areas (like theme check) for a scenario that only occurs in
1072
+ * other areas (like platformos-check) for a scenario that only occurs in
1061
1073
  * completion mode. This means that our types are *wrong* in completion mode
1062
1074
  * but this is the compromise we're making to get completions to work.
1063
1075
  */
@@ -1074,7 +1086,7 @@ function toGraphQLInlineMarkup(node) {
1074
1086
  * When we're in completion mode we won't necessarily have valid named
1075
1087
  * arguments so we need to call toLiquidArgument instead of toNamedArgument.
1076
1088
  * We cast using `as` so that this doesn't affect the type system used in
1077
- * other areas (like theme check) for a scenario that only occurs in
1089
+ * other areas (like platformos-check) for a scenario that only occurs in
1078
1090
  * completion mode. This means that our types are *wrong* in completion mode
1079
1091
  * but this is the compromise we're making to get completions to work.
1080
1092
  */
@@ -1316,7 +1328,7 @@ function toExpression(node) {
1316
1328
  case stage_1_cst_1.ConcreteNodeTypes.JsonArrayLiteral: {
1317
1329
  return {
1318
1330
  type: types_1.NodeTypes.JsonArrayLiteral,
1319
- elements: node.elements.map(toExpression),
1331
+ elements: node.elements.map(toJsonValue),
1320
1332
  position: position(node),
1321
1333
  source: node.source,
1322
1334
  };
@@ -1326,11 +1338,17 @@ function toExpression(node) {
1326
1338
  }
1327
1339
  }
1328
1340
  }
1341
+ function toJsonValue(node) {
1342
+ if (node.type === stage_1_cst_1.ConcreteNodeTypes.LiquidVariable) {
1343
+ return toLiquidVariable(node);
1344
+ }
1345
+ return toExpression(node);
1346
+ }
1329
1347
  function toJsonKeyValuePair(node) {
1330
1348
  return {
1331
1349
  type: types_1.NodeTypes.JsonKeyValuePair,
1332
1350
  key: toExpression(node.key),
1333
- value: toExpression(node.value),
1351
+ value: toJsonValue(node.value),
1334
1352
  position: position(node),
1335
1353
  source: node.source,
1336
1354
  };
@@ -1358,7 +1376,9 @@ function toNamedArgument(node) {
1358
1376
  return {
1359
1377
  type: types_1.NodeTypes.NamedArgument,
1360
1378
  name: node.name,
1361
- value: toExpression(node.value),
1379
+ value: node.value.type === stage_1_cst_1.ConcreteNodeTypes.LiquidVariable
1380
+ ? toLiquidVariable(node.value)
1381
+ : toExpression(node.value),
1362
1382
  position: position(node),
1363
1383
  source: node.source,
1364
1384
  };
package/dist/types.d.ts CHANGED
@@ -35,6 +35,7 @@ export declare enum NodeTypes {
35
35
  Comparison = "Comparison",
36
36
  LogicalExpression = "LogicalExpression",
37
37
  AssignMarkup = "AssignMarkup",
38
+ AssignPushRhs = "AssignPushRhs",
38
39
  HashAssignMarkup = "HashAssignMarkup",
39
40
  ContentForMarkup = "ContentForMarkup",
40
41
  CycleMarkup = "CycleMarkup",
package/dist/types.js CHANGED
@@ -33,6 +33,7 @@ var NodeTypes;
33
33
  NodeTypes["Comparison"] = "Comparison";
34
34
  NodeTypes["LogicalExpression"] = "LogicalExpression";
35
35
  NodeTypes["AssignMarkup"] = "AssignMarkup";
36
+ NodeTypes["AssignPushRhs"] = "AssignPushRhs";
36
37
  NodeTypes["HashAssignMarkup"] = "HashAssignMarkup";
37
38
  NodeTypes["ContentForMarkup"] = "ContentForMarkup";
38
39
  NodeTypes["CycleMarkup"] = "CycleMarkup";
@@ -106,7 +106,7 @@ Liquid <: Helpers {
106
106
 
107
107
  liquidTagOpenGraphQL = liquidTagOpenRule<"graphql", liquidTagGraphQLInlineMarkup>
108
108
  // Use negative lookahead to exclude file-based syntax (with "=")
109
- liquidTagGraphQLInlineMarkup = variableSegment ~(space* "=") renderArguments
109
+ liquidTagGraphQLInlineMarkup = variableSegment ~(space* "=") graphqlRenderArguments
110
110
 
111
111
  liquidTagOpen =
112
112
  | liquidTagOpenStrict
@@ -126,12 +126,21 @@ Liquid <: Helpers {
126
126
  liquidTagEchoMarkup = liquidVariable<delimTag>
127
127
 
128
128
  liquidTagAssign = liquidTagRule<"assign", liquidTagAssignMarkup>
129
- liquidTagAssignMarkup = assignTarget<delimTag> space* assignOperator space* liquidAssignVariable<delimTag>
129
+ liquidTagAssignMarkup = assignTarget<delimTag> space* assignOperator space* liquidAssignValue<delimTag>
130
130
 
131
131
  // Assign-specific sub-rules
132
132
  assignTarget<delim> = variableSegment lookup<delim>*
133
133
  assignOperator = "<<" | "="
134
134
 
135
+ // The RHS of an assign: either an explicit push expression (source << value) or a regular value
136
+ liquidAssignValue<delim> = liquidAssignPushExpr<delim> | liquidAssignVariable<delim>
137
+
138
+ // Explicit push: assign a = source << value (equivalent to assign a << value when source is a)
139
+ liquidAssignPushExpr<delim> = liquidAssignPushSource<delim> space* "<<" space* liquidAssignVariable<delim>
140
+
141
+ // The source expression for a push (no &delim lookahead since "<<" follows)
142
+ liquidAssignPushSource<delim> = liquidAssignExpression<delim> liquidFilter<delim>* space*
143
+
135
144
  // Assign variable: like liquidVariable but expression allows JSON literals
136
145
  liquidAssignVariable<delim> = liquidAssignExpression<delim> liquidFilter<delim>* space* &delim
137
146
  liquidAssignExpression<delim> =
@@ -151,7 +160,16 @@ Liquid <: Helpers {
151
160
  liquidJsonValue<delim> =
152
161
  | liquidJsonHashLiteral<delim>
153
162
  | liquidJsonArrayLiteral<delim>
163
+ | liquidJsonItemVariable<delim>
154
164
  | liquidExpression<delim>
165
+ // Like liquidVariable but without &delim lookahead, so it works inside JSON structures.
166
+ // Requires at least one filter (liquidJsonFilter+) so plain expressions fall through to liquidExpression.
167
+ // Uses liquidJsonFilter (no trailing comma) instead of liquidFilter to avoid consuming the
168
+ // JSON entry separator comma (e.g. the "," in { "a": x | filter: arg, "b": y }).
169
+ liquidJsonItemVariable<delim> = liquidComplexExpression<delim> liquidJsonFilter<delim>+ space*
170
+ // Like liquidFilter but without the trailing (space* ",")? so commas between JSON entries
171
+ // are not consumed as trailing filter argument commas.
172
+ liquidJsonFilter<delim> = space* "|" space* identifier (space* ":" space* arguments<delim>)?
155
173
  liquidJsonSep = space* "," space*
156
174
 
157
175
  liquidTagHashAssign = liquidTagRule<"hash_assign", liquidTagHashAssignMarkup>
@@ -186,17 +204,17 @@ Liquid <: Helpers {
186
204
  liquidTagInclude = liquidTagRule<"include", liquidTagRenderMarkup>
187
205
  liquidTagRender = liquidTagRule<"render", liquidTagRenderMarkup>
188
206
  liquidTagRenderMarkup =
189
- snippetExpression renderVariableExpression? renderAliasExpression? renderArguments
207
+ partialExpression renderVariableExpression? renderAliasExpression? renderArguments
190
208
 
191
209
  liquidTagFunction = liquidTagRule<"function", liquidTagFunctionMarkup>
192
- liquidTagFunctionMarkup = variableSegment space* "=" space* snippetExpression renderArguments
210
+ liquidTagFunctionMarkup = variableSegment space* "=" space* partialExpression renderArguments
193
211
 
194
212
  liquidTagGraphQL = liquidTagRule<"graphql", liquidTagGraphQLMarkup>
195
- liquidTagGraphQLMarkup = variableSegment space* "=" space* snippetExpression renderArguments
213
+ liquidTagGraphQLMarkup = variableSegment space* "=" space* partialExpression graphqlRenderArguments
196
214
 
197
215
  // platformos simple tags
198
216
  liquidTagBackground = liquidTagRule<"background", liquidTagBackgroundMarkup>
199
- liquidTagBackgroundMarkup = variableSegment space* "=" space* snippetExpression renderArguments
217
+ liquidTagBackgroundMarkup = variableSegment space* "=" space* partialExpression renderArguments
200
218
 
201
219
  liquidTagOpenBackground = liquidTagOpenRule<"background", liquidTagBackgroundInlineMarkup>
202
220
  // Use negative lookahead to exclude file-based syntax (with "=")
@@ -243,7 +261,7 @@ Liquid <: Helpers {
243
261
  liquidTagRedirectToMarkup = liquidExpression<delimTag> renderArguments
244
262
 
245
263
  liquidTagIncludeForm = liquidTagRule<"include_form", liquidTagIncludeFormMarkup>
246
- liquidTagIncludeFormMarkup = snippetExpression renderArguments
264
+ liquidTagIncludeFormMarkup = partialExpression renderArguments
247
265
 
248
266
  liquidTagSpamProtection = liquidTagRule<"spam_protection", liquidTagSpamProtectionMarkup>
249
267
  liquidTagSpamProtectionMarkup = liquidExpression<delimTag> renderArguments
@@ -260,7 +278,6 @@ Liquid <: Helpers {
260
278
 
261
279
  renderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space*
262
280
  completionModeRenderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space* (argumentSeparator? liquidVariableLookup<delimTag> space*)?
263
- snippetExpression = liquidString<delimTag> | variableSegmentAsLookup
264
281
  partialExpression = liquidString<delimTag> | variableSegmentAsLookup
265
282
  renderVariableExpression = space+ ("for" | "with") space+ liquidExpression<delimTag>
266
283
  renderAliasExpression = space+ "as" space+ variableSegment
@@ -322,7 +339,7 @@ Liquid <: Helpers {
322
339
  | ">="
323
340
  | "<="
324
341
  | ">"
325
- | "<")
342
+ | "<" ~"<")
326
343
  | ("contains" ~identifier)
327
344
 
328
345
  liquidDrop = "{{" "-"? space* liquidDropCases "-"? "}}"
@@ -420,6 +437,10 @@ Liquid <: Helpers {
420
437
  positionalArgument<delim> = liquidExpression<delim> ~(space* ":")
421
438
  namedArgument<delim> = variableSegment space* ":" space* liquidExpression<delim>
422
439
  tagArguments = listOf<namedArgument<delimTag>, argumentSeparatorOptionalComma>
440
+ graphqlArguments = listOf<graphqlNamedArgument, argumentSeparatorOptionalComma>
441
+ graphqlNamedArgument = variableSegment space* ":" space* graphqlNamedArgumentValue
442
+ graphqlNamedArgumentValue = liquidExpression<delimTag> liquidFilter<delimTag>*
443
+ graphqlRenderArguments = (argumentSeparatorOptionalComma graphqlArguments) (space* ",")? space*
423
444
  filterArguments<delim> =
424
445
  | complexArguments<delim>
425
446
  | simpleArgument<delim>
@@ -709,7 +730,7 @@ StrictLiquidHTML <: LiquidHTML {
709
730
  WithPlaceholderLiquid <: Liquid {
710
731
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
711
732
  liquidTagRenderMarkup :=
712
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
733
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
713
734
  liquidTagName := (letter | "█") (alnum | "_")*
714
735
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
715
736
  liquidDoc :=
@@ -721,7 +742,7 @@ WithPlaceholderLiquid <: Liquid {
721
742
  WithPlaceholderLiquidStatement <: LiquidStatement {
722
743
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
723
744
  liquidTagRenderMarkup :=
724
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
745
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
725
746
  liquidTagName := (letter | "█") (alnum | "_")*
726
747
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
727
748
  liquidDoc :=
@@ -733,7 +754,7 @@ WithPlaceholderLiquidStatement <: LiquidStatement {
733
754
  WithPlaceholderLiquidHTML <: LiquidHTML {
734
755
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
735
756
  liquidTagRenderMarkup :=
736
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
757
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
737
758
  liquidTagName := (letter | "█") (alnum | "_")*
738
759
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
739
760
  leadingTagNameTextNode := (letter | "█") (alnum | "-" | ":" | "█")*
@@ -106,7 +106,7 @@ Liquid <: Helpers {
106
106
 
107
107
  liquidTagOpenGraphQL = liquidTagOpenRule<"graphql", liquidTagGraphQLInlineMarkup>
108
108
  // Use negative lookahead to exclude file-based syntax (with "=")
109
- liquidTagGraphQLInlineMarkup = variableSegment ~(space* "=") renderArguments
109
+ liquidTagGraphQLInlineMarkup = variableSegment ~(space* "=") graphqlRenderArguments
110
110
 
111
111
  liquidTagOpen =
112
112
  | liquidTagOpenStrict
@@ -126,12 +126,21 @@ Liquid <: Helpers {
126
126
  liquidTagEchoMarkup = liquidVariable<delimTag>
127
127
 
128
128
  liquidTagAssign = liquidTagRule<"assign", liquidTagAssignMarkup>
129
- liquidTagAssignMarkup = assignTarget<delimTag> space* assignOperator space* liquidAssignVariable<delimTag>
129
+ liquidTagAssignMarkup = assignTarget<delimTag> space* assignOperator space* liquidAssignValue<delimTag>
130
130
 
131
131
  // Assign-specific sub-rules
132
132
  assignTarget<delim> = variableSegment lookup<delim>*
133
133
  assignOperator = "<<" | "="
134
134
 
135
+ // The RHS of an assign: either an explicit push expression (source << value) or a regular value
136
+ liquidAssignValue<delim> = liquidAssignPushExpr<delim> | liquidAssignVariable<delim>
137
+
138
+ // Explicit push: assign a = source << value (equivalent to assign a << value when source is a)
139
+ liquidAssignPushExpr<delim> = liquidAssignPushSource<delim> space* "<<" space* liquidAssignVariable<delim>
140
+
141
+ // The source expression for a push (no &delim lookahead since "<<" follows)
142
+ liquidAssignPushSource<delim> = liquidAssignExpression<delim> liquidFilter<delim>* space*
143
+
135
144
  // Assign variable: like liquidVariable but expression allows JSON literals
136
145
  liquidAssignVariable<delim> = liquidAssignExpression<delim> liquidFilter<delim>* space* &delim
137
146
  liquidAssignExpression<delim> =
@@ -151,7 +160,16 @@ Liquid <: Helpers {
151
160
  liquidJsonValue<delim> =
152
161
  | liquidJsonHashLiteral<delim>
153
162
  | liquidJsonArrayLiteral<delim>
163
+ | liquidJsonItemVariable<delim>
154
164
  | liquidExpression<delim>
165
+ // Like liquidVariable but without &delim lookahead, so it works inside JSON structures.
166
+ // Requires at least one filter (liquidJsonFilter+) so plain expressions fall through to liquidExpression.
167
+ // Uses liquidJsonFilter (no trailing comma) instead of liquidFilter to avoid consuming the
168
+ // JSON entry separator comma (e.g. the "," in { "a": x | filter: arg, "b": y }).
169
+ liquidJsonItemVariable<delim> = liquidComplexExpression<delim> liquidJsonFilter<delim>+ space*
170
+ // Like liquidFilter but without the trailing (space* ",")? so commas between JSON entries
171
+ // are not consumed as trailing filter argument commas.
172
+ liquidJsonFilter<delim> = space* "|" space* identifier (space* ":" space* arguments<delim>)?
155
173
  liquidJsonSep = space* "," space*
156
174
 
157
175
  liquidTagHashAssign = liquidTagRule<"hash_assign", liquidTagHashAssignMarkup>
@@ -186,17 +204,17 @@ Liquid <: Helpers {
186
204
  liquidTagInclude = liquidTagRule<"include", liquidTagRenderMarkup>
187
205
  liquidTagRender = liquidTagRule<"render", liquidTagRenderMarkup>
188
206
  liquidTagRenderMarkup =
189
- snippetExpression renderVariableExpression? renderAliasExpression? renderArguments
207
+ partialExpression renderVariableExpression? renderAliasExpression? renderArguments
190
208
 
191
209
  liquidTagFunction = liquidTagRule<"function", liquidTagFunctionMarkup>
192
- liquidTagFunctionMarkup = variableSegment space* "=" space* snippetExpression renderArguments
210
+ liquidTagFunctionMarkup = variableSegment space* "=" space* partialExpression renderArguments
193
211
 
194
212
  liquidTagGraphQL = liquidTagRule<"graphql", liquidTagGraphQLMarkup>
195
- liquidTagGraphQLMarkup = variableSegment space* "=" space* snippetExpression renderArguments
213
+ liquidTagGraphQLMarkup = variableSegment space* "=" space* partialExpression graphqlRenderArguments
196
214
 
197
215
  // platformos simple tags
198
216
  liquidTagBackground = liquidTagRule<"background", liquidTagBackgroundMarkup>
199
- liquidTagBackgroundMarkup = variableSegment space* "=" space* snippetExpression renderArguments
217
+ liquidTagBackgroundMarkup = variableSegment space* "=" space* partialExpression renderArguments
200
218
 
201
219
  liquidTagOpenBackground = liquidTagOpenRule<"background", liquidTagBackgroundInlineMarkup>
202
220
  // Use negative lookahead to exclude file-based syntax (with "=")
@@ -243,7 +261,7 @@ Liquid <: Helpers {
243
261
  liquidTagRedirectToMarkup = liquidExpression<delimTag> renderArguments
244
262
 
245
263
  liquidTagIncludeForm = liquidTagRule<"include_form", liquidTagIncludeFormMarkup>
246
- liquidTagIncludeFormMarkup = snippetExpression renderArguments
264
+ liquidTagIncludeFormMarkup = partialExpression renderArguments
247
265
 
248
266
  liquidTagSpamProtection = liquidTagRule<"spam_protection", liquidTagSpamProtectionMarkup>
249
267
  liquidTagSpamProtectionMarkup = liquidExpression<delimTag> renderArguments
@@ -260,7 +278,6 @@ Liquid <: Helpers {
260
278
 
261
279
  renderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space*
262
280
  completionModeRenderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space* (argumentSeparator? liquidVariableLookup<delimTag> space*)?
263
- snippetExpression = liquidString<delimTag> | variableSegmentAsLookup
264
281
  partialExpression = liquidString<delimTag> | variableSegmentAsLookup
265
282
  renderVariableExpression = space+ ("for" | "with") space+ liquidExpression<delimTag>
266
283
  renderAliasExpression = space+ "as" space+ variableSegment
@@ -322,7 +339,7 @@ Liquid <: Helpers {
322
339
  | ">="
323
340
  | "<="
324
341
  | ">"
325
- | "<")
342
+ | "<" ~"<")
326
343
  | ("contains" ~identifier)
327
344
 
328
345
  liquidDrop = "{{" "-"? space* liquidDropCases "-"? "}}"
@@ -420,6 +437,10 @@ Liquid <: Helpers {
420
437
  positionalArgument<delim> = liquidExpression<delim> ~(space* ":")
421
438
  namedArgument<delim> = variableSegment space* ":" space* liquidExpression<delim>
422
439
  tagArguments = listOf<namedArgument<delimTag>, argumentSeparatorOptionalComma>
440
+ graphqlArguments = listOf<graphqlNamedArgument, argumentSeparatorOptionalComma>
441
+ graphqlNamedArgument = variableSegment space* ":" space* graphqlNamedArgumentValue
442
+ graphqlNamedArgumentValue = liquidExpression<delimTag> liquidFilter<delimTag>*
443
+ graphqlRenderArguments = (argumentSeparatorOptionalComma graphqlArguments) (space* ",")? space*
423
444
  filterArguments<delim> =
424
445
  | complexArguments<delim>
425
446
  | simpleArgument<delim>
@@ -709,7 +730,7 @@ StrictLiquidHTML <: LiquidHTML {
709
730
  WithPlaceholderLiquid <: Liquid {
710
731
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
711
732
  liquidTagRenderMarkup :=
712
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
733
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
713
734
  liquidTagName := (letter | "█") (alnum | "_")*
714
735
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
715
736
  liquidDoc :=
@@ -721,7 +742,7 @@ WithPlaceholderLiquid <: Liquid {
721
742
  WithPlaceholderLiquidStatement <: LiquidStatement {
722
743
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
723
744
  liquidTagRenderMarkup :=
724
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
745
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
725
746
  liquidTagName := (letter | "█") (alnum | "_")*
726
747
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
727
748
  liquidDoc :=
@@ -733,7 +754,7 @@ WithPlaceholderLiquidStatement <: LiquidStatement {
733
754
  WithPlaceholderLiquidHTML <: LiquidHTML {
734
755
  liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
735
756
  liquidTagRenderMarkup :=
736
- snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
757
+ partialExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
737
758
  liquidTagName := (letter | "█") (alnum | "_")*
738
759
  variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
739
760
  leadingTagNameTextNode := (letter | "█") (alnum | "-" | ":" | "█")*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformos/liquid-html-parser",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Liquid HTML parser for platformOS",
5
5
  "author": "platformOS",
6
6
  "homepage": "https://github.com/Platform-OS/platformos-tools/tree/master/packages/liquid-html-parser#readme",