@markuplint/rules 4.11.1 → 4.12.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 +9 -3
  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 +14 -1
  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 +161 -1
  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 +10 -10
@@ -2,7 +2,16 @@ import { createRule, getAttrSpecs, ariaSpecs } from '@markuplint/ml-core';
2
2
  import { ARIA_RECOMMENDED_VERSION } from '@markuplint/ml-spec';
3
3
  import { decodeEntities, decodeHref } from '@markuplint/shared';
4
4
  import meta from './meta.js';
5
+ /** CSS selector matching hyperlink elements that have an `href` attribute. */
5
6
  const HYPERLINK_SELECTOR = 'a[href], area[href]';
7
+ /**
8
+ * Rule that validates all ID references in attributes point to existing elements.
9
+ *
10
+ * Checks DOMID and DOMID-list attributes (e.g., `for`, `aria-labelledby`),
11
+ * ARIA ID reference properties, and fragment identifiers in hyperlinks (`href="#id"`).
12
+ * Reports any reference to an ID that does not exist in the document. Skips
13
+ * validation when dynamic IDs or preprocessor blocks are detected.
14
+ */
6
15
  export default createRule({
7
16
  meta: meta,
8
17
  defaultOptions: {
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `no-refer-to-non-existent-id` 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 `no-refer-to-non-existent-id` rule, categorized as accessibility. */
1
2
  export default {
2
3
  category: 'a11y',
3
4
  };
@@ -1,5 +1,15 @@
1
+ /** Configuration options for the `no-use-event-handler-attr` rule. */
1
2
  type Options = {
3
+ /** Attribute name pattern(s) to exclude from the check. */
2
4
  ignore?: string | string[];
3
5
  };
6
+ /**
7
+ * Rule that disallows inline event handler attributes (e.g., `onclick`,
8
+ * `onchange`).
9
+ *
10
+ * Reports any attribute on an HTML element whose name starts with `on`,
11
+ * indicating an inline event handler. An `ignore` option allows specific
12
+ * attribute names or patterns to be excluded from the check.
13
+ */
4
14
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
5
15
  export default _default;
@@ -1,6 +1,14 @@
1
1
  import { createRule } from '@markuplint/ml-core';
2
2
  import { match } from '../helpers.js';
3
3
  import meta from './meta.js';
4
+ /**
5
+ * Rule that disallows inline event handler attributes (e.g., `onclick`,
6
+ * `onchange`).
7
+ *
8
+ * Reports any attribute on an HTML element whose name starts with `on`,
9
+ * indicating an inline event handler. An `ignore` option allows specific
10
+ * attribute names or patterns to be excluded from the check.
11
+ */
4
12
  export default createRule({
5
13
  meta: meta,
6
14
  defaultSeverity: 'warning',
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for `no-use-event-handler-attr`: categorized as a maintainability rule. */
1
2
  declare const _default: {
2
3
  readonly category: "maintainability";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for `no-use-event-handler-attr`: categorized as a maintainability rule. */
1
2
  export default {
2
3
  category: 'maintainability',
3
4
  };
@@ -1,4 +1,21 @@
1
1
  import type { ChildNode, Options, Result, Specs } from './types.js';
2
2
  import type { PermittedContentChoice } from '@markuplint/ml-spec';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
+ /**
5
+ * Evaluates a choice (alternation) pattern against a list of child nodes.
6
+ * Tries each branch of the choice in order and returns the first successful match.
7
+ * If no branch fully matches, selects the "barely matched" result that consumed
8
+ * the most nodes, preferring `UNEXPECTED_EXTRA_NODE` results (which indicate
9
+ * partial progress) over missing-node results.
10
+ *
11
+ * This implements the alternation (`|`) semantics found in content model definitions,
12
+ * e.g., "either flow content or phrasing content".
13
+ *
14
+ * @param pattern - The choice pattern containing multiple alternative content model branches.
15
+ * @param childNodes - The child nodes to validate against the choice branches.
16
+ * @param specs - The resolved spec data for content model lookups.
17
+ * @param options - Validation behavior options.
18
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
19
+ * @returns A result from the best-matching branch, or the branch that came closest to matching.
20
+ */
4
21
  export declare function choice(pattern: ReadonlyDeep<PermittedContentChoice>, childNodes: readonly ChildNode[], specs: Specs, options: Options, depth: number): Result;
@@ -1,7 +1,28 @@
1
1
  import { bgBlue, bgGreen, cmLog } from './debug.js';
2
2
  import { order } from './order.js';
3
3
  import { Collection, modelLog } from './utils.js';
4
+ /**
5
+ * WeakMap that tracks which choice branch index produced each result,
6
+ * used for debug logging to identify the best-matching branch.
7
+ */
4
8
  const indexes = new WeakMap();
9
+ /**
10
+ * Evaluates a choice (alternation) pattern against a list of child nodes.
11
+ * Tries each branch of the choice in order and returns the first successful match.
12
+ * If no branch fully matches, selects the "barely matched" result that consumed
13
+ * the most nodes, preferring `UNEXPECTED_EXTRA_NODE` results (which indicate
14
+ * partial progress) over missing-node results.
15
+ *
16
+ * This implements the alternation (`|`) semantics found in content model definitions,
17
+ * e.g., "either flow content or phrasing content".
18
+ *
19
+ * @param pattern - The choice pattern containing multiple alternative content model branches.
20
+ * @param childNodes - The child nodes to validate against the choice branches.
21
+ * @param specs - The resolved spec data for content model lookups.
22
+ * @param options - Validation behavior options.
23
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
24
+ * @returns A result from the best-matching branch, or the branch that came closest to matching.
25
+ */
5
26
  export function choice(pattern,
6
27
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
28
  childNodes, specs, options, depth) {
@@ -64,6 +85,15 @@ childNodes, specs, options, depth) {
64
85
  hint: barelyMatchedResult.hint,
65
86
  };
66
87
  }
88
+ /**
89
+ * Formats a debug log string for a choice pattern, highlighting the selected
90
+ * branch index with a color (green for a full match, blue for a barely-matched fallback).
91
+ *
92
+ * @param choice - The array of choice branches from the pattern.
93
+ * @param index - The index of the selected branch.
94
+ * @param barely - Whether this is a barely-matched fallback (uses blue) or a full match (uses green).
95
+ * @returns A formatted string showing all branches with the selected one highlighted.
96
+ */
67
97
  function choiceLogString(choice, index, barely = false) {
68
98
  const colorFn = barely ? bgBlue : bgGreen;
69
99
  return choice
@@ -2,13 +2,17 @@ import type { ChildNode, Options, Result, Specs } from './types.js';
2
2
  import type { PermittedContentPattern } from '@markuplint/ml-spec';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
4
  /**
5
- * Check content condition
5
+ * Dispatches a single content model pattern to the appropriate handler based on its type.
6
+ * Acts as a routing layer in the content model validation pipeline:
7
+ * - Choice patterns (alternation) are delegated to `choice`.
8
+ * - Transparent patterns are delegated to `transparent`.
9
+ * - All other quantified patterns (require, optional, oneOrMore, zeroOrMore) are delegated to `countPattern`.
6
10
  *
7
- * @param pattern
8
- * @param childNodes
9
- * @param specs
10
- * @param options
11
- * @param depth
12
- * @returns
11
+ * @param pattern - A single content model pattern to evaluate.
12
+ * @param childNodes - The child nodes to validate against the pattern.
13
+ * @param specs - The resolved spec data for content model lookups.
14
+ * @param options - Validation behavior options.
15
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
16
+ * @returns A result indicating whether the child nodes match the pattern.
13
17
  */
14
18
  export declare function complexBranch(pattern: ReadonlyDeep<PermittedContentPattern>, childNodes: readonly ChildNode[], specs: Specs, options: Options, depth: number): Result;
@@ -3,14 +3,18 @@ import { countPattern } from './count-pattern.js';
3
3
  import { transparent } from './transparent.js';
4
4
  import { isChoice, isTransparent } from './utils.js';
5
5
  /**
6
- * Check content condition
6
+ * Dispatches a single content model pattern to the appropriate handler based on its type.
7
+ * Acts as a routing layer in the content model validation pipeline:
8
+ * - Choice patterns (alternation) are delegated to `choice`.
9
+ * - Transparent patterns are delegated to `transparent`.
10
+ * - All other quantified patterns (require, optional, oneOrMore, zeroOrMore) are delegated to `countPattern`.
7
11
  *
8
- * @param pattern
9
- * @param childNodes
10
- * @param specs
11
- * @param options
12
- * @param depth
13
- * @returns
12
+ * @param pattern - A single content model pattern to evaluate.
13
+ * @param childNodes - The child nodes to validate against the pattern.
14
+ * @param specs - The resolved spec data for content model lookups.
15
+ * @param options - Validation behavior options.
16
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
17
+ * @returns A result indicating whether the child nodes match the pattern.
14
18
  */
15
19
  export function complexBranch(pattern,
16
20
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
@@ -1,2 +1,13 @@
1
1
  import type { ContentModelResult, Element, Options, TagRule } from './types.js';
2
+ /**
3
+ * Top-level entry point for content model validation of a single element.
4
+ * Resolves the element's content model from the spec (possibly augmented
5
+ * by user-defined tag rules), then delegates to `start` to validate
6
+ * the element's child nodes against that model.
7
+ *
8
+ * @param el - The element whose children are to be validated against its content model.
9
+ * @param rules - User-defined tag rules that can override or extend built-in content models.
10
+ * @param options - Validation behavior options (e.g., whether to ignore mutable children).
11
+ * @returns An array of content model results, one per child node issue found (empty if all valid).
12
+ */
2
13
  export declare function contentModel(el: Element, rules: readonly TagRule[], options: Options): ContentModelResult[];
@@ -1,5 +1,16 @@
1
1
  import { getContentModel } from '@markuplint/ml-spec';
2
2
  import { start } from './start.js';
3
+ /**
4
+ * Top-level entry point for content model validation of a single element.
5
+ * Resolves the element's content model from the spec (possibly augmented
6
+ * by user-defined tag rules), then delegates to `start` to validate
7
+ * the element's child nodes against that model.
8
+ *
9
+ * @param el - The element whose children are to be validated against its content model.
10
+ * @param rules - User-defined tag rules that can override or extend built-in content models.
11
+ * @param options - Validation behavior options (e.g., whether to ignore mutable children).
12
+ * @returns An array of content model results, one per child node issue found (empty if all valid).
13
+ */
3
14
  export function contentModel(
4
15
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
5
16
  el, rules, options) {
@@ -17,6 +28,15 @@ el, rules, options) {
17
28
  const result = start(model, el, specs, options);
18
29
  return result;
19
30
  }
31
+ /**
32
+ * Builds the content model and merged specs for a given element.
33
+ * Combines the element's document-level specs with any user-defined
34
+ * tag rules, then looks up the content model for the element.
35
+ *
36
+ * @param el - The element to look up the content model for.
37
+ * @param rules - User-defined tag rules to merge into the spec.
38
+ * @returns An object containing the resolved content model and merged specs.
39
+ */
20
40
  function createModel(
21
41
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
22
42
  el, rules) {
@@ -27,7 +47,19 @@ el, rules) {
27
47
  specs,
28
48
  };
29
49
  }
50
+ /**
51
+ * Cache for merged specs keyed by the JSON-serialized tag rules.
52
+ * Avoids re-merging the same set of user-defined tag rules on every element check.
53
+ */
30
54
  const caches = new Map();
55
+ /**
56
+ * Returns a Specs object that merges the base ML spec with user-defined
57
+ * tag rules. Results are cached by the serialized rules to avoid redundant merging.
58
+ *
59
+ * @param specs - The base ML spec from the document.
60
+ * @param rules - User-defined tag rules to merge.
61
+ * @returns The merged Specs, either from cache or freshly computed.
62
+ */
31
63
  function cachedSpecs(specs, rules) {
32
64
  if (rules.length === 0) {
33
65
  return specs;
@@ -2,13 +2,19 @@ import type { ChildNode, Options, Result, Specs } from './types.js';
2
2
  import type { PermittedContentOneOrMore, PermittedContentOptional, PermittedContentRequire, PermittedContentZeroOrMore } from '@markuplint/ml-spec';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
4
  /**
5
- * Check count
5
+ * Validates a quantified content model pattern (require, optional, oneOrMore, or zeroOrMore)
6
+ * against a list of child nodes. Repeatedly applies the inner pattern via `recursiveBranch`
7
+ * until the minimum count is satisfied and no more nodes match, or until the maximum count
8
+ * is exceeded.
6
9
  *
7
- * @param pattern
8
- * @param childNodes
9
- * @param specs
10
- * @param options
11
- * @param depth
12
- * @returns
10
+ * Implements the repetition/quantifier semantics of content models (e.g., "one or more
11
+ * flow content elements", "optionally a `<caption>`", "exactly one `<tbody>`").
12
+ *
13
+ * @param pattern - A quantified content model pattern (require, optional, oneOrMore, or zeroOrMore).
14
+ * @param childNodes - The child nodes to validate against the repeated pattern.
15
+ * @param specs - The resolved spec data for content model lookups.
16
+ * @param options - Validation behavior options.
17
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
18
+ * @returns A result indicating whether the required count of matches was achieved.
13
19
  */
14
20
  export declare function countPattern(pattern: ReadonlyDeep<PermittedContentOneOrMore> | ReadonlyDeep<PermittedContentOptional> | ReadonlyDeep<PermittedContentRequire> | ReadonlyDeep<PermittedContentZeroOrMore>, childNodes: readonly ChildNode[], specs: Specs, options: Options, depth: number): Result;
@@ -3,14 +3,20 @@ import { recursiveBranch } from './recursive-branch.js';
3
3
  import { Collection, mergeHints, modelLog, normalizeModel } from './utils.js';
4
4
  const cLog = cmLog.extend('countCompereResult');
5
5
  /**
6
- * Check count
6
+ * Validates a quantified content model pattern (require, optional, oneOrMore, or zeroOrMore)
7
+ * against a list of child nodes. Repeatedly applies the inner pattern via `recursiveBranch`
8
+ * until the minimum count is satisfied and no more nodes match, or until the maximum count
9
+ * is exceeded.
7
10
  *
8
- * @param pattern
9
- * @param childNodes
10
- * @param specs
11
- * @param options
12
- * @param depth
13
- * @returns
11
+ * Implements the repetition/quantifier semantics of content models (e.g., "one or more
12
+ * flow content elements", "optionally a `<caption>`", "exactly one `<tbody>`").
13
+ *
14
+ * @param pattern - A quantified content model pattern (require, optional, oneOrMore, or zeroOrMore).
15
+ * @param childNodes - The child nodes to validate against the repeated pattern.
16
+ * @param specs - The resolved spec data for content model lookups.
17
+ * @param options - Validation behavior options.
18
+ * @param depth - The current recursion depth, used for debug logging and nested evaluation.
19
+ * @returns A result indicating whether the required count of matches was achieved.
14
20
  */
15
21
  export function countPattern(pattern,
16
22
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
@@ -139,6 +145,16 @@ childNodes, specs, options, depth) {
139
145
  return compereResult(matchedResult, barelyResult);
140
146
  }
141
147
  }
148
+ /**
149
+ * Compares two results and returns the one that represents the best diagnostic outcome.
150
+ * When the primary result is a match or an unexpected-extra-node, it is preferred.
151
+ * Otherwise, the result with more barely-matched elements (closer to success) is chosen
152
+ * to provide the most helpful error message.
153
+ *
154
+ * @param a - The primary (current iteration) result.
155
+ * @param b - The barely-matched result from a previous successful partial match, or null.
156
+ * @returns The result that should be reported to the user.
157
+ */
142
158
  function compereResult(
143
159
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
144
160
  a,
@@ -1,29 +1,41 @@
1
1
  import type { Log } from '../debug.js';
2
+ /**
3
+ * Debug logger scoped to the content-model validation module (browser build).
4
+ * Extends the parent rule logger with a `content-model` namespace.
5
+ * In the browser environment, color helpers are no-op stubs.
6
+ */
2
7
  export declare const cmLog: Log;
8
+ /** No-op color stub for browser environments: green background. */
3
9
  export declare const bgGreen: {
4
10
  (): void;
5
11
  bold(): void;
6
12
  };
13
+ /** No-op color stub for browser environments: green foreground. */
7
14
  export declare const green: {
8
15
  (): void;
9
16
  bold(): void;
10
17
  };
18
+ /** No-op color stub for browser environments: red background. */
11
19
  export declare const bgRed: {
12
20
  (): void;
13
21
  bold(): void;
14
22
  };
23
+ /** No-op color stub for browser environments: blue background. */
15
24
  export declare const bgBlue: {
16
25
  (): void;
17
26
  bold(): void;
18
27
  };
28
+ /** No-op color stub for browser environments: blue foreground. */
19
29
  export declare const blue: {
20
30
  (): void;
21
31
  bold(): void;
22
32
  };
33
+ /** No-op color stub for browser environments: magenta background. */
23
34
  export declare const bgMagenta: {
24
35
  (): void;
25
36
  bold(): void;
26
37
  };
38
+ /** No-op color stub for browser environments: cyan foreground. */
27
39
  export declare const cyan: {
28
40
  (): void;
29
41
  bold(): void;
@@ -1,11 +1,23 @@
1
1
  import { log } from '../debug.js';
2
+ /**
3
+ * Debug logger scoped to the content-model validation module (browser build).
4
+ * Extends the parent rule logger with a `content-model` namespace.
5
+ * In the browser environment, color helpers are no-op stubs.
6
+ */
2
7
  export const cmLog = log.extend('content-model');
3
8
  const fn = () => { };
4
9
  fn.bold = () => { };
10
+ /** No-op color stub for browser environments: green background. */
5
11
  export const bgGreen = fn;
12
+ /** No-op color stub for browser environments: green foreground. */
6
13
  export const green = fn;
14
+ /** No-op color stub for browser environments: red background. */
7
15
  export const bgRed = fn;
16
+ /** No-op color stub for browser environments: blue background. */
8
17
  export const bgBlue = fn;
18
+ /** No-op color stub for browser environments: blue foreground. */
9
19
  export const blue = fn;
20
+ /** No-op color stub for browser environments: magenta background. */
10
21
  export const bgMagenta = fn;
22
+ /** No-op color stub for browser environments: cyan foreground. */
11
23
  export const cyan = fn;
@@ -1,10 +1,22 @@
1
1
  import type { Log } from '../debug.js';
2
2
  import color from 'ansi-colors';
3
+ /**
4
+ * Debug logger scoped to the content-model validation module.
5
+ * Extends the parent rule logger with a `content-model` namespace
6
+ * for structured debug output during content model evaluation.
7
+ */
3
8
  export declare const cmLog: Log;
9
+ /** ANSI color helper: green background for highlighting locked-and-matched nodes in debug output. */
4
10
  export declare const bgGreen: color.StyleFunction;
11
+ /** ANSI color helper: green foreground for highlighting matched nodes in debug output. */
5
12
  export declare const green: color.StyleFunction;
13
+ /** ANSI color helper: red background for highlighting unexpected/extra nodes in debug output. */
6
14
  export declare const bgRed: color.StyleFunction;
15
+ /** ANSI color helper: blue background for highlighting locked-and-matched transparent nodes in debug output. */
7
16
  export declare const bgBlue: color.StyleFunction;
17
+ /** ANSI color helper: blue foreground for highlighting matched transparent nodes in debug output. */
8
18
  export declare const blue: color.StyleFunction;
19
+ /** ANSI color helper: magenta background for highlighting unexpected transparent nodes in debug output. */
9
20
  export declare const bgMagenta: color.StyleFunction;
21
+ /** ANSI color helper: cyan foreground for highlighting unmatched transparent nodes in debug output. */
10
22
  export declare const cyan: color.StyleFunction;
@@ -1,10 +1,22 @@
1
1
  import color from 'ansi-colors';
2
2
  import { log } from '../debug.js';
3
+ /**
4
+ * Debug logger scoped to the content-model validation module.
5
+ * Extends the parent rule logger with a `content-model` namespace
6
+ * for structured debug output during content model evaluation.
7
+ */
3
8
  export const cmLog = log.extend('content-model');
9
+ /** ANSI color helper: green background for highlighting locked-and-matched nodes in debug output. */
4
10
  export const bgGreen = color.bgGreen;
11
+ /** ANSI color helper: green foreground for highlighting matched nodes in debug output. */
5
12
  export const green = color.green;
13
+ /** ANSI color helper: red background for highlighting unexpected/extra nodes in debug output. */
6
14
  export const bgRed = color.bgRed;
15
+ /** ANSI color helper: blue background for highlighting locked-and-matched transparent nodes in debug output. */
7
16
  export const bgBlue = color.bgBlue;
17
+ /** ANSI color helper: blue foreground for highlighting matched transparent nodes in debug output. */
8
18
  export const blue = color.blue;
19
+ /** ANSI color helper: magenta background for highlighting unexpected transparent nodes in debug output. */
9
20
  export const bgMagenta = color.bgMagenta;
21
+ /** ANSI color helper: cyan foreground for highlighting unmatched transparent nodes in debug output. */
10
22
  export const cyan = color.cyan;
@@ -1,3 +1,15 @@
1
1
  import type { Options, TagRule } from './types.js';
2
+ /**
3
+ * The `permitted-contents` rule validates that each element's child nodes conform
4
+ * to the HTML content model specification. It is the most complex rule in markuplint,
5
+ * implementing a full content model validation engine that handles ordered sequences,
6
+ * quantified patterns (require, optional, oneOrMore, zeroOrMore), choice alternations,
7
+ * transparent content models, and conditional child node branches.
8
+ *
9
+ * For each element, it resolves the applicable content model (from the HTML spec or
10
+ * user-defined tag rules), evaluates the element's children against that model, and
11
+ * reports violations such as unexpected elements, missing required elements, or
12
+ * disallowed content through transparent models.
13
+ */
2
14
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<TagRule[], Options>>;
3
15
  export default _default;
@@ -2,6 +2,18 @@ import { createRule } from '@markuplint/ml-core';
2
2
  import { contentModel } from './content-model.js';
3
3
  import meta from './meta.js';
4
4
  import { transparentMode } from './represent-transparent-nodes.js';
5
+ /**
6
+ * The `permitted-contents` rule validates that each element's child nodes conform
7
+ * to the HTML content model specification. It is the most complex rule in markuplint,
8
+ * implementing a full content model validation engine that handles ordered sequences,
9
+ * quantified patterns (require, optional, oneOrMore, zeroOrMore), choice alternations,
10
+ * transparent content models, and conditional child node branches.
11
+ *
12
+ * For each element, it resolves the applicable content model (from the HTML spec or
13
+ * user-defined tag rules), evaluates the element's children against that model, and
14
+ * reports violations such as unexpected elements, missing required elements, or
15
+ * disallowed content through transparent models.
16
+ */
5
17
  export default createRule({
6
18
  meta: meta,
7
19
  defaultValue: [],
@@ -91,6 +103,15 @@ export default createRule({
91
103
  });
92
104
  },
93
105
  });
106
+ /**
107
+ * Generates a localized, human-readable name for a child node based on its type.
108
+ * Used in error messages to describe the offending node (e.g., 'the "div" element',
109
+ * 'the text node', 'the comment', 'the doctype', 'the code block').
110
+ *
111
+ * @param scope - The child node to generate a name for.
112
+ * @param t - The translator function for localized message formatting.
113
+ * @returns A localized string describing the node.
114
+ */
94
115
  function name(
95
116
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
96
117
  scope, t) {
@@ -1,3 +1,22 @@
1
1
  import type { ChildNode, Result, Specs } from './types.js';
2
+ /**
3
+ * Extended result type for selector matching that includes additional
4
+ * intermediate states: a selector that did not match but allows empty content,
5
+ * a missing node, or unmatched selectors with partial matches.
6
+ */
2
7
  export type SelectorResult = Result<'UNMATCHED_SELECTOR_BUT_MAY_EMPTY' | 'MISSING_NODE' | 'UNMATCHED_SELECTORS'>;
8
+ /**
9
+ * Tests whether a single child node matches a content model query selector.
10
+ * Handles special node types (text nodes, preprocessor blocks, custom elements)
11
+ * and delegates standard element matching to the CSS selector engine.
12
+ *
13
+ * The query string may reference content model categories (e.g., `#phrasing`)
14
+ * which are expanded to concrete tag selectors via `optCondition`.
15
+ *
16
+ * @param query - The content model query string (e.g., `"div"`, `"#phrasing"`, `":model(flow)"`).
17
+ * @param childNode - The child node to test, or undefined if no node is available.
18
+ * @param specs - The resolved spec data for category-to-tag-name expansion.
19
+ * @param depth - The current recursion depth, used for debug logging namespacing.
20
+ * @returns A selector result indicating match status with diagnostic hints.
21
+ */
3
22
  export declare function matchesSelector(query: string, childNode: ChildNode | undefined, specs: Specs, depth: number): SelectorResult;
@@ -1,6 +1,20 @@
1
1
  import { contentModelCategoryToTagNames } from '@markuplint/ml-spec';
2
2
  import { cmLog } from './debug.js';
3
3
  import { cleanObject, matches } from './utils.js';
4
+ /**
5
+ * Tests whether a single child node matches a content model query selector.
6
+ * Handles special node types (text nodes, preprocessor blocks, custom elements)
7
+ * and delegates standard element matching to the CSS selector engine.
8
+ *
9
+ * The query string may reference content model categories (e.g., `#phrasing`)
10
+ * which are expanded to concrete tag selectors via `optCondition`.
11
+ *
12
+ * @param query - The content model query string (e.g., `"div"`, `"#phrasing"`, `":model(flow)"`).
13
+ * @param childNode - The child node to test, or undefined if no node is available.
14
+ * @param specs - The resolved spec data for category-to-tag-name expansion.
15
+ * @param depth - The current recursion depth, used for debug logging namespacing.
16
+ * @returns A selector result indicating match status with diagnostic hints.
17
+ */
4
18
  export function matchesSelector(query,
5
19
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
6
20
  childNode, specs, depth) {
@@ -127,6 +141,9 @@ childNode, specs, depth) {
127
141
  hint: {},
128
142
  };
129
143
  }
144
+ /**
145
+ * Pre-computed conditions for well-known queries that do not depend on specs.
146
+ */
130
147
  const conditionWithoutSpecs = {
131
148
  '#custom': {
132
149
  selector: '#custom',
@@ -139,7 +156,23 @@ const conditionWithoutSpecs = {
139
156
  hasText: true,
140
157
  },
141
158
  };
159
+ /**
160
+ * Cache of parsed conditions keyed by specs instance and query string.
161
+ * Prevents redundant category expansion for the same query across multiple elements.
162
+ */
142
163
  const optConditionSpecsBaseCaches = new Map();
164
+ /**
165
+ * Parses a content model query string into a Condition object by expanding
166
+ * content model category references (e.g., `#phrasing`, `:model(flow)`) into
167
+ * concrete CSS `:is(...)` selectors. Also detects whether the query implicitly
168
+ * includes custom elements or text nodes.
169
+ *
170
+ * Results are cached per specs instance and query string.
171
+ *
172
+ * @param query - The raw content model query string to parse.
173
+ * @param specs - The spec data used to resolve category names to tag lists.
174
+ * @returns A readonly Condition with the resolved selector and flags.
175
+ */
143
176
  function optCondition(query, specs) {
144
177
  const condWithoutSpecs = conditionWithoutSpecs[query];
145
178
  if (condWithoutSpecs) {
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `permitted-contents` validation rule. */
1
2
  declare const _default: {
2
3
  readonly category: "validation";
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Rule metadata for the `permitted-contents` validation rule. */
1
2
  export default {
2
3
  category: 'validation',
3
4
  };
@@ -2,13 +2,20 @@ import type { ChildNode, Options, Result, Specs } from './types.js';
2
2
  import type { PermittedContentPattern } from '@markuplint/ml-spec';
3
3
  import type { ReadonlyDeep } from 'type-fest';
4
4
  /**
5
- * Check ordered array
5
+ * Validates an ordered sequence of content model patterns against a list of child nodes.
6
+ * Each pattern in the `contents` array is matched in order against the remaining unmatched
7
+ * child nodes, consuming nodes as they match. This implements the sequential composition
8
+ * semantics of HTML content models (e.g., "a `<caption>` followed by zero or more `<colgroup>`s
9
+ * followed by a `<thead>`...").
6
10
  *
7
- * @param contents
8
- * @param childNodes
9
- * @param specs
10
- * @param options
11
- * @param depth
12
- * @returns
11
+ * Supports backtracking: when a pattern matches zero nodes (zeroMatch), the algorithm
12
+ * can backtrack to try the next pattern from the previous position if the current pattern fails.
13
+ *
14
+ * @param contents - An ordered array of content model patterns to match sequentially.
15
+ * @param childNodes - The child nodes to validate against the patterns.
16
+ * @param specs - The resolved spec data for content model lookups.
17
+ * @param options - Validation behavior options.
18
+ * @param depth - The current recursion depth, used for debug logging and nested pattern matching.
19
+ * @returns A result indicating overall match status and the matched/unmatched node partitioning.
13
20
  */
14
21
  export declare function order(contents: ReadonlyDeep<PermittedContentPattern[]>, childNodes: readonly ChildNode[], specs: Specs, options: Options, depth: number): Result;