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/cjs/core.js
CHANGED
|
@@ -5059,6 +5059,27 @@ class CloseAttr extends Rule {
|
|
|
5059
5059
|
}
|
|
5060
5060
|
}
|
|
5061
5061
|
|
|
5062
|
+
function* ancestors(node) {
|
|
5063
|
+
if (!node) {
|
|
5064
|
+
return;
|
|
5065
|
+
}
|
|
5066
|
+
let ancestor = node;
|
|
5067
|
+
while (ancestor && !ancestor.isRootElement()) {
|
|
5068
|
+
yield ancestor;
|
|
5069
|
+
ancestor = ancestor.parent;
|
|
5070
|
+
}
|
|
5071
|
+
if (ancestor) {
|
|
5072
|
+
yield ancestor;
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5075
|
+
function findAncestor(node, predicate) {
|
|
5076
|
+
for (const ancestor of ancestors(node)) {
|
|
5077
|
+
if (predicate(ancestor)) {
|
|
5078
|
+
return ancestor;
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
return null;
|
|
5082
|
+
}
|
|
5062
5083
|
class CloseOrder extends Rule {
|
|
5063
5084
|
documentation() {
|
|
5064
5085
|
return {
|
|
@@ -5067,15 +5088,28 @@ class CloseOrder extends Rule {
|
|
|
5067
5088
|
};
|
|
5068
5089
|
}
|
|
5069
5090
|
setup() {
|
|
5091
|
+
let reported;
|
|
5092
|
+
this.on("parse:begin", () => {
|
|
5093
|
+
reported = /* @__PURE__ */ new Set();
|
|
5094
|
+
});
|
|
5095
|
+
this.on("tag:end", (event) => {
|
|
5096
|
+
const current = event.target;
|
|
5097
|
+
const active = event.previous;
|
|
5098
|
+
if (current) {
|
|
5099
|
+
return;
|
|
5100
|
+
}
|
|
5101
|
+
for (const ancestor of ancestors(active)) {
|
|
5102
|
+
if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
|
|
5103
|
+
continue;
|
|
5104
|
+
}
|
|
5105
|
+
this.report(ancestor, `Unclosed element '<${ancestor.tagName}>'`, ancestor.location);
|
|
5106
|
+
reported.add(ancestor.unique);
|
|
5107
|
+
}
|
|
5108
|
+
});
|
|
5070
5109
|
this.on("tag:end", (event) => {
|
|
5071
5110
|
const current = event.target;
|
|
5072
5111
|
const active = event.previous;
|
|
5073
5112
|
if (!current) {
|
|
5074
|
-
this.report(
|
|
5075
|
-
null,
|
|
5076
|
-
`Missing close-tag, expected '</${active.tagName}>' but document ended before it was found.`,
|
|
5077
|
-
event.location
|
|
5078
|
-
);
|
|
5079
5113
|
return;
|
|
5080
5114
|
}
|
|
5081
5115
|
if (current.voidElement) {
|
|
@@ -5092,15 +5126,32 @@ class CloseOrder extends Rule {
|
|
|
5092
5126
|
offset: current.location.offset,
|
|
5093
5127
|
size: current.tagName.length + 1
|
|
5094
5128
|
};
|
|
5095
|
-
this.report(null,
|
|
5129
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, location);
|
|
5130
|
+
return;
|
|
5131
|
+
}
|
|
5132
|
+
if (current.tagName === active.tagName) {
|
|
5096
5133
|
return;
|
|
5097
5134
|
}
|
|
5098
|
-
|
|
5135
|
+
const ancestor = findAncestor(active.parent, (node) => node.is(current.tagName));
|
|
5136
|
+
if (ancestor && !ancestor.isRootElement()) {
|
|
5137
|
+
for (const element of ancestors(active)) {
|
|
5138
|
+
if (ancestor.isSameNode(element)) {
|
|
5139
|
+
break;
|
|
5140
|
+
}
|
|
5141
|
+
if (reported.has(element.unique)) {
|
|
5142
|
+
continue;
|
|
5143
|
+
}
|
|
5144
|
+
this.report(element, `Unclosed element '<${element.tagName}>'`, element.location);
|
|
5145
|
+
reported.add(element.unique);
|
|
5146
|
+
}
|
|
5099
5147
|
this.report(
|
|
5100
5148
|
null,
|
|
5101
|
-
`
|
|
5149
|
+
`End tag '</${current.tagName}>' seen but there were open elements`,
|
|
5102
5150
|
current.location
|
|
5103
5151
|
);
|
|
5152
|
+
reported.add(ancestor.unique);
|
|
5153
|
+
} else {
|
|
5154
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, current.location);
|
|
5104
5155
|
}
|
|
5105
5156
|
});
|
|
5106
5157
|
}
|
|
@@ -11656,8 +11707,9 @@ class Parser {
|
|
|
11656
11707
|
node.closed = NodeClosed.EndTag;
|
|
11657
11708
|
}
|
|
11658
11709
|
this.closeElement(source, node, active, endToken.location);
|
|
11710
|
+
const mismatched = node.tagName !== active.tagName;
|
|
11659
11711
|
const voidClosed = !isStartTag && node.voidElement;
|
|
11660
|
-
if (!voidClosed) {
|
|
11712
|
+
if (!voidClosed && !mismatched) {
|
|
11661
11713
|
this.dom.popActive();
|
|
11662
11714
|
}
|
|
11663
11715
|
} else if (isForeign) {
|
|
@@ -11675,6 +11727,9 @@ class Parser {
|
|
|
11675
11727
|
location
|
|
11676
11728
|
};
|
|
11677
11729
|
this.trigger("tag:end", event);
|
|
11730
|
+
if (node && node.tagName !== active.tagName && active.closed !== NodeClosed.ImplicitClosed) {
|
|
11731
|
+
return;
|
|
11732
|
+
}
|
|
11678
11733
|
if (!active.isRootElement()) {
|
|
11679
11734
|
this.trigger("element:ready", {
|
|
11680
11735
|
target: active,
|