@markuplint/rules 3.0.0-alpha.2 → 3.0.0-alpha.27

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 (62) hide show
  1. package/README.md +10 -44
  2. package/lib/attr-check.d.ts +2 -2
  3. package/lib/attr-value-quotes/index.d.ts +3 -3
  4. package/lib/case-sensitive-attr-name/index.d.ts +1 -1
  5. package/lib/case-sensitive-tag-name/index.d.ts +1 -1
  6. package/lib/class-naming/index.d.ts +1 -1
  7. package/lib/class-naming/index.js +1 -1
  8. package/lib/debug.d.ts +1 -1
  9. package/lib/doctype/index.d.ts +1 -1
  10. package/lib/doctype/index.js +1 -1
  11. package/lib/end-tag/index.js +2 -17
  12. package/lib/helpers.d.ts +2 -31
  13. package/lib/helpers.js +1 -71
  14. package/lib/index.d.ts +2 -58
  15. package/lib/index.js +4 -0
  16. package/lib/invalid-attr/index.d.ts +3 -2
  17. package/lib/invalid-attr/index.js +16 -11
  18. package/lib/label-has-control/index.d.ts +2 -0
  19. package/lib/label-has-control/index.js +28 -0
  20. package/lib/landmark-roles/index.d.ts +3 -3
  21. package/lib/landmark-roles/index.js +2 -2
  22. package/lib/no-empty-palpable-content/index.d.ts +6 -0
  23. package/lib/no-empty-palpable-content/index.js +34 -0
  24. package/lib/no-refer-to-non-existent-id/index.js +1 -1
  25. package/lib/no-use-event-handler-attr/index.d.ts +1 -1
  26. package/lib/no-use-event-handler-attr/index.js +4 -4
  27. package/lib/permitted-contents/debug.browser.d.ts +30 -0
  28. package/lib/permitted-contents/debug.browser.js +14 -0
  29. package/lib/permitted-contents/debug.d.ts +1 -0
  30. package/lib/permitted-contents/debug.js +9 -1
  31. package/lib/permitted-contents/index.js +4 -4
  32. package/lib/permitted-contents/matches-selector.d.ts +1 -1
  33. package/lib/permitted-contents/represent-transparent-nodes.d.ts +1 -1
  34. package/lib/permitted-contents/represent-transparent-nodes.js +0 -3
  35. package/lib/permitted-contents/start.js +1 -1
  36. package/lib/permitted-contents/transparent.js +6 -11
  37. package/lib/permitted-contents/types.d.ts +12 -12
  38. package/lib/permitted-contents/utils.d.ts +4 -4
  39. package/lib/permitted-contents/utils.js +8 -8
  40. package/lib/require-accessible-name/index.d.ts +1 -1
  41. package/lib/require-accessible-name/index.js +7 -3
  42. package/lib/required-attr/index.d.ts +2 -2
  43. package/lib/required-element/index.d.ts +1 -1
  44. package/lib/required-element/index.js +1 -1
  45. package/lib/required-h1/index.js +2 -2
  46. package/lib/use-list/index.d.ts +2 -2
  47. package/lib/use-list/index.js +1 -1
  48. package/lib/wai-aria/checkings/abstract-role.js +1 -1
  49. package/lib/wai-aria/checkings/implicit-role.js +1 -1
  50. package/lib/wai-aria/checkings/{non-existant-role.d.ts → non-existent-role.d.ts} +1 -1
  51. package/lib/wai-aria/checkings/{non-existant-role.js → non-existent-role.js} +4 -4
  52. package/lib/wai-aria/checkings/permitted-roles.js +1 -1
  53. package/lib/wai-aria/checkings/presentational-children.js +1 -1
  54. package/lib/wai-aria/checkings/required-owned-elements.js +40 -10
  55. package/lib/wai-aria/checkings/value.d.ts +6 -0
  56. package/lib/wai-aria/checkings/value.js +74 -4
  57. package/lib/wai-aria/index.js +14 -14
  58. package/lib/wai-aria/types.d.ts +1 -1
  59. package/package.json +11 -8
  60. package/schema.json +6 -0
  61. package/tsconfig.test.json +0 -3
  62. package/tsconfig.tsbuildinfo +0 -1
