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/es/core.js CHANGED
@@ -2149,6 +2149,7 @@ class TextNode extends DOMNode {
2149
2149
  }
2150
2150
  }
2151
2151
 
2152
+ const ROLE = Symbol("role");
2152
2153
  var NodeClosed = /* @__PURE__ */ ((NodeClosed2) => {
2153
2154
  NodeClosed2[NodeClosed2["Open"] = 0] = "Open";
2154
2155
  NodeClosed2[NodeClosed2["EndTag"] = 1] = "EndTag";
@@ -2384,6 +2385,27 @@ class HtmlElement extends DOMNode {
2384
2385
  get meta() {
2385
2386
  return this.metaElement;
2386
2387
  }
2388
+ /**
2389
+ * Get current role for this element (explicit with `role` attribute or mapped
2390
+ * with implicit role).
2391
+ *
2392
+ * @since 8.9.1
2393
+ */
2394
+ get role() {
2395
+ const cached = this.cacheGet(ROLE);
2396
+ if (cached !== void 0) {
2397
+ return cached;
2398
+ }
2399
+ const role = this.getAttribute("role");
2400
+ if (role) {
2401
+ return this.cacheSet(ROLE, role.value);
2402
+ }
2403
+ if (this.metaElement) {
2404
+ const implicitRole = this.metaElement.implicitRole(this._adapter);
2405
+ return this.cacheSet(ROLE, implicitRole);
2406
+ }
2407
+ return this.cacheSet(ROLE, null);
2408
+ }
2387
2409
  /**
2388
2410
  * Set annotation for this element.
2389
2411
  */
@@ -7423,7 +7445,7 @@ class NoRawCharacters extends Rule {
7423
7445
  }
7424
7446
  }
7425
7447
 
7426
- const selectors = ["input[aria-label]", "textarea[aria-label]", "select[aria-label]"];
7448
+ const selectors$1 = ["input[aria-label]", "textarea[aria-label]", "select[aria-label]"];
7427
7449
  class NoRedundantAriaLabel extends Rule {
7428
7450
  documentation() {
7429
7451
  return {
@@ -7434,7 +7456,7 @@ class NoRedundantAriaLabel extends Rule {
7434
7456
  setup() {
7435
7457
  this.on("dom:ready", (event) => {
7436
7458
  const { document } = event;
7437
- const elements = document.querySelectorAll(selectors.join(","));
7459
+ const elements = document.querySelectorAll(selectors$1.join(","));
7438
7460
  for (const element of elements) {
7439
7461
  const ariaLabel = element.getAttribute("aria-label");
7440
7462
  const id = element.id;
@@ -8463,6 +8485,18 @@ class TextContent extends Rule {
8463
8485
  }
8464
8486
  }
8465
8487
 
8488
+ const roles = ["complementary", "contentinfo", "form", "banner", "main", "navigation", "region"];
8489
+ const selectors = [
8490
+ "aside",
8491
+ "footer",
8492
+ "form",
8493
+ "header",
8494
+ "main",
8495
+ "nav",
8496
+ "section",
8497
+ ...roles.map((it) => `[role="${it}"]`)
8498
+ /* <search> does not (yet?) require a unique name */
8499
+ ];
8466
8500
  function getTextFromReference(document, id) {
8467
8501
  if (!id || id instanceof DynamicValue) {
8468
8502
  return id;
@@ -8475,6 +8509,18 @@ function getTextFromReference(document, id) {
8475
8509
  return selector;
8476
8510
  }
8477
8511
  }
8512
+ function groupBy(values, callback) {
8513
+ const result = {};
8514
+ for (const value of values) {
8515
+ const key = callback(value);
8516
+ if (key in result) {
8517
+ result[key].push(value);
8518
+ } else {
8519
+ result[key] = [value];
8520
+ }
8521
+ }
8522
+ return result;
8523
+ }
8478
8524
  function getTextEntryFromElement(document, node) {
8479
8525
  const ariaLabel = node.getAttribute("aria-label");
8480
8526
  if (ariaLabel) {
@@ -8499,6 +8545,13 @@ function getTextEntryFromElement(document, node) {
8499
8545
  location: node.location
8500
8546
  };
8501
8547
  }
8548
+ function isExcluded(entry) {
8549
+ const { node, text } = entry;
8550
+ if (text === null) {
8551
+ return !(node.is("form") || node.is("section"));
8552
+ }
8553
+ return true;
8554
+ }
8502
8555
  class UniqueLandmark extends Rule {
8503
8556
  documentation() {
8504
8557
  return {
@@ -8526,25 +8579,17 @@ class UniqueLandmark extends Rule {
8526
8579
  };
8527
8580
  }
8528
8581
  setup() {
8529
- const selectors = [
8530
- 'aside, [role="complementary"]',
8531
- 'footer, [role="contentinfo"]',
8532
- 'form, [role="form"]',
8533
- 'header, [role="banner"]',
8534
- 'main, [role="main"]',
8535
- 'nav, [role="navigation"]',
8536
- 'section, [role="region"]'
8537
- /* <search> does not (yet?) require a unique name */
8538
- ];
8539
8582
  this.on("dom:ready", (event) => {
8540
8583
  const { document } = event;
8541
- for (const selector of selectors) {
8542
- const nodes = document.querySelectorAll(selector);
8584
+ const elements = document.querySelectorAll(selectors.join(",")).filter((it) => typeof it.role === "string" && roles.includes(it.role));
8585
+ const grouped = groupBy(elements, (it) => it.role);
8586
+ for (const nodes of Object.values(grouped)) {
8543
8587
  if (nodes.length <= 1) {
8544
8588
  continue;
8545
8589
  }
8546
8590
  const entries = nodes.map((it) => getTextEntryFromElement(document, it));
8547
- for (const entry of entries) {
8591
+ const filteredEntries = entries.filter(isExcluded);
8592
+ for (const entry of filteredEntries) {
8548
8593
  if (entry.text instanceof DynamicValue) {
8549
8594
  continue;
8550
8595
  }
@@ -11648,7 +11693,7 @@ class HtmlValidate {
11648
11693
  }
11649
11694
 
11650
11695
  const name = "html-validate";
11651
- const version = "8.9.0";
11696
+ const version = "8.9.1";
11652
11697
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11653
11698
 
11654
11699
  function definePlugin(plugin) {