html-validate 9.2.1 → 9.3.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/es/core.js CHANGED
@@ -436,7 +436,7 @@ class UserError extends NestedError {
436
436
  */
437
437
  /* istanbul ignore next: default implementation */
438
438
  prettyFormat() {
439
- return undefined;
439
+ return void 0;
440
440
  }
441
441
  }
442
442
 
@@ -943,7 +943,7 @@ const ajvRegexpValidate = function(data, dataCxt) {
943
943
  ajvRegexpValidate.errors = [
944
944
  {
945
945
  instancePath: dataCxt?.instancePath,
946
- schemaPath: undefined,
946
+ schemaPath: void 0,
947
947
  keyword: "type",
948
948
  message: "should be a regular expression",
949
949
  params: {
@@ -970,7 +970,7 @@ const ajvFunctionValidate = function(data, dataCxt) {
970
970
  /* istanbul ignore next */
971
971
  dataCxt?.instancePath
972
972
  ),
973
- schemaPath: undefined,
973
+ schemaPath: void 0,
974
974
  keyword: "type",
975
975
  message: "should be a function",
976
976
  params: {
@@ -1025,7 +1025,7 @@ function isSet(value) {
1025
1025
  return typeof value !== "undefined";
1026
1026
  }
1027
1027
  function flag(value) {
1028
- return value ? true : undefined;
1028
+ return value ? true : void 0;
1029
1029
  }
1030
1030
  function stripUndefined(src) {
1031
1031
  const entries = Object.entries(src).filter(([, value]) => isSet(value));
@@ -1035,8 +1035,8 @@ function migrateSingleAttribute(src, key) {
1035
1035
  const result = {};
1036
1036
  result.deprecated = flag(src.deprecatedAttributes?.includes(key));
1037
1037
  result.required = flag(src.requiredAttributes?.includes(key));
1038
- result.omit = undefined;
1039
- const attr = src.attributes ? src.attributes[key] : undefined;
1038
+ result.omit = void 0;
1039
+ const attr = src.attributes ? src.attributes[key] : void 0;
1040
1040
  if (typeof attr === "undefined") {
1041
1041
  return stripUndefined(result);
1042
1042
  }
@@ -1092,7 +1092,7 @@ function migrateElement(src) {
1092
1092
  const result = {
1093
1093
  ...src,
1094
1094
  ...{
1095
- formAssociated: undefined
1095
+ formAssociated: void 0
1096
1096
  },
1097
1097
  attributes: migrateAttributes(src),
1098
1098
  textContent: src.textContent,
@@ -1630,7 +1630,7 @@ class DOMNode {
1630
1630
  if (this.cache) {
1631
1631
  return this.cache.get(key);
1632
1632
  } else {
1633
- return undefined;
1633
+ return void 0;
1634
1634
  }
1635
1635
  }
1636
1636
  cacheSet(key, value) {
@@ -1890,7 +1890,7 @@ function parseCombinator(combinator, pattern) {
1890
1890
  return 5 /* SCOPE */;
1891
1891
  }
1892
1892
  switch (combinator) {
1893
- case undefined:
1893
+ case void 0:
1894
1894
  case null:
1895
1895
  case "":
1896
1896
  return 1 /* DESCENDANT */;
@@ -2122,7 +2122,7 @@ class AttrMatcher extends Matcher {
2122
2122
  const attr = node.getAttribute(this.key, true);
2123
2123
  return attr.some((cur) => {
2124
2124
  switch (this.op) {
2125
- case undefined:
2125
+ case void 0:
2126
2126
  return true;
2127
2127
  /* attribute exists */
2128
2128
  case "=":
@@ -2595,7 +2595,7 @@ class HtmlElement extends DOMNode {
2595
2595
  */
2596
2596
  get role() {
2597
2597
  const cached = this.cacheGet(ROLE);
2598
- if (cached !== undefined) {
2598
+ if (cached !== void 0) {
2599
2599
  return cached;
2600
2600
  }
2601
2601
  const role = this.getAttribute("role");
@@ -2653,7 +2653,7 @@ class HtmlElement extends DOMNode {
2653
2653
  */
2654
2654
  get tabIndex() {
2655
2655
  const cached = this.cacheGet(TABINDEX);
2656
- if (cached !== undefined) {
2656
+ if (cached !== void 0) {
2657
2657
  return cached;
2658
2658
  }
2659
2659
  const tabindex = this.getAttribute("tabindex");
@@ -4598,7 +4598,7 @@ const MATCH_DOCTYPE_OPEN = /^<!(DOCTYPE)\s/i;
4598
4598
  const MATCH_DOCTYPE_VALUE = /^[^>]+/;
4599
4599
  const MATCH_DOCTYPE_CLOSE = /^>/;
4600
4600
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4601
- const MATCH_TAG_OPEN = /^<(\/?)([a-zA-Z0-9\-:]+)/;
4601
+ const MATCH_TAG_OPEN = /^<(\/?)([a-zA-Z0-9\-_:]+)/;
4602
4602
  const MATCH_TAG_CLOSE = /^\/?>/;
4603
4603
  const MATCH_TEXT = /^[^]*?(?=(?:[ \t]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4604
4604
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
@@ -6598,7 +6598,7 @@ const defaults$j = {
6598
6598
  minInitialRank: "h1",
6599
6599
  sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
6600
6600
  };
6601
- function isRelevant$6(event) {
6601
+ function isRelevant$5(event) {
6602
6602
  const node = event.target;
6603
6603
  return Boolean(node.meta?.heading);
6604
6604
  }
@@ -6667,7 +6667,7 @@ class HeadingLevel extends Rule {
6667
6667
  };
6668
6668
  }
6669
6669
  setup() {
6670
- this.on("tag:start", isRelevant$6, (event) => {
6670
+ this.on("tag:start", isRelevant$5, (event) => {
6671
6671
  this.onTagStart(event);
6672
6672
  });
6673
6673
  this.on("tag:ready", (event) => {
@@ -7323,7 +7323,7 @@ class MapDupName extends Rule {
7323
7323
  }
7324
7324
  }
7325
7325
 
7326
- function isRelevant$5(event) {
7326
+ function isRelevant$4(event) {
7327
7327
  return event.target.is("map");
7328
7328
  }
7329
7329
  function hasStaticValue(attr) {
@@ -7337,7 +7337,7 @@ class MapIdName extends Rule {
7337
7337
  };
7338
7338
  }
7339
7339
  setup() {
7340
- this.on("tag:ready", isRelevant$5, (event) => {
7340
+ this.on("tag:ready", isRelevant$4, (event) => {
7341
7341
  const { target } = event;
7342
7342
  const id = target.getAttribute("id");
7343
7343
  const name = target.getAttribute("name");
@@ -7461,7 +7461,7 @@ const abstractRoles = [
7461
7461
  "widget",
7462
7462
  "window"
7463
7463
  ];
7464
- function isRelevant$4(event) {
7464
+ function isRelevant$3(event) {
7465
7465
  return event.key === "role";
7466
7466
  }
7467
7467
  class NoAbstractRole extends Rule {
@@ -7480,7 +7480,7 @@ class NoAbstractRole extends Rule {
7480
7480
  };
7481
7481
  }
7482
7482
  setup() {
7483
- this.on("attr", isRelevant$4, (event) => {
7483
+ this.on("attr", isRelevant$3, (event) => {
7484
7484
  const roles = event.value;
7485
7485
  if (!roles || roles instanceof DynamicValue) {
7486
7486
  return;
@@ -7681,17 +7681,25 @@ class NoDupID extends Rule {
7681
7681
  setup() {
7682
7682
  this.on("dom:ready", (event) => {
7683
7683
  const { document } = event;
7684
+ const rootExisting = getExisting(document.root, document.root);
7685
+ const useRootExisting = !document.querySelector("template");
7684
7686
  const elements = document.querySelectorAll("[id]");
7685
- const relevant = elements.filter(isRelevant$3);
7686
- for (const el of relevant) {
7687
+ for (const el of elements) {
7687
7688
  const attr = el.getAttribute("id");
7688
- if (!attr?.value) {
7689
+ if (!attr) {
7690
+ continue;
7691
+ }
7692
+ if (!attr.value) {
7693
+ continue;
7694
+ }
7695
+ if (attr.isDynamic) {
7689
7696
  continue;
7690
7697
  }
7691
7698
  const id = attr.value.toString();
7692
- const existing = getExisting(el, document.root);
7699
+ const existing = useRootExisting ? rootExisting : getExisting(el, document.root);
7693
7700
  if (existing.has(id)) {
7694
7701
  this.report(el, `Duplicate ID "${id}"`, attr.valueLocation);
7702
+ continue;
7695
7703
  }
7696
7704
  existing.add(id);
7697
7705
  }
@@ -7708,19 +7716,6 @@ function getExisting(element, root) {
7708
7716
  return group.cacheSet(CACHE_KEY, existing2);
7709
7717
  }
7710
7718
  }
7711
- function isRelevant$3(element) {
7712
- const attr = element.getAttribute("id");
7713
- if (!attr) {
7714
- return false;
7715
- }
7716
- if (!attr.value) {
7717
- return false;
7718
- }
7719
- if (attr.isDynamic) {
7720
- return false;
7721
- }
7722
- return true;
7723
- }
7724
7719
 
7725
7720
  function isRelevant$2(event) {
7726
7721
  return event.target.is("button");
@@ -9961,14 +9956,15 @@ class ValidID extends Rule {
9961
9956
  }
9962
9957
  documentation(context) {
9963
9958
  const { relaxed } = this.options;
9964
- const message = this.messages[context].replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9959
+ const { kind, id } = context;
9960
+ const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9965
9961
  const relaxedDescription = relaxed ? [] : [
9966
9962
  " - ID must begin with a letter",
9967
9963
  " - ID must only contain letters, digits, `-` and `_`"
9968
9964
  ];
9969
9965
  return {
9970
9966
  description: [
9971
- `${message}.`,
9967
+ `${interpolate(message, { id })}.`,
9972
9968
  "",
9973
9969
  "Under the current configuration the following rules are applied:",
9974
9970
  "",
@@ -9986,13 +9982,13 @@ class ValidID extends Rule {
9986
9982
  return;
9987
9983
  }
9988
9984
  if (value === "") {
9989
- const context = 1 /* EMPTY */;
9990
- this.report(event.target, this.messages[context], event.location, context);
9985
+ const context = { kind: 1 /* EMPTY */, id: value };
9986
+ this.report(event.target, this.messages[context.kind], event.location, context);
9991
9987
  return;
9992
9988
  }
9993
9989
  if (value.match(/\s/)) {
9994
- const context = 2 /* WHITESPACE */;
9995
- this.report(event.target, this.messages[context], event.valueLocation, context);
9990
+ const context = { kind: 2 /* WHITESPACE */, id: value };
9991
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
9996
9992
  return;
9997
9993
  }
9998
9994
  const { relaxed } = this.options;
@@ -10000,22 +9996,22 @@ class ValidID extends Rule {
10000
9996
  return;
10001
9997
  }
10002
9998
  if (value.match(/^[^\p{L}]/u)) {
10003
- const context = 3 /* LEADING_CHARACTER */;
10004
- this.report(event.target, this.messages[context], event.valueLocation, context);
9999
+ const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10000
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10005
10001
  return;
10006
10002
  }
10007
10003
  if (value.match(/[^\p{L}\p{N}_-]/u)) {
10008
- const context = 4 /* DISALLOWED_CHARACTER */;
10009
- this.report(event.target, this.messages[context], event.valueLocation, context);
10004
+ const context = { kind: 4 /* DISALLOWED_CHARACTER */, id: value };
10005
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10010
10006
  }
10011
10007
  });
10012
10008
  }
10013
10009
  get messages() {
10014
10010
  return {
10015
- [1 /* EMPTY */]: "element id must not be empty",
10016
- [2 /* WHITESPACE */]: "element id must not contain whitespace",
10017
- [3 /* LEADING_CHARACTER */]: "element id must begin with a letter",
10018
- [4 /* DISALLOWED_CHARACTER */]: "element id must only contain letters, digits, dash and underscore characters"
10011
+ [1 /* EMPTY */]: `element id "{{ id }}" must not be empty`,
10012
+ [2 /* WHITESPACE */]: `element id "{{ id }}" must not contain whitespace`,
10013
+ [3 /* LEADING_CHARACTER */]: `element id "{{ id }}" must begin with a letter`,
10014
+ [4 /* DISALLOWED_CHARACTER */]: `element id "{{ id }}" must only contain letters, digits, dash and underscore characters`
10019
10015
  };
10020
10016
  }
10021
10017
  isRelevant(event) {
@@ -10080,29 +10076,41 @@ class VoidStyle extends Rule {
10080
10076
  };
10081
10077
  }
10082
10078
  setup() {
10079
+ const { style } = this;
10080
+ const validateStyle = {
10081
+ [1 /* AlwaysOmit */]: this.validateOmitted.bind(this),
10082
+ [2 /* AlwaysSelfclose */]: this.validateSelfClosed.bind(this)
10083
+ }[style];
10083
10084
  this.on("tag:end", (event) => {
10084
10085
  const active = event.previous;
10085
10086
  if (active.meta) {
10086
- this.validateActive(active);
10087
+ validateStyle(active);
10087
10088
  }
10088
10089
  });
10089
10090
  }
10090
- validateActive(node) {
10091
+ validateOmitted(node) {
10091
10092
  if (!node.voidElement) {
10092
10093
  return;
10093
10094
  }
10094
- if (this.shouldBeOmitted(node)) {
10095
- this.reportError(
10096
- node,
10097
- `Expected omitted end tag <${node.tagName}> instead of self-closing element <${node.tagName}/>`
10098
- );
10095
+ if (node.closed !== NodeClosed.VoidSelfClosed) {
10096
+ return;
10099
10097
  }
10100
- if (this.shouldBeSelfClosed(node)) {
10101
- this.reportError(
10102
- node,
10103
- `Expected self-closing element <${node.tagName}/> instead of omitted end-tag <${node.tagName}>`
10104
- );
10098
+ this.reportError(
10099
+ node,
10100
+ `Expected omitted end tag <${node.tagName}> instead of self-closing element <${node.tagName}/>`
10101
+ );
10102
+ }
10103
+ validateSelfClosed(node) {
10104
+ if (!node.voidElement) {
10105
+ return;
10106
+ }
10107
+ if (node.closed !== NodeClosed.VoidOmitted) {
10108
+ return;
10105
10109
  }
10110
+ this.reportError(
10111
+ node,
10112
+ `Expected self-closing element <${node.tagName}/> instead of omitted end-tag <${node.tagName}>`
10113
+ );
10106
10114
  }
10107
10115
  reportError(node, message) {
10108
10116
  const context = {
@@ -10111,12 +10119,6 @@ class VoidStyle extends Rule {
10111
10119
  };
10112
10120
  super.report(node, message, null, context);
10113
10121
  }
10114
- shouldBeOmitted(node) {
10115
- return this.style === 1 /* AlwaysOmit */ && node.closed === NodeClosed.VoidSelfClosed;
10116
- }
10117
- shouldBeSelfClosed(node) {
10118
- return this.style === 2 /* AlwaysSelfclose */ && node.closed === NodeClosed.VoidOmitted;
10119
- }
10120
10122
  }
10121
10123
  function parseStyle(name) {
10122
10124
  switch (name) {
@@ -11956,7 +11958,7 @@ class Parser {
11956
11958
  */
11957
11959
  getAttributeLocation(key, value) {
11958
11960
  const begin = key.location;
11959
- const end = value && value.type === TokenType.ATTR_VALUE ? value.location : undefined;
11961
+ const end = value && value.type === TokenType.ATTR_VALUE ? value.location : void 0;
11960
11962
  return {
11961
11963
  filename: begin.filename,
11962
11964
  line: begin.line,
@@ -11995,8 +11997,8 @@ class Parser {
11995
11997
  actionOffset,
11996
11998
  actionOffset + action.length
11997
11999
  );
11998
- const optionsLocation = data ? sliceLocation(token.location, optionsOffset, optionsOffset + data.length) : undefined;
11999
- const commentLocation = comment ? sliceLocation(token.location, commentOffset, commentOffset + comment.length) : undefined;
12000
+ const optionsLocation = data ? sliceLocation(token.location, optionsOffset, optionsOffset + data.length) : void 0;
12001
+ const commentLocation = comment ? sliceLocation(token.location, commentOffset, commentOffset + comment.length) : void 0;
12000
12002
  this.trigger("directive", {
12001
12003
  action,
12002
12004
  data,
@@ -12363,7 +12365,7 @@ class Engine {
12363
12365
  rules
12364
12366
  };
12365
12367
  parser.trigger("config:ready", configEvent);
12366
- const { ...sourceData } = source;
12368
+ const { hooks: _, ...sourceData } = source;
12367
12369
  const sourceEvent = {
12368
12370
  location,
12369
12371
  source: sourceData
@@ -12937,13 +12939,13 @@ function isConfigData(value) {
12937
12939
  class HtmlValidate {
12938
12940
  configLoader;
12939
12941
  constructor(arg) {
12940
- const [loader, config] = arg instanceof ConfigLoader ? [arg, undefined] : [undefined, arg];
12942
+ const [loader, config] = arg instanceof ConfigLoader ? [arg, void 0] : [void 0, arg];
12941
12943
  this.configLoader = loader ?? new StaticConfigLoader(config);
12942
12944
  }
12943
12945
  /* eslint-enable @typescript-eslint/unified-signatures */
12944
12946
  validateString(str, arg1, arg2, arg3) {
12945
12947
  const filename = typeof arg1 === "string" ? arg1 : "inline";
12946
- const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : undefined;
12948
+ const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : void 0;
12947
12949
  const hooks = isSourceHooks(arg1) ? arg1 : isSourceHooks(arg2) ? arg2 : arg3;
12948
12950
  const source = {
12949
12951
  data: str,
@@ -12958,7 +12960,7 @@ class HtmlValidate {
12958
12960
  /* eslint-enable @typescript-eslint/unified-signatures */
12959
12961
  validateStringSync(str, arg1, arg2, arg3) {
12960
12962
  const filename = typeof arg1 === "string" ? arg1 : "inline";
12961
- const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : undefined;
12963
+ const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : void 0;
12962
12964
  const hooks = isSourceHooks(arg1) ? arg1 : isSourceHooks(arg2) ? arg2 : arg3;
12963
12965
  const source = {
12964
12966
  data: str,
@@ -13339,7 +13341,7 @@ class HtmlValidate {
13339
13341
  }
13340
13342
 
13341
13343
  const name = "html-validate";
13342
- const version = "9.2.1";
13344
+ const version = "9.3.0";
13343
13345
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
13344
13346
 
13345
13347
  function definePlugin(plugin) {