@markuplint/rules 4.11.2 → 4.18.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.
Files changed (231) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/SKILL.md +76 -0
  3. package/lib/attr-check.d.ts +41 -5
  4. package/lib/attr-check.js +29 -5
  5. package/lib/attr-duplication/index.d.ts +7 -0
  6. package/lib/attr-duplication/index.js +7 -0
  7. package/lib/attr-duplication/meta.d.ts +1 -0
  8. package/lib/attr-duplication/meta.js +1 -0
  9. package/lib/attr-value-quotes/index.d.ts +10 -0
  10. package/lib/attr-value-quotes/index.js +10 -0
  11. package/lib/attr-value-quotes/meta.d.ts +1 -0
  12. package/lib/attr-value-quotes/meta.js +1 -0
  13. package/lib/case-sensitive-attr-name/index.d.ts +9 -0
  14. package/lib/case-sensitive-attr-name/index.js +8 -0
  15. package/lib/case-sensitive-attr-name/meta.d.ts +1 -0
  16. package/lib/case-sensitive-attr-name/meta.js +1 -0
  17. package/lib/case-sensitive-tag-name/index.d.ts +9 -0
  18. package/lib/case-sensitive-tag-name/index.js +8 -0
  19. package/lib/case-sensitive-tag-name/meta.d.ts +1 -0
  20. package/lib/case-sensitive-tag-name/meta.js +1 -0
  21. package/lib/character-reference/index.d.ts +8 -0
  22. package/lib/character-reference/index.js +16 -0
  23. package/lib/character-reference/meta.d.ts +1 -0
  24. package/lib/character-reference/meta.js +1 -0
  25. package/lib/class-naming/index.d.ts +9 -0
  26. package/lib/class-naming/index.js +8 -0
  27. package/lib/class-naming/meta.d.ts +1 -0
  28. package/lib/class-naming/meta.js +1 -0
  29. package/lib/create-message.d.ts +27 -0
  30. package/lib/create-message.js +56 -1
  31. package/lib/debug.d.ts +9 -0
  32. package/lib/debug.js +5 -0
  33. package/lib/deprecated-attr/index.d.ts +6 -0
  34. package/lib/deprecated-attr/index.js +6 -0
  35. package/lib/deprecated-attr/meta.d.ts +1 -0
  36. package/lib/deprecated-attr/meta.js +1 -0
  37. package/lib/deprecated-element/index.d.ts +8 -0
  38. package/lib/deprecated-element/index.js +8 -0
  39. package/lib/deprecated-element/meta.d.ts +1 -0
  40. package/lib/deprecated-element/meta.js +1 -0
  41. package/lib/disallowed-element/index.d.ts +7 -0
  42. package/lib/disallowed-element/index.js +7 -0
  43. package/lib/disallowed-element/meta.d.ts +1 -0
  44. package/lib/disallowed-element/meta.js +1 -0
  45. package/lib/doctype/index.d.ts +10 -0
  46. package/lib/doctype/index.js +8 -0
  47. package/lib/doctype/meta.d.ts +1 -0
  48. package/lib/doctype/meta.js +1 -0
  49. package/lib/end-tag/index.d.ts +7 -0
  50. package/lib/end-tag/index.js +7 -0
  51. package/lib/end-tag/meta.d.ts +1 -0
  52. package/lib/end-tag/meta.js +1 -0
  53. package/lib/heading-levels/index.d.ts +6 -0
  54. package/lib/heading-levels/index.js +6 -0
  55. package/lib/heading-levels/meta.d.ts +1 -0
  56. package/lib/heading-levels/meta.js +1 -0
  57. package/lib/helpers.d.ts +104 -0
  58. package/lib/helpers.js +105 -2
  59. package/lib/id-duplication/index.d.ts +7 -0
  60. package/lib/id-duplication/index.js +7 -0
  61. package/lib/id-duplication/meta.d.ts +1 -0
  62. package/lib/id-duplication/meta.js +1 -0
  63. package/lib/index.d.ts +23 -10
  64. package/lib/index.js +12 -0
  65. package/lib/ineffective-attr/index.d.ts +7 -0
  66. package/lib/ineffective-attr/index.js +7 -0
  67. package/lib/ineffective-attr/meta.d.ts +1 -0
  68. package/lib/ineffective-attr/meta.js +1 -0
  69. package/lib/invalid-attr/index.d.ts +24 -0
  70. package/lib/invalid-attr/index.js +17 -0
  71. package/lib/invalid-attr/meta.d.ts +1 -0
  72. package/lib/invalid-attr/meta.js +1 -0
  73. package/lib/label-has-control/index.d.ts +7 -0
  74. package/lib/label-has-control/index.js +11 -0
  75. package/lib/label-has-control/meta.d.ts +1 -0
  76. package/lib/label-has-control/meta.js +1 -0
  77. package/lib/landmark-roles/index.d.ts +14 -0
  78. package/lib/landmark-roles/index.js +21 -0
  79. package/lib/landmark-roles/meta.d.ts +1 -0
  80. package/lib/landmark-roles/meta.js +1 -0
  81. package/lib/neighbor-popovers/index.d.ts +8 -0
  82. package/lib/neighbor-popovers/index.js +26 -2
  83. package/lib/neighbor-popovers/meta.d.ts +1 -0
  84. package/lib/neighbor-popovers/meta.js +1 -0
  85. package/lib/no-ambiguous-navigable-target-names/index.d.ts +8 -0
  86. package/lib/no-ambiguous-navigable-target-names/index.js +8 -0
  87. package/lib/no-ambiguous-navigable-target-names/meta.d.ts +1 -0
  88. package/lib/no-ambiguous-navigable-target-names/meta.js +1 -0
  89. package/lib/no-boolean-attr-value/index.d.ts +7 -0
  90. package/lib/no-boolean-attr-value/index.js +7 -0
  91. package/lib/no-boolean-attr-value/meta.d.ts +1 -0
  92. package/lib/no-boolean-attr-value/meta.js +1 -0
  93. package/lib/no-consecutive-br/index.d.ts +8 -0
  94. package/lib/no-consecutive-br/index.js +8 -0
  95. package/lib/no-consecutive-br/meta.d.ts +1 -0
  96. package/lib/no-consecutive-br/meta.js +1 -0
  97. package/lib/no-default-value/index.d.ts +7 -0
  98. package/lib/no-default-value/index.js +7 -0
  99. package/lib/no-default-value/meta.d.ts +1 -0
  100. package/lib/no-default-value/meta.js +1 -0
  101. package/lib/no-duplicate-dt/index.d.ts +6 -0
  102. package/lib/no-duplicate-dt/index.js +6 -0
  103. package/lib/no-duplicate-dt/meta.d.ts +1 -0
  104. package/lib/no-duplicate-dt/meta.js +1 -0
  105. package/lib/no-empty-palpable-content/index.d.ts +13 -0
  106. package/lib/no-empty-palpable-content/index.js +12 -0
  107. package/lib/no-empty-palpable-content/meta.d.ts +1 -0
  108. package/lib/no-empty-palpable-content/meta.js +1 -0
  109. package/lib/no-hard-code-id/index.d.ts +8 -0
  110. package/lib/no-hard-code-id/index.js +8 -0
  111. package/lib/no-hard-code-id/meta.d.ts +1 -0
  112. package/lib/no-hard-code-id/meta.js +1 -0
  113. package/lib/no-orphaned-end-tag/index.d.ts +7 -0
  114. package/lib/no-orphaned-end-tag/index.js +7 -0
  115. package/lib/no-orphaned-end-tag/meta.d.ts +1 -0
  116. package/lib/no-orphaned-end-tag/meta.js +1 -0
  117. package/lib/no-refer-to-non-existent-id/index.d.ts +8 -0
  118. package/lib/no-refer-to-non-existent-id/index.js +9 -0
  119. package/lib/no-refer-to-non-existent-id/meta.d.ts +1 -0
  120. package/lib/no-refer-to-non-existent-id/meta.js +1 -0
  121. package/lib/no-use-event-handler-attr/index.d.ts +10 -0
  122. package/lib/no-use-event-handler-attr/index.js +8 -0
  123. package/lib/no-use-event-handler-attr/meta.d.ts +1 -0
  124. package/lib/no-use-event-handler-attr/meta.js +1 -0
  125. package/lib/permitted-contents/choice.d.ts +17 -0
  126. package/lib/permitted-contents/choice.js +30 -0
  127. package/lib/permitted-contents/complex-branch.d.ts +11 -7
  128. package/lib/permitted-contents/complex-branch.js +11 -7
  129. package/lib/permitted-contents/content-model.d.ts +11 -0
  130. package/lib/permitted-contents/content-model.js +32 -0
  131. package/lib/permitted-contents/count-pattern.d.ts +13 -7
  132. package/lib/permitted-contents/count-pattern.js +23 -7
  133. package/lib/permitted-contents/debug.browser.d.ts +12 -0
  134. package/lib/permitted-contents/debug.browser.js +12 -0
  135. package/lib/permitted-contents/debug.d.ts +12 -0
  136. package/lib/permitted-contents/debug.js +12 -0
  137. package/lib/permitted-contents/index.d.ts +12 -0
  138. package/lib/permitted-contents/index.js +21 -0
  139. package/lib/permitted-contents/matches-selector.d.ts +19 -0
  140. package/lib/permitted-contents/matches-selector.js +33 -0
  141. package/lib/permitted-contents/meta.d.ts +1 -0
  142. package/lib/permitted-contents/meta.js +1 -0
  143. package/lib/permitted-contents/order.d.ts +14 -7
  144. package/lib/permitted-contents/order.js +14 -7
  145. package/lib/permitted-contents/recursive-branch.d.ts +17 -0
  146. package/lib/permitted-contents/recursive-branch.js +17 -0
  147. package/lib/permitted-contents/represent-transparent-nodes.d.ts +29 -0
  148. package/lib/permitted-contents/represent-transparent-nodes.js +24 -0
  149. package/lib/permitted-contents/start.d.ts +12 -6
  150. package/lib/permitted-contents/start.js +12 -6
  151. package/lib/permitted-contents/transparent.d.ts +12 -0
  152. package/lib/permitted-contents/transparent.js +12 -0
  153. package/lib/permitted-contents/types.d.ts +67 -0
  154. package/lib/permitted-contents/utils.d.ts +160 -0
  155. package/lib/permitted-contents/utils.js +194 -0
  156. package/lib/placeholder-label-option/index.d.ts +7 -0
  157. package/lib/placeholder-label-option/index.js +19 -15
  158. package/lib/placeholder-label-option/meta.d.ts +1 -0
  159. package/lib/placeholder-label-option/meta.js +1 -0
  160. package/lib/require-accessible-name/index.d.ts +11 -0
  161. package/lib/require-accessible-name/index.js +7 -0
  162. package/lib/require-accessible-name/meta.d.ts +1 -0
  163. package/lib/require-accessible-name/meta.js +1 -0
  164. package/lib/require-datetime/index.d.ts +12 -0
  165. package/lib/require-datetime/index.js +8 -0
  166. package/lib/require-datetime/meta.d.ts +1 -0
  167. package/lib/require-datetime/meta.js +1 -0
  168. package/lib/require-datetime/types.d.ts +7 -0
  169. package/lib/require-datetime/utils.d.ts +18 -5
  170. package/lib/require-datetime/utils.js +53 -9
  171. package/lib/required-attr/index.d.ts +13 -0
  172. package/lib/required-attr/index.js +7 -0
  173. package/lib/required-attr/meta.d.ts +1 -0
  174. package/lib/required-attr/meta.js +1 -0
  175. package/lib/required-element/index.d.ts +14 -0
  176. package/lib/required-element/index.js +14 -2
  177. package/lib/required-element/meta.d.ts +1 -0
  178. package/lib/required-element/meta.js +1 -0
  179. package/lib/required-h1/index.d.ts +12 -0
  180. package/lib/required-h1/index.js +7 -0
  181. package/lib/required-h1/meta.d.ts +1 -0
  182. package/lib/required-h1/meta.js +1 -0
  183. package/lib/table-row-column-alignment/find-children.d.ts +10 -0
  184. package/lib/table-row-column-alignment/find-children.js +11 -0
  185. package/lib/table-row-column-alignment/grid.d.ts +60 -0
  186. package/lib/table-row-column-alignment/grid.js +85 -0
  187. package/lib/table-row-column-alignment/index.d.ts +8 -0
  188. package/lib/table-row-column-alignment/index.js +8 -0
  189. package/lib/table-row-column-alignment/meta.d.ts +1 -0
  190. package/lib/table-row-column-alignment/meta.js +1 -0
  191. package/lib/table-row-column-alignment/types.d.ts +10 -0
  192. package/lib/use-list/index.d.ts +16 -0
  193. package/lib/use-list/index.js +20 -0
  194. package/lib/use-list/meta.d.ts +1 -0
  195. package/lib/use-list/meta.js +1 -0
  196. package/lib/wai-aria/checkings/abstract-role.d.ts +9 -0
  197. package/lib/wai-aria/checkings/abstract-role.js +9 -0
  198. package/lib/wai-aria/checkings/default-value.d.ts +11 -0
  199. package/lib/wai-aria/checkings/default-value.js +11 -0
  200. package/lib/wai-aria/checkings/deprecated-props.d.ts +11 -0
  201. package/lib/wai-aria/checkings/deprecated-props.js +11 -0
  202. package/lib/wai-aria/checkings/deprecated-role.d.ts +10 -0
  203. package/lib/wai-aria/checkings/deprecated-role.js +10 -0
  204. package/lib/wai-aria/checkings/disallowed-prop.d.ts +14 -0
  205. package/lib/wai-aria/checkings/disallowed-prop.js +14 -0
  206. package/lib/wai-aria/checkings/implicit-props.d.ts +13 -0
  207. package/lib/wai-aria/checkings/implicit-props.js +13 -0
  208. package/lib/wai-aria/checkings/implicit-role.d.ts +9 -0
  209. package/lib/wai-aria/checkings/implicit-role.js +9 -0
  210. package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +9 -0
  211. package/lib/wai-aria/checkings/interaction-in-hidden.js +15 -4
  212. package/lib/wai-aria/checkings/no-global-prop.d.ts +10 -0
  213. package/lib/wai-aria/checkings/no-global-prop.js +10 -0
  214. package/lib/wai-aria/checkings/non-existent-role.d.ts +10 -0
  215. package/lib/wai-aria/checkings/non-existent-role.js +10 -0
  216. package/lib/wai-aria/checkings/permitted-roles.d.ts +10 -0
  217. package/lib/wai-aria/checkings/permitted-roles.js +10 -0
  218. package/lib/wai-aria/checkings/presentational-children.d.ts +7 -1
  219. package/lib/wai-aria/checkings/presentational-children.js +14 -1
  220. package/lib/wai-aria/checkings/required-owned-elements.d.ts +9 -1
  221. package/lib/wai-aria/checkings/required-owned-elements.js +16 -1
  222. package/lib/wai-aria/checkings/required-prop.d.ts +13 -0
  223. package/lib/wai-aria/checkings/required-prop.js +13 -0
  224. package/lib/wai-aria/checkings/value.d.ts +23 -0
  225. package/lib/wai-aria/checkings/value.js +32 -0
  226. package/lib/wai-aria/index.d.ts +10 -0
  227. package/lib/wai-aria/index.js +10 -0
  228. package/lib/wai-aria/meta.d.ts +1 -0
  229. package/lib/wai-aria/meta.js +1 -0
  230. package/lib/wai-aria/types.d.ts +17 -0
  231. package/package.json +11 -11
