]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(compiler): basic transform implementation
authorEvan You <yyx990803@gmail.com>
Tue, 17 Sep 2019 23:08:47 +0000 (19:08 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 17 Sep 2019 23:08:47 +0000 (19:08 -0400)
packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap
packages/compiler-core/__tests__/parse.spec.ts
packages/compiler-core/src/ast.ts
packages/compiler-core/src/directives/vIf.ts
packages/compiler-core/src/errorTypes.ts [deleted file]
packages/compiler-core/src/errors.ts [new file with mode: 0644]
packages/compiler-core/src/index.ts
packages/compiler-core/src/parse.ts [moved from packages/compiler-core/src/parser.ts with 86% similarity]
packages/compiler-core/src/transform.ts
packages/compiler-dom/__tests__/parse.spec.ts
packages/compiler-dom/src/parserOptionsMinimal.ts

index 14e2e9d9bc0b0d2ec49ec2612ecea5a4fc8f63c0..f9e949bc628481d35fc9d1410077393977951131 100644 (file)
@@ -4,6 +4,7 @@ exports[`base parser Errors ABRUPT_CLOSING_OF_EMPTY_COMMENT <template><!--></tem
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -20,9 +21,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -38,10 +40,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -57,7 +58,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -65,6 +66,7 @@ exports[`base parser Errors ABRUPT_CLOSING_OF_EMPTY_COMMENT <template><!---></te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -81,9 +83,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -99,10 +102,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -118,7 +120,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -126,6 +128,7 @@ exports[`base parser Errors ABRUPT_CLOSING_OF_EMPTY_COMMENT <template><!----></t
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -142,9 +145,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -160,10 +164,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -179,7 +182,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -187,23 +190,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
-      "children": Array [],
-      "isSelfClosing": false,
-      "loc": Object {
-        "end": Object {
-          "column": 35,
-          "line": 1,
-          "offset": 34,
-        },
-        "source": "<template attr=\\"&#99;\\"></template>",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "attrs": Array [
         Object {
           "loc": Object {
             "end": Object {
@@ -219,7 +206,7 @@ Object {
             },
           },
           "name": "attr",
-          "type": 3,
+          "type": 5,
           "value": Object {
             "content": "c",
             "isEmpty": false,
@@ -236,13 +223,30 @@ Object {
                 "offset": 15,
               },
             },
-            "type": 0,
+            "type": 2,
           },
         },
       ],
+      "children": Array [],
+      "directives": Array [],
+      "isSelfClosing": false,
+      "loc": Object {
+        "end": Object {
+          "column": 35,
+          "line": 1,
+          "offset": 34,
+        },
+        "source": "<template attr=\\"&#99;\\"></template>",
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "ns": 0,
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -258,7 +262,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -266,23 +270,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
-      "children": Array [],
-      "isSelfClosing": false,
-      "loc": Object {
-        "end": Object {
-          "column": 34,
-          "line": 1,
-          "offset": 33,
-        },
-        "source": "<template attr=\\"&#a;\\"></template>",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "attrs": Array [
         Object {
           "loc": Object {
             "end": Object {
@@ -298,7 +286,7 @@ Object {
             },
           },
           "name": "attr",
-          "type": 3,
+          "type": 5,
           "value": Object {
             "content": "&#a;",
             "isEmpty": false,
@@ -315,13 +303,30 @@ Object {
                 "offset": 15,
               },
             },
-            "type": 0,
+            "type": 2,
           },
         },
       ],
+      "children": Array [],
+      "directives": Array [],
+      "isSelfClosing": false,
+      "loc": Object {
+        "end": Object {
+          "column": 34,
+          "line": 1,
+          "offset": 33,
+        },
+        "source": "<template attr=\\"&#a;\\"></template>",
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "ns": 0,
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -337,7 +342,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -345,23 +350,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
-      "children": Array [],
-      "isSelfClosing": false,
-      "loc": Object {
-        "end": Object {
-          "column": 36,
-          "line": 1,
-          "offset": 35,
-        },
-        "source": "<template attr=\\"&#xff;\\"></template>",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "attrs": Array [
         Object {
           "loc": Object {
             "end": Object {
@@ -377,7 +366,7 @@ Object {
             },
           },
           "name": "attr",
-          "type": 3,
+          "type": 5,
           "value": Object {
             "content": "ΓΏ",
             "isEmpty": false,
@@ -394,13 +383,30 @@ Object {
                 "offset": 15,
               },
             },
-            "type": 0,
+            "type": 2,
           },
         },
       ],
+      "children": Array [],
+      "directives": Array [],
+      "isSelfClosing": false,
+      "loc": Object {
+        "end": Object {
+          "column": 36,
+          "line": 1,
+          "offset": 35,
+        },
+        "source": "<template attr=\\"&#xff;\\"></template>",
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "ns": 0,
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -416,7 +422,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -424,23 +430,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
-      "children": Array [],
-      "isSelfClosing": false,
-      "loc": Object {
-        "end": Object {
-          "column": 35,
-          "line": 1,
-          "offset": 34,
-        },
-        "source": "<template attr=\\"&#xg;\\"></template>",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "attrs": Array [
         Object {
           "loc": Object {
             "end": Object {
@@ -456,7 +446,7 @@ Object {
             },
           },
           "name": "attr",
-          "type": 3,
+          "type": 5,
           "value": Object {
             "content": "&#xg;",
             "isEmpty": false,
@@ -473,13 +463,30 @@ Object {
                 "offset": 15,
               },
             },
-            "type": 0,
+            "type": 2,
           },
         },
       ],
+      "children": Array [],
+      "directives": Array [],
+      "isSelfClosing": false,
+      "loc": Object {
+        "end": Object {
+          "column": 35,
+          "line": 1,
+          "offset": 34,
+        },
+        "source": "<template attr=\\"&#xg;\\"></template>",
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "ns": 0,
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -495,7 +502,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -503,6 +510,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "c",
@@ -520,9 +528,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -538,10 +547,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -557,7 +565,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -565,6 +573,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "&#a;",
@@ -582,9 +591,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -600,10 +610,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -619,7 +628,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -627,6 +636,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "ΓΏ",
@@ -644,9 +654,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -662,10 +673,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -681,7 +691,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -689,6 +699,7 @@ exports[`base parser Errors ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "&#xg;",
@@ -706,9 +717,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -724,10 +736,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -743,7 +754,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -751,6 +762,7 @@ exports[`base parser Errors CDATA_IN_HTML_CONTENT <template><![CDATA[cdata]]></t
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "[CDATA[cdata]]",
@@ -767,9 +779,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -785,10 +798,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -804,7 +816,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -812,8 +824,10 @@ exports[`base parser Errors CDATA_IN_HTML_CONTENT <template><svg><![CDATA[cdata]
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [
             Object {
               "content": "cdata",
@@ -831,9 +845,10 @@ Object {
                   "offset": 24,
                 },
               },
-              "type": 0,
+              "type": 2,
             },
           ],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -849,12 +864,12 @@ Object {
             },
           },
           "ns": 1,
-          "props": Array [],
           "tag": "svg",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -870,10 +885,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -889,7 +903,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -897,6 +911,7 @@ exports[`base parser Errors CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE <template>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "οΏ½",
@@ -914,9 +929,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -932,10 +948,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -951,7 +966,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -959,6 +974,7 @@ exports[`base parser Errors CONTROL_CHARACTER_REFERENCE <template>&#0003;</templ
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "\ 3",
@@ -976,9 +992,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -994,10 +1011,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1013,7 +1029,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1021,6 +1037,7 @@ exports[`base parser Errors CONTROL_CHARACTER_REFERENCE <template>&#x7F;</templa
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "\7f",
@@ -1038,9 +1055,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1056,10 +1074,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1075,7 +1092,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1083,25 +1100,10 @@ exports[`base parser Errors DUPLICATE_ATTRIBUTE <template><div id="" id=""></div
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 34,
-              "line": 1,
-              "offset": 33,
-            },
-            "source": "<div id=\\"\\" id=\\"\\"></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -1117,7 +1119,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "",
                 "isEmpty": true,
@@ -1134,7 +1136,7 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
             Object {
@@ -1152,7 +1154,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "",
                 "isEmpty": true,
@@ -1169,15 +1171,33 @@ Object {
                     "offset": 24,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 34,
+              "line": 1,
+              "offset": 33,
+            },
+            "source": "<div id=\\"\\" id=\\"\\"></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1193,10 +1213,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1212,7 +1231,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1220,9 +1239,12 @@ exports[`base parser Errors END_TAG_WITH_ATTRIBUTES <template><div></div id=""><
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -1238,12 +1260,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1259,10 +1281,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1278,7 +1299,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1286,9 +1307,12 @@ exports[`base parser Errors END_TAG_WITH_TRAILING_SOLIDUS <template><div></div/>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -1304,12 +1328,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1325,10 +1349,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1344,7 +1367,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1352,6 +1375,7 @@ exports[`base parser Errors EOF_BEFORE_TAG_NAME <template>< 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "<",
@@ -1369,9 +1393,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1387,10 +1412,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1406,7 +1430,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1414,6 +1438,7 @@ exports[`base parser Errors EOF_BEFORE_TAG_NAME <template></ 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "</",
@@ -1431,9 +1456,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1449,10 +1475,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1468,7 +1493,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1476,9 +1501,12 @@ exports[`base parser Errors EOF_IN_CDATA <template><svg><![CDATA[ 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -1494,12 +1522,12 @@ Object {
             },
           },
           "ns": 1,
-          "props": Array [],
           "tag": "svg",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1515,10 +1543,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1534,7 +1561,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1542,8 +1569,10 @@ exports[`base parser Errors EOF_IN_CDATA <template><svg><![CDATA[cdata 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [
             Object {
               "content": "cdata",
@@ -1561,9 +1590,10 @@ Object {
                   "offset": 24,
                 },
               },
-              "type": 0,
+              "type": 2,
             },
           ],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -1579,12 +1609,12 @@ Object {
             },
           },
           "ns": 1,
-          "props": Array [],
           "tag": "svg",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1600,10 +1630,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1619,7 +1648,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1627,6 +1656,7 @@ exports[`base parser Errors EOF_IN_COMMENT <template><! 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -1643,9 +1673,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1661,10 +1692,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1680,7 +1710,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1688,6 +1718,7 @@ exports[`base parser Errors EOF_IN_COMMENT <template><!- 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "-",
@@ -1704,9 +1735,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1722,10 +1754,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1741,7 +1772,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1749,6 +1780,7 @@ exports[`base parser Errors EOF_IN_COMMENT <template><!-- 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -1765,9 +1797,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1783,10 +1816,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1802,7 +1834,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1810,6 +1842,7 @@ exports[`base parser Errors EOF_IN_COMMENT <template><!--comment 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "comment",
@@ -1826,9 +1859,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1844,10 +1878,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1863,7 +1896,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1871,6 +1904,7 @@ exports[`base parser Errors EOF_IN_COMMENT <template><!abc 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "abc",
@@ -1887,9 +1921,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1905,10 +1940,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1924,7 +1958,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1932,6 +1966,7 @@ exports[`base parser Errors EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT <script><!--con
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "<!--console.log('hello')",
@@ -1949,9 +1984,10 @@ Object {
               "offset": 8,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -1967,10 +2003,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "script",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -1986,7 +2021,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -1994,6 +2029,7 @@ exports[`base parser Errors EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT <script>console
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "console.log('hello')",
@@ -2011,9 +2047,10 @@ Object {
               "offset": 8,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2029,10 +2066,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "script",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2048,7 +2084,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2056,9 +2092,12 @@ exports[`base parser Errors EOF_IN_TAG <template><div  1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -2074,12 +2113,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2095,10 +2134,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2114,7 +2152,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2122,9 +2160,12 @@ exports[`base parser Errors EOF_IN_TAG <template><div 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -2140,12 +2181,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2161,10 +2202,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2180,7 +2220,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2188,25 +2228,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id  1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 19,
-              "line": 1,
-              "offset": 18,
-            },
-            "source": "<div id ",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2222,15 +2247,33 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 19,
+              "line": 1,
+              "offset": 18,
+            },
+            "source": "<div id ",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2246,10 +2289,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2265,7 +2307,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2273,25 +2315,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id = 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 20,
-              "line": 1,
-              "offset": 19,
-            },
-            "source": "<div id =",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2307,15 +2334,33 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 20,
+              "line": 1,
+              "offset": 19,
+            },
+            "source": "<div id =",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2331,10 +2376,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2350,7 +2394,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2358,25 +2402,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 18,
-              "line": 1,
-              "offset": 17,
-            },
-            "source": "<div id",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2392,15 +2421,33 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 18,
+              "line": 1,
+              "offset": 17,
+            },
+            "source": "<div id",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2416,10 +2463,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2435,7 +2481,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2443,25 +2489,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id="abc 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 23,
-              "line": 1,
-              "offset": 22,
-            },
-            "source": "<div id=\\"abc",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2477,7 +2508,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -2494,15 +2525,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 23,
+              "line": 1,
+              "offset": 22,
+            },
+            "source": "<div id=\\"abc",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2518,10 +2567,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2537,7 +2585,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2545,25 +2593,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id="abc" 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 24,
-              "line": 1,
-              "offset": 23,
-            },
-            "source": "<div id=\\"abc\\"",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2579,7 +2612,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -2596,15 +2629,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 24,
+              "line": 1,
+              "offset": 23,
+            },
+            "source": "<div id=\\"abc\\"",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2620,10 +2671,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2639,7 +2689,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2647,25 +2697,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id="abc"/ 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 25,
-              "line": 1,
-              "offset": 24,
-            },
-            "source": "<div id=\\"abc\\"/",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2681,7 +2716,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -2698,15 +2733,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 25,
+              "line": 1,
+              "offset": 24,
+            },
+            "source": "<div id=\\"abc\\"/",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2722,10 +2775,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2741,7 +2793,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2749,25 +2801,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id='abc 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 23,
-              "line": 1,
-              "offset": 22,
-            },
-            "source": "<div id='abc",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2783,7 +2820,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -2800,15 +2837,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 23,
+              "line": 1,
+              "offset": 22,
+            },
+            "source": "<div id='abc",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2824,10 +2879,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2843,7 +2897,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2851,25 +2905,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id='abc' 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 24,
-              "line": 1,
-              "offset": 23,
-            },
-            "source": "<div id='abc'",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2885,7 +2924,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -2902,15 +2941,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 24,
+              "line": 1,
+              "offset": 23,
+            },
+            "source": "<div id='abc'",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -2926,10 +2983,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -2945,7 +3001,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -2953,25 +3009,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id='abc'/ 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 25,
-              "line": 1,
-              "offset": 24,
-            },
-            "source": "<div id='abc'/",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -2987,7 +3028,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -3004,15 +3045,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 25,
+              "line": 1,
+              "offset": 24,
+            },
+            "source": "<div id='abc'/",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3028,10 +3087,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3047,7 +3105,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3055,25 +3113,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id=abc / 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 24,
-              "line": 1,
-              "offset": 23,
-            },
-            "source": "<div id=abc /",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -3089,7 +3132,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -3106,15 +3149,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 24,
+              "line": 1,
+              "offset": 23,
+            },
+            "source": "<div id=abc /",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3130,10 +3191,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3149,7 +3209,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3157,25 +3217,10 @@ exports[`base parser Errors EOF_IN_TAG <template><div id=abc 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 22,
-              "line": 1,
-              "offset": 21,
-            },
-            "source": "<div id=abc",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -3191,7 +3236,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "abc",
                 "isEmpty": false,
@@ -3208,15 +3253,33 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 22,
+              "line": 1,
+              "offset": 21,
+            },
+            "source": "<div id=abc",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3232,10 +3295,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3251,7 +3313,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3259,6 +3321,7 @@ exports[`base parser Errors INCORRECTLY_CLOSED_COMMENT <template><!--comment--!>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "comment",
@@ -3275,9 +3338,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3293,10 +3357,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3312,7 +3375,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3334,7 +3397,7 @@ Object {
           "offset": 0,
         },
       },
