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/cjs/browser.js +1 -1
- package/dist/cjs/core-nodejs.js +0 -3
- package/dist/cjs/core-nodejs.js.map +1 -1
- package/dist/cjs/core.js +219 -148
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/html-validate.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/jest.js +1 -2
- package/dist/cjs/jest.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/cjs/vitest.js +1 -2
- package/dist/cjs/vitest.js.map +1 -1
- package/dist/es/browser.js +1 -1
- package/dist/es/core-nodejs.js +0 -3
- package/dist/es/core-nodejs.js.map +1 -1
- package/dist/es/core.js +219 -148
- package/dist/es/core.js.map +1 -1
- package/dist/es/html-validate.js +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/jest.js +1 -2
- package/dist/es/jest.js.map +1 -1
- package/dist/es/vitest.js +1 -2
- package/dist/es/vitest.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +8 -52
- package/dist/types/index.d.ts +8 -52
- package/package.json +2 -162
package/dist/cjs/core.js
CHANGED
|
@@ -4,7 +4,7 @@ var Ajv = require('ajv');
|
|
|
4
4
|
var elements = require('./elements.js');
|
|
5
5
|
var betterAjvErrors = require('@sidvind/better-ajv-errors');
|
|
6
6
|
var utils_naturalJoin = require('./utils/natural-join.js');
|
|
7
|
-
var fs = require('fs');
|
|
7
|
+
var fs = require('node:fs');
|
|
8
8
|
var kleur = require('kleur');
|
|
9
9
|
var stylish$1 = require('@html-validate/stylish');
|
|
10
10
|
var semver = require('semver');
|
|
@@ -5059,6 +5059,27 @@ class CloseAttr extends Rule {
|
|
|
5059
5059
|
}
|
|
5060
5060
|
}
|
|
5061
5061
|
|
|
5062
|
+
function* ancestors(node) {
|
|
5063
|
+
if (!node) {
|
|
5064
|
+
return;
|
|
5065
|
+
}
|
|
5066
|
+
let ancestor = node;
|
|
5067
|
+
while (ancestor && !ancestor.isRootElement()) {
|
|
5068
|
+
yield ancestor;
|
|
5069
|
+
ancestor = ancestor.parent;
|
|
5070
|
+
}
|
|
5071
|
+
if (ancestor) {
|
|
5072
|
+
yield ancestor;
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5075
|
+
function findAncestor(node, predicate) {
|
|
5076
|
+
for (const ancestor of ancestors(node)) {
|
|
5077
|
+
if (predicate(ancestor)) {
|
|
5078
|
+
return ancestor;
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
return null;
|
|
5082
|
+
}
|
|
5062
5083
|
class CloseOrder extends Rule {
|
|
5063
5084
|
documentation() {
|
|
5064
5085
|
return {
|
|
@@ -5067,15 +5088,28 @@ class CloseOrder extends Rule {
|
|
|
5067
5088
|
};
|
|
5068
5089
|
}
|
|
5069
5090
|
setup() {
|
|
5091
|
+
let reported;
|
|
5092
|
+
this.on("parse:begin", () => {
|
|
5093
|
+
reported = /* @__PURE__ */ new Set();
|
|
5094
|
+
});
|
|
5095
|
+
this.on("tag:end", (event) => {
|
|
5096
|
+
const current = event.target;
|
|
5097
|
+
const active = event.previous;
|
|
5098
|
+
if (current) {
|
|
5099
|
+
return;
|
|
5100
|
+
}
|
|
5101
|
+
for (const ancestor of ancestors(active)) {
|
|
5102
|
+
if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
|
|
5103
|
+
continue;
|
|
5104
|
+
}
|
|
5105
|
+
this.report(ancestor, `Unclosed element '<${ancestor.tagName}>'`, ancestor.location);
|
|
5106
|
+
reported.add(ancestor.unique);
|
|
5107
|
+
}
|
|
5108
|
+
});
|
|
5070
5109
|
this.on("tag:end", (event) => {
|
|
5071
5110
|
const current = event.target;
|
|
5072
5111
|
const active = event.previous;
|
|
5073
5112
|
if (!current) {
|
|
5074
|
-
this.report(
|
|
5075
|
-
null,
|
|
5076
|
-
`Missing close-tag, expected '</${active.tagName}>' but document ended before it was found.`,
|
|
5077
|
-
event.location
|
|
5078
|
-
);
|
|
5079
5113
|
return;
|
|
5080
5114
|
}
|
|
5081
5115
|
if (current.voidElement) {
|
|
@@ -5092,15 +5126,32 @@ class CloseOrder extends Rule {
|
|
|
5092
5126
|
offset: current.location.offset,
|
|
5093
5127
|
size: current.tagName.length + 1
|
|
5094
5128
|
};
|
|
5095
|
-
this.report(null,
|
|
5129
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, location);
|
|
5096
5130
|
return;
|
|
5097
5131
|
}
|
|
5098
|
-
if (current.tagName
|
|
5132
|
+
if (current.tagName === active.tagName) {
|
|
5133
|
+
return;
|
|
5134
|
+
}
|
|
5135
|
+
const ancestor = findAncestor(active.parent, (node) => node.is(current.tagName));
|
|
5136
|
+
if (ancestor && !ancestor.isRootElement()) {
|
|
5137
|
+
for (const element of ancestors(active)) {
|
|
5138
|
+
if (ancestor.isSameNode(element)) {
|
|
5139
|
+
break;
|
|
5140
|
+
}
|
|
5141
|
+
if (reported.has(element.unique)) {
|
|
5142
|
+
continue;
|
|
5143
|
+
}
|
|
5144
|
+
this.report(element, `Unclosed element '<${element.tagName}>'`, element.location);
|
|
5145
|
+
reported.add(element.unique);
|
|
5146
|
+
}
|
|
5099
5147
|
this.report(
|
|
5100
5148
|
null,
|
|
5101
|
-
`
|
|
5149
|
+
`End tag '</${current.tagName}>' seen but there were open elements`,
|
|
5102
5150
|
current.location
|
|
5103
5151
|
);
|
|
5152
|
+
reported.add(ancestor.unique);
|
|
5153
|
+
} else {
|
|
5154
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, current.location);
|
|
5104
5155
|
}
|
|
5105
5156
|
});
|
|
5106
5157
|
}
|
|
@@ -10521,10 +10572,6 @@ var configurationSchema = {
|
|
|
10521
10572
|
properties: properties
|
|
10522
10573
|
};
|
|
10523
10574
|
|
|
10524
|
-
const TRANSFORMER_API = {
|
|
10525
|
-
VERSION: 1
|
|
10526
|
-
};
|
|
10527
|
-
|
|
10528
10575
|
var defaultConfig = {};
|
|
10529
10576
|
|
|
10530
10577
|
const config$5 = {
|
|
@@ -10731,6 +10778,99 @@ const presets = {
|
|
|
10731
10778
|
"html-validate:a17y": config$5
|
|
10732
10779
|
};
|
|
10733
10780
|
|
|
10781
|
+
function getNamedTransformerFromPlugin(name, plugins, pluginName, key) {
|
|
10782
|
+
const plugin = plugins.find((cur) => cur.name === pluginName);
|
|
10783
|
+
if (!plugin) {
|
|
10784
|
+
throw new ConfigError(`No plugin named "${pluginName}" has been loaded`);
|
|
10785
|
+
}
|
|
10786
|
+
if (!plugin.transformer) {
|
|
10787
|
+
throw new ConfigError(`Plugin does not expose any transformers`);
|
|
10788
|
+
}
|
|
10789
|
+
if (typeof plugin.transformer === "function") {
|
|
10790
|
+
throw new ConfigError(
|
|
10791
|
+
`Transformer "${name}" refers to named transformer but plugin exposes only unnamed, use "${pluginName}" instead.`
|
|
10792
|
+
);
|
|
10793
|
+
}
|
|
10794
|
+
const transformer = plugin.transformer[key];
|
|
10795
|
+
if (!transformer) {
|
|
10796
|
+
throw new ConfigError(`Plugin "${pluginName}" does not expose a transformer named "${key}".`);
|
|
10797
|
+
}
|
|
10798
|
+
return transformer;
|
|
10799
|
+
}
|
|
10800
|
+
|
|
10801
|
+
function getTransformerFromModule(resolvers, name) {
|
|
10802
|
+
return resolveTransformer(resolvers, name, { cache: true });
|
|
10803
|
+
}
|
|
10804
|
+
|
|
10805
|
+
function getUnnamedTransformerFromPlugin(name, plugin) {
|
|
10806
|
+
if (!plugin.transformer) {
|
|
10807
|
+
throw new ConfigError(`Plugin does not expose any transformers`);
|
|
10808
|
+
}
|
|
10809
|
+
if (typeof plugin.transformer !== "function") {
|
|
10810
|
+
if (plugin.transformer.default) {
|
|
10811
|
+
return plugin.transformer.default;
|
|
10812
|
+
}
|
|
10813
|
+
throw new ConfigError(
|
|
10814
|
+
`Transformer "${name}" refers to unnamed transformer but plugin exposes only named.`
|
|
10815
|
+
);
|
|
10816
|
+
}
|
|
10817
|
+
return plugin.transformer;
|
|
10818
|
+
}
|
|
10819
|
+
|
|
10820
|
+
const TRANSFORMER_API = {
|
|
10821
|
+
VERSION: 1
|
|
10822
|
+
};
|
|
10823
|
+
|
|
10824
|
+
function validateTransformer(transformer) {
|
|
10825
|
+
const version = transformer.api ?? 0;
|
|
10826
|
+
if (version !== TRANSFORMER_API.VERSION) {
|
|
10827
|
+
throw new ConfigError(
|
|
10828
|
+
`Transformer uses API version ${String(version)} but only version ${String(TRANSFORMER_API.VERSION)} is supported`
|
|
10829
|
+
);
|
|
10830
|
+
}
|
|
10831
|
+
}
|
|
10832
|
+
function loadTransformerFunction(resolvers, name, plugins) {
|
|
10833
|
+
const match = name.match(/(.*):(.*)/);
|
|
10834
|
+
if (match) {
|
|
10835
|
+
const [, pluginName, key] = match;
|
|
10836
|
+
const transformer2 = getNamedTransformerFromPlugin(name, plugins, pluginName, key);
|
|
10837
|
+
validateTransformer(transformer2);
|
|
10838
|
+
return transformer2;
|
|
10839
|
+
}
|
|
10840
|
+
const plugin = plugins.find((cur) => cur.name === name);
|
|
10841
|
+
if (plugin) {
|
|
10842
|
+
const transformer2 = getUnnamedTransformerFromPlugin(name, plugin);
|
|
10843
|
+
validateTransformer(transformer2);
|
|
10844
|
+
return transformer2;
|
|
10845
|
+
}
|
|
10846
|
+
const transformer = getTransformerFromModule(resolvers, name);
|
|
10847
|
+
validateTransformer(transformer);
|
|
10848
|
+
return transformer;
|
|
10849
|
+
}
|
|
10850
|
+
function getTransformerFunction(resolvers, name, plugins) {
|
|
10851
|
+
try {
|
|
10852
|
+
const transformer = loadTransformerFunction(resolvers, name, plugins);
|
|
10853
|
+
validateTransformer(transformer);
|
|
10854
|
+
return transformer;
|
|
10855
|
+
} catch (err) {
|
|
10856
|
+
if (err instanceof ConfigError) {
|
|
10857
|
+
throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
|
|
10858
|
+
} else {
|
|
10859
|
+
throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
|
|
10860
|
+
}
|
|
10861
|
+
}
|
|
10862
|
+
}
|
|
10863
|
+
function getCachedTransformerFunction(cache, resolvers, name, plugins) {
|
|
10864
|
+
const cached = cache.get(name);
|
|
10865
|
+
if (cached) {
|
|
10866
|
+
return cached;
|
|
10867
|
+
} else {
|
|
10868
|
+
const transformer = getTransformerFunction(resolvers, name, plugins);
|
|
10869
|
+
cache.set(name, transformer);
|
|
10870
|
+
return transformer;
|
|
10871
|
+
}
|
|
10872
|
+
}
|
|
10873
|
+
|
|
10734
10874
|
class ResolvedConfig {
|
|
10735
10875
|
/**
|
|
10736
10876
|
* @internal
|
|
@@ -10740,6 +10880,7 @@ class ResolvedConfig {
|
|
|
10740
10880
|
this.plugins = plugins;
|
|
10741
10881
|
this.rules = rules;
|
|
10742
10882
|
this.transformers = transformers;
|
|
10883
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
10743
10884
|
this.original = original;
|
|
10744
10885
|
}
|
|
10745
10886
|
/**
|
|
@@ -10763,48 +10904,48 @@ class ResolvedConfig {
|
|
|
10763
10904
|
*
|
|
10764
10905
|
* When transforming zero or more new sources will be generated.
|
|
10765
10906
|
*
|
|
10907
|
+
* @internal
|
|
10766
10908
|
* @param source - Current source to transform.
|
|
10767
10909
|
* @param filename - If set it is the filename used to match
|
|
10768
10910
|
* transformer. Default is to use filename from source.
|
|
10769
10911
|
* @returns A list of transformed sources ready for validation.
|
|
10770
10912
|
*/
|
|
10771
|
-
transformSource(source, filename) {
|
|
10913
|
+
transformSource(resolvers, source, filename) {
|
|
10772
10914
|
const transformer = this.findTransformer(filename ?? source.filename);
|
|
10773
10915
|
const context = {
|
|
10774
10916
|
hasChain: (filename2) => {
|
|
10775
10917
|
return !!this.findTransformer(filename2);
|
|
10776
10918
|
},
|
|
10777
10919
|
chain: (source2, filename2) => {
|
|
10778
|
-
return this.transformSource(source2, filename2);
|
|
10920
|
+
return this.transformSource(resolvers, source2, filename2);
|
|
10779
10921
|
}
|
|
10780
10922
|
};
|
|
10781
|
-
if (transformer) {
|
|
10782
|
-
try {
|
|
10783
|
-
return Array.from(transformer.fn.call(context, source), (cur) => {
|
|
10784
|
-
cur.transformedBy ??= [];
|
|
10785
|
-
cur.transformedBy.push(transformer.name);
|
|
10786
|
-
return cur;
|
|
10787
|
-
});
|
|
10788
|
-
} catch (err) {
|
|
10789
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
10790
|
-
throw new NestedError(
|
|
10791
|
-
`When transforming "${source.filename}": ${message}`,
|
|
10792
|
-
ensureError(err)
|
|
10793
|
-
);
|
|
10794
|
-
}
|
|
10795
|
-
} else {
|
|
10923
|
+
if (!transformer) {
|
|
10796
10924
|
return [source];
|
|
10797
10925
|
}
|
|
10926
|
+
const fn = getCachedTransformerFunction(this.cache, resolvers, transformer.name, this.plugins);
|
|
10927
|
+
try {
|
|
10928
|
+
const transformedSources = Array.from(fn.call(context, source));
|
|
10929
|
+
for (const source2 of transformedSources) {
|
|
10930
|
+
source2.transformedBy ??= [];
|
|
10931
|
+
source2.transformedBy.push(transformer.name);
|
|
10932
|
+
}
|
|
10933
|
+
return transformedSources;
|
|
10934
|
+
} catch (err) {
|
|
10935
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10936
|
+
throw new NestedError(`When transforming "${source.filename}": ${message}`, ensureError(err));
|
|
10937
|
+
}
|
|
10798
10938
|
}
|
|
10799
10939
|
/**
|
|
10800
10940
|
* Wrapper around [[transformSource]] which reads a file before passing it
|
|
10801
10941
|
* as-is to transformSource.
|
|
10802
10942
|
*
|
|
10943
|
+
* @internal
|
|
10803
10944
|
* @param filename - Filename to transform (according to configured
|
|
10804
10945
|
* transformations)
|
|
10805
10946
|
* @returns A list of transformed sources ready for validation.
|
|
10806
10947
|
*/
|
|
10807
|
-
transformFilename(filename) {
|
|
10948
|
+
transformFilename(resolvers, filename) {
|
|
10808
10949
|
const stdin = 0;
|
|
10809
10950
|
const src = filename !== "/dev/stdin" ? filename : stdin;
|
|
10810
10951
|
const data = fs__default.default.readFileSync(src, { encoding: "utf8" });
|
|
@@ -10816,10 +10957,12 @@ class ResolvedConfig {
|
|
|
10816
10957
|
offset: 0,
|
|
10817
10958
|
originalData: data
|
|
10818
10959
|
};
|
|
10819
|
-
return this.transformSource(source);
|
|
10960
|
+
return this.transformSource(resolvers, source);
|
|
10820
10961
|
}
|
|
10821
10962
|
/**
|
|
10822
10963
|
* Returns true if a transformer matches given filename.
|
|
10964
|
+
*
|
|
10965
|
+
* @public
|
|
10823
10966
|
*/
|
|
10824
10967
|
canTransform(filename) {
|
|
10825
10968
|
const entry = this.findTransformer(filename);
|
|
@@ -10938,6 +11081,12 @@ function toArray(value) {
|
|
|
10938
11081
|
return [value];
|
|
10939
11082
|
}
|
|
10940
11083
|
}
|
|
11084
|
+
function transformerEntries(transform) {
|
|
11085
|
+
return Object.entries(transform).map(([pattern, name]) => {
|
|
11086
|
+
const regex = new RegExp(pattern);
|
|
11087
|
+
return { pattern: regex, name };
|
|
11088
|
+
});
|
|
11089
|
+
}
|
|
10941
11090
|
class Config {
|
|
10942
11091
|
/**
|
|
10943
11092
|
* @internal
|
|
@@ -10952,10 +11101,10 @@ class Config {
|
|
|
10952
11101
|
};
|
|
10953
11102
|
this.config = mergeInternal(initial, options);
|
|
10954
11103
|
this.configurations = /* @__PURE__ */ new Map();
|
|
10955
|
-
this.initialized = false;
|
|
10956
11104
|
this.resolvers = toArray(resolvers);
|
|
10957
11105
|
this.metaTable = null;
|
|
10958
11106
|
this.plugins = [];
|
|
11107
|
+
this.transformers = transformerEntries(this.config.transform ?? {});
|
|
10959
11108
|
}
|
|
10960
11109
|
/**
|
|
10961
11110
|
* Create a new blank configuration. See also `Config.defaultConfig()`.
|
|
@@ -11038,19 +11187,10 @@ class Config {
|
|
|
11038
11187
|
return instance;
|
|
11039
11188
|
}
|
|
11040
11189
|
/**
|
|
11041
|
-
* Initialize plugins, transforms etc.
|
|
11042
|
-
*
|
|
11043
|
-
* Must be called before trying to use config. Can safely be called multiple
|
|
11044
|
-
* times.
|
|
11045
|
-
*
|
|
11046
11190
|
* @public
|
|
11191
|
+
* @deprecated Not needed any longer, this is a dummy noop method.
|
|
11047
11192
|
*/
|
|
11048
11193
|
init() {
|
|
11049
|
-
if (this.initialized) {
|
|
11050
|
-
return;
|
|
11051
|
-
}
|
|
11052
|
-
this.transformers = this.precompileTransformers(this.config.transform ?? {});
|
|
11053
|
-
this.initialized = true;
|
|
11054
11194
|
}
|
|
11055
11195
|
/**
|
|
11056
11196
|
* Returns true if this configuration is marked as "root".
|
|
@@ -11163,6 +11303,14 @@ class Config {
|
|
|
11163
11303
|
getPlugins() {
|
|
11164
11304
|
return this.plugins;
|
|
11165
11305
|
}
|
|
11306
|
+
/**
|
|
11307
|
+
* Get all configured transformers.
|
|
11308
|
+
*
|
|
11309
|
+
* @internal
|
|
11310
|
+
*/
|
|
11311
|
+
getTransformers() {
|
|
11312
|
+
return this.transformers;
|
|
11313
|
+
}
|
|
11166
11314
|
loadPlugins(plugins) {
|
|
11167
11315
|
return plugins.map((moduleName, index) => {
|
|
11168
11316
|
if (typeof moduleName !== "string") {
|
|
@@ -11246,99 +11394,6 @@ class Config {
|
|
|
11246
11394
|
transformers: this.transformers
|
|
11247
11395
|
};
|
|
11248
11396
|
}
|
|
11249
|
-
precompileTransformers(transform) {
|
|
11250
|
-
return Object.entries(transform).map(([pattern, name]) => {
|
|
11251
|
-
try {
|
|
11252
|
-
const fn = this.getTransformFunction(name);
|
|
11253
|
-
const version = fn.api ?? 0;
|
|
11254
|
-
if (version !== TRANSFORMER_API.VERSION) {
|
|
11255
|
-
throw new ConfigError(
|
|
11256
|
-
`Transformer uses API version ${String(version)} but only version ${String(TRANSFORMER_API.VERSION)} is supported`
|
|
11257
|
-
);
|
|
11258
|
-
}
|
|
11259
|
-
return {
|
|
11260
|
-
// eslint-disable-next-line security/detect-non-literal-regexp -- expected to be a regexp
|
|
11261
|
-
pattern: new RegExp(pattern),
|
|
11262
|
-
name,
|
|
11263
|
-
fn
|
|
11264
|
-
};
|
|
11265
|
-
} catch (err) {
|
|
11266
|
-
if (err instanceof ConfigError) {
|
|
11267
|
-
throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
|
|
11268
|
-
} else {
|
|
11269
|
-
throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
|
|
11270
|
-
}
|
|
11271
|
-
}
|
|
11272
|
-
});
|
|
11273
|
-
}
|
|
11274
|
-
/**
|
|
11275
|
-
* Get transformation function requested by configuration.
|
|
11276
|
-
*
|
|
11277
|
-
* Searches:
|
|
11278
|
-
*
|
|
11279
|
-
* - Named transformers from plugins.
|
|
11280
|
-
* - Unnamed transformer from plugin.
|
|
11281
|
-
* - Standalone modules (local or node_modules)
|
|
11282
|
-
*
|
|
11283
|
-
* @param name - Key from configuration
|
|
11284
|
-
*/
|
|
11285
|
-
getTransformFunction(name) {
|
|
11286
|
-
const match = name.match(/(.*):(.*)/);
|
|
11287
|
-
if (match) {
|
|
11288
|
-
const [, pluginName, key] = match;
|
|
11289
|
-
return this.getNamedTransformerFromPlugin(name, pluginName, key);
|
|
11290
|
-
}
|
|
11291
|
-
const plugin = this.plugins.find((cur) => cur.name === name);
|
|
11292
|
-
if (plugin) {
|
|
11293
|
-
return this.getUnnamedTransformerFromPlugin(name, plugin);
|
|
11294
|
-
}
|
|
11295
|
-
return this.getTransformerFromModule(name);
|
|
11296
|
-
}
|
|
11297
|
-
/**
|
|
11298
|
-
* @param name - Original name from configuration
|
|
11299
|
-
* @param pluginName - Name of plugin
|
|
11300
|
-
* @param key - Name of transform (from plugin)
|
|
11301
|
-
*/
|
|
11302
|
-
getNamedTransformerFromPlugin(name, pluginName, key) {
|
|
11303
|
-
const plugin = this.plugins.find((cur) => cur.name === pluginName);
|
|
11304
|
-
if (!plugin) {
|
|
11305
|
-
throw new ConfigError(`No plugin named "${pluginName}" has been loaded`);
|
|
11306
|
-
}
|
|
11307
|
-
if (!plugin.transformer) {
|
|
11308
|
-
throw new ConfigError(`Plugin does not expose any transformer`);
|
|
11309
|
-
}
|
|
11310
|
-
if (typeof plugin.transformer === "function") {
|
|
11311
|
-
throw new ConfigError(
|
|
11312
|
-
`Transformer "${name}" refers to named transformer but plugin exposes only unnamed, use "${pluginName}" instead.`
|
|
11313
|
-
);
|
|
11314
|
-
}
|
|
11315
|
-
const transformer = plugin.transformer[key];
|
|
11316
|
-
if (!transformer) {
|
|
11317
|
-
throw new ConfigError(`Plugin "${pluginName}" does not expose a transformer named "${key}".`);
|
|
11318
|
-
}
|
|
11319
|
-
return transformer;
|
|
11320
|
-
}
|
|
11321
|
-
/**
|
|
11322
|
-
* @param name - Original name from configuration
|
|
11323
|
-
* @param plugin - Plugin instance
|
|
11324
|
-
*/
|
|
11325
|
-
getUnnamedTransformerFromPlugin(name, plugin) {
|
|
11326
|
-
if (!plugin.transformer) {
|
|
11327
|
-
throw new ConfigError(`Plugin does not expose any transformer`);
|
|
11328
|
-
}
|
|
11329
|
-
if (typeof plugin.transformer !== "function") {
|
|
11330
|
-
if (plugin.transformer.default) {
|
|
11331
|
-
return plugin.transformer.default;
|
|
11332
|
-
}
|
|
11333
|
-
throw new ConfigError(
|
|
11334
|
-
`Transformer "${name}" refers to unnamed transformer but plugin exposes only named.`
|
|
11335
|
-
);
|
|
11336
|
-
}
|
|
11337
|
-
return plugin.transformer;
|
|
11338
|
-
}
|
|
11339
|
-
getTransformerFromModule(name) {
|
|
11340
|
-
return resolveTransformer(this.resolvers, name, { cache: true });
|
|
11341
|
-
}
|
|
11342
11397
|
}
|
|
11343
11398
|
|
|
11344
11399
|
class ConfigLoader {
|
|
@@ -11356,6 +11411,12 @@ class ConfigLoader {
|
|
|
11356
11411
|
configData ? this.loadFromObject(configData) : this.defaultConfig()
|
|
11357
11412
|
);
|
|
11358
11413
|
}
|
|
11414
|
+
/**
|
|
11415
|
+
* @internal
|
|
11416
|
+
*/
|
|
11417
|
+
getResolvers() {
|
|
11418
|
+
return this.resolvers;
|
|
11419
|
+
}
|
|
11359
11420
|
/**
|
|
11360
11421
|
* @internal For testing only
|
|
11361
11422
|
*/
|
|
@@ -11656,8 +11717,9 @@ class Parser {
|
|
|
11656
11717
|
node.closed = NodeClosed.EndTag;
|
|
11657
11718
|
}
|
|
11658
11719
|
this.closeElement(source, node, active, endToken.location);
|
|
11720
|
+
const mismatched = node.tagName !== active.tagName;
|
|
11659
11721
|
const voidClosed = !isStartTag && node.voidElement;
|
|
11660
|
-
if (!voidClosed) {
|
|
11722
|
+
if (!voidClosed && !mismatched) {
|
|
11661
11723
|
this.dom.popActive();
|
|
11662
11724
|
}
|
|
11663
11725
|
} else if (isForeign) {
|
|
@@ -11675,6 +11737,9 @@ class Parser {
|
|
|
11675
11737
|
location
|
|
11676
11738
|
};
|
|
11677
11739
|
this.trigger("tag:end", event);
|
|
11740
|
+
if (node && node.tagName !== active.tagName && active.closed !== NodeClosed.ImplicitClosed) {
|
|
11741
|
+
return;
|
|
11742
|
+
}
|
|
11678
11743
|
if (!active.isRootElement()) {
|
|
11679
11744
|
this.trigger("element:ready", {
|
|
11680
11745
|
target: active,
|
|
@@ -12535,11 +12600,9 @@ class StaticConfigLoader extends ConfigLoader {
|
|
|
12535
12600
|
getConfigFor(_handle, configOverride) {
|
|
12536
12601
|
const override = this.loadFromObject(configOverride ?? {});
|
|
12537
12602
|
if (override.isRootFound()) {
|
|
12538
|
-
override.init();
|
|
12539
12603
|
return override.resolve();
|
|
12540
12604
|
}
|
|
12541
12605
|
const merged = this.globalConfig.merge(this.resolvers, override);
|
|
12542
|
-
merged.init();
|
|
12543
12606
|
return merged.resolve();
|
|
12544
12607
|
}
|
|
12545
12608
|
flushCache() {
|
|
@@ -12609,7 +12672,8 @@ class HtmlValidate {
|
|
|
12609
12672
|
async validateSource(input, configOverride) {
|
|
12610
12673
|
const source = normalizeSource(input);
|
|
12611
12674
|
const config = await this.getConfigFor(source.filename, configOverride);
|
|
12612
|
-
const
|
|
12675
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12676
|
+
const transformedSource = config.transformSource(resolvers, source);
|
|
12613
12677
|
const engine = new Engine(config, Parser);
|
|
12614
12678
|
return engine.lint(transformedSource);
|
|
12615
12679
|
}
|
|
@@ -12623,7 +12687,8 @@ class HtmlValidate {
|
|
|
12623
12687
|
validateSourceSync(input, configOverride) {
|
|
12624
12688
|
const source = normalizeSource(input);
|
|
12625
12689
|
const config = this.getConfigForSync(source.filename, configOverride);
|
|
12626
|
-
const
|
|
12690
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12691
|
+
const transformedSource = config.transformSource(resolvers, source);
|
|
12627
12692
|
const engine = new Engine(config, Parser);
|
|
12628
12693
|
return engine.lint(transformedSource);
|
|
12629
12694
|
}
|
|
@@ -12636,7 +12701,8 @@ class HtmlValidate {
|
|
|
12636
12701
|
*/
|
|
12637
12702
|
async validateFile(filename) {
|
|
12638
12703
|
const config = await this.getConfigFor(filename);
|
|
12639
|
-
const
|
|
12704
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12705
|
+
const source = config.transformFilename(resolvers, filename);
|
|
12640
12706
|
const engine = new Engine(config, Parser);
|
|
12641
12707
|
return Promise.resolve(engine.lint(source));
|
|
12642
12708
|
}
|
|
@@ -12649,7 +12715,8 @@ class HtmlValidate {
|
|
|
12649
12715
|
*/
|
|
12650
12716
|
validateFileSync(filename) {
|
|
12651
12717
|
const config = this.getConfigForSync(filename);
|
|
12652
|
-
const
|
|
12718
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12719
|
+
const source = config.transformFilename(resolvers, filename);
|
|
12653
12720
|
const engine = new Engine(config, Parser);
|
|
12654
12721
|
return engine.lint(source);
|
|
12655
12722
|
}
|
|
@@ -12717,7 +12784,8 @@ class HtmlValidate {
|
|
|
12717
12784
|
*/
|
|
12718
12785
|
dumpTokens(filename) {
|
|
12719
12786
|
const config = this.getConfigForSync(filename);
|
|
12720
|
-
const
|
|
12787
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12788
|
+
const source = config.transformFilename(resolvers, filename);
|
|
12721
12789
|
const engine = new Engine(config, Parser);
|
|
12722
12790
|
return engine.dumpTokens(source);
|
|
12723
12791
|
}
|
|
@@ -12732,7 +12800,8 @@ class HtmlValidate {
|
|
|
12732
12800
|
*/
|
|
12733
12801
|
dumpEvents(filename) {
|
|
12734
12802
|
const config = this.getConfigForSync(filename);
|
|
12735
|
-
const
|
|
12803
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12804
|
+
const source = config.transformFilename(resolvers, filename);
|
|
12736
12805
|
const engine = new Engine(config, Parser);
|
|
12737
12806
|
return engine.dumpEvents(source);
|
|
12738
12807
|
}
|
|
@@ -12747,7 +12816,8 @@ class HtmlValidate {
|
|
|
12747
12816
|
*/
|
|
12748
12817
|
dumpTree(filename) {
|
|
12749
12818
|
const config = this.getConfigForSync(filename);
|
|
12750
|
-
const
|
|
12819
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12820
|
+
const source = config.transformFilename(resolvers, filename);
|
|
12751
12821
|
const engine = new Engine(config, Parser);
|
|
12752
12822
|
return engine.dumpTree(source);
|
|
12753
12823
|
}
|
|
@@ -12762,7 +12832,8 @@ class HtmlValidate {
|
|
|
12762
12832
|
*/
|
|
12763
12833
|
dumpSource(filename) {
|
|
12764
12834
|
const config = this.getConfigForSync(filename);
|
|
12765
|
-
const
|
|
12835
|
+
const resolvers = this.configLoader.getResolvers();
|
|
12836
|
+
const sources = config.transformFilename(resolvers, filename);
|
|
12766
12837
|
return sources.reduce((result, source) => {
|
|
12767
12838
|
const line = String(source.line);
|
|
12768
12839
|
const column = String(source.column);
|
|
@@ -12957,7 +13028,7 @@ class HtmlValidate {
|
|
|
12957
13028
|
}
|
|
12958
13029
|
|
|
12959
13030
|
const name = "html-validate";
|
|
12960
|
-
const version = "8.
|
|
13031
|
+
const version = "8.26.0";
|
|
12961
13032
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12962
13033
|
|
|
12963
13034
|
function definePlugin(plugin) {
|