@@ -2,6 +2,14 @@ import { createRule } from '@markuplint/ml-core';
2
2
  import { check } from '@markuplint/types';
3
3
  import meta from './meta.js';
4
4
  import { getCandidateDatetimeString } from './utils.js';
5
+ /**
6
+ * Rule that validates `<time>` elements without a `datetime` attribute have
7
+ * machine-readable date/time content.
8
+ *
9
+ * When a `<time>` element lacks the `datetime` attribute, this rule checks
10
+ * whether the text content is a valid datetime string. If not, it attempts
11
+ * to parse the content as natural language and suggests a `datetime` value.
12
+ */
5
13
  export default createRule({
6
14
  meta: meta,
7
15
  defaultOptions: {
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `require-datetime` rule, categorized as validation. */
1
2
  declare const _default: {
2
3
  readonly category: "validation";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `require-datetime` rule, categorized as validation. */
1
2
  export default {
2
3
  category: 'validation',
3
4
  };
@@ -1,10 +1,17 @@
1
+ /** Union of possible date/time component keys used in parsed datetime data. */
1
2
  export type DateTimeKey = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'ms';
3
+ /** A partial record mapping date/time component keys to their numeric values. */
2
4
  export type DateTimeData = Partial<Record<DateTimeKey, number>>;
5
+ /** Represents a parsed date/time value with optional timezone offset. */
3
6
  export type DateTime = {
7
+ /** The parsed date/time component values. */
4
8
  datetime: DateTimeData;
9
+ /** Timezone offset in minutes from UTC (e.g., -300 for UTC-5). */
5
10
  zone?: number;
6
11
  };
7
12
  /**
13
+ * Supported locale codes for natural language date/time parsing.
14
+ *
8
15
  * @see https://github.com/wanasit/chrono#locales
9
16
  */
10
17
  export type Lang = 'en' | 'ja' | 'fr' | 'nl' | 'ru' | 'de' | 'pt' | 'zh';
@@ -1,11 +1,24 @@
1
1
  import type { DateTime, Lang } from './types.js';
2
2
  /**
3
- * Datetime-ish text to a datetime data
3
+ * Parses natural language datetime text into structured datetime data.
4
4
  *
5
- * @param content
6
- * @param langs
7
- * @param base Reference date for a test
8
- * @returns
5
+ * Tries multiple locale parsers and returns the first successful parse result
6
+ * with only the certain (non-implied) date/time components included.
7
+ *
8
+ * @param content - The text content to parse as a datetime.
9
+ * @param langs - Locale codes to attempt parsing with.
10
+ * @param base - Optional reference date for relative date parsing (e.g., "tomorrow").
11
+ * @returns Parsed datetime data with timezone, or `null` if parsing fails.
9
12
  */
10
13
  export declare function parseADatetime(content: string, langs: readonly Lang[], base?: Readonly<Date>): DateTime | null;
14
+ /**
15
+ * Generates an HTML `datetime` attribute value from natural language text.
16
+ *
17
+ * Parses the text content using chrono-node and formats the result as an
18
+ * ISO 8601-like datetime string suitable for the `datetime` attribute.
19
+ *
20
+ * @param content - The text content to parse.
21
+ * @param langs - Locale codes to use for parsing. Defaults to all supported languages.
22
+ * @returns A formatted datetime string, or `null` if the content cannot be parsed.
23
+ */
11
24
  export declare function getCandidateDatetimeString(content: string, langs?: Lang[]): string | null;
@@ -1,12 +1,16 @@
1
1
  import * as chrono from 'chrono-node';
2
+ /** Default set of languages to try when parsing natural language datetime text. */
2
3
  const defaultLangs = ['en', 'ja', 'fr', 'nl', 'ru', 'de', 'pt', 'zh'];
3
4
  /**
4
- * Datetime-ish text to a datetime data
5
+ * Parses natural language datetime text into structured datetime data.
5
6
  *
6
- * @param content
7
- * @param langs
8
- * @param base Reference date for a test
9
- * @returns
7
+ * Tries multiple locale parsers and returns the first successful parse result
8
+ * with only the certain (non-implied) date/time components included.
9
+ *
10
+ * @param content - The text content to parse as a datetime.
11
+ * @param langs - Locale codes to attempt parsing with.
12
+ * @param base - Optional reference date for relative date parsing (e.g., "tomorrow").
13
+ * @returns Parsed datetime data with timezone, or `null` if parsing fails.
10
14
  */
11
15
  export function parseADatetime(content, langs, base) {
12
16
  const date = parseTryMultipleLangs(content, langs, base);
@@ -43,6 +47,16 @@ export function parseADatetime(content, langs, base) {
43
47
  }
44
48
  return datetime;
45
49
  }
50
+ /**
51
+ * Generates an HTML `datetime` attribute value from natural language text.
52
+ *
53
+ * Parses the text content using chrono-node and formats the result as an
54
+ * ISO 8601-like datetime string suitable for the `datetime` attribute.
55
+ *
56
+ * @param content - The text content to parse.
57
+ * @param langs - Locale codes to use for parsing. Defaults to all supported languages.
58
+ * @returns A formatted datetime string, or `null` if the content cannot be parsed.
59
+ */
46
60
  export function getCandidateDatetimeString(content, langs = defaultLangs) {
47
61
  const date = parseADatetime(content, langs);
48
62
  if (!date) {
@@ -60,6 +74,15 @@ export function getCandidateDatetimeString(content, langs = defaultLangs) {
60
74
  }
61
75
  return datetimeStr;
62
76
  }
77
+ /**
78
+ * Converts parsed datetime data into an ISO 8601-like string.
79
+ *
80
+ * Produces different formats depending on which components are present
81
+ * (e.g., date-only, time-only, or combined date-time).
82
+ *
83
+ * @param date - The parsed date/time component data.
84
+ * @returns A formatted datetime string, or `null` if the components do not match any known format.
85
+ */
63
86
  function toDatetimeString(date) {
64
87
  if (only(date, ['year', 'month'])) {
65
88
  return `${f(date.year, 4)}-${f(date.month, 2)}`;
@@ -90,6 +113,17 @@ function toDatetimeString(date) {
90
113
  }
91
114
  return null;
92
115
  }
116
+ /**
117
+ * Attempts to parse datetime text using multiple locale parsers sequentially.
118
+ *
119
+ * Returns the parsed start component from the first locale that produces a
120
+ * valid result (non-range, single datetime).
121
+ *
122
+ * @param content - The text content to parse.
123
+ * @param langs - Locale codes to try in order.
124
+ * @param base - Optional reference date for relative date parsing.
125
+ * @returns The parsed start component, or `null` if no locale succeeds.
126
+ */
93
127
  function parseTryMultipleLangs(content, langs, base) {
94
128
  for (const lang of langs) {
95
129
  const results =
@@ -111,6 +145,16 @@ function parseTryMultipleLangs(content, langs, base) {
111
145
  }
112
146
  return null;
113
147
  }
148
+ /**
149
+ * Type guard that checks if the given datetime data contains only the specified keys.
150
+ *
151
+ * @template K - The array of datetime keys to check for.
152
+ * @template U - Union of the key types.
153
+ * @template R - The resulting narrowed type with required properties.
154
+ * @param date - The datetime data to check.
155
+ * @param keys - The keys that should be the only ones present.
156
+ * @returns `true` if the date contains only the specified keys (and narrows the type).
157
+ */
114
158
  function only(date, keys) {
115
159
  const list = Object.keys(date);
116
160
  for (const exists of list) {
@@ -121,11 +165,11 @@ function only(date, keys) {
121
165
  return true;
122
166
  }
123
167
  /**
124
- * Formatter
168
+ * Formats a number with zero-padding to the specified width.
125
169
  *
126
- * @param n
127
- * @param pad zero padding
128
- * @returns
170
+ * @param n - The number to format.
171
+ * @param pad - The minimum number of digits in the output string.
172
+ * @returns The zero-padded string representation.
129
173
  */
130
174
  function f(n, pad) {
131
175
  return n.toString(10).padStart(pad, '0');
@@ -1,7 +1,20 @@
1
+ /** The rule value: either a single attribute name or an array of required attribute descriptors. */
1
2
  type RequiredAttributes = string | (string | Attr)[];
3
+ /**
4
+ * Descriptor for a required attribute with an optional set of allowed values.
5
+ */
2
6
  type Attr = {
7
+ /** The attribute name that is required. */
3
8
  name: string;
9
+ /** One or more allowed values for the attribute, if constrained. */
4
10
  value?: string | string[];
5
11
  };
12
+ /**
13
+ * Rule that validates elements have all required attributes.
14
+ *
15
+ * Checks both HTML-spec-defined required attributes and custom required attributes
16
+ * specified in the rule configuration. Also validates that required attribute values
17
+ * match expected patterns when value constraints are provided.
18
+ */
6
19
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<RequiredAttributes, undefined>>;
7
20
  export default _default;
@@ -1,6 +1,13 @@
1
1
  import { createRule, getAttrSpecs } from '@markuplint/ml-core';
2
2
  import { attrMatches, match } from '../helpers.js';
3
3
  import meta from './meta.js';
4
+ /**
5
+ * Rule that validates elements have all required attributes.
6
+ *
7
+ * Checks both HTML-spec-defined required attributes and custom required attributes
8
+ * specified in the rule configuration. Also validates that required attribute values
9
+ * match expected patterns when value constraints are provided.
10
+ */
4
11
  export default createRule({
5
12
  meta: meta,
6
13
  defaultValue: [],
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-attr` rule, categorized as validation. */
1
2
  declare const _default: {
2
3
  readonly category: "validation";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-attr` rule, categorized as validation. */
1
2
  export default {
2
3
  category: 'validation',
3
4
  };
@@ -1,5 +1,19 @@
1
+ /**
2
+ * Configuration options for the required-element rule.
3
+ */
1
4
  type Options = {
5
+ /** Whether to skip validation for elements that contain mutable (dynamic) content. */
2
6
  ignoreHasMutableContents: boolean;
7
+ /** Whether to ignore omitted (ghost) elements that are implicitly created by the HTML parser. */
8
+ ignoreOmittedElements: boolean;
3
9
  };
10
+ /**
11
+ * Rule that validates required child elements are present.
12
+ *
13
+ * Accepts an array of CSS selectors as the rule value. For the document level,
14
+ * reports if any matching element is missing from the entire document. For
15
+ * element-level overrides, checks that the specified child elements exist
16
+ * among the element's direct children.
17
+ */
4
18
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<string[], Options>>;
5
19
  export default _default;
@@ -1,16 +1,28 @@
1
1
  import { createRule } from '@markuplint/ml-core';
2
2
  import meta from './meta.js';
3
+ /**
4
+ * Rule that validates required child elements are present.
5
+ *
6
+ * Accepts an array of CSS selectors as the rule value. For the document level,
7
+ * reports if any matching element is missing from the entire document. For
8
+ * element-level overrides, checks that the specified child elements exist
9
+ * among the element's direct children.
10
+ */
3
11
  export default createRule({
4
12
  meta: meta,
5
13
  defaultValue: [],
6
14
  defaultOptions: {
7
15
  ignoreHasMutableContents: true,
16
+ ignoreOmittedElements: false,
8
17
  },
9
18
  async verify({ document, report, t }) {
10
19
  const hasMutableContent = document.nodeList.some(n => n.is(n.ELEMENT_NODE) && n.hasMutableChildren());
11
20
  if (!hasMutableContent) {
12
21
  for (const query of document.rule.value) {
13
- const exists = document.querySelectorAll(query);
22
+ const matched = document.querySelectorAll(query);
23
+ const exists = document.rule.options.ignoreOmittedElements
24
+ ? [...matched].filter(el => !el.isOmitted)
25
+ : [...matched];
14
26
  if (exists.length === 0) {
15
27
  const message = t('Require {0}', t('the "{0*}" {1}', query, 'element'));
16
28
  report({
@@ -30,7 +42,7 @@ export default createRule({
30
42
  return;
31
43
  }
32
44
  for (const query of el.rule.value) {
33
- const exists = [...el.children].find(child => child.matches(query));
45
+ const exists = [...el.children].find(child => !(el.rule.options.ignoreOmittedElements && child.isOmitted) && child.matches(query));
34
46
  if (!exists) {
35
47
  const message = t('Require {0}', t('the "{0*}" {1}', query, 'element'));
36
48
  report({
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-element` rule, categorized as validation. */
1
2
  declare const _default: {
2
3
  readonly category: "validation";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-element` rule, categorized as validation. */
1
2
  export default {
2
3
  category: 'validation',
3
4
  };
@@ -1,6 +1,18 @@
1
+ /**
2
+ * Configuration options for the required-h1 rule.
3
+ */
1
4
  export interface Options {
5
+ /** Whether to report a violation when more than one `<h1>` element is found. */
2
6
  'expected-once': boolean;
7
+ /** Whether to apply this rule in document fragments (components, partials). */
3
8
  'in-document-fragment': boolean;
4
9
  }
10
+ /**
11
+ * Rule that requires exactly one `<h1>` element in the document.
12
+ *
13
+ * Reports a violation when no `<h1>` is present. Optionally reports when
14
+ * multiple `<h1>` elements exist (controlled by `expected-once`). Can be
15
+ * configured to skip document fragments via the `in-document-fragment` option.
16
+ */
5
17
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
6
18
  export default _default;
@@ -1,5 +1,12 @@
1
1
  import { createRule } from '@markuplint/ml-core';
2
2
  import meta from './meta.js';
3
+ /**
4
+ * Rule that requires exactly one `<h1>` element in the document.
5
+ *
6
+ * Reports a violation when no `<h1>` is present. Optionally reports when
7
+ * multiple `<h1>` elements exist (controlled by `expected-once`). Can be
8
+ * configured to skip document fragments via the `in-document-fragment` option.
9
+ */
3
10
  export default createRule({
4
11
  meta: meta,
5
12
  defaultOptions: {
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-h1` rule, categorized as accessibility. */
1
2
  declare const _default: {
2
3
  readonly category: "a11y";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `required-h1` rule, categorized as accessibility. */
1
2
  export default {
2
3
  category: 'a11y',
3
4
  };
@@ -1,2 +1,12 @@
1
1
  import type { Element } from '@markuplint/ml-core';
2
+ /**
3
+ * Finds direct children of an element matching the given CSS selector, with caching.
4
+ *
5
+ * Results are cached by element UUID and selector to avoid redundant DOM traversals
6
+ * when the same element/selector combination is queried multiple times.
7
+ *
8
+ * @param el - The parent element to search within.
9
+ * @param selector - The CSS selector to match children against.
10
+ * @returns An array of matching child elements.
11
+ */
2
12
  export declare function findChildren(el: Element<boolean>, selector: string): Element<boolean, undefined>[];
@@ -1,4 +1,15 @@
1
+ /** Cache for `findChildren` results, keyed by element UUID and selector. */
1
2
  const findCache = {};
3
+ /**
4
+ * Finds direct children of an element matching the given CSS selector, with caching.
5
+ *
6
+ * Results are cached by element UUID and selector to avoid redundant DOM traversals
7
+ * when the same element/selector combination is queried multiple times.
8
+ *
9
+ * @param el - The parent element to search within.
10
+ * @param selector - The CSS selector to match children against.
11
+ * @returns An array of matching child elements.
12
+ */
2
13
  export function findChildren(
3
14
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
4
15
  el, selector) {
@@ -1,22 +1,82 @@
1
1
  import type { CellType } from './types.js';
2
2
  import type { Element } from '@markuplint/ml-core';
3
+ /**
4
+ * Represents a table as a grid model, splitting it into thead, tbody, and tfoot sections.
5
+ *
6
+ * Each section is modeled as a 2D array of `CellType` values that account for
7
+ * `colspan` and `rowspan` attributes. Used by the `table-row-column-alignment`
8
+ * rule to detect misaligned rows and overlapping cells.
9
+ */
3
10
  export declare class Grid {
4
11
  #private;
12
+ /** The grid model for the `<tbody>` section. */
5
13
  readonly tbodyGrid: ReadonlyArray<ReadonlyArray<CellType>>;
14
+ /** The grid model for the `<tfoot>` section. */
6
15
  readonly tfootGrid: ReadonlyArray<ReadonlyArray<CellType>>;
16
+ /** The grid model for the `<thead>` section. */
7
17
  readonly theadGrid: ReadonlyArray<ReadonlyArray<CellType>>;
18
+ /**
19
+ * Constructs a grid model from a `<table>` element.
20
+ *
21
+ * @param table - The table element to model.
22
+ */
8
23
  constructor(table: Element<boolean>);
24
+ /**
25
+ * Returns all `<tr>` elements across all table sections in document order.
26
+ *
27
+ * @returns Combined array of row elements from thead, tbody, and tfoot.
28
+ */
9
29
  getAllRowElements(): Element<boolean, undefined>[];
30
+ /**
31
+ * Returns all grid rows that contain at least one actual cell element.
32
+ *
33
+ * @returns Combined array of grid rows from thead, tbody, and tfoot, filtered to rows with real cells.
34
+ */
10
35
  getAllRows(): (readonly CellType[])[];
36
+ /**
37
+ * Determines the expected (base) column count for the table.
38
+ *
39
+ * Prefers the thead section if available, then tfoot, then tbody.
40
+ *
41
+ * @returns The base number of columns that rows should have.
42
+ */
11
43
  getBaseColLength(): number;
44
+ /**
45
+ * Returns the grid and row elements for each table section (thead, tbody, tfoot).
46
+ *
47
+ * @returns An array of objects, each containing the section grid and its row elements.
48
+ */
12
49
  getSections(): {
13
50
  section: readonly (readonly CellType[])[];
14
51
  elements: readonly Element<boolean, undefined>[];
15
52
  }[];
53
+ /**
54
+ * Checks whether any cell in the table grid has been marked as overlapping.
55
+ *
56
+ * @returns `true` if any cell has the overlap marker `'x'`.
57
+ */
16
58
  hasOverlapped(): boolean;
59
+ /** Logs the grid data for all three table sections to the console (for debugging). */
17
60
  log(): void;
18
61
  }
62
+ /**
63
+ * Detects a rowspan that extends beyond the available rows in a table section.
64
+ *
65
+ * When a grid row exists without a corresponding row element, it indicates
66
+ * a rowspan overflow. Returns the offending `rowspan` attribute node if found.
67
+ *
68
+ * @param rows - The grid rows for a single table section.
69
+ * @param rowElements - The `<tr>` elements for the section.
70
+ * @returns An object containing the overflowing `rowSpan` attribute, or `null`.
71
+ */
19
72
  export declare function getOverflowRowSpan(rows: ReadonlyArray<ReadonlyArray<CellType>>, rowElements: ReadonlyArray<Element<boolean>>): {
20
73
  rowSpan: import("@markuplint/ml-core").Attr<boolean, undefined>;
21
74
  } | null;
75
+ /**
76
+ * Maps each cell in a grid row to its source cell index (for cells that correspond
77
+ * to actual `<td>`/`<th>` elements), or `null` for spanned cells.
78
+ *
79
+ * @param row - A single row of cell types from the grid model.
80
+ * @returns An array of cell indices or `null` values, one per grid column.
81
+ */
22
82
  export declare function getIndexes(row: readonly CellType[]): (number | null)[];
@@ -11,12 +11,27 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _Grid_tbodyRowElements, _Grid_tfootRowElements, _Grid_theadRowElements;
13
13
  import { findChildren } from './find-children.js';
14
+ /**
15
+ * Represents a table as a grid model, splitting it into thead, tbody, and tfoot sections.
16
+ *
17
+ * Each section is modeled as a 2D array of `CellType` values that account for
18
+ * `colspan` and `rowspan` attributes. Used by the `table-row-column-alignment`
19
+ * rule to detect misaligned rows and overlapping cells.
20
+ */
14
21
  export class Grid {
22
+ /**
23
+ * Constructs a grid model from a `<table>` element.
24
+ *
25
+ * @param table - The table element to model.
26
+ */
15
27
  constructor(
16
28
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
17
29
  table) {
30
+ /** The `<tr>` elements within `<tbody>`. */
18
31
  _Grid_tbodyRowElements.set(this, void 0);
32
+ /** The `<tr>` elements within `<tfoot>`. */
19
33
  _Grid_tfootRowElements.set(this, void 0);
34
+ /** The `<tr>` elements within `<thead>`. */
20
35
  _Grid_theadRowElements.set(this, void 0);
21
36
  const thead = findChildren(table, 'thead')[0];
22
37
  const tbody = findChildren(table, 'tbody')[0];
@@ -28,9 +43,19 @@ export class Grid {
28
43
  this.tbodyGrid = createGrid(__classPrivateFieldGet(this, _Grid_tbodyRowElements, "f"));
29
44
  this.tfootGrid = createGrid(__classPrivateFieldGet(this, _Grid_tfootRowElements, "f"));
30
45
  }
46
+ /**
47
+ * Returns all `<tr>` elements across all table sections in document order.
48
+ *
49
+ * @returns Combined array of row elements from thead, tbody, and tfoot.
50
+ */
31
51
  getAllRowElements() {
32
52
  return [...__classPrivateFieldGet(this, _Grid_theadRowElements, "f"), ...__classPrivateFieldGet(this, _Grid_tbodyRowElements, "f"), ...__classPrivateFieldGet(this, _Grid_tfootRowElements, "f")];
33
53
  }
54
+ /**
55
+ * Returns all grid rows that contain at least one actual cell element.
56
+ *
57
+ * @returns Combined array of grid rows from thead, tbody, and tfoot, filtered to rows with real cells.
58
+ */
34
59
  getAllRows() {
35
60
  return [
36
61
  ...this.theadGrid.filter(hasElementFilter),
@@ -38,6 +63,13 @@ export class Grid {
38
63
  ...this.tfootGrid.filter(hasElementFilter),
39
64
  ];
40
65
  }
66
+ /**
67
+ * Determines the expected (base) column count for the table.
68
+ *
69
+ * Prefers the thead section if available, then tfoot, then tbody.
70
+ *
71
+ * @returns The base number of columns that rows should have.
72
+ */
41
73
  getBaseColLength() {
42
74
  if (this.theadGrid.length > 0) {
43
75
  return getBaseColLength(this.theadGrid);
@@ -47,6 +79,11 @@ export class Grid {
47
79
  }
48
80
  return getBaseColLength(this.tbodyGrid);
49
81
  }
82
+ /**
83
+ * Returns the grid and row elements for each table section (thead, tbody, tfoot).
84
+ *
85
+ * @returns An array of objects, each containing the section grid and its row elements.
86
+ */
50
87
  getSections() {
51
88
  return [
52
89
  {
@@ -63,11 +100,17 @@ export class Grid {
63
100
  },
64
101
  ];
65
102
  }
103
+ /**
104
+ * Checks whether any cell in the table grid has been marked as overlapping.
105
+ *
106
+ * @returns `true` if any cell has the overlap marker `'x'`.
107
+ */
66
108
  hasOverlapped() {
67
109
  return (this.tbodyGrid.some(row => row.includes('x')) ||
68
110
  this.tfootGrid.some(row => row.includes('x')) ||
69
111
  this.theadGrid.some(row => row.includes('x')));
70
112
  }
113
+ /** Logs the grid data for all three table sections to the console (for debugging). */
71
114
  log() {
72
115
  // eslint-disable-next-line no-console
73
116
  console.table(this.theadGrid);
@@ -78,6 +121,16 @@ export class Grid {
78
121
  }
79
122
  }
80
123
  _Grid_tbodyRowElements = new WeakMap(), _Grid_tfootRowElements = new WeakMap(), _Grid_theadRowElements = new WeakMap();
124
+ /**
125
+ * Detects a rowspan that extends beyond the available rows in a table section.
126
+ *
127
+ * When a grid row exists without a corresponding row element, it indicates
128
+ * a rowspan overflow. Returns the offending `rowspan` attribute node if found.
129
+ *
130
+ * @param rows - The grid rows for a single table section.
131
+ * @param rowElements - The `<tr>` elements for the section.
132
+ * @returns An object containing the overflowing `rowSpan` attribute, or `null`.
133
+ */
81
134
  export function getOverflowRowSpan(rows,
82
135
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
83
136
  rowElements) {
@@ -114,10 +167,26 @@ rowElements) {
114
167
  }
115
168
  return null;
116
169
  }
170
+ /**
171
+ * Maps each cell in a grid row to its source cell index (for cells that correspond
172
+ * to actual `<td>`/`<th>` elements), or `null` for spanned cells.
173
+ *
174
+ * @param row - A single row of cell types from the grid model.
175
+ * @returns An array of cell indices or `null` values, one per grid column.
176
+ */
117
177
  export function getIndexes(row) {
118
178
  let indexCounter = 0;
119
179
  return row.map(col => (col === '●' || col === '◎' ? indexCounter++ : null));
120
180
  }
181
+ /**
182
+ * Calculates the base (expected) column count from a section grid.
183
+ *
184
+ * For grids with 3 or more rows, uses the row length closest to the
185
+ * average to handle minor variations from spans. Otherwise uses the first row.
186
+ *
187
+ * @param grid - The 2D grid for a table section.
188
+ * @returns The base number of columns.
189
+ */
121
190
  function getBaseColLength(grid) {
122
191
  let baseColLength;
123
192
  if (grid.length >= 3) {
@@ -136,6 +205,16 @@ function getBaseColLength(grid) {
136
205
  }
137
206
  return baseColLength;
138
207
  }
208
+ /**
209
+ * Builds a 2D grid model from an array of `<tr>` elements.
210
+ *
211
+ * Processes each row's `<th>` and `<td>` cells, expanding `colspan` and `rowspan`
212
+ * attributes into the grid. Marks cells with appropriate cell types including
213
+ * span origins, continuations, and overlaps.
214
+ *
215
+ * @param rows - The `<tr>` elements to convert into a grid.
216
+ * @returns A 2D array of cell types representing the table section layout.
217
+ */
139
218
  function createGrid(
140
219
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
141
220
  rows) {
@@ -181,6 +260,12 @@ rows) {
181
260
  }
182
261
  return matrix;
183
262
  }
263
+ /**
264
+ * Filter predicate that returns `true` if a grid row contains at least one actual cell element.
265
+ *
266
+ * @param row - A single row of cell types.
267
+ * @returns `true` if the row has a regular or span-origin cell.
268
+ */
184
269
  function hasElementFilter(row) {
185
270
  return row.some(cell => cell === '●' || cell === '◎');
186
271
  }
@@ -1,2 +1,10 @@
1
+ /**
2
+ * Rule that validates table row and column alignment.
3
+ *
4
+ * Builds a grid model of each `<table>` and checks that all rows have a
5
+ * consistent number of columns, that `colspan`/`rowspan` attributes do not
6
+ * cause cell overlap, and that `rowspan` values do not exceed the available
7
+ * rows in their table section.
8
+ */
1
9
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
2
10
  export default _default;
@@ -2,6 +2,14 @@ import { createRule } from '@markuplint/ml-core';
2
2
  import { findChildren } from './find-children.js';
3
3
  import { Grid, getIndexes, getOverflowRowSpan } from './grid.js';
4
4
  import meta from './meta.js';
5
+ /**
6
+ * Rule that validates table row and column alignment.
7
+ *
8
+ * Builds a grid model of each `<table>` and checks that all rows have a
9
+ * consistent number of columns, that `colspan`/`rowspan` attributes do not
10
+ * cause cell overlap, and that `rowspan` values do not exceed the available
11
+ * rows in their table section.
12
+ */
5
13
  export default createRule({
6
14
  meta,
7
15
  defaultSeverity: 'warning',
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `table-row-column-alignment` rule, categorized as accessibility. */
1
2
  declare const _default: {
2
3
  readonly category: "a11y";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `table-row-column-alignment` rule, categorized as accessibility. */
1
2
  export default {
2
3
  category: 'a11y',
3
4
  };