chaffjs 0.27.1 → 0.29.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 (923) hide show
  1. package/README.md +2 -1
  2. package/dist/ai-score/of-document.d.ts.map +1 -1
  3. package/dist/ai-score/of-document.js +23 -14
  4. package/dist/ai-score/of-document.js.map +1 -1
  5. package/dist/ai-score/render.d.ts.map +1 -1
  6. package/dist/ai-score/render.js +13 -4
  7. package/dist/ai-score/render.js.map +1 -1
  8. package/dist/ai-score/score.d.ts +16 -1
  9. package/dist/ai-score/score.d.ts.map +1 -1
  10. package/dist/ai-score/score.js +15 -3
  11. package/dist/ai-score/score.js.map +1 -1
  12. package/dist/ai-score/signals.d.ts +2 -4
  13. package/dist/ai-score/signals.d.ts.map +1 -1
  14. package/dist/ai-score/signals.js +11 -2
  15. package/dist/ai-score/signals.js.map +1 -1
  16. package/dist/ai-score/text.d.ts +2 -0
  17. package/dist/ai-score/text.d.ts.map +1 -1
  18. package/dist/ai-score/text.js +4 -2
  19. package/dist/ai-score/text.js.map +1 -1
  20. package/dist/announced-count.d.ts +2 -0
  21. package/dist/announced-count.d.ts.map +1 -1
  22. package/dist/announced-count.js +14 -7
  23. package/dist/announced-count.js.map +1 -1
  24. package/dist/check-source.d.ts +3 -1
  25. package/dist/check-source.d.ts.map +1 -1
  26. package/dist/check-source.js +3 -1
  27. package/dist/check-source.js.map +1 -1
  28. package/dist/cli-text.d.ts.map +1 -1
  29. package/dist/cli-text.js +42 -18
  30. package/dist/cli-text.js.map +1 -1
  31. package/dist/cli.d.ts.map +1 -1
  32. package/dist/cli.js +2 -1
  33. package/dist/cli.js.map +1 -1
  34. package/dist/commands/cite-claims.d.ts +36 -0
  35. package/dist/commands/cite-claims.d.ts.map +1 -0
  36. package/dist/commands/cite-claims.js +81 -0
  37. package/dist/commands/cite-claims.js.map +1 -0
  38. package/dist/commands/cite-page.d.ts +14 -0
  39. package/dist/commands/cite-page.d.ts.map +1 -0
  40. package/dist/commands/cite-page.js +47 -0
  41. package/dist/commands/cite-page.js.map +1 -0
  42. package/dist/commands/cite-scaffold.d.ts +16 -0
  43. package/dist/commands/cite-scaffold.d.ts.map +1 -0
  44. package/dist/commands/cite-scaffold.js +21 -0
  45. package/dist/commands/cite-scaffold.js.map +1 -0
  46. package/dist/commands/cite.d.ts +3 -12
  47. package/dist/commands/cite.d.ts.map +1 -1
  48. package/dist/commands/cite.js +110 -51
  49. package/dist/commands/cite.js.map +1 -1
  50. package/dist/company-names.d.ts +34 -0
  51. package/dist/company-names.d.ts.map +1 -0
  52. package/dist/company-names.js +158 -0
  53. package/dist/company-names.js.map +1 -0
  54. package/dist/default-values.d.ts +17 -0
  55. package/dist/default-values.d.ts.map +1 -0
  56. package/dist/default-values.js +134 -0
  57. package/dist/default-values.js.map +1 -0
  58. package/dist/deprecated-use.d.ts +17 -0
  59. package/dist/deprecated-use.d.ts.map +1 -0
  60. package/dist/deprecated-use.js +95 -0
  61. package/dist/deprecated-use.js.map +1 -0
  62. package/dist/derived/number-word-counts.d.ts +10 -0
  63. package/dist/derived/number-word-counts.d.ts.map +1 -0
  64. package/dist/derived/number-word-counts.js +21 -0
  65. package/dist/derived/number-word-counts.js.map +1 -0
  66. package/dist/derived/stays.d.ts +43 -0
  67. package/dist/derived/stays.d.ts.map +1 -0
  68. package/dist/derived/stays.js +105 -0
  69. package/dist/derived/stays.js.map +1 -0
  70. package/dist/detectors/acronym-context.d.ts +2 -2
  71. package/dist/detectors/acronym-context.d.ts.map +1 -1
  72. package/dist/detectors/acronym-context.js +6 -0
  73. package/dist/detectors/acronym-context.js.map +1 -1
  74. package/dist/detectors/address-word.d.ts +3 -0
  75. package/dist/detectors/address-word.d.ts.map +1 -0
  76. package/dist/detectors/address-word.js +7 -0
  77. package/dist/detectors/address-word.js.map +1 -0
  78. package/dist/detectors/agreement-slip.d.ts.map +1 -1
  79. package/dist/detectors/agreement-slip.js +4 -1
  80. package/dist/detectors/agreement-slip.js.map +1 -1
  81. package/dist/detectors/ai-phrasing.d.ts +0 -4
  82. package/dist/detectors/ai-phrasing.d.ts.map +1 -1
  83. package/dist/detectors/ai-phrasing.js +5 -1
  84. package/dist/detectors/ai-phrasing.js.map +1 -1
  85. package/dist/detectors/amount-range.d.ts +3 -0
  86. package/dist/detectors/amount-range.d.ts.map +1 -0
  87. package/dist/detectors/amount-range.js +38 -0
  88. package/dist/detectors/amount-range.js.map +1 -0
  89. package/dist/detectors/amount-scale.d.ts +8 -0
  90. package/dist/detectors/amount-scale.d.ts.map +1 -0
  91. package/dist/detectors/amount-scale.js +74 -0
  92. package/dist/detectors/amount-scale.js.map +1 -0
  93. package/dist/detectors/announced-count.d.ts +1 -1
  94. package/dist/detectors/announced-count.d.ts.map +1 -1
  95. package/dist/detectors/announced-count.js +18 -3
  96. package/dist/detectors/announced-count.js.map +1 -1
  97. package/dist/detectors/bare-comparative.d.ts.map +1 -1
  98. package/dist/detectors/bare-comparative.js +4 -1
  99. package/dist/detectors/bare-comparative.js.map +1 -1
  100. package/dist/detectors/block-quotation.d.ts +13 -0
  101. package/dist/detectors/block-quotation.d.ts.map +1 -0
  102. package/dist/detectors/block-quotation.js +86 -0
  103. package/dist/detectors/block-quotation.js.map +1 -0
  104. package/dist/detectors/bracket-label.d.ts +10 -0
  105. package/dist/detectors/bracket-label.d.ts.map +1 -0
  106. package/dist/detectors/bracket-label.js +51 -0
  107. package/dist/detectors/bracket-label.js.map +1 -0
  108. package/dist/detectors/change-rate.d.ts.map +1 -1
  109. package/dist/detectors/change-rate.js +12 -1
  110. package/dist/detectors/change-rate.js.map +1 -1
  111. package/dist/detectors/citation-entry.d.ts +5 -0
  112. package/dist/detectors/citation-entry.d.ts.map +1 -1
  113. package/dist/detectors/citation-entry.js +19 -5
  114. package/dist/detectors/citation-entry.js.map +1 -1
  115. package/dist/detectors/code-before.d.ts +6 -0
  116. package/dist/detectors/code-before.d.ts.map +1 -0
  117. package/dist/detectors/code-before.js +15 -0
  118. package/dist/detectors/code-before.js.map +1 -0
  119. package/dist/detectors/connective-hierarchy.d.ts +11 -1
  120. package/dist/detectors/connective-hierarchy.d.ts.map +1 -1
  121. package/dist/detectors/connective-hierarchy.js +26 -6
  122. package/dist/detectors/connective-hierarchy.js.map +1 -1
  123. package/dist/detectors/currency-notation.d.ts +3 -1
  124. package/dist/detectors/currency-notation.d.ts.map +1 -1
  125. package/dist/detectors/currency-notation.js +4 -3
  126. package/dist/detectors/currency-notation.js.map +1 -1
  127. package/dist/detectors/date-outside-period.d.ts +4 -0
  128. package/dist/detectors/date-outside-period.d.ts.map +1 -0
  129. package/dist/detectors/date-outside-period.js +34 -0
  130. package/dist/detectors/date-outside-period.js.map +1 -0
  131. package/dist/detectors/default-values.d.ts +3 -0
  132. package/dist/detectors/default-values.d.ts.map +1 -0
  133. package/dist/detectors/default-values.js +14 -0
  134. package/dist/detectors/default-values.js.map +1 -0
  135. package/dist/detectors/defined-term-form.d.ts +6 -2
  136. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  137. package/dist/detectors/defined-term-form.js +72 -12
  138. package/dist/detectors/defined-term-form.js.map +1 -1
  139. package/dist/detectors/definition-use.d.ts.map +1 -1
  140. package/dist/detectors/definition-use.js +8 -1
  141. package/dist/detectors/definition-use.js.map +1 -1
  142. package/dist/detectors/deprecated-use.d.ts +3 -0
  143. package/dist/detectors/deprecated-use.d.ts.map +1 -0
  144. package/dist/detectors/deprecated-use.js +14 -0
  145. package/dist/detectors/deprecated-use.js.map +1 -0
  146. package/dist/detectors/derived-numbers.d.ts +1 -1
  147. package/dist/detectors/derived-numbers.d.ts.map +1 -1
  148. package/dist/detectors/derived-numbers.js +79 -16
  149. package/dist/detectors/derived-numbers.js.map +1 -1
  150. package/dist/detectors/document-shape.d.ts +1 -0
  151. package/dist/detectors/document-shape.d.ts.map +1 -1
  152. package/dist/detectors/document-shape.js +4 -1
  153. package/dist/detectors/document-shape.js.map +1 -1
  154. package/dist/detectors/due-date.d.ts +3 -0
  155. package/dist/detectors/due-date.d.ts.map +1 -0
  156. package/dist/detectors/due-date.js +38 -0
  157. package/dist/detectors/due-date.js.map +1 -0
  158. package/dist/detectors/en-shape.d.ts.map +1 -1
  159. package/dist/detectors/en-shape.js +17 -9
  160. package/dist/detectors/en-shape.js.map +1 -1
  161. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  162. package/dist/detectors/fact-consistency.js +89 -2
  163. package/dist/detectors/fact-consistency.js.map +1 -1
  164. package/dist/detectors/heading-echo.d.ts.map +1 -1
  165. package/dist/detectors/heading-echo.js +10 -1
  166. package/dist/detectors/heading-echo.js.map +1 -1
  167. package/dist/detectors/kana-function-word.d.ts +12 -0
  168. package/dist/detectors/kana-function-word.d.ts.map +1 -0
  169. package/dist/detectors/kana-function-word.js +59 -0
  170. package/dist/detectors/kana-function-word.js.map +1 -0
  171. package/dist/detectors/line-amount.d.ts +3 -0
  172. package/dist/detectors/line-amount.d.ts.map +1 -0
  173. package/dist/detectors/line-amount.js +22 -0
  174. package/dist/detectors/line-amount.js.map +1 -0
  175. package/dist/detectors/location-pointer.d.ts +6 -0
  176. package/dist/detectors/location-pointer.d.ts.map +1 -0
  177. package/dist/detectors/location-pointer.js +22 -0
  178. package/dist/detectors/location-pointer.js.map +1 -0
  179. package/dist/detectors/mark-shape.d.ts.map +1 -1
  180. package/dist/detectors/mark-shape.js +13 -1
  181. package/dist/detectors/mark-shape.js.map +1 -1
  182. package/dist/detectors/nado-closed-list.d.ts +3 -0
  183. package/dist/detectors/nado-closed-list.d.ts.map +1 -0
  184. package/dist/detectors/nado-closed-list.js +21 -0
  185. package/dist/detectors/nado-closed-list.js.map +1 -0
  186. package/dist/detectors/name-variant.d.ts.map +1 -1
  187. package/dist/detectors/name-variant.js +92 -10
  188. package/dist/detectors/name-variant.js.map +1 -1
  189. package/dist/detectors/next-word.d.ts.map +1 -1
  190. package/dist/detectors/next-word.js +41 -8
  191. package/dist/detectors/next-word.js.map +1 -1
  192. package/dist/detectors/number-word-figure.d.ts +5 -0
  193. package/dist/detectors/number-word-figure.d.ts.map +1 -0
  194. package/dist/detectors/number-word-figure.js +32 -0
  195. package/dist/detectors/number-word-figure.js.map +1 -0
  196. package/dist/detectors/obligation-without-deadline.d.ts +39 -0
  197. package/dist/detectors/obligation-without-deadline.d.ts.map +1 -0
  198. package/dist/detectors/obligation-without-deadline.js +148 -0
  199. package/dist/detectors/obligation-without-deadline.js.map +1 -0
  200. package/dist/detectors/open-end-names.d.ts +23 -0
  201. package/dist/detectors/open-end-names.d.ts.map +1 -0
  202. package/dist/detectors/open-end-names.js +95 -0
  203. package/dist/detectors/open-end-names.js.map +1 -0
  204. package/dist/detectors/ordinal-run-gaps.d.ts +8 -0
  205. package/dist/detectors/ordinal-run-gaps.d.ts.map +1 -0
  206. package/dist/detectors/ordinal-run-gaps.js +80 -0
  207. package/dist/detectors/ordinal-run-gaps.js.map +1 -0
  208. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  209. package/dist/detectors/orthographic-variant.js +26 -9
  210. package/dist/detectors/orthographic-variant.js.map +1 -1
  211. package/dist/detectors/orthography.d.ts.map +1 -1
  212. package/dist/detectors/orthography.js +5 -0
  213. package/dist/detectors/orthography.js.map +1 -1
  214. package/dist/detectors/parameter-table.d.ts +3 -0
  215. package/dist/detectors/parameter-table.d.ts.map +1 -0
  216. package/dist/detectors/parameter-table.js +16 -0
  217. package/dist/detectors/parameter-table.js.map +1 -0
  218. package/dist/detectors/phone-number-variant.d.ts +3 -0
  219. package/dist/detectors/phone-number-variant.d.ts.map +1 -0
  220. package/dist/detectors/phone-number-variant.js +18 -0
  221. package/dist/detectors/phone-number-variant.js.map +1 -0
  222. package/dist/detectors/prerequisite-order.d.ts +3 -0
  223. package/dist/detectors/prerequisite-order.d.ts.map +1 -0
  224. package/dist/detectors/prerequisite-order.js +30 -0
  225. package/dist/detectors/prerequisite-order.js.map +1 -0
  226. package/dist/detectors/quote-unnamed-speaker.d.ts +3 -0
  227. package/dist/detectors/quote-unnamed-speaker.d.ts.map +1 -0
  228. package/dist/detectors/quote-unnamed-speaker.js +18 -0
  229. package/dist/detectors/quote-unnamed-speaker.js.map +1 -0
  230. package/dist/detectors/quote-without-source.d.ts +12 -2
  231. package/dist/detectors/quote-without-source.d.ts.map +1 -1
  232. package/dist/detectors/quote-without-source.js +45 -11
  233. package/dist/detectors/quote-without-source.js.map +1 -1
  234. package/dist/detectors/registry/amount-range.d.ts +3 -0
  235. package/dist/detectors/registry/amount-range.d.ts.map +1 -0
  236. package/dist/detectors/registry/amount-range.js +3 -0
  237. package/dist/detectors/registry/amount-range.js.map +1 -0
  238. package/dist/detectors/registry/amount-scale.d.ts +3 -0
  239. package/dist/detectors/registry/amount-scale.d.ts.map +1 -0
  240. package/dist/detectors/registry/amount-scale.js +3 -0
  241. package/dist/detectors/registry/amount-scale.js.map +1 -0
  242. package/dist/detectors/registry/arrival-before-departure.d.ts +3 -0
  243. package/dist/detectors/registry/arrival-before-departure.d.ts.map +1 -0
  244. package/dist/detectors/registry/arrival-before-departure.js +3 -0
  245. package/dist/detectors/registry/arrival-before-departure.js.map +1 -0
  246. package/dist/detectors/registry/date-outside-period.d.ts +3 -0
  247. package/dist/detectors/registry/date-outside-period.d.ts.map +1 -0
  248. package/dist/detectors/registry/date-outside-period.js +3 -0
  249. package/dist/detectors/registry/date-outside-period.js.map +1 -0
  250. package/dist/detectors/registry/default-values.d.ts +3 -0
  251. package/dist/detectors/registry/default-values.d.ts.map +1 -0
  252. package/dist/detectors/registry/default-values.js +3 -0
  253. package/dist/detectors/registry/default-values.js.map +1 -0
  254. package/dist/detectors/registry/deprecated-use.d.ts +3 -0
  255. package/dist/detectors/registry/deprecated-use.d.ts.map +1 -0
  256. package/dist/detectors/registry/deprecated-use.js +3 -0
  257. package/dist/detectors/registry/deprecated-use.js.map +1 -0
  258. package/dist/detectors/registry/due-date.d.ts +3 -0
  259. package/dist/detectors/registry/due-date.d.ts.map +1 -0
  260. package/dist/detectors/registry/due-date.js +3 -0
  261. package/dist/detectors/registry/due-date.js.map +1 -0
  262. package/dist/detectors/registry/kana-function-word.d.ts +3 -0
  263. package/dist/detectors/registry/kana-function-word.d.ts.map +1 -0
  264. package/dist/detectors/registry/kana-function-word.js +3 -0
  265. package/dist/detectors/registry/kana-function-word.js.map +1 -0
  266. package/dist/detectors/registry/line-amount.d.ts +3 -0
  267. package/dist/detectors/registry/line-amount.d.ts.map +1 -0
  268. package/dist/detectors/registry/line-amount.js +3 -0
  269. package/dist/detectors/registry/line-amount.js.map +1 -0
  270. package/dist/detectors/registry/nado-closed-list.d.ts +3 -0
  271. package/dist/detectors/registry/nado-closed-list.d.ts.map +1 -0
  272. package/dist/detectors/registry/nado-closed-list.js +3 -0
  273. package/dist/detectors/registry/nado-closed-list.js.map +1 -0
  274. package/dist/detectors/registry/number-word-figure.d.ts +3 -0
  275. package/dist/detectors/registry/number-word-figure.d.ts.map +1 -0
  276. package/dist/detectors/registry/number-word-figure.js +3 -0
  277. package/dist/detectors/registry/number-word-figure.js.map +1 -0
  278. package/dist/detectors/registry/obligation-without-deadline.d.ts +3 -0
  279. package/dist/detectors/registry/obligation-without-deadline.d.ts.map +1 -0
  280. package/dist/detectors/registry/obligation-without-deadline.js +3 -0
  281. package/dist/detectors/registry/obligation-without-deadline.js.map +1 -0
  282. package/dist/detectors/registry/parameter-table.d.ts +3 -0
  283. package/dist/detectors/registry/parameter-table.d.ts.map +1 -0
  284. package/dist/detectors/registry/parameter-table.js +3 -0
  285. package/dist/detectors/registry/parameter-table.js.map +1 -0
  286. package/dist/detectors/registry/phone-number-variant.d.ts +3 -0
  287. package/dist/detectors/registry/phone-number-variant.d.ts.map +1 -0
  288. package/dist/detectors/registry/phone-number-variant.js +3 -0
  289. package/dist/detectors/registry/phone-number-variant.js.map +1 -0
  290. package/dist/detectors/registry/prerequisite-order.d.ts +3 -0
  291. package/dist/detectors/registry/prerequisite-order.d.ts.map +1 -0
  292. package/dist/detectors/registry/prerequisite-order.js +3 -0
  293. package/dist/detectors/registry/prerequisite-order.js.map +1 -0
  294. package/dist/detectors/registry/quote-unnamed-speaker.d.ts +3 -0
  295. package/dist/detectors/registry/quote-unnamed-speaker.d.ts.map +1 -0
  296. package/dist/detectors/registry/quote-unnamed-speaker.js +3 -0
  297. package/dist/detectors/registry/quote-unnamed-speaker.js.map +1 -0
  298. package/dist/detectors/registry/tax-amount.d.ts +3 -0
  299. package/dist/detectors/registry/tax-amount.d.ts.map +1 -0
  300. package/dist/detectors/registry/tax-amount.js +3 -0
  301. package/dist/detectors/registry/tax-amount.js.map +1 -0
  302. package/dist/detectors/registry/time-order.d.ts +3 -0
  303. package/dist/detectors/registry/time-order.d.ts.map +1 -0
  304. package/dist/detectors/registry/time-order.js +3 -0
  305. package/dist/detectors/registry/time-order.js.map +1 -0
  306. package/dist/detectors/registry/ui-label.d.ts +3 -0
  307. package/dist/detectors/registry/ui-label.d.ts.map +1 -0
  308. package/dist/detectors/registry/ui-label.js +3 -0
  309. package/dist/detectors/registry/ui-label.js.map +1 -0
  310. package/dist/detectors/registry/undefined-call.d.ts +3 -0
  311. package/dist/detectors/registry/undefined-call.d.ts.map +1 -0
  312. package/dist/detectors/registry/undefined-call.js +3 -0
  313. package/dist/detectors/registry/undefined-call.js.map +1 -0
  314. package/dist/detectors/registry/undefined-term.d.ts +3 -0
  315. package/dist/detectors/registry/undefined-term.d.ts.map +1 -0
  316. package/dist/detectors/registry/undefined-term.js +3 -0
  317. package/dist/detectors/registry/undefined-term.js.map +1 -0
  318. package/dist/detectors/registry/version-order.d.ts +3 -0
  319. package/dist/detectors/registry/version-order.d.ts.map +1 -0
  320. package/dist/detectors/registry/version-order.js +3 -0
  321. package/dist/detectors/registry/version-order.js.map +1 -0
  322. package/dist/detectors/registry/warning-action.d.ts +3 -0
  323. package/dist/detectors/registry/warning-action.d.ts.map +1 -0
  324. package/dist/detectors/registry/warning-action.js +3 -0
  325. package/dist/detectors/registry/warning-action.js.map +1 -0
  326. package/dist/detectors/requirement-smell.d.ts.map +1 -1
  327. package/dist/detectors/requirement-smell.js +25 -8
  328. package/dist/detectors/requirement-smell.js.map +1 -1
  329. package/dist/detectors/structure-tree.d.ts +12 -4
  330. package/dist/detectors/structure-tree.d.ts.map +1 -1
  331. package/dist/detectors/structure-tree.js +31 -14
  332. package/dist/detectors/structure-tree.js.map +1 -1
  333. package/dist/detectors/superlative-scope.d.ts.map +1 -1
  334. package/dist/detectors/superlative-scope.js +11 -1
  335. package/dist/detectors/superlative-scope.js.map +1 -1
  336. package/dist/detectors/tax-amount.d.ts +3 -0
  337. package/dist/detectors/tax-amount.d.ts.map +1 -0
  338. package/dist/detectors/tax-amount.js +19 -0
  339. package/dist/detectors/tax-amount.js.map +1 -0
  340. package/dist/detectors/technical-docs.d.ts.map +1 -1
  341. package/dist/detectors/technical-docs.js +5 -1
  342. package/dist/detectors/technical-docs.js.map +1 -1
  343. package/dist/detectors/term-extension.d.ts +14 -0
  344. package/dist/detectors/term-extension.d.ts.map +1 -0
  345. package/dist/detectors/term-extension.js +67 -0
  346. package/dist/detectors/term-extension.js.map +1 -0
  347. package/dist/detectors/time-order.d.ts +4 -0
  348. package/dist/detectors/time-order.d.ts.map +1 -0
  349. package/dist/detectors/time-order.js +32 -0
  350. package/dist/detectors/time-order.js.map +1 -0
  351. package/dist/detectors/ui-label.d.ts +3 -0
  352. package/dist/detectors/ui-label.d.ts.map +1 -0
  353. package/dist/detectors/ui-label.js +16 -0
  354. package/dist/detectors/ui-label.js.map +1 -0
  355. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
  356. package/dist/detectors/unbalanced-bracket.js +8 -13
  357. package/dist/detectors/unbalanced-bracket.js.map +1 -1
  358. package/dist/detectors/undefined-call.d.ts +3 -0
  359. package/dist/detectors/undefined-call.d.ts.map +1 -0
  360. package/dist/detectors/undefined-call.js +18 -0
  361. package/dist/detectors/undefined-call.js.map +1 -0
  362. package/dist/detectors/undefined-term.d.ts +22 -0
  363. package/dist/detectors/undefined-term.d.ts.map +1 -0
  364. package/dist/detectors/undefined-term.js +85 -0
  365. package/dist/detectors/undefined-term.js.map +1 -0
  366. package/dist/detectors/unknown-word.d.ts +1 -1
  367. package/dist/detectors/unknown-word.js +3 -3
  368. package/dist/detectors/unknown-word.js.map +1 -1
  369. package/dist/detectors/vague-deadline.d.ts +4 -0
  370. package/dist/detectors/vague-deadline.d.ts.map +1 -1
  371. package/dist/detectors/vague-deadline.js +3 -3
  372. package/dist/detectors/vague-deadline.js.map +1 -1
  373. package/dist/detectors/version-mismatch.d.ts.map +1 -1
  374. package/dist/detectors/version-mismatch.js +18 -1
  375. package/dist/detectors/version-mismatch.js.map +1 -1
  376. package/dist/detectors/version-order.d.ts +3 -0
  377. package/dist/detectors/version-order.d.ts.map +1 -0
  378. package/dist/detectors/version-order.js +43 -0
  379. package/dist/detectors/version-order.js.map +1 -0
  380. package/dist/detectors/warning-action.d.ts +3 -0
  381. package/dist/detectors/warning-action.d.ts.map +1 -0
  382. package/dist/detectors/warning-action.js +48 -0
  383. package/dist/detectors/warning-action.js.map +1 -0
  384. package/dist/facts/condition-pairs.d.ts +51 -0
  385. package/dist/facts/condition-pairs.d.ts.map +1 -0
  386. package/dist/facts/condition-pairs.js +203 -0
  387. package/dist/facts/condition-pairs.js.map +1 -0
  388. package/dist/facts/counted-facts.d.ts +16 -0
  389. package/dist/facts/counted-facts.d.ts.map +1 -0
  390. package/dist/facts/counted-facts.js +45 -0
  391. package/dist/facts/counted-facts.js.map +1 -0
  392. package/dist/facts/event-dates.d.ts +26 -0
  393. package/dist/facts/event-dates.d.ts.map +1 -0
  394. package/dist/facts/event-dates.js +38 -0
  395. package/dist/facts/event-dates.js.map +1 -0
  396. package/dist/facts/fact-scope.d.ts +2 -0
  397. package/dist/facts/fact-scope.d.ts.map +1 -1
  398. package/dist/facts/fact-scope.js +5 -0
  399. package/dist/facts/fact-scope.js.map +1 -1
  400. package/dist/facts/labelled-facts.d.ts +2 -0
  401. package/dist/facts/labelled-facts.d.ts.map +1 -1
  402. package/dist/facts/labelled-facts.js +9 -1
  403. package/dist/facts/labelled-facts.js.map +1 -1
  404. package/dist/facts/table-facts.d.ts +16 -0
  405. package/dist/facts/table-facts.d.ts.map +1 -1
  406. package/dist/facts/table-facts.js +2 -2
  407. package/dist/facts/table-facts.js.map +1 -1
  408. package/dist/grade/ai-score.d.ts +1 -1
  409. package/dist/grade/ai-score.d.ts.map +1 -1
  410. package/dist/grade/text.js +2 -2
  411. package/dist/grade/text.js.map +1 -1
  412. package/dist/heading-numbering.js +2 -2
  413. package/dist/heading-numbering.js.map +1 -1
  414. package/dist/html/fetch-page.d.ts +20 -0
  415. package/dist/html/fetch-page.d.ts.map +1 -0
  416. package/dist/html/fetch-page.js +51 -0
  417. package/dist/html/fetch-page.js.map +1 -0
  418. package/dist/html/fetched-text.d.ts +5 -0
  419. package/dist/html/fetched-text.d.ts.map +1 -0
  420. package/dist/html/fetched-text.js +25 -0
  421. package/dist/html/fetched-text.js.map +1 -0
  422. package/dist/html/html-content-block.d.ts +6 -0
  423. package/dist/html/html-content-block.d.ts.map +1 -0
  424. package/dist/html/html-content-block.js +86 -0
  425. package/dist/html/html-content-block.js.map +1 -0
  426. package/dist/html/html-elements.d.ts +41 -0
  427. package/dist/html/html-elements.d.ts.map +1 -0
  428. package/dist/html/html-elements.js +91 -0
  429. package/dist/html/html-elements.js.map +1 -0
  430. package/dist/html/html-footnote-marks.d.ts +2 -0
  431. package/dist/html/html-footnote-marks.d.ts.map +1 -0
  432. package/dist/html/html-footnote-marks.js +15 -0
  433. package/dist/html/html-footnote-marks.js.map +1 -0
  434. package/dist/html/html-heading-links.d.ts +6 -0
  435. package/dist/html/html-heading-links.d.ts.map +1 -0
  436. package/dist/html/html-heading-links.js +71 -0
  437. package/dist/html/html-heading-links.js.map +1 -0
  438. package/dist/html/html-lost-tags.d.ts +3 -0
  439. package/dist/html/html-lost-tags.d.ts.map +1 -0
  440. package/dist/html/html-lost-tags.js +11 -0
  441. package/dist/html/html-lost-tags.js.map +1 -0
  442. package/dist/html/html-markdown.d.ts +2 -0
  443. package/dist/html/html-markdown.d.ts.map +1 -0
  444. package/dist/html/html-markdown.js +347 -0
  445. package/dist/html/html-markdown.js.map +1 -0
  446. package/dist/html/html-preformatted.d.ts +17 -0
  447. package/dist/html/html-preformatted.d.ts.map +1 -0
  448. package/dist/html/html-preformatted.js +82 -0
  449. package/dist/html/html-preformatted.js.map +1 -0
  450. package/dist/html/html-reader-only.d.ts +6 -0
  451. package/dist/html/html-reader-only.d.ts.map +1 -0
  452. package/dist/html/html-reader-only.js +63 -0
  453. package/dist/html/html-reader-only.js.map +1 -0
  454. package/dist/html/html-run-in-headings.d.ts +2 -0
  455. package/dist/html/html-run-in-headings.d.ts.map +1 -0
  456. package/dist/html/html-run-in-headings.js +36 -0
  457. package/dist/html/html-run-in-headings.js.map +1 -0
  458. package/dist/html/html-tables.d.ts +3 -0
  459. package/dist/html/html-tables.d.ts.map +1 -0
  460. package/dist/html/html-tables.js +58 -0
  461. package/dist/html/html-tables.js.map +1 -0
  462. package/dist/html/html-widgets.d.ts +3 -0
  463. package/dist/html/html-widgets.d.ts.map +1 -0
  464. package/dist/html/html-widgets.js +71 -0
  465. package/dist/html/html-widgets.js.map +1 -0
  466. package/dist/html/markup-text.d.ts +5 -0
  467. package/dist/html/markup-text.d.ts.map +1 -0
  468. package/dist/html/markup-text.js +32 -0
  469. package/dist/html/markup-text.js.map +1 -0
  470. package/dist/html/page-document.d.ts +9 -0
  471. package/dist/html/page-document.d.ts.map +1 -0
  472. package/dist/html/page-document.js +19 -0
  473. package/dist/html/page-document.js.map +1 -0
  474. package/dist/inline-count.d.ts +19 -0
  475. package/dist/inline-count.d.ts.map +1 -0
  476. package/dist/inline-count.js +109 -0
  477. package/dist/inline-count.js.map +1 -0
  478. package/dist/kana-spelling.d.ts +5 -0
  479. package/dist/kana-spelling.d.ts.map +1 -1
  480. package/dist/kana-spelling.js +5 -0
  481. package/dist/kana-spelling.js.map +1 -1
  482. package/dist/location-part.d.ts +13 -0
  483. package/dist/location-part.d.ts.map +1 -0
  484. package/dist/location-part.js +24 -0
  485. package/dist/location-part.js.map +1 -0
  486. package/dist/nado-closed-list.d.ts +20 -0
  487. package/dist/nado-closed-list.d.ts.map +1 -0
  488. package/dist/nado-closed-list.js +72 -0
  489. package/dist/nado-closed-list.js.map +1 -0
  490. package/dist/name-cue.d.ts +17 -0
  491. package/dist/name-cue.d.ts.map +1 -0
  492. package/dist/name-cue.js +29 -0
  493. package/dist/name-cue.js.map +1 -0
  494. package/dist/name-variants.d.ts +41 -5
  495. package/dist/name-variants.d.ts.map +1 -1
  496. package/dist/name-variants.js +93 -8
  497. package/dist/name-variants.js.map +1 -1
  498. package/dist/paragraph-runs.d.ts +6 -1
  499. package/dist/paragraph-runs.d.ts.map +1 -1
  500. package/dist/paragraph-runs.js +9 -2
  501. package/dist/paragraph-runs.js.map +1 -1
  502. package/dist/parameter-table.d.ts +19 -0
  503. package/dist/parameter-table.d.ts.map +1 -0
  504. package/dist/parameter-table.js +191 -0
  505. package/dist/parameter-table.js.map +1 -0
  506. package/dist/phone-numbers.d.ts +23 -0
  507. package/dist/phone-numbers.d.ts.map +1 -0
  508. package/dist/phone-numbers.js +83 -0
  509. package/dist/phone-numbers.js.map +1 -0
  510. package/dist/place-names.d.ts +55 -0
  511. package/dist/place-names.d.ts.map +1 -0
  512. package/dist/place-names.js +196 -0
  513. package/dist/place-names.js.map +1 -0
  514. package/dist/plugin.d.ts +4 -0
  515. package/dist/plugin.d.ts.map +1 -1
  516. package/dist/prerequisite-order.d.ts +16 -0
  517. package/dist/prerequisite-order.d.ts.map +1 -0
  518. package/dist/prerequisite-order.js +29 -0
  519. package/dist/prerequisite-order.js.map +1 -0
  520. package/dist/profile/parse.d.ts.map +1 -1
  521. package/dist/profile/parse.js +10 -1
  522. package/dist/profile/parse.js.map +1 -1
  523. package/dist/reasons.d.ts +2 -0
  524. package/dist/reasons.d.ts.map +1 -1
  525. package/dist/reasons.js +2 -0
  526. package/dist/reasons.js.map +1 -1
  527. package/dist/render/rules-json.d.ts.map +1 -1
  528. package/dist/render/rules-json.js +4 -0
  529. package/dist/render/rules-json.js.map +1 -1
  530. package/dist/render/rules-table.d.ts.map +1 -1
  531. package/dist/render/rules-table.js +6 -2
  532. package/dist/render/rules-table.js.map +1 -1
  533. package/dist/rule-genres.d.ts +5 -2
  534. package/dist/rule-genres.d.ts.map +1 -1
  535. package/dist/rule-genres.js +2 -0
  536. package/dist/rule-genres.js.map +1 -1
  537. package/dist/rule-load.d.ts.map +1 -1
  538. package/dist/rule-load.js +2 -1
  539. package/dist/rule-load.js.map +1 -1
  540. package/dist/run.d.ts.map +1 -1
  541. package/dist/run.js +5 -1
  542. package/dist/run.js.map +1 -1
  543. package/dist/spelling.d.ts +2 -0
  544. package/dist/spelling.d.ts.map +1 -1
  545. package/dist/spelling.js +6 -0
  546. package/dist/spelling.js.map +1 -1
  547. package/dist/structure/action-due.d.ts +21 -0
  548. package/dist/structure/action-due.d.ts.map +1 -0
  549. package/dist/structure/action-due.js +126 -0
  550. package/dist/structure/action-due.js.map +1 -0
  551. package/dist/structure/amount-range.d.ts +30 -0
  552. package/dist/structure/amount-range.d.ts.map +1 -0
  553. package/dist/structure/amount-range.js +153 -0
  554. package/dist/structure/amount-range.js.map +1 -0
  555. package/dist/structure/amount-scale.d.ts +35 -0
  556. package/dist/structure/amount-scale.d.ts.map +1 -0
  557. package/dist/structure/amount-scale.js +83 -0
  558. package/dist/structure/amount-scale.js.map +1 -0
  559. package/dist/structure/cite.d.ts +5 -2
  560. package/dist/structure/cite.d.ts.map +1 -1
  561. package/dist/structure/cite.js +20 -1
  562. package/dist/structure/cite.js.map +1 -1
  563. package/dist/structure/counted-amounts.d.ts +12 -0
  564. package/dist/structure/counted-amounts.d.ts.map +1 -0
  565. package/dist/structure/counted-amounts.js +30 -0
  566. package/dist/structure/counted-amounts.js.map +1 -0
  567. package/dist/structure/date-order.d.ts +24 -3
  568. package/dist/structure/date-order.d.ts.map +1 -1
  569. package/dist/structure/date-order.js +49 -17
  570. package/dist/structure/date-order.js.map +1 -1
  571. package/dist/structure/date-outside-period.d.ts +27 -0
  572. package/dist/structure/date-outside-period.d.ts.map +1 -0
  573. package/dist/structure/date-outside-period.js +86 -0
  574. package/dist/structure/date-outside-period.js.map +1 -0
  575. package/dist/structure/definition-use.d.ts +5 -2
  576. package/dist/structure/definition-use.d.ts.map +1 -1
  577. package/dist/structure/definition-use.js +11 -3
  578. package/dist/structure/definition-use.js.map +1 -1
  579. package/dist/structure/due-date.d.ts +19 -0
  580. package/dist/structure/due-date.d.ts.map +1 -0
  581. package/dist/structure/due-date.js +30 -0
  582. package/dist/structure/due-date.js.map +1 -0
  583. package/dist/structure/heading-runs.d.ts +9 -0
  584. package/dist/structure/heading-runs.d.ts.map +1 -0
  585. package/dist/structure/heading-runs.js +23 -0
  586. package/dist/structure/heading-runs.js.map +1 -0
  587. package/dist/structure/install-pin.d.ts +46 -0
  588. package/dist/structure/install-pin.d.ts.map +1 -0
  589. package/dist/structure/install-pin.js +85 -0
  590. package/dist/structure/install-pin.js.map +1 -0
  591. package/dist/structure/leg-times.d.ts +34 -0
  592. package/dist/structure/leg-times.d.ts.map +1 -0
  593. package/dist/structure/leg-times.js +135 -0
  594. package/dist/structure/leg-times.js.map +1 -0
  595. package/dist/structure/line-amount-unit.d.ts +24 -0
  596. package/dist/structure/line-amount-unit.d.ts.map +1 -0
  597. package/dist/structure/line-amount-unit.js +24 -0
  598. package/dist/structure/line-amount-unit.js.map +1 -0
  599. package/dist/structure/line-amount.d.ts +40 -0
  600. package/dist/structure/line-amount.d.ts.map +1 -0
  601. package/dist/structure/line-amount.js +118 -0
  602. package/dist/structure/line-amount.js.map +1 -0
  603. package/dist/structure/number-word-figure.d.ts +37 -0
  604. package/dist/structure/number-word-figure.d.ts.map +1 -0
  605. package/dist/structure/number-word-figure.js +151 -0
  606. package/dist/structure/number-word-figure.js.map +1 -0
  607. package/dist/structure/numbering.d.ts +1 -0
  608. package/dist/structure/numbering.d.ts.map +1 -1
  609. package/dist/structure/numbering.js +3 -0
  610. package/dist/structure/numbering.js.map +1 -1
  611. package/dist/structure/ordinal-runs.d.ts +45 -0
  612. package/dist/structure/ordinal-runs.d.ts.map +1 -0
  613. package/dist/structure/ordinal-runs.js +78 -0
  614. package/dist/structure/ordinal-runs.js.map +1 -0
  615. package/dist/structure/percent-sum-prose.d.ts +1 -1
  616. package/dist/structure/percent-sum-prose.d.ts.map +1 -1
  617. package/dist/structure/percent-sum-prose.js +45 -3
  618. package/dist/structure/percent-sum-prose.js.map +1 -1
  619. package/dist/structure/percent-sum.d.ts +8 -0
  620. package/dist/structure/percent-sum.d.ts.map +1 -1
  621. package/dist/structure/percent-sum.js +8 -1
  622. package/dist/structure/percent-sum.js.map +1 -1
  623. package/dist/structure/release-list.d.ts +9 -0
  624. package/dist/structure/release-list.d.ts.map +1 -0
  625. package/dist/structure/release-list.js +46 -0
  626. package/dist/structure/release-list.js.map +1 -0
  627. package/dist/structure/share-column.d.ts +7 -0
  628. package/dist/structure/share-column.d.ts.map +1 -0
  629. package/dist/structure/share-column.js +22 -0
  630. package/dist/structure/share-column.js.map +1 -0
  631. package/dist/structure/stated-period.d.ts +31 -0
  632. package/dist/structure/stated-period.d.ts.map +1 -0
  633. package/dist/structure/stated-period.js +127 -0
  634. package/dist/structure/stated-period.js.map +1 -0
  635. package/dist/structure/subject-change.d.ts +8 -0
  636. package/dist/structure/subject-change.d.ts.map +1 -0
  637. package/dist/structure/subject-change.js +31 -0
  638. package/dist/structure/subject-change.js.map +1 -0
  639. package/dist/structure/tax.d.ts +25 -0
  640. package/dist/structure/tax.d.ts.map +1 -0
  641. package/dist/structure/tax.js +86 -0
  642. package/dist/structure/tax.js.map +1 -0
  643. package/dist/structure/time-marks.d.ts +58 -0
  644. package/dist/structure/time-marks.d.ts.map +1 -0
  645. package/dist/structure/time-marks.js +74 -0
  646. package/dist/structure/time-marks.js.map +1 -0
  647. package/dist/structure/time-order.d.ts +21 -0
  648. package/dist/structure/time-order.d.ts.map +1 -0
  649. package/dist/structure/time-order.js +108 -0
  650. package/dist/structure/time-order.js.map +1 -0
  651. package/dist/structure/title-lines.d.ts +8 -0
  652. package/dist/structure/title-lines.d.ts.map +1 -0
  653. package/dist/structure/title-lines.js +27 -0
  654. package/dist/structure/title-lines.js.map +1 -0
  655. package/dist/structure/total.d.ts.map +1 -1
  656. package/dist/structure/total.js +3 -1
  657. package/dist/structure/total.js.map +1 -1
  658. package/dist/structure/version-mismatch.d.ts +1 -5
  659. package/dist/structure/version-mismatch.d.ts.map +1 -1
  660. package/dist/structure/version-mismatch.js +65 -12
  661. package/dist/structure/version-mismatch.js.map +1 -1
  662. package/dist/structure/version-order.d.ts +23 -0
  663. package/dist/structure/version-order.d.ts.map +1 -0
  664. package/dist/structure/version-order.js +67 -0
  665. package/dist/structure/version-order.js.map +1 -0
  666. package/dist/table-text.d.ts +9 -0
  667. package/dist/table-text.d.ts.map +1 -0
  668. package/dist/table-text.js +36 -0
  669. package/dist/table-text.js.map +1 -0
  670. package/dist/ui-labels.d.ts +16 -0
  671. package/dist/ui-labels.d.ts.map +1 -0
  672. package/dist/ui-labels.js +42 -0
  673. package/dist/ui-labels.js.map +1 -0
  674. package/dist/undefined-call.d.ts +13 -0
  675. package/dist/undefined-call.d.ts.map +1 -0
  676. package/dist/undefined-call.js +55 -0
  677. package/dist/undefined-call.js.map +1 -0
  678. package/dist/unnamed-speaker.d.ts +23 -0
  679. package/dist/unnamed-speaker.d.ts.map +1 -0
  680. package/dist/unnamed-speaker.js +176 -0
  681. package/dist/unnamed-speaker.js.map +1 -0
  682. package/dist/warning-action.d.ts +22 -0
  683. package/dist/warning-action.d.ts.map +1 -0
  684. package/dist/warning-action.js +58 -0
  685. package/dist/warning-action.js.map +1 -0
  686. package/genres.yaml +2 -0
  687. package/package.json +4 -3
  688. package/profiles/statute.yaml +8 -0
  689. package/rules/agreement-slip.yaml +2 -2
  690. package/rules/amount-range-reversed.yaml +52 -0
  691. package/rules/amount-scale-consistency.yaml +74 -0
  692. package/rules/announced-count-mismatch.yaml +9 -4
  693. package/rules/arrival-before-departure.yaml +48 -0
  694. package/rules/change-rate-mismatch.yaml +5 -4
  695. package/rules/connective-hierarchy.yaml +3 -3
  696. package/rules/currency-notation-consistency.yaml +2 -2
  697. package/rules/date-order.yaml +9 -4
  698. package/rules/date-outside-period.yaml +64 -0
  699. package/rules/default-value-mismatch.yaml +79 -0
  700. package/rules/defined-term-form.yaml +9 -7
  701. package/rules/deprecated-option-used.yaml +78 -0
  702. package/rules/doubled-nado.yaml +28 -12
  703. package/rules/due-before-issue.yaml +68 -0
  704. package/rules/duplicate-definition.yaml +2 -2
  705. package/rules/duration-mismatch.yaml +12 -4
  706. package/rules/elapsed-years-mismatch.yaml +2 -2
  707. package/rules/heading-echo.yaml +2 -2
  708. package/rules/hyphen-as-dash.yaml +2 -2
  709. package/rules/kana-function-word.yaml +58 -0
  710. package/rules/latin-spacing.yaml +6 -5
  711. package/rules/line-amount-mismatch.yaml +58 -0
  712. package/rules/nado-closed-list.yaml +77 -0
  713. package/rules/name-variant.yaml +17 -2
  714. package/rules/number-word-figure-mismatch.yaml +76 -0
  715. package/rules/numbering-gap.yaml +2 -2
  716. package/rules/obligation-without-deadline.yaml +95 -0
  717. package/rules/one-sentence-paragraph-run.yaml +2 -3
  718. package/rules/parameter-table-mismatch.yaml +90 -0
  719. package/rules/percent-sum-mismatch.yaml +2 -2
  720. package/rules/phone-number-variant.yaml +68 -0
  721. package/rules/prerequisite-after-step.yaml +78 -0
  722. package/rules/quote-unnamed-speaker.yaml +67 -0
  723. package/rules/quote-without-source.yaml +6 -6
  724. package/rules/requirement-smell.yaml +3 -3
  725. package/rules/sentence-initial-conjunction-run.yaml +13 -7
  726. package/rules/summary-fact-mismatch.yaml +4 -4
  727. package/rules/tax-mismatch.yaml +71 -0
  728. package/rules/time-order.yaml +65 -0
  729. package/rules/title-length.yaml +2 -2
  730. package/rules/ui-label-variant.yaml +70 -0
  731. package/rules/unbalanced-bracket.yaml +4 -4
  732. package/rules/uncomparable-graded.yaml +29 -10
  733. package/rules/undefined-function-call.yaml +77 -0
  734. package/rules/undefined-term.yaml +72 -0
  735. package/rules/unknown-word.yaml +2 -2
  736. package/rules/unqualified-superlative.yaml +2 -2
  737. package/rules/use-before-definition.yaml +2 -2
  738. package/rules/version-mismatch.yaml +12 -4
  739. package/rules/version-order.yaml +85 -0
  740. package/rules/very-adjective.yaml +31 -13
  741. package/rules/warning-without-action.yaml +64 -0
  742. package/rules/wordy-phrase.yaml +27 -9
  743. package/src/ai-score/of-document.ts +19 -9
  744. package/src/ai-score/render.ts +24 -4
  745. package/src/ai-score/score.ts +24 -3
  746. package/src/ai-score/signals.ts +12 -2
  747. package/src/ai-score/text.ts +7 -2
  748. package/src/announced-count.ts +19 -12
  749. package/src/check-source.ts +11 -2
  750. package/src/cli-text.ts +42 -18
  751. package/src/cli.ts +2 -1
  752. package/src/commands/cite-claims.ts +103 -0
  753. package/src/commands/cite-page.ts +61 -0
  754. package/src/commands/cite-scaffold.ts +27 -0
  755. package/src/commands/cite.ts +127 -58
  756. package/src/company-names.ts +202 -0
  757. package/src/default-values.ts +158 -0
  758. package/src/deprecated-use.ts +122 -0
  759. package/src/derived/number-word-counts.ts +28 -0
  760. package/src/derived/stays.ts +145 -0
  761. package/src/detectors/acronym-context.ts +10 -2
  762. package/src/detectors/address-word.ts +9 -0
  763. package/src/detectors/agreement-slip.ts +7 -1
  764. package/src/detectors/ai-phrasing.ts +6 -1
  765. package/src/detectors/amount-range.ts +54 -0
  766. package/src/detectors/amount-scale.ts +96 -0
  767. package/src/detectors/announced-count.ts +29 -11
  768. package/src/detectors/bare-comparative.ts +7 -2
  769. package/src/detectors/block-quotation.ts +95 -0
  770. package/src/detectors/bracket-label.ts +58 -0
  771. package/src/detectors/change-rate.ts +15 -2
  772. package/src/detectors/citation-entry.ts +20 -5
  773. package/src/detectors/code-before.ts +14 -0
  774. package/src/detectors/connective-hierarchy.ts +39 -11
  775. package/src/detectors/currency-notation.ts +4 -3
  776. package/src/detectors/date-outside-period.ts +38 -0
  777. package/src/detectors/default-values.ts +17 -0
  778. package/src/detectors/defined-term-form.ts +84 -15
  779. package/src/detectors/definition-use.ts +10 -2
  780. package/src/detectors/deprecated-use.ts +17 -0
  781. package/src/detectors/derived-numbers.ts +115 -17
  782. package/src/detectors/document-shape.ts +6 -1
  783. package/src/detectors/due-date.ts +47 -0
  784. package/src/detectors/en-shape.ts +27 -11
  785. package/src/detectors/fact-consistency.ts +110 -2
  786. package/src/detectors/heading-echo.ts +11 -1
  787. package/src/detectors/kana-function-word.ts +71 -0
  788. package/src/detectors/line-amount.ts +33 -0
  789. package/src/detectors/location-pointer.ts +30 -0
  790. package/src/detectors/mark-shape.ts +18 -1
  791. package/src/detectors/nado-closed-list.ts +25 -0
  792. package/src/detectors/name-variant.ts +114 -11
  793. package/src/detectors/next-word.ts +56 -9
  794. package/src/detectors/number-word-figure.ts +43 -0
  795. package/src/detectors/obligation-without-deadline.ts +192 -0
  796. package/src/detectors/open-end-names.ts +140 -0
  797. package/src/detectors/ordinal-run-gaps.ts +101 -0
  798. package/src/detectors/orthographic-variant.ts +39 -14
  799. package/src/detectors/orthography.ts +6 -1
  800. package/src/detectors/parameter-table.ts +17 -0
  801. package/src/detectors/phone-number-variant.ts +18 -0
  802. package/src/detectors/prerequisite-order.ts +35 -0
  803. package/src/detectors/quote-unnamed-speaker.ts +19 -0
  804. package/src/detectors/quote-without-source.ts +57 -10
  805. package/src/detectors/registry/amount-range.ts +4 -0
  806. package/src/detectors/registry/amount-scale.ts +4 -0
  807. package/src/detectors/registry/arrival-before-departure.ts +4 -0
  808. package/src/detectors/registry/date-outside-period.ts +4 -0
  809. package/src/detectors/registry/default-values.ts +4 -0
  810. package/src/detectors/registry/deprecated-use.ts +4 -0
  811. package/src/detectors/registry/due-date.ts +4 -0
  812. package/src/detectors/registry/kana-function-word.ts +4 -0
  813. package/src/detectors/registry/line-amount.ts +4 -0
  814. package/src/detectors/registry/nado-closed-list.ts +4 -0
  815. package/src/detectors/registry/number-word-figure.ts +4 -0
  816. package/src/detectors/registry/obligation-without-deadline.ts +4 -0
  817. package/src/detectors/registry/parameter-table.ts +4 -0
  818. package/src/detectors/registry/phone-number-variant.ts +4 -0
  819. package/src/detectors/registry/prerequisite-order.ts +4 -0
  820. package/src/detectors/registry/quote-unnamed-speaker.ts +4 -0
  821. package/src/detectors/registry/tax-amount.ts +4 -0
  822. package/src/detectors/registry/time-order.ts +4 -0
  823. package/src/detectors/registry/ui-label.ts +4 -0
  824. package/src/detectors/registry/undefined-call.ts +4 -0
  825. package/src/detectors/registry/undefined-term.ts +4 -0
  826. package/src/detectors/registry/version-order.ts +4 -0
  827. package/src/detectors/registry/warning-action.ts +4 -0
  828. package/src/detectors/requirement-smell.ts +29 -9
  829. package/src/detectors/structure-tree.ts +43 -21
  830. package/src/detectors/superlative-scope.ts +13 -1
  831. package/src/detectors/tax-amount.ts +25 -0
  832. package/src/detectors/technical-docs.ts +7 -1
  833. package/src/detectors/term-extension.ts +67 -0
  834. package/src/detectors/time-order.ts +49 -0
  835. package/src/detectors/ui-label.ts +17 -0
  836. package/src/detectors/unbalanced-bracket.ts +7 -14
  837. package/src/detectors/undefined-call.ts +19 -0
  838. package/src/detectors/undefined-term.ts +103 -0
  839. package/src/detectors/unknown-word.ts +3 -3
  840. package/src/detectors/vague-deadline.ts +3 -3
  841. package/src/detectors/version-mismatch.ts +26 -5
  842. package/src/detectors/version-order.ts +50 -0
  843. package/src/detectors/warning-action.ts +49 -0
  844. package/src/facts/condition-pairs.ts +289 -0
  845. package/src/facts/counted-facts.ts +59 -0
  846. package/src/facts/event-dates.ts +63 -0
  847. package/src/facts/fact-scope.ts +6 -0
  848. package/src/facts/labelled-facts.ts +13 -1
  849. package/src/facts/table-facts.ts +3 -3
  850. package/src/grade/ai-score.ts +1 -1
  851. package/src/grade/text.ts +2 -2
  852. package/src/heading-numbering.ts +2 -2
  853. package/src/html/fetch-page.ts +64 -0
  854. package/src/html/fetched-text.ts +32 -0
  855. package/src/html/html-content-block.ts +107 -0
  856. package/src/html/html-elements.ts +127 -0
  857. package/src/html/html-footnote-marks.ts +20 -0
  858. package/src/html/html-heading-links.ts +93 -0
  859. package/src/html/html-lost-tags.ts +14 -0
  860. package/src/html/html-markdown.ts +481 -0
  861. package/src/html/html-preformatted.ts +110 -0
  862. package/src/html/html-reader-only.ts +82 -0
  863. package/src/html/html-run-in-headings.ts +43 -0
  864. package/src/html/html-tables.ts +76 -0
  865. package/src/html/html-widgets.ts +114 -0
  866. package/src/html/markup-text.ts +35 -0
  867. package/src/html/page-document.ts +22 -0
  868. package/src/inline-count.ts +146 -0
  869. package/src/kana-spelling.ts +7 -0
  870. package/src/location-part.ts +30 -0
  871. package/src/nado-closed-list.ts +106 -0
  872. package/src/name-cue.ts +35 -0
  873. package/src/name-variants.ts +152 -11
  874. package/src/paragraph-runs.ts +12 -2
  875. package/src/parameter-table.ts +208 -0
  876. package/src/phone-numbers.ts +98 -0
  877. package/src/place-names.ts +248 -0
  878. package/src/plugin.ts +4 -0
  879. package/src/prerequisite-order.ts +39 -0
  880. package/src/profile/parse.ts +10 -1
  881. package/src/reasons.ts +4 -0
  882. package/src/render/rules-json.ts +4 -0
  883. package/src/render/rules-table.ts +6 -3
  884. package/src/rule-genres.ts +5 -2
  885. package/src/rule-load.ts +3 -2
  886. package/src/run.ts +3 -1
  887. package/src/spelling.ts +8 -0
  888. package/src/structure/action-due.ts +179 -0
  889. package/src/structure/amount-range.ts +219 -0
  890. package/src/structure/amount-scale.ts +115 -0
  891. package/src/structure/cite.ts +21 -2
  892. package/src/structure/counted-amounts.ts +42 -0
  893. package/src/structure/date-order.ts +72 -22
  894. package/src/structure/date-outside-period.ts +127 -0
  895. package/src/structure/definition-use.ts +24 -3
  896. package/src/structure/due-date.ts +46 -0
  897. package/src/structure/heading-runs.ts +24 -0
  898. package/src/structure/install-pin.ts +115 -0
  899. package/src/structure/leg-times.ts +198 -0
  900. package/src/structure/line-amount-unit.ts +35 -0
  901. package/src/structure/line-amount.ts +162 -0
  902. package/src/structure/number-word-figure.ts +199 -0
  903. package/src/structure/numbering.ts +3 -0
  904. package/src/structure/ordinal-runs.ts +107 -0
  905. package/src/structure/percent-sum-prose.ts +46 -3
  906. package/src/structure/percent-sum.ts +16 -2
  907. package/src/structure/release-list.ts +69 -0
  908. package/src/structure/share-column.ts +25 -0
  909. package/src/structure/stated-period.ts +161 -0
  910. package/src/structure/subject-change.ts +35 -0
  911. package/src/structure/tax.ts +114 -0
  912. package/src/structure/time-marks.ts +127 -0
  913. package/src/structure/time-order.ts +140 -0
  914. package/src/structure/title-lines.ts +33 -0
  915. package/src/structure/total.ts +5 -1
  916. package/src/structure/version-mismatch.ts +67 -13
  917. package/src/structure/version-order.ts +84 -0
  918. package/src/table-text.ts +39 -0
  919. package/src/ui-labels.ts +55 -0
  920. package/src/undefined-call.ts +65 -0
  921. package/src/unnamed-speaker.ts +224 -0
  922. package/src/warning-action.ts +73 -0
  923. package/styles/koyobun.yaml +7 -4
