Hone logo
Hone
Problems

Vue Component AST Generator

Building a compiler or transpiler often requires understanding the structure of the code being processed. This challenge asks you to implement a simplified AST (Abstract Syntax Tree) generator for Vue components, focusing on the template portion. This is a fundamental step in many Vue-related tools, such as static site generators, advanced build systems, and code analysis tools.

Problem Description

You are tasked with creating a TypeScript function generateAST that takes a Vue component's template string as input and returns a simplified AST representation. The AST should represent the structure of the template, focusing on element tags, attributes, and text nodes. The AST will be a tree-like structure where each node represents a part of the template.

What needs to be achieved:

  • Parse the template string.
  • Identify elements (tags), attributes, and text nodes.
  • Construct an AST representing this structure.

Key Requirements:

  • The AST should be a TypeScript data structure. Define interfaces for ASTNode, ElementNode, AttributeNode, and TextNode.
  • Handle basic HTML-like tags (e.g., <div>, <p>, <span>).
  • Handle attributes within elements (e.g., class="my-class", id="unique-id").
  • Handle text nodes (plain text between elements).
  • Ignore directives (e.g., v-if, v-for) for simplicity.
  • Ignore comments for simplicity.
  • Handle nested elements correctly.

Expected Behavior:

The generateAST function should return an array of ASTNode objects, representing the root of the AST. The AST should accurately reflect the structure of the input template.

Edge Cases to Consider:

  • Empty template string.
  • Template strings with only text.
  • Template strings with nested elements.
  • Attributes with no values (e.g., <input type="text">).
  • Self-closing tags (e.g., <img src="image.jpg" />). Treat these as regular elements with closing tags.
  • Multiple attributes with the same name (e.g., <div class="a" class="b">). The last attribute should take precedence.

Examples

Example 1:

Input: "<div id='app'>Hello, world!</div>"
Output: [
  {
    type: 'ElementNode',
    tag: 'div',
    attributes: [
      { name: 'id', value: 'app' }
    ],
    children: [
      {
        type: 'TextNode',
        text: 'Hello, world!'
      }
    ]
  }
]
Explanation: The input template is a single `div` element with an `id` attribute and a text node as its child. The output AST reflects this structure.

Example 2:

Input: "<p>This is a <span>simple</span> example.</p>"
Output: [
  {
    type: 'ElementNode',
    tag: 'p',
    attributes: [],
    children: [
      {
        type: 'TextNode',
        text: 'This is a '
      },
      {
        type: 'ElementNode',
        tag: 'span',
        attributes: [],
        children: [
          {
            type: 'TextNode',
            text: 'simple'
          }
        ]
      },
      {
        type: 'TextNode',
        text: ' example.'
      }
    ]
  }
]
Explanation: The input template contains a `p` element with a `span` element nested within it. The output AST accurately represents this nested structure.

Example 3:

Input: "<img src='image.jpg' alt='My Image' />"
Output: [
  {
    type: 'ElementNode',
    tag: 'img',
    attributes: [
      { name: 'src', value: 'image.jpg' },
      { name: 'alt', value: 'My Image' }
    ],
    children: []
  }
]
Explanation: This example demonstrates handling attributes and a self-closing tag. The output AST includes the `img` tag and its attributes.

Constraints

  • Template String Length: The input template string will be no longer than 1024 characters.
  • Attribute Values: Attribute values will be enclosed in single or double quotes, or may be unquoted (e.g., <div class=myclass>). Unquoted attributes are allowed, but should be treated as if they were quoted.
  • Performance: The AST generation should complete within 500ms for typical templates.
  • Error Handling: The function should not throw errors. Invalid templates should result in a valid (though potentially incomplete) AST.

Notes

  • You can use regular expressions to help with parsing, but be mindful of their limitations when dealing with complex HTML structures.
  • Consider using a recursive approach to handle nested elements.
  • Focus on the core functionality of AST generation. Advanced features like directive parsing and expression evaluation are beyond the scope of this challenge.
  • The order of attributes in the AST does not matter.
  • The value property of AttributeNode should always be a string.
  • The text property of TextNode should always be a string.
  • Start with a simple template and gradually increase complexity as you build your parser.
// Define the AST node interfaces
interface ASTNode {
  type: 'ElementNode' | 'TextNode';
}

interface ElementNode extends ASTNode {
  tag: string;
  attributes: AttributeNode[];
  children: ASTNode[];
}

interface AttributeNode {
  name: string;
  value: string;
}

interface TextNode extends ASTNode {
  text: string;
}

// Function to generate the AST
function generateAST(template: string): ASTNode[] {
  // Your code here
  return [];
}
Loading editor...
typescript