-      "type": 1,
+      "type": 3,
     },
   ],
   "loc": Object {
@@ -3350,7 +3413,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3358,6 +3421,7 @@ exports[`base parser Errors INCORRECTLY_OPENED_COMMENT <template><!></template>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "",
@@ -3374,9 +3438,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3392,10 +3457,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3411,7 +3475,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3419,6 +3483,7 @@ exports[`base parser Errors INCORRECTLY_OPENED_COMMENT <template><!-></template>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "-",
@@ -3435,9 +3500,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3453,10 +3519,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3472,7 +3537,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3480,6 +3545,7 @@ exports[`base parser Errors INCORRECTLY_OPENED_COMMENT <template><!ELEMENT br EM
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "ELEMENT br EMPTY",
@@ -3496,9 +3562,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3514,10 +3581,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3533,7 +3599,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3541,6 +3607,7 @@ exports[`base parser Errors INVALID_FIRST_CHARACTER_OF_TAG_NAME <template></οΏ½>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "οΏ½",
@@ -3557,9 +3624,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3575,10 +3643,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3594,7 +3661,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3602,6 +3669,7 @@ exports[`base parser Errors INVALID_FIRST_CHARACTER_OF_TAG_NAME <template><οΏ½><
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "<οΏ½>",
@@ -3619,9 +3687,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3637,10 +3706,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3656,7 +3724,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3664,6 +3732,7 @@ exports[`base parser Errors INVALID_FIRST_CHARACTER_OF_TAG_NAME <template>{{a <
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a < b",
@@ -3684,6 +3753,7 @@ Object {
           "type": 4,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3699,10 +3769,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3718,7 +3787,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3726,6 +3795,7 @@ exports[`base parser Errors INVALID_FIRST_CHARACTER_OF_TAG_NAME <template>a < b<
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a < b",
@@ -3743,9 +3813,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3761,10 +3832,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3780,7 +3850,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3788,6 +3858,7 @@ exports[`base parser Errors INVALID_FIRST_CHARACTER_OF_TAG_NAME <template>a </ b
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a ",
@@ -3805,7 +3876,7 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
         Object {
           "content": " b</template",
@@ -3822,9 +3893,10 @@ Object {
               "offset": 12,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3840,10 +3912,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3859,7 +3930,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3867,25 +3938,10 @@ exports[`base parser Errors MISSING_ATTRIBUTE_VALUE <template><div id= /></div><
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 28,
-              "line": 1,
-              "offset": 27,
-            },
-            "source": "<div id= /></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -3901,7 +3957,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "/",
                 "isEmpty": false,
@@ -3918,15 +3974,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 28,
+              "line": 1,
+              "offset": 27,
+            },
+            "source": "<div id= /></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -3942,10 +4016,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -3961,7 +4034,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -3969,25 +4042,10 @@ exports[`base parser Errors MISSING_ATTRIBUTE_VALUE <template><div id= ></div></
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 27,
-              "line": 1,
-              "offset": 26,
-            },
-            "source": "<div id= ></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -4003,15 +4061,33 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 27,
+              "line": 1,
+              "offset": 26,
+            },
+            "source": "<div id= ></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4027,10 +4103,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4046,7 +4121,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4054,25 +4129,10 @@ exports[`base parser Errors MISSING_ATTRIBUTE_VALUE <template><div id=></div></t
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 26,
-              "line": 1,
-              "offset": 25,
-            },
-            "source": "<div id=></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -4088,15 +4148,33 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 26,
+              "line": 1,
+              "offset": 25,
+            },
+            "source": "<div id=></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4112,10 +4190,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4131,7 +4208,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4139,7 +4216,9 @@ exports[`base parser Errors MISSING_END_TAG_NAME <template></></template> 1`] =
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4155,10 +4234,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4174,7 +4252,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4182,6 +4260,7 @@ exports[`base parser Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE <templat
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "(",
@@ -4199,9 +4278,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4217,10 +4297,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4236,7 +4315,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4244,6 +4323,7 @@ exports[`base parser Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE <templat
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "@",
@@ -4261,9 +4341,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4279,10 +4360,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4298,7 +4378,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4306,6 +4386,7 @@ exports[`base parser Errors MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE <templat
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "&",
@@ -4323,9 +4404,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4341,10 +4423,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4360,7 +4441,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4368,26 +4449,10 @@ exports[`base parser Errors MISSING_WHITESPACE_BETWEEN_ATTRIBUTES <template><div
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 19,
-              "line": 2,
-              "offset": 43,
-            },
-            "source": "<div id=\\"foo\\"
-class=\\"bar\\"></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -4403,7 +4468,7 @@ class=\\"bar\\"></div>",
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "foo",
                 "isEmpty": false,
@@ -4420,7 +4485,7 @@ class=\\"bar\\"></div>",
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
             Object {
@@ -4438,7 +4503,7 @@ class=\\"bar\\"></div>",
                 },
               },
               "name": "class",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar",
                 "isEmpty": false,
@@ -4455,15 +4520,34 @@ class=\\"bar\\"></div>",
                     "offset": 31,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 19,
+              "line": 2,
+              "offset": 43,
+            },
+            "source": "<div id=\\"foo\\"
+class=\\"bar\\"></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4480,10 +4564,9 @@ class=\\"bar\\"></div></template>",
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4500,7 +4583,7 @@ class=\\"bar\\"></div></template>",
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4508,25 +4591,10 @@ exports[`base parser Errors MISSING_WHITESPACE_BETWEEN_ATTRIBUTES <template><div
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 42,
-              "line": 1,
-              "offset": 41,
-            },
-            "source": "<div id=\\"foo\\"class=\\"bar\\"></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -4542,7 +4610,7 @@ Object {
                 },
               },
               "name": "id",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "foo",
                 "isEmpty": false,
@@ -4559,7 +4627,7 @@ Object {
                     "offset": 18,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
             Object {
@@ -4577,7 +4645,7 @@ Object {
                 },
               },
               "name": "class",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar",
                 "isEmpty": false,
@@ -4594,15 +4662,33 @@ Object {
                     "offset": 29,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 42,
+              "line": 1,
+              "offset": 41,
+            },
+            "source": "<div id=\\"foo\\"class=\\"bar\\"></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4618,10 +4704,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4637,7 +4722,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4645,6 +4730,7 @@ exports[`base parser Errors NESTED_COMMENT <template><!--a<!-- 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a<!--",
@@ -4661,9 +4747,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4679,10 +4766,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4698,7 +4784,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4706,6 +4792,7 @@ exports[`base parser Errors NESTED_COMMENT <template><!--a<!--></template> 1`] =
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a<!",
@@ -4722,9 +4809,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4740,10 +4828,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4759,7 +4846,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4767,6 +4854,7 @@ exports[`base parser Errors NESTED_COMMENT <template><!--a<!--b<!--c--></templat
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a<!--b<!--c",
@@ -4783,9 +4871,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4801,10 +4890,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4820,7 +4908,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4828,6 +4916,7 @@ exports[`base parser Errors NESTED_COMMENT <template><!--a<!--b--></template> 1`
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "a<!--b",
@@ -4844,9 +4933,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4862,10 +4952,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4881,7 +4970,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4889,6 +4978,7 @@ exports[`base parser Errors NONCHARACTER_CHARACTER_REFERENCE <template>&#x1FFFF;
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "🿿",
@@ -4906,9 +4996,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4924,10 +5015,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -4943,7 +5033,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -4951,6 +5041,7 @@ exports[`base parser Errors NONCHARACTER_CHARACTER_REFERENCE <template>&#xFFFE;<
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "οΏΎ",
@@ -4968,9 +5059,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -4986,10 +5078,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5005,7 +5096,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5013,6 +5104,7 @@ exports[`base parser Errors NULL_CHARACTER_REFERENCE <template>&#0000;</template
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "οΏ½",
@@ -5030,9 +5122,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5048,10 +5141,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5067,7 +5159,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5075,6 +5167,7 @@ exports[`base parser Errors SURROGATE_CHARACTER_REFERENCE <template>&#xD800;</te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "οΏ½",
@@ -5092,9 +5185,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5110,10 +5204,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5129,7 +5222,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5137,25 +5230,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME <template><di
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 30,
-              "line": 1,
-              "offset": 29,
-            },
-            "source": "<div a\\"bc=''></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5171,7 +5249,7 @@ Object {
                 },
               },
               "name": "a\\"bc",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "",
                 "isEmpty": true,
@@ -5188,15 +5266,33 @@ Object {
                     "offset": 20,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 30,
+              "line": 1,
+              "offset": 29,
+            },
+            "source": "<div a\\"bc=''></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5212,10 +5308,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5231,7 +5326,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5239,25 +5334,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME <template><di
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 30,
-              "line": 1,
-              "offset": 29,
-            },
-            "source": "<div a'bc=''></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5273,7 +5353,7 @@ Object {
                 },
               },
               "name": "a'bc",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "",
                 "isEmpty": true,
@@ -5290,15 +5370,33 @@ Object {
                     "offset": 20,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 30,
+              "line": 1,
+              "offset": 29,
+            },
+            "source": "<div a'bc=''></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5314,10 +5412,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5333,7 +5430,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5341,25 +5438,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME <template><di
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 30,
-              "line": 1,
-              "offset": 29,
-            },
-            "source": "<div a<bc=''></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5375,7 +5457,7 @@ Object {
                 },
               },
               "name": "a<bc",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "",
                 "isEmpty": true,
@@ -5392,15 +5474,33 @@ Object {
                     "offset": 20,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 30,
+              "line": 1,
+              "offset": 29,
+            },
+            "source": "<div a<bc=''></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5416,10 +5516,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5435,7 +5534,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5443,25 +5542,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 31,
-              "line": 1,
-              "offset": 30,
-            },
-            "source": "<div foo=bar\\"></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5477,7 +5561,7 @@ Object {
                 },
               },
               "name": "foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar\\"",
                 "isEmpty": false,
@@ -5494,15 +5578,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 31,
+              "line": 1,
+              "offset": 30,
+            },
+            "source": "<div foo=bar\\"></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5518,10 +5620,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5537,7 +5638,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5545,25 +5646,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 31,
-              "line": 1,
-              "offset": 30,
-            },
-            "source": "<div foo=bar'></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5579,7 +5665,7 @@ Object {
                 },
               },
               "name": "foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar'",
                 "isEmpty": false,
@@ -5596,15 +5682,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 31,
+              "line": 1,
+              "offset": 30,
+            },
+            "source": "<div foo=bar'></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5620,10 +5724,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5639,7 +5742,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5647,25 +5750,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 34,
-              "line": 1,
-              "offset": 33,
-            },
-            "source": "<div foo=bar<div></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5681,7 +5769,7 @@ Object {
                 },
               },
               "name": "foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar<div",
                 "isEmpty": false,
@@ -5698,15 +5786,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 34,
+              "line": 1,
+              "offset": 33,
+            },
+            "source": "<div foo=bar<div></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5722,10 +5828,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5741,7 +5846,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5749,25 +5854,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 34,
-              "line": 1,
-              "offset": 33,
-            },
-            "source": "<div foo=bar=baz></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5783,7 +5873,7 @@ Object {
                 },
               },
               "name": "foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar=baz",
                 "isEmpty": false,
@@ -5800,15 +5890,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 34,
+              "line": 1,
+              "offset": 33,
+            },
+            "source": "<div foo=bar=baz></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5824,10 +5932,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5843,7 +5950,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5851,25 +5958,10 @@ exports[`base parser Errors UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE <te
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 31,
-              "line": 1,
-              "offset": 30,
-            },
-            "source": "<div foo=bar\`></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5885,7 +5977,7 @@ Object {
                 },
               },
               "name": "foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar\`",
                 "isEmpty": false,
@@ -5902,15 +5994,33 @@ Object {
                     "offset": 19,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 31,
+              "line": 1,
+              "offset": 30,
+            },
+            "source": "<div foo=bar\`></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -5926,10 +6036,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -5945,7 +6054,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -5953,25 +6062,10 @@ exports[`base parser Errors UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME <templa
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 24,
-              "line": 1,
-              "offset": 23,
-            },
-            "source": "<div =></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -5987,15 +6081,33 @@ Object {
                 },
               },
               "name": "=",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
-          ],
+          ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 24,
+              "line": 1,
+              "offset": 23,
+            },
+            "source": "<div =></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6011,10 +6123,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6030,7 +6141,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6038,25 +6149,10 @@ exports[`base parser Errors UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME <templa
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 31,
-              "line": 1,
-              "offset": 30,
-            },
-            "source": "<div =foo=bar></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -6072,7 +6168,7 @@ Object {
                 },
               },
               "name": "=foo",
