@markuplint/rules 5.0.0-rc.2 → 5.0.0-rc.5

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 (573) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/CLAUDE.md +31 -2
  3. package/lib/{wai-aria-deprecated-role → aria-prop-requires-role}/index.d.ts +0 -1
  4. package/lib/{wai-aria-no-global-prop → aria-prop-requires-role}/index.js +0 -1
  5. package/lib/attr-check.d.ts +0 -48
  6. package/lib/attr-check.js +0 -36
  7. package/lib/attr-eligibility.d.ts +41 -0
  8. package/lib/attr-eligibility.js +60 -0
  9. package/lib/attr-value-quotes/index.d.ts +0 -7
  10. package/lib/attr-value-quotes/index.js +0 -7
  11. package/lib/attr-value-quotes/meta.d.ts +0 -1
  12. package/lib/attr-value-quotes/meta.js +0 -1
  13. package/lib/case-sensitive-attr-name/index.d.ts +0 -8
  14. package/lib/case-sensitive-attr-name/index.js +0 -8
  15. package/lib/case-sensitive-attr-name/meta.d.ts +0 -1
  16. package/lib/case-sensitive-attr-name/meta.js +0 -1
  17. package/lib/case-sensitive-tag-name/index.d.ts +0 -8
  18. package/lib/case-sensitive-tag-name/index.js +0 -8
  19. package/lib/case-sensitive-tag-name/meta.d.ts +0 -1
  20. package/lib/case-sensitive-tag-name/meta.js +0 -1
  21. package/lib/class-naming/index.d.ts +0 -8
  22. package/lib/class-naming/index.js +0 -8
  23. package/lib/class-naming/meta.d.ts +1 -2
  24. package/lib/class-naming/meta.js +1 -2
  25. package/lib/consistent-table-row-length/index.d.ts +14 -0
  26. package/lib/consistent-table-row-length/index.js +69 -0
  27. package/lib/consistent-table-row-length/meta.d.ts +4 -0
  28. package/lib/consistent-table-row-length/meta.js +3 -0
  29. package/lib/create-message.d.ts +2 -25
  30. package/lib/create-message.js +2 -53
  31. package/lib/debug.d.ts +1 -9
  32. package/lib/debug.js +1 -5
  33. package/lib/element-supports-aria-prop/index.d.ts +12 -0
  34. package/lib/element-supports-aria-prop/index.js +38 -0
  35. package/lib/form-attr-references-form/index.d.ts +12 -0
  36. package/lib/form-attr-references-form/index.js +64 -0
  37. package/lib/{correct-aspect-ratio → form-attr-references-form}/meta.d.ts +1 -1
  38. package/lib/form-attr-references-form/meta.js +3 -0
  39. package/lib/head-element-order/meta.d.ts +1 -1
  40. package/lib/head-element-order/meta.js +1 -1
  41. package/lib/helpers.d.ts +8 -138
  42. package/lib/helpers.js +24 -165
  43. package/lib/index.d.ts +135 -78
  44. package/lib/index.js +167 -82
  45. package/lib/input-list-references-datalist/index.d.ts +13 -0
  46. package/lib/input-list-references-datalist/index.js +46 -0
  47. package/lib/input-list-references-datalist/meta.d.ts +4 -0
  48. package/lib/input-list-references-datalist/meta.js +3 -0
  49. package/lib/itemprop-requires-itemscope/index.d.ts +21 -0
  50. package/lib/itemprop-requires-itemscope/index.js +53 -0
  51. package/lib/itemprop-requires-itemscope/meta.d.ts +4 -0
  52. package/lib/itemprop-requires-itemscope/meta.js +3 -0
  53. package/lib/label-for-references-labelable/index.d.ts +12 -0
  54. package/lib/label-for-references-labelable/index.js +68 -0
  55. package/lib/label-for-references-labelable/meta.d.ts +4 -0
  56. package/lib/label-for-references-labelable/meta.js +3 -0
  57. package/lib/label-has-control/index.d.ts +5 -5
  58. package/lib/label-has-control/index.js +5 -18
  59. package/lib/label-has-control/meta.d.ts +0 -1
  60. package/lib/label-has-control/meta.js +0 -1
  61. package/lib/label-no-multiple-controls/index.d.ts +31 -0
  62. package/lib/label-no-multiple-controls/index.js +104 -0
  63. package/lib/label-no-multiple-controls/meta.d.ts +4 -0
  64. package/lib/label-no-multiple-controls/meta.js +3 -0
  65. package/lib/landmark-roles/roles.d.ts +32 -0
  66. package/lib/landmark-roles/roles.js +73 -0
  67. package/lib/link-types/index.d.ts +0 -5
  68. package/lib/link-types/index.js +5 -6
  69. package/lib/link-types/meta.d.ts +1 -2
  70. package/lib/link-types/meta.js +1 -2
  71. package/lib/map-id-name-match/index.d.ts +10 -0
  72. package/lib/map-id-name-match/index.js +39 -0
  73. package/lib/map-id-name-match/meta.d.ts +4 -0
  74. package/lib/map-id-name-match/meta.js +3 -0
  75. package/lib/meta-charset-position/index.d.ts +15 -0
  76. package/lib/meta-charset-position/index.js +31 -0
  77. package/lib/meta-charset-position/meta.d.ts +4 -0
  78. package/lib/meta-charset-position/meta.js +3 -0
  79. package/lib/meter-value-bounds/index.d.ts +10 -0
  80. package/lib/meter-value-bounds/index.js +123 -0
  81. package/lib/meter-value-bounds/meta.d.ts +4 -0
  82. package/lib/meter-value-bounds/meta.js +3 -0
  83. package/lib/{wai-aria-required-props → no-abstract-role}/index.d.ts +0 -1
  84. package/lib/{wai-aria-abstract-role → no-abstract-role}/index.js +0 -1
  85. package/lib/no-always-matching-source/index.d.ts +13 -0
  86. package/lib/no-always-matching-source/index.js +100 -0
  87. package/lib/no-always-matching-source/meta.d.ts +4 -0
  88. package/lib/no-always-matching-source/meta.js +3 -0
  89. package/lib/no-ambiguous-navigable-target-names/index.d.ts +0 -8
  90. package/lib/no-ambiguous-navigable-target-names/index.js +0 -8
  91. package/lib/no-ambiguous-navigable-target-names/meta.d.ts +1 -2
  92. package/lib/no-ambiguous-navigable-target-names/meta.js +1 -2
  93. package/lib/{wai-aria-required-owned-elements → no-aria-on-presentational-children}/index.d.ts +0 -1
  94. package/lib/{wai-aria-presentational-children → no-aria-on-presentational-children}/index.js +0 -1
  95. package/lib/no-aria-on-unsupported-element/index.d.ts +11 -0
  96. package/lib/no-aria-on-unsupported-element/index.js +35 -0
  97. package/lib/no-aria-on-unsupported-element/meta.d.ts +9 -0
  98. package/lib/no-aria-on-unsupported-element/meta.js +8 -0
  99. package/lib/no-boolean-attr-value/index.d.ts +0 -7
  100. package/lib/no-boolean-attr-value/index.js +0 -7
  101. package/lib/no-boolean-attr-value/meta.d.ts +0 -1
  102. package/lib/no-boolean-attr-value/meta.js +0 -1
  103. package/lib/no-broken-fragment-link/index.d.ts +15 -0
  104. package/lib/no-broken-fragment-link/index.js +93 -0
  105. package/lib/no-broken-fragment-link/meta.d.ts +4 -0
  106. package/lib/no-broken-fragment-link/meta.js +3 -0
  107. package/lib/no-consecutive-br/index.d.ts +0 -8
  108. package/lib/no-consecutive-br/index.js +0 -8
  109. package/lib/no-consecutive-br/meta.d.ts +0 -1
  110. package/lib/no-consecutive-br/meta.js +0 -1
  111. package/lib/no-content-after-body/index.d.ts +25 -0
  112. package/lib/no-content-after-body/index.js +51 -0
  113. package/lib/no-content-after-body/meta.d.ts +4 -0
  114. package/lib/no-content-after-body/meta.js +3 -0
  115. package/lib/no-contradictory-aria-prop/index.d.ts +10 -0
  116. package/lib/no-contradictory-aria-prop/index.js +34 -0
  117. package/lib/{wai-aria-abstract-role → no-default-aria-value}/index.d.ts +0 -1
  118. package/lib/{wai-aria-default-value → no-default-aria-value}/index.js +0 -1
  119. package/lib/no-default-value/index.d.ts +0 -7
  120. package/lib/no-default-value/index.js +0 -7
  121. package/lib/no-default-value/meta.d.ts +0 -1
  122. package/lib/no-default-value/meta.js +0 -1
  123. package/lib/no-deprecated-aria-prop/index.d.ts +3 -0
  124. package/lib/{wai-aria-deprecated-props → no-deprecated-aria-prop}/index.js +0 -1
  125. package/lib/no-deprecated-attr/index.d.ts +2 -0
  126. package/lib/{deprecated-attr → no-deprecated-attr}/index.js +5 -9
  127. package/lib/no-deprecated-attr/meta.d.ts +4 -0
  128. package/lib/no-deprecated-attr/meta.js +3 -0
  129. package/lib/no-deprecated-element/index.d.ts +2 -0
  130. package/lib/no-deprecated-element/index.js +27 -0
  131. package/lib/no-deprecated-element/meta.d.ts +4 -0
  132. package/lib/no-deprecated-element/meta.js +3 -0
  133. package/lib/no-deprecated-role/index.d.ts +3 -0
  134. package/lib/{wai-aria-deprecated-role → no-deprecated-role}/index.js +0 -1
  135. package/lib/no-disallowed-ancestor/index.d.ts +2 -0
  136. package/lib/no-disallowed-ancestor/index.js +25 -0
  137. package/lib/no-disallowed-ancestor/meta.d.ts +4 -0
  138. package/lib/no-disallowed-ancestor/meta.js +3 -0
  139. package/lib/no-disallowed-attr/index.d.ts +28 -0
  140. package/lib/no-disallowed-attr/index.js +77 -0
  141. package/lib/no-disallowed-attr/meta.d.ts +4 -0
  142. package/lib/no-disallowed-attr/meta.js +3 -0
  143. package/lib/no-duplicate-attr/index.d.ts +2 -0
  144. package/lib/{attr-duplication → no-duplicate-attr}/index.js +0 -7
  145. package/lib/no-duplicate-attr/meta.d.ts +6 -0
  146. package/lib/no-duplicate-attr/meta.js +10 -0
  147. package/lib/no-duplicate-autofocus/index.d.ts +0 -5
  148. package/lib/no-duplicate-autofocus/index.js +20 -6
  149. package/lib/no-duplicate-autofocus/meta.d.ts +1 -1
  150. package/lib/no-duplicate-autofocus/meta.js +1 -1
  151. package/lib/no-duplicate-dt/index.d.ts +0 -6
  152. package/lib/no-duplicate-dt/index.js +1 -6
  153. package/lib/no-duplicate-dt/meta.d.ts +1 -2
  154. package/lib/no-duplicate-dt/meta.js +1 -2
  155. package/lib/no-duplicate-h1/index.d.ts +18 -0
  156. package/lib/no-duplicate-h1/index.js +41 -0
  157. package/lib/no-duplicate-h1/meta.d.ts +4 -0
  158. package/lib/no-duplicate-h1/meta.js +3 -0
  159. package/lib/no-duplicate-id/index.d.ts +2 -0
  160. package/lib/{id-duplication → no-duplicate-id}/index.js +0 -7
  161. package/lib/no-duplicate-id/meta.d.ts +4 -0
  162. package/lib/no-duplicate-id/meta.js +3 -0
  163. package/lib/no-duplicate-sibling-attr/index.d.ts +2 -0
  164. package/lib/no-duplicate-sibling-attr/index.js +35 -0
  165. package/lib/no-duplicate-sibling-attr/meta.d.ts +4 -0
  166. package/lib/no-duplicate-sibling-attr/meta.js +3 -0
  167. package/lib/no-duplicate-visible-main/index.d.ts +0 -1
  168. package/lib/no-duplicate-visible-main/index.js +0 -1
  169. package/lib/no-duplicate-visible-main/meta.d.ts +1 -1
  170. package/lib/no-duplicate-visible-main/meta.js +1 -1
  171. package/lib/no-empty-palpable-content/index.d.ts +0 -8
  172. package/lib/no-empty-palpable-content/index.js +0 -8
  173. package/lib/no-empty-palpable-content/meta.d.ts +1 -2
  174. package/lib/no-empty-palpable-content/meta.js +1 -2
  175. package/lib/no-empty-table-track/index.d.ts +12 -0
  176. package/lib/no-empty-table-track/index.js +42 -0
  177. package/lib/no-empty-table-track/meta.d.ts +4 -0
  178. package/lib/no-empty-table-track/meta.js +3 -0
  179. package/lib/no-event-handler-attr/index.d.ts +7 -0
  180. package/lib/{no-use-event-handler-attr → no-event-handler-attr}/index.js +0 -11
  181. package/lib/no-event-handler-attr/meta.d.ts +4 -0
  182. package/lib/no-event-handler-attr/meta.js +3 -0
  183. package/lib/no-experimental-features/index.d.ts +9 -0
  184. package/lib/no-experimental-features/index.js +53 -0
  185. package/lib/no-experimental-features/meta.d.ts +4 -0
  186. package/lib/no-experimental-features/meta.js +3 -0
  187. package/lib/no-extra-selected-options/index.d.ts +10 -0
  188. package/lib/no-extra-selected-options/index.js +37 -0
  189. package/lib/no-extra-selected-options/meta.d.ts +4 -0
  190. package/lib/no-extra-selected-options/meta.js +3 -0
  191. package/lib/no-focusable-in-aria-hidden/index.d.ts +3 -0
  192. package/lib/{wai-aria-interaction-in-hidden → no-focusable-in-aria-hidden}/index.js +0 -1
  193. package/lib/no-focusable-in-aria-hidden/meta.d.ts +4 -0
  194. package/lib/no-focusable-in-aria-hidden/meta.js +3 -0
  195. package/lib/no-hardcoded-id/index.d.ts +2 -0
  196. package/lib/{no-hard-code-id → no-hardcoded-id}/index.js +0 -8
  197. package/lib/no-hardcoded-id/meta.d.ts +4 -0
  198. package/lib/no-hardcoded-id/meta.js +3 -0
  199. package/lib/no-ineffective-attr/index.d.ts +2 -0
  200. package/lib/{ineffective-attr → no-ineffective-attr}/index.js +0 -7
  201. package/lib/no-ineffective-attr/meta.d.ts +5 -0
  202. package/lib/no-ineffective-attr/meta.js +4 -0
  203. package/lib/no-input-file-value/index.d.ts +10 -0
  204. package/lib/no-input-file-value/index.js +41 -0
  205. package/lib/no-input-file-value/meta.d.ts +4 -0
  206. package/lib/no-input-file-value/meta.js +3 -0
  207. package/lib/no-invalid-aria-prop-value/index.d.ts +3 -0
  208. package/lib/{wai-aria-value → no-invalid-aria-prop-value}/index.js +0 -1
  209. package/lib/no-invalid-aria-prop-value/meta.d.ts +4 -0
  210. package/lib/no-invalid-aria-prop-value/meta.js +3 -0
  211. package/lib/no-invalid-attr-value/index.d.ts +27 -0
  212. package/lib/no-invalid-attr-value/index.js +83 -0
  213. package/lib/no-invalid-attr-value/meta.d.ts +4 -0
  214. package/lib/no-invalid-attr-value/meta.js +3 -0
  215. package/lib/no-malformed-character-reference/index.d.ts +2 -0
  216. package/lib/no-malformed-character-reference/index.js +38 -0
  217. package/lib/no-malformed-character-reference/meta.d.ts +5 -0
  218. package/lib/no-malformed-character-reference/meta.js +20 -0
  219. package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/index.js +13 -3
  220. package/lib/no-mismatched-aspect-ratio/meta.d.ts +4 -0
  221. package/lib/no-mismatched-aspect-ratio/meta.js +3 -0
  222. package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/resolve-image-size.js +8 -2
  223. package/lib/no-mixed-srcset-descriptors/index.d.ts +12 -0
  224. package/lib/no-mixed-srcset-descriptors/index.js +47 -0
  225. package/lib/no-mixed-srcset-descriptors/meta.d.ts +4 -0
  226. package/lib/no-mixed-srcset-descriptors/meta.js +3 -0
  227. package/lib/no-nested-top-level-landmark/index.d.ts +10 -0
  228. package/lib/no-nested-top-level-landmark/index.js +52 -0
  229. package/lib/no-nested-top-level-landmark/meta.d.ts +4 -0
  230. package/lib/no-nested-top-level-landmark/meta.js +3 -0
  231. package/lib/no-nonstandard-features/index.d.ts +9 -0
  232. package/lib/no-nonstandard-features/index.js +53 -0
  233. package/lib/no-nonstandard-features/meta.d.ts +4 -0
  234. package/lib/no-nonstandard-features/meta.js +3 -0
  235. package/lib/no-obsolete-attr/index.d.ts +2 -0
  236. package/lib/no-obsolete-attr/index.js +27 -0
  237. package/lib/no-obsolete-attr/meta.d.ts +4 -0
  238. package/lib/no-obsolete-attr/meta.js +3 -0
  239. package/lib/no-obsolete-doctype/index.d.ts +2 -0
  240. package/lib/{doctype → no-obsolete-doctype}/index.js +9 -16
  241. package/lib/no-obsolete-doctype/meta.d.ts +4 -0
  242. package/lib/no-obsolete-doctype/meta.js +3 -0
  243. package/lib/no-obsolete-element/index.d.ts +2 -0
  244. package/lib/{deprecated-element → no-obsolete-element}/index.js +6 -10
  245. package/lib/no-obsolete-element/meta.d.ts +4 -0
  246. package/lib/no-obsolete-element/meta.js +3 -0
  247. package/lib/no-orphaned-end-tag/index.d.ts +0 -7
  248. package/lib/no-orphaned-end-tag/index.js +0 -7
  249. package/lib/no-orphaned-end-tag/meta.d.ts +2 -2
  250. package/lib/no-orphaned-end-tag/meta.js +5 -2
  251. package/lib/no-prohibited-naming/index.d.ts +8 -0
  252. package/lib/no-prohibited-naming/index.js +36 -0
  253. package/lib/no-prohibited-naming/meta.d.ts +4 -0
  254. package/lib/no-prohibited-naming/meta.js +3 -0
  255. package/lib/{use-list → no-pseudo-list}/index.d.ts +1 -8
  256. package/lib/{use-list → no-pseudo-list}/index.js +0 -7
  257. package/lib/no-pseudo-list/meta.d.ts +4 -0
  258. package/lib/no-pseudo-list/meta.js +3 -0
  259. package/lib/{redundant-accessible-name → no-redundant-accessible-name}/index.d.ts +0 -4
  260. package/lib/{redundant-accessible-name → no-redundant-accessible-name}/index.js +0 -4
  261. package/lib/no-redundant-accessible-name/meta.d.ts +4 -0
  262. package/lib/no-redundant-accessible-name/meta.js +3 -0
  263. package/lib/no-redundant-aria-prop/index.d.ts +10 -0
  264. package/lib/{wai-aria-implicit-props → no-redundant-aria-prop}/index.js +9 -3
  265. package/lib/no-redundant-aria-prop/meta.d.ts +4 -0
  266. package/lib/no-redundant-aria-prop/meta.js +3 -0
  267. package/lib/no-redundant-role/index.d.ts +3 -0
  268. package/lib/{wai-aria-implicit-role → no-redundant-role}/index.js +0 -1
  269. package/lib/no-redundant-role/meta.d.ts +4 -0
  270. package/lib/no-redundant-role/meta.js +3 -0
  271. package/lib/no-refer-to-non-existent-id/index.d.ts +0 -9
  272. package/lib/no-refer-to-non-existent-id/index.js +1 -62
  273. package/lib/no-refer-to-non-existent-id/meta.d.ts +1 -2
  274. package/lib/no-refer-to-non-existent-id/meta.js +1 -2
  275. package/lib/no-restricted-attr/index.d.ts +27 -0
  276. package/lib/no-restricted-attr/index.js +96 -0
  277. package/lib/no-restricted-attr/meta.d.ts +4 -0
  278. package/lib/no-restricted-attr/meta.js +3 -0
  279. package/lib/no-restricted-element/index.d.ts +2 -0
  280. package/lib/{disallowed-element → no-restricted-element}/index.js +7 -8
  281. package/lib/no-restricted-element/meta.d.ts +4 -0
  282. package/lib/no-restricted-element/meta.js +3 -0
  283. package/lib/no-skipped-heading-level/index.d.ts +13 -0
  284. package/lib/{heading-levels → no-skipped-heading-level}/index.js +10 -5
  285. package/lib/no-skipped-heading-level/meta.d.ts +4 -0
  286. package/lib/no-skipped-heading-level/meta.js +3 -0
  287. package/lib/no-stray-head-or-body-tag/index.d.ts +28 -0
  288. package/lib/no-stray-head-or-body-tag/index.js +61 -0
  289. package/lib/no-stray-head-or-body-tag/meta.d.ts +4 -0
  290. package/lib/no-stray-head-or-body-tag/meta.js +3 -0
  291. package/lib/no-table-cell-overlap/index.d.ts +12 -0
  292. package/lib/no-table-cell-overlap/index.js +30 -0
  293. package/lib/no-table-cell-overlap/meta.d.ts +4 -0
  294. package/lib/no-table-cell-overlap/meta.js +3 -0
  295. package/lib/no-table-span-overflow/index.d.ts +12 -0
  296. package/lib/no-table-span-overflow/index.js +37 -0
  297. package/lib/no-table-span-overflow/meta.d.ts +4 -0
  298. package/lib/no-table-span-overflow/meta.js +3 -0
  299. package/lib/no-unclosed-element-at-eof/index.d.ts +2 -0
  300. package/lib/no-unclosed-element-at-eof/index.js +86 -0
  301. package/lib/no-unclosed-element-at-eof/meta.d.ts +4 -0
  302. package/lib/no-unclosed-element-at-eof/meta.js +3 -0
  303. package/lib/no-unescaped-char/index.d.ts +14 -0
  304. package/lib/{character-reference → no-unescaped-char}/index.js +31 -20
  305. package/lib/no-unescaped-char/meta.d.ts +4 -0
  306. package/lib/no-unescaped-char/meta.js +3 -0
  307. package/lib/{invalid-attr → no-unknown-attr}/index.d.ts +4 -19
  308. package/lib/no-unknown-attr/index.js +91 -0
  309. package/lib/no-unknown-attr/meta.d.ts +4 -0
  310. package/lib/no-unknown-attr/meta.js +3 -0
  311. package/lib/no-unknown-role/index.d.ts +3 -0
  312. package/lib/{wai-aria-non-existent-role → no-unknown-role}/index.js +0 -1
  313. package/lib/no-unknown-role/meta.d.ts +4 -0
  314. package/lib/no-unknown-role/meta.js +3 -0
  315. package/lib/no-unpaired-srcset-sizes/index.d.ts +12 -0
  316. package/lib/no-unpaired-srcset-sizes/index.js +77 -0
  317. package/lib/no-unpaired-srcset-sizes/meta.d.ts +4 -0
  318. package/lib/no-unpaired-srcset-sizes/meta.js +3 -0
  319. package/lib/{no-unsupported-features → no-unsupported-browser-features}/index.d.ts +1 -10
  320. package/lib/no-unsupported-browser-features/index.js +81 -0
  321. package/lib/no-unsupported-browser-features/meta.d.ts +4 -0
  322. package/lib/no-unsupported-browser-features/meta.js +3 -0
  323. package/lib/permitted-contents/index.d.ts +0 -18
  324. package/lib/permitted-contents/index.js +0 -78
  325. package/lib/permitted-contents/meta.d.ts +1 -2
  326. package/lib/permitted-contents/meta.js +1 -2
  327. package/lib/permitted-contents/represent-transparent-nodes.js +15 -6
  328. package/lib/permitted-roles/index.d.ts +3 -0
  329. package/lib/{wai-aria-permitted-roles → permitted-roles}/index.js +0 -1
  330. package/lib/permitted-roles/meta.d.ts +4 -0
  331. package/lib/permitted-roles/meta.js +3 -0
  332. package/lib/placeholder-label-option/index.d.ts +10 -4
  333. package/lib/placeholder-label-option/index.js +30 -17
  334. package/lib/placeholder-label-option/meta.d.ts +1 -2
  335. package/lib/placeholder-label-option/meta.js +1 -2
  336. package/lib/progress-value-bounds/index.d.ts +10 -0
  337. package/lib/progress-value-bounds/index.js +59 -0
  338. package/lib/progress-value-bounds/meta.d.ts +4 -0
  339. package/lib/progress-value-bounds/meta.js +3 -0
  340. package/lib/require-accessible-name/index.d.ts +0 -7
  341. package/lib/require-accessible-name/index.js +0 -7
  342. package/lib/require-accessible-name/meta.d.ts +0 -1
  343. package/lib/require-accessible-name/meta.js +0 -1
  344. package/lib/require-adjacent-popover/index.d.ts +2 -0
  345. package/lib/{neighbor-popovers → require-adjacent-popover}/index.js +1 -8
  346. package/lib/require-adjacent-popover/meta.d.ts +4 -0
  347. package/lib/require-adjacent-popover/meta.js +3 -0
  348. package/lib/require-ancestor/index.d.ts +2 -0
  349. package/lib/require-ancestor/index.js +29 -0
  350. package/lib/require-ancestor/meta.d.ts +4 -0
  351. package/lib/require-ancestor/meta.js +3 -0
  352. package/lib/require-aria-prop/index.d.ts +3 -0
  353. package/lib/{wai-aria-required-props → require-aria-prop}/index.js +0 -1
  354. package/lib/require-aria-prop/meta.d.ts +4 -0
  355. package/lib/require-aria-prop/meta.js +3 -0
  356. package/lib/{required-attr → require-attr}/index.d.ts +2 -9
  357. package/lib/{required-attr → require-attr}/index.js +0 -7
  358. package/lib/require-attr/meta.d.ts +4 -0
  359. package/lib/require-attr/meta.js +3 -0
  360. package/lib/require-datetime/index.d.ts +0 -8
  361. package/lib/require-datetime/index.js +0 -8
  362. package/lib/require-datetime/meta.d.ts +1 -2
  363. package/lib/require-datetime/meta.js +1 -2
  364. package/lib/require-dialog-autofocus/index.d.ts +0 -10
  365. package/lib/require-dialog-autofocus/index.js +0 -10
  366. package/lib/require-dialog-autofocus/meta.d.ts +0 -1
  367. package/lib/require-dialog-autofocus/meta.js +0 -1
  368. package/lib/require-doctype/index.d.ts +2 -0
  369. package/lib/require-doctype/index.js +19 -0
  370. package/lib/require-doctype/meta.d.ts +5 -0
  371. package/lib/require-doctype/meta.js +10 -0
  372. package/lib/{required-element → require-element}/index.d.ts +1 -9
  373. package/lib/{required-element → require-element}/index.js +0 -8
  374. package/lib/require-element/meta.d.ts +4 -0
  375. package/lib/require-element/meta.js +3 -0
  376. package/lib/require-end-tag/index.d.ts +2 -0
  377. package/lib/{end-tag → require-end-tag}/index.js +0 -7
  378. package/lib/require-end-tag/meta.d.ts +4 -0
  379. package/lib/require-end-tag/meta.js +3 -0
  380. package/lib/require-h1/index.d.ts +17 -0
  381. package/lib/{required-h1 → require-h1}/index.js +6 -14
  382. package/lib/require-h1/meta.d.ts +4 -0
  383. package/lib/require-h1/meta.js +3 -0
  384. package/lib/require-landmark-label/index.d.ts +11 -0
  385. package/lib/require-landmark-label/index.js +55 -0
  386. package/lib/require-landmark-label/meta.d.ts +4 -0
  387. package/lib/require-landmark-label/meta.js +3 -0
  388. package/lib/require-owned-elements/index.d.ts +3 -0
  389. package/lib/{wai-aria-required-owned-elements → require-owned-elements}/index.js +0 -2
  390. package/lib/require-owned-elements/meta.d.ts +4 -0
  391. package/lib/require-owned-elements/meta.js +3 -0
  392. package/lib/require-parent-role/index.d.ts +3 -0
  393. package/lib/{wai-aria-required-parent-role → require-parent-role}/index.js +0 -1
  394. package/lib/require-parent-role/meta.d.ts +4 -0
  395. package/lib/require-parent-role/meta.js +3 -0
  396. package/lib/role-supports-aria-prop/index.d.ts +8 -0
  397. package/lib/{wai-aria-disallowed-props → role-supports-aria-prop}/index.js +11 -10
  398. package/lib/role-supports-aria-prop/meta.d.ts +4 -0
  399. package/lib/role-supports-aria-prop/meta.js +3 -0
  400. package/lib/rule-aliases.d.ts +2 -0
  401. package/lib/rule-aliases.js +325 -0
  402. package/lib/sizes-auto-requires-lazy-loading/index.d.ts +14 -0
  403. package/lib/sizes-auto-requires-lazy-loading/index.js +68 -0
  404. package/lib/sizes-auto-requires-lazy-loading/meta.d.ts +4 -0
  405. package/lib/sizes-auto-requires-lazy-loading/meta.js +3 -0
  406. package/lib/srcset-sizes-constraint/parse-srcset.d.ts +6 -0
  407. package/lib/srcset-sizes-constraint/parse-srcset.js +6 -0
  408. package/lib/srcset-sizes-constraint/sibling-helpers.d.ts +21 -0
  409. package/lib/srcset-sizes-constraint/sibling-helpers.js +37 -0
  410. package/lib/tab-requires-tabpanel/index.d.ts +3 -0
  411. package/lib/tab-requires-tabpanel/index.js +21 -0
  412. package/lib/tab-requires-tabpanel/meta.d.ts +4 -0
  413. package/lib/tab-requires-tabpanel/meta.js +3 -0
  414. package/lib/table-row-column-alignment/grid.d.ts +108 -52
  415. package/lib/table-row-column-alignment/grid.js +276 -203
  416. package/lib/table-row-column-alignment/types.d.ts +6 -8
  417. package/lib/usemap-references-map/index.d.ts +14 -0
  418. package/lib/usemap-references-map/index.js +46 -0
  419. package/lib/usemap-references-map/meta.d.ts +4 -0
  420. package/lib/usemap-references-map/meta.js +3 -0
  421. package/lib/valid-importmap/index.d.ts +2 -0
  422. package/lib/valid-importmap/index.js +176 -0
  423. package/lib/valid-importmap/meta.d.ts +4 -0
  424. package/lib/valid-importmap/meta.js +3 -0
  425. package/lib/valid-speculation-rules/index.d.ts +2 -0
  426. package/lib/valid-speculation-rules/index.js +292 -0
  427. package/lib/valid-speculation-rules/meta.d.ts +4 -0
  428. package/lib/valid-speculation-rules/meta.js +3 -0
  429. package/lib/wai-aria/checkings/contradictory-aria-prop.d.ts +23 -0
  430. package/lib/wai-aria/checkings/{implicit-props.js → contradictory-aria-prop.js} +22 -14
  431. package/lib/wai-aria/checkings/element-supports-aria-prop.d.ts +20 -0
  432. package/lib/wai-aria/checkings/element-supports-aria-prop.js +83 -0
  433. package/lib/wai-aria/checkings/prohibited-naming.d.ts +35 -0
  434. package/lib/wai-aria/checkings/prohibited-naming.js +64 -0
  435. package/lib/wai-aria/checkings/redundant-aria-prop.d.ts +23 -0
  436. package/lib/wai-aria/checkings/redundant-aria-prop.js +53 -0
  437. package/lib/wai-aria/checkings/required-prop.d.ts +4 -0
  438. package/lib/wai-aria/checkings/required-prop.js +16 -3
  439. package/lib/wai-aria/checkings/role-supports-aria-prop.d.ts +20 -0
  440. package/lib/wai-aria/checkings/role-supports-aria-prop.js +30 -0
  441. package/lib/wai-aria/checkings/tab-requires-tabpanel.d.ts +19 -0
  442. package/lib/wai-aria/checkings/tab-requires-tabpanel.js +56 -0
  443. package/lib/wai-aria/default-options.js +1 -0
  444. package/lib/wai-aria/types.d.ts +2 -0
  445. package/package.json +11 -10
  446. package/schema.json +275 -59
  447. package/SKILL.md +0 -77
  448. package/lib/attr-duplication/index.d.ts +0 -9
  449. package/lib/attr-duplication/meta.d.ts +0 -6
  450. package/lib/attr-duplication/meta.js +0 -5
  451. package/lib/character-reference/index.d.ts +0 -12
  452. package/lib/character-reference/meta.d.ts +0 -5
  453. package/lib/character-reference/meta.js +0 -4
  454. package/lib/correct-aspect-ratio/meta.js +0 -3
  455. package/lib/deprecated-attr/index.d.ts +0 -8
  456. package/lib/deprecated-attr/meta.d.ts +0 -5
  457. package/lib/deprecated-attr/meta.js +0 -4
  458. package/lib/deprecated-element/index.d.ts +0 -8
  459. package/lib/deprecated-element/meta.d.ts +0 -5
  460. package/lib/deprecated-element/meta.js +0 -4
  461. package/lib/disallowed-element/index.d.ts +0 -9
  462. package/lib/disallowed-element/meta.d.ts +0 -5
  463. package/lib/disallowed-element/meta.js +0 -4
  464. package/lib/doctype/index.d.ts +0 -15
  465. package/lib/doctype/meta.d.ts +0 -5
  466. package/lib/doctype/meta.js +0 -4
  467. package/lib/end-tag/index.d.ts +0 -9
  468. package/lib/end-tag/meta.d.ts +0 -5
  469. package/lib/end-tag/meta.js +0 -4
  470. package/lib/heading-levels/index.d.ts +0 -8
  471. package/lib/heading-levels/meta.d.ts +0 -5
  472. package/lib/heading-levels/meta.js +0 -4
  473. package/lib/id-duplication/index.d.ts +0 -9
  474. package/lib/id-duplication/meta.d.ts +0 -5
  475. package/lib/id-duplication/meta.js +0 -4
  476. package/lib/ineffective-attr/index.d.ts +0 -9
  477. package/lib/ineffective-attr/meta.d.ts +0 -6
  478. package/lib/ineffective-attr/meta.js +0 -5
  479. package/lib/invalid-attr/index.js +0 -207
  480. package/lib/invalid-attr/meta.d.ts +0 -5
  481. package/lib/invalid-attr/meta.js +0 -4
  482. package/lib/landmark-roles/index.d.ts +0 -22
  483. package/lib/landmark-roles/index.js +0 -142
  484. package/lib/landmark-roles/meta.d.ts +0 -5
  485. package/lib/landmark-roles/meta.js +0 -4
  486. package/lib/neighbor-popovers/index.d.ts +0 -10
  487. package/lib/neighbor-popovers/meta.d.ts +0 -5
  488. package/lib/neighbor-popovers/meta.js +0 -4
  489. package/lib/no-hard-code-id/index.d.ts +0 -10
  490. package/lib/no-hard-code-id/meta.d.ts +0 -5
  491. package/lib/no-hard-code-id/meta.js +0 -4
  492. package/lib/no-unsupported-features/index.js +0 -139
  493. package/lib/no-unsupported-features/meta.d.ts +0 -5
  494. package/lib/no-unsupported-features/meta.js +0 -4
  495. package/lib/no-use-event-handler-attr/index.d.ts +0 -18
  496. package/lib/no-use-event-handler-attr/meta.d.ts +0 -5
  497. package/lib/no-use-event-handler-attr/meta.js +0 -4
  498. package/lib/redundant-accessible-name/meta.d.ts +0 -5
  499. package/lib/redundant-accessible-name/meta.js +0 -4
  500. package/lib/required-attr/meta.d.ts +0 -5
  501. package/lib/required-attr/meta.js +0 -4
  502. package/lib/required-element/meta.d.ts +0 -5
  503. package/lib/required-element/meta.js +0 -4
  504. package/lib/required-h1/index.d.ts +0 -18
  505. package/lib/required-h1/meta.d.ts +0 -5
  506. package/lib/required-h1/meta.js +0 -4
  507. package/lib/srcset-sizes-constraint/index.d.ts +0 -6
  508. package/lib/srcset-sizes-constraint/index.js +0 -108
  509. package/lib/srcset-sizes-constraint/meta.d.ts +0 -5
  510. package/lib/srcset-sizes-constraint/meta.js +0 -4
  511. package/lib/table-row-column-alignment/index.d.ts +0 -10
  512. package/lib/table-row-column-alignment/index.js +0 -97
  513. package/lib/table-row-column-alignment/meta.d.ts +0 -5
  514. package/lib/table-row-column-alignment/meta.js +0 -4
  515. package/lib/use-list/meta.d.ts +0 -5
  516. package/lib/use-list/meta.js +0 -4
  517. package/lib/wai-aria/checkings/disallowed-prop.d.ts +0 -23
  518. package/lib/wai-aria/checkings/disallowed-prop.js +0 -84
  519. package/lib/wai-aria/checkings/implicit-props.d.ts +0 -20
  520. package/lib/wai-aria/index.d.ts +0 -13
  521. package/lib/wai-aria/index.js +0 -115
  522. package/lib/wai-aria/meta.d.ts +0 -5
  523. package/lib/wai-aria/meta.js +0 -4
  524. package/lib/wai-aria-default-value/index.d.ts +0 -4
  525. package/lib/wai-aria-default-value/meta.d.ts +0 -5
  526. package/lib/wai-aria-default-value/meta.js +0 -4
  527. package/lib/wai-aria-deprecated-props/index.d.ts +0 -4
  528. package/lib/wai-aria-deprecated-props/meta.d.ts +0 -5
  529. package/lib/wai-aria-deprecated-props/meta.js +0 -4
  530. package/lib/wai-aria-disallowed-props/index.d.ts +0 -4
  531. package/lib/wai-aria-disallowed-props/meta.d.ts +0 -5
  532. package/lib/wai-aria-disallowed-props/meta.js +0 -4
  533. package/lib/wai-aria-implicit-props/index.d.ts +0 -4
  534. package/lib/wai-aria-implicit-props/meta.d.ts +0 -5
  535. package/lib/wai-aria-implicit-props/meta.js +0 -4
  536. package/lib/wai-aria-implicit-role/index.d.ts +0 -4
  537. package/lib/wai-aria-interaction-in-hidden/index.d.ts +0 -4
  538. package/lib/wai-aria-interaction-in-hidden/meta.d.ts +0 -5
  539. package/lib/wai-aria-interaction-in-hidden/meta.js +0 -4
  540. package/lib/wai-aria-no-global-prop/index.d.ts +0 -4
  541. package/lib/wai-aria-no-global-prop/meta.d.ts +0 -5
  542. package/lib/wai-aria-no-global-prop/meta.js +0 -4
  543. package/lib/wai-aria-non-existent-role/index.d.ts +0 -4
  544. package/lib/wai-aria-permitted-roles/index.d.ts +0 -4
  545. package/lib/wai-aria-presentational-children/index.d.ts +0 -4
  546. package/lib/wai-aria-presentational-children/meta.d.ts +0 -5
  547. package/lib/wai-aria-presentational-children/meta.js +0 -4
  548. package/lib/wai-aria-required-parent-role/index.d.ts +0 -4
  549. package/lib/wai-aria-value/index.d.ts +0 -4
  550. package/lib/wai-aria-value/meta.d.ts +0 -5
  551. package/lib/wai-aria-value/meta.js +0 -4
  552. /package/lib/{wai-aria-abstract-role → aria-prop-requires-role}/meta.d.ts +0 -0
  553. /package/lib/{wai-aria-abstract-role → aria-prop-requires-role}/meta.js +0 -0
  554. /package/lib/{wai-aria-deprecated-role → element-supports-aria-prop}/meta.d.ts +0 -0
  555. /package/lib/{wai-aria-deprecated-role → element-supports-aria-prop}/meta.js +0 -0
  556. /package/lib/{wai-aria-implicit-role → no-abstract-role}/meta.d.ts +0 -0
  557. /package/lib/{wai-aria-implicit-role → no-abstract-role}/meta.js +0 -0
  558. /package/lib/{wai-aria-non-existent-role → no-aria-on-presentational-children}/meta.d.ts +0 -0
  559. /package/lib/{wai-aria-non-existent-role → no-aria-on-presentational-children}/meta.js +0 -0
  560. /package/lib/{wai-aria-permitted-roles → no-contradictory-aria-prop}/meta.d.ts +0 -0
  561. /package/lib/{wai-aria-permitted-roles → no-contradictory-aria-prop}/meta.js +0 -0
  562. /package/lib/{wai-aria-required-owned-elements → no-default-aria-value}/meta.d.ts +0 -0
  563. /package/lib/{wai-aria-required-owned-elements → no-default-aria-value}/meta.js +0 -0
  564. /package/lib/{wai-aria-required-parent-role → no-deprecated-aria-prop}/meta.d.ts +0 -0
  565. /package/lib/{wai-aria-required-parent-role → no-deprecated-aria-prop}/meta.js +0 -0
  566. /package/lib/{wai-aria-required-props → no-deprecated-role}/meta.d.ts +0 -0
  567. /package/lib/{wai-aria-required-props → no-deprecated-role}/meta.js +0 -0
  568. /package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/index.d.ts +0 -0
  569. /package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/resolve-image-size.d.ts +0 -0
  570. /package/lib/{no-unsupported-features → no-unsupported-browser-features}/compat-data.d.ts +0 -0
  571. /package/lib/{no-unsupported-features → no-unsupported-browser-features}/compat-data.js +0 -0
  572. /package/lib/{no-unsupported-features → no-unsupported-browser-features}/resolve-browsers.d.ts +0 -0
  573. /package/lib/{no-unsupported-features → no-unsupported-browser-features}/resolve-browsers.js +0 -0