package/README.md CHANGED
@@ -1,58 +1,24 @@
1
1
  # @markuplint/rules
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40markuplint%2Frules.svg)](https://www.npmjs.com/package/@markuplint/rules)
4
- [![Build Status](https://travis-ci.org/markuplint/markuplint.svg?branch=main)](https://travis-ci.org/markuplint/markuplint)
5
- [![Coverage Status](https://coveralls.io/repos/github/markuplint/markuplint/badge.svg?branch=main)](https://coveralls.io/github/markuplint/markuplint?branch=main)
6
4
 
7
- ## Rules
5
+ **Built-in rules**
8
6
 
9
- ### Conformance checking
7
+ ## Documentation
10
8
 
11
- - [`attr-duplication`](./src/attr-duplication)
12
- - [`character-reference`](./src/character-reference)
13
- - [`deprecated-attr`](./src/deprecated-attr)
14
- - [`deprecated-element`](./src/deprecated-element)
15
- - [`disallowed-element`](./src/disallowed-element)
16
- - [`doctype`](./src/doctype)
17
- - [`id-duplication`](./src/id-duplication)
18
- - [`ineffective-attr`](./src/ineffective-attr)
19
- - [`invalid-attr`](./src/invalid-attr)
20
- - [`permitted-contents`](./src/permitted-contents)
21
- - [`required-attr`](./src/required-attr)
22
- - [`required-element`](./src/required-element)
23
-
24
- ### Accessibility
25
-
26
- - [`landmark-roles`](./src/landmark-roles)
27
- - [`no-refer-to-non-existent-id`](./src/no-refer-to-non-existent-id)
28
- - [`required-h1`](./src/required-h1)
29
- - [`use-list`](./src/use-list)
30
- - [`wai-aria`](./src/wai-aria)
31
-
32
- ### Naming Convention
33
-
34
- - [`class-naming`](./src/class-naming)
35
-
36
- ### Maintainability
37
-
38
- - [`no-hard-code-id`](./src/no-hard-code-id)
39
- - [`no-use-event-handler-attr`](./src/no-use-event-handler-attr)
40
-
41
- ### Style
42
-
43
- - [`attr-value-quotes`](./src/attr-value-quotes)
44
- - [`case-sensitive-attr-name`](./src/case-sensitive-attr-name)
45
- - [`case-sensitive-tag-name`](./src/case-sensitive-tag-name)
46
- - [`end-tag`](./src/end-tag)
47
- - [`no-boolean-attr-value`](./src/no-boolean-attr-value)
48
- - [`no-default-value`](./src/no-default-value)
9
+ - [Rules](https://markuplint.dev/rules/)
49
10
 
50
11
  ## Install
51
12
 
52
- Generally, you **don't have to install** this package because markuplint dependents it by default.
13
+ [`markuplint`](https://www.npmjs.com/package/markuplint) package includes this package.
53
14
 
54
- ```sh
15
+ <details>
16
+ <summary>If you are installing purposely, how below:</summary>
17
+
18
+ ```shell
55
19
  $ npm install -D @markuplint/rules
56
20
 
57
21
  $ yarn add -D @markuplint/rules
58
22
  ```
23
+
24
+ </details>
@@ -1,11 +1,11 @@
1
1
  import type { Translator } from '@markuplint/i18n';
2
2
  import type { Attribute as AttrSpec, AttributeType } from '@markuplint/ml-spec';
3
- declare type Invalid = {
3
+ type Invalid = {
4
4
  invalidType: 'non-existent' | 'invalid-value';
5
5
  message: string;
6
6
  loc?: Loc;
7
7
  };
8
- declare type Loc = {
8
+ type Loc = {
9
9
  raw: string;
10
10
  line: number;
11
11
  col: number;
@@ -1,6 +1,6 @@
1
- export declare type Type = 'double' | 'single';
2
- export declare type Quote = '"' | "'";
3
- export declare type QuoteMap = {
1
+ export type Type = 'double' | 'single';
2
+ export type Quote = '"' | "'";
3
+ export type QuoteMap = {
4
4
  [P in Type]: Quote;
5
5
  };
6
6
  declare const _default: import("@markuplint/ml-core").RuleSeed<Type, null>;
@@ -1,3 +1,3 @@
1
- export declare type Value = 'lower' | 'upper';
1
+ export type Value = 'lower' | 'upper';
2
2
  declare const _default: import("@markuplint/ml-core").RuleSeed<Value, null>;
3
3
  export default _default;
@@ -1,3 +1,3 @@
1
- export declare type Value = 'lower' | 'upper';
1
+ export type Value = 'lower' | 'upper';
2
2
  declare const _default: import("@markuplint/ml-core").RuleSeed<Value, null>;
3
3
  export default _default;
@@ -1,3 +1,3 @@
1
- export declare type Value = string | string[] | null;
1
+ export type Value = string | string[] | null;
2
2
  declare const _default: import("@markuplint/ml-core").RuleSeed<Value, null>;
3
3
  export default _default;
@@ -10,7 +10,7 @@ exports.default = (0, ml_core_1.createRule)({
10
10
  if (!el.rule.value) {
11
11
  return;
12
12
  }
13
- const classPatterns = Array.isArray(el.rule.value) ? el.rule.value : [el.rule.value];
13
+ const classPatterns = (Array.isArray(el.rule.value) ? el.rule.value : [el.rule.value]).filter(className => className && typeof className === 'string');
14
14
  const attrs = el.getAttributeToken('class');
15
15
  for (const attr of attrs) {
16
16
  if (attr.isDynamicValue) {
package/lib/debug.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import debug from 'debug';
2
- export declare type Log = debug.Debugger;
2
+ export type Log = debug.Debugger;
3
3
  export declare const log: debug.Debugger;
@@ -1,4 +1,4 @@
1
- declare type Option = {
1
+ type Option = {
2
2
  denyObsoleteType: boolean;
3
3
  };
4
4
  declare const _default: import("@markuplint/ml-core").RuleSeed<"always", Option>;
@@ -23,7 +23,7 @@ exports.default = (0, ml_core_1.createRule)({
23
23
  if ((doctype.name.toLowerCase() === 'html' && doctype.publicId) || doctype.systemId) {
24
24
  report({
25
25
  scope: doctype,
26
- message: t('Never {0} {1}', 'declarate', 'obsolete doctype'),
26
+ message: t('Never {0} {1}', 'declare', 'obsolete doctype'),
27
27
  });
28
28
  }
29
29
  },
@@ -1,22 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
- const voidElements = [
5
- 'area',
6
- 'base',
7
- 'br',
8
- 'col',
9
- 'embed',
10
- 'hr',
11
- 'img',
12
- 'input',
13
- 'link',
14
- 'meta',
15
- 'param',
16
- 'source',
17
- 'track',
18
- 'wbr',
19
- ];
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
20
5
  exports.default = (0, ml_core_1.createRule)({
21
6
  defaultSeverity: 'warning',
22
7
  async verify({ document, report, t }) {
@@ -28,7 +13,7 @@ exports.default = (0, ml_core_1.createRule)({
28
13
  if (el.isOmitted) {
29
14
  return;
30
15
  }
31
- if (voidElements.some(vE => vE === el.localName)) {
16
+ if ((0, ml_spec_1.isVoidElement)(el)) {
32
17
  return;
33
18
  }
34
19
  if (el.closeTag != null) {
package/lib/helpers.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Log } from './debug';
2
2
  import type { Translator } from '@markuplint/i18n';
3
3
  import type { Element, RuleConfigValue, Document } from '@markuplint/ml-core';
4
- import type { ARIAVersion, Attribute, MLMLSpec } from '@markuplint/ml-spec';
4
+ import type { Attribute } from '@markuplint/ml-spec';
5
5
  export declare function attrMatches<T extends RuleConfigValue, R>(node: Element<T, R>, condition: Attribute['condition']): boolean;
6
6
  export declare function match(needle: string, pattern: string): boolean;
7
7
  /**
@@ -30,35 +30,6 @@ export declare function isValidAttr(t: Translator, name: string, value: string,
30
30
  } | undefined;
31
31
  };
32
32
  export declare function toNormalizedValue(value: string, spec: Attribute): string;
33
- /**
34
- *
35
- * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
36
- *
37
- * @param type
38
- * @param value
39
- * @param tokenEnum
40
- */
41
- export declare function checkAriaValue(type: string, value: string, tokenEnum: string[]): boolean;
42
- export declare function checkAria(specs: Readonly<MLMLSpec>, attrName: string, currentValue: string, version: ARIAVersion, role?: string): {
43
- currentValue: string;
44
- isValid: boolean;
45
- } | {
46
- currentValue: string;
47
- isValid: boolean;
48
- name: string;
49
- type: "property" | "state";
50
- deprecated?: true | undefined;
51
- isGlobal?: true | undefined;
52
- value: import("@markuplint/ml-spec").ARIAAttributeValue;
53
- conditionalValue?: {
54
- role: string[];
55
- value: import("@markuplint/ml-spec").ARIAAttributeValue;
56
- }[] | undefined;
57
- enum: string[];
58
- defaultValue?: string | undefined;
59
- equivalentHtmlAttrs?: import("@markuplint/ml-spec").EquivalentHtmlAttr[] | undefined;
60
- valueDescriptions?: Record<string, string> | undefined;
61
- };
62
33
  export declare function accnameMayBeMutable(el: Element<any, any>, document: Document<any, any>): boolean;
63
34
  export declare function getOwnedLabel<V extends RuleConfigValue, O>(el: Element<V, O>, document: Document<V, O>): Element<V, O> | null;
64
35
  export declare function decodeCharRef(characterReference: string): string;
@@ -69,7 +40,7 @@ export declare class Collection<T> {
69
40
  add(...items: (T | null | undefined)[]): void;
70
41
  toArray(): readonly T[];
71
42
  }
72
- declare type Writeable<T> = {
43
+ type Writeable<T> = {
73
44
  -readonly [P in keyof T]: T[P];
74
45
  };
75
46
  export declare function deepCopy<T>(value: T): Writeable<T>;
package/lib/helpers.js CHANGED
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  var _Collection_items;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.deepCopy = exports.Collection = exports.decodeCharRef = exports.getOwnedLabel = exports.accnameMayBeMutable = exports.checkAria = exports.checkAriaValue = exports.toNormalizedValue = exports.isValidAttr = exports.rePCENChar = exports.match = exports.attrMatches = void 0;
4
+ exports.deepCopy = exports.Collection = exports.decodeCharRef = exports.getOwnedLabel = exports.accnameMayBeMutable = exports.toNormalizedValue = exports.isValidAttr = exports.rePCENChar = exports.match = exports.attrMatches = void 0;
5
5
  const tslib_1 = require("tslib");
6
- const ml_core_1 = require("@markuplint/ml-core");
7
6
  // @ts-ignore
8
7
  const structured_clone_1 = tslib_1.__importDefault(require("@ungap/structured-clone"));
9
8
  const html_entities_1 = require("html-entities");
@@ -107,75 +106,6 @@ function toNormalizedValue(value, spec) {
107
106
  return normalized;
108
107
  }
109
108
  exports.toNormalizedValue = toNormalizedValue;
110
- /**
111
- *
112
- * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
113
- *
114
- * @param type
115
- * @param value
116
- * @param tokenEnum
117
- */
118
- function checkAriaValue(type, value, tokenEnum) {
119
- switch (type) {
120
- case 'token': {
121
- return tokenEnum.includes(value);
122
- }
123
- case 'token list': {
124
- const list = value.split(/\s+/g).map(s => s.trim());
125
- return list.every(token => tokenEnum.includes(token));
126
- }
127
- case 'string':
128
- case 'ID reference':
129
- case 'ID reference list': {
130
- return true;
131
- }
132
- case 'true/false': {
133
- return ['true', 'false'].includes(value);
134
- }
135
- case 'tristate': {
136
- return ['mixed', 'true', 'false', 'undefined'].includes(value);
137
- }
138
- case 'true/false/undefined': {
139
- return ['true', 'false', 'undefined'].includes(value);
140
- }
141
- case 'integer': {
142
- return parseInt(value).toString() === value;
143
- }
144
- case 'number': {
145
- return parseFloat(value).toString() === value;
146
- }
147
- }
148
- // For skipping checking
149
- return true;
150
- }
151
- exports.checkAriaValue = checkAriaValue;
152
- function checkAria(specs, attrName, currentValue, version, role) {
153
- const ariaAttrs = (0, ml_core_1.ariaSpecs)(specs, version).props;
154
- const aria = ariaAttrs.find(a => a.name === attrName);
155
- if (!aria) {
156
- return {
157
- currentValue,
158
- // For skipping checking
159
- isValid: true,
160
- };
161
- }
162
- let valueType = aria.value;
163
- if (role && aria.conditionalValue) {
164
- for (const cond of aria.conditionalValue) {
165
- if (cond.role.includes(role)) {
166
- valueType = cond.value;
167
- break;
168
- }
169
- }
170
- }
171
- const isValid = checkAriaValue(valueType, currentValue, aria.enum);
172
- return {
173
- ...aria,
174
- currentValue,
175
- isValid,
176
- };
177
- }
178
- exports.checkAria = checkAria;
179
109
  function accnameMayBeMutable(el, document) {
180
110
  if (el.hasMutableAttributes() || el.hasMutableChildren(true)) {
181
111
  return true;
package/lib/index.d.ts CHANGED
@@ -1,59 +1,3 @@
1
- declare const _default: {
2
- 'attr-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
3
- 'attr-value-quotes': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./attr-value-quotes").Type, null>;
4
- 'case-sensitive-attr-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-attr-name").Value, null>;
5
- 'case-sensitive-tag-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-tag-name").Value, null>;
6
- 'character-reference': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
7
- 'class-naming': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./class-naming").Value, null>;
8
- 'deprecated-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
9
- 'deprecated-element': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
10
- 'disallowed-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], null>;
11
- doctype: import("packages/@markuplint/ml-core/lib").RuleSeed<"always", {
12
- denyObsoleteType: boolean;
13
- }>;
14
- 'end-tag': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, null>;
15
- 'id-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
16
- 'ineffective-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
17
- 'invalid-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
18
- attrs?: Record<string, {
19
- enum: [string, ...string[]];
20
- } | {
21
- pattern: string;
22
- } | {
23
- type: import("packages/@markuplint/ml-spec/lib").AttributeType;
24
- } | {
25
- disallowed: true;
26
- }> | undefined;
27
- ignoreAttrNamePrefix?: string | string[] | undefined;
28
- }>;
29
- 'landmark-roles': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
30
- ignoreRoles: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[];
31
- labelEachArea: boolean;
32
- }>;
33
- 'no-boolean-attr-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
34
- 'no-default-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
35
- 'no-hard-code-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
36
- 'no-refer-to-non-existent-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, {
37
- ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
38
- }>;
39
- 'no-use-event-handler-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
40
- ignore?: string | string[] | undefined;
41
- }>;
42
- 'permitted-contents': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./permitted-contents/types").TagRule[], import("./permitted-contents/types").Options>;
43
- 'require-accessible-name': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
44
- ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
45
- }>;
46
- 'required-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<string | (string | {
47
- name: string;
48
- value: string | string[];
49
- })[], null>;
50
- 'required-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
51
- ignoreHasMutableContents: boolean;
52
- }>;
53
- 'required-h1': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./required-h1").Options>;
54
- 'use-list': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
55
- spaceNeededBullets?: string[] | undefined;
56
- }>;
57
- 'wai-aria': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./wai-aria/types").Options>;
58
- };
1
+ import type { AnyRuleSeed } from '@markuplint/ml-core';
2
+ declare const _default: Record<string, AnyRuleSeed>;
59
3
  export default _default;
package/lib/index.js CHANGED
@@ -15,9 +15,11 @@ const end_tag_1 = tslib_1.__importDefault(require("./end-tag"));
15
15
  const id_duplication_1 = tslib_1.__importDefault(require("./id-duplication"));
16
16
  const ineffective_attr_1 = tslib_1.__importDefault(require("./ineffective-attr"));
17
17
  const invalid_attr_1 = tslib_1.__importDefault(require("./invalid-attr"));
18
+ const label_has_control_1 = tslib_1.__importDefault(require("./label-has-control"));
18
19
  const landmark_roles_1 = tslib_1.__importDefault(require("./landmark-roles"));
19
20
  const no_boolean_attr_value_1 = tslib_1.__importDefault(require("./no-boolean-attr-value"));
20
21
  const no_default_value_1 = tslib_1.__importDefault(require("./no-default-value"));
22
+ const no_empty_palpable_content_1 = tslib_1.__importDefault(require("./no-empty-palpable-content"));
21
23
  const no_hard_code_id_1 = tslib_1.__importDefault(require("./no-hard-code-id"));
22
24
  const no_refer_to_non_existent_id_1 = tslib_1.__importDefault(require("./no-refer-to-non-existent-id"));
23
25
  const no_use_event_handler_attr_1 = tslib_1.__importDefault(require("./no-use-event-handler-attr"));
@@ -43,9 +45,11 @@ exports.default = {
43
45
  'id-duplication': id_duplication_1.default,
44
46
  'ineffective-attr': ineffective_attr_1.default,
45
47
  'invalid-attr': invalid_attr_1.default,
48
+ 'label-has-control': label_has_control_1.default,
46
49
  'landmark-roles': landmark_roles_1.default,
47
50
  'no-boolean-attr-value': no_boolean_attr_value_1.default,
48
51
  'no-default-value': no_default_value_1.default,
52
+ 'no-empty-palpable-content': no_empty_palpable_content_1.default,
49
53
  'no-hard-code-id': no_hard_code_id_1.default,
50
54
  'no-refer-to-non-existent-id': no_refer_to_non_existent_id_1.default,
51
55
  'no-use-event-handler-attr': no_use_event_handler_attr_1.default,
@@ -1,9 +1,10 @@
1
1
  import type { AttributeType } from '@markuplint/ml-spec';
2
- declare type Option = {
2
+ type Option = {
3
3
  attrs?: Record<string, Rule>;
4
4
  ignoreAttrNamePrefix?: string | string[];
5
+ allowToAddPropertiesForPretender?: boolean;
5
6
  };
6
- declare type Rule = {
7
+ type Rule = {
7
8
  enum: [string, ...string[]];
8
9
  } | {
9
10
  pattern: string;
@@ -9,7 +9,9 @@ exports.default = (0, ml_core_1.createRule)({
9
9
  defaultOptions: {},
10
10
  async verify({ document, report, t }) {
11
11
  await document.walkOn('Attr', attr => {
12
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
12
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
13
+ // Default
14
+ const allowToAddPropertiesForPretender = (_a = attr.rule.options.allowToAddPropertiesForPretender) !== null && _a !== void 0 ? _a : true;
13
15
  if (attr.isDirective) {
14
16
  return;
15
17
  }
@@ -31,16 +33,16 @@ exports.default = (0, ml_core_1.createRule)({
31
33
  }
32
34
  const valueNode = attr.valueNode;
33
35
  const value = attr.value;
34
- if (attr.rule.option.ignoreAttrNamePrefix) {
35
- const ignoreAttrNamePrefixes = Array.isArray(attr.rule.option.ignoreAttrNamePrefix)
36
- ? attr.rule.option.ignoreAttrNamePrefix
37
- : [attr.rule.option.ignoreAttrNamePrefix];
36
+ if (attr.rule.options.ignoreAttrNamePrefix) {
37
+ const ignoreAttrNamePrefixes = Array.isArray(attr.rule.options.ignoreAttrNamePrefix)
38
+ ? attr.rule.options.ignoreAttrNamePrefix
39
+ : [attr.rule.options.ignoreAttrNamePrefix];
38
40
  if (ignoreAttrNamePrefixes.some(prefix => name.indexOf(prefix) === 0)) {
39
41
  return;
40
42
  }
41
43
  }
42
44
  let invalid = false;
43
- const customRule = attr.rule.option.attrs ? attr.rule.option.attrs[name] : null;
45
+ const customRule = attr.rule.options.attrs ? attr.rule.options.attrs[name] : null;
44
46
  if (customRule) {
45
47
  if ('enum' in customRule) {
46
48
  invalid = (0, attr_check_1.attrCheck)(t, name.toLowerCase(), value, true, {
@@ -82,15 +84,18 @@ exports.default = (0, ml_core_1.createRule)({
82
84
  report({
83
85
  scope: attr,
84
86
  message: invalid.message,
85
- line: ((_a = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startLine) !== null && _a !== void 0 ? _a : 0) + ((_c = (_b = invalid.loc) === null || _b === void 0 ? void 0 : _b.line) !== null && _c !== void 0 ? _c : 0),
86
- col: ((_d = invalid.loc) === null || _d === void 0 ? void 0 : _d.line)
87
- ? ((_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.col) + 1
88
- : ((_f = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startCol) !== null && _f !== void 0 ? _f : 0) + ((_h = (_g = invalid.loc) === null || _g === void 0 ? void 0 : _g.col) !== null && _h !== void 0 ? _h : 0),
89
- raw: (_k = (_j = invalid.loc) === null || _j === void 0 ? void 0 : _j.raw) !== null && _k !== void 0 ? _k : value,
87
+ line: ((_b = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startLine) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = invalid.loc) === null || _c === void 0 ? void 0 : _c.line) !== null && _d !== void 0 ? _d : 0),
88
+ col: ((_e = invalid.loc) === null || _e === void 0 ? void 0 : _e.line)
89
+ ? ((_f = invalid.loc) === null || _f === void 0 ? void 0 : _f.col) + 1
90
+ : ((_g = valueNode === null || valueNode === void 0 ? void 0 : valueNode.startCol) !== null && _g !== void 0 ? _g : 0) + ((_j = (_h = invalid.loc) === null || _h === void 0 ? void 0 : _h.col) !== null && _j !== void 0 ? _j : 0),
91
+ raw: (_l = (_k = invalid.loc) === null || _k === void 0 ? void 0 : _k.raw) !== null && _l !== void 0 ? _l : value,
90
92
  });
91
93
  break;
92
94
  }
93
95
  case 'non-existent': {
96
+ if (allowToAddPropertiesForPretender && ((_m = attr.ownerElement.pretenderContext) === null || _m === void 0 ? void 0 : _m.type) === 'origin') {
97
+ return;
98
+ }
94
99
  const spec = (0, ml_core_1.getSpec)(attr.ownerElement, document.specs.specs);
95
100
  if (spec === null || spec === void 0 ? void 0 : spec.possibleToAddProperties) {
96
101
  return;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, null>;
2
+ export default _default;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ml_core_1 = require("@markuplint/ml-core");
4
+ const controlSelector = ["input:not([type='hidden' i])", 'select', 'textarea'].join(',');
5
+ exports.default = (0, ml_core_1.createRule)({
6
+ defaultSeverity: 'warning',
7
+ async verify({ document, report, t }) {
8
+ await document.walkOn('Element', el => {
9
+ if (el.localName !== 'label') {
10
+ return;
11
+ }
12
+ if (el.children.length === 0 && !el.hasAttribute('for')) {
13
+ report({
14
+ scope: el,
15
+ message: t('{0} should associate with {1}', t('The "{0*}" {1}', 'label', 'element'), t('a {0}', 'control')),
16
+ });
17
+ }
18
+ const controls = el.querySelectorAll(controlSelector);
19
+ const secondControl = controls[1];
20
+ if (secondControl) {
21
+ report({
22
+ scope: secondControl,
23
+ message: t('{0} associates only {1}', t('The "{0*}" {1}', 'label', 'element'), t('first {0}', 'control')),
24
+ });
25
+ }
26
+ });
27
+ },
28
+ });
@@ -1,8 +1,8 @@
1
- declare type Options = {
1
+ type Options = {
2
2
  ignoreRoles: Roles[];
3
3
  labelEachArea: boolean;
4
4
  };
5
- declare type TopLevelRoles = 'banner' | 'main' | 'complementary' | 'contentinfo';
6
- declare type Roles = TopLevelRoles | 'form' | 'navigation' | 'region';
5
+ type TopLevelRoles = 'banner' | 'main' | 'complementary' | 'contentinfo';
6
+ type Roles = TopLevelRoles | 'form' | 'navigation' | 'region';
7
7
  declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, Options>;
8
8
  export default _default;
@@ -72,7 +72,7 @@ exports.default = (0, ml_core_1.createRule)({
72
72
  if (el.rule.disabled) {
73
73
  continue;
74
74
  }
75
- if ((_a = el.rule.option.ignoreRoles) === null || _a === void 0 ? void 0 : _a.includes(role)) {
75
+ if ((_a = el.rule.options.ignoreRoles) === null || _a === void 0 ? void 0 : _a.includes(role)) {
76
76
  continue;
77
77
  }
78
78
  if (el.isDescendantByUUIDList(uuidList)) {
@@ -93,7 +93,7 @@ exports.default = (0, ml_core_1.createRule)({
93
93
  if (el.rule.disabled) {
94
94
  continue;
95
95
  }
96
- if (!el.rule.option.labelEachArea) {
96
+ if (!el.rule.options.labelEachArea) {
97
97
  continue;
98
98
  }
99
99
  if (!hasLabel(el)) {
@@ -0,0 +1,6 @@
1
+ type Options = {
2
+ extendsExposableElements?: boolean;
3
+ ignoreIfAriaBusy?: boolean;
4
+ };
5
+ declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, Options>;
6
+ export default _default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ml_core_1 = require("@markuplint/ml-core");
4
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
+ exports.default = (0, ml_core_1.createRule)({
6
+ defaultSeverity: 'warning',
7
+ defaultOptions: {
8
+ extendsExposableElements: true,
9
+ ignoreIfAriaBusy: true,
10
+ },
11
+ async verify({ document, report, t }) {
12
+ await document.walkOn('Element', el => {
13
+ if (!(0, ml_spec_1.isPalpableElement)(el, el.ownerMLDocument.specs, {
14
+ extendsSvg: false,
15
+ extendsExposableElements: el.rule.options.extendsExposableElements,
16
+ })) {
17
+ return;
18
+ }
19
+ if ((0, ml_spec_1.isNothingContentModel)(el)) {
20
+ return;
21
+ }
22
+ if (el.rule.options.ignoreIfAriaBusy && el.getAttribute('aria-busy') === 'true') {
23
+ return;
24
+ }
25
+ const isEmpty = Array.from(el.childNodes).every(node => node.is(node.TEXT_NODE) && node.isWhitespace());
26
+ if (isEmpty) {
27
+ report({
28
+ scope: el,
29
+ message: t('{0} should not {1}', t('the {0}', 'element'), 'empty'),
30
+ });
31
+ }
32
+ });
33
+ },
34
+ });
@@ -69,7 +69,7 @@ exports.default = (0, ml_core_1.createRule)({
69
69
  }
70
70
  }
71
71
  }
72
- const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.option.ariaVersion);
72
+ const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.options.ariaVersion);
73
73
  const aria = props.find(prop => prop.name === name);
74
74
  if (aria) {
75
75
  if (aria.value === 'ID reference' && !idList.has(value)) {
@@ -1,4 +1,4 @@
1
- declare type Options = {
1
+ type Options = {
2
2
  ignore?: string | string[];
3
3
  };
4
4
  declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, Options>;
@@ -10,10 +10,10 @@ exports.default = (0, ml_core_1.createRule)({
10
10
  if (attr.ownerElement.elementType !== 'html') {
11
11
  return;
12
12
  }
13
- const ignoreList = Array.isArray(attr.rule.option.ignore)
14
- ? attr.rule.option.ignore
15
- : attr.rule.option.ignore
16
- ? [attr.rule.option.ignore]
13
+ const ignoreList = Array.isArray(attr.rule.options.ignore)
14
+ ? attr.rule.options.ignore
15
+ : attr.rule.options.ignore
16
+ ? [attr.rule.options.ignore]
17
17
  : [];
18
18
  const name = attr.name;
19
19
  for (const ignore of ignoreList) {