-              "type": 3,
+              "type": 5,
               "value": Object {
                 "content": "bar",
                 "isEmpty": false,
@@ -6089,15 +6185,33 @@ Object {
                     "offset": 20,
                   },
                 },
-                "type": 0,
+                "type": 2,
               },
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 31,
+              "line": 1,
+              "offset": 30,
+            },
+            "source": "<div =foo=bar></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6113,10 +6227,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6132,7 +6245,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6140,6 +6253,7 @@ exports[`base parser Errors UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME <templa
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "?xml?",
@@ -6156,9 +6270,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6174,10 +6289,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6193,7 +6307,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6201,25 +6315,10 @@ exports[`base parser Errors UNEXPECTED_SOLIDUS_IN_TAG <template><div a/b></div><
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
-          "children": Array [],
-          "isSelfClosing": false,
-          "loc": Object {
-            "end": Object {
-              "column": 26,
-              "line": 1,
-              "offset": 25,
-            },
-            "source": "<div a/b></div>",
-            "start": Object {
-              "column": 11,
-              "line": 1,
-              "offset": 10,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "attrs": Array [
             Object {
               "loc": Object {
                 "end": Object {
@@ -6235,7 +6334,7 @@ Object {
                 },
               },
               "name": "a",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
             Object {
@@ -6253,15 +6352,33 @@ Object {
                 },
               },
               "name": "b",
-              "type": 3,
+              "type": 5,
               "value": undefined,
             },
           ],
+          "children": Array [],
+          "directives": Array [],
+          "isSelfClosing": false,
+          "loc": Object {
+            "end": Object {
+              "column": 26,
+              "line": 1,
+              "offset": 25,
+            },
+            "source": "<div a/b></div>",
+            "start": Object {
+              "column": 11,
+              "line": 1,
+              "offset": 10,
+            },
+          },
+          "ns": 0,
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6277,10 +6394,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6296,7 +6412,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6304,6 +6420,7 @@ exports[`base parser Errors UNKNOWN_NAMED_CHARACTER_REFERENCE <template>&unknown
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "&unknown;",
@@ -6321,9 +6438,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6339,10 +6457,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6358,7 +6475,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6366,6 +6483,7 @@ exports[`base parser Errors X_INVALID_END_TAG <svg><![CDATA[</div>]]></svg> 1`]
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "</div>",
@@ -6383,9 +6501,10 @@ Object {
               "offset": 14,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6401,10 +6520,9 @@ Object {
         },
       },
       "ns": 1,
-      "props": Array [],
       "tag": "svg",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6420,7 +6538,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6428,6 +6546,7 @@ exports[`base parser Errors X_INVALID_END_TAG <svg><!--</div>--></svg> 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "</div>",
@@ -6444,9 +6563,10 @@ Object {
               "offset": 5,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6462,10 +6582,9 @@ Object {
         },
       },
       "ns": 1,
-      "props": Array [],
       "tag": "svg",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6481,7 +6600,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6489,7 +6608,9 @@ exports[`base parser Errors X_INVALID_END_TAG <template></div></div></template>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6505,10 +6626,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6524,7 +6644,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6532,7 +6652,9 @@ exports[`base parser Errors X_INVALID_END_TAG <template></div></template> 1`] =
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6548,10 +6670,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6567,7 +6688,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6575,6 +6696,7 @@ exports[`base parser Errors X_INVALID_END_TAG <template>{{'</div>'}}</template>
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "'</div>'",
@@ -6595,6 +6717,7 @@ Object {
           "type": 4,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6610,10 +6733,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6629,7 +6751,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6637,6 +6759,7 @@ exports[`base parser Errors X_INVALID_END_TAG <textarea></div></textarea> 1`] =
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
           "content": "</div>",
@@ -6654,9 +6777,10 @@ Object {
               "offset": 10,
             },
           },
-          "type": 0,
+          "type": 2,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6672,10 +6796,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "textarea",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6691,7 +6814,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6699,9 +6822,12 @@ exports[`base parser Errors X_MISSING_END_TAG <template><div> 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -6717,12 +6843,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6738,10 +6864,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6757,7 +6882,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6765,9 +6890,12 @@ exports[`base parser Errors X_MISSING_END_TAG <template><div></template> 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -6783,12 +6911,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "div",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6804,10 +6932,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "template",
       "tagType": 3,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -6823,7 +6950,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6846,7 +6973,7 @@ Object {
           "offset": 0,
         },
       },
-      "type": 0,
+      "type": 2,
     },
   ],
   "loc": Object {
@@ -6862,7 +6989,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6885,7 +7012,7 @@ Object {
           "offset": 0,
         },
       },
-      "type": 0,
+      "type": 2,
     },
   ],
   "loc": Object {
@@ -6901,7 +7028,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6940,7 +7067,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -6948,9 +7075,12 @@ exports[`base parser invalid html 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
+          "directives": Array [],
           "isSelfClosing": false,
           "loc": Object {
             "end": Object {
@@ -6967,12 +7097,12 @@ Object {
             },
           },
           "ns": 0,
-          "props": Array [],
           "tag": "span",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
       ],
+      "directives": Array [],
       "isSelfClosing": false,
       "loc": Object {
         "end": Object {
@@ -6990,10 +7120,9 @@ Object {
         },
       },
       "ns": 0,
-      "props": Array [],
       "tag": "div",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -7012,7 +7141,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -7020,23 +7149,9 @@ exports[`base parser self closing multiple tag 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [],
-      "isSelfClosing": true,
-      "loc": Object {
-        "end": Object {
-          "column": 37,
-          "line": 1,
-          "offset": 36,
-        },
-        "source": "<div :class=\\"{ some: condition }\\" />",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "directives": Array [
         Object {
           "arg": Object {
             "content": "class",
@@ -7089,31 +7204,32 @@ Object {
           },
           "modifiers": Array [],
           "name": "bind",
-          "type": 5,
+          "type": 6,
         },
       ],
-      "tag": "div",
-      "tagType": 0,
-      "type": 2,
-    },
-    Object {
-      "children": Array [],
       "isSelfClosing": true,
       "loc": Object {
         "end": Object {
           "column": 37,
-          "line": 2,
-          "offset": 73,
+          "line": 1,
+          "offset": 36,
         },
-        "source": "<p v-bind:style=\\"{ color: 'red' }\\"/>",
+        "source": "<div :class=\\"{ some: condition }\\" />",
         "start": Object {
           "column": 1,
-          "line": 2,
-          "offset": 37,
+          "line": 1,
+          "offset": 0,
         },
       },
       "ns": 0,
-      "props": Array [
+      "tag": "div",
+      "tagType": 0,
+      "type": 1,
+    },
+    Object {
+      "attrs": Array [],
+      "children": Array [],
+      "directives": Array [
         Object {
           "arg": Object {
             "content": "style",
@@ -7166,12 +7282,27 @@ Object {
           },
           "modifiers": Array [],
           "name": "bind",
-          "type": 5,
+          "type": 6,
         },
       ],
+      "isSelfClosing": true,
+      "loc": Object {
+        "end": Object {
+          "column": 37,
+          "line": 2,
+          "offset": 73,
+        },
+        "source": "<p v-bind:style=\\"{ color: 'red' }\\"/>",
+        "start": Object {
+          "column": 1,
+          "line": 2,
+          "offset": 37,
+        },
+      },
+      "ns": 0,
       "tag": "p",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -7188,7 +7319,7 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
 
@@ -7196,25 +7327,12 @@ exports[`base parser valid html 1`] = `
 Object {
   "children": Array [
     Object {
+      "attrs": Array [],
       "children": Array [
         Object {
+          "attrs": Array [],
           "children": Array [],
-          "isSelfClosing": true,
-          "loc": Object {
-            "end": Object {
-              "column": 38,
-              "line": 2,
-              "offset": 73,
-            },
-            "source": "<p v-bind:style=\\"{ color: 'red' }\\"/>",
-            "start": Object {
-              "column": 2,
-              "line": 2,
-              "offset": 37,
-            },
-          },
-          "ns": 0,
-          "props": Array [
+          "directives": Array [
             Object {
               "arg": Object {
                 "content": "style",
@@ -7267,12 +7385,27 @@ Object {
               },
               "modifiers": Array [],
               "name": "bind",
-              "type": 5,
+              "type": 6,
             },
           ],
+          "isSelfClosing": true,
+          "loc": Object {
+            "end": Object {
+              "column": 38,
+              "line": 2,
+              "offset": 73,
+            },
+            "source": "<p v-bind:style=\\"{ color: 'red' }\\"/>",
+            "start": Object {
+              "column": 2,
+              "line": 2,
+              "offset": 37,
+            },
+          },
+          "ns": 0,
           "tag": "p",
           "tagType": 0,
-          "type": 2,
+          "type": 1,
         },
         Object {
           "content": " a comment with <html> inside it ",
@@ -7289,28 +7422,10 @@ Object {
               "offset": 76,
             },
           },
-          "type": 1,
+          "type": 3,
         },
       ],
-      "isSelfClosing": false,
-      "loc": Object {
-        "end": Object {
-          "column": 7,
-          "line": 4,
-          "offset": 123,
-        },
-        "source": "<div :class=\\"{ some: condition }\\">
-  <p v-bind:style=\\"{ color: 'red' }\\"/>
-  <!-- a comment with <html> inside it -->
-</div>",
-        "start": Object {
-          "column": 1,
-          "line": 1,
-          "offset": 0,
-        },
-      },
-      "ns": 0,
-      "props": Array [
+      "directives": Array [
         Object {
           "arg": Object {
             "content": "class",
@@ -7363,12 +7478,30 @@ Object {
           },
           "modifiers": Array [],
           "name": "bind",
-          "type": 5,
+          "type": 6,
         },
       ],
+      "isSelfClosing": false,
+      "loc": Object {
+        "end": Object {
+          "column": 7,
+          "line": 4,
+          "offset": 123,
+        },
+        "source": "<div :class=\\"{ some: condition }\\">
+  <p v-bind:style=\\"{ color: 'red' }\\"/>
+  <!-- a comment with <html> inside it -->
+</div>",
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "ns": 0,
       "tag": "div",
       "tagType": 0,
-      "type": 2,
+      "type": 1,
     },
   ],
   "loc": Object {
@@ -7387,6 +7520,6 @@ Object {
       "offset": 0,
     },
   },
-  "type": 6,
+  "type": 0,
 }
 `;
index dbe2e334d67000330c12cdd4daaa8709255d176e..348dbd9e45005a8479c59085006ac46968bf0bbd 100644 (file)
@@ -1,8 +1,7 @@
-import { parse, ParserOptions, TextModes } from '../src/parser'
-import { ParserErrorTypes } from '../src/errorTypes'
+import { parse, ParserOptions, TextModes } from '../src/parse'
+import { ErrorCodes } from '../src/errors'
 import {
   CommentNode,
-  DirectiveNode,
   ElementNode,
   ElementTypes,
   ExpressionNode,
@@ -132,11 +131,9 @@ describe('base parser', () => {
 
     test('lonly "<" don\'t separate nodes', () => {
       const ast = parse('a < b', {
-        onError: errorCode => {
-          if (
-            errorCode !== ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME
-          ) {
-            throw new Error(`${errorCode}`)
+        onError: err => {
+          if (err.code !== ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME) {
+            throw err
           }
         }
       })
@@ -156,9 +153,9 @@ describe('base parser', () => {
 
     test('lonly "{{" don\'t separate nodes', () => {
       const ast = parse('a {{ b', {
-        onError: errorCode => {
-          if (errorCode !== ParserErrorTypes.X_MISSING_INTERPOLATION_END) {
-            throw new Error(`${errorCode}`)
+        onError: error => {
+          if (error.code !== ErrorCodes.X_MISSING_INTERPOLATION_END) {
+            throw error
           }
         }
       })
@@ -194,10 +191,12 @@ describe('base parser', () => {
           source: '&ampersand;'
         }
       })
-      expect(spy.mock.calls).toEqual([
+      expect(spy.mock.calls).toMatchObject([
         [
-          ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
-          { offset: 4, line: 1, column: 5 }
+          {
+            code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+            loc: { offset: 4, line: 1, column: 5 }
+          }
         ]
       ])
     })
@@ -212,9 +211,9 @@ describe('base parser', () => {
         }
       )
       const element = ast.children[0] as ElementNode
-      const text1 = (element.props[0] as AttributeNode).value
-      const text2 = (element.props[1] as AttributeNode).value
-      const text3 = (element.props[2] as AttributeNode).value
+      const text1 = (element.attrs[0] as AttributeNode).value
+      const text2 = (element.attrs[1] as AttributeNode).value
+      const text3 = (element.attrs[2] as AttributeNode).value
 
       expect(text1).toStrictEqual({
         type: NodeTypes.TEXT,
@@ -246,10 +245,12 @@ describe('base parser', () => {
           source: '"&amp!"'
         }
       })
-      expect(spy.mock.calls).toEqual([
+      expect(spy.mock.calls).toMatchObject([
         [
-          ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
-          { offset: 45, line: 1, column: 46 }
+          {
+            code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+            loc: { offset: 45, line: 1, column: 46 }
+          }
         ]
       ])
     })
@@ -269,10 +270,12 @@ describe('base parser', () => {
           source: '&#x86;'
         }
       })
-      expect(spy.mock.calls).toEqual([
+      expect(spy.mock.calls).toMatchObject([
         [
-          ParserErrorTypes.CONTROL_CHARACTER_REFERENCE,
-          { offset: 0, line: 1, column: 1 }
+          {
+            code: ErrorCodes.CONTROL_CHARACTER_REFERENCE,
+            loc: { offset: 0, line: 1, column: 1 }
+          }
         ]
       ])
     })
@@ -423,7 +426,8 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [],
+        attrs: [],
+        directives: [],
         isSelfClosing: false,
         children: [
           {
@@ -454,7 +458,8 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [],
+        attrs: [],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -474,7 +479,8 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [],
+        attrs: [],
+        directives: [],
         isSelfClosing: true,
         children: [],
         loc: {
@@ -496,7 +502,8 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'img',
         tagType: ElementTypes.ELEMENT,
-        props: [],
+        attrs: [],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -516,7 +523,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -528,6 +535,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -547,7 +555,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -568,6 +576,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -587,7 +596,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -608,6 +617,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -627,7 +637,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -648,6 +658,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -667,7 +678,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -688,6 +699,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -707,7 +719,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -728,6 +740,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -747,7 +760,7 @@ describe('base parser', () => {
         ns: Namespaces.HTML,
         tag: 'div',
         tagType: ElementTypes.ELEMENT,
-        props: [
+        attrs: [
           {
             type: NodeTypes.ATTRIBUTE,
             name: 'id',
@@ -816,6 +829,7 @@ describe('base parser', () => {
             }
           }
         ],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -828,8 +842,7 @@ describe('base parser', () => {
 
     test('directive with no value', () => {
       const ast = parse('<div v-if/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -847,8 +860,7 @@ describe('base parser', () => {
 
     test('directive with value', () => {
       const ast = parse('<div v-if="a"/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -875,8 +887,7 @@ describe('base parser', () => {
 
     test('directive with argument', () => {
       const ast = parse('<div v-on:click/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -911,8 +922,7 @@ describe('base parser', () => {
 
     test('directive with a modifier', () => {
       const ast = parse('<div v-on.enter/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -930,8 +940,7 @@ describe('base parser', () => {
 
     test('directive with two modifiers', () => {
       const ast = parse('<div v-on.enter.exact/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -949,8 +958,7 @@ describe('base parser', () => {
 
     test('directive with argument and modifiers', () => {
       const ast = parse('<div v-on:click.enter.exact/>')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -985,8 +993,7 @@ describe('base parser', () => {
 
     test('v-bind shorthand', () => {
       const ast = parse('<div :a=b />')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -1030,8 +1037,7 @@ describe('base parser', () => {
 
     test('v-bind shorthand with modifier', () => {
       const ast = parse('<div :a.sync=b />')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -1075,8 +1081,7 @@ describe('base parser', () => {
 
     test('v-on shorthand', () => {
       const ast = parse('<div @a=b />')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -1120,8 +1125,7 @@ describe('base parser', () => {
 
     test('v-on shorthand with modifier', () => {
       const ast = parse('<div @a.enter=b />')
-      const directive = (ast.children[0] as ElementNode)
-        .props[0] as DirectiveNode
+      const directive = (ast.children[0] as ElementNode).directives[0]
 
       expect(directive).toStrictEqual({
         type: NodeTypes.DIRECTIVE,
@@ -1235,16 +1239,29 @@ describe('base parser', () => {
       onError: spy
     })
 
-    expect(spy).toBeCalledWith(ParserErrorTypes.X_MISSING_END_TAG, {
-      offset: 13,
-      line: 3,
-      column: 1
-    })
-    expect(spy).toBeCalledWith(ParserErrorTypes.X_INVALID_END_TAG, {
-      offset: 20,
-      line: 4,
-      column: 1
-    })
+    expect(spy.mock.calls).toMatchObject([
+      [
+        {
+          code: ErrorCodes.X_MISSING_END_TAG,
+          loc: {
+            offset: 13,
+            line: 3,
+            column: 1
+          }
+        }
+      ],
+      [
+        {
+          code: ErrorCodes.X_INVALID_END_TAG,
+          loc: {
+            offset: 20,
+            line: 4,
+            column: 1
+          }
+        }
+      ]
+    ])
+
     expect(ast).toMatchSnapshot()
   })
 
@@ -1290,7 +1307,7 @@ describe('base parser', () => {
     const patterns: {
       [key: string]: Array<{
         code: string
-        errors: Array<{ type: ParserErrorTypes; loc: Position }>
+        errors: Array<{ type: ErrorCodes; loc: Position }>
         options?: Partial<ParserOptions>
       }>
     } = {
@@ -1299,7 +1316,7 @@ describe('base parser', () => {
           code: '<template><!--></template>',
           errors: [
             {
-              type: ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,
+              type: ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1308,7 +1325,7 @@ describe('base parser', () => {
           code: '<template><!---></template>',
           errors: [
             {
-              type: ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,
+              type: ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1323,8 +1340,7 @@ describe('base parser', () => {
           code: '<template>&#a;</template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
+              type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1333,8 +1349,7 @@ describe('base parser', () => {
           code: '<template>&#xg;</template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
+              type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1351,8 +1366,7 @@ describe('base parser', () => {
           code: '<template attr="&#a;"></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
+              type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -1361,8 +1375,7 @@ describe('base parser', () => {
           code: '<template attr="&#xg;"></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
+              type: ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -1381,7 +1394,7 @@ describe('base parser', () => {
           code: '<template><![CDATA[cdata]]></template>',
           errors: [
             {
-              type: ParserErrorTypes.CDATA_IN_HTML_CONTENT,
+              type: ErrorCodes.CDATA_IN_HTML_CONTENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1396,7 +1409,7 @@ describe('base parser', () => {
           code: '<template>&#1234567;</template>',
           errors: [
             {
-              type: ParserErrorTypes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE,
+              type: ErrorCodes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1407,7 +1420,7 @@ describe('base parser', () => {
           code: '<template>&#0003;</template>',
           errors: [
             {
-              type: ParserErrorTypes.CONTROL_CHARACTER_REFERENCE,
+              type: ErrorCodes.CONTROL_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1416,7 +1429,7 @@ describe('base parser', () => {
           code: '<template>&#x7F;</template>',
           errors: [
             {
-              type: ParserErrorTypes.CONTROL_CHARACTER_REFERENCE,
+              type: ErrorCodes.CONTROL_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1427,7 +1440,7 @@ describe('base parser', () => {
           code: '<template><div id="" id=""></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.DUPLICATE_ATTRIBUTE,
+              type: ErrorCodes.DUPLICATE_ATTRIBUTE,
               loc: { offset: 21, line: 1, column: 22 }
             }
           ]
@@ -1438,7 +1451,7 @@ describe('base parser', () => {
           code: '<template><div></div id=""></template>',
           errors: [
             {
-              type: ParserErrorTypes.END_TAG_WITH_ATTRIBUTES,
+              type: ErrorCodes.END_TAG_WITH_ATTRIBUTES,
               loc: { offset: 21, line: 1, column: 22 }
             }
           ]
@@ -1449,7 +1462,7 @@ describe('base parser', () => {
           code: '<template><div></div/></template>',
           errors: [
             {
-              type: ParserErrorTypes.END_TAG_WITH_TRAILING_SOLIDUS,
+              type: ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS,
               loc: { offset: 20, line: 1, column: 21 }
             }
           ]
@@ -1460,11 +1473,11 @@ describe('base parser', () => {
           code: '<template><',
           errors: [
             {
-              type: ParserErrorTypes.EOF_BEFORE_TAG_NAME,
+              type: ErrorCodes.EOF_BEFORE_TAG_NAME,
               loc: { offset: 11, line: 1, column: 12 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 11, line: 1, column: 12 }
             }
           ]
@@ -1473,11 +1486,11 @@ describe('base parser', () => {
           code: '<template></',
           errors: [
             {
-              type: ParserErrorTypes.EOF_BEFORE_TAG_NAME,
+              type: ErrorCodes.EOF_BEFORE_TAG_NAME,
               loc: { offset: 12, line: 1, column: 13 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 12, line: 1, column: 13 }
             }
           ]
@@ -1488,15 +1501,15 @@ describe('base parser', () => {
           code: '<template><svg><![CDATA[cdata',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_CDATA,
+              type: ErrorCodes.EOF_IN_CDATA,
               loc: { offset: 29, line: 1, column: 30 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 29, line: 1, column: 30 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 29, line: 1, column: 30 }
             }
           ]
@@ -1505,15 +1518,15 @@ describe('base parser', () => {
           code: '<template><svg><![CDATA[',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_CDATA,
+              type: ErrorCodes.EOF_IN_CDATA,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             }
           ]
@@ -1524,11 +1537,11 @@ describe('base parser', () => {
           code: '<template><!--comment',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_COMMENT,
+              type: ErrorCodes.EOF_IN_COMMENT,
               loc: { offset: 21, line: 1, column: 22 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 21, line: 1, column: 22 }
             }
           ]
@@ -1537,11 +1550,11 @@ describe('base parser', () => {
           code: '<template><!--',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_COMMENT,
+              type: ErrorCodes.EOF_IN_COMMENT,
               loc: { offset: 14, line: 1, column: 15 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 14, line: 1, column: 15 }
             }
           ]
@@ -1552,11 +1565,11 @@ describe('base parser', () => {
           code: '<template><!',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 12, line: 1, column: 13 }
             }
           ]
@@ -1565,11 +1578,11 @@ describe('base parser', () => {
           code: '<template><!-',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 13, line: 1, column: 14 }
             }
           ]
@@ -1578,11 +1591,11 @@ describe('base parser', () => {
           code: '<template><!abc',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -1593,11 +1606,11 @@ describe('base parser', () => {
           code: "<script><!--console.log('hello')",
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 32, line: 1, column: 33 }
             },
             {
-              type: ParserErrorTypes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,
+              type: ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,
               loc: { offset: 32, line: 1, column: 33 }
             }
           ]
@@ -1606,7 +1619,7 @@ describe('base parser', () => {
           code: "<script>console.log('hello')",
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 28, line: 1, column: 29 }
             }
           ]
@@ -1617,15 +1630,15 @@ describe('base parser', () => {
           code: '<template><div',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 14, line: 1, column: 15 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 14, line: 1, column: 15 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 14, line: 1, column: 15 }
             }
           ]
@@ -1634,15 +1647,15 @@ describe('base parser', () => {
           code: '<template><div ',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -1651,15 +1664,15 @@ describe('base parser', () => {
           code: '<template><div id',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 17, line: 1, column: 18 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 17, line: 1, column: 18 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 17, line: 1, column: 18 }
             }
           ]
@@ -1668,15 +1681,15 @@ describe('base parser', () => {
           code: '<template><div id ',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 18, line: 1, column: 19 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 18, line: 1, column: 19 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 18, line: 1, column: 19 }
             }
           ]
@@ -1685,19 +1698,19 @@ describe('base parser', () => {
           code: '<template><div id =',
           errors: [
             {
-              type: ParserErrorTypes.MISSING_ATTRIBUTE_VALUE,
+              type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,
               loc: { offset: 19, line: 1, column: 20 }
             },
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 19, line: 1, column: 20 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 19, line: 1, column: 20 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 19, line: 1, column: 20 }
             }
           ]
@@ -1706,15 +1719,15 @@ describe('base parser', () => {
           code: "<template><div id='abc",
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -1723,15 +1736,15 @@ describe('base parser', () => {
           code: '<template><div id="abc',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -1740,15 +1753,15 @@ describe('base parser', () => {
           code: "<template><div id='abc'",
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             }
           ]
@@ -1757,15 +1770,15 @@ describe('base parser', () => {
           code: '<template><div id="abc"',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             }
           ]
@@ -1774,15 +1787,15 @@ describe('base parser', () => {
           code: '<template><div id=abc',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 21, line: 1, column: 22 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 21, line: 1, column: 22 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 21, line: 1, column: 22 }
             }
           ]
@@ -1791,19 +1804,19 @@ describe('base parser', () => {
           code: "<template><div id='abc'/",
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG,
+              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             }
           ]
@@ -1812,19 +1825,19 @@ describe('base parser', () => {
           code: '<template><div id="abc"/',
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG,
+              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 24, line: 1, column: 25 }
             }
           ]
@@ -1833,19 +1846,19 @@ describe('base parser', () => {
           code: '<template><div id=abc /',
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG,
+              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,
               loc: { offset: 22, line: 1, column: 23 }
             },
             {
-              type: ParserErrorTypes.EOF_IN_TAG,
+              type: ErrorCodes.EOF_IN_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 23, line: 1, column: 24 }
             }
           ]
@@ -1856,7 +1869,7 @@ describe('base parser', () => {
           code: '<template><!--comment--!></template>',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_CLOSED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_CLOSED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1867,7 +1880,7 @@ describe('base parser', () => {
           code: '<template><!></template>',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1876,7 +1889,7 @@ describe('base parser', () => {
           code: '<template><!-></template>',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1885,7 +1898,7 @@ describe('base parser', () => {
           code: '<template><!ELEMENT br EMPTY></template>',
           errors: [
             {
-              type: ParserErrorTypes.INCORRECTLY_OPENED_COMMENT,
+              type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -1901,7 +1914,7 @@ describe('base parser', () => {
           code: '<template>a < b</template>',
           errors: [
             {
-              type: ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
+              type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
               loc: { offset: 13, line: 1, column: 14 }
             }
           ]
@@ -1910,7 +1923,7 @@ describe('base parser', () => {
           code: '<template><οΏ½></template>',
           errors: [
             {
-              type: ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
+              type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
               loc: { offset: 11, line: 1, column: 12 }
             }
           ]
@@ -1919,11 +1932,11 @@ describe('base parser', () => {
           code: '<template>a </ b</template>',
           errors: [
             {
-              type: ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
+              type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
               loc: { offset: 14, line: 1, column: 15 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 27, line: 1, column: 28 }
             }
           ]
@@ -1932,7 +1945,7 @@ describe('base parser', () => {
           code: '<template></οΏ½></template>',
           errors: [
             {
-              type: ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
+              type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
               loc: { offset: 12, line: 1, column: 13 }
             }
           ]
@@ -1948,7 +1961,7 @@ describe('base parser', () => {
           code: '<template><div id=></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.MISSING_ATTRIBUTE_VALUE,
+              type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,
               loc: { offset: 18, line: 1, column: 19 }
             }
           ]
@@ -1957,7 +1970,7 @@ describe('base parser', () => {
           code: '<template><div id= ></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.MISSING_ATTRIBUTE_VALUE,
+              type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,
               loc: { offset: 19, line: 1, column: 20 }
             }
           ]
@@ -1972,7 +1985,7 @@ describe('base parser', () => {
           code: '<template></></template>',
           errors: [
             {
-              type: ParserErrorTypes.MISSING_END_TAG_NAME,
+              type: ErrorCodes.MISSING_END_TAG_NAME,
               loc: { offset: 12, line: 1, column: 13 }
             }
           ]
@@ -1984,8 +1997,7 @@ describe('base parser', () => {
           options: { namedCharacterReferences: { amp: '&' } },
           errors: [
             {
-              type:
-                ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+              type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
               loc: { offset: 14, line: 1, column: 15 }
             }
           ]
@@ -1994,8 +2006,7 @@ describe('base parser', () => {
           code: '<template>&#40</template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+              type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
               loc: { offset: 14, line: 1, column: 15 }
             }
           ]
@@ -2004,8 +2015,7 @@ describe('base parser', () => {
           code: '<template>&#x40</template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+              type: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2016,7 +2026,7 @@ describe('base parser', () => {
           code: '<template><div id="foo"class="bar"></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,
+              type: ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,
               loc: { offset: 23, line: 1, column: 24 }
             }
           ]
@@ -2033,7 +2043,7 @@ describe('base parser', () => {
           code: '<template><!--a<!--b--></template>',
           errors: [
             {
-              type: ParserErrorTypes.NESTED_COMMENT,
+              type: ErrorCodes.NESTED_COMMENT,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2042,11 +2052,11 @@ describe('base parser', () => {
           code: '<template><!--a<!--b<!--c--></template>',
           errors: [
             {
-              type: ParserErrorTypes.NESTED_COMMENT,
+              type: ErrorCodes.NESTED_COMMENT,
               loc: { offset: 15, line: 1, column: 16 }
             },
             {
-              type: ParserErrorTypes.NESTED_COMMENT,
+              type: ErrorCodes.NESTED_COMMENT,
               loc: { offset: 20, line: 1, column: 21 }
             }
           ]
@@ -2059,11 +2069,11 @@ describe('base parser', () => {
           code: '<template><!--a<!--',
           errors: [
             {
-              type: ParserErrorTypes.EOF_IN_COMMENT,
+              type: ErrorCodes.EOF_IN_COMMENT,
               loc: { offset: 19, line: 1, column: 20 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 19, line: 1, column: 20 }
             }
           ]
@@ -2074,7 +2084,7 @@ describe('base parser', () => {
           code: '<template>&#xFFFE;</template>',
           errors: [
             {
-              type: ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE,
+              type: ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2083,7 +2093,7 @@ describe('base parser', () => {
           code: '<template>&#x1FFFF;</template>',
           errors: [
             {
-              type: ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE,
+              type: ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2094,7 +2104,7 @@ describe('base parser', () => {
           code: '<template>&#0000;</template>',
           errors: [
             {
-              type: ParserErrorTypes.NULL_CHARACTER_REFERENCE,
+              type: ErrorCodes.NULL_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2105,7 +2115,7 @@ describe('base parser', () => {
           code: '<template>&#xD800;</template>',
           errors: [
             {
-              type: ParserErrorTypes.SURROGATE_CHARACTER_REFERENCE,
+              type: ErrorCodes.SURROGATE_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2116,7 +2126,7 @@ describe('base parser', () => {
           code: "<template><div a\"bc=''></div></template>",
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -2125,7 +2135,7 @@ describe('base parser', () => {
           code: "<template><div a'bc=''></div></template>",
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -2134,7 +2144,7 @@ describe('base parser', () => {
           code: "<template><div a<bc=''></div></template>",
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -2145,8 +2155,7 @@ describe('base parser', () => {
           code: '<template><div foo=bar"></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -2155,8 +2164,7 @@ describe('base parser', () => {
           code: "<template><div foo=bar'></div></template>",
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -2165,8 +2173,7 @@ describe('base parser', () => {
           code: '<template><div foo=bar<div></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -2175,8 +2182,7 @@ describe('base parser', () => {
           code: '<template><div foo=bar=baz></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -2185,8 +2191,7 @@ describe('base parser', () => {
           code: '<template><div foo=bar`></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
               loc: { offset: 22, line: 1, column: 23 }
             }
           ]
@@ -2197,8 +2202,7 @@ describe('base parser', () => {
           code: '<template><div =foo=bar></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
+              type: ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2207,8 +2211,7 @@ describe('base parser', () => {
           code: '<template><div =></div></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
+              type: ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2219,8 +2222,7 @@ describe('base parser', () => {
           code: '<template><?xml?></template>',
           errors: [
             {
-              type:
-                ParserErrorTypes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
+              type: ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
               loc: { offset: 11, line: 1, column: 12 }
             }
           ]
@@ -2231,7 +2233,7 @@ describe('base parser', () => {
           code: '<template><div a/b></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG,
+              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -2242,7 +2244,7 @@ describe('base parser', () => {
           code: '<template>&unknown;</template>',
           errors: [
             {
-              type: ParserErrorTypes.UNKNOWN_NAMED_CHARACTER_REFERENCE,
+              type: ErrorCodes.UNKNOWN_NAMED_CHARACTER_REFERENCE,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2253,7 +2255,7 @@ describe('base parser', () => {
           code: '<template></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.X_INVALID_END_TAG,
+              type: ErrorCodes.X_INVALID_END_TAG,
               loc: { offset: 10, line: 1, column: 11 }
             }
           ]
@@ -2262,11 +2264,11 @@ describe('base parser', () => {
           code: '<template></div></div></template>',
           errors: [
             {
-              type: ParserErrorTypes.X_INVALID_END_TAG,
+              type: ErrorCodes.X_INVALID_END_TAG,
               loc: { offset: 10, line: 1, column: 11 }
             },
             {
-              type: ParserErrorTypes.X_INVALID_END_TAG,
+              type: ErrorCodes.X_INVALID_END_TAG,
               loc: { offset: 16, line: 1, column: 17 }
             }
           ]
@@ -2293,7 +2295,7 @@ describe('base parser', () => {
           code: '<template><div></template>',
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2302,11 +2304,11 @@ describe('base parser', () => {
           code: '<template><div>',
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             },
             {
-              type: ParserErrorTypes.X_MISSING_END_TAG,
+              type: ErrorCodes.X_MISSING_END_TAG,
               loc: { offset: 15, line: 1, column: 16 }
             }
           ]
@@ -2317,7 +2319,7 @@ describe('base parser', () => {
           code: '{{ foo',
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_INTERPOLATION_END,
+              type: ErrorCodes.X_MISSING_INTERPOLATION_END,
               loc: { offset: 0, line: 1, column: 1 }
             }
           ]
@@ -2326,7 +2328,7 @@ describe('base parser', () => {
           code: '{{',
           errors: [
             {
-              type: ParserErrorTypes.X_MISSING_INTERPOLATION_END,
+              type: ErrorCodes.X_MISSING_INTERPOLATION_END,
               loc: { offset: 0, line: 1, column: 1 }
             }
           ]
@@ -2371,9 +2373,12 @@ describe('base parser', () => {
                 onError: spy
               })
 
-              expect(spy.mock.calls).toEqual(
-                errors.map(({ type, loc }) => [type, loc])
-              )
+              expect(
+                spy.mock.calls.map(([err]) => ({
+                  type: err.code,
+                  loc: err.loc
+                }))
+              ).toMatchObject(errors)
               expect(ast).toMatchSnapshot()
             }
           )
index 72049ba48c86a86b2d6388b71e3cfaee30153a68..b743e86f276fbf2903a1aed4a3982c20b8a9dc33 100644 (file)
@@ -8,20 +8,23 @@ export const enum Namespaces {
 }
 
 export const enum NodeTypes {
+  ROOT,
+  ELEMENT,
   TEXT,
   COMMENT,
-  ELEMENT,
-  ATTRIBUTE,
   EXPRESSION,
+  ATTRIBUTE,
   DIRECTIVE,
-  ROOT
+  IF,
+  IF_BRANCH,
+  FOR
 }
 
 export const enum ElementTypes {
   ELEMENT,
   COMPONENT,
-  SLOT, // slot
-  TEMPLATE // template, component
+  SLOT,
+  TEMPLATE
 }
 
 export interface Node {
@@ -29,9 +32,18 @@ export interface Node {
   loc: SourceLocation
 }
 
+export type ParentNode = RootNode | ElementNode | IfBranchNode | ForNode
+export type ChildNode =
+  | ElementNode
+  | ExpressionNode
+  | TextNode
+  | CommentNode
+  | IfNode
+  | ForNode
+
 export interface RootNode extends Node {
   type: NodeTypes.ROOT
-  children: Array<ElementNode | ExpressionNode | TextNode | CommentNode>
+  children: ChildNode[]
 }
 
 export interface ElementNode extends Node {
@@ -40,8 +52,9 @@ export interface ElementNode extends Node {
   tag: string
   tagType: ElementTypes
   isSelfClosing: boolean
-  props: Array<AttributeNode | DirectiveNode>
-  children: Array<ElementNode | ExpressionNode | TextNode | CommentNode>
+  attrs: AttributeNode[]
+  directives: DirectiveNode[]
+  children: ChildNode[]
 }
 
 export interface TextNode extends Node {
@@ -75,8 +88,28 @@ export interface ExpressionNode extends Node {
   isStatic: boolean
 }
 
+export interface IfNode extends Node {
+  type: NodeTypes.IF
+  branches: IfBranchNode[]
+}
+
+export interface IfBranchNode extends Node {
+  type: NodeTypes.IF_BRANCH
+  condition: ExpressionNode | undefined // else
+  children: ChildNode[]
+}
+
+export interface ForNode extends Node {
+  type: NodeTypes.FOR
+  source: ExpressionNode
+  valueAlias: ExpressionNode
+  keyAlias: ExpressionNode
+  objectIndexAlias: ExpressionNode
+  children: ChildNode[]
+}
+
 export interface Position {
-  offset: number // from start of file
+  offset: number // from start of file (in SFCs)
   line: number
   column: number
 }
index 70b786d12ed055a08b57f5cf47f717bf6a266301..61fae264d1808b3e4b48c02521d51a9991a3a264 100644 (file)
@@ -1 +1,56 @@
-// TODO
+import { createDirectiveTransform } from '../transform'
+import {
+  NodeTypes,
+  ElementTypes,
+  ElementNode,
+  DirectiveNode,
+  IfBranchNode
+} from '../ast'
+import { createCompilerError, ErrorCodes } from '../errors'
+
+export const transformIf = createDirectiveTransform(
+  /^(if|else|else-if)$/,
+  (node, dir, context) => {
+    if (dir.name === 'if') {
+      context.replaceNode({
+        type: NodeTypes.IF,
+        loc: node.loc,
+        branches: [createIfBranch(node, dir)]
+      })
+    } else {
+      // locate the adjacent v-if
+      const siblings = context.parent.children
+      let i = context.childIndex
+      while (i--) {
+        const sibling = siblings[i]
+        if (sibling.type === NodeTypes.COMMENT) {
+          continue
+        }
+        if (sibling.type === NodeTypes.IF) {
+          // move the node to the if node's branches
+          context.removeNode()
+          sibling.branches.push(createIfBranch(node, dir))
+        } else {
+          context.onError(
+            createCompilerError(
+              dir.name === 'else'
+                ? ErrorCodes.X_ELSE_NO_ADJACENT_IF
+                : ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
+              node.loc.start
+            )
+          )
+        }
+        break
+      }
+    }
+  }
+)
+
+function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
+  return {
+    type: NodeTypes.IF_BRANCH,
+    loc: node.loc,
+    condition: dir.name === 'else' ? undefined : dir.exp,
+    children: node.tagType === ElementTypes.TEMPLATE ? node.children : [node]
+  }
+}
diff --git a/packages/compiler-core/src/errorTypes.ts b/packages/compiler-core/src/errorTypes.ts
deleted file mode 100644 (file)
index b449e0e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-export const enum ParserErrorTypes {
-  ABRUPT_CLOSING_OF_EMPTY_COMMENT,
-  ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
-  CDATA_IN_HTML_CONTENT,
-  CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE,
-  CONTROL_CHARACTER_REFERENCE,
-  DUPLICATE_ATTRIBUTE,
-  END_TAG_WITH_ATTRIBUTES,
-  END_TAG_WITH_TRAILING_SOLIDUS,
-  EOF_BEFORE_TAG_NAME,
-  EOF_IN_CDATA,
-  EOF_IN_COMMENT,
-  EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,
-  EOF_IN_TAG,
-  INCORRECTLY_CLOSED_COMMENT,
-  INCORRECTLY_OPENED_COMMENT,
-  INVALID_FIRST_CHARACTER_OF_TAG_NAME,
-  MISSING_ATTRIBUTE_VALUE,
-  MISSING_END_TAG_NAME,
-  MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
-  MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,
-  NESTED_COMMENT,
-  NONCHARACTER_CHARACTER_REFERENCE,
-  NULL_CHARACTER_REFERENCE,
-  SURROGATE_CHARACTER_REFERENCE,
-  UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
-  UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
-  UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
-  UNEXPECTED_NULL_CHARACTER,
-  UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
-  UNEXPECTED_SOLIDUS_IN_TAG,
-  UNKNOWN_NAMED_CHARACTER_REFERENCE,
-  X_INVALID_END_TAG,
-  X_MISSING_END_TAG,
-  X_MISSING_INTERPOLATION_END,
-  X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END
-}
-
-export const errorMessages: { [code: number]: string } = {
-  [ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',
-  [ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE]:
-    'Illegal numeric character reference: invalid character.',
-  [ParserErrorTypes.CDATA_IN_HTML_CONTENT]:
-    'CDATA section is allowed only in XML context.',
-  [ParserErrorTypes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE]:
-    'Illegal numeric character reference: too big.',
-  [ParserErrorTypes.CONTROL_CHARACTER_REFERENCE]:
-    'Illegal numeric character reference: control character.',
-  [ParserErrorTypes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',
-  [ParserErrorTypes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',
-  [ParserErrorTypes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.",
-  [ParserErrorTypes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',
-  [ParserErrorTypes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',
-  [ParserErrorTypes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',
-  [ParserErrorTypes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT]:
-    'Unexpected EOF in script.',
-  [ParserErrorTypes.EOF_IN_TAG]: 'Unexpected EOF in tag.',
-  [ParserErrorTypes.INCORRECTLY_CLOSED_COMMENT]: 'Incorrectly closed comment.',
-  [ParserErrorTypes.INCORRECTLY_OPENED_COMMENT]: 'Incorrectly opened comment.',
-  [ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME]:
-    "Illegal tag name. Use '&lt;' to print '<'.",
-  [ParserErrorTypes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.',
-  [ParserErrorTypes.MISSING_END_TAG_NAME]: 'End tag name was expected.',
-  [ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE]:
-    'Semicolon was expected.',
-  [ParserErrorTypes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]:
-    'Whitespace was expected.',
-  [ParserErrorTypes.NESTED_COMMENT]: "Unexpected '<!--' in comment.",
-  [ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE]:
-    'Illegal numeric character reference: non character.',
-  [ParserErrorTypes.NULL_CHARACTER_REFERENCE]:
-    'Illegal numeric character reference: null character.',
-  [ParserErrorTypes.SURROGATE_CHARACTER_REFERENCE]:
-    'Illegal numeric character reference: non-pair surrogate.',
-  [ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME]:
-    'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
-  [ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE]:
-    'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
-  [ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME]:
-    "Attribute name cannot start with '='.",
-  [ParserErrorTypes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME]:
-    "'<?' is allowed only in XML context.",
-  [ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG]: "Illegal '/' in tags.",
-  [ParserErrorTypes.UNKNOWN_NAMED_CHARACTER_REFERENCE]: 'Unknown entity name.',
-  [ParserErrorTypes.X_INVALID_END_TAG]: 'Invalid end tag.',
-  [ParserErrorTypes.X_MISSING_END_TAG]: 'End tag was not found.',
-  [ParserErrorTypes.X_MISSING_INTERPOLATION_END]:
-    'Interpolation end sign was not found.'
-}
diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts
new file mode 100644 (file)
index 0000000..735f20c
--- /dev/null
@@ -0,0 +1,120 @@
+import { Position } from './ast'
+
+export interface CompilerError extends SyntaxError {
+  code: ErrorCodes
+  loc: Position
+}
+
+export function createCompilerError(
+  code: ErrorCodes,
+  loc: Position
+): CompilerError {
+  const error = new SyntaxError(
+    `${__DEV__ || !__BROWSER__ ? errorMessages[code] : code} (${loc.line}:${
+      loc.column
+    })`
+  ) as CompilerError
+  error.code = code
+  error.loc = loc
+  return error
+}
+
+export const enum ErrorCodes {
+  // parse errors
+  ABRUPT_CLOSING_OF_EMPTY_COMMENT,
+  ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE,
+  CDATA_IN_HTML_CONTENT,
+  CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE,
+  CONTROL_CHARACTER_REFERENCE,
+  DUPLICATE_ATTRIBUTE,
+  END_TAG_WITH_ATTRIBUTES,
+  END_TAG_WITH_TRAILING_SOLIDUS,
+  EOF_BEFORE_TAG_NAME,
+  EOF_IN_CDATA,
+  EOF_IN_COMMENT,
+  EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,
+  EOF_IN_TAG,
+  INCORRECTLY_CLOSED_COMMENT,
+  INCORRECTLY_OPENED_COMMENT,
+  INVALID_FIRST_CHARACTER_OF_TAG_NAME,
+  MISSING_ATTRIBUTE_VALUE,
+  MISSING_END_TAG_NAME,
+  MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
+  MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,
+  NESTED_COMMENT,
+  NONCHARACTER_CHARACTER_REFERENCE,
+  NULL_CHARACTER_REFERENCE,
+  SURROGATE_CHARACTER_REFERENCE,
+  UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
+  UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+  UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
+  UNEXPECTED_NULL_CHARACTER,
+  UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
+  UNEXPECTED_SOLIDUS_IN_TAG,
+  UNKNOWN_NAMED_CHARACTER_REFERENCE,
+  X_INVALID_END_TAG,
+  X_MISSING_END_TAG,
+  X_MISSING_INTERPOLATION_END,
+  X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
+
+  // transform errors
+  X_ELSE_IF_NO_ADJACENT_IF,
+  X_ELSE_NO_ADJACENT_IF
+}
+
+export const errorMessages: { [code: number]: string } = {
+  // parse errors
+  [ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',
+  [ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE]:
+    'Illegal numeric character reference: invalid character.',
+  [ErrorCodes.CDATA_IN_HTML_CONTENT]:
+    'CDATA section is allowed only in XML context.',
+  [ErrorCodes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE]:
+    'Illegal numeric character reference: too big.',
+  [ErrorCodes.CONTROL_CHARACTER_REFERENCE]:
+    'Illegal numeric character reference: control character.',
+  [ErrorCodes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',
+  [ErrorCodes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',
+  [ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.",
+  [ErrorCodes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',
+  [ErrorCodes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',
+  [ErrorCodes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',
+  [ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT]:
+    'Unexpected EOF in script.',
+  [ErrorCodes.EOF_IN_TAG]: 'Unexpected EOF in tag.',
+  [ErrorCodes.INCORRECTLY_CLOSED_COMMENT]: 'Incorrectly closed comment.',
+  [ErrorCodes.INCORRECTLY_OPENED_COMMENT]: 'Incorrectly opened comment.',
+  [ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME]:
+    "Illegal tag name. Use '&lt;' to print '<'.",
+  [ErrorCodes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.',
+  [ErrorCodes.MISSING_END_TAG_NAME]: 'End tag name was expected.',
+  [ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE]:
+    'Semicolon was expected.',
+  [ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]:
+    'Whitespace was expected.',
+  [ErrorCodes.NESTED_COMMENT]: "Unexpected '<!--' in comment.",
+  [ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE]:
+    'Illegal numeric character reference: non character.',
+  [ErrorCodes.NULL_CHARACTER_REFERENCE]:
+    'Illegal numeric character reference: null character.',
+  [ErrorCodes.SURROGATE_CHARACTER_REFERENCE]:
+    'Illegal numeric character reference: non-pair surrogate.',
+  [ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME]:
+    'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
+  [ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE]:
+    'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
+  [ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME]:
+    "Attribute name cannot start with '='.",
+  [ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME]:
+    "'<?' is allowed only in XML context.",
+  [ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG]: "Illegal '/' in tags.",
+  [ErrorCodes.UNKNOWN_NAMED_CHARACTER_REFERENCE]: 'Unknown entity name.',
+  [ErrorCodes.X_INVALID_END_TAG]: 'Invalid end tag.',
+  [ErrorCodes.X_MISSING_END_TAG]: 'End tag was not found.',
+  [ErrorCodes.X_MISSING_INTERPOLATION_END]:
+    'Interpolation end sign was not found.',
+
+  // transform errors
+  [ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF]: `v-else-if has no adjacent v-if`,
+  [ErrorCodes.X_ELSE_NO_ADJACENT_IF]: `v-else has no adjacent v-if`
+}
index 6cd157a49c74f08f368747b08a8b17bd797a5704..d2f3542f0cf871604536a491a40b853c75d03be5 100644 (file)
@@ -1,3 +1,6 @@
-export { parse, ParserOptions, TextModes } from './parser'
-export { ParserErrorTypes } from './errorTypes'
+export { parse, ParserOptions, TextModes } from './parse'
+export { transform, Transform, TransformContext } from './transform'
+export { ErrorCodes } from './errors'
 export * from './ast'
+
+export { transformIf } from './directives/vIf'
similarity index 86%
rename from packages/compiler-core/src/parser.ts
rename to packages/compiler-core/src/parse.ts
index 0b45b5c609cfae0d69a0e3481f975c22fcce6f72..838b7910295a844a0813f8e5bfcaf96a236af846 100644 (file)
@@ -1,4 +1,4 @@
-import { ParserErrorTypes, errorMessages } from './errorTypes'
+import { ErrorCodes, CompilerError, createCompilerError } from './errors'
 import {
   Namespace,
   Namespaces,
@@ -12,7 +12,8 @@ import {
   Position,
   RootNode,
   SourceLocation,
-  TextNode
+  TextNode,
+  ChildNode
 } from './ast'
 
 export interface ParserOptions {
@@ -26,7 +27,7 @@ export interface ParserOptions {
   // The full set is https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
   namedCharacterReferences?: { [name: string]: string | undefined }
 
-  onError?: (type: ParserErrorTypes, loc: Position) => void
+  onError?: (error: CompilerError) => void
 }
 
 export const defaultParserOptions: Required<ParserOptions> = {
@@ -42,14 +43,7 @@ export const defaultParserOptions: Required<ParserOptions> = {
     'apos;': "'",
     'quot;': '"'
   },
-  onError(code: ParserErrorTypes, loc: Position): void {
-    const error: any = new SyntaxError(
-      `${__DEV__ || !__BROWSER__ ? errorMessages[code] : code} (${loc.line}:${
-        loc.column
-      })`
-    )
-    error.code = code
-    error.loc = loc
+  onError(error: CompilerError): void {
     throw error
   }
 }
@@ -106,10 +100,10 @@ function parseChildren(
   context: ParserContext,
   mode: TextModes,
   ancestors: ElementNode[]
-): RootNode['children'] {
+): ChildNode[] {
   const parent = last(ancestors)
   const ns = parent ? parent.ns : Namespaces.HTML
-  const nodes: RootNode['children'] = []
+  const nodes: ChildNode[] = []
 
   while (!isEnd(context, mode, ancestors)) {
     __DEV__ && assert(context.source.length > 0)
@@ -122,7 +116,7 @@ function parseChildren(
     } else if (mode === TextModes.DATA && s[0] === '<') {
       // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
       if (s.length === 1) {
-        emitError(context, ParserErrorTypes.EOF_BEFORE_TAG_NAME, 1)
+        emitError(context, ErrorCodes.EOF_BEFORE_TAG_NAME, 1)
       } else if (s[1] === '!') {
         // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state
         if (startsWith(s, '<!--')) {
@@ -134,31 +128,27 @@ function parseChildren(
           if (ns !== Namespaces.HTML) {
             node = parseCDATA(context, ancestors)
           } else {
-            emitError(context, ParserErrorTypes.CDATA_IN_HTML_CONTENT)
+            emitError(context, ErrorCodes.CDATA_IN_HTML_CONTENT)
             node = parseBogusComment(context)
           }
         } else {
-          emitError(context, ParserErrorTypes.INCORRECTLY_OPENED_COMMENT)
+          emitError(context, ErrorCodes.INCORRECTLY_OPENED_COMMENT)
           node = parseBogusComment(context)
         }
       } else if (s[1] === '/') {
         // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state
         if (s.length === 2) {
-          emitError(context, ParserErrorTypes.EOF_BEFORE_TAG_NAME, 2)
+          emitError(context, ErrorCodes.EOF_BEFORE_TAG_NAME, 2)
         } else if (s[2] === '>') {
-          emitError(context, ParserErrorTypes.MISSING_END_TAG_NAME, 2)
+          emitError(context, ErrorCodes.MISSING_END_TAG_NAME, 2)
           advanceBy(context, 3)
           continue
         } else if (/[a-z]/i.test(s[2])) {
-          emitError(context, ParserErrorTypes.X_INVALID_END_TAG)
+          emitError(context, ErrorCodes.X_INVALID_END_TAG)
           parseTag(context, TagType.End, parent)
           continue
         } else {
-          emitError(
-            context,
-            ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
-            2
-          )
+          emitError(context, ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME, 2)
           node = parseBogusComment(context)
         }
       } else if (/[a-z]/i.test(s[1])) {
@@ -166,16 +156,12 @@ function parseChildren(
       } else if (s[1] === '?') {
         emitError(
           context,
-          ParserErrorTypes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
+          ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
           1
         )
         node = parseBogusComment(context)
       } else {
-        emitError(
-          context,
-          ParserErrorTypes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,
-          1
-        )
+        emitError(context, ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME, 1)
       }
     }
     if (!node) {
@@ -183,7 +169,9 @@ function parseChildren(
     }
 
     if (Array.isArray(node)) {
-      node.forEach(pushNode.bind(null, context, nodes))
+      for (let i = 0; i < node.length; i++) {
+        pushNode(context, nodes, node[i])
+      }
     } else {
       pushNode(context, nodes, node)
     }
@@ -194,8 +182,8 @@ function parseChildren(
 
 function pushNode(
   context: ParserContext,
-  nodes: RootNode['children'],
-  node: RootNode['children'][0]
+  nodes: ChildNode[],
+  node: ChildNode
 ): void {
   if (context.ignoreSpaces && node.type === NodeTypes.TEXT && node.isEmpty) {
     return
@@ -222,7 +210,7 @@ function pushNode(
 function parseCDATA(
   context: ParserContext,
   ancestors: ElementNode[]
-): RootNode['children'] {
+): ChildNode[] {
   __DEV__ &&
     assert(last(ancestors) == null || last(ancestors)!.ns !== Namespaces.HTML)
   __DEV__ && assert(startsWith(context.source, '<![CDATA['))
@@ -230,7 +218,7 @@ function parseCDATA(
   advanceBy(context, 9)
   const nodes = parseChildren(context, TextModes.CDATA, ancestors)
   if (context.source.length === 0) {
-    emitError(context, ParserErrorTypes.EOF_IN_CDATA)
+    emitError(context, ErrorCodes.EOF_IN_CDATA)
   } else {
     __DEV__ && assert(startsWith(context.source, ']]>'))
     advanceBy(context, 3)
@@ -250,13 +238,13 @@ function parseComment(context: ParserContext): CommentNode {
   if (!match) {
     content = context.source.slice(4)
     advanceBy(context, context.source.length)
-    emitError(context, ParserErrorTypes.EOF_IN_COMMENT)
+    emitError(context, ErrorCodes.EOF_IN_COMMENT)
   } else {
     if (match.index <= 3) {
-      emitError(context, ParserErrorTypes.ABRUPT_CLOSING_OF_EMPTY_COMMENT)
+      emitError(context, ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT)
     }
     if (match[1]) {
-      emitError(context, ParserErrorTypes.INCORRECTLY_CLOSED_COMMENT)
+      emitError(context, ErrorCodes.INCORRECTLY_CLOSED_COMMENT)
     }
     content = context.source.slice(4, match.index)
 
@@ -267,7 +255,7 @@ function parseComment(context: ParserContext): CommentNode {
     while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {
       advanceBy(context, nestedIndex - prevIndex + 1)
       if (nestedIndex + 4 < s.length) {
-        emitError(context, ParserErrorTypes.NESTED_COMMENT)
+        emitError(context, ErrorCodes.NESTED_COMMENT)
       }
       prevIndex = nestedIndex + 1
     }
@@ -333,14 +321,11 @@ function parseElement(
   if (startsWithEndTagOpen(context.source, element.tag)) {
     parseTag(context, TagType.End, parent)
   } else {
-    emitError(context, ParserErrorTypes.X_MISSING_END_TAG)
+    emitError(context, ErrorCodes.X_MISSING_END_TAG)
     if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {
       const first = children[0]
       if (first && startsWith(first.loc.source, '<!--')) {
-        emitError(
-          context,
-          ParserErrorTypes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT
-        )
+        emitError(context, ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT)
       }
     }
   }
@@ -372,7 +357,8 @@ function parseTag(
   const start = getCursor(context)
   const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source)!
   const tag = match[1]
-  const props = []
+  const attrs = []
+  const directives = []
   const ns = context.getNamespace(tag, parent)
 
   advanceBy(context, match[0].length)
@@ -386,22 +372,26 @@ function parseTag(
     !startsWith(context.source, '/>')
   ) {
     if (startsWith(context.source, '/')) {
-      emitError(context, ParserErrorTypes.UNEXPECTED_SOLIDUS_IN_TAG)
+      emitError(context, ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG)
       advanceBy(context, 1)
       advanceSpaces(context)
       continue
     }
     if (type === TagType.End) {
-      emitError(context, ParserErrorTypes.END_TAG_WITH_ATTRIBUTES)
+      emitError(context, ErrorCodes.END_TAG_WITH_ATTRIBUTES)
     }
 
     const attr = parseAttribute(context, attributeNames)
     if (type === TagType.Start) {
-      props.push(attr)
+      if (attr.type === NodeTypes.DIRECTIVE) {
+        directives.push(attr)
+      } else {
+        attrs.push(attr)
+      }
     }
 
     if (/^[^\t\r\n\f />]/.test(context.source)) {
-      emitError(context, ParserErrorTypes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES)
+      emitError(context, ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES)
     }
     advanceSpaces(context)
   }
@@ -409,11 +399,11 @@ function parseTag(
   // Tag close.
   let isSelfClosing = false
   if (context.source.length === 0) {
-    emitError(context, ParserErrorTypes.EOF_IN_TAG)
+    emitError(context, ErrorCodes.EOF_IN_TAG)
   } else {
     isSelfClosing = startsWith(context.source, '/>')
     if (type === TagType.End && isSelfClosing) {
-      emitError(context, ParserErrorTypes.END_TAG_WITH_TRAILING_SOLIDUS)
+      emitError(context, ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS)
     }
     advanceBy(context, isSelfClosing ? 2 : 1)
   }
@@ -429,7 +419,8 @@ function parseTag(
     ns,
     tag,
     tagType,
-    props,
+    attrs,
+    directives,
     isSelfClosing,
     children: [],
     loc: getSelection(context, start)
@@ -448,15 +439,12 @@ function parseAttribute(
   const name = match[0]
 
   if (nameSet.has(name)) {
-    emitError(context, ParserErrorTypes.DUPLICATE_ATTRIBUTE)
+    emitError(context, ErrorCodes.DUPLICATE_ATTRIBUTE)
   }
   nameSet.add(name)
 
   if (name[0] === '=') {
-    emitError(
-      context,
-      ParserErrorTypes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME
-    )
+    emitError(context, ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME)
   }
   {
     const pattern = /["'<]/g
@@ -464,7 +452,7 @@ function parseAttribute(
     while ((m = pattern.exec(name)) !== null) {
       emitError(
         context,
-        ParserErrorTypes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
+        ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
         m.index
       )
     }
@@ -480,7 +468,7 @@ function parseAttribute(
     advanceSpaces(context)
     value = parseAttributeValue(context)
     if (!value) {
-      emitError(context, ParserErrorTypes.MISSING_ATTRIBUTE_VALUE)
+      emitError(context, ErrorCodes.MISSING_ATTRIBUTE_VALUE)
     }
   }
   const loc = getSelection(context, start)
@@ -508,7 +496,7 @@ function parseAttribute(
         if (!content.endsWith(']')) {
           emitError(
             context,
-            ParserErrorTypes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END
+            ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END
           )
         }
 
@@ -590,7 +578,7 @@ function parseAttributeValue(
     while ((m = unexpectedChars.exec(match[0])) !== null) {
       emitError(
         context,
-        ParserErrorTypes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
+        ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
         m.index
       )
     }
@@ -609,7 +597,7 @@ function parseInterpolation(
 
   const closeIndex = context.source.indexOf(close, open.length)
   if (closeIndex === -1) {
-    emitError(context, ParserErrorTypes.X_MISSING_INTERPOLATION_END)
+    emitError(context, ErrorCodes.X_MISSING_INTERPOLATION_END)
     return undefined
   }
 
@@ -712,12 +700,12 @@ function parseTextData(
             if (!semi) {
               emitError(
                 context,
-                ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE
+                ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE
               )
             }
           }
         } else {
-          emitError(context, ParserErrorTypes.UNKNOWN_NAMED_CHARACTER_REFERENCE)
+          emitError(context, ErrorCodes.UNKNOWN_NAMED_CHARACTER_REFERENCE)
           text += '&'
           text += name
           advanceBy(context, 1 + name.length)
@@ -735,33 +723,33 @@ function parseTextData(
         text += head[0]
         emitError(
           context,
-          ParserErrorTypes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE
+          ErrorCodes.ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE
         )
         advanceBy(context, head[0].length)
       } else {
         // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
         let cp = Number.parseInt(body[1], hex ? 16 : 10)
         if (cp === 0) {
-          emitError(context, ParserErrorTypes.NULL_CHARACTER_REFERENCE)
+          emitError(context, ErrorCodes.NULL_CHARACTER_REFERENCE)
           cp = 0xfffd
         } else if (cp > 0x10ffff) {
           emitError(
             context,
-            ParserErrorTypes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE
+            ErrorCodes.CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE
           )
           cp = 0xfffd
         } else if (cp >= 0xd800 && cp <= 0xdfff) {
-          emitError(context, ParserErrorTypes.SURROGATE_CHARACTER_REFERENCE)
+          emitError(context, ErrorCodes.SURROGATE_CHARACTER_REFERENCE)
           cp = 0xfffd
         } else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {
-          emitError(context, ParserErrorTypes.NONCHARACTER_CHARACTER_REFERENCE)
+          emitError(context, ErrorCodes.NONCHARACTER_CHARACTER_REFERENCE)
         } else if (
           (cp >= 0x01 && cp <= 0x08) ||
           cp === 0x0b ||
           (cp >= 0x0d && cp <= 0x1f) ||
           (cp >= 0x7f && cp <= 0x9f)
         ) {
-          emitError(context, ParserErrorTypes.CONTROL_CHARACTER_REFERENCE)
+          emitError(context, ErrorCodes.CONTROL_CHARACTER_REFERENCE)
           cp = CCR_REPLACEMENTS[cp] || cp
         }
         text += String.fromCodePoint(cp)
@@ -769,7 +757,7 @@ function parseTextData(
         if (!body![0].endsWith(';')) {
           emitError(
             context,
-            ParserErrorTypes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE
+            ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE
           )
         }
       }
@@ -854,7 +842,7 @@ function getNewPosition(
 
 function emitError(
   context: ParserContext,
-  type: ParserErrorTypes,
+  code: ErrorCodes,
   offset?: number
 ): void {
   const loc = getCursor(context)
@@ -862,7 +850,7 @@ function emitError(
     loc.offset += offset
     loc.column += offset
   }
-  context.onError(type, loc)
+  context.onError(createCompilerError(code, loc))
 }
 
 function isEnd(
index 70b786d12ed055a08b57f5cf47f717bf6a266301..8ef56927f572b2b0e9562d3a140c358c214087a3 100644 (file)
@@ -1 +1,143 @@
-// TODO
+import {
+  RootNode,
+  NodeTypes,
+  ParentNode,
+  ChildNode,
+  ElementNode,
+  DirectiveNode
+} from './ast'
+import { isString } from '@vue/shared'
+import { CompilerError } from './errors'
+
+export type Transform = (node: ChildNode, context: TransformContext) => void
+
+export type DirectiveTransform = (
+  node: ElementNode,
+  dir: DirectiveNode,
+  context: TransformContext
+) => false | void
+
+export interface TransformOptions {
+  transforms: Transform[]
+  onError?: (error: CompilerError) => void
+}
+
+export interface TransformContext extends Required<TransformOptions> {
+  parent: ParentNode
+  ancestors: ParentNode[]
+  childIndex: number
+  replaceNode(node: ChildNode): void
+  removeNode(): void
+  nodeRemoved: boolean
+}
+
+export function transform(root: RootNode, options: TransformOptions) {
+  const context = createTransformContext(root, options)
+  traverseChildren(root, context, context.ancestors)
+}
+
+function createTransformContext(
+  root: RootNode,
+  options: TransformOptions
+): TransformContext {
+  const context: TransformContext = {
+    onError(error: CompilerError) {
+      throw error
+    },
+    ...options,
+    parent: root,
+    ancestors: [root],
+    childIndex: 0,
+    replaceNode(node) {
+      context.parent.children[context.childIndex] = node
+    },
+    removeNode() {
+      context.parent.children.splice(context.childIndex, 1)
+      context.nodeRemoved = true
+    },
+    nodeRemoved: false
+  }
+  return context
+}
+
+function traverseChildren(
+  parent: ParentNode,
+  context: TransformContext,
+  ancestors: ParentNode[]
+) {
+  ancestors = ancestors.concat(parent)
+  for (let i = 0; i < parent.children.length; i++) {
+    context.parent = parent
+    context.ancestors = ancestors
+    context.childIndex = i
+    traverseNode(parent.children[i], context, ancestors)
+    if (context.nodeRemoved) {
+      i--
+    }
+  }
+}
+
+function traverseNode(
+  node: ChildNode,
+  context: TransformContext,
+  ancestors: ParentNode[]
+) {
+  // apply transform plugins
+  const transforms = context.transforms
+  for (let i = 0; i < transforms.length; i++) {
+    const transform = transforms[i]
+    context.nodeRemoved = false
+    transform(node, context)
+    if (context.nodeRemoved) {
+      return
+    } else {
+      // node may have been replaced
+      node = context.parent.children[context.childIndex]
+    }
+  }
+
+  // further traverse downwards
+  switch (node.type) {
+    case NodeTypes.IF:
+      for (let i = 0; i < node.branches.length; i++) {
+        traverseChildren(node.branches[i], context, ancestors)
+      }
+      break
+    case NodeTypes.FOR:
+    case NodeTypes.ELEMENT:
+      traverseChildren(node, context, ancestors)
+      break
+  }
+}
+
+const identity = <T>(_: T): T => _
+
+export function createDirectiveTransform(
+  name: string | RegExp,
+  fn: DirectiveTransform
+): Transform {
+  const matches = isString(name)
+    ? (n: string) => n === name
+    : (n: string) => name.test(n)
+
+  return (node, context) => {
+    if (node.type === NodeTypes.ELEMENT) {
+      const dirs = node.directives
+      let didRemove = false
+      for (let i = 0; i < dirs.length; i++) {
+        if (matches(dirs[i].name)) {
+          const res = fn(node, dirs[i], context)
+          // Directives are removed after transformation by default. A transform
+          // returning false means the directive should not be removed.
+          if (res !== false) {
+            ;(dirs as any)[i] = undefined
+            didRemove = true
+          }
+        }
+      }
+      if (didRemove) {
+        node.directives = dirs.filter(identity)
+      }
+    }
+  }
+}
index 7d43a6d049bb8786f9c80aa2bb09c5eb51adb829..c076cfa478e486bbd5f1ad6e19d7226d6df0e19b 100644 (file)
@@ -3,7 +3,7 @@ import {
   NodeTypes,
   ElementNode,
   TextNode,
-  ParserErrorTypes,
+  ErrorCodes,
   ExpressionNode,
   ElementTypes
 } from '@vue/compiler-core'
@@ -134,7 +134,8 @@ describe('DOM parser', () => {
         ns: DOMNamespaces.HTML,
         tag: 'img',
         tagType: ElementTypes.ELEMENT,
-        props: [],
+        attrs: [],
+        directives: [],
         isSelfClosing: false,
         children: [],
         loc: {
@@ -150,9 +151,9 @@ describe('DOM parser', () => {
         '<textarea>hello</textarea</textarea0></texTArea a="<>">',
         {
           ...parserOptions,
-          onError: type => {
-            if (type !== ParserErrorTypes.END_TAG_WITH_ATTRIBUTES) {
-              throw new Error(String(type))
+          onError: err => {
+            if (err.code !== ErrorCodes.END_TAG_WITH_ATTRIBUTES) {
+              throw err
             }
           }
         }
index f74120d4bbd7c07947c44edc796d6c31c8452eeb..ac6754fab3668ceae53ae57d1890914b516dac18 100644 (file)
@@ -1,5 +1,4 @@
 import {
-  NodeTypes,
   TextModes,
   ParserOptions,
   ElementNode,
@@ -23,9 +22,8 @@ export const parserOptionsMinimal: ParserOptions = {
           return DOMNamespaces.SVG
         }
         if (
-          parent.props.some(
+          parent.attrs.some(
             a =>
-              a.type === NodeTypes.ATTRIBUTE &&
               a.name === 'encoding' &&
               a.value != null &&
               (a.value.content === 'text/html' ||