Example

HTML Fragment

Nested HTML-like markup.

← All examples

Specification

$flags: 'FLEXIBLE_WHITESPACE'

Attribute:
  $types:
    Identifier: '[a-zA-Z][a-zA-Z0-9-]+'
    String: '.*?'
  $fields:
    name: Identifier
    value: String
  $patterns: '#{name}=\"#{value}\"'

Node:
  Comment: '<!--.*?-->'
  Text: '(?<=>)${!Node}[^>\s][^>]*(?=<)'
  Tag:
    $types:
      Identifier: '[a-zA-Z][a-zA-Z0-9-]+'
    $fields:
      name: Identifier
      attributes: Attribute[]
      children: Node[]
    $patterns:
      - '<#{name}( #{attributes})*>(\s*#{children}\s*)*</#{=name}>'
      - '<#{name}( #{attributes})*/>'

Sample input

<div class="container">
  <div class="content" id="content-panel" height="200px">
    <h1 id="main-title">Hello, World!</h1>
    <br/>
   </div>
   <!-- <div> Commented Node </div> -->
</div>

Result

[
  {
    "type": "Node::Tag",
    "text": "<div class=\"container\">\n  <div class=\"content\" id=\"content-panel\" height=\"200px\">\n    <h1 id=\"main-title\">Hello, World!</h1>\n    <br/>\n   </div>\n   <!-- <div> Commented Node </div> -->\n</div>",
    "start": 0,
    "end": 191,
    "fields": [
      {
        "type": "Identifier",
        "field": "name",
        "text": "div",
        "start": 1,
        "end": 4
      },
      {
        "type": "Attribute[]",
        "field": "attributes",
        "text": "class=\"container\"",
        "start": 5,
        "end": 22,
        "items": [
          {
            "type": "Attribute",
            "text": "class=\"container\"",
            "start": 5,
            "end": 22,
            "fields": [
              {
                "type": "Identifier",
                "field": "name",
                "text": "class",
                "start": 5,
                "end": 10
              },
              {
                "type": "String",
                "field": "value",
                "text": "container",
                "start": 12,
                "end": 21
              }
            ]
          }
        ]
      },
      {
        "type": "Node[]",
        "field": "children",
        "text": "<div class=\"content\" id=\"content-panel\" height=\"200px\">\n    <h1 id=\"main-title\">Hello, World!</h1>\n    <br/>\n   </div>\n   <!-- <div> Commented Node </div> -->",
        "start": 26,
        "end": 184,
        "items": [
          {
            "type": "Node::Tag",
            "text": "<div class=\"content\" id=\"content-panel\" height=\"200px\">\n    <h1 id=\"main-title\">Hello, World!</h1>\n    <br/>\n   </div>",
            "start": 26,
            "end": 144,
            "fields": [
              {
                "type": "Identifier",
                "field": "name",
                "text": "div",
                "start": 27,
                "end": 30
              },
              {
                "type": "Attribute[]",
                "field": "attributes",
                "text": "class=\"content\" id=\"content-panel\" height=\"200px\"",
                "start": 31,
                "end": 80,
                "items": [
                  {
                    "type": "Attribute",
                    "text": "class=\"content\"",
                    "start": 31,
                    "end": 46,
                    "fields": [
                      {
                        "type": "Identifier",
                        "field": "name",
                        "text": "class",
                        "start": 31,
                        "end": 36
                      },
                      {
                        "type": "String",
                        "field": "value",
                        "text": "content",
                        "start": 38,
                        "end": 45
                      }
                    ]
                  },
                  {
                    "type": "Attribute",
                    "text": "id=\"content-panel\"",
                    "start": 47,
                    "end": 65,
                    "fields": [
                      {
                        "type": "Identifier",
                        "field": "name",
                        "text": "id",
                        "start": 47,
                        "end": 49
                      },
                      {
                        "type": "String",
                        "field": "value",
                        "text": "content-panel",
                        "start": 51,
                        "end": 64
                      }
                    ]
                  },
                  {
                    "type": "Attribute",
                    "text": "height=\"200px\"",
                    "start": 66,
                    "end": 80,
                    "fields": [
                      {
                        "type": "Identifier",
                        "field": "name",
                        "text": "height",
                        "start": 66,
                        "end": 72
                      },
                      {
                        "type": "String",
                        "field": "value",
                        "text": "200px",
                        "start": 74,
                        "end": 79
                      }
                    ]
                  }
                ]
              },
              {
                "type": "Node[]",
                "field": "children",
                "text": "<h1 id=\"main-title\">Hello, World!</h1>\n    <br/>",
                "start": 86,
                "end": 134,
                "items": [
                  {
                    "type": "Node::Tag",
                    "text": "<h1 id=\"main-title\">Hello, World!</h1>",
                    "start": 86,
                    "end": 124,
                    "fields": [
                      {
                        "type": "Identifier",
                        "field": "name",
                        "text": "h1",
                        "start": 87,
                        "end": 89
                      },
                      {
                        "type": "Attribute[]",
                        "field": "attributes",
                        "text": "id=\"main-title\"",
                        "start": 90,
                        "end": 105,
                        "items": [
                          {
                            "type": "Attribute",
                            "text": "id=\"main-title\"",
                            "start": 90,
                            "end": 105,
                            "fields": [
                              {
                                "type": "Identifier",
                                "field": "name",
                                "text": "id",
                                "start": 90,
                                "end": 92
                              },
                              {
                                "type": "String",
                                "field": "value",
                                "text": "main-title",
                                "start": 94,
                                "end": 104
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "Node[]",
                        "field": "children",
                        "text": "Hello, World!",
                        "start": 106,
                        "end": 119,
                        "items": [
                          {
                            "type": "Node::Text",
                            "text": "Hello, World!",
                            "start": 106,
                            "end": 119
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "type": "Node::Tag",
                    "text": "<br/>",
                    "start": 129,
                    "end": 134,
                    "fields": [
                      {
                        "type": "Identifier",
                        "field": "name",
                        "text": "br",
                        "start": 130,
                        "end": 132
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "Node::Comment",
            "text": "<!-- <div> Commented Node </div> -->",
            "start": 148,
            "end": 184
          }
        ]
      }
    ]
  }
]

Notes

# HTML Fragment

Recognize a small nested HTML-like fragment.

## Notice

- `Attribute` and `Node::Tag` use scoped `$types` for tag and attribute names.
- `Attribute` extracts `name` and `value`.
- `Node` is the parent type for comments, text, and tags.
- `Node::Tag` references `${Node}` to allow nesting.
- Closing tags use `#{=name}` to reference the opening tag field.

Try adding a nested tag or another attribute.