Vue Template to Abstract Syntax Tree (AST) Generator
Vue's reactivity and rendering system are powered by an Abstract Syntax Tree (AST) representation of its templates. This challenge asks you to build a simplified AST generator for Vue templates written in TypeScript. Understanding this process is fundamental to comprehending how Vue compiles templates into efficient JavaScript code.
Problem Description
Your task is to create a function that takes a Vue template string as input and produces its corresponding Abstract Syntax Tree (AST) representation. This AST should capture the hierarchical structure of the template, including elements, attributes, text nodes, and directives.
Key Requirements
- Parsing: The generator must parse the HTML-like Vue template syntax.
- AST Structure: The generated AST should follow a defined structure that represents different node types:
ElementNode: Represents HTML elements (<div>,<span>, etc.). Should contain:tag: The element tag name (e.g.,"div").attributes: An array ofAttributeNodeobjects.children: An array of child nodes (which can be otherElementNodes,TextNodes, etc.).
TextNode: Represents plain text content within an element. Should contain:content: The text string.
AttributeNode: Represents attributes on an element. Should contain:name: The attribute name (e.g.,"id","class","v-model").value: The attribute value (e.g.,"my-element","active","message"). For directives likev-bind:, the value could also be an expression.
- Directive Handling: Recognize and represent common Vue directives like
v-bind,v-on, andv-model. These should be stored asAttributeNodes with specific names. - Nesting: Correctly handle nested elements.
Expected Behavior
The function should transform a string containing a Vue template into a structured object (the AST). The AST should accurately mirror the DOM structure implied by the template.
Edge Cases to Consider
- Empty templates.
- Templates with only text.
- Self-closing tags (though for this simplified version, we can assume they are closed properly, e.g.,
<br>vs<br/>). - Attributes without values (e.g.,
<input disabled>). - Attributes with empty values (e.g.,
<div class="">).
Examples
Example 1:
Input: "<div>Hello</div>"
Output: {
"type": "ElementNode",
"tag": "div",
"attributes": [],
"children": [
{
"type": "TextNode",
"content": "Hello"
}
]
}
Explanation: The input is a simple div element containing text. The AST represents the div as an ElementNode with no attributes and a single child, a TextNode with the content "Hello".
Example 2:
Input: "<div id=\"app\" class=\"container\"><p v-if=\"showMessage\">Welcome!</p></div>"
Output: {
"type": "ElementNode",
"tag": "div",
"attributes": [
{ "type": "AttributeNode", "name": "id", "value": "app" },
{ "type": "AttributeNode", "name": "class", "value": "container" }
],
"children": [
{
"type": "ElementNode",
"tag": "p",
"attributes": [
{ "type": "AttributeNode", "name": "v-if", "value": "showMessage" }
],
"children": [
{
"type": "TextNode",
"content": "Welcome!"
}
]
}
]
}
Explanation: This AST represents a nested structure. The outer div has id and class attributes. Its child is a p element with a v-if directive and text content.
Example 3:
Input: "<div><input type=\"text\" v-model=\"message\" /></div>"
Output: {
"type": "ElementNode",
"tag": "div",
"attributes": [],
"children": [
{
"type": "ElementNode",
"tag": "input",
"attributes": [
{ "type": "AttributeNode", "name": "type", "value": "text" },
{ "type": "AttributeNode", "name": "v-model", "value": "message" }
],
"children": []
}
]
}
Explanation: This demonstrates handling an input element with multiple attributes, including a v-model directive. Since the input tag is self-closing or empty, its children array is empty.
Constraints
- The input template string will contain only valid HTML-like syntax for this problem, without script tags, comments, or complex template expressions that require full Vue compiler parsing.
- Attributes will be enclosed in double quotes (e.g.,
attr="value"). - Attribute names and tag names will be alphanumeric.
- The maximum depth of nested elements will be at most 10.
- The total number of nodes in the AST will not exceed 100.
Notes
This is a simplified AST generator. A real Vue compiler handles much more complexity, including:
- Expression Parsing: For
v-bindvalues,v-ifconditions, and text interpolations ({{ }}). You can treat these as raw strings for this challenge. - Event Handling:
v-on:clickattributes. - Slots and Components: More advanced template features.
- Error Handling: Robust parsing of malformed templates.
- Whitespace Handling: Different strategies for preserving or normalizing whitespace.
Focus on correctly parsing the basic structure of elements, text, and attributes, including common directives. You'll need to define TypeScript interfaces for your AST nodes.