@platformos/liquid-html-parser 0.0.2

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.
@@ -0,0 +1,1104 @@
1
+ "use strict";
2
+ /**
3
+ * This is the first stage of the parser.
4
+ *
5
+ * Input:
6
+ * Source code: string
7
+ *
8
+ * Output:
9
+ * Concrete Syntax Tree (CST): LiquidHtmlCST
10
+ *
11
+ * We use OhmJS's toAST method to turn the OhmJS nodes into an "almost-AST." We
12
+ * call that a Concrete Syntax Tree because it considers Open and Close nodes as
13
+ * separate nodes.
14
+ *
15
+ * It is mostly "flat."
16
+ *
17
+ * e.g.
18
+ * {% if cond %}hi <em>there!</em>{% endif %}
19
+ *
20
+ * becomes
21
+ * - LiquidTagOpen/if
22
+ * condition: LiquidVariableExpression/cond
23
+ * - TextNode/"hi "
24
+ * - HtmlTagOpen/em
25
+ * - TextNode/"there!"
26
+ * - HtmlTagClose/em
27
+ * - LiquidTagClose/if
28
+ *
29
+ * In the Concrete Syntax Tree, all nodes are siblings instead of having a
30
+ * parent/children relationship.
31
+ *
32
+ */
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ exports.LiquidLiteralValues = exports.ConcreteNodeTypes = void 0;
35
+ exports.toLiquidHtmlCST = toLiquidHtmlCST;
36
+ exports.toLiquidCST = toLiquidCST;
37
+ const extras_1 = require("ohm-js/extras");
38
+ const grammar_1 = require("./grammar");
39
+ const errors_1 = require("./errors");
40
+ const types_1 = require("./types");
41
+ var ConcreteNodeTypes;
42
+ (function (ConcreteNodeTypes) {
43
+ ConcreteNodeTypes["HtmlDoctype"] = "HtmlDoctype";
44
+ ConcreteNodeTypes["HtmlComment"] = "HtmlComment";
45
+ ConcreteNodeTypes["HtmlRawTag"] = "HtmlRawTag";
46
+ ConcreteNodeTypes["HtmlVoidElement"] = "HtmlVoidElement";
47
+ ConcreteNodeTypes["HtmlSelfClosingElement"] = "HtmlSelfClosingElement";
48
+ ConcreteNodeTypes["HtmlTagOpen"] = "HtmlTagOpen";
49
+ ConcreteNodeTypes["HtmlTagClose"] = "HtmlTagClose";
50
+ ConcreteNodeTypes["AttrSingleQuoted"] = "AttrSingleQuoted";
51
+ ConcreteNodeTypes["AttrDoubleQuoted"] = "AttrDoubleQuoted";
52
+ ConcreteNodeTypes["AttrUnquoted"] = "AttrUnquoted";
53
+ ConcreteNodeTypes["AttrEmpty"] = "AttrEmpty";
54
+ ConcreteNodeTypes["LiquidVariableOutput"] = "LiquidVariableOutput";
55
+ ConcreteNodeTypes["LiquidRawTag"] = "LiquidRawTag";
56
+ ConcreteNodeTypes["LiquidTag"] = "LiquidTag";
57
+ ConcreteNodeTypes["LiquidTagOpen"] = "LiquidTagOpen";
58
+ ConcreteNodeTypes["LiquidTagClose"] = "LiquidTagClose";
59
+ ConcreteNodeTypes["TextNode"] = "TextNode";
60
+ ConcreteNodeTypes["YAMLFrontmatter"] = "YAMLFrontmatter";
61
+ ConcreteNodeTypes["LiquidVariable"] = "LiquidVariable";
62
+ ConcreteNodeTypes["LiquidFilter"] = "LiquidFilter";
63
+ ConcreteNodeTypes["NamedArgument"] = "NamedArgument";
64
+ ConcreteNodeTypes["LiquidLiteral"] = "LiquidLiteral";
65
+ ConcreteNodeTypes["VariableLookup"] = "VariableLookup";
66
+ ConcreteNodeTypes["BooleanExpression"] = "BooleanExpression";
67
+ ConcreteNodeTypes["String"] = "String";
68
+ ConcreteNodeTypes["Number"] = "Number";
69
+ ConcreteNodeTypes["Range"] = "Range";
70
+ ConcreteNodeTypes["Comparison"] = "Comparison";
71
+ ConcreteNodeTypes["Condition"] = "Condition";
72
+ ConcreteNodeTypes["AssignMarkup"] = "AssignMarkup";
73
+ ConcreteNodeTypes["HashAssignMarkup"] = "HashAssignMarkup";
74
+ ConcreteNodeTypes["ContentForMarkup"] = "ContentForMarkup";
75
+ ConcreteNodeTypes["CycleMarkup"] = "CycleMarkup";
76
+ ConcreteNodeTypes["ForMarkup"] = "ForMarkup";
77
+ ConcreteNodeTypes["RenderMarkup"] = "RenderMarkup";
78
+ ConcreteNodeTypes["FunctionMarkup"] = "FunctionMarkup";
79
+ ConcreteNodeTypes["GraphQLMarkup"] = "GraphQLMarkup";
80
+ ConcreteNodeTypes["GraphQLInlineMarkup"] = "GraphQLInlineMarkup";
81
+ ConcreteNodeTypes["PaginateMarkup"] = "PaginateMarkup";
82
+ ConcreteNodeTypes["RenderVariableExpression"] = "RenderVariableExpression";
83
+ ConcreteNodeTypes["RenderAliasExpression"] = "RenderAliasExpression";
84
+ ConcreteNodeTypes["ContentForNamedArgument"] = "ContentForNamedArgument";
85
+ ConcreteNodeTypes["LiquidDocParamNode"] = "LiquidDocParamNode";
86
+ ConcreteNodeTypes["LiquidDocParamNameNode"] = "LiquidDocParamNameNode";
87
+ ConcreteNodeTypes["LiquidDocDescriptionNode"] = "LiquidDocDescriptionNode";
88
+ ConcreteNodeTypes["LiquidDocExampleNode"] = "LiquidDocExampleNode";
89
+ ConcreteNodeTypes["LiquidDocPromptNode"] = "LiquidDocPromptNode";
90
+ // platformos markup types
91
+ ConcreteNodeTypes["BackgroundMarkup"] = "BackgroundMarkup";
92
+ ConcreteNodeTypes["BackgroundInlineMarkup"] = "BackgroundInlineMarkup";
93
+ ConcreteNodeTypes["CacheMarkup"] = "CacheMarkup";
94
+ ConcreteNodeTypes["LogMarkup"] = "LogMarkup";
95
+ ConcreteNodeTypes["SessionMarkup"] = "SessionMarkup";
96
+ ConcreteNodeTypes["ExportMarkup"] = "ExportMarkup";
97
+ ConcreteNodeTypes["RedirectToMarkup"] = "RedirectToMarkup";
98
+ ConcreteNodeTypes["IncludeFormMarkup"] = "IncludeFormMarkup";
99
+ ConcreteNodeTypes["SpamProtectionMarkup"] = "SpamProtectionMarkup";
100
+ })(ConcreteNodeTypes || (exports.ConcreteNodeTypes = ConcreteNodeTypes = {}));
101
+ exports.LiquidLiteralValues = {
102
+ nil: null,
103
+ null: null,
104
+ true: true,
105
+ false: false,
106
+ blank: '',
107
+ empty: '',
108
+ };
109
+ const markup = (i) => (tokens) => tokens[i].sourceString.trim();
110
+ const markupTrimEnd = (i) => (tokens) => tokens[i].sourceString.trimEnd();
111
+ const Grammars = {
112
+ strict: grammar_1.strictGrammars,
113
+ tolerant: grammar_1.tolerantGrammars,
114
+ completion: grammar_1.placeholderGrammars,
115
+ };
116
+ function toLiquidHtmlCST(source, options = { mode: 'tolerant' }) {
117
+ const grammars = Grammars[options.mode];
118
+ const grammar = grammars.LiquidHTML;
119
+ return toCST(source, grammars, grammar, [
120
+ 'HelperMappings',
121
+ 'LiquidMappings',
122
+ 'LiquidHTMLMappings',
123
+ ]);
124
+ }
125
+ function toLiquidCST(source, options = { mode: 'tolerant' }) {
126
+ const grammars = Grammars[options.mode];
127
+ const grammar = grammars.Liquid;
128
+ return toCST(source, grammars, grammar, ['HelperMappings', 'LiquidMappings']);
129
+ }
130
+ function toCST(source /* the original file */, grammars, grammar, cstMappings, matchingSource = source /* for subtree parsing */, offset = 0 /* for subtree parsing location offsets */) {
131
+ // When we switch parser, our locStart and locEnd functions must account
132
+ // for the offset of the {% liquid %} markup
133
+ const locStart = (tokens) => offset + tokens[0].source.startIdx;
134
+ const locEnd = (tokens) => offset + tokens[tokens.length - 1].source.endIdx;
135
+ const locEndSecondToLast = (tokens) => offset + tokens[tokens.length - 2].source.endIdx;
136
+ const textNode = {
137
+ type: ConcreteNodeTypes.TextNode,
138
+ value: function () {
139
+ return this.sourceString;
140
+ },
141
+ locStart,
142
+ locEnd,
143
+ source,
144
+ };
145
+ const res = grammar.match(matchingSource, 'Node');
146
+ if (res.failed()) {
147
+ throw new errors_1.LiquidHTMLCSTParsingError(res);
148
+ }
149
+ const HelperMappings = {
150
+ Node: 0,
151
+ TextNode: textNode,
152
+ orderedListOf: 0,
153
+ empty: () => null,
154
+ nonemptyOrderedListOf: 0,
155
+ nonemptyOrderedListOfBoth(nonemptyListOfA, _sep, nonemptyListOfB) {
156
+ const self = this;
157
+ return nonemptyListOfA
158
+ .toAST(self.args.mapping)
159
+ .concat(nonemptyListOfB.toAST(self.args.mapping));
160
+ },
161
+ };
162
+ const LiquidMappings = {
163
+ liquidNode: 0,
164
+ liquidRawTag: 0,
165
+ liquidRawTagImpl: {
166
+ type: ConcreteNodeTypes.LiquidRawTag,
167
+ name: 3,
168
+ body: 9,
169
+ children: (tokens) => {
170
+ const nameNode = tokens[3];
171
+ const rawMarkupStringNode = tokens[9];
172
+ switch (nameNode.sourceString) {
173
+ // {% schema %} parses its content as a string and should not be visited
174
+ case 'schema':
175
+ // {% raw %} accepts syntax errors, we shouldn't try to parse that
176
+ case 'raw': {
177
+ return toCST(source, grammars, grammar_1.TextNodeGrammar, ['HelperMappings'], rawMarkupStringNode.sourceString, offset + rawMarkupStringNode.source.startIdx);
178
+ }
179
+ // {% style %} actually parses its child nodes, so they are part of the AST
180
+ // {% javascript %}, {% stylesheet %} don't, but we want to flag folks that
181
+ // those are not supported in StaticStylesheetAndJavascriptTags, so we put
182
+ // them in the AST
183
+ default: {
184
+ return toCST(source, grammars, grammars.Liquid, ['HelperMappings', 'LiquidMappings'], rawMarkupStringNode.sourceString, offset + rawMarkupStringNode.source.startIdx);
185
+ }
186
+ }
187
+ },
188
+ markup: 6,
189
+ whitespaceStart: 1,
190
+ whitespaceEnd: 7,
191
+ delimiterWhitespaceStart: 11,
192
+ delimiterWhitespaceEnd: 17,
193
+ locStart,
194
+ locEnd,
195
+ source,
196
+ blockStartLocStart: (tokens) => tokens[0].source.startIdx,
197
+ blockStartLocEnd: (tokens) => tokens[8].source.endIdx,
198
+ blockEndLocStart: (tokens) => tokens[10].source.startIdx,
199
+ blockEndLocEnd: (tokens) => tokens[18].source.endIdx,
200
+ },
201
+ liquidBlockComment: {
202
+ type: ConcreteNodeTypes.LiquidRawTag,
203
+ name: 'comment',
204
+ body: (tokens) => tokens[1].sourceString,
205
+ children: (tokens) => {
206
+ return toCST(source, grammars, grammar_1.TextNodeGrammar, ['HelperMappings'], tokens[1].sourceString, offset + tokens[1].source.startIdx);
207
+ },
208
+ whitespaceStart: (tokens) => tokens[0].children[1].sourceString,
209
+ whitespaceEnd: (tokens) => tokens[0].children[7].sourceString,
210
+ delimiterWhitespaceStart: (tokens) => tokens[2].children[1].sourceString,
211
+ delimiterWhitespaceEnd: (tokens) => tokens[2].children[7].sourceString,
212
+ locStart,
213
+ locEnd,
214
+ source,
215
+ blockStartLocStart: (tokens) => tokens[0].source.startIdx,
216
+ blockStartLocEnd: (tokens) => tokens[0].source.endIdx,
217
+ blockEndLocStart: (tokens) => tokens[2].source.startIdx,
218
+ blockEndLocEnd: (tokens) => tokens[2].source.endIdx,
219
+ },
220
+ liquidDoc: {
221
+ type: ConcreteNodeTypes.LiquidRawTag,
222
+ name: 'doc',
223
+ body: (tokens) => tokens[1].sourceString,
224
+ children: (tokens) => {
225
+ const contentNode = tokens[1];
226
+ return toLiquidDocAST(source, contentNode.sourceString, offset + contentNode.source.startIdx);
227
+ },
228
+ whitespaceStart: (tokens) => tokens[0].children[1].sourceString,
229
+ whitespaceEnd: (tokens) => tokens[0].children[7].sourceString,
230
+ delimiterWhitespaceStart: (tokens) => tokens[2].children[1]?.sourceString || '',
231
+ delimiterWhitespaceEnd: (tokens) => tokens[2].children[7]?.sourceString || '',
232
+ locStart,
233
+ locEnd,
234
+ source,
235
+ blockStartLocStart: (tokens) => tokens[0].source.startIdx,
236
+ blockStartLocEnd: (tokens) => tokens[0].source.endIdx,
237
+ blockEndLocStart: (tokens) => tokens[2].source.startIdx,
238
+ blockEndLocEnd: (tokens) => tokens[2].source.endIdx,
239
+ },
240
+ liquidInlineComment: {
241
+ type: ConcreteNodeTypes.LiquidTag,
242
+ name: 3,
243
+ markup: markupTrimEnd(5),
244
+ whitespaceStart: 1,
245
+ whitespaceEnd: 6,
246
+ locStart,
247
+ locEnd,
248
+ source,
249
+ },
250
+ liquidTagOpen: 0,
251
+ liquidTagOpenStrict: 0,
252
+ liquidTagOpenBaseCase: 0,
253
+ liquidTagOpenRule: {
254
+ type: ConcreteNodeTypes.LiquidTagOpen,
255
+ name: 3,
256
+ markup(nodes) {
257
+ const markupNode = nodes[6];
258
+ const nameNode = nodes[3];
259
+ if (types_1.NamedTags.hasOwnProperty(nameNode.sourceString)) {
260
+ return markupNode.toAST(this.args.mapping);
261
+ }
262
+ return markupNode.sourceString.trim();
263
+ },
264
+ whitespaceStart: 1,
265
+ whitespaceEnd: 7,
266
+ locStart,
267
+ locEnd,
268
+ source,
269
+ },
270
+ liquidTagOpenCapture: 0,
271
+ liquidTagOpenForm: 0,
272
+ liquidTagOpenFormMarkup: 0,
273
+ liquidTagOpenFor: 0,
274
+ liquidTagOpenGraphQL: 0,
275
+ liquidTagOpenForMarkup: {
276
+ type: ConcreteNodeTypes.ForMarkup,
277
+ variableName: 0,
278
+ collection: 4,
279
+ reversed: 6,
280
+ args: 8,
281
+ locStart,
282
+ locEnd,
283
+ source,
284
+ },
285
+ liquidTagBreak: 0,
286
+ liquidTagContinue: 0,
287
+ liquidTagOpenTablerow: 0,
288
+ liquidTagOpenPaginate: 0,
289
+ liquidTagOpenPaginateMarkup: {
290
+ type: ConcreteNodeTypes.PaginateMarkup,
291
+ collection: 0,
292
+ pageSize: 4,
293
+ args: 6,
294
+ locStart,
295
+ locEnd,
296
+ source,
297
+ },
298
+ liquidTagOpenCase: 0,
299
+ liquidTagOpenCaseMarkup: 0,
300
+ liquidTagWhen: 0,
301
+ liquidTagWhenMarkup: 0,
302
+ liquidTagOpenIf: 0,
303
+ liquidTagOpenUnless: 0,
304
+ liquidTagElsif: 0,
305
+ liquidTagElse: 0,
306
+ liquidTagOpenConditionalMarkup: 0,
307
+ condition: {
308
+ type: ConcreteNodeTypes.Condition,
309
+ relation: 0,
310
+ expression: 2,
311
+ locStart,
312
+ locEnd,
313
+ source,
314
+ },
315
+ comparison: {
316
+ type: ConcreteNodeTypes.Comparison,
317
+ comparator: 2,
318
+ left: 0,
319
+ right: 4,
320
+ locStart,
321
+ locEnd,
322
+ source,
323
+ },
324
+ liquidTagClose: {
325
+ type: ConcreteNodeTypes.LiquidTagClose,
326
+ name: 4,
327
+ whitespaceStart: 1,
328
+ whitespaceEnd: 7,
329
+ locStart,
330
+ locEnd,
331
+ source,
332
+ },
333
+ liquidTag: 0,
334
+ liquidTagStrict: 0,
335
+ liquidTagBaseCase: 0,
336
+ liquidTagAssign: 0,
337
+ liquidTagHashAssign: 0,
338
+ liquidTagEcho: 0,
339
+ liquidTagContentFor: 0,
340
+ liquidTagCycle: 0,
341
+ liquidTagIncrement: 0,
342
+ liquidTagDecrement: 0,
343
+ liquidTagRender: 0,
344
+ liquidTagFunction: 0,
345
+ liquidTagGraphQL: 0,
346
+ liquidTagInclude: 0,
347
+ liquidTagSection: 0,
348
+ liquidTagSections: 0,
349
+ liquidTagLayout: 0,
350
+ liquidTagRule: {
351
+ type: ConcreteNodeTypes.LiquidTag,
352
+ name: 3,
353
+ markup(nodes) {
354
+ const markupNode = nodes[6];
355
+ const nameNode = nodes[3];
356
+ if (types_1.NamedTags.hasOwnProperty(nameNode.sourceString)) {
357
+ return markupNode.toAST(this.args.mapping);
358
+ }
359
+ return markupNode.sourceString.trim();
360
+ },
361
+ whitespaceStart: 1,
362
+ whitespaceEnd: 7,
363
+ source,
364
+ locStart,
365
+ locEnd,
366
+ },
367
+ liquidTagLiquid: 0,
368
+ liquidTagLiquidMarkup(tagMarkup) {
369
+ return toCST(source, grammars, grammars.LiquidStatement, ['HelperMappings', 'LiquidMappings', 'LiquidStatement'], tagMarkup.sourceString, offset + tagMarkup.source.startIdx);
370
+ },
371
+ liquidTagEchoMarkup: 0,
372
+ liquidTagSectionMarkup: 0,
373
+ liquidTagSectionsMarkup: 0,
374
+ liquidTagLayoutMarkup: 0,
375
+ liquidTagAssignMarkup: {
376
+ type: ConcreteNodeTypes.AssignMarkup,
377
+ name: 0,
378
+ value: 4,
379
+ locStart,
380
+ locEnd,
381
+ source,
382
+ },
383
+ liquidTagHashAssignMarkup: {
384
+ type: ConcreteNodeTypes.HashAssignMarkup,
385
+ target: 0,
386
+ value: 4,
387
+ locStart,
388
+ locEnd,
389
+ source,
390
+ },
391
+ liquidTagCycleMarkup: {
392
+ type: ConcreteNodeTypes.CycleMarkup,
393
+ groupName: 0,
394
+ args: 3,
395
+ locStart,
396
+ locEnd,
397
+ source,
398
+ },
399
+ liquidTagContentForMarkup: {
400
+ type: ConcreteNodeTypes.ContentForMarkup,
401
+ contentForType: 0,
402
+ args: 2,
403
+ locStart,
404
+ locEnd,
405
+ source,
406
+ },
407
+ contentForType: 0,
408
+ liquidTagRenderMarkup: {
409
+ type: ConcreteNodeTypes.RenderMarkup,
410
+ snippet: 0,
411
+ variable: 1,
412
+ alias: 2,
413
+ renderArguments: 3,
414
+ locStart,
415
+ locEnd,
416
+ source,
417
+ },
418
+ liquidTagFunctionMarkup: {
419
+ type: ConcreteNodeTypes.FunctionMarkup,
420
+ name: 0,
421
+ partial: 4,
422
+ functionArguments: 5,
423
+ locStart,
424
+ locEnd,
425
+ source,
426
+ },
427
+ liquidTagGraphQLMarkup: {
428
+ type: ConcreteNodeTypes.GraphQLMarkup,
429
+ name: 0,
430
+ graphql: 4,
431
+ functionArguments: 5,
432
+ locStart,
433
+ locEnd,
434
+ source,
435
+ },
436
+ liquidTagGraphQLInlineMarkup: {
437
+ type: ConcreteNodeTypes.GraphQLInlineMarkup,
438
+ name: 0,
439
+ args: 1,
440
+ locStart,
441
+ locEnd,
442
+ source,
443
+ },
444
+ // platformos tag mappings
445
+ liquidTagBackground: 0,
446
+ liquidTagBackgroundMarkup: {
447
+ type: ConcreteNodeTypes.BackgroundMarkup,
448
+ jobId: 0,
449
+ partial: 4,
450
+ args: 5,
451
+ locStart,
452
+ locEnd,
453
+ source,
454
+ },
455
+ liquidTagOpenBackground: 0,
456
+ liquidTagBackgroundInlineMarkup: {
457
+ type: ConcreteNodeTypes.BackgroundInlineMarkup,
458
+ jobId: 0,
459
+ args: 2,
460
+ locStart,
461
+ locEnd,
462
+ source,
463
+ },
464
+ liquidTagOpenCache: 0,
465
+ liquidTagCacheMarkup: {
466
+ type: ConcreteNodeTypes.CacheMarkup,
467
+ key: 0,
468
+ args: 1,
469
+ locStart,
470
+ locEnd,
471
+ source,
472
+ },
473
+ liquidTagOpenParseJson: 0,
474
+ liquidTagOpenTransaction: 0,
475
+ liquidTagOpenTransactionMarkup: 0,
476
+ liquidTagOpenTry: 0,
477
+ liquidTagCatch: 0,
478
+ liquidTagLog: 0,
479
+ liquidTagLogMarkup: {
480
+ type: ConcreteNodeTypes.LogMarkup,
481
+ value: 0,
482
+ args: 1,
483
+ locStart,
484
+ locEnd,
485
+ source,
486
+ },
487
+ liquidTagPrint: 0,
488
+ liquidTagReturn: 0,
489
+ liquidTagYield: 0,
490
+ liquidTagYieldMarkup: 0,
491
+ liquidTagSession: 0,
492
+ liquidTagSessionMarkup: {
493
+ type: ConcreteNodeTypes.SessionMarkup,
494
+ name: 0,
495
+ value: 4,
496
+ locStart,
497
+ locEnd,
498
+ source,
499
+ },
500
+ liquidTagExport: 0,
501
+ liquidTagExportMarkup: {
502
+ type: ConcreteNodeTypes.ExportMarkup,
503
+ variables: 0,
504
+ namespace: 2,
505
+ locStart,
506
+ locEnd,
507
+ source,
508
+ },
509
+ exportVariable: 0,
510
+ liquidTagContext: 0,
511
+ liquidTagContextMarkup: 0,
512
+ liquidTagSignIn: 0,
513
+ liquidTagSignInMarkup: 0,
514
+ liquidTagRedirectTo: 0,
515
+ liquidTagRedirectToMarkup: {
516
+ type: ConcreteNodeTypes.RedirectToMarkup,
517
+ url: 0,
518
+ args: 1,
519
+ locStart,
520
+ locEnd,
521
+ source,
522
+ },
523
+ liquidTagIncludeForm: 0,
524
+ liquidTagIncludeFormMarkup: {
525
+ type: ConcreteNodeTypes.IncludeFormMarkup,
526
+ form: 0,
527
+ args: 1,
528
+ locStart,
529
+ locEnd,
530
+ source,
531
+ },
532
+ liquidTagSpamProtection: 0,
533
+ liquidTagSpamProtectionMarkup: {
534
+ type: ConcreteNodeTypes.SpamProtectionMarkup,
535
+ version: 0,
536
+ args: 1,
537
+ locStart,
538
+ locEnd,
539
+ source,
540
+ },
541
+ liquidTagThemeRenderRc: 0,
542
+ liquidTagResponseStatus: 0,
543
+ liquidTagResponseStatusMarkup: 0,
544
+ liquidTagResponseHeaders: 0,
545
+ liquidTagResponseHeadersMarkup: 0,
546
+ liquidTagRollback: 0,
547
+ renderArguments: 1,
548
+ completionModeRenderArguments: function (_0, namedArguments, _2, _3, _4, _5, variableLookup, _7) {
549
+ const self = this;
550
+ // variableLookup.sourceString can be '' when there are no incomplete params
551
+ return namedArguments
552
+ .toAST(self.args.mapping)
553
+ .concat(variableLookup.sourceString === '' ? [] : variableLookup.toAST(self.args.mapping));
554
+ },
555
+ snippetExpression: 0,
556
+ renderVariableExpression: {
557
+ type: ConcreteNodeTypes.RenderVariableExpression,
558
+ kind: 1,
559
+ name: 3,
560
+ locStart,
561
+ locEnd,
562
+ source,
563
+ },
564
+ renderAliasExpression: {
565
+ type: ConcreteNodeTypes.RenderAliasExpression,
566
+ value: 3,
567
+ locStart,
568
+ locEnd,
569
+ source,
570
+ },
571
+ liquidDrop: {
572
+ type: ConcreteNodeTypes.LiquidVariableOutput,
573
+ markup: 3,
574
+ whitespaceStart: 1,
575
+ whitespaceEnd: 4,
576
+ locStart,
577
+ locEnd,
578
+ source,
579
+ },
580
+ liquidDropCases: 0,
581
+ liquidExpression: 0,
582
+ liquidComplexExpression: 0,
583
+ liquidDropBaseCase: (sw) => sw.sourceString.trimEnd(),
584
+ liquidVariable: {
585
+ type: ConcreteNodeTypes.LiquidVariable,
586
+ expression: 0,
587
+ filters: 1,
588
+ rawSource: (tokens) => source.slice(locStart(tokens), tokens[tokens.length - 2].source.endIdx).trimEnd(),
589
+ locStart,
590
+ // The last node of this rule is a positive lookahead, we don't
591
+ // want its endIdx, we want the endIdx of the previous one.
592
+ locEnd: locEndSecondToLast,
593
+ source,
594
+ },
595
+ liquidFilter: {
596
+ type: ConcreteNodeTypes.LiquidFilter,
597
+ name: 3,
598
+ locStart,
599
+ locEnd,
600
+ source,
601
+ args(nodes) {
602
+ // Traditinally, this would get transformed into null or array. But
603
+ // it's better if we have an empty array instead of null here.
604
+ if (nodes[7].sourceString === '') {
605
+ return [];
606
+ }
607
+ else {
608
+ return nodes[7].toAST(this.args.mapping);
609
+ }
610
+ },
611
+ },
612
+ filterArguments: 0,
613
+ arguments: 0,
614
+ complexArguments: function (completeParams, _space1, _comma, _space2, incompleteParam) {
615
+ const self = this;
616
+ return completeParams
617
+ .toAST(self.args.mapping)
618
+ .concat(incompleteParam.sourceString === '' ? [] : incompleteParam.toAST(self.args.mapping));
619
+ },
620
+ simpleArgument: 0,
621
+ tagArguments: 0,
622
+ contentForTagArgument: 0,
623
+ completionModeContentForTagArgument: function (namedArguments, _separator, variableLookup) {
624
+ const self = this;
625
+ return namedArguments
626
+ .toAST(self.args.mapping)
627
+ .concat(variableLookup.sourceString === '' ? [] : variableLookup.toAST(self.args.mapping));
628
+ },
629
+ positionalArgument: 0,
630
+ namedArgument: {
631
+ type: ConcreteNodeTypes.NamedArgument,
632
+ name: 0,
633
+ value: 4,
634
+ locStart,
635
+ locEnd,
636
+ source,
637
+ },
638
+ contentForNamedArgument: {
639
+ type: ConcreteNodeTypes.NamedArgument,
640
+ name: (node) => node[0].sourceString + node[1].sourceString,
641
+ value: 6,
642
+ locStart,
643
+ locEnd,
644
+ source,
645
+ },
646
+ liquidBooleanExpression(initialCondition, subsequentConditions) {
647
+ const initialConditionAst = initialCondition.toAST(this.args.mapping);
648
+ const subsequentConditionAsts = subsequentConditions.toAST(this.args.mapping);
649
+ // liquidBooleanExpression can capture too much. If there are no comparisons (e.g. `==`, `>`, etc.)
650
+ // and we only have a single condition (i.e. no `and` or `or` operators), we can return the expression directly.
651
+ if (subsequentConditionAsts.length === 0 &&
652
+ initialConditionAst.expression.type !== ConcreteNodeTypes.Comparison) {
653
+ return initialConditionAst.expression;
654
+ }
655
+ const asts = [initialConditionAst, ...subsequentConditionAsts];
656
+ return {
657
+ type: ConcreteNodeTypes.BooleanExpression,
658
+ conditions: asts,
659
+ locStart: asts.at(0).locStart,
660
+ locEnd: asts.at(-1).locEnd,
661
+ source,
662
+ };
663
+ },
664
+ booleanExpressionCondition: {
665
+ type: ConcreteNodeTypes.Condition,
666
+ relation: null,
667
+ expression: 0,
668
+ locStart,
669
+ locEnd,
670
+ source,
671
+ },
672
+ booleanExpressionSubsequentCondition: {
673
+ type: ConcreteNodeTypes.Condition,
674
+ relation: 1,
675
+ expression: 3,
676
+ locStart,
677
+ locEnd,
678
+ source,
679
+ },
680
+ liquidString: 0,
681
+ liquidDoubleQuotedString: {
682
+ type: ConcreteNodeTypes.String,
683
+ single: () => false,
684
+ value: 1,
685
+ locStart,
686
+ locEnd,
687
+ source,
688
+ },
689
+ liquidSingleQuotedString: {
690
+ type: ConcreteNodeTypes.String,
691
+ single: () => true,
692
+ value: 1,
693
+ locStart,
694
+ locEnd,
695
+ source,
696
+ },
697
+ liquidNumber: {
698
+ type: ConcreteNodeTypes.Number,
699
+ value: 0,
700
+ locStart,
701
+ locEnd,
702
+ source,
703
+ },
704
+ liquidLiteral: {
705
+ type: ConcreteNodeTypes.LiquidLiteral,
706
+ value: (tokens) => {
707
+ const keyword = tokens[0].sourceString;
708
+ return exports.LiquidLiteralValues[keyword];
709
+ },
710
+ keyword: 0,
711
+ locStart,
712
+ locEnd,
713
+ source,
714
+ },
715
+ liquidRange: {
716
+ type: ConcreteNodeTypes.Range,
717
+ start: 2,
718
+ end: 6,
719
+ locStart,
720
+ locEnd,
721
+ source,
722
+ },
723
+ liquidVariableLookup: {
724
+ type: ConcreteNodeTypes.VariableLookup,
725
+ name: 0,
726
+ lookups: 1,
727
+ locStart,
728
+ locEnd,
729
+ source,
730
+ },
731
+ variableSegmentAsLookupMarkup: 0,
732
+ variableSegmentAsLookup: {
733
+ type: ConcreteNodeTypes.VariableLookup,
734
+ name: 0,
735
+ lookups: () => [],
736
+ locStart,
737
+ locEnd,
738
+ source,
739
+ },
740
+ lookup: 0,
741
+ indexLookup: 3,
742
+ dotLookup: {
743
+ type: ConcreteNodeTypes.String,
744
+ value: 3,
745
+ locStart: (nodes) => offset + nodes[2].source.startIdx,
746
+ locEnd: (nodes) => offset + nodes[nodes.length - 1].source.endIdx,
747
+ source,
748
+ },
749
+ // trim on both sides
750
+ tagMarkup: (n) => n.sourceString.trim(),
751
+ };
752
+ const LiquidStatement = {
753
+ LiquidStatement: 0,
754
+ liquidTagOpenRule: {
755
+ type: ConcreteNodeTypes.LiquidTagOpen,
756
+ name: 0,
757
+ markup(nodes) {
758
+ const markupNode = nodes[2];
759
+ const nameNode = nodes[0];
760
+ if (types_1.NamedTags.hasOwnProperty(nameNode.sourceString)) {
761
+ return markupNode.toAST(this.args.mapping);
762
+ }
763
+ return markupNode.sourceString.trim();
764
+ },
765
+ whitespaceStart: null,
766
+ whitespaceEnd: null,
767
+ locStart,
768
+ locEnd: locEndSecondToLast,
769
+ source,
770
+ },
771
+ liquidTagClose: {
772
+ type: ConcreteNodeTypes.LiquidTagClose,
773
+ name: 1,
774
+ whitespaceStart: null,
775
+ whitespaceEnd: null,
776
+ locStart,
777
+ locEnd: locEndSecondToLast,
778
+ source,
779
+ },
780
+ liquidTagRule: {
781
+ type: ConcreteNodeTypes.LiquidTag,
782
+ name: 0,
783
+ markup(nodes) {
784
+ const markupNode = nodes[2];
785
+ const nameNode = nodes[0];
786
+ if (types_1.NamedTags.hasOwnProperty(nameNode.sourceString)) {
787
+ return markupNode.toAST(this.args.mapping);
788
+ }
789
+ return markupNode.sourceString.trim();
790
+ },
791
+ whitespaceStart: null,
792
+ whitespaceEnd: null,
793
+ locStart,
794
+ locEnd: locEndSecondToLast,
795
+ source,
796
+ },
797
+ liquidRawTagImpl: {
798
+ type: ConcreteNodeTypes.LiquidRawTag,
799
+ name: 0,
800
+ body: 4,
801
+ children(nodes) {
802
+ return toCST(source, grammars, grammar_1.TextNodeGrammar, ['HelperMappings'], nodes[4].sourceString, offset + nodes[4].source.startIdx);
803
+ },
804
+ whitespaceStart: null,
805
+ whitespaceEnd: null,
806
+ delimiterWhitespaceStart: null,
807
+ delimiterWhitespaceEnd: null,
808
+ locStart,
809
+ locEnd: locEndSecondToLast,
810
+ source,
811
+ blockStartLocStart: (tokens) => offset + tokens[0].source.startIdx,
812
+ blockStartLocEnd: (tokens) => offset + tokens[2].source.endIdx,
813
+ blockEndLocStart: (tokens) => offset + tokens[5].source.startIdx,
814
+ blockEndLocEnd: (tokens) => offset + tokens[5].source.endIdx,
815
+ },
816
+ liquidBlockComment: {
817
+ type: ConcreteNodeTypes.LiquidRawTag,
818
+ name: 'comment',
819
+ body: (tokens) =>
820
+ // We want this to behave like LiquidRawTag, so we have to do some
821
+ // shenanigans to make it behave the same while also supporting
822
+ // nested comments
823
+ //
824
+ // We're stripping the newline from the statementSep, that's why we
825
+ // slice(1). Since statementSep = newline (space | newline)*
826
+ tokens[1].sourceString.slice(1) + tokens[2].sourceString,
827
+ children(tokens) {
828
+ const commentSource = tokens[1].sourceString.slice(1) + tokens[2].sourceString;
829
+ return toCST(source, grammars, grammar_1.TextNodeGrammar, ['HelperMappings'], commentSource, offset + tokens[1].source.startIdx + 1);
830
+ },
831
+ whitespaceStart: '',
832
+ whitespaceEnd: '',
833
+ delimiterWhitespaceStart: '',
834
+ delimiterWhitespaceEnd: '',
835
+ locStart,
836
+ locEnd,
837
+ source,
838
+ blockStartLocStart: (tokens) => offset + tokens[0].source.startIdx,
839
+ blockStartLocEnd: (tokens) => offset + tokens[0].source.endIdx,
840
+ blockEndLocStart: (tokens) => offset + tokens[4].source.startIdx,
841
+ blockEndLocEnd: (tokens) => offset + tokens[4].source.endIdx,
842
+ },
843
+ liquidInlineComment: {
844
+ type: ConcreteNodeTypes.LiquidTag,
845
+ name: 0,
846
+ markup: markupTrimEnd(2),
847
+ whitespaceStart: null,
848
+ whitespaceEnd: null,
849
+ locStart,
850
+ locEnd: locEndSecondToLast,
851
+ source,
852
+ },
853
+ };
854
+ const LiquidHTMLMappings = {
855
+ Node(frontmatter, nodes) {
856
+ const self = this;
857
+ const frontmatterNode = frontmatter.sourceString.length === 0 ? [] : [frontmatter.toAST(self.args.mapping)];
858
+ return frontmatterNode.concat(nodes.toAST(self.args.mapping));
859
+ },
860
+ yamlFrontmatter: {
861
+ type: ConcreteNodeTypes.YAMLFrontmatter,
862
+ body: 2,
863
+ locStart,
864
+ locEnd,
865
+ source,
866
+ },
867
+ HtmlDoctype: {
868
+ type: ConcreteNodeTypes.HtmlDoctype,
869
+ legacyDoctypeString: 4,
870
+ locStart,
871
+ locEnd,
872
+ source,
873
+ },
874
+ HtmlComment: {
875
+ type: ConcreteNodeTypes.HtmlComment,
876
+ body: markup(1),
877
+ locStart,
878
+ locEnd,
879
+ source,
880
+ },
881
+ HtmlRawTagImpl: {
882
+ type: ConcreteNodeTypes.HtmlRawTag,
883
+ name: (tokens) => tokens[0].children[1].sourceString,
884
+ attrList(tokens) {
885
+ const mappings = this.args.mapping;
886
+ return tokens[0].children[2].toAST(mappings);
887
+ },
888
+ body: (tokens) => source.slice(tokens[0].source.endIdx, tokens[2].source.startIdx),
889
+ children: (tokens) => {
890
+ const rawMarkup = source.slice(tokens[0].source.endIdx, tokens[2].source.startIdx);
891
+ return toCST(source, grammars, grammars.Liquid, ['HelperMappings', 'LiquidMappings'], rawMarkup, tokens[0].source.endIdx);
892
+ },
893
+ locStart,
894
+ locEnd,
895
+ source,
896
+ blockStartLocStart: (tokens) => tokens[0].source.startIdx,
897
+ blockStartLocEnd: (tokens) => tokens[0].source.endIdx,
898
+ blockEndLocStart: (tokens) => tokens[2].source.startIdx,
899
+ blockEndLocEnd: (tokens) => tokens[2].source.endIdx,
900
+ },
901
+ HtmlVoidElement: {
902
+ type: ConcreteNodeTypes.HtmlVoidElement,
903
+ name: 1,
904
+ attrList: 3,
905
+ locStart,
906
+ locEnd,
907
+ source,
908
+ },
909
+ HtmlSelfClosingElement: {
910
+ type: ConcreteNodeTypes.HtmlSelfClosingElement,
911
+ name: 1,
912
+ attrList: 2,
913
+ locStart,
914
+ locEnd,
915
+ source,
916
+ },
917
+ HtmlTagOpen: {
918
+ type: ConcreteNodeTypes.HtmlTagOpen,
919
+ name: 1,
920
+ attrList: 2,
921
+ locStart,
922
+ locEnd,
923
+ source,
924
+ },
925
+ HtmlTagClose: {
926
+ type: ConcreteNodeTypes.HtmlTagClose,
927
+ name: 1,
928
+ locStart,
929
+ locEnd,
930
+ source,
931
+ },
932
+ leadingTagNamePart: 0,
933
+ leadingTagNameTextNode: textNode,
934
+ trailingTagNamePart: 0,
935
+ trailingTagNameTextNode: textNode,
936
+ tagName(leadingPart, trailingParts) {
937
+ const mappings = this.args.mapping;
938
+ return [leadingPart.toAST(mappings)].concat(trailingParts.toAST(mappings));
939
+ },
940
+ AttrUnquoted: {
941
+ type: ConcreteNodeTypes.AttrUnquoted,
942
+ name: 0,
943
+ value: 2,
944
+ locStart,
945
+ locEnd,
946
+ source,
947
+ },
948
+ AttrSingleQuoted: {
949
+ type: ConcreteNodeTypes.AttrSingleQuoted,
950
+ name: 0,
951
+ value: 3,
952
+ locStart,
953
+ locEnd,
954
+ source,
955
+ },
956
+ AttrDoubleQuoted: {
957
+ type: ConcreteNodeTypes.AttrDoubleQuoted,
958
+ name: 0,
959
+ value: 3,
960
+ locStart,
961
+ locEnd,
962
+ source,
963
+ },
964
+ attrEmpty: {
965
+ type: ConcreteNodeTypes.AttrEmpty,
966
+ name: 0,
967
+ locStart,
968
+ locEnd,
969
+ source,
970
+ },
971
+ attrName: 0,
972
+ attrNameTextNode: textNode,
973
+ attrDoubleQuotedValue: 0,
974
+ attrSingleQuotedValue: 0,
975
+ attrUnquotedValue: 0,
976
+ attrDoubleQuotedTextNode: textNode,
977
+ attrSingleQuotedTextNode: textNode,
978
+ attrUnquotedTextNode: textNode,
979
+ };
980
+ const defaultMappings = {
981
+ HelperMappings,
982
+ LiquidMappings,
983
+ LiquidHTMLMappings,
984
+ LiquidStatement,
985
+ };
986
+ const selectedMappings = cstMappings.reduce((mappings, key) => ({
987
+ ...mappings,
988
+ ...defaultMappings[key],
989
+ }), {});
990
+ return (0, extras_1.toAST)(res, selectedMappings);
991
+ }
992
+ /**
993
+ * Builds an AST for LiquidDoc content.
994
+ *
995
+ * `toCST` includes mappings and logic that are not needed for LiquidDoc so we're separating this logic
996
+ */
997
+ function toLiquidDocAST(source, matchingSource, offset) {
998
+ // When we switch parser, our locStart and locEnd functions must account
999
+ // for the offset of the {% doc %} markup
1000
+ const locStart = (tokens) => offset + tokens[0].source.startIdx;
1001
+ const locEnd = (tokens) => offset + tokens[tokens.length - 1].source.endIdx;
1002
+ const res = grammar_1.LiquidDocGrammar.match(matchingSource, 'Node');
1003
+ if (res.failed()) {
1004
+ throw new errors_1.LiquidHTMLCSTParsingError(res);
1005
+ }
1006
+ /**
1007
+ * Reusable text node type
1008
+ */
1009
+ const textNode = () => ({
1010
+ type: ConcreteNodeTypes.TextNode,
1011
+ value: function () {
1012
+ return this.sourceString;
1013
+ },
1014
+ locStart,
1015
+ locEnd,
1016
+ source,
1017
+ });
1018
+ const LiquidDocMappings = {
1019
+ Node(implicitDescription, body) {
1020
+ const self = this;
1021
+ const implicitDescriptionNode = implicitDescription.sourceString.length === 0
1022
+ ? []
1023
+ : [implicitDescription.toAST(self.args.mapping)];
1024
+ return implicitDescriptionNode.concat(body.toAST(self.args.mapping));
1025
+ },
1026
+ ImplicitDescription: {
1027
+ type: ConcreteNodeTypes.LiquidDocDescriptionNode,
1028
+ name: 'description',
1029
+ locStart,
1030
+ locEnd,
1031
+ source,
1032
+ content: 0,
1033
+ isImplicit: true,
1034
+ isInline: true,
1035
+ },
1036
+ TextNode: textNode(),
1037
+ paramNode: {
1038
+ type: ConcreteNodeTypes.LiquidDocParamNode,
1039
+ name: 'param',
1040
+ locStart,
1041
+ locEnd,
1042
+ source,
1043
+ paramType: 2,
1044
+ paramName: 4,
1045
+ paramDescription: 8,
1046
+ },
1047
+ descriptionNode: {
1048
+ type: ConcreteNodeTypes.LiquidDocDescriptionNode,
1049
+ name: 'description',
1050
+ locStart,
1051
+ locEnd,
1052
+ source,
1053
+ content: 2,
1054
+ isImplicit: false,
1055
+ isInline: function () {
1056
+ return !this.children[1].sourceString.includes('\n');
1057
+ },
1058
+ },
1059
+ descriptionContent: textNode(),
1060
+ paramType: 2,
1061
+ paramTypeContent: textNode(),
1062
+ paramName: {
1063
+ type: ConcreteNodeTypes.LiquidDocParamNameNode,
1064
+ content: 0,
1065
+ locStart,
1066
+ locEnd,
1067
+ source,
1068
+ required: true,
1069
+ },
1070
+ optionalParamName: {
1071
+ type: ConcreteNodeTypes.LiquidDocParamNameNode,
1072
+ content: 2,
1073
+ locStart,
1074
+ locEnd,
1075
+ source,
1076
+ required: false,
1077
+ },
1078
+ paramDescription: textNode(),
1079
+ exampleNode: {
1080
+ type: ConcreteNodeTypes.LiquidDocExampleNode,
1081
+ name: 'example',
1082
+ locStart,
1083
+ locEnd,
1084
+ source,
1085
+ content: 2,
1086
+ isInline: function () {
1087
+ return !this.children[1].sourceString.includes('\n');
1088
+ },
1089
+ },
1090
+ promptNode: {
1091
+ type: ConcreteNodeTypes.LiquidDocPromptNode,
1092
+ name: 'prompt',
1093
+ locStart,
1094
+ locEnd,
1095
+ source,
1096
+ content: 1,
1097
+ },
1098
+ multilineTextContent: textNode(),
1099
+ textValue: textNode(),
1100
+ fallbackNode: textNode(),
1101
+ };
1102
+ return (0, extras_1.toAST)(res, LiquidDocMappings);
1103
+ }
1104
+ //# sourceMappingURL=stage-1-cst.js.map