html-validate 9.2.2 → 9.4.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
@@ -2,7 +2,6 @@ import Ajv from 'ajv';
2
2
  import { e as entities$1, h as html5, b as bundledElements } from './elements.js';
3
3
  import betterAjvErrors from '@sidvind/better-ajv-errors';
4
4
  import { n as naturalJoin } from './utils/natural-join.js';
5
- import fs from 'node:fs';
6
5
  import kleur from 'kleur';
7
6
  import { stylish as stylish$1 } from '@html-validate/stylish';
8
7
  import semver from 'semver';
@@ -6598,7 +6597,7 @@ const defaults$j = {
6598
6597
  minInitialRank: "h1",
6599
6598
  sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
6600
6599
  };
6601
- function isRelevant$6(event) {
6600
+ function isRelevant$5(event) {
6602
6601
  const node = event.target;
6603
6602
  return Boolean(node.meta?.heading);
6604
6603
  }
@@ -6667,7 +6666,7 @@ class HeadingLevel extends Rule {
6667
6666
  };
6668
6667
  }
6669
6668
  setup() {
6670
- this.on("tag:start", isRelevant$6, (event) => {
6669
+ this.on("tag:start", isRelevant$5, (event) => {
6671
6670
  this.onTagStart(event);
6672
6671
  });
6673
6672
  this.on("tag:ready", (event) => {
@@ -7323,7 +7322,7 @@ class MapDupName extends Rule {
7323
7322
  }
7324
7323
  }
7325
7324
 
7326
- function isRelevant$5(event) {
7325
+ function isRelevant$4(event) {
7327
7326
  return event.target.is("map");
7328
7327
  }
7329
7328
  function hasStaticValue(attr) {
@@ -7337,7 +7336,7 @@ class MapIdName extends Rule {
7337
7336
  };
7338
7337
  }
7339
7338
  setup() {
7340
- this.on("tag:ready", isRelevant$5, (event) => {
7339
+ this.on("tag:ready", isRelevant$4, (event) => {
7341
7340
  const { target } = event;
7342
7341
  const id = target.getAttribute("id");
7343
7342
  const name = target.getAttribute("name");
@@ -7461,7 +7460,7 @@ const abstractRoles = [
7461
7460
  "widget",
7462
7461
  "window"
7463
7462
  ];
7464
- function isRelevant$4(event) {
7463
+ function isRelevant$3(event) {
7465
7464
  return event.key === "role";
7466
7465
  }
7467
7466
  class NoAbstractRole extends Rule {
@@ -7480,7 +7479,7 @@ class NoAbstractRole extends Rule {
7480
7479
  };
7481
7480
  }
7482
7481
  setup() {
7483
- this.on("attr", isRelevant$4, (event) => {
7482
+ this.on("attr", isRelevant$3, (event) => {
7484
7483
  const roles = event.value;
7485
7484
  if (!roles || roles instanceof DynamicValue) {
7486
7485
  return;
@@ -7681,17 +7680,25 @@ class NoDupID extends Rule {
7681
7680
  setup() {
7682
7681
  this.on("dom:ready", (event) => {
7683
7682
  const { document } = event;
7683
+ const rootExisting = getExisting(document.root, document.root);
7684
+ const useRootExisting = !document.querySelector("template");
7684
7685
  const elements = document.querySelectorAll("[id]");
7685
- const relevant = elements.filter(isRelevant$3);
7686
- for (const el of relevant) {
7686
+ for (const el of elements) {
7687
7687
  const attr = el.getAttribute("id");
7688
- if (!attr?.value) {
7688
+ if (!attr) {
7689
+ continue;
7690
+ }
7691
+ if (!attr.value) {
7692
+ continue;
7693
+ }
7694
+ if (attr.isDynamic) {
7689
7695
  continue;
7690
7696
  }
7691
7697
  const id = attr.value.toString();
7692
- const existing = getExisting(el, document.root);
7698
+ const existing = useRootExisting ? rootExisting : getExisting(el, document.root);
7693
7699
  if (existing.has(id)) {
7694
7700
  this.report(el, `Duplicate ID "${id}"`, attr.valueLocation);
7701
+ continue;
7695
7702
  }
7696
7703
  existing.add(id);
7697
7704
  }
@@ -7708,19 +7715,6 @@ function getExisting(element, root) {
7708
7715
  return group.cacheSet(CACHE_KEY, existing2);
7709
7716
  }
7710
7717
  }
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
7718
 
7725
7719
  function isRelevant$2(event) {
7726
7720
  return event.target.is("button");
@@ -9961,14 +9955,15 @@ class ValidID extends Rule {
9961
9955
  }
9962
9956
  documentation(context) {
9963
9957
  const { relaxed } = this.options;
9964
- const message = this.messages[context].replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9958
+ const { kind, id } = context;
9959
+ const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
9965
9960
  const relaxedDescription = relaxed ? [] : [
9966
9961
  " - ID must begin with a letter",
9967
9962
  " - ID must only contain letters, digits, `-` and `_`"
9968
9963
  ];
9969
9964
  return {
9970
9965
  description: [
9971
- `${message}.`,
9966
+ `${interpolate(message, { id })}.`,
9972
9967
  "",
9973
9968
  "Under the current configuration the following rules are applied:",
9974
9969
  "",
@@ -9986,13 +9981,13 @@ class ValidID extends Rule {
9986
9981
  return;
9987
9982
  }
9988
9983
  if (value === "") {
9989
- const context = 1 /* EMPTY */;
9990
- this.report(event.target, this.messages[context], event.location, context);
9984
+ const context = { kind: 1 /* EMPTY */, id: value };
9985
+ this.report(event.target, this.messages[context.kind], event.location, context);
9991
9986
  return;
9992
9987
  }
9993
9988
  if (value.match(/\s/)) {
9994
- const context = 2 /* WHITESPACE */;
9995
- this.report(event.target, this.messages[context], event.valueLocation, context);
9989
+ const context = { kind: 2 /* WHITESPACE */, id: value };
9990
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
9996
9991
  return;
9997
9992
  }
9998
9993
  const { relaxed } = this.options;
@@ -10000,22 +9995,22 @@ class ValidID extends Rule {
10000
9995
  return;
10001
9996
  }
10002
9997
  if (value.match(/^[^\p{L}]/u)) {
10003
- const context = 3 /* LEADING_CHARACTER */;
10004
- this.report(event.target, this.messages[context], event.valueLocation, context);
9998
+ const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
9999
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10005
10000
  return;
10006
10001
  }
10007
10002
  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);
10003
+ const context = { kind: 4 /* DISALLOWED_CHARACTER */, id: value };
10004
+ this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10010
10005
  }
10011
10006
  });
10012
10007
  }
10013
10008
  get messages() {
10014
10009
  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"
10010
+ [1 /* EMPTY */]: `element id "{{ id }}" must not be empty`,
10011
+ [2 /* WHITESPACE */]: `element id "{{ id }}" must not contain whitespace`,
10012
+ [3 /* LEADING_CHARACTER */]: `element id "{{ id }}" must begin with a letter`,
10013
+ [4 /* DISALLOWED_CHARACTER */]: `element id "{{ id }}" must only contain letters, digits, dash and underscore characters`
10019
10014
  };
10020
10015
  }
10021
10016
  isRelevant(event) {
@@ -10080,29 +10075,41 @@ class VoidStyle extends Rule {
10080
10075
  };
10081
10076
  }
10082
10077
  setup() {
10078
+ const { style } = this;
10079
+ const validateStyle = {
10080
+ [1 /* AlwaysOmit */]: this.validateOmitted.bind(this),
10081
+ [2 /* AlwaysSelfclose */]: this.validateSelfClosed.bind(this)
10082
+ }[style];
10083
10083
  this.on("tag:end", (event) => {
10084
10084
  const active = event.previous;
10085
10085
  if (active.meta) {
10086
- this.validateActive(active);
10086
+ validateStyle(active);
10087
10087
  }
10088
10088
  });
10089
10089
  }
10090
- validateActive(node) {
10090
+ validateOmitted(node) {
10091
10091
  if (!node.voidElement) {
10092
10092
  return;
10093
10093
  }
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
- );
10094
+ if (node.closed !== NodeClosed.VoidSelfClosed) {
10095
+ return;
10099
10096
  }
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
- );
10097
+ this.reportError(
10098
+ node,
10099
+ `Expected omitted end tag <${node.tagName}> instead of self-closing element <${node.tagName}/>`
10100
+ );
10101
+ }
10102
+ validateSelfClosed(node) {
10103
+ if (!node.voidElement) {
10104
+ return;
10105
+ }
10106
+ if (node.closed !== NodeClosed.VoidOmitted) {
10107
+ return;
10105
10108
  }
10109
+ this.reportError(
10110
+ node,
10111
+ `Expected self-closing element <${node.tagName}/> instead of omitted end-tag <${node.tagName}>`
10112
+ );
10106
10113
  }
10107
10114
  reportError(node, message) {
10108
10115
  const context = {
@@ -10111,12 +10118,6 @@ class VoidStyle extends Rule {
10111
10118
  };
10112
10119
  super.report(node, message, null, context);
10113
10120
  }
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
10121
  }
10121
10122
  function parseStyle(name) {
10122
10123
  switch (name) {
@@ -11511,6 +11512,75 @@ function defineConfig(config) {
11511
11512
  return config;
11512
11513
  }
11513
11514
 
11515
+ const defaultResolvers = [];
11516
+ function hasResolver(value) {
11517
+ return Array.isArray(value[0]);
11518
+ }
11519
+ class StaticConfigLoader extends ConfigLoader {
11520
+ constructor(...args) {
11521
+ if (hasResolver(args)) {
11522
+ const [resolvers, config] = args;
11523
+ super(resolvers, config);
11524
+ } else {
11525
+ const [config] = args;
11526
+ super(defaultResolvers, config);
11527
+ }
11528
+ }
11529
+ /**
11530
+ * Set a new configuration for this loader.
11531
+ *
11532
+ * @public
11533
+ * @since 8.20.0
11534
+ * @param config - New configuration to use.
11535
+ */
11536
+ setConfig(config) {
11537
+ this.setConfigData(config);
11538
+ }
11539
+ getConfigFor(_handle, configOverride) {
11540
+ const override = this.loadFromObject(configOverride ?? {});
11541
+ if (isThenable(override)) {
11542
+ return override.then((override2) => this._resolveConfig(override2));
11543
+ } else {
11544
+ return this._resolveConfig(override);
11545
+ }
11546
+ }
11547
+ flushCache() {
11548
+ }
11549
+ defaultConfig() {
11550
+ return this.loadFromObject({
11551
+ extends: ["html-validate:recommended"],
11552
+ elements: ["html5"]
11553
+ });
11554
+ }
11555
+ _resolveConfig(override) {
11556
+ if (override.isRootFound()) {
11557
+ return override.resolve();
11558
+ }
11559
+ const globalConfig = this.getGlobalConfig();
11560
+ if (isThenable(globalConfig)) {
11561
+ return globalConfig.then((globalConfig2) => {
11562
+ const merged = globalConfig2.merge(this.resolvers, override);
11563
+ if (isThenable(merged)) {
11564
+ return merged.then((merged2) => {
11565
+ return merged2.resolve();
11566
+ });
11567
+ } else {
11568
+ return merged.resolve();
11569
+ }
11570
+ });
11571
+ } else {
11572
+ const merged = globalConfig.merge(this.resolvers, override);
11573
+ if (isThenable(merged)) {
11574
+ return merged.then((merged2) => {
11575
+ return merged2.resolve();
11576
+ });
11577
+ } else {
11578
+ return merged.resolve();
11579
+ }
11580
+ }
11581
+ }
11582
+ }
11583
+
11514
11584
  class EventHandler {
11515
11585
  listeners;
11516
11586
  constructor() {
@@ -11572,6 +11642,153 @@ class EventHandler {
11572
11642
  }
11573
11643
  }
11574
11644
 
11645
+ const name = "html-validate";
11646
+ const version = "9.4.0";
11647
+ const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11648
+
11649
+ function freeze(src) {
11650
+ return {
11651
+ ...src,
11652
+ selector: src.selector()
11653
+ };
11654
+ }
11655
+ function isThenableArray(value) {
11656
+ if (value.length === 0) {
11657
+ return false;
11658
+ }
11659
+ return isThenable(value[0]);
11660
+ }
11661
+ class Reporter {
11662
+ result;
11663
+ constructor() {
11664
+ this.result = {};
11665
+ }
11666
+ static merge(reports) {
11667
+ if (isThenable(reports)) {
11668
+ return reports.then((reports2) => this.merge(reports2));
11669
+ }
11670
+ if (isThenableArray(reports)) {
11671
+ return Promise.all(reports).then((reports2) => this.merge(reports2));
11672
+ }
11673
+ const valid = reports.every((report) => report.valid);
11674
+ const merged = {};
11675
+ reports.forEach((report) => {
11676
+ report.results.forEach((result) => {
11677
+ const key = result.filePath;
11678
+ if (key in merged) {
11679
+ merged[key].messages = [...merged[key].messages, ...result.messages];
11680
+ } else {
11681
+ merged[key] = { ...result };
11682
+ }
11683
+ });
11684
+ });
11685
+ const results = Object.values(merged).map((result) => {
11686
+ result.errorCount = countErrors(result.messages);
11687
+ result.warningCount = countWarnings(result.messages);
11688
+ return result;
11689
+ });
11690
+ return {
11691
+ valid,
11692
+ results,
11693
+ errorCount: sumErrors(results),
11694
+ warningCount: sumWarnings(results)
11695
+ };
11696
+ }
11697
+ add(rule, message, severity, node, location, context) {
11698
+ if (!(location.filename in this.result)) {
11699
+ this.result[location.filename] = [];
11700
+ }
11701
+ const ruleUrl = rule.documentation(context)?.url;
11702
+ const entry = {
11703
+ ruleId: rule.name,
11704
+ severity,
11705
+ message,
11706
+ offset: location.offset,
11707
+ line: location.line,
11708
+ column: location.column,
11709
+ size: location.size || 0,
11710
+ selector() {
11711
+ return node ? node.generateSelector() : null;
11712
+ }
11713
+ };
11714
+ if (ruleUrl) {
11715
+ entry.ruleUrl = ruleUrl;
11716
+ }
11717
+ if (context) {
11718
+ entry.context = context;
11719
+ }
11720
+ this.result[location.filename].push(entry);
11721
+ }
11722
+ addManual(filename, message) {
11723
+ if (!(filename in this.result)) {
11724
+ this.result[filename] = [];
11725
+ }
11726
+ this.result[filename].push(message);
11727
+ }
11728
+ save(sources) {
11729
+ const report = {
11730
+ valid: this.isValid(),
11731
+ results: Object.keys(this.result).map((filePath) => {
11732
+ const messages = Array.from(this.result[filePath], freeze).sort(messageSort);
11733
+ const source = (sources ?? []).find((source2) => filePath === source2.filename);
11734
+ return {
11735
+ filePath,
11736
+ messages,
11737
+ errorCount: countErrors(messages),
11738
+ warningCount: countWarnings(messages),
11739
+ source: source ? source.originalData ?? source.data : null
11740
+ };
11741
+ }),
11742
+ errorCount: 0,
11743
+ warningCount: 0
11744
+ };
11745
+ report.errorCount = sumErrors(report.results);
11746
+ report.warningCount = sumWarnings(report.results);
11747
+ return report;
11748
+ }
11749
+ isValid() {
11750
+ const numErrors = Object.values(this.result).reduce((sum, messages) => {
11751
+ return sum + countErrors(messages);
11752
+ }, 0);
11753
+ return numErrors === 0;
11754
+ }
11755
+ }
11756
+ function countErrors(messages) {
11757
+ return messages.filter((m) => m.severity === Number(Severity.ERROR)).length;
11758
+ }
11759
+ function countWarnings(messages) {
11760
+ return messages.filter((m) => m.severity === Number(Severity.WARN)).length;
11761
+ }
11762
+ function sumErrors(results) {
11763
+ return results.reduce((sum, result) => {
11764
+ return sum + result.errorCount;
11765
+ }, 0);
11766
+ }
11767
+ function sumWarnings(results) {
11768
+ return results.reduce((sum, result) => {
11769
+ return sum + result.warningCount;
11770
+ }, 0);
11771
+ }
11772
+ function messageSort(a, b) {
11773
+ if (a.line < b.line) {
11774
+ return -1;
11775
+ }
11776
+ if (a.line > b.line) {
11777
+ return 1;
11778
+ }
11779
+ if (a.column < b.column) {
11780
+ return -1;
11781
+ }
11782
+ if (a.column > b.column) {
11783
+ return 1;
11784
+ }
11785
+ return 0;
11786
+ }
11787
+
11788
+ function definePlugin(plugin) {
11789
+ return plugin;
11790
+ }
11791
+
11575
11792
  const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
11576
11793
  function* parseConditionalComment(comment, commentLocation) {
11577
11794
  let match;
@@ -12171,145 +12388,6 @@ class Parser {
12171
12388
  }
12172
12389
  }
12173
12390
 
12174
- function freeze(src) {
12175
- return {
12176
- ...src,
12177
- selector: src.selector()
12178
- };
12179
- }
12180
- function isThenableArray(value) {
12181
- if (value.length === 0) {
12182
- return false;
12183
- }
12184
- return isThenable(value[0]);
12185
- }
12186
- class Reporter {
12187
- result;
12188
- constructor() {
12189
- this.result = {};
12190
- }
12191
- static merge(reports) {
12192
- if (isThenable(reports)) {
12193
- return reports.then((reports2) => this.merge(reports2));
12194
- }
12195
- if (isThenableArray(reports)) {
12196
- return Promise.all(reports).then((reports2) => this.merge(reports2));
12197
- }
12198
- const valid = reports.every((report) => report.valid);
12199
- const merged = {};
12200
- reports.forEach((report) => {
12201
- report.results.forEach((result) => {
12202
- const key = result.filePath;
12203
- if (key in merged) {
12204
- merged[key].messages = [...merged[key].messages, ...result.messages];
12205
- } else {
12206
- merged[key] = { ...result };
12207
- }
12208
- });
12209
- });
12210
- const results = Object.values(merged).map((result) => {
12211
- result.errorCount = countErrors(result.messages);
12212
- result.warningCount = countWarnings(result.messages);
12213
- return result;
12214
- });
12215
- return {
12216
- valid,
12217
- results,
12218
- errorCount: sumErrors(results),
12219
- warningCount: sumWarnings(results)
12220
- };
12221
- }
12222
- add(rule, message, severity, node, location, context) {
12223
- if (!(location.filename in this.result)) {
12224
- this.result[location.filename] = [];
12225
- }
12226
- const ruleUrl = rule.documentation(context)?.url;
12227
- const entry = {
12228
- ruleId: rule.name,
12229
- severity,
12230
- message,
12231
- offset: location.offset,
12232
- line: location.line,
12233
- column: location.column,
12234
- size: location.size || 0,
12235
- selector() {
12236
- return node ? node.generateSelector() : null;
12237
- }
12238
- };
12239
- if (ruleUrl) {
12240
- entry.ruleUrl = ruleUrl;
12241
- }
12242
- if (context) {
12243
- entry.context = context;
12244
- }
12245
- this.result[location.filename].push(entry);
12246
- }
12247
- addManual(filename, message) {
12248
- if (!(filename in this.result)) {
12249
- this.result[filename] = [];
12250
- }
12251
- this.result[filename].push(message);
12252
- }
12253
- save(sources) {
12254
- const report = {
12255
- valid: this.isValid(),
12256
- results: Object.keys(this.result).map((filePath) => {
12257
- const messages = Array.from(this.result[filePath], freeze).sort(messageSort);
12258
- const source = (sources ?? []).find((source2) => filePath === source2.filename);
12259
- return {
12260
- filePath,
12261
- messages,
12262
- errorCount: countErrors(messages),
12263
- warningCount: countWarnings(messages),
12264
- source: source ? source.originalData ?? source.data : null
12265
- };
12266
- }),
12267
- errorCount: 0,
12268
- warningCount: 0
12269
- };
12270
- report.errorCount = sumErrors(report.results);
12271
- report.warningCount = sumWarnings(report.results);
12272
- return report;
12273
- }
12274
- isValid() {
12275
- const numErrors = Object.values(this.result).reduce((sum, messages) => {
12276
- return sum + countErrors(messages);
12277
- }, 0);
12278
- return numErrors === 0;
12279
- }
12280
- }
12281
- function countErrors(messages) {
12282
- return messages.filter((m) => m.severity === Number(Severity.ERROR)).length;
12283
- }
12284
- function countWarnings(messages) {
12285
- return messages.filter((m) => m.severity === Number(Severity.WARN)).length;
12286
- }
12287
- function sumErrors(results) {
12288
- return results.reduce((sum, result) => {
12289
- return sum + result.errorCount;
12290
- }, 0);
12291
- }
12292
- function sumWarnings(results) {
12293
- return results.reduce((sum, result) => {
12294
- return sum + result.warningCount;
12295
- }, 0);
12296
- }
12297
- function messageSort(a, b) {
12298
- if (a.line < b.line) {
12299
- return -1;
12300
- }
12301
- if (a.line > b.line) {
12302
- return 1;
12303
- }
12304
- if (a.column < b.column) {
12305
- return -1;
12306
- }
12307
- if (a.column > b.column) {
12308
- return 1;
12309
- }
12310
- return 0;
12311
- }
12312
-
12313
12391
  let blockerCounter = 1;
12314
12392
  function createBlocker() {
12315
12393
  const id = blockerCounter++;
@@ -12645,75 +12723,6 @@ class Engine {
12645
12723
  }
12646
12724
  }
12647
12725
 
12648
- const defaultResolvers = [];
12649
- function hasResolver(value) {
12650
- return Array.isArray(value[0]);
12651
- }
12652
- class StaticConfigLoader extends ConfigLoader {
12653
- constructor(...args) {
12654
- if (hasResolver(args)) {
12655
- const [resolvers, config] = args;
12656
- super(resolvers, config);
12657
- } else {
12658
- const [config] = args;
12659
- super(defaultResolvers, config);
12660
- }
12661
- }
12662
- /**
12663
- * Set a new configuration for this loader.
12664
- *
12665
- * @public
12666
- * @since 8.20.0
12667
- * @param config - New configuration to use.
12668
- */
12669
- setConfig(config) {
12670
- this.setConfigData(config);
12671
- }
12672
- getConfigFor(_handle, configOverride) {
12673
- const override = this.loadFromObject(configOverride ?? {});
12674
- if (isThenable(override)) {
12675
- return override.then((override2) => this._resolveConfig(override2));
12676
- } else {
12677
- return this._resolveConfig(override);
12678
- }
12679
- }
12680
- flushCache() {
12681
- }
12682
- defaultConfig() {
12683
- return this.loadFromObject({
12684
- extends: ["html-validate:recommended"],
12685
- elements: ["html5"]
12686
- });
12687
- }
12688
- _resolveConfig(override) {
12689
- if (override.isRootFound()) {
12690
- return override.resolve();
12691
- }
12692
- const globalConfig = this.getGlobalConfig();
12693
- if (isThenable(globalConfig)) {
12694
- return globalConfig.then((globalConfig2) => {
12695
- const merged = globalConfig2.merge(this.resolvers, override);
12696
- if (isThenable(merged)) {
12697
- return merged.then((merged2) => {
12698
- return merged2.resolve();
12699
- });
12700
- } else {
12701
- return merged.resolve();
12702
- }
12703
- });
12704
- } else {
12705
- const merged = globalConfig.merge(this.resolvers, override);
12706
- if (isThenable(merged)) {
12707
- return merged.then((merged2) => {
12708
- return merged2.resolve();
12709
- });
12710
- } else {
12711
- return merged.resolve();
12712
- }
12713
- }
12714
- }
12715
- }
12716
-
12717
12726
  function getNamedTransformerFromPlugin(name, plugins, pluginName, key) {
12718
12727
  const plugin = plugins.find((cur) => cur.name === pluginName);
12719
12728
  if (!plugin) {
@@ -12893,10 +12902,11 @@ function transformSourceSync(resolvers, config, source, filename) {
12893
12902
  }
12894
12903
  }
12895
12904
 
12896
- function transformFilename(resolvers, config, filename) {
12905
+ function transformFilename(resolvers, config, filename, fs) {
12897
12906
  const stdin = 0;
12898
12907
  const src = filename !== "/dev/stdin" ? filename : stdin;
12899
- const data = fs.readFileSync(src, { encoding: "utf8" });
12908
+ const output = fs.readFileSync(src, { encoding: "utf8" });
12909
+ const data = typeof output === "string" ? output : output.toString("utf8");
12900
12910
  const source = {
12901
12911
  data,
12902
12912
  filename,
@@ -12907,10 +12917,11 @@ function transformFilename(resolvers, config, filename) {
12907
12917
  };
12908
12918
  return transformSource(resolvers, config, source, filename);
12909
12919
  }
12910
- function transformFilenameSync(resolvers, config, filename) {
12920
+ function transformFilenameSync(resolvers, config, filename, fs) {
12911
12921
  const stdin = 0;
12912
12922
  const src = filename !== "/dev/stdin" ? filename : stdin;
12913
- const data = fs.readFileSync(src, { encoding: "utf8" });
12923
+ const output = fs.readFileSync(src, { encoding: "utf8" });
12924
+ const data = typeof output === "string" ? output : output.toString("utf8");
12914
12925
  const source = {
12915
12926
  data,
12916
12927
  filename,
@@ -12922,430 +12933,6 @@ function transformFilenameSync(resolvers, config, filename) {
12922
12933
  return transformSourceSync(resolvers, config, source, filename);
12923
12934
  }
12924
12935
 
12925
- function isSourceHooks(value) {
12926
- if (!value || typeof value === "string") {
12927
- return false;
12928
- }
12929
- return Boolean(value.processAttribute || value.processElement);
12930
- }
12931
- function isConfigData(value) {
12932
- if (!value || typeof value === "string") {
12933
- return false;
12934
- }
12935
- return !(value.processAttribute || value.processElement);
12936
- }
12937
- class HtmlValidate {
12938
- configLoader;
12939
- constructor(arg) {
12940
- const [loader, config] = arg instanceof ConfigLoader ? [arg, void 0] : [void 0, arg];
12941
- this.configLoader = loader ?? new StaticConfigLoader(config);
12942
- }
12943
- /* eslint-enable @typescript-eslint/unified-signatures */
12944
- validateString(str, arg1, arg2, arg3) {
12945
- const filename = typeof arg1 === "string" ? arg1 : "inline";
12946
- const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : void 0;
12947
- const hooks = isSourceHooks(arg1) ? arg1 : isSourceHooks(arg2) ? arg2 : arg3;
12948
- const source = {
12949
- data: str,
12950
- filename,
12951
- line: 1,
12952
- column: 1,
12953
- offset: 0,
12954
- hooks
12955
- };
12956
- return this.validateSource(source, options);
12957
- }
12958
- /* eslint-enable @typescript-eslint/unified-signatures */
12959
- validateStringSync(str, arg1, arg2, arg3) {
12960
- const filename = typeof arg1 === "string" ? arg1 : "inline";
12961
- const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : void 0;
12962
- const hooks = isSourceHooks(arg1) ? arg1 : isSourceHooks(arg2) ? arg2 : arg3;
12963
- const source = {
12964
- data: str,
12965
- filename,
12966
- line: 1,
12967
- column: 1,
12968
- offset: 0,
12969
- hooks
12970
- };
12971
- return this.validateSourceSync(source, options);
12972
- }
12973
- /**
12974
- * Parse and validate HTML from [[Source]].
12975
- *
12976
- * @public
12977
- * @param input - Source to parse.
12978
- * @returns Report output.
12979
- */
12980
- async validateSource(input, configOverride) {
12981
- const source = normalizeSource(input);
12982
- const config = await this.getConfigFor(source.filename, configOverride);
12983
- const resolvers = this.configLoader.getResolvers();
12984
- const transformedSource = await transformSource(resolvers, config, source);
12985
- const engine = new Engine(config, Parser);
12986
- return engine.lint(transformedSource);
12987
- }
12988
- /**
12989
- * Parse and validate HTML from [[Source]].
12990
- *
12991
- * @public
12992
- * @param input - Source to parse.
12993
- * @returns Report output.
12994
- */
12995
- validateSourceSync(input, configOverride) {
12996
- const source = normalizeSource(input);
12997
- const config = this.getConfigForSync(source.filename, configOverride);
12998
- const resolvers = this.configLoader.getResolvers();
12999
- const transformedSource = transformSourceSync(resolvers, config, source);
13000
- const engine = new Engine(config, Parser);
13001
- return engine.lint(transformedSource);
13002
- }
13003
- /**
13004
- * Parse and validate HTML from file.
13005
- *
13006
- * @public
13007
- * @param filename - Filename to read and parse.
13008
- * @returns Report output.
13009
- */
13010
- async validateFile(filename) {
13011
- const config = await this.getConfigFor(filename);
13012
- const resolvers = this.configLoader.getResolvers();
13013
- const source = await transformFilename(resolvers, config, filename);
13014
- const engine = new Engine(config, Parser);
13015
- return Promise.resolve(engine.lint(source));
13016
- }
13017
- /**
13018
- * Parse and validate HTML from file.
13019
- *
13020
- * @public
13021
- * @param filename - Filename to read and parse.
13022
- * @returns Report output.
13023
- */
13024
- validateFileSync(filename) {
13025
- const config = this.getConfigForSync(filename);
13026
- const resolvers = this.configLoader.getResolvers();
13027
- const source = transformFilenameSync(resolvers, config, filename);
13028
- const engine = new Engine(config, Parser);
13029
- return engine.lint(source);
13030
- }
13031
- /**
13032
- * Parse and validate HTML from multiple files. Result is merged together to a
13033
- * single report.
13034
- *
13035
- * @param filenames - Filenames to read and parse.
13036
- * @returns Report output.
13037
- */
13038
- async validateMultipleFiles(filenames) {
13039
- return Reporter.merge(filenames.map((filename) => this.validateFile(filename)));
13040
- }
13041
- /**
13042
- * Parse and validate HTML from multiple files. Result is merged together to a
13043
- * single report.
13044
- *
13045
- * @param filenames - Filenames to read and parse.
13046
- * @returns Report output.
13047
- */
13048
- validateMultipleFilesSync(filenames) {
13049
- return Reporter.merge(filenames.map((filename) => this.validateFileSync(filename)));
13050
- }
13051
- /**
13052
- * Returns true if the given filename can be validated.
13053
- *
13054
- * A file is considered to be validatable if the extension is `.html` or if a
13055
- * transformer matches the filename.
13056
- *
13057
- * This is mostly useful for tooling to determine whenever to validate the
13058
- * file or not. CLI tools will run on all the given files anyway.
13059
- */
13060
- async canValidate(filename) {
13061
- if (filename.toLowerCase().endsWith(".html")) {
13062
- return true;
13063
- }
13064
- const config = await this.getConfigFor(filename);
13065
- return config.canTransform(filename);
13066
- }
13067
- /**
13068
- * Returns true if the given filename can be validated.
13069
- *
13070
- * A file is considered to be validatable if the extension is `.html` or if a
13071
- * transformer matches the filename.
13072
- *
13073
- * This is mostly useful for tooling to determine whenever to validate the
13074
- * file or not. CLI tools will run on all the given files anyway.
13075
- */
13076
- canValidateSync(filename) {
13077
- if (filename.toLowerCase().endsWith(".html")) {
13078
- return true;
13079
- }
13080
- const config = this.getConfigForSync(filename);
13081
- return config.canTransform(filename);
13082
- }
13083
- /**
13084
- * Tokenize filename and output all tokens.
13085
- *
13086
- * Using CLI this is enabled with `--dump-tokens`. Mostly useful for
13087
- * debugging.
13088
- *
13089
- * @internal
13090
- * @param filename - Filename to tokenize.
13091
- */
13092
- async dumpTokens(filename) {
13093
- const config = await this.getConfigFor(filename);
13094
- const resolvers = this.configLoader.getResolvers();
13095
- const source = await transformFilename(resolvers, config, filename);
13096
- const engine = new Engine(config, Parser);
13097
- return engine.dumpTokens(source);
13098
- }
13099
- /**
13100
- * Parse filename and output all events.
13101
- *
13102
- * Using CLI this is enabled with `--dump-events`. Mostly useful for
13103
- * debugging.
13104
- *
13105
- * @internal
13106
- * @param filename - Filename to dump events from.
13107
- */
13108
- async dumpEvents(filename) {
13109
- const config = await this.getConfigFor(filename);
13110
- const resolvers = this.configLoader.getResolvers();
13111
- const source = await transformFilename(resolvers, config, filename);
13112
- const engine = new Engine(config, Parser);
13113
- return engine.dumpEvents(source);
13114
- }
13115
- /**
13116
- * Parse filename and output DOM tree.
13117
- *
13118
- * Using CLI this is enabled with `--dump-tree`. Mostly useful for
13119
- * debugging.
13120
- *
13121
- * @internal
13122
- * @param filename - Filename to dump DOM tree from.
13123
- */
13124
- async dumpTree(filename) {
13125
- const config = await this.getConfigFor(filename);
13126
- const resolvers = this.configLoader.getResolvers();
13127
- const source = await transformFilename(resolvers, config, filename);
13128
- const engine = new Engine(config, Parser);
13129
- return engine.dumpTree(source);
13130
- }
13131
- /**
13132
- * Transform filename and output source data.
13133
- *
13134
- * Using CLI this is enabled with `--dump-source`. Mostly useful for
13135
- * debugging.
13136
- *
13137
- * @internal
13138
- * @param filename - Filename to dump source from.
13139
- */
13140
- async dumpSource(filename) {
13141
- const config = await this.getConfigFor(filename);
13142
- const resolvers = this.configLoader.getResolvers();
13143
- const sources = await transformFilename(resolvers, config, filename);
13144
- return sources.reduce((result, source) => {
13145
- const line = String(source.line);
13146
- const column = String(source.column);
13147
- const offset = String(source.offset);
13148
- result.push(`Source ${source.filename}@${line}:${column} (offset: ${offset})`);
13149
- if (source.transformedBy) {
13150
- result.push("Transformed by:");
13151
- result = result.concat(source.transformedBy.reverse().map((name) => ` - ${name}`));
13152
- }
13153
- if (source.hooks && Object.keys(source.hooks).length > 0) {
13154
- result.push("Hooks");
13155
- for (const [key, present] of Object.entries(source.hooks)) {
13156
- if (present) {
13157
- result.push(` - ${key}`);
13158
- }
13159
- }
13160
- }
13161
- result.push("---");
13162
- result = result.concat(source.data.split("\n"));
13163
- result.push("---");
13164
- return result;
13165
- }, []);
13166
- }
13167
- /**
13168
- * Get effective configuration schema.
13169
- */
13170
- getConfigurationSchema() {
13171
- return Promise.resolve(configurationSchema);
13172
- }
13173
- /**
13174
- * Get effective metadata element schema.
13175
- *
13176
- * If a filename is given the configured plugins can extend the
13177
- * schema. Filename must not be an existing file or a filetype normally
13178
- * handled by html-validate but the path will be used when resolving
13179
- * configuration. As a rule-of-thumb, set it to the elements json file.
13180
- */
13181
- async getElementsSchema(filename) {
13182
- const config = await this.getConfigFor(filename ?? "inline");
13183
- const metaTable = config.getMetaTable();
13184
- return metaTable.getJSONSchema();
13185
- }
13186
- /**
13187
- * Get effective metadata element schema.
13188
- *
13189
- * If a filename is given the configured plugins can extend the
13190
- * schema. Filename must not be an existing file or a filetype normally
13191
- * handled by html-validate but the path will be used when resolving
13192
- * configuration. As a rule-of-thumb, set it to the elements json file.
13193
- */
13194
- getElementsSchemaSync(filename) {
13195
- const config = this.getConfigForSync(filename ?? "inline");
13196
- const metaTable = config.getMetaTable();
13197
- return metaTable.getJSONSchema();
13198
- }
13199
- async getContextualDocumentation(message, filenameOrConfig = "inline") {
13200
- const config = typeof filenameOrConfig === "string" ? await this.getConfigFor(filenameOrConfig) : await filenameOrConfig;
13201
- const engine = new Engine(config, Parser);
13202
- return engine.getRuleDocumentation(message);
13203
- }
13204
- getContextualDocumentationSync(message, filenameOrConfig = "inline") {
13205
- const config = typeof filenameOrConfig === "string" ? this.getConfigForSync(filenameOrConfig) : filenameOrConfig;
13206
- const engine = new Engine(config, Parser);
13207
- return engine.getRuleDocumentation(message);
13208
- }
13209
- /**
13210
- * Get contextual documentation for the given rule.
13211
- *
13212
- * Typical usage:
13213
- *
13214
- * ```js
13215
- * const report = await htmlvalidate.validateFile("my-file.html");
13216
- * for (const result of report.results){
13217
- * const config = await htmlvalidate.getConfigFor(result.filePath);
13218
- * for (const message of result.messages){
13219
- * const documentation = await htmlvalidate.getRuleDocumentation(message.ruleId, config, message.context);
13220
- * // do something with documentation
13221
- * }
13222
- * }
13223
- * ```
13224
- *
13225
- * @public
13226
- * @deprecated Deprecated since 8.0.0, use [[getContextualDocumentation]] instead.
13227
- * @param ruleId - Rule to get documentation for.
13228
- * @param config - If set it provides more accurate description by using the
13229
- * correct configuration for the file.
13230
- * @param context - If set to `Message.context` some rules can provide
13231
- * contextual details and suggestions.
13232
- */
13233
- async getRuleDocumentation(ruleId, config = null, context = null) {
13234
- const c = config ?? this.getConfigFor("inline");
13235
- const engine = new Engine(await c, Parser);
13236
- return engine.getRuleDocumentation({ ruleId, context });
13237
- }
13238
- /**
13239
- * Get contextual documentation for the given rule.
13240
- *
13241
- * Typical usage:
13242
- *
13243
- * ```js
13244
- * const report = htmlvalidate.validateFileSync("my-file.html");
13245
- * for (const result of report.results){
13246
- * const config = htmlvalidate.getConfigForSync(result.filePath);
13247
- * for (const message of result.messages){
13248
- * const documentation = htmlvalidate.getRuleDocumentationSync(message.ruleId, config, message.context);
13249
- * // do something with documentation
13250
- * }
13251
- * }
13252
- * ```
13253
- *
13254
- * @public
13255
- * @deprecated Deprecated since 8.0.0, use [[getContextualDocumentationSync]] instead.
13256
- * @param ruleId - Rule to get documentation for.
13257
- * @param config - If set it provides more accurate description by using the
13258
- * correct configuration for the file.
13259
- * @param context - If set to `Message.context` some rules can provide
13260
- * contextual details and suggestions.
13261
- */
13262
- getRuleDocumentationSync(ruleId, config = null, context = null) {
13263
- const c = config ?? this.getConfigForSync("inline");
13264
- const engine = new Engine(c, Parser);
13265
- return engine.getRuleDocumentation({ ruleId, context });
13266
- }
13267
- /**
13268
- * Create a parser configured for given filename.
13269
- *
13270
- * @internal
13271
- * @param source - Source to use.
13272
- */
13273
- async getParserFor(source) {
13274
- const config = await this.getConfigFor(source.filename);
13275
- return new Parser(config);
13276
- }
13277
- /**
13278
- * Get configuration for given filename.
13279
- *
13280
- * See [[FileSystemConfigLoader]] for details.
13281
- *
13282
- * @public
13283
- * @param filename - Filename to get configuration for.
13284
- * @param configOverride - Configuration to apply last.
13285
- */
13286
- getConfigFor(filename, configOverride) {
13287
- const config = this.configLoader.getConfigFor(filename, configOverride);
13288
- return Promise.resolve(config);
13289
- }
13290
- /**
13291
- * Get configuration for given filename.
13292
- *
13293
- * See [[FileSystemConfigLoader]] for details.
13294
- *
13295
- * @public
13296
- * @param filename - Filename to get configuration for.
13297
- * @param configOverride - Configuration to apply last.
13298
- */
13299
- getConfigForSync(filename, configOverride) {
13300
- const config = this.configLoader.getConfigFor(filename, configOverride);
13301
- if (isThenable(config)) {
13302
- throw new UserError("Cannot use asynchronous config loader with synchronous api");
13303
- }
13304
- return config;
13305
- }
13306
- /**
13307
- * Get current configuration loader.
13308
- *
13309
- * @public
13310
- * @since %version%
13311
- * @returns Current configuration loader.
13312
- */
13313
- /* istanbul ignore next -- not testing setters/getters */
13314
- getConfigLoader() {
13315
- return this.configLoader;
13316
- }
13317
- /**
13318
- * Set configuration loader.
13319
- *
13320
- * @public
13321
- * @since %version%
13322
- * @param loader - New configuration loader to use.
13323
- */
13324
- /* istanbul ignore next -- not testing setters/getters */
13325
- setConfigLoader(loader) {
13326
- this.configLoader = loader;
13327
- }
13328
- /**
13329
- * Flush configuration cache. Clears full cache unless a filename is given.
13330
- *
13331
- * See [[FileSystemConfigLoader]] for details.
13332
- *
13333
- * @public
13334
- * @param filename - If set, only flush cache for given filename.
13335
- */
13336
- flushConfigCache(filename) {
13337
- this.configLoader.flushCache(filename);
13338
- }
13339
- }
13340
-
13341
- const name = "html-validate";
13342
- const version = "9.2.2";
13343
- const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
13344
-
13345
- function definePlugin(plugin) {
13346
- return plugin;
13347
- }
13348
-
13349
12936
  const entities = {
13350
12937
  ">": "&gt;",
13351
12938
  "<": "&lt;",
@@ -14453,5 +14040,5 @@ const engines = {
14453
14040
 
14454
14041
  var workerPath = "./jest-worker.js";
14455
14042
 
14456
- export { Attribute as A, sliceLocation as B, Config as C, DOMNode as D, Reporter as E, definePlugin as F, ruleExists as G, HtmlValidate as H, walk as I, EventHandler as J, engines as K, compatibilityCheckImpl as L, MetaCopyableProperty as M, NodeClosed as N, isThenable as O, Parser as P, workerPath as Q, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, codeframe as X, name as Y, bugs as Z, ConfigError as a, ConfigLoader as b, defineConfig as c, deepmerge as d, ensureError as e, StaticConfigLoader as f, getFormatter as g, DOMTokenList as h, ignore as i, DOMTree as j, DynamicValue as k, HtmlElement as l, NodeType as m, NestedError as n, SchemaValidationError as o, presets as p, isUserError as q, MetaTable as r, staticResolver as s, TextContent$1 as t, Rule as u, version as v, ariaNaming as w, TextClassification as x, classifyNodeText as y, keywordPatternMatcher as z };
14043
+ export { compatibilityCheckImpl as $, Attribute as A, Reporter as B, Config as C, DOMNode as D, definePlugin as E, ruleExists as F, walk as G, HtmlElement as H, EventHandler as I, engines as J, normalizeSource as K, transformSource as L, MetaCopyableProperty as M, NodeClosed as N, Engine as O, Parser as P, transformSourceSync as Q, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, transformFilename as X, transformFilenameSync as Y, configurationSchema as Z, isThenable as _, ConfigError as a, workerPath as a0, codeframe as a1, name as a2, bugs as a3, ConfigLoader as b, defineConfig as c, deepmerge as d, ensureError as e, StaticConfigLoader as f, getFormatter as g, DOMTokenList as h, ignore as i, DOMTree as j, DynamicValue as k, NodeType as l, NestedError as m, SchemaValidationError as n, isUserError as o, presets as p, MetaTable as q, TextContent$1 as r, staticResolver as s, Rule as t, ariaNaming as u, version as v, TextClassification as w, classifyNodeText as x, keywordPatternMatcher as y, sliceLocation as z };
14457
14044
  //# sourceMappingURL=core.js.map