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/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,
|
|
5119
|
+
this.report(null, `Stray end tag '</${current.tagName}>'`, location);
|
|
5086
5120
|
return;
|
|
5087
5121
|
}
|
|
5088
|
-
if (current.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
|
-
`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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) {
|