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.
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.47.11"
8
+ "packageVersion": "7.48.0"
9
9
  }
10
10
  ]
11
11
  }
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, "Unexpected close-tag, expected opening tag.", location);
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
- if (current.tagName !== active.tagName) {
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
- `Mismatched close-tag, expected '</${active.tagName}>' but found '</${current.tagName}>'.`,
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,