@@ -0,0 +1,86 @@
1
+ import { createRule } from '@markuplint/ml-core';
2
+ import { isVoidElement } from '@markuplint/ml-spec';
3
+ import meta from './meta.js';
4
+ /**
5
+ * HTML LS "in body" insertion mode, "An end-of-file token":
6
+ *
7
+ * > If there is a node in the stack of open elements that is not either a dd
8
+ * > element, a dt element, an li element, an optgroup element, an option
9
+ * > element, a p element, an rb element, an rp element, an rt element, an
10
+ * > rtc element, a tbody element, a td element, a tfoot element, a th
11
+ * > element, a thead element, a tr element, the body element, or the html
12
+ * > element, then this is a parse error.
13
+ *
14
+ * Every name in that list has its own optional-tag-omission rule elsewhere in
15
+ * the spec, so parse5 never records an explicit end tag for it even in
16
+ * well-formed documents; excluding them keeps this rule from re-flagging
17
+ * markup that `end-tag` (a style preference, not this spec-conformance rule)
18
+ * already tolerates. Anything else still open when the source runs out —
19
+ * e.g. `<picture>`, which has no such omission rule — is this parse error.
20
+ *
21
+ * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody
22
+ */
23
+ const EOF_EXEMPT_NAMES = new Set([
24
+ 'dd',
25
+ 'dt',
26
+ 'li',
27
+ 'optgroup',
28
+ 'option',
29
+ 'p',
30
+ 'rb',
31
+ 'rp',
32
+ 'rt',
33
+ 'rtc',
34
+ 'tbody',
35
+ 'td',
36
+ 'tfoot',
37
+ 'th',
38
+ 'thead',
39
+ 'tr',
40
+ 'body',
41
+ 'html',
42
+ ]);
43
+ /**
44
+ * The end offset of a node's own content, following the last descendant to
45
+ * its end when the node itself has no end tag. Elements without an explicit
46
+ * end tag only carry a start-tag span in `raw`/`startOffset`
47
+ * (`@markuplint/html-parser`'s `nodeize`), so their children's own closing
48
+ * position is the only way to find where the element's content actually
49
+ * ends in the source.
50
+ */
51
+ function deepEndOffset(node) {
52
+ if (node.closeTag) {
53
+ return node.closeTag.startOffset + node.closeTag.raw.length;
54
+ }
55
+ const last = node.childNodes ? [...node.childNodes].at(-1) : undefined;
56
+ if (last) {
57
+ return deepEndOffset(last);
58
+ }
59
+ return node.startOffset + node.raw.length;
60
+ }
61
+ export default createRule({
62
+ meta: meta,
63
+ async verify({ document, report, t }) {
64
+ const eof = document.raw.length;
65
+ await document.walkOn('Element', el => {
66
+ if (el.isOmitted)
67
+ return;
68
+ if (isVoidElement(el))
69
+ return;
70
+ if (el.closeTag != null)
71
+ return;
72
+ if (EOF_EXEMPT_NAMES.has(el.localName))
73
+ return;
74
+ // Only the case where nothing but whitespace follows is the EOF
75
+ // case this rule targets — content implicitly closing the element
76
+ // mid-document (e.g. a sibling autoclosing it) is out of scope.
77
+ const contentEnd = deepEndOffset(el);
78
+ if (document.raw.slice(contentEnd, eof).trim() !== '')
79
+ return;
80
+ report({
81
+ scope: el,
82
+ message: t('{0} is not closed at the end of the file', t('the "{0}" {1}', el.localName, 'element')),
83
+ });
84
+ });
85
+ },
86
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "syntax";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'syntax',
3
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Configuration options for the `no-unescaped-char` rule.
3
+ */
4
+ type Option = {
5
+ /**
6
+ * When `true`, also flags `>`, `"`, and every bare `&` (not just a
7
+ * literal `<`). Off by default because HTML LS only prohibits `<` and
8
+ * ambiguous ampersands unescaped — `>` and `"` are conforming as-is, and
9
+ * a bare `&` not shaped like a reference attempt is not "ambiguous".
10
+ */
11
+ strict?: boolean;
12
+ };
13
+ declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
14
+ export default _default;
@@ -1,26 +1,29 @@
1
1
  import { createRule, getLocationFromChars } from '@markuplint/ml-core';
2
2
  import meta from './meta.js';
3
3
  /**
4
- * Characters that must be escaped using character references in HTML text
5
- * and attribute values.
4
+ * HTML LS §13.1.2.3–4 prohibits exactly two things unescaped in text content
5
+ * and attribute values: a literal `<`, and an "ambiguous ampersand" (`&`
6
+ * followed by ASCII alphanumerics and a `;` that don't form a recognized
7
+ * named/numeric reference). Detecting the latter precisely requires
8
+ * validating the name against the full named-character-reference table —
9
+ * work parse5's tokenizer already does, surfaced as `no-malformed-character-reference`
10
+ * (`unknown-named-character-reference` and friends). So by default this rule
11
+ * only checks `<`; `strict` restores the pre-split behavior of also flagging
12
+ * `>`, `"`, and every bare `&` (entity-shaped sequences still exempted, so
13
+ * `&amp;` is never flagged even in strict mode).
6
14
  */
7
- const defaultChars = ['"', '&', '<', '>'];
15
+ /** Characters that must always be escaped, regardless of `strict`. */
16
+ const defaultChars = ['<'];
17
+ /** Characters `strict: true` additionally requires to be escaped. */
18
+ const strictChars = ['"', '&', '<', '>'];
8
19
  /**
9
20
  * Parent elements whose text content is exempt from character reference checks
10
21
  * because their content is not parsed as HTML.
11
22
  */
12
23
  const ignoreParentElement = new Set(['script', 'style']);
13
- /**
14
- * Rule that checks whether special characters are properly escaped as
15
- * character references.
16
- *
17
- * Scans text nodes and attribute values for the characters `"`, `&`, `<`,
18
- * and `>` that are not already part of a valid character reference. Text
19
- * inside `<script>` and `<style>` elements is excluded, as are bogus
20
- * text nodes (e.g., orphaned end tags).
21
- */
22
24
  export default createRule({
23
25
  meta: meta,
26
+ defaultOptions: {},
24
27
  async verify({ document, report, t }) {
25
28
  const targetNodes = [];
26
29
  await document.walkOn('Text', node => {
@@ -50,21 +53,29 @@ export default createRule({
50
53
  continue;
51
54
  }
52
55
  const valueNode = attr.valueNode;
56
+ if (!valueNode) {
57
+ continue;
58
+ }
53
59
  targetNodes.push({
54
60
  scope: node,
55
- line: valueNode?.startLine,
56
- col: valueNode?.startCol,
57
- raw: valueNode?.raw,
61
+ line: valueNode.startLine,
62
+ col: valueNode.startCol,
63
+ raw: valueNode.raw,
58
64
  message,
59
65
  });
60
66
  }
61
67
  });
62
68
  for (const targetNode of targetNodes) {
63
- if (!('scope' in targetNode && 'line' in targetNode && targetNode.line != null)) {
64
- continue;
65
- }
66
- const escapedText = targetNode.raw.replaceAll(/&(?:[a-z]+|#\d+|#x[\da-f]+);/gi, $0 => '*'.repeat($0.length));
67
- for (const location of getLocationFromChars(defaultChars, escapedText, targetNode.line, targetNode.col)) {
69
+ const strict = targetNode.scope.rule.options?.strict ?? false;
70
+ const chars = strict ? strictChars : defaultChars;
71
+ // Entity-shaped sequences (`&name;`, `&#123;`, `&#x1A;`) are never
72
+ // flagged, valid name or not — an unrecognized name is
73
+ // `no-malformed-character-reference`'s concern (it mirrors parse5's
74
+ // `unknown-named-character-reference`), not this rule's.
75
+ const escapedText = strict
76
+ ? targetNode.raw.replaceAll(/&(?:[a-z]+|#\d+|#x[\da-f]+);/gi, $0 => '*'.repeat($0.length))
77
+ : targetNode.raw;
78
+ for (const location of getLocationFromChars(chars, escapedText, targetNode.line, targetNode.col)) {
68
79
  report({
69
80
  scope: targetNode.scope,
70
81
  message: targetNode.message,
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "syntax";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'syntax',
3
+ };
@@ -1,22 +1,17 @@
1
1
  import type { AttributeType } from '@markuplint/ml-spec';
2
2
  import type { Pattern } from '@markuplint/types';
3
3
  /**
4
- * Configuration options for the `invalid-attr` rule.
4
+ * Configuration options for the `no-unknown-attr` rule.
5
5
  */
6
6
  type Option = {
7
7
  /**
8
- * Attributes to allow beyond what the spec permits.
9
- * Can override spec-level restrictions such as `noUse`.
8
+ * Attribute names to treat as known, beyond what the spec defines.
9
+ * The value type is used by `no-invalid-attr-value` to validate the
10
+ * attribute's value; here it only determines whether the name is known.
10
11
  *
11
12
  * @since 3.7.0
12
13
  */
13
14
  allowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
14
- /**
15
- * Attributes to disallow in addition to spec restrictions.
16
- *
17
- * @since 3.7.0
18
- */
19
- disallowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
20
15
  /** Attribute name prefix(es) to ignore during validation. */
21
16
  ignoreAttrNamePrefix?: string | string[];
22
17
  /** Whether to allow additional properties for pretender elements (defaults to `true`). */
@@ -31,15 +26,5 @@ type Attr = {
31
26
  /** The expected attribute value type or validation rule. */
32
27
  value: AttributeType | Pattern;
33
28
  };
34
- /**
35
- * Rule that validates attributes against the HTML spec, allowed lists,
36
- * and disallowed lists.
37
- *
38
- * Checks each attribute for: existence in the spec, correct value type,
39
- * allowed/disallowed overrides from configuration, and typo suggestions
40
- * via candidate matching. Supports `allowAttrs` and `disallowAttrs`.
41
- * Non-existent attributes on elements that allow additional properties
42
- * (pretenders) can be optionally permitted.
43
- */
44
29
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
45
30
  export default _default;
@@ -0,0 +1,91 @@
1
+ import { createRule, getAttrSpecs, getSpec } from '@markuplint/ml-core';
2
+ import { resolveAttrEligibility, suggestionSuffix } from '../attr-eligibility.js';
3
+ import meta from './meta.js';
4
+ function allowedNames(allowAttrs) {
5
+ if (!allowAttrs) {
6
+ return new Set();
7
+ }
8
+ if (Array.isArray(allowAttrs)) {
9
+ return new Set(allowAttrs.map(a => (typeof a === 'string' ? a : a.name)));
10
+ }
11
+ return new Set(Object.keys(allowAttrs));
12
+ }
13
+ export default createRule({
14
+ meta: meta,
15
+ defaultOptions: {},
16
+ async verify({ document, report, t }) {
17
+ await document.walkOn('Attr', attr => {
18
+ if (attr.isDirective) {
19
+ return;
20
+ }
21
+ const allowToAddPropertiesForPretender = attr.rule.options.allowToAddPropertiesForPretender ?? true;
22
+ const name = attr.name;
23
+ const attrName = attr.nameNode;
24
+ // A parser-supplied IDL naming suggestion (e.g. `tabindex` -> `tabIndex`
25
+ // in JSX) takes priority over spec-driven typo detection below.
26
+ if (attr.ownerElement.elementType === 'html' && attr.candidate) {
27
+ report({
28
+ scope: attr,
29
+ line: attrName?.startLine,
30
+ col: attrName?.startCol,
31
+ raw: attrName?.raw,
32
+ message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
33
+ t('. ') +
34
+ t('Did you mean "{0}"?', attr.candidate),
35
+ });
36
+ return;
37
+ }
38
+ if (attr.rule.options.ignoreAttrNamePrefix != null) {
39
+ const prefixes = Array.isArray(attr.rule.options.ignoreAttrNamePrefix)
40
+ ? attr.rule.options.ignoreAttrNamePrefix
41
+ : [attr.rule.options.ignoreAttrNamePrefix];
42
+ if (prefixes.some(prefix => name.indexOf(prefix) === 0)) {
43
+ return;
44
+ }
45
+ }
46
+ if (allowedNames(attr.rule.options.allowAttrs).has(name)) {
47
+ return;
48
+ }
49
+ if (attr.ownerElement.elementType !== 'html') {
50
+ return;
51
+ }
52
+ const attrSpecs = getAttrSpecs(attr.ownerElement, document.specs);
53
+ if (!attrSpecs) {
54
+ return;
55
+ }
56
+ const eligibility = resolveAttrEligibility(name, attr.ownerElement, attrSpecs);
57
+ let message;
58
+ switch (eligibility.status) {
59
+ case 'unknown': {
60
+ message =
61
+ t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
62
+ suggestionSuffix(t, eligibility.candidate);
63
+ break;
64
+ }
65
+ case 'case-mismatch': {
66
+ message =
67
+ t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
68
+ suggestionSuffix(t, eligibility.expectedName);
69
+ break;
70
+ }
71
+ default: {
72
+ return;
73
+ }
74
+ }
75
+ if (allowToAddPropertiesForPretender && attr.ownerElement.pretenderContext?.type === 'origin') {
76
+ return;
77
+ }
78
+ const spec = getSpec(attr.ownerElement, document.specs.specs);
79
+ if (spec?.possibleToAddProperties) {
80
+ return;
81
+ }
82
+ report({
83
+ scope: attr,
84
+ message,
85
+ line: attrName?.startLine,
86
+ col: attrName?.startCol,
87
+ raw: attrName?.raw,
88
+ });
89
+ });
90
+ },
91
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "attributes";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'attributes',
3
+ };
@@ -0,0 +1,3 @@
1
+ import type { Options } from '../wai-aria/types.js';
2
+ declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
3
+ export default _default;
@@ -2,7 +2,6 @@ import { createRule, getSpec } from '@markuplint/ml-core';
2
2
  import { checkingNonExistentRole } from '../wai-aria/checkings/non-existent-role.js';
3
3
  import { defaultOptions } from '../wai-aria/default-options.js';
4
4
  import meta from './meta.js';
5
- /** Warns when a role attribute value does not exist in the WAI-ARIA specification. */
6
5
  export default createRule({
7
6
  meta,
8
7
  defaultOptions,
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "a11y";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'a11y',
3
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * HTML LS § img/source `srcset` attributes: `sizes` and a width-descriptor
3
+ * `srcset` are mutually required. Split out of the former
4
+ * `srcset-sizes-constraint` rule's Checks 1 and 5, the two directions of this
5
+ * one constraint.
6
+ *
7
+ * `<source>`'s direction (Check 5) is conditional: `sizes` "may" be omitted
8
+ * when the following sibling `<img>` has `loading="lazy"` (auto-sizes
9
+ * support). `<img>`'s direction (Check 1) has no such escape.
10
+ */
11
+ declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
12
+ export default _default;
@@ -0,0 +1,77 @@
1
+ import { createRule } from '@markuplint/ml-core';
2
+ import { parseSrcset } from '../srcset-sizes-constraint/parse-srcset.js';
3
+ import { findFollowingImg } from '../srcset-sizes-constraint/sibling-helpers.js';
4
+ import meta from './meta.js';
5
+ /**
6
+ * HTML LS § img/source `srcset` attributes: `sizes` and a width-descriptor
7
+ * `srcset` are mutually required. Split out of the former
8
+ * `srcset-sizes-constraint` rule's Checks 1 and 5, the two directions of this
9
+ * one constraint.
10
+ *
11
+ * `<source>`'s direction (Check 5) is conditional: `sizes` "may" be omitted
12
+ * when the following sibling `<img>` has `loading="lazy"` (auto-sizes
13
+ * support). `<img>`'s direction (Check 1) has no such escape.
14
+ */
15
+ export default createRule({
16
+ meta,
17
+ async verify({ document, report }) {
18
+ await document.walkOn('Element', el => {
19
+ const localName = el.localName;
20
+ // Only check img and source (inside picture) elements
21
+ if (localName !== 'img' && localName !== 'source') {
22
+ return;
23
+ }
24
+ // source is only relevant inside <picture>
25
+ if (localName === 'source' && el.parentElement?.localName !== 'picture') {
26
+ return;
27
+ }
28
+ // Skip if element has spread attributes (dynamic props)
29
+ if (el.hasSpreadAttr) {
30
+ return;
31
+ }
32
+ const srcsetAttr = el.getAttributeNode('srcset');
33
+ if (!srcsetAttr) {
34
+ return;
35
+ }
36
+ const srcsetIsDynamic = srcsetAttr.isDynamicValue;
37
+ const sizesAttr = el.getAttributeNode('sizes');
38
+ const sizesIsDynamic = sizesAttr?.isDynamicValue;
39
+ // Parse srcset unless dynamic
40
+ const parsed = srcsetIsDynamic ? null : parseSrcset(srcsetAttr.value);
41
+ // sizes present → srcset must use width descriptors
42
+ if (sizesAttr && !sizesIsDynamic && parsed && !parsed.hasWidth) {
43
+ report({
44
+ scope: el,
45
+ line: srcsetAttr.valueNode?.startLine,
46
+ col: srcsetAttr.valueNode?.startCol,
47
+ raw: srcsetAttr.valueNode?.raw,
48
+ message: 'The "srcset" attribute requires width descriptors when the "sizes" attribute is present',
49
+ });
50
+ }
51
+ // img / source-in-picture with w descriptors → sizes required.
52
+ //
53
+ // HTML LS § img srcset: unconditional — "the sizes attribute must
54
+ // also be present" when any candidate uses a width descriptor.
55
+ //
56
+ // HTML LS § source: conditional — sizes "may" be present with w
57
+ // descriptors, but the following sibling img must support
58
+ // auto-sizes for it to be omittable. img supports auto-sizes when
59
+ // loading=lazy (the dimensionsAttribute condition is also part of
60
+ // the spec but the lazy attribute is the user-facing trigger).
61
+ if (parsed && parsed.hasWidth && !sizesAttr) {
62
+ // For `<source>`, `findFollowingImg` may return null (malformed
63
+ // <picture> with no img). Optional chaining short-circuits to
64
+ // undefined, and `undefined === 'lazy'` is false → sizes is
65
+ // required. That's the correct fail-closed behaviour: an absent
66
+ // img cannot supply auto-sizes for the source.
67
+ const siblingImgLazy = localName === 'source' && findFollowingImg(el)?.getAttribute('loading') === 'lazy';
68
+ if (!siblingImgLazy) {
69
+ report({
70
+ scope: el,
71
+ message: 'The "sizes" attribute is required when the "srcset" attribute uses width descriptors',
72
+ });
73
+ }
74
+ }
75
+ });
76
+ },
77
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "attributes";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'attributes',
3
+ };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Options for the `no-unsupported-features` rule.
2
+ * Options for the `no-unsupported-browser-features` rule.
3
3
  */
4
4
  type Options = {
5
5
  /** A browserslist query to override project configuration. */
@@ -10,15 +10,6 @@ type Options = {
10
10
  readonly browserslistEnv?: string;
11
11
  /** Features to ignore. Element name ("dialog") or attribute pattern ("input[list]"). */
12
12
  readonly ignoreFeatures?: readonly string[];
13
- /** Whether to warn about experimental elements and attributes. */
14
- readonly checkExperimental?: boolean;
15
- /** Whether to warn about non-standard elements and attributes. */
16
- readonly checkNonStandard?: boolean;
17
13
  };
18
- /**
19
- * Rule that warns when using HTML elements or attributes that are not
20
- * supported by the project's target browsers (via browserslist),
21
- * or that are experimental/non-standard.
22
- */
23
14
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
24
15
  export default _default;
@@ -0,0 +1,81 @@
1
+ import { createRule } from '@markuplint/ml-core';
2
+ import { checkAttributeSupport, checkElementSupport } from './compat-data.js';
3
+ import meta from './meta.js';
4
+ import { clearBrowserslistCache, resolveTargetBrowsers } from './resolve-browsers.js';
5
+ export default createRule({
6
+ meta: meta,
7
+ defaultSeverity: 'warning',
8
+ defaultOptions: {},
9
+ async verify({ document, report, t }) {
10
+ const options = document.rule.options;
11
+ const targetBrowsers = resolveTargetBrowsers(document.filename, {
12
+ browserslist: options.browserslist,
13
+ browserslistConfig: options.browserslistConfig,
14
+ browserslistEnv: options.browserslistEnv,
15
+ });
16
+ // Without a browserslist configuration, there is nothing to check against.
17
+ if (targetBrowsers == null || targetBrowsers.length === 0) {
18
+ return;
19
+ }
20
+ const ignoreFeatures = new Set(options.ignoreFeatures);
21
+ await document.walkOn('Element', async (el) => {
22
+ // Web components and authored elements (JSX/Vue/Svelte) reach this rule
23
+ // via `pretenders`: they masquerade as a known HTML element on `el.localName`,
24
+ // so BCD lookups below resolve correctly. See #3740.
25
+ if (el.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||
26
+ (el.elementType !== 'html' && el.pretenderContext?.type !== 'pretender')) {
27
+ return;
28
+ }
29
+ const elName = el.localName;
30
+ const elOptions = el.rule.options;
31
+ const elIgnoreFeatures = new Set(elOptions.ignoreFeatures ?? ignoreFeatures);
32
+ if (!elIgnoreFeatures.has(elName)) {
33
+ const unsupported = await checkElementSupport(elName, targetBrowsers);
34
+ if (unsupported.length > 0) {
35
+ report({
36
+ scope: el,
37
+ message: formatUnsupportedMessage(t, elName, 'element', unsupported),
38
+ });
39
+ }
40
+ }
41
+ for (const attr of el.attributes) {
42
+ if (attr.isDirective) {
43
+ continue;
44
+ }
45
+ const attrName = attr.name;
46
+ const ignoreKey = `${elName}[${attrName}]`;
47
+ if (elIgnoreFeatures.has(ignoreKey)) {
48
+ continue;
49
+ }
50
+ const unsupported = await checkAttributeSupport(elName, attrName, targetBrowsers);
51
+ if (unsupported.length > 0) {
52
+ report({
53
+ scope: attr,
54
+ line: attr.nameNode?.startLine,
55
+ col: attr.nameNode?.startCol,
56
+ raw: attr.nameNode?.raw,
57
+ message: formatUnsupportedMessage(t, attrName, 'attribute', unsupported),
58
+ });
59
+ }
60
+ }
61
+ });
62
+ clearBrowserslistCache();
63
+ },
64
+ });
65
+ /**
66
+ * Format an unsupported feature message listing affected browsers.
67
+ */
68
+ function formatUnsupportedMessage(t, featureName, featureType, unsupported) {
69
+ const browserDetails = unsupported
70
+ .map(u => {
71
+ if (u.addedVersion === false) {
72
+ if (u.removedVersion) {
73
+ return `${u.displayName} (removed in ${u.removedVersion})`;
74
+ }
75
+ return `${u.displayName} (not supported)`;
76
+ }
77
+ return `${u.displayName} (added in ${u.addedVersion}, target: ${u.targetVersion})`;
78
+ })
79
+ .join(', ');
80
+ return t('{0} is not supported in {1}', t('the "{0*}" {1}', featureName, featureType), browserDetails);
81
+ }
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ readonly category: "compat";
3
+ };
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export default {
2
+ category: 'compat',
3
+ };
@@ -1,21 +1,3 @@
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. It also checks forbidden ancestor
13
- * constraints — elements like `<header>`, `<footer>`, `<main>`, and `<address>` must
14
- * not appear as descendants of certain other elements as defined by the HTML spec.
15
- * Additionally, it enforces required ancestor constraints (`descendantOf`) — certain
16
- * elements must appear as descendants of specific other elements. It also validates
17
- * sibling-unique attribute constraints (`uniqueAttrs`) — certain attributes must not
18
- * appear on more than one element of the same type within the same parent.
19
- */
20
2
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<TagRule[], Options>>;
21
3
  export default _default;