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/es/core.js
CHANGED
|
@@ -657,6 +657,11 @@ const patternProperties = {
|
|
|
657
657
|
}
|
|
658
658
|
]
|
|
659
659
|
},
|
|
660
|
+
templateRoot: {
|
|
661
|
+
title: "Mark element as an element ignoring DOM ancestry, i.e. <template>.",
|
|
662
|
+
description: "The <template> element can contain any elements.",
|
|
663
|
+
type: "boolean"
|
|
664
|
+
},
|
|
660
665
|
deprecatedAttributes: {
|
|
661
666
|
title: "List of deprecated attributes",
|
|
662
667
|
type: "array",
|
|
@@ -1098,6 +1103,7 @@ function migrateElement(src) {
|
|
|
1098
1103
|
textContent: src.textContent,
|
|
1099
1104
|
focusable: src.focusable ?? false,
|
|
1100
1105
|
implicitRole,
|
|
1106
|
+
templateRoot: src.templateRoot === true,
|
|
1101
1107
|
aria: {
|
|
1102
1108
|
implicitRole,
|
|
1103
1109
|
naming: normalizeAriaNaming(src.aria?.naming)
|
|
@@ -4104,7 +4110,7 @@ class Rule {
|
|
|
4104
4110
|
}
|
|
4105
4111
|
}
|
|
4106
4112
|
|
|
4107
|
-
const defaults$
|
|
4113
|
+
const defaults$y = {
|
|
4108
4114
|
allowExternal: true,
|
|
4109
4115
|
allowRelative: true,
|
|
4110
4116
|
allowAbsolute: true,
|
|
@@ -4148,7 +4154,7 @@ class AllowedLinks extends Rule {
|
|
|
4148
4154
|
allowRelative;
|
|
4149
4155
|
allowAbsolute;
|
|
4150
4156
|
constructor(options) {
|
|
4151
|
-
super({ ...defaults$
|
|
4157
|
+
super({ ...defaults$y, ...options });
|
|
4152
4158
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
4153
4159
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
4154
4160
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -4316,7 +4322,7 @@ class AllowedLinks extends Rule {
|
|
|
4316
4322
|
}
|
|
4317
4323
|
}
|
|
4318
4324
|
|
|
4319
|
-
const defaults$
|
|
4325
|
+
const defaults$x = {
|
|
4320
4326
|
accessible: true
|
|
4321
4327
|
};
|
|
4322
4328
|
function findByTarget(target, siblings) {
|
|
@@ -4346,7 +4352,7 @@ function getDescription$1(context) {
|
|
|
4346
4352
|
}
|
|
4347
4353
|
class AreaAlt extends Rule {
|
|
4348
4354
|
constructor(options) {
|
|
4349
|
-
super({ ...defaults$
|
|
4355
|
+
super({ ...defaults$x, ...options });
|
|
4350
4356
|
}
|
|
4351
4357
|
static schema() {
|
|
4352
4358
|
return {
|
|
@@ -4425,7 +4431,7 @@ class AriaHiddenBody extends Rule {
|
|
|
4425
4431
|
}
|
|
4426
4432
|
}
|
|
4427
4433
|
|
|
4428
|
-
const defaults$
|
|
4434
|
+
const defaults$w = {
|
|
4429
4435
|
allowAnyNamable: false
|
|
4430
4436
|
};
|
|
4431
4437
|
const whitelisted = [
|
|
@@ -4467,7 +4473,7 @@ function isValidUsage(target, meta) {
|
|
|
4467
4473
|
}
|
|
4468
4474
|
class AriaLabelMisuse extends Rule {
|
|
4469
4475
|
constructor(options) {
|
|
4470
|
-
super({ ...defaults$
|
|
4476
|
+
super({ ...defaults$w, ...options });
|
|
4471
4477
|
}
|
|
4472
4478
|
documentation() {
|
|
4473
4479
|
const valid = [
|
|
@@ -4578,14 +4584,14 @@ class CaseStyle {
|
|
|
4578
4584
|
}
|
|
4579
4585
|
}
|
|
4580
4586
|
|
|
4581
|
-
const defaults$
|
|
4587
|
+
const defaults$v = {
|
|
4582
4588
|
style: "lowercase",
|
|
4583
4589
|
ignoreForeign: true
|
|
4584
4590
|
};
|
|
4585
4591
|
class AttrCase extends Rule {
|
|
4586
4592
|
style;
|
|
4587
4593
|
constructor(options) {
|
|
4588
|
-
super({ ...defaults$
|
|
4594
|
+
super({ ...defaults$v, ...options });
|
|
4589
4595
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4590
4596
|
}
|
|
4591
4597
|
static schema() {
|
|
@@ -4943,7 +4949,7 @@ class AttrDelimiter extends Rule {
|
|
|
4943
4949
|
}
|
|
4944
4950
|
|
|
4945
4951
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4946
|
-
const defaults$
|
|
4952
|
+
const defaults$u = {
|
|
4947
4953
|
pattern: DEFAULT_PATTERN,
|
|
4948
4954
|
ignoreForeign: true
|
|
4949
4955
|
};
|
|
@@ -4976,7 +4982,7 @@ function generateDescription(name, pattern) {
|
|
|
4976
4982
|
class AttrPattern extends Rule {
|
|
4977
4983
|
pattern;
|
|
4978
4984
|
constructor(options) {
|
|
4979
|
-
super({ ...defaults$
|
|
4985
|
+
super({ ...defaults$u, ...options });
|
|
4980
4986
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4981
4987
|
}
|
|
4982
4988
|
static schema() {
|
|
@@ -5023,7 +5029,7 @@ class AttrPattern extends Rule {
|
|
|
5023
5029
|
}
|
|
5024
5030
|
}
|
|
5025
5031
|
|
|
5026
|
-
const defaults$
|
|
5032
|
+
const defaults$t = {
|
|
5027
5033
|
style: "auto",
|
|
5028
5034
|
unquoted: false
|
|
5029
5035
|
};
|
|
@@ -5089,7 +5095,7 @@ class AttrQuotes extends Rule {
|
|
|
5089
5095
|
};
|
|
5090
5096
|
}
|
|
5091
5097
|
constructor(options) {
|
|
5092
|
-
super({ ...defaults$
|
|
5098
|
+
super({ ...defaults$t, ...options });
|
|
5093
5099
|
this.style = parseStyle$3(this.options.style);
|
|
5094
5100
|
}
|
|
5095
5101
|
setup() {
|
|
@@ -5246,13 +5252,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
5246
5252
|
}
|
|
5247
5253
|
}
|
|
5248
5254
|
|
|
5249
|
-
const defaults$
|
|
5255
|
+
const defaults$s = {
|
|
5250
5256
|
style: "omit"
|
|
5251
5257
|
};
|
|
5252
5258
|
class AttributeBooleanStyle extends Rule {
|
|
5253
5259
|
hasInvalidStyle;
|
|
5254
5260
|
constructor(options) {
|
|
5255
|
-
super({ ...defaults$
|
|
5261
|
+
super({ ...defaults$s, ...options });
|
|
5256
5262
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
5257
5263
|
}
|
|
5258
5264
|
static schema() {
|
|
@@ -5318,13 +5324,13 @@ function reportMessage$1(attr, style) {
|
|
|
5318
5324
|
return "";
|
|
5319
5325
|
}
|
|
5320
5326
|
|
|
5321
|
-
const defaults$
|
|
5327
|
+
const defaults$r = {
|
|
5322
5328
|
style: "omit"
|
|
5323
5329
|
};
|
|
5324
5330
|
class AttributeEmptyStyle extends Rule {
|
|
5325
5331
|
hasInvalidStyle;
|
|
5326
5332
|
constructor(options) {
|
|
5327
|
-
super({ ...defaults$
|
|
5333
|
+
super({ ...defaults$r, ...options });
|
|
5328
5334
|
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
5329
5335
|
}
|
|
5330
5336
|
static schema() {
|
|
@@ -5519,12 +5525,12 @@ class BasePatternRule extends Rule {
|
|
|
5519
5525
|
}
|
|
5520
5526
|
}
|
|
5521
5527
|
|
|
5522
|
-
const defaults$
|
|
5528
|
+
const defaults$q = {
|
|
5523
5529
|
pattern: "kebabcase"
|
|
5524
5530
|
};
|
|
5525
5531
|
class ClassPattern extends BasePatternRule {
|
|
5526
5532
|
constructor(options) {
|
|
5527
|
-
super("class", { ...defaults$
|
|
5533
|
+
super("class", { ...defaults$q, ...options });
|
|
5528
5534
|
}
|
|
5529
5535
|
static schema() {
|
|
5530
5536
|
return BasePatternRule.schema();
|
|
@@ -5671,13 +5677,13 @@ class CloseOrder extends Rule {
|
|
|
5671
5677
|
}
|
|
5672
5678
|
}
|
|
5673
5679
|
|
|
5674
|
-
const defaults$
|
|
5680
|
+
const defaults$p = {
|
|
5675
5681
|
include: null,
|
|
5676
5682
|
exclude: null
|
|
5677
5683
|
};
|
|
5678
5684
|
class Deprecated extends Rule {
|
|
5679
5685
|
constructor(options) {
|
|
5680
|
-
super({ ...defaults$
|
|
5686
|
+
super({ ...defaults$p, ...options });
|
|
5681
5687
|
}
|
|
5682
5688
|
static schema() {
|
|
5683
5689
|
return {
|
|
@@ -5831,12 +5837,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5831
5837
|
}
|
|
5832
5838
|
};
|
|
5833
5839
|
|
|
5834
|
-
const defaults$
|
|
5840
|
+
const defaults$o = {
|
|
5835
5841
|
style: "uppercase"
|
|
5836
5842
|
};
|
|
5837
5843
|
class DoctypeStyle extends Rule {
|
|
5838
5844
|
constructor(options) {
|
|
5839
|
-
super({ ...defaults$
|
|
5845
|
+
super({ ...defaults$o, ...options });
|
|
5840
5846
|
}
|
|
5841
5847
|
static schema() {
|
|
5842
5848
|
return {
|
|
@@ -5864,13 +5870,13 @@ class DoctypeStyle extends Rule {
|
|
|
5864
5870
|
}
|
|
5865
5871
|
}
|
|
5866
5872
|
|
|
5867
|
-
const defaults$
|
|
5873
|
+
const defaults$n = {
|
|
5868
5874
|
style: "lowercase"
|
|
5869
5875
|
};
|
|
5870
5876
|
class ElementCase extends Rule {
|
|
5871
5877
|
style;
|
|
5872
5878
|
constructor(options) {
|
|
5873
|
-
super({ ...defaults$
|
|
5879
|
+
super({ ...defaults$n, ...options });
|
|
5874
5880
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
5875
5881
|
}
|
|
5876
5882
|
static schema() {
|
|
@@ -5930,7 +5936,7 @@ class ElementCase extends Rule {
|
|
|
5930
5936
|
}
|
|
5931
5937
|
}
|
|
5932
5938
|
|
|
5933
|
-
const defaults$
|
|
5939
|
+
const defaults$m = {
|
|
5934
5940
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5935
5941
|
whitelist: [],
|
|
5936
5942
|
blacklist: []
|
|
@@ -5938,7 +5944,7 @@ const defaults$l = {
|
|
|
5938
5944
|
class ElementName extends Rule {
|
|
5939
5945
|
pattern;
|
|
5940
5946
|
constructor(options) {
|
|
5941
|
-
super({ ...defaults$
|
|
5947
|
+
super({ ...defaults$m, ...options });
|
|
5942
5948
|
this.pattern = new RegExp(this.options.pattern);
|
|
5943
5949
|
}
|
|
5944
5950
|
static schema() {
|
|
@@ -5975,7 +5981,7 @@ class ElementName extends Rule {
|
|
|
5975
5981
|
...context.blacklist.map((cur) => `- ${cur}`)
|
|
5976
5982
|
];
|
|
5977
5983
|
}
|
|
5978
|
-
if (context.pattern !== defaults$
|
|
5984
|
+
if (context.pattern !== defaults$m.pattern) {
|
|
5979
5985
|
return [
|
|
5980
5986
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
5981
5987
|
"",
|
|
@@ -6020,6 +6026,10 @@ class ElementName extends Rule {
|
|
|
6020
6026
|
}
|
|
6021
6027
|
}
|
|
6022
6028
|
|
|
6029
|
+
function isNativeTemplate(node) {
|
|
6030
|
+
const { tagName, meta } = node;
|
|
6031
|
+
return Boolean(tagName === "template" && meta?.templateRoot && meta?.scriptSupporting);
|
|
6032
|
+
}
|
|
6023
6033
|
function getTransparentChildren(node, transparent) {
|
|
6024
6034
|
if (typeof transparent === "boolean") {
|
|
6025
6035
|
return node.childElements;
|
|
@@ -6093,7 +6103,7 @@ class ElementPermittedContent extends Rule {
|
|
|
6093
6103
|
return false;
|
|
6094
6104
|
}
|
|
6095
6105
|
validatePermittedDescendant(node, parent) {
|
|
6096
|
-
for (let cur = parent; cur && !cur.isRootElement() && cur
|
|
6106
|
+
for (let cur = parent; cur && !cur.isRootElement() && !isNativeTemplate(cur); cur = /* istanbul ignore next */
|
|
6097
6107
|
cur.parent ?? null) {
|
|
6098
6108
|
const meta = cur.meta;
|
|
6099
6109
|
if (!meta) {
|
|
@@ -6461,7 +6471,7 @@ class EmptyTitle extends Rule {
|
|
|
6461
6471
|
}
|
|
6462
6472
|
}
|
|
6463
6473
|
|
|
6464
|
-
const defaults$
|
|
6474
|
+
const defaults$l = {
|
|
6465
6475
|
allowArrayBrackets: true,
|
|
6466
6476
|
allowCheckboxDefault: true,
|
|
6467
6477
|
shared: ["radio", "button", "reset", "submit"]
|
|
@@ -6509,7 +6519,7 @@ function getDocumentation(context) {
|
|
|
6509
6519
|
}
|
|
6510
6520
|
class FormDupName extends Rule {
|
|
6511
6521
|
constructor(options) {
|
|
6512
|
-
super({ ...defaults$
|
|
6522
|
+
super({ ...defaults$l, ...options });
|
|
6513
6523
|
}
|
|
6514
6524
|
static schema() {
|
|
6515
6525
|
return {
|
|
@@ -6668,7 +6678,7 @@ class FormDupName extends Rule {
|
|
|
6668
6678
|
}
|
|
6669
6679
|
}
|
|
6670
6680
|
|
|
6671
|
-
const defaults$
|
|
6681
|
+
const defaults$k = {
|
|
6672
6682
|
allowMultipleH1: false,
|
|
6673
6683
|
minInitialRank: "h1",
|
|
6674
6684
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
|
|
@@ -6700,7 +6710,7 @@ class HeadingLevel extends Rule {
|
|
|
6700
6710
|
sectionRoots;
|
|
6701
6711
|
stack = [];
|
|
6702
6712
|
constructor(options) {
|
|
6703
|
-
super({ ...defaults$
|
|
6713
|
+
super({ ...defaults$k, ...options });
|
|
6704
6714
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
6705
6715
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
|
|
6706
6716
|
this.stack.push({
|
|
@@ -6937,12 +6947,12 @@ class HiddenFocusable extends Rule {
|
|
|
6937
6947
|
}
|
|
6938
6948
|
}
|
|
6939
6949
|
|
|
6940
|
-
const defaults$
|
|
6950
|
+
const defaults$j = {
|
|
6941
6951
|
pattern: "kebabcase"
|
|
6942
6952
|
};
|
|
6943
6953
|
class IdPattern extends BasePatternRule {
|
|
6944
6954
|
constructor(options) {
|
|
6945
|
-
super("id", { ...defaults$
|
|
6955
|
+
super("id", { ...defaults$j, ...options });
|
|
6946
6956
|
}
|
|
6947
6957
|
static schema() {
|
|
6948
6958
|
return BasePatternRule.schema();
|
|
@@ -7260,13 +7270,13 @@ function findLabelByParent(el) {
|
|
|
7260
7270
|
return [];
|
|
7261
7271
|
}
|
|
7262
7272
|
|
|
7263
|
-
const defaults$
|
|
7273
|
+
const defaults$i = {
|
|
7264
7274
|
maxlength: 70
|
|
7265
7275
|
};
|
|
7266
7276
|
class LongTitle extends Rule {
|
|
7267
7277
|
maxlength;
|
|
7268
7278
|
constructor(options) {
|
|
7269
|
-
super({ ...defaults$
|
|
7279
|
+
super({ ...defaults$i, ...options });
|
|
7270
7280
|
this.maxlength = this.options.maxlength;
|
|
7271
7281
|
}
|
|
7272
7282
|
static schema() {
|
|
@@ -7294,12 +7304,12 @@ class LongTitle extends Rule {
|
|
|
7294
7304
|
}
|
|
7295
7305
|
}
|
|
7296
7306
|
|
|
7297
|
-
const defaults$
|
|
7307
|
+
const defaults$h = {
|
|
7298
7308
|
allowLongDelay: false
|
|
7299
7309
|
};
|
|
7300
7310
|
class MetaRefresh extends Rule {
|
|
7301
7311
|
constructor(options) {
|
|
7302
|
-
super({ ...defaults$
|
|
7312
|
+
super({ ...defaults$h, ...options });
|
|
7303
7313
|
}
|
|
7304
7314
|
documentation() {
|
|
7305
7315
|
return {
|
|
@@ -7484,12 +7494,12 @@ class MultipleLabeledControls extends Rule {
|
|
|
7484
7494
|
}
|
|
7485
7495
|
}
|
|
7486
7496
|
|
|
7487
|
-
const defaults$
|
|
7497
|
+
const defaults$g = {
|
|
7488
7498
|
pattern: "camelcase"
|
|
7489
7499
|
};
|
|
7490
7500
|
class NamePattern extends BasePatternRule {
|
|
7491
7501
|
constructor(options) {
|
|
7492
|
-
super("name", { ...defaults$
|
|
7502
|
+
super("name", { ...defaults$g, ...options });
|
|
7493
7503
|
}
|
|
7494
7504
|
static schema() {
|
|
7495
7505
|
return BasePatternRule.schema();
|
|
@@ -7578,13 +7588,13 @@ class NoAbstractRole extends Rule {
|
|
|
7578
7588
|
}
|
|
7579
7589
|
}
|
|
7580
7590
|
|
|
7581
|
-
const defaults$
|
|
7591
|
+
const defaults$f = {
|
|
7582
7592
|
include: null,
|
|
7583
7593
|
exclude: null
|
|
7584
7594
|
};
|
|
7585
7595
|
class NoAutoplay extends Rule {
|
|
7586
7596
|
constructor(options) {
|
|
7587
|
-
super({ ...defaults$
|
|
7597
|
+
super({ ...defaults$f, ...options });
|
|
7588
7598
|
}
|
|
7589
7599
|
documentation(context) {
|
|
7590
7600
|
return {
|
|
@@ -7903,14 +7913,14 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
7903
7913
|
}
|
|
7904
7914
|
}
|
|
7905
7915
|
|
|
7906
|
-
const defaults$
|
|
7916
|
+
const defaults$e = {
|
|
7907
7917
|
include: null,
|
|
7908
7918
|
exclude: null,
|
|
7909
7919
|
allowedProperties: ["display"]
|
|
7910
7920
|
};
|
|
7911
7921
|
class NoInlineStyle extends Rule {
|
|
7912
7922
|
constructor(options) {
|
|
7913
|
-
super({ ...defaults$
|
|
7923
|
+
super({ ...defaults$e, ...options });
|
|
7914
7924
|
}
|
|
7915
7925
|
static schema() {
|
|
7916
7926
|
return {
|
|
@@ -8096,7 +8106,7 @@ class NoMultipleMain extends Rule {
|
|
|
8096
8106
|
}
|
|
8097
8107
|
}
|
|
8098
8108
|
|
|
8099
|
-
const defaults$
|
|
8109
|
+
const defaults$d = {
|
|
8100
8110
|
relaxed: false
|
|
8101
8111
|
};
|
|
8102
8112
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -8114,7 +8124,7 @@ const replacementTable = {
|
|
|
8114
8124
|
class NoRawCharacters extends Rule {
|
|
8115
8125
|
relaxed;
|
|
8116
8126
|
constructor(options) {
|
|
8117
|
-
super({ ...defaults$
|
|
8127
|
+
super({ ...defaults$d, ...options });
|
|
8118
8128
|
this.relaxed = this.options.relaxed;
|
|
8119
8129
|
}
|
|
8120
8130
|
static schema() {
|
|
@@ -8287,13 +8297,13 @@ class NoRedundantRole extends Rule {
|
|
|
8287
8297
|
}
|
|
8288
8298
|
|
|
8289
8299
|
const xmlns = /^(.+):.+$/;
|
|
8290
|
-
const defaults$
|
|
8300
|
+
const defaults$c = {
|
|
8291
8301
|
ignoreForeign: true,
|
|
8292
8302
|
ignoreXML: true
|
|
8293
8303
|
};
|
|
8294
8304
|
class NoSelfClosing extends Rule {
|
|
8295
8305
|
constructor(options) {
|
|
8296
|
-
super({ ...defaults$
|
|
8306
|
+
super({ ...defaults$c, ...options });
|
|
8297
8307
|
}
|
|
8298
8308
|
static schema() {
|
|
8299
8309
|
return {
|
|
@@ -8377,13 +8387,13 @@ class NoTrailingWhitespace extends Rule {
|
|
|
8377
8387
|
}
|
|
8378
8388
|
}
|
|
8379
8389
|
|
|
8380
|
-
const defaults$
|
|
8390
|
+
const defaults$b = {
|
|
8381
8391
|
include: null,
|
|
8382
8392
|
exclude: null
|
|
8383
8393
|
};
|
|
8384
8394
|
class NoUnknownElements extends Rule {
|
|
8385
8395
|
constructor(options) {
|
|
8386
|
-
super({ ...defaults$
|
|
8396
|
+
super({ ...defaults$b, ...options });
|
|
8387
8397
|
}
|
|
8388
8398
|
static schema() {
|
|
8389
8399
|
return {
|
|
@@ -8489,13 +8499,13 @@ const replacement = {
|
|
|
8489
8499
|
reset: '<button type="reset">',
|
|
8490
8500
|
image: '<button type="button">'
|
|
8491
8501
|
};
|
|
8492
|
-
const defaults$
|
|
8502
|
+
const defaults$a = {
|
|
8493
8503
|
include: null,
|
|
8494
8504
|
exclude: null
|
|
8495
8505
|
};
|
|
8496
8506
|
class PreferButton extends Rule {
|
|
8497
8507
|
constructor(options) {
|
|
8498
|
-
super({ ...defaults$
|
|
8508
|
+
super({ ...defaults$a, ...options });
|
|
8499
8509
|
}
|
|
8500
8510
|
static schema() {
|
|
8501
8511
|
return {
|
|
@@ -8561,7 +8571,7 @@ class PreferButton extends Rule {
|
|
|
8561
8571
|
}
|
|
8562
8572
|
}
|
|
8563
8573
|
|
|
8564
|
-
const defaults$
|
|
8574
|
+
const defaults$9 = {
|
|
8565
8575
|
mapping: {
|
|
8566
8576
|
article: "article",
|
|
8567
8577
|
banner: "header",
|
|
@@ -8591,7 +8601,7 @@ const defaults$8 = {
|
|
|
8591
8601
|
};
|
|
8592
8602
|
class PreferNativeElement extends Rule {
|
|
8593
8603
|
constructor(options) {
|
|
8594
|
-
super({ ...defaults$
|
|
8604
|
+
super({ ...defaults$9, ...options });
|
|
8595
8605
|
}
|
|
8596
8606
|
static schema() {
|
|
8597
8607
|
return {
|
|
@@ -8705,12 +8715,12 @@ class PreferTbody extends Rule {
|
|
|
8705
8715
|
}
|
|
8706
8716
|
}
|
|
8707
8717
|
|
|
8708
|
-
const defaults$
|
|
8718
|
+
const defaults$8 = {
|
|
8709
8719
|
tags: ["script", "style"]
|
|
8710
8720
|
};
|
|
8711
8721
|
class RequireCSPNonce extends Rule {
|
|
8712
8722
|
constructor(options) {
|
|
8713
|
-
super({ ...defaults$
|
|
8723
|
+
super({ ...defaults$8, ...options });
|
|
8714
8724
|
}
|
|
8715
8725
|
static schema() {
|
|
8716
8726
|
return {
|
|
@@ -8757,7 +8767,7 @@ class RequireCSPNonce extends Rule {
|
|
|
8757
8767
|
}
|
|
8758
8768
|
}
|
|
8759
8769
|
|
|
8760
|
-
const defaults$
|
|
8770
|
+
const defaults$7 = {
|
|
8761
8771
|
target: "all",
|
|
8762
8772
|
include: null,
|
|
8763
8773
|
exclude: null
|
|
@@ -8786,7 +8796,7 @@ function linkSupportsSri(node) {
|
|
|
8786
8796
|
class RequireSri extends Rule {
|
|
8787
8797
|
target;
|
|
8788
8798
|
constructor(options) {
|
|
8789
|
-
super({ ...defaults$
|
|
8799
|
+
super({ ...defaults$7, ...options });
|
|
8790
8800
|
this.target = this.options.target;
|
|
8791
8801
|
}
|
|
8792
8802
|
static schema() {
|
|
@@ -8959,7 +8969,7 @@ class SvgFocusable extends Rule {
|
|
|
8959
8969
|
}
|
|
8960
8970
|
}
|
|
8961
8971
|
|
|
8962
|
-
const defaults$
|
|
8972
|
+
const defaults$6 = {
|
|
8963
8973
|
characters: [
|
|
8964
8974
|
{ pattern: " ", replacement: " ", description: "non-breaking space" },
|
|
8965
8975
|
{ pattern: "-", replacement: "‑", description: "non-breaking hyphen" }
|
|
@@ -8991,7 +9001,7 @@ function matchAll(text, regexp) {
|
|
|
8991
9001
|
class TelNonBreaking extends Rule {
|
|
8992
9002
|
regex;
|
|
8993
9003
|
constructor(options) {
|
|
8994
|
-
super({ ...defaults$
|
|
9004
|
+
super({ ...defaults$6, ...options });
|
|
8995
9005
|
this.regex = constructRegex(this.options.characters);
|
|
8996
9006
|
}
|
|
8997
9007
|
static schema() {
|
|
@@ -9366,7 +9376,7 @@ class UniqueLandmark extends Rule {
|
|
|
9366
9376
|
}
|
|
9367
9377
|
}
|
|
9368
9378
|
|
|
9369
|
-
const defaults$
|
|
9379
|
+
const defaults$5 = {
|
|
9370
9380
|
ignoreCase: false,
|
|
9371
9381
|
requireSemicolon: true
|
|
9372
9382
|
};
|
|
@@ -9400,7 +9410,7 @@ function getDescription(context, options) {
|
|
|
9400
9410
|
}
|
|
9401
9411
|
class UnknownCharReference extends Rule {
|
|
9402
9412
|
constructor(options) {
|
|
9403
|
-
super({ ...defaults$
|
|
9413
|
+
super({ ...defaults$5, ...options });
|
|
9404
9414
|
}
|
|
9405
9415
|
static schema() {
|
|
9406
9416
|
return {
|
|
@@ -10016,12 +10026,12 @@ class ValidAutocomplete extends Rule {
|
|
|
10016
10026
|
}
|
|
10017
10027
|
}
|
|
10018
10028
|
|
|
10019
|
-
const defaults$
|
|
10029
|
+
const defaults$4 = {
|
|
10020
10030
|
relaxed: false
|
|
10021
10031
|
};
|
|
10022
10032
|
class ValidID extends Rule {
|
|
10023
10033
|
constructor(options) {
|
|
10024
|
-
super({ ...defaults$
|
|
10034
|
+
super({ ...defaults$4, ...options });
|
|
10025
10035
|
}
|
|
10026
10036
|
static schema() {
|
|
10027
10037
|
return {
|
|
@@ -10127,13 +10137,13 @@ class VoidContent extends Rule {
|
|
|
10127
10137
|
}
|
|
10128
10138
|
}
|
|
10129
10139
|
|
|
10130
|
-
const defaults$
|
|
10140
|
+
const defaults$3 = {
|
|
10131
10141
|
style: "omit"
|
|
10132
10142
|
};
|
|
10133
10143
|
class VoidStyle extends Rule {
|
|
10134
10144
|
style;
|
|
10135
10145
|
constructor(options) {
|
|
10136
|
-
super({ ...defaults$
|
|
10146
|
+
super({ ...defaults$3, ...options });
|
|
10137
10147
|
this.style = parseStyle(this.options.style);
|
|
10138
10148
|
}
|
|
10139
10149
|
static schema() {
|
|
@@ -10334,13 +10344,13 @@ class H36 extends Rule {
|
|
|
10334
10344
|
}
|
|
10335
10345
|
}
|
|
10336
10346
|
|
|
10337
|
-
const defaults$
|
|
10347
|
+
const defaults$2 = {
|
|
10338
10348
|
allowEmpty: true,
|
|
10339
10349
|
alias: []
|
|
10340
10350
|
};
|
|
10341
10351
|
class H37 extends Rule {
|
|
10342
10352
|
constructor(options) {
|
|
10343
|
-
super({ ...defaults$
|
|
10353
|
+
super({ ...defaults$2, ...options });
|
|
10344
10354
|
if (!Array.isArray(this.options.alias)) {
|
|
10345
10355
|
this.options.alias = [this.options.alias];
|
|
10346
10356
|
}
|
|
@@ -10402,9 +10412,62 @@ class H37 extends Rule {
|
|
|
10402
10412
|
}
|
|
10403
10413
|
}
|
|
10404
10414
|
|
|
10415
|
+
const defaults$1 = {
|
|
10416
|
+
strict: false
|
|
10417
|
+
};
|
|
10405
10418
|
const { enum: validScopes } = html5.th.attributes?.scope;
|
|
10406
10419
|
const joinedScopes = naturalJoin(validScopes);
|
|
10420
|
+
const td = 0;
|
|
10421
|
+
const th = 1;
|
|
10422
|
+
function getShape(cells) {
|
|
10423
|
+
const rows = cells.length;
|
|
10424
|
+
const cols = cells[0].length;
|
|
10425
|
+
return { rows, cols };
|
|
10426
|
+
}
|
|
10427
|
+
function isSimpleTable(table) {
|
|
10428
|
+
const haveHeadersAttr = table.querySelector("> tr > [headers], > tbody > tr > [headers]");
|
|
10429
|
+
if (haveHeadersAttr) {
|
|
10430
|
+
return false;
|
|
10431
|
+
}
|
|
10432
|
+
const rows = table.querySelectorAll("> tr, > thead > tr, > tbody > tr");
|
|
10433
|
+
if (rows.length === 0) {
|
|
10434
|
+
return false;
|
|
10435
|
+
}
|
|
10436
|
+
const cells = rows.map((tr) => tr.querySelectorAll("> *").map((el) => el.is("th") ? th : td));
|
|
10437
|
+
if (cells[0].length === 0) {
|
|
10438
|
+
return false;
|
|
10439
|
+
}
|
|
10440
|
+
const numColumns = cells[0].length;
|
|
10441
|
+
if (!cells.every((row) => row.length === numColumns)) {
|
|
10442
|
+
return false;
|
|
10443
|
+
}
|
|
10444
|
+
const shape = getShape(cells);
|
|
10445
|
+
const headersPerRow = cells.map((row) => row.reduce((sum, cell) => sum + cell, 0));
|
|
10446
|
+
const headersPerColumn = Array(shape.cols).fill(0).map((_, index) => {
|
|
10447
|
+
return cells.reduce((sum, it) => sum + it[index], 0);
|
|
10448
|
+
});
|
|
10449
|
+
const [firstRow, ...otherRows] = headersPerRow;
|
|
10450
|
+
if (firstRow === shape.cols && otherRows.every((row) => row === 0)) {
|
|
10451
|
+
return true;
|
|
10452
|
+
}
|
|
10453
|
+
const [firstCol, ...otherCols] = headersPerColumn;
|
|
10454
|
+
const haveThead = Boolean(table.querySelector("> thead"));
|
|
10455
|
+
if (firstCol === shape.rows && otherCols.every((col) => col === 0) && !haveThead) {
|
|
10456
|
+
return true;
|
|
10457
|
+
}
|
|
10458
|
+
return false;
|
|
10459
|
+
}
|
|
10407
10460
|
class H63 extends Rule {
|
|
10461
|
+
constructor(options) {
|
|
10462
|
+
super({ ...defaults$1, ...options });
|
|
10463
|
+
}
|
|
10464
|
+
static schema() {
|
|
10465
|
+
return {
|
|
10466
|
+
strict: {
|
|
10467
|
+
type: "boolean"
|
|
10468
|
+
}
|
|
10469
|
+
};
|
|
10470
|
+
}
|
|
10408
10471
|
documentation() {
|
|
10409
10472
|
return {
|
|
10410
10473
|
description: "H63: Using the scope attribute to associate header cells and data cells in data tables",
|
|
@@ -10412,23 +10475,31 @@ class H63 extends Rule {
|
|
|
10412
10475
|
};
|
|
10413
10476
|
}
|
|
10414
10477
|
setup() {
|
|
10415
|
-
|
|
10478
|
+
const { strict } = this.options;
|
|
10479
|
+
this.on("element:ready", (event) => {
|
|
10416
10480
|
const node = event.target;
|
|
10417
|
-
if (node.
|
|
10481
|
+
if (!node.is("table")) {
|
|
10418
10482
|
return;
|
|
10419
10483
|
}
|
|
10420
|
-
|
|
10484
|
+
if (strict || !isSimpleTable(node)) {
|
|
10485
|
+
this.validateTable(node);
|
|
10486
|
+
}
|
|
10487
|
+
});
|
|
10488
|
+
}
|
|
10489
|
+
validateTable(node) {
|
|
10490
|
+
for (const th2 of node.querySelectorAll("th")) {
|
|
10491
|
+
const scope = th2.getAttribute("scope");
|
|
10421
10492
|
const value = scope?.value;
|
|
10422
10493
|
if (value instanceof DynamicValue) {
|
|
10423
|
-
|
|
10494
|
+
continue;
|
|
10424
10495
|
}
|
|
10425
10496
|
if (value && validScopes.includes(value)) {
|
|
10426
|
-
|
|
10497
|
+
continue;
|
|
10427
10498
|
}
|
|
10428
10499
|
const message = `<th> element must have a valid scope attribute: ${joinedScopes}`;
|
|
10429
|
-
const location = scope?.valueLocation ?? scope?.keyLocation ??
|
|
10430
|
-
this.report(
|
|
10431
|
-
}
|
|
10500
|
+
const location = scope?.valueLocation ?? scope?.keyLocation ?? th2.location;
|
|
10501
|
+
this.report(th2, message, location);
|
|
10502
|
+
}
|
|
10432
10503
|
}
|
|
10433
10504
|
}
|
|
10434
10505
|
|
|
@@ -11720,7 +11791,7 @@ class EventHandler {
|
|
|
11720
11791
|
}
|
|
11721
11792
|
|
|
11722
11793
|
const name = "html-validate";
|
|
11723
|
-
const version = "9.
|
|
11794
|
+
const version = "9.7.0";
|
|
11724
11795
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11725
11796
|
|
|
11726
11797
|
function freeze(src) {
|