html-validate 8.18.2 → 8.19.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.43.1"
8
+ "packageVersion": "7.43.7"
9
9
  }
10
10
  ]
11
11
  }
package/dist/es/core.js CHANGED
@@ -5,7 +5,7 @@ import { n as naturalJoin } from './utils/natural-join.js';
5
5
  import fs from 'fs';
6
6
  import { codeFrameColumns } from '@babel/code-frame';
7
7
  import kleur from 'kleur';
8
- import { stylish as stylish$2 } from '@html-validate/stylish';
8
+ import { stylish as stylish$1 } from '@html-validate/stylish';
9
9
  import semver from 'semver';
10
10
 
11
11
  const $schema$2 = "http://json-schema.org/draft-06/schema#";
@@ -6214,6 +6214,7 @@ class EmptyTitle extends Rule {
6214
6214
 
6215
6215
  const defaults$k = {
6216
6216
  allowArrayBrackets: true,
6217
+ allowCheckboxDefault: true,
6217
6218
  shared: ["radio", "button", "reset", "submit"]
6218
6219
  };
6219
6220
  const UNIQUE_CACHE_KEY = Symbol("form-elements-unique");
@@ -6225,6 +6226,25 @@ function allowSharedName(node, shared) {
6225
6226
  const type = node.getAttribute("type");
6226
6227
  return Boolean(type == null ? void 0 : type.valueMatches(shared, false));
6227
6228
  }
6229
+ function isInputHidden(element) {
6230
+ return element.is("input") && element.getAttributeValue("type") === "hidden";
6231
+ }
6232
+ function isInputCheckbox(element) {
6233
+ return element.is("input") && element.getAttributeValue("type") === "checkbox";
6234
+ }
6235
+ function isCheckboxWithDefault(control, previous, options) {
6236
+ const { allowCheckboxDefault } = options;
6237
+ if (!allowCheckboxDefault) {
6238
+ return false;
6239
+ }
6240
+ if (!previous.potentialHiddenDefault) {
6241
+ return false;
6242
+ }
6243
+ if (!isInputCheckbox(control)) {
6244
+ return false;
6245
+ }
6246
+ return true;
6247
+ }
6228
6248
  function getDocumentation(context) {
6229
6249
  const trailer = "Each form control must have a unique name.";
6230
6250
  const { name } = context;
@@ -6247,6 +6267,9 @@ class FormDupName extends Rule {
6247
6267
  allowArrayBrackets: {
6248
6268
  type: "boolean"
6249
6269
  },
6270
+ allowCheckboxDefault: {
6271
+ type: "boolean"
6272
+ },
6250
6273
  shared: {
6251
6274
  type: "array",
6252
6275
  items: {
@@ -6312,14 +6335,20 @@ class FormDupName extends Rule {
6312
6335
  }
6313
6336
  if (!details && isarray) {
6314
6337
  elements.set(basename, {
6315
- array: true
6338
+ array: true,
6339
+ potentialHiddenDefault: false
6316
6340
  });
6317
6341
  }
6318
6342
  if (isarray) {
6319
6343
  return;
6320
6344
  }
6321
6345
  }
6322
- if (elements.has(name)) {
6346
+ const previous = elements.get(name);
6347
+ if (previous) {
6348
+ if (isCheckboxWithDefault(control, previous, this.options)) {
6349
+ previous.potentialHiddenDefault = false;
6350
+ return;
6351
+ }
6323
6352
  const context = {
6324
6353
  name,
6325
6354
  kind: "duplicate"
@@ -6332,7 +6361,8 @@ class FormDupName extends Rule {
6332
6361
  });
6333
6362
  } else {
6334
6363
  elements.set(name, {
6335
- array: false
6364
+ array: false,
6365
+ potentialHiddenDefault: isInputHidden(control)
6336
6366
  });
6337
6367
  }
6338
6368
  }
@@ -7186,20 +7216,23 @@ class MultipleLabeledControls extends Rule {
7186
7216
  }
7187
7217
  setup() {
7188
7218
  this.labelable = this.getTagsWithProperty("labelable").join(",");
7189
- this.on("element:ready", (event) => {
7190
- const { target } = event;
7191
- if (target.tagName !== "label") {
7192
- return;
7193
- }
7194
- const numControls = this.getNumLabledControls(target);
7195
- if (numControls <= 1) {
7196
- return;
7219
+ this.on("dom:ready", (event) => {
7220
+ const { document } = event;
7221
+ const labels = document.querySelectorAll("label");
7222
+ for (const label of labels) {
7223
+ const numControls = this.getNumLabledControls(label);
7224
+ if (numControls <= 1) {
7225
+ continue;
7226
+ }
7227
+ this.report(label, "<label> is associated with multiple controls", label.location);
7197
7228
  }
7198
- this.report(target, "<label> is associated with multiple controls", target.location);
7199
7229
  });
7200
7230
  }
7201
7231
  getNumLabledControls(src) {
7202
- const controls = src.querySelectorAll(this.labelable).map((node) => node.id);
7232
+ const controls = src.querySelectorAll(this.labelable).filter((node) => {
7233
+ var _a;
7234
+ return (_a = node.meta) == null ? void 0 : _a.labelable;
7235
+ }).map((node) => node.id);
7203
7236
  const attr = src.getAttribute("for");
7204
7237
  if (!attr || attr.isDynamic || !attr.value) {
7205
7238
  return controls.length;
@@ -9743,7 +9776,7 @@ class ValidID extends Rule {
9743
9776
  const message = this.messages[context].replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9744
9777
  const relaxedDescription = relaxed ? [] : [
9745
9778
  " - ID must begin with a letter",
9746
- " - ID must only contain alphanumerical characters, `-` and `_`"
9779
+ " - ID must only contain letters, digits, `-` and `_`"
9747
9780
  ];
9748
9781
  return {
9749
9782
  description: [
@@ -9778,12 +9811,12 @@ class ValidID extends Rule {
9778
9811
  if (relaxed) {
9779
9812
  return;
9780
9813
  }
9781
- if (value.match(/^[^a-zA-Z]/)) {
9814
+ if (value.match(/^[^\p{L}]/u)) {
9782
9815
  const context = 3 /* LEADING_CHARACTER */;
9783
9816
  this.report(event.target, this.messages[context], event.valueLocation, context);
9784
9817
  return;
9785
9818
  }
9786
- if (value.match(/[^a-zA-Z0-9-_]/)) {
9819
+ if (value.match(/[^\p{L}\p{N}_-]/u)) {
9787
9820
  const context = 4 /* DISALLOWED_CHARACTER */;
9788
9821
  this.report(event.target, this.messages[context], event.valueLocation, context);
9789
9822
  }
@@ -9794,7 +9827,7 @@ class ValidID extends Rule {
9794
9827
  [1 /* EMPTY */]: "element id must not be empty",
9795
9828
  [2 /* WHITESPACE */]: "element id must not contain whitespace",
9796
9829
  [3 /* LEADING_CHARACTER */]: "element id must begin with a letter",
9797
- [4 /* DISALLOWED_CHARACTER */]: "element id must only contain alphanumerical, dash and underscore characters"
9830
+ [4 /* DISALLOWED_CHARACTER */]: "element id must only contain letters, digits, dash and underscore characters"
9798
9831
  };
9799
9832
  }
9800
9833
  isRelevant(event) {
@@ -9921,7 +9954,7 @@ function styleDescription(style) {
9921
9954
  class H30 extends Rule {
9922
9955
  documentation() {
9923
9956
  return {
9924
- description: "WCAG 2.1 requires each `<a>` anchor link to have a text describing the purpose of the link using either plain text or an `<img>` with the `alt` attribute set.",
9957
+ description: "WCAG 2.1 requires each `<a href>` anchor link to have a text describing the purpose of the link using either plain text or an `<img>` with the `alt` attribute set.",
9925
9958
  url: "https://html-validate.org/rules/wcag/h30.html"
9926
9959
  };
9927
9960
  }
@@ -9929,6 +9962,9 @@ class H30 extends Rule {
9929
9962
  this.on("dom:ready", (event) => {
9930
9963
  const links = event.document.getElementsByTagName("a");
9931
9964
  for (const link of links) {
9965
+ if (!link.hasAttribute("href")) {
9966
+ continue;
9967
+ }
9932
9968
  if (!inAccessibilityTree(link)) {
9933
9969
  continue;
9934
9970
  }
@@ -10197,7 +10233,6 @@ const bundledRules$1 = {
10197
10233
  "wcag/h67": H67,
10198
10234
  "wcag/h71": H71
10199
10235
  };
10200
- var WCAG = bundledRules$1;
10201
10236
 
10202
10237
  const bundledRules = {
10203
10238
  "allowed-links": AllowedLinks,
@@ -10283,7 +10318,7 @@ const bundledRules = {
10283
10318
  "valid-id": ValidID,
10284
10319
  "void-content": VoidContent,
10285
10320
  "void-style": VoidStyle,
10286
- ...WCAG
10321
+ ...bundledRules$1
10287
10322
  };
10288
10323
 
10289
10324
  var defaultConfig = {};
@@ -10320,7 +10355,6 @@ const config$4 = {
10320
10355
  "wcag/h71": "error"
10321
10356
  }
10322
10357
  };
10323
- var a11y = config$4;
10324
10358
 
10325
10359
  const config$3 = {
10326
10360
  rules: {
@@ -10331,7 +10365,6 @@ const config$3 = {
10331
10365
  "require-sri": "error"
10332
10366
  }
10333
10367
  };
10334
- var document = config$3;
10335
10368
 
10336
10369
  const config$2 = {
10337
10370
  rules: {
@@ -10340,7 +10373,6 @@ const config$2 = {
10340
10373
  "void-style": "off"
10341
10374
  }
10342
10375
  };
10343
- var prettier = config$2;
10344
10376
 
10345
10377
  const config$1 = {
10346
10378
  rules: {
@@ -10424,7 +10456,6 @@ const config$1 = {
10424
10456
  "wcag/h71": "error"
10425
10457
  }
10426
10458
  };
10427
- var recommended = config$1;
10428
10459
 
10429
10460
  const config = {
10430
10461
  rules: {
@@ -10463,18 +10494,17 @@ const config = {
10463
10494
  "void-content": "error"
10464
10495
  }
10465
10496
  };
10466
- var standard = config;
10467
10497
 
10468
10498
  const presets = {
10469
- "html-validate:a11y": a11y,
10470
- "html-validate:document": document,
10471
- "html-validate:prettier": prettier,
10472
- "html-validate:recommended": recommended,
10473
- "html-validate:standard": standard,
10499
+ "html-validate:a11y": config$4,
10500
+ "html-validate:document": config$3,
10501
+ "html-validate:prettier": config$2,
10502
+ "html-validate:recommended": config$1,
10503
+ "html-validate:standard": config,
10474
10504
  /* @deprecated aliases */
10475
- "htmlvalidate:recommended": recommended,
10476
- "htmlvalidate:document": document,
10477
- "html-validate:a17y": a11y
10505
+ "htmlvalidate:recommended": config$1,
10506
+ "htmlvalidate:document": config$3,
10507
+ "html-validate:a17y": config$4
10478
10508
  };
10479
10509
  var Presets = presets;
10480
10510
 
@@ -12689,7 +12719,7 @@ class HtmlValidate {
12689
12719
  }
12690
12720
 
12691
12721
  const name = "html-validate";
12692
- const version = "8.18.2";
12722
+ const version = "8.19.0";
12693
12723
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12694
12724
 
12695
12725
  function definePlugin(plugin) {
@@ -13375,7 +13405,6 @@ function checkstyleFormatter(results) {
13375
13405
  return output;
13376
13406
  }
13377
13407
  const formatter$3 = checkstyleFormatter;
13378
- var checkstyle = formatter$3;
13379
13408
 
13380
13409
  const defaults = {
13381
13410
  showLink: true,
@@ -13481,7 +13510,6 @@ function jsonFormatter(results) {
13481
13510
  return JSON.stringify(results);
13482
13511
  }
13483
13512
  const formatter$2 = jsonFormatter;
13484
- var json = formatter$2;
13485
13513
 
13486
13514
  function linkSummary(results) {
13487
13515
  const urls = results.reduce((result, it) => {
@@ -13500,7 +13528,7 @@ ${lines.join("")}
13500
13528
  `;
13501
13529
  }
13502
13530
  function stylish(results) {
13503
- const errors = stylish$2(
13531
+ const errors = stylish$1(
13504
13532
  results.map((it) => ({
13505
13533
  ...it,
13506
13534
  fixableErrorCount: 0,
@@ -13511,7 +13539,6 @@ function stylish(results) {
13511
13539
  return `${errors}${links}`;
13512
13540
  }
13513
13541
  const formatter$1 = stylish;
13514
- var stylish$1 = formatter$1;
13515
13542
 
13516
13543
  function textFormatter(results) {
13517
13544
  let output = "";
@@ -13539,14 +13566,13 @@ function textFormatter(results) {
13539
13566
  return total > 0 ? output : "";
13540
13567
  }
13541
13568
  const formatter = textFormatter;
13542
- var text = formatter;
13543
13569
 
13544
13570
  const availableFormatters = {
13545
- checkstyle,
13571
+ checkstyle: formatter$3,
13546
13572
  codeframe,
13547
- json,
13548
- stylish: stylish$1,
13549
- text
13573
+ json: formatter$2,
13574
+ stylish: formatter$1,
13575
+ text: formatter
13550
13576
  };
13551
13577
  function getFormatter(name) {
13552
13578
  return availableFormatters[name] ?? null;