html-validate 5.5.0 → 6.1.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 +64 -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 +615 -360
- 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 +7 -8
- 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 +578 -323
- 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/es/jest-lib.js +3 -2
- package/dist/es/jest-lib.js.map +1 -1
- package/dist/schema/elements.json +43 -5
- package/elements/html5.json +940 -307
- package/package.json +21 -22
package/dist/es/core.js
CHANGED
|
@@ -574,18 +574,63 @@ const definitions = {
|
|
|
574
574
|
type: "object",
|
|
575
575
|
patternProperties: {
|
|
576
576
|
"^.*$": {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
{
|
|
577
|
+
anyOf: [
|
|
578
|
+
{
|
|
579
|
+
type: "object",
|
|
580
|
+
additionalProperties: false,
|
|
581
|
+
properties: {
|
|
582
|
+
boolean: {
|
|
583
|
+
type: "boolean",
|
|
584
|
+
title: "Set to true if this is a boolean attribute"
|
|
585
|
+
},
|
|
586
|
+
deprecated: {
|
|
587
|
+
title: "Set to true or string if this attribute is deprecated",
|
|
588
|
+
oneOf: [
|
|
589
|
+
{
|
|
590
|
+
type: "boolean"
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
type: "string"
|
|
594
|
+
}
|
|
595
|
+
]
|
|
596
|
+
},
|
|
597
|
+
list: {
|
|
598
|
+
type: "boolean",
|
|
599
|
+
title: "Set to true if this attribute is a list of space-separated tokens, each which must be valid by itself"
|
|
600
|
+
},
|
|
601
|
+
"enum": {
|
|
602
|
+
type: "array",
|
|
603
|
+
title: "Exhaustive list of values (string or regex) this attribute accepts",
|
|
604
|
+
uniqueItems: true,
|
|
605
|
+
items: {
|
|
606
|
+
anyOf: [
|
|
607
|
+
{
|
|
608
|
+
type: "string"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
regexp: true
|
|
612
|
+
}
|
|
613
|
+
]
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
omit: {
|
|
617
|
+
type: "boolean",
|
|
618
|
+
title: "Set to true if this attribute can optionally omit its value"
|
|
619
|
+
},
|
|
620
|
+
required: {
|
|
621
|
+
type: "boolean",
|
|
622
|
+
title: "Set to true if this attribute is required"
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
type: "array",
|
|
628
|
+
uniqueItems: true,
|
|
629
|
+
items: {
|
|
582
630
|
type: "string"
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
regexp: true
|
|
586
631
|
}
|
|
587
|
-
|
|
588
|
-
|
|
632
|
+
}
|
|
633
|
+
]
|
|
589
634
|
}
|
|
590
635
|
}
|
|
591
636
|
},
|
|
@@ -636,6 +681,111 @@ var schema = {
|
|
|
636
681
|
definitions: definitions
|
|
637
682
|
};
|
|
638
683
|
|
|
684
|
+
var TextContent$1;
|
|
685
|
+
(function (TextContent) {
|
|
686
|
+
/* forbid node to have text content, inter-element whitespace is ignored */
|
|
687
|
+
TextContent["NONE"] = "none";
|
|
688
|
+
/* node can have text but not required too */
|
|
689
|
+
TextContent["DEFAULT"] = "default";
|
|
690
|
+
/* node requires text-nodes to be present (direct or by descendant) */
|
|
691
|
+
TextContent["REQUIRED"] = "required";
|
|
692
|
+
/* node requires accessible text (hidden text is ignored, tries to get text from accessibility tree) */
|
|
693
|
+
TextContent["ACCESSIBLE"] = "accessible";
|
|
694
|
+
})(TextContent$1 || (TextContent$1 = {}));
|
|
695
|
+
/**
|
|
696
|
+
* Properties listed here can be copied (loaded) onto another element using
|
|
697
|
+
* [[HtmlElement.loadMeta]].
|
|
698
|
+
*/
|
|
699
|
+
const MetaCopyableProperty = [
|
|
700
|
+
"metadata",
|
|
701
|
+
"flow",
|
|
702
|
+
"sectioning",
|
|
703
|
+
"heading",
|
|
704
|
+
"phrasing",
|
|
705
|
+
"embedded",
|
|
706
|
+
"interactive",
|
|
707
|
+
"transparent",
|
|
708
|
+
"form",
|
|
709
|
+
"labelable",
|
|
710
|
+
"attributes",
|
|
711
|
+
"permittedContent",
|
|
712
|
+
"permittedDescendants",
|
|
713
|
+
"permittedOrder",
|
|
714
|
+
"requiredAncestors",
|
|
715
|
+
"requiredContent",
|
|
716
|
+
];
|
|
717
|
+
/**
|
|
718
|
+
* @internal
|
|
719
|
+
*/
|
|
720
|
+
function setMetaProperty(dst, key, value) {
|
|
721
|
+
dst[key] = value;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function isSet(value) {
|
|
725
|
+
return typeof value !== "undefined";
|
|
726
|
+
}
|
|
727
|
+
function flag(value) {
|
|
728
|
+
return value ? true : undefined;
|
|
729
|
+
}
|
|
730
|
+
function stripUndefined(src) {
|
|
731
|
+
const entries = Object.entries(src).filter(([, value]) => isSet(value));
|
|
732
|
+
return Object.fromEntries(entries);
|
|
733
|
+
}
|
|
734
|
+
function migrateSingleAttribute(src, key) {
|
|
735
|
+
var _a, _b;
|
|
736
|
+
const result = {};
|
|
737
|
+
result.deprecated = flag((_a = src.deprecatedAttributes) === null || _a === void 0 ? void 0 : _a.includes(key));
|
|
738
|
+
result.required = flag((_b = src.requiredAttributes) === null || _b === void 0 ? void 0 : _b.includes(key));
|
|
739
|
+
result.omit = undefined;
|
|
740
|
+
const attr = src.attributes ? src.attributes[key] : undefined;
|
|
741
|
+
if (typeof attr === "undefined") {
|
|
742
|
+
return stripUndefined(result);
|
|
743
|
+
}
|
|
744
|
+
/* when the attribute is set to null we use a special property "delete" to
|
|
745
|
+
* flag it, if it is still set during merge (inheritance, overwriting, etc) the attribute will be removed */
|
|
746
|
+
if (attr === null) {
|
|
747
|
+
result.delete = true;
|
|
748
|
+
return stripUndefined(result);
|
|
749
|
+
}
|
|
750
|
+
if (Array.isArray(attr)) {
|
|
751
|
+
if (attr.length === 0) {
|
|
752
|
+
result.boolean = true;
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
result.enum = attr.filter((it) => it !== "");
|
|
756
|
+
if (attr.includes("")) {
|
|
757
|
+
result.omit = true;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return stripUndefined(result);
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
return stripUndefined({ ...result, ...attr });
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function migrateAttributes(src) {
|
|
767
|
+
var _a, _b, _c;
|
|
768
|
+
const keys = [
|
|
769
|
+
...Object.keys((_a = src.attributes) !== null && _a !== void 0 ? _a : {}),
|
|
770
|
+
...((_b = src.requiredAttributes) !== null && _b !== void 0 ? _b : []),
|
|
771
|
+
...((_c = src.deprecatedAttributes) !== null && _c !== void 0 ? _c : []),
|
|
772
|
+
].sort();
|
|
773
|
+
const entries = keys.map((key) => {
|
|
774
|
+
return [key, migrateSingleAttribute(src, key)];
|
|
775
|
+
});
|
|
776
|
+
return Object.fromEntries(entries);
|
|
777
|
+
}
|
|
778
|
+
function migrateElement(src) {
|
|
779
|
+
const result = {
|
|
780
|
+
...src,
|
|
781
|
+
attributes: migrateAttributes(src),
|
|
782
|
+
};
|
|
783
|
+
/* removed properties */
|
|
784
|
+
delete result.deprecatedAttributes;
|
|
785
|
+
delete result.requiredAttributes;
|
|
786
|
+
return result;
|
|
787
|
+
}
|
|
788
|
+
|
|
639
789
|
const dynamicKeys = [
|
|
640
790
|
"metadata",
|
|
641
791
|
"flow",
|
|
@@ -729,7 +879,7 @@ class MetaTable {
|
|
|
729
879
|
for (const [key, value] of Object.entries(obj)) {
|
|
730
880
|
if (key === "$schema")
|
|
731
881
|
continue;
|
|
732
|
-
this.addEntry(key, value);
|
|
882
|
+
this.addEntry(key, migrateElement(value));
|
|
733
883
|
}
|
|
734
884
|
}
|
|
735
885
|
/**
|
|
@@ -757,7 +907,7 @@ class MetaTable {
|
|
|
757
907
|
*/
|
|
758
908
|
getMetaFor(tagName) {
|
|
759
909
|
tagName = tagName.toLowerCase();
|
|
760
|
-
return this.elements[tagName] ?
|
|
910
|
+
return this.elements[tagName] ? { ...this.elements[tagName] } : null;
|
|
761
911
|
}
|
|
762
912
|
/**
|
|
763
913
|
* Find all tags which has enabled given property.
|
|
@@ -786,7 +936,7 @@ class MetaTable {
|
|
|
786
936
|
}
|
|
787
937
|
}
|
|
788
938
|
/* merge all sources together */
|
|
789
|
-
const expanded =
|
|
939
|
+
const expanded = this.mergeElement(parent, { ...entry, tagName });
|
|
790
940
|
expandRegex(expanded);
|
|
791
941
|
this.elements[tagName] = expanded;
|
|
792
942
|
}
|
|
@@ -824,7 +974,16 @@ class MetaTable {
|
|
|
824
974
|
}
|
|
825
975
|
}
|
|
826
976
|
mergeElement(a, b) {
|
|
827
|
-
|
|
977
|
+
const merged = deepmerge(a, b, { arrayMerge: overwriteMerge$1 });
|
|
978
|
+
/* special handling when removing attributes by setting them to null
|
|
979
|
+
* resulting in the deletion flag being set */
|
|
980
|
+
const filteredAttrs = Object.entries(merged.attributes).filter(([, attr]) => {
|
|
981
|
+
const val = !attr.delete;
|
|
982
|
+
delete attr.delete;
|
|
983
|
+
return val;
|
|
984
|
+
});
|
|
985
|
+
merged.attributes = Object.fromEntries(filteredAttrs);
|
|
986
|
+
return merged;
|
|
828
987
|
}
|
|
829
988
|
resolve(node) {
|
|
830
989
|
if (node.meta) {
|
|
@@ -836,7 +995,7 @@ function expandProperties(node, entry) {
|
|
|
836
995
|
for (const key of dynamicKeys) {
|
|
837
996
|
const property = entry[key];
|
|
838
997
|
if (property && typeof property !== "boolean") {
|
|
839
|
-
entry
|
|
998
|
+
setMetaProperty(entry, key, evaluateProperty(node, property));
|
|
840
999
|
}
|
|
841
1000
|
}
|
|
842
1001
|
}
|
|
@@ -862,14 +1021,9 @@ function expandRegexValue(value) {
|
|
|
862
1021
|
* Expand all regular expressions in strings ("/../"). This mutates the object.
|
|
863
1022
|
*/
|
|
864
1023
|
function expandRegex(entry) {
|
|
865
|
-
if (!entry.attributes)
|
|
866
|
-
return;
|
|
867
1024
|
for (const [name, values] of Object.entries(entry.attributes)) {
|
|
868
|
-
if (values) {
|
|
869
|
-
entry.attributes[name] = values.map(expandRegexValue);
|
|
870
|
-
}
|
|
871
|
-
else {
|
|
872
|
-
delete entry.attributes[name];
|
|
1025
|
+
if (values.enum) {
|
|
1026
|
+
entry.attributes[name].enum = values.enum.map(expandRegexValue);
|
|
873
1027
|
}
|
|
874
1028
|
}
|
|
875
1029
|
}
|
|
@@ -925,41 +1079,6 @@ function matchAttribute(node, match) {
|
|
|
925
1079
|
}
|
|
926
1080
|
}
|
|
927
1081
|
|
|
928
|
-
var TextContent$1;
|
|
929
|
-
(function (TextContent) {
|
|
930
|
-
/* forbid node to have text content, inter-element whitespace is ignored */
|
|
931
|
-
TextContent["NONE"] = "none";
|
|
932
|
-
/* node can have text but not required too */
|
|
933
|
-
TextContent["DEFAULT"] = "default";
|
|
934
|
-
/* node requires text-nodes to be present (direct or by descendant) */
|
|
935
|
-
TextContent["REQUIRED"] = "required";
|
|
936
|
-
/* node requires accessible text (hidden text is ignored, tries to get text from accessibility tree) */
|
|
937
|
-
TextContent["ACCESSIBLE"] = "accessible";
|
|
938
|
-
})(TextContent$1 || (TextContent$1 = {}));
|
|
939
|
-
/**
|
|
940
|
-
* Properties listed here can be copied (loaded) onto another element using
|
|
941
|
-
* [[HtmlElement.loadMeta]].
|
|
942
|
-
*/
|
|
943
|
-
const MetaCopyableProperty = [
|
|
944
|
-
"metadata",
|
|
945
|
-
"flow",
|
|
946
|
-
"sectioning",
|
|
947
|
-
"heading",
|
|
948
|
-
"phrasing",
|
|
949
|
-
"embedded",
|
|
950
|
-
"interactive",
|
|
951
|
-
"transparent",
|
|
952
|
-
"form",
|
|
953
|
-
"labelable",
|
|
954
|
-
"requiredAttributes",
|
|
955
|
-
"attributes",
|
|
956
|
-
"permittedContent",
|
|
957
|
-
"permittedDescendants",
|
|
958
|
-
"permittedOrder",
|
|
959
|
-
"requiredAncestors",
|
|
960
|
-
"requiredContent",
|
|
961
|
-
];
|
|
962
|
-
|
|
963
1082
|
class DynamicValue {
|
|
964
1083
|
constructor(expr) {
|
|
965
1084
|
this.expr = expr;
|
|
@@ -1811,8 +1930,9 @@ class HtmlElement extends DOMNode {
|
|
|
1811
1930
|
this.metaElement = {};
|
|
1812
1931
|
}
|
|
1813
1932
|
for (const key of MetaCopyableProperty) {
|
|
1814
|
-
|
|
1815
|
-
|
|
1933
|
+
const value = meta[key];
|
|
1934
|
+
if (typeof value !== "undefined") {
|
|
1935
|
+
setMetaProperty(this.metaElement, key, value);
|
|
1816
1936
|
}
|
|
1817
1937
|
else {
|
|
1818
1938
|
delete this.metaElement[key];
|
|
@@ -2228,6 +2348,7 @@ class Validator {
|
|
|
2228
2348
|
* @param rules - Element attribute metadta.
|
|
2229
2349
|
* @returns `true` if attribute passes all tests.
|
|
2230
2350
|
*/
|
|
2351
|
+
/* eslint-disable-next-line complexity */
|
|
2231
2352
|
static validateAttribute(attr, rules) {
|
|
2232
2353
|
const rule = rules[attr.key];
|
|
2233
2354
|
if (!rule) {
|
|
@@ -2241,19 +2362,34 @@ class Validator {
|
|
|
2241
2362
|
return true;
|
|
2242
2363
|
}
|
|
2243
2364
|
const empty = value === null || value === "";
|
|
2244
|
-
/*
|
|
2245
|
-
|
|
2365
|
+
/* if boolean is set the value can be either null, empty string or the
|
|
2366
|
+
* attribute key (attribute-boolean-style regulates style) */
|
|
2367
|
+
if (rule.boolean) {
|
|
2246
2368
|
return empty || value === attr.key;
|
|
2247
2369
|
}
|
|
2248
|
-
/* if the
|
|
2249
|
-
* (
|
|
2250
|
-
if (rule.
|
|
2370
|
+
/* if omit is set the value can be either null or empty string
|
|
2371
|
+
* (attribute-empty style regulates style) */
|
|
2372
|
+
if (rule.omit && empty) {
|
|
2373
|
+
return true;
|
|
2374
|
+
}
|
|
2375
|
+
/* validate each token when using list, all tokens must be valid */
|
|
2376
|
+
if (rule.list) {
|
|
2377
|
+
const tokens = new DOMTokenList(value, attr.valueLocation);
|
|
2378
|
+
return tokens.every((token) => {
|
|
2379
|
+
return this.validateAttributeValue(token, rule);
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
return this.validateAttributeValue(value, rule);
|
|
2383
|
+
}
|
|
2384
|
+
static validateAttributeValue(value, rule) {
|
|
2385
|
+
/* skip attribute if it not have enumerated list */
|
|
2386
|
+
if (!rule.enum) {
|
|
2251
2387
|
return true;
|
|
2252
2388
|
}
|
|
2253
2389
|
if (value === null || value === undefined) {
|
|
2254
2390
|
return false;
|
|
2255
2391
|
}
|
|
2256
|
-
return rule.some((entry) => {
|
|
2392
|
+
return rule.enum.some((entry) => {
|
|
2257
2393
|
if (entry instanceof RegExp) {
|
|
2258
2394
|
return !!value.match(entry);
|
|
2259
2395
|
}
|
|
@@ -2519,12 +2655,12 @@ var configurationSchema = {
|
|
|
2519
2655
|
const espree = legacyRequire("espree");
|
|
2520
2656
|
const walk = legacyRequire("acorn-walk");
|
|
2521
2657
|
function joinTemplateLiteral(nodes) {
|
|
2522
|
-
let offset = nodes[0].start;
|
|
2658
|
+
let offset = nodes[0].start + 1;
|
|
2523
2659
|
let output = "";
|
|
2524
2660
|
for (const node of nodes) {
|
|
2525
|
-
output += " ".repeat(node.start - offset);
|
|
2661
|
+
output += " ".repeat(node.start + 1 - offset);
|
|
2526
2662
|
output += node.value.raw;
|
|
2527
|
-
offset = node.end;
|
|
2663
|
+
offset = node.end - 2;
|
|
2528
2664
|
}
|
|
2529
2665
|
return output;
|
|
2530
2666
|
}
|
|
@@ -2716,7 +2852,7 @@ var TRANSFORMER_API;
|
|
|
2716
2852
|
})(TRANSFORMER_API || (TRANSFORMER_API = {}));
|
|
2717
2853
|
|
|
2718
2854
|
const name = "html-validate";
|
|
2719
|
-
const version = "
|
|
2855
|
+
const version = "6.1.0";
|
|
2720
2856
|
const homepage = "https://html-validate.org";
|
|
2721
2857
|
const bugs = {
|
|
2722
2858
|
url: "https://gitlab.com/html-validate/html-validate/issues/new"
|
|
@@ -3006,24 +3142,60 @@ const description = {
|
|
|
3006
3142
|
["absolute" /* ABSOLUTE */]: "Absolute links are not allowed by current configuration.",
|
|
3007
3143
|
["anchor" /* ANCHOR */]: null,
|
|
3008
3144
|
};
|
|
3145
|
+
function parseAllow(value) {
|
|
3146
|
+
if (typeof value === "boolean") {
|
|
3147
|
+
return value;
|
|
3148
|
+
}
|
|
3149
|
+
return {
|
|
3150
|
+
/* eslint-disable security/detect-non-literal-regexp */
|
|
3151
|
+
include: value.include ? value.include.map((it) => new RegExp(it)) : null,
|
|
3152
|
+
exclude: value.exclude ? value.exclude.map((it) => new RegExp(it)) : null,
|
|
3153
|
+
/* eslint-enable security/detect-non-literal-regexp */
|
|
3154
|
+
};
|
|
3155
|
+
}
|
|
3156
|
+
/**
|
|
3157
|
+
* @internal
|
|
3158
|
+
*/
|
|
3159
|
+
function matchList(value, list) {
|
|
3160
|
+
if (list.include && !list.include.some((it) => it.test(value))) {
|
|
3161
|
+
return false;
|
|
3162
|
+
}
|
|
3163
|
+
if (list.exclude && list.exclude.some((it) => it.test(value))) {
|
|
3164
|
+
return false;
|
|
3165
|
+
}
|
|
3166
|
+
return true;
|
|
3167
|
+
}
|
|
3009
3168
|
class AllowedLinks extends Rule {
|
|
3010
3169
|
constructor(options) {
|
|
3011
|
-
super(
|
|
3170
|
+
super({ ...defaults$p, ...options });
|
|
3171
|
+
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
3172
|
+
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
3173
|
+
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
3012
3174
|
}
|
|
3013
3175
|
static schema() {
|
|
3176
|
+
const booleanOrObject = {
|
|
3177
|
+
anyOf: [
|
|
3178
|
+
{ type: "boolean" },
|
|
3179
|
+
{
|
|
3180
|
+
type: "object",
|
|
3181
|
+
properties: {
|
|
3182
|
+
include: {
|
|
3183
|
+
type: "array",
|
|
3184
|
+
items: { type: "string" },
|
|
3185
|
+
},
|
|
3186
|
+
exclude: {
|
|
3187
|
+
type: "array",
|
|
3188
|
+
items: { type: "string" },
|
|
3189
|
+
},
|
|
3190
|
+
},
|
|
3191
|
+
},
|
|
3192
|
+
],
|
|
3193
|
+
};
|
|
3014
3194
|
return {
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
},
|
|
3018
|
-
allowBase: {
|
|
3019
|
-
type: "boolean",
|
|
3020
|
-
},
|
|
3021
|
-
allowExternal: {
|
|
3022
|
-
type: "boolean",
|
|
3023
|
-
},
|
|
3024
|
-
allowRelative: {
|
|
3025
|
-
type: "boolean",
|
|
3026
|
-
},
|
|
3195
|
+
allowExternal: { ...booleanOrObject },
|
|
3196
|
+
allowRelative: { ...booleanOrObject },
|
|
3197
|
+
allowAbsolute: { ...booleanOrObject },
|
|
3198
|
+
allowBase: { type: "boolean" },
|
|
3027
3199
|
};
|
|
3028
3200
|
}
|
|
3029
3201
|
documentation(context) {
|
|
@@ -3045,16 +3217,16 @@ class AllowedLinks extends Rule {
|
|
|
3045
3217
|
/* anchor links are always allowed by this rule */
|
|
3046
3218
|
break;
|
|
3047
3219
|
case "absolute" /* ABSOLUTE */:
|
|
3048
|
-
this.handleAbsolute(event, style);
|
|
3220
|
+
this.handleAbsolute(link, event, style);
|
|
3049
3221
|
break;
|
|
3050
3222
|
case "external" /* EXTERNAL */:
|
|
3051
|
-
this.handleExternal(event, style);
|
|
3223
|
+
this.handleExternal(link, event, style);
|
|
3052
3224
|
break;
|
|
3053
3225
|
case "relative-base" /* RELATIVE_BASE */:
|
|
3054
|
-
this.handleRelativeBase(event, style);
|
|
3226
|
+
this.handleRelativeBase(link, event, style);
|
|
3055
3227
|
break;
|
|
3056
3228
|
case "relative-path" /* RELATIVE_PATH */:
|
|
3057
|
-
this.handleRelativePath(event, style);
|
|
3229
|
+
this.handleRelativePath(link, event, style);
|
|
3058
3230
|
break;
|
|
3059
3231
|
}
|
|
3060
3232
|
});
|
|
@@ -3088,28 +3260,49 @@ class AllowedLinks extends Rule {
|
|
|
3088
3260
|
return "relative-base" /* RELATIVE_BASE */;
|
|
3089
3261
|
}
|
|
3090
3262
|
}
|
|
3091
|
-
handleAbsolute(event, style) {
|
|
3092
|
-
const { allowAbsolute } = this
|
|
3093
|
-
if (
|
|
3263
|
+
handleAbsolute(target, event, style) {
|
|
3264
|
+
const { allowAbsolute } = this;
|
|
3265
|
+
if (allowAbsolute === true) {
|
|
3266
|
+
return;
|
|
3267
|
+
}
|
|
3268
|
+
else if (allowAbsolute === false) {
|
|
3094
3269
|
this.report(event.target, "Link destination must not be absolute url", event.valueLocation, style);
|
|
3095
3270
|
}
|
|
3271
|
+
else if (!matchList(target, allowAbsolute)) {
|
|
3272
|
+
this.report(event.target, "Absolute link to this destination is not allowed by current configuration", event.valueLocation, style);
|
|
3273
|
+
}
|
|
3096
3274
|
}
|
|
3097
|
-
handleExternal(event, style) {
|
|
3098
|
-
const { allowExternal } = this
|
|
3099
|
-
if (
|
|
3275
|
+
handleExternal(target, event, style) {
|
|
3276
|
+
const { allowExternal } = this;
|
|
3277
|
+
if (allowExternal === true) {
|
|
3278
|
+
return;
|
|
3279
|
+
}
|
|
3280
|
+
else if (allowExternal === false) {
|
|
3100
3281
|
this.report(event.target, "Link destination must not be external url", event.valueLocation, style);
|
|
3101
3282
|
}
|
|
3283
|
+
else if (!matchList(target, allowExternal)) {
|
|
3284
|
+
this.report(event.target, "External link to this destination is not allowed by current configuration", event.valueLocation, style);
|
|
3285
|
+
}
|
|
3102
3286
|
}
|
|
3103
|
-
handleRelativePath(event, style) {
|
|
3104
|
-
const { allowRelative } = this
|
|
3105
|
-
if (
|
|
3287
|
+
handleRelativePath(target, event, style) {
|
|
3288
|
+
const { allowRelative } = this;
|
|
3289
|
+
if (allowRelative === true) {
|
|
3290
|
+
return false;
|
|
3291
|
+
}
|
|
3292
|
+
else if (allowRelative === false) {
|
|
3106
3293
|
this.report(event.target, "Link destination must not be relative url", event.valueLocation, style);
|
|
3294
|
+
return true;
|
|
3295
|
+
}
|
|
3296
|
+
else if (!matchList(target, allowRelative)) {
|
|
3297
|
+
this.report(event.target, "Relative link to this destination is not allowed by current configuration", event.valueLocation, style);
|
|
3298
|
+
return true;
|
|
3107
3299
|
}
|
|
3300
|
+
return false;
|
|
3108
3301
|
}
|
|
3109
|
-
handleRelativeBase(event, style) {
|
|
3110
|
-
const {
|
|
3111
|
-
if (
|
|
3112
|
-
|
|
3302
|
+
handleRelativeBase(target, event, style) {
|
|
3303
|
+
const { allowBase } = this.options;
|
|
3304
|
+
if (this.handleRelativePath(target, event, style)) {
|
|
3305
|
+
return;
|
|
3113
3306
|
}
|
|
3114
3307
|
else if (!allowBase) {
|
|
3115
3308
|
this.report(event.target, "Relative links must be relative to current folder", event.valueLocation, style);
|
|
@@ -3256,7 +3449,7 @@ const defaults$o = {
|
|
|
3256
3449
|
};
|
|
3257
3450
|
class AttrCase extends Rule {
|
|
3258
3451
|
constructor(options) {
|
|
3259
|
-
super(
|
|
3452
|
+
super({ ...defaults$o, ...options });
|
|
3260
3453
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
3261
3454
|
}
|
|
3262
3455
|
static schema() {
|
|
@@ -3346,7 +3539,7 @@ const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
|
|
|
3346
3539
|
const MATCH_TAG_OPEN = /^<(\/?)([a-zA-Z0-9\-:]+)/; // https://www.w3.org/TR/html/syntax.html#start-tags
|
|
3347
3540
|
const MATCH_TAG_CLOSE = /^\/?>/;
|
|
3348
3541
|
const MATCH_TEXT = /^[^]*?(?=(?:[ \t]*(?:\r\n|\r|\n)|<[^ ]|$))/;
|
|
3349
|
-
const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)
|
|
3542
|
+
const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
|
|
3350
3543
|
const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
|
|
3351
3544
|
const MATCH_ATTR_START = /^([^\t\r\n\f \/><"'=]+)/; // https://www.w3.org/TR/html/syntax.html#elements-attributes
|
|
3352
3545
|
const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
|
|
@@ -3609,7 +3802,7 @@ function generateDescription(name, pattern) {
|
|
|
3609
3802
|
}
|
|
3610
3803
|
class AttrPattern extends Rule {
|
|
3611
3804
|
constructor(options) {
|
|
3612
|
-
super(
|
|
3805
|
+
super({ ...defaults$n, ...options });
|
|
3613
3806
|
this.pattern = generateRegexp(this.options.pattern);
|
|
3614
3807
|
}
|
|
3615
3808
|
static schema() {
|
|
@@ -3675,7 +3868,7 @@ const defaults$m = {
|
|
|
3675
3868
|
};
|
|
3676
3869
|
class AttrQuotes extends Rule {
|
|
3677
3870
|
constructor(options) {
|
|
3678
|
-
super(
|
|
3871
|
+
super({ ...defaults$m, ...options });
|
|
3679
3872
|
this.style = parseStyle$4(this.options.style);
|
|
3680
3873
|
}
|
|
3681
3874
|
static schema() {
|
|
@@ -3771,11 +3964,11 @@ class AttributeAllowedValues extends Rule {
|
|
|
3771
3964
|
if (!context) {
|
|
3772
3965
|
return docs;
|
|
3773
3966
|
}
|
|
3774
|
-
if (context.allowed.
|
|
3775
|
-
const allowed = context.allowed.map((val) => `- \`${val}\``);
|
|
3967
|
+
if (context.allowed.enum) {
|
|
3968
|
+
const allowed = context.allowed.enum.map((val) => `- \`${val}\``);
|
|
3776
3969
|
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")}`;
|
|
3777
3970
|
}
|
|
3778
|
-
else {
|
|
3971
|
+
else if (context.allowed.boolean) {
|
|
3779
3972
|
docs.description = `Element <${context.element}> attribute \`${context.attribute}\` must be a boolean attribute, e.g. \`<${context.element} ${context.attribute}>\``;
|
|
3780
3973
|
}
|
|
3781
3974
|
return docs;
|
|
@@ -3831,7 +4024,7 @@ const defaults$l = {
|
|
|
3831
4024
|
};
|
|
3832
4025
|
class AttributeBooleanStyle extends Rule {
|
|
3833
4026
|
constructor(options) {
|
|
3834
|
-
super(
|
|
4027
|
+
super({ ...defaults$l, ...options });
|
|
3835
4028
|
this.hasInvalidStyle = parseStyle$3(this.options.style);
|
|
3836
4029
|
}
|
|
3837
4030
|
static schema() {
|
|
@@ -3876,7 +4069,8 @@ class AttributeBooleanStyle extends Rule {
|
|
|
3876
4069
|
});
|
|
3877
4070
|
}
|
|
3878
4071
|
isBoolean(attr, rules) {
|
|
3879
|
-
|
|
4072
|
+
var _a;
|
|
4073
|
+
return Boolean((_a = rules[attr.key]) === null || _a === void 0 ? void 0 : _a.boolean);
|
|
3880
4074
|
}
|
|
3881
4075
|
}
|
|
3882
4076
|
function parseStyle$3(style) {
|
|
@@ -3911,7 +4105,7 @@ const defaults$k = {
|
|
|
3911
4105
|
};
|
|
3912
4106
|
class AttributeEmptyStyle extends Rule {
|
|
3913
4107
|
constructor(options) {
|
|
3914
|
-
super(
|
|
4108
|
+
super({ ...defaults$k, ...options });
|
|
3915
4109
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
3916
4110
|
}
|
|
3917
4111
|
static schema() {
|
|
@@ -3960,7 +4154,8 @@ class AttributeEmptyStyle extends Rule {
|
|
|
3960
4154
|
}
|
|
3961
4155
|
}
|
|
3962
4156
|
function allowsEmpty(attr, rules) {
|
|
3963
|
-
|
|
4157
|
+
var _a;
|
|
4158
|
+
return Boolean((_a = rules[attr.key]) === null || _a === void 0 ? void 0 : _a.omit);
|
|
3964
4159
|
}
|
|
3965
4160
|
function isEmptyValue(attr) {
|
|
3966
4161
|
/* dynamic values are ignored, assumed to contain a value */
|
|
@@ -4023,7 +4218,7 @@ const defaults$j = {
|
|
|
4023
4218
|
};
|
|
4024
4219
|
class ClassPattern extends Rule {
|
|
4025
4220
|
constructor(options) {
|
|
4026
|
-
super(
|
|
4221
|
+
super({ ...defaults$j, ...options });
|
|
4027
4222
|
this.pattern = parsePattern(this.options.pattern);
|
|
4028
4223
|
}
|
|
4029
4224
|
static schema() {
|
|
@@ -4136,7 +4331,7 @@ const defaults$i = {
|
|
|
4136
4331
|
};
|
|
4137
4332
|
class Deprecated extends Rule {
|
|
4138
4333
|
constructor(options) {
|
|
4139
|
-
super(
|
|
4334
|
+
super({ ...defaults$i, ...options });
|
|
4140
4335
|
}
|
|
4141
4336
|
static schema() {
|
|
4142
4337
|
return {
|
|
@@ -4230,7 +4425,7 @@ class Deprecated extends Rule {
|
|
|
4230
4425
|
this.report(node, message, location, context);
|
|
4231
4426
|
}
|
|
4232
4427
|
reportObject(deprecated, node, location) {
|
|
4233
|
-
const context =
|
|
4428
|
+
const context = { ...deprecated, tagName: node.tagName };
|
|
4234
4429
|
const notice = deprecated.message ? `: ${deprecated.message}` : "";
|
|
4235
4430
|
const message = `<${node.tagName}> is deprecated${notice}`;
|
|
4236
4431
|
this.report(node, message, location, context);
|
|
@@ -4304,7 +4499,7 @@ const defaults$h = {
|
|
|
4304
4499
|
};
|
|
4305
4500
|
class DoctypeStyle extends Rule {
|
|
4306
4501
|
constructor(options) {
|
|
4307
|
-
super(
|
|
4502
|
+
super({ ...defaults$h, ...options });
|
|
4308
4503
|
}
|
|
4309
4504
|
static schema() {
|
|
4310
4505
|
return {
|
|
@@ -4341,7 +4536,7 @@ const defaults$g = {
|
|
|
4341
4536
|
};
|
|
4342
4537
|
class ElementCase extends Rule {
|
|
4343
4538
|
constructor(options) {
|
|
4344
|
-
super(
|
|
4539
|
+
super({ ...defaults$g, ...options });
|
|
4345
4540
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
4346
4541
|
}
|
|
4347
4542
|
static schema() {
|
|
@@ -4411,7 +4606,7 @@ const defaults$f = {
|
|
|
4411
4606
|
};
|
|
4412
4607
|
class ElementName extends Rule {
|
|
4413
4608
|
constructor(options) {
|
|
4414
|
-
super(
|
|
4609
|
+
super({ ...defaults$f, ...options });
|
|
4415
4610
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
4416
4611
|
this.pattern = new RegExp(this.options.pattern);
|
|
4417
4612
|
}
|
|
@@ -4683,9 +4878,14 @@ class ElementRequiredAttributes extends Rule {
|
|
|
4683
4878
|
this.on("tag:end", (event) => {
|
|
4684
4879
|
const node = event.previous;
|
|
4685
4880
|
const meta = node.meta;
|
|
4686
|
-
|
|
4881
|
+
/* handle missing metadata and missing attributes */
|
|
4882
|
+
if (!meta || !meta.attributes) {
|
|
4687
4883
|
return;
|
|
4688
|
-
|
|
4884
|
+
}
|
|
4885
|
+
for (const [key, attr] of Object.entries(meta.attributes)) {
|
|
4886
|
+
if (!attr.required) {
|
|
4887
|
+
continue;
|
|
4888
|
+
}
|
|
4689
4889
|
if (node.hasAttribute(key))
|
|
4690
4890
|
continue;
|
|
4691
4891
|
const context = {
|
|
@@ -4868,7 +5068,7 @@ function parseMaxInitial(value) {
|
|
|
4868
5068
|
}
|
|
4869
5069
|
class HeadingLevel extends Rule {
|
|
4870
5070
|
constructor(options) {
|
|
4871
|
-
super(
|
|
5071
|
+
super({ ...defaults$e, ...options });
|
|
4872
5072
|
this.stack = [];
|
|
4873
5073
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
4874
5074
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
|
|
@@ -5031,7 +5231,7 @@ const defaults$d = {
|
|
|
5031
5231
|
};
|
|
5032
5232
|
class IdPattern extends Rule {
|
|
5033
5233
|
constructor(options) {
|
|
5034
|
-
super(
|
|
5234
|
+
super({ ...defaults$d, ...options });
|
|
5035
5235
|
this.pattern = parsePattern(this.options.pattern);
|
|
5036
5236
|
}
|
|
5037
5237
|
static schema() {
|
|
@@ -5383,7 +5583,7 @@ const defaults$c = {
|
|
|
5383
5583
|
};
|
|
5384
5584
|
class LongTitle extends Rule {
|
|
5385
5585
|
constructor(options) {
|
|
5386
|
-
super(
|
|
5586
|
+
super({ ...defaults$c, ...options });
|
|
5387
5587
|
this.maxlength = this.options.maxlength;
|
|
5388
5588
|
}
|
|
5389
5589
|
static schema() {
|
|
@@ -5536,7 +5736,7 @@ const defaults$b = {
|
|
|
5536
5736
|
};
|
|
5537
5737
|
class NoAutoplay extends Rule {
|
|
5538
5738
|
constructor(options) {
|
|
5539
|
-
super(
|
|
5739
|
+
super({ ...defaults$b, ...options });
|
|
5540
5740
|
}
|
|
5541
5741
|
documentation(context) {
|
|
5542
5742
|
const tagName = context ? ` on <${context.tagName}>` : "";
|
|
@@ -5632,8 +5832,12 @@ class NoDeprecatedAttr extends Rule {
|
|
|
5632
5832
|
if (meta === null) {
|
|
5633
5833
|
return;
|
|
5634
5834
|
}
|
|
5635
|
-
const
|
|
5636
|
-
if (
|
|
5835
|
+
const metaAttribute = meta.attributes && meta.attributes[attr];
|
|
5836
|
+
if (!metaAttribute) {
|
|
5837
|
+
return;
|
|
5838
|
+
}
|
|
5839
|
+
const deprecated = metaAttribute.deprecated;
|
|
5840
|
+
if (deprecated) {
|
|
5637
5841
|
this.report(node, `Attribute "${event.key}" is deprecated on <${node.tagName}> element`, event.keyLocation);
|
|
5638
5842
|
}
|
|
5639
5843
|
});
|
|
@@ -5790,7 +5994,7 @@ function getCSSDeclarations(value) {
|
|
|
5790
5994
|
}
|
|
5791
5995
|
class NoInlineStyle extends Rule {
|
|
5792
5996
|
constructor(options) {
|
|
5793
|
-
super(
|
|
5997
|
+
super({ ...defaults$a, ...options });
|
|
5794
5998
|
}
|
|
5795
5999
|
static schema() {
|
|
5796
6000
|
return {
|
|
@@ -6000,7 +6204,7 @@ const defaults$9 = {
|
|
|
6000
6204
|
};
|
|
6001
6205
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
6002
6206
|
const unquotedAttrRegexp = /([<>"'=`]|&(?![a-zA-Z0-9#]+;))/g;
|
|
6003
|
-
const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)
|
|
6207
|
+
const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
|
|
6004
6208
|
const replacementTable = new Map([
|
|
6005
6209
|
['"', """],
|
|
6006
6210
|
["&", "&"],
|
|
@@ -6012,7 +6216,7 @@ const replacementTable = new Map([
|
|
|
6012
6216
|
]);
|
|
6013
6217
|
class NoRawCharacters extends Rule {
|
|
6014
6218
|
constructor(options) {
|
|
6015
|
-
super(
|
|
6219
|
+
super({ ...defaults$9, ...options });
|
|
6016
6220
|
this.relaxed = this.options.relaxed;
|
|
6017
6221
|
}
|
|
6018
6222
|
static schema() {
|
|
@@ -6197,7 +6401,7 @@ const defaults$8 = {
|
|
|
6197
6401
|
};
|
|
6198
6402
|
class NoSelfClosing extends Rule {
|
|
6199
6403
|
constructor(options) {
|
|
6200
|
-
super(
|
|
6404
|
+
super({ ...defaults$8, ...options });
|
|
6201
6405
|
}
|
|
6202
6406
|
static schema() {
|
|
6203
6407
|
return {
|
|
@@ -6336,7 +6540,7 @@ const defaults$7 = {
|
|
|
6336
6540
|
};
|
|
6337
6541
|
class PreferButton extends Rule {
|
|
6338
6542
|
constructor(options) {
|
|
6339
|
-
super(
|
|
6543
|
+
super({ ...defaults$7, ...options });
|
|
6340
6544
|
}
|
|
6341
6545
|
static schema() {
|
|
6342
6546
|
return {
|
|
@@ -6441,7 +6645,7 @@ const defaults$6 = {
|
|
|
6441
6645
|
};
|
|
6442
6646
|
class PreferNativeElement extends Rule {
|
|
6443
6647
|
constructor(options) {
|
|
6444
|
-
super(
|
|
6648
|
+
super({ ...defaults$6, ...options });
|
|
6445
6649
|
}
|
|
6446
6650
|
static schema() {
|
|
6447
6651
|
return {
|
|
@@ -6571,7 +6775,7 @@ const supportSri = {
|
|
|
6571
6775
|
};
|
|
6572
6776
|
class RequireSri extends Rule {
|
|
6573
6777
|
constructor(options) {
|
|
6574
|
-
super(
|
|
6778
|
+
super({ ...defaults$5, ...options });
|
|
6575
6779
|
this.target = this.options.target;
|
|
6576
6780
|
}
|
|
6577
6781
|
static schema() {
|
|
@@ -8666,7 +8870,7 @@ const defaults$4 = {
|
|
|
8666
8870
|
};
|
|
8667
8871
|
class Void extends Rule {
|
|
8668
8872
|
constructor(options) {
|
|
8669
|
-
super(
|
|
8873
|
+
super({ ...defaults$4, ...options });
|
|
8670
8874
|
this.style = parseStyle$1(this.options.style);
|
|
8671
8875
|
}
|
|
8672
8876
|
get deprecated() {
|
|
@@ -8775,7 +8979,7 @@ const defaults$3 = {
|
|
|
8775
8979
|
};
|
|
8776
8980
|
class VoidStyle extends Rule {
|
|
8777
8981
|
constructor(options) {
|
|
8778
|
-
super(
|
|
8982
|
+
super({ ...defaults$3, ...options });
|
|
8779
8983
|
this.style = parseStyle(this.options.style);
|
|
8780
8984
|
}
|
|
8781
8985
|
static schema() {
|
|
@@ -8978,7 +9182,7 @@ const defaults$2 = {
|
|
|
8978
9182
|
};
|
|
8979
9183
|
class H37 extends Rule {
|
|
8980
9184
|
constructor(options) {
|
|
8981
|
-
super(
|
|
9185
|
+
super({ ...defaults$2, ...options });
|
|
8982
9186
|
/* ensure alias is array */
|
|
8983
9187
|
if (!Array.isArray(this.options.alias)) {
|
|
8984
9188
|
this.options.alias = [this.options.alias];
|
|
@@ -9105,7 +9309,73 @@ const bundledRules$1 = {
|
|
|
9105
9309
|
"wcag/h71": H71,
|
|
9106
9310
|
};
|
|
9107
9311
|
|
|
9108
|
-
const bundledRules =
|
|
9312
|
+
const bundledRules = {
|
|
9313
|
+
"allowed-links": AllowedLinks,
|
|
9314
|
+
"aria-label-misuse": AriaLabelMisuse,
|
|
9315
|
+
"attr-case": AttrCase,
|
|
9316
|
+
"attr-delimiter": AttrDelimiter,
|
|
9317
|
+
"attr-pattern": AttrPattern,
|
|
9318
|
+
"attr-quotes": AttrQuotes,
|
|
9319
|
+
"attr-spacing": AttrSpacing,
|
|
9320
|
+
"attribute-allowed-values": AttributeAllowedValues,
|
|
9321
|
+
"attribute-boolean-style": AttributeBooleanStyle,
|
|
9322
|
+
"attribute-empty-style": AttributeEmptyStyle,
|
|
9323
|
+
"class-pattern": ClassPattern,
|
|
9324
|
+
"close-attr": CloseAttr,
|
|
9325
|
+
"close-order": CloseOrder,
|
|
9326
|
+
deprecated: Deprecated,
|
|
9327
|
+
"deprecated-rule": DeprecatedRule,
|
|
9328
|
+
"doctype-html": NoStyleTag$1,
|
|
9329
|
+
"doctype-style": DoctypeStyle,
|
|
9330
|
+
"element-case": ElementCase,
|
|
9331
|
+
"element-name": ElementName,
|
|
9332
|
+
"element-permitted-content": ElementPermittedContent,
|
|
9333
|
+
"element-permitted-occurrences": ElementPermittedOccurrences,
|
|
9334
|
+
"element-permitted-order": ElementPermittedOrder,
|
|
9335
|
+
"element-required-attributes": ElementRequiredAttributes,
|
|
9336
|
+
"element-required-content": ElementRequiredContent,
|
|
9337
|
+
"empty-heading": EmptyHeading,
|
|
9338
|
+
"empty-title": EmptyTitle,
|
|
9339
|
+
"heading-level": HeadingLevel,
|
|
9340
|
+
"id-pattern": IdPattern,
|
|
9341
|
+
"input-attributes": InputAttributes,
|
|
9342
|
+
"input-missing-label": InputMissingLabel,
|
|
9343
|
+
"long-title": LongTitle,
|
|
9344
|
+
"meta-refresh": MetaRefresh,
|
|
9345
|
+
"missing-doctype": MissingDoctype,
|
|
9346
|
+
"multiple-labeled-controls": MultipleLabeledControls,
|
|
9347
|
+
"no-autoplay": NoAutoplay,
|
|
9348
|
+
"no-conditional-comment": NoConditionalComment,
|
|
9349
|
+
"no-deprecated-attr": NoDeprecatedAttr,
|
|
9350
|
+
"no-dup-attr": NoDupAttr,
|
|
9351
|
+
"no-dup-class": NoDupClass,
|
|
9352
|
+
"no-dup-id": NoDupID,
|
|
9353
|
+
"no-implicit-close": NoImplicitClose,
|
|
9354
|
+
"no-inline-style": NoInlineStyle,
|
|
9355
|
+
"no-missing-references": NoMissingReferences,
|
|
9356
|
+
"no-multiple-main": NoMultipleMain,
|
|
9357
|
+
"no-raw-characters": NoRawCharacters,
|
|
9358
|
+
"no-redundant-for": NoRedundantFor,
|
|
9359
|
+
"no-redundant-role": NoRedundantRole,
|
|
9360
|
+
"no-self-closing": NoSelfClosing,
|
|
9361
|
+
"no-style-tag": NoStyleTag,
|
|
9362
|
+
"no-trailing-whitespace": NoTrailingWhitespace,
|
|
9363
|
+
"no-unknown-elements": NoUnknownElements,
|
|
9364
|
+
"no-utf8-bom": NoUtf8Bom,
|
|
9365
|
+
"prefer-button": PreferButton,
|
|
9366
|
+
"prefer-native-element": PreferNativeElement,
|
|
9367
|
+
"prefer-tbody": PreferTbody,
|
|
9368
|
+
"require-sri": RequireSri,
|
|
9369
|
+
"script-element": ScriptElement,
|
|
9370
|
+
"script-type": ScriptType,
|
|
9371
|
+
"svg-focusable": SvgFocusable,
|
|
9372
|
+
"text-content": TextContent,
|
|
9373
|
+
"unrecognized-char-ref": UnknownCharReference,
|
|
9374
|
+
void: Void,
|
|
9375
|
+
"void-content": VoidContent,
|
|
9376
|
+
"void-style": VoidStyle,
|
|
9377
|
+
...bundledRules$1,
|
|
9378
|
+
};
|
|
9109
9379
|
|
|
9110
9380
|
var defaultConfig = {};
|
|
9111
9381
|
|
|
@@ -9343,7 +9613,7 @@ function overwriteMerge(a, b) {
|
|
|
9343
9613
|
return b;
|
|
9344
9614
|
}
|
|
9345
9615
|
function mergeInternal(base, rhs) {
|
|
9346
|
-
const dst = deepmerge(base,
|
|
9616
|
+
const dst = deepmerge(base, { ...rhs, rules: {} });
|
|
9347
9617
|
/* rules need some special care, should overwrite arrays instead of
|
|
9348
9618
|
* concaternation, i.e. ["error", {...options}] should not be merged by
|
|
9349
9619
|
* appending to old value */
|
|
@@ -9568,7 +9838,7 @@ class Config {
|
|
|
9568
9838
|
* @internal primary purpose is unittests
|
|
9569
9839
|
*/
|
|
9570
9840
|
get() {
|
|
9571
|
-
const config =
|
|
9841
|
+
const config = { ...this.config };
|
|
9572
9842
|
if (config.elements) {
|
|
9573
9843
|
config.elements = config.elements.map((cur) => {
|
|
9574
9844
|
if (typeof cur === "string") {
|
|
@@ -9654,7 +9924,11 @@ class Config {
|
|
|
9654
9924
|
if (!properties) {
|
|
9655
9925
|
continue;
|
|
9656
9926
|
}
|
|
9657
|
-
for (const [
|
|
9927
|
+
for (const [raw, schema] of Object.entries(properties)) {
|
|
9928
|
+
/* at compile time this is a fixed list but the point of this method is
|
|
9929
|
+
* to augment the runtime with additional keys so it is a bit of lying
|
|
9930
|
+
* to typescript */
|
|
9931
|
+
const key = raw;
|
|
9658
9932
|
if (schema.copyable && !MetaCopyableProperty.includes(key)) {
|
|
9659
9933
|
MetaCopyableProperty.push(key);
|
|
9660
9934
|
}
|
|
@@ -9850,31 +10124,6 @@ class ConfigLoader {
|
|
|
9850
10124
|
}
|
|
9851
10125
|
}
|
|
9852
10126
|
|
|
9853
|
-
/*! *****************************************************************************
|
|
9854
|
-
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
9855
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
9856
|
-
this file except in compliance with the License. You may obtain a copy of the
|
|
9857
|
-
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9858
|
-
|
|
9859
|
-
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
9860
|
-
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
9861
|
-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
9862
|
-
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
9863
|
-
|
|
9864
|
-
See the Apache Version 2.0 License for specific language governing permissions
|
|
9865
|
-
and limitations under the License.
|
|
9866
|
-
***************************************************************************** */
|
|
9867
|
-
|
|
9868
|
-
function __rest(s, e) {
|
|
9869
|
-
var t = {};
|
|
9870
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
9871
|
-
t[p] = s[p];
|
|
9872
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
9873
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
|
|
9874
|
-
t[p[i]] = s[p[i]];
|
|
9875
|
-
return t;
|
|
9876
|
-
}
|
|
9877
|
-
|
|
9878
10127
|
class EventHandler {
|
|
9879
10128
|
constructor() {
|
|
9880
10129
|
this.listeners = {};
|
|
@@ -10448,7 +10697,7 @@ class Reporter {
|
|
|
10448
10697
|
merged[key].messages = [...merged[key].messages, ...result.messages];
|
|
10449
10698
|
}
|
|
10450
10699
|
else {
|
|
10451
|
-
merged[key] =
|
|
10700
|
+
merged[key] = { ...result };
|
|
10452
10701
|
}
|
|
10453
10702
|
});
|
|
10454
10703
|
});
|
|
@@ -10550,14 +10799,16 @@ function messageSort(a, b) {
|
|
|
10550
10799
|
}
|
|
10551
10800
|
|
|
10552
10801
|
class Engine {
|
|
10553
|
-
constructor(config,
|
|
10802
|
+
constructor(config, ParserClass) {
|
|
10554
10803
|
this.report = new Reporter();
|
|
10555
|
-
this.configData = configData;
|
|
10556
10804
|
this.config = config;
|
|
10557
10805
|
this.ParserClass = ParserClass;
|
|
10558
10806
|
/* initialize plugins and rules */
|
|
10559
10807
|
const result = this.initPlugins(this.config);
|
|
10560
|
-
this.availableRules =
|
|
10808
|
+
this.availableRules = {
|
|
10809
|
+
...bundledRules,
|
|
10810
|
+
...result.availableRules,
|
|
10811
|
+
};
|
|
10561
10812
|
}
|
|
10562
10813
|
/**
|
|
10563
10814
|
* Lint sources and return report
|
|
@@ -10582,13 +10833,13 @@ class Engine {
|
|
|
10582
10833
|
/* trigger configuration ready event */
|
|
10583
10834
|
const configEvent = {
|
|
10584
10835
|
location,
|
|
10585
|
-
config: this.
|
|
10836
|
+
config: this.config,
|
|
10586
10837
|
rules,
|
|
10587
10838
|
};
|
|
10588
10839
|
parser.trigger("config:ready", configEvent);
|
|
10589
10840
|
/* trigger source ready event */
|
|
10590
10841
|
/* eslint-disable-next-line @typescript-eslint/no-unused-vars -- object destructured on purpose to remove property */
|
|
10591
|
-
const sourceData =
|
|
10842
|
+
const { hooks: _, ...sourceData } = source;
|
|
10592
10843
|
const sourceEvent = {
|
|
10593
10844
|
location,
|
|
10594
10845
|
source: sourceData,
|
|
@@ -10895,133 +11146,31 @@ class Engine {
|
|
|
10895
11146
|
}
|
|
10896
11147
|
|
|
10897
11148
|
/**
|
|
10898
|
-
*
|
|
10899
|
-
|
|
10900
|
-
function findConfigurationFiles(directory) {
|
|
10901
|
-
return ["json", "cjs", "js"]
|
|
10902
|
-
.map((extension) => path.join(directory, `.htmlvalidate.${extension}`))
|
|
10903
|
-
.filter((filePath) => fs.existsSync(filePath));
|
|
10904
|
-
}
|
|
10905
|
-
/**
|
|
10906
|
-
* Loads configuration by traversing filesystem.
|
|
10907
|
-
*
|
|
10908
|
-
* Configuration is read from three sources and in the following order:
|
|
10909
|
-
*
|
|
10910
|
-
* 1. Global configuration passed to constructor.
|
|
10911
|
-
* 2. Configuration files found when traversing the directory structure.
|
|
10912
|
-
* 3. Override passed to this function.
|
|
10913
|
-
*
|
|
10914
|
-
* The following configuration filenames are searched:
|
|
10915
|
-
*
|
|
10916
|
-
* - `.htmlvalidate.json`
|
|
10917
|
-
* - `.htmlvalidate.js`
|
|
10918
|
-
* - `.htmlvalidate.cjs`
|
|
10919
|
-
*
|
|
10920
|
-
* Global configuration is used when no configuration file is found. The
|
|
10921
|
-
* result is always merged with override if present.
|
|
10922
|
-
*
|
|
10923
|
-
* The `root` property set to `true` affects the configuration as following:
|
|
11149
|
+
* The static configuration loader does not do any per-handle lookup. Only the
|
|
11150
|
+
* global or per-call configuration is used.
|
|
10924
11151
|
*
|
|
10925
|
-
*
|
|
10926
|
-
*
|
|
10927
|
-
* returned. No configuration files are searched.
|
|
10928
|
-
* 3. Setting `root` in configuration file only stops directory traversal.
|
|
11152
|
+
* In practice this means no configuration is fetch by traversing the
|
|
11153
|
+
* filesystem.
|
|
10929
11154
|
*/
|
|
10930
|
-
class
|
|
10931
|
-
|
|
10932
|
-
* @param config - Global configuration
|
|
10933
|
-
* @param configFactory - Optional configuration factory
|
|
10934
|
-
*/
|
|
10935
|
-
constructor(config, configFactory = Config) {
|
|
10936
|
-
super(config, configFactory);
|
|
10937
|
-
this.cache = new Map();
|
|
10938
|
-
}
|
|
10939
|
-
/**
|
|
10940
|
-
* Get configuration for given filename.
|
|
10941
|
-
*
|
|
10942
|
-
* @param filename - Filename to get configuration for.
|
|
10943
|
-
* @param configOverride - Configuration to merge final result with.
|
|
10944
|
-
*/
|
|
10945
|
-
getConfigFor(filename, configOverride) {
|
|
10946
|
-
/* special case when the overridden configuration is marked as root, should
|
|
10947
|
-
* not try to load any more configuration files */
|
|
11155
|
+
class StaticConfigLoader extends ConfigLoader {
|
|
11156
|
+
getConfigFor(handle, configOverride) {
|
|
10948
11157
|
const override = this.loadFromObject(configOverride || {});
|
|
10949
11158
|
if (override.isRootFound()) {
|
|
10950
11159
|
override.init();
|
|
10951
11160
|
return override;
|
|
10952
11161
|
}
|
|
10953
|
-
|
|
10954
|
-
* try to load and more configuration files */
|
|
10955
|
-
if (this.globalConfig.isRootFound()) {
|
|
10956
|
-
const merged = this.globalConfig.merge(override);
|
|
10957
|
-
merged.init();
|
|
10958
|
-
return merged;
|
|
10959
|
-
}
|
|
10960
|
-
const config = this.fromFilename(filename);
|
|
10961
|
-
const merged = config ? config.merge(override) : this.globalConfig.merge(override);
|
|
11162
|
+
const merged = this.globalConfig.merge(override);
|
|
10962
11163
|
merged.init();
|
|
10963
11164
|
return merged;
|
|
10964
11165
|
}
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
*
|
|
10968
|
-
* @param filename - If given only the cache for that file is flushed.
|
|
10969
|
-
*/
|
|
10970
|
-
flushCache(filename) {
|
|
10971
|
-
if (filename) {
|
|
10972
|
-
this.cache.delete(filename);
|
|
10973
|
-
}
|
|
10974
|
-
else {
|
|
10975
|
-
this.cache.clear();
|
|
10976
|
-
}
|
|
10977
|
-
}
|
|
10978
|
-
/**
|
|
10979
|
-
* Load raw configuration from directory traversal.
|
|
10980
|
-
*
|
|
10981
|
-
* This configuration is not merged with global configuration and may return
|
|
10982
|
-
* `null` if no configuration files are found.
|
|
10983
|
-
*/
|
|
10984
|
-
fromFilename(filename) {
|
|
10985
|
-
var _a;
|
|
10986
|
-
if (filename === "inline") {
|
|
10987
|
-
return null;
|
|
10988
|
-
}
|
|
10989
|
-
if (this.cache.has(filename)) {
|
|
10990
|
-
return (_a = this.cache.get(filename)) !== null && _a !== void 0 ? _a : null;
|
|
10991
|
-
}
|
|
10992
|
-
let found = false;
|
|
10993
|
-
let current = path.resolve(path.dirname(filename));
|
|
10994
|
-
let config = this.empty();
|
|
10995
|
-
// eslint-disable-next-line no-constant-condition
|
|
10996
|
-
while (true) {
|
|
10997
|
-
/* search configuration files in current directory */
|
|
10998
|
-
for (const configFile of findConfigurationFiles(current)) {
|
|
10999
|
-
const local = this.loadFromFile(configFile);
|
|
11000
|
-
found = true;
|
|
11001
|
-
config = local.merge(config);
|
|
11002
|
-
}
|
|
11003
|
-
/* stop if a configuration with "root" is set to true */
|
|
11004
|
-
if (config.isRootFound()) {
|
|
11005
|
-
break;
|
|
11006
|
-
}
|
|
11007
|
-
/* get the parent directory */
|
|
11008
|
-
const child = current;
|
|
11009
|
-
current = path.dirname(current);
|
|
11010
|
-
/* stop if this is the root directory */
|
|
11011
|
-
if (current === child) {
|
|
11012
|
-
break;
|
|
11013
|
-
}
|
|
11014
|
-
}
|
|
11015
|
-
/* no config was found by loader, return null and let caller decide what to do */
|
|
11016
|
-
if (!found) {
|
|
11017
|
-
this.cache.set(filename, null);
|
|
11018
|
-
return null;
|
|
11019
|
-
}
|
|
11020
|
-
this.cache.set(filename, config);
|
|
11021
|
-
return config;
|
|
11166
|
+
flushCache() {
|
|
11167
|
+
/* do nothing */
|
|
11022
11168
|
}
|
|
11023
11169
|
defaultConfig() {
|
|
11024
|
-
return this.
|
|
11170
|
+
return this.loadFromObject({
|
|
11171
|
+
extends: ["html-validate:recommended"],
|
|
11172
|
+
elements: ["html5"],
|
|
11173
|
+
});
|
|
11025
11174
|
}
|
|
11026
11175
|
}
|
|
11027
11176
|
|
|
@@ -11045,7 +11194,7 @@ function isConfigData(value) {
|
|
|
11045
11194
|
class HtmlValidate {
|
|
11046
11195
|
constructor(arg) {
|
|
11047
11196
|
const [loader, config] = arg instanceof ConfigLoader ? [arg, undefined] : [undefined, arg];
|
|
11048
|
-
this.configLoader = loader !== null && loader !== void 0 ? loader : new
|
|
11197
|
+
this.configLoader = loader !== null && loader !== void 0 ? loader : new StaticConfigLoader(config);
|
|
11049
11198
|
}
|
|
11050
11199
|
validateString(str, arg1, arg2, arg3) {
|
|
11051
11200
|
const filename = typeof arg1 === "string" ? arg1 : "inline";
|
|
@@ -11072,7 +11221,7 @@ class HtmlValidate {
|
|
|
11072
11221
|
const config = this.getConfigFor(input.filename, configOverride);
|
|
11073
11222
|
const resolved = config.resolve();
|
|
11074
11223
|
const source = resolved.transformSource(input);
|
|
11075
|
-
const engine = new Engine(resolved,
|
|
11224
|
+
const engine = new Engine(resolved, Parser);
|
|
11076
11225
|
return engine.lint(source);
|
|
11077
11226
|
}
|
|
11078
11227
|
/**
|
|
@@ -11086,7 +11235,7 @@ class HtmlValidate {
|
|
|
11086
11235
|
const config = this.getConfigFor(filename);
|
|
11087
11236
|
const resolved = config.resolve();
|
|
11088
11237
|
const source = resolved.transformFilename(filename);
|
|
11089
|
-
const engine = new Engine(resolved,
|
|
11238
|
+
const engine = new Engine(resolved, Parser);
|
|
11090
11239
|
return engine.lint(source);
|
|
11091
11240
|
}
|
|
11092
11241
|
/**
|
|
@@ -11131,7 +11280,7 @@ class HtmlValidate {
|
|
|
11131
11280
|
const config = this.getConfigFor(filename);
|
|
11132
11281
|
const resolved = config.resolve();
|
|
11133
11282
|
const source = resolved.transformFilename(filename);
|
|
11134
|
-
const engine = new Engine(resolved,
|
|
11283
|
+
const engine = new Engine(resolved, Parser);
|
|
11135
11284
|
return engine.dumpTokens(source);
|
|
11136
11285
|
}
|
|
11137
11286
|
/**
|
|
@@ -11146,7 +11295,7 @@ class HtmlValidate {
|
|
|
11146
11295
|
const config = this.getConfigFor(filename);
|
|
11147
11296
|
const resolved = config.resolve();
|
|
11148
11297
|
const source = resolved.transformFilename(filename);
|
|
11149
|
-
const engine = new Engine(resolved,
|
|
11298
|
+
const engine = new Engine(resolved, Parser);
|
|
11150
11299
|
return engine.dumpEvents(source);
|
|
11151
11300
|
}
|
|
11152
11301
|
/**
|
|
@@ -11161,7 +11310,7 @@ class HtmlValidate {
|
|
|
11161
11310
|
const config = this.getConfigFor(filename);
|
|
11162
11311
|
const resolved = config.resolve();
|
|
11163
11312
|
const source = resolved.transformFilename(filename);
|
|
11164
|
-
const engine = new Engine(resolved,
|
|
11313
|
+
const engine = new Engine(resolved, Parser);
|
|
11165
11314
|
return engine.dumpTree(source);
|
|
11166
11315
|
}
|
|
11167
11316
|
/**
|
|
@@ -11239,7 +11388,7 @@ class HtmlValidate {
|
|
|
11239
11388
|
*/
|
|
11240
11389
|
getRuleDocumentation(ruleId, config = null, context = null) {
|
|
11241
11390
|
const c = config || this.getConfigFor("inline");
|
|
11242
|
-
const engine = new Engine(c.resolve(),
|
|
11391
|
+
const engine = new Engine(c.resolve(), Parser);
|
|
11243
11392
|
return engine.getRuleDocumentation(ruleId, context);
|
|
11244
11393
|
}
|
|
11245
11394
|
/**
|
|
@@ -11276,35 +11425,6 @@ class HtmlValidate {
|
|
|
11276
11425
|
}
|
|
11277
11426
|
}
|
|
11278
11427
|
|
|
11279
|
-
/**
|
|
11280
|
-
* The static configuration loader does not do any per-handle lookup. Only the
|
|
11281
|
-
* global or per-call configuration is used.
|
|
11282
|
-
*
|
|
11283
|
-
* In practice this means no configuration is fetch by traversing the
|
|
11284
|
-
* filesystem.
|
|
11285
|
-
*/
|
|
11286
|
-
class StaticConfigLoader extends ConfigLoader {
|
|
11287
|
-
getConfigFor(handle, configOverride) {
|
|
11288
|
-
const override = this.loadFromObject(configOverride || {});
|
|
11289
|
-
if (override.isRootFound()) {
|
|
11290
|
-
override.init();
|
|
11291
|
-
return override;
|
|
11292
|
-
}
|
|
11293
|
-
const merged = this.globalConfig.merge(override);
|
|
11294
|
-
merged.init();
|
|
11295
|
-
return merged;
|
|
11296
|
-
}
|
|
11297
|
-
flushCache() {
|
|
11298
|
-
/* do nothing */
|
|
11299
|
-
}
|
|
11300
|
-
defaultConfig() {
|
|
11301
|
-
return this.loadFromObject({
|
|
11302
|
-
extends: ["html-validate:recommended"],
|
|
11303
|
-
elements: ["html5"],
|
|
11304
|
-
});
|
|
11305
|
-
}
|
|
11306
|
-
}
|
|
11307
|
-
|
|
11308
11428
|
const defaults$1 = {
|
|
11309
11429
|
silent: false,
|
|
11310
11430
|
version,
|
|
@@ -11322,7 +11442,7 @@ const defaults$1 = {
|
|
|
11322
11442
|
* @returns - `true` if version is compatible
|
|
11323
11443
|
*/
|
|
11324
11444
|
function compatibilityCheck(name, declared, options) {
|
|
11325
|
-
const { silent, version: current, logger } =
|
|
11445
|
+
const { silent, version: current, logger } = { ...defaults$1, ...options };
|
|
11326
11446
|
const valid = semver.satisfies(current, declared);
|
|
11327
11447
|
if (valid || silent) {
|
|
11328
11448
|
return valid;
|
|
@@ -11352,6 +11472,137 @@ function ruleExists(ruleId) {
|
|
|
11352
11472
|
return ruleIds.has(ruleId);
|
|
11353
11473
|
}
|
|
11354
11474
|
|
|
11475
|
+
/**
|
|
11476
|
+
* @internal
|
|
11477
|
+
*/
|
|
11478
|
+
function findConfigurationFiles(directory) {
|
|
11479
|
+
return ["json", "cjs", "js"]
|
|
11480
|
+
.map((extension) => path.join(directory, `.htmlvalidate.${extension}`))
|
|
11481
|
+
.filter((filePath) => fs.existsSync(filePath));
|
|
11482
|
+
}
|
|
11483
|
+
/**
|
|
11484
|
+
* Loads configuration by traversing filesystem.
|
|
11485
|
+
*
|
|
11486
|
+
* Configuration is read from three sources and in the following order:
|
|
11487
|
+
*
|
|
11488
|
+
* 1. Global configuration passed to constructor.
|
|
11489
|
+
* 2. Configuration files found when traversing the directory structure.
|
|
11490
|
+
* 3. Override passed to this function.
|
|
11491
|
+
*
|
|
11492
|
+
* The following configuration filenames are searched:
|
|
11493
|
+
*
|
|
11494
|
+
* - `.htmlvalidate.json`
|
|
11495
|
+
* - `.htmlvalidate.js`
|
|
11496
|
+
* - `.htmlvalidate.cjs`
|
|
11497
|
+
*
|
|
11498
|
+
* Global configuration is used when no configuration file is found. The
|
|
11499
|
+
* result is always merged with override if present.
|
|
11500
|
+
*
|
|
11501
|
+
* The `root` property set to `true` affects the configuration as following:
|
|
11502
|
+
*
|
|
11503
|
+
* 1. If set in override the override is returned as-is.
|
|
11504
|
+
* 2. If set in the global config the override is merged into global and
|
|
11505
|
+
* returned. No configuration files are searched.
|
|
11506
|
+
* 3. Setting `root` in configuration file only stops directory traversal.
|
|
11507
|
+
*/
|
|
11508
|
+
class FileSystemConfigLoader extends ConfigLoader {
|
|
11509
|
+
/**
|
|
11510
|
+
* @param config - Global configuration
|
|
11511
|
+
* @param configFactory - Optional configuration factory
|
|
11512
|
+
*/
|
|
11513
|
+
constructor(config, configFactory = Config) {
|
|
11514
|
+
super(config, configFactory);
|
|
11515
|
+
this.cache = new Map();
|
|
11516
|
+
}
|
|
11517
|
+
/**
|
|
11518
|
+
* Get configuration for given filename.
|
|
11519
|
+
*
|
|
11520
|
+
* @param filename - Filename to get configuration for.
|
|
11521
|
+
* @param configOverride - Configuration to merge final result with.
|
|
11522
|
+
*/
|
|
11523
|
+
getConfigFor(filename, configOverride) {
|
|
11524
|
+
/* special case when the overridden configuration is marked as root, should
|
|
11525
|
+
* not try to load any more configuration files */
|
|
11526
|
+
const override = this.loadFromObject(configOverride || {});
|
|
11527
|
+
if (override.isRootFound()) {
|
|
11528
|
+
override.init();
|
|
11529
|
+
return override;
|
|
11530
|
+
}
|
|
11531
|
+
/* special case when the global configuration is marked as root, should not
|
|
11532
|
+
* try to load and more configuration files */
|
|
11533
|
+
if (this.globalConfig.isRootFound()) {
|
|
11534
|
+
const merged = this.globalConfig.merge(override);
|
|
11535
|
+
merged.init();
|
|
11536
|
+
return merged;
|
|
11537
|
+
}
|
|
11538
|
+
const config = this.fromFilename(filename);
|
|
11539
|
+
const merged = config ? config.merge(override) : this.globalConfig.merge(override);
|
|
11540
|
+
merged.init();
|
|
11541
|
+
return merged;
|
|
11542
|
+
}
|
|
11543
|
+
/**
|
|
11544
|
+
* Flush configuration cache.
|
|
11545
|
+
*
|
|
11546
|
+
* @param filename - If given only the cache for that file is flushed.
|
|
11547
|
+
*/
|
|
11548
|
+
flushCache(filename) {
|
|
11549
|
+
if (filename) {
|
|
11550
|
+
this.cache.delete(filename);
|
|
11551
|
+
}
|
|
11552
|
+
else {
|
|
11553
|
+
this.cache.clear();
|
|
11554
|
+
}
|
|
11555
|
+
}
|
|
11556
|
+
/**
|
|
11557
|
+
* Load raw configuration from directory traversal.
|
|
11558
|
+
*
|
|
11559
|
+
* This configuration is not merged with global configuration and may return
|
|
11560
|
+
* `null` if no configuration files are found.
|
|
11561
|
+
*/
|
|
11562
|
+
fromFilename(filename) {
|
|
11563
|
+
var _a;
|
|
11564
|
+
if (filename === "inline") {
|
|
11565
|
+
return null;
|
|
11566
|
+
}
|
|
11567
|
+
if (this.cache.has(filename)) {
|
|
11568
|
+
return (_a = this.cache.get(filename)) !== null && _a !== void 0 ? _a : null;
|
|
11569
|
+
}
|
|
11570
|
+
let found = false;
|
|
11571
|
+
let current = path.resolve(path.dirname(filename));
|
|
11572
|
+
let config = this.empty();
|
|
11573
|
+
// eslint-disable-next-line no-constant-condition
|
|
11574
|
+
while (true) {
|
|
11575
|
+
/* search configuration files in current directory */
|
|
11576
|
+
for (const configFile of findConfigurationFiles(current)) {
|
|
11577
|
+
const local = this.loadFromFile(configFile);
|
|
11578
|
+
found = true;
|
|
11579
|
+
config = local.merge(config);
|
|
11580
|
+
}
|
|
11581
|
+
/* stop if a configuration with "root" is set to true */
|
|
11582
|
+
if (config.isRootFound()) {
|
|
11583
|
+
break;
|
|
11584
|
+
}
|
|
11585
|
+
/* get the parent directory */
|
|
11586
|
+
const child = current;
|
|
11587
|
+
current = path.dirname(current);
|
|
11588
|
+
/* stop if this is the root directory */
|
|
11589
|
+
if (current === child) {
|
|
11590
|
+
break;
|
|
11591
|
+
}
|
|
11592
|
+
}
|
|
11593
|
+
/* no config was found by loader, return null and let caller decide what to do */
|
|
11594
|
+
if (!found) {
|
|
11595
|
+
this.cache.set(filename, null);
|
|
11596
|
+
return null;
|
|
11597
|
+
}
|
|
11598
|
+
this.cache.set(filename, config);
|
|
11599
|
+
return config;
|
|
11600
|
+
}
|
|
11601
|
+
defaultConfig() {
|
|
11602
|
+
return this.configFactory.defaultConfig();
|
|
11603
|
+
}
|
|
11604
|
+
}
|
|
11605
|
+
|
|
11355
11606
|
const entities = {
|
|
11356
11607
|
">": ">",
|
|
11357
11608
|
"<": "<",
|
|
@@ -11502,7 +11753,7 @@ function formatSummary(errors, warnings) {
|
|
|
11502
11753
|
return kleur[summaryColor]().bold(`${summary.join(" and ")} found.`);
|
|
11503
11754
|
}
|
|
11504
11755
|
function codeframe(results, options) {
|
|
11505
|
-
const merged =
|
|
11756
|
+
const merged = { ...defaults, ...options };
|
|
11506
11757
|
let errors = 0;
|
|
11507
11758
|
let warnings = 0;
|
|
11508
11759
|
const resultsWithMessages = results.filter((result) => result.messages.length > 0);
|
|
@@ -11543,7 +11794,11 @@ function linkSummary(results) {
|
|
|
11543
11794
|
return `\n${kleur.bold("More information")}:\n${lines.join("")}\n`;
|
|
11544
11795
|
}
|
|
11545
11796
|
function stylish(results) {
|
|
11546
|
-
const errors = stylishImpl(results.map((it) => (
|
|
11797
|
+
const errors = stylishImpl(results.map((it) => ({
|
|
11798
|
+
...it,
|
|
11799
|
+
fixableErrorCount: 0,
|
|
11800
|
+
fixableWarningCount: 0,
|
|
11801
|
+
})));
|
|
11547
11802
|
const links = linkSummary(results);
|
|
11548
11803
|
return `${errors}${links}`;
|
|
11549
11804
|
}
|