html-validate 10.1.0 → 10.1.2

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.
Files changed (42) hide show
  1. package/dist/cjs/cli.js +200 -202
  2. package/dist/cjs/cli.js.map +1 -1
  3. package/dist/cjs/core-browser.js.map +1 -1
  4. package/dist/cjs/core-nodejs.js.map +1 -1
  5. package/dist/cjs/core.js +370 -315
  6. package/dist/cjs/core.js.map +1 -1
  7. package/dist/cjs/html-validate.js +1 -2
  8. package/dist/cjs/html-validate.js.map +1 -1
  9. package/dist/cjs/index.js +0 -1
  10. package/dist/cjs/index.js.map +1 -1
  11. package/dist/cjs/jest.js +1 -1
  12. package/dist/cjs/jest.js.map +1 -1
  13. package/dist/cjs/matchers-jestonly.js +1 -1
  14. package/dist/cjs/matchers-jestonly.js.map +1 -1
  15. package/dist/cjs/matchers.js.map +1 -1
  16. package/dist/cjs/test-utils.js +2 -2
  17. package/dist/cjs/test-utils.js.map +2 -2
  18. package/dist/cjs/tsdoc-metadata.json +1 -1
  19. package/dist/cjs/vitest.js.map +1 -1
  20. package/dist/esm/browser.js +1 -1
  21. package/dist/esm/cli.js +200 -201
  22. package/dist/esm/cli.js.map +1 -1
  23. package/dist/esm/core-browser.js.map +1 -1
  24. package/dist/esm/core-nodejs.js.map +1 -1
  25. package/dist/esm/core.js +371 -316
  26. package/dist/esm/core.js.map +1 -1
  27. package/dist/esm/html-validate.js +1 -2
  28. package/dist/esm/html-validate.js.map +1 -1
  29. package/dist/esm/index.js +1 -2
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/jest.js +1 -1
  32. package/dist/esm/jest.js.map +1 -1
  33. package/dist/esm/matchers-jestonly.js +1 -1
  34. package/dist/esm/matchers-jestonly.js.map +1 -1
  35. package/dist/esm/matchers.js.map +1 -1
  36. package/dist/esm/test-utils.js +1 -1
  37. package/dist/esm/test-utils.js.map +1 -1
  38. package/dist/esm/vitest.js.map +1 -1
  39. package/dist/tsdoc-metadata.json +1 -1
  40. package/dist/types/browser.d.ts +1 -0
  41. package/dist/types/index.d.ts +1 -0
  42. package/package.json +1 -1
package/dist/cjs/core.js CHANGED
@@ -505,27 +505,6 @@ class SchemaValidationError extends UserError {
505
505
  }
506
506
  }
507
507
 
508
- function cyrb53(str) {
509
- const a = 2654435761;
510
- const b = 1597334677;
511
- const c = 2246822507;
512
- const d = 3266489909;
513
- const e = 4294967296;
514
- const f = 2097151;
515
- const seed = 0;
516
- let h1 = 3735928559 ^ seed;
517
- let h2 = 1103547991 ^ seed;
518
- for (let i = 0, ch; i < str.length; i++) {
519
- ch = str.charCodeAt(i);
520
- h1 = Math.imul(h1 ^ ch, a);
521
- h2 = Math.imul(h2 ^ ch, b);
522
- }
523
- h1 = Math.imul(h1 ^ h1 >>> 16, c) ^ Math.imul(h2 ^ h2 >>> 13, d);
524
- h2 = Math.imul(h2 ^ h2 >>> 16, c) ^ Math.imul(h1 ^ h1 >>> 13, d);
525
- return e * (f & h2) + (h1 >>> 0);
526
- }
527
- const computeHash = cyrb53;
528
-
529
508
  const $schema$1 = "http://json-schema.org/draft-06/schema#";
530
509
  const $id$1 = "https://html-validate.org/schemas/elements.json";
531
510
  const type$1 = "object";
