html-validate 6.6.1 → 6.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/browser.js +2 -0
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/cli.js +9 -5
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core.d.ts +1 -3
- package/dist/cjs/core.js +273 -82
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/html-validate.js +11 -6
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/jest-lib.d.ts +2 -1
- package/dist/cjs/jest-lib.js +52 -27
- package/dist/cjs/jest-lib.js.map +1 -1
- package/dist/cjs/jest.js +2 -0
- package/dist/cjs/jest.js.map +1 -1
- package/dist/es/browser.js +2 -0
- package/dist/es/browser.js.map +1 -1
- package/dist/es/cli.js +9 -5
- package/dist/es/cli.js.map +1 -1
- package/dist/es/core.d.ts +1 -3
- package/dist/es/core.js +251 -80
- package/dist/es/core.js.map +1 -1
- package/dist/es/html-validate.js +11 -6
- package/dist/es/html-validate.js.map +1 -1
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/jest-lib.d.ts +2 -1
- package/dist/es/jest-lib.js +52 -27
- package/dist/es/jest-lib.js.map +1 -1
- package/dist/es/jest.js +2 -0
- package/dist/es/jest.js.map +1 -1
- package/package.json +1 -153
package/dist/cjs/core.js
CHANGED
|
@@ -4,6 +4,8 @@ var fs = require('fs');
|
|
|
4
4
|
var betterAjvErrors = require('@sidvind/better-ajv-errors');
|
|
5
5
|
var Ajv = require('ajv');
|
|
6
6
|
var deepmerge = require('deepmerge');
|
|
7
|
+
var espree = require('espree');
|
|
8
|
+
var walk = require('acorn-walk');
|
|
7
9
|
var path = require('path');
|
|
8
10
|
var semver = require('semver');
|
|
9
11
|
var kleur = require('kleur');
|
|
@@ -12,10 +14,30 @@ var stylishImpl = require('@html-validate/stylish');
|
|
|
12
14
|
|
|
13
15
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
16
|
|
|
17
|
+
function _interopNamespace(e) {
|
|
18
|
+
if (e && e.__esModule) return e;
|
|
19
|
+
var n = Object.create(null);
|
|
20
|
+
if (e) {
|
|
21
|
+
Object.keys(e).forEach(function (k) {
|
|
22
|
+
if (k !== 'default') {
|
|
23
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
24
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return e[k]; }
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
n["default"] = e;
|
|
32
|
+
return Object.freeze(n);
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
16
36
|
var betterAjvErrors__default = /*#__PURE__*/_interopDefaultLegacy(betterAjvErrors);
|
|
17
37
|
var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
|
|
18
38
|
var deepmerge__default = /*#__PURE__*/_interopDefaultLegacy(deepmerge);
|
|
39
|
+
var espree__namespace = /*#__PURE__*/_interopNamespace(espree);
|
|
40
|
+
var walk__namespace = /*#__PURE__*/_interopNamespace(walk);
|
|
19
41
|
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
20
42
|
var semver__default = /*#__PURE__*/_interopDefaultLegacy(semver);
|
|
21
43
|
var kleur__default = /*#__PURE__*/_interopDefaultLegacy(kleur);
|
|
@@ -256,7 +278,7 @@ class NestedError extends Error {
|
|
|
256
278
|
constructor(message, nested) {
|
|
257
279
|
super(message);
|
|
258
280
|
Error.captureStackTrace(this, NestedError);
|
|
259
|
-
if (nested) {
|
|
281
|
+
if (nested && nested.stack) {
|
|
260
282
|
this.stack += `\nCaused by: ${nested.stack}`;
|
|
261
283
|
}
|
|
262
284
|
}
|
|
@@ -1849,8 +1871,13 @@ exports.NodeClosed = void 0;
|
|
|
1849
1871
|
NodeClosed[NodeClosed["VoidSelfClosed"] = 3] = "VoidSelfClosed";
|
|
1850
1872
|
NodeClosed[NodeClosed["ImplicitClosed"] = 4] = "ImplicitClosed";
|
|
1851
1873
|
})(exports.NodeClosed || (exports.NodeClosed = {}));
|
|
1852
|
-
|
|
1853
|
-
|
|
1874
|
+
/**
|
|
1875
|
+
* Returns true if the node is an element node.
|
|
1876
|
+
*
|
|
1877
|
+
* @public
|
|
1878
|
+
*/
|
|
1879
|
+
function isElementNode(node) {
|
|
1880
|
+
return Boolean(node && node.nodeType === NodeType.ELEMENT_NODE);
|
|
1854
1881
|
}
|
|
1855
1882
|
function isValidTagName(tagName) {
|
|
1856
1883
|
return Boolean(tagName !== "" && tagName !== "*");
|
|
@@ -1924,7 +1951,7 @@ class HtmlElement extends DOMNode {
|
|
|
1924
1951
|
* Similar to childNodes but only elements.
|
|
1925
1952
|
*/
|
|
1926
1953
|
get childElements() {
|
|
1927
|
-
return this.childNodes.filter(
|
|
1954
|
+
return this.childNodes.filter(isElementNode);
|
|
1928
1955
|
}
|
|
1929
1956
|
/**
|
|
1930
1957
|
* Find the first ancestor matching a selector.
|
|
@@ -2185,8 +2212,9 @@ class HtmlElement extends DOMNode {
|
|
|
2185
2212
|
}, []);
|
|
2186
2213
|
}
|
|
2187
2214
|
querySelector(selector) {
|
|
2215
|
+
var _a;
|
|
2188
2216
|
const it = this.querySelectorImpl(selector);
|
|
2189
|
-
return it.next().value
|
|
2217
|
+
return (_a = it.next().value) !== null && _a !== void 0 ? _a : null; // eslint-disable-line @typescript-eslint/no-unsafe-return
|
|
2190
2218
|
}
|
|
2191
2219
|
querySelectorAll(selector) {
|
|
2192
2220
|
const it = this.querySelectorImpl(selector);
|
|
@@ -2753,8 +2781,6 @@ var configurationSchema = {
|
|
|
2753
2781
|
};
|
|
2754
2782
|
|
|
2755
2783
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2756
|
-
const espree = legacyRequire("espree");
|
|
2757
|
-
const walk = legacyRequire("acorn-walk");
|
|
2758
2784
|
function joinTemplateLiteral(nodes) {
|
|
2759
2785
|
let offset = nodes[0].start + 1;
|
|
2760
2786
|
let output = "";
|
|
@@ -2870,7 +2896,7 @@ class TemplateExtractor {
|
|
|
2870
2896
|
}
|
|
2871
2897
|
static fromFilename(filename) {
|
|
2872
2898
|
const source = fs__default["default"].readFileSync(filename, "utf-8");
|
|
2873
|
-
const ast =
|
|
2899
|
+
const ast = espree__namespace.parse(source, {
|
|
2874
2900
|
ecmaVersion: 2017,
|
|
2875
2901
|
sourceType: "module",
|
|
2876
2902
|
loc: true,
|
|
@@ -2889,7 +2915,7 @@ class TemplateExtractor {
|
|
|
2889
2915
|
* `Source`. Defauls to `"inline"`.
|
|
2890
2916
|
*/
|
|
2891
2917
|
static fromString(source, filename) {
|
|
2892
|
-
const ast =
|
|
2918
|
+
const ast = espree__namespace.parse(source, {
|
|
2893
2919
|
ecmaVersion: 2017,
|
|
2894
2920
|
sourceType: "module",
|
|
2895
2921
|
loc: true,
|
|
@@ -2935,7 +2961,8 @@ class TemplateExtractor {
|
|
|
2935
2961
|
extractObjectProperty(key) {
|
|
2936
2962
|
const result = [];
|
|
2937
2963
|
const { filename, data } = this;
|
|
2938
|
-
|
|
2964
|
+
const node = this.ast;
|
|
2965
|
+
walk__namespace.simple(node, {
|
|
2939
2966
|
Property(node) {
|
|
2940
2967
|
if (compareKey(node.key, key, filename)) {
|
|
2941
2968
|
const source = extractLiteral(node.value, filename, data);
|
|
@@ -2959,7 +2986,7 @@ var TRANSFORMER_API;
|
|
|
2959
2986
|
/** @public */
|
|
2960
2987
|
const name = "html-validate";
|
|
2961
2988
|
/** @public */
|
|
2962
|
-
const version = "6.
|
|
2989
|
+
const version = "6.7.0";
|
|
2963
2990
|
/** @public */
|
|
2964
2991
|
const homepage = "https://html-validate.org";
|
|
2965
2992
|
/** @public */
|
|
@@ -3280,7 +3307,7 @@ function ruleDocumentationUrl(filename) {
|
|
|
3280
3307
|
return `${homepage}/rules/${normalized}.html`;
|
|
3281
3308
|
}
|
|
3282
3309
|
|
|
3283
|
-
const defaults$
|
|
3310
|
+
const defaults$q = {
|
|
3284
3311
|
allowExternal: true,
|
|
3285
3312
|
allowRelative: true,
|
|
3286
3313
|
allowAbsolute: true,
|
|
@@ -3324,7 +3351,7 @@ function matchList(value, list) {
|
|
|
3324
3351
|
}
|
|
3325
3352
|
class AllowedLinks extends Rule {
|
|
3326
3353
|
constructor(options) {
|
|
3327
|
-
super({ ...defaults$
|
|
3354
|
+
super({ ...defaults$q, ...options });
|
|
3328
3355
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
3329
3356
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
3330
3357
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -3603,7 +3630,7 @@ class CaseStyle {
|
|
|
3603
3630
|
default: {
|
|
3604
3631
|
const last = names.slice(-1);
|
|
3605
3632
|
const rest = names.slice(0, -1);
|
|
3606
|
-
return `${rest.join(", ")} or ${last}`;
|
|
3633
|
+
return `${rest.join(", ")} or ${last[0]}`;
|
|
3607
3634
|
}
|
|
3608
3635
|
}
|
|
3609
3636
|
}
|
|
@@ -3619,19 +3646,19 @@ class CaseStyle {
|
|
|
3619
3646
|
case "camelcase":
|
|
3620
3647
|
return { pattern: /^[a-z][A-Za-z]*$/, name: "camelCase" };
|
|
3621
3648
|
default:
|
|
3622
|
-
throw new ConfigError(`Invalid style "${
|
|
3649
|
+
throw new ConfigError(`Invalid style "${cur}" for ${ruleId} rule`);
|
|
3623
3650
|
}
|
|
3624
3651
|
});
|
|
3625
3652
|
}
|
|
3626
3653
|
}
|
|
3627
3654
|
|
|
3628
|
-
const defaults$
|
|
3655
|
+
const defaults$p = {
|
|
3629
3656
|
style: "lowercase",
|
|
3630
3657
|
ignoreForeign: true,
|
|
3631
3658
|
};
|
|
3632
3659
|
class AttrCase extends Rule {
|
|
3633
3660
|
constructor(options) {
|
|
3634
|
-
super({ ...defaults$
|
|
3661
|
+
super({ ...defaults$p, ...options });
|
|
3635
3662
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
3636
3663
|
}
|
|
3637
3664
|
static schema() {
|
|
@@ -3658,8 +3685,11 @@ class AttrCase extends Rule {
|
|
|
3658
3685
|
};
|
|
3659
3686
|
}
|
|
3660
3687
|
documentation() {
|
|
3688
|
+
const { style } = this.options;
|
|
3661
3689
|
return {
|
|
3662
|
-
description:
|
|
3690
|
+
description: Array.isArray(style)
|
|
3691
|
+
? [`Attribute name must be in one of:`, "", ...style.map((it) => `- ${it}`)].join("\n")
|
|
3692
|
+
: `Attribute name must be in ${style}.`,
|
|
3663
3693
|
url: ruleDocumentationUrl("@/rules/attr-case.ts"),
|
|
3664
3694
|
};
|
|
3665
3695
|
}
|
|
@@ -3950,7 +3980,7 @@ function isRelevant$3(event) {
|
|
|
3950
3980
|
class AttrDelimiter extends Rule {
|
|
3951
3981
|
documentation() {
|
|
3952
3982
|
return {
|
|
3953
|
-
description: `Attribute value
|
|
3983
|
+
description: `Attribute value must not be separated by whitespace.`,
|
|
3954
3984
|
url: ruleDocumentationUrl("@/rules/attr-delimiter.ts"),
|
|
3955
3985
|
};
|
|
3956
3986
|
}
|
|
@@ -3967,7 +3997,7 @@ class AttrDelimiter extends Rule {
|
|
|
3967
3997
|
}
|
|
3968
3998
|
|
|
3969
3999
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
3970
|
-
const defaults$
|
|
4000
|
+
const defaults$o = {
|
|
3971
4001
|
pattern: DEFAULT_PATTERN,
|
|
3972
4002
|
ignoreForeign: true,
|
|
3973
4003
|
};
|
|
@@ -4004,7 +4034,7 @@ function generateDescription(name, pattern) {
|
|
|
4004
4034
|
}
|
|
4005
4035
|
class AttrPattern extends Rule {
|
|
4006
4036
|
constructor(options) {
|
|
4007
|
-
super({ ...defaults$
|
|
4037
|
+
super({ ...defaults$o, ...options });
|
|
4008
4038
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4009
4039
|
}
|
|
4010
4040
|
static schema() {
|
|
@@ -4064,13 +4094,13 @@ var QuoteStyle;
|
|
|
4064
4094
|
QuoteStyle["DOUBLE_QUOTE"] = "\"";
|
|
4065
4095
|
QuoteStyle["AUTO_QUOTE"] = "auto";
|
|
4066
4096
|
})(QuoteStyle || (QuoteStyle = {}));
|
|
4067
|
-
const defaults$
|
|
4097
|
+
const defaults$n = {
|
|
4068
4098
|
style: "auto",
|
|
4069
4099
|
unquoted: false,
|
|
4070
4100
|
};
|
|
4071
4101
|
class AttrQuotes extends Rule {
|
|
4072
4102
|
constructor(options) {
|
|
4073
|
-
super({ ...defaults$
|
|
4103
|
+
super({ ...defaults$n, ...options });
|
|
4074
4104
|
this.style = parseStyle$4(this.options.style);
|
|
4075
4105
|
}
|
|
4076
4106
|
static schema() {
|
|
@@ -4235,12 +4265,12 @@ class AttributeAllowedValues extends Rule {
|
|
|
4235
4265
|
}
|
|
4236
4266
|
}
|
|
4237
4267
|
|
|
4238
|
-
const defaults$
|
|
4268
|
+
const defaults$m = {
|
|
4239
4269
|
style: "omit",
|
|
4240
4270
|
};
|
|
4241
4271
|
class AttributeBooleanStyle extends Rule {
|
|
4242
4272
|
constructor(options) {
|
|
4243
|
-
super({ ...defaults$
|
|
4273
|
+
super({ ...defaults$m, ...options });
|
|
4244
4274
|
this.hasInvalidStyle = parseStyle$3(this.options.style);
|
|
4245
4275
|
}
|
|
4246
4276
|
static schema() {
|
|
@@ -4316,12 +4346,12 @@ function reportMessage$1(attr, style) {
|
|
|
4316
4346
|
return "";
|
|
4317
4347
|
}
|
|
4318
4348
|
|
|
4319
|
-
const defaults$
|
|
4349
|
+
const defaults$l = {
|
|
4320
4350
|
style: "omit",
|
|
4321
4351
|
};
|
|
4322
4352
|
class AttributeEmptyStyle extends Rule {
|
|
4323
4353
|
constructor(options) {
|
|
4324
|
-
super({ ...defaults$
|
|
4354
|
+
super({ ...defaults$l, ...options });
|
|
4325
4355
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
4326
4356
|
}
|
|
4327
4357
|
static schema() {
|
|
@@ -4429,12 +4459,12 @@ function describePattern(pattern) {
|
|
|
4429
4459
|
}
|
|
4430
4460
|
}
|
|
4431
4461
|
|
|
4432
|
-
const defaults$
|
|
4462
|
+
const defaults$k = {
|
|
4433
4463
|
pattern: "kebabcase",
|
|
4434
4464
|
};
|
|
4435
4465
|
class ClassPattern extends Rule {
|
|
4436
4466
|
constructor(options) {
|
|
4437
|
-
super({ ...defaults$
|
|
4467
|
+
super({ ...defaults$k, ...options });
|
|
4438
4468
|
this.pattern = parsePattern(this.options.pattern);
|
|
4439
4469
|
}
|
|
4440
4470
|
static schema() {
|
|
@@ -4460,7 +4490,9 @@ class ClassPattern extends Rule {
|
|
|
4460
4490
|
classes.forEach((cur, index) => {
|
|
4461
4491
|
if (!cur.match(this.pattern)) {
|
|
4462
4492
|
const location = classes.location(index);
|
|
4463
|
-
|
|
4493
|
+
const pattern = this.pattern.toString();
|
|
4494
|
+
const message = `Class "${cur}" does not match required pattern "${pattern}"`;
|
|
4495
|
+
this.report(event.target, message, location);
|
|
4464
4496
|
}
|
|
4465
4497
|
});
|
|
4466
4498
|
});
|
|
@@ -4541,13 +4573,13 @@ class CloseOrder extends Rule {
|
|
|
4541
4573
|
}
|
|
4542
4574
|
}
|
|
4543
4575
|
|
|
4544
|
-
const defaults$
|
|
4576
|
+
const defaults$j = {
|
|
4545
4577
|
include: null,
|
|
4546
4578
|
exclude: null,
|
|
4547
4579
|
};
|
|
4548
4580
|
class Deprecated extends Rule {
|
|
4549
4581
|
constructor(options) {
|
|
4550
|
-
super({ ...defaults$
|
|
4582
|
+
super({ ...defaults$j, ...options });
|
|
4551
4583
|
}
|
|
4552
4584
|
static schema() {
|
|
4553
4585
|
return {
|
|
@@ -4710,12 +4742,12 @@ class NoStyleTag$1 extends Rule {
|
|
|
4710
4742
|
}
|
|
4711
4743
|
}
|
|
4712
4744
|
|
|
4713
|
-
const defaults$
|
|
4745
|
+
const defaults$i = {
|
|
4714
4746
|
style: "uppercase",
|
|
4715
4747
|
};
|
|
4716
4748
|
class DoctypeStyle extends Rule {
|
|
4717
4749
|
constructor(options) {
|
|
4718
|
-
super({ ...defaults$
|
|
4750
|
+
super({ ...defaults$i, ...options });
|
|
4719
4751
|
}
|
|
4720
4752
|
static schema() {
|
|
4721
4753
|
return {
|
|
@@ -4747,12 +4779,12 @@ class DoctypeStyle extends Rule {
|
|
|
4747
4779
|
}
|
|
4748
4780
|
}
|
|
4749
4781
|
|
|
4750
|
-
const defaults$
|
|
4782
|
+
const defaults$h = {
|
|
4751
4783
|
style: "lowercase",
|
|
4752
4784
|
};
|
|
4753
4785
|
class ElementCase extends Rule {
|
|
4754
4786
|
constructor(options) {
|
|
4755
|
-
super({ ...defaults$
|
|
4787
|
+
super({ ...defaults$h, ...options });
|
|
4756
4788
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
4757
4789
|
}
|
|
4758
4790
|
static schema() {
|
|
@@ -4776,8 +4808,11 @@ class ElementCase extends Rule {
|
|
|
4776
4808
|
};
|
|
4777
4809
|
}
|
|
4778
4810
|
documentation() {
|
|
4811
|
+
const { style } = this.options;
|
|
4779
4812
|
return {
|
|
4780
|
-
description:
|
|
4813
|
+
description: Array.isArray(style)
|
|
4814
|
+
? [`Element tagname must be in one of:`, "", ...style.map((it) => `- ${it}`)].join("\n")
|
|
4815
|
+
: `Element tagname must be in ${style}.`,
|
|
4781
4816
|
url: ruleDocumentationUrl("@/rules/element-case.ts"),
|
|
4782
4817
|
};
|
|
4783
4818
|
}
|
|
@@ -4815,14 +4850,14 @@ class ElementCase extends Rule {
|
|
|
4815
4850
|
}
|
|
4816
4851
|
}
|
|
4817
4852
|
|
|
4818
|
-
const defaults$
|
|
4853
|
+
const defaults$g = {
|
|
4819
4854
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
4820
4855
|
whitelist: [],
|
|
4821
4856
|
blacklist: [],
|
|
4822
4857
|
};
|
|
4823
4858
|
class ElementName extends Rule {
|
|
4824
4859
|
constructor(options) {
|
|
4825
|
-
super({ ...defaults$
|
|
4860
|
+
super({ ...defaults$g, ...options });
|
|
4826
4861
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
4827
4862
|
this.pattern = new RegExp(this.options.pattern);
|
|
4828
4863
|
}
|
|
@@ -4863,7 +4898,7 @@ class ElementName extends Rule {
|
|
|
4863
4898
|
...context.blacklist.map((cur) => `- ${cur}`),
|
|
4864
4899
|
];
|
|
4865
4900
|
}
|
|
4866
|
-
if (context.pattern !== defaults$
|
|
4901
|
+
if (context.pattern !== defaults$g.pattern) {
|
|
4867
4902
|
return [
|
|
4868
4903
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
4869
4904
|
"",
|
|
@@ -5265,7 +5300,7 @@ class EmptyTitle extends Rule {
|
|
|
5265
5300
|
}
|
|
5266
5301
|
}
|
|
5267
5302
|
|
|
5268
|
-
const defaults$
|
|
5303
|
+
const defaults$f = {
|
|
5269
5304
|
allowMultipleH1: false,
|
|
5270
5305
|
minInitialRank: "h1",
|
|
5271
5306
|
sectioningRoots: ["dialog", '[role="dialog"]'],
|
|
@@ -5296,7 +5331,7 @@ function parseMaxInitial(value) {
|
|
|
5296
5331
|
}
|
|
5297
5332
|
class HeadingLevel extends Rule {
|
|
5298
5333
|
constructor(options) {
|
|
5299
|
-
super({ ...defaults$
|
|
5334
|
+
super({ ...defaults$f, ...options });
|
|
5300
5335
|
this.stack = [];
|
|
5301
5336
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
5302
5337
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
|
|
@@ -5454,12 +5489,12 @@ class HeadingLevel extends Rule {
|
|
|
5454
5489
|
}
|
|
5455
5490
|
}
|
|
5456
5491
|
|
|
5457
|
-
const defaults$
|
|
5492
|
+
const defaults$e = {
|
|
5458
5493
|
pattern: "kebabcase",
|
|
5459
5494
|
};
|
|
5460
5495
|
class IdPattern extends Rule {
|
|
5461
5496
|
constructor(options) {
|
|
5462
|
-
super({ ...defaults$
|
|
5497
|
+
super({ ...defaults$e, ...options });
|
|
5463
5498
|
this.pattern = parsePattern(this.options.pattern);
|
|
5464
5499
|
}
|
|
5465
5500
|
static schema() {
|
|
@@ -5478,6 +5513,7 @@ class IdPattern extends Rule {
|
|
|
5478
5513
|
}
|
|
5479
5514
|
setup() {
|
|
5480
5515
|
this.on("attr", (event) => {
|
|
5516
|
+
var _a;
|
|
5481
5517
|
if (event.key.toLowerCase() !== "id") {
|
|
5482
5518
|
return;
|
|
5483
5519
|
}
|
|
@@ -5486,7 +5522,10 @@ class IdPattern extends Rule {
|
|
|
5486
5522
|
return;
|
|
5487
5523
|
}
|
|
5488
5524
|
if (!event.value || !event.value.match(this.pattern)) {
|
|
5489
|
-
|
|
5525
|
+
const value = (_a = event.value) !== null && _a !== void 0 ? _a : "";
|
|
5526
|
+
const pattern = this.pattern.toString();
|
|
5527
|
+
const message = `ID "${value}" does not match required pattern "${pattern}"`;
|
|
5528
|
+
this.report(event.target, message, event.valueLocation);
|
|
5490
5529
|
}
|
|
5491
5530
|
});
|
|
5492
5531
|
}
|
|
@@ -5806,12 +5845,12 @@ function findLabelByParent(el) {
|
|
|
5806
5845
|
return [];
|
|
5807
5846
|
}
|
|
5808
5847
|
|
|
5809
|
-
const defaults$
|
|
5848
|
+
const defaults$d = {
|
|
5810
5849
|
maxlength: 70,
|
|
5811
5850
|
};
|
|
5812
5851
|
class LongTitle extends Rule {
|
|
5813
5852
|
constructor(options) {
|
|
5814
|
-
super({ ...defaults$
|
|
5853
|
+
super({ ...defaults$d, ...options });
|
|
5815
5854
|
this.maxlength = this.options.maxlength;
|
|
5816
5855
|
}
|
|
5817
5856
|
static schema() {
|
|
@@ -5958,13 +5997,13 @@ class MultipleLabeledControls extends Rule {
|
|
|
5958
5997
|
}
|
|
5959
5998
|
}
|
|
5960
5999
|
|
|
5961
|
-
const defaults$
|
|
6000
|
+
const defaults$c = {
|
|
5962
6001
|
include: null,
|
|
5963
6002
|
exclude: null,
|
|
5964
6003
|
};
|
|
5965
6004
|
class NoAutoplay extends Rule {
|
|
5966
6005
|
constructor(options) {
|
|
5967
|
-
super({ ...defaults$
|
|
6006
|
+
super({ ...defaults$c, ...options });
|
|
5968
6007
|
}
|
|
5969
6008
|
documentation(context) {
|
|
5970
6009
|
const tagName = context ? ` on <${context.tagName}>` : "";
|
|
@@ -6205,7 +6244,7 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
|
|
|
6205
6244
|
}
|
|
6206
6245
|
}
|
|
6207
6246
|
|
|
6208
|
-
const defaults$
|
|
6247
|
+
const defaults$b = {
|
|
6209
6248
|
include: null,
|
|
6210
6249
|
exclude: null,
|
|
6211
6250
|
allowedProperties: ["display"],
|
|
@@ -6222,7 +6261,7 @@ function getCSSDeclarations(value) {
|
|
|
6222
6261
|
}
|
|
6223
6262
|
class NoInlineStyle extends Rule {
|
|
6224
6263
|
constructor(options) {
|
|
6225
|
-
super({ ...defaults$
|
|
6264
|
+
super({ ...defaults$b, ...options });
|
|
6226
6265
|
}
|
|
6227
6266
|
static schema() {
|
|
6228
6267
|
return {
|
|
@@ -6427,24 +6466,24 @@ class NoMultipleMain extends Rule {
|
|
|
6427
6466
|
}
|
|
6428
6467
|
}
|
|
6429
6468
|
|
|
6430
|
-
const defaults$
|
|
6469
|
+
const defaults$a = {
|
|
6431
6470
|
relaxed: false,
|
|
6432
6471
|
};
|
|
6433
6472
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
6434
6473
|
const unquotedAttrRegexp = /([<>"'=`]|&(?![a-zA-Z0-9#]+;))/g;
|
|
6435
6474
|
const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
|
|
6436
|
-
const replacementTable =
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6475
|
+
const replacementTable = {
|
|
6476
|
+
'"': """,
|
|
6477
|
+
"&": "&",
|
|
6478
|
+
"'": "'",
|
|
6479
|
+
"<": "<",
|
|
6480
|
+
"=": "=",
|
|
6481
|
+
">": ">",
|
|
6482
|
+
"`": "`",
|
|
6483
|
+
};
|
|
6445
6484
|
class NoRawCharacters extends Rule {
|
|
6446
6485
|
constructor(options) {
|
|
6447
|
-
super({ ...defaults$
|
|
6486
|
+
super({ ...defaults$a, ...options });
|
|
6448
6487
|
this.relaxed = this.options.relaxed;
|
|
6449
6488
|
}
|
|
6450
6489
|
static schema() {
|
|
@@ -6494,7 +6533,6 @@ class NoRawCharacters extends Rule {
|
|
|
6494
6533
|
* @param text - The full text to find unescaped raw characters in.
|
|
6495
6534
|
* @param location - Location of text.
|
|
6496
6535
|
* @param regexp - Regexp pattern to match using.
|
|
6497
|
-
* @param ignore - List of characters to ignore for this text.
|
|
6498
6536
|
*/
|
|
6499
6537
|
findRawChars(node, text, location, regexp) {
|
|
6500
6538
|
let match;
|
|
@@ -6510,7 +6548,7 @@ class NoRawCharacters extends Rule {
|
|
|
6510
6548
|
continue;
|
|
6511
6549
|
}
|
|
6512
6550
|
/* determine replacement character and location */
|
|
6513
|
-
const replacement = replacementTable
|
|
6551
|
+
const replacement = replacementTable[char];
|
|
6514
6552
|
const charLocation = sliceLocation(location, match.index, match.index + 1);
|
|
6515
6553
|
/* report as error */
|
|
6516
6554
|
this.report(node, `Raw "${char}" must be encoded as "${replacement}"`, charLocation);
|
|
@@ -6623,13 +6661,13 @@ class NoRedundantRole extends Rule {
|
|
|
6623
6661
|
}
|
|
6624
6662
|
|
|
6625
6663
|
const xmlns = /^(.+):.+$/;
|
|
6626
|
-
const defaults$
|
|
6664
|
+
const defaults$9 = {
|
|
6627
6665
|
ignoreForeign: true,
|
|
6628
6666
|
ignoreXML: true,
|
|
6629
6667
|
};
|
|
6630
6668
|
class NoSelfClosing extends Rule {
|
|
6631
6669
|
constructor(options) {
|
|
6632
|
-
super({ ...defaults$
|
|
6670
|
+
super({ ...defaults$9, ...options });
|
|
6633
6671
|
}
|
|
6634
6672
|
static schema() {
|
|
6635
6673
|
return {
|
|
@@ -6762,13 +6800,13 @@ const replacement = {
|
|
|
6762
6800
|
reset: '<button type="reset">',
|
|
6763
6801
|
image: '<button type="button">',
|
|
6764
6802
|
};
|
|
6765
|
-
const defaults$
|
|
6803
|
+
const defaults$8 = {
|
|
6766
6804
|
include: null,
|
|
6767
6805
|
exclude: null,
|
|
6768
6806
|
};
|
|
6769
6807
|
class PreferButton extends Rule {
|
|
6770
6808
|
constructor(options) {
|
|
6771
|
-
super({ ...defaults$
|
|
6809
|
+
super({ ...defaults$8, ...options });
|
|
6772
6810
|
}
|
|
6773
6811
|
static schema() {
|
|
6774
6812
|
return {
|
|
@@ -6843,7 +6881,7 @@ class PreferButton extends Rule {
|
|
|
6843
6881
|
}
|
|
6844
6882
|
}
|
|
6845
6883
|
|
|
6846
|
-
const defaults$
|
|
6884
|
+
const defaults$7 = {
|
|
6847
6885
|
mapping: {
|
|
6848
6886
|
article: "article",
|
|
6849
6887
|
banner: "header",
|
|
@@ -6873,7 +6911,7 @@ const defaults$6 = {
|
|
|
6873
6911
|
};
|
|
6874
6912
|
class PreferNativeElement extends Rule {
|
|
6875
6913
|
constructor(options) {
|
|
6876
|
-
super({ ...defaults$
|
|
6914
|
+
super({ ...defaults$7, ...options });
|
|
6877
6915
|
}
|
|
6878
6916
|
static schema() {
|
|
6879
6917
|
return {
|
|
@@ -6993,7 +7031,7 @@ class PreferTbody extends Rule {
|
|
|
6993
7031
|
}
|
|
6994
7032
|
}
|
|
6995
7033
|
|
|
6996
|
-
const defaults$
|
|
7034
|
+
const defaults$6 = {
|
|
6997
7035
|
target: "all",
|
|
6998
7036
|
};
|
|
6999
7037
|
const crossorigin = new RegExp("^(\\w+://|//)"); /* e.g. https:// or // */
|
|
@@ -7003,7 +7041,7 @@ const supportSri = {
|
|
|
7003
7041
|
};
|
|
7004
7042
|
class RequireSri extends Rule {
|
|
7005
7043
|
constructor(options) {
|
|
7006
|
-
super({ ...defaults$
|
|
7044
|
+
super({ ...defaults$6, ...options });
|
|
7007
7045
|
this.target = this.options.target;
|
|
7008
7046
|
}
|
|
7009
7047
|
static schema() {
|
|
@@ -7131,6 +7169,155 @@ class SvgFocusable extends Rule {
|
|
|
7131
7169
|
}
|
|
7132
7170
|
}
|
|
7133
7171
|
|
|
7172
|
+
const defaults$5 = {
|
|
7173
|
+
characters: [
|
|
7174
|
+
{ pattern: " ", replacement: " ", description: "non-breaking space" },
|
|
7175
|
+
{ pattern: "-", replacement: "‑", description: "non-breaking hyphen" },
|
|
7176
|
+
],
|
|
7177
|
+
ignoreClasses: [],
|
|
7178
|
+
};
|
|
7179
|
+
function constructRegex(characters) {
|
|
7180
|
+
const disallowed = characters
|
|
7181
|
+
.map((it) => {
|
|
7182
|
+
return it.pattern;
|
|
7183
|
+
})
|
|
7184
|
+
.join("|");
|
|
7185
|
+
const pattern = `(${disallowed})`;
|
|
7186
|
+
/* eslint-disable-next-line security/detect-non-literal-regexp */
|
|
7187
|
+
return new RegExp(pattern, "g");
|
|
7188
|
+
}
|
|
7189
|
+
function getText(node) {
|
|
7190
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
|
7191
|
+
const match = node.textContent.match(/^(\s*)(.*)$/);
|
|
7192
|
+
const [, leading, text] = match;
|
|
7193
|
+
return [leading.length, text.trimEnd()];
|
|
7194
|
+
}
|
|
7195
|
+
/**
|
|
7196
|
+
* Node 12 does not support String.matchAll, this simulates it's behavior.
|
|
7197
|
+
*/
|
|
7198
|
+
function matchAll(text, regexp) {
|
|
7199
|
+
/* eslint-disable-next-line security/detect-non-literal-regexp */
|
|
7200
|
+
const copy = new RegExp(regexp);
|
|
7201
|
+
const matches = [];
|
|
7202
|
+
/* eslint-disable-next-line no-constant-condition */
|
|
7203
|
+
while (true) {
|
|
7204
|
+
const match = copy.exec(text);
|
|
7205
|
+
if (match === null) {
|
|
7206
|
+
break;
|
|
7207
|
+
}
|
|
7208
|
+
matches.push(match);
|
|
7209
|
+
}
|
|
7210
|
+
return matches;
|
|
7211
|
+
}
|
|
7212
|
+
class TelNonBreaking extends Rule {
|
|
7213
|
+
constructor(options) {
|
|
7214
|
+
super({ ...defaults$5, ...options });
|
|
7215
|
+
this.regex = constructRegex(this.options.characters);
|
|
7216
|
+
}
|
|
7217
|
+
static schema() {
|
|
7218
|
+
return {
|
|
7219
|
+
characters: {
|
|
7220
|
+
type: "array",
|
|
7221
|
+
items: {
|
|
7222
|
+
type: "object",
|
|
7223
|
+
additionalProperties: false,
|
|
7224
|
+
properties: {
|
|
7225
|
+
pattern: {
|
|
7226
|
+
type: "string",
|
|
7227
|
+
},
|
|
7228
|
+
replacement: {
|
|
7229
|
+
type: "string",
|
|
7230
|
+
},
|
|
7231
|
+
description: {
|
|
7232
|
+
type: "string",
|
|
7233
|
+
},
|
|
7234
|
+
},
|
|
7235
|
+
},
|
|
7236
|
+
},
|
|
7237
|
+
ignoreClasses: {
|
|
7238
|
+
type: "array",
|
|
7239
|
+
items: {
|
|
7240
|
+
type: "string",
|
|
7241
|
+
},
|
|
7242
|
+
},
|
|
7243
|
+
};
|
|
7244
|
+
}
|
|
7245
|
+
documentation(context) {
|
|
7246
|
+
const { characters } = this.options;
|
|
7247
|
+
const replacements = characters.map((it) => {
|
|
7248
|
+
return ` - \`${it.pattern}\` - replace with \`${it.replacement}\` (${it.description}).`;
|
|
7249
|
+
});
|
|
7250
|
+
return {
|
|
7251
|
+
description: [
|
|
7252
|
+
context
|
|
7253
|
+
? `The \`${context.pattern}\` character should be replaced with \`${context.replacement}\` character (${context.description}) when used in a telephone number.`
|
|
7254
|
+
: `Replace this character with a non-breaking version.`,
|
|
7255
|
+
"",
|
|
7256
|
+
"Unless non-breaking characters is used there could be a line break inserted at that character.",
|
|
7257
|
+
"Line breaks make is harder to read and understand the telephone number.",
|
|
7258
|
+
"",
|
|
7259
|
+
"The following characters should be avoided:",
|
|
7260
|
+
"",
|
|
7261
|
+
...replacements,
|
|
7262
|
+
].join("\n"),
|
|
7263
|
+
url: ruleDocumentationUrl("@/rules/tel-non-breaking.ts"),
|
|
7264
|
+
};
|
|
7265
|
+
}
|
|
7266
|
+
setup() {
|
|
7267
|
+
this.on("element:ready", this.isRelevant, (event) => {
|
|
7268
|
+
const { target } = event;
|
|
7269
|
+
const { ignoreClasses } = this.options;
|
|
7270
|
+
/* skip if element has a class in the ignore list */
|
|
7271
|
+
const isIgnored = ignoreClasses.some((it) => target.classList.contains(it));
|
|
7272
|
+
if (isIgnored) {
|
|
7273
|
+
return;
|
|
7274
|
+
}
|
|
7275
|
+
this.walk(target);
|
|
7276
|
+
});
|
|
7277
|
+
}
|
|
7278
|
+
isRelevant(event) {
|
|
7279
|
+
const { target } = event;
|
|
7280
|
+
/* should only deal with anchors */
|
|
7281
|
+
if (!target.is("a")) {
|
|
7282
|
+
return false;
|
|
7283
|
+
}
|
|
7284
|
+
/* ignore if anchor does not have tel href */
|
|
7285
|
+
const attr = target.getAttribute("href");
|
|
7286
|
+
if (!attr || !attr.valueMatches(/^tel:/, false)) {
|
|
7287
|
+
return false;
|
|
7288
|
+
}
|
|
7289
|
+
return true;
|
|
7290
|
+
}
|
|
7291
|
+
walk(node) {
|
|
7292
|
+
for (const child of node.childNodes) {
|
|
7293
|
+
if (isTextNode(child)) {
|
|
7294
|
+
this.detectDisallowed(child);
|
|
7295
|
+
}
|
|
7296
|
+
else if (isElementNode(child)) {
|
|
7297
|
+
this.walk(child);
|
|
7298
|
+
}
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
detectDisallowed(node) {
|
|
7302
|
+
const [offset, text] = getText(node);
|
|
7303
|
+
const matches = matchAll(text, this.regex);
|
|
7304
|
+
for (const match of matches) {
|
|
7305
|
+
const detected = match[0];
|
|
7306
|
+
const entry = this.options.characters.find((it) => it.pattern === detected);
|
|
7307
|
+
/* istanbul ignore next: should never happen and cannot be tested, just a sanity check */
|
|
7308
|
+
if (!entry) {
|
|
7309
|
+
throw new Error(`Failed to find entry for "${detected}" when searching text "${text}"`);
|
|
7310
|
+
}
|
|
7311
|
+
const message = `"${detected}" should be replaced with "${entry.replacement}" in telephone number`;
|
|
7312
|
+
const begin = offset + match.index;
|
|
7313
|
+
const end = begin + detected.length;
|
|
7314
|
+
const location = sliceLocation(node.location, begin, end);
|
|
7315
|
+
const context = entry;
|
|
7316
|
+
this.report(node, message, location, context);
|
|
7317
|
+
}
|
|
7318
|
+
}
|
|
7319
|
+
}
|
|
7320
|
+
|
|
7134
7321
|
function hasAltText(image) {
|
|
7135
7322
|
const alt = image.getAttribute("alt");
|
|
7136
7323
|
/* missing or boolean */
|
|
@@ -9161,9 +9348,6 @@ function parseStyle$1(name) {
|
|
|
9161
9348
|
case "selfclose":
|
|
9162
9349
|
case "selfclosing":
|
|
9163
9350
|
return Style$1.AlwaysSelfclose;
|
|
9164
|
-
/* istanbul ignore next: covered by schema validation */
|
|
9165
|
-
default:
|
|
9166
|
-
throw new Error(`Invalid style "${name}" for "void" rule`);
|
|
9167
9351
|
}
|
|
9168
9352
|
}
|
|
9169
9353
|
|
|
@@ -9595,6 +9779,7 @@ const bundledRules = {
|
|
|
9595
9779
|
"script-element": ScriptElement,
|
|
9596
9780
|
"script-type": ScriptType,
|
|
9597
9781
|
"svg-focusable": SvgFocusable,
|
|
9782
|
+
"tel-non-breaking": TelNonBreaking,
|
|
9598
9783
|
"text-content": TextContent,
|
|
9599
9784
|
"unrecognized-char-ref": UnknownCharReference,
|
|
9600
9785
|
void: Void,
|
|
@@ -9691,6 +9876,7 @@ const config$1 = {
|
|
|
9691
9876
|
"script-element": "error",
|
|
9692
9877
|
"script-type": "error",
|
|
9693
9878
|
"svg-focusable": "off",
|
|
9879
|
+
"tel-non-breaking": "error",
|
|
9694
9880
|
"text-content": "error",
|
|
9695
9881
|
"unrecognized-char-ref": "error",
|
|
9696
9882
|
void: "off",
|
|
@@ -9796,7 +9982,8 @@ class ResolvedConfig {
|
|
|
9796
9982
|
});
|
|
9797
9983
|
}
|
|
9798
9984
|
catch (err) {
|
|
9799
|
-
|
|
9985
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9986
|
+
throw new NestedError(`When transforming "${source.filename}": ${message}`, err);
|
|
9800
9987
|
}
|
|
9801
9988
|
}
|
|
9802
9989
|
else {
|
|
@@ -9872,9 +10059,10 @@ function loadFromFile(filename) {
|
|
|
9872
10059
|
}
|
|
9873
10060
|
/* expand any relative paths */
|
|
9874
10061
|
for (const key of ["extends", "elements", "plugins"]) {
|
|
9875
|
-
|
|
10062
|
+
const value = json[key];
|
|
10063
|
+
if (!value)
|
|
9876
10064
|
continue;
|
|
9877
|
-
json[key] =
|
|
10065
|
+
json[key] = value.map((ref) => {
|
|
9878
10066
|
return Config.expandRelative(ref, path__default["default"].dirname(filename));
|
|
9879
10067
|
});
|
|
9880
10068
|
}
|
|
@@ -10032,6 +10220,7 @@ class Config {
|
|
|
10032
10220
|
/**
|
|
10033
10221
|
* Get element metadata.
|
|
10034
10222
|
*/
|
|
10223
|
+
/* eslint-disable-next-line complexity, sonarjs/cognitive-complexity */
|
|
10035
10224
|
getMetaTable() {
|
|
10036
10225
|
/* use cached table if it exists */
|
|
10037
10226
|
if (this.metaTable) {
|
|
@@ -10070,7 +10259,8 @@ class Config {
|
|
|
10070
10259
|
metaTable.loadFromObject(legacyRequire(entry));
|
|
10071
10260
|
}
|
|
10072
10261
|
catch (err) {
|
|
10073
|
-
|
|
10262
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10263
|
+
throw new ConfigError(`Failed to load elements from "${entry}": ${message}`, err);
|
|
10074
10264
|
}
|
|
10075
10265
|
}
|
|
10076
10266
|
metaTable.init();
|
|
@@ -10146,7 +10336,8 @@ class Config {
|
|
|
10146
10336
|
return plugin;
|
|
10147
10337
|
}
|
|
10148
10338
|
catch (err) {
|
|
10149
|
-
|
|
10339
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10340
|
+
throw new ConfigError(`Failed to load plugin "${moduleName}": ${message}`, err);
|
|
10150
10341
|
}
|
|
10151
10342
|
});
|
|
10152
10343
|
}
|
|
@@ -11150,7 +11341,7 @@ class Engine {
|
|
|
11150
11341
|
/**
|
|
11151
11342
|
* Lint sources and return report
|
|
11152
11343
|
*
|
|
11153
|
-
* @param
|
|
11344
|
+
* @param sources - Sources to lint.
|
|
11154
11345
|
* @returns Report output.
|
|
11155
11346
|
*/
|
|
11156
11347
|
lint(sources) {
|
|
@@ -11244,7 +11435,7 @@ class Engine {
|
|
|
11244
11435
|
const lines = [];
|
|
11245
11436
|
function decoration(node) {
|
|
11246
11437
|
let output = "";
|
|
11247
|
-
if (node.
|
|
11438
|
+
if (node.id) {
|
|
11248
11439
|
output += `#${node.id}`;
|
|
11249
11440
|
}
|
|
11250
11441
|
if (node.hasAttribute("class")) {
|