html-validate 7.18.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.js +4 -4
- package/dist/cjs/cli.js +23 -9
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core.js +632 -598
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/html-validate.js +13 -3
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/index.js +5 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/jest-lib.js +2 -2
- package/dist/cjs/jest-lib.js.map +1 -1
- package/dist/cjs/jest.js +3 -3
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/es/browser.js +5 -5
- package/dist/es/cli.js +24 -10
- package/dist/es/cli.js.map +1 -1
- package/dist/es/core.js +628 -576
- package/dist/es/core.js.map +1 -1
- package/dist/es/html-validate.js +13 -4
- package/dist/es/html-validate.js.map +1 -1
- package/dist/es/index.js +5 -5
- package/dist/es/jest-lib.js +2 -2
- package/dist/es/jest-lib.js.map +1 -1
- package/dist/es/jest.js +4 -4
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +343 -91
- package/dist/types/index.d.ts +402 -94
- package/package.json +13 -16
package/dist/es/core.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import * as espree from 'espree';
|
|
3
|
-
import * as walk from 'acorn-walk';
|
|
4
1
|
import path from 'path';
|
|
5
2
|
import semver from 'semver';
|
|
6
3
|
import kleur from 'kleur';
|
|
4
|
+
import fs$1 from 'node:fs';
|
|
5
|
+
import path$1 from 'node:path';
|
|
7
6
|
import Ajv from 'ajv';
|
|
8
7
|
import deepmerge from 'deepmerge';
|
|
9
8
|
import { e as entities$1, h as html5, b as bundledElements } from './elements.js';
|
|
10
|
-
import { createRequire } from 'module';
|
|
11
9
|
import { i as isKeywordIgnored, C as CaseStyle, n as naturalJoin, c as classifyNodeText, T as TextClassification, h as hasAltText, p as partition, a as isHTMLHidden, b as isAriaHidden, d as hasAccessibleName, k as keywordPatternMatcher, e as inAccessibilityTree, f as hasAriaLabel } from './rules-helper.js';
|
|
10
|
+
import fs from 'fs';
|
|
12
11
|
import betterAjvErrors from '@sidvind/better-ajv-errors';
|
|
12
|
+
import { createRequire } from 'module';
|
|
13
13
|
import { codeFrameColumns } from '@babel/code-frame';
|
|
14
14
|
import { stylish as stylish$2 } from '@html-validate/stylish';
|
|
15
15
|
|
|
@@ -3157,232 +3157,11 @@ var configurationSchema = {
|
|
|
3157
3157
|
properties: properties
|
|
3158
3158
|
};
|
|
3159
3159
|
|
|
3160
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion -- declarations say
|
|
3161
|
-
* location fields are optional but they are always present when `{loc: true}` */
|
|
3162
|
-
function joinTemplateLiteral(nodes) {
|
|
3163
|
-
let offset = nodes[0].start + 1;
|
|
3164
|
-
let output = "";
|
|
3165
|
-
for (const node of nodes) {
|
|
3166
|
-
output += " ".repeat(node.start + 1 - offset);
|
|
3167
|
-
output += node.value.raw;
|
|
3168
|
-
offset = node.end - 2;
|
|
3169
|
-
}
|
|
3170
|
-
return output;
|
|
3171
|
-
}
|
|
3172
|
-
/**
|
|
3173
|
-
* Compute source offset from line and column and the given markup.
|
|
3174
|
-
*
|
|
3175
|
-
* @param position - Line and column.
|
|
3176
|
-
* @param data - Source markup.
|
|
3177
|
-
* @returns The byte offset into the markup which line and column corresponds to.
|
|
3178
|
-
*/
|
|
3179
|
-
function computeOffset(position, data) {
|
|
3180
|
-
let line = position.line;
|
|
3181
|
-
let column = position.column + 1;
|
|
3182
|
-
for (let i = 0; i < data.length; i++) {
|
|
3183
|
-
if (line > 1) {
|
|
3184
|
-
/* not yet on the correct line */
|
|
3185
|
-
if (data[i] === "\n") {
|
|
3186
|
-
line--;
|
|
3187
|
-
}
|
|
3188
|
-
}
|
|
3189
|
-
else if (column > 1) {
|
|
3190
|
-
/* not yet on the correct column */
|
|
3191
|
-
column--;
|
|
3192
|
-
}
|
|
3193
|
-
else {
|
|
3194
|
-
/* line/column found, return current position */
|
|
3195
|
-
return i;
|
|
3196
|
-
}
|
|
3197
|
-
}
|
|
3198
|
-
/* istanbul ignore next: should never reach this line unless espree passes bad
|
|
3199
|
-
* positions, no sane way to test */
|
|
3200
|
-
throw new Error("Failed to compute location offset from position");
|
|
3201
|
-
}
|
|
3202
|
-
function extractLiteral(node, filename, data) {
|
|
3203
|
-
switch (node.type) {
|
|
3204
|
-
/* ignored nodes */
|
|
3205
|
-
case "FunctionExpression":
|
|
3206
|
-
case "Identifier":
|
|
3207
|
-
return null;
|
|
3208
|
-
case "Literal":
|
|
3209
|
-
if (typeof node.value !== "string") {
|
|
3210
|
-
return null;
|
|
3211
|
-
}
|
|
3212
|
-
return {
|
|
3213
|
-
data: node.value.toString(),
|
|
3214
|
-
filename,
|
|
3215
|
-
line: node.loc.start.line,
|
|
3216
|
-
column: node.loc.start.column + 1,
|
|
3217
|
-
offset: computeOffset(node.loc.start, data) + 1,
|
|
3218
|
-
};
|
|
3219
|
-
case "TemplateLiteral":
|
|
3220
|
-
return {
|
|
3221
|
-
data: joinTemplateLiteral(node.quasis),
|
|
3222
|
-
filename,
|
|
3223
|
-
line: node.loc.start.line,
|
|
3224
|
-
column: node.loc.start.column + 1,
|
|
3225
|
-
offset: computeOffset(node.loc.start, data) + 1,
|
|
3226
|
-
};
|
|
3227
|
-
case "TaggedTemplateExpression":
|
|
3228
|
-
return {
|
|
3229
|
-
data: joinTemplateLiteral(node.quasi.quasis),
|
|
3230
|
-
filename,
|
|
3231
|
-
line: node.quasi.loc.start.line,
|
|
3232
|
-
column: node.quasi.loc.start.column + 1,
|
|
3233
|
-
offset: computeOffset(node.quasi.loc.start, data) + 1,
|
|
3234
|
-
};
|
|
3235
|
-
case "ArrowFunctionExpression": {
|
|
3236
|
-
const whitelist = ["Literal", "TemplateLiteral"];
|
|
3237
|
-
if (whitelist.includes(node.body.type)) {
|
|
3238
|
-
return extractLiteral(node.body, filename, data);
|
|
3239
|
-
}
|
|
3240
|
-
else {
|
|
3241
|
-
return null;
|
|
3242
|
-
}
|
|
3243
|
-
}
|
|
3244
|
-
/* istanbul ignore next: this only provides a better error, all currently known nodes are tested */
|
|
3245
|
-
default: {
|
|
3246
|
-
const loc = node.loc.start;
|
|
3247
|
-
const context = `${filename}:${loc.line}:${loc.column}`;
|
|
3248
|
-
throw new Error(`Unhandled node type "${node.type}" at "${context}" in extractLiteral`);
|
|
3249
|
-
}
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
function compareKey(node, key, filename) {
|
|
3253
|
-
switch (node.type) {
|
|
3254
|
-
case "Identifier":
|
|
3255
|
-
return node.name === key;
|
|
3256
|
-
case "Literal":
|
|
3257
|
-
return node.value === key;
|
|
3258
|
-
/* istanbul ignore next: this only provides a better error, all currently known nodes are tested */
|
|
3259
|
-
default: {
|
|
3260
|
-
const loc = node.loc.start;
|
|
3261
|
-
const context = `${filename}:${loc.line}:${loc.column}`;
|
|
3262
|
-
throw new Error(`Unhandled node type "${node.type}" at "${context}" in compareKey`);
|
|
3263
|
-
}
|
|
3264
|
-
}
|
|
3265
|
-
}
|
|
3266
|
-
/**
|
|
3267
|
-
* @public
|
|
3268
|
-
*/
|
|
3269
|
-
class TemplateExtractor {
|
|
3270
|
-
constructor(ast, filename, data) {
|
|
3271
|
-
this.ast = ast;
|
|
3272
|
-
this.filename = filename;
|
|
3273
|
-
this.data = data;
|
|
3274
|
-
}
|
|
3275
|
-
static fromFilename(filename) {
|
|
3276
|
-
const source = fs.readFileSync(filename, "utf-8");
|
|
3277
|
-
const ast = espree.parse(source, {
|
|
3278
|
-
ecmaVersion: 2017,
|
|
3279
|
-
sourceType: "module",
|
|
3280
|
-
loc: true,
|
|
3281
|
-
});
|
|
3282
|
-
return new TemplateExtractor(ast, filename, source);
|
|
3283
|
-
}
|
|
3284
|
-
/**
|
|
3285
|
-
* Create a new [[TemplateExtractor]] from javascript source code.
|
|
3286
|
-
*
|
|
3287
|
-
* `Source` offsets will be relative to the string, i.e. offset 0 is the first
|
|
3288
|
-
* character of the string. If the string is only a subset of a larger string
|
|
3289
|
-
* the offsets must be adjusted manually.
|
|
3290
|
-
*
|
|
3291
|
-
* @param source - Source code.
|
|
3292
|
-
* @param filename - Optional filename to set in the resulting
|
|
3293
|
-
* `Source`. Defauls to `"inline"`.
|
|
3294
|
-
*/
|
|
3295
|
-
static fromString(source, filename) {
|
|
3296
|
-
const ast = espree.parse(source, {
|
|
3297
|
-
ecmaVersion: 2017,
|
|
3298
|
-
sourceType: "module",
|
|
3299
|
-
loc: true,
|
|
3300
|
-
});
|
|
3301
|
-
return new TemplateExtractor(ast, filename || "inline", source);
|
|
3302
|
-
}
|
|
3303
|
-
/**
|
|
3304
|
-
* Convenience function to create a [[Source]] instance from an existing file.
|
|
3305
|
-
*
|
|
3306
|
-
* @param filename - Filename with javascript source code. The file must exist
|
|
3307
|
-
* and be readable by the user.
|
|
3308
|
-
* @returns An array of Source's suitable for passing to [[Engine]] linting
|
|
3309
|
-
* functions.
|
|
3310
|
-
*/
|
|
3311
|
-
static createSource(filename) {
|
|
3312
|
-
const data = fs.readFileSync(filename, "utf-8");
|
|
3313
|
-
return [
|
|
3314
|
-
{
|
|
3315
|
-
column: 1,
|
|
3316
|
-
data,
|
|
3317
|
-
filename,
|
|
3318
|
-
line: 1,
|
|
3319
|
-
offset: 0,
|
|
3320
|
-
},
|
|
3321
|
-
];
|
|
3322
|
-
}
|
|
3323
|
-
/**
|
|
3324
|
-
* Extract object properties.
|
|
3325
|
-
*
|
|
3326
|
-
* Given a key `"template"` this method finds all objects literals with a
|
|
3327
|
-
* `"template"` property and creates a [[Source]] instance with proper offsets
|
|
3328
|
-
* with the value of the property. For instance:
|
|
3329
|
-
*
|
|
3330
|
-
* ```
|
|
3331
|
-
* const myObj = {
|
|
3332
|
-
* foo: 'bar',
|
|
3333
|
-
* };
|
|
3334
|
-
* ```
|
|
3335
|
-
*
|
|
3336
|
-
* The above snippet would yield a `Source` with the content `bar`.
|
|
3337
|
-
*
|
|
3338
|
-
*/
|
|
3339
|
-
extractObjectProperty(key) {
|
|
3340
|
-
const result = [];
|
|
3341
|
-
const { filename, data } = this;
|
|
3342
|
-
const node = this.ast;
|
|
3343
|
-
walk.simple(node, {
|
|
3344
|
-
Property(node) {
|
|
3345
|
-
if (compareKey(node.key, key, filename)) {
|
|
3346
|
-
const source = extractLiteral(node.value, filename, data);
|
|
3347
|
-
if (source) {
|
|
3348
|
-
source.filename = filename;
|
|
3349
|
-
result.push(source);
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
|
-
},
|
|
3353
|
-
});
|
|
3354
|
-
return result;
|
|
3355
|
-
}
|
|
3356
|
-
}
|
|
3357
|
-
|
|
3358
3160
|
var TRANSFORMER_API;
|
|
3359
3161
|
(function (TRANSFORMER_API) {
|
|
3360
3162
|
TRANSFORMER_API[TRANSFORMER_API["VERSION"] = 1] = "VERSION";
|
|
3361
3163
|
})(TRANSFORMER_API || (TRANSFORMER_API = {}));
|
|
3362
3164
|
|
|
3363
|
-
/**
|
|
3364
|
-
* Similar to `require(..)` but removes the cached copy first.
|
|
3365
|
-
*/
|
|
3366
|
-
function requireUncached(require, moduleId) {
|
|
3367
|
-
const filename = require.resolve(moduleId);
|
|
3368
|
-
/* remove references from the parent module to prevent memory leak */
|
|
3369
|
-
const m = require.cache[filename];
|
|
3370
|
-
if (m && m.parent) {
|
|
3371
|
-
const { parent } = m;
|
|
3372
|
-
for (let i = parent.children.length - 1; i >= 0; i--) {
|
|
3373
|
-
if (parent.children[i].id === filename) {
|
|
3374
|
-
parent.children.splice(i, 1);
|
|
3375
|
-
}
|
|
3376
|
-
}
|
|
3377
|
-
}
|
|
3378
|
-
/* remove old module from cache */
|
|
3379
|
-
delete require.cache[filename];
|
|
3380
|
-
/* eslint-disable-next-line import/no-dynamic-require, security/detect-non-literal-require -- as expected but should be moved to upcoming resolver class */
|
|
3381
|
-
return require(filename);
|
|
3382
|
-
}
|
|
3383
|
-
|
|
3384
|
-
const legacyRequire = createRequire(import.meta.url);
|
|
3385
|
-
|
|
3386
3165
|
/**
|
|
3387
3166
|
* @public
|
|
3388
3167
|
*/
|
|
@@ -3400,11 +3179,6 @@ function parseSeverity(value) {
|
|
|
3400
3179
|
case 0:
|
|
3401
3180
|
case "off":
|
|
3402
3181
|
return Severity.DISABLED;
|
|
3403
|
-
/* istanbul ignore next: deprecated code which will be removed later */
|
|
3404
|
-
case "disable":
|
|
3405
|
-
// eslint-disable-next-line no-console -- expected to log
|
|
3406
|
-
console.warn(`Deprecated alias "disabled" will be removed, replace with severity "off"`);
|
|
3407
|
-
return Severity.DISABLED;
|
|
3408
3182
|
case 1:
|
|
3409
3183
|
case "warn":
|
|
3410
3184
|
return Severity.WARN;
|
|
@@ -3739,6 +3513,8 @@ class Rule {
|
|
|
3739
3513
|
* Called when requesting additional documentation for a rule. Some rules
|
|
3740
3514
|
* provide additional context to provide context-aware suggestions.
|
|
3741
3515
|
*
|
|
3516
|
+
* @public
|
|
3517
|
+
* @virtual
|
|
3742
3518
|
* @param context - Error context given by a reported error.
|
|
3743
3519
|
* @returns Rule documentation and url with additional details or `null` if no
|
|
3744
3520
|
* additional documentation is available.
|
|
@@ -3749,15 +3525,15 @@ class Rule {
|
|
|
3749
3525
|
}
|
|
3750
3526
|
}
|
|
3751
3527
|
|
|
3752
|
-
var Style$
|
|
3528
|
+
var Style$1;
|
|
3753
3529
|
(function (Style) {
|
|
3754
3530
|
Style["EXTERNAL"] = "external";
|
|
3755
3531
|
Style["RELATIVE_BASE"] = "relative-base";
|
|
3756
3532
|
Style["RELATIVE_PATH"] = "relative-path";
|
|
3757
3533
|
Style["ABSOLUTE"] = "absolute";
|
|
3758
3534
|
Style["ANCHOR"] = "anchor";
|
|
3759
|
-
})(Style$
|
|
3760
|
-
const defaults$
|
|
3535
|
+
})(Style$1 || (Style$1 = {}));
|
|
3536
|
+
const defaults$v = {
|
|
3761
3537
|
allowExternal: true,
|
|
3762
3538
|
allowRelative: true,
|
|
3763
3539
|
allowAbsolute: true,
|
|
@@ -3770,11 +3546,11 @@ const mapping$1 = {
|
|
|
3770
3546
|
script: "src",
|
|
3771
3547
|
};
|
|
3772
3548
|
const description = {
|
|
3773
|
-
[Style$
|
|
3774
|
-
[Style$
|
|
3775
|
-
[Style$
|
|
3776
|
-
[Style$
|
|
3777
|
-
[Style$
|
|
3549
|
+
[Style$1.EXTERNAL]: "External links are not allowed by current configuration.",
|
|
3550
|
+
[Style$1.RELATIVE_BASE]: "Links relative to <base> are not allowed by current configuration.",
|
|
3551
|
+
[Style$1.RELATIVE_PATH]: "Relative links are not allowed by current configuration.",
|
|
3552
|
+
[Style$1.ABSOLUTE]: "Absolute links are not allowed by current configuration.",
|
|
3553
|
+
[Style$1.ANCHOR]: null,
|
|
3778
3554
|
};
|
|
3779
3555
|
function parseAllow(value) {
|
|
3780
3556
|
if (typeof value === "boolean") {
|
|
@@ -3801,7 +3577,7 @@ function matchList(value, list) {
|
|
|
3801
3577
|
}
|
|
3802
3578
|
class AllowedLinks extends Rule {
|
|
3803
3579
|
constructor(options) {
|
|
3804
|
-
super({ ...defaults$
|
|
3580
|
+
super({ ...defaults$v, ...options });
|
|
3805
3581
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
3806
3582
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
3807
3583
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -3847,19 +3623,19 @@ class AllowedLinks extends Rule {
|
|
|
3847
3623
|
const link = event.value.toString();
|
|
3848
3624
|
const style = this.getStyle(link);
|
|
3849
3625
|
switch (style) {
|
|
3850
|
-
case Style$
|
|
3626
|
+
case Style$1.ANCHOR:
|
|
3851
3627
|
/* anchor links are always allowed by this rule */
|
|
3852
3628
|
break;
|
|
3853
|
-
case Style$
|
|
3629
|
+
case Style$1.ABSOLUTE:
|
|
3854
3630
|
this.handleAbsolute(link, event, style);
|
|
3855
3631
|
break;
|
|
3856
|
-
case Style$
|
|
3632
|
+
case Style$1.EXTERNAL:
|
|
3857
3633
|
this.handleExternal(link, event, style);
|
|
3858
3634
|
break;
|
|
3859
|
-
case Style$
|
|
3635
|
+
case Style$1.RELATIVE_BASE:
|
|
3860
3636
|
this.handleRelativeBase(link, event, style);
|
|
3861
3637
|
break;
|
|
3862
|
-
case Style$
|
|
3638
|
+
case Style$1.RELATIVE_PATH:
|
|
3863
3639
|
this.handleRelativePath(link, event, style);
|
|
3864
3640
|
break;
|
|
3865
3641
|
}
|
|
@@ -3877,21 +3653,21 @@ class AllowedLinks extends Rule {
|
|
|
3877
3653
|
getStyle(value) {
|
|
3878
3654
|
/* http://example.net or //example.net */
|
|
3879
3655
|
if (value.match(/^([a-z]+:)?\/\//g)) {
|
|
3880
|
-
return Style$
|
|
3656
|
+
return Style$1.EXTERNAL;
|
|
3881
3657
|
}
|
|
3882
3658
|
switch (value[0]) {
|
|
3883
3659
|
/* /foo/bar */
|
|
3884
3660
|
case "/":
|
|
3885
|
-
return Style$
|
|
3661
|
+
return Style$1.ABSOLUTE;
|
|
3886
3662
|
/* ../foo/bar */
|
|
3887
3663
|
case ".":
|
|
3888
|
-
return Style$
|
|
3664
|
+
return Style$1.RELATIVE_PATH;
|
|
3889
3665
|
/* #foo */
|
|
3890
3666
|
case "#":
|
|
3891
|
-
return Style$
|
|
3667
|
+
return Style$1.ANCHOR;
|
|
3892
3668
|
/* foo/bar */
|
|
3893
3669
|
default:
|
|
3894
|
-
return Style$
|
|
3670
|
+
return Style$1.RELATIVE_BASE;
|
|
3895
3671
|
}
|
|
3896
3672
|
}
|
|
3897
3673
|
handleAbsolute(target, event, style) {
|
|
@@ -3949,7 +3725,7 @@ var RuleContext$1;
|
|
|
3949
3725
|
RuleContext["MISSING_ALT"] = "missing-alt";
|
|
3950
3726
|
RuleContext["MISSING_HREF"] = "missing-href";
|
|
3951
3727
|
})(RuleContext$1 || (RuleContext$1 = {}));
|
|
3952
|
-
const defaults$
|
|
3728
|
+
const defaults$u = {
|
|
3953
3729
|
accessible: true,
|
|
3954
3730
|
};
|
|
3955
3731
|
function findByTarget(target, siblings) {
|
|
@@ -3987,7 +3763,7 @@ function getDescription$1(context) {
|
|
|
3987
3763
|
}
|
|
3988
3764
|
class AreaAlt extends Rule {
|
|
3989
3765
|
constructor(options) {
|
|
3990
|
-
super({ ...defaults$
|
|
3766
|
+
super({ ...defaults$u, ...options });
|
|
3991
3767
|
}
|
|
3992
3768
|
static schema() {
|
|
3993
3769
|
return {
|
|
@@ -4167,13 +3943,13 @@ class ConfigError extends UserError {
|
|
|
4167
3943
|
}
|
|
4168
3944
|
}
|
|
4169
3945
|
|
|
4170
|
-
const defaults$
|
|
3946
|
+
const defaults$t = {
|
|
4171
3947
|
style: "lowercase",
|
|
4172
3948
|
ignoreForeign: true,
|
|
4173
3949
|
};
|
|
4174
3950
|
class AttrCase extends Rule {
|
|
4175
3951
|
constructor(options) {
|
|
4176
|
-
super({ ...defaults$
|
|
3952
|
+
super({ ...defaults$t, ...options });
|
|
4177
3953
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4178
3954
|
}
|
|
4179
3955
|
static schema() {
|
|
@@ -4521,7 +4297,7 @@ class AttrDelimiter extends Rule {
|
|
|
4521
4297
|
}
|
|
4522
4298
|
|
|
4523
4299
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4524
|
-
const defaults$
|
|
4300
|
+
const defaults$s = {
|
|
4525
4301
|
pattern: DEFAULT_PATTERN,
|
|
4526
4302
|
ignoreForeign: true,
|
|
4527
4303
|
};
|
|
@@ -4558,7 +4334,7 @@ function generateDescription(name, pattern) {
|
|
|
4558
4334
|
}
|
|
4559
4335
|
class AttrPattern extends Rule {
|
|
4560
4336
|
constructor(options) {
|
|
4561
|
-
super({ ...defaults$
|
|
4337
|
+
super({ ...defaults$s, ...options });
|
|
4562
4338
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4563
4339
|
}
|
|
4564
4340
|
static schema() {
|
|
@@ -4619,7 +4395,7 @@ var QuoteStyle;
|
|
|
4619
4395
|
QuoteStyle["AUTO_QUOTE"] = "auto";
|
|
4620
4396
|
QuoteStyle["ANY_QUOTE"] = "any";
|
|
4621
4397
|
})(QuoteStyle || (QuoteStyle = {}));
|
|
4622
|
-
const defaults$
|
|
4398
|
+
const defaults$r = {
|
|
4623
4399
|
style: "auto",
|
|
4624
4400
|
unquoted: false,
|
|
4625
4401
|
};
|
|
@@ -4686,8 +4462,8 @@ class AttrQuotes extends Rule {
|
|
|
4686
4462
|
};
|
|
4687
4463
|
}
|
|
4688
4464
|
constructor(options) {
|
|
4689
|
-
super({ ...defaults$
|
|
4690
|
-
this.style = parseStyle$
|
|
4465
|
+
super({ ...defaults$r, ...options });
|
|
4466
|
+
this.style = parseStyle$3(this.options.style);
|
|
4691
4467
|
}
|
|
4692
4468
|
setup() {
|
|
4693
4469
|
this.on("attr", (event) => {
|
|
@@ -4734,7 +4510,7 @@ class AttrQuotes extends Rule {
|
|
|
4734
4510
|
}
|
|
4735
4511
|
}
|
|
4736
4512
|
}
|
|
4737
|
-
function parseStyle$
|
|
4513
|
+
function parseStyle$3(style) {
|
|
4738
4514
|
switch (style.toLowerCase()) {
|
|
4739
4515
|
case "auto":
|
|
4740
4516
|
return QuoteStyle.AUTO_QUOTE;
|
|
@@ -4856,13 +4632,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
4856
4632
|
}
|
|
4857
4633
|
}
|
|
4858
4634
|
|
|
4859
|
-
const defaults$
|
|
4635
|
+
const defaults$q = {
|
|
4860
4636
|
style: "omit",
|
|
4861
4637
|
};
|
|
4862
4638
|
class AttributeBooleanStyle extends Rule {
|
|
4863
4639
|
constructor(options) {
|
|
4864
|
-
super({ ...defaults$
|
|
4865
|
-
this.hasInvalidStyle = parseStyle$
|
|
4640
|
+
super({ ...defaults$q, ...options });
|
|
4641
|
+
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
4866
4642
|
}
|
|
4867
4643
|
static schema() {
|
|
4868
4644
|
return {
|
|
@@ -4910,7 +4686,7 @@ class AttributeBooleanStyle extends Rule {
|
|
|
4910
4686
|
return Boolean((_a = rules[attr.key]) === null || _a === void 0 ? void 0 : _a.boolean);
|
|
4911
4687
|
}
|
|
4912
4688
|
}
|
|
4913
|
-
function parseStyle$
|
|
4689
|
+
function parseStyle$2(style) {
|
|
4914
4690
|
switch (style.toLowerCase()) {
|
|
4915
4691
|
case "omit":
|
|
4916
4692
|
return (attr) => attr.value !== null;
|
|
@@ -4937,13 +4713,13 @@ function reportMessage$1(attr, style) {
|
|
|
4937
4713
|
return "";
|
|
4938
4714
|
}
|
|
4939
4715
|
|
|
4940
|
-
const defaults$
|
|
4716
|
+
const defaults$p = {
|
|
4941
4717
|
style: "omit",
|
|
4942
4718
|
};
|
|
4943
4719
|
class AttributeEmptyStyle extends Rule {
|
|
4944
4720
|
constructor(options) {
|
|
4945
|
-
super({ ...defaults$
|
|
4946
|
-
this.hasInvalidStyle = parseStyle$
|
|
4721
|
+
super({ ...defaults$p, ...options });
|
|
4722
|
+
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
4947
4723
|
}
|
|
4948
4724
|
static schema() {
|
|
4949
4725
|
return {
|
|
@@ -5001,7 +4777,7 @@ function isEmptyValue(attr) {
|
|
|
5001
4777
|
}
|
|
5002
4778
|
return attr.value === null || attr.value === "";
|
|
5003
4779
|
}
|
|
5004
|
-
function parseStyle$
|
|
4780
|
+
function parseStyle$1(style) {
|
|
5005
4781
|
switch (style.toLowerCase()) {
|
|
5006
4782
|
case "omit":
|
|
5007
4783
|
return (attr) => attr.value !== null;
|
|
@@ -5098,12 +4874,12 @@ function describePattern(pattern) {
|
|
|
5098
4874
|
}
|
|
5099
4875
|
}
|
|
5100
4876
|
|
|
5101
|
-
const defaults$
|
|
4877
|
+
const defaults$o = {
|
|
5102
4878
|
pattern: "kebabcase",
|
|
5103
4879
|
};
|
|
5104
4880
|
class ClassPattern extends Rule {
|
|
5105
4881
|
constructor(options) {
|
|
5106
|
-
super({ ...defaults$
|
|
4882
|
+
super({ ...defaults$o, ...options });
|
|
5107
4883
|
this.pattern = parsePattern(this.options.pattern);
|
|
5108
4884
|
}
|
|
5109
4885
|
static schema() {
|
|
@@ -5212,13 +4988,13 @@ class CloseOrder extends Rule {
|
|
|
5212
4988
|
}
|
|
5213
4989
|
}
|
|
5214
4990
|
|
|
5215
|
-
const defaults$
|
|
4991
|
+
const defaults$n = {
|
|
5216
4992
|
include: null,
|
|
5217
4993
|
exclude: null,
|
|
5218
4994
|
};
|
|
5219
4995
|
class Deprecated extends Rule {
|
|
5220
4996
|
constructor(options) {
|
|
5221
|
-
super({ ...defaults$
|
|
4997
|
+
super({ ...defaults$n, ...options });
|
|
5222
4998
|
}
|
|
5223
4999
|
static schema() {
|
|
5224
5000
|
return {
|
|
@@ -5381,12 +5157,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
5381
5157
|
}
|
|
5382
5158
|
};
|
|
5383
5159
|
|
|
5384
|
-
const defaults$
|
|
5160
|
+
const defaults$m = {
|
|
5385
5161
|
style: "uppercase",
|
|
5386
5162
|
};
|
|
5387
5163
|
class DoctypeStyle extends Rule {
|
|
5388
5164
|
constructor(options) {
|
|
5389
|
-
super({ ...defaults$
|
|
5165
|
+
super({ ...defaults$m, ...options });
|
|
5390
5166
|
}
|
|
5391
5167
|
static schema() {
|
|
5392
5168
|
return {
|
|
@@ -5418,12 +5194,12 @@ class DoctypeStyle extends Rule {
|
|
|
5418
5194
|
}
|
|
5419
5195
|
}
|
|
5420
5196
|
|
|
5421
|
-
const defaults$
|
|
5197
|
+
const defaults$l = {
|
|
5422
5198
|
style: "lowercase",
|
|
5423
5199
|
};
|
|
5424
5200
|
class ElementCase extends Rule {
|
|
5425
5201
|
constructor(options) {
|
|
5426
|
-
super({ ...defaults$
|
|
5202
|
+
super({ ...defaults$l, ...options });
|
|
5427
5203
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
5428
5204
|
}
|
|
5429
5205
|
static schema() {
|
|
@@ -5489,14 +5265,14 @@ class ElementCase extends Rule {
|
|
|
5489
5265
|
}
|
|
5490
5266
|
}
|
|
5491
5267
|
|
|
5492
|
-
const defaults$
|
|
5268
|
+
const defaults$k = {
|
|
5493
5269
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
5494
5270
|
whitelist: [],
|
|
5495
5271
|
blacklist: [],
|
|
5496
5272
|
};
|
|
5497
5273
|
class ElementName extends Rule {
|
|
5498
5274
|
constructor(options) {
|
|
5499
|
-
super({ ...defaults$
|
|
5275
|
+
super({ ...defaults$k, ...options });
|
|
5500
5276
|
/* eslint-disable-next-line security/detect-non-literal-regexp -- expected to be a regexp */
|
|
5501
5277
|
this.pattern = new RegExp(this.options.pattern);
|
|
5502
5278
|
}
|
|
@@ -5537,7 +5313,7 @@ class ElementName extends Rule {
|
|
|
5537
5313
|
...context.blacklist.map((cur) => `- ${cur}`),
|
|
5538
5314
|
];
|
|
5539
5315
|
}
|
|
5540
|
-
if (context.pattern !== defaults$
|
|
5316
|
+
if (context.pattern !== defaults$k.pattern) {
|
|
5541
5317
|
return [
|
|
5542
5318
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
5543
5319
|
"",
|
|
@@ -6081,7 +5857,7 @@ class EmptyTitle extends Rule {
|
|
|
6081
5857
|
}
|
|
6082
5858
|
}
|
|
6083
5859
|
|
|
6084
|
-
const defaults$
|
|
5860
|
+
const defaults$j = {
|
|
6085
5861
|
allowArrayBrackets: true,
|
|
6086
5862
|
shared: ["radio", "button", "reset", "submit"],
|
|
6087
5863
|
};
|
|
@@ -6114,7 +5890,7 @@ function getDocumentation(context) {
|
|
|
6114
5890
|
}
|
|
6115
5891
|
class FormDupName extends Rule {
|
|
6116
5892
|
constructor(options) {
|
|
6117
|
-
super({ ...defaults$
|
|
5893
|
+
super({ ...defaults$j, ...options });
|
|
6118
5894
|
}
|
|
6119
5895
|
static schema() {
|
|
6120
5896
|
return {
|
|
@@ -6274,7 +6050,7 @@ class FormDupName extends Rule {
|
|
|
6274
6050
|
}
|
|
6275
6051
|
}
|
|
6276
6052
|
|
|
6277
|
-
const defaults$
|
|
6053
|
+
const defaults$i = {
|
|
6278
6054
|
allowMultipleH1: false,
|
|
6279
6055
|
minInitialRank: "h1",
|
|
6280
6056
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]'],
|
|
@@ -6305,7 +6081,7 @@ function parseMaxInitial(value) {
|
|
|
6305
6081
|
}
|
|
6306
6082
|
class HeadingLevel extends Rule {
|
|
6307
6083
|
constructor(options) {
|
|
6308
|
-
super({ ...defaults$
|
|
6084
|
+
super({ ...defaults$i, ...options });
|
|
6309
6085
|
this.stack = [];
|
|
6310
6086
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
6311
6087
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
|
|
@@ -6463,12 +6239,12 @@ class HeadingLevel extends Rule {
|
|
|
6463
6239
|
}
|
|
6464
6240
|
}
|
|
6465
6241
|
|
|
6466
|
-
const defaults$
|
|
6242
|
+
const defaults$h = {
|
|
6467
6243
|
pattern: "kebabcase",
|
|
6468
6244
|
};
|
|
6469
6245
|
class IdPattern extends Rule {
|
|
6470
6246
|
constructor(options) {
|
|
6471
|
-
super({ ...defaults$
|
|
6247
|
+
super({ ...defaults$h, ...options });
|
|
6472
6248
|
this.pattern = parsePattern(this.options.pattern);
|
|
6473
6249
|
}
|
|
6474
6250
|
static schema() {
|
|
@@ -6750,12 +6526,12 @@ function findLabelByParent(el) {
|
|
|
6750
6526
|
return [];
|
|
6751
6527
|
}
|
|
6752
6528
|
|
|
6753
|
-
const defaults$
|
|
6529
|
+
const defaults$g = {
|
|
6754
6530
|
maxlength: 70,
|
|
6755
6531
|
};
|
|
6756
6532
|
class LongTitle extends Rule {
|
|
6757
6533
|
constructor(options) {
|
|
6758
|
-
super({ ...defaults$
|
|
6534
|
+
super({ ...defaults$g, ...options });
|
|
6759
6535
|
this.maxlength = this.options.maxlength;
|
|
6760
6536
|
}
|
|
6761
6537
|
static schema() {
|
|
@@ -6981,13 +6757,13 @@ class MultipleLabeledControls extends Rule {
|
|
|
6981
6757
|
}
|
|
6982
6758
|
}
|
|
6983
6759
|
|
|
6984
|
-
const defaults$
|
|
6760
|
+
const defaults$f = {
|
|
6985
6761
|
include: null,
|
|
6986
6762
|
exclude: null,
|
|
6987
6763
|
};
|
|
6988
6764
|
class NoAutoplay extends Rule {
|
|
6989
6765
|
constructor(options) {
|
|
6990
|
-
super({ ...defaults$
|
|
6766
|
+
super({ ...defaults$f, ...options });
|
|
6991
6767
|
}
|
|
6992
6768
|
documentation(context) {
|
|
6993
6769
|
const tagName = context ? ` on <${context.tagName}>` : "";
|
|
@@ -7228,14 +7004,14 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
7228
7004
|
}
|
|
7229
7005
|
}
|
|
7230
7006
|
|
|
7231
|
-
const defaults$
|
|
7007
|
+
const defaults$e = {
|
|
7232
7008
|
include: null,
|
|
7233
7009
|
exclude: null,
|
|
7234
7010
|
allowedProperties: ["display"],
|
|
7235
7011
|
};
|
|
7236
7012
|
class NoInlineStyle extends Rule {
|
|
7237
7013
|
constructor(options) {
|
|
7238
|
-
super({ ...defaults$
|
|
7014
|
+
super({ ...defaults$e, ...options });
|
|
7239
7015
|
}
|
|
7240
7016
|
static schema() {
|
|
7241
7017
|
return {
|
|
@@ -7437,7 +7213,7 @@ class NoMultipleMain extends Rule {
|
|
|
7437
7213
|
}
|
|
7438
7214
|
}
|
|
7439
7215
|
|
|
7440
|
-
const defaults$
|
|
7216
|
+
const defaults$d = {
|
|
7441
7217
|
relaxed: false,
|
|
7442
7218
|
};
|
|
7443
7219
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -7454,7 +7230,7 @@ const replacementTable = {
|
|
|
7454
7230
|
};
|
|
7455
7231
|
class NoRawCharacters extends Rule {
|
|
7456
7232
|
constructor(options) {
|
|
7457
|
-
super({ ...defaults$
|
|
7233
|
+
super({ ...defaults$d, ...options });
|
|
7458
7234
|
this.relaxed = this.options.relaxed;
|
|
7459
7235
|
}
|
|
7460
7236
|
static schema() {
|
|
@@ -7632,13 +7408,13 @@ class NoRedundantRole extends Rule {
|
|
|
7632
7408
|
}
|
|
7633
7409
|
|
|
7634
7410
|
const xmlns = /^(.+):.+$/;
|
|
7635
|
-
const defaults$
|
|
7411
|
+
const defaults$c = {
|
|
7636
7412
|
ignoreForeign: true,
|
|
7637
7413
|
ignoreXML: true,
|
|
7638
7414
|
};
|
|
7639
7415
|
class NoSelfClosing extends Rule {
|
|
7640
7416
|
constructor(options) {
|
|
7641
|
-
super({ ...defaults$
|
|
7417
|
+
super({ ...defaults$c, ...options });
|
|
7642
7418
|
}
|
|
7643
7419
|
static schema() {
|
|
7644
7420
|
return {
|
|
@@ -7727,13 +7503,13 @@ class NoTrailingWhitespace extends Rule {
|
|
|
7727
7503
|
}
|
|
7728
7504
|
}
|
|
7729
7505
|
|
|
7730
|
-
const defaults$
|
|
7506
|
+
const defaults$b = {
|
|
7731
7507
|
include: null,
|
|
7732
7508
|
exclude: null,
|
|
7733
7509
|
};
|
|
7734
7510
|
class NoUnknownElements extends Rule {
|
|
7735
7511
|
constructor(options) {
|
|
7736
|
-
super({ ...defaults$
|
|
7512
|
+
super({ ...defaults$b, ...options });
|
|
7737
7513
|
}
|
|
7738
7514
|
static schema() {
|
|
7739
7515
|
return {
|
|
@@ -7845,13 +7621,13 @@ const replacement = {
|
|
|
7845
7621
|
reset: '<button type="reset">',
|
|
7846
7622
|
image: '<button type="button">',
|
|
7847
7623
|
};
|
|
7848
|
-
const defaults$
|
|
7624
|
+
const defaults$a = {
|
|
7849
7625
|
include: null,
|
|
7850
7626
|
exclude: null,
|
|
7851
7627
|
};
|
|
7852
7628
|
class PreferButton extends Rule {
|
|
7853
7629
|
constructor(options) {
|
|
7854
|
-
super({ ...defaults$
|
|
7630
|
+
super({ ...defaults$a, ...options });
|
|
7855
7631
|
}
|
|
7856
7632
|
static schema() {
|
|
7857
7633
|
return {
|
|
@@ -7926,7 +7702,7 @@ class PreferButton extends Rule {
|
|
|
7926
7702
|
}
|
|
7927
7703
|
}
|
|
7928
7704
|
|
|
7929
|
-
const defaults$
|
|
7705
|
+
const defaults$9 = {
|
|
7930
7706
|
mapping: {
|
|
7931
7707
|
article: "article",
|
|
7932
7708
|
banner: "header",
|
|
@@ -7956,7 +7732,7 @@ const defaults$a = {
|
|
|
7956
7732
|
};
|
|
7957
7733
|
class PreferNativeElement extends Rule {
|
|
7958
7734
|
constructor(options) {
|
|
7959
|
-
super({ ...defaults$
|
|
7735
|
+
super({ ...defaults$9, ...options });
|
|
7960
7736
|
}
|
|
7961
7737
|
static schema() {
|
|
7962
7738
|
return {
|
|
@@ -8076,12 +7852,12 @@ class PreferTbody extends Rule {
|
|
|
8076
7852
|
}
|
|
8077
7853
|
}
|
|
8078
7854
|
|
|
8079
|
-
const defaults$
|
|
7855
|
+
const defaults$8 = {
|
|
8080
7856
|
tags: ["script", "style"],
|
|
8081
7857
|
};
|
|
8082
7858
|
class RequireCSPNonce extends Rule {
|
|
8083
7859
|
constructor(options) {
|
|
8084
|
-
super({ ...defaults$
|
|
7860
|
+
super({ ...defaults$8, ...options });
|
|
8085
7861
|
}
|
|
8086
7862
|
static schema() {
|
|
8087
7863
|
return {
|
|
@@ -8132,7 +7908,7 @@ class RequireCSPNonce extends Rule {
|
|
|
8132
7908
|
}
|
|
8133
7909
|
}
|
|
8134
7910
|
|
|
8135
|
-
const defaults$
|
|
7911
|
+
const defaults$7 = {
|
|
8136
7912
|
target: "all",
|
|
8137
7913
|
include: null,
|
|
8138
7914
|
exclude: null,
|
|
@@ -8144,7 +7920,7 @@ const supportSri = {
|
|
|
8144
7920
|
};
|
|
8145
7921
|
class RequireSri extends Rule {
|
|
8146
7922
|
constructor(options) {
|
|
8147
|
-
super({ ...defaults$
|
|
7923
|
+
super({ ...defaults$7, ...options });
|
|
8148
7924
|
this.target = this.options.target;
|
|
8149
7925
|
}
|
|
8150
7926
|
static schema() {
|
|
@@ -8306,7 +8082,7 @@ class SvgFocusable extends Rule {
|
|
|
8306
8082
|
}
|
|
8307
8083
|
}
|
|
8308
8084
|
|
|
8309
|
-
const defaults$
|
|
8085
|
+
const defaults$6 = {
|
|
8310
8086
|
characters: [
|
|
8311
8087
|
{ pattern: " ", replacement: " ", description: "non-breaking space" },
|
|
8312
8088
|
{ pattern: "-", replacement: "‑", description: "non-breaking hyphen" },
|
|
@@ -8345,7 +8121,7 @@ function matchAll(text, regexp) {
|
|
|
8345
8121
|
}
|
|
8346
8122
|
class TelNonBreaking extends Rule {
|
|
8347
8123
|
constructor(options) {
|
|
8348
|
-
super({ ...defaults$
|
|
8124
|
+
super({ ...defaults$6, ...options });
|
|
8349
8125
|
this.regex = constructRegex(this.options.characters);
|
|
8350
8126
|
}
|
|
8351
8127
|
static schema() {
|
|
@@ -8633,7 +8409,7 @@ class TextContent extends Rule {
|
|
|
8633
8409
|
}
|
|
8634
8410
|
}
|
|
8635
8411
|
|
|
8636
|
-
const defaults$
|
|
8412
|
+
const defaults$5 = {
|
|
8637
8413
|
ignoreCase: false,
|
|
8638
8414
|
requireSemicolon: true,
|
|
8639
8415
|
};
|
|
@@ -8675,7 +8451,7 @@ function getDescription(context, options) {
|
|
|
8675
8451
|
}
|
|
8676
8452
|
class UnknownCharReference extends Rule {
|
|
8677
8453
|
constructor(options) {
|
|
8678
|
-
super({ ...defaults$
|
|
8454
|
+
super({ ...defaults$5, ...options });
|
|
8679
8455
|
}
|
|
8680
8456
|
static schema() {
|
|
8681
8457
|
return {
|
|
@@ -8792,12 +8568,12 @@ var RuleContext;
|
|
|
8792
8568
|
RuleContext[RuleContext["LEADING_CHARACTER"] = 3] = "LEADING_CHARACTER";
|
|
8793
8569
|
RuleContext[RuleContext["DISALLOWED_CHARACTER"] = 4] = "DISALLOWED_CHARACTER";
|
|
8794
8570
|
})(RuleContext || (RuleContext = {}));
|
|
8795
|
-
const defaults$
|
|
8571
|
+
const defaults$4 = {
|
|
8796
8572
|
relaxed: false,
|
|
8797
8573
|
};
|
|
8798
8574
|
class ValidID extends Rule {
|
|
8799
8575
|
constructor(options) {
|
|
8800
|
-
super({ ...defaults$
|
|
8576
|
+
super({ ...defaults$4, ...options });
|
|
8801
8577
|
}
|
|
8802
8578
|
static schema() {
|
|
8803
8579
|
return {
|
|
@@ -8874,119 +8650,39 @@ class ValidID extends Rule {
|
|
|
8874
8650
|
}
|
|
8875
8651
|
}
|
|
8876
8652
|
|
|
8877
|
-
|
|
8653
|
+
class VoidContent extends Rule {
|
|
8654
|
+
documentation(tagName) {
|
|
8655
|
+
const doc = {
|
|
8656
|
+
description: "HTML void elements cannot have any content and must not have content or end tag.",
|
|
8657
|
+
url: "https://html-validate.org/rules/void-content.html",
|
|
8658
|
+
};
|
|
8659
|
+
if (tagName) {
|
|
8660
|
+
doc.description = `<${tagName}> is a void element and must not have content or end tag.`;
|
|
8661
|
+
}
|
|
8662
|
+
return doc;
|
|
8663
|
+
}
|
|
8664
|
+
setup() {
|
|
8665
|
+
this.on("tag:end", (event) => {
|
|
8666
|
+
const node = event.target; // The current element being closed.
|
|
8667
|
+
if (!node) {
|
|
8668
|
+
return;
|
|
8669
|
+
}
|
|
8670
|
+
if (!node.voidElement) {
|
|
8671
|
+
return;
|
|
8672
|
+
}
|
|
8673
|
+
if (node.closed === NodeClosed.EndTag) {
|
|
8674
|
+
this.report(null, `End tag for <${node.tagName}> must be omitted`, node.location, node.tagName);
|
|
8675
|
+
}
|
|
8676
|
+
});
|
|
8677
|
+
}
|
|
8678
|
+
}
|
|
8679
|
+
|
|
8680
|
+
var Style;
|
|
8878
8681
|
(function (Style) {
|
|
8879
|
-
Style[Style["Any"] = 0] = "Any";
|
|
8880
8682
|
Style[Style["AlwaysOmit"] = 1] = "AlwaysOmit";
|
|
8881
8683
|
Style[Style["AlwaysSelfclose"] = 2] = "AlwaysSelfclose";
|
|
8882
|
-
})(Style
|
|
8883
|
-
const defaults$
|
|
8884
|
-
style: "omit",
|
|
8885
|
-
};
|
|
8886
|
-
class Void extends Rule {
|
|
8887
|
-
get deprecated() {
|
|
8888
|
-
return true;
|
|
8889
|
-
}
|
|
8890
|
-
static schema() {
|
|
8891
|
-
return {
|
|
8892
|
-
style: {
|
|
8893
|
-
enum: ["any", "omit", "selfclose", "selfclosing"],
|
|
8894
|
-
type: "string",
|
|
8895
|
-
},
|
|
8896
|
-
};
|
|
8897
|
-
}
|
|
8898
|
-
documentation() {
|
|
8899
|
-
return {
|
|
8900
|
-
description: "HTML void elements cannot have any content and must not have an end tag.",
|
|
8901
|
-
url: "https://html-validate.org/rules/void.html",
|
|
8902
|
-
};
|
|
8903
|
-
}
|
|
8904
|
-
constructor(options) {
|
|
8905
|
-
super({ ...defaults$4, ...options });
|
|
8906
|
-
this.style = parseStyle$1(this.options.style);
|
|
8907
|
-
}
|
|
8908
|
-
setup() {
|
|
8909
|
-
this.on("tag:end", (event) => {
|
|
8910
|
-
const current = event.target; // The current element being closed
|
|
8911
|
-
const active = event.previous; // The current active element (that is, the current element on the stack)
|
|
8912
|
-
if (current && current.meta) {
|
|
8913
|
-
this.validateCurrent(current);
|
|
8914
|
-
}
|
|
8915
|
-
if (active && active.meta) {
|
|
8916
|
-
this.validateActive(active, active.meta);
|
|
8917
|
-
}
|
|
8918
|
-
});
|
|
8919
|
-
}
|
|
8920
|
-
validateCurrent(node) {
|
|
8921
|
-
if (node.voidElement && node.closed === NodeClosed.EndTag) {
|
|
8922
|
-
this.report(null, `End tag for <${node.tagName}> must be omitted`, node.location);
|
|
8923
|
-
}
|
|
8924
|
-
}
|
|
8925
|
-
validateActive(node, meta) {
|
|
8926
|
-
/* ignore foreign elements, they may or may not be self-closed and both are
|
|
8927
|
-
* valid */
|
|
8928
|
-
if (meta.foreign) {
|
|
8929
|
-
return;
|
|
8930
|
-
}
|
|
8931
|
-
const selfOrOmitted = node.closed === NodeClosed.VoidOmitted || node.closed === NodeClosed.VoidSelfClosed;
|
|
8932
|
-
if (node.voidElement) {
|
|
8933
|
-
if (this.style === Style$1.AlwaysOmit && node.closed === NodeClosed.VoidSelfClosed) {
|
|
8934
|
-
this.report(node, `Expected omitted end tag <${node.tagName}> instead of self-closing element <${node.tagName}/>`);
|
|
8935
|
-
}
|
|
8936
|
-
if (this.style === Style$1.AlwaysSelfclose && node.closed === NodeClosed.VoidOmitted) {
|
|
8937
|
-
this.report(node, `Expected self-closing element <${node.tagName}/> instead of omitted end-tag <${node.tagName}>`);
|
|
8938
|
-
}
|
|
8939
|
-
}
|
|
8940
|
-
if (selfOrOmitted && node.voidElement === false) {
|
|
8941
|
-
this.report(node, `End tag for <${node.tagName}> must not be omitted`);
|
|
8942
|
-
}
|
|
8943
|
-
}
|
|
8944
|
-
}
|
|
8945
|
-
function parseStyle$1(name) {
|
|
8946
|
-
switch (name) {
|
|
8947
|
-
case "any":
|
|
8948
|
-
return Style$1.Any;
|
|
8949
|
-
case "omit":
|
|
8950
|
-
return Style$1.AlwaysOmit;
|
|
8951
|
-
case "selfclose":
|
|
8952
|
-
case "selfclosing":
|
|
8953
|
-
return Style$1.AlwaysSelfclose;
|
|
8954
|
-
}
|
|
8955
|
-
}
|
|
8956
|
-
|
|
8957
|
-
class VoidContent extends Rule {
|
|
8958
|
-
documentation(tagName) {
|
|
8959
|
-
const doc = {
|
|
8960
|
-
description: "HTML void elements cannot have any content and must not have content or end tag.",
|
|
8961
|
-
url: "https://html-validate.org/rules/void-content.html",
|
|
8962
|
-
};
|
|
8963
|
-
if (tagName) {
|
|
8964
|
-
doc.description = `<${tagName}> is a void element and must not have content or end tag.`;
|
|
8965
|
-
}
|
|
8966
|
-
return doc;
|
|
8967
|
-
}
|
|
8968
|
-
setup() {
|
|
8969
|
-
this.on("tag:end", (event) => {
|
|
8970
|
-
const node = event.target; // The current element being closed.
|
|
8971
|
-
if (!node) {
|
|
8972
|
-
return;
|
|
8973
|
-
}
|
|
8974
|
-
if (!node.voidElement) {
|
|
8975
|
-
return;
|
|
8976
|
-
}
|
|
8977
|
-
if (node.closed === NodeClosed.EndTag) {
|
|
8978
|
-
this.report(null, `End tag for <${node.tagName}> must be omitted`, node.location, node.tagName);
|
|
8979
|
-
}
|
|
8980
|
-
});
|
|
8981
|
-
}
|
|
8982
|
-
}
|
|
8983
|
-
|
|
8984
|
-
var Style;
|
|
8985
|
-
(function (Style) {
|
|
8986
|
-
Style[Style["AlwaysOmit"] = 1] = "AlwaysOmit";
|
|
8987
|
-
Style[Style["AlwaysSelfclose"] = 2] = "AlwaysSelfclose";
|
|
8988
|
-
})(Style || (Style = {}));
|
|
8989
|
-
const defaults$3 = {
|
|
8684
|
+
})(Style || (Style = {}));
|
|
8685
|
+
const defaults$3 = {
|
|
8990
8686
|
style: "omit",
|
|
8991
8687
|
};
|
|
8992
8688
|
class VoidStyle extends Rule {
|
|
@@ -9455,7 +9151,6 @@ const bundledRules = {
|
|
|
9455
9151
|
"text-content": TextContent,
|
|
9456
9152
|
"unrecognized-char-ref": UnknownCharReference,
|
|
9457
9153
|
"valid-id": ValidID,
|
|
9458
|
-
void: Void,
|
|
9459
9154
|
"void-content": VoidContent,
|
|
9460
9155
|
"void-style": VoidStyle,
|
|
9461
9156
|
...WCAG,
|
|
@@ -9748,7 +9443,112 @@ class ResolvedConfig {
|
|
|
9748
9443
|
}
|
|
9749
9444
|
}
|
|
9750
9445
|
|
|
9751
|
-
|
|
9446
|
+
function haveResolver(key, value) {
|
|
9447
|
+
return key in value;
|
|
9448
|
+
}
|
|
9449
|
+
function haveConfigResolver(value) {
|
|
9450
|
+
return haveResolver("resolveConfig", value);
|
|
9451
|
+
}
|
|
9452
|
+
function haveElementsResolver(value) {
|
|
9453
|
+
return haveResolver("resolveElements", value);
|
|
9454
|
+
}
|
|
9455
|
+
function havePluginResolver(value) {
|
|
9456
|
+
return haveResolver("resolvePlugin", value);
|
|
9457
|
+
}
|
|
9458
|
+
function haveTransformerResolver(value) {
|
|
9459
|
+
return haveResolver("resolveTransformer", value);
|
|
9460
|
+
}
|
|
9461
|
+
/**
|
|
9462
|
+
* @internal
|
|
9463
|
+
*/
|
|
9464
|
+
function resolveConfig(resolvers, id, options) {
|
|
9465
|
+
for (const resolver of resolvers.filter(haveConfigResolver)) {
|
|
9466
|
+
const config = resolver.resolveConfig(id, options);
|
|
9467
|
+
if (config) {
|
|
9468
|
+
return config;
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
throw new UserError(`Failed to load configuration from "${id}"`);
|
|
9472
|
+
}
|
|
9473
|
+
/**
|
|
9474
|
+
* @internal
|
|
9475
|
+
*/
|
|
9476
|
+
function resolveElements(resolvers, id, options) {
|
|
9477
|
+
for (const resolver of resolvers.filter(haveElementsResolver)) {
|
|
9478
|
+
const elements = resolver.resolveElements(id, options);
|
|
9479
|
+
if (elements) {
|
|
9480
|
+
return elements;
|
|
9481
|
+
}
|
|
9482
|
+
}
|
|
9483
|
+
throw new UserError(`Failed to load elements from "${id}"`);
|
|
9484
|
+
}
|
|
9485
|
+
/**
|
|
9486
|
+
* @internal
|
|
9487
|
+
*/
|
|
9488
|
+
function resolvePlugin(resolvers, id, options) {
|
|
9489
|
+
for (const resolver of resolvers.filter(havePluginResolver)) {
|
|
9490
|
+
const plugin = resolver.resolvePlugin(id, options);
|
|
9491
|
+
if (plugin) {
|
|
9492
|
+
return plugin;
|
|
9493
|
+
}
|
|
9494
|
+
}
|
|
9495
|
+
throw new UserError(`Failed to load plugin from "${id}"`);
|
|
9496
|
+
}
|
|
9497
|
+
/**
|
|
9498
|
+
* @internal
|
|
9499
|
+
*/
|
|
9500
|
+
function resolveTransformer(resolvers, id, options) {
|
|
9501
|
+
for (const resolver of resolvers.filter(haveTransformerResolver)) {
|
|
9502
|
+
const transformer = resolver.resolveTransformer(id, options);
|
|
9503
|
+
if (transformer) {
|
|
9504
|
+
return transformer;
|
|
9505
|
+
}
|
|
9506
|
+
}
|
|
9507
|
+
throw new UserError(`Failed to load transformer from "${id}"`);
|
|
9508
|
+
}
|
|
9509
|
+
|
|
9510
|
+
/**
|
|
9511
|
+
* Create a new resolver for static content, i.e. plugins or transformers known
|
|
9512
|
+
* at compile time.
|
|
9513
|
+
*
|
|
9514
|
+
* @public
|
|
9515
|
+
* @since 8.0.0
|
|
9516
|
+
*/
|
|
9517
|
+
function staticResolver(map = {}) {
|
|
9518
|
+
const { elements = {}, configs = {}, plugins = {}, transformers = {} } = map;
|
|
9519
|
+
return {
|
|
9520
|
+
name: "static-qresolver",
|
|
9521
|
+
addElements(id, value) {
|
|
9522
|
+
elements[id] = value;
|
|
9523
|
+
},
|
|
9524
|
+
addConfig(id, value) {
|
|
9525
|
+
configs[id] = value;
|
|
9526
|
+
},
|
|
9527
|
+
addPlugin(id, value) {
|
|
9528
|
+
plugins[id] = value;
|
|
9529
|
+
},
|
|
9530
|
+
addTransformer(id, value) {
|
|
9531
|
+
transformers[id] = value;
|
|
9532
|
+
},
|
|
9533
|
+
resolveElements(id) {
|
|
9534
|
+
var _a;
|
|
9535
|
+
return (_a = elements[id]) !== null && _a !== void 0 ? _a : null;
|
|
9536
|
+
},
|
|
9537
|
+
resolveConfig(id) {
|
|
9538
|
+
var _a;
|
|
9539
|
+
return (_a = configs[id]) !== null && _a !== void 0 ? _a : null;
|
|
9540
|
+
},
|
|
9541
|
+
resolvePlugin(id) {
|
|
9542
|
+
var _a;
|
|
9543
|
+
return (_a = plugins[id]) !== null && _a !== void 0 ? _a : null;
|
|
9544
|
+
},
|
|
9545
|
+
resolveTransformer(id) {
|
|
9546
|
+
var _a;
|
|
9547
|
+
return (_a = transformers[id]) !== null && _a !== void 0 ? _a : null;
|
|
9548
|
+
},
|
|
9549
|
+
};
|
|
9550
|
+
}
|
|
9551
|
+
|
|
9752
9552
|
const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
|
|
9753
9553
|
ajv.addMetaSchema(ajvSchemaDraft);
|
|
9754
9554
|
const validator = ajv.compile(configurationSchema);
|
|
@@ -9771,30 +9571,13 @@ function mergeInternal(base, rhs) {
|
|
|
9771
9571
|
}
|
|
9772
9572
|
return dst;
|
|
9773
9573
|
}
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
/* load using require as it can process both js and json */
|
|
9781
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- technical debt, should be refactored into something more typesafe */
|
|
9782
|
-
json = requireUncached(legacyRequire, filename);
|
|
9783
|
-
}
|
|
9784
|
-
catch (err) {
|
|
9785
|
-
throw new ConfigError(`Failed to read configuration from "${filename}"`, ensureError(err));
|
|
9786
|
-
}
|
|
9787
|
-
/* expand any relative paths */
|
|
9788
|
-
for (const key of ["extends", "elements", "plugins"]) {
|
|
9789
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- technical debt, should be refactored into something more typesafe */
|
|
9790
|
-
const value = json[key];
|
|
9791
|
-
if (!value)
|
|
9792
|
-
continue;
|
|
9793
|
-
json[key] = value.map((ref) => {
|
|
9794
|
-
return Config.expandRelative(ref, path.dirname(filename));
|
|
9795
|
-
});
|
|
9574
|
+
function toArray(value) {
|
|
9575
|
+
if (Array.isArray(value)) {
|
|
9576
|
+
return value;
|
|
9577
|
+
}
|
|
9578
|
+
else {
|
|
9579
|
+
return [value];
|
|
9796
9580
|
}
|
|
9797
|
-
return json;
|
|
9798
9581
|
}
|
|
9799
9582
|
/**
|
|
9800
9583
|
* Configuration holder.
|
|
@@ -9808,7 +9591,7 @@ class Config {
|
|
|
9808
9591
|
* Create a new blank configuration. See also `Config.defaultConfig()`.
|
|
9809
9592
|
*/
|
|
9810
9593
|
static empty() {
|
|
9811
|
-
return new Config({
|
|
9594
|
+
return new Config([], {
|
|
9812
9595
|
extends: [],
|
|
9813
9596
|
rules: {},
|
|
9814
9597
|
plugins: [],
|
|
@@ -9818,9 +9601,9 @@ class Config {
|
|
|
9818
9601
|
/**
|
|
9819
9602
|
* Create configuration from object.
|
|
9820
9603
|
*/
|
|
9821
|
-
static fromObject(options, filename = null) {
|
|
9604
|
+
static fromObject(resolvers, options, filename = null) {
|
|
9822
9605
|
Config.validate(options, filename);
|
|
9823
|
-
return new Config(options);
|
|
9606
|
+
return new Config(resolvers, options);
|
|
9824
9607
|
}
|
|
9825
9608
|
/**
|
|
9826
9609
|
* Read configuration from filename.
|
|
@@ -9831,9 +9614,9 @@ class Config {
|
|
|
9831
9614
|
* @internal
|
|
9832
9615
|
* @param filename - The file to read from
|
|
9833
9616
|
*/
|
|
9834
|
-
static fromFile(filename) {
|
|
9835
|
-
const
|
|
9836
|
-
return Config.fromObject(
|
|
9617
|
+
static fromFile(resolvers, filename) {
|
|
9618
|
+
const configData = resolveConfig(toArray(resolvers), filename, { cache: false });
|
|
9619
|
+
return Config.fromObject(resolvers, configData, filename);
|
|
9837
9620
|
}
|
|
9838
9621
|
/**
|
|
9839
9622
|
* Validate configuration data.
|
|
@@ -9863,12 +9646,12 @@ class Config {
|
|
|
9863
9646
|
* Load a default configuration object.
|
|
9864
9647
|
*/
|
|
9865
9648
|
static defaultConfig() {
|
|
9866
|
-
return new Config(defaultConfig);
|
|
9649
|
+
return new Config([], defaultConfig);
|
|
9867
9650
|
}
|
|
9868
9651
|
/**
|
|
9869
9652
|
* @internal
|
|
9870
9653
|
*/
|
|
9871
|
-
constructor(options) {
|
|
9654
|
+
constructor(resolvers, options) {
|
|
9872
9655
|
var _a;
|
|
9873
9656
|
this.transformers = [];
|
|
9874
9657
|
const initial = {
|
|
@@ -9877,10 +9660,10 @@ class Config {
|
|
|
9877
9660
|
rules: {},
|
|
9878
9661
|
transform: {},
|
|
9879
9662
|
};
|
|
9880
|
-
this.config = mergeInternal(initial, options
|
|
9663
|
+
this.config = mergeInternal(initial, options);
|
|
9881
9664
|
this.metaTable = null;
|
|
9882
|
-
this.rootDir = this.findRootDir();
|
|
9883
9665
|
this.initialized = false;
|
|
9666
|
+
this.resolvers = toArray(resolvers);
|
|
9884
9667
|
/* load plugins */
|
|
9885
9668
|
this.plugins = this.loadPlugins(this.config.plugins || []);
|
|
9886
9669
|
this.configurations = this.loadConfigurations(this.plugins);
|
|
@@ -9926,8 +9709,8 @@ class Config {
|
|
|
9926
9709
|
* @public
|
|
9927
9710
|
* @param rhs - Configuration to merge with this one.
|
|
9928
9711
|
*/
|
|
9929
|
-
merge(rhs) {
|
|
9930
|
-
return new Config(mergeInternal(this.config, rhs.config));
|
|
9712
|
+
merge(resolvers, rhs) {
|
|
9713
|
+
return new Config(resolvers, mergeInternal(this.config, rhs.config));
|
|
9931
9714
|
}
|
|
9932
9715
|
extendConfig(entries) {
|
|
9933
9716
|
if (entries.length === 0) {
|
|
@@ -9941,7 +9724,7 @@ class Config {
|
|
|
9941
9724
|
extended = this.configurations.get(entry);
|
|
9942
9725
|
}
|
|
9943
9726
|
else {
|
|
9944
|
-
extended = Config.fromFile(entry).config;
|
|
9727
|
+
extended = Config.fromFile(this.resolvers, entry).config;
|
|
9945
9728
|
}
|
|
9946
9729
|
base = mergeInternal(base, extended);
|
|
9947
9730
|
}
|
|
@@ -9978,30 +9761,20 @@ class Config {
|
|
|
9978
9761
|
metaTable.loadFromObject(bundled);
|
|
9979
9762
|
continue;
|
|
9980
9763
|
}
|
|
9981
|
-
/*
|
|
9982
|
-
const id = entry.replace("<rootDir>", this.rootDir);
|
|
9764
|
+
/* load with resolver */
|
|
9983
9765
|
try {
|
|
9984
|
-
const data =
|
|
9985
|
-
metaTable.loadFromObject(data,
|
|
9766
|
+
const data = resolveElements(this.resolvers, entry, { cache: false });
|
|
9767
|
+
metaTable.loadFromObject(data, entry);
|
|
9986
9768
|
}
|
|
9987
9769
|
catch (err) {
|
|
9988
9770
|
/* istanbul ignore next: only used as a fallback */
|
|
9989
9771
|
const message = err instanceof Error ? err.message : String(err);
|
|
9990
|
-
throw new ConfigError(`Failed to load elements from "${
|
|
9772
|
+
throw new ConfigError(`Failed to load elements from "${entry}": ${message}`, ensureError(err));
|
|
9991
9773
|
}
|
|
9992
9774
|
}
|
|
9993
9775
|
metaTable.init();
|
|
9994
9776
|
return (this.metaTable = metaTable);
|
|
9995
9777
|
}
|
|
9996
|
-
/**
|
|
9997
|
-
* @internal exposed for testing only
|
|
9998
|
-
*/
|
|
9999
|
-
static expandRelative(src, currentPath) {
|
|
10000
|
-
if (src[0] === ".") {
|
|
10001
|
-
return path.normalize(`${currentPath}/${src}`);
|
|
10002
|
-
}
|
|
10003
|
-
return src;
|
|
10004
|
-
}
|
|
10005
9778
|
/**
|
|
10006
9779
|
* Get a copy of internal configuration data.
|
|
10007
9780
|
*
|
|
@@ -10053,7 +9826,7 @@ class Config {
|
|
|
10053
9826
|
return plugin;
|
|
10054
9827
|
}
|
|
10055
9828
|
try {
|
|
10056
|
-
const plugin =
|
|
9829
|
+
const plugin = resolvePlugin(this.resolvers, moduleName, { cache: true });
|
|
10057
9830
|
plugin.name = plugin.name || moduleName;
|
|
10058
9831
|
plugin.originalName = moduleName;
|
|
10059
9832
|
return plugin;
|
|
@@ -10226,57 +9999,7 @@ class Config {
|
|
|
10226
9999
|
return plugin.transformer;
|
|
10227
10000
|
}
|
|
10228
10001
|
getTransformerFromModule(name) {
|
|
10229
|
-
|
|
10230
|
-
const moduleName = name.replace("<rootDir>", this.rootDir);
|
|
10231
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- technical debt, the code kinda does the right thing but it should be reflected in the typing too */
|
|
10232
|
-
const fn = legacyRequire(moduleName);
|
|
10233
|
-
/* sanity check */
|
|
10234
|
-
if (typeof fn !== "function") {
|
|
10235
|
-
/* this is not a proper transformer, is it a plugin exposing a transformer? */
|
|
10236
|
-
if (fn.transformer) {
|
|
10237
|
-
throw new ConfigError(`Module is not a valid transformer. This looks like a plugin, did you forget to load the plugin first?`);
|
|
10238
|
-
}
|
|
10239
|
-
throw new ConfigError(`Module is not a valid transformer.`);
|
|
10240
|
-
}
|
|
10241
|
-
return fn;
|
|
10242
|
-
}
|
|
10243
|
-
/**
|
|
10244
|
-
* @internal
|
|
10245
|
-
*/
|
|
10246
|
-
get rootDirCache() {
|
|
10247
|
-
/* return global instance */
|
|
10248
|
-
return rootDirCache;
|
|
10249
|
-
}
|
|
10250
|
-
set rootDirCache(value) {
|
|
10251
|
-
/* set global instance */
|
|
10252
|
-
rootDirCache = value;
|
|
10253
|
-
}
|
|
10254
|
-
/**
|
|
10255
|
-
* @internal
|
|
10256
|
-
*/
|
|
10257
|
-
findRootDir() {
|
|
10258
|
-
const cache = this.rootDirCache;
|
|
10259
|
-
if (cache !== null) {
|
|
10260
|
-
return cache;
|
|
10261
|
-
}
|
|
10262
|
-
/* try to locate package.json */
|
|
10263
|
-
let current = process.cwd();
|
|
10264
|
-
// eslint-disable-next-line no-constant-condition -- break outs when filesystem is traversed
|
|
10265
|
-
while (true) {
|
|
10266
|
-
const search = path.join(current, "package.json");
|
|
10267
|
-
if (fs.existsSync(search)) {
|
|
10268
|
-
return (this.rootDirCache = current);
|
|
10269
|
-
}
|
|
10270
|
-
/* get the parent directory */
|
|
10271
|
-
const child = current;
|
|
10272
|
-
current = path.dirname(current);
|
|
10273
|
-
/* stop if this is the root directory */
|
|
10274
|
-
if (current === child) {
|
|
10275
|
-
break;
|
|
10276
|
-
}
|
|
10277
|
-
}
|
|
10278
|
-
/* default to working directory if no package.json is found */
|
|
10279
|
-
return (this.rootDirCache = process.cwd());
|
|
10002
|
+
return resolveTransformer(this.resolvers, name, { cache: true });
|
|
10280
10003
|
}
|
|
10281
10004
|
}
|
|
10282
10005
|
|
|
@@ -10289,19 +10012,25 @@ class Config {
|
|
|
10289
10012
|
* @public
|
|
10290
10013
|
*/
|
|
10291
10014
|
class ConfigLoader {
|
|
10292
|
-
constructor(
|
|
10293
|
-
const defaults =
|
|
10294
|
-
this.
|
|
10295
|
-
this.globalConfig = defaults.merge(config ? this.loadFromObject(config) : this.defaultConfig());
|
|
10015
|
+
constructor(resolvers, config) {
|
|
10016
|
+
const defaults = Config.empty();
|
|
10017
|
+
this.resolvers = resolvers;
|
|
10018
|
+
this.globalConfig = defaults.merge(this.resolvers, config ? this.loadFromObject(config) : this.defaultConfig());
|
|
10019
|
+
}
|
|
10020
|
+
/**
|
|
10021
|
+
* @internal For testing only
|
|
10022
|
+
*/
|
|
10023
|
+
_getGlobalConfig() {
|
|
10024
|
+
return this.globalConfig.get();
|
|
10296
10025
|
}
|
|
10297
10026
|
empty() {
|
|
10298
|
-
return
|
|
10027
|
+
return Config.empty();
|
|
10299
10028
|
}
|
|
10300
10029
|
loadFromObject(options, filename) {
|
|
10301
|
-
return
|
|
10030
|
+
return Config.fromObject(this.resolvers, options, filename);
|
|
10302
10031
|
}
|
|
10303
10032
|
loadFromFile(filename) {
|
|
10304
|
-
return
|
|
10033
|
+
return Config.fromFile(this.resolvers, filename);
|
|
10305
10034
|
}
|
|
10306
10035
|
}
|
|
10307
10036
|
|
|
@@ -11289,7 +11018,7 @@ class Engine {
|
|
|
11289
11018
|
/**
|
|
11290
11019
|
* Get rule documentation.
|
|
11291
11020
|
*/
|
|
11292
|
-
getRuleDocumentation(ruleId, context) {
|
|
11021
|
+
getRuleDocumentation({ ruleId, context, }) {
|
|
11293
11022
|
const rules = this.config.getRules();
|
|
11294
11023
|
const ruleData = rules.get(ruleId);
|
|
11295
11024
|
if (ruleData) {
|
|
@@ -11526,6 +11255,10 @@ class Engine {
|
|
|
11526
11255
|
}
|
|
11527
11256
|
}
|
|
11528
11257
|
|
|
11258
|
+
const defaultResolvers$1 = [];
|
|
11259
|
+
function hasResolver$1(value) {
|
|
11260
|
+
return Array.isArray(value[0]);
|
|
11261
|
+
}
|
|
11529
11262
|
/**
|
|
11530
11263
|
* The static configuration loader does not do any per-handle lookup. Only the
|
|
11531
11264
|
* global or per-call configuration is used.
|
|
@@ -11536,13 +11269,23 @@ class Engine {
|
|
|
11536
11269
|
* @public
|
|
11537
11270
|
*/
|
|
11538
11271
|
class StaticConfigLoader extends ConfigLoader {
|
|
11272
|
+
constructor(...args) {
|
|
11273
|
+
if (hasResolver$1(args)) {
|
|
11274
|
+
const [resolvers, config] = args;
|
|
11275
|
+
super(resolvers, config);
|
|
11276
|
+
}
|
|
11277
|
+
else {
|
|
11278
|
+
const [config] = args;
|
|
11279
|
+
super(defaultResolvers$1, config);
|
|
11280
|
+
}
|
|
11281
|
+
}
|
|
11539
11282
|
getConfigFor(_handle, configOverride) {
|
|
11540
11283
|
const override = this.loadFromObject(configOverride || {});
|
|
11541
11284
|
if (override.isRootFound()) {
|
|
11542
11285
|
override.init();
|
|
11543
11286
|
return override.resolve();
|
|
11544
11287
|
}
|
|
11545
|
-
const merged = this.globalConfig.merge(override);
|
|
11288
|
+
const merged = this.globalConfig.merge(this.resolvers, override);
|
|
11546
11289
|
merged.init();
|
|
11547
11290
|
return merged.resolve();
|
|
11548
11291
|
}
|
|
@@ -11595,6 +11338,33 @@ class HtmlValidate {
|
|
|
11595
11338
|
};
|
|
11596
11339
|
return this.validateSource(source, options);
|
|
11597
11340
|
}
|
|
11341
|
+
validateStringSync(str, arg1, arg2, arg3) {
|
|
11342
|
+
const filename = typeof arg1 === "string" ? arg1 : "inline";
|
|
11343
|
+
const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : undefined;
|
|
11344
|
+
const hooks = isSourceHooks(arg1) ? arg1 : isSourceHooks(arg2) ? arg2 : arg3;
|
|
11345
|
+
const source = {
|
|
11346
|
+
data: str,
|
|
11347
|
+
filename,
|
|
11348
|
+
line: 1,
|
|
11349
|
+
column: 1,
|
|
11350
|
+
offset: 0,
|
|
11351
|
+
hooks,
|
|
11352
|
+
};
|
|
11353
|
+
return this.validateSourceSync(source, options);
|
|
11354
|
+
}
|
|
11355
|
+
/**
|
|
11356
|
+
* Parse and validate HTML from [[Source]].
|
|
11357
|
+
*
|
|
11358
|
+
* @public
|
|
11359
|
+
* @param input - Source to parse.
|
|
11360
|
+
* @returns Report output.
|
|
11361
|
+
*/
|
|
11362
|
+
async validateSource(input, configOverride) {
|
|
11363
|
+
const config = await this.getConfigFor(input.filename, configOverride);
|
|
11364
|
+
const source = config.transformSource(input);
|
|
11365
|
+
const engine = new Engine(config, Parser);
|
|
11366
|
+
return engine.lint(source);
|
|
11367
|
+
}
|
|
11598
11368
|
/**
|
|
11599
11369
|
* Parse and validate HTML from [[Source]].
|
|
11600
11370
|
*
|
|
@@ -11602,8 +11372,8 @@ class HtmlValidate {
|
|
|
11602
11372
|
* @param input - Source to parse.
|
|
11603
11373
|
* @returns Report output.
|
|
11604
11374
|
*/
|
|
11605
|
-
|
|
11606
|
-
const config = this.
|
|
11375
|
+
validateSourceSync(input, configOverride) {
|
|
11376
|
+
const config = this.getConfigForSync(input.filename, configOverride);
|
|
11607
11377
|
const source = config.transformSource(input);
|
|
11608
11378
|
const engine = new Engine(config, Parser);
|
|
11609
11379
|
return engine.lint(source);
|
|
@@ -11615,8 +11385,21 @@ class HtmlValidate {
|
|
|
11615
11385
|
* @param filename - Filename to read and parse.
|
|
11616
11386
|
* @returns Report output.
|
|
11617
11387
|
*/
|
|
11618
|
-
validateFile(filename) {
|
|
11619
|
-
const config = this.getConfigFor(filename);
|
|
11388
|
+
async validateFile(filename) {
|
|
11389
|
+
const config = await this.getConfigFor(filename);
|
|
11390
|
+
const source = config.transformFilename(filename);
|
|
11391
|
+
const engine = new Engine(config, Parser);
|
|
11392
|
+
return Promise.resolve(engine.lint(source));
|
|
11393
|
+
}
|
|
11394
|
+
/**
|
|
11395
|
+
* Parse and validate HTML from file.
|
|
11396
|
+
*
|
|
11397
|
+
* @public
|
|
11398
|
+
* @param filename - Filename to read and parse.
|
|
11399
|
+
* @returns Report output.
|
|
11400
|
+
*/
|
|
11401
|
+
validateFileSync(filename) {
|
|
11402
|
+
const config = this.getConfigForSync(filename);
|
|
11620
11403
|
const source = config.transformFilename(filename);
|
|
11621
11404
|
const engine = new Engine(config, Parser);
|
|
11622
11405
|
return engine.lint(source);
|
|
@@ -11628,8 +11411,38 @@ class HtmlValidate {
|
|
|
11628
11411
|
* @param filenames - Filenames to read and parse.
|
|
11629
11412
|
* @returns Report output.
|
|
11630
11413
|
*/
|
|
11631
|
-
validateMultipleFiles(filenames) {
|
|
11632
|
-
|
|
11414
|
+
async validateMultipleFiles(filenames) {
|
|
11415
|
+
const report = Reporter.merge(filenames.map((filename) => this.validateFileSync(filename)));
|
|
11416
|
+
return Promise.resolve(report);
|
|
11417
|
+
}
|
|
11418
|
+
/**
|
|
11419
|
+
* Parse and validate HTML from multiple files. Result is merged together to a
|
|
11420
|
+
* single report.
|
|
11421
|
+
*
|
|
11422
|
+
* @param filenames - Filenames to read and parse.
|
|
11423
|
+
* @returns Report output.
|
|
11424
|
+
*/
|
|
11425
|
+
validateMultipleFilesSync(filenames) {
|
|
11426
|
+
return Reporter.merge(filenames.map((filename) => this.validateFileSync(filename)));
|
|
11427
|
+
}
|
|
11428
|
+
/**
|
|
11429
|
+
* Returns true if the given filename can be validated.
|
|
11430
|
+
*
|
|
11431
|
+
* A file is considered to be validatable if the extension is `.html` or if a
|
|
11432
|
+
* transformer matches the filename.
|
|
11433
|
+
*
|
|
11434
|
+
* This is mostly useful for tooling to determine whenever to validate the
|
|
11435
|
+
* file or not. CLI tools will run on all the given files anyway.
|
|
11436
|
+
*/
|
|
11437
|
+
async canValidate(filename) {
|
|
11438
|
+
/* .html is always supported */
|
|
11439
|
+
const extension = path.extname(filename).toLowerCase();
|
|
11440
|
+
if (extension === ".html") {
|
|
11441
|
+
return true;
|
|
11442
|
+
}
|
|
11443
|
+
/* test if there is a matching transformer */
|
|
11444
|
+
const config = await this.getConfigFor(filename);
|
|
11445
|
+
return config.canTransform(filename);
|
|
11633
11446
|
}
|
|
11634
11447
|
/**
|
|
11635
11448
|
* Returns true if the given filename can be validated.
|
|
@@ -11640,14 +11453,14 @@ class HtmlValidate {
|
|
|
11640
11453
|
* This is mostly useful for tooling to determine whenever to validate the
|
|
11641
11454
|
* file or not. CLI tools will run on all the given files anyway.
|
|
11642
11455
|
*/
|
|
11643
|
-
|
|
11456
|
+
canValidateSync(filename) {
|
|
11644
11457
|
/* .html is always supported */
|
|
11645
11458
|
const extension = path.extname(filename).toLowerCase();
|
|
11646
11459
|
if (extension === ".html") {
|
|
11647
11460
|
return true;
|
|
11648
11461
|
}
|
|
11649
11462
|
/* test if there is a matching transformer */
|
|
11650
|
-
const config = this.
|
|
11463
|
+
const config = this.getConfigForSync(filename);
|
|
11651
11464
|
return config.canTransform(filename);
|
|
11652
11465
|
}
|
|
11653
11466
|
/**
|
|
@@ -11660,7 +11473,7 @@ class HtmlValidate {
|
|
|
11660
11473
|
* @param filename - Filename to tokenize.
|
|
11661
11474
|
*/
|
|
11662
11475
|
dumpTokens(filename) {
|
|
11663
|
-
const config = this.
|
|
11476
|
+
const config = this.getConfigForSync(filename);
|
|
11664
11477
|
const source = config.transformFilename(filename);
|
|
11665
11478
|
const engine = new Engine(config, Parser);
|
|
11666
11479
|
return engine.dumpTokens(source);
|
|
@@ -11675,7 +11488,7 @@ class HtmlValidate {
|
|
|
11675
11488
|
* @param filename - Filename to dump events from.
|
|
11676
11489
|
*/
|
|
11677
11490
|
dumpEvents(filename) {
|
|
11678
|
-
const config = this.
|
|
11491
|
+
const config = this.getConfigForSync(filename);
|
|
11679
11492
|
const source = config.transformFilename(filename);
|
|
11680
11493
|
const engine = new Engine(config, Parser);
|
|
11681
11494
|
return engine.dumpEvents(source);
|
|
@@ -11690,7 +11503,7 @@ class HtmlValidate {
|
|
|
11690
11503
|
* @param filename - Filename to dump DOM tree from.
|
|
11691
11504
|
*/
|
|
11692
11505
|
dumpTree(filename) {
|
|
11693
|
-
const config = this.
|
|
11506
|
+
const config = this.getConfigForSync(filename);
|
|
11694
11507
|
const source = config.transformFilename(filename);
|
|
11695
11508
|
const engine = new Engine(config, Parser);
|
|
11696
11509
|
return engine.dumpTree(source);
|
|
@@ -11705,7 +11518,7 @@ class HtmlValidate {
|
|
|
11705
11518
|
* @param filename - Filename to dump source from.
|
|
11706
11519
|
*/
|
|
11707
11520
|
dumpSource(filename) {
|
|
11708
|
-
const config = this.
|
|
11521
|
+
const config = this.getConfigForSync(filename);
|
|
11709
11522
|
const sources = config.transformFilename(filename);
|
|
11710
11523
|
return sources.reduce((result, source) => {
|
|
11711
11524
|
result.push(`Source ${source.filename}@${source.line}:${source.column} (offset: ${source.offset})`);
|
|
@@ -11741,37 +11554,95 @@ class HtmlValidate {
|
|
|
11741
11554
|
* handled by html-validate but the path will be used when resolving
|
|
11742
11555
|
* configuration. As a rule-of-thumb, set it to the elements json file.
|
|
11743
11556
|
*/
|
|
11744
|
-
getElementsSchema(filename) {
|
|
11745
|
-
const config = this.getConfigFor(filename !== null && filename !== void 0 ? filename : "inline");
|
|
11557
|
+
async getElementsSchema(filename) {
|
|
11558
|
+
const config = await this.getConfigFor(filename !== null && filename !== void 0 ? filename : "inline");
|
|
11746
11559
|
const metaTable = config.getMetaTable();
|
|
11747
11560
|
return metaTable.getJSONSchema();
|
|
11748
11561
|
}
|
|
11562
|
+
/**
|
|
11563
|
+
* Get effective metadata element schema.
|
|
11564
|
+
*
|
|
11565
|
+
* If a filename is given the configured plugins can extend the
|
|
11566
|
+
* schema. Filename must not be an existing file or a filetype normally
|
|
11567
|
+
* handled by html-validate but the path will be used when resolving
|
|
11568
|
+
* configuration. As a rule-of-thumb, set it to the elements json file.
|
|
11569
|
+
*/
|
|
11570
|
+
getElementsSchemaSync(filename) {
|
|
11571
|
+
const config = this.getConfigForSync(filename !== null && filename !== void 0 ? filename : "inline");
|
|
11572
|
+
const metaTable = config.getMetaTable();
|
|
11573
|
+
return metaTable.getJSONSchema();
|
|
11574
|
+
}
|
|
11575
|
+
async getContextualDocumentation(message, filenameOrConfig = "inline") {
|
|
11576
|
+
const config = typeof filenameOrConfig === "string"
|
|
11577
|
+
? await this.getConfigFor(filenameOrConfig)
|
|
11578
|
+
: await filenameOrConfig;
|
|
11579
|
+
const engine = new Engine(config, Parser);
|
|
11580
|
+
return engine.getRuleDocumentation(message);
|
|
11581
|
+
}
|
|
11582
|
+
getContextualDocumentationSync(message, filenameOrConfig = "inline") {
|
|
11583
|
+
const config = typeof filenameOrConfig === "string"
|
|
11584
|
+
? this.getConfigForSync(filenameOrConfig)
|
|
11585
|
+
: filenameOrConfig;
|
|
11586
|
+
const engine = new Engine(config, Parser);
|
|
11587
|
+
return engine.getRuleDocumentation(message);
|
|
11588
|
+
}
|
|
11749
11589
|
/**
|
|
11750
11590
|
* Get contextual documentation for the given rule.
|
|
11751
11591
|
*
|
|
11752
11592
|
* Typical usage:
|
|
11753
11593
|
*
|
|
11754
11594
|
* ```js
|
|
11755
|
-
* const report = htmlvalidate.validateFile("my-file.html");
|
|
11595
|
+
* const report = await htmlvalidate.validateFile("my-file.html");
|
|
11756
11596
|
* for (const result of report.results){
|
|
11757
|
-
* const config = htmlvalidate.getConfigFor(result.filePath);
|
|
11597
|
+
* const config = await htmlvalidate.getConfigFor(result.filePath);
|
|
11758
11598
|
* for (const message of result.messages){
|
|
11759
|
-
* const documentation = htmlvalidate.getRuleDocumentation(message.ruleId, config, message.context);
|
|
11599
|
+
* const documentation = await htmlvalidate.getRuleDocumentation(message.ruleId, config, message.context);
|
|
11760
11600
|
* // do something with documentation
|
|
11761
11601
|
* }
|
|
11762
11602
|
* }
|
|
11763
11603
|
* ```
|
|
11764
11604
|
*
|
|
11605
|
+
* @public
|
|
11606
|
+
* @deprecated Deprecated since 8.0.0, use [[getContextualDocumentation]] instead.
|
|
11765
11607
|
* @param ruleId - Rule to get documentation for.
|
|
11766
11608
|
* @param config - If set it provides more accurate description by using the
|
|
11767
11609
|
* correct configuration for the file.
|
|
11768
11610
|
* @param context - If set to `Message.context` some rules can provide
|
|
11769
11611
|
* contextual details and suggestions.
|
|
11770
11612
|
*/
|
|
11771
|
-
getRuleDocumentation(ruleId, config = null, context = null) {
|
|
11613
|
+
async getRuleDocumentation(ruleId, config = null, context = null) {
|
|
11772
11614
|
const c = config || this.getConfigFor("inline");
|
|
11615
|
+
const engine = new Engine(await c, Parser);
|
|
11616
|
+
return engine.getRuleDocumentation({ ruleId, context });
|
|
11617
|
+
}
|
|
11618
|
+
/**
|
|
11619
|
+
* Get contextual documentation for the given rule.
|
|
11620
|
+
*
|
|
11621
|
+
* Typical usage:
|
|
11622
|
+
*
|
|
11623
|
+
* ```js
|
|
11624
|
+
* const report = htmlvalidate.validateFileSync("my-file.html");
|
|
11625
|
+
* for (const result of report.results){
|
|
11626
|
+
* const config = htmlvalidate.getConfigForSync(result.filePath);
|
|
11627
|
+
* for (const message of result.messages){
|
|
11628
|
+
* const documentation = htmlvalidate.getRuleDocumentationSync(message.ruleId, config, message.context);
|
|
11629
|
+
* // do something with documentation
|
|
11630
|
+
* }
|
|
11631
|
+
* }
|
|
11632
|
+
* ```
|
|
11633
|
+
*
|
|
11634
|
+
* @public
|
|
11635
|
+
* @deprecated Deprecated since 8.0.0, use [[getContextualDocumentationSync]] instead.
|
|
11636
|
+
* @param ruleId - Rule to get documentation for.
|
|
11637
|
+
* @param config - If set it provides more accurate description by using the
|
|
11638
|
+
* correct configuration for the file.
|
|
11639
|
+
* @param context - If set to `Message.context` some rules can provide
|
|
11640
|
+
* contextual details and suggestions.
|
|
11641
|
+
*/
|
|
11642
|
+
getRuleDocumentationSync(ruleId, config = null, context = null) {
|
|
11643
|
+
const c = config || this.getConfigForSync("inline");
|
|
11773
11644
|
const engine = new Engine(c, Parser);
|
|
11774
|
-
return engine.getRuleDocumentation(ruleId, context);
|
|
11645
|
+
return engine.getRuleDocumentation({ ruleId, context });
|
|
11775
11646
|
}
|
|
11776
11647
|
/**
|
|
11777
11648
|
* Create a parser configured for given filename.
|
|
@@ -11779,8 +11650,8 @@ class HtmlValidate {
|
|
|
11779
11650
|
* @internal
|
|
11780
11651
|
* @param source - Source to use.
|
|
11781
11652
|
*/
|
|
11782
|
-
getParserFor(source) {
|
|
11783
|
-
const config = this.getConfigFor(source.filename);
|
|
11653
|
+
async getParserFor(source) {
|
|
11654
|
+
const config = await this.getConfigFor(source.filename);
|
|
11784
11655
|
return new Parser(config);
|
|
11785
11656
|
}
|
|
11786
11657
|
/**
|
|
@@ -11794,11 +11665,19 @@ class HtmlValidate {
|
|
|
11794
11665
|
*/
|
|
11795
11666
|
getConfigFor(filename, configOverride) {
|
|
11796
11667
|
const config = this.configLoader.getConfigFor(filename, configOverride);
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11668
|
+
return Promise.resolve(config);
|
|
11669
|
+
}
|
|
11670
|
+
/**
|
|
11671
|
+
* Get configuration for given filename.
|
|
11672
|
+
*
|
|
11673
|
+
* See [[FileSystemConfigLoader]] for details.
|
|
11674
|
+
*
|
|
11675
|
+
* @public
|
|
11676
|
+
* @param filename - Filename to get configuration for.
|
|
11677
|
+
* @param configOverride - Configuration to apply last.
|
|
11678
|
+
*/
|
|
11679
|
+
getConfigForSync(filename, configOverride) {
|
|
11680
|
+
return this.configLoader.getConfigFor(filename, configOverride);
|
|
11802
11681
|
}
|
|
11803
11682
|
/**
|
|
11804
11683
|
* Flush configuration cache. Clears full cache unless a filename is given.
|
|
@@ -11817,7 +11696,7 @@ class HtmlValidate {
|
|
|
11817
11696
|
/** @public */
|
|
11818
11697
|
const name = "html-validate";
|
|
11819
11698
|
/** @public */
|
|
11820
|
-
const version = "
|
|
11699
|
+
const version = "8.0.0";
|
|
11821
11700
|
/** @public */
|
|
11822
11701
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11823
11702
|
|
|
@@ -11843,6 +11722,7 @@ const defaults$1 = {
|
|
|
11843
11722
|
* option is used a warning is displayed on the console.
|
|
11844
11723
|
*
|
|
11845
11724
|
* @public
|
|
11725
|
+
* @since v5.0.0
|
|
11846
11726
|
* @param name - Name of plugin
|
|
11847
11727
|
* @param declared - What library versions the plugin support (e.g. declared peerDependencies)
|
|
11848
11728
|
* @returns - `true` if version is compatible
|
|
@@ -11863,6 +11743,27 @@ function compatibilityCheck(name, declared, options) {
|
|
|
11863
11743
|
return false;
|
|
11864
11744
|
}
|
|
11865
11745
|
|
|
11746
|
+
/**
|
|
11747
|
+
* Similar to `require(..)` but removes the cached copy first.
|
|
11748
|
+
*/
|
|
11749
|
+
function requireUncached(require, moduleId) {
|
|
11750
|
+
const filename = require.resolve(moduleId);
|
|
11751
|
+
/* remove references from the parent module to prevent memory leak */
|
|
11752
|
+
const m = require.cache[filename];
|
|
11753
|
+
if (m && m.parent) {
|
|
11754
|
+
const { parent } = m;
|
|
11755
|
+
for (let i = parent.children.length - 1; i >= 0; i--) {
|
|
11756
|
+
if (parent.children[i].id === filename) {
|
|
11757
|
+
parent.children.splice(i, 1);
|
|
11758
|
+
}
|
|
11759
|
+
}
|
|
11760
|
+
}
|
|
11761
|
+
/* remove old module from cache */
|
|
11762
|
+
delete require.cache[filename];
|
|
11763
|
+
/* eslint-disable-next-line import/no-dynamic-require, security/detect-non-literal-require -- as expected but should be moved to upcoming resolver class */
|
|
11764
|
+
return require(filename);
|
|
11765
|
+
}
|
|
11766
|
+
|
|
11866
11767
|
const ruleIds = new Set(Object.keys(rules));
|
|
11867
11768
|
/**
|
|
11868
11769
|
* Returns true if given ruleId is an existing builtin rule. It does not handle
|
|
@@ -11879,14 +11780,149 @@ function ruleExists(ruleId) {
|
|
|
11879
11780
|
return ruleIds.has(ruleId);
|
|
11880
11781
|
}
|
|
11881
11782
|
|
|
11783
|
+
const legacyRequire = createRequire(import.meta.url);
|
|
11784
|
+
|
|
11785
|
+
let cachedRootDir = null;
|
|
11786
|
+
/**
|
|
11787
|
+
* @internal
|
|
11788
|
+
*/
|
|
11789
|
+
function determineRootDirImpl(intial, fs) {
|
|
11790
|
+
/* try to locate package.json */
|
|
11791
|
+
let current = intial;
|
|
11792
|
+
// eslint-disable-next-line no-constant-condition -- break outs when filesystem is traversed
|
|
11793
|
+
while (true) {
|
|
11794
|
+
const search = path$1.join(current, "package.json");
|
|
11795
|
+
if (fs.existsSync(search)) {
|
|
11796
|
+
return current;
|
|
11797
|
+
}
|
|
11798
|
+
/* get the parent directory */
|
|
11799
|
+
const child = current;
|
|
11800
|
+
current = path$1.dirname(current);
|
|
11801
|
+
/* stop if this is the root directory */
|
|
11802
|
+
if (current === child) {
|
|
11803
|
+
break;
|
|
11804
|
+
}
|
|
11805
|
+
}
|
|
11806
|
+
/* default to working directory if no package.json is found */
|
|
11807
|
+
return intial;
|
|
11808
|
+
}
|
|
11809
|
+
/**
|
|
11810
|
+
* Try to determine root directory based on the location of the closest
|
|
11811
|
+
* `package.json`. Fallbacks on `process.cwd()` if no package.json was found.
|
|
11812
|
+
*
|
|
11813
|
+
* @internal
|
|
11814
|
+
*/
|
|
11815
|
+
/* istanbul ignore next: cached version of determineRootDirImpl, no need to test */
|
|
11816
|
+
function determineRootDir() {
|
|
11817
|
+
if (cachedRootDir === null) {
|
|
11818
|
+
cachedRootDir = determineRootDirImpl(process.cwd(), fs$1);
|
|
11819
|
+
}
|
|
11820
|
+
return cachedRootDir;
|
|
11821
|
+
}
|
|
11822
|
+
|
|
11823
|
+
/**
|
|
11824
|
+
* @internal
|
|
11825
|
+
*/
|
|
11826
|
+
function expandRelativePath(value, { cwd }) {
|
|
11827
|
+
if (typeof value === "string" && value[0] === ".") {
|
|
11828
|
+
return path$1.normalize(path$1.join(cwd, value));
|
|
11829
|
+
}
|
|
11830
|
+
else {
|
|
11831
|
+
return value;
|
|
11832
|
+
}
|
|
11833
|
+
}
|
|
11834
|
+
|
|
11835
|
+
function isRequireError(error) {
|
|
11836
|
+
return Boolean(error && typeof error === "object" && "code" in error);
|
|
11837
|
+
}
|
|
11838
|
+
function isTransformer(value) {
|
|
11839
|
+
return typeof value === "function";
|
|
11840
|
+
}
|
|
11841
|
+
/**
|
|
11842
|
+
* Create a new resolver for NodeJS packages using `require(..)`.
|
|
11843
|
+
*
|
|
11844
|
+
* If the module name contains `<rootDir>` (e.g. `<rootDir/foo`) it will be
|
|
11845
|
+
* expanded relative to the root directory either explicitly set by the
|
|
11846
|
+
* `rootDir` parameter or determined automatically by the closest `package.json`
|
|
11847
|
+
* file (starting at the current working directory).
|
|
11848
|
+
*
|
|
11849
|
+
* @public
|
|
11850
|
+
* @since 8.0.0
|
|
11851
|
+
*/
|
|
11852
|
+
function nodejsResolver(options = {}) {
|
|
11853
|
+
var _a;
|
|
11854
|
+
const rootDir = (_a = options.rootDir) !== null && _a !== void 0 ? _a : determineRootDir();
|
|
11855
|
+
function internalRequire(id, { cache }) {
|
|
11856
|
+
const moduleName = id.replace("<rootDir>", rootDir);
|
|
11857
|
+
try {
|
|
11858
|
+
/* istanbul ignore else: the tests only runs the cached versions to get
|
|
11859
|
+
* unmodified access to `require`, the implementation of `requireUncached`
|
|
11860
|
+
* is assumed to be tested elsewhere */
|
|
11861
|
+
if (cache) {
|
|
11862
|
+
return legacyRequire(moduleName);
|
|
11863
|
+
}
|
|
11864
|
+
else {
|
|
11865
|
+
return requireUncached(legacyRequire, moduleName);
|
|
11866
|
+
}
|
|
11867
|
+
}
|
|
11868
|
+
catch (err) {
|
|
11869
|
+
if (isRequireError(err) && err.code === "MODULE_NOT_FOUND") {
|
|
11870
|
+
return null;
|
|
11871
|
+
}
|
|
11872
|
+
throw err;
|
|
11873
|
+
}
|
|
11874
|
+
}
|
|
11875
|
+
return {
|
|
11876
|
+
name: "nodejs-resolver",
|
|
11877
|
+
resolveElements(id, options) {
|
|
11878
|
+
return internalRequire(id, options);
|
|
11879
|
+
},
|
|
11880
|
+
resolveConfig(id, options) {
|
|
11881
|
+
var _a, _b, _c;
|
|
11882
|
+
const configData = internalRequire(id, options);
|
|
11883
|
+
if (!configData) {
|
|
11884
|
+
return null;
|
|
11885
|
+
}
|
|
11886
|
+
/* expand any relative paths */
|
|
11887
|
+
const cwd = path$1.dirname(id);
|
|
11888
|
+
const expand = (value) => expandRelativePath(value, { cwd });
|
|
11889
|
+
configData.elements = (_a = configData.elements) === null || _a === void 0 ? void 0 : _a.map(expand);
|
|
11890
|
+
configData.extends = (_b = configData.extends) === null || _b === void 0 ? void 0 : _b.map(expand);
|
|
11891
|
+
configData.plugins = (_c = configData.plugins) === null || _c === void 0 ? void 0 : _c.map(expand);
|
|
11892
|
+
return configData;
|
|
11893
|
+
},
|
|
11894
|
+
resolvePlugin(id, options) {
|
|
11895
|
+
return internalRequire(id, options);
|
|
11896
|
+
},
|
|
11897
|
+
resolveTransformer(id, options) {
|
|
11898
|
+
const mod = internalRequire(id, options);
|
|
11899
|
+
if (!mod) {
|
|
11900
|
+
return null;
|
|
11901
|
+
}
|
|
11902
|
+
if (isTransformer(mod)) {
|
|
11903
|
+
return mod;
|
|
11904
|
+
}
|
|
11905
|
+
/* this is not a proper transformer, is it a plugin exposing a transformer? */
|
|
11906
|
+
if (mod.transformer) {
|
|
11907
|
+
throw new ConfigError(`Module "${id}" is not a valid transformer. This looks like a plugin, did you forget to load the plugin first?`);
|
|
11908
|
+
}
|
|
11909
|
+
throw new ConfigError(`Module "${id}" is not a valid transformer.`);
|
|
11910
|
+
},
|
|
11911
|
+
};
|
|
11912
|
+
}
|
|
11913
|
+
|
|
11882
11914
|
/**
|
|
11883
11915
|
* @internal
|
|
11884
11916
|
*/
|
|
11885
|
-
function findConfigurationFiles(directory) {
|
|
11917
|
+
function findConfigurationFiles(fs, directory) {
|
|
11886
11918
|
return ["json", "cjs", "js"]
|
|
11887
|
-
.map((extension) => path.join(directory, `.htmlvalidate.${extension}`))
|
|
11919
|
+
.map((extension) => path$1.join(directory, `.htmlvalidate.${extension}`))
|
|
11888
11920
|
.filter((filePath) => fs.existsSync(filePath));
|
|
11889
11921
|
}
|
|
11922
|
+
const defaultResolvers = [nodejsResolver()];
|
|
11923
|
+
function hasResolver(value) {
|
|
11924
|
+
return Array.isArray(value[0]);
|
|
11925
|
+
}
|
|
11890
11926
|
/**
|
|
11891
11927
|
* Loads configuration by traversing filesystem.
|
|
11892
11928
|
*
|
|
@@ -11915,12 +11951,20 @@ function findConfigurationFiles(directory) {
|
|
|
11915
11951
|
* @public
|
|
11916
11952
|
*/
|
|
11917
11953
|
class FileSystemConfigLoader extends ConfigLoader {
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11954
|
+
constructor(...args) {
|
|
11955
|
+
var _a, _b;
|
|
11956
|
+
if (hasResolver(args)) {
|
|
11957
|
+
/* istanbul ignore next */
|
|
11958
|
+
const [resolvers, config, options = {}] = args;
|
|
11959
|
+
super(resolvers, config);
|
|
11960
|
+
this.fs = /* istanbul ignore next */ (_a = options.fs) !== null && _a !== void 0 ? _a : fs$1;
|
|
11961
|
+
}
|
|
11962
|
+
else {
|
|
11963
|
+
/* istanbul ignore next */
|
|
11964
|
+
const [config, options = {}] = args;
|
|
11965
|
+
super(defaultResolvers, config);
|
|
11966
|
+
this.fs = /* istanbul ignore next */ (_b = options.fs) !== null && _b !== void 0 ? _b : fs$1;
|
|
11967
|
+
}
|
|
11924
11968
|
this.cache = new Map();
|
|
11925
11969
|
}
|
|
11926
11970
|
/**
|
|
@@ -11940,12 +11984,14 @@ class FileSystemConfigLoader extends ConfigLoader {
|
|
|
11940
11984
|
/* special case when the global configuration is marked as root, should not
|
|
11941
11985
|
* try to load and more configuration files */
|
|
11942
11986
|
if (this.globalConfig.isRootFound()) {
|
|
11943
|
-
const merged = this.globalConfig.merge(override);
|
|
11987
|
+
const merged = this.globalConfig.merge(this.resolvers, override);
|
|
11944
11988
|
merged.init();
|
|
11945
11989
|
return merged.resolve();
|
|
11946
11990
|
}
|
|
11947
11991
|
const config = this.fromFilename(filename);
|
|
11948
|
-
const merged = config
|
|
11992
|
+
const merged = config
|
|
11993
|
+
? config.merge(this.resolvers, override)
|
|
11994
|
+
: this.globalConfig.merge(this.resolvers, override);
|
|
11949
11995
|
merged.init();
|
|
11950
11996
|
return merged.resolve();
|
|
11951
11997
|
}
|
|
@@ -11977,15 +12023,15 @@ class FileSystemConfigLoader extends ConfigLoader {
|
|
|
11977
12023
|
return cache;
|
|
11978
12024
|
}
|
|
11979
12025
|
let found = false;
|
|
11980
|
-
let current = path.resolve(path.dirname(filename));
|
|
12026
|
+
let current = path$1.resolve(path$1.dirname(filename));
|
|
11981
12027
|
let config = this.empty();
|
|
11982
12028
|
// eslint-disable-next-line no-constant-condition -- it will break out when filesystem is traversed
|
|
11983
12029
|
while (true) {
|
|
11984
12030
|
/* search configuration files in current directory */
|
|
11985
|
-
for (const configFile of findConfigurationFiles(current)) {
|
|
12031
|
+
for (const configFile of findConfigurationFiles(this.fs, current)) {
|
|
11986
12032
|
const local = this.loadFromFile(configFile);
|
|
11987
12033
|
found = true;
|
|
11988
|
-
config = local.merge(config);
|
|
12034
|
+
config = local.merge(this.resolvers, config);
|
|
11989
12035
|
}
|
|
11990
12036
|
/* stop if a configuration with "root" is set to true */
|
|
11991
12037
|
if (config.isRootFound()) {
|
|
@@ -11993,7 +12039,7 @@ class FileSystemConfigLoader extends ConfigLoader {
|
|
|
11993
12039
|
}
|
|
11994
12040
|
/* get the parent directory */
|
|
11995
12041
|
const child = current;
|
|
11996
|
-
current = path.dirname(current);
|
|
12042
|
+
current = path$1.dirname(current);
|
|
11997
12043
|
/* stop if this is the root directory */
|
|
11998
12044
|
if (current === child) {
|
|
11999
12045
|
break;
|
|
@@ -12007,8 +12053,14 @@ class FileSystemConfigLoader extends ConfigLoader {
|
|
|
12007
12053
|
this.cache.set(filename, config);
|
|
12008
12054
|
return config;
|
|
12009
12055
|
}
|
|
12056
|
+
/**
|
|
12057
|
+
* @internal For testing only
|
|
12058
|
+
*/
|
|
12059
|
+
_getInternalCache() {
|
|
12060
|
+
return this.cache;
|
|
12061
|
+
}
|
|
12010
12062
|
defaultConfig() {
|
|
12011
|
-
return
|
|
12063
|
+
return Config.defaultConfig();
|
|
12012
12064
|
}
|
|
12013
12065
|
}
|
|
12014
12066
|
|
|
@@ -12263,5 +12315,5 @@ function getFormatter(name) {
|
|
|
12263
12315
|
return (_a = availableFormatters[name]) !== null && _a !== void 0 ? _a : null;
|
|
12264
12316
|
}
|
|
12265
12317
|
|
|
12266
|
-
export { Attribute as A, isTextNode as B, Config as C, DynamicValue as D, EventHandler as E, FileSystemConfigLoader as F, isElementNode as G, HtmlValidate as H, generateIdSelector as I, name as J, bugs as K, MetaTable as M, NodeClosed as N, Presets as P, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, ConfigError as a, ConfigLoader as b, StaticConfigLoader as c, DOMTokenList as d, HtmlElement as e, DOMNode as f, DOMTree as g, NodeType as h, SchemaValidationError as i, NestedError as j, TextContent$1 as k, MetaCopyableProperty as l, Rule as m,
|
|
12318
|
+
export { Attribute as A, isTextNode as B, Config as C, DynamicValue as D, EventHandler as E, FileSystemConfigLoader as F, isElementNode as G, HtmlValidate as H, generateIdSelector as I, name as J, bugs as K, MetaTable as M, NodeClosed as N, Presets as P, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, ConfigError as a, ConfigLoader as b, StaticConfigLoader as c, DOMTokenList as d, HtmlElement as e, DOMNode as f, DOMTree as g, NodeType as h, SchemaValidationError as i, NestedError as j, TextContent$1 as k, MetaCopyableProperty as l, Rule as m, sliceLocation as n, Reporter as o, definePlugin as p, Parser as q, ruleExists as r, staticResolver as s, getFormatter as t, legacyRequire as u, version as v, ensureError as w, nodejsResolver as x, compatibilityCheck as y, codeframe as z };
|
|
12267
12319
|
//# sourceMappingURL=core.js.map
|