@@ -1001,6 +980,27 @@ const ajvFunctionKeyword = {
1001
980
  validate: ajvFunctionValidate
1002
981
  };
1003
982
 
983
+ function cyrb53(str) {
984
+ const a = 2654435761;
985
+ const b = 1597334677;
986
+ const c = 2246822507;
987
+ const d = 3266489909;
988
+ const e = 4294967296;
989
+ const f = 2097151;
990
+ const seed = 0;
991
+ let h1 = 3735928559 ^ seed;
992
+ let h2 = 1103547991 ^ seed;
993
+ for (let i = 0, ch; i < str.length; i++) {
994
+ ch = str.charCodeAt(i);
995
+ h1 = Math.imul(h1 ^ ch, a);
996
+ h2 = Math.imul(h2 ^ ch, b);
997
+ }
998
+ h1 = Math.imul(h1 ^ h1 >>> 16, c) ^ Math.imul(h2 ^ h2 >>> 13, d);
999
+ h2 = Math.imul(h2 ^ h2 >>> 16, c) ^ Math.imul(h1 ^ h1 >>> 13, d);
1000
+ return e * (f & h2) + (h1 >>> 0);
1001
+ }
1002
+ const computeHash = cyrb53;
1003
+
1004
1004
  var TextContent$1 = /* @__PURE__ */ ((TextContent2) => {
1005
1005
  TextContent2["NONE"] = "none";
1006
1006
  TextContent2["DEFAULT"] = "default";
@@ -1601,7 +1601,6 @@ class DOMNode {
1601
1601
  * @internal
1602
1602
  */
1603
1603
  unique;
1604
- /* eslint-disable-next-line sonarjs/use-type-alias -- technical debt */
1605
1604
  cache;
1606
1605
  /**
1607
1606
  * Set of disabled rules for this node.
@@ -1641,8 +1640,8 @@ class DOMNode {
1641
1640
  *
1642
1641
  * @internal
1643
1642
  */
1644
- cacheEnable() {
1645
- this.cache = /* @__PURE__ */ new Map();
1643
+ cacheEnable(enable = true) {
1644
+ this.cache = enable ? /* @__PURE__ */ new Map() : null;
1646
1645
  }
1647
1646
  cacheGet(key) {
1648
1647
  if (this.cache) {
@@ -2761,6 +2760,22 @@ class HtmlElement extends DOMNode {
2761
2760
  }
2762
2761
  return this.cacheSet(TABINDEX, parsed);
2763
2762
  }
2763
+ /**
2764
+ * Read-only property with the type of the text content of this
2765
+ * element.
2766
+ *
2767
+ * @internal
2768
+ */
2769
+ get textType() {
2770
+ const tagName = this.tagName.toLowerCase();
2771
+ if (tagName === "script") {
2772
+ return "script";
2773
+ } else if (tagName === "style") {
2774
+ return "css";
2775
+ } else {
2776
+ return "text";
2777
+ }
2778
+ }
2764
2779
  /**
2765
2780
  * Get a list of all attributes on this node.
2766
2781
  */
@@ -3313,172 +3328,6 @@ function parseQuantifier(quantifier) {
3313
3328
  }
3314
3329
  }
3315
3330
 
3316
- const $schema = "http://json-schema.org/draft-06/schema#";
3317
- const $id = "https://html-validate.org/schemas/config.json";
3318
- const type = "object";
3319
- const additionalProperties = false;
3320
- const properties = {
3321
- $schema: {
3322
- type: "string"
3323
- },
3324
- root: {
3325
- type: "boolean",
3326
- title: "Mark as root configuration",
3327
- description: "If this is set to true no further configurations will be searched.",
3328
- "default": false
3329
- },
3330
- "extends": {
3331
- type: "array",
3332
- items: {
3333
- type: "string"
3334
- },
3335
- title: "Configurations to extend",
3336
- description: "Array of shareable or builtin configurations to extend."
3337
- },
3338
- elements: {
3339
- type: "array",
3340
- items: {
3341
- anyOf: [
3342
- {
3343
- type: "string"
3344
- },
3345
- {
3346
- type: "object"
3347
- }
3348
- ]
3349
- },
3350
- title: "Element metadata to load",
3351
- description: "Array of modules, plugins or files to load element metadata from. Use <rootDir> to refer to the folder with the package.json file.",
3352
- examples: [
3353
- [
3354
- "html-validate:recommended",
3355
- "plugin:recommended",
3356
- "module",
3357
- "./local-file.json"
3358
- ]
3359
- ]
3360
- },
3361
- plugins: {
3362
- type: "array",
3363
- items: {
3364
- anyOf: [
3365
- {
3366
- type: "string"
3367
- },
3368
- {
3369
- type: "object"
3370
- }
3371
- ]
3372
- },
3373
- title: "Plugins to load",
3374
- description: "Array of plugins load. Use <rootDir> to refer to the folder with the package.json file.",
3375
- examples: [
3376
- [
3377
- "my-plugin",
3378
- "./local-plugin"
3379
- ]
3380
- ]
3381
- },
3382
- transform: {
3383
- type: "object",
3384
- additionalProperties: {
3385
- anyOf: [
3386
- {
3387
- type: "string"
3388
- },
3389
- {
3390
- "function": true
3391
- }
3392
- ]
3393
- },
3394
- title: "File transformations to use.",
3395
- description: "Object where key is regular expression to match filename and value is name of transformer or a function.",
3396
- examples: [
3397
- {
3398
- "^.*\\.foo$": "my-transformer",
3399
- "^.*\\.bar$": "my-plugin",
3400
- "^.*\\.baz$": "my-plugin:named"
3401
- }
3402
- ]
3403
- },
3404
- rules: {
3405
- type: "object",
3406
- patternProperties: {
3407
- ".*": {
3408
- anyOf: [
3409
- {
3410
- "enum": [
3411
- 0,
3412
- 1,
3413
- 2,
3414
- "off",
3415
- "warn",
3416
- "error"
3417
- ]
3418
- },
3419
- {
3420
- type: "array",
3421
- minItems: 1,
3422
- maxItems: 1,
3423
- items: [
3424
- {
3425
- "enum": [
3426
- 0,
3427
- 1,
3428
- 2,
3429
- "off",
3430
- "warn",
3431
- "error"
3432
- ]
3433
- }
3434
- ]
3435
- },
3436
- {
3437
- type: "array",
3438
- minItems: 2,
3439
- maxItems: 2,
3440
- items: [
3441
- {
3442
- "enum": [
3443
- 0,
3444
- 1,
3445
- 2,
3446
- "off",
3447
- "warn",
3448
- "error"
3449
- ]
3450
- },
3451
- {
3452
- }
3453
- ]
3454
- }
3455
- ]
3456
- }
3457
- },
3458
- title: "Rule configuration.",
3459
- description: "Enable/disable rules, set severity. Some rules have additional configuration like style or patterns to use.",
3460
- examples: [
3461
- {
3462
- foo: "error",
3463
- bar: "off",
3464
- baz: [
3465
- "error",
3466
- {
3467
- style: "camelcase"
3468
- }
3469
- ]
3470
- }
3471
- ]
3472
- }
3473
- };
3474
- var configurationSchema = {
3475
- $schema: $schema,
3476
- $id: $id,
3477
- type: type,
3478
- additionalProperties: additionalProperties,
3479
- properties: properties
3480
- };
3481
-
3482
3331
  var Severity = /* @__PURE__ */ ((Severity2) => {
3483
3332
  Severity2[Severity2["DISABLED"] = 0] = "DISABLED";
3484
3333
  Severity2[Severity2["WARN"] = 1] = "WARN";
@@ -3501,35 +3350,6 @@ function parseSeverity(value) {
3501
3350
  }
3502
3351
  }
3503
3352
 
3504
- function escape(value) {
3505
- return JSON.stringify(value);
3506
- }
3507
- function format(value, quote = false) {
3508
- if (value === null || value === void 0) {
3509
- return "null";
3510
- }
3511
- if (typeof value === "number") {
3512
- return value.toString();
3513
- }
3514
- if (typeof value === "string") {
3515
- return quote ? escape(value) : value;
3516
- }
3517
- if (Array.isArray(value)) {
3518
- const content = value.map((it) => format(it, true)).join(", ");
3519
- return `[ ${content} ]`;
3520
- }
3521
- if (typeof value === "object") {
3522
- const content = Object.entries(value).map(([key, nested]) => `${key}: ${format(nested, true)}`).join(", ");
3523
- return `{ ${content} }`;
3524
- }
3525
- return String(value);
3526
- }
3527
- function interpolate(text, data) {
3528
- return text.replace(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3529
- return typeof data[key] !== "undefined" ? format(data[key]) : match;
3530
- });
3531
- }
3532
-
3533
3353
  const cacheKey = Symbol("aria-naming");
3534
3354
  const defaultValue = "allowed";
3535
3355
  const prohibitedRoles = [
@@ -3571,6 +3391,31 @@ function ariaNaming(element) {
3571
3391
  return element.cacheSet(cacheKey, byMeta(element, meta));
3572
3392
  }
3573
3393
 
3394
+ const INPUT_DISABLED_CACHE = Symbol(isInputDisabled.name);
3395
+ function isInputDisabled(node, details) {
3396
+ const cached = node.cacheGet(INPUT_DISABLED_CACHE);
3397
+ if (cached) {
3398
+ return details ? cached : cached.byFieldset || cached.bySelf;
3399
+ }
3400
+ const result = node.cacheSet(INPUT_DISABLED_CACHE, isInputDisabledImpl(node));
3401
+ return details ? result : result.byFieldset || result.bySelf;
3402
+ }
3403
+ function isInputDisabledImpl(node) {
3404
+ const hasDisabledAttr = (node2) => {
3405
+ const disabled = node2.getAttribute("disabled");
3406
+ return Boolean(disabled?.isStatic);
3407
+ };
3408
+ const hasDisabledFieldset = (node2) => {
3409
+ const fieldset = node2.closest("fieldset[disabled]");
3410
+ const disabled = fieldset?.getAttribute("disabled");
3411
+ return Boolean(disabled?.isStatic);
3412
+ };
3413
+ return {
3414
+ byFieldset: hasDisabledFieldset(node),
3415
+ bySelf: hasDisabledAttr(node)
3416
+ };
3417
+ }
3418
+
3574
3419
  const patternCache = /* @__PURE__ */ new Map();
3575
3420
  function compileStringPattern(pattern) {
3576
3421
  const regexp = pattern.replace(/[*]+/g, ".+");
@@ -3824,6 +3669,35 @@ function partition(values, predicate) {
3824
3669
  }, initial);
3825
3670
  }
3826
3671
 
3672
+ function escape(value) {
3673
+ return JSON.stringify(value);
3674
+ }
3675
+ function format(value, quote = false) {
3676
+ if (value === null || value === void 0) {
3677
+ return "null";
3678
+ }
3679
+ if (typeof value === "number") {
3680
+ return value.toString();
3681
+ }
3682
+ if (typeof value === "string") {
3683
+ return quote ? escape(value) : value;
3684
+ }
3685
+ if (Array.isArray(value)) {
3686
+ const content = value.map((it) => format(it, true)).join(", ");
3687
+ return `[ ${content} ]`;
3688
+ }
3689
+ if (typeof value === "object") {
3690
+ const content = Object.entries(value).map(([key, nested]) => `${key}: ${format(nested, true)}`).join(", ");
3691
+ return `{ ${content} }`;
3692
+ }
3693
+ return String(value);
3694
+ }
3695
+ function interpolate(text, data) {
3696
+ return text.replace(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3697
+ return typeof data[key] !== "undefined" ? format(data[key]) : match;
3698
+ });
3699
+ }
3700
+
3827
3701
  const ajv$1 = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
3828
3702
  ajv$1.addMetaSchema(ajvSchemaDraft);
3829
3703
  function getSchemaValidator(ruleId, properties) {
@@ -6512,6 +6386,18 @@ const defaults$l = {
6512
6386
  };
6513
6387
  const UNIQUE_CACHE_KEY = Symbol("form-elements-unique");
6514
6388
  const SHARED_CACHE_KEY = Symbol("form-elements-shared");
6389
+ function isEnabled(element) {
6390
+ if (isHTMLHidden(element)) {
6391
+ return false;
6392
+ }
6393
+ if (isInert(element)) {
6394
+ return false;
6395
+ }
6396
+ if (isInputDisabled(element)) {
6397
+ return false;
6398
+ }
6399
+ return true;
6400
+ }
6515
6401
  function haveName(name) {
6516
6402
  return typeof name === "string" && name !== "";
6517
6403
  }
@@ -6582,7 +6468,7 @@ class FormDupName extends Rule {
6582
6468
  const { shared } = this.options;
6583
6469
  this.on("dom:ready", (event) => {
6584
6470
  const { document } = event;
6585
- const controls = document.querySelectorAll(selector);
6471
+ const controls = document.querySelectorAll(selector).filter(isEnabled);
6586
6472
  const [sharedControls, uniqueControls] = partition(controls, (it) => {
6587
6473
  return allowSharedName(it, shared);
6588
6474
  });
@@ -7338,69 +7224,6 @@ class LongTitle extends Rule {
7338
7224
  }
7339
7225
  }
7340
7226
 
7341
- const defaults$h = {
7342
- allowLongDelay: false
7343
- };
7344
- class MetaRefresh extends Rule {
7345
- constructor(options) {
7346
- super({ ...defaults$h, ...options });
7347
- }
7348
- documentation() {
7349
- return {
7350
- description: `Meta refresh directive must use the \`0;url=...\` format. Non-zero values for time interval is disallowed as people with assistive technology might be unable to read and understand the page content before automatically reloading. For the same reason skipping the url is disallowed as it would put the browser in an infinite loop reloading the same page over and over again.`,
7351
- url: "https://html-validate.org/rules/meta-refresh.html"
7352
- };
7353
- }
7354
- setup() {
7355
- this.on("element:ready", ({ target }) => {
7356
- if (!target.is("meta")) {
7357
- return;
7358
- }
7359
- const httpEquiv = target.getAttributeValue("http-equiv");
7360
- if (httpEquiv !== "refresh") {
7361
- return;
7362
- }
7363
- const content = target.getAttribute("content");
7364
- if (!content?.value || content.isDynamic) {
7365
- return;
7366
- }
7367
- const location = content.valueLocation;
7368
- const value = parseContent(content.value.toString());
7369
- if (!value) {
7370
- this.report(target, "Malformed meta refresh directive", location);
7371
- return;
7372
- }
7373
- const { delay, url } = value;
7374
- this.validateDelay(target, location, delay, url);
7375
- });
7376
- }
7377
- validateDelay(target, location, delay, url) {
7378
- const { allowLongDelay } = this.options;
7379
- if (allowLongDelay && delay > 72e3) {
7380
- return;
7381
- }
7382
- if (!url && delay === 0) {
7383
- this.report(target, "Don't use instant meta refresh to reload the page", location);
7384
- return;
7385
- }
7386
- if (delay !== 0) {
7387
- const message = allowLongDelay ? "Meta refresh must be instant (0 second delay) or greater than 20 hours (72000 second delay)" : "Meta refresh must be instant (0 second delay)";
7388
- this.report(target, message, location);
7389
- }
7390
- }
7391
- }
7392
- function parseContent(text) {
7393
- const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
7394
- if (match) {
7395
- return {
7396
- delay: parseInt(match[1], 10),
7397
- url: match[2]
7398
- };
7399
- } else {
7400
- return null;
7401
- }
7402
- }
7403
-
7404
7227
  function getName(attr) {
7405
7228
  const name = attr.value;
7406
7229
  if (!name || name instanceof DynamicValue) {
@@ -7463,16 +7286,79 @@ class MapIdName extends Rule {
7463
7286
  if (!hasStaticValue(id) || !hasStaticValue(name)) {
7464
7287
  return;
7465
7288
  }
7466
- if (id.value === name.value) {
7289
+ if (id.value === name.value) {
7290
+ return;
7291
+ }
7292
+ this.report({
7293
+ node: event.target,
7294
+ message: `"id" and "name" attribute must be the same on <map> elements`,
7295
+ location: id.valueLocation ?? name.valueLocation
7296
+ });
7297
+ });
7298
+ }
7299
+ }
7300
+
7301
+ const defaults$h = {
7302
+ allowLongDelay: false
7303
+ };
7304
+ class MetaRefresh extends Rule {
7305
+ constructor(options) {
7306
+ super({ ...defaults$h, ...options });
7307
+ }
7308
+ documentation() {
7309
+ return {
7310
+ description: `Meta refresh directive must use the \`0;url=...\` format. Non-zero values for time interval is disallowed as people with assistive technology might be unable to read and understand the page content before automatically reloading. For the same reason skipping the url is disallowed as it would put the browser in an infinite loop reloading the same page over and over again.`,
7311
+ url: "https://html-validate.org/rules/meta-refresh.html"
7312
+ };
7313
+ }
7314
+ setup() {
7315
+ this.on("element:ready", ({ target }) => {
7316
+ if (!target.is("meta")) {
7317
+ return;
7318
+ }
7319
+ const httpEquiv = target.getAttributeValue("http-equiv");
7320
+ if (httpEquiv !== "refresh") {
7321
+ return;
7322
+ }
7323
+ const content = target.getAttribute("content");
7324
+ if (!content?.value || content.isDynamic) {
7325
+ return;
7326
+ }
7327
+ const location = content.valueLocation;
7328
+ const value = parseContent(content.value.toString());
7329
+ if (!value) {
7330
+ this.report(target, "Malformed meta refresh directive", location);
7467
7331
  return;
7468
7332
  }
7469
- this.report({
7470
- node: event.target,
7471
- message: `"id" and "name" attribute must be the same on <map> elements`,
7472
- location: id.valueLocation ?? name.valueLocation
7473
- });
7333
+ const { delay, url } = value;
7334
+ this.validateDelay(target, location, delay, url);
7474
7335
  });
7475
7336
  }
7337
+ validateDelay(target, location, delay, url) {
7338
+ const { allowLongDelay } = this.options;
7339
+ if (allowLongDelay && delay > 72e3) {
7340
+ return;
7341
+ }
7342
+ if (!url && delay === 0) {
7343
+ this.report(target, "Don't use instant meta refresh to reload the page", location);
7344
+ return;
7345
+ }
7346
+ if (delay !== 0) {
7347
+ const message = allowLongDelay ? "Meta refresh must be instant (0 second delay) or greater than 20 hours (72000 second delay)" : "Meta refresh must be instant (0 second delay)";
7348
+ this.report(target, message, location);
7349
+ }
7350
+ }
7351
+ }
7352
+ function parseContent(text) {
7353
+ const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
7354
+ if (match) {
7355
+ return {
7356
+ delay: parseInt(match[1], 10),
7357
+ url: match[2]
7358
+ };
7359
+ } else {
7360
+ return null;
7361
+ }
7476
7362
  }
7477
7363
 
7478
7364
  class MissingDoctype extends Rule {
@@ -7871,30 +7757,6 @@ class NoImplicitButtonType extends Rule {
7871
7757
  }
7872
7758
  }
7873
7759
 
7874
- function isRelevant$1(event) {
7875
- return event.target.is("input");
7876
- }
7877
- class NoImplicitInputType extends Rule {
7878
- documentation() {
7879
- return {
7880
- description: ["`<input>` is missing recommended `type` attribute"].join("\n"),
7881
- url: "https://html-validate.org/rules/no-implicit-input-type.html"
7882
- };
7883
- }
7884
- setup() {
7885
- this.on("element:ready", isRelevant$1, (event) => {
7886
- const { target } = event;
7887
- const attr = target.getAttribute("type");
7888
- if (!attr) {
7889
- this.report({
7890
- node: event.target,
7891
- message: `<input> is missing recommended "type" attribute`
7892
- });
7893
- }
7894
- });
7895
- }
7896
- }
7897
-
7898
7760
  class NoImplicitClose extends Rule {
7899
7761
  documentation() {
7900
7762
  return {
@@ -7947,6 +7809,30 @@ Omitted end tags can be ambigious for humans to read and many editors have troub
7947
7809
  }
7948
7810
  }
7949
7811
 
7812
+ function isRelevant$1(event) {
7813
+ return event.target.is("input");
7814
+ }
7815
+ class NoImplicitInputType extends Rule {
7816
+ documentation() {
7817
+ return {
7818
+ description: ["`<input>` is missing recommended `type` attribute"].join("\n"),
7819
+ url: "https://html-validate.org/rules/no-implicit-input-type.html"
7820
+ };
7821
+ }
7822
+ setup() {
7823
+ this.on("element:ready", isRelevant$1, (event) => {
7824
+ const { target } = event;
7825
+ const attr = target.getAttribute("type");
7826
+ if (!attr) {
7827
+ this.report({
7828
+ node: event.target,
7829
+ message: `<input> is missing recommended "type" attribute`
7830
+ });
7831
+ }
7832
+ });
7833
+ }
7834
+ }
7835
+
7950
7836
  const defaults$e = {
7951
7837
  include: null,
7952
7838
  exclude: null,
@@ -8177,7 +8063,7 @@ class NoRawCharacters extends Rule {
8177
8063
  setup() {
8178
8064
  this.on("element:ready", (event) => {
8179
8065
  const node = event.target;
8180
- if (node.matches("script, style")) {
8066
+ if (node.textType !== "text") {
8181
8067
  return;
8182
8068
  }
8183
8069
  for (const child of node.childNodes) {
@@ -9472,6 +9358,9 @@ class UnknownCharReference extends Rule {
9472
9358
  setup() {
9473
9359
  this.on("element:ready", (event) => {
9474
9360
  const node = event.target;
9361
+ if (node.textType !== "text") {
9362
+ return;
9363
+ }
9475
9364
  for (const child of node.childNodes) {
9476
9365
  if (child.nodeType !== NodeType.TEXT_NODE) {
9477
9366
  continue;
@@ -10697,6 +10586,172 @@ const bundledRules = {
10697
10586
  ...bundledRules$1
10698
10587
  };
10699
10588
 
10589
+ const $schema = "http://json-schema.org/draft-06/schema#";
10590
+ const $id = "https://html-validate.org/schemas/config.json";
10591
+ const type = "object";
10592
+ const additionalProperties = false;
10593
+ const properties = {
10594
+ $schema: {
10595
+ type: "string"
10596
+ },
10597
+ root: {
10598
+ type: "boolean",
10599
+ title: "Mark as root configuration",
10600
+ description: "If this is set to true no further configurations will be searched.",
10601
+ "default": false
10602
+ },
10603
+ "extends": {
10604
+ type: "array",
10605
+ items: {
10606
+ type: "string"
10607
+ },
10608
+ title: "Configurations to extend",
10609
+ description: "Array of shareable or builtin configurations to extend."
10610
+ },
10611
+ elements: {
10612
+ type: "array",
10613
+ items: {
10614
+ anyOf: [
10615
+ {
10616
+ type: "string"
10617
+ },
10618
+ {
10619
+ type: "object"
10620
+ }
10621
+ ]
10622
+ },
10623
+ title: "Element metadata to load",
10624
+ description: "Array of modules, plugins or files to load element metadata from. Use <rootDir> to refer to the folder with the package.json file.",
10625
+ examples: [
10626
+ [
10627
+ "html-validate:recommended",
10628
+ "plugin:recommended",
10629
+ "module",
10630
+ "./local-file.json"
10631
+ ]
10632
+ ]
10633
+ },
10634
+ plugins: {
10635
+ type: "array",
10636
+ items: {
10637
+ anyOf: [
10638
+ {
10639
+ type: "string"
10640
+ },
10641
+ {
10642
+ type: "object"
10643
+ }
10644
+ ]
10645
+ },
10646
+ title: "Plugins to load",
10647
+ description: "Array of plugins load. Use <rootDir> to refer to the folder with the package.json file.",
10648
+ examples: [
10649
+ [
10650
+ "my-plugin",
10651
+ "./local-plugin"
10652
+ ]
10653
+ ]
10654
+ },
10655
+ transform: {
10656
+ type: "object",
10657
+ additionalProperties: {
10658
+ anyOf: [
10659
+ {
10660
+ type: "string"
10661
+ },
10662
+ {
10663
+ "function": true
10664
+ }
10665
+ ]
10666
+ },
10667
+ title: "File transformations to use.",
10668
+ description: "Object where key is regular expression to match filename and value is name of transformer or a function.",
10669
+ examples: [
10670
+ {
10671
+ "^.*\\.foo$": "my-transformer",
10672
+ "^.*\\.bar$": "my-plugin",
10673
+ "^.*\\.baz$": "my-plugin:named"
10674
+ }
10675
+ ]
10676
+ },
10677
+ rules: {
10678
+ type: "object",
10679
+ patternProperties: {
10680
+ ".*": {
10681
+ anyOf: [
10682
+ {
10683
+ "enum": [
10684
+ 0,
10685
+ 1,
10686
+ 2,
10687
+ "off",
10688
+ "warn",
10689
+ "error"
10690
+ ]
10691
+ },
10692
+ {
10693
+ type: "array",
10694
+ minItems: 1,
10695
+ maxItems: 1,
10696
+ items: [
10697
+ {
10698
+ "enum": [
10699
+ 0,
10700
+ 1,
10701
+ 2,
10702
+ "off",
10703
+ "warn",
10704
+ "error"
10705
+ ]
10706
+ }
10707
+ ]
10708
+ },
10709
+ {
10710
+ type: "array",
10711
+ minItems: 2,
10712
+ maxItems: 2,
10713
+ items: [
10714
+ {
10715
+ "enum": [
10716
+ 0,
10717
+ 1,
10718
+ 2,
10719
+ "off",
10720
+ "warn",
10721
+ "error"
10722
+ ]
10723
+ },
10724
+ {
10725
+ }
10726
+ ]
10727
+ }
10728
+ ]
10729
+ }
10730
+ },
10731
+ title: "Rule configuration.",
10732
+ description: "Enable/disable rules, set severity. Some rules have additional configuration like style or patterns to use.",
10733
+ examples: [
10734
+ {
10735
+ foo: "error",
10736
+ bar: "off",
10737
+ baz: [
10738
+ "error",
10739
+ {
10740
+ style: "camelcase"
10741
+ }
10742
+ ]
10743
+ }
10744
+ ]
10745
+ }
10746
+ };
10747
+ var configurationSchema = {
10748
+ $schema: $schema,
10749
+ $id: $id,
10750
+ type: type,
10751
+ additionalProperties: additionalProperties,
10752
+ properties: properties
10753
+ };
10754
+
10700
10755
  function dumpTree(root) {
10701
10756
  const lines = [];
10702
10757
  function decoration(node) {
@@ -11832,7 +11887,7 @@ class EventHandler {
11832
11887
  }
11833
11888
 
11834
11889
  const name = "html-validate";
11835
- const version = "10.1.0";
11890
+ const version = "10.1.2";
11836
11891
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11837
11892
 
11838
11893
  function freeze(src) {