@@ -0,0 +1,91 @@
1
+ // The pieces of an HTML page the converters look at: tags, links, attributes and elements matched to their own
2
+ // closing tag. Pure; a regular-expression reading, not a parser.
3
+ import { decodeEntities } from "./markup-text.js";
4
+ // In a tag a quote opens a value only after "=", and the value ends only at its matching quote, whatever it holds.
5
+ const TAG_BODY = String.raw `(?:[^>=]|=\s*"[^"]*"|=\s*'[^']*'|=(?!\s*["']))*`;
6
+ // A comment, a processing instruction, a script and a style are matched whole, so that no tag is read inside them
7
+ // (the converter drops them anyway), and a "<!--" inside a value is escaped before comments are looked for.
8
+ const TAG = new RegExp(String.raw `<!--[\s\S]*?-->|<\?[\s\S]*?\?>|<(script|style)\b${TAG_BODY}>[\s\S]*?<\/\1\s*>|<[a-z][a-z0-9-]*${TAG_BODY}>`, "giu");
9
+ const QUOTED_VALUE = /=(\s*)("[^"]*"|'[^']*')/gu;
10
+ const withValuesEscaped = (tag) => tag.replace(QUOTED_VALUE, (_whole, space, value) => `=${space}${value.replaceAll("<", "&lt;").replaceAll(">", "&gt;")}`);
11
+ /**
12
+ * Each "<" and ">" inside a quoted attribute value (title="published under the <span>…</span>") as a character
13
+ * reference, which means the same in a value, so that a scanner reading a tag up to its first ">" reads all of it.
14
+ */
15
+ export const withAttributeMarkupEscaped = (html) => html.replace(TAG, (tag) => withValuesEscaped(tag));
16
+ /** Apply step until the text stops changing: nested elements are removed from the inside out. */
17
+ export const untilStable = (text, step) => {
18
+ const next = step(text);
19
+ return next === text ? text : untilStable(next, step);
20
+ };
21
+ export const stripTags = (html) => html.replace(/<\/?[a-z!][^>]*>/giu, "");
22
+ export const plainText = (html) => decodeEntities(stripTags(html)).replace(/\s+/gu, " ").trim();
23
+ /** Text put back into markup, so that decoding it again gives the same text. */
24
+ export const asMarkup = (text) => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;");
25
+ /** A full stop, question or exclamation mark closing a sentence, also before a closing quote or bracket; not the point in "3.5". */
26
+ export const CLOSED_SENTENCE = /[。.!?]|[.!?][)\]"'”’]*(?=\s|$)/u;
27
+ /** Whether the markup closes a sentence, each tag read as a space so that "Done.</li><li>Next" ends one. */
28
+ export const hasSentence = (html) => CLOSED_SENTENCE.test(plainText(html.replace(/<\/?[a-z!][^>]*>/giu, " ")));
29
+ export const hasNoWords = (text) => !/[\p{L}\p{N}]/u.test(text);
30
+ export const ANY_LINK = /<a\b[^>]*>[\s\S]*?<\/a\s*>/giu;
31
+ const HREF = /\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))/iu;
32
+ const PAGE_EXTENSION = /^(?:[sx]?html?|php|aspx?|jsp|cgi)$/iu;
33
+ // The host is not part of the path: "https://example.com" names a site, not a file ending in .com.
34
+ const SCHEME_AND_HOST = /^(?:[a-z][a-z0-9+.-]*:)?\/\/[^/?#]*/iu;
35
+ // A link that opens no page (tel:, mailto:, sms:) carries its own content, a number or an address.
36
+ const OTHER_SCHEME = /^\s*(?!https?:)[a-z][a-z0-9+.-]*:(?!\/\/)/iu;
37
+ const hrefOf = (link) => {
38
+ const href = HREF.exec(link);
39
+ return href?.[1] ?? href?.[2] ?? href?.[3] ?? "";
40
+ };
41
+ /** The extension of the file a link opens ("pdf", "mp3"), or undefined for a page or a site. */
42
+ export const fileExtension = (link) => {
43
+ const path = hrefOf(link).replace(SCHEME_AND_HOST, "").split(/[?#]/u)[0] ?? "";
44
+ const extension = /\.([a-z0-9]{1,5})$/iu.exec(path.split("/").at(-1) ?? "")?.[1];
45
+ return extension !== undefined && !PAGE_EXTENSION.test(extension) ? extension : undefined;
46
+ };
47
+ /** A link to a file (an appendix as PDF, a table as .xlsx), or one that opens no page, is part of the document. */
48
+ export const isFileLink = (link) => OTHER_SCHEME.test(hrefOf(link)) || fileExtension(link) !== undefined;
49
+ /** Attributes before a given one, each skipped whole so that a quoted value (title="x role=main") is not read as one. */
50
+ export const ATTRIBUTES = String.raw `(?:\s+[^\s"'>=/]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'>]+))?)*?`;
51
+ const closeLast = (html, scan, close) => {
52
+ const opener = scan.open.at(-1);
53
+ if (opener === undefined)
54
+ return scan;
55
+ const range = {
56
+ start: opener.index,
57
+ end: close.index + close[0].length,
58
+ openTag: opener[0],
59
+ inner: html.slice(opener.index + opener[0].length, close.index),
60
+ };
61
+ return { open: scan.open.slice(0, -1), ranges: [...scan.ranges, range] };
62
+ };
63
+ /** Every <tag>…</tag>, nested ones matched to their own closing tag, in document order (outer before inner). */
64
+ export const elementRanges = (html, tag) => [...html.matchAll(new RegExp(`<(/?)${tag}\\b[^>]*>`, "giu"))]
65
+ .reduce((scan, match) => (match[1] === "/" ? closeLast(html, scan, match) : { open: [...scan.open, match], ranges: scan.ranges }), {
66
+ open: [],
67
+ ranges: [],
68
+ })
69
+ .ranges.toSorted((left, right) => left.start - right.start);
70
+ export const isInside = (outer, inner) => outer.start < inner.start && inner.end <= outer.end;
71
+ /** The ranges (in document order) each replaced by a space; one inside another cut one goes with it. */
72
+ export const withoutRanges = (html, ranges) => {
73
+ const chosen = ranges.reduce((kept, range) => {
74
+ const insideKept = (kept.at(-1)?.end ?? 0) > range.start;
75
+ if (!insideKept)
76
+ kept.push(range);
77
+ return kept;
78
+ }, []);
79
+ const cut = chosen.reduce((acc, range) => ({ parts: [...acc.parts, html.slice(acc.from, range.start), " "], from: range.end }), { parts: [], from: 0 });
80
+ return [...cut.parts, html.slice(cut.from)].join("");
81
+ };
82
+ /** The <tag> elements that are chrome, each replaced by a space; one inside another dropped one goes with it. */
83
+ export const withoutElementsWhere = (html, tag, isChrome) => withoutRanges(html, elementRanges(html, tag).filter(isChrome));
84
+ /** Every <tag> whose opening matches, for each tag that opens that way, replaced by a space. */
85
+ export const withoutElementsOpening = (html, opening, isChrome) => {
86
+ const tags = new Set([...html.matchAll(opening)].map((match) => (match[1] ?? "").toLowerCase()));
87
+ return [...tags].reduce((text, tag) => withoutElementsWhere(text, tag, isChrome), html);
88
+ };
89
+ export const HEADING_TAGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
90
+ export const headingRanges = (html) => HEADING_TAGS.flatMap((tag) => elementRanges(html, tag));
91
+ //# sourceMappingURL=html-elements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-elements.js","sourceRoot":"","sources":["../../src/html/html-elements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const withoutFootnoteMarks: (html: string) => string;
2
+ //# sourceMappingURL=html-footnote-marks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-footnote-marks.d.ts","sourceRoot":"","sources":["../../src/html/html-footnote-marks.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MAG8E,CAAC"}
@@ -0,0 +1,15 @@
1
+ // A footnote's reference mark: a superscript that is a link (<sup><a …>1</a></sup>), or a link to a place on the same
2
+ // page holding nothing but a superscript (<a href="#fn1"><sup>1</sup></a>). Read as text the number sticks to the
3
+ // sentence it follows ("recessions.1 Over"), so the mark is dropped; the note itself stays where the page has it. A
4
+ // superscript that is a link is a mark wherever the link goes (the notes may be on another page); a link around a
5
+ // superscript is one only when it stays on this page, since "Brand<a href=…><sup>TM</sup></a>" is a sign. A superscript
6
+ // with no link ("25<sup>th</sup>") is text. Pure.
7
+ const LINK_IN_SUPERSCRIPT = /<sup\b[^>]*>\s*<a\b[^>]*>[^<]*<\/a\s*>\s*<\/sup\s*>/giu;
8
+ const SUPERSCRIPT_LINK = /<a\b([^>]*)>\s*<sup\b[^>]*>([^<]*)<\/sup\s*>\s*<\/a\s*>/giu;
9
+ // The fragment must name something: href="#" alone goes nowhere and is a control.
10
+ const IN_PAGE_HREF = /\shref\s*=\s*(?:"#[^"\s]+"|'#[^'\s]+'|#[^\s"'>]+)/iu;
11
+ const isFootnoteLink = (attributes, mark) => IN_PAGE_HREF.test(attributes) && mark.trim() !== "";
12
+ export const withoutFootnoteMarks = (html) => html
13
+ .replace(LINK_IN_SUPERSCRIPT, "")
14
+ .replace(SUPERSCRIPT_LINK, (link, attributes, mark) => (isFootnoteLink(attributes, mark) ? "" : link));
15
+ //# sourceMappingURL=html-footnote-marks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-footnote-marks.js","sourceRoot":"","sources":["../../src/html/html-footnote-marks.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,kHAAkH;AAClH,oHAAoH;AACpH,kHAAkH;AAClH,wHAAwH;AACxH,kDAAkD;AAElD,MAAM,mBAAmB,GAAG,wDAAwD,CAAC;AAErF,MAAM,gBAAgB,GAAG,4DAA4D,CAAC;AAEtF,kFAAkF;AAClF,MAAM,YAAY,GAAG,qDAAqD,CAAC;AAE3E,MAAM,cAAc,GAAG,CAAC,UAAkB,EAAE,IAAY,EAAW,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAE1H,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAU,EAAE,CAC3D,IAAI;KACD,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;KAChC,OAAO,CAAC,gBAAgB,EAAE,CAAC,IAAY,EAAE,UAAkB,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A heading's link to its own section goes when it stands just after the heading ("Copy link to Context"), or inside
3
+ * it as a mark without words ("Scope ¶"). A link with words inside the heading is its title and stays.
4
+ */
5
+ export declare const withoutHeadingSelfLinks: (html: string) => string;
6
+ //# sourceMappingURL=html-heading-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-heading-links.d.ts","sourceRoot":"","sources":["../../src/html/html-heading-links.ts"],"names":[],"mappings":"AA8EA;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAUtD,CAAC"}
@@ -0,0 +1,71 @@
1
+ // A heading's link to its own section (a permalink beside or after the title), taken out of an HTML page. Pure.
2
+ import { ANY_LINK, ATTRIBUTES, elementRanges, hasNoWords, plainText } from "./html-elements.js";
3
+ import { decodeEntities } from "./markup-text.js";
4
+ const ID = new RegExp(String.raw `<([a-z][a-z0-9-]*)${ATTRIBUTES}\s+id\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))`, "giu");
5
+ /** Where each id's element opens, and which element it is; the first one when an id is repeated. */
6
+ const idTargets = (html) => [...html.matchAll(ID)].reduce((targets, match) => {
7
+ const id = decodeEntities(match[2] ?? match[3] ?? match[4] ?? "");
8
+ return targets.has(id) ? targets : targets.set(id, { start: match.index, tag: (match[1] ?? "").toLowerCase() });
9
+ }, new Map());
10
+ const FRAGMENT = /^<a\b[^>]*\bhref\s*=\s*["']?[^"'#\s>]*#([^"'\s>]+)/iu;
11
+ /** The id a link's fragment names, its character references and percent escapes undone. */
12
+ const fragmentId = (link) => {
13
+ const fragment = FRAGMENT.exec(link)?.[1];
14
+ if (fragment === undefined)
15
+ return undefined;
16
+ const decoded = decodeEntities(fragment);
17
+ try {
18
+ return decodeURIComponent(decoded);
19
+ }
20
+ catch {
21
+ return decoded;
22
+ }
23
+ };
24
+ const HEADING_OPENING = /<h[1-6]\b/iu;
25
+ /** The target opens before the heading and closes after it, with no other heading opening in between. */
26
+ const isSectionOf = (target, place) => place.rangesOf(target.tag).some((range) => range.start === target.start && range.end >= place.end) &&
27
+ !HEADING_OPENING.test(place.html.slice(target.start, place.start));
28
+ /** A link to the heading's own section: the heading, something inside it, or the block it opens (a permalink, "Copy link to Context"). */
29
+ const isSelfLink = (link, place) => {
30
+ const id = fragmentId(link);
31
+ const target = id === undefined ? undefined : place.ids.get(id);
32
+ if (target === undefined || target.start >= place.end)
33
+ return false;
34
+ return target.start >= place.start || isSectionOf(target, place);
35
+ };
36
+ /** A permalink mark inside the heading (¶, #, an icon); a self-link with words is the title, or part of it. */
37
+ const isPermalinkMark = (link, place) => hasNoWords(plainText(link)) && isSelfLink(link, place);
38
+ const HEADING_THEN_LINK = /(<h([1-6])\b[^>]*>)([\s\S]*?)(<\/h\2\s*>)(\s*<a\b[^>]*>[\s\S]*?<\/a\s*>)?/giu;
39
+ /** The heading as matched, without its permalink marks or the self-link standing after it. */
40
+ const headingWithoutSelfLinks = (match, page) => {
41
+ const [, open = "", , inside = "", close = "", after] = match;
42
+ const place = { ...page, start: match.index, end: match.index + open.length + inside.length + close.length };
43
+ const kept = inside.replace(ANY_LINK, (link) => (isPermalinkMark(link, place) ? " " : link));
44
+ const next = after === undefined || isSelfLink(after.trim(), place) ? "" : after;
45
+ return `${open}${kept}${close}${next}`;
46
+ };
47
+ /** elementRanges for each tag, computed once. */
48
+ const rangesByTag = (html) => {
49
+ const cache = new Map();
50
+ return (tag) => {
51
+ const known = cache.get(tag);
52
+ if (known !== undefined)
53
+ return known;
54
+ const ranges = elementRanges(html, tag);
55
+ cache.set(tag, ranges);
56
+ return ranges;
57
+ };
58
+ };
59
+ /**
60
+ * A heading's link to its own section goes when it stands just after the heading ("Copy link to Context"), or inside
61
+ * it as a mark without words ("Scope ¶"). A link with words inside the heading is its title and stays.
62
+ */
63
+ export const withoutHeadingSelfLinks = (html) => {
64
+ const page = { ids: idTargets(html), html, rangesOf: rangesByTag(html) };
65
+ const cut = [...html.matchAll(HEADING_THEN_LINK)].reduce((acc, match) => ({
66
+ parts: [...acc.parts, html.slice(acc.from, match.index), headingWithoutSelfLinks(match, page)],
67
+ from: match.index + match[0].length,
68
+ }), { parts: [], from: 0 });
69
+ return [...cut.parts, html.slice(cut.from)].join("");
70
+ };
71
+ //# sourceMappingURL=html-heading-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-heading-links.js","sourceRoot":"","sources":["../../src/html/html-heading-links.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** The HTML with each lost paragraph start tag in its text put back as <p>. */
2
+ export declare const withLostParagraphTagsRestored: (html: string) => string;
3
+ //# sourceMappingURL=html-lost-tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-lost-tags.d.ts","sourceRoot":"","sources":["../../src/html/html-lost-tags.ts"],"names":[],"mappings":"AAWA,+EAA+E;AAC/E,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,KAAG,MAC2C,CAAC"}
@@ -0,0 +1,11 @@
1
+ // A paragraph's start tag that lost its "<" upstream and so reached the page as text: the eCFR serves 16 CFR 310.4(b)
2
+ // with "… 45 CFR 160.103. P&gt;(2) It is an abusive …", where "P>" is what is left of the <P> that opened paragraph (2).
3
+ // Read as text it glues the paragraph to the one before and leaves "P>" in the sentence. Only a P and a ">" standing
4
+ // after a sentence's end and right before a paragraph's designation ("(2)", "(iv)", "(A)") and a capital are taken for the lost
5
+ // tag; "P>0.05", "P > (2)" and a formula opening a sentence ("P>(2) follows") stay text. Pure.
6
+ const LOST_PARAGRAPH_TAG = /(?<=[.;:][)"'”’]?[ \t])[Pp](?:&gt;|>)(?=\([0-9A-Za-z]{1,4}\)[ \t]\p{Lu})/gu;
7
+ /** Whether at is inside a tag. An attribute's ">" is escaped by then (withAttributeMarkupEscaped), so a tag has none before its end. */
8
+ const isInsideTag = (html, at) => html.lastIndexOf("<", at) > html.lastIndexOf(">", at - 1);
9
+ /** The HTML with each lost paragraph start tag in its text put back as <p>. */
10
+ export const withLostParagraphTagsRestored = (html) => html.replace(LOST_PARAGRAPH_TAG, (lost, at) => (isInsideTag(html, at) ? lost : "<p>"));
11
+ //# sourceMappingURL=html-lost-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-lost-tags.js","sourceRoot":"","sources":["../../src/html/html-lost-tags.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,yHAAyH;AACzH,qHAAqH;AACrH,gIAAgI;AAChI,+FAA+F;AAE/F,MAAM,kBAAkB,GAAG,4EAA4E,CAAC;AAExG,wIAAwI;AACxI,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAU,EAAW,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;AAErH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,IAAY,EAAU,EAAE,CACpE,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,IAAY,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const htmlToMarkdown: (html: string) => string;
2
+ //# sourceMappingURL=html-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-markdown.d.ts","sourceRoot":"","sources":["../../src/html/html-markdown.ts"],"names":[],"mappings":"AA+cA,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,MAiB7C,CAAC"}
@@ -0,0 +1,347 @@
1
+ // An HTML page (a CRS report as EveryCRSReport serves it, a ministry's page) as plain Markdown: headings, paragraphs,
2
+ // list items and the text of links; ruby keeps its base text and loses its reading. Only the <main> element (else the
3
+ // role="main" element, else a sole <article>, else the block holding the title and nearly every sentence) is read when
4
+ // the page has one. Scripts, styles, the head, navigation (by
5
+ // element or by role, and breadcrumbs), asides, footers, forms, tables without sentences (html-tables.ts), footnote marks, lists and blocks of nothing but
6
+ // links (a menu, a table of contents, previous/next links, a breadcrumb trail, also as a list ending in the page's
7
+ // title), a list of the page in other languages, a block of icons with only a label, a block before the page's title that holds a menu or only links and no sentence (the site's header, with its tagline and
8
+ // labels), buttons outside a heading, controls (html-widgets.ts: tooltips, media players, scripted link buttons, paging
9
+ // bars, unspoken text), hidden elements, text for a screen reader only (a visually-hidden class, a skip
10
+ // link's target), a heading's link to its own section beside or after its title,
11
+ // lines of nothing but in-page or script links (never a heading), a heading drawn as an image unless its alt text is the page's
12
+ // title, blocks of nothing but links closing the page, and a copyright notice closing the page, with an address just
13
+ // before it, are dropped. A paragraph tag that lost its "<" upstream (html-lost-tags.ts) opens its paragraph again. Markup's spacing collapses; U+3000 is text and stays. Pure; a regular-expression reading that
14
+ // is enough for the documents in the corpus, not a parser for any HTML.
15
+ import { ANY_LINK, ATTRIBUTES, CLOSED_SENTENCE, asMarkup, elementRanges, hasNoWords, hasSentence, isFileLink, isInside, headingRanges, plainText, stripTags, withAttributeMarkupEscaped, withoutElementsOpening, withoutElementsWhere, withoutRanges, untilStable, } from "./html-elements.js";
16
+ import { contentBlock } from "./html-content-block.js";
17
+ import { withoutFootnoteMarks } from "./html-footnote-marks.js";
18
+ import { withoutHeadingSelfLinks } from "./html-heading-links.js";
19
+ import { withLostParagraphTagsRestored } from "./html-lost-tags.js";
20
+ import { withoutReaderOnlyText } from "./html-reader-only.js";
21
+ import { withRunInHeadingsRead } from "./html-run-in-headings.js";
22
+ import { withoutWidgets } from "./html-widgets.js";
23
+ import { withPreformattedRestored, withPreformattedStashed } from "./html-preformatted.js";
24
+ import { withTablesRead } from "./html-tables.js";
25
+ import { decodeEntities, tidyLines } from "./markup-text.js";
26
+ const DROPPED = ["script", "style", "head", "nav", "aside", "footer", "form", "noscript", "svg"];
27
+ const withoutElement = (html, tag) => {
28
+ const innermost = new RegExp(`<${tag}\\b[^>]*>(?:(?!<${tag}\\b)[\\s\\S])*?</${tag}\\s*>`, "giu");
29
+ return untilStable(html, (text) => text.replace(innermost, " "));
30
+ };
31
+ // HTML lets a ruby's parts omit their closing tags: a reading container (<rtc>) ends at the next <rb> or <rtc>, a
32
+ // reading (<rt>) or its bracket (<rp>) at the next <rb>, <rt> or <rp>; any of them at the end of the <ruby>.
33
+ const RUBY_TEXT_CONTAINER = /<rtc\b[^>]*>[\s\S]*?(?:<\/rtc\s*>|(?=<(?:rb|rtc)\b|$))/giu;
34
+ const RUBY_TEXT = /<(rt|rp)\b[^>]*>[\s\S]*?(?:<\/\1\s*>|(?=<(?:rb|rt|rp)\b|$))/giu;
35
+ /** Ruby as its base text alone: 漢字 with its reading becomes 漢字. */
36
+ const withoutRubyText = (html) => html.replace(/<ruby\b[^>]*>([\s\S]*?)<\/ruby\s*>/giu, (_whole, inside) => inside.replace(RUBY_TEXT_CONTAINER, "").replace(RUBY_TEXT, ""));
37
+ /**
38
+ * A link that moves within the page (a table of contents, "back to top"), through a series (rel="prev" / "next"), or
39
+ * goes nowhere and runs a script instead (href="javascript:…", a print or share button).
40
+ */
41
+ const isChromeLink = (link) => /^<a\b[^>]*\bhref\s*=\s*(?:["']\s*)?(?:#|javascript:)/iu.test(link) || /^<a\b[^>]*\brel\s*=\s*(?:["'][^"']*\b)?(?:prev|next)\b/iu.test(link);
42
+ /** A list whose every item is only a link, such as a site menu or a table of contents. */
43
+ const isNavigation = (body) => [...body.matchAll(ANY_LINK)].length > 0 && stripTags(body.replace(ANY_LINK, "")).trim() === "";
44
+ // A role is a list of tokens and the first one counts: role="main document" is main.
45
+ const MAIN_ROLE = String.raw `${ATTRIBUTES}\s+role\s*=\s*(?:"\s*main(?:\s[^"]*)?"|'\s*main(?:\s[^']*)?'|main(?=[\s/>]))`;
46
+ /** The first element marked role="main" (a CMS's <article id="contents" role="main">), matched to its own closing tag. */
47
+ const mainLandmark = (html) => {
48
+ const tag = new RegExp(String.raw `<([a-z][a-z0-9]*)${MAIN_ROLE}`, "iu").exec(html)?.[1];
49
+ if (tag === undefined)
50
+ return undefined;
51
+ return elementRanges(html, tag).find((range) => new RegExp(String.raw `^<[a-z][a-z0-9]*${MAIN_ROLE}`, "iu").test(range.openTag))?.inner;
52
+ };
53
+ const isOutermost = (range, _index, all) => !all.some((outer) => isInside(outer, range));
54
+ const holdsEveryTitle = (html, range) => [...html.matchAll(/<h1\b/giu)].every((title) => title.index > range.start && title.index < range.end);
55
+ /**
56
+ * The one <article> not nested in another, when the page has exactly one and no <h1> outside it: the composition the
57
+ * page was made for. A page title outside the article means the article is only part of the page's content.
58
+ */
59
+ const soleArticle = (html) => {
60
+ const [only, ...others] = elementRanges(html, "article").filter(isOutermost);
61
+ return only !== undefined && others.length === 0 && holdsEveryTitle(html, only) ? only.inner : undefined;
62
+ };
63
+ /**
64
+ * The page's own content: inside <main>, else the element marked role="main", else a sole <article>, else the block
65
+ * holding the title and nearly every sentence (html-content-block.ts), else the whole page.
66
+ */
67
+ const mainContent = (html) => /<main\b[^>]*>([\s\S]*)<\/main\s*>/iu.exec(html)?.[1] ?? mainLandmark(html) ?? soleArticle(html) ?? contentBlock(html) ?? html;
68
+ const LANDMARK = String.raw `(?:\brole\s*=\s*["']?navigation\b|\baria-label\s*=\s*(?:["'][^"']*|[^\s"'>]*)breadcrumb)`;
69
+ const LANDMARK_OPENING = new RegExp(String.raw `<([a-z][a-z0-9]*)\b[^>]*${LANDMARK}`, "giu");
70
+ const isLandmark = (range) => new RegExp(`^<[^>]*${LANDMARK}`, "iu").test(range.openTag);
71
+ /** Navigation that is not a <nav>: any element with role="navigation", or labelled as a breadcrumb. */
72
+ const withoutNavigationLandmarks = (html) => withoutElementsOpening(html, LANDMARK_OPENING, isLandmark);
73
+ // hidden="until-found" is found by the browser's search and opened, so its text is the page's.
74
+ const HIDDEN = String.raw `${ATTRIBUTES}\s+hidden(?=[\s/>=])(?!\s*=\s*(?:"until-found"|'until-found'|until-found(?=[\s/>])))`;
75
+ const HIDDEN_OPENING = new RegExp(String.raw `<([a-z][a-z0-9-]*)${HIDDEN}`, "giu");
76
+ const isHidden = (range) => new RegExp(String.raw `^<[a-z][a-z0-9-]*${HIDDEN}`, "iu").test(range.openTag);
77
+ /** Elements the page does not show (the hidden attribute): a tooltip, a closed menu. */
78
+ const withoutHiddenElements = (html) => withoutElementsOpening(html, HIDDEN_OPENING, isHidden);
79
+ /**
80
+ * Buttons are controls ("Close", "Share", "Cite this publication"), not prose, except one inside a heading, which is
81
+ * how an accordion draws its section's title.
82
+ */
83
+ const withoutButtons = (html) => {
84
+ const headings = headingRanges(html);
85
+ return withoutElementsWhere(html, "button", (button) => !headings.some((heading) => isInside(heading, button)));
86
+ };
87
+ const LINK_MARK = "\u0003";
88
+ /** Links joined by ">" or another arrow, then the current page's name as plain text. */
89
+ const BREADCRUMB_TRAIL = new RegExp(`^\\s*(?:${LINK_MARK}\\s*[>›»>→]\\s*){2,}[^${LINK_MARK}>›»>→]*$`, "u");
90
+ /** A link wrapping blocks (a card with a title and a summary) carries content, not a way around the site. */
91
+ const isCard = (link) => /<(?:div|p|h[1-6]|ul|ol|dl|section|article|figure)\b/iu.test(link);
92
+ /** The links in html, or none when one of them wraps blocks. */
93
+ const plainLinks = (html) => {
94
+ const links = [...html.matchAll(ANY_LINK)].map((link) => link[0]);
95
+ return links.some(isCard) ? [] : links;
96
+ };
97
+ /** The text with each link standing as one mark. */
98
+ const withLinksMarked = (html) => decodeEntities(stripTags(html.replace(ANY_LINK, LINK_MARK)));
99
+ const isBreadcrumbTrail = (html) => plainLinks(html).length > 0 && BREADCRUMB_TRAIL.test(withLinksMarked(html));
100
+ const isOnlyLinks = (html) => hasNoWords(withLinksMarked(html).replaceAll(LINK_MARK, ""));
101
+ const MIN_GROUP_LINKS = 2;
102
+ /** A block made of two or more links and nothing else (a menu, previous and next), or a breadcrumb trail. */
103
+ const isLinkGroup = (range) => {
104
+ const links = plainLinks(range.inner);
105
+ if (links.length === 0)
106
+ return false;
107
+ return isOnlyLinks(range.inner) ? links.length >= MIN_GROUP_LINKS : isBreadcrumbTrail(range.inner);
108
+ };
109
+ /** A block of links and nothing else, even a single one: before the page's title, a way around the site ("English"). */
110
+ const isLinksOnly = (range) => plainLinks(range.inner).length > 0 && isOnlyLinks(range.inner);
111
+ const withoutLinkGroups = (html) => ["div", "section", "p"].reduce((text, tag) => withoutElementsWhere(text, tag, isLinkGroup), html);
112
+ /** The page's first <h1>: what it reads and where it opens. */
113
+ const pageTitle = (html) => {
114
+ const title = /<h1\b[^>]*>([\s\S]*?)<\/h1\s*>/iu.exec(html);
115
+ return title === null ? undefined : { text: plainText(title[1] ?? ""), start: title.index };
116
+ };
117
+ const MIN_TRAIL_LINKS = 2;
118
+ /**
119
+ * A breadcrumb as a list above the page's title: two or more items that are each only a link, then the title itself as
120
+ * the last item. The same list further down is the page's own content (steps ending in the one this page is about).
121
+ */
122
+ const isBreadcrumbList = (body, at, title) => {
123
+ const items = body.split(/<li\b[^>]*>/iu).slice(1);
124
+ const current = items.at(-1);
125
+ const trail = items.slice(0, -1);
126
+ return (title !== undefined &&
127
+ at < title.start &&
128
+ current !== undefined &&
129
+ plainText(current) === title.text &&
130
+ trail.length >= MIN_TRAIL_LINKS &&
131
+ trail.every(isNavigation));
132
+ };
133
+ /** A list with items and not a word in them: buttons drawn as images, such as a text-size switch. */
134
+ const isWordlessList = (body) => /<li\b/iu.test(body) && hasNoWords(plainText(body));
135
+ const HREFLANG = /^<a\b[^>]*\shreflang\s*=/iu;
136
+ /**
137
+ * A list of this page in other languages: every link names its language (hreflang) and opens a page, and every other
138
+ * item is only a label, the language being read ("English", "Español"). An item with a sentence, or a link to a file
139
+ * (a form in each language), makes it the document's.
140
+ */
141
+ const isLanguageSwitch = (body) => {
142
+ const links = [...body.matchAll(ANY_LINK)].map((link) => link[0]);
143
+ const items = body.split(/<li\b[^>]*>/iu).slice(1);
144
+ return (links.length > 0 &&
145
+ links.every((link) => HREFLANG.test(link) && !isFileLink(link)) &&
146
+ items.every((item) => isNavigation(item) || !/<a\b/iu.test(item)) &&
147
+ !hasSentence(body));
148
+ };
149
+ /** From the inside out, so a nested table of contents goes too once its inner lists are gone. */
150
+ const withoutNavigation = (html) => untilStable(html, (text) => {
151
+ const title = pageTitle(text);
152
+ return text.replace(/<(ul|ol)\b[^>]*>((?:(?!<[uo]l\b)[\s\S])*?)<\/\1\s*>/giu, (whole, _tag, body, at) => isNavigation(body) || isWordlessList(body) || isLanguageSwitch(body) || isBreadcrumbList(body, at, title) ? " " : whole);
153
+ });
154
+ const DEFINITION = /<dd\b[^>]*>([\s\S]*?)(?:<\/dd\s*>|(?=<d[dt]\b)|$)/giu;
155
+ const isMenuDefinition = (definition) => isNavigation(definition) || isBreadcrumbTrail(definition);
156
+ /**
157
+ * A definition list whose every definition is only links or a breadcrumb trail: a menu with its label as the term
158
+ * ("文字サイズ: 標準 大", "現在位置: トップ > 教育 > この頁").
159
+ */
160
+ const isLabelledMenu = (list) => [...list.matchAll(DEFINITION)].every((definition) => isMenuDefinition(definition[1] ?? ""));
161
+ const isDefinitionList = (range) => /^<dl\b/iu.test(range.openTag);
162
+ /** What a block holds besides its menus: its link-only lists taken out, or a labelled menu's terms. */
163
+ const besideMenus = (range) => isDefinitionList(range) && isLabelledMenu(range.inner) ? range.inner.replace(DEFINITION, " ") : withoutNavigation(range.inner);
164
+ const holdsMenu = (range) => besideMenus(range) !== range.inner || isLinksOnly(range);
165
+ /** Nothing but labels beside the menus: a sentence beside a menu makes the block the document's. */
166
+ const hasNoSentenceBesideMenus = (range) => !CLOSED_SENTENCE.test(plainText(besideMenus(range)));
167
+ const HEADER_BLOCKS = ["div", "section", "header", "dl"];
168
+ /**
169
+ * The innermost block that closes before the page's title opens and holds a menu (or only links), with no sentence beside it, is part
170
+ * of the site's header: it goes whole, with the tagline and labels beside the menu. Only the innermost, so that text
171
+ * sharing an outer block with a menu block (an agency and docket number) is kept; so is a block with a sentence in it.
172
+ */
173
+ const withoutSiteHeader = (html) => {
174
+ const title = pageTitle(html);
175
+ if (title === undefined)
176
+ return html;
177
+ const menus = HEADER_BLOCKS.flatMap((tag) => elementRanges(html, tag)).filter((range) => range.end <= title.start && holdsMenu(range));
178
+ const innermost = menus.filter((range) => !menus.some((inner) => isInside(range, inner)));
179
+ return withoutRanges(html, innermost.filter(hasNoSentenceBesideMenus).toSorted((left, right) => left.start - right.start));
180
+ };
181
+ const ICON_MENU_BLOCKS = ["div", "section"];
182
+ const LIST = /<(ul|ol)\b[^>]*>(?:(?!<[uo]l\b)[\s\S])*?<\/\1\s*>/giu;
183
+ const wordlessLists = (html) => [...html.matchAll(LIST)].map((list) => list[0]).filter((list) => isWordlessList(list.replace(/^<[^>]*>/u, "")));
184
+ /** What a block holds beside its lists of icons. */
185
+ const besideIcons = (range) => wordlessLists(range.inner).reduce((text, list) => text.replace(list, " "), range.inner);
186
+ /**
187
+ * Beside its wordless lists, one line, no sentence and no heading: the label of a row of icons ("Share & print",
188
+ * "Follow us"). A heading beside share buttons is the page's title.
189
+ */
190
+ const isIconMenu = (range) => {
191
+ const beside = besideIcons(range);
192
+ return textLines(beside).length === 1 && !hasSentence(beside) && !/<h[1-6]\b/iu.test(beside);
193
+ };
194
+ /**
195
+ * The innermost block holding a list of icons (share buttons, social links) and anything else goes whole when that is
196
+ * only a label; a wrapper around the list alone is passed over for the block that holds its label.
197
+ */
198
+ const withoutIconMenus = (html) => {
199
+ const menus = ICON_MENU_BLOCKS.flatMap((tag) => elementRanges(html, tag)).filter((range) => wordlessLists(range.inner).length > 0 && textLines(besideIcons(range)).length > 0);
200
+ const innermost = menus.filter((range) => !menus.some((inner) => isInside(range, inner)));
201
+ return withoutRanges(html, innermost.filter(isIconMenu).toSorted((left, right) => left.start - right.start));
202
+ };
203
+ const IMAGE = /<img\b[^>]*>/giu;
204
+ const ALT = /\salt\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))/iu;
205
+ const altText = (image) => {
206
+ const alt = ALT.exec(image);
207
+ return plainText(alt?.[1] ?? alt?.[2] ?? alt?.[3] ?? "");
208
+ };
209
+ /** The page's <title>, which names the page wherever it is shown (a tab, a bookmark, a search result). */
210
+ const documentTitle = (html) => plainText(/<title\b[^>]*>([\s\S]*?)<\/title\s*>/iu.exec(html)?.[1] ?? "");
211
+ /**
212
+ * A heading holding images and nothing else (a logo, a banner, a title set as a picture) carries the images' alt text
213
+ * only when that text is the page's title, which the reader sees drawn there; otherwise it goes whole, since the
214
+ * converter keeps no image's alt text anywhere else either.
215
+ */
216
+ const withImageHeadingsRead = (html, title) => html.replace(/<h([1-6])\b([^>]*)>([\s\S]*?)<\/h\1\s*>/giu, (whole, level, attributes, inside) => {
217
+ const images = inside.match(IMAGE) ?? [];
218
+ if (images.length === 0 || plainText(inside) !== "")
219
+ return whole;
220
+ const alt = images.map(altText).join(" ").trim();
221
+ return alt !== "" && alt === title ? `<h${level}${attributes}>${asMarkup(alt)}</h${level}>` : " ";
222
+ });
223
+ // An in-page link is wrapped in these marks so that one standing alone on its line ("Jump to main text") can be told
224
+ // from one inside a sentence ("see Table 1"); the first is dropped, the second keeps its text.
225
+ const LINK_START = "\u0001";
226
+ const LINK_END = "\u0002";
227
+ const markChromeLinks = (html) => html.replace(ANY_LINK, (link) => (isChromeLink(link) ? `${LINK_START}${stripTags(link)}${LINK_END}` : link));
228
+ const MARKED_LINK = new RegExp(`${LINK_START}[^${LINK_END}]*${LINK_END}`, "gu");
229
+ /**
230
+ * A line of in-page or paging links and at most a mark such as "▲" or "|" between them. Never a heading: a heading
231
+ * wrapped in a link back to the table of contents is still the section's title.
232
+ */
233
+ const isChromeLinkLine = (line) => headingLevel(line) === 0 && line.includes(LINK_START) && hasNoWords(line.replace(MARKED_LINK, ""));
234
+ // Without a year only the sign marks a notice: "(c)" alone opens an enumerated paragraph, "Copyright" alone a sentence.
235
+ const COPYRIGHT_NOTICE = /^(?:(?:copyright\s*)?(?:©|\(c\)|copyright)\s*\d{4}\b|copyright\s*(?:©|\(c\))|©)/iu;
236
+ /** A copyright notice at the very end of the page, where a site puts it when it has no <footer>. */
237
+ const withoutClosingCopyright = (lines) => {
238
+ const last = lines.findLastIndex((line) => line !== "");
239
+ return last >= 0 && COPYRIGHT_NOTICE.test(lines[last] ?? "") ? withoutClosingCopyright(lines.slice(0, last)) : [...lines];
240
+ };
241
+ const headingLevel = (line) => /^#{1,6} /u.exec(line)?.[0].length ?? 0;
242
+ /** A rule drawn with characters ("_____", "-----"), which Markdown reads as a thematic break: a line, not text. */
243
+ const isDrawnRule = (line) => /^(?:([-_*=])\s*)(?:\1\s*){2,}$/u.test(line);
244
+ /**
245
+ * Headings with nothing under them before the next heading of the same or a higher level: what dropped navigation left.
246
+ * A drawn rule under a heading is not something under it.
247
+ */
248
+ const withoutEmptySections = (lines) => lines.reduceRight((state, line) => {
249
+ if (line === "" || isDrawnRule(line))
250
+ return { kept: [line, ...state.kept], nextLevel: state.nextLevel };
251
+ const level = headingLevel(line) - 1;
252
+ if (level < 0)
253
+ return { kept: [line, ...state.kept], nextLevel: Number.POSITIVE_INFINITY };
254
+ if (state.nextLevel <= level)
255
+ return state;
256
+ return { kept: [line, ...state.kept], nextLevel: level };
257
+ }, { kept: [], nextLevel: 0 }).kept;
258
+ const BLOCK_TAGS = new Set([
259
+ "p",
260
+ "div",
261
+ "ul",
262
+ "ol",
263
+ "hr",
264
+ "blockquote",
265
+ "section",
266
+ "article",
267
+ "header",
268
+ "footer",
269
+ "main",
270
+ "aside",
271
+ "dl",
272
+ "dt",
273
+ "dd",
274
+ "figure",
275
+ "figcaption",
276
+ "pre",
277
+ "body",
278
+ "html",
279
+ ]);
280
+ const heading = (_whole, level, inside) => `\n\n${"#".repeat(Number(level))} ${stripTags(inside).trim()}\n\n`;
281
+ const asLines = (html) => html
282
+ .replace(/<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1\s*>/giu, heading)
283
+ .replace(/<li\b[^>]*>/giu, "\n- ")
284
+ .replace(/<\/li\s*>/giu, "")
285
+ .replace(/<br\s*\/?>/giu, "\n")
286
+ .replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/giu, (whole, tag) => (BLOCK_TAGS.has(tag.toLowerCase()) ? "\n\n" : whole));
287
+ const textLines = (html) => decodeEntities(stripTags(asLines(html)))
288
+ .split("\n")
289
+ .map((line) => line.trim())
290
+ .filter((line) => line !== "");
291
+ const ADDRESS = /<address\b[^>]*>[\s\S]*?<\/address\s*>/giu;
292
+ const isOnlyNotices = (html) => {
293
+ const lines = textLines(html);
294
+ return lines.length > 0 && lines.every((line) => COPYRIGHT_NOTICE.test(line));
295
+ };
296
+ const ADDRESS_BLOCKS = ["div", "section"];
297
+ /** What the innermost block around the address holds besides it, when it holds anything else. */
298
+ const besideAddress = (html, address) => {
299
+ const end = address.index + address[0].length;
300
+ const around = ADDRESS_BLOCKS.flatMap((tag) => elementRanges(html, tag))
301
+ .filter((range) => range.start < address.index && end <= range.end)
302
+ .toSorted((left, right) => right.start - left.start)
303
+ .map((range) => range.inner.replace(address[0], " "));
304
+ return around.find((beside) => textLines(beside).length > 0);
305
+ };
306
+ /**
307
+ * An <address> that shares its block with nothing but copyright notices, and has nothing but them after it, closes
308
+ * the page: the site's own contact line, in a footer written without <footer>. An address beside any other text (a
309
+ * label such as "Send comments to:"), with anything else after it, or with nothing after it, is kept.
310
+ */
311
+ const withoutClosingAddress = (html) => {
312
+ const last = [...html.matchAll(ADDRESS)].at(-1);
313
+ if (last === undefined)
314
+ return html;
315
+ const end = last.index + last[0].length;
316
+ const beside = besideAddress(html, last);
317
+ const isFooter = beside !== undefined && isOnlyNotices(beside) && isOnlyNotices(html.slice(end));
318
+ return isFooter ? `${html.slice(0, last.index)} ${html.slice(end)}` : html;
319
+ };
320
+ const CLOSING_BLOCKS = ["div", "section", "p"];
321
+ const isClosingMenu = (text, range) => isLinksOnly(range) && !plainLinks(range.inner).some(isFileLink) && textLines(text.slice(range.end)).length === 0;
322
+ /** Blocks of links to pages with nothing after them ("一覧に戻る"): a way around the site, as a menu is above the title. */
323
+ const withoutClosingLinks = (html) => untilStable(html, (text) => {
324
+ const closing = CLOSING_BLOCKS.flatMap((tag) => elementRanges(text, tag)).filter((range) => isClosingMenu(text, range));
325
+ return withoutRanges(text, closing.toSorted((left, right) => left.start - right.start));
326
+ });
327
+ // Markup's own spacing, collapsed as HTML does; U+3000 is a character Japanese text writes (a clause number and its text), so it stays.
328
+ const MARKUP_SPACE = /[^\S\u3000]+/gu;
329
+ // A zero-width space or joiner draws nothing, so a line of nothing else is empty (a page-number anchor).
330
+ const INVISIBLE_ONLY = /^[\s\p{Cf}]*$/u;
331
+ // An <h2> with no text in it (a spacer, an emptied widget) becomes "##": a heading with nothing to read.
332
+ const UNTITLED_HEADING = /^#{1,6}$/u;
333
+ export const htmlToMarkdown = (html) => {
334
+ const uncommented = withLostParagraphTagsRestored(withAttributeMarkupEscaped(html).replace(/<!--[\s\S]*?-->|<\?[\s\S]*?\?>/gu, ""));
335
+ const preformatted = withPreformattedStashed(withTablesRead(DROPPED.reduce(withoutElement, withoutRubyText(uncommented))));
336
+ const kept = withoutFootnoteMarks(withoutHeadingSelfLinks(withoutWidgets(withoutButtons(withoutReaderOnlyText(withoutHiddenElements(mainContent(preformatted.html))))))).replace(MARKUP_SPACE, " ");
337
+ const content = withoutClosingLinks(withoutLinkGroups(withoutNavigation(withoutIconMenus(withoutSiteHeader(withoutNavigationLandmarks(withoutClosingAddress(kept)))))));
338
+ const text = decodeEntities(stripTags(asLines(markChromeLinks(withImageHeadingsRead(withRunInHeadingsRead(content), documentTitle(uncommented))))));
339
+ const lines = text
340
+ .split("\n")
341
+ .map((line) => (INVISIBLE_ONLY.test(line) ? "" : line.trim()))
342
+ .filter((line) => line !== "-" && !isChromeLinkLine(line))
343
+ .map((line) => line.replaceAll(LINK_START, "").replaceAll(LINK_END, ""))
344
+ .filter((line) => !UNTITLED_HEADING.test(line));
345
+ return tidyLines(withPreformattedRestored(withoutEmptySections(withoutClosingCopyright(withoutEmptySections(lines))), preformatted.blocks));
346
+ };
347
+ //# sourceMappingURL=html-markdown.js.map