html-validate 10.5.0 → 10.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/cli.js +3 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core.js +308 -92
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/matchers.js.map +1 -1
- package/dist/esm/browser.js +1 -1
- package/dist/esm/cli.js +4 -2
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/core-browser.js +1 -1
- package/dist/esm/core-nodejs.js +1 -1
- package/dist/esm/core.js +309 -93
- 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/esm/matchers.js.map +1 -1
- package/dist/types/browser.d.ts +14 -0
- package/dist/types/index.d.ts +14 -0
- package/package.json +1 -1
package/dist/esm/core.js
CHANGED
|
@@ -1207,7 +1207,9 @@ class MetaTable {
|
|
|
1207
1207
|
);
|
|
1208
1208
|
}
|
|
1209
1209
|
for (const [key, value] of Object.entries(obj)) {
|
|
1210
|
-
if (key === "$schema")
|
|
1210
|
+
if (key === "$schema") {
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1211
1213
|
this.addEntry(key, migrateElement(value));
|
|
1212
1214
|
}
|
|
1213
1215
|
} catch (err) {
|
|
@@ -1307,7 +1309,9 @@ class MetaTable {
|
|
|
1307
1309
|
* global, e.g. to assign global attributes.
|
|
1308
1310
|
*/
|
|
1309
1311
|
resolveGlobal() {
|
|
1310
|
-
if (!this.elements["*"])
|
|
1312
|
+
if (!this.elements["*"]) {
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1311
1315
|
const global = this.elements["*"];
|
|
1312
1316
|
delete this.elements["*"];
|
|
1313
1317
|
delete global.tagName;
|
|
@@ -1481,7 +1485,9 @@ function sliceSize(size, begin, end) {
|
|
|
1481
1485
|
return Math.min(size, end - begin);
|
|
1482
1486
|
}
|
|
1483
1487
|
function sliceLocation(location, begin, end, wrap) {
|
|
1484
|
-
if (!location)
|
|
1488
|
+
if (!location) {
|
|
1489
|
+
return null;
|
|
1490
|
+
}
|
|
1485
1491
|
const size = sliceSize(location.size, begin, end);
|
|
1486
1492
|
const sliced = {
|
|
1487
1493
|
filename: location.filename,
|
|
@@ -2360,7 +2366,7 @@ class Selector {
|
|
|
2360
2366
|
|
|
2361
2367
|
const TEXT_NODE_NAME = "#text";
|
|
2362
2368
|
function isTextNode(node) {
|
|
2363
|
-
return
|
|
2369
|
+
return node?.nodeType === NodeType.TEXT_NODE;
|
|
2364
2370
|
}
|
|
2365
2371
|
class TextNode extends DOMNode {
|
|
2366
2372
|
text;
|
|
@@ -2404,7 +2410,7 @@ var NodeClosed = /* @__PURE__ */ ((NodeClosed2) => {
|
|
|
2404
2410
|
return NodeClosed2;
|
|
2405
2411
|
})(NodeClosed || {});
|
|
2406
2412
|
function isElementNode(node) {
|
|
2407
|
-
return
|
|
2413
|
+
return node?.nodeType === NodeType.ELEMENT_NODE;
|
|
2408
2414
|
}
|
|
2409
2415
|
function isInvalidTagName(tagName) {
|
|
2410
2416
|
return tagName === "" || tagName === "*";
|
|
@@ -3700,6 +3706,7 @@ function interpolate(text, data) {
|
|
|
3700
3706
|
|
|
3701
3707
|
const ajv$1 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
|
|
3702
3708
|
ajv$1.addMetaSchema(ajvSchemaDraft);
|
|
3709
|
+
ajv$1.addKeyword(ajvRegexpKeyword);
|
|
3703
3710
|
function getSchemaValidator(ruleId, properties) {
|
|
3704
3711
|
const $id = `rule/${ruleId}`;
|
|
3705
3712
|
const cached = ajv$1.getSchema($id);
|
|
@@ -3956,6 +3963,7 @@ class Rule {
|
|
|
3956
3963
|
*
|
|
3957
3964
|
* @internal
|
|
3958
3965
|
*/
|
|
3966
|
+
/* eslint-disable-next-line @typescript-eslint/max-params -- technical debt */
|
|
3959
3967
|
static validateOptions(cls, ruleId, jsonPath, options, filename, config) {
|
|
3960
3968
|
if (!cls) {
|
|
3961
3969
|
return;
|
|
@@ -3991,7 +3999,7 @@ class Rule {
|
|
|
3991
3999
|
}
|
|
3992
4000
|
}
|
|
3993
4001
|
|
|
3994
|
-
const defaults$
|
|
4002
|
+
const defaults$z = {
|
|
3995
4003
|
allowExternal: true,
|
|
3996
4004
|
allowRelative: true,
|
|
3997
4005
|
allowAbsolute: true,
|
|
@@ -4035,7 +4043,7 @@ class AllowedLinks extends Rule {
|
|
|
4035
4043
|
allowRelative;
|
|
4036
4044
|
allowAbsolute;
|
|
4037
4045
|
constructor(options) {
|
|
4038
|
-
super({ ...defaults$
|
|
4046
|
+
super({ ...defaults$z, ...options });
|
|
4039
4047
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
4040
4048
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
4041
4049
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -4203,7 +4211,7 @@ class AllowedLinks extends Rule {
|
|
|
4203
4211
|
}
|
|
4204
4212
|
}
|
|
4205
4213
|
|
|
4206
|
-
const defaults$
|
|
4214
|
+
const defaults$y = {
|
|
4207
4215
|
accessible: true
|
|
4208
4216
|
};
|
|
4209
4217
|
function findByTarget(target, siblings) {
|
|
@@ -4233,7 +4241,7 @@ function getDescription$1(context) {
|
|
|
4233
4241
|
}
|
|
4234
4242
|
class AreaAlt extends Rule {
|
|
4235
4243
|
constructor(options) {
|
|
4236
|
-
super({ ...defaults$
|
|
4244
|
+
super({ ...defaults$y, ...options });
|
|
4237
4245
|
}
|
|
4238
4246
|
static schema() {
|
|
4239
4247
|
return {
|
|
@@ -4312,8 +4320,12 @@ class AriaHiddenBody extends Rule {
|
|
|
4312
4320
|
}
|
|
4313
4321
|
}
|
|
4314
4322
|
|
|
4315
|
-
const defaults$
|
|
4316
|
-
allowAnyNamable: false
|
|
4323
|
+
const defaults$x = {
|
|
4324
|
+
allowAnyNamable: false,
|
|
4325
|
+
elements: {
|
|
4326
|
+
include: null,
|
|
4327
|
+
exclude: null
|
|
4328
|
+
}
|
|
4317
4329
|
};
|
|
4318
4330
|
const allowlist = /* @__PURE__ */ new Set([
|
|
4319
4331
|
"main",
|
|
@@ -4356,7 +4368,26 @@ function isValidUsage(target, meta) {
|
|
|
4356
4368
|
}
|
|
4357
4369
|
class AriaLabelMisuse extends Rule {
|
|
4358
4370
|
constructor(options) {
|
|
4359
|
-
super({ ...defaults$
|
|
4371
|
+
super({ ...defaults$x, ...options });
|
|
4372
|
+
}
|
|
4373
|
+
static schema() {
|
|
4374
|
+
return {
|
|
4375
|
+
allowAnyNamable: {
|
|
4376
|
+
type: "boolean"
|
|
4377
|
+
},
|
|
4378
|
+
elements: {
|
|
4379
|
+
type: "object",
|
|
4380
|
+
properties: {
|
|
4381
|
+
include: {
|
|
4382
|
+
anyOf: [{ type: "array", items: { type: "string" } }, { type: "null" }]
|
|
4383
|
+
},
|
|
4384
|
+
exclude: {
|
|
4385
|
+
anyOf: [{ type: "array", items: { type: "string" } }, { type: "null" }]
|
|
4386
|
+
}
|
|
4387
|
+
},
|
|
4388
|
+
additionalProperties: false
|
|
4389
|
+
}
|
|
4390
|
+
};
|
|
4360
4391
|
}
|
|
4361
4392
|
documentation(context) {
|
|
4362
4393
|
const valid = [
|
|
@@ -4414,6 +4445,9 @@ class AriaLabelMisuse extends Rule {
|
|
|
4414
4445
|
if (!meta) {
|
|
4415
4446
|
return;
|
|
4416
4447
|
}
|
|
4448
|
+
if (this.shouldIgnoreElement(target)) {
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4417
4451
|
if (isValidUsage(target, meta)) {
|
|
4418
4452
|
return;
|
|
4419
4453
|
}
|
|
@@ -4438,6 +4472,9 @@ class AriaLabelMisuse extends Rule {
|
|
|
4438
4472
|
});
|
|
4439
4473
|
}
|
|
4440
4474
|
}
|
|
4475
|
+
shouldIgnoreElement(target) {
|
|
4476
|
+
return isKeywordIgnored(this.options.elements, target.tagName, keywordPatternMatcher);
|
|
4477
|
+
}
|
|
4441
4478
|
}
|
|
4442
4479
|
|
|
4443
4480
|
class ConfigError extends UserError {
|
|
@@ -4500,14 +4537,14 @@ class CaseStyle {
|
|
|
4500
4537
|
}
|
|
4501
4538
|
}
|
|
4502
4539
|
|
|
4503
|
-
const defaults$
|
|
4540
|
+
const defaults$w = {
|
|
4504
4541
|
style: "lowercase",
|
|
4505
4542
|
ignoreForeign: true
|
|
4506
4543
|
};
|
|
4507
4544
|
class AttrCase extends Rule {
|
|
4508
4545
|
style;
|
|
4509
4546
|
constructor(options) {
|
|
4510
|
-
super({ ...defaults$
|
|
4547
|
+
super({ ...defaults$w, ...options });
|
|
4511
4548
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4512
4549
|
}
|
|
4513
4550
|
static schema() {
|
|
@@ -4614,7 +4651,7 @@ const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
|
|
|
4614
4651
|
const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
|
|
4615
4652
|
const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
|
|
4616
4653
|
const MATCH_TITLE_END = /^<(\/)(title)/;
|
|
4617
|
-
const MATCH_DIRECTIVE = /^(<!--\s*\[html-validate-)([a-z0-9-]+)(\s*)(.*?)(]?\s*-->)/;
|
|
4654
|
+
const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([a-z0-9-]+)(\s*)(.*?)(]?\s*-->)/;
|
|
4618
4655
|
const MATCH_COMMENT = /^<!--([^]*?)-->/;
|
|
4619
4656
|
const MATCH_CONDITIONAL = /^<!\[([^\]]*?)\]>/;
|
|
4620
4657
|
class InvalidTokenError extends Error {
|
|
@@ -4912,7 +4949,7 @@ class AttrDelimiter extends Rule {
|
|
|
4912
4949
|
}
|
|
4913
4950
|
|
|
4914
4951
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4915
|
-
const defaults$
|
|
4952
|
+
const defaults$v = {
|
|
4916
4953
|
pattern: DEFAULT_PATTERN,
|
|
4917
4954
|
ignoreForeign: true
|
|
4918
4955
|
};
|
|
@@ -4945,7 +4982,7 @@ function generateDescription(name, pattern) {
|
|
|
4945
4982
|
class AttrPattern extends Rule {
|
|
4946
4983
|
pattern;
|
|
4947
4984
|
constructor(options) {
|
|
4948
|
-
super({ ...defaults$
|
|
4985
|
+
super({ ...defaults$v, ...options });
|
|
4949
4986
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4950
4987
|
}
|
|
4951
4988
|
static schema() {
|
|
@@ -4992,7 +5029,7 @@ class AttrPattern extends Rule {
|
|
|
4992
5029
|
}
|
|
4993
5030
|
}
|
|
4994
5031
|
|
|
4995
|
-
const defaults$
|
|
5032
|
+
const defaults$u = {
|
|
4996
5033
|
style: "auto",
|
|
4997
5034
|
unquoted: false
|
|
4998
5035
|
};
|
|
@@ -5058,7 +5095,7 @@ class AttrQuotes extends Rule {
|
|
|
5058
5095
|
};
|
|
5059
5096
|
}
|
|
5060
5097
|
constructor(options) {
|
|
5061
|
-
super({ ...defaults$
|
|
5098
|
+
super({ ...defaults$u, ...options });
|
|
5062
5099
|
this.style = parseStyle$3(this.options.style);
|
|
5063
5100
|
}
|
|
5064
5101
|
setup() {
|
|
@@ -5180,7 +5217,9 @@ class AttributeAllowedValues extends Rule {
|
|
|
5180
5217
|
const doc = event.document;
|
|
5181
5218
|
walk.depthFirst(doc, (node) => {
|
|
5182
5219
|
const meta = node.meta;
|
|
5183
|
-
if (!meta?.attributes)
|
|
5220
|
+
if (!meta?.attributes) {
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5184
5223
|
for (const attr of node.attributes) {
|
|
5185
5224
|
if (Validator.validateAttribute(attr, meta.attributes)) {
|
|
5186
5225
|
continue;
|
|
@@ -5212,13 +5251,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
5212
5251
|
}
|
|
5213
5252
|
}
|
|
5214
5253
|
|
|
5215
|
-
const defaults$
|
|
5254
|
+
const defaults$t = {
|
|
5216
5255
|
style: "omit"
|
|
5217
5256
|
};
|
|
5218
5257
|
class AttributeBooleanStyle extends Rule {
|
|
5219
5258
|
hasInvalidStyle;
|
|
5220
5259
|
constructor(options) {
|
|
5221
|
-
super({ ...defaults$
|
|
5260
|
+
super({ ...defaults$t, ...options });
|
|
5222
5261
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
5223
5262
|
}
|
|
5224
5263
|
static schema() {
|
|
@@ -5240,9 +5279,13 @@ class AttributeBooleanStyle extends Rule {
|
|
|
5240
5279
|
const doc = event.document;
|
|
5241
5280
|
walk.depthFirst(doc, (node) => {
|
|
5242
5281
|
const meta = node.meta;
|
|
5243
|
-
if (!meta?.attributes)
|
|
5282
|
+
if (!meta?.attributes) {
|
|
5283
|
+
return;
|
|
5284
|
+
}
|
|
5244
5285
|
for (const attr of node.attributes) {
|
|
5245
|
-
if (!this.isBoolean(attr, meta.attributes))
|
|
5286
|
+
if (!this.isBoolean(attr, meta.attributes)) {
|
|
5287
|
+
continue;
|
|
5288
|
+
}
|
|
5246
5289
|
if (attr.originalAttribute) {
|
|
5247
5290
|
continue;
|
|
5248
5291
|
}
|
|
@@ -5284,13 +5327,13 @@ function reportMessage$1(attr, style) {
|
|
|
5284
5327
|
return "";
|
|
5285
5328
|
}
|
|
5286
5329
|
|
|
5287
|
-
const defaults$
|
|
5330
|
+
const defaults$s = {
|
|
5288
5331
|
style: "omit"
|
|
5289
5332
|
};
|
|
5290
5333
|
class AttributeEmptyStyle extends Rule {
|
|
5291
5334
|
hasInvalidStyle;
|
|
5292
5335
|
constructor(options) {
|
|
5293
|
-
super({ ...defaults$
|
|
5336
|
+
super({ ...defaults$s, ...options });
|
|
5294
5337
|
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
5295
5338
|
}
|
|
5296
5339
|
static schema() {
|
|
@@ -5312,7 +5355,9 @@ class AttributeEmptyStyle extends Rule {
|
|
|
5312
5355
|
const doc = event.document;
|
|
5313
5356
|
walk.depthFirst(doc, (node) => {
|
|
5314
5357
|
const meta = node.meta;
|
|
5315
|
-
if (!meta?.attributes)
|
|
5358
|
+
if (!meta?.attributes) {
|
|
5359
|
+
return;
|
|
5360
|
+
}
|
|
5316
5361
|
for (const attr of node.attributes) {
|
|
5317
5362
|
if (!allowsEmpty(attr, meta.attributes)) {
|
|
5318
5363
|
continue;
|
|
@@ -5405,7 +5450,22 @@ class AttributeMisuse extends Rule {
|
|
|
5405
5450
|
}
|
|
5406
5451
|
}
|
|
5407
5452
|
|
|
5453
|
+
const patternNamesValues = [
|
|
5454
|
+
"kebabcase",
|
|
5455
|
+
"camelcase",
|
|
5456
|
+
"underscore",
|
|
5457
|
+
"snakecase",
|
|
5458
|
+
"bem",
|
|
5459
|
+
"tailwind"
|
|
5460
|
+
];
|
|
5461
|
+
const patternNames = new Set(patternNamesValues);
|
|
5462
|
+
function isNamedPattern(value) {
|
|
5463
|
+
return typeof value === "string" && patternNames.has(value);
|
|
5464
|
+
}
|
|
5408
5465
|
function parsePattern(pattern) {
|
|
5466
|
+
if (pattern instanceof RegExp) {
|
|
5467
|
+
return { regexp: pattern, description: pattern.toString() };
|
|
5468
|
+
}
|
|
5409
5469
|
switch (pattern) {
|
|
5410
5470
|
case "kebabcase":
|
|
5411
5471
|
return { regexp: /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/, description: pattern };
|
|
@@ -5423,7 +5483,21 @@ function parsePattern(pattern) {
|
|
|
5423
5483
|
description: pattern
|
|
5424
5484
|
};
|
|
5425
5485
|
}
|
|
5486
|
+
case "tailwind": {
|
|
5487
|
+
return {
|
|
5488
|
+
regexp: /^!?(?:[-a-z[]|\d+xl:)[\w\-:./\\[\]()#'&>,!=%]*$/,
|
|
5489
|
+
description: "tailwind"
|
|
5490
|
+
};
|
|
5491
|
+
}
|
|
5426
5492
|
default: {
|
|
5493
|
+
if (pattern.startsWith("/") && pattern.endsWith("/")) {
|
|
5494
|
+
const regexpSource = pattern.slice(1, -1);
|
|
5495
|
+
const regexp2 = new RegExp(regexpSource);
|
|
5496
|
+
return { regexp: regexp2, description: regexp2.toString() };
|
|
5497
|
+
}
|
|
5498
|
+
console.warn(
|
|
5499
|
+
`Custom pattern "${pattern}" should be wrapped in forward slashes, e.g., "/${pattern}/". Support for unwrapped patterns is deprecated and will be removed in a future version.`
|
|
5500
|
+
);
|
|
5427
5501
|
const regexp = new RegExp(pattern);
|
|
5428
5502
|
return { regexp, description: regexp.toString() };
|
|
5429
5503
|
}
|
|
@@ -5431,27 +5505,49 @@ function parsePattern(pattern) {
|
|
|
5431
5505
|
}
|
|
5432
5506
|
|
|
5433
5507
|
function toArray$2(value) {
|
|
5434
|
-
|
|
5508
|
+
if (Array.isArray(value)) {
|
|
5509
|
+
return value;
|
|
5510
|
+
} else {
|
|
5511
|
+
return [value];
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
5514
|
+
function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
|
|
5515
|
+
const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
|
|
5516
|
+
if (extraneous.length > 0) {
|
|
5517
|
+
const quote = (it) => `"${it}"`;
|
|
5518
|
+
const disallowed = naturalJoin(extraneous.map(quote), "and");
|
|
5519
|
+
const allowed = naturalJoin(Array.from(allowedPatterns, quote), "and");
|
|
5520
|
+
throw new Error(
|
|
5521
|
+
`Pattern ${disallowed} cannot be used with "${ruleId}". Allowed patterns: ${allowed}`
|
|
5522
|
+
);
|
|
5523
|
+
}
|
|
5435
5524
|
}
|
|
5436
5525
|
class BasePatternRule extends Rule {
|
|
5437
5526
|
/** Attribute being tested */
|
|
5438
5527
|
attr;
|
|
5439
5528
|
/** Parsed configured patterns */
|
|
5440
5529
|
patterns;
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5530
|
+
constructor({
|
|
5531
|
+
ruleId,
|
|
5532
|
+
attr,
|
|
5533
|
+
options,
|
|
5534
|
+
allowedPatterns
|
|
5535
|
+
}) {
|
|
5446
5536
|
super(options);
|
|
5447
5537
|
const { pattern } = this.options;
|
|
5448
5538
|
this.attr = attr;
|
|
5449
|
-
|
|
5539
|
+
const patterns = toArray$2(pattern);
|
|
5540
|
+
validateAllowedPatterns(patterns, allowedPatterns, ruleId);
|
|
5541
|
+
this.patterns = patterns.map((it) => parsePattern(it));
|
|
5450
5542
|
}
|
|
5451
5543
|
static schema() {
|
|
5452
5544
|
return {
|
|
5453
5545
|
pattern: {
|
|
5454
|
-
|
|
5546
|
+
anyOf: [
|
|
5547
|
+
{ type: "array", items: { anyOf: [{ type: "string" }, { regexp: true }] }, minItems: 1 },
|
|
5548
|
+
{ type: "string" },
|
|
5549
|
+
{ regexp: true }
|
|
5550
|
+
]
|
|
5455
5551
|
}
|
|
5456
5552
|
};
|
|
5457
5553
|
}
|
|
@@ -5485,12 +5581,18 @@ class BasePatternRule extends Rule {
|
|
|
5485
5581
|
}
|
|
5486
5582
|
}
|
|
5487
5583
|
|
|
5488
|
-
const defaults$
|
|
5584
|
+
const defaults$r = {
|
|
5489
5585
|
pattern: "kebabcase"
|
|
5490
5586
|
};
|
|
5491
5587
|
class ClassPattern extends BasePatternRule {
|
|
5492
5588
|
constructor(options) {
|
|
5493
|
-
super(
|
|
5589
|
+
super({
|
|
5590
|
+
ruleId: "class-pattern",
|
|
5591
|
+
attr: "class",
|
|
5592
|
+
options: { ...defaults$r, ...options },
|
|
5593
|
+
allowedPatterns: patternNames
|
|
5594
|
+
// allow all patterns
|
|
5595
|
+
});
|
|
5494
5596
|
}
|
|
5495
5597
|
static schema() {
|
|
5496
5598
|
return BasePatternRule.schema();
|
|
@@ -5637,13 +5739,13 @@ class CloseOrder extends Rule {
|
|
|
5637
5739
|
}
|
|
5638
5740
|
}
|
|
5639
5741
|
|
|
5640
|
-
const defaults$
|
|
5742
|
+
const defaults$q = {
|
|
5641
5743
|
include: null,
|
|
5642
5744
|
exclude: null
|
|
5643
5745
|
};
|
|
5644
5746
|
class Deprecated extends Rule {
|
|
5645
5747
|
constructor(options) {
|
|
5646
|
-
super({ ...defaults$
|
|
5748
|
+
super({ ...defaults$q, ...options });
|
|
5647
5749
|
}
|
|
5648
5750
|
static schema() {
|
|
5649
5751
|
return {
|
|
@@ -5797,12 +5899,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5797
5899
|
}
|
|
5798
5900
|
};
|
|
5799
5901
|
|
|
5800
|
-
const defaults$
|
|
5902
|
+
const defaults$p = {
|
|
5801
5903
|
style: "uppercase"
|
|
5802
5904
|
};
|
|
5803
5905
|
class DoctypeStyle extends Rule {
|
|
5804
5906
|
constructor(options) {
|
|
5805
|
-
super({ ...defaults$
|
|
5907
|
+
super({ ...defaults$p, ...options });
|
|
5806
5908
|
}
|
|
5807
5909
|
static schema() {
|
|
5808
5910
|
return {
|
|
@@ -5830,13 +5932,13 @@ class DoctypeStyle extends Rule {
|
|
|
5830
5932
|
}
|
|
5831
5933
|
}
|
|
5832
5934
|
|
|
5833
|
-
const defaults$
|
|
5935
|
+
const defaults$o = {
|
|
5834
5936
|
style: "lowercase"
|
|
5835
5937
|
};
|
|
5836
5938
|
class ElementCase extends Rule {
|
|
5837
5939
|
style;
|
|
5838
5940
|
constructor(options) {
|
|
5839
|
-
super({ ...defaults$
|
|
5941
|
+
super({ ...defaults$o, ...options });
|
|
5840
5942
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
5841
5943
|
}
|
|
5842
5944
|
static schema() {
|
|
@@ -5896,7 +5998,7 @@ class ElementCase extends Rule {
|
|
|
5896
5998
|
}
|
|
5897
5999
|
}
|
|
5898
6000
|
|
|
5899
|
-
const defaults$
|
|
6001
|
+
const defaults$n = {
|
|
5900
6002
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5901
6003
|
whitelist: [],
|
|
5902
6004
|
blacklist: []
|
|
@@ -5904,7 +6006,7 @@ const defaults$m = {
|
|
|
5904
6006
|
class ElementName extends Rule {
|
|
5905
6007
|
pattern;
|
|
5906
6008
|
constructor(options) {
|
|
5907
|
-
super({ ...defaults$
|
|
6009
|
+
super({ ...defaults$n, ...options });
|
|
5908
6010
|
this.pattern = new RegExp(this.options.pattern);
|
|
5909
6011
|
}
|
|
5910
6012
|
static schema() {
|
|
@@ -5941,7 +6043,7 @@ class ElementName extends Rule {
|
|
|
5941
6043
|
...context.blacklist.map((cur) => `- ${cur}`)
|
|
5942
6044
|
];
|
|
5943
6045
|
}
|
|
5944
|
-
if (context.pattern !== defaults$
|
|
6046
|
+
if (context.pattern !== defaults$n.pattern) {
|
|
5945
6047
|
return [
|
|
5946
6048
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
5947
6049
|
"",
|
|
@@ -6440,7 +6542,9 @@ class EmptyTitle extends Rule {
|
|
|
6440
6542
|
setup() {
|
|
6441
6543
|
this.on("tag:end", (event) => {
|
|
6442
6544
|
const node = event.previous;
|
|
6443
|
-
if (node.tagName !== "title")
|
|
6545
|
+
if (node.tagName !== "title") {
|
|
6546
|
+
return;
|
|
6547
|
+
}
|
|
6444
6548
|
switch (classifyNodeText(node)) {
|
|
6445
6549
|
case TextClassification.DYNAMIC_TEXT:
|
|
6446
6550
|
case TextClassification.STATIC_TEXT:
|
|
@@ -6456,7 +6560,7 @@ class EmptyTitle extends Rule {
|
|
|
6456
6560
|
}
|
|
6457
6561
|
}
|
|
6458
6562
|
|
|
6459
|
-
const defaults$
|
|
6563
|
+
const defaults$m = {
|
|
6460
6564
|
allowArrayBrackets: true,
|
|
6461
6565
|
allowCheckboxDefault: true,
|
|
6462
6566
|
shared: ["radio", "button", "reset", "submit"]
|
|
@@ -6516,7 +6620,7 @@ function getDocumentation(context) {
|
|
|
6516
6620
|
}
|
|
6517
6621
|
class FormDupName extends Rule {
|
|
6518
6622
|
constructor(options) {
|
|
6519
|
-
super({ ...defaults$
|
|
6623
|
+
super({ ...defaults$m, ...options });
|
|
6520
6624
|
}
|
|
6521
6625
|
static schema() {
|
|
6522
6626
|
return {
|
|
@@ -6675,7 +6779,7 @@ class FormDupName extends Rule {
|
|
|
6675
6779
|
}
|
|
6676
6780
|
}
|
|
6677
6781
|
|
|
6678
|
-
const defaults$
|
|
6782
|
+
const defaults$l = {
|
|
6679
6783
|
allowMultipleH1: false,
|
|
6680
6784
|
minInitialRank: "h1",
|
|
6681
6785
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
|
|
@@ -6707,7 +6811,7 @@ class HeadingLevel extends Rule {
|
|
|
6707
6811
|
sectionRoots;
|
|
6708
6812
|
stack = [];
|
|
6709
6813
|
constructor(options) {
|
|
6710
|
-
super({ ...defaults$
|
|
6814
|
+
super({ ...defaults$l, ...options });
|
|
6711
6815
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
6712
6816
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
|
|
6713
6817
|
this.stack.push({
|
|
@@ -6761,7 +6865,9 @@ class HeadingLevel extends Rule {
|
|
|
6761
6865
|
}
|
|
6762
6866
|
onTagStart(event) {
|
|
6763
6867
|
const level = extractLevel(event.target);
|
|
6764
|
-
if (!level)
|
|
6868
|
+
if (!level) {
|
|
6869
|
+
return;
|
|
6870
|
+
}
|
|
6765
6871
|
const root = this.getCurrentRoot();
|
|
6766
6872
|
if (!this.options.allowMultipleH1 && level === 1) {
|
|
6767
6873
|
if (root.h1Count >= 1) {
|
|
@@ -6944,12 +7050,25 @@ class HiddenFocusable extends Rule {
|
|
|
6944
7050
|
}
|
|
6945
7051
|
}
|
|
6946
7052
|
|
|
6947
|
-
const defaults$
|
|
7053
|
+
const defaults$k = {
|
|
6948
7054
|
pattern: "kebabcase"
|
|
6949
7055
|
};
|
|
7056
|
+
function exclude$1(set, ...values) {
|
|
7057
|
+
const result = new Set(set);
|
|
7058
|
+
for (const value of values) {
|
|
7059
|
+
result.delete(value);
|
|
7060
|
+
}
|
|
7061
|
+
return result;
|
|
7062
|
+
}
|
|
6950
7063
|
class IdPattern extends BasePatternRule {
|
|
6951
7064
|
constructor(options) {
|
|
6952
|
-
|
|
7065
|
+
const allowedPatterns = exclude$1(patternNames, "tailwind");
|
|
7066
|
+
super({
|
|
7067
|
+
ruleId: "id-pattern",
|
|
7068
|
+
attr: "id",
|
|
7069
|
+
options: { ...defaults$k, ...options },
|
|
7070
|
+
allowedPatterns
|
|
7071
|
+
});
|
|
6953
7072
|
}
|
|
6954
7073
|
static schema() {
|
|
6955
7074
|
return BasePatternRule.schema();
|
|
@@ -7253,7 +7372,9 @@ class InputMissingLabel extends Rule {
|
|
|
7253
7372
|
}
|
|
7254
7373
|
}
|
|
7255
7374
|
function findLabelById(root, id) {
|
|
7256
|
-
if (!id)
|
|
7375
|
+
if (!id) {
|
|
7376
|
+
return [];
|
|
7377
|
+
}
|
|
7257
7378
|
return root.querySelectorAll(`label[for="${id}"]`);
|
|
7258
7379
|
}
|
|
7259
7380
|
function findLabelByParent(el) {
|
|
@@ -7267,13 +7388,13 @@ function findLabelByParent(el) {
|
|
|
7267
7388
|
return [];
|
|
7268
7389
|
}
|
|
7269
7390
|
|
|
7270
|
-
const defaults$
|
|
7391
|
+
const defaults$j = {
|
|
7271
7392
|
maxlength: 70
|
|
7272
7393
|
};
|
|
7273
7394
|
class LongTitle extends Rule {
|
|
7274
7395
|
maxlength;
|
|
7275
7396
|
constructor(options) {
|
|
7276
|
-
super({ ...defaults$
|
|
7397
|
+
super({ ...defaults$j, ...options });
|
|
7277
7398
|
this.maxlength = this.options.maxlength;
|
|
7278
7399
|
}
|
|
7279
7400
|
static schema() {
|
|
@@ -7292,7 +7413,9 @@ class LongTitle extends Rule {
|
|
|
7292
7413
|
setup() {
|
|
7293
7414
|
this.on("tag:end", (event) => {
|
|
7294
7415
|
const node = event.previous;
|
|
7295
|
-
if (node.tagName !== "title")
|
|
7416
|
+
if (node.tagName !== "title") {
|
|
7417
|
+
return;
|
|
7418
|
+
}
|
|
7296
7419
|
const text = node.textContent;
|
|
7297
7420
|
if (text.length > this.maxlength) {
|
|
7298
7421
|
this.report(node, `title text cannot be longer than ${String(this.maxlength)} characters`);
|
|
@@ -7375,12 +7498,12 @@ class MapIdName extends Rule {
|
|
|
7375
7498
|
}
|
|
7376
7499
|
}
|
|
7377
7500
|
|
|
7378
|
-
const defaults$
|
|
7501
|
+
const defaults$i = {
|
|
7379
7502
|
allowLongDelay: false
|
|
7380
7503
|
};
|
|
7381
7504
|
class MetaRefresh extends Rule {
|
|
7382
7505
|
constructor(options) {
|
|
7383
|
-
super({ ...defaults$
|
|
7506
|
+
super({ ...defaults$i, ...options });
|
|
7384
7507
|
}
|
|
7385
7508
|
documentation() {
|
|
7386
7509
|
return {
|
|
@@ -7491,12 +7614,25 @@ class MultipleLabeledControls extends Rule {
|
|
|
7491
7614
|
}
|
|
7492
7615
|
}
|
|
7493
7616
|
|
|
7494
|
-
const defaults$
|
|
7617
|
+
const defaults$h = {
|
|
7495
7618
|
pattern: "camelcase"
|
|
7496
7619
|
};
|
|
7620
|
+
function exclude(set, ...values) {
|
|
7621
|
+
const result = new Set(set);
|
|
7622
|
+
for (const value of values) {
|
|
7623
|
+
result.delete(value);
|
|
7624
|
+
}
|
|
7625
|
+
return result;
|
|
7626
|
+
}
|
|
7497
7627
|
class NamePattern extends BasePatternRule {
|
|
7498
7628
|
constructor(options) {
|
|
7499
|
-
|
|
7629
|
+
const allowedPatterns = exclude(patternNames, "tailwind");
|
|
7630
|
+
super({
|
|
7631
|
+
ruleId: "name-pattern",
|
|
7632
|
+
attr: "name",
|
|
7633
|
+
options: { ...defaults$h, ...options },
|
|
7634
|
+
allowedPatterns
|
|
7635
|
+
});
|
|
7500
7636
|
}
|
|
7501
7637
|
static schema() {
|
|
7502
7638
|
return BasePatternRule.schema();
|
|
@@ -7585,13 +7721,13 @@ class NoAbstractRole extends Rule {
|
|
|
7585
7721
|
}
|
|
7586
7722
|
}
|
|
7587
7723
|
|
|
7588
|
-
const defaults$
|
|
7724
|
+
const defaults$g = {
|
|
7589
7725
|
include: null,
|
|
7590
7726
|
exclude: null
|
|
7591
7727
|
};
|
|
7592
7728
|
class NoAutoplay extends Rule {
|
|
7593
7729
|
constructor(options) {
|
|
7594
|
-
super({ ...defaults$
|
|
7730
|
+
super({ ...defaults$g, ...options });
|
|
7595
7731
|
}
|
|
7596
7732
|
documentation(context) {
|
|
7597
7733
|
return {
|
|
@@ -7857,7 +7993,7 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
7857
7993
|
return;
|
|
7858
7994
|
}
|
|
7859
7995
|
const parent = closed.parent;
|
|
7860
|
-
const closedByParent = parent
|
|
7996
|
+
const closedByParent = parent?.tagName === by.tagName;
|
|
7861
7997
|
const closedByDocument = closedByParent && parent.isRootElement();
|
|
7862
7998
|
const sameTag = closed.tagName === by.tagName;
|
|
7863
7999
|
if (closedByDocument) {
|
|
@@ -7913,14 +8049,14 @@ class NoImplicitInputType extends Rule {
|
|
|
7913
8049
|
}
|
|
7914
8050
|
}
|
|
7915
8051
|
|
|
7916
|
-
const defaults$
|
|
8052
|
+
const defaults$f = {
|
|
7917
8053
|
include: null,
|
|
7918
8054
|
exclude: null,
|
|
7919
8055
|
allowedProperties: ["display"]
|
|
7920
8056
|
};
|
|
7921
8057
|
class NoInlineStyle extends Rule {
|
|
7922
8058
|
constructor(options) {
|
|
7923
|
-
super({ ...defaults$
|
|
8059
|
+
super({ ...defaults$f, ...options });
|
|
7924
8060
|
}
|
|
7925
8061
|
static schema() {
|
|
7926
8062
|
return {
|
|
@@ -8106,7 +8242,7 @@ class NoMultipleMain extends Rule {
|
|
|
8106
8242
|
}
|
|
8107
8243
|
}
|
|
8108
8244
|
|
|
8109
|
-
const defaults$
|
|
8245
|
+
const defaults$e = {
|
|
8110
8246
|
relaxed: false
|
|
8111
8247
|
};
|
|
8112
8248
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -8124,7 +8260,7 @@ const replacementTable = {
|
|
|
8124
8260
|
class NoRawCharacters extends Rule {
|
|
8125
8261
|
relaxed;
|
|
8126
8262
|
constructor(options) {
|
|
8127
|
-
super({ ...defaults$
|
|
8263
|
+
super({ ...defaults$e, ...options });
|
|
8128
8264
|
this.relaxed = this.options.relaxed;
|
|
8129
8265
|
}
|
|
8130
8266
|
static schema() {
|
|
@@ -8219,7 +8355,7 @@ class NoRedundantAriaLabel extends Rule {
|
|
|
8219
8355
|
continue;
|
|
8220
8356
|
}
|
|
8221
8357
|
const label = document.querySelector(`label[for="${id}"]`);
|
|
8222
|
-
if (!ariaLabel ||
|
|
8358
|
+
if (!ariaLabel || label?.textContent.trim() !== ariaLabel.value) {
|
|
8223
8359
|
continue;
|
|
8224
8360
|
}
|
|
8225
8361
|
const message = "aria-label is redundant when label containing same text exists";
|
|
@@ -8304,13 +8440,13 @@ class NoRedundantRole extends Rule {
|
|
|
8304
8440
|
}
|
|
8305
8441
|
|
|
8306
8442
|
const xmlns = /^(.+):.+$/;
|
|
8307
|
-
const defaults$
|
|
8443
|
+
const defaults$d = {
|
|
8308
8444
|
ignoreForeign: true,
|
|
8309
8445
|
ignoreXML: true
|
|
8310
8446
|
};
|
|
8311
8447
|
class NoSelfClosing extends Rule {
|
|
8312
8448
|
constructor(options) {
|
|
8313
|
-
super({ ...defaults$
|
|
8449
|
+
super({ ...defaults$d, ...options });
|
|
8314
8450
|
}
|
|
8315
8451
|
static schema() {
|
|
8316
8452
|
return {
|
|
@@ -8360,7 +8496,20 @@ function isRelevant(node, options) {
|
|
|
8360
8496
|
return true;
|
|
8361
8497
|
}
|
|
8362
8498
|
|
|
8499
|
+
const defaults$c = {
|
|
8500
|
+
allowTemplate: true
|
|
8501
|
+
};
|
|
8363
8502
|
class NoStyleTag extends Rule {
|
|
8503
|
+
constructor(options) {
|
|
8504
|
+
super({ ...defaults$c, ...options });
|
|
8505
|
+
}
|
|
8506
|
+
static schema() {
|
|
8507
|
+
return {
|
|
8508
|
+
allowTemplate: {
|
|
8509
|
+
type: "boolean"
|
|
8510
|
+
}
|
|
8511
|
+
};
|
|
8512
|
+
}
|
|
8364
8513
|
documentation() {
|
|
8365
8514
|
return {
|
|
8366
8515
|
description: "Prefer to use external stylesheets with the `<link>` tag instead of inlining the styling.",
|
|
@@ -8368,9 +8517,13 @@ class NoStyleTag extends Rule {
|
|
|
8368
8517
|
};
|
|
8369
8518
|
}
|
|
8370
8519
|
setup() {
|
|
8520
|
+
const { allowTemplate } = this.options;
|
|
8371
8521
|
this.on("tag:start", (event) => {
|
|
8372
8522
|
const node = event.target;
|
|
8373
8523
|
if (node.tagName === "style") {
|
|
8524
|
+
if (allowTemplate && node.parent?.is("template")) {
|
|
8525
|
+
return;
|
|
8526
|
+
}
|
|
8374
8527
|
this.report(node, "Use external stylesheet with <link> instead of <style> tag");
|
|
8375
8528
|
}
|
|
8376
8529
|
});
|
|
@@ -9277,7 +9430,7 @@ function getTextFromReference(document, id) {
|
|
|
9277
9430
|
if (!id || id instanceof DynamicValue) {
|
|
9278
9431
|
return id;
|
|
9279
9432
|
}
|
|
9280
|
-
const selector =
|
|
9433
|
+
const selector = generateIdSelector(id);
|
|
9281
9434
|
const ref = document.querySelector(selector);
|
|
9282
9435
|
if (ref) {
|
|
9283
9436
|
return ref.textContent;
|
|
@@ -10038,6 +10191,46 @@ class ValidAutocomplete extends Rule {
|
|
|
10038
10191
|
}
|
|
10039
10192
|
}
|
|
10040
10193
|
|
|
10194
|
+
function isLabelable(target) {
|
|
10195
|
+
const { meta } = target;
|
|
10196
|
+
if (!meta) {
|
|
10197
|
+
return true;
|
|
10198
|
+
}
|
|
10199
|
+
return Boolean(meta.labelable);
|
|
10200
|
+
}
|
|
10201
|
+
class ValidFor extends Rule {
|
|
10202
|
+
documentation() {
|
|
10203
|
+
return {
|
|
10204
|
+
description: `The \`<label>\` \`for\` attribute must reference a labelable form control.`,
|
|
10205
|
+
url: "https://html-validate.org/rules/valid-for.html"
|
|
10206
|
+
};
|
|
10207
|
+
}
|
|
10208
|
+
setup() {
|
|
10209
|
+
this.on("dom:ready", (event) => {
|
|
10210
|
+
const { document } = event;
|
|
10211
|
+
for (const node of document.querySelectorAll("label[for]")) {
|
|
10212
|
+
const attr = node.getAttribute("for");
|
|
10213
|
+
if (!isStaticAttribute(attr) || !attr.value) {
|
|
10214
|
+
continue;
|
|
10215
|
+
}
|
|
10216
|
+
const selector = generateIdSelector(attr.value);
|
|
10217
|
+
const target = document.querySelector(selector);
|
|
10218
|
+
if (!target) {
|
|
10219
|
+
continue;
|
|
10220
|
+
}
|
|
10221
|
+
if (isLabelable(target)) {
|
|
10222
|
+
continue;
|
|
10223
|
+
}
|
|
10224
|
+
this.report({
|
|
10225
|
+
node,
|
|
10226
|
+
message: '<label> "for" attribute must reference a labelable form control',
|
|
10227
|
+
location: attr.valueLocation
|
|
10228
|
+
});
|
|
10229
|
+
}
|
|
10230
|
+
});
|
|
10231
|
+
}
|
|
10232
|
+
}
|
|
10233
|
+
|
|
10041
10234
|
const defaults$4 = {
|
|
10042
10235
|
relaxed: false
|
|
10043
10236
|
};
|
|
@@ -10336,7 +10529,9 @@ class H36 extends Rule {
|
|
|
10336
10529
|
setup() {
|
|
10337
10530
|
this.on("tag:end", (event) => {
|
|
10338
10531
|
const node = event.previous;
|
|
10339
|
-
if (node.tagName !== "input")
|
|
10532
|
+
if (node.tagName !== "input") {
|
|
10533
|
+
return;
|
|
10534
|
+
}
|
|
10340
10535
|
if (node.getAttributeValue("type") !== "image") {
|
|
10341
10536
|
return;
|
|
10342
10537
|
}
|
|
@@ -10662,6 +10857,7 @@ const bundledRules = {
|
|
|
10662
10857
|
"unique-landmark": UniqueLandmark,
|
|
10663
10858
|
"unrecognized-char-ref": UnknownCharReference,
|
|
10664
10859
|
"valid-autocomplete": ValidAutocomplete,
|
|
10860
|
+
"valid-for": ValidFor,
|
|
10665
10861
|
"valid-id": ValidID,
|
|
10666
10862
|
"void-content": VoidContent,
|
|
10667
10863
|
"void-style": VoidStyle,
|
|
@@ -11015,6 +11211,7 @@ const config$1 = {
|
|
|
11015
11211
|
"unique-landmark": "error",
|
|
11016
11212
|
"unrecognized-char-ref": "error",
|
|
11017
11213
|
"valid-autocomplete": "error",
|
|
11214
|
+
"valid-for": "error",
|
|
11018
11215
|
"valid-id": ["error", { relaxed: false }],
|
|
11019
11216
|
void: "off",
|
|
11020
11217
|
"void-content": "error",
|
|
@@ -11062,6 +11259,7 @@ const config = {
|
|
|
11062
11259
|
"script-element": "error",
|
|
11063
11260
|
"unrecognized-char-ref": "error",
|
|
11064
11261
|
"valid-autocomplete": "error",
|
|
11262
|
+
"valid-for": "error",
|
|
11065
11263
|
"valid-id": ["error", { relaxed: true }],
|
|
11066
11264
|
"void-content": "error"
|
|
11067
11265
|
}
|
|
@@ -11668,7 +11866,9 @@ class Config {
|
|
|
11668
11866
|
}
|
|
11669
11867
|
for (const plugin of plugins) {
|
|
11670
11868
|
for (const [name, config] of Object.entries(plugin.configs ?? {})) {
|
|
11671
|
-
if (!config)
|
|
11869
|
+
if (!config) {
|
|
11870
|
+
continue;
|
|
11871
|
+
}
|
|
11672
11872
|
Config.validate(config, name);
|
|
11673
11873
|
configs.set(`${plugin.name}:${name}`, config);
|
|
11674
11874
|
if (plugin.name !== plugin.originalName) {
|
|
@@ -11969,7 +12169,7 @@ class EventHandler {
|
|
|
11969
12169
|
}
|
|
11970
12170
|
|
|
11971
12171
|
const name = "html-validate";
|
|
11972
|
-
const version = "10.
|
|
12172
|
+
const version = "10.7.0";
|
|
11973
12173
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11974
12174
|
|
|
11975
12175
|
function freeze(src) {
|
|
@@ -12020,6 +12220,7 @@ class Reporter {
|
|
|
12020
12220
|
warningCount: sumWarnings(results)
|
|
12021
12221
|
};
|
|
12022
12222
|
}
|
|
12223
|
+
/* eslint-disable-next-line @typescript-eslint/max-params -- technical debt */
|
|
12023
12224
|
add(rule, message, severity, node, location, context) {
|
|
12024
12225
|
if (!(location.filename in this.result)) {
|
|
12025
12226
|
this.result[location.filename] = [];
|
|
@@ -12139,7 +12340,7 @@ class ParserError extends Error {
|
|
|
12139
12340
|
}
|
|
12140
12341
|
|
|
12141
12342
|
function isAttrValueToken(token) {
|
|
12142
|
-
return
|
|
12343
|
+
return token?.type === TokenType.ATTR_VALUE;
|
|
12143
12344
|
}
|
|
12144
12345
|
function svgShouldRetainTag(foreignTagName, tagName) {
|
|
12145
12346
|
return foreignTagName === "svg" && ["title", "desc"].includes(tagName);
|
|
@@ -12485,7 +12686,7 @@ class Parser {
|
|
|
12485
12686
|
* ^^^ ^^^ ^^^ (null) (null)
|
|
12486
12687
|
*/
|
|
12487
12688
|
getAttributeValueLocation(token) {
|
|
12488
|
-
if (
|
|
12689
|
+
if (token?.type !== TokenType.ATTR_VALUE || token.data[2] === "") {
|
|
12489
12690
|
return null;
|
|
12490
12691
|
}
|
|
12491
12692
|
const quote = token.data[3];
|
|
@@ -12501,7 +12702,7 @@ class Parser {
|
|
|
12501
12702
|
*/
|
|
12502
12703
|
getAttributeLocation(key, value) {
|
|
12503
12704
|
const begin = key.location;
|
|
12504
|
-
const end = value
|
|
12705
|
+
const end = value?.type === TokenType.ATTR_VALUE ? value.location : void 0;
|
|
12505
12706
|
return {
|
|
12506
12707
|
filename: begin.filename,
|
|
12507
12708
|
line: begin.line,
|
|
@@ -12514,27 +12715,34 @@ class Parser {
|
|
|
12514
12715
|
* @internal
|
|
12515
12716
|
*/
|
|
12516
12717
|
consumeDirective(token) {
|
|
12517
|
-
const [text, preamble, action, separator1, directive, postamble] = token.data;
|
|
12518
|
-
|
|
12519
|
-
|
|
12718
|
+
const [text, preamble, prefix, action, separator1, directive, postamble] = token.data;
|
|
12719
|
+
const hasStartBracket = preamble.includes("[");
|
|
12720
|
+
const hasEndBracket = postamble.startsWith("]");
|
|
12721
|
+
if (hasStartBracket && !hasEndBracket) {
|
|
12722
|
+
this.trigger("parse:error", {
|
|
12723
|
+
location: sliceLocation(token.location, preamble.length - 1, -postamble.length),
|
|
12724
|
+
message: `Missing end bracket "]" on directive "${text}"`
|
|
12725
|
+
});
|
|
12726
|
+
return;
|
|
12520
12727
|
}
|
|
12521
12728
|
const match = /^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/.exec(directive);
|
|
12522
12729
|
if (!match) {
|
|
12523
12730
|
throw new Error(`Failed to parse directive "${text}"`);
|
|
12524
12731
|
}
|
|
12525
12732
|
if (!isValidDirective(action)) {
|
|
12526
|
-
|
|
12733
|
+
const begin = preamble.length;
|
|
12734
|
+
const end = preamble.length + prefix.length + action.length;
|
|
12735
|
+
this.trigger("parse:error", {
|
|
12736
|
+
location: sliceLocation(token.location, begin, -text.length + end),
|
|
12737
|
+
message: `Unknown directive "${action}"`
|
|
12738
|
+
});
|
|
12739
|
+
return;
|
|
12527
12740
|
}
|
|
12528
12741
|
const [, data, separator2, comment] = match;
|
|
12529
|
-
const
|
|
12530
|
-
const actionOffset = preamble.length;
|
|
12742
|
+
const actionOffset = preamble.length + prefix.length;
|
|
12531
12743
|
const optionsOffset = actionOffset + action.length + separator1.length;
|
|
12532
12744
|
const commentOffset = optionsOffset + data.length + (separator2 || "").length;
|
|
12533
|
-
const location = sliceLocation(
|
|
12534
|
-
token.location,
|
|
12535
|
-
preamble.length - prefix.length - 1,
|
|
12536
|
-
-postamble.length + 1
|
|
12537
|
-
);
|
|
12745
|
+
const location = sliceLocation(token.location, preamble.length - 1, -postamble.length + 1);
|
|
12538
12746
|
const actionLocation = sliceLocation(
|
|
12539
12747
|
token.location,
|
|
12540
12748
|
actionOffset,
|
|
@@ -12616,7 +12824,9 @@ class Parser {
|
|
|
12616
12824
|
while (!it.done) {
|
|
12617
12825
|
const token = it.value;
|
|
12618
12826
|
yield token;
|
|
12619
|
-
if (token.type === search)
|
|
12827
|
+
if (token.type === search) {
|
|
12828
|
+
return;
|
|
12829
|
+
}
|
|
12620
12830
|
it = this.next(tokenStream);
|
|
12621
12831
|
}
|
|
12622
12832
|
throw new ParserError(
|
|
@@ -12779,6 +12989,9 @@ class Engine {
|
|
|
12779
12989
|
parser.on("directive", (_2, event) => {
|
|
12780
12990
|
this.processDirective(event, parser, directiveContext);
|
|
12781
12991
|
});
|
|
12992
|
+
parser.on("parse:error", (_2, event) => {
|
|
12993
|
+
this.reportError("parser-error", event.message, event.location);
|
|
12994
|
+
});
|
|
12782
12995
|
try {
|
|
12783
12996
|
parser.parseHtml(source);
|
|
12784
12997
|
} catch (e) {
|
|
@@ -12976,7 +13189,9 @@ class Engine {
|
|
|
12976
13189
|
const availableRules = {};
|
|
12977
13190
|
for (const plugin of config.getPlugins()) {
|
|
12978
13191
|
for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
|
|
12979
|
-
if (!rule)
|
|
13192
|
+
if (!rule) {
|
|
13193
|
+
continue;
|
|
13194
|
+
}
|
|
12980
13195
|
availableRules[name] = rule;
|
|
12981
13196
|
}
|
|
12982
13197
|
}
|
|
@@ -13009,6 +13224,7 @@ class Engine {
|
|
|
13009
13224
|
/**
|
|
13010
13225
|
* Load and setup a rule using current config.
|
|
13011
13226
|
*/
|
|
13227
|
+
/* eslint-disable-next-line @typescript-eslint/max-params -- technical debt */
|
|
13012
13228
|
loadRule(ruleId, config, severity, options, parser, report) {
|
|
13013
13229
|
const meta = config.getMetaTable();
|
|
13014
13230
|
const rule = this.instantiateRule(ruleId, options);
|
|
@@ -14373,5 +14589,5 @@ const engines = {
|
|
|
14373
14589
|
|
|
14374
14590
|
var workerPath = "./jest-worker.js";
|
|
14375
14591
|
|
|
14376
|
-
export {
|
|
14592
|
+
export { engines as $, Attribute as A, isUserError as B, ConfigLoader as C, DOMNode as D, Engine as E, MetaTable as F, TextContent$1 as G, HtmlElement as H, Rule as I, TextClassification as J, ariaNaming as K, classifyNodeText as L, MetaCopyableProperty as M, NodeClosed as N, keywordPatternMatcher as O, Parser as P, sliceLocation as Q, Reporter as R, StaticConfigLoader as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, definePlugin as X, ruleExists as Y, walk as Z, EventHandler as _, transformSourceSync as a, workerPath as a0, codeframe as a1, name as a2, bugs as a3, transformFilename as b, transformFilenameSync as c, configurationSchema as d, ConfigError as e, Config as f, compatibilityCheckImpl as g, getFormatter as h, isThenable as i, ensureError as j, deepmerge as k, ignore as l, ResolvedConfig as m, normalizeSource as n, Severity as o, presets as p, defineConfig as q, DOMTokenList as r, staticResolver as s, transformSource as t, DOMTree as u, version as v, DynamicValue as w, NodeType as x, NestedError as y, SchemaValidationError as z };
|
|
14377
14593
|
//# sourceMappingURL=core.js.map
|