html-validate 5.5.0 → 6.0.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/CHANGELOG.md +42 -0
- package/dist/cjs/browser.js +2 -6
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/cli.js +41 -27
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core.d.ts +16 -7
- package/dist/cjs/core.js +527 -329
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/html-validate.js +9 -9
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/index.d.ts +11 -1
- package/dist/cjs/index.js +2 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/jest-lib.js +5 -7
- package/dist/cjs/jest-lib.js.map +1 -1
- package/dist/cjs/test-utils.js +1 -1
- package/dist/es/cli.js +19 -5
- package/dist/es/cli.js.map +1 -1
- package/dist/es/core.d.ts +16 -7
- package/dist/es/core.js +490 -292
- package/dist/es/core.js.map +1 -1
- package/dist/es/html-validate.js.map +1 -1
- package/dist/es/index.d.ts +11 -1
- package/dist/schema/elements.json +43 -5
- package/elements/html5.json +940 -307
- package/package.json +20 -21
package/dist/cjs/core.js
CHANGED
|
@@ -268,7 +268,7 @@ class UserError extends NestedError {
|
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
function getSummary(schema, obj, errors) {
|
|
271
|
-
const output = betterAjvErrors__default[
|
|
271
|
+
const output = betterAjvErrors__default["default"](schema, obj, errors, {
|
|
272
272
|
format: "js",
|
|
273
273
|
});
|
|
274
274
|
// istanbul ignore next: for safety only
|
|
@@ -285,15 +285,15 @@ class SchemaValidationError extends UserError {
|
|
|
285
285
|
}
|
|
286
286
|
prettyError() {
|
|
287
287
|
const json = this.getRawJSON();
|
|
288
|
-
return betterAjvErrors__default[
|
|
288
|
+
return betterAjvErrors__default["default"](this.schema, this.obj, this.errors, {
|
|
289
289
|
format: "cli",
|
|
290
290
|
indent: 2,
|
|
291
291
|
json,
|
|
292
292
|
});
|
|
293
293
|
}
|
|
294
294
|
getRawJSON() {
|
|
295
|
-
if (this.filename && fs__default[
|
|
296
|
-
return fs__default[
|
|
295
|
+
if (this.filename && fs__default["default"].existsSync(this.filename)) {
|
|
296
|
+
return fs__default["default"].readFileSync(this.filename, "utf-8");
|
|
297
297
|
}
|
|
298
298
|
else {
|
|
299
299
|
return null;
|
|
@@ -301,9 +301,9 @@ class SchemaValidationError extends UserError {
|
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
const projectRoot = path__default[
|
|
304
|
+
const projectRoot = path__default["default"].resolve(__dirname, "../../");
|
|
305
305
|
const legacyRequire = require;
|
|
306
|
-
const distFolder = path__default[
|
|
306
|
+
const distFolder = path__default["default"].resolve(projectRoot, "dist/cjs");
|
|
307
307
|
|
|
308
308
|
/**
|
|
309
309
|
* Similar to `require(..)` but removes the cached copy first.
|
|
@@ -586,18 +586,63 @@ const definitions = {
|
|
|
586
586
|
type: "object",
|
|
587
587
|
patternProperties: {
|
|
588
588
|
"^.*$": {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
{
|
|
589
|
+
anyOf: [
|
|
590
|
+
{
|
|
591
|
+
type: "object",
|
|
592
|
+
additionalProperties: false,
|
|
593
|
+
properties: {
|
|
594
|
+
boolean: {
|
|
595
|
+
type: "boolean",
|
|
596
|
+
title: "Set to true if this is a boolean attribute"
|
|
597
|
+
},
|
|
598
|
+
deprecated: {
|
|
599
|
+
title: "Set to true or string if this attribute is deprecated",
|
|
600
|
+
oneOf: [
|
|
601
|
+
{
|
|
602
|
+
type: "boolean"
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
type: "string"
|
|
606
|
+
}
|
|
607
|
+
]
|
|
608
|
+
},
|
|
609
|
+
list: {
|
|
610
|
+
type: "boolean",
|
|
611
|
+
title: "Set to true if this attribute is a list of space-separated tokens, each which must be valid by itself"
|
|
612
|
+
},
|
|
613
|
+
"enum": {
|
|
614
|
+
type: "array",
|
|
615
|
+
title: "Exhaustive list of values (string or regex) this attribute accepts",
|
|
616
|
+
uniqueItems: true,
|
|
617
|
+
items: {
|
|
618
|
+
anyOf: [
|
|
619
|
+
{
|
|
620
|
+
type: "string"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
regexp: true
|
|
624
|
+
}
|
|
625
|
+
]
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
omit: {
|
|
629
|
+
type: "boolean",
|
|
630
|
+
title: "Set to true if this attribute can optionally omit its value"
|
|
631
|
+
},
|
|
632
|
+
required: {
|
|
633
|
+
type: "boolean",
|
|
634
|
+
title: "Set to true if this attribute is required"
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
type: "array",
|
|
640
|
+
uniqueItems: true,
|
|
641
|
+
items: {
|
|
594
642
|
type: "string"
|
|
595
|
-
},
|
|
596
|
-
{
|
|
597
|
-
regexp: true
|
|
598
643
|
}
|
|
599
|
-
|
|
600
|
-
|
|
644
|
+
}
|
|
645
|
+
]
|
|
601
646
|
}
|
|
602
647
|
}
|
|
603
648
|
},
|
|
@@ -648,6 +693,111 @@ var schema = {
|
|
|
648
693
|
definitions: definitions
|
|
649
694
|
};
|
|
650
695
|
|
|
696
|
+
var TextContent$1;
|
|
697
|
+
(function (TextContent) {
|
|
698
|
+
/* forbid node to have text content, inter-element whitespace is ignored */
|
|
699
|
+
TextContent["NONE"] = "none";
|
|
700
|
+
/* node can have text but not required too */
|
|
701
|
+
TextContent["DEFAULT"] = "default";
|
|
702
|
+
/* node requires text-nodes to be present (direct or by descendant) */
|
|
703
|
+
TextContent["REQUIRED"] = "required";
|
|
704
|
+
/* node requires accessible text (hidden text is ignored, tries to get text from accessibility tree) */
|
|
705
|
+
TextContent["ACCESSIBLE"] = "accessible";
|
|
706
|
+
})(TextContent$1 || (TextContent$1 = {}));
|
|
707
|
+
/**
|
|
708
|
+
* Properties listed here can be copied (loaded) onto another element using
|
|
709
|
+
* [[HtmlElement.loadMeta]].
|
|
710
|
+
*/
|
|
711
|
+
const MetaCopyableProperty = [
|
|
712
|
+
"metadata",
|
|
713
|
+
"flow",
|
|
714
|
+
"sectioning",
|
|
715
|
+
"heading",
|
|
716
|
+
"phrasing",
|
|
717
|
+
"embedded",
|
|
718
|
+
"interactive",
|
|
719
|
+
"transparent",
|
|
720
|
+
"form",
|
|
721
|
+
"labelable",
|
|
722
|
+
"attributes",
|
|
723
|
+
"permittedContent",
|
|
724
|
+
"permittedDescendants",
|
|
725
|
+
"permittedOrder",
|
|
726
|
+
"requiredAncestors",
|
|
727
|
+
"requiredContent",
|
|
728
|
+
];
|
|
729
|
+
/**
|
|
730
|
+
* @internal
|
|
731
|
+
*/
|
|
732
|
+
function setMetaProperty(dst, key, value) {
|
|
733
|
+
dst[key] = value;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function isSet(value) {
|
|
737
|
+
return typeof value !== "undefined";
|
|
738
|
+
}
|
|
739
|
+
function flag(value) {
|
|
740
|
+
return value ? true : undefined;
|
|
741
|
+
}
|
|
742
|
+
function stripUndefined(src) {
|
|
743
|
+
const entries = Object.entries(src).filter(([, value]) => isSet(value));
|
|
744
|
+
return Object.fromEntries(entries);
|
|
745
|
+
}
|
|
746
|
+
function migrateSingleAttribute(src, key) {
|
|
747
|
+
var _a, _b;
|
|
748
|
+
const result = {};
|
|
749
|
+
result.deprecated = flag((_a = src.deprecatedAttributes) === null || _a === void 0 ? void 0 : _a.includes(key));
|
|
750
|
+
result.required = flag((_b = src.requiredAttributes) === null || _b === void 0 ? void 0 : _b.includes(key));
|
|
751
|
+
result.omit = undefined;
|
|
752
|
+
const attr = src.attributes ? src.attributes[key] : undefined;
|
|
753
|
+
if (typeof attr === "undefined") {
|
|
754
|
+
return stripUndefined(result);
|
|
755
|
+
}
|
|
756
|
+
/* when the attribute is set to null we use a special property "delete" to
|
|
757
|
+
* flag it, if it is still set during merge (inheritance, overwriting, etc) the attribute will be removed */
|
|
758
|
+
if (attr === null) {
|
|
759
|
+
result.delete = true;
|
|
760
|
+
return stripUndefined(result);
|
|
761
|
+
}
|
|
762
|
+
if (Array.isArray(attr)) {
|
|
763
|
+
if (attr.length === 0) {
|
|
764
|
+
result.boolean = true;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
result.enum = attr.filter((it) => it !== "");
|
|
768
|
+
if (attr.includes("")) {
|
|
769
|
+
result.omit = true;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return stripUndefined(result);
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
return stripUndefined({ ...result, ...attr });
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
function migrateAttributes(src) {
|
|
779
|
+
var _a, _b, _c;
|
|
780
|
+
const keys = [
|
|
781
|
+
...Object.keys((_a = src.attributes) !== null && _a !== void 0 ? _a : {}),
|
|
782
|
+
...((_b = src.requiredAttributes) !== null && _b !== void 0 ? _b : []),
|
|
783
|
+
...((_c = src.deprecatedAttributes) !== null && _c !== void 0 ? _c : []),
|
|
784
|
+
].sort();
|
|
785
|
+
const entries = keys.map((key) => {
|
|
786
|
+
return [key, migrateSingleAttribute(src, key)];
|
|
787
|
+
});
|
|
788
|
+
return Object.fromEntries(entries);
|
|
789
|
+
}
|
|
790
|
+
function migrateElement(src) {
|
|
791
|
+
const result = {
|
|
792
|
+
...src,
|
|
793
|
+
attributes: migrateAttributes(src),
|
|
794
|
+
};
|
|
795
|
+
/* removed properties */
|
|
796
|
+
delete result.deprecatedAttributes;
|
|
797
|
+
delete result.requiredAttributes;
|
|
798
|
+
return result;
|
|
799
|
+
}
|
|
800
|
+
|
|
651
801
|
const dynamicKeys = [
|
|
652
802
|
"metadata",
|
|
653
803
|
"flow",
|
|
@@ -710,7 +860,7 @@ class MetaTable {
|
|
|
710
860
|
*/
|
|
711
861
|
extendValidationSchema(patch) {
|
|
712
862
|
if (patch.properties) {
|
|
713
|
-
this.schema = jsonMergePatch__default[
|
|
863
|
+
this.schema = jsonMergePatch__default["default"].apply(this.schema, {
|
|
714
864
|
patternProperties: {
|
|
715
865
|
"^[^$].*$": {
|
|
716
866
|
properties: patch.properties,
|
|
@@ -719,7 +869,7 @@ class MetaTable {
|
|
|
719
869
|
});
|
|
720
870
|
}
|
|
721
871
|
if (patch.definitions) {
|
|
722
|
-
this.schema = jsonMergePatch__default[
|
|
872
|
+
this.schema = jsonMergePatch__default["default"].apply(this.schema, {
|
|
723
873
|
definitions: patch.definitions,
|
|
724
874
|
});
|
|
725
875
|
}
|
|
@@ -741,7 +891,7 @@ class MetaTable {
|
|
|
741
891
|
for (const [key, value] of Object.entries(obj)) {
|
|
742
892
|
if (key === "$schema")
|
|
743
893
|
continue;
|
|
744
|
-
this.addEntry(key, value);
|
|
894
|
+
this.addEntry(key, migrateElement(value));
|
|
745
895
|
}
|
|
746
896
|
}
|
|
747
897
|
/**
|
|
@@ -769,7 +919,7 @@ class MetaTable {
|
|
|
769
919
|
*/
|
|
770
920
|
getMetaFor(tagName) {
|
|
771
921
|
tagName = tagName.toLowerCase();
|
|
772
|
-
return this.elements[tagName] ?
|
|
922
|
+
return this.elements[tagName] ? { ...this.elements[tagName] } : null;
|
|
773
923
|
}
|
|
774
924
|
/**
|
|
775
925
|
* Find all tags which has enabled given property.
|
|
@@ -798,7 +948,7 @@ class MetaTable {
|
|
|
798
948
|
}
|
|
799
949
|
}
|
|
800
950
|
/* merge all sources together */
|
|
801
|
-
const expanded =
|
|
951
|
+
const expanded = this.mergeElement(parent, { ...entry, tagName });
|
|
802
952
|
expandRegex(expanded);
|
|
803
953
|
this.elements[tagName] = expanded;
|
|
804
954
|
}
|
|
@@ -806,7 +956,7 @@ class MetaTable {
|
|
|
806
956
|
* Construct a new AJV schema validator.
|
|
807
957
|
*/
|
|
808
958
|
getSchemaValidator() {
|
|
809
|
-
const ajv = new Ajv__default[
|
|
959
|
+
const ajv = new Ajv__default["default"]({ strict: true, strictTuples: true, strictTypes: true });
|
|
810
960
|
ajv.addMetaSchema(ajvSchemaDraft);
|
|
811
961
|
ajv.addKeyword(ajvRegexpKeyword);
|
|
812
962
|
ajv.addKeyword({ keyword: "copyable" });
|
|
@@ -836,7 +986,16 @@ class MetaTable {
|
|
|
836
986
|
}
|
|
837
987
|
}
|
|
838
988
|
mergeElement(a, b) {
|
|
839
|
-
|
|
989
|
+
const merged = deepmerge__default["default"](a, b, { arrayMerge: overwriteMerge$1 });
|
|
990
|
+
/* special handling when removing attributes by setting them to null
|
|
991
|
+
* resulting in the deletion flag being set */
|
|
992
|
+
const filteredAttrs = Object.entries(merged.attributes).filter(([, attr]) => {
|
|
993
|
+
const val = !attr.delete;
|
|
994
|
+
delete attr.delete;
|
|
995
|
+
return val;
|
|
996
|
+
});
|
|
997
|
+
merged.attributes = Object.fromEntries(filteredAttrs);
|
|
998
|
+
return merged;
|
|
840
999
|
}
|
|
841
1000
|
resolve(node) {
|
|
842
1001
|
if (node.meta) {
|
|
@@ -848,7 +1007,7 @@ function expandProperties(node, entry) {
|
|
|
848
1007
|
for (const key of dynamicKeys) {
|
|
849
1008
|
const property = entry[key];
|
|
850
1009
|
if (property && typeof property !== "boolean") {
|
|
851
|
-
entry
|
|
1010
|
+
setMetaProperty(entry, key, evaluateProperty(node, property));
|
|
852
1011
|
}
|
|
853
1012
|
}
|
|
854
1013
|
}
|
|
@@ -874,14 +1033,9 @@ function expandRegexValue(value) {
|
|
|
874
1033
|
* Expand all regular expressions in strings ("/../"). This mutates the object.
|
|
875
1034
|
*/
|
|
876
1035
|
function expandRegex(entry) {
|
|
877
|
-
if (!entry.attributes)
|
|
878
|
-
return;
|
|
879
1036
|
for (const [name, values] of Object.entries(entry.attributes)) {
|
|
880
|
-
if (values) {
|
|
881
|
-
entry.attributes[name] = values.map(expandRegexValue);
|
|
882
|
-
}
|
|
883
|
-
else {
|
|
884
|
-
delete entry.attributes[name];
|
|
1037
|
+
if (values.enum) {
|
|
1038
|
+
entry.attributes[name].enum = values.enum.map(expandRegexValue);
|
|
885
1039
|
}
|
|
886
1040
|
}
|
|
887
1041
|
}
|
|
@@ -937,41 +1091,6 @@ function matchAttribute(node, match) {
|
|
|
937
1091
|
}
|
|
938
1092
|
}
|
|
939
1093
|
|
|
940
|
-
var TextContent$1;
|
|
941
|
-
(function (TextContent) {
|
|
942
|
-
/* forbid node to have text content, inter-element whitespace is ignored */
|
|
943
|
-
TextContent["NONE"] = "none";
|
|
944
|
-
/* node can have text but not required too */
|
|
945
|
-
TextContent["DEFAULT"] = "default";
|
|
946
|
-
/* node requires text-nodes to be present (direct or by descendant) */
|
|
947
|
-
TextContent["REQUIRED"] = "required";
|
|
948
|
-
/* node requires accessible text (hidden text is ignored, tries to get text from accessibility tree) */
|
|
949
|
-
TextContent["ACCESSIBLE"] = "accessible";
|
|
950
|
-
})(TextContent$1 || (TextContent$1 = {}));
|
|
951
|
-
/**
|
|
952
|
-
* Properties listed here can be copied (loaded) onto another element using
|
|
953
|
-
* [[HtmlElement.loadMeta]].
|
|
954
|
-
*/
|
|
955
|
-
const MetaCopyableProperty = [
|
|
956
|
-
"metadata",
|
|
957
|
-
"flow",
|
|
958
|
-
"sectioning",
|
|
959
|
-
"heading",
|
|
960
|
-
"phrasing",
|
|
961
|
-
"embedded",
|
|
962
|
-
"interactive",
|
|
963
|
-
"transparent",
|
|
964
|
-
"form",
|
|
965
|
-
"labelable",
|
|
966
|
-
"requiredAttributes",
|
|
967
|
-
"attributes",
|
|
968
|
-
"permittedContent",
|
|
969
|
-
"permittedDescendants",
|
|
970
|
-
"permittedOrder",
|
|
971
|
-
"requiredAncestors",
|
|
972
|
-
"requiredContent",
|
|
973
|
-
];
|
|
974
|
-
|
|
975
1094
|
class DynamicValue {
|
|
976
1095
|
constructor(expr) {
|
|
977
1096
|
this.expr = expr;
|
|
@@ -1823,8 +1942,9 @@ class HtmlElement extends DOMNode {
|
|
|
1823
1942
|
this.metaElement = {};
|
|
1824
1943
|
}
|
|
1825
1944
|
for (const key of MetaCopyableProperty) {
|
|
1826
|
-
|
|
1827
|
-
|
|
1945
|
+
const value = meta[key];
|
|
1946
|
+
if (typeof value !== "undefined") {
|
|
1947
|
+
setMetaProperty(this.metaElement, key, value);
|
|
1828
1948
|
}
|
|
1829
1949
|
else {
|
|
1830
1950
|
delete this.metaElement[key];
|
|
@@ -2240,6 +2360,7 @@ class Validator {
|
|
|
2240
2360
|
* @param rules - Element attribute metadta.
|
|
2241
2361
|
* @returns `true` if attribute passes all tests.
|
|
2242
2362
|
*/
|
|
2363
|
+
/* eslint-disable-next-line complexity */
|
|
2243
2364
|
static validateAttribute(attr, rules) {
|
|
2244
2365
|
const rule = rules[attr.key];
|
|
2245
2366
|
if (!rule) {
|
|
@@ -2253,19 +2374,34 @@ class Validator {
|
|
|
2253
2374
|
return true;
|
|
2254
2375
|
}
|
|
2255
2376
|
const empty = value === null || value === "";
|
|
2256
|
-
/*
|
|
2257
|
-
|
|
2377
|
+
/* if boolean is set the value can be either null, empty string or the
|
|
2378
|
+
* attribute key (attribute-boolean-style regulates style) */
|
|
2379
|
+
if (rule.boolean) {
|
|
2258
2380
|
return empty || value === attr.key;
|
|
2259
2381
|
}
|
|
2260
|
-
/* if the
|
|
2261
|
-
* (
|
|
2262
|
-
if (rule.
|
|
2382
|
+
/* if omit is set the value can be either null or empty string
|
|
2383
|
+
* (attribute-empty style regulates style) */
|
|
2384
|
+
if (rule.omit && empty) {
|
|
2385
|
+
return true;
|
|
2386
|
+
}
|
|
2387
|
+
/* validate each token when using list, all tokens must be valid */
|
|
2388
|
+
if (rule.list) {
|
|
2389
|
+
const tokens = new DOMTokenList(value, attr.valueLocation);
|
|
2390
|
+
return tokens.every((token) => {
|
|
2391
|
+
return this.validateAttributeValue(token, rule);
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
return this.validateAttributeValue(value, rule);
|
|
2395
|
+
}
|
|
2396
|
+
static validateAttributeValue(value, rule) {
|
|
2397
|
+
/* skip attribute if it not have enumerated list */
|
|
2398
|
+
if (!rule.enum) {
|
|
2263
2399
|
return true;
|
|
2264
2400
|
}
|
|
2265
2401
|
if (value === null || value === undefined) {
|
|
2266
2402
|
return false;
|
|
2267
2403
|
}
|
|
2268
|
-
return rule.some((entry) => {
|
|
2404
|
+
return rule.enum.some((entry) => {
|
|
2269
2405
|
if (entry instanceof RegExp) {
|
|
2270
2406
|
return !!value.match(entry);
|
|
2271
2407
|
}
|
|
@@ -2531,12 +2667,12 @@ var configurationSchema = {
|
|
|
2531
2667
|
const espree = legacyRequire("espree");
|
|
2532
2668
|
const walk = legacyRequire("acorn-walk");
|
|
2533
2669
|
function joinTemplateLiteral(nodes) {
|
|
2534
|
-
let offset = nodes[0].start;
|
|
2670
|
+
let offset = nodes[0].start + 1;
|
|
2535
2671
|
let output = "";
|
|
2536
2672
|
for (const node of nodes) {
|
|
2537
|
-
output += " ".repeat(node.start - offset);
|
|
2673
|
+
output += " ".repeat(node.start + 1 - offset);
|
|
2538
2674
|
output += node.value.raw;
|
|
2539
|
-
offset = node.end;
|
|
2675
|
+
offset = node.end - 2;
|
|
2540
2676
|
}
|
|
2541
2677
|
return output;
|
|
2542
2678
|
}
|
|
@@ -2641,7 +2777,7 @@ class TemplateExtractor {
|
|
|
2641
2777
|
this.data = data;
|
|
2642
2778
|
}
|
|
2643
2779
|
static fromFilename(filename) {
|
|
2644
|
-
const source = fs__default[
|
|
2780
|
+
const source = fs__default["default"].readFileSync(filename, "utf-8");
|
|
2645
2781
|
const ast = espree.parse(source, {
|
|
2646
2782
|
ecmaVersion: 2017,
|
|
2647
2783
|
sourceType: "module",
|
|
@@ -2677,7 +2813,7 @@ class TemplateExtractor {
|
|
|
2677
2813
|
* functions.
|
|
2678
2814
|
*/
|
|
2679
2815
|
static createSource(filename) {
|
|
2680
|
-
const data = fs__default[
|
|
2816
|
+
const data = fs__default["default"].readFileSync(filename, "utf-8");
|
|
2681
2817
|
return [
|
|
2682
2818
|
{
|
|
2683
2819
|
column: 1,
|
|
@@ -2728,7 +2864,7 @@ var TRANSFORMER_API;
|
|
|
2728
2864
|
})(TRANSFORMER_API || (TRANSFORMER_API = {}));
|
|
2729
2865
|
|
|
2730
2866
|
const name = "html-validate";
|
|
2731
|
-
const version = "
|
|
2867
|
+
const version = "6.0.0";
|
|
2732
2868
|
const homepage = "https://html-validate.org";
|
|
2733
2869
|
const bugs = {
|
|
2734
2870
|
url: "https://gitlab.com/html-validate/html-validate/issues/new"
|
|
@@ -2765,7 +2901,7 @@ const remapEvents = {
|
|
|
2765
2901
|
"tag:open": "tag:start",
|
|
2766
2902
|
"tag:close": "tag:end",
|
|
2767
2903
|
};
|
|
2768
|
-
const ajv$1 = new Ajv__default[
|
|
2904
|
+
const ajv$1 = new Ajv__default["default"]({ strict: true, strictTuples: true, strictTypes: true });
|
|
2769
2905
|
ajv$1.addMetaSchema(ajvSchemaDraft);
|
|
2770
2906
|
/**
|
|
2771
2907
|
* Get (cached) schema validator for rule options.
|
|
@@ -2993,9 +3129,9 @@ function ruleDocumentationUrl(filename) {
|
|
|
2993
3129
|
* folder and with the @/ prefix, by replacing the @ with the dist folder we
|
|
2994
3130
|
* can resolve the path properly */
|
|
2995
3131
|
filename = filename.replace("@", distFolder);
|
|
2996
|
-
const p = path__default[
|
|
2997
|
-
const root = path__default[
|
|
2998
|
-
const rel = path__default[
|
|
3132
|
+
const p = path__default["default"].parse(filename);
|
|
3133
|
+
const root = path__default["default"].join(distFolder, "rules");
|
|
3134
|
+
const rel = path__default["default"].relative(root, path__default["default"].join(p.dir, p.name));
|
|
2999
3135
|
return `${homepage}/rules/${rel}.html`;
|
|
3000
3136
|
}
|
|
3001
3137
|
|
|
@@ -3020,7 +3156,7 @@ const description = {
|
|
|
3020
3156
|
};
|
|
3021
3157
|
class AllowedLinks extends Rule {
|
|
3022
3158
|
constructor(options) {
|
|
3023
|
-
super(
|
|
3159
|
+
super({ ...defaults$p, ...options });
|
|
3024
3160
|
}
|
|
3025
3161
|
static schema() {
|
|
3026
3162
|
return {
|
|
@@ -3268,7 +3404,7 @@ const defaults$o = {
|
|
|
3268
3404
|
};
|
|
3269
3405
|
class AttrCase extends Rule {
|
|
3270
3406
|
constructor(options) {
|
|
3271
|
-
super(
|
|
3407
|
+
super({ ...defaults$o, ...options });
|
|
3272
3408
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
3273
3409
|
}
|
|
3274
3410
|
static schema() {
|
|
@@ -3621,7 +3757,7 @@ function generateDescription(name, pattern) {
|
|
|
3621
3757
|
}
|
|
3622
3758
|
class AttrPattern extends Rule {
|
|
3623
3759
|
constructor(options) {
|
|
3624
|
-
super(
|
|
3760
|
+
super({ ...defaults$n, ...options });
|
|
3625
3761
|
this.pattern = generateRegexp(this.options.pattern);
|
|
3626
3762
|
}
|
|
3627
3763
|
static schema() {
|
|
@@ -3687,7 +3823,7 @@ const defaults$m = {
|
|
|
3687
3823
|
};
|
|
3688
3824
|
class AttrQuotes extends Rule {
|
|
3689
3825
|
constructor(options) {
|
|
3690
|
-
super(
|
|
3826
|
+
super({ ...defaults$m, ...options });
|
|
3691
3827
|
this.style = parseStyle$4(this.options.style);
|
|
3692
3828
|
}
|
|
3693
3829
|
static schema() {
|
|
@@ -3783,11 +3919,11 @@ class AttributeAllowedValues extends Rule {
|
|
|
3783
3919
|
if (!context) {
|
|
3784
3920
|
return docs;
|
|
3785
3921
|
}
|
|
3786
|
-
if (context.allowed.
|
|
3787
|
-
const allowed = context.allowed.map((val) => `- \`${val}\``);
|
|
3922
|
+
if (context.allowed.enum) {
|
|
3923
|
+
const allowed = context.allowed.enum.map((val) => `- \`${val}\``);
|
|
3788
3924
|
docs.description = `Element <${context.element}> does not allow attribute \`${context.attribute}\` to have the value \`"${context.value}"\`, it must match one of the following:\n\n${allowed.join("\n")}`;
|
|
3789
3925
|
}
|
|
3790
|
-
else {
|
|
3926
|
+
else if (context.allowed.boolean) {
|
|
3791
3927
|
docs.description = `Element <${context.element}> attribute \`${context.attribute}\` must be a boolean attribute, e.g. \`<${context.element} ${context.attribute}>\``;
|
|
3792
3928
|
}
|
|
3793
3929
|
return docs;
|
|
@@ -3843,7 +3979,7 @@ const defaults$l = {
|
|
|
3843
3979
|
};
|
|
3844
3980
|
class AttributeBooleanStyle extends Rule {
|
|
3845
3981
|
constructor(options) {
|
|
3846
|
-
super(
|
|
3982
|
+
super({ ...defaults$l, ...options });
|
|
3847
3983
|
this.hasInvalidStyle = parseStyle$3(this.options.style);
|
|
3848
3984
|
}
|
|
3849
3985
|
static schema() {
|
|
@@ -3888,7 +4024,8 @@ class AttributeBooleanStyle extends Rule {
|
|
|
3888
4024
|
});
|
|
3889
4025
|
}
|
|
3890
4026
|
isBoolean(attr, rules) {
|
|
3891
|
-
|
|
4027
|
+
var _a;
|
|
4028
|
+
return Boolean((_a = rules[attr.key]) === null || _a === void 0 ? void 0 : _a.boolean);
|
|
3892
4029
|
}
|
|
3893
4030
|
}
|
|
3894
4031
|
function parseStyle$3(style) {
|
|
@@ -3923,7 +4060,7 @@ const defaults$k = {
|
|
|
3923
4060
|
};
|
|
3924
4061
|
class AttributeEmptyStyle extends Rule {
|
|
3925
4062
|
constructor(options) {
|
|
3926
|
-
super(
|
|
4063
|
+
super({ ...defaults$k, ...options });
|
|
3927
4064
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
3928
4065
|
}
|
|
3929
4066
|
static schema() {
|
|
@@ -3972,7 +4109,8 @@ class AttributeEmptyStyle extends Rule {
|
|
|
3972
4109
|
}
|
|
3973
4110
|
}
|
|
3974
4111
|
function allowsEmpty(attr, rules) {
|
|
3975
|
-
|
|
4112
|
+
var _a;
|
|
4113
|
+
return Boolean((_a = rules[attr.key]) === null || _a === void 0 ? void 0 : _a.omit);
|
|
3976
4114
|
}
|
|
3977
4115
|
function isEmptyValue(attr) {
|
|
3978
4116
|
/* dynamic values are ignored, assumed to contain a value */
|
|
@@ -4035,7 +4173,7 @@ const defaults$j = {
|
|
|
4035
4173
|
};
|
|
4036
4174
|
class ClassPattern extends Rule {
|
|
4037
4175
|
constructor(options) {
|
|
4038
|
-
super(
|
|
4176
|
+
super({ ...defaults$j, ...options });
|
|
4039
4177
|
this.pattern = parsePattern(this.options.pattern);
|
|
4040
4178
|
}
|
|
4041
4179
|
static schema() {
|
|
@@ -4148,7 +4286,7 @@ const defaults$i = {
|
|
|
4148
4286
|
};
|
|
4149
4287
|
class Deprecated extends Rule {
|
|
4150
4288
|
constructor(options) {
|
|
4151
|
-
super(
|
|
4289
|
+
super({ ...defaults$i, ...options });
|
|
4152
4290
|
}
|
|
4153
4291
|
static schema() {
|
|
4154
4292
|
return {
|
|
@@ -4242,7 +4380,7 @@ class Deprecated extends Rule {
|
|
|
4242
4380
|
this.report(node, message, location, context);
|
|
4243
4381
|
}
|
|
4244
4382
|
reportObject(deprecated, node, location) {
|
|
4245
|
-
const context =
|
|
4383
|
+
const context = { ...deprecated, tagName: node.tagName };
|
|
4246
4384
|
const notice = deprecated.message ? `: ${deprecated.message}` : "";
|
|
4247
4385
|
const message = `<${node.tagName}> is deprecated${notice}`;
|
|
4248
4386
|
this.report(node, message, location, context);
|
|
@@ -4316,7 +4454,7 @@ const defaults$h = {
|
|
|
4316
4454
|
};
|
|
4317
4455
|
class DoctypeStyle extends Rule {
|
|
4318
4456
|
constructor(options) {
|
|
4319
|
-
super(
|
|
4457
|
+
super({ ...defaults$h, ...options });
|
|
4320
4458
|
}
|
|
4321
4459
|
static schema() {
|
|
4322
4460
|
return {
|
|
@@ -4353,7 +4491,7 @@ const defaults$g = {
|
|
|
4353
4491
|
};
|
|
4354
4492
|
class ElementCase extends Rule {
|
|
4355
4493
|
constructor(options) {
|
|
4356
|
-
super(
|
|
4494
|
+
super({ ...defaults$g, ...options });
|
|
4357
4495
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
4358
4496
|
}
|
|
4359
4497
|
static schema() {
|
|
@@ -4423,7 +4561,7 @@ const defaults$f = {
|
|
|
4423
4561
|
};
|
|
4424
4562
|
class ElementName extends Rule {
|
|
4425
4563
|
constructor(options) {
|
|
4426
|
-
super(
|
|
4564
|
+
super({ ...defaults$f, ...options });
|
|
4427
4565
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
4428
4566
|
this.pattern = new RegExp(this.options.pattern);
|
|
4429
4567
|
}
|
|
@@ -4695,9 +4833,14 @@ class ElementRequiredAttributes extends Rule {
|
|
|
4695
4833
|
this.on("tag:end", (event) => {
|
|
4696
4834
|
const node = event.previous;
|
|
4697
4835
|
const meta = node.meta;
|
|
4698
|
-
|
|
4836
|
+
/* handle missing metadata and missing attributes */
|
|
4837
|
+
if (!meta || !meta.attributes) {
|
|
4699
4838
|
return;
|
|
4700
|
-
|
|
4839
|
+
}
|
|
4840
|
+
for (const [key, attr] of Object.entries(meta.attributes)) {
|
|
4841
|
+
if (!attr.required) {
|
|
4842
|
+
continue;
|
|
4843
|
+
}
|
|
4701
4844
|
if (node.hasAttribute(key))
|
|
4702
4845
|
continue;
|
|
4703
4846
|
const context = {
|
|
@@ -4880,7 +5023,7 @@ function parseMaxInitial(value) {
|
|
|
4880
5023
|
}
|
|
4881
5024
|
class HeadingLevel extends Rule {
|
|
4882
5025
|
constructor(options) {
|
|
4883
|
-
super(
|
|
5026
|
+
super({ ...defaults$e, ...options });
|
|
4884
5027
|
this.stack = [];
|
|
4885
5028
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
4886
5029
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
|
|
@@ -5043,7 +5186,7 @@ const defaults$d = {
|
|
|
5043
5186
|
};
|
|
5044
5187
|
class IdPattern extends Rule {
|
|
5045
5188
|
constructor(options) {
|
|
5046
|
-
super(
|
|
5189
|
+
super({ ...defaults$d, ...options });
|
|
5047
5190
|
this.pattern = parsePattern(this.options.pattern);
|
|
5048
5191
|
}
|
|
5049
5192
|
static schema() {
|
|
@@ -5395,7 +5538,7 @@ const defaults$c = {
|
|
|
5395
5538
|
};
|
|
5396
5539
|
class LongTitle extends Rule {
|
|
5397
5540
|
constructor(options) {
|
|
5398
|
-
super(
|
|
5541
|
+
super({ ...defaults$c, ...options });
|
|
5399
5542
|
this.maxlength = this.options.maxlength;
|
|
5400
5543
|
}
|
|
5401
5544
|
static schema() {
|
|
@@ -5548,7 +5691,7 @@ const defaults$b = {
|
|
|
5548
5691
|
};
|
|
5549
5692
|
class NoAutoplay extends Rule {
|
|
5550
5693
|
constructor(options) {
|
|
5551
|
-
super(
|
|
5694
|
+
super({ ...defaults$b, ...options });
|
|
5552
5695
|
}
|
|
5553
5696
|
documentation(context) {
|
|
5554
5697
|
const tagName = context ? ` on <${context.tagName}>` : "";
|
|
@@ -5644,8 +5787,12 @@ class NoDeprecatedAttr extends Rule {
|
|
|
5644
5787
|
if (meta === null) {
|
|
5645
5788
|
return;
|
|
5646
5789
|
}
|
|
5647
|
-
const
|
|
5648
|
-
if (
|
|
5790
|
+
const metaAttribute = meta.attributes && meta.attributes[attr];
|
|
5791
|
+
if (!metaAttribute) {
|
|
5792
|
+
return;
|
|
5793
|
+
}
|
|
5794
|
+
const deprecated = metaAttribute.deprecated;
|
|
5795
|
+
if (deprecated) {
|
|
5649
5796
|
this.report(node, `Attribute "${event.key}" is deprecated on <${node.tagName}> element`, event.keyLocation);
|
|
5650
5797
|
}
|
|
5651
5798
|
});
|
|
@@ -5802,7 +5949,7 @@ function getCSSDeclarations(value) {
|
|
|
5802
5949
|
}
|
|
5803
5950
|
class NoInlineStyle extends Rule {
|
|
5804
5951
|
constructor(options) {
|
|
5805
|
-
super(
|
|
5952
|
+
super({ ...defaults$a, ...options });
|
|
5806
5953
|
}
|
|
5807
5954
|
static schema() {
|
|
5808
5955
|
return {
|
|
@@ -6024,7 +6171,7 @@ const replacementTable = new Map([
|
|
|
6024
6171
|
]);
|
|
6025
6172
|
class NoRawCharacters extends Rule {
|
|
6026
6173
|
constructor(options) {
|
|
6027
|
-
super(
|
|
6174
|
+
super({ ...defaults$9, ...options });
|
|
6028
6175
|
this.relaxed = this.options.relaxed;
|
|
6029
6176
|
}
|
|
6030
6177
|
static schema() {
|
|
@@ -6209,7 +6356,7 @@ const defaults$8 = {
|
|
|
6209
6356
|
};
|
|
6210
6357
|
class NoSelfClosing extends Rule {
|
|
6211
6358
|
constructor(options) {
|
|
6212
|
-
super(
|
|
6359
|
+
super({ ...defaults$8, ...options });
|
|
6213
6360
|
}
|
|
6214
6361
|
static schema() {
|
|
6215
6362
|
return {
|
|
@@ -6348,7 +6495,7 @@ const defaults$7 = {
|
|
|
6348
6495
|
};
|
|
6349
6496
|
class PreferButton extends Rule {
|
|
6350
6497
|
constructor(options) {
|
|
6351
|
-
super(
|
|
6498
|
+
super({ ...defaults$7, ...options });
|
|
6352
6499
|
}
|
|
6353
6500
|
static schema() {
|
|
6354
6501
|
return {
|
|
@@ -6453,7 +6600,7 @@ const defaults$6 = {
|
|
|
6453
6600
|
};
|
|
6454
6601
|
class PreferNativeElement extends Rule {
|
|
6455
6602
|
constructor(options) {
|
|
6456
|
-
super(
|
|
6603
|
+
super({ ...defaults$6, ...options });
|
|
6457
6604
|
}
|
|
6458
6605
|
static schema() {
|
|
6459
6606
|
return {
|
|
@@ -6583,7 +6730,7 @@ const supportSri = {
|
|
|
6583
6730
|
};
|
|
6584
6731
|
class RequireSri extends Rule {
|
|
6585
6732
|
constructor(options) {
|
|
6586
|
-
super(
|
|
6733
|
+
super({ ...defaults$5, ...options });
|
|
6587
6734
|
this.target = this.options.target;
|
|
6588
6735
|
}
|
|
6589
6736
|
static schema() {
|
|
@@ -8678,7 +8825,7 @@ const defaults$4 = {
|
|
|
8678
8825
|
};
|
|
8679
8826
|
class Void extends Rule {
|
|
8680
8827
|
constructor(options) {
|
|
8681
|
-
super(
|
|
8828
|
+
super({ ...defaults$4, ...options });
|
|
8682
8829
|
this.style = parseStyle$1(this.options.style);
|
|
8683
8830
|
}
|
|
8684
8831
|
get deprecated() {
|
|
@@ -8787,7 +8934,7 @@ const defaults$3 = {
|
|
|
8787
8934
|
};
|
|
8788
8935
|
class VoidStyle extends Rule {
|
|
8789
8936
|
constructor(options) {
|
|
8790
|
-
super(
|
|
8937
|
+
super({ ...defaults$3, ...options });
|
|
8791
8938
|
this.style = parseStyle(this.options.style);
|
|
8792
8939
|
}
|
|
8793
8940
|
static schema() {
|
|
@@ -8990,7 +9137,7 @@ const defaults$2 = {
|
|
|
8990
9137
|
};
|
|
8991
9138
|
class H37 extends Rule {
|
|
8992
9139
|
constructor(options) {
|
|
8993
|
-
super(
|
|
9140
|
+
super({ ...defaults$2, ...options });
|
|
8994
9141
|
/* ensure alias is array */
|
|
8995
9142
|
if (!Array.isArray(this.options.alias)) {
|
|
8996
9143
|
this.options.alias = [this.options.alias];
|
|
@@ -9117,7 +9264,73 @@ const bundledRules$1 = {
|
|
|
9117
9264
|
"wcag/h71": H71,
|
|
9118
9265
|
};
|
|
9119
9266
|
|
|
9120
|
-
const bundledRules =
|
|
9267
|
+
const bundledRules = {
|
|
9268
|
+
"allowed-links": AllowedLinks,
|
|
9269
|
+
"aria-label-misuse": AriaLabelMisuse,
|
|
9270
|
+
"attr-case": AttrCase,
|
|
9271
|
+
"attr-delimiter": AttrDelimiter,
|
|
9272
|
+
"attr-pattern": AttrPattern,
|
|
9273
|
+
"attr-quotes": AttrQuotes,
|
|
9274
|
+
"attr-spacing": AttrSpacing,
|
|
9275
|
+
"attribute-allowed-values": AttributeAllowedValues,
|
|
9276
|
+
"attribute-boolean-style": AttributeBooleanStyle,
|
|
9277
|
+
"attribute-empty-style": AttributeEmptyStyle,
|
|
9278
|
+
"class-pattern": ClassPattern,
|
|
9279
|
+
"close-attr": CloseAttr,
|
|
9280
|
+
"close-order": CloseOrder,
|
|
9281
|
+
deprecated: Deprecated,
|
|
9282
|
+
"deprecated-rule": DeprecatedRule,
|
|
9283
|
+
"doctype-html": NoStyleTag$1,
|
|
9284
|
+
"doctype-style": DoctypeStyle,
|
|
9285
|
+
"element-case": ElementCase,
|
|
9286
|
+
"element-name": ElementName,
|
|
9287
|
+
"element-permitted-content": ElementPermittedContent,
|
|
9288
|
+
"element-permitted-occurrences": ElementPermittedOccurrences,
|
|
9289
|
+
"element-permitted-order": ElementPermittedOrder,
|
|
9290
|
+
"element-required-attributes": ElementRequiredAttributes,
|
|
9291
|
+
"element-required-content": ElementRequiredContent,
|
|
9292
|
+
"empty-heading": EmptyHeading,
|
|
9293
|
+
"empty-title": EmptyTitle,
|
|
9294
|
+
"heading-level": HeadingLevel,
|
|
9295
|
+
"id-pattern": IdPattern,
|
|
9296
|
+
"input-attributes": InputAttributes,
|
|
9297
|
+
"input-missing-label": InputMissingLabel,
|
|
9298
|
+
"long-title": LongTitle,
|
|
9299
|
+
"meta-refresh": MetaRefresh,
|
|
9300
|
+
"missing-doctype": MissingDoctype,
|
|
9301
|
+
"multiple-labeled-controls": MultipleLabeledControls,
|
|
9302
|
+
"no-autoplay": NoAutoplay,
|
|
9303
|
+
"no-conditional-comment": NoConditionalComment,
|
|
9304
|
+
"no-deprecated-attr": NoDeprecatedAttr,
|
|
9305
|
+
"no-dup-attr": NoDupAttr,
|
|
9306
|
+
"no-dup-class": NoDupClass,
|
|
9307
|
+
"no-dup-id": NoDupID,
|
|
9308
|
+
"no-implicit-close": NoImplicitClose,
|
|
9309
|
+
"no-inline-style": NoInlineStyle,
|
|
9310
|
+
"no-missing-references": NoMissingReferences,
|
|
9311
|
+
"no-multiple-main": NoMultipleMain,
|
|
9312
|
+
"no-raw-characters": NoRawCharacters,
|
|
9313
|
+
"no-redundant-for": NoRedundantFor,
|
|
9314
|
+
"no-redundant-role": NoRedundantRole,
|
|
9315
|
+
"no-self-closing": NoSelfClosing,
|
|
9316
|
+
"no-style-tag": NoStyleTag,
|
|
9317
|
+
"no-trailing-whitespace": NoTrailingWhitespace,
|
|
9318
|
+
"no-unknown-elements": NoUnknownElements,
|
|
9319
|
+
"no-utf8-bom": NoUtf8Bom,
|
|
9320
|
+
"prefer-button": PreferButton,
|
|
9321
|
+
"prefer-native-element": PreferNativeElement,
|
|
9322
|
+
"prefer-tbody": PreferTbody,
|
|
9323
|
+
"require-sri": RequireSri,
|
|
9324
|
+
"script-element": ScriptElement,
|
|
9325
|
+
"script-type": ScriptType,
|
|
9326
|
+
"svg-focusable": SvgFocusable,
|
|
9327
|
+
"text-content": TextContent,
|
|
9328
|
+
"unrecognized-char-ref": UnknownCharReference,
|
|
9329
|
+
void: Void,
|
|
9330
|
+
"void-content": VoidContent,
|
|
9331
|
+
"void-style": VoidStyle,
|
|
9332
|
+
...bundledRules$1,
|
|
9333
|
+
};
|
|
9121
9334
|
|
|
9122
9335
|
var defaultConfig = {};
|
|
9123
9336
|
|
|
@@ -9323,7 +9536,7 @@ class ResolvedConfig {
|
|
|
9323
9536
|
* @returns A list of transformed sources ready for validation.
|
|
9324
9537
|
*/
|
|
9325
9538
|
transformFilename(filename) {
|
|
9326
|
-
const data = fs__default[
|
|
9539
|
+
const data = fs__default["default"].readFileSync(filename, { encoding: "utf8" });
|
|
9327
9540
|
const source = {
|
|
9328
9541
|
data,
|
|
9329
9542
|
filename,
|
|
@@ -9348,19 +9561,19 @@ class ResolvedConfig {
|
|
|
9348
9561
|
}
|
|
9349
9562
|
|
|
9350
9563
|
let rootDirCache = null;
|
|
9351
|
-
const ajv = new Ajv__default[
|
|
9564
|
+
const ajv = new Ajv__default["default"]({ strict: true, strictTuples: true, strictTypes: true });
|
|
9352
9565
|
ajv.addMetaSchema(ajvSchemaDraft);
|
|
9353
9566
|
const validator = ajv.compile(configurationSchema);
|
|
9354
9567
|
function overwriteMerge(a, b) {
|
|
9355
9568
|
return b;
|
|
9356
9569
|
}
|
|
9357
9570
|
function mergeInternal(base, rhs) {
|
|
9358
|
-
const dst = deepmerge__default[
|
|
9571
|
+
const dst = deepmerge__default["default"](base, { ...rhs, rules: {} });
|
|
9359
9572
|
/* rules need some special care, should overwrite arrays instead of
|
|
9360
9573
|
* concaternation, i.e. ["error", {...options}] should not be merged by
|
|
9361
9574
|
* appending to old value */
|
|
9362
9575
|
if (rhs.rules) {
|
|
9363
|
-
dst.rules = deepmerge__default[
|
|
9576
|
+
dst.rules = deepmerge__default["default"](dst.rules, rhs.rules, { arrayMerge: overwriteMerge });
|
|
9364
9577
|
}
|
|
9365
9578
|
/* root property is merged with boolean "or" since it should always be truthy
|
|
9366
9579
|
* if any config has it set. */
|
|
@@ -9384,7 +9597,7 @@ function loadFromFile(filename) {
|
|
|
9384
9597
|
if (!json[key])
|
|
9385
9598
|
continue;
|
|
9386
9599
|
json[key] = json[key].map((ref) => {
|
|
9387
|
-
return Config.expandRelative(ref, path__default[
|
|
9600
|
+
return Config.expandRelative(ref, path__default["default"].dirname(filename));
|
|
9388
9601
|
});
|
|
9389
9602
|
}
|
|
9390
9603
|
return json;
|
|
@@ -9543,14 +9756,14 @@ class Config {
|
|
|
9543
9756
|
}
|
|
9544
9757
|
let filename;
|
|
9545
9758
|
/* try searching builtin metadata */
|
|
9546
|
-
filename = path__default[
|
|
9547
|
-
if (fs__default[
|
|
9759
|
+
filename = path__default["default"].join(projectRoot, "elements", `${entry}.json`);
|
|
9760
|
+
if (fs__default["default"].existsSync(filename)) {
|
|
9548
9761
|
metaTable.loadFromFile(filename);
|
|
9549
9762
|
continue;
|
|
9550
9763
|
}
|
|
9551
9764
|
/* try as regular file */
|
|
9552
9765
|
filename = entry.replace("<rootDir>", this.rootDir);
|
|
9553
|
-
if (fs__default[
|
|
9766
|
+
if (fs__default["default"].existsSync(filename)) {
|
|
9554
9767
|
metaTable.loadFromFile(filename);
|
|
9555
9768
|
continue;
|
|
9556
9769
|
}
|
|
@@ -9570,7 +9783,7 @@ class Config {
|
|
|
9570
9783
|
*/
|
|
9571
9784
|
static expandRelative(src, currentPath) {
|
|
9572
9785
|
if (src[0] === ".") {
|
|
9573
|
-
return path__default[
|
|
9786
|
+
return path__default["default"].normalize(`${currentPath}/${src}`);
|
|
9574
9787
|
}
|
|
9575
9788
|
return src;
|
|
9576
9789
|
}
|
|
@@ -9580,7 +9793,7 @@ class Config {
|
|
|
9580
9793
|
* @internal primary purpose is unittests
|
|
9581
9794
|
*/
|
|
9582
9795
|
get() {
|
|
9583
|
-
const config =
|
|
9796
|
+
const config = { ...this.config };
|
|
9584
9797
|
if (config.elements) {
|
|
9585
9798
|
config.elements = config.elements.map((cur) => {
|
|
9586
9799
|
if (typeof cur === "string") {
|
|
@@ -9666,7 +9879,11 @@ class Config {
|
|
|
9666
9879
|
if (!properties) {
|
|
9667
9880
|
continue;
|
|
9668
9881
|
}
|
|
9669
|
-
for (const [
|
|
9882
|
+
for (const [raw, schema] of Object.entries(properties)) {
|
|
9883
|
+
/* at compile time this is a fixed list but the point of this method is
|
|
9884
|
+
* to augment the runtime with additional keys so it is a bit of lying
|
|
9885
|
+
* to typescript */
|
|
9886
|
+
const key = raw;
|
|
9670
9887
|
if (schema.copyable && !MetaCopyableProperty.includes(key)) {
|
|
9671
9888
|
MetaCopyableProperty.push(key);
|
|
9672
9889
|
}
|
|
@@ -9820,13 +10037,13 @@ class Config {
|
|
|
9820
10037
|
let current = process.cwd();
|
|
9821
10038
|
// eslint-disable-next-line no-constant-condition
|
|
9822
10039
|
while (true) {
|
|
9823
|
-
const search = path__default[
|
|
9824
|
-
if (fs__default[
|
|
10040
|
+
const search = path__default["default"].join(current, "package.json");
|
|
10041
|
+
if (fs__default["default"].existsSync(search)) {
|
|
9825
10042
|
return (this.rootDirCache = current);
|
|
9826
10043
|
}
|
|
9827
10044
|
/* get the parent directory */
|
|
9828
10045
|
const child = current;
|
|
9829
|
-
current = path__default[
|
|
10046
|
+
current = path__default["default"].dirname(current);
|
|
9830
10047
|
/* stop if this is the root directory */
|
|
9831
10048
|
if (current === child) {
|
|
9832
10049
|
break;
|
|
@@ -9862,31 +10079,6 @@ class ConfigLoader {
|
|
|
9862
10079
|
}
|
|
9863
10080
|
}
|
|
9864
10081
|
|
|
9865
|
-
/*! *****************************************************************************
|
|
9866
|
-
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
9867
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
9868
|
-
this file except in compliance with the License. You may obtain a copy of the
|
|
9869
|
-
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9870
|
-
|
|
9871
|
-
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
9872
|
-
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
9873
|
-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
9874
|
-
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
9875
|
-
|
|
9876
|
-
See the Apache Version 2.0 License for specific language governing permissions
|
|
9877
|
-
and limitations under the License.
|
|
9878
|
-
***************************************************************************** */
|
|
9879
|
-
|
|
9880
|
-
function __rest(s, e) {
|
|
9881
|
-
var t = {};
|
|
9882
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
9883
|
-
t[p] = s[p];
|
|
9884
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
9885
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
|
|
9886
|
-
t[p[i]] = s[p[i]];
|
|
9887
|
-
return t;
|
|
9888
|
-
}
|
|
9889
|
-
|
|
9890
10082
|
class EventHandler {
|
|
9891
10083
|
constructor() {
|
|
9892
10084
|
this.listeners = {};
|
|
@@ -10460,7 +10652,7 @@ class Reporter {
|
|
|
10460
10652
|
merged[key].messages = [...merged[key].messages, ...result.messages];
|
|
10461
10653
|
}
|
|
10462
10654
|
else {
|
|
10463
|
-
merged[key] =
|
|
10655
|
+
merged[key] = { ...result };
|
|
10464
10656
|
}
|
|
10465
10657
|
});
|
|
10466
10658
|
});
|
|
@@ -10562,14 +10754,16 @@ function messageSort(a, b) {
|
|
|
10562
10754
|
}
|
|
10563
10755
|
|
|
10564
10756
|
class Engine {
|
|
10565
|
-
constructor(config,
|
|
10757
|
+
constructor(config, ParserClass) {
|
|
10566
10758
|
this.report = new Reporter();
|
|
10567
|
-
this.configData = configData;
|
|
10568
10759
|
this.config = config;
|
|
10569
10760
|
this.ParserClass = ParserClass;
|
|
10570
10761
|
/* initialize plugins and rules */
|
|
10571
10762
|
const result = this.initPlugins(this.config);
|
|
10572
|
-
this.availableRules =
|
|
10763
|
+
this.availableRules = {
|
|
10764
|
+
...bundledRules,
|
|
10765
|
+
...result.availableRules,
|
|
10766
|
+
};
|
|
10573
10767
|
}
|
|
10574
10768
|
/**
|
|
10575
10769
|
* Lint sources and return report
|
|
@@ -10594,13 +10788,13 @@ class Engine {
|
|
|
10594
10788
|
/* trigger configuration ready event */
|
|
10595
10789
|
const configEvent = {
|
|
10596
10790
|
location,
|
|
10597
|
-
config: this.
|
|
10791
|
+
config: this.config,
|
|
10598
10792
|
rules,
|
|
10599
10793
|
};
|
|
10600
10794
|
parser.trigger("config:ready", configEvent);
|
|
10601
10795
|
/* trigger source ready event */
|
|
10602
10796
|
/* eslint-disable-next-line @typescript-eslint/no-unused-vars -- object destructured on purpose to remove property */
|
|
10603
|
-
const sourceData =
|
|
10797
|
+
const { hooks: _, ...sourceData } = source;
|
|
10604
10798
|
const sourceEvent = {
|
|
10605
10799
|
location,
|
|
10606
10800
|
source: sourceData,
|
|
@@ -10907,133 +11101,31 @@ class Engine {
|
|
|
10907
11101
|
}
|
|
10908
11102
|
|
|
10909
11103
|
/**
|
|
10910
|
-
*
|
|
10911
|
-
|
|
10912
|
-
function findConfigurationFiles(directory) {
|
|
10913
|
-
return ["json", "cjs", "js"]
|
|
10914
|
-
.map((extension) => path__default['default'].join(directory, `.htmlvalidate.${extension}`))
|
|
10915
|
-
.filter((filePath) => fs__default['default'].existsSync(filePath));
|
|
10916
|
-
}
|
|
10917
|
-
/**
|
|
10918
|
-
* Loads configuration by traversing filesystem.
|
|
10919
|
-
*
|
|
10920
|
-
* Configuration is read from three sources and in the following order:
|
|
10921
|
-
*
|
|
10922
|
-
* 1. Global configuration passed to constructor.
|
|
10923
|
-
* 2. Configuration files found when traversing the directory structure.
|
|
10924
|
-
* 3. Override passed to this function.
|
|
10925
|
-
*
|
|
10926
|
-
* The following configuration filenames are searched:
|
|
10927
|
-
*
|
|
10928
|
-
* - `.htmlvalidate.json`
|
|
10929
|
-
* - `.htmlvalidate.js`
|
|
10930
|
-
* - `.htmlvalidate.cjs`
|
|
10931
|
-
*
|
|
10932
|
-
* Global configuration is used when no configuration file is found. The
|
|
10933
|
-
* result is always merged with override if present.
|
|
10934
|
-
*
|
|
10935
|
-
* The `root` property set to `true` affects the configuration as following:
|
|
11104
|
+
* The static configuration loader does not do any per-handle lookup. Only the
|
|
11105
|
+
* global or per-call configuration is used.
|
|
10936
11106
|
*
|
|
10937
|
-
*
|
|
10938
|
-
*
|
|
10939
|
-
* returned. No configuration files are searched.
|
|
10940
|
-
* 3. Setting `root` in configuration file only stops directory traversal.
|
|
11107
|
+
* In practice this means no configuration is fetch by traversing the
|
|
11108
|
+
* filesystem.
|
|
10941
11109
|
*/
|
|
10942
|
-
class
|
|
10943
|
-
|
|
10944
|
-
* @param config - Global configuration
|
|
10945
|
-
* @param configFactory - Optional configuration factory
|
|
10946
|
-
*/
|
|
10947
|
-
constructor(config, configFactory = Config) {
|
|
10948
|
-
super(config, configFactory);
|
|
10949
|
-
this.cache = new Map();
|
|
10950
|
-
}
|
|
10951
|
-
/**
|
|
10952
|
-
* Get configuration for given filename.
|
|
10953
|
-
*
|
|
10954
|
-
* @param filename - Filename to get configuration for.
|
|
10955
|
-
* @param configOverride - Configuration to merge final result with.
|
|
10956
|
-
*/
|
|
10957
|
-
getConfigFor(filename, configOverride) {
|
|
10958
|
-
/* special case when the overridden configuration is marked as root, should
|
|
10959
|
-
* not try to load any more configuration files */
|
|
11110
|
+
class StaticConfigLoader extends ConfigLoader {
|
|
11111
|
+
getConfigFor(handle, configOverride) {
|
|
10960
11112
|
const override = this.loadFromObject(configOverride || {});
|
|
10961
11113
|
if (override.isRootFound()) {
|
|
10962
11114
|
override.init();
|
|
10963
11115
|
return override;
|
|
10964
11116
|
}
|
|
10965
|
-
|
|
10966
|
-
* try to load and more configuration files */
|
|
10967
|
-
if (this.globalConfig.isRootFound()) {
|
|
10968
|
-
const merged = this.globalConfig.merge(override);
|
|
10969
|
-
merged.init();
|
|
10970
|
-
return merged;
|
|
10971
|
-
}
|
|
10972
|
-
const config = this.fromFilename(filename);
|
|
10973
|
-
const merged = config ? config.merge(override) : this.globalConfig.merge(override);
|
|
11117
|
+
const merged = this.globalConfig.merge(override);
|
|
10974
11118
|
merged.init();
|
|
10975
11119
|
return merged;
|
|
10976
11120
|
}
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
*
|
|
10980
|
-
* @param filename - If given only the cache for that file is flushed.
|
|
10981
|
-
*/
|
|
10982
|
-
flushCache(filename) {
|
|
10983
|
-
if (filename) {
|
|
10984
|
-
this.cache.delete(filename);
|
|
10985
|
-
}
|
|
10986
|
-
else {
|
|
10987
|
-
this.cache.clear();
|
|
10988
|
-
}
|
|
10989
|
-
}
|
|
10990
|
-
/**
|
|
10991
|
-
* Load raw configuration from directory traversal.
|
|
10992
|
-
*
|
|
10993
|
-
* This configuration is not merged with global configuration and may return
|
|
10994
|
-
* `null` if no configuration files are found.
|
|
10995
|
-
*/
|
|
10996
|
-
fromFilename(filename) {
|
|
10997
|
-
var _a;
|
|
10998
|
-
if (filename === "inline") {
|
|
10999
|
-
return null;
|
|
11000
|
-
}
|
|
11001
|
-
if (this.cache.has(filename)) {
|
|
11002
|
-
return (_a = this.cache.get(filename)) !== null && _a !== void 0 ? _a : null;
|
|
11003
|
-
}
|
|
11004
|
-
let found = false;
|
|
11005
|
-
let current = path__default['default'].resolve(path__default['default'].dirname(filename));
|
|
11006
|
-
let config = this.empty();
|
|
11007
|
-
// eslint-disable-next-line no-constant-condition
|
|
11008
|
-
while (true) {
|
|
11009
|
-
/* search configuration files in current directory */
|
|
11010
|
-
for (const configFile of findConfigurationFiles(current)) {
|
|
11011
|
-
const local = this.loadFromFile(configFile);
|
|
11012
|
-
found = true;
|
|
11013
|
-
config = local.merge(config);
|
|
11014
|
-
}
|
|
11015
|
-
/* stop if a configuration with "root" is set to true */
|
|
11016
|
-
if (config.isRootFound()) {
|
|
11017
|
-
break;
|
|
11018
|
-
}
|
|
11019
|
-
/* get the parent directory */
|
|
11020
|
-
const child = current;
|
|
11021
|
-
current = path__default['default'].dirname(current);
|
|
11022
|
-
/* stop if this is the root directory */
|
|
11023
|
-
if (current === child) {
|
|
11024
|
-
break;
|
|
11025
|
-
}
|
|
11026
|
-
}
|
|
11027
|
-
/* no config was found by loader, return null and let caller decide what to do */
|
|
11028
|
-
if (!found) {
|
|
11029
|
-
this.cache.set(filename, null);
|
|
11030
|
-
return null;
|
|
11031
|
-
}
|
|
11032
|
-
this.cache.set(filename, config);
|
|
11033
|
-
return config;
|
|
11121
|
+
flushCache() {
|
|
11122
|
+
/* do nothing */
|
|
11034
11123
|
}
|
|
11035
11124
|
defaultConfig() {
|
|
11036
|
-
return this.
|
|
11125
|
+
return this.loadFromObject({
|
|
11126
|
+
extends: ["html-validate:recommended"],
|
|
11127
|
+
elements: ["html5"],
|
|
11128
|
+
});
|
|
11037
11129
|
}
|
|
11038
11130
|
}
|
|
11039
11131
|
|
|
@@ -11057,7 +11149,7 @@ function isConfigData(value) {
|
|
|
11057
11149
|
class HtmlValidate {
|
|
11058
11150
|
constructor(arg) {
|
|
11059
11151
|
const [loader, config] = arg instanceof ConfigLoader ? [arg, undefined] : [undefined, arg];
|
|
11060
|
-
this.configLoader = loader !== null && loader !== void 0 ? loader : new
|
|
11152
|
+
this.configLoader = loader !== null && loader !== void 0 ? loader : new StaticConfigLoader(config);
|
|
11061
11153
|
}
|
|
11062
11154
|
validateString(str, arg1, arg2, arg3) {
|
|
11063
11155
|
const filename = typeof arg1 === "string" ? arg1 : "inline";
|
|
@@ -11084,7 +11176,7 @@ class HtmlValidate {
|
|
|
11084
11176
|
const config = this.getConfigFor(input.filename, configOverride);
|
|
11085
11177
|
const resolved = config.resolve();
|
|
11086
11178
|
const source = resolved.transformSource(input);
|
|
11087
|
-
const engine = new Engine(resolved,
|
|
11179
|
+
const engine = new Engine(resolved, Parser);
|
|
11088
11180
|
return engine.lint(source);
|
|
11089
11181
|
}
|
|
11090
11182
|
/**
|
|
@@ -11098,7 +11190,7 @@ class HtmlValidate {
|
|
|
11098
11190
|
const config = this.getConfigFor(filename);
|
|
11099
11191
|
const resolved = config.resolve();
|
|
11100
11192
|
const source = resolved.transformFilename(filename);
|
|
11101
|
-
const engine = new Engine(resolved,
|
|
11193
|
+
const engine = new Engine(resolved, Parser);
|
|
11102
11194
|
return engine.lint(source);
|
|
11103
11195
|
}
|
|
11104
11196
|
/**
|
|
@@ -11122,7 +11214,7 @@ class HtmlValidate {
|
|
|
11122
11214
|
*/
|
|
11123
11215
|
canValidate(filename) {
|
|
11124
11216
|
/* .html is always supported */
|
|
11125
|
-
const extension = path__default[
|
|
11217
|
+
const extension = path__default["default"].extname(filename).toLowerCase();
|
|
11126
11218
|
if (extension === ".html") {
|
|
11127
11219
|
return true;
|
|
11128
11220
|
}
|
|
@@ -11143,7 +11235,7 @@ class HtmlValidate {
|
|
|
11143
11235
|
const config = this.getConfigFor(filename);
|
|
11144
11236
|
const resolved = config.resolve();
|
|
11145
11237
|
const source = resolved.transformFilename(filename);
|
|
11146
|
-
const engine = new Engine(resolved,
|
|
11238
|
+
const engine = new Engine(resolved, Parser);
|
|
11147
11239
|
return engine.dumpTokens(source);
|
|
11148
11240
|
}
|
|
11149
11241
|
/**
|
|
@@ -11158,7 +11250,7 @@ class HtmlValidate {
|
|
|
11158
11250
|
const config = this.getConfigFor(filename);
|
|
11159
11251
|
const resolved = config.resolve();
|
|
11160
11252
|
const source = resolved.transformFilename(filename);
|
|
11161
|
-
const engine = new Engine(resolved,
|
|
11253
|
+
const engine = new Engine(resolved, Parser);
|
|
11162
11254
|
return engine.dumpEvents(source);
|
|
11163
11255
|
}
|
|
11164
11256
|
/**
|
|
@@ -11173,7 +11265,7 @@ class HtmlValidate {
|
|
|
11173
11265
|
const config = this.getConfigFor(filename);
|
|
11174
11266
|
const resolved = config.resolve();
|
|
11175
11267
|
const source = resolved.transformFilename(filename);
|
|
11176
|
-
const engine = new Engine(resolved,
|
|
11268
|
+
const engine = new Engine(resolved, Parser);
|
|
11177
11269
|
return engine.dumpTree(source);
|
|
11178
11270
|
}
|
|
11179
11271
|
/**
|
|
@@ -11251,7 +11343,7 @@ class HtmlValidate {
|
|
|
11251
11343
|
*/
|
|
11252
11344
|
getRuleDocumentation(ruleId, config = null, context = null) {
|
|
11253
11345
|
const c = config || this.getConfigFor("inline");
|
|
11254
|
-
const engine = new Engine(c.resolve(),
|
|
11346
|
+
const engine = new Engine(c.resolve(), Parser);
|
|
11255
11347
|
return engine.getRuleDocumentation(ruleId, context);
|
|
11256
11348
|
}
|
|
11257
11349
|
/**
|
|
@@ -11288,41 +11380,12 @@ class HtmlValidate {
|
|
|
11288
11380
|
}
|
|
11289
11381
|
}
|
|
11290
11382
|
|
|
11291
|
-
/**
|
|
11292
|
-
* The static configuration loader does not do any per-handle lookup. Only the
|
|
11293
|
-
* global or per-call configuration is used.
|
|
11294
|
-
*
|
|
11295
|
-
* In practice this means no configuration is fetch by traversing the
|
|
11296
|
-
* filesystem.
|
|
11297
|
-
*/
|
|
11298
|
-
class StaticConfigLoader extends ConfigLoader {
|
|
11299
|
-
getConfigFor(handle, configOverride) {
|
|
11300
|
-
const override = this.loadFromObject(configOverride || {});
|
|
11301
|
-
if (override.isRootFound()) {
|
|
11302
|
-
override.init();
|
|
11303
|
-
return override;
|
|
11304
|
-
}
|
|
11305
|
-
const merged = this.globalConfig.merge(override);
|
|
11306
|
-
merged.init();
|
|
11307
|
-
return merged;
|
|
11308
|
-
}
|
|
11309
|
-
flushCache() {
|
|
11310
|
-
/* do nothing */
|
|
11311
|
-
}
|
|
11312
|
-
defaultConfig() {
|
|
11313
|
-
return this.loadFromObject({
|
|
11314
|
-
extends: ["html-validate:recommended"],
|
|
11315
|
-
elements: ["html5"],
|
|
11316
|
-
});
|
|
11317
|
-
}
|
|
11318
|
-
}
|
|
11319
|
-
|
|
11320
11383
|
const defaults$1 = {
|
|
11321
11384
|
silent: false,
|
|
11322
11385
|
version,
|
|
11323
11386
|
logger(text) {
|
|
11324
11387
|
/* eslint-disable-next-line no-console */
|
|
11325
|
-
console.error(kleur__default[
|
|
11388
|
+
console.error(kleur__default["default"].red(text));
|
|
11326
11389
|
},
|
|
11327
11390
|
};
|
|
11328
11391
|
/**
|
|
@@ -11334,8 +11397,8 @@ const defaults$1 = {
|
|
|
11334
11397
|
* @returns - `true` if version is compatible
|
|
11335
11398
|
*/
|
|
11336
11399
|
function compatibilityCheck(name, declared, options) {
|
|
11337
|
-
const { silent, version: current, logger } =
|
|
11338
|
-
const valid = semver__default[
|
|
11400
|
+
const { silent, version: current, logger } = { ...defaults$1, ...options };
|
|
11401
|
+
const valid = semver__default["default"].satisfies(current, declared);
|
|
11339
11402
|
if (valid || silent) {
|
|
11340
11403
|
return valid;
|
|
11341
11404
|
}
|
|
@@ -11364,6 +11427,137 @@ function ruleExists(ruleId) {
|
|
|
11364
11427
|
return ruleIds.has(ruleId);
|
|
11365
11428
|
}
|
|
11366
11429
|
|
|
11430
|
+
/**
|
|
11431
|
+
* @internal
|
|
11432
|
+
*/
|
|
11433
|
+
function findConfigurationFiles(directory) {
|
|
11434
|
+
return ["json", "cjs", "js"]
|
|
11435
|
+
.map((extension) => path__default["default"].join(directory, `.htmlvalidate.${extension}`))
|
|
11436
|
+
.filter((filePath) => fs__default["default"].existsSync(filePath));
|
|
11437
|
+
}
|
|
11438
|
+
/**
|
|
11439
|
+
* Loads configuration by traversing filesystem.
|
|
11440
|
+
*
|
|
11441
|
+
* Configuration is read from three sources and in the following order:
|
|
11442
|
+
*
|
|
11443
|
+
* 1. Global configuration passed to constructor.
|
|
11444
|
+
* 2. Configuration files found when traversing the directory structure.
|
|
11445
|
+
* 3. Override passed to this function.
|
|
11446
|
+
*
|
|
11447
|
+
* The following configuration filenames are searched:
|
|
11448
|
+
*
|
|
11449
|
+
* - `.htmlvalidate.json`
|
|
11450
|
+
* - `.htmlvalidate.js`
|
|
11451
|
+
* - `.htmlvalidate.cjs`
|
|
11452
|
+
*
|
|
11453
|
+
* Global configuration is used when no configuration file is found. The
|
|
11454
|
+
* result is always merged with override if present.
|
|
11455
|
+
*
|
|
11456
|
+
* The `root` property set to `true` affects the configuration as following:
|
|
11457
|
+
*
|
|
11458
|
+
* 1. If set in override the override is returned as-is.
|
|
11459
|
+
* 2. If set in the global config the override is merged into global and
|
|
11460
|
+
* returned. No configuration files are searched.
|
|
11461
|
+
* 3. Setting `root` in configuration file only stops directory traversal.
|
|
11462
|
+
*/
|
|
11463
|
+
class FileSystemConfigLoader extends ConfigLoader {
|
|
11464
|
+
/**
|
|
11465
|
+
* @param config - Global configuration
|
|
11466
|
+
* @param configFactory - Optional configuration factory
|
|
11467
|
+
*/
|
|
11468
|
+
constructor(config, configFactory = Config) {
|
|
11469
|
+
super(config, configFactory);
|
|
11470
|
+
this.cache = new Map();
|
|
11471
|
+
}
|
|
11472
|
+
/**
|
|
11473
|
+
* Get configuration for given filename.
|
|
11474
|
+
*
|
|
11475
|
+
* @param filename - Filename to get configuration for.
|
|
11476
|
+
* @param configOverride - Configuration to merge final result with.
|
|
11477
|
+
*/
|
|
11478
|
+
getConfigFor(filename, configOverride) {
|
|
11479
|
+
/* special case when the overridden configuration is marked as root, should
|
|
11480
|
+
* not try to load any more configuration files */
|
|
11481
|
+
const override = this.loadFromObject(configOverride || {});
|
|
11482
|
+
if (override.isRootFound()) {
|
|
11483
|
+
override.init();
|
|
11484
|
+
return override;
|
|
11485
|
+
}
|
|
11486
|
+
/* special case when the global configuration is marked as root, should not
|
|
11487
|
+
* try to load and more configuration files */
|
|
11488
|
+
if (this.globalConfig.isRootFound()) {
|
|
11489
|
+
const merged = this.globalConfig.merge(override);
|
|
11490
|
+
merged.init();
|
|
11491
|
+
return merged;
|
|
11492
|
+
}
|
|
11493
|
+
const config = this.fromFilename(filename);
|
|
11494
|
+
const merged = config ? config.merge(override) : this.globalConfig.merge(override);
|
|
11495
|
+
merged.init();
|
|
11496
|
+
return merged;
|
|
11497
|
+
}
|
|
11498
|
+
/**
|
|
11499
|
+
* Flush configuration cache.
|
|
11500
|
+
*
|
|
11501
|
+
* @param filename - If given only the cache for that file is flushed.
|
|
11502
|
+
*/
|
|
11503
|
+
flushCache(filename) {
|
|
11504
|
+
if (filename) {
|
|
11505
|
+
this.cache.delete(filename);
|
|
11506
|
+
}
|
|
11507
|
+
else {
|
|
11508
|
+
this.cache.clear();
|
|
11509
|
+
}
|
|
11510
|
+
}
|
|
11511
|
+
/**
|
|
11512
|
+
* Load raw configuration from directory traversal.
|
|
11513
|
+
*
|
|
11514
|
+
* This configuration is not merged with global configuration and may return
|
|
11515
|
+
* `null` if no configuration files are found.
|
|
11516
|
+
*/
|
|
11517
|
+
fromFilename(filename) {
|
|
11518
|
+
var _a;
|
|
11519
|
+
if (filename === "inline") {
|
|
11520
|
+
return null;
|
|
11521
|
+
}
|
|
11522
|
+
if (this.cache.has(filename)) {
|
|
11523
|
+
return (_a = this.cache.get(filename)) !== null && _a !== void 0 ? _a : null;
|
|
11524
|
+
}
|
|
11525
|
+
let found = false;
|
|
11526
|
+
let current = path__default["default"].resolve(path__default["default"].dirname(filename));
|
|
11527
|
+
let config = this.empty();
|
|
11528
|
+
// eslint-disable-next-line no-constant-condition
|
|
11529
|
+
while (true) {
|
|
11530
|
+
/* search configuration files in current directory */
|
|
11531
|
+
for (const configFile of findConfigurationFiles(current)) {
|
|
11532
|
+
const local = this.loadFromFile(configFile);
|
|
11533
|
+
found = true;
|
|
11534
|
+
config = local.merge(config);
|
|
11535
|
+
}
|
|
11536
|
+
/* stop if a configuration with "root" is set to true */
|
|
11537
|
+
if (config.isRootFound()) {
|
|
11538
|
+
break;
|
|
11539
|
+
}
|
|
11540
|
+
/* get the parent directory */
|
|
11541
|
+
const child = current;
|
|
11542
|
+
current = path__default["default"].dirname(current);
|
|
11543
|
+
/* stop if this is the root directory */
|
|
11544
|
+
if (current === child) {
|
|
11545
|
+
break;
|
|
11546
|
+
}
|
|
11547
|
+
}
|
|
11548
|
+
/* no config was found by loader, return null and let caller decide what to do */
|
|
11549
|
+
if (!found) {
|
|
11550
|
+
this.cache.set(filename, null);
|
|
11551
|
+
return null;
|
|
11552
|
+
}
|
|
11553
|
+
this.cache.set(filename, config);
|
|
11554
|
+
return config;
|
|
11555
|
+
}
|
|
11556
|
+
defaultConfig() {
|
|
11557
|
+
return this.configFactory.defaultConfig();
|
|
11558
|
+
}
|
|
11559
|
+
}
|
|
11560
|
+
|
|
11367
11561
|
const entities = {
|
|
11368
11562
|
">": ">",
|
|
11369
11563
|
"<": "<",
|
|
@@ -11435,12 +11629,12 @@ function pluralize(word, count) {
|
|
|
11435
11629
|
* @returns The formatted file path.
|
|
11436
11630
|
*/
|
|
11437
11631
|
function formatFilePath(filePath, line, column) {
|
|
11438
|
-
let relPath = path__default[
|
|
11632
|
+
let relPath = path__default["default"].relative(process.cwd(), filePath);
|
|
11439
11633
|
/* istanbul ignore next: safety check from original implementation */
|
|
11440
11634
|
if (line && column) {
|
|
11441
11635
|
relPath += `:${line}:${column}`;
|
|
11442
11636
|
}
|
|
11443
|
-
return kleur__default[
|
|
11637
|
+
return kleur__default["default"].green(relPath);
|
|
11444
11638
|
}
|
|
11445
11639
|
function getStartLocation(message) {
|
|
11446
11640
|
return {
|
|
@@ -11469,9 +11663,9 @@ function getEndLocation(message, source) {
|
|
|
11469
11663
|
* @returns The formatted output.
|
|
11470
11664
|
*/
|
|
11471
11665
|
function formatMessage(message, parentResult, options) {
|
|
11472
|
-
const type = message.severity === 2 ? kleur__default[
|
|
11473
|
-
const msg = `${kleur__default[
|
|
11474
|
-
const ruleId = kleur__default[
|
|
11666
|
+
const type = message.severity === 2 ? kleur__default["default"].red("error") : kleur__default["default"].yellow("warning");
|
|
11667
|
+
const msg = `${kleur__default["default"].bold(message.message.replace(/([^ ])\.$/, "$1"))}`;
|
|
11668
|
+
const ruleId = kleur__default["default"].dim(`(${message.ruleId})`);
|
|
11475
11669
|
const filePath = formatFilePath(parentResult.filePath, message.line, message.column);
|
|
11476
11670
|
const sourceCode = parentResult.source;
|
|
11477
11671
|
/* istanbul ignore next: safety check from original implementation */
|
|
@@ -11492,7 +11686,7 @@ function formatMessage(message, parentResult, options) {
|
|
|
11492
11686
|
}, { highlightCode: false }));
|
|
11493
11687
|
}
|
|
11494
11688
|
if (options.showLink && message.ruleUrl) {
|
|
11495
|
-
result.push(`${kleur__default[
|
|
11689
|
+
result.push(`${kleur__default["default"].bold("Details:")} ${message.ruleUrl}`);
|
|
11496
11690
|
}
|
|
11497
11691
|
return result.join("\n");
|
|
11498
11692
|
}
|
|
@@ -11511,10 +11705,10 @@ function formatSummary(errors, warnings) {
|
|
|
11511
11705
|
if (warnings > 0) {
|
|
11512
11706
|
summary.push(`${warnings} ${pluralize("warning", warnings)}`);
|
|
11513
11707
|
}
|
|
11514
|
-
return kleur__default[
|
|
11708
|
+
return kleur__default["default"][summaryColor]().bold(`${summary.join(" and ")} found.`);
|
|
11515
11709
|
}
|
|
11516
11710
|
function codeframe(results, options) {
|
|
11517
|
-
const merged =
|
|
11711
|
+
const merged = { ...defaults, ...options };
|
|
11518
11712
|
let errors = 0;
|
|
11519
11713
|
let warnings = 0;
|
|
11520
11714
|
const resultsWithMessages = results.filter((result) => result.messages.length > 0);
|
|
@@ -11552,10 +11746,14 @@ function linkSummary(results) {
|
|
|
11552
11746
|
return "";
|
|
11553
11747
|
}
|
|
11554
11748
|
const lines = unique.map((url) => ` ${url}\n`);
|
|
11555
|
-
return `\n${kleur__default[
|
|
11749
|
+
return `\n${kleur__default["default"].bold("More information")}:\n${lines.join("")}\n`;
|
|
11556
11750
|
}
|
|
11557
11751
|
function stylish(results) {
|
|
11558
|
-
const errors = stylishImpl__default[
|
|
11752
|
+
const errors = stylishImpl__default["default"](results.map((it) => ({
|
|
11753
|
+
...it,
|
|
11754
|
+
fixableErrorCount: 0,
|
|
11755
|
+
fixableWarningCount: 0,
|
|
11756
|
+
})));
|
|
11559
11757
|
const links = linkSummary(results);
|
|
11560
11758
|
return `${errors}${links}`;
|
|
11561
11759
|
}
|