html-validate 8.25.1 → 8.27.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,7 @@ 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 'fs';
5
+ import fs from 'node:fs';
6
6
  import kleur from 'kleur';
7
7
  import { stylish as stylish$1 } from '@html-validate/stylish';
8
8
  import semver from 'semver';
@@ -5049,6 +5049,27 @@ class CloseAttr extends Rule {
5049
5049
  }
5050
5050
  }
5051
5051
 
5052
+ function* ancestors(node) {
5053
+ if (!node) {
5054
+ return;
5055
+ }
5056
+ let ancestor = node;
5057
+ while (ancestor && !ancestor.isRootElement()) {
5058
+ yield ancestor;
5059
+ ancestor = ancestor.parent;
5060
+ }
5061
+ if (ancestor) {
5062
+ yield ancestor;
5063
+ }
5064
+ }
5065
+ function findAncestor(node, predicate) {
5066
+ for (const ancestor of ancestors(node)) {
5067
+ if (predicate(ancestor)) {
5068
+ return ancestor;
5069
+ }
5070
+ }
5071
+ return null;
5072
+ }
5052
5073
  class CloseOrder extends Rule {
5053
5074
  documentation() {
5054
5075
  return {
@@ -5057,15 +5078,28 @@ class CloseOrder extends Rule {
5057
5078
  };
5058
5079
  }
5059
5080
  setup() {
5081
+ let reported;
5082
+ this.on("parse:begin", () => {
5083
+ reported = /* @__PURE__ */ new Set();
5084
+ });
5085
+ this.on("tag:end", (event) => {
5086
+ const current = event.target;
5087
+ const active = event.previous;
5088
+ if (current) {
5089
+ return;
5090
+ }
5091
+ for (const ancestor of ancestors(active)) {
5092
+ if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
5093
+ continue;
5094
+ }
5095
+ this.report(ancestor, `Unclosed element '<${ancestor.tagName}>'`, ancestor.location);
5096
+ reported.add(ancestor.unique);
5097
+ }
5098
+ });
5060
5099
  this.on("tag:end", (event) => {
5061
5100
  const current = event.target;
5062
5101
  const active = event.previous;
5063
5102
  if (!current) {
5064
- this.report(
5065
- null,
5066
- `Missing close-tag, expected '</${active.tagName}>' but document ended before it was found.`,
5067
- event.location
5068
- );
5069
5103
  return;
5070
5104
  }
5071
5105
  if (current.voidElement) {
@@ -5082,15 +5116,32 @@ class CloseOrder extends Rule {
5082
5116
  offset: current.location.offset,
5083
5117
  size: current.tagName.length + 1
5084
5118
  };
5085
- this.report(null, "Unexpected close-tag, expected opening tag.", location);
5119
+ this.report(null, `Stray end tag '</${current.tagName}>'`, location);
5086
5120
  return;
5087
5121
  }
5088
- if (current.tagName !== active.tagName) {
5122
+ if (current.tagName === active.tagName) {
5123
+ return;
5124
+ }
5125
+ const ancestor = findAncestor(active.parent, (node) => node.is(current.tagName));
5126
+ if (ancestor && !ancestor.isRootElement()) {
5127
+ for (const element of ancestors(active)) {
5128
+ if (ancestor.isSameNode(element)) {
5129
+ break;
5130
+ }
5131
+ if (reported.has(element.unique)) {
5132
+ continue;
5133
+ }
5134
+ this.report(element, `Unclosed element '<${element.tagName}>'`, element.location);
5135
+ reported.add(element.unique);
5136
+ }
5089
5137
  this.report(
5090
5138
  null,
5091
- `Mismatched close-tag, expected '</${active.tagName}>' but found '</${current.tagName}>'.`,
5139
+ `End tag '</${current.tagName}>' seen but there were open elements`,
5092
5140
  current.location
5093
5141
  );
5142
+ reported.add(ancestor.unique);
5143
+ } else {
5144
+ this.report(null, `Stray end tag '</${current.tagName}>'`, current.location);
5094
5145
  }
5095
5146
  });
5096
5147
  }
@@ -10511,10 +10562,6 @@ var configurationSchema = {
10511
10562
  properties: properties
10512
10563
  };
10513
10564
 
10514
- const TRANSFORMER_API = {
10515
- VERSION: 1
10516
- };
10517
-
10518
10565
  var defaultConfig = {};
10519
10566
 
10520
10567
  const config$5 = {
@@ -10721,6 +10768,99 @@ const presets = {
10721
10768
  "html-validate:a17y": config$5
10722
10769
  };
10723
10770
 
10771
+ function getNamedTransformerFromPlugin(name, plugins, pluginName, key) {
10772
+ const plugin = plugins.find((cur) => cur.name === pluginName);
10773
+ if (!plugin) {
10774
+ throw new ConfigError(`No plugin named "${pluginName}" has been loaded`);
10775
+ }
10776
+ if (!plugin.transformer) {
10777
+ throw new ConfigError(`Plugin does not expose any transformers`);
10778
+ }
10779
+ if (typeof plugin.transformer === "function") {
10780
+ throw new ConfigError(
10781
+ `Transformer "${name}" refers to named transformer but plugin exposes only unnamed, use "${pluginName}" instead.`
10782
+ );
10783
+ }
10784
+ const transformer = plugin.transformer[key];
10785
+ if (!transformer) {
10786
+ throw new ConfigError(`Plugin "${pluginName}" does not expose a transformer named "${key}".`);
10787
+ }
10788
+ return transformer;
10789
+ }
10790
+
10791
+ function getTransformerFromModule(resolvers, name) {
10792
+ return resolveTransformer(resolvers, name, { cache: true });
10793
+ }
10794
+
10795
+ function getUnnamedTransformerFromPlugin(name, plugin) {
10796
+ if (!plugin.transformer) {
10797
+ throw new ConfigError(`Plugin does not expose any transformers`);
10798
+ }
10799
+ if (typeof plugin.transformer !== "function") {
10800
+ if (plugin.transformer.default) {
10801
+ return plugin.transformer.default;
10802
+ }
10803
+ throw new ConfigError(
10804
+ `Transformer "${name}" refers to unnamed transformer but plugin exposes only named.`
10805
+ );
10806
+ }
10807
+ return plugin.transformer;
10808
+ }
10809
+
10810
+ const TRANSFORMER_API = {
10811
+ VERSION: 1
10812
+ };
10813
+
10814
+ function validateTransformer(transformer) {
10815
+ const version = transformer.api ?? 0;
10816
+ if (version !== TRANSFORMER_API.VERSION) {
10817
+ throw new ConfigError(
10818
+ `Transformer uses API version ${String(version)} but only version ${String(TRANSFORMER_API.VERSION)} is supported`
10819
+ );
10820
+ }
10821
+ }
10822
+ function loadTransformerFunction(resolvers, name, plugins) {
10823
+ const match = name.match(/(.*):(.*)/);
10824
+ if (match) {
10825
+ const [, pluginName, key] = match;
10826
+ const transformer2 = getNamedTransformerFromPlugin(name, plugins, pluginName, key);
10827
+ validateTransformer(transformer2);
10828
+ return transformer2;
10829
+ }
10830
+ const plugin = plugins.find((cur) => cur.name === name);
10831
+ if (plugin) {
10832
+ const transformer2 = getUnnamedTransformerFromPlugin(name, plugin);
10833
+ validateTransformer(transformer2);
10834
+ return transformer2;
10835
+ }
10836
+ const transformer = getTransformerFromModule(resolvers, name);
10837
+ validateTransformer(transformer);
10838
+ return transformer;
10839
+ }
10840
+ function getTransformerFunction(resolvers, name, plugins) {
10841
+ try {
10842
+ const transformer = loadTransformerFunction(resolvers, name, plugins);
10843
+ validateTransformer(transformer);
10844
+ return transformer;
10845
+ } catch (err) {
10846
+ if (err instanceof ConfigError) {
10847
+ throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
10848
+ } else {
10849
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
10850
+ }
10851
+ }
10852
+ }
10853
+ function getCachedTransformerFunction(cache, resolvers, name, plugins) {
10854
+ const cached = cache.get(name);
10855
+ if (cached) {
10856
+ return cached;
10857
+ } else {
10858
+ const transformer = getTransformerFunction(resolvers, name, plugins);
10859
+ cache.set(name, transformer);
10860
+ return transformer;
10861
+ }
10862
+ }
10863
+
10724
10864
  class ResolvedConfig {
10725
10865
  /**
10726
10866
  * @internal
@@ -10730,6 +10870,7 @@ class ResolvedConfig {
10730
10870
  this.plugins = plugins;
10731
10871
  this.rules = rules;
10732
10872
  this.transformers = transformers;
10873
+ this.cache = /* @__PURE__ */ new Map();
10733
10874
  this.original = original;
10734
10875
  }
10735
10876
  /**
@@ -10753,48 +10894,48 @@ class ResolvedConfig {
10753
10894
  *
10754
10895
  * When transforming zero or more new sources will be generated.
10755
10896
  *
10897
+ * @internal
10756
10898
  * @param source - Current source to transform.
10757
10899
  * @param filename - If set it is the filename used to match
10758
10900
  * transformer. Default is to use filename from source.
10759
10901
  * @returns A list of transformed sources ready for validation.
10760
10902
  */
10761
- transformSource(source, filename) {
10903
+ transformSource(resolvers, source, filename) {
10762
10904
  const transformer = this.findTransformer(filename ?? source.filename);
10763
10905
  const context = {
10764
10906
  hasChain: (filename2) => {
10765
10907
  return !!this.findTransformer(filename2);
10766
10908
  },
10767
10909
  chain: (source2, filename2) => {
10768
- return this.transformSource(source2, filename2);
10910
+ return this.transformSource(resolvers, source2, filename2);
10769
10911
  }
10770
10912
  };
10771
- if (transformer) {
10772
- try {
10773
- return Array.from(transformer.fn.call(context, source), (cur) => {
10774
- cur.transformedBy ??= [];
10775
- cur.transformedBy.push(transformer.name);
10776
- return cur;
10777
- });
10778
- } catch (err) {
10779
- const message = err instanceof Error ? err.message : String(err);
10780
- throw new NestedError(
10781
- `When transforming "${source.filename}": ${message}`,
10782
- ensureError(err)
10783
- );
10784
- }
10785
- } else {
10913
+ if (!transformer) {
10786
10914
  return [source];
10787
10915
  }
10916
+ const fn = getCachedTransformerFunction(this.cache, resolvers, transformer.name, this.plugins);
10917
+ try {
10918
+ const transformedSources = Array.from(fn.call(context, source));
10919
+ for (const source2 of transformedSources) {
10920
+ source2.transformedBy ??= [];
10921
+ source2.transformedBy.push(transformer.name);
10922
+ }
10923
+ return transformedSources;
10924
+ } catch (err) {
10925
+ const message = err instanceof Error ? err.message : String(err);
10926
+ throw new NestedError(`When transforming "${source.filename}": ${message}`, ensureError(err));
10927
+ }
10788
10928
  }
10789
10929
  /**
10790
10930
  * Wrapper around [[transformSource]] which reads a file before passing it
10791
10931
  * as-is to transformSource.
10792
10932
  *
10933
+ * @internal
10793
10934
  * @param filename - Filename to transform (according to configured
10794
10935
  * transformations)
10795
10936
  * @returns A list of transformed sources ready for validation.
10796
10937
  */
10797
- transformFilename(filename) {
10938
+ transformFilename(resolvers, filename) {
10798
10939
  const stdin = 0;
10799
10940
  const src = filename !== "/dev/stdin" ? filename : stdin;
10800
10941
  const data = fs.readFileSync(src, { encoding: "utf8" });
@@ -10806,10 +10947,12 @@ class ResolvedConfig {
10806
10947
  offset: 0,
10807
10948
  originalData: data
10808
10949
  };
10809
- return this.transformSource(source);
10950
+ return this.transformSource(resolvers, source);
10810
10951
  }
10811
10952
  /**
10812
10953
  * Returns true if a transformer matches given filename.
10954
+ *
10955
+ * @public
10813
10956
  */
10814
10957
  canTransform(filename) {
10815
10958
  const entry = this.findTransformer(filename);
@@ -10928,6 +11071,12 @@ function toArray(value) {
10928
11071
  return [value];
10929
11072
  }
10930
11073
  }
11074
+ function transformerEntries(transform) {
11075
+ return Object.entries(transform).map(([pattern, name]) => {
11076
+ const regex = new RegExp(pattern);
11077
+ return { pattern: regex, name };
11078
+ });
11079
+ }
10931
11080
  class Config {
10932
11081
  /**
10933
11082
  * @internal
@@ -10942,10 +11091,10 @@ class Config {
10942
11091
  };
10943
11092
  this.config = mergeInternal(initial, options);
10944
11093
  this.configurations = /* @__PURE__ */ new Map();
10945
- this.initialized = false;
10946
11094
  this.resolvers = toArray(resolvers);
10947
11095
  this.metaTable = null;
10948
11096
  this.plugins = [];
11097
+ this.transformers = transformerEntries(this.config.transform ?? {});
10949
11098
  }
10950
11099
  /**
10951
11100
  * Create a new blank configuration. See also `Config.defaultConfig()`.
@@ -11028,19 +11177,10 @@ class Config {
11028
11177
  return instance;
11029
11178
  }
11030
11179
  /**
11031
- * Initialize plugins, transforms etc.
11032
- *
11033
- * Must be called before trying to use config. Can safely be called multiple
11034
- * times.
11035
- *
11036
11180
  * @public
11181
+ * @deprecated Not needed any longer, this is a dummy noop method.
11037
11182
  */
11038
11183
  init() {
11039
- if (this.initialized) {
11040
- return;
11041
- }
11042
- this.transformers = this.precompileTransformers(this.config.transform ?? {});
11043
- this.initialized = true;
11044
11184
  }
11045
11185
  /**
11046
11186
  * Returns true if this configuration is marked as "root".
@@ -11153,6 +11293,14 @@ class Config {
11153
11293
  getPlugins() {
11154
11294
  return this.plugins;
11155
11295
  }
11296
+ /**
11297
+ * Get all configured transformers.
11298
+ *
11299
+ * @internal
11300
+ */
11301
+ getTransformers() {
11302
+ return this.transformers;
11303
+ }
11156
11304
  loadPlugins(plugins) {
11157
11305
  return plugins.map((moduleName, index) => {
11158
11306
  if (typeof moduleName !== "string") {
@@ -11236,99 +11384,6 @@ class Config {
11236
11384
  transformers: this.transformers
11237
11385
  };
11238
11386
  }
11239
- precompileTransformers(transform) {
11240
- return Object.entries(transform).map(([pattern, name]) => {
11241
- try {
11242
- const fn = this.getTransformFunction(name);
11243
- const version = fn.api ?? 0;
11244
- if (version !== TRANSFORMER_API.VERSION) {
11245
- throw new ConfigError(
11246
- `Transformer uses API version ${String(version)} but only version ${String(TRANSFORMER_API.VERSION)} is supported`
11247
- );
11248
- }
11249
- return {
11250
- // eslint-disable-next-line security/detect-non-literal-regexp -- expected to be a regexp
11251
- pattern: new RegExp(pattern),
11252
- name,
11253
- fn
11254
- };
11255
- } catch (err) {
11256
- if (err instanceof ConfigError) {
11257
- throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
11258
- } else {
11259
- throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
11260
- }
11261
- }
11262
- });
11263
- }
11264
- /**
11265
- * Get transformation function requested by configuration.
11266
- *
11267
- * Searches:
11268
- *
11269
- * - Named transformers from plugins.
11270
- * - Unnamed transformer from plugin.
11271
- * - Standalone modules (local or node_modules)
11272
- *
11273
- * @param name - Key from configuration
11274
- */
11275
- getTransformFunction(name) {
11276
- const match = name.match(/(.*):(.*)/);
11277
- if (match) {
11278
- const [, pluginName, key] = match;
11279
- return this.getNamedTransformerFromPlugin(name, pluginName, key);
11280
- }
11281
- const plugin = this.plugins.find((cur) => cur.name === name);
11282
- if (plugin) {
11283
- return this.getUnnamedTransformerFromPlugin(name, plugin);
11284
- }
11285
- return this.getTransformerFromModule(name);
11286
- }
11287
- /**
11288
- * @param name - Original name from configuration
11289
- * @param pluginName - Name of plugin
11290
- * @param key - Name of transform (from plugin)
11291
- */
11292
- getNamedTransformerFromPlugin(name, pluginName, key) {
11293
- const plugin = this.plugins.find((cur) => cur.name === pluginName);
11294
- if (!plugin) {
11295
- throw new ConfigError(`No plugin named "${pluginName}" has been loaded`);
11296
- }
11297
- if (!plugin.transformer) {
11298
- throw new ConfigError(`Plugin does not expose any transformer`);
11299
- }
11300
- if (typeof plugin.transformer === "function") {
11301
- throw new ConfigError(
11302
- `Transformer "${name}" refers to named transformer but plugin exposes only unnamed, use "${pluginName}" instead.`
11303
- );
11304
- }
11305
- const transformer = plugin.transformer[key];
11306
- if (!transformer) {
11307
- throw new ConfigError(`Plugin "${pluginName}" does not expose a transformer named "${key}".`);
11308
- }
11309
- return transformer;
11310
- }
11311
- /**
11312
- * @param name - Original name from configuration
11313
- * @param plugin - Plugin instance
11314
- */
11315
- getUnnamedTransformerFromPlugin(name, plugin) {
11316
- if (!plugin.transformer) {
11317
- throw new ConfigError(`Plugin does not expose any transformer`);
11318
- }
11319
- if (typeof plugin.transformer !== "function") {
11320
- if (plugin.transformer.default) {
11321
- return plugin.transformer.default;
11322
- }
11323
- throw new ConfigError(
11324
- `Transformer "${name}" refers to unnamed transformer but plugin exposes only named.`
11325
- );
11326
- }
11327
- return plugin.transformer;
11328
- }
11329
- getTransformerFromModule(name) {
11330
- return resolveTransformer(this.resolvers, name, { cache: true });
11331
- }
11332
11387
  }
11333
11388
 
11334
11389
  class ConfigLoader {
@@ -11346,6 +11401,12 @@ class ConfigLoader {
11346
11401
  configData ? this.loadFromObject(configData) : this.defaultConfig()
11347
11402
  );
11348
11403
  }
11404
+ /**
11405
+ * @internal
11406
+ */
11407
+ getResolvers() {
11408
+ return this.resolvers;
11409
+ }
11349
11410
  /**
11350
11411
  * @internal For testing only
11351
11412
  */
@@ -11646,8 +11707,9 @@ class Parser {
11646
11707
  node.closed = NodeClosed.EndTag;
11647
11708
  }
11648
11709
  this.closeElement(source, node, active, endToken.location);
11710
+ const mismatched = node.tagName !== active.tagName;
11649
11711
  const voidClosed = !isStartTag && node.voidElement;
11650
- if (!voidClosed) {
11712
+ if (!voidClosed && !mismatched) {
11651
11713
  this.dom.popActive();
11652
11714
  }
11653
11715
  } else if (isForeign) {
@@ -11665,6 +11727,9 @@ class Parser {
11665
11727
  location
11666
11728
  };
11667
11729
  this.trigger("tag:end", event);
11730
+ if (node && node.tagName !== active.tagName && active.closed !== NodeClosed.ImplicitClosed) {
11731
+ return;
11732
+ }
11668
11733
  if (!active.isRootElement()) {
11669
11734
  this.trigger("element:ready", {
11670
11735
  target: active,
@@ -12525,11 +12590,9 @@ class StaticConfigLoader extends ConfigLoader {
12525
12590
  getConfigFor(_handle, configOverride) {
12526
12591
  const override = this.loadFromObject(configOverride ?? {});
12527
12592
  if (override.isRootFound()) {
12528
- override.init();
12529
12593
  return override.resolve();
12530
12594
  }
12531
12595
  const merged = this.globalConfig.merge(this.resolvers, override);
12532
- merged.init();
12533
12596
  return merged.resolve();
12534
12597
  }
12535
12598
  flushCache() {
@@ -12599,7 +12662,8 @@ class HtmlValidate {
12599
12662
  async validateSource(input, configOverride) {
12600
12663
  const source = normalizeSource(input);
12601
12664
  const config = await this.getConfigFor(source.filename, configOverride);
12602
- const transformedSource = config.transformSource(source);
12665
+ const resolvers = this.configLoader.getResolvers();
12666
+ const transformedSource = config.transformSource(resolvers, source);
12603
12667
  const engine = new Engine(config, Parser);
12604
12668
  return engine.lint(transformedSource);
12605
12669
  }
@@ -12613,7 +12677,8 @@ class HtmlValidate {
12613
12677
  validateSourceSync(input, configOverride) {
12614
12678
  const source = normalizeSource(input);
12615
12679
  const config = this.getConfigForSync(source.filename, configOverride);
12616
- const transformedSource = config.transformSource(source);
12680
+ const resolvers = this.configLoader.getResolvers();
12681
+ const transformedSource = config.transformSource(resolvers, source);
12617
12682
  const engine = new Engine(config, Parser);
12618
12683
  return engine.lint(transformedSource);
12619
12684
  }
@@ -12626,7 +12691,8 @@ class HtmlValidate {
12626
12691
  */
12627
12692
  async validateFile(filename) {
12628
12693
  const config = await this.getConfigFor(filename);
12629
- const source = config.transformFilename(filename);
12694
+ const resolvers = this.configLoader.getResolvers();
12695
+ const source = config.transformFilename(resolvers, filename);
12630
12696
  const engine = new Engine(config, Parser);
12631
12697
  return Promise.resolve(engine.lint(source));
12632
12698
  }
@@ -12639,7 +12705,8 @@ class HtmlValidate {
12639
12705
  */
12640
12706
  validateFileSync(filename) {
12641
12707
  const config = this.getConfigForSync(filename);
12642
- const source = config.transformFilename(filename);
12708
+ const resolvers = this.configLoader.getResolvers();
12709
+ const source = config.transformFilename(resolvers, filename);
12643
12710
  const engine = new Engine(config, Parser);
12644
12711
  return engine.lint(source);
12645
12712
  }
@@ -12707,7 +12774,8 @@ class HtmlValidate {
12707
12774
  */
12708
12775
  dumpTokens(filename) {
12709
12776
  const config = this.getConfigForSync(filename);
12710
- const source = config.transformFilename(filename);
12777
+ const resolvers = this.configLoader.getResolvers();
12778
+ const source = config.transformFilename(resolvers, filename);
12711
12779
  const engine = new Engine(config, Parser);
12712
12780
  return engine.dumpTokens(source);
12713
12781
  }
@@ -12722,7 +12790,8 @@ class HtmlValidate {
12722
12790
  */
12723
12791
  dumpEvents(filename) {
12724
12792
  const config = this.getConfigForSync(filename);
12725
- const source = config.transformFilename(filename);
12793
+ const resolvers = this.configLoader.getResolvers();
12794
+ const source = config.transformFilename(resolvers, filename);
12726
12795
  const engine = new Engine(config, Parser);
12727
12796
  return engine.dumpEvents(source);
12728
12797
  }
@@ -12737,7 +12806,8 @@ class HtmlValidate {
12737
12806
  */
12738
12807
  dumpTree(filename) {
12739
12808
  const config = this.getConfigForSync(filename);
12740
- const source = config.transformFilename(filename);
12809
+ const resolvers = this.configLoader.getResolvers();
12810
+ const source = config.transformFilename(resolvers, filename);
12741
12811
  const engine = new Engine(config, Parser);
12742
12812
  return engine.dumpTree(source);
12743
12813
  }
@@ -12752,7 +12822,8 @@ class HtmlValidate {
12752
12822
  */
12753
12823
  dumpSource(filename) {
12754
12824
  const config = this.getConfigForSync(filename);
12755
- const sources = config.transformFilename(filename);
12825
+ const resolvers = this.configLoader.getResolvers();
12826
+ const sources = config.transformFilename(resolvers, filename);
12756
12827
  return sources.reduce((result, source) => {
12757
12828
  const line = String(source.line);
12758
12829
  const column = String(source.column);
@@ -12947,7 +13018,7 @@ class HtmlValidate {
12947
13018
  }
12948
13019
 
12949
13020
  const name = "html-validate";
12950
- const version = "8.25.1";
13021
+ const version = "8.26.0";
12951
13022
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12952
13023
 
12953
13024
  function definePlugin(plugin) {