html-validate 10.6.0 → 10.8.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 +229 -64
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/esm/browser.js +1 -1
- package/dist/esm/cli.js +2 -2
- package/dist/esm/core-browser.js +1 -1
- package/dist/esm/core-nodejs.js +1 -1
- package/dist/esm/core.js +230 -65
- package/dist/esm/core.js.map +1 -1
- package/dist/esm/html-validate.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/matchers.js +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/package.json +1 -1
package/dist/cjs/core.js
CHANGED
|
@@ -4008,7 +4008,7 @@ class Rule {
|
|
|
4008
4008
|
}
|
|
4009
4009
|
}
|
|
4010
4010
|
|
|
4011
|
-
const defaults$
|
|
4011
|
+
const defaults$A = {
|
|
4012
4012
|
allowExternal: true,
|
|
4013
4013
|
allowRelative: true,
|
|
4014
4014
|
allowAbsolute: true,
|
|
@@ -4052,7 +4052,7 @@ class AllowedLinks extends Rule {
|
|
|
4052
4052
|
allowRelative;
|
|
4053
4053
|
allowAbsolute;
|
|
4054
4054
|
constructor(options) {
|
|
4055
|
-
super({ ...defaults$
|
|
4055
|
+
super({ ...defaults$A, ...options });
|
|
4056
4056
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
4057
4057
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
4058
4058
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -4220,7 +4220,7 @@ class AllowedLinks extends Rule {
|
|
|
4220
4220
|
}
|
|
4221
4221
|
}
|
|
4222
4222
|
|
|
4223
|
-
const defaults$
|
|
4223
|
+
const defaults$z = {
|
|
4224
4224
|
accessible: true
|
|
4225
4225
|
};
|
|
4226
4226
|
function findByTarget(target, siblings) {
|
|
@@ -4250,7 +4250,7 @@ function getDescription$1(context) {
|
|
|
4250
4250
|
}
|
|
4251
4251
|
class AreaAlt extends Rule {
|
|
4252
4252
|
constructor(options) {
|
|
4253
|
-
super({ ...defaults$
|
|
4253
|
+
super({ ...defaults$z, ...options });
|
|
4254
4254
|
}
|
|
4255
4255
|
static schema() {
|
|
4256
4256
|
return {
|
|
@@ -4329,8 +4329,12 @@ class AriaHiddenBody extends Rule {
|
|
|
4329
4329
|
}
|
|
4330
4330
|
}
|
|
4331
4331
|
|
|
4332
|
-
const defaults$
|
|
4333
|
-
allowAnyNamable: false
|
|
4332
|
+
const defaults$y = {
|
|
4333
|
+
allowAnyNamable: false,
|
|
4334
|
+
elements: {
|
|
4335
|
+
include: null,
|
|
4336
|
+
exclude: null
|
|
4337
|
+
}
|
|
4334
4338
|
};
|
|
4335
4339
|
const allowlist = /* @__PURE__ */ new Set([
|
|
4336
4340
|
"main",
|
|
@@ -4373,7 +4377,26 @@ function isValidUsage(target, meta) {
|
|
|
4373
4377
|
}
|
|
4374
4378
|
class AriaLabelMisuse extends Rule {
|
|
4375
4379
|
constructor(options) {
|
|
4376
|
-
super({ ...defaults$
|
|
4380
|
+
super({ ...defaults$y, ...options });
|
|
4381
|
+
}
|
|
4382
|
+
static schema() {
|
|
4383
|
+
return {
|
|
4384
|
+
allowAnyNamable: {
|
|
4385
|
+
type: "boolean"
|
|
4386
|
+
},
|
|
4387
|
+
elements: {
|
|
4388
|
+
type: "object",
|
|
4389
|
+
properties: {
|
|
4390
|
+
include: {
|
|
4391
|
+
anyOf: [{ type: "array", items: { type: "string" } }, { type: "null" }]
|
|
4392
|
+
},
|
|
4393
|
+
exclude: {
|
|
4394
|
+
anyOf: [{ type: "array", items: { type: "string" } }, { type: "null" }]
|
|
4395
|
+
}
|
|
4396
|
+
},
|
|
4397
|
+
additionalProperties: false
|
|
4398
|
+
}
|
|
4399
|
+
};
|
|
4377
4400
|
}
|
|
4378
4401
|
documentation(context) {
|
|
4379
4402
|
const valid = [
|
|
@@ -4431,6 +4454,9 @@ class AriaLabelMisuse extends Rule {
|
|
|
4431
4454
|
if (!meta) {
|
|
4432
4455
|
return;
|
|
4433
4456
|
}
|
|
4457
|
+
if (this.shouldIgnoreElement(target)) {
|
|
4458
|
+
return;
|
|
4459
|
+
}
|
|
4434
4460
|
if (isValidUsage(target, meta)) {
|
|
4435
4461
|
return;
|
|
4436
4462
|
}
|
|
@@ -4455,6 +4481,9 @@ class AriaLabelMisuse extends Rule {
|
|
|
4455
4481
|
});
|
|
4456
4482
|
}
|
|
4457
4483
|
}
|
|
4484
|
+
shouldIgnoreElement(target) {
|
|
4485
|
+
return isKeywordIgnored(this.options.elements, target.tagName, keywordPatternMatcher);
|
|
4486
|
+
}
|
|
4458
4487
|
}
|
|
4459
4488
|
|
|
4460
4489
|
class ConfigError extends UserError {
|
|
@@ -4517,14 +4546,14 @@ class CaseStyle {
|
|
|
4517
4546
|
}
|
|
4518
4547
|
}
|
|
4519
4548
|
|
|
4520
|
-
const defaults$
|
|
4549
|
+
const defaults$x = {
|
|
4521
4550
|
style: "lowercase",
|
|
4522
4551
|
ignoreForeign: true
|
|
4523
4552
|
};
|
|
4524
4553
|
class AttrCase extends Rule {
|
|
4525
4554
|
style;
|
|
4526
4555
|
constructor(options) {
|
|
4527
|
-
super({ ...defaults$
|
|
4556
|
+
super({ ...defaults$x, ...options });
|
|
4528
4557
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4529
4558
|
}
|
|
4530
4559
|
static schema() {
|
|
@@ -4631,7 +4660,7 @@ const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
|
|
|
4631
4660
|
const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
|
|
4632
4661
|
const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
|
|
4633
4662
|
const MATCH_TITLE_END = /^<(\/)(title)/;
|
|
4634
|
-
const MATCH_DIRECTIVE = /^(<!--\s*\[html-validate-)([a-z0-9-]+)(\s*)(.*?)(]?\s*-->)/;
|
|
4663
|
+
const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([a-z0-9-]+)(\s*)(.*?)(]?\s*-->)/;
|
|
4635
4664
|
const MATCH_COMMENT = /^<!--([^]*?)-->/;
|
|
4636
4665
|
const MATCH_CONDITIONAL = /^<!\[([^\]]*?)\]>/;
|
|
4637
4666
|
class InvalidTokenError extends Error {
|
|
@@ -4929,7 +4958,7 @@ class AttrDelimiter extends Rule {
|
|
|
4929
4958
|
}
|
|
4930
4959
|
|
|
4931
4960
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4932
|
-
const defaults$
|
|
4961
|
+
const defaults$w = {
|
|
4933
4962
|
pattern: DEFAULT_PATTERN,
|
|
4934
4963
|
ignoreForeign: true
|
|
4935
4964
|
};
|
|
@@ -4962,7 +4991,7 @@ function generateDescription(name, pattern) {
|
|
|
4962
4991
|
class AttrPattern extends Rule {
|
|
4963
4992
|
pattern;
|
|
4964
4993
|
constructor(options) {
|
|
4965
|
-
super({ ...defaults$
|
|
4994
|
+
super({ ...defaults$w, ...options });
|
|
4966
4995
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4967
4996
|
}
|
|
4968
4997
|
static schema() {
|
|
@@ -5009,7 +5038,7 @@ class AttrPattern extends Rule {
|
|
|
5009
5038
|
}
|
|
5010
5039
|
}
|
|
5011
5040
|
|
|
5012
|
-
const defaults$
|
|
5041
|
+
const defaults$v = {
|
|
5013
5042
|
style: "auto",
|
|
5014
5043
|
unquoted: false
|
|
5015
5044
|
};
|
|
@@ -5075,7 +5104,7 @@ class AttrQuotes extends Rule {
|
|
|
5075
5104
|
};
|
|
5076
5105
|
}
|
|
5077
5106
|
constructor(options) {
|
|
5078
|
-
super({ ...defaults$
|
|
5107
|
+
super({ ...defaults$v, ...options });
|
|
5079
5108
|
this.style = parseStyle$3(this.options.style);
|
|
5080
5109
|
}
|
|
5081
5110
|
setup() {
|
|
@@ -5231,13 +5260,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
5231
5260
|
}
|
|
5232
5261
|
}
|
|
5233
5262
|
|
|
5234
|
-
const defaults$
|
|
5263
|
+
const defaults$u = {
|
|
5235
5264
|
style: "omit"
|
|
5236
5265
|
};
|
|
5237
5266
|
class AttributeBooleanStyle extends Rule {
|
|
5238
5267
|
hasInvalidStyle;
|
|
5239
5268
|
constructor(options) {
|
|
5240
|
-
super({ ...defaults$
|
|
5269
|
+
super({ ...defaults$u, ...options });
|
|
5241
5270
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
5242
5271
|
}
|
|
5243
5272
|
static schema() {
|
|
@@ -5307,13 +5336,13 @@ function reportMessage$1(attr, style) {
|
|
|
5307
5336
|
return "";
|
|
5308
5337
|
}
|
|
5309
5338
|
|
|
5310
|
-
const defaults$
|
|
5339
|
+
const defaults$t = {
|
|
5311
5340
|
style: "omit"
|
|
5312
5341
|
};
|
|
5313
5342
|
class AttributeEmptyStyle extends Rule {
|
|
5314
5343
|
hasInvalidStyle;
|
|
5315
5344
|
constructor(options) {
|
|
5316
|
-
super({ ...defaults$
|
|
5345
|
+
super({ ...defaults$t, ...options });
|
|
5317
5346
|
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
5318
5347
|
}
|
|
5319
5348
|
static schema() {
|
|
@@ -5430,6 +5459,122 @@ class AttributeMisuse extends Rule {
|
|
|
5430
5459
|
}
|
|
5431
5460
|
}
|
|
5432
5461
|
|
|
5462
|
+
const defaults$s = {
|
|
5463
|
+
preferred: void 0
|
|
5464
|
+
};
|
|
5465
|
+
function isPasswordInput(event) {
|
|
5466
|
+
const { target } = event;
|
|
5467
|
+
if (!target.is("input")) {
|
|
5468
|
+
return false;
|
|
5469
|
+
}
|
|
5470
|
+
const type = target.getAttribute("type");
|
|
5471
|
+
return type?.value?.toString().toLowerCase() === "password";
|
|
5472
|
+
}
|
|
5473
|
+
function isGroupingToken(token) {
|
|
5474
|
+
return token.startsWith("section-") || token === "shipping" || token === "billing";
|
|
5475
|
+
}
|
|
5476
|
+
class AutocompletePassword extends Rule {
|
|
5477
|
+
preferred;
|
|
5478
|
+
constructor(options) {
|
|
5479
|
+
super({ ...defaults$s, ...options });
|
|
5480
|
+
this.preferred = options.preferred?.toLowerCase();
|
|
5481
|
+
}
|
|
5482
|
+
static schema() {
|
|
5483
|
+
return {
|
|
5484
|
+
preferred: {
|
|
5485
|
+
type: "string"
|
|
5486
|
+
}
|
|
5487
|
+
};
|
|
5488
|
+
}
|
|
5489
|
+
documentation(context) {
|
|
5490
|
+
const url = "https://html-validate.org/rules/autocomplete-password.html";
|
|
5491
|
+
switch (context.kind) {
|
|
5492
|
+
case "preferred-mismatch":
|
|
5493
|
+
return {
|
|
5494
|
+
description: [
|
|
5495
|
+
`\`<input type="password">\` should use \`autocomplete="${context.preferred}"\`.`,
|
|
5496
|
+
"",
|
|
5497
|
+
`The configured preferred autocomplete value is \`"${context.preferred}"\` but the element uses \`"${context.value}"\`.`
|
|
5498
|
+
].join("\n"),
|
|
5499
|
+
url
|
|
5500
|
+
};
|
|
5501
|
+
case "off":
|
|
5502
|
+
case "missing":
|
|
5503
|
+
default: {
|
|
5504
|
+
const error = context.kind === "off" ? '`<input type="password">` should not use `autocomplete="off"`.' : '`<input type="password">` must have the `autocomplete` attribute.';
|
|
5505
|
+
return {
|
|
5506
|
+
description: [
|
|
5507
|
+
error,
|
|
5508
|
+
"",
|
|
5509
|
+
"Browsers and password managers often ignore the absence of autocomplete and autofill password fields anyway, which can lead to unexpected behavior where users unknowingly submit autofilled passwords for unrelated fields.",
|
|
5510
|
+
"",
|
|
5511
|
+
"Use one of the following values:",
|
|
5512
|
+
"",
|
|
5513
|
+
'- `autocomplete="new-password"` for password creation forms',
|
|
5514
|
+
'- `autocomplete="current-password"` for login forms'
|
|
5515
|
+
].join("\n"),
|
|
5516
|
+
url
|
|
5517
|
+
};
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
setup() {
|
|
5522
|
+
this.on("tag:ready", isPasswordInput, (event) => {
|
|
5523
|
+
const { preferred } = this;
|
|
5524
|
+
const { target } = event;
|
|
5525
|
+
const autocomplete = target.getAttribute("autocomplete");
|
|
5526
|
+
if (!autocomplete) {
|
|
5527
|
+
const context = { kind: "missing" };
|
|
5528
|
+
this.report({
|
|
5529
|
+
node: target,
|
|
5530
|
+
message: '<input type="password"> is missing required "autocomplete" attribute',
|
|
5531
|
+
location: target.location,
|
|
5532
|
+
context
|
|
5533
|
+
});
|
|
5534
|
+
return;
|
|
5535
|
+
}
|
|
5536
|
+
if (autocomplete.isDynamic || !autocomplete.value) {
|
|
5537
|
+
return;
|
|
5538
|
+
}
|
|
5539
|
+
const raw = autocomplete.value.toString().toLowerCase();
|
|
5540
|
+
const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
|
|
5541
|
+
const index = tokens.findIndex((token) => !isGroupingToken(token));
|
|
5542
|
+
const value = tokens.item(index);
|
|
5543
|
+
const location = tokens.location(index);
|
|
5544
|
+
if (!value) {
|
|
5545
|
+
return;
|
|
5546
|
+
}
|
|
5547
|
+
if (value === "off") {
|
|
5548
|
+
const context = { kind: "off" };
|
|
5549
|
+
this.report({
|
|
5550
|
+
node: target,
|
|
5551
|
+
message: '<input type="password"> should not use autocomplete="off"',
|
|
5552
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- location must be present if value is */
|
|
5553
|
+
location,
|
|
5554
|
+
context
|
|
5555
|
+
});
|
|
5556
|
+
return;
|
|
5557
|
+
}
|
|
5558
|
+
if (preferred) {
|
|
5559
|
+
if (value !== preferred) {
|
|
5560
|
+
const context = {
|
|
5561
|
+
kind: "preferred-mismatch",
|
|
5562
|
+
value,
|
|
5563
|
+
preferred
|
|
5564
|
+
};
|
|
5565
|
+
this.report({
|
|
5566
|
+
node: target,
|
|
5567
|
+
message: `<input type="password"> should use autocomplete="${preferred}"`,
|
|
5568
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- location must be present if value is */
|
|
5569
|
+
location,
|
|
5570
|
+
context
|
|
5571
|
+
});
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
});
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
|
|
5433
5578
|
const patternNamesValues = [
|
|
5434
5579
|
"kebabcase",
|
|
5435
5580
|
"camelcase",
|
|
@@ -5561,7 +5706,7 @@ class BasePatternRule extends Rule {
|
|
|
5561
5706
|
}
|
|
5562
5707
|
}
|
|
5563
5708
|
|
|
5564
|
-
const defaults$
|
|
5709
|
+
const defaults$r = {
|
|
5565
5710
|
pattern: "kebabcase"
|
|
5566
5711
|
};
|
|
5567
5712
|
class ClassPattern extends BasePatternRule {
|
|
@@ -5569,7 +5714,7 @@ class ClassPattern extends BasePatternRule {
|
|
|
5569
5714
|
super({
|
|
5570
5715
|
ruleId: "class-pattern",
|
|
5571
5716
|
attr: "class",
|
|
5572
|
-
options: { ...defaults$
|
|
5717
|
+
options: { ...defaults$r, ...options },
|
|
5573
5718
|
allowedPatterns: patternNames
|
|
5574
5719
|
// allow all patterns
|
|
5575
5720
|
});
|
|
@@ -5719,13 +5864,13 @@ class CloseOrder extends Rule {
|
|
|
5719
5864
|
}
|
|
5720
5865
|
}
|
|
5721
5866
|
|
|
5722
|
-
const defaults$
|
|
5867
|
+
const defaults$q = {
|
|
5723
5868
|
include: null,
|
|
5724
5869
|
exclude: null
|
|
5725
5870
|
};
|
|
5726
5871
|
class Deprecated extends Rule {
|
|
5727
5872
|
constructor(options) {
|
|
5728
|
-
super({ ...defaults$
|
|
5873
|
+
super({ ...defaults$q, ...options });
|
|
5729
5874
|
}
|
|
5730
5875
|
static schema() {
|
|
5731
5876
|
return {
|
|
@@ -5879,12 +6024,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5879
6024
|
}
|
|
5880
6025
|
};
|
|
5881
6026
|
|
|
5882
|
-
const defaults$
|
|
6027
|
+
const defaults$p = {
|
|
5883
6028
|
style: "uppercase"
|
|
5884
6029
|
};
|
|
5885
6030
|
class DoctypeStyle extends Rule {
|
|
5886
6031
|
constructor(options) {
|
|
5887
|
-
super({ ...defaults$
|
|
6032
|
+
super({ ...defaults$p, ...options });
|
|
5888
6033
|
}
|
|
5889
6034
|
static schema() {
|
|
5890
6035
|
return {
|
|
@@ -5912,13 +6057,13 @@ class DoctypeStyle extends Rule {
|
|
|
5912
6057
|
}
|
|
5913
6058
|
}
|
|
5914
6059
|
|
|
5915
|
-
const defaults$
|
|
6060
|
+
const defaults$o = {
|
|
5916
6061
|
style: "lowercase"
|
|
5917
6062
|
};
|
|
5918
6063
|
class ElementCase extends Rule {
|
|
5919
6064
|
style;
|
|
5920
6065
|
constructor(options) {
|
|
5921
|
-
super({ ...defaults$
|
|
6066
|
+
super({ ...defaults$o, ...options });
|
|
5922
6067
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
5923
6068
|
}
|
|
5924
6069
|
static schema() {
|
|
@@ -5978,7 +6123,7 @@ class ElementCase extends Rule {
|
|
|
5978
6123
|
}
|
|
5979
6124
|
}
|
|
5980
6125
|
|
|
5981
|
-
const defaults$
|
|
6126
|
+
const defaults$n = {
|
|
5982
6127
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5983
6128
|
whitelist: [],
|
|
5984
6129
|
blacklist: []
|
|
@@ -5986,7 +6131,7 @@ const defaults$m = {
|
|
|
5986
6131
|
class ElementName extends Rule {
|
|
5987
6132
|
pattern;
|
|
5988
6133
|
constructor(options) {
|
|
5989
|
-
super({ ...defaults$
|
|
6134
|
+
super({ ...defaults$n, ...options });
|
|
5990
6135
|
this.pattern = new RegExp(this.options.pattern);
|
|
5991
6136
|
}
|
|
5992
6137
|
static schema() {
|
|
@@ -6023,7 +6168,7 @@ class ElementName extends Rule {
|
|
|
6023
6168
|
...context.blacklist.map((cur) => `- ${cur}`)
|
|
6024
6169
|
];
|
|
6025
6170
|
}
|
|
6026
|
-
if (context.pattern !== defaults$
|
|
6171
|
+
if (context.pattern !== defaults$n.pattern) {
|
|
6027
6172
|
return [
|
|
6028
6173
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
6029
6174
|
"",
|
|
@@ -6540,7 +6685,7 @@ class EmptyTitle extends Rule {
|
|
|
6540
6685
|
}
|
|
6541
6686
|
}
|
|
6542
6687
|
|
|
6543
|
-
const defaults$
|
|
6688
|
+
const defaults$m = {
|
|
6544
6689
|
allowArrayBrackets: true,
|
|
6545
6690
|
allowCheckboxDefault: true,
|
|
6546
6691
|
shared: ["radio", "button", "reset", "submit"]
|
|
@@ -6600,7 +6745,7 @@ function getDocumentation(context) {
|
|
|
6600
6745
|
}
|
|
6601
6746
|
class FormDupName extends Rule {
|
|
6602
6747
|
constructor(options) {
|
|
6603
|
-
super({ ...defaults$
|
|
6748
|
+
super({ ...defaults$m, ...options });
|
|
6604
6749
|
}
|
|
6605
6750
|
static schema() {
|
|
6606
6751
|
return {
|
|
@@ -6759,7 +6904,7 @@ class FormDupName extends Rule {
|
|
|
6759
6904
|
}
|
|
6760
6905
|
}
|
|
6761
6906
|
|
|
6762
|
-
const defaults$
|
|
6907
|
+
const defaults$l = {
|
|
6763
6908
|
allowMultipleH1: false,
|
|
6764
6909
|
minInitialRank: "h1",
|
|
6765
6910
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
|
|
@@ -6791,7 +6936,7 @@ class HeadingLevel extends Rule {
|
|
|
6791
6936
|
sectionRoots;
|
|
6792
6937
|
stack = [];
|
|
6793
6938
|
constructor(options) {
|
|
6794
|
-
super({ ...defaults$
|
|
6939
|
+
super({ ...defaults$l, ...options });
|
|
6795
6940
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
6796
6941
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
|
|
6797
6942
|
this.stack.push({
|
|
@@ -7030,7 +7175,7 @@ class HiddenFocusable extends Rule {
|
|
|
7030
7175
|
}
|
|
7031
7176
|
}
|
|
7032
7177
|
|
|
7033
|
-
const defaults$
|
|
7178
|
+
const defaults$k = {
|
|
7034
7179
|
pattern: "kebabcase"
|
|
7035
7180
|
};
|
|
7036
7181
|
function exclude$1(set, ...values) {
|
|
@@ -7046,7 +7191,7 @@ class IdPattern extends BasePatternRule {
|
|
|
7046
7191
|
super({
|
|
7047
7192
|
ruleId: "id-pattern",
|
|
7048
7193
|
attr: "id",
|
|
7049
|
-
options: { ...defaults$
|
|
7194
|
+
options: { ...defaults$k, ...options },
|
|
7050
7195
|
allowedPatterns
|
|
7051
7196
|
});
|
|
7052
7197
|
}
|
|
@@ -7368,13 +7513,13 @@ function findLabelByParent(el) {
|
|
|
7368
7513
|
return [];
|
|
7369
7514
|
}
|
|
7370
7515
|
|
|
7371
|
-
const defaults$
|
|
7516
|
+
const defaults$j = {
|
|
7372
7517
|
maxlength: 70
|
|
7373
7518
|
};
|
|
7374
7519
|
class LongTitle extends Rule {
|
|
7375
7520
|
maxlength;
|
|
7376
7521
|
constructor(options) {
|
|
7377
|
-
super({ ...defaults$
|
|
7522
|
+
super({ ...defaults$j, ...options });
|
|
7378
7523
|
this.maxlength = this.options.maxlength;
|
|
7379
7524
|
}
|
|
7380
7525
|
static schema() {
|
|
@@ -7478,12 +7623,12 @@ class MapIdName extends Rule {
|
|
|
7478
7623
|
}
|
|
7479
7624
|
}
|
|
7480
7625
|
|
|
7481
|
-
const defaults$
|
|
7626
|
+
const defaults$i = {
|
|
7482
7627
|
allowLongDelay: false
|
|
7483
7628
|
};
|
|
7484
7629
|
class MetaRefresh extends Rule {
|
|
7485
7630
|
constructor(options) {
|
|
7486
|
-
super({ ...defaults$
|
|
7631
|
+
super({ ...defaults$i, ...options });
|
|
7487
7632
|
}
|
|
7488
7633
|
documentation() {
|
|
7489
7634
|
return {
|
|
@@ -7594,7 +7739,7 @@ class MultipleLabeledControls extends Rule {
|
|
|
7594
7739
|
}
|
|
7595
7740
|
}
|
|
7596
7741
|
|
|
7597
|
-
const defaults$
|
|
7742
|
+
const defaults$h = {
|
|
7598
7743
|
pattern: "camelcase"
|
|
7599
7744
|
};
|
|
7600
7745
|
function exclude(set, ...values) {
|
|
@@ -7610,7 +7755,7 @@ class NamePattern extends BasePatternRule {
|
|
|
7610
7755
|
super({
|
|
7611
7756
|
ruleId: "name-pattern",
|
|
7612
7757
|
attr: "name",
|
|
7613
|
-
options: { ...defaults$
|
|
7758
|
+
options: { ...defaults$h, ...options },
|
|
7614
7759
|
allowedPatterns
|
|
7615
7760
|
});
|
|
7616
7761
|
}
|
|
@@ -7701,13 +7846,13 @@ class NoAbstractRole extends Rule {
|
|
|
7701
7846
|
}
|
|
7702
7847
|
}
|
|
7703
7848
|
|
|
7704
|
-
const defaults$
|
|
7849
|
+
const defaults$g = {
|
|
7705
7850
|
include: null,
|
|
7706
7851
|
exclude: null
|
|
7707
7852
|
};
|
|
7708
7853
|
class NoAutoplay extends Rule {
|
|
7709
7854
|
constructor(options) {
|
|
7710
|
-
super({ ...defaults$
|
|
7855
|
+
super({ ...defaults$g, ...options });
|
|
7711
7856
|
}
|
|
7712
7857
|
documentation(context) {
|
|
7713
7858
|
return {
|
|
@@ -8029,14 +8174,14 @@ class NoImplicitInputType extends Rule {
|
|
|
8029
8174
|
}
|
|
8030
8175
|
}
|
|
8031
8176
|
|
|
8032
|
-
const defaults$
|
|
8177
|
+
const defaults$f = {
|
|
8033
8178
|
include: null,
|
|
8034
8179
|
exclude: null,
|
|
8035
8180
|
allowedProperties: ["display"]
|
|
8036
8181
|
};
|
|
8037
8182
|
class NoInlineStyle extends Rule {
|
|
8038
8183
|
constructor(options) {
|
|
8039
|
-
super({ ...defaults$
|
|
8184
|
+
super({ ...defaults$f, ...options });
|
|
8040
8185
|
}
|
|
8041
8186
|
static schema() {
|
|
8042
8187
|
return {
|
|
@@ -8222,7 +8367,7 @@ class NoMultipleMain extends Rule {
|
|
|
8222
8367
|
}
|
|
8223
8368
|
}
|
|
8224
8369
|
|
|
8225
|
-
const defaults$
|
|
8370
|
+
const defaults$e = {
|
|
8226
8371
|
relaxed: false
|
|
8227
8372
|
};
|
|
8228
8373
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -8240,7 +8385,7 @@ const replacementTable = {
|
|
|
8240
8385
|
class NoRawCharacters extends Rule {
|
|
8241
8386
|
relaxed;
|
|
8242
8387
|
constructor(options) {
|
|
8243
|
-
super({ ...defaults$
|
|
8388
|
+
super({ ...defaults$e, ...options });
|
|
8244
8389
|
this.relaxed = this.options.relaxed;
|
|
8245
8390
|
}
|
|
8246
8391
|
static schema() {
|
|
@@ -8420,13 +8565,13 @@ class NoRedundantRole extends Rule {
|
|
|
8420
8565
|
}
|
|
8421
8566
|
|
|
8422
8567
|
const xmlns = /^(.+):.+$/;
|
|
8423
|
-
const defaults$
|
|
8568
|
+
const defaults$d = {
|
|
8424
8569
|
ignoreForeign: true,
|
|
8425
8570
|
ignoreXML: true
|
|
8426
8571
|
};
|
|
8427
8572
|
class NoSelfClosing extends Rule {
|
|
8428
8573
|
constructor(options) {
|
|
8429
|
-
super({ ...defaults$
|
|
8574
|
+
super({ ...defaults$d, ...options });
|
|
8430
8575
|
}
|
|
8431
8576
|
static schema() {
|
|
8432
8577
|
return {
|
|
@@ -8476,7 +8621,20 @@ function isRelevant(node, options) {
|
|
|
8476
8621
|
return true;
|
|
8477
8622
|
}
|
|
8478
8623
|
|
|
8624
|
+
const defaults$c = {
|
|
8625
|
+
allowTemplate: true
|
|
8626
|
+
};
|
|
8479
8627
|
class NoStyleTag extends Rule {
|
|
8628
|
+
constructor(options) {
|
|
8629
|
+
super({ ...defaults$c, ...options });
|
|
8630
|
+
}
|
|
8631
|
+
static schema() {
|
|
8632
|
+
return {
|
|
8633
|
+
allowTemplate: {
|
|
8634
|
+
type: "boolean"
|
|
8635
|
+
}
|
|
8636
|
+
};
|
|
8637
|
+
}
|
|
8480
8638
|
documentation() {
|
|
8481
8639
|
return {
|
|
8482
8640
|
description: "Prefer to use external stylesheets with the `<link>` tag instead of inlining the styling.",
|
|
@@ -8484,9 +8642,13 @@ class NoStyleTag extends Rule {
|
|
|
8484
8642
|
};
|
|
8485
8643
|
}
|
|
8486
8644
|
setup() {
|
|
8645
|
+
const { allowTemplate } = this.options;
|
|
8487
8646
|
this.on("tag:start", (event) => {
|
|
8488
8647
|
const node = event.target;
|
|
8489
8648
|
if (node.tagName === "style") {
|
|
8649
|
+
if (allowTemplate && node.parent?.is("template")) {
|
|
8650
|
+
return;
|
|
8651
|
+
}
|
|
8490
8652
|
this.report(node, "Use external stylesheet with <link> instead of <style> tag");
|
|
8491
8653
|
}
|
|
8492
8654
|
});
|
|
@@ -9393,7 +9555,7 @@ function getTextFromReference(document, id) {
|
|
|
9393
9555
|
if (!id || id instanceof DynamicValue) {
|
|
9394
9556
|
return id;
|
|
9395
9557
|
}
|
|
9396
|
-
const selector =
|
|
9558
|
+
const selector = generateIdSelector(id);
|
|
9397
9559
|
const ref = document.querySelector(selector);
|
|
9398
9560
|
if (ref) {
|
|
9399
9561
|
return ref.textContent;
|
|
@@ -9709,9 +9871,7 @@ const fieldNameGroup = {
|
|
|
9709
9871
|
nickname: "text",
|
|
9710
9872
|
username: "username",
|
|
9711
9873
|
"new-password": "password",
|
|
9712
|
-
// eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
|
|
9713
9874
|
"current-password": "password",
|
|
9714
|
-
// eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
|
|
9715
9875
|
"one-time-code": "password",
|
|
9716
9876
|
"organization-title": "text",
|
|
9717
9877
|
organization: "text",
|
|
@@ -10753,6 +10913,7 @@ const bundledRules = {
|
|
|
10753
10913
|
"attribute-boolean-style": AttributeBooleanStyle,
|
|
10754
10914
|
"attribute-empty-style": AttributeEmptyStyle,
|
|
10755
10915
|
"attribute-misuse": AttributeMisuse,
|
|
10916
|
+
"autocomplete-password": AutocompletePassword,
|
|
10756
10917
|
"class-pattern": ClassPattern,
|
|
10757
10918
|
"close-attr": CloseAttr,
|
|
10758
10919
|
"close-order": CloseOrder,
|
|
@@ -11118,6 +11279,7 @@ const config$1 = {
|
|
|
11118
11279
|
"attribute-boolean-style": "error",
|
|
11119
11280
|
"attribute-empty-style": "error",
|
|
11120
11281
|
"attribute-misuse": "error",
|
|
11282
|
+
"autocomplete-password": "error",
|
|
11121
11283
|
"close-attr": "error",
|
|
11122
11284
|
"close-order": "error",
|
|
11123
11285
|
deprecated: "error",
|
|
@@ -12132,7 +12294,7 @@ class EventHandler {
|
|
|
12132
12294
|
}
|
|
12133
12295
|
|
|
12134
12296
|
const name = "html-validate";
|
|
12135
|
-
const version = "10.
|
|
12297
|
+
const version = "10.8.0";
|
|
12136
12298
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12137
12299
|
|
|
12138
12300
|
function freeze(src) {
|
|
@@ -12678,31 +12840,34 @@ class Parser {
|
|
|
12678
12840
|
* @internal
|
|
12679
12841
|
*/
|
|
12680
12842
|
consumeDirective(token) {
|
|
12681
|
-
const [text, preamble, action, separator1, directive, postamble] = token.data;
|
|
12682
|
-
|
|
12683
|
-
|
|
12843
|
+
const [text, preamble, prefix, action, separator1, directive, postamble] = token.data;
|
|
12844
|
+
const hasStartBracket = preamble.includes("[");
|
|
12845
|
+
const hasEndBracket = postamble.startsWith("]");
|
|
12846
|
+
if (hasStartBracket && !hasEndBracket) {
|
|
12847
|
+
this.trigger("parse:error", {
|
|
12848
|
+
location: sliceLocation(token.location, preamble.length - 1, -postamble.length),
|
|
12849
|
+
message: `Missing end bracket "]" on directive "${text}"`
|
|
12850
|
+
});
|
|
12851
|
+
return;
|
|
12684
12852
|
}
|
|
12685
12853
|
const match = /^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/.exec(directive);
|
|
12686
12854
|
if (!match) {
|
|
12687
12855
|
throw new Error(`Failed to parse directive "${text}"`);
|
|
12688
12856
|
}
|
|
12689
12857
|
if (!isValidDirective(action)) {
|
|
12858
|
+
const begin = preamble.length;
|
|
12859
|
+
const end = preamble.length + prefix.length + action.length;
|
|
12690
12860
|
this.trigger("parse:error", {
|
|
12691
|
-
location: token.location,
|
|
12861
|
+
location: sliceLocation(token.location, begin, -text.length + end),
|
|
12692
12862
|
message: `Unknown directive "${action}"`
|
|
12693
12863
|
});
|
|
12694
12864
|
return;
|
|
12695
12865
|
}
|
|
12696
12866
|
const [, data, separator2, comment] = match;
|
|
12697
|
-
const
|
|
12698
|
-
const actionOffset = preamble.length;
|
|
12867
|
+
const actionOffset = preamble.length + prefix.length;
|
|
12699
12868
|
const optionsOffset = actionOffset + action.length + separator1.length;
|
|
12700
12869
|
const commentOffset = optionsOffset + data.length + (separator2 || "").length;
|
|
12701
|
-
const location = sliceLocation(
|
|
12702
|
-
token.location,
|
|
12703
|
-
preamble.length - prefix.length - 1,
|
|
12704
|
-
-postamble.length + 1
|
|
12705
|
-
);
|
|
12870
|
+
const location = sliceLocation(token.location, preamble.length - 1, -postamble.length + 1);
|
|
12706
12871
|
const actionLocation = sliceLocation(
|
|
12707
12872
|
token.location,
|
|
12708
12873
|
actionOffset,
|