shopware-twig-parser 0.2.0 → 0.3.1

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.
@@ -3,7 +3,7 @@ type Tree = {
3
3
  };
4
4
  type TemplateNode = {
5
5
  type: "template";
6
- children: TwigStatementDirectiveNode[];
6
+ children: (TwigStatementDirectiveNode | HtmlElementNode | ContentNode | HtmlDoctypeNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
7
7
  };
8
8
  type TwigStatementDirectiveNode = {
9
9
  type: "twig_statement_directive";
@@ -11,7 +11,7 @@ type TwigStatementDirectiveNode = {
11
11
  variable?: TwigVariableNode;
12
12
  function?: TwigFunctionNode;
13
13
  condition?: TwigConditionNode;
14
- children?: (TwigStatementDirectiveNode | ContentNode)[];
14
+ children?: (TwigStatementDirectiveNode | ContentNode | HtmlElementNode | HtmlDoctypeNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
15
15
  };
16
16
  type TwigConditionNode = {
17
17
  type: "twig_condition";
@@ -37,6 +37,29 @@ type TwigFunctionNode = {
37
37
  type: "twig_function";
38
38
  name: string;
39
39
  };
40
+ type HtmlAttributeNode = {
41
+ type: "html_attribute";
42
+ name: string;
43
+ value?: string;
44
+ };
45
+ type HtmlElementNode = {
46
+ type: "html_element";
47
+ name: string;
48
+ attributes?: HtmlAttributeNode[];
49
+ children: (HtmlElementNode | ContentNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
50
+ void?: boolean;
51
+ };
52
+ type HtmlDoctypeNode = {
53
+ type: "doctype";
54
+ };
55
+ type HtmlNamedEntityNode = {
56
+ type: "html_named_entity";
57
+ content: string;
58
+ };
59
+ type HtmlNumericEntityNode = {
60
+ type: "html_numeric_entity";
61
+ content: string;
62
+ };
40
63
  export declare function parse(content: string): Tree;
41
64
  export {};
42
65
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,0BAA0B,EAAE,CAAC;CACxC,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,IAAI,EAAE,0BAA0B,CAAC;IACjC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,0BAA0B,GAAG,WAAW,CAAC,EAAE,CAAC;CACzD,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAMF,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA6O3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,CACN,0BAA0B,GAC1B,eAAe,GACf,WAAW,GACX,eAAe,GACf,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;CACL,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,IAAI,EAAE,0BAA0B,CAAC;IACjC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,QAAQ,CAAC,EAAE,CACP,0BAA0B,GAC1B,WAAW,GACX,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;CACL,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,CACN,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAMF,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwf3C"}
@@ -65,6 +65,118 @@ function parse(content) {
65
65
  const rawNodes = [];
66
66
  // Also collect content nodes
67
67
  const allNodes = [];
68
+ function convertHtmlEntity(node) {
69
+ if (node.type === "html_entity") {
70
+ const entityText = node.text;
71
+ // Check if it's a numeric entity (starts with &#)
72
+ if (entityText.startsWith("&#")) {
73
+ return {
74
+ type: "html_numeric_entity",
75
+ content: entityText,
76
+ };
77
+ }
78
+ else if (entityText.startsWith("&")) {
79
+ return {
80
+ type: "html_named_entity",
81
+ content: entityText,
82
+ };
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+ function convertHtmlElement(node) {
88
+ if (node.type === "html_element") {
89
+ // Check for self-closing tag first
90
+ const selfClosingTag = node.children.find((child) => child.type === "html_self_closing_tag");
91
+ // Check for void tag
92
+ const voidTag = node.children.find((child) => child.type === "html_void_tag");
93
+ // Find the start tag to get the element name
94
+ const startTag = node.children.find((child) => child.type === "html_start_tag");
95
+ // Use self-closing tag, void tag, or start tag in that order of preference
96
+ const tagToUse = selfClosingTag || voidTag || startTag;
97
+ if (!tagToUse)
98
+ return null;
99
+ let tagName;
100
+ if (voidTag) {
101
+ // For void tags, the tag name is nested inside html_start_tag within the void tag
102
+ const voidStartTag = voidTag.children.find((child) => child.type === "html_start_tag");
103
+ tagName = voidStartTag?.children.find((child) => child.type === "html_tag_name");
104
+ }
105
+ else {
106
+ // For regular and self-closing tags, tag name is directly in the tag
107
+ tagName = tagToUse.children.find((child) => child.type === "html_tag_name");
108
+ }
109
+ if (!tagName)
110
+ return null;
111
+ // Check if this is a void element
112
+ const hasVoidTag = node.children.some((child) => child.type === "html_void_tag");
113
+ const hasSelfClosingTag = node.children.some((child) => child.type === "html_self_closing_tag");
114
+ const isVoid = hasVoidTag || hasSelfClosingTag;
115
+ // Parse attributes from the tag (either self-closing or start tag)
116
+ const attributes = [];
117
+ const attributeNodes = tagToUse.children.filter((child) => child.type === "html_attribute");
118
+ for (const attrNode of attributeNodes) {
119
+ const nameNode = attrNode.children.find((child) => child.type === "html_attribute_name");
120
+ if (!nameNode)
121
+ continue;
122
+ const valueNode = attrNode.children.find((child) => child.type === "html_attribute_value");
123
+ const quotedValueNode = attrNode.children.find((child) => child.type === "html_quoted_attribute_value");
124
+ let value;
125
+ if (quotedValueNode) {
126
+ // For quoted values, find the inner html_attribute_value
127
+ const innerValueNode = quotedValueNode.children.find((child) => child.type === "html_attribute_value");
128
+ value = innerValueNode ? innerValueNode.text : undefined;
129
+ }
130
+ else if (valueNode) {
131
+ value = valueNode.text;
132
+ }
133
+ const attribute = {
134
+ type: "html_attribute",
135
+ name: nameNode.text,
136
+ };
137
+ // Only include value property if there's actually a value
138
+ if (value !== undefined) {
139
+ attribute.value = value;
140
+ }
141
+ attributes.push(attribute);
142
+ }
143
+ const elementChildren = [];
144
+ // Process all children that are not start/end tags
145
+ for (const child of node.children) {
146
+ if (child.type === "content") {
147
+ elementChildren.push({
148
+ type: "content",
149
+ content: child.text,
150
+ });
151
+ }
152
+ else if (child.type === "html_element") {
153
+ const nestedElement = convertHtmlElement(child);
154
+ if (nestedElement) {
155
+ elementChildren.push(nestedElement);
156
+ }
157
+ }
158
+ else if (child.type === "html_entity") {
159
+ const entityNode = convertHtmlEntity(child);
160
+ if (entityNode) {
161
+ elementChildren.push(entityNode);
162
+ }
163
+ }
164
+ }
165
+ const result = {
166
+ type: "html_element",
167
+ name: tagName.text,
168
+ children: elementChildren,
169
+ };
170
+ if (attributes.length > 0) {
171
+ result.attributes = attributes;
172
+ }
173
+ if (isVoid) {
174
+ result.void = true;
175
+ }
176
+ return result;
177
+ }
178
+ return null;
179
+ }
68
180
  for (const child of tree.rootNode.children) {
69
181
  if (child.type === "content") {
70
182
  allNodes.push({
@@ -72,6 +184,23 @@ function parse(content) {
72
184
  content: child.text,
73
185
  });
74
186
  }
187
+ else if (child.type === "html_element") {
188
+ const htmlElement = convertHtmlElement(child);
189
+ if (htmlElement) {
190
+ allNodes.push(htmlElement);
191
+ }
192
+ }
193
+ else if (child.type === "html_doctype") {
194
+ allNodes.push({
195
+ type: "doctype",
196
+ });
197
+ }
198
+ else if (child.type === "html_entity") {
199
+ const entityNode = convertHtmlEntity(child);
200
+ if (entityNode) {
201
+ allNodes.push(entityNode);
202
+ }
203
+ }
75
204
  else {
76
205
  const converted = convertNode(child);
77
206
  if (converted) {
@@ -187,6 +316,65 @@ function parse(content) {
187
316
  });
188
317
  }
189
318
  }
319
+ else if (node.type === "html_element" && "name" in node) {
320
+ // HTML elements are already processed and can be added directly
321
+ const htmlNode = node;
322
+ if (stack.length > 0) {
323
+ // Add to the current parent's children
324
+ const parent = stack[stack.length - 1];
325
+ if (parent && parent.children) {
326
+ parent.children.push(htmlNode);
327
+ }
328
+ }
329
+ else {
330
+ // Add to root level
331
+ result.push(htmlNode);
332
+ }
333
+ }
334
+ else if (node.type === "doctype") {
335
+ const doctypeNode = {
336
+ type: "doctype",
337
+ };
338
+ if (stack.length > 0) {
339
+ // Add to the current parent's children
340
+ const parent = stack[stack.length - 1];
341
+ if (parent && parent.children) {
342
+ parent.children.push(doctypeNode);
343
+ }
344
+ }
345
+ else {
346
+ // Add to root level
347
+ result.push(doctypeNode);
348
+ }
349
+ }
350
+ else if (node.type === "html_named_entity" && "content" in node) {
351
+ const entityNode = node;
352
+ if (stack.length > 0) {
353
+ // Add to the current parent's children
354
+ const parent = stack[stack.length - 1];
355
+ if (parent && parent.children) {
356
+ parent.children.push(entityNode);
357
+ }
358
+ }
359
+ else {
360
+ // Add to root level
361
+ result.push(entityNode);
362
+ }
363
+ }
364
+ else if (node.type === "html_numeric_entity" && "content" in node) {
365
+ const entityNode = node;
366
+ if (stack.length > 0) {
367
+ // Add to the current parent's children
368
+ const parent = stack[stack.length - 1];
369
+ if (parent && parent.children) {
370
+ parent.children.push(entityNode);
371
+ }
372
+ }
373
+ else {
374
+ // Add to root level
375
+ result.push(entityNode);
376
+ }
377
+ }
190
378
  }
191
379
  return result;
192
380
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import Parser from \"tree-sitter\";\nimport ShopwareTwig from \"tree-sitter-shopware-twig\";\n\ntype Tree = {\n rootNode: TemplateNode;\n};\n\ntype TemplateNode = {\n type: \"template\";\n children: TwigStatementDirectiveNode[];\n};\n\ntype TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\";\n tag?: TwigTagNode;\n variable?: TwigVariableNode;\n function?: TwigFunctionNode;\n condition?: TwigConditionNode;\n children?: (TwigStatementDirectiveNode | ContentNode)[];\n};\n\ntype TwigConditionNode = {\n type: \"twig_condition\";\n expression: TwigExpressionNode;\n};\n\ntype TwigExpressionNode = {\n type: \"twig_expression\";\n content: string;\n};\n\ntype ContentNode = {\n type: \"content\";\n content: string;\n};\n\ntype TwigTagNode = {\n type: \"twig_tag\";\n name: string;\n};\n\ntype TwigVariableNode = {\n type: \"twig_variable\";\n content: string;\n};\n\ntype TwigFunctionNode = {\n type: \"twig_function\";\n name: string;\n};\n\nconst parser = new Parser();\n// @ts-expect-error\nparser.setLanguage(ShopwareTwig);\n\nexport function parse(content: string): Tree {\n const tree = parser.parse(content);\n\n function convertNode(node: any): {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n } | null {\n if (node.type === \"statement_directive\") {\n // Check for if_statement\n const ifStatement = node.children.find(\n (child: any) => child.type === \"if_statement\"\n );\n if (ifStatement) {\n const conditionalNode = ifStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = ifStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (conditionalNode && conditionalNode.text === \"if\" && variableNode) {\n return {\n type: \"if\",\n expression: variableNode.text,\n };\n }\n }\n\n // Check for tag_statement\n const tagStatement = node.children.find(\n (child: any) => child.type === \"tag_statement\"\n );\n const functionCall = node.children.find(\n (child: any) => child.type === \"function_call\"\n );\n\n if (tagStatement) {\n const tagNode = tagStatement.children.find(\n (child: any) => child.type === \"tag\"\n );\n const conditionalNode = tagStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = tagStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (tagNode && tagNode.text === \"block\" && variableNode) {\n return {\n type: \"block\",\n name: variableNode.text,\n };\n } else if (tagNode && tagNode.text === \"endblock\") {\n return {\n type: \"endblock\",\n };\n } else if (conditionalNode && conditionalNode.text === \"endif\") {\n return {\n type: \"endif\",\n };\n }\n } else if (functionCall) {\n const functionIdentifier = functionCall.children.find(\n (child: any) => child.type === \"function_identifier\"\n );\n\n if (functionIdentifier) {\n return {\n type: \"function\",\n functionName: functionIdentifier.text,\n };\n }\n }\n }\n return null;\n }\n\n // First pass: convert all nodes to intermediate format\n const rawNodes: {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n }[] = [];\n\n // Also collect content nodes\n const allNodes: Array<{\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\" | \"content\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }> = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === \"content\") {\n allNodes.push({\n type: \"content\",\n content: child.text,\n });\n } else {\n const converted = convertNode(child);\n if (converted) {\n rawNodes.push(converted);\n allNodes.push(converted);\n }\n }\n }\n\n // Second pass: build nested structure using a stack\n function buildNestedStructure(\n nodes: Array<{\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\" | \"content\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }>\n ): TwigStatementDirectiveNode[] {\n const result: TwigStatementDirectiveNode[] = [];\n const stack: TwigStatementDirectiveNode[] = [];\n\n for (const node of nodes) {\n if (node.type === \"block\") {\n const blockNode: TwigStatementDirectiveNode = {\n tag: {\n type: \"twig_tag\",\n name: \"block\",\n },\n type: \"twig_statement_directive\",\n variable: {\n type: \"twig_variable\",\n content: node.name!,\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(blockNode);\n }\n } else {\n // Add to root level\n result.push(blockNode);\n }\n\n // Push to stack for nesting\n stack.push(blockNode);\n } else if (node.type === \"endblock\") {\n // Pop from stack when we encounter an endblock\n stack.pop();\n } else if (node.type === \"if\") {\n const ifNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n condition: {\n type: \"twig_condition\",\n expression: {\n type: \"twig_expression\",\n content: node.expression!,\n },\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(ifNode);\n }\n } else {\n // Add to root level\n result.push(ifNode);\n }\n\n // Push to stack for nesting\n stack.push(ifNode);\n } else if (node.type === \"endif\") {\n // Pop from stack when we encounter an endif\n stack.pop();\n } else if (node.type === \"function\") {\n const functionNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n function: {\n type: \"twig_function\",\n name: node.functionName!,\n },\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(functionNode);\n }\n } else {\n // Add to root level\n result.push(functionNode);\n }\n } else if (node.type === \"content\") {\n const contentNode: ContentNode = {\n type: \"content\",\n content: node.content!,\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(contentNode);\n }\n } else {\n // Content at root level - this shouldn't happen in well-formed templates\n // but we'll handle it gracefully\n result.push({\n type: \"twig_statement_directive\",\n children: [contentNode],\n });\n }\n }\n }\n\n return result;\n }\n\n const children = buildNestedStructure(allNodes);\n\n return {\n rootNode: {\n type: \"template\",\n children,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import Parser from \"tree-sitter\";\nimport ShopwareTwig from \"tree-sitter-shopware-twig\";\n\ntype Tree = {\n rootNode: TemplateNode;\n};\n\ntype TemplateNode = {\n type: \"template\";\n children: (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n};\n\ntype TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\";\n tag?: TwigTagNode;\n variable?: TwigVariableNode;\n function?: TwigFunctionNode;\n condition?: TwigConditionNode;\n children?: (\n | TwigStatementDirectiveNode\n | ContentNode\n | HtmlElementNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n};\n\ntype TwigConditionNode = {\n type: \"twig_condition\";\n expression: TwigExpressionNode;\n};\n\ntype TwigExpressionNode = {\n type: \"twig_expression\";\n content: string;\n};\n\ntype ContentNode = {\n type: \"content\";\n content: string;\n};\n\ntype TwigTagNode = {\n type: \"twig_tag\";\n name: string;\n};\n\ntype TwigVariableNode = {\n type: \"twig_variable\";\n content: string;\n};\n\ntype TwigFunctionNode = {\n type: \"twig_function\";\n name: string;\n};\n\ntype HtmlAttributeNode = {\n type: \"html_attribute\";\n name: string;\n value?: string;\n};\n\ntype HtmlElementNode = {\n type: \"html_element\";\n name: string;\n attributes?: HtmlAttributeNode[];\n children: (\n | HtmlElementNode\n | ContentNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n void?: boolean;\n};\n\ntype HtmlDoctypeNode = {\n type: \"doctype\";\n};\n\ntype HtmlNamedEntityNode = {\n type: \"html_named_entity\";\n content: string;\n};\n\ntype HtmlNumericEntityNode = {\n type: \"html_numeric_entity\";\n content: string;\n};\n\nconst parser = new Parser();\n// @ts-expect-error\nparser.setLanguage(ShopwareTwig);\n\nexport function parse(content: string): Tree {\n const tree = parser.parse(content);\n\n function convertNode(node: any): {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n } | null {\n if (node.type === \"statement_directive\") {\n // Check for if_statement\n const ifStatement = node.children.find(\n (child: any) => child.type === \"if_statement\"\n );\n if (ifStatement) {\n const conditionalNode = ifStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = ifStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (conditionalNode && conditionalNode.text === \"if\" && variableNode) {\n return {\n type: \"if\",\n expression: variableNode.text,\n };\n }\n }\n\n // Check for tag_statement\n const tagStatement = node.children.find(\n (child: any) => child.type === \"tag_statement\"\n );\n const functionCall = node.children.find(\n (child: any) => child.type === \"function_call\"\n );\n\n if (tagStatement) {\n const tagNode = tagStatement.children.find(\n (child: any) => child.type === \"tag\"\n );\n const conditionalNode = tagStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = tagStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (tagNode && tagNode.text === \"block\" && variableNode) {\n return {\n type: \"block\",\n name: variableNode.text,\n };\n } else if (tagNode && tagNode.text === \"endblock\") {\n return {\n type: \"endblock\",\n };\n } else if (conditionalNode && conditionalNode.text === \"endif\") {\n return {\n type: \"endif\",\n };\n }\n } else if (functionCall) {\n const functionIdentifier = functionCall.children.find(\n (child: any) => child.type === \"function_identifier\"\n );\n\n if (functionIdentifier) {\n return {\n type: \"function\",\n functionName: functionIdentifier.text,\n };\n }\n }\n }\n return null;\n }\n\n // First pass: convert all nodes to intermediate format\n const rawNodes: {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n }[] = [];\n\n // Also collect content nodes\n const allNodes: Array<\n | {\n type:\n | \"block\"\n | \"endblock\"\n | \"function\"\n | \"if\"\n | \"endif\"\n | \"content\"\n | \"html_element\"\n | \"doctype\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }\n | HtmlElementNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n > = [];\n\n function convertHtmlEntity(\n node: any\n ): HtmlNamedEntityNode | HtmlNumericEntityNode | null {\n if (node.type === \"html_entity\") {\n const entityText = node.text;\n\n // Check if it's a numeric entity (starts with &#)\n if (entityText.startsWith(\"&#\")) {\n return {\n type: \"html_numeric_entity\",\n content: entityText,\n };\n } else if (entityText.startsWith(\"&\")) {\n return {\n type: \"html_named_entity\",\n content: entityText,\n };\n }\n }\n return null;\n }\n\n function convertHtmlElement(node: any): HtmlElementNode | null {\n if (node.type === \"html_element\") {\n // Check for self-closing tag first\n const selfClosingTag = node.children.find(\n (child: any) => child.type === \"html_self_closing_tag\"\n );\n\n // Check for void tag\n const voidTag = node.children.find(\n (child: any) => child.type === \"html_void_tag\"\n );\n\n // Find the start tag to get the element name\n const startTag = node.children.find(\n (child: any) => child.type === \"html_start_tag\"\n );\n\n // Use self-closing tag, void tag, or start tag in that order of preference\n const tagToUse = selfClosingTag || voidTag || startTag;\n if (!tagToUse) return null;\n\n let tagName: any;\n if (voidTag) {\n // For void tags, the tag name is nested inside html_start_tag within the void tag\n const voidStartTag = voidTag.children.find(\n (child: any) => child.type === \"html_start_tag\"\n );\n tagName = voidStartTag?.children.find(\n (child: any) => child.type === \"html_tag_name\"\n );\n } else {\n // For regular and self-closing tags, tag name is directly in the tag\n tagName = tagToUse.children.find(\n (child: any) => child.type === \"html_tag_name\"\n );\n }\n if (!tagName) return null;\n\n // Check if this is a void element\n const hasVoidTag = node.children.some(\n (child: any) => child.type === \"html_void_tag\"\n );\n const hasSelfClosingTag = node.children.some(\n (child: any) => child.type === \"html_self_closing_tag\"\n );\n const isVoid = hasVoidTag || hasSelfClosingTag;\n\n // Parse attributes from the tag (either self-closing or start tag)\n const attributes: HtmlAttributeNode[] = [];\n const attributeNodes = tagToUse.children.filter(\n (child: any) => child.type === \"html_attribute\"\n );\n\n for (const attrNode of attributeNodes) {\n const nameNode = attrNode.children.find(\n (child: any) => child.type === \"html_attribute_name\"\n );\n if (!nameNode) continue;\n\n const valueNode = attrNode.children.find(\n (child: any) => child.type === \"html_attribute_value\"\n );\n const quotedValueNode = attrNode.children.find(\n (child: any) => child.type === \"html_quoted_attribute_value\"\n );\n\n let value: string | undefined;\n if (quotedValueNode) {\n // For quoted values, find the inner html_attribute_value\n const innerValueNode = quotedValueNode.children.find(\n (child: any) => child.type === \"html_attribute_value\"\n );\n value = innerValueNode ? innerValueNode.text : undefined;\n } else if (valueNode) {\n value = valueNode.text;\n }\n\n const attribute: HtmlAttributeNode = {\n type: \"html_attribute\",\n name: nameNode.text,\n };\n\n // Only include value property if there's actually a value\n if (value !== undefined) {\n attribute.value = value;\n }\n\n attributes.push(attribute);\n }\n\n const elementChildren: (\n | HtmlElementNode\n | ContentNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] = [];\n\n // Process all children that are not start/end tags\n for (const child of node.children) {\n if (child.type === \"content\") {\n elementChildren.push({\n type: \"content\",\n content: child.text,\n });\n } else if (child.type === \"html_element\") {\n const nestedElement = convertHtmlElement(child);\n if (nestedElement) {\n elementChildren.push(nestedElement);\n }\n } else if (child.type === \"html_entity\") {\n const entityNode = convertHtmlEntity(child);\n if (entityNode) {\n elementChildren.push(entityNode);\n }\n }\n }\n\n const result: HtmlElementNode = {\n type: \"html_element\",\n name: tagName.text,\n children: elementChildren,\n };\n\n if (attributes.length > 0) {\n result.attributes = attributes;\n }\n\n if (isVoid) {\n result.void = true;\n }\n\n return result;\n }\n return null;\n }\n\n for (const child of tree.rootNode.children) {\n if (child.type === \"content\") {\n allNodes.push({\n type: \"content\",\n content: child.text,\n });\n } else if (child.type === \"html_element\") {\n const htmlElement = convertHtmlElement(child);\n if (htmlElement) {\n allNodes.push(htmlElement);\n }\n } else if (child.type === \"html_doctype\") {\n allNodes.push({\n type: \"doctype\",\n });\n } else if (child.type === \"html_entity\") {\n const entityNode = convertHtmlEntity(child);\n if (entityNode) {\n allNodes.push(entityNode);\n }\n } else {\n const converted = convertNode(child);\n if (converted) {\n rawNodes.push(converted);\n allNodes.push(converted);\n }\n }\n }\n\n // Second pass: build nested structure using a stack\n function buildNestedStructure(\n nodes: Array<\n | {\n type:\n | \"block\"\n | \"endblock\"\n | \"function\"\n | \"if\"\n | \"endif\"\n | \"content\"\n | \"html_element\"\n | \"doctype\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }\n | HtmlElementNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n >\n ): (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] {\n const result: (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] = [];\n const stack: TwigStatementDirectiveNode[] = [];\n\n for (const node of nodes) {\n if (node.type === \"block\") {\n const blockNode: TwigStatementDirectiveNode = {\n tag: {\n type: \"twig_tag\",\n name: \"block\",\n },\n type: \"twig_statement_directive\",\n variable: {\n type: \"twig_variable\",\n content: node.name!,\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(blockNode);\n }\n } else {\n // Add to root level\n result.push(blockNode);\n }\n\n // Push to stack for nesting\n stack.push(blockNode);\n } else if (node.type === \"endblock\") {\n // Pop from stack when we encounter an endblock\n stack.pop();\n } else if (node.type === \"if\") {\n const ifNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n condition: {\n type: \"twig_condition\",\n expression: {\n type: \"twig_expression\",\n content: node.expression!,\n },\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(ifNode);\n }\n } else {\n // Add to root level\n result.push(ifNode);\n }\n\n // Push to stack for nesting\n stack.push(ifNode);\n } else if (node.type === \"endif\") {\n // Pop from stack when we encounter an endif\n stack.pop();\n } else if (node.type === \"function\") {\n const functionNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n function: {\n type: \"twig_function\",\n name: node.functionName!,\n },\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(functionNode);\n }\n } else {\n // Add to root level\n result.push(functionNode);\n }\n } else if (node.type === \"content\") {\n const contentNode: ContentNode = {\n type: \"content\",\n content: node.content!,\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(contentNode);\n }\n } else {\n // Content at root level - this shouldn't happen in well-formed templates\n // but we'll handle it gracefully\n result.push({\n type: \"twig_statement_directive\",\n children: [contentNode],\n });\n }\n } else if (node.type === \"html_element\" && \"name\" in node) {\n // HTML elements are already processed and can be added directly\n const htmlNode = node as HtmlElementNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(htmlNode);\n }\n } else {\n // Add to root level\n result.push(htmlNode);\n }\n } else if (node.type === \"doctype\") {\n const doctypeNode: HtmlDoctypeNode = {\n type: \"doctype\",\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(doctypeNode);\n }\n } else {\n // Add to root level\n result.push(doctypeNode);\n }\n } else if (node.type === \"html_named_entity\" && \"content\" in node) {\n const entityNode = node as HtmlNamedEntityNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(entityNode);\n }\n } else {\n // Add to root level\n result.push(entityNode);\n }\n } else if (node.type === \"html_numeric_entity\" && \"content\" in node) {\n const entityNode = node as HtmlNumericEntityNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(entityNode);\n }\n } else {\n // Add to root level\n result.push(entityNode);\n }\n }\n }\n\n return result;\n }\n\n const children = buildNestedStructure(allNodes);\n\n return {\n rootNode: {\n type: \"template\",\n children,\n },\n };\n}\n"]}
@@ -3,7 +3,7 @@ type Tree = {
3
3
  };
4
4
  type TemplateNode = {
5
5
  type: "template";
6
- children: TwigStatementDirectiveNode[];
6
+ children: (TwigStatementDirectiveNode | HtmlElementNode | ContentNode | HtmlDoctypeNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
7
7
  };
8
8
  type TwigStatementDirectiveNode = {
9
9
  type: "twig_statement_directive";
@@ -11,7 +11,7 @@ type TwigStatementDirectiveNode = {
11
11
  variable?: TwigVariableNode;
12
12
  function?: TwigFunctionNode;
13
13
  condition?: TwigConditionNode;
14
- children?: (TwigStatementDirectiveNode | ContentNode)[];
14
+ children?: (TwigStatementDirectiveNode | ContentNode | HtmlElementNode | HtmlDoctypeNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
15
15
  };
16
16
  type TwigConditionNode = {
17
17
  type: "twig_condition";
@@ -37,6 +37,29 @@ type TwigFunctionNode = {
37
37
  type: "twig_function";
38
38
  name: string;
39
39
  };
40
+ type HtmlAttributeNode = {
41
+ type: "html_attribute";
42
+ name: string;
43
+ value?: string;
44
+ };
45
+ type HtmlElementNode = {
46
+ type: "html_element";
47
+ name: string;
48
+ attributes?: HtmlAttributeNode[];
49
+ children: (HtmlElementNode | ContentNode | HtmlNamedEntityNode | HtmlNumericEntityNode)[];
50
+ void?: boolean;
51
+ };
52
+ type HtmlDoctypeNode = {
53
+ type: "doctype";
54
+ };
55
+ type HtmlNamedEntityNode = {
56
+ type: "html_named_entity";
57
+ content: string;
58
+ };
59
+ type HtmlNumericEntityNode = {
60
+ type: "html_numeric_entity";
61
+ content: string;
62
+ };
40
63
  export declare function parse(content: string): Tree;
41
64
  export {};
42
65
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,0BAA0B,EAAE,CAAC;CACxC,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,IAAI,EAAE,0BAA0B,CAAC;IACjC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,0BAA0B,GAAG,WAAW,CAAC,EAAE,CAAC;CACzD,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAMF,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA6O3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,CACN,0BAA0B,GAC1B,eAAe,GACf,WAAW,GACX,eAAe,GACf,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;CACL,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,IAAI,EAAE,0BAA0B,CAAC;IACjC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,QAAQ,CAAC,EAAE,CACP,0BAA0B,GAC1B,WAAW,GACX,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;CACL,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,CACN,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,qBAAqB,CACxB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAMF,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAwf3C"}
package/dist/esm/index.js CHANGED
@@ -59,6 +59,118 @@ export function parse(content) {
59
59
  const rawNodes = [];
60
60
  // Also collect content nodes
61
61
  const allNodes = [];
62
+ function convertHtmlEntity(node) {
63
+ if (node.type === "html_entity") {
64
+ const entityText = node.text;
65
+ // Check if it's a numeric entity (starts with &#)
66
+ if (entityText.startsWith("&#")) {
67
+ return {
68
+ type: "html_numeric_entity",
69
+ content: entityText,
70
+ };
71
+ }
72
+ else if (entityText.startsWith("&")) {
73
+ return {
74
+ type: "html_named_entity",
75
+ content: entityText,
76
+ };
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ function convertHtmlElement(node) {
82
+ if (node.type === "html_element") {
83
+ // Check for self-closing tag first
84
+ const selfClosingTag = node.children.find((child) => child.type === "html_self_closing_tag");
85
+ // Check for void tag
86
+ const voidTag = node.children.find((child) => child.type === "html_void_tag");
87
+ // Find the start tag to get the element name
88
+ const startTag = node.children.find((child) => child.type === "html_start_tag");
89
+ // Use self-closing tag, void tag, or start tag in that order of preference
90
+ const tagToUse = selfClosingTag || voidTag || startTag;
91
+ if (!tagToUse)
92
+ return null;
93
+ let tagName;
94
+ if (voidTag) {
95
+ // For void tags, the tag name is nested inside html_start_tag within the void tag
96
+ const voidStartTag = voidTag.children.find((child) => child.type === "html_start_tag");
97
+ tagName = voidStartTag?.children.find((child) => child.type === "html_tag_name");
98
+ }
99
+ else {
100
+ // For regular and self-closing tags, tag name is directly in the tag
101
+ tagName = tagToUse.children.find((child) => child.type === "html_tag_name");
102
+ }
103
+ if (!tagName)
104
+ return null;
105
+ // Check if this is a void element
106
+ const hasVoidTag = node.children.some((child) => child.type === "html_void_tag");
107
+ const hasSelfClosingTag = node.children.some((child) => child.type === "html_self_closing_tag");
108
+ const isVoid = hasVoidTag || hasSelfClosingTag;
109
+ // Parse attributes from the tag (either self-closing or start tag)
110
+ const attributes = [];
111
+ const attributeNodes = tagToUse.children.filter((child) => child.type === "html_attribute");
112
+ for (const attrNode of attributeNodes) {
113
+ const nameNode = attrNode.children.find((child) => child.type === "html_attribute_name");
114
+ if (!nameNode)
115
+ continue;
116
+ const valueNode = attrNode.children.find((child) => child.type === "html_attribute_value");
117
+ const quotedValueNode = attrNode.children.find((child) => child.type === "html_quoted_attribute_value");
118
+ let value;
119
+ if (quotedValueNode) {
120
+ // For quoted values, find the inner html_attribute_value
121
+ const innerValueNode = quotedValueNode.children.find((child) => child.type === "html_attribute_value");
122
+ value = innerValueNode ? innerValueNode.text : undefined;
123
+ }
124
+ else if (valueNode) {
125
+ value = valueNode.text;
126
+ }
127
+ const attribute = {
128
+ type: "html_attribute",
129
+ name: nameNode.text,
130
+ };
131
+ // Only include value property if there's actually a value
132
+ if (value !== undefined) {
133
+ attribute.value = value;
134
+ }
135
+ attributes.push(attribute);
136
+ }
137
+ const elementChildren = [];
138
+ // Process all children that are not start/end tags
139
+ for (const child of node.children) {
140
+ if (child.type === "content") {
141
+ elementChildren.push({
142
+ type: "content",
143
+ content: child.text,
144
+ });
145
+ }
146
+ else if (child.type === "html_element") {
147
+ const nestedElement = convertHtmlElement(child);
148
+ if (nestedElement) {
149
+ elementChildren.push(nestedElement);
150
+ }
151
+ }
152
+ else if (child.type === "html_entity") {
153
+ const entityNode = convertHtmlEntity(child);
154
+ if (entityNode) {
155
+ elementChildren.push(entityNode);
156
+ }
157
+ }
158
+ }
159
+ const result = {
160
+ type: "html_element",
161
+ name: tagName.text,
162
+ children: elementChildren,
163
+ };
164
+ if (attributes.length > 0) {
165
+ result.attributes = attributes;
166
+ }
167
+ if (isVoid) {
168
+ result.void = true;
169
+ }
170
+ return result;
171
+ }
172
+ return null;
173
+ }
62
174
  for (const child of tree.rootNode.children) {
63
175
  if (child.type === "content") {
64
176
  allNodes.push({
@@ -66,6 +178,23 @@ export function parse(content) {
66
178
  content: child.text,
67
179
  });
68
180
  }
181
+ else if (child.type === "html_element") {
182
+ const htmlElement = convertHtmlElement(child);
183
+ if (htmlElement) {
184
+ allNodes.push(htmlElement);
185
+ }
186
+ }
187
+ else if (child.type === "html_doctype") {
188
+ allNodes.push({
189
+ type: "doctype",
190
+ });
191
+ }
192
+ else if (child.type === "html_entity") {
193
+ const entityNode = convertHtmlEntity(child);
194
+ if (entityNode) {
195
+ allNodes.push(entityNode);
196
+ }
197
+ }
69
198
  else {
70
199
  const converted = convertNode(child);
71
200
  if (converted) {
@@ -181,6 +310,65 @@ export function parse(content) {
181
310
  });
182
311
  }
183
312
  }
313
+ else if (node.type === "html_element" && "name" in node) {
314
+ // HTML elements are already processed and can be added directly
315
+ const htmlNode = node;
316
+ if (stack.length > 0) {
317
+ // Add to the current parent's children
318
+ const parent = stack[stack.length - 1];
319
+ if (parent && parent.children) {
320
+ parent.children.push(htmlNode);
321
+ }
322
+ }
323
+ else {
324
+ // Add to root level
325
+ result.push(htmlNode);
326
+ }
327
+ }
328
+ else if (node.type === "doctype") {
329
+ const doctypeNode = {
330
+ type: "doctype",
331
+ };
332
+ if (stack.length > 0) {
333
+ // Add to the current parent's children
334
+ const parent = stack[stack.length - 1];
335
+ if (parent && parent.children) {
336
+ parent.children.push(doctypeNode);
337
+ }
338
+ }
339
+ else {
340
+ // Add to root level
341
+ result.push(doctypeNode);
342
+ }
343
+ }
344
+ else if (node.type === "html_named_entity" && "content" in node) {
345
+ const entityNode = node;
346
+ if (stack.length > 0) {
347
+ // Add to the current parent's children
348
+ const parent = stack[stack.length - 1];
349
+ if (parent && parent.children) {
350
+ parent.children.push(entityNode);
351
+ }
352
+ }
353
+ else {
354
+ // Add to root level
355
+ result.push(entityNode);
356
+ }
357
+ }
358
+ else if (node.type === "html_numeric_entity" && "content" in node) {
359
+ const entityNode = node;
360
+ if (stack.length > 0) {
361
+ // Add to the current parent's children
362
+ const parent = stack[stack.length - 1];
363
+ if (parent && parent.children) {
364
+ parent.children.push(entityNode);
365
+ }
366
+ }
367
+ else {
368
+ // Add to root level
369
+ result.push(entityNode);
370
+ }
371
+ }
184
372
  }
185
373
  return result;
186
374
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import Parser from \"tree-sitter\";\nimport ShopwareTwig from \"tree-sitter-shopware-twig\";\n\ntype Tree = {\n rootNode: TemplateNode;\n};\n\ntype TemplateNode = {\n type: \"template\";\n children: TwigStatementDirectiveNode[];\n};\n\ntype TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\";\n tag?: TwigTagNode;\n variable?: TwigVariableNode;\n function?: TwigFunctionNode;\n condition?: TwigConditionNode;\n children?: (TwigStatementDirectiveNode | ContentNode)[];\n};\n\ntype TwigConditionNode = {\n type: \"twig_condition\";\n expression: TwigExpressionNode;\n};\n\ntype TwigExpressionNode = {\n type: \"twig_expression\";\n content: string;\n};\n\ntype ContentNode = {\n type: \"content\";\n content: string;\n};\n\ntype TwigTagNode = {\n type: \"twig_tag\";\n name: string;\n};\n\ntype TwigVariableNode = {\n type: \"twig_variable\";\n content: string;\n};\n\ntype TwigFunctionNode = {\n type: \"twig_function\";\n name: string;\n};\n\nconst parser = new Parser();\n// @ts-expect-error\nparser.setLanguage(ShopwareTwig);\n\nexport function parse(content: string): Tree {\n const tree = parser.parse(content);\n\n function convertNode(node: any): {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n } | null {\n if (node.type === \"statement_directive\") {\n // Check for if_statement\n const ifStatement = node.children.find(\n (child: any) => child.type === \"if_statement\"\n );\n if (ifStatement) {\n const conditionalNode = ifStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = ifStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (conditionalNode && conditionalNode.text === \"if\" && variableNode) {\n return {\n type: \"if\",\n expression: variableNode.text,\n };\n }\n }\n\n // Check for tag_statement\n const tagStatement = node.children.find(\n (child: any) => child.type === \"tag_statement\"\n );\n const functionCall = node.children.find(\n (child: any) => child.type === \"function_call\"\n );\n\n if (tagStatement) {\n const tagNode = tagStatement.children.find(\n (child: any) => child.type === \"tag\"\n );\n const conditionalNode = tagStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = tagStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (tagNode && tagNode.text === \"block\" && variableNode) {\n return {\n type: \"block\",\n name: variableNode.text,\n };\n } else if (tagNode && tagNode.text === \"endblock\") {\n return {\n type: \"endblock\",\n };\n } else if (conditionalNode && conditionalNode.text === \"endif\") {\n return {\n type: \"endif\",\n };\n }\n } else if (functionCall) {\n const functionIdentifier = functionCall.children.find(\n (child: any) => child.type === \"function_identifier\"\n );\n\n if (functionIdentifier) {\n return {\n type: \"function\",\n functionName: functionIdentifier.text,\n };\n }\n }\n }\n return null;\n }\n\n // First pass: convert all nodes to intermediate format\n const rawNodes: {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n }[] = [];\n\n // Also collect content nodes\n const allNodes: Array<{\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\" | \"content\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }> = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === \"content\") {\n allNodes.push({\n type: \"content\",\n content: child.text,\n });\n } else {\n const converted = convertNode(child);\n if (converted) {\n rawNodes.push(converted);\n allNodes.push(converted);\n }\n }\n }\n\n // Second pass: build nested structure using a stack\n function buildNestedStructure(\n nodes: Array<{\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\" | \"content\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }>\n ): TwigStatementDirectiveNode[] {\n const result: TwigStatementDirectiveNode[] = [];\n const stack: TwigStatementDirectiveNode[] = [];\n\n for (const node of nodes) {\n if (node.type === \"block\") {\n const blockNode: TwigStatementDirectiveNode = {\n tag: {\n type: \"twig_tag\",\n name: \"block\",\n },\n type: \"twig_statement_directive\",\n variable: {\n type: \"twig_variable\",\n content: node.name!,\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(blockNode);\n }\n } else {\n // Add to root level\n result.push(blockNode);\n }\n\n // Push to stack for nesting\n stack.push(blockNode);\n } else if (node.type === \"endblock\") {\n // Pop from stack when we encounter an endblock\n stack.pop();\n } else if (node.type === \"if\") {\n const ifNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n condition: {\n type: \"twig_condition\",\n expression: {\n type: \"twig_expression\",\n content: node.expression!,\n },\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(ifNode);\n }\n } else {\n // Add to root level\n result.push(ifNode);\n }\n\n // Push to stack for nesting\n stack.push(ifNode);\n } else if (node.type === \"endif\") {\n // Pop from stack when we encounter an endif\n stack.pop();\n } else if (node.type === \"function\") {\n const functionNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n function: {\n type: \"twig_function\",\n name: node.functionName!,\n },\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(functionNode);\n }\n } else {\n // Add to root level\n result.push(functionNode);\n }\n } else if (node.type === \"content\") {\n const contentNode: ContentNode = {\n type: \"content\",\n content: node.content!,\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(contentNode);\n }\n } else {\n // Content at root level - this shouldn't happen in well-formed templates\n // but we'll handle it gracefully\n result.push({\n type: \"twig_statement_directive\",\n children: [contentNode],\n });\n }\n }\n }\n\n return result;\n }\n\n const children = buildNestedStructure(allNodes);\n\n return {\n rootNode: {\n type: \"template\",\n children,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import Parser from \"tree-sitter\";\nimport ShopwareTwig from \"tree-sitter-shopware-twig\";\n\ntype Tree = {\n rootNode: TemplateNode;\n};\n\ntype TemplateNode = {\n type: \"template\";\n children: (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n};\n\ntype TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\";\n tag?: TwigTagNode;\n variable?: TwigVariableNode;\n function?: TwigFunctionNode;\n condition?: TwigConditionNode;\n children?: (\n | TwigStatementDirectiveNode\n | ContentNode\n | HtmlElementNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n};\n\ntype TwigConditionNode = {\n type: \"twig_condition\";\n expression: TwigExpressionNode;\n};\n\ntype TwigExpressionNode = {\n type: \"twig_expression\";\n content: string;\n};\n\ntype ContentNode = {\n type: \"content\";\n content: string;\n};\n\ntype TwigTagNode = {\n type: \"twig_tag\";\n name: string;\n};\n\ntype TwigVariableNode = {\n type: \"twig_variable\";\n content: string;\n};\n\ntype TwigFunctionNode = {\n type: \"twig_function\";\n name: string;\n};\n\ntype HtmlAttributeNode = {\n type: \"html_attribute\";\n name: string;\n value?: string;\n};\n\ntype HtmlElementNode = {\n type: \"html_element\";\n name: string;\n attributes?: HtmlAttributeNode[];\n children: (\n | HtmlElementNode\n | ContentNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[];\n void?: boolean;\n};\n\ntype HtmlDoctypeNode = {\n type: \"doctype\";\n};\n\ntype HtmlNamedEntityNode = {\n type: \"html_named_entity\";\n content: string;\n};\n\ntype HtmlNumericEntityNode = {\n type: \"html_numeric_entity\";\n content: string;\n};\n\nconst parser = new Parser();\n// @ts-expect-error\nparser.setLanguage(ShopwareTwig);\n\nexport function parse(content: string): Tree {\n const tree = parser.parse(content);\n\n function convertNode(node: any): {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n } | null {\n if (node.type === \"statement_directive\") {\n // Check for if_statement\n const ifStatement = node.children.find(\n (child: any) => child.type === \"if_statement\"\n );\n if (ifStatement) {\n const conditionalNode = ifStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = ifStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (conditionalNode && conditionalNode.text === \"if\" && variableNode) {\n return {\n type: \"if\",\n expression: variableNode.text,\n };\n }\n }\n\n // Check for tag_statement\n const tagStatement = node.children.find(\n (child: any) => child.type === \"tag_statement\"\n );\n const functionCall = node.children.find(\n (child: any) => child.type === \"function_call\"\n );\n\n if (tagStatement) {\n const tagNode = tagStatement.children.find(\n (child: any) => child.type === \"tag\"\n );\n const conditionalNode = tagStatement.children.find(\n (child: any) => child.type === \"conditional\"\n );\n const variableNode = tagStatement.children.find(\n (child: any) => child.type === \"variable\"\n );\n\n if (tagNode && tagNode.text === \"block\" && variableNode) {\n return {\n type: \"block\",\n name: variableNode.text,\n };\n } else if (tagNode && tagNode.text === \"endblock\") {\n return {\n type: \"endblock\",\n };\n } else if (conditionalNode && conditionalNode.text === \"endif\") {\n return {\n type: \"endif\",\n };\n }\n } else if (functionCall) {\n const functionIdentifier = functionCall.children.find(\n (child: any) => child.type === \"function_identifier\"\n );\n\n if (functionIdentifier) {\n return {\n type: \"function\",\n functionName: functionIdentifier.text,\n };\n }\n }\n }\n return null;\n }\n\n // First pass: convert all nodes to intermediate format\n const rawNodes: {\n type: \"block\" | \"endblock\" | \"function\" | \"if\" | \"endif\";\n name?: string;\n functionName?: string;\n expression?: string;\n }[] = [];\n\n // Also collect content nodes\n const allNodes: Array<\n | {\n type:\n | \"block\"\n | \"endblock\"\n | \"function\"\n | \"if\"\n | \"endif\"\n | \"content\"\n | \"html_element\"\n | \"doctype\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }\n | HtmlElementNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n > = [];\n\n function convertHtmlEntity(\n node: any\n ): HtmlNamedEntityNode | HtmlNumericEntityNode | null {\n if (node.type === \"html_entity\") {\n const entityText = node.text;\n\n // Check if it's a numeric entity (starts with &#)\n if (entityText.startsWith(\"&#\")) {\n return {\n type: \"html_numeric_entity\",\n content: entityText,\n };\n } else if (entityText.startsWith(\"&\")) {\n return {\n type: \"html_named_entity\",\n content: entityText,\n };\n }\n }\n return null;\n }\n\n function convertHtmlElement(node: any): HtmlElementNode | null {\n if (node.type === \"html_element\") {\n // Check for self-closing tag first\n const selfClosingTag = node.children.find(\n (child: any) => child.type === \"html_self_closing_tag\"\n );\n\n // Check for void tag\n const voidTag = node.children.find(\n (child: any) => child.type === \"html_void_tag\"\n );\n\n // Find the start tag to get the element name\n const startTag = node.children.find(\n (child: any) => child.type === \"html_start_tag\"\n );\n\n // Use self-closing tag, void tag, or start tag in that order of preference\n const tagToUse = selfClosingTag || voidTag || startTag;\n if (!tagToUse) return null;\n\n let tagName: any;\n if (voidTag) {\n // For void tags, the tag name is nested inside html_start_tag within the void tag\n const voidStartTag = voidTag.children.find(\n (child: any) => child.type === \"html_start_tag\"\n );\n tagName = voidStartTag?.children.find(\n (child: any) => child.type === \"html_tag_name\"\n );\n } else {\n // For regular and self-closing tags, tag name is directly in the tag\n tagName = tagToUse.children.find(\n (child: any) => child.type === \"html_tag_name\"\n );\n }\n if (!tagName) return null;\n\n // Check if this is a void element\n const hasVoidTag = node.children.some(\n (child: any) => child.type === \"html_void_tag\"\n );\n const hasSelfClosingTag = node.children.some(\n (child: any) => child.type === \"html_self_closing_tag\"\n );\n const isVoid = hasVoidTag || hasSelfClosingTag;\n\n // Parse attributes from the tag (either self-closing or start tag)\n const attributes: HtmlAttributeNode[] = [];\n const attributeNodes = tagToUse.children.filter(\n (child: any) => child.type === \"html_attribute\"\n );\n\n for (const attrNode of attributeNodes) {\n const nameNode = attrNode.children.find(\n (child: any) => child.type === \"html_attribute_name\"\n );\n if (!nameNode) continue;\n\n const valueNode = attrNode.children.find(\n (child: any) => child.type === \"html_attribute_value\"\n );\n const quotedValueNode = attrNode.children.find(\n (child: any) => child.type === \"html_quoted_attribute_value\"\n );\n\n let value: string | undefined;\n if (quotedValueNode) {\n // For quoted values, find the inner html_attribute_value\n const innerValueNode = quotedValueNode.children.find(\n (child: any) => child.type === \"html_attribute_value\"\n );\n value = innerValueNode ? innerValueNode.text : undefined;\n } else if (valueNode) {\n value = valueNode.text;\n }\n\n const attribute: HtmlAttributeNode = {\n type: \"html_attribute\",\n name: nameNode.text,\n };\n\n // Only include value property if there's actually a value\n if (value !== undefined) {\n attribute.value = value;\n }\n\n attributes.push(attribute);\n }\n\n const elementChildren: (\n | HtmlElementNode\n | ContentNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] = [];\n\n // Process all children that are not start/end tags\n for (const child of node.children) {\n if (child.type === \"content\") {\n elementChildren.push({\n type: \"content\",\n content: child.text,\n });\n } else if (child.type === \"html_element\") {\n const nestedElement = convertHtmlElement(child);\n if (nestedElement) {\n elementChildren.push(nestedElement);\n }\n } else if (child.type === \"html_entity\") {\n const entityNode = convertHtmlEntity(child);\n if (entityNode) {\n elementChildren.push(entityNode);\n }\n }\n }\n\n const result: HtmlElementNode = {\n type: \"html_element\",\n name: tagName.text,\n children: elementChildren,\n };\n\n if (attributes.length > 0) {\n result.attributes = attributes;\n }\n\n if (isVoid) {\n result.void = true;\n }\n\n return result;\n }\n return null;\n }\n\n for (const child of tree.rootNode.children) {\n if (child.type === \"content\") {\n allNodes.push({\n type: \"content\",\n content: child.text,\n });\n } else if (child.type === \"html_element\") {\n const htmlElement = convertHtmlElement(child);\n if (htmlElement) {\n allNodes.push(htmlElement);\n }\n } else if (child.type === \"html_doctype\") {\n allNodes.push({\n type: \"doctype\",\n });\n } else if (child.type === \"html_entity\") {\n const entityNode = convertHtmlEntity(child);\n if (entityNode) {\n allNodes.push(entityNode);\n }\n } else {\n const converted = convertNode(child);\n if (converted) {\n rawNodes.push(converted);\n allNodes.push(converted);\n }\n }\n }\n\n // Second pass: build nested structure using a stack\n function buildNestedStructure(\n nodes: Array<\n | {\n type:\n | \"block\"\n | \"endblock\"\n | \"function\"\n | \"if\"\n | \"endif\"\n | \"content\"\n | \"html_element\"\n | \"doctype\";\n name?: string;\n functionName?: string;\n expression?: string;\n content?: string;\n }\n | HtmlElementNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n >\n ): (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] {\n const result: (\n | TwigStatementDirectiveNode\n | HtmlElementNode\n | ContentNode\n | HtmlDoctypeNode\n | HtmlNamedEntityNode\n | HtmlNumericEntityNode\n )[] = [];\n const stack: TwigStatementDirectiveNode[] = [];\n\n for (const node of nodes) {\n if (node.type === \"block\") {\n const blockNode: TwigStatementDirectiveNode = {\n tag: {\n type: \"twig_tag\",\n name: \"block\",\n },\n type: \"twig_statement_directive\",\n variable: {\n type: \"twig_variable\",\n content: node.name!,\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(blockNode);\n }\n } else {\n // Add to root level\n result.push(blockNode);\n }\n\n // Push to stack for nesting\n stack.push(blockNode);\n } else if (node.type === \"endblock\") {\n // Pop from stack when we encounter an endblock\n stack.pop();\n } else if (node.type === \"if\") {\n const ifNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n condition: {\n type: \"twig_condition\",\n expression: {\n type: \"twig_expression\",\n content: node.expression!,\n },\n },\n children: [],\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(ifNode);\n }\n } else {\n // Add to root level\n result.push(ifNode);\n }\n\n // Push to stack for nesting\n stack.push(ifNode);\n } else if (node.type === \"endif\") {\n // Pop from stack when we encounter an endif\n stack.pop();\n } else if (node.type === \"function\") {\n const functionNode: TwigStatementDirectiveNode = {\n type: \"twig_statement_directive\",\n function: {\n type: \"twig_function\",\n name: node.functionName!,\n },\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(functionNode);\n }\n } else {\n // Add to root level\n result.push(functionNode);\n }\n } else if (node.type === \"content\") {\n const contentNode: ContentNode = {\n type: \"content\",\n content: node.content!,\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(contentNode);\n }\n } else {\n // Content at root level - this shouldn't happen in well-formed templates\n // but we'll handle it gracefully\n result.push({\n type: \"twig_statement_directive\",\n children: [contentNode],\n });\n }\n } else if (node.type === \"html_element\" && \"name\" in node) {\n // HTML elements are already processed and can be added directly\n const htmlNode = node as HtmlElementNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(htmlNode);\n }\n } else {\n // Add to root level\n result.push(htmlNode);\n }\n } else if (node.type === \"doctype\") {\n const doctypeNode: HtmlDoctypeNode = {\n type: \"doctype\",\n };\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(doctypeNode);\n }\n } else {\n // Add to root level\n result.push(doctypeNode);\n }\n } else if (node.type === \"html_named_entity\" && \"content\" in node) {\n const entityNode = node as HtmlNamedEntityNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(entityNode);\n }\n } else {\n // Add to root level\n result.push(entityNode);\n }\n } else if (node.type === \"html_numeric_entity\" && \"content\" in node) {\n const entityNode = node as HtmlNumericEntityNode;\n\n if (stack.length > 0) {\n // Add to the current parent's children\n const parent = stack[stack.length - 1];\n if (parent && parent.children) {\n parent.children.push(entityNode);\n }\n } else {\n // Add to root level\n result.push(entityNode);\n }\n }\n }\n\n return result;\n }\n\n const children = buildNestedStructure(allNodes);\n\n return {\n rootNode: {\n type: \"template\",\n children,\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopware-twig-parser",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "main": "./dist/commonjs/index.js",
5
5
  "files": [
6
6
  "dist"
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "tree-sitter": "^0.25.0",
21
- "tree-sitter-shopware-twig": "^0.2.4"
21
+ "tree-sitter-shopware-twig": "1.0.0"
22
22
  },
23
23
  "type": "module",
24
24
  "tshy": {