html-validate 10.7.0 → 10.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.55.2"
8
+ "packageVersion": "7.56.3"
9
9
  }
10
10
  ]
11
11
  }
@@ -1,5 +1,5 @@
1
1
  export { H as HtmlValidate, c as compatibilityCheck, e as esmResolver } from './core-browser.js';
2
- export { A as Attribute, f as Config, e as ConfigError, C as ConfigLoader, D as DOMNode, r as DOMTokenList, u as DOMTree, w as DynamicValue, _ as EventHandler, H as HtmlElement, M as MetaCopyableProperty, F as MetaTable, y as NestedError, N as NodeClosed, x as NodeType, P as Parser, R as Reporter, m as ResolvedConfig, I as Rule, z as SchemaValidationError, o as Severity, S as StaticConfigLoader, J as TextClassification, G as TextContent, T as TextNode, U as UserError, V as Validator, W as WrappedError, K as ariaNaming, L as classifyNodeText, p as configPresets, q as defineConfig, X as definePlugin, B as isUserError, O as keywordPatternMatcher, Y as ruleExists, Q as sliceLocation, s as staticResolver, v as version, Z as walk } from './core.js';
2
+ export { A as Attribute, f as Config, e as ConfigError, C as ConfigLoader, D as DOMNode, m as DOMTokenList, o as DOMTree, p as DynamicValue, q as EventHandler, H as HtmlElement, M as MetaCopyableProperty, r as MetaTable, N as NestedError, s as NodeClosed, u as NodeType, P as Parser, R as Reporter, w as ResolvedConfig, x as Rule, y as SchemaValidationError, z as Severity, S as StaticConfigLoader, T as TextClassification, B as TextContent, F as TextNode, U as UserError, V as Validator, W as WrappedError, G as ariaNaming, I as classifyNodeText, J as configPresets, K as defineConfig, L as definePlugin, O as isUserError, Q as keywordPatternMatcher, X as ruleExists, Y as sliceLocation, Z as staticResolver, v as version, _ as walk } from './core.js';
3
3
  export { d as defineMetadata, m as metadataHelper } from './meta-helper.js';
4
4
  import 'ajv';
5
5
  import './elements.js';
package/dist/esm/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import { l as legacyRequire, F as FileSystemConfigLoader, e as esmResolver, H as HtmlValidate } from './core-nodejs.js';
2
- import { h as getFormatter$1, U as UserError, j as ensureError, k as deepmerge, l as ignore, R as Reporter, $ as engines } from './core.js';
1
+ import { l as legacyRequire, F as FileSystemConfigLoader, H as HtmlValidate, e as esmResolver } from './core-nodejs.js';
2
+ import { U as UserError, h as ensureError, j as getFormatter$1, k as deepmerge, l as ignore, R as Reporter, $ as engines } from './core.js';
3
3
  import path$1 from 'node:path/posix';
4
4
  import fs from 'node:fs';
5
5
  import path from 'node:path';
@@ -1,4 +1,4 @@
1
- import { S as StaticConfigLoader, n as normalizeSource, t as transformSource, E as Engine, P as Parser, a as transformSourceSync, b as transformFilename, c as transformFilenameSync, R as Reporter, d as configurationSchema, i as isThenable, U as UserError, C as ConfigLoader, g as compatibilityCheckImpl, v as version } from './core.js';
1
+ import { S as StaticConfigLoader, t as transformSource, E as Engine, P as Parser, a as transformSourceSync, b as transformFilename, c as transformFilenameSync, R as Reporter, d as configurationSchema, i as isThenable, U as UserError, C as ConfigLoader, n as normalizeSource, g as compatibilityCheckImpl, v as version } from './core.js';
2
2
 
