html-validate 8.9.0 → 8.9.1

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 CHANGED
@@ -2159,6 +2159,7 @@ class TextNode extends DOMNode {
2159
2159
  }
2160
2160
  }
2161
2161
 
2162
+ const ROLE = Symbol("role");
2162
2163
  var NodeClosed = /* @__PURE__ */ ((NodeClosed2) => {
2163
2164
  NodeClosed2[NodeClosed2["Open"] = 0] = "Open";
2164
2165
  NodeClosed2[NodeClosed2["EndTag"] = 1] = "EndTag";
@@ -2394,6 +2395,27 @@ class HtmlElement extends DOMNode {
2394
2395
  get meta() {
2395
2396
  return this.metaElement;
2396
2397
  }
2398
+ /**
2399
+ * Get current role for this element (explicit with `role` attribute or mapped
2400
+ * with implicit role).
2401
+ *
2402
+ * @since 8.9.1
2403
+ */
2404
+ get role() {
2405
+ const cached = this.cacheGet(ROLE);
2406
+ if (cached !== void 0) {
2407
+ return cached;
2408
+ }
2409
+ const role = this.getAttribute("role");
2410
+ if (role) {
2411
+ return this.cacheSet(ROLE, role.value);
2412
+ }
2413
+ if (this.metaElement) {
2414
+ const implicitRole = this.metaElement.implicitRole(this._adapter);
2415
+ return this.cacheSet(ROLE, implicitRole);
2416
+ }
2417
+ return this.cacheSet(ROLE, null);
2418
+ }
2397
2419
  /**
2398
2420
  * Set annotation for this element.
2399
2421
  */
@@ -7433,7 +7455,7 @@ class NoRawCharacters extends Rule {
7433
7455
  }
7434
7456
  }
7435
7457
 
7436
- const selectors = ["input[aria-label]", "textarea[aria-label]", "select[aria-label]"];
7458
+ const selectors$1 = ["input[aria-label]", "textarea[aria-label]", "select[aria-label]"];
7437
7459
  class NoRedundantAriaLabel extends Rule {
7438
7460
  documentation() {
7439
7461
  return {
@@ -7444,7 +7466,7 @@ class NoRedundantAriaLabel extends Rule {
7444
7466
  setup() {
7445
7467
  this.on("dom:ready", (event) => {
7446
7468
  const { document } = event;
7447
- const elements = document.querySelectorAll(selectors.join(","));
7469
+ const elements = document.querySelectorAll(selectors$1.join(","));
7448
7470
  for (const element of elements) {
7449
7471
  const ariaLabel = element.getAttribute("aria-label");
7450
7472
  const id = element.id;
@@ -8473,6 +8495,18 @@ class TextContent extends Rule {
8473
8495
  }
8474
8496
  }
8475
8497
 
8498
+ const roles = ["complementary", "contentinfo", "form", "banner", "main", "navigation", "region"];
8499
+ const selectors = [
8500
+ "aside",
8501
+ "footer",
8502
+ "form",
8503
+ "header",
8504
+ "main",
8505
+ "nav",
8506
+ "section",
8507
+ ...roles.map((it) => `[role="${it}"]`)
8508
+ /* <search> does not (yet?) require a unique name */
8509
+ ];
8476
8510
  function getTextFromReference(document, id) {
8477
8511
  if (!id || id instanceof DynamicValue) {
8478
8512
  return id;
@@ -8485,6 +8519,18 @@ function getTextFromReference(document, id) {
8485
8519
  return selector;
8486
8520
  }
8487
8521
  }
8522
+ function groupBy(values, callback) {
8523
+ const result = {};
8524
+ for (const value of values) {
8525
+ const key = callback(value);
8526
+ if (key in result) {
8527
+ result[key].push(value);
8528
+ } else {
8529
+ result[key] = [value];
8530
+ }
8531
+ }
8532
+ return result;
8533
+ }
8488
8534
  function getTextEntryFromElement(document, node) {
8489
8535
  const ariaLabel = node.getAttribute("aria-label");
8490
8536
  if (ariaLabel) {
@@ -8509,6 +8555,13 @@ function getTextEntryFromElement(document, node) {
8509
8555
  location: node.location
8510
8556
  };
8511
8557
  }
8558
+ function isExcluded(entry) {
8559
+ const { node, text } = entry;
8560
+ if (text === null) {
8561
+ return !(node.is("form") || node.is("section"));
8562
+ }
8563
+ return true;
8564
+ }
8512
8565
  class UniqueLandmark extends Rule {
8513
8566
  documentation() {
8514
8567
  return {
@@ -8536,25 +8589,17 @@ class UniqueLandmark extends Rule {
8536
8589
  };
8537
8590
  }
8538
8591
  setup() {
8539
- const selectors = [
8540
- 'aside, [role="complementary"]',
8541
- 'footer, [role="contentinfo"]',
8542
- 'form, [role="form"]',
8543
- 'header, [role="banner"]',
8544
- 'main, [role="main"]',
8545
- 'nav, [role="navigation"]',
8546
- 'section, [role="region"]'
8547
- /* <search> does not (yet?) require a unique name */
8548
- ];
8549
8592
  this.on("dom:ready", (event) => {
8550
8593
  const { document } = event;
8551
- for (const selector of selectors) {
8552
- const nodes = document.querySelectorAll(selector);
8594
+ const elements = document.querySelectorAll(selectors.join(",")).filter((it) => typeof it.role === "string" && roles.includes(it.role));
8595
+ const grouped = groupBy(elements, (it) => it.role);
8596
+ for (const nodes of Object.values(grouped)) {
8553
8597
  if (nodes.length <= 1) {
8554
8598
  continue;
8555
8599
  }
8556
8600
  const entries = nodes.map((it) => getTextEntryFromElement(document, it));
8557
- for (const entry of entries) {
8601
+ const filteredEntries = entries.filter(isExcluded);
8602
+ for (const entry of filteredEntries) {
8558
8603
  if (entry.text instanceof DynamicValue) {
8559
8604
  continue;
8560
8605
  }
@@ -11658,7 +11703,7 @@ class HtmlValidate {
11658
11703
  }
11659
11704
 
11660
11705
  const name = "html-validate";
11661
- const version = "8.9.0";
11706
+ const version = "8.9.1";
11662
11707
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11663
11708
 
11664
11709
  function definePlugin(plugin) {