html-validate 8.25.1 → 8.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core.js +64 -9
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/es/core.js +64 -9
- package/dist/es/core.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/package.json +2 -162
package/dist/es/core.js
CHANGED
|
@@ -5049,6 +5049,27 @@ class CloseAttr extends Rule {
|
|
|
5049
5049
|
}
|
|
5050
5050
|
}
|
|
5051
5051
|
|
|
5052
|
+
function* ancestors(node) {
|
|
5053
|
+
if (!node) {
|
|
5054
|
+
return;
|
|
5055
|
+
}
|
|
5056
|
+
let ancestor = node;
|
|
5057
|
+
while (ancestor && !ancestor.isRootElement()) {
|
|
5058
|
+
yield ancestor;
|
|
5059
|
+
ancestor = ancestor.parent;
|
|
5060
|
+
}
|
|
5061
|
+
if (ancestor) {
|
|
5062
|
+
yield ancestor;
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5065
|
+
function findAncestor(node, predicate) {
|
|
5066
|
+
for (const ancestor of ancestors(node)) {
|
|
5067
|
+
if (predicate(ancestor)) {
|
|
5068
|
+
return ancestor;
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
return null;
|
|
5072
|
+
}
|
|
5052
5073
|
class CloseOrder extends Rule {
|
|
5053
5074
|
documentation() {
|
|
5054
5075
|
return {
|
|
@@ -5057,15 +5078,28 @@ class CloseOrder extends Rule {
|
|
|
5057
5078
|
};
|
|
5058
5079
|
}
|
|
5059
5080
|
setup() {
|
|
5081
|
+
let reported;
|
|
5082
|
+
this.on("parse:begin", () => {
|
|
5083
|
+
reported = /* @__PURE__ */ new Set();
|
|
5084
|
+
});
|
|
5085
|
+
this.on("tag:end", (event) => {
|
|
5086
|
+
const current = event.target;
|
|
5087
|
+
const active = event.previous;
|
|
5088
|
+
if (current) {
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
for (const ancestor of ancestors(active)) {
|
|
5092
|
+
if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
|
|
5093
|
+
continue;
|
|
5094
|
+
}
|
|
5095
|
+
this.report(ancestor, `Unclosed element '<${ancestor.tagName}>'`, ancestor.location);
|
|
5096
|
+
reported.add(ancestor.unique);
|
|
5097
|
+
}
|
|
5098
|
+
});
|
|
5060
5099
|
this.on("tag:end", (event) => {
|
|
5061
5100
|
const current = event.target;
|
|
5062
5101
|
const active = event.previous;
|
|
5063
5102
|
if (!current) {
|
|
5064
|
-
this.report(
|
|
5065
|
-
null,
|
|
5066
|
-
`Missing close-tag, expected '</${active.tagName}>' but document ended before it was found.`,
|
|
5067
|
-
event.location
|
|
5068
|
-
);
|
|
5069
5103
|
return;
|
|
5070
5104
|
}
|
|
5071
5105
|
if (current.voidElement) {
|
|
@@ -5082,15 +5116,32 @@ class CloseOrder extends Rule {
|
|
|
5082
5116
|
offset: current.location.offset,
|
|
5083
5117
|
size: current.tagName.length + 1
|
|
5084
5118
|
};
|
|
5085
|
-
this.report(null,
|
|
5119
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, location);
|
|
5120
|
+
return;
|
|
5121
|
+
}
|
|
5122
|
+
if (current.tagName === active.tagName) {
|
|
5086
5123
|
return;
|
|
5087
5124
|
}
|
|
5088
|
-
|
|
5125
|
+
const ancestor = findAncestor(active.parent, (node) => node.is(current.tagName));
|
|
5126
|
+
if (ancestor && !ancestor.isRootElement()) {
|
|
5127
|
+
for (const element of ancestors(active)) {
|
|
5128
|
+
if (ancestor.isSameNode(element)) {
|
|
5129
|
+
break;
|
|
5130
|
+
}
|
|
5131
|
+
if (reported.has(element.unique)) {
|
|
5132
|
+
continue;
|
|
5133
|
+
}
|
|
5134
|
+
this.report(element, `Unclosed element '<${element.tagName}>'`, element.location);
|
|
5135
|
+
reported.add(element.unique);
|
|
5136
|
+
}
|
|
5089
5137
|
this.report(
|
|
5090
5138
|
null,
|
|
5091
|
-
`
|
|
5139
|
+
`End tag '</${current.tagName}>' seen but there were open elements`,
|
|
5092
5140
|
current.location
|
|
5093
5141
|
);
|
|
5142
|
+
reported.add(ancestor.unique);
|
|
5143
|
+
} else {
|
|
5144
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, current.location);
|
|
5094
5145
|
}
|
|
5095
5146
|
});
|
|
5096
5147
|
}
|
|
@@ -11646,8 +11697,9 @@ class Parser {
|
|
|
11646
11697
|
node.closed = NodeClosed.EndTag;
|
|
11647
11698
|
}
|
|
11648
11699
|
this.closeElement(source, node, active, endToken.location);
|
|
11700
|
+
const mismatched = node.tagName !== active.tagName;
|
|
11649
11701
|
const voidClosed = !isStartTag && node.voidElement;
|
|
11650
|
-
if (!voidClosed) {
|
|
11702
|
+
if (!voidClosed && !mismatched) {
|
|
11651
11703
|
this.dom.popActive();
|
|
11652
11704
|
}
|
|
11653
11705
|
} else if (isForeign) {
|
|
@@ -11665,6 +11717,9 @@ class Parser {
|
|
|
11665
11717
|
location
|
|
11666
11718
|
};
|
|
11667
11719
|
this.trigger("tag:end", event);
|
|
11720
|
+
if (node && node.tagName !== active.tagName && active.closed !== NodeClosed.ImplicitClosed) {
|
|
11721
|
+
return;
|
|
11722
|
+
}
|
|
11668
11723
|
if (!active.isRootElement()) {
|
|
11669
11724
|
this.trigger("element:ready", {
|
|
11670
11725
|
target: active,
|