html-validate 6.2.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core.d.ts +12 -2
- package/dist/cjs/core.js +79 -17
- package/dist/cjs/core.js.map +1 -1
- package/dist/es/core.d.ts +12 -2
- package/dist/es/core.js +79 -17
- package/dist/es/core.js.map +1 -1
- package/package.json +21 -24
- package/CHANGELOG.md +0 -1734
package/dist/es/core.d.ts
CHANGED
|
@@ -502,6 +502,8 @@ interface ConditionalEvent extends Event {
|
|
|
502
502
|
location: Location;
|
|
503
503
|
/** Condition including markers. */
|
|
504
504
|
condition: string;
|
|
505
|
+
/** The element containing the conditional, if any. */
|
|
506
|
+
parent: HtmlElement | null;
|
|
505
507
|
}
|
|
506
508
|
/**
|
|
507
509
|
* Event emitted when html-validate directives `<!-- [html-validate-...] -->`
|
|
@@ -651,10 +653,17 @@ declare class Parser {
|
|
|
651
653
|
*/
|
|
652
654
|
private getAttributeLocation;
|
|
653
655
|
protected consumeDirective(token: Token): void;
|
|
656
|
+
/**
|
|
657
|
+
* Consumes conditional comment in tag form.
|
|
658
|
+
*
|
|
659
|
+
* See also the related [[consumeCommend]] method.
|
|
660
|
+
*/
|
|
661
|
+
protected consumeConditional(token: Token): void;
|
|
654
662
|
/**
|
|
655
663
|
* Consumes comment token.
|
|
656
664
|
*
|
|
657
|
-
* Tries to find IE conditional comments and emits conditional token if
|
|
665
|
+
* Tries to find IE conditional comments and emits conditional token if
|
|
666
|
+
* found. See also the related [[consumeConditional]] method.
|
|
658
667
|
*/
|
|
659
668
|
protected consumeComment(token: Token): void;
|
|
660
669
|
/**
|
|
@@ -1575,7 +1584,8 @@ declare class MetaTable {
|
|
|
1575
1584
|
*/
|
|
1576
1585
|
loadFromFile(filename: string): void;
|
|
1577
1586
|
/**
|
|
1578
|
-
* Get [[MetaElement]] for the given tag
|
|
1587
|
+
* Get [[MetaElement]] for the given tag. If no specific metadata is present
|
|
1588
|
+
* the global metadata is returned or null if no global is present.
|
|
1579
1589
|
*
|
|
1580
1590
|
* @public
|
|
1581
1591
|
* @returns A shallow copy of metadata.
|
package/dist/es/core.js
CHANGED
|
@@ -933,14 +933,23 @@ class MetaTable {
|
|
|
933
933
|
}
|
|
934
934
|
}
|
|
935
935
|
/**
|
|
936
|
-
* Get [[MetaElement]] for the given tag
|
|
936
|
+
* Get [[MetaElement]] for the given tag. If no specific metadata is present
|
|
937
|
+
* the global metadata is returned or null if no global is present.
|
|
937
938
|
*
|
|
938
939
|
* @public
|
|
939
940
|
* @returns A shallow copy of metadata.
|
|
940
941
|
*/
|
|
941
942
|
getMetaFor(tagName) {
|
|
943
|
+
/* try to locate by tagname */
|
|
942
944
|
tagName = tagName.toLowerCase();
|
|
943
|
-
|
|
945
|
+
if (this.elements[tagName]) {
|
|
946
|
+
return { ...this.elements[tagName] };
|
|
947
|
+
}
|
|
948
|
+
/* try to locate global element */
|
|
949
|
+
if (this.elements["*"]) {
|
|
950
|
+
return { ...this.elements["*"] };
|
|
951
|
+
}
|
|
952
|
+
return null;
|
|
944
953
|
}
|
|
945
954
|
/**
|
|
946
955
|
* Find all tags which has enabled given property.
|
|
@@ -2936,7 +2945,7 @@ var TRANSFORMER_API;
|
|
|
2936
2945
|
/** @public */
|
|
2937
2946
|
const name = "html-validate";
|
|
2938
2947
|
/** @public */
|
|
2939
|
-
const version = "6.
|
|
2948
|
+
const version = "6.4.0";
|
|
2940
2949
|
/** @public */
|
|
2941
2950
|
const homepage = "https://html-validate.org";
|
|
2942
2951
|
/** @public */
|
|
@@ -3216,7 +3225,8 @@ function ruleDocumentationUrl(filename) {
|
|
|
3216
3225
|
const p = path.parse(filename);
|
|
3217
3226
|
const root = path.join(distFolder, "rules");
|
|
3218
3227
|
const rel = path.relative(root, path.join(p.dir, p.name));
|
|
3219
|
-
|
|
3228
|
+
const normalized = rel.replace(/\\/g, "/");
|
|
3229
|
+
return `${homepage}/rules/${normalized}.html`;
|
|
3220
3230
|
}
|
|
3221
3231
|
|
|
3222
3232
|
const defaults$p = {
|
|
@@ -3406,6 +3416,28 @@ class AllowedLinks extends Rule {
|
|
|
3406
3416
|
}
|
|
3407
3417
|
}
|
|
3408
3418
|
|
|
3419
|
+
class AriaHiddenBody extends Rule {
|
|
3420
|
+
documentation() {
|
|
3421
|
+
return {
|
|
3422
|
+
description: "`aria-hidden` must not be used on the `<body>` element as it makes the page inaccessible to assistive technology such as screenreaders",
|
|
3423
|
+
url: ruleDocumentationUrl("@/rules/aria-hidden-body.ts"),
|
|
3424
|
+
};
|
|
3425
|
+
}
|
|
3426
|
+
setup() {
|
|
3427
|
+
this.on("tag:ready", this.isRelevant, (event) => {
|
|
3428
|
+
const { target } = event;
|
|
3429
|
+
const attr = target.getAttribute("aria-hidden");
|
|
3430
|
+
if (!attr || !attr.valueMatches("true", true)) {
|
|
3431
|
+
return;
|
|
3432
|
+
}
|
|
3433
|
+
this.report(target, "aria-hidden must not be used on <body>", attr.keyLocation);
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
isRelevant(event) {
|
|
3437
|
+
return event.target.is("body");
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3409
3441
|
const whitelisted = [
|
|
3410
3442
|
"main",
|
|
3411
3443
|
"nav",
|
|
@@ -5033,8 +5065,9 @@ class ElementRequiredAttributes extends Rule {
|
|
|
5033
5065
|
class ElementRequiredContent extends Rule {
|
|
5034
5066
|
documentation(context) {
|
|
5035
5067
|
if (context) {
|
|
5068
|
+
const { element, missing } = context;
|
|
5036
5069
|
return {
|
|
5037
|
-
description: `The
|
|
5070
|
+
description: `The \`${element}\` element requires a \`${missing}\` to be present as content.`,
|
|
5038
5071
|
url: ruleDocumentationUrl("@/rules/element-required-content.ts"),
|
|
5039
5072
|
};
|
|
5040
5073
|
}
|
|
@@ -5060,10 +5093,11 @@ class ElementRequiredContent extends Rule {
|
|
|
5060
5093
|
}
|
|
5061
5094
|
for (const missing of Validator.validateRequiredContent(node, rules)) {
|
|
5062
5095
|
const context = {
|
|
5063
|
-
|
|
5064
|
-
missing
|
|
5096
|
+
element: node.annotatedName,
|
|
5097
|
+
missing: `<${missing}>`,
|
|
5065
5098
|
};
|
|
5066
|
-
|
|
5099
|
+
const message = `${node.annotatedName} element must have <${missing}> as content`;
|
|
5100
|
+
this.report(node, message, null, context);
|
|
5067
5101
|
}
|
|
5068
5102
|
});
|
|
5069
5103
|
});
|
|
@@ -5146,7 +5180,14 @@ class EmptyHeading extends Rule {
|
|
|
5146
5180
|
class EmptyTitle extends Rule {
|
|
5147
5181
|
documentation() {
|
|
5148
5182
|
return {
|
|
5149
|
-
description:
|
|
5183
|
+
description: [
|
|
5184
|
+
"The `<title>` element cannot be empty, it must have textual content.",
|
|
5185
|
+
"",
|
|
5186
|
+
"It is used to describe the document and is shown in the browser tab and titlebar.",
|
|
5187
|
+
"WCAG and SEO requires a descriptive title and preferably unique within the site.",
|
|
5188
|
+
"",
|
|
5189
|
+
"Whitespace is ignored.",
|
|
5190
|
+
].join("\n"),
|
|
5150
5191
|
url: ruleDocumentationUrl("@/rules/empty-title.ts"),
|
|
5151
5192
|
};
|
|
5152
5193
|
}
|
|
@@ -5162,7 +5203,10 @@ class EmptyTitle extends Rule {
|
|
|
5162
5203
|
break;
|
|
5163
5204
|
case TextClassification.EMPTY_TEXT:
|
|
5164
5205
|
/* no content or whitespace only */
|
|
5165
|
-
|
|
5206
|
+
{
|
|
5207
|
+
const message = `<${node.tagName}> cannot be empty, must have text content`;
|
|
5208
|
+
this.report(node, message, node.location);
|
|
5209
|
+
}
|
|
5166
5210
|
break;
|
|
5167
5211
|
}
|
|
5168
5212
|
});
|
|
@@ -5943,7 +5987,7 @@ class NoConditionalComment extends Rule {
|
|
|
5943
5987
|
}
|
|
5944
5988
|
setup() {
|
|
5945
5989
|
this.on("conditional", (event) => {
|
|
5946
|
-
this.report(
|
|
5990
|
+
this.report(event.parent, "Use of conditional comments are deprecated", event.location);
|
|
5947
5991
|
});
|
|
5948
5992
|
}
|
|
5949
5993
|
}
|
|
@@ -9440,6 +9484,7 @@ const bundledRules$1 = {
|
|
|
9440
9484
|
|
|
9441
9485
|
const bundledRules = {
|
|
9442
9486
|
"allowed-links": AllowedLinks,
|
|
9487
|
+
"aria-hidden-body": AriaHiddenBody,
|
|
9443
9488
|
"aria-label-misuse": AriaLabelMisuse,
|
|
9444
9489
|
"attr-case": AttrCase,
|
|
9445
9490
|
"attr-delimiter": AttrDelimiter,
|
|
@@ -9510,6 +9555,7 @@ var defaultConfig = {};
|
|
|
9510
9555
|
|
|
9511
9556
|
const config$3 = {
|
|
9512
9557
|
rules: {
|
|
9558
|
+
"aria-hidden-body": "error",
|
|
9513
9559
|
"aria-label-misuse": "error",
|
|
9514
9560
|
"deprecated-rule": "warn",
|
|
9515
9561
|
"empty-heading": "error",
|
|
@@ -9544,6 +9590,7 @@ const config$2 = {
|
|
|
9544
9590
|
|
|
9545
9591
|
const config$1 = {
|
|
9546
9592
|
rules: {
|
|
9593
|
+
"aria-hidden-body": "error",
|
|
9547
9594
|
"aria-label-misuse": "error",
|
|
9548
9595
|
"attr-case": "error",
|
|
9549
9596
|
"attr-delimiter": "error",
|
|
@@ -9713,7 +9760,9 @@ class ResolvedConfig {
|
|
|
9713
9760
|
* @returns A list of transformed sources ready for validation.
|
|
9714
9761
|
*/
|
|
9715
9762
|
transformFilename(filename) {
|
|
9716
|
-
const
|
|
9763
|
+
const stdin = 0;
|
|
9764
|
+
const src = filename !== "/dev/stdin" ? filename : stdin;
|
|
9765
|
+
const data = fs.readFileSync(src, { encoding: "utf8" });
|
|
9717
9766
|
const source = {
|
|
9718
9767
|
data,
|
|
9719
9768
|
filename,
|
|
@@ -10435,10 +10484,7 @@ class Parser {
|
|
|
10435
10484
|
this.consumeDirective(token);
|
|
10436
10485
|
break;
|
|
10437
10486
|
case TokenType.CONDITIONAL:
|
|
10438
|
-
this.
|
|
10439
|
-
condition: token.data[1],
|
|
10440
|
-
location: token.location,
|
|
10441
|
-
});
|
|
10487
|
+
this.consumeConditional(token);
|
|
10442
10488
|
break;
|
|
10443
10489
|
case TokenType.COMMENT:
|
|
10444
10490
|
this.consumeComment(token);
|
|
@@ -10743,17 +10789,33 @@ class Parser {
|
|
|
10743
10789
|
location: token.location,
|
|
10744
10790
|
});
|
|
10745
10791
|
}
|
|
10792
|
+
/**
|
|
10793
|
+
* Consumes conditional comment in tag form.
|
|
10794
|
+
*
|
|
10795
|
+
* See also the related [[consumeCommend]] method.
|
|
10796
|
+
*/
|
|
10797
|
+
consumeConditional(token) {
|
|
10798
|
+
const element = this.dom.getActive();
|
|
10799
|
+
this.trigger("conditional", {
|
|
10800
|
+
condition: token.data[1],
|
|
10801
|
+
location: token.location,
|
|
10802
|
+
parent: element,
|
|
10803
|
+
});
|
|
10804
|
+
}
|
|
10746
10805
|
/**
|
|
10747
10806
|
* Consumes comment token.
|
|
10748
10807
|
*
|
|
10749
|
-
* Tries to find IE conditional comments and emits conditional token if
|
|
10808
|
+
* Tries to find IE conditional comments and emits conditional token if
|
|
10809
|
+
* found. See also the related [[consumeConditional]] method.
|
|
10750
10810
|
*/
|
|
10751
10811
|
consumeComment(token) {
|
|
10752
10812
|
const comment = token.data[0];
|
|
10813
|
+
const element = this.dom.getActive();
|
|
10753
10814
|
for (const conditional of parseConditionalComment(comment, token.location)) {
|
|
10754
10815
|
this.trigger("conditional", {
|
|
10755
10816
|
condition: conditional.expression,
|
|
10756
10817
|
location: conditional.location,
|
|
10818
|
+
parent: element,
|
|
10757
10819
|
});
|
|
10758
10820
|
}
|
|
10759
10821
|
}
|