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.
package/dist/cjs/core.js CHANGED
@@ -7,7 +7,7 @@ var utils_naturalJoin = require('./utils/natural-join.js');
7
7
  var fs = require('fs');
8
8
  var codeFrame = require('@babel/code-frame');
9
9
  var kleur = require('kleur');
10
- var stylish$2 = require('@html-validate/stylish');
10
+ var stylish$1 = require('@html-validate/stylish');
11
11
  var semver = require('semver');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -6224,6 +6224,7 @@ class EmptyTitle extends Rule {
6224
6224
 
6225
6225
  const defaults$k = {
6226
6226
  allowArrayBrackets: true,
6227
+ allowCheckboxDefault: true,
6227
6228
  shared: ["radio", "button", "reset", "submit"]
6228
6229
  };
6229
6230
  const UNIQUE_CACHE_KEY = Symbol("form-elements-unique");
@@ -6235,6 +6236,25 @@ function allowSharedName(node, shared) {
6235
6236
  const type = node.getAttribute("type");
6236
6237
  return Boolean(type == null ? void 0 : type.valueMatches(shared, false));
6237
6238
  }
6239
+ function isInputHidden(element) {
6240
+ return element.is("input") && element.getAttributeValue("type") === "hidden";
6241
+ }
6242
+ function isInputCheckbox(element) {
6243
+ return element.is("input") && element.getAttributeValue("type") === "checkbox";
6244
+ }
6245
+ function isCheckboxWithDefault(control, previous, options) {
6246
+ const { allowCheckboxDefault } = options;
6247
+ if (!allowCheckboxDefault) {
6248
+ return false;
6249
+ }
6250
+ if (!previous.potentialHiddenDefault) {
6251
+ return false;
6252
+ }
6253
+ if (!isInputCheckbox(control)) {
6254
+ return false;
6255
+ }
6256
+ return true;
6257
+ }
6238
6258
  function getDocumentation(context) {
6239
6259
  const trailer = "Each form control must have a unique name.";
6240
6260
  const { name } = context;
@@ -6257,6 +6277,9 @@ class FormDupName extends Rule {
6257
6277
  allowArrayBrackets: {
6258
6278
  type: "boolean"
6259
6279
  },
6280
+ allowCheckboxDefault: {
6281
+ type: "boolean"
6282
+ },
6260
6283
  shared: {
6261
6284
  type: "array",
6262
6285
  items: {
@@ -6322,14 +6345,20 @@ class FormDupName extends Rule {
6322
6345
  }
6323
6346
  if (!details && isarray) {
6324
6347
  elements.set(basename, {
6325
- array: true
6348
+ array: true,
6349
+ potentialHiddenDefault: false
6326
6350
  });
6327
6351
  }
6328
6352
  if (isarray) {
6329
6353
  return;
6330
6354
  }
6331
6355
  }
6332
- if (elements.has(name)) {
6356
+ const previous = elements.get(name);
6357
+ if (previous) {
6358
+ if (isCheckboxWithDefault(control, previous, this.options)) {
6359
+ previous.potentialHiddenDefault = false;
6360
+ return;
6361
+ }
6333
6362
  const context = {
6334
6363
  name,
6335
6364
  kind: "duplicate"
@@ -6342,7 +6371,8 @@ class FormDupName extends Rule {
6342
6371
  });
6343
6372
  } else {
6344
6373
  elements.set(name, {
6345
- array: false
6374
+ array: false,
6375
+ potentialHiddenDefault: isInputHidden(control)
6346
6376
  });
6347
6377
  }
6348
6378
  }
@@ -7196,20 +7226,23 @@ class MultipleLabeledControls extends Rule {
7196
7226
  }
7197
7227
  setup() {
7198
7228
  this.labelable = this.getTagsWithProperty("labelable").join(",");
7199
- this.on("element:ready", (event) => {
7200
- const { target } = event;
7201
- if (target.tagName !== "label") {
7202
- return;
7203
- }
7204
- const numControls = this.getNumLabledControls(target);
7205
- if (numControls <= 1) {
7206
- return;
7229
+ this.on("dom:ready", (event) => {
7230
+ const { document } = event;
7231
+ const labels = document.querySelectorAll("label");
7232
+ for (const label of labels) {
7233
+ const numControls = this.getNumLabledControls(label);
7234
+ if (numControls <= 1) {
7235
+ continue;
7236
+ }
7237
+ this.report(label, "<label> is associated with multiple controls", label.location);
7207
7238
  }
7208
- this.report(target, "<label> is associated with multiple controls", target.location);
7209
7239
  });
7210
7240
  }
7211
7241
  getNumLabledControls(src) {
7212
- const controls = src.querySelectorAll(this.labelable).map((node) => node.id);
7242
+ const controls = src.querySelectorAll(this.labelable).filter((node) => {
7243
+ var _a;
7244
+ return (_a = node.meta) == null ? void 0 : _a.labelable;
7245
+ }).map((node) => node.id);
7213
7246
  const attr = src.getAttribute("for");
7214
7247
  if (!attr || attr.isDynamic || !attr.value) {
7215
7248
  return controls.length;
@@ -9753,7 +9786,7 @@ class ValidID extends Rule {
9753
9786
  const message = this.messages[context].replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9754
9787
  const relaxedDescription = relaxed ? [] : [
9755
9788
  " - ID must begin with a letter",
9756
- " - ID must only contain alphanumerical characters, `-` and `_`"
9789
+ " - ID must only contain letters, digits, `-` and `_`"
9757
9790
  ];
9758
9791
  return {
9759
9792
  description: [
@@ -9788,12 +9821,12 @@ class ValidID extends Rule {
9788
9821
  if (relaxed) {
9789
9822
  return;
9790
9823
  }
9791
- if (value.match(/^[^a-zA-Z]/)) {
9824
+ if (value.match(/^[^\p{L}]/u)) {
9792
9825
  const context = 3 /* LEADING_CHARACTER */;
9793
9826
  this.report(event.target, this.messages[context], event.valueLocation, context);
9794
9827
  return;
9795
9828
  }
9796
- if (value.match(/[^a-zA-Z0-9-_]/)) {
9829
+ if (value.match(/[^\p{L}\p{N}_-]/u)) {
9797
9830
  const context = 4 /* DISALLOWED_CHARACTER */;
9798
9831
  this.report(event.target, this.messages[context], event.valueLocation, context);
9799
9832
  }
@@ -9804,7 +9837,7 @@ class ValidID extends Rule {
9804
9837
  [1 /* EMPTY */]: "element id must not be empty",
9805
9838
  [2 /* WHITESPACE */]: "element id must not contain whitespace",
9806
9839
  [3 /* LEADING_CHARACTER */]: "element id must begin with a letter",
9807
- [4 /* DISALLOWED_CHARACTER */]: "element id must only contain alphanumerical, dash and underscore characters"
9840
+ [4 /* DISALLOWED_CHARACTER */]: "element id must only contain letters, digits, dash and underscore characters"
9808
9841
  };
9809
9842
  }
9810
9843
  isRelevant(event) {
@@ -9931,7 +9964,7 @@ function styleDescription(style) {
9931
9964
  class H30 extends Rule {
9932
9965
  documentation() {
9933
9966
  return {
9934
- 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.",
9967
+ 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.",
9935
9968
  url: "https://html-validate.org/rules/wcag/h30.html"
9936
9969
  };
9937
9970
  }
@@ -9939,6 +9972,9 @@ class H30 extends Rule {
9939
9972
  this.on("dom:ready", (event) => {
9940
9973
  const links = event.document.getElementsByTagName("a");
9941
9974
  for (const link of links) {
9975
+ if (!link.hasAttribute("href")) {
9976
+ continue;
9977
+ }
9942
9978
  if (!inAccessibilityTree(link)) {
9943
9979
  continue;
9944
9980
  }
@@ -10207,7 +10243,6 @@ const bundledRules$1 = {
10207
10243
  "wcag/h67": H67,
10208
10244
  "wcag/h71": H71
10209
10245
  };
10210
- var WCAG = bundledRules$1;
10211
10246
 
10212
10247
  const bundledRules = {
10213
10248
  "allowed-links": AllowedLinks,
@@ -10293,7 +10328,7 @@ const bundledRules = {
10293
10328
  "valid-id": ValidID,
10294
10329
  "void-content": VoidContent,
10295
10330
  "void-style": VoidStyle,
10296
- ...WCAG
10331
+ ...bundledRules$1
10297
10332
  };
10298
10333
 
10299
10334
  var defaultConfig = {};
@@ -10330,7 +10365,6 @@ const config$4 = {
10330
10365
  "wcag/h71": "error"
10331
10366
  }
10332
10367
  };
10333
- var a11y = config$4;
10334
10368
 
10335
10369
  const config$3 = {
10336
10370
  rules: {
@@ -10341,7 +10375,6 @@ const config$3 = {
10341
10375
  "require-sri": "error"
10342
10376
  }
10343
10377
  };
10344
- var document = config$3;
10345
10378
 
10346
10379
  const config$2 = {
10347
10380
  rules: {
@@ -10350,7 +10383,6 @@ const config$2 = {
10350
10383
  "void-style": "off"
10351
10384
  }
10352
10385
  };
10353
- var prettier = config$2;
10354
10386
 
10355
10387
  const config$1 = {
10356
10388
  rules: {
@@ -10434,7 +10466,6 @@ const config$1 = {
10434
10466
  "wcag/h71": "error"
10435
10467
  }
10436
10468
  };
10437
- var recommended = config$1;
10438
10469
 
10439
10470
  const config = {
10440
10471
  rules: {
@@ -10473,18 +10504,17 @@ const config = {
10473
10504
  "void-content": "error"
10474
10505
  }
10475
10506
  };
10476
- var standard = config;
10477
10507
 
10478
10508
  const presets = {
10479
- "html-validate:a11y": a11y,
10480
- "html-validate:document": document,
10481
- "html-validate:prettier": prettier,
10482
- "html-validate:recommended": recommended,
10483
- "html-validate:standard": standard,
10509
+ "html-validate:a11y": config$4,
10510
+ "html-validate:document": config$3,
10511
+ "html-validate:prettier": config$2,
10512
+ "html-validate:recommended": config$1,
10513
+ "html-validate:standard": config,
10484
10514
  /* @deprecated aliases */
10485
- "htmlvalidate:recommended": recommended,
10486
- "htmlvalidate:document": document,
10487
- "html-validate:a17y": a11y
10515
+ "htmlvalidate:recommended": config$1,
10516
+ "htmlvalidate:document": config$3,
10517
+ "html-validate:a17y": config$4
10488
10518
  };
10489
10519
  var Presets = presets;
10490
10520
 
@@ -12699,7 +12729,7 @@ class HtmlValidate {
12699
12729
  }
12700
12730
 
12701
12731
  const name = "html-validate";
12702
- const version = "8.18.2";
12732
+ const version = "8.19.0";
12703
12733
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12704
12734
 
12705
12735
  function definePlugin(plugin) {
@@ -13385,7 +13415,6 @@ function checkstyleFormatter(results) {
13385
13415
  return output;
13386
13416
  }
13387
13417
  const formatter$3 = checkstyleFormatter;
13388
- var checkstyle = formatter$3;
13389
13418
 
13390
13419
  const defaults = {
13391
13420
  showLink: true,
@@ -13491,7 +13520,6 @@ function jsonFormatter(results) {
13491
13520
  return JSON.stringify(results);
13492
13521
  }
13493
13522
  const formatter$2 = jsonFormatter;
13494
- var json = formatter$2;
13495
13523
 
13496
13524
  function linkSummary(results) {
13497
13525
  const urls = results.reduce((result, it) => {
@@ -13510,7 +13538,7 @@ ${lines.join("")}
13510
13538
  `;
13511
13539
  }
13512
13540
  function stylish(results) {
13513
- const errors = stylish$2.stylish(
13541
+ const errors = stylish$1.stylish(
13514
13542
  results.map((it) => ({
13515
13543
  ...it,
13516
13544
  fixableErrorCount: 0,
@@ -13521,7 +13549,6 @@ function stylish(results) {
13521
13549
  return `${errors}${links}`;
13522
13550
  }
13523
13551
  const formatter$1 = stylish;
13524
- var stylish$1 = formatter$1;
13525
13552
 
13526
13553
  function textFormatter(results) {
13527
13554
  let output = "";
@@ -13549,14 +13576,13 @@ function textFormatter(results) {
13549
13576
  return total > 0 ? output : "";
13550
13577
  }
13551
13578
  const formatter = textFormatter;
13552
- var text = formatter;
13553
13579
 
13554
13580
  const availableFormatters = {
13555
- checkstyle,
13581
+ checkstyle: formatter$3,
13556
13582
  codeframe,
13557
- json,
13558
- stylish: stylish$1,
13559
- text
13583
+ json: formatter$2,
13584
+ stylish: formatter$1,
13585
+ text: formatter
13560
13586
  };
13561
13587
  function getFormatter(name) {
13562
13588
  return availableFormatters[name] ?? null;