3
3
  function isSourceHooks(value) {
4
4
  if (!value || typeof value === "string") {
@@ -1,5 +1,5 @@
1
1
  import fs, { existsSync } from 'node:fs';
2
- import { S as StaticConfigLoader, n as normalizeSource, t as transformSource, E as Engine, P as Parser, a as transformSourceSync, b as transformFilename, c as transformFilenameSync, R as Reporter, d as configurationSchema, i as isThenable, U as UserError, C as ConfigLoader, e as ConfigError, f as Config, g as compatibilityCheckImpl, v as version } from './core.js';
2
+ import { S as StaticConfigLoader, t as transformSource, E as Engine, P as Parser, a as transformSourceSync, b as transformFilename, c as transformFilenameSync, R as Reporter, d as configurationSchema, i as isThenable, U as UserError, C as ConfigLoader, n as normalizeSource, e as ConfigError, f as Config, g as compatibilityCheckImpl, v as version } from './core.js';
3
3
  import path from 'node:path';
4
4
  import fs$1 from 'node:fs/promises';
5
5
  import { pathToFileURL } from 'node:url';
package/dist/esm/core.js CHANGED
@@ -3999,7 +3999,7 @@ class Rule {
3999
3999
  }
4000
4000
  }
4001
4001
 
4002
- const defaults$z = {
4002
+ const defaults$A = {
4003
4003
  allowExternal: true,
4004
4004
  allowRelative: true,
4005
4005
  allowAbsolute: true,
@@ -4043,7 +4043,7 @@ class AllowedLinks extends Rule {
4043
4043
  allowRelative;
4044
4044
  allowAbsolute;
4045
4045
  constructor(options) {
4046
- super({ ...defaults$z, ...options });
4046
+ super({ ...defaults$A, ...options });
4047
4047
  this.allowExternal = parseAllow(this.options.allowExternal);
4048
4048
  this.allowRelative = parseAllow(this.options.allowRelative);
4049
4049
  this.allowAbsolute = parseAllow(this.options.allowAbsolute);
@@ -4211,7 +4211,7 @@ class AllowedLinks extends Rule {
4211
4211
  }
4212
4212
  }
4213
4213
 
4214
- const defaults$y = {
4214
+ const defaults$z = {
4215
4215
  accessible: true
4216
4216
  };
4217
4217
  function findByTarget(target, siblings) {
@@ -4241,7 +4241,7 @@ function getDescription$1(context) {
4241
4241
  }
4242
4242
  class AreaAlt extends Rule {
4243
4243
  constructor(options) {
4244
- super({ ...defaults$y, ...options });
4244
+ super({ ...defaults$z, ...options });
4245
4245
  }
4246
4246
  static schema() {
4247
4247
  return {
@@ -4320,7 +4320,7 @@ class AriaHiddenBody extends Rule {
4320
4320
  }
4321
4321
  }
4322
4322
 
4323
- const defaults$x = {
4323
+ const defaults$y = {
4324
4324
  allowAnyNamable: false,
4325
4325
  elements: {
4326
4326
  include: null,
@@ -4368,7 +4368,7 @@ function isValidUsage(target, meta) {
4368
4368
  }
4369
4369
  class AriaLabelMisuse extends Rule {
4370
4370
  constructor(options) {
4371
- super({ ...defaults$x, ...options });
4371
+ super({ ...defaults$y, ...options });
4372
4372
  }
4373
4373
  static schema() {
4374
4374
  return {
@@ -4537,14 +4537,14 @@ class CaseStyle {
4537
4537
  }
4538
4538
  }
4539
4539
 
4540
- const defaults$w = {
4540
+ const defaults$x = {
4541
4541
  style: "lowercase",
4542
4542
  ignoreForeign: true
4543
4543
  };
4544
4544
  class AttrCase extends Rule {
4545
4545
  style;
4546
4546
  constructor(options) {
4547
- super({ ...defaults$w, ...options });
4547
+ super({ ...defaults$x, ...options });
4548
4548
  this.style = new CaseStyle(this.options.style, "attr-case");
4549
4549
  }
4550
4550
  static schema() {
@@ -4949,7 +4949,7 @@ class AttrDelimiter extends Rule {
4949
4949
  }
4950
4950
 
4951
4951
  const DEFAULT_PATTERN = "[a-z0-9-:]+";
4952
- const defaults$v = {
4952
+ const defaults$w = {
4953
4953
  pattern: DEFAULT_PATTERN,
4954
4954
  ignoreForeign: true
4955
4955
  };
@@ -4982,7 +4982,7 @@ function generateDescription(name, pattern) {
4982
4982
  class AttrPattern extends Rule {
4983
4983
  pattern;
4984
4984
  constructor(options) {
4985
- super({ ...defaults$v, ...options });
4985
+ super({ ...defaults$w, ...options });
4986
4986
  this.pattern = generateRegexp(this.options.pattern);
4987
4987
  }
4988
4988
  static schema() {
@@ -5029,7 +5029,7 @@ class AttrPattern extends Rule {
5029
5029
  }
5030
5030
  }
5031
5031
 
5032
- const defaults$u = {
5032
+ const defaults$v = {
5033
5033
  style: "auto",
5034
5034
  unquoted: false
5035
5035
  };
@@ -5095,7 +5095,7 @@ class AttrQuotes extends Rule {
5095
5095
  };
5096
5096
  }
5097
5097
  constructor(options) {
5098
- super({ ...defaults$u, ...options });
5098
+ super({ ...defaults$v, ...options });
5099
5099
  this.style = parseStyle$3(this.options.style);
5100
5100
  }
5101
5101
  setup() {
@@ -5251,13 +5251,13 @@ class AttributeAllowedValues extends Rule {
5251
5251
  }
5252
5252
  }
5253
5253
 
5254
- const defaults$t = {
5254
+ const defaults$u = {
5255
5255
  style: "omit"
5256
5256
  };
5257
5257
  class AttributeBooleanStyle extends Rule {
5258
5258
  hasInvalidStyle;
5259
5259
  constructor(options) {
5260
- super({ ...defaults$t, ...options });
5260
+ super({ ...defaults$u, ...options });
5261
5261
  this.hasInvalidStyle = parseStyle$2(this.options.style);
5262
5262
  }
5263
5263
  static schema() {
@@ -5327,13 +5327,13 @@ function reportMessage$1(attr, style) {
5327
5327
  return "";
5328
5328
  }
5329
5329
 
5330
- const defaults$s = {
5330
+ const defaults$t = {
5331
5331
  style: "omit"
5332
5332
  };
5333
5333
  class AttributeEmptyStyle extends Rule {
5334
5334
  hasInvalidStyle;
5335
5335
  constructor(options) {
5336
- super({ ...defaults$s, ...options });
5336
+ super({ ...defaults$t, ...options });
5337
5337
  this.hasInvalidStyle = parseStyle$1(this.options.style);
5338
5338
  }
5339
5339
  static schema() {
@@ -5450,6 +5450,122 @@ class AttributeMisuse extends Rule {
5450
5450
  }
5451
5451
  }
5452
5452
 
5453
+ const defaults$s = {
5454
+ preferred: void 0
5455
+ };
5456
+ function isPasswordInput(event) {
5457
+ const { target } = event;
5458
+ if (!target.is("input")) {
5459
+ return false;
5460
+ }
5461
+ const type = target.getAttribute("type");
5462
+ return type?.value?.toString().toLowerCase() === "password";
5463
+ }
5464
+ function isGroupingToken(token) {
5465
+ return token.startsWith("section-") || token === "shipping" || token === "billing";
5466
+ }
5467
+ class AutocompletePassword extends Rule {
5468
+ preferred;
5469
+ constructor(options) {
5470
+ super({ ...defaults$s, ...options });
5471
+ this.preferred = options.preferred?.toLowerCase();
5472
+ }
5473
+ static schema() {
5474
+ return {
5475
+ preferred: {
5476
+ type: "string"
5477
+ }
5478
+ };
5479
+ }
5480
+ documentation(context) {
5481
+ const url = "https://html-validate.org/rules/autocomplete-password.html";
5482
+ switch (context.kind) {
5483
+ case "preferred-mismatch":
5484
+ return {
5485
+ description: [
5486
+ `\`<input type="password">\` should use \`autocomplete="${context.preferred}"\`.`,
5487
+ "",
5488
+ `The configured preferred autocomplete value is \`"${context.preferred}"\` but the element uses \`"${context.value}"\`.`
5489
+ ].join("\n"),
5490
+ url
5491
+ };
5492
+ case "off":
5493
+ case "missing":
5494
+ default: {
5495
+ const error = context.kind === "off" ? '`<input type="password">` should not use `autocomplete="off"`.' : '`<input type="password">` must have the `autocomplete` attribute.';
5496
+ return {
5497
+ description: [
5498
+ error,
5499
+ "",
5500
+ "Browsers and password managers often ignore the absence of autocomplete and autofill password fields anyway, which can lead to unexpected behavior where users unknowingly submit autofilled passwords for unrelated fields.",
5501
+ "",
5502
+ "Use one of the following values:",
5503
+ "",
5504
+ '- `autocomplete="new-password"` for password creation forms',
5505
+ '- `autocomplete="current-password"` for login forms'
5506
+ ].join("\n"),
5507
+ url
5508
+ };
5509
+ }
5510
+ }
5511
+ }
5512
+ setup() {
5513
+ this.on("tag:ready", isPasswordInput, (event) => {
5514
+ const { preferred } = this;
5515
+ const { target } = event;
5516
+ const autocomplete = target.getAttribute("autocomplete");
5517
+ if (!autocomplete) {
5518
+ const context = { kind: "missing" };
5519
+ this.report({
5520
+ node: target,
5521
+ message: '<input type="password"> is missing required "autocomplete" attribute',
5522
+ location: target.location,
5523
+ context
5524
+ });
5525
+ return;
5526
+ }
5527
+ if (autocomplete.isDynamic || !autocomplete.value) {
5528
+ return;
5529
+ }
5530
+ const raw = autocomplete.value.toString().toLowerCase();
5531
+ const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5532
+ const index = tokens.findIndex((token) => !isGroupingToken(token));
5533
+ const value = tokens.item(index);
5534
+ const location = tokens.location(index);
5535
+ if (!value) {
5536
+ return;
5537
+ }
5538
+ if (value === "off") {
5539
+ const context = { kind: "off" };
5540
+ this.report({
5541
+ node: target,
5542
+ message: '<input type="password"> should not use autocomplete="off"',
5543
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- location must be present if value is */
5544
+ location,
5545
+ context
5546
+ });
5547
+ return;
5548
+ }
5549
+ if (preferred) {
5550
+ if (value !== preferred) {
5551
+ const context = {
5552
+ kind: "preferred-mismatch",
5553
+ value,
5554
+ preferred
5555
+ };
5556
+ this.report({
5557
+ node: target,
5558
+ message: `<input type="password"> should use autocomplete="${preferred}"`,
5559
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- location must be present if value is */
5560
+ location,
5561
+ context
5562
+ });
5563
+ }
5564
+ }
5565
+ });
5566
+ }
5567
+ }
5568
+
5453
5569
  const patternNamesValues = [
5454
5570
  "kebabcase",
5455
5571
  "camelcase",
@@ -9746,9 +9862,7 @@ const fieldNameGroup = {
9746
9862
  nickname: "text",
9747
9863
  username: "username",
9748
9864
  "new-password": "password",
9749
- // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9750
9865
  "current-password": "password",
9751
- // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9752
9866
  "one-time-code": "password",
9753
9867
  "organization-title": "text",
9754
9868
  organization: "text",
@@ -10790,6 +10904,7 @@ const bundledRules = {
10790
10904
  "attribute-boolean-style": AttributeBooleanStyle,
10791
10905
  "attribute-empty-style": AttributeEmptyStyle,
10792
10906
  "attribute-misuse": AttributeMisuse,
10907
+ "autocomplete-password": AutocompletePassword,
10793
10908
  "class-pattern": ClassPattern,
10794
10909
  "close-attr": CloseAttr,
10795
10910
  "close-order": CloseOrder,
@@ -11155,6 +11270,7 @@ const config$1 = {
11155
11270
  "attribute-boolean-style": "error",
11156
11271
  "attribute-empty-style": "error",
11157
11272
  "attribute-misuse": "error",
11273
+ "autocomplete-password": "error",
11158
11274
  "close-attr": "error",
11159
11275
  "close-order": "error",
11160
11276
  deprecated: "error",
@@ -12169,7 +12285,7 @@ class EventHandler {
12169
12285
  }
12170
12286
 
12171
12287
  const name = "html-validate";
12172
- const version = "10.7.0";
12288
+ const version = "10.8.0";
12173
12289
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12174
12290
 
12175
12291
  function freeze(src) {
@@ -14589,5 +14705,5 @@ const engines = {
14589
14705
 
14590
14706
  var workerPath = "./jest-worker.js";
14591
14707
 
14592
- export { engines as $, Attribute as A, isUserError as B, ConfigLoader as C, DOMNode as D, Engine as E, MetaTable as F, TextContent$1 as G, HtmlElement as H, Rule as I, TextClassification as J, ariaNaming as K, classifyNodeText as L, MetaCopyableProperty as M, NodeClosed as N, keywordPatternMatcher as O, Parser as P, sliceLocation as Q, Reporter as R, StaticConfigLoader as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, definePlugin as X, ruleExists as Y, walk as Z, EventHandler as _, transformSourceSync as a, workerPath as a0, codeframe as a1, name as a2, bugs as a3, transformFilename as b, transformFilenameSync as c, configurationSchema as d, ConfigError as e, Config as f, compatibilityCheckImpl as g, getFormatter as h, isThenable as i, ensureError as j, deepmerge as k, ignore as l, ResolvedConfig as m, normalizeSource as n, Severity as o, presets as p, defineConfig as q, DOMTokenList as r, staticResolver as s, transformSource as t, DOMTree as u, version as v, DynamicValue as w, NodeType as x, NestedError as y, SchemaValidationError as z };
14708
+ export { engines as $, Attribute as A, TextContent$1 as B, ConfigLoader as C, DOMNode as D, Engine as E, TextNode as F, ariaNaming as G, HtmlElement as H, classifyNodeText as I, presets as J, defineConfig as K, definePlugin as L, MetaCopyableProperty as M, NestedError as N, isUserError as O, Parser as P, keywordPatternMatcher as Q, Reporter as R, StaticConfigLoader as S, TextClassification as T, UserError as U, Validator as V, WrappedError as W, ruleExists as X, sliceLocation as Y, staticResolver as Z, walk as _, transformSourceSync as a, workerPath as a0, codeframe as a1, name as a2, bugs as a3, transformFilename as b, transformFilenameSync as c, configurationSchema as d, ConfigError as e, Config as f, compatibilityCheckImpl as g, ensureError as h, isThenable as i, getFormatter as j, deepmerge as k, ignore as l, DOMTokenList as m, normalizeSource as n, DOMTree as o, DynamicValue as p, EventHandler as q, MetaTable as r, NodeClosed as s, transformSource as t, NodeType as u, version as v, ResolvedConfig as w, Rule as x, SchemaValidationError as y, Severity as z };
14593
14709
  //# sourceMappingURL=core.js.map