@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.
- package/README.md +62 -0
- package/dist/conditional-comment.d.ts +5 -0
- package/dist/conditional-comment.js +16 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +57 -0
- package/dist/grammar.d.ts +16 -0
- package/dist/grammar.js +42 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +28 -0
- package/dist/stage-1-cst.d.ts +477 -0
- package/dist/stage-1-cst.js +1104 -0
- package/dist/stage-2-ast.d.ts +794 -0
- package/dist/stage-2-ast.js +1513 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.js +146 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +31 -0
- package/grammar/liquid-html.ohm +750 -0
- package/grammar/liquid-html.ohm.js +751 -0
- package/package.json +41 -0
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is the second stage of the parser.
|
|
3
|
+
*
|
|
4
|
+
* Input:
|
|
5
|
+
* - A Concrete Syntax Tree (CST)
|
|
6
|
+
*
|
|
7
|
+
* Output:
|
|
8
|
+
* - An Abstract Syntax Tree (AST)
|
|
9
|
+
*
|
|
10
|
+
* This stage traverses the flat tree we get from the previous stage and
|
|
11
|
+
* establishes the parent/child relationship between the nodes.
|
|
12
|
+
*
|
|
13
|
+
* Recall the Liquid example we had in the first stage:
|
|
14
|
+
* {% if cond %}hi <em>there!</em>{% endif %}
|
|
15
|
+
*
|
|
16
|
+
* Whereas the previous stage gives us this CST:
|
|
17
|
+
* - LiquidTagOpen/if
|
|
18
|
+
* condition: LiquidVariableExpression/cond
|
|
19
|
+
* - TextNode/"hi "
|
|
20
|
+
* - HtmlTagOpen/em
|
|
21
|
+
* - TextNode/"there!"
|
|
22
|
+
* - HtmlTagClose/em
|
|
23
|
+
* - LiquidTagClose/if
|
|
24
|
+
*
|
|
25
|
+
* We now traverse all the nodes and turn that into a proper AST:
|
|
26
|
+
* - LiquidTag/if
|
|
27
|
+
* condition: LiquidVariableExpression
|
|
28
|
+
* children:
|
|
29
|
+
* - TextNode/"hi "
|
|
30
|
+
* - HtmlElement/em
|
|
31
|
+
* children:
|
|
32
|
+
* - TextNode/"there!"
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
import { ConcreteAttributeNode, ConcreteHtmlTagClose, ConcreteLiquidTagClose, LiquidCST, LiquidHtmlCST, ConcreteLiquidLiteral } from './stage-1-cst';
|
|
36
|
+
import { Comparators, NamedTags, NodeTypes, Position } from './types';
|
|
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 | PaginateMarkup | RawMarkup | RenderVariableExpression | RenderAliasExpression | LiquidLogicalExpression | LiquidComparison | TextNode | LiquidDocParamNode | LiquidDocExampleNode | LiquidDocPromptNode | LiquidDocDescriptionNode | BackgroundMarkup | BackgroundInlineMarkup | CacheMarkup | LogMarkup | SessionMarkup | ExportMarkup | RedirectToMarkup | IncludeFormMarkup | SpamProtectionMarkup;
|
|
39
|
+
/** The root node of all LiquidHTML ASTs. */
|
|
40
|
+
export interface DocumentNode extends ASTNode<NodeTypes.Document> {
|
|
41
|
+
children: LiquidHtmlNode[];
|
|
42
|
+
name: '#document';
|
|
43
|
+
_source: string;
|
|
44
|
+
}
|
|
45
|
+
export interface YAMLFrontmatter extends ASTNode<NodeTypes.YAMLFrontmatter> {
|
|
46
|
+
body: string;
|
|
47
|
+
}
|
|
48
|
+
/** The union type of every node that are considered Liquid. {% ... %}, {{ ... }} */
|
|
49
|
+
export type LiquidNode = LiquidRawTag | LiquidTag | LiquidVariableOutput | LiquidBranch;
|
|
50
|
+
/** The union type of every node that could should up in a {% liquid %} tag */
|
|
51
|
+
export type LiquidStatement = LiquidRawTag | LiquidTag | LiquidBranch;
|
|
52
|
+
export interface HasChildren {
|
|
53
|
+
children?: LiquidHtmlNode[];
|
|
54
|
+
}
|
|
55
|
+
export interface HasAttributes {
|
|
56
|
+
attributes: AttributeNode[];
|
|
57
|
+
}
|
|
58
|
+
export interface HasValue {
|
|
59
|
+
value: (TextNode | LiquidNode)[];
|
|
60
|
+
}
|
|
61
|
+
export interface HasName {
|
|
62
|
+
name: string | LiquidVariableOutput;
|
|
63
|
+
}
|
|
64
|
+
export interface HasCompoundName {
|
|
65
|
+
name: (TextNode | LiquidNode)[];
|
|
66
|
+
}
|
|
67
|
+
export type ParentNode = Extract<LiquidHtmlNode, HasChildren | HasAttributes | HasValue | HasName | HasCompoundName>;
|
|
68
|
+
/**
|
|
69
|
+
* A LiquidRawTag is one that is parsed such that its body is a raw string.
|
|
70
|
+
*
|
|
71
|
+
* Examples:
|
|
72
|
+
* - {% raw %}...{% endraw %}
|
|
73
|
+
* - {% javascript %}...{% endjavascript %}
|
|
74
|
+
* - {% style %}...{% endstyle %}
|
|
75
|
+
*/
|
|
76
|
+
export interface LiquidRawTag extends ASTNode<NodeTypes.LiquidRawTag> {
|
|
77
|
+
/** e.g. raw, style, javascript */
|
|
78
|
+
name: string;
|
|
79
|
+
/** The non-name part inside the opening Liquid tag. {% tagName [markup] %} */
|
|
80
|
+
markup: string;
|
|
81
|
+
/** String body of the tag. We don't try to parse it. */
|
|
82
|
+
body: RawMarkup;
|
|
83
|
+
/** {%- tag %} */
|
|
84
|
+
whitespaceStart: '-' | '';
|
|
85
|
+
/** {% tag -%} */
|
|
86
|
+
whitespaceEnd: '-' | '';
|
|
87
|
+
/** {%- endtag %} */
|
|
88
|
+
delimiterWhitespaceStart: '-' | '';
|
|
89
|
+
/** {% endtag -%} */
|
|
90
|
+
delimiterWhitespaceEnd: '-' | '';
|
|
91
|
+
/** the range of the opening tag {% tag %} */
|
|
92
|
+
blockStartPosition: Position;
|
|
93
|
+
/** the range of the closing tag {% endtag %}*/
|
|
94
|
+
blockEndPosition: Position;
|
|
95
|
+
}
|
|
96
|
+
/** The union type of strictly typed and loosely typed Liquid tag nodes */
|
|
97
|
+
export type LiquidTag = LiquidTagNamed | LiquidTagBaseCase;
|
|
98
|
+
/** The union type of all strictly typed LiquidTag nodes */
|
|
99
|
+
export type LiquidTagNamed = LiquidTagAssign | LiquidTagHashAssign | LiquidTagCase | LiquidTagCapture | LiquidTagContentFor | LiquidTagCycle | LiquidTagDecrement | LiquidTagEcho | LiquidTagFor | LiquidTagForm | LiquidTagIf | LiquidTagInclude | LiquidTagIncrement | LiquidTagLayout | LiquidTagLiquid | LiquidTagPaginate | LiquidTagRender | LiquidTagFunction | LiquidTagGraphQL | LiquidTagSection | LiquidTagSections | LiquidTagTablerow | LiquidTagUnless | LiquidTagBackground | LiquidTagCache | LiquidTagContext | LiquidTagExport | LiquidTagIncludeForm | LiquidTagLog | LiquidTagParseJson | LiquidTagPrint | LiquidTagRedirectTo | LiquidTagResponseHeaders | LiquidTagResponseStatus | LiquidTagReturn | LiquidTagRollback | LiquidTagSession | LiquidTagSignIn | LiquidTagSpamProtection | LiquidTagThemeRenderRc | LiquidTagTransaction | LiquidTagTry | LiquidTagYield;
|
|
100
|
+
export interface LiquidTagNode<Name, Markup> extends ASTNode<NodeTypes.LiquidTag> {
|
|
101
|
+
/** e.g. if, ifchanged, for, etc. */
|
|
102
|
+
name: Name;
|
|
103
|
+
/** The non-name part inside the opening Liquid tag. {% tagName [markup] %} */
|
|
104
|
+
markup: Markup;
|
|
105
|
+
/** If the node has child nodes, the array of child nodes */
|
|
106
|
+
children?: LiquidHtmlNode[];
|
|
107
|
+
/** {%- tag %} */
|
|
108
|
+
whitespaceStart: '-' | '';
|
|
109
|
+
/** {% tag -%} */
|
|
110
|
+
whitespaceEnd: '-' | '';
|
|
111
|
+
/** {%- endtag %}, if it has one */
|
|
112
|
+
delimiterWhitespaceStart?: '-' | '';
|
|
113
|
+
/** {% endtag -%}, if it has one */
|
|
114
|
+
delimiterWhitespaceEnd?: '-' | '';
|
|
115
|
+
/** the range of the opening tag {% tag %} */
|
|
116
|
+
blockStartPosition: Position;
|
|
117
|
+
/** the range of the closing tag {% endtag %}, if it has one */
|
|
118
|
+
blockEndPosition?: Position;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* LiquidTagBaseCase exists as a fallback for when we can't strictly parse a tag.
|
|
122
|
+
*
|
|
123
|
+
* For any of the following reasons:
|
|
124
|
+
* - there's a syntax error in the markup and we want to be resilient
|
|
125
|
+
* - the parser does not support the tag (yet) and we want to be resilient
|
|
126
|
+
*
|
|
127
|
+
* As such, when we parse `{% tagName [markup] %}`, LiquidTagBaseCase is the
|
|
128
|
+
* case where `markup` is parsed as a string instead of anything specific.
|
|
129
|
+
*/
|
|
130
|
+
export interface LiquidTagBaseCase extends LiquidTagNode<string, string> {
|
|
131
|
+
}
|
|
132
|
+
/** https://shopify.dev/docs/api/liquid/tags#echo */
|
|
133
|
+
export interface LiquidTagEcho extends LiquidTagNode<NamedTags.echo, LiquidVariable> {
|
|
134
|
+
}
|
|
135
|
+
/** https://shopify.dev/docs/api/liquid/tags#assign */
|
|
136
|
+
export interface LiquidTagAssign extends LiquidTagNode<NamedTags.assign, AssignMarkup> {
|
|
137
|
+
}
|
|
138
|
+
/** {% assign name = value %} */
|
|
139
|
+
export interface AssignMarkup extends ASTNode<NodeTypes.AssignMarkup> {
|
|
140
|
+
/** the name of the variable that is being assigned */
|
|
141
|
+
name: string;
|
|
142
|
+
/** the value of the variable that is being assigned */
|
|
143
|
+
value: LiquidVariable;
|
|
144
|
+
}
|
|
145
|
+
export interface LiquidTagHashAssign extends LiquidTagNode<NamedTags.hash_assign, HashAssignMarkup> {
|
|
146
|
+
}
|
|
147
|
+
/** {% hash_assign target['key'] = value | parse_json %} */
|
|
148
|
+
export interface HashAssignMarkup extends ASTNode<NodeTypes.HashAssignMarkup> {
|
|
149
|
+
/** the target variable lookup (e.g., a['key'] or a['nested']['key']) */
|
|
150
|
+
target: LiquidVariableLookup;
|
|
151
|
+
/** the value of the variable that is being assigned */
|
|
152
|
+
value: LiquidVariable;
|
|
153
|
+
}
|
|
154
|
+
/** https://shopify.dev/docs/api/liquid/tags#increment */
|
|
155
|
+
export interface LiquidTagIncrement extends LiquidTagNode<NamedTags.increment, LiquidVariableLookup> {
|
|
156
|
+
}
|
|
157
|
+
/** https://shopify.dev/docs/api/liquid/tags#decrement */
|
|
158
|
+
export interface LiquidTagDecrement extends LiquidTagNode<NamedTags.decrement, LiquidVariableLookup> {
|
|
159
|
+
}
|
|
160
|
+
/** https://shopify.dev/docs/api/liquid/tags#capture */
|
|
161
|
+
export interface LiquidTagCapture extends LiquidTagNode<NamedTags.capture, LiquidVariableLookup> {
|
|
162
|
+
}
|
|
163
|
+
/** https://shopify.dev/docs/api/liquid/tags#cycle */
|
|
164
|
+
export interface LiquidTagCycle extends LiquidTagNode<NamedTags.cycle, CycleMarkup> {
|
|
165
|
+
}
|
|
166
|
+
/** {% cycle [groupName:] arg1, arg2, arg3 %} */
|
|
167
|
+
export interface CycleMarkup extends ASTNode<NodeTypes.CycleMarkup> {
|
|
168
|
+
/** {% cycle groupName: arg1, arg2, arg3 %} */
|
|
169
|
+
groupName: LiquidExpression | null;
|
|
170
|
+
/** {% cycle arg1, arg2, arg3, ... %} */
|
|
171
|
+
args: LiquidExpression[];
|
|
172
|
+
}
|
|
173
|
+
/** https://shopify.dev/docs/api/liquid/tags#case */
|
|
174
|
+
export interface LiquidTagCase extends LiquidTagNode<NamedTags.case, LiquidExpression> {
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* {% when expression1, expression2 or expression3 %}
|
|
178
|
+
* children
|
|
179
|
+
*/
|
|
180
|
+
export interface LiquidBranchWhen extends LiquidBranchNode<NamedTags.when, LiquidExpression[]> {
|
|
181
|
+
}
|
|
182
|
+
/** https://shopify.dev/docs/api/liquid/tags#form */
|
|
183
|
+
export interface LiquidTagForm extends LiquidTagNode<NamedTags.form, LiquidArgument[]> {
|
|
184
|
+
}
|
|
185
|
+
/** https://shopify.dev/docs/api/liquid/tags#for */
|
|
186
|
+
export interface LiquidTagFor extends LiquidTagNode<NamedTags.for, ForMarkup> {
|
|
187
|
+
}
|
|
188
|
+
/** {% for variableName in collection [reversed] [...namedArguments] %} */
|
|
189
|
+
export interface ForMarkup extends ASTNode<NodeTypes.ForMarkup> {
|
|
190
|
+
/** {% for variableName in collection %} */
|
|
191
|
+
variableName: string;
|
|
192
|
+
/** {% for variableName in collection %} */
|
|
193
|
+
collection: LiquidExpression;
|
|
194
|
+
/** Whether the for loop is reversed */
|
|
195
|
+
reversed: boolean;
|
|
196
|
+
/** Holds arguments such as limit: 10, offset: 3 */
|
|
197
|
+
args: LiquidNamedArgument[];
|
|
198
|
+
}
|
|
199
|
+
/** https://shopify.dev/docs/api/liquid/tags#tablerow */
|
|
200
|
+
export interface LiquidTagTablerow extends LiquidTagNode<NamedTags.tablerow, ForMarkup> {
|
|
201
|
+
}
|
|
202
|
+
/** https://shopify.dev/docs/api/liquid/tags#if */
|
|
203
|
+
export interface LiquidTagIf extends LiquidTagConditional<NamedTags.if> {
|
|
204
|
+
}
|
|
205
|
+
/** https://shopify.dev/docs/api/liquid/tags#unless */
|
|
206
|
+
export interface LiquidTagUnless extends LiquidTagConditional<NamedTags.unless> {
|
|
207
|
+
}
|
|
208
|
+
/** {% elsif cond %} */
|
|
209
|
+
export interface LiquidBranchElsif extends LiquidBranchNode<NamedTags.elsif, LiquidConditionalExpression> {
|
|
210
|
+
}
|
|
211
|
+
export interface LiquidTagConditional<Name> extends LiquidTagNode<Name, LiquidConditionalExpression> {
|
|
212
|
+
}
|
|
213
|
+
/** The union type of all conditional expression nodes */
|
|
214
|
+
export type LiquidConditionalExpression = LiquidLogicalExpression | LiquidComparison | LiquidExpression;
|
|
215
|
+
/** Represents `left (and|or) right` conditional expressions */
|
|
216
|
+
export interface LiquidLogicalExpression extends ASTNode<NodeTypes.LogicalExpression> {
|
|
217
|
+
relation: 'and' | 'or';
|
|
218
|
+
left: LiquidConditionalExpression;
|
|
219
|
+
right: LiquidConditionalExpression;
|
|
220
|
+
}
|
|
221
|
+
/** Represents `left (<|<=|=|>=|>|contains) right` conditional expressions */
|
|
222
|
+
export interface LiquidComparison extends ASTNode<NodeTypes.Comparison> {
|
|
223
|
+
comparator: Comparators;
|
|
224
|
+
left: LiquidExpression;
|
|
225
|
+
right: LiquidExpression;
|
|
226
|
+
}
|
|
227
|
+
/** https://shopify.dev/docs/api/liquid/tags#paginate */
|
|
228
|
+
export interface LiquidTagPaginate extends LiquidTagNode<NamedTags.paginate, PaginateMarkup> {
|
|
229
|
+
}
|
|
230
|
+
/** {% paginate collection by pageSize [...namedArgs] %} */
|
|
231
|
+
export interface PaginateMarkup extends ASTNode<NodeTypes.PaginateMarkup> {
|
|
232
|
+
/** {% paginate collection by pageSize %} */
|
|
233
|
+
collection: LiquidExpression;
|
|
234
|
+
/** {% paginate collection by pageSize %} */
|
|
235
|
+
pageSize: LiquidExpression;
|
|
236
|
+
/** optional named arguments such as `window_size: 10` */
|
|
237
|
+
args: LiquidNamedArgument[];
|
|
238
|
+
}
|
|
239
|
+
/** https://shopify.dev/docs/api/liquid/tags#content_for */
|
|
240
|
+
export interface LiquidTagContentFor extends LiquidTagNode<NamedTags.content_for, ContentForMarkup> {
|
|
241
|
+
}
|
|
242
|
+
/** https://shopify.dev/docs/api/liquid/tags#render */
|
|
243
|
+
export interface LiquidTagRender extends LiquidTagNode<NamedTags.render, RenderMarkup> {
|
|
244
|
+
}
|
|
245
|
+
export interface LiquidTagFunction extends LiquidTagNode<NamedTags.function, FunctionMarkup> {
|
|
246
|
+
}
|
|
247
|
+
export interface LiquidTagGraphQL extends LiquidTagNode<NamedTags.graphql, GraphQLMarkup | GraphQLInlineMarkup> {
|
|
248
|
+
}
|
|
249
|
+
/** https://shopify.dev/docs/api/liquid/tags#include */
|
|
250
|
+
export interface LiquidTagInclude extends LiquidTagNode<NamedTags.include, RenderMarkup> {
|
|
251
|
+
}
|
|
252
|
+
/** https://shopify.dev/docs/api/liquid/tags#section */
|
|
253
|
+
export interface LiquidTagSection extends LiquidTagNode<NamedTags.section, LiquidString> {
|
|
254
|
+
}
|
|
255
|
+
/** https://shopify.dev/docs/api/liquid/tags#sections */
|
|
256
|
+
export interface LiquidTagSections extends LiquidTagNode<NamedTags.sections, LiquidString> {
|
|
257
|
+
}
|
|
258
|
+
/** https://shopify.dev/docs/api/liquid/tags#layout */
|
|
259
|
+
export interface LiquidTagLayout extends LiquidTagNode<NamedTags.layout, LiquidExpression> {
|
|
260
|
+
}
|
|
261
|
+
/** https://shopify.dev/docs/api/liquid/tags#liquid */
|
|
262
|
+
export interface LiquidTagLiquid extends LiquidTagNode<NamedTags.liquid, LiquidStatement[]> {
|
|
263
|
+
}
|
|
264
|
+
/** {% content_for 'contentForType' [...namedArguments] %} */
|
|
265
|
+
export interface ContentForMarkup extends ASTNode<NodeTypes.ContentForMarkup> {
|
|
266
|
+
/** {% content_for 'contentForType' %} */
|
|
267
|
+
contentForType: LiquidString;
|
|
268
|
+
/**
|
|
269
|
+
* WARNING: `args` could contain LiquidVariableLookup when we are in a completion context
|
|
270
|
+
* because the NamedArgument isn't fully typed out.
|
|
271
|
+
* E.g. {% content_for 'contentForType', arg1: value1, arg2█ %}
|
|
272
|
+
*
|
|
273
|
+
* @example {% content_for 'contentForType', arg1: value1, arg2: value2 %}
|
|
274
|
+
*/
|
|
275
|
+
args: LiquidNamedArgument[];
|
|
276
|
+
}
|
|
277
|
+
/** {% render 'partial' [(with|for) variable [as alias]], [...namedArguments] %} */
|
|
278
|
+
export interface RenderMarkup extends ASTNode<NodeTypes.RenderMarkup> {
|
|
279
|
+
/** {% render snippet %} */
|
|
280
|
+
snippet: LiquidString | LiquidVariableLookup;
|
|
281
|
+
/** {% render 'partial' with thing as alias %} */
|
|
282
|
+
alias: RenderAliasExpression | null;
|
|
283
|
+
/** {% render 'partial' [with variable] %} */
|
|
284
|
+
variable: RenderVariableExpression | null;
|
|
285
|
+
/**
|
|
286
|
+
* WARNING: `args` could contain LiquidVariableLookup when we are in a completion context
|
|
287
|
+
* because the NamedArgument isn't fully typed out.
|
|
288
|
+
* E.g. {% render 'partial', arg1: value1, arg2█ %}
|
|
289
|
+
*
|
|
290
|
+
* @example {% render 'partial', arg1: value1, arg2: value2 %}
|
|
291
|
+
*/
|
|
292
|
+
args: LiquidNamedArgument[];
|
|
293
|
+
}
|
|
294
|
+
/** {% function res = 'partial', [...namedArguments] %} */
|
|
295
|
+
export interface FunctionMarkup extends ASTNode<NodeTypes.FunctionMarkup> {
|
|
296
|
+
/** {% render res = snippet %} */
|
|
297
|
+
name: string;
|
|
298
|
+
partial: LiquidString | LiquidVariableLookup;
|
|
299
|
+
/**
|
|
300
|
+
* WARNING: `args` could contain LiquidVariableLookup when we are in a completion context
|
|
301
|
+
* because the NamedArgument isn't fully typed out.
|
|
302
|
+
* E.g. {% function res = 'partial', arg1: value1, arg2█ %}
|
|
303
|
+
*
|
|
304
|
+
* @example {% function res = 'partial', arg1: value1, arg2: value2 %}
|
|
305
|
+
*/
|
|
306
|
+
args: LiquidNamedArgument[];
|
|
307
|
+
}
|
|
308
|
+
/** {% graphql res = 'path/to/graphql/file', [...namedArguments] %} (file-based) */
|
|
309
|
+
export interface GraphQLMarkup extends ASTNode<NodeTypes.GraphQLMarkup> {
|
|
310
|
+
/** {% graphql res = snippet %} */
|
|
311
|
+
name: string;
|
|
312
|
+
graphql: LiquidString | LiquidVariableLookup;
|
|
313
|
+
/**
|
|
314
|
+
* WARNING: `args` could contain LiquidVariableLookup when we are in a completion context
|
|
315
|
+
* because the NamedArgument isn't fully typed out.
|
|
316
|
+
* E.g. {% graphql res = 'file', arg1: value1, arg2█ %}
|
|
317
|
+
*
|
|
318
|
+
* @example {% graphql res = 'file', arg1: value1, arg2: value2 %}
|
|
319
|
+
*/
|
|
320
|
+
args: LiquidNamedArgument[];
|
|
321
|
+
}
|
|
322
|
+
/** {% graphql res, [...namedArguments] %}...{% endgraphql %} (inline) */
|
|
323
|
+
export interface GraphQLInlineMarkup extends ASTNode<NodeTypes.GraphQLInlineMarkup> {
|
|
324
|
+
/** {% graphql res %} */
|
|
325
|
+
name: string;
|
|
326
|
+
/**
|
|
327
|
+
* WARNING: `args` could contain LiquidVariableLookup when we are in a completion context
|
|
328
|
+
* because the NamedArgument isn't fully typed out.
|
|
329
|
+
* E.g. {% graphql res, arg1: value1, arg2█ %}
|
|
330
|
+
*
|
|
331
|
+
* @example {% graphql res, arg1: value1, arg2: value2 %}
|
|
332
|
+
*/
|
|
333
|
+
args: LiquidNamedArgument[];
|
|
334
|
+
}
|
|
335
|
+
export interface LiquidTagBackground extends LiquidTagNode<NamedTags.background, BackgroundMarkup | BackgroundInlineMarkup> {
|
|
336
|
+
}
|
|
337
|
+
export interface LiquidTagCache extends LiquidTagNode<NamedTags.cache, CacheMarkup> {
|
|
338
|
+
}
|
|
339
|
+
export interface LiquidTagContext extends LiquidTagNode<NamedTags.context, LiquidNamedArgument[]> {
|
|
340
|
+
}
|
|
341
|
+
export interface LiquidTagExport extends LiquidTagNode<NamedTags.export, ExportMarkup> {
|
|
342
|
+
}
|
|
343
|
+
export interface LiquidTagIncludeForm extends LiquidTagNode<NamedTags.include_form, IncludeFormMarkup> {
|
|
344
|
+
}
|
|
345
|
+
export interface LiquidTagLog extends LiquidTagNode<NamedTags.log, LogMarkup> {
|
|
346
|
+
}
|
|
347
|
+
export interface LiquidTagParseJson extends LiquidTagNode<NamedTags.parse_json, LiquidVariableLookup> {
|
|
348
|
+
}
|
|
349
|
+
export interface LiquidTagPrint extends LiquidTagNode<NamedTags.print, LiquidVariable> {
|
|
350
|
+
}
|
|
351
|
+
export interface LiquidTagRedirectTo extends LiquidTagNode<NamedTags.redirect_to, RedirectToMarkup> {
|
|
352
|
+
}
|
|
353
|
+
export interface LiquidTagResponseHeaders extends LiquidTagNode<NamedTags.response_headers, LiquidExpression> {
|
|
354
|
+
}
|
|
355
|
+
export interface LiquidTagResponseStatus extends LiquidTagNode<NamedTags.response_status, LiquidNumber> {
|
|
356
|
+
}
|
|
357
|
+
export interface LiquidTagReturn extends LiquidTagNode<NamedTags.return, LiquidVariable> {
|
|
358
|
+
}
|
|
359
|
+
export interface LiquidTagRollback extends LiquidTagNode<NamedTags.rollback, string> {
|
|
360
|
+
}
|
|
361
|
+
export interface LiquidTagSession extends LiquidTagNode<NamedTags.session, SessionMarkup> {
|
|
362
|
+
}
|
|
363
|
+
export interface LiquidTagSignIn extends LiquidTagNode<NamedTags.sign_in, LiquidNamedArgument[]> {
|
|
364
|
+
}
|
|
365
|
+
export interface LiquidTagSpamProtection extends LiquidTagNode<NamedTags.spam_protection, SpamProtectionMarkup> {
|
|
366
|
+
}
|
|
367
|
+
export interface LiquidTagThemeRenderRc extends LiquidTagNode<NamedTags.theme_render_rc, RenderMarkup> {
|
|
368
|
+
}
|
|
369
|
+
export interface LiquidTagTransaction extends LiquidTagNode<NamedTags.transaction, LiquidNamedArgument[]> {
|
|
370
|
+
}
|
|
371
|
+
export interface LiquidTagTry extends LiquidTagNode<NamedTags.try, string> {
|
|
372
|
+
}
|
|
373
|
+
export interface LiquidTagYield extends LiquidTagNode<NamedTags.yield, LiquidExpression> {
|
|
374
|
+
}
|
|
375
|
+
export interface LiquidBranchCatch extends LiquidBranchNode<NamedTags.catch, LiquidVariableLookup> {
|
|
376
|
+
}
|
|
377
|
+
/** {% background job_id = 'partial', [...namedArguments] %} (file-based) */
|
|
378
|
+
export interface BackgroundMarkup extends ASTNode<NodeTypes.BackgroundMarkup> {
|
|
379
|
+
jobId: string;
|
|
380
|
+
partial: LiquidString | LiquidVariableLookup;
|
|
381
|
+
args: LiquidNamedArgument[];
|
|
382
|
+
}
|
|
383
|
+
/** {% background jobId[, ...namedArguments] %}...{% endbackground %} (inline) */
|
|
384
|
+
export interface BackgroundInlineMarkup extends ASTNode<NodeTypes.BackgroundInlineMarkup> {
|
|
385
|
+
jobId: LiquidVariableLookup;
|
|
386
|
+
args: LiquidNamedArgument[];
|
|
387
|
+
}
|
|
388
|
+
/** {% cache 'key', [...namedArguments] %}...{% endcache %} */
|
|
389
|
+
export interface CacheMarkup extends ASTNode<NodeTypes.CacheMarkup> {
|
|
390
|
+
key: LiquidExpression;
|
|
391
|
+
args: LiquidNamedArgument[];
|
|
392
|
+
}
|
|
393
|
+
/** {% log value, [...namedArguments] %} */
|
|
394
|
+
export interface LogMarkup extends ASTNode<NodeTypes.LogMarkup> {
|
|
395
|
+
value: LiquidExpression;
|
|
396
|
+
args: LiquidNamedArgument[];
|
|
397
|
+
}
|
|
398
|
+
/** {% session name = value %} */
|
|
399
|
+
export interface SessionMarkup extends ASTNode<NodeTypes.SessionMarkup> {
|
|
400
|
+
name: string;
|
|
401
|
+
value: LiquidExpression;
|
|
402
|
+
}
|
|
403
|
+
/** {% export a, b, namespace: 'ns' %} */
|
|
404
|
+
export interface ExportMarkup extends ASTNode<NodeTypes.ExportMarkup> {
|
|
405
|
+
variables: LiquidVariableLookup[];
|
|
406
|
+
namespace: LiquidNamedArgument;
|
|
407
|
+
}
|
|
408
|
+
/** {% redirect_to '/path', [...namedArguments] %} */
|
|
409
|
+
export interface RedirectToMarkup extends ASTNode<NodeTypes.RedirectToMarkup> {
|
|
410
|
+
url: LiquidExpression;
|
|
411
|
+
args: LiquidNamedArgument[];
|
|
412
|
+
}
|
|
413
|
+
/** {% include_form 'form', [...namedArguments] %} */
|
|
414
|
+
export interface IncludeFormMarkup extends ASTNode<NodeTypes.IncludeFormMarkup> {
|
|
415
|
+
form: LiquidString | LiquidVariableLookup;
|
|
416
|
+
args: LiquidNamedArgument[];
|
|
417
|
+
}
|
|
418
|
+
/** {% spam_protection 'version', [...namedArguments] %} */
|
|
419
|
+
export interface SpamProtectionMarkup extends ASTNode<NodeTypes.SpamProtectionMarkup> {
|
|
420
|
+
version: LiquidExpression;
|
|
421
|
+
args: LiquidNamedArgument[];
|
|
422
|
+
}
|
|
423
|
+
/** Represents the `for name` or `with name` expressions in render nodes */
|
|
424
|
+
export interface RenderVariableExpression extends ASTNode<NodeTypes.RenderVariableExpression> {
|
|
425
|
+
/** {% render 'partial' (for|with) name %} */
|
|
426
|
+
kind: 'for' | 'with';
|
|
427
|
+
/** {% render 'partial' (for|with) name %} */
|
|
428
|
+
name: LiquidExpression;
|
|
429
|
+
}
|
|
430
|
+
/** Represents the `as name` expressions in render nodes */
|
|
431
|
+
export interface RenderAliasExpression extends ASTNode<NodeTypes.RenderAliasExpression> {
|
|
432
|
+
/** {% render 'partial' for array as name %}` or `{% render 'snippet' with object as name %} */
|
|
433
|
+
value: string;
|
|
434
|
+
}
|
|
435
|
+
/** The union type of the strictly and loosely typed LiquidBranch nodes */
|
|
436
|
+
export type LiquidBranch = LiquidBranchUnnamed | LiquidBranchBaseCase | LiquidBranchNamed;
|
|
437
|
+
/** The union type of the strictly typed LiquidBranch nodes */
|
|
438
|
+
export type LiquidBranchNamed = LiquidBranchElsif | LiquidBranchWhen | LiquidBranchCatch;
|
|
439
|
+
interface LiquidBranchNode<Name, Markup> extends ASTNode<NodeTypes.LiquidBranch> {
|
|
440
|
+
/**
|
|
441
|
+
* The liquid tag name of the branch, null when the first branch.
|
|
442
|
+
*
|
|
443
|
+
* {% if condA %}
|
|
444
|
+
* defaultBranchContents
|
|
445
|
+
* {% elseif condB %}
|
|
446
|
+
* elsifBranchContents
|
|
447
|
+
* {% endif %}
|
|
448
|
+
*
|
|
449
|
+
* This creates the following AST:
|
|
450
|
+
* type: LiquidTag
|
|
451
|
+
* name: if
|
|
452
|
+
* markup: condA
|
|
453
|
+
* children:
|
|
454
|
+
* - type: LiquidBranch
|
|
455
|
+
* name: null
|
|
456
|
+
* markup: ''
|
|
457
|
+
* children:
|
|
458
|
+
* - defaultBranchContents
|
|
459
|
+
* - type: LiquidBranch
|
|
460
|
+
* name: elsif
|
|
461
|
+
* markup: condB
|
|
462
|
+
* children:
|
|
463
|
+
* - elsifBranchContents
|
|
464
|
+
*/
|
|
465
|
+
name: Name;
|
|
466
|
+
/** {% name [markup] %} */
|
|
467
|
+
markup: Markup;
|
|
468
|
+
/** The child nodes of the branch */
|
|
469
|
+
children: LiquidHtmlNode[];
|
|
470
|
+
/** {%- elsif %} */
|
|
471
|
+
whitespaceStart: '-' | '';
|
|
472
|
+
/** {% elsif -%} */
|
|
473
|
+
whitespaceEnd: '-' | '';
|
|
474
|
+
/** Range of the LiquidTag that delimits the branch (does not include children) */
|
|
475
|
+
blockStartPosition: Position;
|
|
476
|
+
/** 0-size range that delimits where the branch ends, (-1, -1) when unclosed */
|
|
477
|
+
blockEndPosition: Position;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* The first branch inside branched statements (e.g. if, when, for)
|
|
481
|
+
*
|
|
482
|
+
* This one is different in the sense that it doesn't have a name or markup
|
|
483
|
+
* since that information is held by the parent node.
|
|
484
|
+
*/
|
|
485
|
+
export interface LiquidBranchUnnamed extends LiquidBranchNode<null, string> {
|
|
486
|
+
}
|
|
487
|
+
/** Loosely typed LiquidBranch nodes. Markup is a string because we can't strictly parse it. */
|
|
488
|
+
export interface LiquidBranchBaseCase extends LiquidBranchNode<string, string> {
|
|
489
|
+
}
|
|
490
|
+
/** Represents {{ expression (| filters)* }}. Its position includes the braces. */
|
|
491
|
+
export interface LiquidVariableOutput extends ASTNode<NodeTypes.LiquidVariableOutput> {
|
|
492
|
+
/** The body of the variable output. May contain filters. Not trimmed. */
|
|
493
|
+
markup: string | LiquidVariable;
|
|
494
|
+
/** {{- variable }} */
|
|
495
|
+
whitespaceStart: '-' | '';
|
|
496
|
+
/** {{ variable -}} */
|
|
497
|
+
whitespaceEnd: '-' | '';
|
|
498
|
+
}
|
|
499
|
+
/** Represents an expression and filters, e.g. expression | filter1 | filter2 */
|
|
500
|
+
export interface LiquidVariable extends ASTNode<NodeTypes.LiquidVariable> {
|
|
501
|
+
/** expression | filter1 | filter2 */
|
|
502
|
+
expression: ComplexLiquidExpression;
|
|
503
|
+
/** expression | filter1 | filter2 */
|
|
504
|
+
filters: LiquidFilter[];
|
|
505
|
+
/** Used internally */
|
|
506
|
+
rawSource: string;
|
|
507
|
+
}
|
|
508
|
+
/** The union type of all Liquid expression nodes */
|
|
509
|
+
export type LiquidExpression = LiquidString | LiquidNumber | LiquidLiteral | LiquidRange | LiquidVariableLookup;
|
|
510
|
+
export type ComplexLiquidExpression = LiquidBooleanExpression | LiquidExpression;
|
|
511
|
+
/** https://shopify.dev/docs/api/liquid/filters */
|
|
512
|
+
export interface LiquidFilter extends ASTNode<NodeTypes.LiquidFilter> {
|
|
513
|
+
/** name: arg1, arg2, namedArg3: value3 */
|
|
514
|
+
name: string;
|
|
515
|
+
/** name: arg1, arg2, namedArg3: value3 */
|
|
516
|
+
args: LiquidArgument[];
|
|
517
|
+
}
|
|
518
|
+
/** Represents the union type of positional and named arguments */
|
|
519
|
+
export type LiquidArgument = LiquidExpression | LiquidNamedArgument;
|
|
520
|
+
/** Named arguments are the ones used in kwargs, such as `name: value` */
|
|
521
|
+
export interface LiquidNamedArgument extends ASTNode<NodeTypes.NamedArgument> {
|
|
522
|
+
/** name: value */
|
|
523
|
+
name: string;
|
|
524
|
+
/** name: value */
|
|
525
|
+
value: LiquidExpression;
|
|
526
|
+
}
|
|
527
|
+
export interface LiquidBooleanExpression extends ASTNode<NodeTypes.BooleanExpression> {
|
|
528
|
+
condition: LiquidConditionalExpression;
|
|
529
|
+
}
|
|
530
|
+
/** https://shopify.dev/docs/api/liquid/basics#string */
|
|
531
|
+
export interface LiquidString extends ASTNode<NodeTypes.String> {
|
|
532
|
+
/** single or double quote? */
|
|
533
|
+
single: boolean;
|
|
534
|
+
/** The contents of the string, parsed, does not included the delimiting quote characters */
|
|
535
|
+
value: string;
|
|
536
|
+
}
|
|
537
|
+
/** https://shopify.dev/docs/api/liquid/basics#number */
|
|
538
|
+
export interface LiquidNumber extends ASTNode<NodeTypes.Number> {
|
|
539
|
+
/** as a string for compatibility with numbers like 100_000 */
|
|
540
|
+
value: string;
|
|
541
|
+
}
|
|
542
|
+
/** https://shopify.dev/docs/api/liquid/tags/for#for-range */
|
|
543
|
+
export interface LiquidRange extends ASTNode<NodeTypes.Range> {
|
|
544
|
+
start: LiquidExpression;
|
|
545
|
+
end: LiquidExpression;
|
|
546
|
+
}
|
|
547
|
+
/** empty, null, true, false, etc. */
|
|
548
|
+
export interface LiquidLiteral extends ASTNode<NodeTypes.LiquidLiteral> {
|
|
549
|
+
/** string representation of the literal (e.g. nil) */
|
|
550
|
+
keyword: ConcreteLiquidLiteral['keyword'];
|
|
551
|
+
/** value representation of the literal (e.g. null) */
|
|
552
|
+
value: ConcreteLiquidLiteral['value'];
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* What we think of when we think of variables.
|
|
556
|
+
* variable.lookup1[lookup2].lookup3
|
|
557
|
+
*/
|
|
558
|
+
export interface LiquidVariableLookup extends ASTNode<NodeTypes.VariableLookup> {
|
|
559
|
+
/**
|
|
560
|
+
* The root name of the lookup, `null` for the global access exception:
|
|
561
|
+
* {{ product }} -> name = 'product', lookups = []
|
|
562
|
+
* {{ ['product'] }} -> name = null, lookups = ['product']
|
|
563
|
+
*/
|
|
564
|
+
name: string | null;
|
|
565
|
+
/** name.lookup1[lookup2] */
|
|
566
|
+
lookups: LiquidExpression[];
|
|
567
|
+
}
|
|
568
|
+
/** The union type of all HTML nodes */
|
|
569
|
+
export type HtmlNode = HtmlComment | HtmlElement | HtmlDanglingMarkerClose | HtmlVoidElement | HtmlSelfClosingElement | HtmlRawNode;
|
|
570
|
+
/** The basic HTML node with an opening and closing tags. */
|
|
571
|
+
export interface HtmlElement extends HtmlNodeBase<NodeTypes.HtmlElement> {
|
|
572
|
+
/**
|
|
573
|
+
* The name of the tag can be compound
|
|
574
|
+
* e.g. `<{{ header_type }}--header />`
|
|
575
|
+
*/
|
|
576
|
+
name: (TextNode | LiquidVariableOutput)[];
|
|
577
|
+
/** The child nodes delimited by the start and end tags */
|
|
578
|
+
children: LiquidHtmlNode[];
|
|
579
|
+
/** The range covered by the end tag */
|
|
580
|
+
blockEndPosition: Position;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* The node used to represent close tags without its matching opening tag.
|
|
584
|
+
*
|
|
585
|
+
* Typically found inside if statements.
|
|
586
|
+
|
|
587
|
+
* ```
|
|
588
|
+
* {% if cond %}
|
|
589
|
+
* </wrapper>
|
|
590
|
+
* {% endif %}
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
export interface HtmlDanglingMarkerClose extends ASTNode<NodeTypes.HtmlDanglingMarkerClose> {
|
|
594
|
+
/**
|
|
595
|
+
* The name of the tag can be compound
|
|
596
|
+
* e.g. `<{{ header_type }}--header />`
|
|
597
|
+
*/
|
|
598
|
+
name: (TextNode | LiquidVariableOutput)[];
|
|
599
|
+
/** The range covered by the dangling end tag */
|
|
600
|
+
blockStartPosition: Position;
|
|
601
|
+
}
|
|
602
|
+
export interface HtmlSelfClosingElement extends HtmlNodeBase<NodeTypes.HtmlSelfClosingElement> {
|
|
603
|
+
/**
|
|
604
|
+
* The name of the tag can be compound
|
|
605
|
+
* @example `<{{ header_type }}--header />`
|
|
606
|
+
*/
|
|
607
|
+
name: (TextNode | LiquidVariableOutput)[];
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Represents HTML Void elements. The ones that cannot have child nodes.
|
|
611
|
+
*
|
|
612
|
+
* https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
|
613
|
+
*/
|
|
614
|
+
export interface HtmlVoidElement extends HtmlNodeBase<NodeTypes.HtmlVoidElement> {
|
|
615
|
+
/** This one can't have a compound name since they come from a list */
|
|
616
|
+
name: string;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Special case of HTML Element for which we don't want to try to parse the
|
|
620
|
+
* children. The children is parsed as a raw string.
|
|
621
|
+
*
|
|
622
|
+
* e.g. `script`, `style`
|
|
623
|
+
*/
|
|
624
|
+
export interface HtmlRawNode extends HtmlNodeBase<NodeTypes.HtmlRawNode> {
|
|
625
|
+
/** The innerHTML of the tag as a string. Not trimmed. Not parsed. */
|
|
626
|
+
body: RawMarkup;
|
|
627
|
+
/** script, style, etc. */
|
|
628
|
+
name: string;
|
|
629
|
+
/** The range covered by the end tag */
|
|
630
|
+
blockEndPosition: Position;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* The infered kind of raw markup
|
|
634
|
+
* - `<script>` is javascript
|
|
635
|
+
* - `<script type="application/json">` is JSON
|
|
636
|
+
* - `<style>` is css
|
|
637
|
+
* - etc.
|
|
638
|
+
*/
|
|
639
|
+
export declare enum RawMarkupKinds {
|
|
640
|
+
css = "css",
|
|
641
|
+
html = "html",
|
|
642
|
+
javascript = "javascript",
|
|
643
|
+
json = "json",
|
|
644
|
+
markdown = "markdown",
|
|
645
|
+
typescript = "typescript",
|
|
646
|
+
text = "text"
|
|
647
|
+
}
|
|
648
|
+
/** Represents parsed-as-string content. */
|
|
649
|
+
export interface RawMarkup extends ASTNode<NodeTypes.RawMarkup> {
|
|
650
|
+
/** javascript, css, markdown, text, etc. */
|
|
651
|
+
kind: RawMarkupKinds;
|
|
652
|
+
/** string value of the contents */
|
|
653
|
+
value: string;
|
|
654
|
+
/** parsed contents for when you want to visit the tree anyway! */
|
|
655
|
+
nodes: (LiquidNode | TextNode)[];
|
|
656
|
+
}
|
|
657
|
+
/** Used to represent the `<!doctype html>` nodes */
|
|
658
|
+
export interface HtmlDoctype extends ASTNode<NodeTypes.HtmlDoctype> {
|
|
659
|
+
legacyDoctypeString: string | null;
|
|
660
|
+
}
|
|
661
|
+
/** Represents `<!-- comments -->` */
|
|
662
|
+
export interface HtmlComment extends ASTNode<NodeTypes.HtmlComment> {
|
|
663
|
+
body: string;
|
|
664
|
+
}
|
|
665
|
+
export interface HtmlNodeBase<T> extends ASTNode<T> {
|
|
666
|
+
/** the HTML and Liquid attributes of the HTML tag */
|
|
667
|
+
attributes: AttributeNode[];
|
|
668
|
+
/** the range covered by the start tag */
|
|
669
|
+
blockStartPosition: Position;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* The union type of HTML attributes and Liquid nodes
|
|
673
|
+
*
|
|
674
|
+
* ```
|
|
675
|
+
* <link
|
|
676
|
+
* {% if attr1 %}
|
|
677
|
+
* attr1
|
|
678
|
+
* {% endif %}
|
|
679
|
+
* attr2=unquoted
|
|
680
|
+
* attr3='singleQuoted'
|
|
681
|
+
* attr4="doubleQuoted + {{ product }}"
|
|
682
|
+
* {{ block_attributes }}
|
|
683
|
+
* >
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
export type AttributeNode = LiquidNode | AttrSingleQuoted | AttrDoubleQuoted | AttrUnquoted | AttrEmpty;
|
|
687
|
+
/** `<tag attr='single quoted'>` */
|
|
688
|
+
export interface AttrSingleQuoted extends AttributeNodeBase<NodeTypes.AttrSingleQuoted> {
|
|
689
|
+
}
|
|
690
|
+
/** `<tag attr="double quoted">` */
|
|
691
|
+
export interface AttrDoubleQuoted extends AttributeNodeBase<NodeTypes.AttrDoubleQuoted> {
|
|
692
|
+
}
|
|
693
|
+
/** `<tag attr=unquoted>` */
|
|
694
|
+
export interface AttrUnquoted extends AttributeNodeBase<NodeTypes.AttrUnquoted> {
|
|
695
|
+
}
|
|
696
|
+
/** `<tag empty>` */
|
|
697
|
+
export interface AttrEmpty extends ASTNode<NodeTypes.AttrEmpty> {
|
|
698
|
+
name: (TextNode | LiquidVariableOutput)[];
|
|
699
|
+
}
|
|
700
|
+
/** Attribute values are represented by the concatenation of Text and Liquid nodes */
|
|
701
|
+
export type ValueNode = TextNode | LiquidNode;
|
|
702
|
+
export interface AttributeNodeBase<T> extends ASTNode<T> {
|
|
703
|
+
/**
|
|
704
|
+
* HTML attribute names are represented by the concatenation of Text and Liquid nodes.
|
|
705
|
+
*
|
|
706
|
+
* `<tag compound--{{ name }}="value">`
|
|
707
|
+
*/
|
|
708
|
+
name: (TextNode | LiquidVariableOutput)[];
|
|
709
|
+
/**
|
|
710
|
+
* HTML attribute values are represented by the concatenation of Text and Liquid nodes.
|
|
711
|
+
*
|
|
712
|
+
* `<tag attr="text and {{ product }} and text">`
|
|
713
|
+
*/
|
|
714
|
+
value: ValueNode[];
|
|
715
|
+
/** The range covered by the attribute value (excluding quotes) */
|
|
716
|
+
attributePosition: Position;
|
|
717
|
+
}
|
|
718
|
+
/** Represent generic text */
|
|
719
|
+
export interface TextNode extends ASTNode<NodeTypes.TextNode> {
|
|
720
|
+
value: string;
|
|
721
|
+
}
|
|
722
|
+
/** Represents a `@param` node in a LiquidDoc comment - `@param {paramType} [paramName] - paramDescription` */
|
|
723
|
+
export interface LiquidDocParamNode extends ASTNode<NodeTypes.LiquidDocParamNode> {
|
|
724
|
+
name: 'param';
|
|
725
|
+
/** The name of the parameter (e.g. "product"). Only includes the name, not the optional delimiters or whitespace. */
|
|
726
|
+
paramName: TextNode;
|
|
727
|
+
/** Optional description of the parameter in a Liquid doc comment (e.g. "The product title") */
|
|
728
|
+
paramDescription: TextNode | null;
|
|
729
|
+
/** Optional type annotation for the parameter (e.g. "{string}", "{number}") */
|
|
730
|
+
paramType: TextNode | null;
|
|
731
|
+
/** Whether this parameter must be passed when using the partial */
|
|
732
|
+
required: boolean;
|
|
733
|
+
}
|
|
734
|
+
/** Represents a `@description` node in a LiquidDoc comment - `@description descriptionContent` */
|
|
735
|
+
export interface LiquidDocDescriptionNode extends ASTNode<NodeTypes.LiquidDocDescriptionNode> {
|
|
736
|
+
name: 'description';
|
|
737
|
+
/** The contents of the description (e.g. "This is a description"). Can be multiline. */
|
|
738
|
+
content: TextNode;
|
|
739
|
+
/** Whether this description is implicit (e.g. not appended by a @description annotation) */
|
|
740
|
+
isImplicit: boolean;
|
|
741
|
+
/** Whether this description starts on the same line as the @description annotation. This is false for implicit descriptions. */
|
|
742
|
+
isInline: boolean;
|
|
743
|
+
}
|
|
744
|
+
/** Represents a `@example` node in a LiquidDoc comment - `@example exampleContent` */
|
|
745
|
+
export interface LiquidDocExampleNode extends ASTNode<NodeTypes.LiquidDocExampleNode> {
|
|
746
|
+
name: 'example';
|
|
747
|
+
/** The contents of the example (e.g. "{{ product }}"). Can be multiline. */
|
|
748
|
+
content: TextNode;
|
|
749
|
+
/** Whether this example starts on the same line as the @example annotation. */
|
|
750
|
+
isInline: boolean;
|
|
751
|
+
}
|
|
752
|
+
/** Represents a `@prompt` node in a LiquidDoc comment - `@prompt promptContent` */
|
|
753
|
+
export interface LiquidDocPromptNode extends ASTNode<NodeTypes.LiquidDocPromptNode> {
|
|
754
|
+
name: 'prompt';
|
|
755
|
+
/** The contents of the prompt (e.g. "Build me a sale sticker for my shop with a rotating @ symbol"). Can be multiline. */
|
|
756
|
+
content: TextNode;
|
|
757
|
+
}
|
|
758
|
+
export interface ASTNode<T> {
|
|
759
|
+
/**
|
|
760
|
+
* The type of the node, as a string.
|
|
761
|
+
* This property is used in discriminated unions.
|
|
762
|
+
*/
|
|
763
|
+
type: T;
|
|
764
|
+
/** The range that the node covers */
|
|
765
|
+
position: Position;
|
|
766
|
+
/**
|
|
767
|
+
* The contents of the entire document.
|
|
768
|
+
*
|
|
769
|
+
* To obtain the source of the node, use the following:
|
|
770
|
+
*
|
|
771
|
+
* `node.source.slice(node.position.start, node.position.end)`
|
|
772
|
+
*/
|
|
773
|
+
source: string;
|
|
774
|
+
}
|
|
775
|
+
interface ASTBuildOptions {
|
|
776
|
+
/** Whether the parser should throw if the document node isn't closed */
|
|
777
|
+
allowUnclosedDocumentNode: boolean;
|
|
778
|
+
/**
|
|
779
|
+
* 'strict' will disable the Liquid parsing base cases. Which means that we will
|
|
780
|
+
* throw an error if we can't parse the node `markup` properly.
|
|
781
|
+
*
|
|
782
|
+
* 'tolerant' is the default case so that prettier can pretty print nodes
|
|
783
|
+
* that it doesn't understand.
|
|
784
|
+
*/
|
|
785
|
+
mode: 'strict' | 'tolerant' | 'completion';
|
|
786
|
+
}
|
|
787
|
+
export declare function isBranchedTag(node: LiquidHtmlNode): boolean;
|
|
788
|
+
export declare function toLiquidAST(source: string, options?: ASTBuildOptions): DocumentNode;
|
|
789
|
+
export declare function toLiquidHtmlAST(source: string, options?: ASTBuildOptions): DocumentNode;
|
|
790
|
+
export declare function getName(node: ConcreteLiquidTagClose | ConcreteHtmlTagClose | ParentNode | undefined): string | null;
|
|
791
|
+
export declare function cstToAst(cst: LiquidHtmlCST | LiquidCST | ConcreteAttributeNode[], options: ASTBuildOptions): LiquidHtmlNode[];
|
|
792
|
+
export declare function walk(ast: LiquidHtmlNode, fn: (ast: LiquidHtmlNode, parentNode: LiquidHtmlNode | undefined) => void, parentNode?: LiquidHtmlNode): void;
|
|
793
|
+
export declare function isLiquidHtmlNode(value: any): value is LiquidHtmlNode;
|
|
794
|
+
export {};
|