html-validate 6.9.0 → 6.11.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
@@ -243,6 +243,42 @@ var ajvSchemaDraft = {
243
243
  }
244
244
  };
245
245
 
246
+ function stringify(value) {
247
+ if (typeof value === "string") {
248
+ return String(value);
249
+ }
250
+ else {
251
+ return JSON.stringify(value);
252
+ }
253
+ }
254
+ /**
255
+ * Represents an `Error` created from arbitrary values.
256
+ *
257
+ * @public
258
+ */
259
+ class WrappedError extends Error {
260
+ constructor(message) {
261
+ super(stringify(message));
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Ensures the value is an Error.
267
+ *
268
+ * If the passed value is not an `Error` instance a [[WrappedError]] is
269
+ * constructed with the stringified value.
270
+ *
271
+ * @internal
272
+ */
273
+ function ensureError(value) {
274
+ if (value instanceof Error) {
275
+ return value;
276
+ }
277
+ else {
278
+ return new WrappedError(value);
279
+ }
280
+ }
281
+
246
282
  class NestedError extends Error {
247
283
  constructor(message, nested) {
248
284
  super(message);
@@ -296,6 +332,32 @@ class SchemaValidationError extends UserError {
296
332
  }
297
333
  }
298
334
 
335
+ /**
336
+ * Computes hash for given string.
337
+ *
338
+ * @internal
339
+ */
340
+ function cyrb53(str) {
341
+ const a = 2654435761;
342
+ const b = 1597334677;
343
+ const c = 2246822507;
344
+ const d = 3266489909;
345
+ const e = 4294967296;
346
+ const f = 2097151;
347
+ const seed = 0;
348
+ let h1 = 0xdeadbeef ^ seed;
349
+ let h2 = 0x41c6ce57 ^ seed;
350
+ for (let i = 0, ch; i < str.length; i++) {
351
+ ch = str.charCodeAt(i);
352
+ h1 = Math.imul(h1 ^ ch, a);
353
+ h2 = Math.imul(h2 ^ ch, b);
354
+ }
355
+ h1 = Math.imul(h1 ^ (h1 >>> 16), c) ^ Math.imul(h2 ^ (h2 >>> 13), d);
356
+ h2 = Math.imul(h2 ^ (h2 >>> 16), c) ^ Math.imul(h1 ^ (h1 >>> 13), d);
357
+ return e * (f & h2) + (h1 >>> 0);
358
+ }
359
+ const computeHash = cyrb53;
360
+
299
361
  const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../");
300
362
  const legacyRequire = createRequire(import.meta.url);
301
363
  const distFolder = path.resolve(projectRoot, "dist/es");
@@ -700,6 +762,35 @@ var schema = {
700
762
  definitions: definitions
701
763
  };
702
764
 
765
+ /**
766
+ * AJV keyword "regexp" to validate the type to be a regular expression.
767
+ * Injects errors with the "type" keyword to give the same output.
768
+ */
769
+ /* istanbul ignore next: manual testing */
770
+ const ajvRegexpValidate = function (data, dataCxt) {
771
+ const valid = data instanceof RegExp;
772
+ if (!valid) {
773
+ ajvRegexpValidate.errors = [
774
+ {
775
+ instancePath: dataCxt === null || dataCxt === void 0 ? void 0 : dataCxt.instancePath,
776
+ schemaPath: undefined,
777
+ keyword: "type",
778
+ message: "should be a regular expression",
779
+ params: {
780
+ keyword: "type",
781
+ },
782
+ },
783
+ ];
784
+ }
785
+ return valid;
786
+ };
787
+ const ajvRegexpKeyword = {
788
+ keyword: "regexp",
789
+ schema: false,
790
+ errors: true,
791
+ validate: ajvRegexpValidate,
792
+ };
793
+
703
794
  var TextContent$1;
704
795
  (function (TextContent) {
705
796
  /* forbid node to have text content, inter-element whitespace is ignored */
@@ -807,6 +898,43 @@ function migrateElement(src) {
807
898
  return result;
808
899
  }
809
900
 
901
+ /**
902
+ * Returns true if given element is a descendant of given tagname.
903
+ *
904
+ * @internal
905
+ */
906
+ function isDescendant(node, tagName) {
907
+ let cur = node.parent;
908
+ while (cur && !cur.isRootElement()) {
909
+ if (cur.is(tagName)) {
910
+ return true;
911
+ }
912
+ cur = cur.parent;
913
+ }
914
+ return false;
915
+ }
916
+
917
+ /**
918
+ * Returns true if given element has given attribute (no matter the value, null,
919
+ * dynamic, etc).
920
+ */
921
+ function hasAttribute(node, attr) {
922
+ return node.hasAttribute(attr);
923
+ }
924
+
925
+ /**
926
+ * Matches attribute against value.
927
+ */
928
+ function matchAttribute(node, key, op, value) {
929
+ const nodeValue = (node.getAttributeValue(key) || "").toLowerCase();
930
+ switch (op) {
931
+ case "!=":
932
+ return nodeValue !== value;
933
+ case "=":
934
+ return nodeValue === value;
935
+ }
936
+ }
937
+
810
938
  const dynamicKeys = [
811
939
  "metadata",
812
940
  "flow",
@@ -818,44 +946,17 @@ const dynamicKeys = [
818
946
  "labelable",
819
947
  ];
820
948
  const functionTable = {
821
- isDescendant,
822
- hasAttribute,
823
- matchAttribute,
949
+ isDescendant: isDescendantFacade,
950
+ hasAttribute: hasAttributeFacade,
951
+ matchAttribute: matchAttributeFacade,
824
952
  };
953
+ const schemaCache = new Map();
825
954
  function clone(src) {
826
955
  return JSON.parse(JSON.stringify(src));
827
956
  }
828
957
  function overwriteMerge$1(a, b) {
829
958
  return b;
830
959
  }
831
- /**
832
- * AJV keyword "regexp" to validate the type to be a regular expression.
833
- * Injects errors with the "type" keyword to give the same output.
834
- */
835
- /* istanbul ignore next: manual testing */
836
- const ajvRegexpValidate = function (data, dataCxt) {
837
- const valid = data instanceof RegExp;
838
- if (!valid) {
839
- ajvRegexpValidate.errors = [
840
- {
841
- instancePath: dataCxt === null || dataCxt === void 0 ? void 0 : dataCxt.instancePath,
842
- schemaPath: undefined,
843
- keyword: "type",
844
- message: "should be regexp",
845
- params: {
846
- keyword: "type",
847
- },
848
- },
849
- ];
850
- }
851
- return valid;
852
- };
853
- const ajvRegexpKeyword = {
854
- keyword: "regexp",
855
- schema: false,
856
- errors: true,
857
- validate: ajvRegexpValidate,
858
- };
859
960
  /**
860
961
  * @public
861
962
  */
@@ -931,7 +1032,7 @@ class MetaTable {
931
1032
  if (err instanceof SchemaValidationError) {
932
1033
  throw err;
933
1034
  }
934
- throw new UserError(`Failed to load element metadata from "${filename}"`, err);
1035
+ throw new UserError(`Failed to load element metadata from "${filename}"`, ensureError(err));
935
1036
  }
936
1037
  }
937
1038
  /**
@@ -992,11 +1093,20 @@ class MetaTable {
992
1093
  * Construct a new AJV schema validator.
993
1094
  */
994
1095
  getSchemaValidator() {
995
- const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
996
- ajv.addMetaSchema(ajvSchemaDraft);
997
- ajv.addKeyword(ajvRegexpKeyword);
998
- ajv.addKeyword({ keyword: "copyable" });
999
- return ajv.compile(this.schema);
1096
+ const hash = computeHash(JSON.stringify(this.schema));
1097
+ const cached = schemaCache.get(hash);
1098
+ if (cached) {
1099
+ return cached;
1100
+ }
1101
+ else {
1102
+ const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
1103
+ ajv.addMetaSchema(ajvSchemaDraft);
1104
+ ajv.addKeyword(ajvRegexpKeyword);
1105
+ ajv.addKeyword({ keyword: "copyable" });
1106
+ const validate = ajv.compile(this.schema);
1107
+ schemaCache.set(hash, validate);
1108
+ return validate;
1109
+ }
1000
1110
  }
1001
1111
  /**
1002
1112
  * @public
@@ -1098,36 +1208,27 @@ function parseExpression(expr) {
1098
1208
  return [func, options];
1099
1209
  }
1100
1210
  }
1101
- function isDescendant(node, tagName) {
1211
+ function isDescendantFacade(node, tagName) {
1102
1212
  if (typeof tagName !== "string") {
1103
1213
  throw new Error(`Property expression "isDescendant" must take string argument when evaluating metadata for <${node.tagName}>`);
1104
1214
  }
1105
- let cur = node.parent;
1106
- while (cur && !cur.isRootElement()) {
1107
- if (cur.is(tagName)) {
1108
- return true;
1109
- }
1110
- cur = cur.parent;
1111
- }
1112
- return false;
1215
+ return isDescendant(node, tagName);
1113
1216
  }
1114
- function hasAttribute(node, attr) {
1217
+ function hasAttributeFacade(node, attr) {
1115
1218
  if (typeof attr !== "string") {
1116
1219
  throw new Error(`Property expression "hasAttribute" must take string argument when evaluating metadata for <${node.tagName}>`);
1117
1220
  }
1118
- return node.hasAttribute(attr);
1221
+ return hasAttribute(node, attr);
1119
1222
  }
1120
- function matchAttribute(node, match) {
1223
+ function matchAttributeFacade(node, match) {
1121
1224
  if (!Array.isArray(match) || match.length !== 3) {
1122
1225
  throw new Error(`Property expression "matchAttribute" must take [key, op, value] array as argument when evaluating metadata for <${node.tagName}>`);
1123
1226
  }
1124
1227
  const [key, op, value] = match.map((x) => x.toLowerCase());
1125
- const nodeValue = (node.getAttributeValue(key) || "").toLowerCase();
1126
1228
  switch (op) {
1127
1229
  case "!=":
1128
- return nodeValue !== value;
1129
1230
  case "=":
1130
- return nodeValue === value;
1231
+ return matchAttribute(node, key, op, value);
1131
1232
  default:
1132
1233
  throw new Error(`Property expression "matchAttribute" has invalid operator "${op}" when evaluating metadata for <${node.tagName}>`);
1133
1234
  }
@@ -2981,7 +3082,7 @@ var TRANSFORMER_API;
2981
3082
  /** @public */
2982
3083
  const name = "html-validate";
2983
3084
  /** @public */
2984
- const version = "6.9.0";
3085
+ const version = "6.11.0";
2985
3086
  /** @public */
2986
3087
  const homepage = "https://html-validate.org";
2987
3088
  /** @public */
@@ -3969,9 +4070,6 @@ class Lexer {
3969
4070
  }
3970
4071
 
3971
4072
  const whitespace = /(\s+)/;
3972
- function isRelevant$3(event) {
3973
- return event.type === TokenType.ATTR_VALUE;
3974
- }
3975
4073
  class AttrDelimiter extends Rule {
3976
4074
  documentation() {
3977
4075
  return {
@@ -3980,8 +4078,12 @@ class AttrDelimiter extends Rule {
3980
4078
  };
3981
4079
  }
3982
4080
  setup() {
3983
- this.on("token", isRelevant$3, (event) => {
3984
- const delimiter = event.data[1];
4081
+ this.on("token", (event) => {
4082
+ const { token } = event;
4083
+ if (token.type !== TokenType.ATTR_VALUE) {
4084
+ return;
4085
+ }
4086
+ const delimiter = token.data[1];
3985
4087
  const match = whitespace.exec(delimiter);
3986
4088
  if (match) {
3987
4089
  const location = sliceLocation(event.location, 0, delimiter.length);
@@ -10077,7 +10179,7 @@ class ResolvedConfig {
10077
10179
  }
10078
10180
  catch (err) {
10079
10181
  const message = err instanceof Error ? err.message : String(err);
10080
- throw new NestedError(`When transforming "${source.filename}": ${message}`, err);
10182
+ throw new NestedError(`When transforming "${source.filename}": ${message}`, ensureError(err));
10081
10183
  }
10082
10184
  }
10083
10185
  else {
@@ -10149,7 +10251,7 @@ function loadFromFile(filename) {
10149
10251
  json = requireUncached(filename);
10150
10252
  }
10151
10253
  catch (err) {
10152
- throw new ConfigError(`Failed to read configuration from "${filename}"`, err);
10254
+ throw new ConfigError(`Failed to read configuration from "${filename}"`, ensureError(err));
10153
10255
  }
10154
10256
  /* expand any relative paths */
10155
10257
  for (const key of ["extends", "elements", "plugins"]) {
@@ -10354,7 +10456,7 @@ class Config {
10354
10456
  }
10355
10457
  catch (err) {
10356
10458
  const message = err instanceof Error ? err.message : String(err);
10357
- throw new ConfigError(`Failed to load elements from "${entry}": ${message}`, err);
10459
+ throw new ConfigError(`Failed to load elements from "${entry}": ${message}`, ensureError(err));
10358
10460
  }
10359
10461
  }
10360
10462
  metaTable.init();
@@ -10431,7 +10533,7 @@ class Config {
10431
10533
  }
10432
10534
  catch (err) {
10433
10535
  const message = err instanceof Error ? err.message : String(err);
10434
- throw new ConfigError(`Failed to load plugin "${moduleName}": ${message}`, err);
10536
+ throw new ConfigError(`Failed to load plugin "${moduleName}": ${message}`, ensureError(err));
10435
10537
  }
10436
10538
  });
10437
10539
  }
@@ -10524,7 +10626,7 @@ class Config {
10524
10626
  throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
10525
10627
  }
10526
10628
  else {
10527
- throw new ConfigError(`Failed to load transformer "${name}"`, err);
10629
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
10528
10630
  }
10529
10631
  }
10530
10632
  });
@@ -11248,6 +11350,7 @@ class Parser {
11248
11350
  location: token.location,
11249
11351
  type: token.type,
11250
11352
  data: Array.from(token.data),
11353
+ token,
11251
11354
  });
11252
11355
  }
11253
11356
  return it;
@@ -11566,8 +11669,9 @@ class Engine {
11566
11669
  getRuleDocumentation(ruleId, context // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
11567
11670
  ) {
11568
11671
  const rules = this.config.getRules();
11569
- if (rules.has(ruleId)) {
11570
- const [, options] = rules.get(ruleId);
11672
+ const ruleData = rules.get(ruleId);
11673
+ if (ruleData) {
11674
+ const [, options] = ruleData;
11571
11675
  const rule = this.instantiateRule(ruleId, options);
11572
11676
  return rule.documentation(context);
11573
11677
  }
@@ -12498,5 +12602,5 @@ function getFormatter(name) {
12498
12602
  return (_a = availableFormatters[name]) !== null && _a !== void 0 ? _a : null;
12499
12603
  }
12500
12604
 
12501
- export { Config as C, DynamicValue as D, EventHandler as E, FileSystemConfigLoader as F, HtmlValidate as H, MetaTable as M, NodeClosed as N, Parser as P, Rule as R, Severity as S, TextNode as T, UserError as U, ConfigError as a, ConfigLoader as b, StaticConfigLoader as c, HtmlElement as d, SchemaValidationError as e, MetaCopyableProperty as f, Reporter as g, TemplateExtractor as h, getFormatter as i, compatibilityCheck as j, codeframe as k, legacyRequire as l, bugs as m, name as n, presets as p, ruleExists as r, version as v };
12605
+ export { Config as C, DynamicValue as D, EventHandler as E, FileSystemConfigLoader as F, HtmlValidate as H, MetaTable as M, NodeClosed as N, Parser as P, Rule as R, Severity as S, TextNode as T, UserError as U, WrappedError as W, ConfigError as a, ConfigLoader as b, StaticConfigLoader as c, HtmlElement as d, SchemaValidationError as e, NestedError as f, MetaCopyableProperty as g, Reporter as h, TemplateExtractor as i, getFormatter as j, ensureError as k, legacyRequire as l, compatibilityCheck as m, codeframe as n, name as o, presets as p, bugs as q, ruleExists as r, version as v };
12502
12606
  //# sourceMappingURL=core.js.map