html-validate 7.10.0 → 7.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.d.ts +1 -1
- package/dist/cjs/browser.js +2 -1
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/cli.js +0 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core.d.ts +1 -4
- package/dist/cjs/core.js +149 -106
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +6 -2
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/html-validate.js +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/jest-lib.js +0 -1
- package/dist/cjs/jest-lib.js.map +1 -1
- package/dist/cjs/jest.d.ts +1 -0
- package/dist/cjs/jest.js +2 -2
- package/dist/cjs/meta-helper.d.ts +1 -0
- package/dist/cjs/rules-helper.d.ts +10 -1
- package/dist/cjs/rules-helper.js +54 -1
- package/dist/cjs/rules-helper.js.map +1 -1
- package/dist/cjs/test-utils.d.ts +1 -0
- package/dist/es/browser.d.ts +1 -1
- package/dist/es/browser.js +2 -2
- package/dist/es/cli.js +0 -1
- package/dist/es/cli.js.map +1 -1
- package/dist/es/core.d.ts +1 -4
- package/dist/es/core.js +150 -107
- package/dist/es/core.js.map +1 -1
- package/dist/es/elements.js +6 -2
- package/dist/es/elements.js.map +1 -1
- package/dist/es/html-validate.js +2 -2
- package/dist/es/index.d.ts +1 -1
- package/dist/es/index.js +2 -2
- package/dist/es/jest-lib.js +0 -1
- package/dist/es/jest-lib.js.map +1 -1
- package/dist/es/jest.d.ts +1 -0
- package/dist/es/jest.js +2 -2
- package/dist/es/meta-helper.d.ts +1 -0
- package/dist/es/rules-helper.d.ts +10 -1
- package/dist/es/rules-helper.js +53 -2
- package/dist/es/rules-helper.js.map +1 -1
- package/dist/es/test-utils.d.ts +1 -0
- package/package.json +19 -19
package/dist/cjs/core.js
CHANGED
|
@@ -7,10 +7,10 @@ var Ajv = require('ajv');
|
|
|
7
7
|
var deepmerge = require('deepmerge');
|
|
8
8
|
var espree = require('espree');
|
|
9
9
|
var walk = require('acorn-walk');
|
|
10
|
-
var elements = require('./elements.js');
|
|
11
10
|
var path = require('path');
|
|
12
11
|
var semver = require('semver');
|
|
13
12
|
var kleur = require('kleur');
|
|
13
|
+
var elements = require('./elements.js');
|
|
14
14
|
var codeFrame = require('@babel/code-frame');
|
|
15
15
|
var stylishImpl = require('@html-validate/stylish');
|
|
16
16
|
|
|
@@ -2646,29 +2646,40 @@ class Validator {
|
|
|
2646
2646
|
*
|
|
2647
2647
|
* For instance, a `<table>` element can only contain a single `<tbody>`
|
|
2648
2648
|
* child. If multiple `<tbody>` exists this test will fail both nodes.
|
|
2649
|
+
* Note that this is called on the parent but will fail the children violating
|
|
2650
|
+
* the rule.
|
|
2649
2651
|
*
|
|
2650
|
-
* @param
|
|
2651
|
-
* @param rules - List of rules.
|
|
2652
|
-
* @
|
|
2653
|
-
* exists (including the element itself)
|
|
2654
|
-
* @returns `true` if the element passes the test.
|
|
2652
|
+
* @param children - Array of children to validate.
|
|
2653
|
+
* @param rules - List of rules of the parent element.
|
|
2654
|
+
* @returns `true` if the parent element of the children passes the test.
|
|
2655
2655
|
*/
|
|
2656
|
-
static validateOccurrences(
|
|
2656
|
+
static validateOccurrences(children, rules, cb) {
|
|
2657
2657
|
if (!rules) {
|
|
2658
2658
|
return true;
|
|
2659
2659
|
}
|
|
2660
|
-
|
|
2660
|
+
let valid = true;
|
|
2661
|
+
for (const rule of rules) {
|
|
2661
2662
|
/** @todo handle complex rules and not just plain arrays (but as of now
|
|
2662
2663
|
* there is no use-case for it) */
|
|
2663
2664
|
// istanbul ignore next
|
|
2664
|
-
if (typeof
|
|
2665
|
+
if (typeof rule !== "string") {
|
|
2665
2666
|
return false;
|
|
2666
2667
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2668
|
+
// Check if the rule has a quantifier
|
|
2669
|
+
const [, category, quantifier] = rule.match(/^(@?.*?)([?*]?)$/);
|
|
2670
|
+
const limit = category && quantifier && parseQuantifier(quantifier);
|
|
2671
|
+
if (limit) {
|
|
2672
|
+
const siblings = children.filter((cur) => Validator.validatePermittedCategory(cur, rule, true));
|
|
2673
|
+
if (siblings.length > limit) {
|
|
2674
|
+
// fail only the children above the limit (currently limit can only be 1)
|
|
2675
|
+
for (const child of siblings.slice(limit)) {
|
|
2676
|
+
cb(child, category);
|
|
2677
|
+
}
|
|
2678
|
+
valid = false;
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
return valid;
|
|
2672
2683
|
}
|
|
2673
2684
|
/**
|
|
2674
2685
|
* Validate elements order.
|
|
@@ -2730,14 +2741,15 @@ class Validator {
|
|
|
2730
2741
|
* Check if an element has the required set of elements. At least one of the
|
|
2731
2742
|
* selectors must match.
|
|
2732
2743
|
*
|
|
2733
|
-
* Returns [] when valid or a list of
|
|
2744
|
+
* Returns `[]` when valid or a list of required but missing tagnames or
|
|
2745
|
+
* categories.
|
|
2734
2746
|
*/
|
|
2735
2747
|
static validateRequiredContent(node, rules) {
|
|
2736
2748
|
if (!rules || rules.length === 0) {
|
|
2737
2749
|
return [];
|
|
2738
2750
|
}
|
|
2739
2751
|
return rules.filter((tagName) => {
|
|
2740
|
-
const haveMatchingChild = node.childElements.some((child) =>
|
|
2752
|
+
const haveMatchingChild = node.childElements.some((child) => Validator.validatePermittedCategory(child, tagName, false));
|
|
2741
2753
|
return !haveMatchingChild;
|
|
2742
2754
|
});
|
|
2743
2755
|
}
|
|
@@ -2841,16 +2853,16 @@ class Validator {
|
|
|
2841
2853
|
*/
|
|
2842
2854
|
// eslint-disable-next-line complexity
|
|
2843
2855
|
static validatePermittedCategory(node, category, defaultMatch) {
|
|
2856
|
+
const [, rawCategory] = category.match(/^(@?.*?)([?*]?)$/);
|
|
2844
2857
|
/* match tagName when an explicit name is given */
|
|
2845
|
-
if (
|
|
2846
|
-
|
|
2847
|
-
return node.tagName === tagName;
|
|
2858
|
+
if (rawCategory[0] !== "@") {
|
|
2859
|
+
return node.tagName === rawCategory;
|
|
2848
2860
|
}
|
|
2849
2861
|
/* if the meta entry is missing assume any content model would match */
|
|
2850
2862
|
if (!node.meta) {
|
|
2851
2863
|
return defaultMatch;
|
|
2852
2864
|
}
|
|
2853
|
-
switch (
|
|
2865
|
+
switch (rawCategory) {
|
|
2854
2866
|
case "@meta":
|
|
2855
2867
|
return node.meta.metadata;
|
|
2856
2868
|
case "@flow":
|
|
@@ -2882,23 +2894,15 @@ function validateKeys(rule) {
|
|
|
2882
2894
|
}
|
|
2883
2895
|
}
|
|
2884
2896
|
}
|
|
2885
|
-
function
|
|
2886
|
-
|
|
2887
|
-
/* content not allowed, catched by another rule so just assume unlimited
|
|
2888
|
-
* usage for this purpose */
|
|
2889
|
-
return null;
|
|
2890
|
-
}
|
|
2891
|
-
const [, qualifier] = category.match(/^.*?([?*]?)$/);
|
|
2892
|
-
switch (qualifier) {
|
|
2897
|
+
function parseQuantifier(quantifier) {
|
|
2898
|
+
switch (quantifier) {
|
|
2893
2899
|
case "?":
|
|
2894
2900
|
return 1;
|
|
2895
|
-
case "":
|
|
2896
|
-
return null;
|
|
2897
2901
|
case "*":
|
|
2898
2902
|
return null;
|
|
2899
|
-
|
|
2903
|
+
// istanbul ignore next
|
|
2900
2904
|
default:
|
|
2901
|
-
throw new Error(`Invalid
|
|
2905
|
+
throw new Error(`Invalid quantifier "${quantifier}" used`);
|
|
2902
2906
|
}
|
|
2903
2907
|
}
|
|
2904
2908
|
|
|
@@ -3430,16 +3434,7 @@ class Rule {
|
|
|
3430
3434
|
* `exclude`.
|
|
3431
3435
|
*/
|
|
3432
3436
|
isKeywordIgnored(keyword, matcher = (list, it) => list.includes(it)) {
|
|
3433
|
-
|
|
3434
|
-
/* ignore keyword if not present in "include" */
|
|
3435
|
-
if (include && !matcher(include, keyword)) {
|
|
3436
|
-
return true;
|
|
3437
|
-
}
|
|
3438
|
-
/* ignore keyword if present in "excludes" */
|
|
3439
|
-
if (exclude && matcher(exclude, keyword)) {
|
|
3440
|
-
return true;
|
|
3441
|
-
}
|
|
3442
|
-
return false;
|
|
3437
|
+
return rulesHelper.isKeywordIgnored(this.options, keyword, matcher);
|
|
3443
3438
|
}
|
|
3444
3439
|
/**
|
|
3445
3440
|
* Find all tags which has enabled given property.
|
|
@@ -3565,7 +3560,7 @@ class Rule {
|
|
|
3565
3560
|
}
|
|
3566
3561
|
}
|
|
3567
3562
|
|
|
3568
|
-
const defaults$
|
|
3563
|
+
const defaults$v = {
|
|
3569
3564
|
allowExternal: true,
|
|
3570
3565
|
allowRelative: true,
|
|
3571
3566
|
allowAbsolute: true,
|
|
@@ -3609,7 +3604,7 @@ function matchList(value, list) {
|
|
|
3609
3604
|
}
|
|
3610
3605
|
class AllowedLinks extends Rule {
|
|
3611
3606
|
constructor(options) {
|
|
3612
|
-
super({ ...defaults$
|
|
3607
|
+
super({ ...defaults$v, ...options });
|
|
3613
3608
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
3614
3609
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
3615
3610
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -3757,7 +3752,7 @@ var RuleContext$1;
|
|
|
3757
3752
|
RuleContext["MISSING_ALT"] = "missing-alt";
|
|
3758
3753
|
RuleContext["MISSING_HREF"] = "missing-href";
|
|
3759
3754
|
})(RuleContext$1 || (RuleContext$1 = {}));
|
|
3760
|
-
const defaults$
|
|
3755
|
+
const defaults$u = {
|
|
3761
3756
|
accessible: true,
|
|
3762
3757
|
};
|
|
3763
3758
|
function findByTarget(target, siblings) {
|
|
@@ -3795,7 +3790,7 @@ function getDescription$1(context) {
|
|
|
3795
3790
|
}
|
|
3796
3791
|
class AreaAlt extends Rule {
|
|
3797
3792
|
constructor(options) {
|
|
3798
|
-
super({ ...defaults$
|
|
3793
|
+
super({ ...defaults$u, ...options });
|
|
3799
3794
|
}
|
|
3800
3795
|
static schema() {
|
|
3801
3796
|
return {
|
|
@@ -3959,13 +3954,13 @@ class AriaLabelMisuse extends Rule {
|
|
|
3959
3954
|
class ConfigError extends UserError {
|
|
3960
3955
|
}
|
|
3961
3956
|
|
|
3962
|
-
const defaults$
|
|
3957
|
+
const defaults$t = {
|
|
3963
3958
|
style: "lowercase",
|
|
3964
3959
|
ignoreForeign: true,
|
|
3965
3960
|
};
|
|
3966
3961
|
class AttrCase extends Rule {
|
|
3967
3962
|
constructor(options) {
|
|
3968
|
-
super({ ...defaults$
|
|
3963
|
+
super({ ...defaults$t, ...options });
|
|
3969
3964
|
this.style = new rulesHelper.CaseStyle(this.options.style, "attr-case");
|
|
3970
3965
|
}
|
|
3971
3966
|
static schema() {
|
|
@@ -4310,7 +4305,7 @@ class AttrDelimiter extends Rule {
|
|
|
4310
4305
|
}
|
|
4311
4306
|
|
|
4312
4307
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4313
|
-
const defaults$
|
|
4308
|
+
const defaults$s = {
|
|
4314
4309
|
pattern: DEFAULT_PATTERN,
|
|
4315
4310
|
ignoreForeign: true,
|
|
4316
4311
|
};
|
|
@@ -4347,7 +4342,7 @@ function generateDescription(name, pattern) {
|
|
|
4347
4342
|
}
|
|
4348
4343
|
class AttrPattern extends Rule {
|
|
4349
4344
|
constructor(options) {
|
|
4350
|
-
super({ ...defaults$
|
|
4345
|
+
super({ ...defaults$s, ...options });
|
|
4351
4346
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4352
4347
|
}
|
|
4353
4348
|
static schema() {
|
|
@@ -4408,7 +4403,7 @@ var QuoteStyle;
|
|
|
4408
4403
|
QuoteStyle["AUTO_QUOTE"] = "auto";
|
|
4409
4404
|
QuoteStyle["ANY_QUOTE"] = "any";
|
|
4410
4405
|
})(QuoteStyle || (QuoteStyle = {}));
|
|
4411
|
-
const defaults$
|
|
4406
|
+
const defaults$r = {
|
|
4412
4407
|
style: "auto",
|
|
4413
4408
|
unquoted: false,
|
|
4414
4409
|
};
|
|
@@ -4475,7 +4470,7 @@ class AttrQuotes extends Rule {
|
|
|
4475
4470
|
};
|
|
4476
4471
|
}
|
|
4477
4472
|
constructor(options) {
|
|
4478
|
-
super({ ...defaults$
|
|
4473
|
+
super({ ...defaults$r, ...options });
|
|
4479
4474
|
this.style = parseStyle$4(this.options.style);
|
|
4480
4475
|
}
|
|
4481
4476
|
setup() {
|
|
@@ -4645,12 +4640,12 @@ class AttributeAllowedValues extends Rule {
|
|
|
4645
4640
|
}
|
|
4646
4641
|
}
|
|
4647
4642
|
|
|
4648
|
-
const defaults$
|
|
4643
|
+
const defaults$q = {
|
|
4649
4644
|
style: "omit",
|
|
4650
4645
|
};
|
|
4651
4646
|
class AttributeBooleanStyle extends Rule {
|
|
4652
4647
|
constructor(options) {
|
|
4653
|
-
super({ ...defaults$
|
|
4648
|
+
super({ ...defaults$q, ...options });
|
|
4654
4649
|
this.hasInvalidStyle = parseStyle$3(this.options.style);
|
|
4655
4650
|
}
|
|
4656
4651
|
static schema() {
|
|
@@ -4726,12 +4721,12 @@ function reportMessage$1(attr, style) {
|
|
|
4726
4721
|
return "";
|
|
4727
4722
|
}
|
|
4728
4723
|
|
|
4729
|
-
const defaults$
|
|
4724
|
+
const defaults$p = {
|
|
4730
4725
|
style: "omit",
|
|
4731
4726
|
};
|
|
4732
4727
|
class AttributeEmptyStyle extends Rule {
|
|
4733
4728
|
constructor(options) {
|
|
4734
|
-
super({ ...defaults$
|
|
4729
|
+
super({ ...defaults$p, ...options });
|
|
4735
4730
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
4736
4731
|
}
|
|
4737
4732
|
static schema() {
|
|
@@ -4887,12 +4882,12 @@ function describePattern(pattern) {
|
|
|
4887
4882
|
}
|
|
4888
4883
|
}
|
|
4889
4884
|
|
|
4890
|
-
const defaults$
|
|
4885
|
+
const defaults$o = {
|
|
4891
4886
|
pattern: "kebabcase",
|
|
4892
4887
|
};
|
|
4893
4888
|
class ClassPattern extends Rule {
|
|
4894
4889
|
constructor(options) {
|
|
4895
|
-
super({ ...defaults$
|
|
4890
|
+
super({ ...defaults$o, ...options });
|
|
4896
4891
|
this.pattern = parsePattern(this.options.pattern);
|
|
4897
4892
|
}
|
|
4898
4893
|
static schema() {
|
|
@@ -5001,13 +4996,13 @@ class CloseOrder extends Rule {
|
|
|
5001
4996
|
}
|
|
5002
4997
|
}
|
|
5003
4998
|
|
|
5004
|
-
const defaults$
|
|
4999
|
+
const defaults$n = {
|
|
5005
5000
|
include: null,
|
|
5006
5001
|
exclude: null,
|
|
5007
5002
|
};
|
|
5008
5003
|
class Deprecated extends Rule {
|
|
5009
5004
|
constructor(options) {
|
|
5010
|
-
super({ ...defaults$
|
|
5005
|
+
super({ ...defaults$n, ...options });
|
|
5011
5006
|
}
|
|
5012
5007
|
static schema() {
|
|
5013
5008
|
return {
|
|
@@ -5170,12 +5165,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5170
5165
|
}
|
|
5171
5166
|
};
|
|
5172
5167
|
|
|
5173
|
-
const defaults$
|
|
5168
|
+
const defaults$m = {
|
|
5174
5169
|
style: "uppercase",
|
|
5175
5170
|
};
|
|
5176
5171
|
class DoctypeStyle extends Rule {
|
|
5177
5172
|
constructor(options) {
|
|
5178
|
-
super({ ...defaults$
|
|
5173
|
+
super({ ...defaults$m, ...options });
|
|
5179
5174
|
}
|
|
5180
5175
|
static schema() {
|
|
5181
5176
|
return {
|
|
@@ -5207,12 +5202,12 @@ class DoctypeStyle extends Rule {
|
|
|
5207
5202
|
}
|
|
5208
5203
|
}
|
|
5209
5204
|
|
|
5210
|
-
const defaults$
|
|
5205
|
+
const defaults$l = {
|
|
5211
5206
|
style: "lowercase",
|
|
5212
5207
|
};
|
|
5213
5208
|
class ElementCase extends Rule {
|
|
5214
5209
|
constructor(options) {
|
|
5215
|
-
super({ ...defaults$
|
|
5210
|
+
super({ ...defaults$l, ...options });
|
|
5216
5211
|
this.style = new rulesHelper.CaseStyle(this.options.style, "element-case");
|
|
5217
5212
|
}
|
|
5218
5213
|
static schema() {
|
|
@@ -5278,14 +5273,14 @@ class ElementCase extends Rule {
|
|
|
5278
5273
|
}
|
|
5279
5274
|
}
|
|
5280
5275
|
|
|
5281
|
-
const defaults$
|
|
5276
|
+
const defaults$k = {
|
|
5282
5277
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5283
5278
|
whitelist: [],
|
|
5284
5279
|
blacklist: [],
|
|
5285
5280
|
};
|
|
5286
5281
|
class ElementName extends Rule {
|
|
5287
5282
|
constructor(options) {
|
|
5288
|
-
super({ ...defaults$
|
|
5283
|
+
super({ ...defaults$k, ...options });
|
|
5289
5284
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
5290
5285
|
this.pattern = new RegExp(this.options.pattern);
|
|
5291
5286
|
}
|
|
@@ -5326,7 +5321,7 @@ class ElementName extends Rule {
|
|
|
5326
5321
|
...context.blacklist.map((cur) => `- ${cur}`),
|
|
5327
5322
|
];
|
|
5328
5323
|
}
|
|
5329
|
-
if (context.pattern !== defaults$
|
|
5324
|
+
if (context.pattern !== defaults$k.pattern) {
|
|
5330
5325
|
return [
|
|
5331
5326
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
5332
5327
|
"",
|
|
@@ -5517,24 +5512,16 @@ class ElementPermittedOccurrences extends Rule {
|
|
|
5517
5512
|
this.on("dom:ready", (event) => {
|
|
5518
5513
|
const doc = event.document;
|
|
5519
5514
|
doc.visitDepthFirst((node) => {
|
|
5520
|
-
|
|
5521
|
-
if (!parent || !parent.meta) {
|
|
5515
|
+
if (!node || !node.meta) {
|
|
5522
5516
|
return;
|
|
5523
5517
|
}
|
|
5524
|
-
const rules =
|
|
5518
|
+
const rules = node.meta.permittedContent;
|
|
5525
5519
|
if (!rules) {
|
|
5526
5520
|
return;
|
|
5527
5521
|
}
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
* subsequent occurrences should. */
|
|
5532
|
-
if (first) {
|
|
5533
|
-
return;
|
|
5534
|
-
}
|
|
5535
|
-
if (parent.meta && !Validator.validateOccurrences(node, rules, siblings.length)) {
|
|
5536
|
-
this.report(node, `Element <${node.tagName}> can only appear once under ${parent.annotatedName}`);
|
|
5537
|
-
}
|
|
5522
|
+
Validator.validateOccurrences(node.childElements, rules, (child, category) => {
|
|
5523
|
+
this.report(child, `Element <${category}> can only appear once under ${node.annotatedName}`);
|
|
5524
|
+
});
|
|
5538
5525
|
});
|
|
5539
5526
|
});
|
|
5540
5527
|
}
|
|
@@ -5569,11 +5556,11 @@ class ElementPermittedOrder extends Rule {
|
|
|
5569
5556
|
function isCategoryOrTag(value) {
|
|
5570
5557
|
return typeof value === "string";
|
|
5571
5558
|
}
|
|
5572
|
-
function isCategory(value) {
|
|
5559
|
+
function isCategory$1(value) {
|
|
5573
5560
|
return value[0] === "@";
|
|
5574
5561
|
}
|
|
5575
5562
|
function formatCategoryOrTag(value) {
|
|
5576
|
-
return isCategory(value) ? value.slice(1) : `<${value}>`;
|
|
5563
|
+
return isCategory$1(value) ? value.slice(1) : `<${value}>`;
|
|
5577
5564
|
}
|
|
5578
5565
|
function isFormattable(rules) {
|
|
5579
5566
|
return rules.length > 0 && rules.every(isCategoryOrTag);
|
|
@@ -5586,7 +5573,7 @@ function getRuleDescription$1(context) {
|
|
|
5586
5573
|
const preamble = `The \`${child}\` element cannot have a \`${parent}\` element as parent.`;
|
|
5587
5574
|
if (isFormattable(rules)) {
|
|
5588
5575
|
const allowed = rules.filter(isCategoryOrTag).map((it) => {
|
|
5589
|
-
if (isCategory(it)) {
|
|
5576
|
+
if (isCategory$1(it)) {
|
|
5590
5577
|
return `- any ${it.slice(1)} element`;
|
|
5591
5578
|
}
|
|
5592
5579
|
else {
|
|
@@ -5749,6 +5736,9 @@ class ElementRequiredAttributes extends Rule {
|
|
|
5749
5736
|
}
|
|
5750
5737
|
}
|
|
5751
5738
|
|
|
5739
|
+
function isCategory(value) {
|
|
5740
|
+
return value[0] === "@";
|
|
5741
|
+
}
|
|
5752
5742
|
class ElementRequiredContent extends Rule {
|
|
5753
5743
|
documentation(context) {
|
|
5754
5744
|
if (context) {
|
|
@@ -5783,7 +5773,8 @@ class ElementRequiredContent extends Rule {
|
|
|
5783
5773
|
element: node.annotatedName,
|
|
5784
5774
|
missing: `<${missing}>`,
|
|
5785
5775
|
};
|
|
5786
|
-
const
|
|
5776
|
+
const tag = isCategory(missing) ? `${missing.slice(1)} element` : `<${missing}>`;
|
|
5777
|
+
const message = `${node.annotatedName} element must have ${tag} as content`;
|
|
5787
5778
|
this.report(node, message, null, context);
|
|
5788
5779
|
}
|
|
5789
5780
|
});
|
|
@@ -5874,7 +5865,7 @@ class EmptyTitle extends Rule {
|
|
|
5874
5865
|
}
|
|
5875
5866
|
}
|
|
5876
5867
|
|
|
5877
|
-
const defaults$
|
|
5868
|
+
const defaults$j = {
|
|
5878
5869
|
allowMultipleH1: false,
|
|
5879
5870
|
minInitialRank: "h1",
|
|
5880
5871
|
sectioningRoots: ["dialog", '[role="dialog"]'],
|
|
@@ -5905,7 +5896,7 @@ function parseMaxInitial(value) {
|
|
|
5905
5896
|
}
|
|
5906
5897
|
class HeadingLevel extends Rule {
|
|
5907
5898
|
constructor(options) {
|
|
5908
|
-
super({ ...defaults$
|
|
5899
|
+
super({ ...defaults$j, ...options });
|
|
5909
5900
|
this.stack = [];
|
|
5910
5901
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
5911
5902
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
|
|
@@ -6063,12 +6054,12 @@ class HeadingLevel extends Rule {
|
|
|
6063
6054
|
}
|
|
6064
6055
|
}
|
|
6065
6056
|
|
|
6066
|
-
const defaults$
|
|
6057
|
+
const defaults$i = {
|
|
6067
6058
|
pattern: "kebabcase",
|
|
6068
6059
|
};
|
|
6069
6060
|
class IdPattern extends Rule {
|
|
6070
6061
|
constructor(options) {
|
|
6071
|
-
super({ ...defaults$
|
|
6062
|
+
super({ ...defaults$i, ...options });
|
|
6072
6063
|
this.pattern = parsePattern(this.options.pattern);
|
|
6073
6064
|
}
|
|
6074
6065
|
static schema() {
|
|
@@ -6350,12 +6341,12 @@ function findLabelByParent(el) {
|
|
|
6350
6341
|
return [];
|
|
6351
6342
|
}
|
|
6352
6343
|
|
|
6353
|
-
const defaults$
|
|
6344
|
+
const defaults$h = {
|
|
6354
6345
|
maxlength: 70,
|
|
6355
6346
|
};
|
|
6356
6347
|
class LongTitle extends Rule {
|
|
6357
6348
|
constructor(options) {
|
|
6358
|
-
super({ ...defaults$
|
|
6349
|
+
super({ ...defaults$h, ...options });
|
|
6359
6350
|
this.maxlength = this.options.maxlength;
|
|
6360
6351
|
}
|
|
6361
6352
|
static schema() {
|
|
@@ -6545,13 +6536,13 @@ class MultipleLabeledControls extends Rule {
|
|
|
6545
6536
|
}
|
|
6546
6537
|
}
|
|
6547
6538
|
|
|
6548
|
-
const defaults$
|
|
6539
|
+
const defaults$g = {
|
|
6549
6540
|
include: null,
|
|
6550
6541
|
exclude: null,
|
|
6551
6542
|
};
|
|
6552
6543
|
class NoAutoplay extends Rule {
|
|
6553
6544
|
constructor(options) {
|
|
6554
|
-
super({ ...defaults$
|
|
6545
|
+
super({ ...defaults$g, ...options });
|
|
6555
6546
|
}
|
|
6556
6547
|
documentation(context) {
|
|
6557
6548
|
const tagName = context ? ` on <${context.tagName}>` : "";
|
|
@@ -6792,14 +6783,14 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
6792
6783
|
}
|
|
6793
6784
|
}
|
|
6794
6785
|
|
|
6795
|
-
const defaults$
|
|
6786
|
+
const defaults$f = {
|
|
6796
6787
|
include: null,
|
|
6797
6788
|
exclude: null,
|
|
6798
6789
|
allowedProperties: ["display"],
|
|
6799
6790
|
};
|
|
6800
6791
|
class NoInlineStyle extends Rule {
|
|
6801
6792
|
constructor(options) {
|
|
6802
|
-
super({ ...defaults$
|
|
6793
|
+
super({ ...defaults$f, ...options });
|
|
6803
6794
|
}
|
|
6804
6795
|
static schema() {
|
|
6805
6796
|
return {
|
|
@@ -7001,7 +6992,7 @@ class NoMultipleMain extends Rule {
|
|
|
7001
6992
|
}
|
|
7002
6993
|
}
|
|
7003
6994
|
|
|
7004
|
-
const defaults$
|
|
6995
|
+
const defaults$e = {
|
|
7005
6996
|
relaxed: false,
|
|
7006
6997
|
};
|
|
7007
6998
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -7018,7 +7009,7 @@ const replacementTable = {
|
|
|
7018
7009
|
};
|
|
7019
7010
|
class NoRawCharacters extends Rule {
|
|
7020
7011
|
constructor(options) {
|
|
7021
|
-
super({ ...defaults$
|
|
7012
|
+
super({ ...defaults$e, ...options });
|
|
7022
7013
|
this.relaxed = this.options.relaxed;
|
|
7023
7014
|
}
|
|
7024
7015
|
static schema() {
|
|
@@ -7196,13 +7187,13 @@ class NoRedundantRole extends Rule {
|
|
|
7196
7187
|
}
|
|
7197
7188
|
|
|
7198
7189
|
const xmlns = /^(.+):.+$/;
|
|
7199
|
-
const defaults$
|
|
7190
|
+
const defaults$d = {
|
|
7200
7191
|
ignoreForeign: true,
|
|
7201
7192
|
ignoreXML: true,
|
|
7202
7193
|
};
|
|
7203
7194
|
class NoSelfClosing extends Rule {
|
|
7204
7195
|
constructor(options) {
|
|
7205
|
-
super({ ...defaults$
|
|
7196
|
+
super({ ...defaults$d, ...options });
|
|
7206
7197
|
}
|
|
7207
7198
|
static schema() {
|
|
7208
7199
|
return {
|
|
@@ -7291,7 +7282,44 @@ class NoTrailingWhitespace extends Rule {
|
|
|
7291
7282
|
}
|
|
7292
7283
|
}
|
|
7293
7284
|
|
|
7285
|
+
const defaults$c = {
|
|
7286
|
+
include: null,
|
|
7287
|
+
exclude: null,
|
|
7288
|
+
};
|
|
7294
7289
|
class NoUnknownElements extends Rule {
|
|
7290
|
+
constructor(options) {
|
|
7291
|
+
super({ ...defaults$c, ...options });
|
|
7292
|
+
}
|
|
7293
|
+
static schema() {
|
|
7294
|
+
return {
|
|
7295
|
+
exclude: {
|
|
7296
|
+
anyOf: [
|
|
7297
|
+
{
|
|
7298
|
+
items: {
|
|
7299
|
+
type: "string",
|
|
7300
|
+
},
|
|
7301
|
+
type: "array",
|
|
7302
|
+
},
|
|
7303
|
+
{
|
|
7304
|
+
type: "null",
|
|
7305
|
+
},
|
|
7306
|
+
],
|
|
7307
|
+
},
|
|
7308
|
+
include: {
|
|
7309
|
+
anyOf: [
|
|
7310
|
+
{
|
|
7311
|
+
items: {
|
|
7312
|
+
type: "string",
|
|
7313
|
+
},
|
|
7314
|
+
type: "array",
|
|
7315
|
+
},
|
|
7316
|
+
{
|
|
7317
|
+
type: "null",
|
|
7318
|
+
},
|
|
7319
|
+
],
|
|
7320
|
+
},
|
|
7321
|
+
};
|
|
7322
|
+
}
|
|
7295
7323
|
documentation(context) {
|
|
7296
7324
|
const element = context ? ` <${context}>` : "";
|
|
7297
7325
|
return {
|
|
@@ -7302,9 +7330,13 @@ class NoUnknownElements extends Rule {
|
|
|
7302
7330
|
setup() {
|
|
7303
7331
|
this.on("tag:start", (event) => {
|
|
7304
7332
|
const node = event.target;
|
|
7305
|
-
if (
|
|
7306
|
-
|
|
7333
|
+
if (node.meta) {
|
|
7334
|
+
return;
|
|
7307
7335
|
}
|
|
7336
|
+
if (this.isKeywordIgnored(node.tagName, rulesHelper.keywordPatternMatcher)) {
|
|
7337
|
+
return;
|
|
7338
|
+
}
|
|
7339
|
+
this.report(node, `Unknown element <${node.tagName}>`, null, node.tagName);
|
|
7308
7340
|
});
|
|
7309
7341
|
}
|
|
7310
7342
|
}
|
|
@@ -8766,6 +8798,11 @@ class H37 extends Rule {
|
|
|
8766
8798
|
}
|
|
8767
8799
|
}
|
|
8768
8800
|
|
|
8801
|
+
var _a;
|
|
8802
|
+
/* istanbul ignore next: this will always be present for the <th>
|
|
8803
|
+
* attribute (or the tests would fail) */
|
|
8804
|
+
const { enum: validScopes } = (_a = elements.html5.th.attributes) === null || _a === void 0 ? void 0 : _a.scope;
|
|
8805
|
+
const joinedScopes = rulesHelper.naturalJoin(validScopes);
|
|
8769
8806
|
class H63 extends Rule {
|
|
8770
8807
|
documentation() {
|
|
8771
8808
|
return {
|
|
@@ -8775,19 +8812,25 @@ class H63 extends Rule {
|
|
|
8775
8812
|
}
|
|
8776
8813
|
setup() {
|
|
8777
8814
|
this.on("tag:ready", (event) => {
|
|
8778
|
-
var _a, _b
|
|
8815
|
+
var _a, _b;
|
|
8779
8816
|
const node = event.target;
|
|
8780
8817
|
/* only validate th */
|
|
8781
8818
|
if (!node || node.tagName !== "th") {
|
|
8782
8819
|
return;
|
|
8783
8820
|
}
|
|
8821
|
+
const scope = node.getAttribute("scope");
|
|
8822
|
+
const value = scope === null || scope === void 0 ? void 0 : scope.value;
|
|
8823
|
+
/* ignore dynamic scope */
|
|
8824
|
+
if (value instanceof DynamicValue) {
|
|
8825
|
+
return;
|
|
8826
|
+
}
|
|
8784
8827
|
/* ignore elements with valid scope values */
|
|
8785
|
-
|
|
8786
|
-
const scopeMeta = (_b = (_a = elements.html5 === null || elements.html5 === void 0 ? void 0 : elements.html5.th) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.scope;
|
|
8787
|
-
if (scope && ((_c = scopeMeta.enum) === null || _c === void 0 ? void 0 : _c.includes(scope))) {
|
|
8828
|
+
if (value && validScopes.includes(value)) {
|
|
8788
8829
|
return;
|
|
8789
8830
|
}
|
|
8790
|
-
|
|
8831
|
+
const message = `<th> element must have a valid scope attribute: ${joinedScopes}`;
|
|
8832
|
+
const location = (_b = (_a = scope === null || scope === void 0 ? void 0 : scope.valueLocation) !== null && _a !== void 0 ? _a : scope === null || scope === void 0 ? void 0 : scope.keyLocation) !== null && _b !== void 0 ? _b : node.location;
|
|
8833
|
+
this.report(node, message, location);
|
|
8791
8834
|
});
|
|
8792
8835
|
}
|
|
8793
8836
|
}
|
|
@@ -11158,7 +11201,7 @@ class HtmlValidate {
|
|
|
11158
11201
|
/** @public */
|
|
11159
11202
|
const name = "html-validate";
|
|
11160
11203
|
/** @public */
|
|
11161
|
-
const version = "7.
|
|
11204
|
+
const version = "7.11.0";
|
|
11162
11205
|
/** @public */
|
|
11163
11206
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11164
11207
|
|