html-validate 9.6.0 → 9.7.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.js +148 -77
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +1 -0
- package/dist/cjs/elements.js.map +1 -1
- package/dist/es/core.js +148 -77
- package/dist/es/core.js.map +1 -1
- package/dist/es/elements.js +1 -0
- package/dist/es/elements.js.map +1 -1
- package/dist/schema/elements.json +6 -0
- package/dist/types/browser.d.ts +16 -0
- package/dist/types/index.d.ts +16 -0
- package/elements/html5.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/core.js
CHANGED
|
@@ -666,6 +666,11 @@ const patternProperties = {
|
|
|
666
666
|
}
|
|
667
667
|
]
|
|
668
668
|
},
|
|
669
|
+
templateRoot: {
|
|
670
|
+
title: "Mark element as an element ignoring DOM ancestry, i.e. <template>.",
|
|
671
|
+
description: "The <template> element can contain any elements.",
|
|
672
|
+
type: "boolean"
|
|
673
|
+
},
|
|
669
674
|
deprecatedAttributes: {
|
|
670
675
|
title: "List of deprecated attributes",
|
|
671
676
|
type: "array",
|
|
@@ -1107,6 +1112,7 @@ function migrateElement(src) {
|
|
|
1107
1112
|
textContent: src.textContent,
|
|
1108
1113
|
focusable: src.focusable ?? false,
|
|
1109
1114
|
implicitRole,
|
|
1115
|
+
templateRoot: src.templateRoot === true,
|
|
1110
1116
|
aria: {
|
|
1111
1117
|
implicitRole,
|
|
1112
1118
|
naming: normalizeAriaNaming(src.aria?.naming)
|
|
@@ -4113,7 +4119,7 @@ class Rule {
|
|
|
4113
4119
|
}
|
|
4114
4120
|
}
|
|
4115
4121
|
|
|
4116
|
-
const defaults$
|
|
4122
|
+
const defaults$y = {
|
|
4117
4123
|
allowExternal: true,
|
|
4118
4124
|
allowRelative: true,
|
|
4119
4125
|
allowAbsolute: true,
|
|
@@ -4157,7 +4163,7 @@ class AllowedLinks extends Rule {
|
|
|
4157
4163
|
allowRelative;
|
|
4158
4164
|
allowAbsolute;
|
|
4159
4165
|
constructor(options) {
|
|
4160
|
-
super({ ...defaults$
|
|
4166
|
+
super({ ...defaults$y, ...options });
|
|
4161
4167
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
4162
4168
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
4163
4169
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -4325,7 +4331,7 @@ class AllowedLinks extends Rule {
|
|
|
4325
4331
|
}
|
|
4326
4332
|
}
|
|
4327
4333
|
|
|
4328
|
-
const defaults$
|
|
4334
|
+
const defaults$x = {
|
|
4329
4335
|
accessible: true
|
|
4330
4336
|
};
|
|
4331
4337
|
function findByTarget(target, siblings) {
|
|
@@ -4355,7 +4361,7 @@ function getDescription$1(context) {
|
|
|
4355
4361
|
}
|
|
4356
4362
|
class AreaAlt extends Rule {
|
|
4357
4363
|
constructor(options) {
|
|
4358
|
-
super({ ...defaults$
|
|
4364
|
+
super({ ...defaults$x, ...options });
|
|
4359
4365
|
}
|
|
4360
4366
|
static schema() {
|
|
4361
4367
|
return {
|
|
@@ -4434,7 +4440,7 @@ class AriaHiddenBody extends Rule {
|
|
|
4434
4440
|
}
|
|
4435
4441
|
}
|
|
4436
4442
|
|
|
4437
|
-
const defaults$
|
|
4443
|
+
const defaults$w = {
|
|
4438
4444
|
allowAnyNamable: false
|
|
4439
4445
|
};
|
|
4440
4446
|
const whitelisted = [
|
|
@@ -4476,7 +4482,7 @@ function isValidUsage(target, meta) {
|
|
|
4476
4482
|
}
|
|
4477
4483
|
class AriaLabelMisuse extends Rule {
|
|
4478
4484
|
constructor(options) {
|
|
4479
|
-
super({ ...defaults$
|
|
4485
|
+
super({ ...defaults$w, ...options });
|
|
4480
4486
|
}
|
|
4481
4487
|
documentation() {
|
|
4482
4488
|
const valid = [
|
|
@@ -4587,14 +4593,14 @@ class CaseStyle {
|
|
|
4587
4593
|
}
|
|
4588
4594
|
}
|
|
4589
4595
|
|
|
4590
|
-
const defaults$
|
|
4596
|
+
const defaults$v = {
|
|
4591
4597
|
style: "lowercase",
|
|
4592
4598
|
ignoreForeign: true
|
|
4593
4599
|
};
|
|
4594
4600
|
class AttrCase extends Rule {
|
|
4595
4601
|
style;
|
|
4596
4602
|
constructor(options) {
|
|
4597
|
-
super({ ...defaults$
|
|
4603
|
+
super({ ...defaults$v, ...options });
|
|
4598
4604
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4599
4605
|
}
|
|
4600
4606
|
static schema() {
|
|
@@ -4952,7 +4958,7 @@ class AttrDelimiter extends Rule {
|
|
|
4952
4958
|
}
|
|
4953
4959
|
|
|
4954
4960
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4955
|
-
const defaults$
|
|
4961
|
+
const defaults$u = {
|
|
4956
4962
|
pattern: DEFAULT_PATTERN,
|
|
4957
4963
|
ignoreForeign: true
|
|
4958
4964
|
};
|
|
@@ -4985,7 +4991,7 @@ function generateDescription(name, pattern) {
|
|
|
4985
4991
|
class AttrPattern extends Rule {
|
|
4986
4992
|
pattern;
|
|
4987
4993
|
constructor(options) {
|
|
4988
|
-
super({ ...defaults$
|
|
4994
|
+
super({ ...defaults$u, ...options });
|
|
4989
4995
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4990
4996
|
}
|
|
4991
4997
|
static schema() {
|
|
@@ -5032,7 +5038,7 @@ class AttrPattern extends Rule {
|
|
|
5032
5038
|
}
|
|
5033
5039
|
}
|
|
5034
5040
|
|
|
5035
|
-
const defaults$
|
|
5041
|
+
const defaults$t = {
|
|
5036
5042
|
style: "auto",
|
|
5037
5043
|
unquoted: false
|
|
5038
5044
|
};
|
|
@@ -5098,7 +5104,7 @@ class AttrQuotes extends Rule {
|
|
|
5098
5104
|
};
|
|
5099
5105
|
}
|
|
5100
5106
|
constructor(options) {
|
|
5101
|
-
super({ ...defaults$
|
|
5107
|
+
super({ ...defaults$t, ...options });
|
|
5102
5108
|
this.style = parseStyle$3(this.options.style);
|
|
5103
5109
|
}
|
|
5104
5110
|
setup() {
|
|
@@ -5255,13 +5261,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
5255
5261
|
}
|
|
5256
5262
|
}
|
|
5257
5263
|
|
|
5258
|
-
const defaults$
|
|
5264
|
+
const defaults$s = {
|
|
5259
5265
|
style: "omit"
|
|
5260
5266
|
};
|
|
5261
5267
|
class AttributeBooleanStyle extends Rule {
|
|
5262
5268
|
hasInvalidStyle;
|
|
5263
5269
|
constructor(options) {
|
|
5264
|
-
super({ ...defaults$
|
|
5270
|
+
super({ ...defaults$s, ...options });
|
|
5265
5271
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
5266
5272
|
}
|
|
5267
5273
|
static schema() {
|
|
@@ -5327,13 +5333,13 @@ function reportMessage$1(attr, style) {
|
|
|
5327
5333
|
return "";
|
|
5328
5334
|
}
|
|
5329
5335
|
|
|
5330
|
-
const defaults$
|
|
5336
|
+
const defaults$r = {
|
|
5331
5337
|
style: "omit"
|
|
5332
5338
|
};
|
|
5333
5339
|
class AttributeEmptyStyle extends Rule {
|
|
5334
5340
|
hasInvalidStyle;
|
|
5335
5341
|
constructor(options) {
|
|
5336
|
-
super({ ...defaults$
|
|
5342
|
+
super({ ...defaults$r, ...options });
|
|
5337
5343
|
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
5338
5344
|
}
|
|
5339
5345
|
static schema() {
|
|
@@ -5528,12 +5534,12 @@ class BasePatternRule extends Rule {
|
|
|
5528
5534
|
}
|
|
5529
5535
|
}
|
|
5530
5536
|
|
|
5531
|
-
const defaults$
|
|
5537
|
+
const defaults$q = {
|
|
5532
5538
|
pattern: "kebabcase"
|
|
5533
5539
|
};
|
|
5534
5540
|
class ClassPattern extends BasePatternRule {
|
|
5535
5541
|
constructor(options) {
|
|
5536
|
-
super("class", { ...defaults$
|
|
5542
|
+
super("class", { ...defaults$q, ...options });
|
|
5537
5543
|
}
|
|
5538
5544
|
static schema() {
|
|
5539
5545
|
return BasePatternRule.schema();
|
|
@@ -5680,13 +5686,13 @@ class CloseOrder extends Rule {
|
|
|
5680
5686
|
}
|
|
5681
5687
|
}
|
|
5682
5688
|
|
|
5683
|
-
const defaults$
|
|
5689
|
+
const defaults$p = {
|
|
5684
5690
|
include: null,
|
|
5685
5691
|
exclude: null
|
|
5686
5692
|
};
|
|
5687
5693
|
class Deprecated extends Rule {
|
|
5688
5694
|
constructor(options) {
|
|
5689
|
-
super({ ...defaults$
|
|
5695
|
+
super({ ...defaults$p, ...options });
|
|
5690
5696
|
}
|
|
5691
5697
|
static schema() {
|
|
5692
5698
|
return {
|
|
@@ -5840,12 +5846,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5840
5846
|
}
|
|
5841
5847
|
};
|
|
5842
5848
|
|
|
5843
|
-
const defaults$
|
|
5849
|
+
const defaults$o = {
|
|
5844
5850
|
style: "uppercase"
|
|
5845
5851
|
};
|
|
5846
5852
|
class DoctypeStyle extends Rule {
|
|
5847
5853
|
constructor(options) {
|
|
5848
|
-
super({ ...defaults$
|
|
5854
|
+
super({ ...defaults$o, ...options });
|
|
5849
5855
|
}
|
|
5850
5856
|
static schema() {
|
|
5851
5857
|
return {
|
|
@@ -5873,13 +5879,13 @@ class DoctypeStyle extends Rule {
|
|
|
5873
5879
|
}
|
|
5874
5880
|
}
|
|
5875
5881
|
|
|
5876
|
-
const defaults$
|
|
5882
|
+
const defaults$n = {
|
|
5877
5883
|
style: "lowercase"
|
|
5878
5884
|
};
|
|
5879
5885
|
class ElementCase extends Rule {
|
|
5880
5886
|
style;
|
|
5881
5887
|
constructor(options) {
|
|
5882
|
-
super({ ...defaults$
|
|
5888
|
+
super({ ...defaults$n, ...options });
|
|
5883
5889
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
5884
5890
|
}
|
|
5885
5891
|
static schema() {
|
|
@@ -5939,7 +5945,7 @@ class ElementCase extends Rule {
|
|
|
5939
5945
|
}
|
|
5940
5946
|
}
|
|
5941
5947
|
|
|
5942
|
-
const defaults$
|
|
5948
|
+
const defaults$m = {
|
|
5943
5949
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5944
5950
|
whitelist: [],
|
|
5945
5951
|
blacklist: []
|
|
@@ -5947,7 +5953,7 @@ const defaults$l = {
|
|
|
5947
5953
|
class ElementName extends Rule {
|
|
5948
5954
|
pattern;
|
|
5949
5955
|
constructor(options) {
|
|
5950
|
-
super({ ...defaults$
|
|
5956
|
+
super({ ...defaults$m, ...options });
|
|
5951
5957
|
this.pattern = new RegExp(this.options.pattern);
|
|
5952
5958
|
}
|
|
5953
5959
|
static schema() {
|
|
@@ -5984,7 +5990,7 @@ class ElementName extends Rule {
|
|
|
5984
5990
|
...context.blacklist.map((cur) => `- ${cur}`)
|
|
5985
5991
|
];
|
|
5986
5992
|
}
|
|
5987
|
-
if (context.pattern !== defaults$
|
|
5993
|
+
if (context.pattern !== defaults$m.pattern) {
|
|
5988
5994
|
return [
|
|
5989
5995
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
5990
5996
|
"",
|
|
@@ -6029,6 +6035,10 @@ class ElementName extends Rule {
|
|
|
6029
6035
|
}
|
|
6030
6036
|
}
|
|
6031
6037
|
|
|
6038
|
+
function isNativeTemplate(node) {
|
|
6039
|
+
const { tagName, meta } = node;
|
|
6040
|
+
return Boolean(tagName === "template" && meta?.templateRoot && meta?.scriptSupporting);
|
|
6041
|
+
}
|
|
6032
6042
|
function getTransparentChildren(node, transparent) {
|
|
6033
6043
|
if (typeof transparent === "boolean") {
|
|
6034
6044
|
return node.childElements;
|
|
@@ -6102,7 +6112,7 @@ class ElementPermittedContent extends Rule {
|
|
|
6102
6112
|
return false;
|
|
6103
6113
|
}
|
|
6104
6114
|
validatePermittedDescendant(node, parent) {
|
|
6105
|
-
for (let cur = parent; cur && !cur.isRootElement() && cur
|
|
6115
|
+
for (let cur = parent; cur && !cur.isRootElement() && !isNativeTemplate(cur); cur = /* istanbul ignore next */
|
|
6106
6116
|
cur.parent ?? null) {
|
|
6107
6117
|
const meta = cur.meta;
|
|
6108
6118
|
if (!meta) {
|
|
@@ -6470,7 +6480,7 @@ class EmptyTitle extends Rule {
|
|
|
6470
6480
|
}
|
|
6471
6481
|
}
|
|
6472
6482
|
|
|
6473
|
-
const defaults$
|
|
6483
|
+
const defaults$l = {
|
|
6474
6484
|
allowArrayBrackets: true,
|
|
6475
6485
|
allowCheckboxDefault: true,
|
|
6476
6486
|
shared: ["radio", "button", "reset", "submit"]
|
|
@@ -6518,7 +6528,7 @@ function getDocumentation(context) {
|
|
|
6518
6528
|
}
|
|
6519
6529
|
class FormDupName extends Rule {
|
|
6520
6530
|
constructor(options) {
|
|
6521
|
-
super({ ...defaults$
|
|
6531
|
+
super({ ...defaults$l, ...options });
|
|
6522
6532
|
}
|
|
6523
6533
|
static schema() {
|
|
6524
6534
|
return {
|
|
@@ -6677,7 +6687,7 @@ class FormDupName extends Rule {
|
|
|
6677
6687
|
}
|
|
6678
6688
|
}
|
|
6679
6689
|
|
|
6680
|
-
const defaults$
|
|
6690
|
+
const defaults$k = {
|
|
6681
6691
|
allowMultipleH1: false,
|
|
6682
6692
|
minInitialRank: "h1",
|
|
6683
6693
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
|
|
@@ -6709,7 +6719,7 @@ class HeadingLevel extends Rule {
|
|
|
6709
6719
|
sectionRoots;
|
|
6710
6720
|
stack = [];
|
|
6711
6721
|
constructor(options) {
|
|
6712
|
-
super({ ...defaults$
|
|
6722
|
+
super({ ...defaults$k, ...options });
|
|
6713
6723
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
6714
6724
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
|
|
6715
6725
|
this.stack.push({
|
|
@@ -6946,12 +6956,12 @@ class HiddenFocusable extends Rule {
|
|
|
6946
6956
|
}
|
|
6947
6957
|
}
|
|
6948
6958
|
|
|
6949
|
-
const defaults$
|
|
6959
|
+
const defaults$j = {
|
|
6950
6960
|
pattern: "kebabcase"
|
|
6951
6961
|
};
|
|
6952
6962
|
class IdPattern extends BasePatternRule {
|
|
6953
6963
|
constructor(options) {
|
|
6954
|
-
super("id", { ...defaults$
|
|
6964
|
+
super("id", { ...defaults$j, ...options });
|
|
6955
6965
|
}
|
|
6956
6966
|
static schema() {
|
|
6957
6967
|
return BasePatternRule.schema();
|
|
@@ -7269,13 +7279,13 @@ function findLabelByParent(el) {
|
|
|
7269
7279
|
return [];
|
|
7270
7280
|
}
|
|
7271
7281
|
|
|
7272
|
-
const defaults$
|
|
7282
|
+
const defaults$i = {
|
|
7273
7283
|
maxlength: 70
|
|
7274
7284
|
};
|
|
7275
7285
|
class LongTitle extends Rule {
|
|
7276
7286
|
maxlength;
|
|
7277
7287
|
constructor(options) {
|
|
7278
|
-
super({ ...defaults$
|
|
7288
|
+
super({ ...defaults$i, ...options });
|
|
7279
7289
|
this.maxlength = this.options.maxlength;
|
|
7280
7290
|
}
|
|
7281
7291
|
static schema() {
|
|
@@ -7303,12 +7313,12 @@ class LongTitle extends Rule {
|
|
|
7303
7313
|
}
|
|
7304
7314
|
}
|
|
7305
7315
|
|
|
7306
|
-
const defaults$
|
|
7316
|
+
const defaults$h = {
|
|
7307
7317
|
allowLongDelay: false
|
|
7308
7318
|
};
|
|
7309
7319
|
class MetaRefresh extends Rule {
|
|
7310
7320
|
constructor(options) {
|
|
7311
|
-
super({ ...defaults$
|
|
7321
|
+
super({ ...defaults$h, ...options });
|
|
7312
7322
|
}
|
|
7313
7323
|
documentation() {
|
|
7314
7324
|
return {
|
|
@@ -7493,12 +7503,12 @@ class MultipleLabeledControls extends Rule {
|
|
|
7493
7503
|
}
|
|
7494
7504
|
}
|
|
7495
7505
|
|
|
7496
|
-
const defaults$
|
|
7506
|
+
const defaults$g = {
|
|
7497
7507
|
pattern: "camelcase"
|
|
7498
7508
|
};
|
|
7499
7509
|
class NamePattern extends BasePatternRule {
|
|
7500
7510
|
constructor(options) {
|
|
7501
|
-
super("name", { ...defaults$
|
|
7511
|
+
super("name", { ...defaults$g, ...options });
|
|
7502
7512
|
}
|
|
7503
7513
|
static schema() {
|
|
7504
7514
|
return BasePatternRule.schema();
|
|
@@ -7587,13 +7597,13 @@ class NoAbstractRole extends Rule {
|
|
|
7587
7597
|
}
|
|
7588
7598
|
}
|
|
7589
7599
|
|
|
7590
|
-
const defaults$
|
|
7600
|
+
const defaults$f = {
|
|
7591
7601
|
include: null,
|
|
7592
7602
|
exclude: null
|
|
7593
7603
|
};
|
|
7594
7604
|
class NoAutoplay extends Rule {
|
|
7595
7605
|
constructor(options) {
|
|
7596
|
-
super({ ...defaults$
|
|
7606
|
+
super({ ...defaults$f, ...options });
|
|
7597
7607
|
}
|
|
7598
7608
|
documentation(context) {
|
|
7599
7609
|
return {
|
|
@@ -7912,14 +7922,14 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
7912
7922
|
}
|
|
7913
7923
|
}
|
|
7914
7924
|
|
|
7915
|
-
const defaults$
|
|
7925
|
+
const defaults$e = {
|
|
7916
7926
|
include: null,
|
|
7917
7927
|
exclude: null,
|
|
7918
7928
|
allowedProperties: ["display"]
|
|
7919
7929
|
};
|
|
7920
7930
|
class NoInlineStyle extends Rule {
|
|
7921
7931
|
constructor(options) {
|
|
7922
|
-
super({ ...defaults$
|
|
7932
|
+
super({ ...defaults$e, ...options });
|
|
7923
7933
|
}
|
|
7924
7934
|
static schema() {
|
|
7925
7935
|
return {
|
|
@@ -8105,7 +8115,7 @@ class NoMultipleMain extends Rule {
|
|
|
8105
8115
|
}
|
|
8106
8116
|
}
|
|
8107
8117
|
|
|
8108
|
-
const defaults$
|
|
8118
|
+
const defaults$d = {
|
|
8109
8119
|
relaxed: false
|
|
8110
8120
|
};
|
|
8111
8121
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -8123,7 +8133,7 @@ const replacementTable = {
|
|
|
8123
8133
|
class NoRawCharacters extends Rule {
|
|
8124
8134
|
relaxed;
|
|
8125
8135
|
constructor(options) {
|
|
8126
|
-
super({ ...defaults$
|
|
8136
|
+
super({ ...defaults$d, ...options });
|
|
8127
8137
|
this.relaxed = this.options.relaxed;
|
|
8128
8138
|
}
|
|
8129
8139
|
static schema() {
|
|
@@ -8296,13 +8306,13 @@ class NoRedundantRole extends Rule {
|
|
|
8296
8306
|
}
|
|
8297
8307
|
|
|
8298
8308
|
const xmlns = /^(.+):.+$/;
|
|
8299
|
-
const defaults$
|
|
8309
|
+
const defaults$c = {
|
|
8300
8310
|
ignoreForeign: true,
|
|
8301
8311
|
ignoreXML: true
|
|
8302
8312
|
};
|
|
8303
8313
|
class NoSelfClosing extends Rule {
|
|
8304
8314
|
constructor(options) {
|
|
8305
|
-
super({ ...defaults$
|
|
8315
|
+
super({ ...defaults$c, ...options });
|
|
8306
8316
|
}
|
|
8307
8317
|
static schema() {
|
|
8308
8318
|
return {
|
|
@@ -8386,13 +8396,13 @@ class NoTrailingWhitespace extends Rule {
|
|
|
8386
8396
|
}
|
|
8387
8397
|
}
|
|
8388
8398
|
|
|
8389
|
-
const defaults$
|
|
8399
|
+
const defaults$b = {
|
|
8390
8400
|
include: null,
|
|
8391
8401
|
exclude: null
|
|
8392
8402
|
};
|
|
8393
8403
|
class NoUnknownElements extends Rule {
|
|
8394
8404
|
constructor(options) {
|
|
8395
|
-
super({ ...defaults$
|
|
8405
|
+
super({ ...defaults$b, ...options });
|
|
8396
8406
|
}
|
|
8397
8407
|
static schema() {
|
|
8398
8408
|
return {
|
|
@@ -8498,13 +8508,13 @@ const replacement = {
|
|
|
8498
8508
|
reset: '<button type="reset">',
|
|
8499
8509
|
image: '<button type="button">'
|
|
8500
8510
|
};
|
|
8501
|
-
const defaults$
|
|
8511
|
+
const defaults$a = {
|
|
8502
8512
|
include: null,
|
|
8503
8513
|
exclude: null
|
|
8504
8514
|
};
|
|
8505
8515
|
class PreferButton extends Rule {
|
|
8506
8516
|
constructor(options) {
|
|
8507
|
-
super({ ...defaults$
|
|
8517
|
+
super({ ...defaults$a, ...options });
|
|
8508
8518
|
}
|
|
8509
8519
|
static schema() {
|
|
8510
8520
|
return {
|
|
@@ -8570,7 +8580,7 @@ class PreferButton extends Rule {
|
|
|
8570
8580
|
}
|
|
8571
8581
|
}
|
|
8572
8582
|
|
|
8573
|
-
const defaults$
|
|
8583
|
+
const defaults$9 = {
|
|
8574
8584
|
mapping: {
|
|
8575
8585
|
article: "article",
|
|
8576
8586
|
banner: "header",
|
|
@@ -8600,7 +8610,7 @@ const defaults$8 = {
|
|
|
8600
8610
|
};
|
|
8601
8611
|
class PreferNativeElement extends Rule {
|
|
8602
8612
|
constructor(options) {
|
|
8603
|
-
super({ ...defaults$
|
|
8613
|
+
super({ ...defaults$9, ...options });
|
|
8604
8614
|
}
|
|
8605
8615
|
static schema() {
|
|
8606
8616
|
return {
|
|
@@ -8714,12 +8724,12 @@ class PreferTbody extends Rule {
|
|
|
8714
8724
|
}
|
|
8715
8725
|
}
|
|
8716
8726
|
|
|
8717
|
-
const defaults$
|
|
8727
|
+
const defaults$8 = {
|
|
8718
8728
|
tags: ["script", "style"]
|
|
8719
8729
|
};
|
|
8720
8730
|
class RequireCSPNonce extends Rule {
|
|
8721
8731
|
constructor(options) {
|
|
8722
|
-
super({ ...defaults$
|
|
8732
|
+
super({ ...defaults$8, ...options });
|
|
8723
8733
|
}
|
|
8724
8734
|
static schema() {
|
|
8725
8735
|
return {
|
|
@@ -8766,7 +8776,7 @@ class RequireCSPNonce extends Rule {
|
|
|
8766
8776
|
}
|
|
8767
8777
|
}
|
|
8768
8778
|
|
|
8769
|
-
const defaults$
|
|
8779
|
+
const defaults$7 = {
|
|
8770
8780
|
target: "all",
|
|
8771
8781
|
include: null,
|
|
8772
8782
|
exclude: null
|
|
@@ -8795,7 +8805,7 @@ function linkSupportsSri(node) {
|
|
|
8795
8805
|
class RequireSri extends Rule {
|
|
8796
8806
|
target;
|
|
8797
8807
|
constructor(options) {
|
|
8798
|
-
super({ ...defaults$
|
|
8808
|
+
super({ ...defaults$7, ...options });
|
|
8799
8809
|
this.target = this.options.target;
|
|
8800
8810
|
}
|
|
8801
8811
|
static schema() {
|
|
@@ -8968,7 +8978,7 @@ class SvgFocusable extends Rule {
|
|
|
8968
8978
|
}
|
|
8969
8979
|
}
|
|
8970
8980
|
|
|
8971
|
-
const defaults$
|
|
8981
|
+
const defaults$6 = {
|
|
8972
8982
|
characters: [
|
|
8973
8983
|
{ pattern: " ", replacement: " ", description: "non-breaking space" },
|
|
8974
8984
|
{ pattern: "-", replacement: "‑", description: "non-breaking hyphen" }
|
|
@@ -9000,7 +9010,7 @@ function matchAll(text, regexp) {
|
|
|
9000
9010
|
class TelNonBreaking extends Rule {
|
|
9001
9011
|
regex;
|
|
9002
9012
|
constructor(options) {
|
|
9003
|
-
super({ ...defaults$
|
|
9013
|
+
super({ ...defaults$6, ...options });
|
|
9004
9014
|
this.regex = constructRegex(this.options.characters);
|
|
9005
9015
|
}
|
|
9006
9016
|
static schema() {
|
|
@@ -9375,7 +9385,7 @@ class UniqueLandmark extends Rule {
|
|
|
9375
9385
|
}
|
|
9376
9386
|
}
|
|
9377
9387
|
|
|
9378
|
-
const defaults$
|
|
9388
|
+
const defaults$5 = {
|
|
9379
9389
|
ignoreCase: false,
|
|
9380
9390
|
requireSemicolon: true
|
|
9381
9391
|
};
|
|
@@ -9409,7 +9419,7 @@ function getDescription(context, options) {
|
|
|
9409
9419
|
}
|
|
9410
9420
|
class UnknownCharReference extends Rule {
|
|
9411
9421
|
constructor(options) {
|
|
9412
|
-
super({ ...defaults$
|
|
9422
|
+
super({ ...defaults$5, ...options });
|
|
9413
9423
|
}
|
|
9414
9424
|
static schema() {
|
|
9415
9425
|
return {
|
|
@@ -10025,12 +10035,12 @@ class ValidAutocomplete extends Rule {
|
|
|
10025
10035
|
}
|
|
10026
10036
|
}
|
|
10027
10037
|
|
|
10028
|
-
const defaults$
|
|
10038
|
+
const defaults$4 = {
|
|
10029
10039
|
relaxed: false
|
|
10030
10040
|
};
|
|
10031
10041
|
class ValidID extends Rule {
|
|
10032
10042
|
constructor(options) {
|
|
10033
|
-
super({ ...defaults$
|
|
10043
|
+
super({ ...defaults$4, ...options });
|
|
10034
10044
|
}
|
|
10035
10045
|
static schema() {
|
|
10036
10046
|
return {
|
|
@@ -10136,13 +10146,13 @@ class VoidContent extends Rule {
|
|
|
10136
10146
|
}
|
|
10137
10147
|
}
|
|
10138
10148
|
|
|
10139
|
-
const defaults$
|
|
10149
|
+
const defaults$3 = {
|
|
10140
10150
|
style: "omit"
|
|
10141
10151
|
};
|
|
10142
10152
|
class VoidStyle extends Rule {
|
|
10143
10153
|
style;
|
|
10144
10154
|
constructor(options) {
|
|
10145
|
-
super({ ...defaults$
|
|
10155
|
+
super({ ...defaults$3, ...options });
|
|
10146
10156
|
this.style = parseStyle(this.options.style);
|
|
10147
10157
|
}
|
|
10148
10158
|
static schema() {
|
|
@@ -10343,13 +10353,13 @@ class H36 extends Rule {
|
|
|
10343
10353
|
}
|
|
10344
10354
|
}
|
|
10345
10355
|
|
|
10346
|
-
const defaults$
|
|
10356
|
+
const defaults$2 = {
|
|
10347
10357
|
allowEmpty: true,
|
|
10348
10358
|
alias: []
|
|
10349
10359
|
};
|
|
10350
10360
|
class H37 extends Rule {
|
|
10351
10361
|
constructor(options) {
|
|
10352
|
-
super({ ...defaults$
|
|
10362
|
+
super({ ...defaults$2, ...options });
|
|
10353
10363
|
if (!Array.isArray(this.options.alias)) {
|
|
10354
10364
|
this.options.alias = [this.options.alias];
|
|
10355
10365
|
}
|
|
@@ -10411,9 +10421,62 @@ class H37 extends Rule {
|
|
|
10411
10421
|
}
|
|
10412
10422
|
}
|
|
10413
10423
|
|
|
10424
|
+
const defaults$1 = {
|
|
10425
|
+
strict: false
|
|
10426
|
+
};
|
|
10414
10427
|
const { enum: validScopes } = elements.html5.th.attributes?.scope;
|
|
10415
10428
|
const joinedScopes = utils_naturalJoin.naturalJoin(validScopes);
|
|
10429
|
+
const td = 0;
|
|
10430
|
+
const th = 1;
|
|
10431
|
+
function getShape(cells) {
|
|
10432
|
+
const rows = cells.length;
|
|
10433
|
+
const cols = cells[0].length;
|
|
10434
|
+
return { rows, cols };
|
|
10435
|
+
}
|
|
10436
|
+
function isSimpleTable(table) {
|
|
10437
|
+
const haveHeadersAttr = table.querySelector("> tr > [headers], > tbody > tr > [headers]");
|
|
10438
|
+
if (haveHeadersAttr) {
|
|
10439
|
+
return false;
|
|
10440
|
+
}
|
|
10441
|
+
const rows = table.querySelectorAll("> tr, > thead > tr, > tbody > tr");
|
|
10442
|
+
if (rows.length === 0) {
|
|
10443
|
+
return false;
|
|
10444
|
+
}
|
|
10445
|
+
const cells = rows.map((tr) => tr.querySelectorAll("> *").map((el) => el.is("th") ? th : td));
|
|
10446
|
+
if (cells[0].length === 0) {
|
|
10447
|
+
return false;
|
|
10448
|
+
}
|
|
10449
|
+
const numColumns = cells[0].length;
|
|
10450
|
+
if (!cells.every((row) => row.length === numColumns)) {
|
|
10451
|
+
return false;
|
|
10452
|
+
}
|
|
10453
|
+
const shape = getShape(cells);
|
|
10454
|
+
const headersPerRow = cells.map((row) => row.reduce((sum, cell) => sum + cell, 0));
|
|
10455
|
+
const headersPerColumn = Array(shape.cols).fill(0).map((_, index) => {
|
|
10456
|
+
return cells.reduce((sum, it) => sum + it[index], 0);
|
|
10457
|
+
});
|
|
10458
|
+
const [firstRow, ...otherRows] = headersPerRow;
|
|
10459
|
+
if (firstRow === shape.cols && otherRows.every((row) => row === 0)) {
|
|
10460
|
+
return true;
|
|
10461
|
+
}
|
|
10462
|
+
const [firstCol, ...otherCols] = headersPerColumn;
|
|
10463
|
+
const haveThead = Boolean(table.querySelector("> thead"));
|
|
10464
|
+
if (firstCol === shape.rows && otherCols.every((col) => col === 0) && !haveThead) {
|
|
10465
|
+
return true;
|
|
10466
|
+
}
|
|
10467
|
+
return false;
|
|
10468
|
+
}
|
|
10416
10469
|
class H63 extends Rule {
|
|
10470
|
+
constructor(options) {
|
|
10471
|
+
super({ ...defaults$1, ...options });
|
|
10472
|
+
}
|
|
10473
|
+
static schema() {
|
|
10474
|
+
return {
|
|
10475
|
+
strict: {
|
|
10476
|
+
type: "boolean"
|
|
10477
|
+
}
|
|
10478
|
+
};
|
|
10479
|
+
}
|
|
10417
10480
|
documentation() {
|
|
10418
10481
|
return {
|
|
10419
10482
|
description: "H63: Using the scope attribute to associate header cells and data cells in data tables",
|
|
@@ -10421,23 +10484,31 @@ class H63 extends Rule {
|
|
|
10421
10484
|
};
|
|
10422
10485
|
}
|
|
10423
10486
|
setup() {
|
|
10424
|
-
|
|
10487
|
+
const { strict } = this.options;
|
|
10488
|
+
this.on("element:ready", (event) => {
|
|
10425
10489
|
const node = event.target;
|
|
10426
|
-
if (node.
|
|
10490
|
+
if (!node.is("table")) {
|
|
10427
10491
|
return;
|
|
10428
10492
|
}
|
|
10429
|
-
|
|
10493
|
+
if (strict || !isSimpleTable(node)) {
|
|
10494
|
+
this.validateTable(node);
|
|
10495
|
+
}
|
|
10496
|
+
});
|
|
10497
|
+
}
|
|
10498
|
+
validateTable(node) {
|
|
10499
|
+
for (const th2 of node.querySelectorAll("th")) {
|
|
10500
|
+
const scope = th2.getAttribute("scope");
|
|
10430
10501
|
const value = scope?.value;
|
|
10431
10502
|
if (value instanceof DynamicValue) {
|
|
10432
|
-
|
|
10503
|
+
continue;
|
|
10433
10504
|
}
|
|
10434
10505
|
if (value && validScopes.includes(value)) {
|
|
10435
|
-
|
|
10506
|
+
continue;
|
|
10436
10507
|
}
|
|
10437
10508
|
const message = `<th> element must have a valid scope attribute: ${joinedScopes}`;
|
|
10438
|
-
const location = scope?.valueLocation ?? scope?.keyLocation ??
|
|
10439
|
-
this.report(
|
|
10440
|
-
}
|
|
10509
|
+
const location = scope?.valueLocation ?? scope?.keyLocation ?? th2.location;
|
|
10510
|
+
this.report(th2, message, location);
|
|
10511
|
+
}
|
|
10441
10512
|
}
|
|
10442
10513
|
}
|
|
10443
10514
|
|
|
@@ -11729,7 +11800,7 @@ class EventHandler {
|
|
|
11729
11800
|
}
|
|
11730
11801
|
|
|
11731
11802
|
const name = "html-validate";
|
|
11732
|
-
const version = "9.
|
|
11803
|
+
const version = "9.7.0";
|
|
11733
11804
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11734
11805
|
|
|
11735
11806
|
function freeze(src) {
|