html-validate 7.12.1 → 7.12.2

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
@@ -3621,7 +3621,7 @@ class Rule {
3621
3621
  }
3622
3622
  }
3623
3623
 
3624
- const defaults$v = {
3624
+ const defaults$w = {
3625
3625
  allowExternal: true,
3626
3626
  allowRelative: true,
3627
3627
  allowAbsolute: true,
@@ -3665,7 +3665,7 @@ function matchList(value, list) {
3665
3665
  }
3666
3666
  class AllowedLinks extends Rule {
3667
3667
  constructor(options) {
3668
- super({ ...defaults$v, ...options });
3668
+ super({ ...defaults$w, ...options });
3669
3669
  this.allowExternal = parseAllow(this.options.allowExternal);
3670
3670
  this.allowRelative = parseAllow(this.options.allowRelative);
3671
3671
  this.allowAbsolute = parseAllow(this.options.allowAbsolute);
@@ -3813,7 +3813,7 @@ var RuleContext$1;
3813
3813
  RuleContext["MISSING_ALT"] = "missing-alt";
3814
3814
  RuleContext["MISSING_HREF"] = "missing-href";
3815
3815
  })(RuleContext$1 || (RuleContext$1 = {}));
3816
- const defaults$u = {
3816
+ const defaults$v = {
3817
3817
  accessible: true,
3818
3818
  };
3819
3819
  function findByTarget(target, siblings) {
@@ -3851,7 +3851,7 @@ function getDescription$1(context) {
3851
3851
  }
3852
3852
  class AreaAlt extends Rule {
3853
3853
  constructor(options) {
3854
- super({ ...defaults$u, ...options });
3854
+ super({ ...defaults$v, ...options });
3855
3855
  }
3856
3856
  static schema() {
3857
3857
  return {
@@ -4020,13 +4020,13 @@ class ConfigError extends UserError {
4020
4020
  }
4021
4021
  }
4022
4022
 
4023
- const defaults$t = {
4023
+ const defaults$u = {
4024
4024
  style: "lowercase",
4025
4025
  ignoreForeign: true,
4026
4026
  };
4027
4027
  class AttrCase extends Rule {
4028
4028
  constructor(options) {
4029
- super({ ...defaults$t, ...options });
4029
+ super({ ...defaults$u, ...options });
4030
4030
  this.style = new CaseStyle(this.options.style, "attr-case");
4031
4031
  }
4032
4032
  static schema() {
@@ -4371,7 +4371,7 @@ class AttrDelimiter extends Rule {
4371
4371
  }
4372
4372
 
4373
4373
  const DEFAULT_PATTERN = "[a-z0-9-:]+";
4374
- const defaults$s = {
4374
+ const defaults$t = {
4375
4375
  pattern: DEFAULT_PATTERN,
4376
4376
  ignoreForeign: true,
4377
4377
  };
@@ -4408,7 +4408,7 @@ function generateDescription(name, pattern) {
4408
4408
  }
4409
4409
  class AttrPattern extends Rule {
4410
4410
  constructor(options) {
4411
- super({ ...defaults$s, ...options });
4411
+ super({ ...defaults$t, ...options });
4412
4412
  this.pattern = generateRegexp(this.options.pattern);
4413
4413
  }
4414
4414
  static schema() {
@@ -4469,7 +4469,7 @@ var QuoteStyle;
4469
4469
  QuoteStyle["AUTO_QUOTE"] = "auto";
4470
4470
  QuoteStyle["ANY_QUOTE"] = "any";
4471
4471
  })(QuoteStyle || (QuoteStyle = {}));
4472
- const defaults$r = {
4472
+ const defaults$s = {
4473
4473
  style: "auto",
4474
4474
  unquoted: false,
4475
4475
  };
@@ -4536,7 +4536,7 @@ class AttrQuotes extends Rule {
4536
4536
  };
4537
4537
  }
4538
4538
  constructor(options) {
4539
- super({ ...defaults$r, ...options });
4539
+ super({ ...defaults$s, ...options });
4540
4540
  this.style = parseStyle$4(this.options.style);
4541
4541
  }
4542
4542
  setup() {
@@ -4706,12 +4706,12 @@ class AttributeAllowedValues extends Rule {
4706
4706
  }
4707
4707
  }
4708
4708
 
4709
- const defaults$q = {
4709
+ const defaults$r = {
4710
4710
  style: "omit",
4711
4711
  };
4712
4712
  class AttributeBooleanStyle extends Rule {
4713
4713
  constructor(options) {
4714
- super({ ...defaults$q, ...options });
4714
+ super({ ...defaults$r, ...options });
4715
4715
  this.hasInvalidStyle = parseStyle$3(this.options.style);
4716
4716
  }
4717
4717
  static schema() {
@@ -4787,12 +4787,12 @@ function reportMessage$1(attr, style) {
4787
4787
  return "";
4788
4788
  }
4789
4789
 
4790
- const defaults$p = {
4790
+ const defaults$q = {
4791
4791
  style: "omit",
4792
4792
  };
4793
4793
  class AttributeEmptyStyle extends Rule {
4794
4794
  constructor(options) {
4795
- super({ ...defaults$p, ...options });
4795
+ super({ ...defaults$q, ...options });
4796
4796
  this.hasInvalidStyle = parseStyle$2(this.options.style);
4797
4797
  }
4798
4798
  static schema() {
@@ -4948,12 +4948,12 @@ function describePattern(pattern) {
4948
4948
  }
4949
4949
  }
4950
4950
 
4951
- const defaults$o = {
4951
+ const defaults$p = {
4952
4952
  pattern: "kebabcase",
4953
4953
  };
4954
4954
  class ClassPattern extends Rule {
4955
4955
  constructor(options) {
4956
- super({ ...defaults$o, ...options });
4956
+ super({ ...defaults$p, ...options });
4957
4957
  this.pattern = parsePattern(this.options.pattern);
4958
4958
  }
4959
4959
  static schema() {
@@ -5062,13 +5062,13 @@ class CloseOrder extends Rule {
5062
5062
  }
5063
5063
  }
5064
5064
 
5065
- const defaults$n = {
5065
+ const defaults$o = {
5066
5066
  include: null,
5067
5067
  exclude: null,
5068
5068
  };
5069
5069
  class Deprecated extends Rule {
5070
5070
  constructor(options) {
5071
- super({ ...defaults$n, ...options });
5071
+ super({ ...defaults$o, ...options });
5072
5072
  }
5073
5073
  static schema() {
5074
5074
  return {
@@ -5231,12 +5231,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
5231
5231
  }
5232
5232
  };
5233
5233
 
5234
- const defaults$m = {
5234
+ const defaults$n = {
5235
5235
  style: "uppercase",
5236
5236
  };
5237
5237
  class DoctypeStyle extends Rule {
5238
5238
  constructor(options) {
5239
- super({ ...defaults$m, ...options });
5239
+ super({ ...defaults$n, ...options });
5240
5240
  }
5241
5241
  static schema() {
5242
5242
  return {
@@ -5268,12 +5268,12 @@ class DoctypeStyle extends Rule {
5268
5268
  }
5269
5269
  }
5270
5270
 
5271
- const defaults$l = {
5271
+ const defaults$m = {
5272
5272
  style: "lowercase",
5273
5273
  };
5274
5274
  class ElementCase extends Rule {
5275
5275
  constructor(options) {
5276
- super({ ...defaults$l, ...options });
5276
+ super({ ...defaults$m, ...options });
5277
5277
  this.style = new CaseStyle(this.options.style, "element-case");
5278
5278
  }
5279
5279
  static schema() {
@@ -5339,14 +5339,14 @@ class ElementCase extends Rule {
5339
5339
  }
5340
5340
  }
5341
5341
 
5342
- const defaults$k = {
5342
+ const defaults$l = {
5343
5343
  pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
5344
5344
  whitelist: [],
5345
5345
  blacklist: [],
5346
5346
  };
5347
5347
  class ElementName extends Rule {
5348
5348
  constructor(options) {
5349
- super({ ...defaults$k, ...options });
5349
+ super({ ...defaults$l, ...options });
5350
5350
  // eslint-disable-next-line security/detect-non-literal-regexp
5351
5351
  this.pattern = new RegExp(this.options.pattern);
5352
5352
  }
@@ -5387,7 +5387,7 @@ class ElementName extends Rule {
5387
5387
  ...context.blacklist.map((cur) => `- ${cur}`),
5388
5388
  ];
5389
5389
  }
5390
- if (context.pattern !== defaults$k.pattern) {
5390
+ if (context.pattern !== defaults$l.pattern) {
5391
5391
  return [
5392
5392
  `<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
5393
5393
  "",
@@ -5931,29 +5931,70 @@ class EmptyTitle extends Rule {
5931
5931
  }
5932
5932
  }
5933
5933
 
5934
+ const defaults$k = {
5935
+ allowArrayBrackets: true,
5936
+ shared: ["radio"],
5937
+ };
5934
5938
  const UNIQUE_CACHE_KEY = Symbol("form-elements-unique");
5935
5939
  const SHARED_CACHE_KEY = Symbol("form-elements-shared");
5936
5940
  function haveName(name) {
5937
5941
  return typeof name === "string" && name !== "";
5938
5942
  }
5939
- function allowSharedName(node) {
5943
+ function allowSharedName(node, shared) {
5940
5944
  const type = node.getAttribute("type");
5941
- return Boolean(type && type.valueMatches(["radio", "checkbox"], false));
5945
+ return Boolean(type && type.valueMatches(shared, false));
5946
+ }
5947
+ function getDocumentation(context) {
5948
+ const trailer = "Each form control must have a unique name.";
5949
+ if (!context) {
5950
+ return trailer;
5951
+ }
5952
+ else {
5953
+ const { name } = context;
5954
+ switch (context.kind) {
5955
+ case "duplicate":
5956
+ return [`Duplicate form control name "${name}"`, trailer].join("\n");
5957
+ case "mix":
5958
+ return [
5959
+ `Form control name cannot mix regular name "{{ name }}" with array brackets "{{ name }}[]"`,
5960
+ trailer,
5961
+ ].join("\n");
5962
+ }
5963
+ }
5942
5964
  }
5943
5965
  class FormDupName extends Rule {
5944
- documentation() {
5966
+ constructor(options) {
5967
+ super({ ...defaults$k, ...options });
5968
+ }
5969
+ static schema() {
5945
5970
  return {
5946
- description: "Each form control must have a unique name.",
5971
+ allowArrayBrackets: {
5972
+ type: "boolean",
5973
+ },
5974
+ shared: {
5975
+ type: "array",
5976
+ items: {
5977
+ enum: ["radio", "checkbox", "submit"],
5978
+ },
5979
+ },
5980
+ };
5981
+ }
5982
+ documentation(context) {
5983
+ return {
5984
+ description: getDocumentation(context),
5947
5985
  url: "https://html-validate.org/rules/form-dup-name.html",
5948
5986
  };
5949
5987
  }
5950
5988
  setup() {
5951
5989
  const selector = this.getSelector();
5990
+ const { shared } = this.options;
5952
5991
  this.on("dom:ready", (event) => {
5953
5992
  var _a, _b;
5954
5993
  const { document } = event;
5955
5994
  const controls = document.querySelectorAll(selector);
5956
- const [sharedControls, uniqueControls] = partition(controls, allowSharedName);
5995
+ const [sharedControls, uniqueControls] = partition(controls, (it) => {
5996
+ return allowSharedName(it, shared);
5997
+ });
5957
5998
  /* validate all form controls which require unique elements first so each
5958
5999
  * form has a populated list of unique names */
5959
6000
  for (const control of uniqueControls) {
@@ -5980,9 +6021,35 @@ class FormDupName extends Rule {
5980
6021
  }
5981
6022
  validateUniqueName(control, form, attr, name) {
5982
6023
  const elements = this.getUniqueElements(form);
6024
+ const { allowArrayBrackets } = this.options;
6025
+ if (allowArrayBrackets) {
6026
+ const isarray = name.endsWith("[]");
6027
+ const basename = isarray ? name.slice(0, -2) : name;
6028
+ const details = elements.get(basename);
6029
+ if (details && details.array !== isarray) {
6030
+ const context = {
6031
+ name: basename,
6032
+ kind: "mix",
6033
+ };
6034
+ this.report({
6035
+ node: control,
6036
+ location: attr.valueLocation,
6037
+ message: 'Cannot mix "{{ name }}[]" and "{{ name }}"',
6038
+ context,
6039
+ });
6040
+ return;
6041
+ }
6042
+ else if (!details && isarray) {
6043
+ elements.set(basename, {
6044
+ array: true,
6045
+ });
6046
+ return;
6047
+ }
6048
+ }
5983
6049
  if (elements.has(name)) {
5984
6050
  const context = {
5985
6051
  name,
6052
+ kind: "duplicate",
5986
6053
  };
5987
6054
  this.report({
5988
6055
  node: control,
@@ -5992,7 +6059,9 @@ class FormDupName extends Rule {
5992
6059
  });
5993
6060
  }
5994
6061
  else {
5995
- elements.add(name);
6062
+ elements.set(name, {
6063
+ array: false,
6064
+ });
5996
6065
  }
5997
6066
  }
5998
6067
  validateSharedName(control, form, attr, name) {
@@ -6005,6 +6074,7 @@ class FormDupName extends Rule {
6005
6074
  (sharedElements.has(name) && sharedElements.get(name) !== type)) {
6006
6075
  const context = {
6007
6076
  name,
6077
+ kind: "duplicate",
6008
6078
  };
6009
6079
  this.report({
6010
6080
  node: control,
@@ -6036,7 +6106,7 @@ class FormDupName extends Rule {
6036
6106
  return existing;
6037
6107
  }
6038
6108
  else {
6039
- const elements = new Set();
6109
+ const elements = new Map();
6040
6110
  form.cacheSet(UNIQUE_CACHE_KEY, elements);
6041
6111
  return elements;
6042
6112
  }
@@ -11435,7 +11505,7 @@ class HtmlValidate {
11435
11505
  /** @public */
11436
11506
  const name = "html-validate";
11437
11507
  /** @public */
11438
- const version = "7.12.1";
11508
+ const version = "7.12.2";
11439
11509
  /** @public */
11440
11510
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11441
11511