chaffjs 0.28.0 → 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 (895) hide show
  1. package/dist/ai-score/of-document.d.ts.map +1 -1
  2. package/dist/ai-score/of-document.js +23 -14
  3. package/dist/ai-score/of-document.js.map +1 -1
  4. package/dist/ai-score/render.d.ts.map +1 -1
  5. package/dist/ai-score/render.js +13 -4
  6. package/dist/ai-score/render.js.map +1 -1
  7. package/dist/ai-score/score.d.ts +16 -1
  8. package/dist/ai-score/score.d.ts.map +1 -1
  9. package/dist/ai-score/score.js +15 -3
  10. package/dist/ai-score/score.js.map +1 -1
  11. package/dist/ai-score/signals.d.ts +2 -4
  12. package/dist/ai-score/signals.d.ts.map +1 -1
  13. package/dist/ai-score/signals.js +11 -2
  14. package/dist/ai-score/signals.js.map +1 -1
  15. package/dist/ai-score/text.d.ts +2 -0
  16. package/dist/ai-score/text.d.ts.map +1 -1
  17. package/dist/ai-score/text.js +4 -2
  18. package/dist/ai-score/text.js.map +1 -1
  19. package/dist/announced-count.d.ts +2 -0
  20. package/dist/announced-count.d.ts.map +1 -1
  21. package/dist/announced-count.js +14 -7
  22. package/dist/announced-count.js.map +1 -1
  23. package/dist/check-source.d.ts +3 -1
  24. package/dist/check-source.d.ts.map +1 -1
  25. package/dist/check-source.js +3 -1
  26. package/dist/check-source.js.map +1 -1
  27. package/dist/cli-text.d.ts.map +1 -1
  28. package/dist/cli-text.js +38 -16
  29. package/dist/cli-text.js.map +1 -1
  30. package/dist/cli.d.ts.map +1 -1
  31. package/dist/cli.js +2 -1
  32. package/dist/cli.js.map +1 -1
  33. package/dist/commands/cite-claims.d.ts +36 -0
  34. package/dist/commands/cite-claims.d.ts.map +1 -0
  35. package/dist/commands/cite-claims.js +81 -0
  36. package/dist/commands/cite-claims.js.map +1 -0
  37. package/dist/commands/cite-page.d.ts +14 -0
  38. package/dist/commands/cite-page.d.ts.map +1 -0
  39. package/dist/commands/cite-page.js +47 -0
  40. package/dist/commands/cite-page.js.map +1 -0
  41. package/dist/commands/cite-scaffold.d.ts +16 -0
  42. package/dist/commands/cite-scaffold.d.ts.map +1 -0
  43. package/dist/commands/cite-scaffold.js +21 -0
  44. package/dist/commands/cite-scaffold.js.map +1 -0
  45. package/dist/commands/cite.d.ts +3 -12
  46. package/dist/commands/cite.d.ts.map +1 -1
  47. package/dist/commands/cite.js +110 -51
  48. package/dist/commands/cite.js.map +1 -1
  49. package/dist/company-names.d.ts +34 -0
  50. package/dist/company-names.d.ts.map +1 -0
  51. package/dist/company-names.js +158 -0
  52. package/dist/company-names.js.map +1 -0
  53. package/dist/default-values.d.ts +17 -0
  54. package/dist/default-values.d.ts.map +1 -0
  55. package/dist/default-values.js +134 -0
  56. package/dist/default-values.js.map +1 -0
  57. package/dist/deprecated-use.d.ts +17 -0
  58. package/dist/deprecated-use.d.ts.map +1 -0
  59. package/dist/deprecated-use.js +95 -0
  60. package/dist/deprecated-use.js.map +1 -0
  61. package/dist/derived/stays.d.ts +43 -0
  62. package/dist/derived/stays.d.ts.map +1 -0
  63. package/dist/derived/stays.js +105 -0
  64. package/dist/derived/stays.js.map +1 -0
  65. package/dist/detectors/acronym-context.d.ts +2 -2
  66. package/dist/detectors/acronym-context.d.ts.map +1 -1
  67. package/dist/detectors/acronym-context.js +6 -0
  68. package/dist/detectors/acronym-context.js.map +1 -1
  69. package/dist/detectors/address-word.d.ts +3 -0
  70. package/dist/detectors/address-word.d.ts.map +1 -0
  71. package/dist/detectors/address-word.js +7 -0
  72. package/dist/detectors/address-word.js.map +1 -0
  73. package/dist/detectors/agreement-slip.d.ts.map +1 -1
  74. package/dist/detectors/agreement-slip.js +4 -1
  75. package/dist/detectors/agreement-slip.js.map +1 -1
  76. package/dist/detectors/ai-phrasing.d.ts +0 -4
  77. package/dist/detectors/ai-phrasing.d.ts.map +1 -1
  78. package/dist/detectors/ai-phrasing.js +5 -1
  79. package/dist/detectors/ai-phrasing.js.map +1 -1
  80. package/dist/detectors/amount-range.d.ts +3 -0
  81. package/dist/detectors/amount-range.d.ts.map +1 -0
  82. package/dist/detectors/amount-range.js +38 -0
  83. package/dist/detectors/amount-range.js.map +1 -0
  84. package/dist/detectors/amount-scale.d.ts +6 -1
  85. package/dist/detectors/amount-scale.d.ts.map +1 -1
  86. package/dist/detectors/amount-scale.js +33 -9
  87. package/dist/detectors/amount-scale.js.map +1 -1
  88. package/dist/detectors/announced-count.d.ts +1 -1
  89. package/dist/detectors/announced-count.d.ts.map +1 -1
  90. package/dist/detectors/announced-count.js +18 -3
  91. package/dist/detectors/announced-count.js.map +1 -1
  92. package/dist/detectors/bare-comparative.d.ts.map +1 -1
  93. package/dist/detectors/bare-comparative.js +4 -1
  94. package/dist/detectors/bare-comparative.js.map +1 -1
  95. package/dist/detectors/block-quotation.d.ts +13 -0
  96. package/dist/detectors/block-quotation.d.ts.map +1 -0
  97. package/dist/detectors/block-quotation.js +86 -0
  98. package/dist/detectors/block-quotation.js.map +1 -0
  99. package/dist/detectors/bracket-label.d.ts +10 -0
  100. package/dist/detectors/bracket-label.d.ts.map +1 -0
  101. package/dist/detectors/bracket-label.js +51 -0
  102. package/dist/detectors/bracket-label.js.map +1 -0
  103. package/dist/detectors/citation-entry.d.ts +5 -0
  104. package/dist/detectors/citation-entry.d.ts.map +1 -1
  105. package/dist/detectors/citation-entry.js +19 -5
  106. package/dist/detectors/citation-entry.js.map +1 -1
  107. package/dist/detectors/code-before.d.ts +6 -0
  108. package/dist/detectors/code-before.d.ts.map +1 -0
  109. package/dist/detectors/code-before.js +15 -0
  110. package/dist/detectors/code-before.js.map +1 -0
  111. package/dist/detectors/connective-hierarchy.d.ts +11 -1
  112. package/dist/detectors/connective-hierarchy.d.ts.map +1 -1
  113. package/dist/detectors/connective-hierarchy.js +26 -6
  114. package/dist/detectors/connective-hierarchy.js.map +1 -1
  115. package/dist/detectors/currency-notation.d.ts.map +1 -1
  116. package/dist/detectors/currency-notation.js +2 -1
  117. package/dist/detectors/currency-notation.js.map +1 -1
  118. package/dist/detectors/date-outside-period.d.ts +4 -0
  119. package/dist/detectors/date-outside-period.d.ts.map +1 -0
  120. package/dist/detectors/date-outside-period.js +34 -0
  121. package/dist/detectors/date-outside-period.js.map +1 -0
  122. package/dist/detectors/default-values.d.ts +3 -0
  123. package/dist/detectors/default-values.d.ts.map +1 -0
  124. package/dist/detectors/default-values.js +14 -0
  125. package/dist/detectors/default-values.js.map +1 -0
  126. package/dist/detectors/defined-term-form.d.ts +6 -2
  127. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  128. package/dist/detectors/defined-term-form.js +72 -12
  129. package/dist/detectors/defined-term-form.js.map +1 -1
  130. package/dist/detectors/definition-use.d.ts.map +1 -1
  131. package/dist/detectors/definition-use.js +8 -1
  132. package/dist/detectors/definition-use.js.map +1 -1
  133. package/dist/detectors/deprecated-use.d.ts +3 -0
  134. package/dist/detectors/deprecated-use.d.ts.map +1 -0
  135. package/dist/detectors/deprecated-use.js +14 -0
  136. package/dist/detectors/deprecated-use.js.map +1 -0
  137. package/dist/detectors/derived-numbers.d.ts +1 -1
  138. package/dist/detectors/derived-numbers.d.ts.map +1 -1
  139. package/dist/detectors/derived-numbers.js +70 -15
  140. package/dist/detectors/derived-numbers.js.map +1 -1
  141. package/dist/detectors/document-shape.d.ts +1 -0
  142. package/dist/detectors/document-shape.d.ts.map +1 -1
  143. package/dist/detectors/document-shape.js +4 -1
  144. package/dist/detectors/document-shape.js.map +1 -1
  145. package/dist/detectors/due-date.d.ts +3 -0
  146. package/dist/detectors/due-date.d.ts.map +1 -0
  147. package/dist/detectors/due-date.js +38 -0
  148. package/dist/detectors/due-date.js.map +1 -0
  149. package/dist/detectors/en-shape.d.ts.map +1 -1
  150. package/dist/detectors/en-shape.js +17 -9
  151. package/dist/detectors/en-shape.js.map +1 -1
  152. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  153. package/dist/detectors/fact-consistency.js +76 -2
  154. package/dist/detectors/fact-consistency.js.map +1 -1
  155. package/dist/detectors/heading-echo.d.ts.map +1 -1
  156. package/dist/detectors/heading-echo.js +10 -1
  157. package/dist/detectors/heading-echo.js.map +1 -1
  158. package/dist/detectors/kana-function-word.d.ts +12 -0
  159. package/dist/detectors/kana-function-word.d.ts.map +1 -0
  160. package/dist/detectors/kana-function-word.js +59 -0
  161. package/dist/detectors/kana-function-word.js.map +1 -0
  162. package/dist/detectors/line-amount.d.ts +3 -0
  163. package/dist/detectors/line-amount.d.ts.map +1 -0
  164. package/dist/detectors/line-amount.js +22 -0
  165. package/dist/detectors/line-amount.js.map +1 -0
  166. package/dist/detectors/location-pointer.d.ts +6 -0
  167. package/dist/detectors/location-pointer.d.ts.map +1 -0
  168. package/dist/detectors/location-pointer.js +22 -0
  169. package/dist/detectors/location-pointer.js.map +1 -0
  170. package/dist/detectors/mark-shape.d.ts.map +1 -1
  171. package/dist/detectors/mark-shape.js +13 -1
  172. package/dist/detectors/mark-shape.js.map +1 -1
  173. package/dist/detectors/nado-closed-list.d.ts +3 -0
  174. package/dist/detectors/nado-closed-list.d.ts.map +1 -0
  175. package/dist/detectors/nado-closed-list.js +21 -0
  176. package/dist/detectors/nado-closed-list.js.map +1 -0
  177. package/dist/detectors/name-variant.d.ts.map +1 -1
  178. package/dist/detectors/name-variant.js +82 -8
  179. package/dist/detectors/name-variant.js.map +1 -1
  180. package/dist/detectors/next-word.d.ts.map +1 -1
  181. package/dist/detectors/next-word.js +41 -8
  182. package/dist/detectors/next-word.js.map +1 -1
  183. package/dist/detectors/number-word-figure.d.ts +5 -0
  184. package/dist/detectors/number-word-figure.d.ts.map +1 -0
  185. package/dist/detectors/number-word-figure.js +32 -0
  186. package/dist/detectors/number-word-figure.js.map +1 -0
  187. package/dist/detectors/obligation-without-deadline.d.ts +39 -0
  188. package/dist/detectors/obligation-without-deadline.d.ts.map +1 -0
  189. package/dist/detectors/obligation-without-deadline.js +148 -0
  190. package/dist/detectors/obligation-without-deadline.js.map +1 -0
  191. package/dist/detectors/open-end-names.d.ts +23 -0
  192. package/dist/detectors/open-end-names.d.ts.map +1 -0
  193. package/dist/detectors/open-end-names.js +95 -0
  194. package/dist/detectors/open-end-names.js.map +1 -0
  195. package/dist/detectors/ordinal-run-gaps.d.ts +8 -0
  196. package/dist/detectors/ordinal-run-gaps.d.ts.map +1 -0
  197. package/dist/detectors/ordinal-run-gaps.js +80 -0
  198. package/dist/detectors/ordinal-run-gaps.js.map +1 -0
  199. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  200. package/dist/detectors/orthographic-variant.js +26 -9
  201. package/dist/detectors/orthographic-variant.js.map +1 -1
  202. package/dist/detectors/orthography.d.ts.map +1 -1
  203. package/dist/detectors/orthography.js +5 -0
  204. package/dist/detectors/orthography.js.map +1 -1
  205. package/dist/detectors/parameter-table.d.ts +3 -0
  206. package/dist/detectors/parameter-table.d.ts.map +1 -0
  207. package/dist/detectors/parameter-table.js +16 -0
  208. package/dist/detectors/parameter-table.js.map +1 -0
  209. package/dist/detectors/phone-number-variant.d.ts +3 -0
  210. package/dist/detectors/phone-number-variant.d.ts.map +1 -0
  211. package/dist/detectors/phone-number-variant.js +18 -0
  212. package/dist/detectors/phone-number-variant.js.map +1 -0
  213. package/dist/detectors/prerequisite-order.d.ts +3 -0
  214. package/dist/detectors/prerequisite-order.d.ts.map +1 -0
  215. package/dist/detectors/prerequisite-order.js +30 -0
  216. package/dist/detectors/prerequisite-order.js.map +1 -0
  217. package/dist/detectors/quote-unnamed-speaker.d.ts +3 -0
  218. package/dist/detectors/quote-unnamed-speaker.d.ts.map +1 -0
  219. package/dist/detectors/quote-unnamed-speaker.js +18 -0
  220. package/dist/detectors/quote-unnamed-speaker.js.map +1 -0
  221. package/dist/detectors/quote-without-source.d.ts +12 -2
  222. package/dist/detectors/quote-without-source.d.ts.map +1 -1
  223. package/dist/detectors/quote-without-source.js +45 -11
  224. package/dist/detectors/quote-without-source.js.map +1 -1
  225. package/dist/detectors/registry/amount-range.d.ts +3 -0
  226. package/dist/detectors/registry/amount-range.d.ts.map +1 -0
  227. package/dist/detectors/registry/amount-range.js +3 -0
  228. package/dist/detectors/registry/amount-range.js.map +1 -0
  229. package/dist/detectors/registry/arrival-before-departure.d.ts +3 -0
  230. package/dist/detectors/registry/arrival-before-departure.d.ts.map +1 -0
  231. package/dist/detectors/registry/arrival-before-departure.js +3 -0
  232. package/dist/detectors/registry/arrival-before-departure.js.map +1 -0
  233. package/dist/detectors/registry/date-outside-period.d.ts +3 -0
  234. package/dist/detectors/registry/date-outside-period.d.ts.map +1 -0
  235. package/dist/detectors/registry/date-outside-period.js +3 -0
  236. package/dist/detectors/registry/date-outside-period.js.map +1 -0
  237. package/dist/detectors/registry/default-values.d.ts +3 -0
  238. package/dist/detectors/registry/default-values.d.ts.map +1 -0
  239. package/dist/detectors/registry/default-values.js +3 -0
  240. package/dist/detectors/registry/default-values.js.map +1 -0
  241. package/dist/detectors/registry/deprecated-use.d.ts +3 -0
  242. package/dist/detectors/registry/deprecated-use.d.ts.map +1 -0
  243. package/dist/detectors/registry/deprecated-use.js +3 -0
  244. package/dist/detectors/registry/deprecated-use.js.map +1 -0
  245. package/dist/detectors/registry/due-date.d.ts +3 -0
  246. package/dist/detectors/registry/due-date.d.ts.map +1 -0
  247. package/dist/detectors/registry/due-date.js +3 -0
  248. package/dist/detectors/registry/due-date.js.map +1 -0
  249. package/dist/detectors/registry/kana-function-word.d.ts +3 -0
  250. package/dist/detectors/registry/kana-function-word.d.ts.map +1 -0
  251. package/dist/detectors/registry/kana-function-word.js +3 -0
  252. package/dist/detectors/registry/kana-function-word.js.map +1 -0
  253. package/dist/detectors/registry/line-amount.d.ts +3 -0
  254. package/dist/detectors/registry/line-amount.d.ts.map +1 -0
  255. package/dist/detectors/registry/line-amount.js +3 -0
  256. package/dist/detectors/registry/line-amount.js.map +1 -0
  257. package/dist/detectors/registry/nado-closed-list.d.ts +3 -0
  258. package/dist/detectors/registry/nado-closed-list.d.ts.map +1 -0
  259. package/dist/detectors/registry/nado-closed-list.js +3 -0
  260. package/dist/detectors/registry/nado-closed-list.js.map +1 -0
  261. package/dist/detectors/registry/number-word-figure.d.ts +3 -0
  262. package/dist/detectors/registry/number-word-figure.d.ts.map +1 -0
  263. package/dist/detectors/registry/number-word-figure.js +3 -0
  264. package/dist/detectors/registry/number-word-figure.js.map +1 -0
  265. package/dist/detectors/registry/obligation-without-deadline.d.ts +3 -0
  266. package/dist/detectors/registry/obligation-without-deadline.d.ts.map +1 -0
  267. package/dist/detectors/registry/obligation-without-deadline.js +3 -0
  268. package/dist/detectors/registry/obligation-without-deadline.js.map +1 -0
  269. package/dist/detectors/registry/parameter-table.d.ts +3 -0
  270. package/dist/detectors/registry/parameter-table.d.ts.map +1 -0
  271. package/dist/detectors/registry/parameter-table.js +3 -0
  272. package/dist/detectors/registry/parameter-table.js.map +1 -0
  273. package/dist/detectors/registry/phone-number-variant.d.ts +3 -0
  274. package/dist/detectors/registry/phone-number-variant.d.ts.map +1 -0
  275. package/dist/detectors/registry/phone-number-variant.js +3 -0
  276. package/dist/detectors/registry/phone-number-variant.js.map +1 -0
  277. package/dist/detectors/registry/prerequisite-order.d.ts +3 -0
  278. package/dist/detectors/registry/prerequisite-order.d.ts.map +1 -0
  279. package/dist/detectors/registry/prerequisite-order.js +3 -0
  280. package/dist/detectors/registry/prerequisite-order.js.map +1 -0
  281. package/dist/detectors/registry/quote-unnamed-speaker.d.ts +3 -0
  282. package/dist/detectors/registry/quote-unnamed-speaker.d.ts.map +1 -0
  283. package/dist/detectors/registry/quote-unnamed-speaker.js +3 -0
  284. package/dist/detectors/registry/quote-unnamed-speaker.js.map +1 -0
  285. package/dist/detectors/registry/tax-amount.d.ts +3 -0
  286. package/dist/detectors/registry/tax-amount.d.ts.map +1 -0
  287. package/dist/detectors/registry/tax-amount.js +3 -0
  288. package/dist/detectors/registry/tax-amount.js.map +1 -0
  289. package/dist/detectors/registry/time-order.d.ts +3 -0
  290. package/dist/detectors/registry/time-order.d.ts.map +1 -0
  291. package/dist/detectors/registry/time-order.js +3 -0
  292. package/dist/detectors/registry/time-order.js.map +1 -0
  293. package/dist/detectors/registry/ui-label.d.ts +3 -0
  294. package/dist/detectors/registry/ui-label.d.ts.map +1 -0
  295. package/dist/detectors/registry/ui-label.js +3 -0
  296. package/dist/detectors/registry/ui-label.js.map +1 -0
  297. package/dist/detectors/registry/undefined-call.d.ts +3 -0
  298. package/dist/detectors/registry/undefined-call.d.ts.map +1 -0
  299. package/dist/detectors/registry/undefined-call.js +3 -0
  300. package/dist/detectors/registry/undefined-call.js.map +1 -0
  301. package/dist/detectors/registry/undefined-term.d.ts +3 -0
  302. package/dist/detectors/registry/undefined-term.d.ts.map +1 -0
  303. package/dist/detectors/registry/undefined-term.js +3 -0
  304. package/dist/detectors/registry/undefined-term.js.map +1 -0
  305. package/dist/detectors/registry/version-order.d.ts +3 -0
  306. package/dist/detectors/registry/version-order.d.ts.map +1 -0
  307. package/dist/detectors/registry/version-order.js +3 -0
  308. package/dist/detectors/registry/version-order.js.map +1 -0
  309. package/dist/detectors/registry/warning-action.d.ts +3 -0
  310. package/dist/detectors/registry/warning-action.d.ts.map +1 -0
  311. package/dist/detectors/registry/warning-action.js +3 -0
  312. package/dist/detectors/registry/warning-action.js.map +1 -0
  313. package/dist/detectors/requirement-smell.d.ts.map +1 -1
  314. package/dist/detectors/requirement-smell.js +25 -8
  315. package/dist/detectors/requirement-smell.js.map +1 -1
  316. package/dist/detectors/structure-tree.d.ts +12 -4
  317. package/dist/detectors/structure-tree.d.ts.map +1 -1
  318. package/dist/detectors/structure-tree.js +31 -14
  319. package/dist/detectors/structure-tree.js.map +1 -1
  320. package/dist/detectors/superlative-scope.d.ts.map +1 -1
  321. package/dist/detectors/superlative-scope.js +11 -1
  322. package/dist/detectors/superlative-scope.js.map +1 -1
  323. package/dist/detectors/tax-amount.d.ts +3 -0
  324. package/dist/detectors/tax-amount.d.ts.map +1 -0
  325. package/dist/detectors/tax-amount.js +19 -0
  326. package/dist/detectors/tax-amount.js.map +1 -0
  327. package/dist/detectors/technical-docs.d.ts.map +1 -1
  328. package/dist/detectors/technical-docs.js +5 -1
  329. package/dist/detectors/technical-docs.js.map +1 -1
  330. package/dist/detectors/term-extension.d.ts +14 -0
  331. package/dist/detectors/term-extension.d.ts.map +1 -0
  332. package/dist/detectors/term-extension.js +67 -0
  333. package/dist/detectors/term-extension.js.map +1 -0
  334. package/dist/detectors/time-order.d.ts +4 -0
  335. package/dist/detectors/time-order.d.ts.map +1 -0
  336. package/dist/detectors/time-order.js +32 -0
  337. package/dist/detectors/time-order.js.map +1 -0
  338. package/dist/detectors/ui-label.d.ts +3 -0
  339. package/dist/detectors/ui-label.d.ts.map +1 -0
  340. package/dist/detectors/ui-label.js +16 -0
  341. package/dist/detectors/ui-label.js.map +1 -0
  342. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
  343. package/dist/detectors/unbalanced-bracket.js +8 -13
  344. package/dist/detectors/unbalanced-bracket.js.map +1 -1
  345. package/dist/detectors/undefined-call.d.ts +3 -0
  346. package/dist/detectors/undefined-call.d.ts.map +1 -0
  347. package/dist/detectors/undefined-call.js +18 -0
  348. package/dist/detectors/undefined-call.js.map +1 -0
  349. package/dist/detectors/undefined-term.d.ts +22 -0
  350. package/dist/detectors/undefined-term.d.ts.map +1 -0
  351. package/dist/detectors/undefined-term.js +85 -0
  352. package/dist/detectors/undefined-term.js.map +1 -0
  353. package/dist/detectors/unknown-word.d.ts +1 -1
  354. package/dist/detectors/unknown-word.js +3 -3
  355. package/dist/detectors/unknown-word.js.map +1 -1
  356. package/dist/detectors/vague-deadline.d.ts +4 -0
  357. package/dist/detectors/vague-deadline.d.ts.map +1 -1
  358. package/dist/detectors/vague-deadline.js +3 -3
  359. package/dist/detectors/vague-deadline.js.map +1 -1
  360. package/dist/detectors/version-mismatch.d.ts.map +1 -1
  361. package/dist/detectors/version-mismatch.js +18 -1
  362. package/dist/detectors/version-mismatch.js.map +1 -1
  363. package/dist/detectors/version-order.d.ts +3 -0
  364. package/dist/detectors/version-order.d.ts.map +1 -0
  365. package/dist/detectors/version-order.js +43 -0
  366. package/dist/detectors/version-order.js.map +1 -0
  367. package/dist/detectors/warning-action.d.ts +3 -0
  368. package/dist/detectors/warning-action.d.ts.map +1 -0
  369. package/dist/detectors/warning-action.js +48 -0
  370. package/dist/detectors/warning-action.js.map +1 -0
  371. package/dist/facts/condition-pairs.d.ts +51 -0
  372. package/dist/facts/condition-pairs.d.ts.map +1 -0
  373. package/dist/facts/condition-pairs.js +203 -0
  374. package/dist/facts/condition-pairs.js.map +1 -0
  375. package/dist/facts/event-dates.d.ts +26 -0
  376. package/dist/facts/event-dates.d.ts.map +1 -0
  377. package/dist/facts/event-dates.js +38 -0
  378. package/dist/facts/event-dates.js.map +1 -0
  379. package/dist/facts/fact-scope.d.ts +2 -0
  380. package/dist/facts/fact-scope.d.ts.map +1 -1
  381. package/dist/facts/fact-scope.js +5 -0
  382. package/dist/facts/fact-scope.js.map +1 -1
  383. package/dist/facts/labelled-facts.d.ts +2 -0
  384. package/dist/facts/labelled-facts.d.ts.map +1 -1
  385. package/dist/facts/labelled-facts.js +9 -1
  386. package/dist/facts/labelled-facts.js.map +1 -1
  387. package/dist/facts/table-facts.d.ts +16 -0
  388. package/dist/facts/table-facts.d.ts.map +1 -1
  389. package/dist/facts/table-facts.js +2 -2
  390. package/dist/facts/table-facts.js.map +1 -1
  391. package/dist/grade/ai-score.d.ts +1 -1
  392. package/dist/grade/ai-score.d.ts.map +1 -1
  393. package/dist/grade/text.js +2 -2
  394. package/dist/grade/text.js.map +1 -1
  395. package/dist/heading-numbering.js +2 -2
  396. package/dist/heading-numbering.js.map +1 -1
  397. package/dist/html/fetch-page.d.ts +20 -0
  398. package/dist/html/fetch-page.d.ts.map +1 -0
  399. package/dist/html/fetch-page.js +51 -0
  400. package/dist/html/fetch-page.js.map +1 -0
  401. package/dist/html/fetched-text.d.ts +5 -0
  402. package/dist/html/fetched-text.d.ts.map +1 -0
  403. package/dist/html/fetched-text.js +25 -0
  404. package/dist/html/fetched-text.js.map +1 -0
  405. package/dist/html/html-content-block.d.ts +6 -0
  406. package/dist/html/html-content-block.d.ts.map +1 -0
  407. package/dist/html/html-content-block.js +86 -0
  408. package/dist/html/html-content-block.js.map +1 -0
  409. package/dist/html/html-elements.d.ts +41 -0
  410. package/dist/html/html-elements.d.ts.map +1 -0
  411. package/dist/html/html-elements.js +91 -0
  412. package/dist/html/html-elements.js.map +1 -0
  413. package/dist/html/html-footnote-marks.d.ts +2 -0
  414. package/dist/html/html-footnote-marks.d.ts.map +1 -0
  415. package/dist/html/html-footnote-marks.js +15 -0
  416. package/dist/html/html-footnote-marks.js.map +1 -0
  417. package/dist/html/html-heading-links.d.ts +6 -0
  418. package/dist/html/html-heading-links.d.ts.map +1 -0
  419. package/dist/html/html-heading-links.js +71 -0
  420. package/dist/html/html-heading-links.js.map +1 -0
  421. package/dist/html/html-lost-tags.d.ts +3 -0
  422. package/dist/html/html-lost-tags.d.ts.map +1 -0
  423. package/dist/html/html-lost-tags.js +11 -0
  424. package/dist/html/html-lost-tags.js.map +1 -0
  425. package/dist/html/html-markdown.d.ts +2 -0
  426. package/dist/html/html-markdown.d.ts.map +1 -0
  427. package/dist/html/html-markdown.js +347 -0
  428. package/dist/html/html-markdown.js.map +1 -0
  429. package/dist/html/html-preformatted.d.ts +17 -0
  430. package/dist/html/html-preformatted.d.ts.map +1 -0
  431. package/dist/html/html-preformatted.js +82 -0
  432. package/dist/html/html-preformatted.js.map +1 -0
  433. package/dist/html/html-reader-only.d.ts +6 -0
  434. package/dist/html/html-reader-only.d.ts.map +1 -0
  435. package/dist/html/html-reader-only.js +63 -0
  436. package/dist/html/html-reader-only.js.map +1 -0
  437. package/dist/html/html-run-in-headings.d.ts +2 -0
  438. package/dist/html/html-run-in-headings.d.ts.map +1 -0
  439. package/dist/html/html-run-in-headings.js +36 -0
  440. package/dist/html/html-run-in-headings.js.map +1 -0
  441. package/dist/html/html-tables.d.ts +3 -0
  442. package/dist/html/html-tables.d.ts.map +1 -0
  443. package/dist/html/html-tables.js +58 -0
  444. package/dist/html/html-tables.js.map +1 -0
  445. package/dist/html/html-widgets.d.ts +3 -0
  446. package/dist/html/html-widgets.d.ts.map +1 -0
  447. package/dist/html/html-widgets.js +71 -0
  448. package/dist/html/html-widgets.js.map +1 -0
  449. package/dist/html/markup-text.d.ts +5 -0
  450. package/dist/html/markup-text.d.ts.map +1 -0
  451. package/dist/html/markup-text.js +32 -0
  452. package/dist/html/markup-text.js.map +1 -0
  453. package/dist/html/page-document.d.ts +9 -0
  454. package/dist/html/page-document.d.ts.map +1 -0
  455. package/dist/html/page-document.js +19 -0
  456. package/dist/html/page-document.js.map +1 -0
  457. package/dist/inline-count.d.ts +19 -0
  458. package/dist/inline-count.d.ts.map +1 -0
  459. package/dist/inline-count.js +109 -0
  460. package/dist/inline-count.js.map +1 -0
  461. package/dist/kana-spelling.d.ts +5 -0
  462. package/dist/kana-spelling.d.ts.map +1 -1
  463. package/dist/kana-spelling.js +5 -0
  464. package/dist/kana-spelling.js.map +1 -1
  465. package/dist/location-part.d.ts +13 -0
  466. package/dist/location-part.d.ts.map +1 -0
  467. package/dist/location-part.js +24 -0
  468. package/dist/location-part.js.map +1 -0
  469. package/dist/nado-closed-list.d.ts +20 -0
  470. package/dist/nado-closed-list.d.ts.map +1 -0
  471. package/dist/nado-closed-list.js +72 -0
  472. package/dist/nado-closed-list.js.map +1 -0
  473. package/dist/name-cue.d.ts +17 -0
  474. package/dist/name-cue.d.ts.map +1 -0
  475. package/dist/name-cue.js +29 -0
  476. package/dist/name-cue.js.map +1 -0
  477. package/dist/name-variants.d.ts +23 -1
  478. package/dist/name-variants.d.ts.map +1 -1
  479. package/dist/name-variants.js +39 -8
  480. package/dist/name-variants.js.map +1 -1
  481. package/dist/paragraph-runs.d.ts +6 -1
  482. package/dist/paragraph-runs.d.ts.map +1 -1
  483. package/dist/paragraph-runs.js +9 -2
  484. package/dist/paragraph-runs.js.map +1 -1
  485. package/dist/parameter-table.d.ts +19 -0
  486. package/dist/parameter-table.d.ts.map +1 -0
  487. package/dist/parameter-table.js +191 -0
  488. package/dist/parameter-table.js.map +1 -0
  489. package/dist/phone-numbers.d.ts +23 -0
  490. package/dist/phone-numbers.d.ts.map +1 -0
  491. package/dist/phone-numbers.js +83 -0
  492. package/dist/phone-numbers.js.map +1 -0
  493. package/dist/place-names.d.ts +55 -0
  494. package/dist/place-names.d.ts.map +1 -0
  495. package/dist/place-names.js +196 -0
  496. package/dist/place-names.js.map +1 -0
  497. package/dist/plugin.d.ts +4 -0
  498. package/dist/plugin.d.ts.map +1 -1
  499. package/dist/prerequisite-order.d.ts +16 -0
  500. package/dist/prerequisite-order.d.ts.map +1 -0
  501. package/dist/prerequisite-order.js +29 -0
  502. package/dist/prerequisite-order.js.map +1 -0
  503. package/dist/profile/parse.d.ts.map +1 -1
  504. package/dist/profile/parse.js +10 -1
  505. package/dist/profile/parse.js.map +1 -1
  506. package/dist/reasons.d.ts +2 -0
  507. package/dist/reasons.d.ts.map +1 -1
  508. package/dist/reasons.js +2 -0
  509. package/dist/reasons.js.map +1 -1
  510. package/dist/render/rules-json.d.ts.map +1 -1
  511. package/dist/render/rules-json.js +4 -0
  512. package/dist/render/rules-json.js.map +1 -1
  513. package/dist/render/rules-table.d.ts.map +1 -1
  514. package/dist/render/rules-table.js +6 -2
  515. package/dist/render/rules-table.js.map +1 -1
  516. package/dist/rule-genres.d.ts +5 -2
  517. package/dist/rule-genres.d.ts.map +1 -1
  518. package/dist/rule-genres.js +2 -0
  519. package/dist/rule-genres.js.map +1 -1
  520. package/dist/rule-load.d.ts.map +1 -1
  521. package/dist/rule-load.js +2 -1
  522. package/dist/rule-load.js.map +1 -1
  523. package/dist/run.d.ts.map +1 -1
  524. package/dist/run.js +5 -1
  525. package/dist/run.js.map +1 -1
  526. package/dist/spelling.d.ts +2 -0
  527. package/dist/spelling.d.ts.map +1 -1
  528. package/dist/spelling.js +6 -0
  529. package/dist/spelling.js.map +1 -1
  530. package/dist/structure/action-due.d.ts +21 -0
  531. package/dist/structure/action-due.d.ts.map +1 -0
  532. package/dist/structure/action-due.js +126 -0
  533. package/dist/structure/action-due.js.map +1 -0
  534. package/dist/structure/amount-range.d.ts +30 -0
  535. package/dist/structure/amount-range.d.ts.map +1 -0
  536. package/dist/structure/amount-range.js +153 -0
  537. package/dist/structure/amount-range.js.map +1 -0
  538. package/dist/structure/amount-scale.d.ts +6 -0
  539. package/dist/structure/amount-scale.d.ts.map +1 -1
  540. package/dist/structure/amount-scale.js +13 -0
  541. package/dist/structure/amount-scale.js.map +1 -1
  542. package/dist/structure/cite.d.ts +5 -2
  543. package/dist/structure/cite.d.ts.map +1 -1
  544. package/dist/structure/cite.js +20 -1
  545. package/dist/structure/cite.js.map +1 -1
  546. package/dist/structure/counted-amounts.d.ts +12 -0
  547. package/dist/structure/counted-amounts.d.ts.map +1 -0
  548. package/dist/structure/counted-amounts.js +30 -0
  549. package/dist/structure/counted-amounts.js.map +1 -0
  550. package/dist/structure/date-order.d.ts +24 -3
  551. package/dist/structure/date-order.d.ts.map +1 -1
  552. package/dist/structure/date-order.js +49 -17
  553. package/dist/structure/date-order.js.map +1 -1
  554. package/dist/structure/date-outside-period.d.ts +27 -0
  555. package/dist/structure/date-outside-period.d.ts.map +1 -0
  556. package/dist/structure/date-outside-period.js +86 -0
  557. package/dist/structure/date-outside-period.js.map +1 -0
  558. package/dist/structure/definition-use.d.ts +5 -2
  559. package/dist/structure/definition-use.d.ts.map +1 -1
  560. package/dist/structure/definition-use.js +11 -3
  561. package/dist/structure/definition-use.js.map +1 -1
  562. package/dist/structure/due-date.d.ts +19 -0
  563. package/dist/structure/due-date.d.ts.map +1 -0
  564. package/dist/structure/due-date.js +30 -0
  565. package/dist/structure/due-date.js.map +1 -0
  566. package/dist/structure/heading-runs.d.ts +9 -0
  567. package/dist/structure/heading-runs.d.ts.map +1 -0
  568. package/dist/structure/heading-runs.js +23 -0
  569. package/dist/structure/heading-runs.js.map +1 -0
  570. package/dist/structure/install-pin.d.ts +46 -0
  571. package/dist/structure/install-pin.d.ts.map +1 -0
  572. package/dist/structure/install-pin.js +85 -0
  573. package/dist/structure/install-pin.js.map +1 -0
  574. package/dist/structure/leg-times.d.ts +34 -0
  575. package/dist/structure/leg-times.d.ts.map +1 -0
  576. package/dist/structure/leg-times.js +135 -0
  577. package/dist/structure/leg-times.js.map +1 -0
  578. package/dist/structure/line-amount-unit.d.ts +24 -0
  579. package/dist/structure/line-amount-unit.d.ts.map +1 -0
  580. package/dist/structure/line-amount-unit.js +24 -0
  581. package/dist/structure/line-amount-unit.js.map +1 -0
  582. package/dist/structure/line-amount.d.ts +40 -0
  583. package/dist/structure/line-amount.d.ts.map +1 -0
  584. package/dist/structure/line-amount.js +118 -0
  585. package/dist/structure/line-amount.js.map +1 -0
  586. package/dist/structure/number-word-figure.d.ts +37 -0
  587. package/dist/structure/number-word-figure.d.ts.map +1 -0
  588. package/dist/structure/number-word-figure.js +151 -0
  589. package/dist/structure/number-word-figure.js.map +1 -0
  590. package/dist/structure/numbering.d.ts +1 -0
  591. package/dist/structure/numbering.d.ts.map +1 -1
  592. package/dist/structure/numbering.js +3 -0
  593. package/dist/structure/numbering.js.map +1 -1
  594. package/dist/structure/ordinal-runs.d.ts +45 -0
  595. package/dist/structure/ordinal-runs.d.ts.map +1 -0
  596. package/dist/structure/ordinal-runs.js +78 -0
  597. package/dist/structure/ordinal-runs.js.map +1 -0
  598. package/dist/structure/percent-sum-prose.d.ts +1 -1
  599. package/dist/structure/percent-sum-prose.d.ts.map +1 -1
  600. package/dist/structure/percent-sum-prose.js +45 -3
  601. package/dist/structure/percent-sum-prose.js.map +1 -1
  602. package/dist/structure/percent-sum.d.ts +8 -0
  603. package/dist/structure/percent-sum.d.ts.map +1 -1
  604. package/dist/structure/percent-sum.js +8 -1
  605. package/dist/structure/percent-sum.js.map +1 -1
  606. package/dist/structure/release-list.d.ts +9 -0
  607. package/dist/structure/release-list.d.ts.map +1 -0
  608. package/dist/structure/release-list.js +46 -0
  609. package/dist/structure/release-list.js.map +1 -0
  610. package/dist/structure/share-column.d.ts +7 -0
  611. package/dist/structure/share-column.d.ts.map +1 -0
  612. package/dist/structure/share-column.js +22 -0
  613. package/dist/structure/share-column.js.map +1 -0
  614. package/dist/structure/stated-period.d.ts +31 -0
  615. package/dist/structure/stated-period.d.ts.map +1 -0
  616. package/dist/structure/stated-period.js +127 -0
  617. package/dist/structure/stated-period.js.map +1 -0
  618. package/dist/structure/tax.d.ts +25 -0
  619. package/dist/structure/tax.d.ts.map +1 -0
  620. package/dist/structure/tax.js +86 -0
  621. package/dist/structure/tax.js.map +1 -0
  622. package/dist/structure/time-marks.d.ts +58 -0
  623. package/dist/structure/time-marks.d.ts.map +1 -0
  624. package/dist/structure/time-marks.js +74 -0
  625. package/dist/structure/time-marks.js.map +1 -0
  626. package/dist/structure/time-order.d.ts +21 -0
  627. package/dist/structure/time-order.d.ts.map +1 -0
  628. package/dist/structure/time-order.js +108 -0
  629. package/dist/structure/time-order.js.map +1 -0
  630. package/dist/structure/title-lines.d.ts +8 -0
  631. package/dist/structure/title-lines.d.ts.map +1 -0
  632. package/dist/structure/title-lines.js +27 -0
  633. package/dist/structure/title-lines.js.map +1 -0
  634. package/dist/structure/total.d.ts.map +1 -1
  635. package/dist/structure/total.js +3 -1
  636. package/dist/structure/total.js.map +1 -1
  637. package/dist/structure/version-mismatch.d.ts +1 -5
  638. package/dist/structure/version-mismatch.d.ts.map +1 -1
  639. package/dist/structure/version-mismatch.js +65 -12
  640. package/dist/structure/version-mismatch.js.map +1 -1
  641. package/dist/structure/version-order.d.ts +23 -0
  642. package/dist/structure/version-order.d.ts.map +1 -0
  643. package/dist/structure/version-order.js +67 -0
  644. package/dist/structure/version-order.js.map +1 -0
  645. package/dist/table-text.d.ts +9 -0
  646. package/dist/table-text.d.ts.map +1 -0
  647. package/dist/table-text.js +36 -0
  648. package/dist/table-text.js.map +1 -0
  649. package/dist/ui-labels.d.ts +16 -0
  650. package/dist/ui-labels.d.ts.map +1 -0
  651. package/dist/ui-labels.js +42 -0
  652. package/dist/ui-labels.js.map +1 -0
  653. package/dist/undefined-call.d.ts +13 -0
  654. package/dist/undefined-call.d.ts.map +1 -0
  655. package/dist/undefined-call.js +55 -0
  656. package/dist/undefined-call.js.map +1 -0
  657. package/dist/unnamed-speaker.d.ts +23 -0
  658. package/dist/unnamed-speaker.d.ts.map +1 -0
  659. package/dist/unnamed-speaker.js +176 -0
  660. package/dist/unnamed-speaker.js.map +1 -0
  661. package/dist/warning-action.d.ts +22 -0
  662. package/dist/warning-action.d.ts.map +1 -0
  663. package/dist/warning-action.js +58 -0
  664. package/dist/warning-action.js.map +1 -0
  665. package/genres.yaml +2 -0
  666. package/package.json +4 -3
  667. package/profiles/statute.yaml +8 -0
  668. package/rules/agreement-slip.yaml +2 -2
  669. package/rules/amount-range-reversed.yaml +52 -0
  670. package/rules/amount-scale-consistency.yaml +4 -4
  671. package/rules/announced-count-mismatch.yaml +9 -4
  672. package/rules/arrival-before-departure.yaml +48 -0
  673. package/rules/connective-hierarchy.yaml +3 -3
  674. package/rules/currency-notation-consistency.yaml +2 -2
  675. package/rules/date-order.yaml +9 -4
  676. package/rules/date-outside-period.yaml +64 -0
  677. package/rules/default-value-mismatch.yaml +79 -0
  678. package/rules/defined-term-form.yaml +9 -7
  679. package/rules/deprecated-option-used.yaml +78 -0
  680. package/rules/doubled-nado.yaml +28 -12
  681. package/rules/due-before-issue.yaml +68 -0
  682. package/rules/duplicate-definition.yaml +2 -2
  683. package/rules/duration-mismatch.yaml +12 -4
  684. package/rules/heading-echo.yaml +2 -2
  685. package/rules/hyphen-as-dash.yaml +2 -2
  686. package/rules/kana-function-word.yaml +58 -0
  687. package/rules/latin-spacing.yaml +6 -5
  688. package/rules/line-amount-mismatch.yaml +58 -0
  689. package/rules/nado-closed-list.yaml +77 -0
  690. package/rules/name-variant.yaml +14 -2
  691. package/rules/number-word-figure-mismatch.yaml +76 -0
  692. package/rules/numbering-gap.yaml +2 -2
  693. package/rules/obligation-without-deadline.yaml +95 -0
  694. package/rules/one-sentence-paragraph-run.yaml +2 -3
  695. package/rules/parameter-table-mismatch.yaml +90 -0
  696. package/rules/percent-sum-mismatch.yaml +2 -2
  697. package/rules/phone-number-variant.yaml +68 -0
  698. package/rules/prerequisite-after-step.yaml +78 -0
  699. package/rules/quote-unnamed-speaker.yaml +67 -0
  700. package/rules/quote-without-source.yaml +6 -6
  701. package/rules/requirement-smell.yaml +3 -3
  702. package/rules/sentence-initial-conjunction-run.yaml +13 -7
  703. package/rules/summary-fact-mismatch.yaml +4 -4
  704. package/rules/tax-mismatch.yaml +71 -0
  705. package/rules/time-order.yaml +65 -0
  706. package/rules/title-length.yaml +2 -2
  707. package/rules/ui-label-variant.yaml +70 -0
  708. package/rules/unbalanced-bracket.yaml +4 -4
  709. package/rules/uncomparable-graded.yaml +29 -10
  710. package/rules/undefined-function-call.yaml +77 -0
  711. package/rules/undefined-term.yaml +72 -0
  712. package/rules/unknown-word.yaml +2 -2
  713. package/rules/unqualified-superlative.yaml +2 -2
  714. package/rules/use-before-definition.yaml +2 -2
  715. package/rules/version-mismatch.yaml +12 -4
  716. package/rules/version-order.yaml +85 -0
  717. package/rules/very-adjective.yaml +31 -13
  718. package/rules/warning-without-action.yaml +64 -0
  719. package/rules/wordy-phrase.yaml +27 -9
  720. package/src/ai-score/of-document.ts +19 -9
  721. package/src/ai-score/render.ts +24 -4
  722. package/src/ai-score/score.ts +24 -3
  723. package/src/ai-score/signals.ts +12 -2
  724. package/src/ai-score/text.ts +7 -2
  725. package/src/announced-count.ts +19 -12
  726. package/src/check-source.ts +11 -2
  727. package/src/cli-text.ts +38 -16
  728. package/src/cli.ts +2 -1
  729. package/src/commands/cite-claims.ts +103 -0
  730. package/src/commands/cite-page.ts +61 -0
  731. package/src/commands/cite-scaffold.ts +27 -0
  732. package/src/commands/cite.ts +127 -58
  733. package/src/company-names.ts +202 -0
  734. package/src/default-values.ts +158 -0
  735. package/src/deprecated-use.ts +122 -0
  736. package/src/derived/stays.ts +145 -0
  737. package/src/detectors/acronym-context.ts +10 -2
  738. package/src/detectors/address-word.ts +9 -0
  739. package/src/detectors/agreement-slip.ts +7 -1
  740. package/src/detectors/ai-phrasing.ts +6 -1
  741. package/src/detectors/amount-range.ts +54 -0
  742. package/src/detectors/amount-scale.ts +50 -17
  743. package/src/detectors/announced-count.ts +29 -11
  744. package/src/detectors/bare-comparative.ts +7 -2
  745. package/src/detectors/block-quotation.ts +95 -0
  746. package/src/detectors/bracket-label.ts +58 -0
  747. package/src/detectors/citation-entry.ts +20 -5
  748. package/src/detectors/code-before.ts +14 -0
  749. package/src/detectors/connective-hierarchy.ts +39 -11
  750. package/src/detectors/currency-notation.ts +2 -1
  751. package/src/detectors/date-outside-period.ts +38 -0
  752. package/src/detectors/default-values.ts +17 -0
  753. package/src/detectors/defined-term-form.ts +84 -15
  754. package/src/detectors/definition-use.ts +10 -2
  755. package/src/detectors/deprecated-use.ts +17 -0
  756. package/src/detectors/derived-numbers.ts +106 -15
  757. package/src/detectors/document-shape.ts +6 -1
  758. package/src/detectors/due-date.ts +47 -0
  759. package/src/detectors/en-shape.ts +27 -11
  760. package/src/detectors/fact-consistency.ts +95 -3
  761. package/src/detectors/heading-echo.ts +11 -1
  762. package/src/detectors/kana-function-word.ts +71 -0
  763. package/src/detectors/line-amount.ts +33 -0
  764. package/src/detectors/location-pointer.ts +30 -0
  765. package/src/detectors/mark-shape.ts +18 -1
  766. package/src/detectors/nado-closed-list.ts +25 -0
  767. package/src/detectors/name-variant.ts +106 -13
  768. package/src/detectors/next-word.ts +56 -9
  769. package/src/detectors/number-word-figure.ts +43 -0
  770. package/src/detectors/obligation-without-deadline.ts +192 -0
  771. package/src/detectors/open-end-names.ts +140 -0
  772. package/src/detectors/ordinal-run-gaps.ts +101 -0
  773. package/src/detectors/orthographic-variant.ts +39 -14
  774. package/src/detectors/orthography.ts +6 -1
  775. package/src/detectors/parameter-table.ts +17 -0
  776. package/src/detectors/phone-number-variant.ts +18 -0
  777. package/src/detectors/prerequisite-order.ts +35 -0
  778. package/src/detectors/quote-unnamed-speaker.ts +19 -0
  779. package/src/detectors/quote-without-source.ts +57 -10
  780. package/src/detectors/registry/amount-range.ts +4 -0
  781. package/src/detectors/registry/arrival-before-departure.ts +4 -0
  782. package/src/detectors/registry/date-outside-period.ts +4 -0
  783. package/src/detectors/registry/default-values.ts +4 -0
  784. package/src/detectors/registry/deprecated-use.ts +4 -0
  785. package/src/detectors/registry/due-date.ts +4 -0
  786. package/src/detectors/registry/kana-function-word.ts +4 -0
  787. package/src/detectors/registry/line-amount.ts +4 -0
  788. package/src/detectors/registry/nado-closed-list.ts +4 -0
  789. package/src/detectors/registry/number-word-figure.ts +4 -0
  790. package/src/detectors/registry/obligation-without-deadline.ts +4 -0
  791. package/src/detectors/registry/parameter-table.ts +4 -0
  792. package/src/detectors/registry/phone-number-variant.ts +4 -0
  793. package/src/detectors/registry/prerequisite-order.ts +4 -0
  794. package/src/detectors/registry/quote-unnamed-speaker.ts +4 -0
  795. package/src/detectors/registry/tax-amount.ts +4 -0
  796. package/src/detectors/registry/time-order.ts +4 -0
  797. package/src/detectors/registry/ui-label.ts +4 -0
  798. package/src/detectors/registry/undefined-call.ts +4 -0
  799. package/src/detectors/registry/undefined-term.ts +4 -0
  800. package/src/detectors/registry/version-order.ts +4 -0
  801. package/src/detectors/registry/warning-action.ts +4 -0
  802. package/src/detectors/requirement-smell.ts +29 -9
  803. package/src/detectors/structure-tree.ts +43 -21
  804. package/src/detectors/superlative-scope.ts +13 -1
  805. package/src/detectors/tax-amount.ts +25 -0
  806. package/src/detectors/technical-docs.ts +7 -1
  807. package/src/detectors/term-extension.ts +67 -0
  808. package/src/detectors/time-order.ts +49 -0
  809. package/src/detectors/ui-label.ts +17 -0
  810. package/src/detectors/unbalanced-bracket.ts +7 -14
  811. package/src/detectors/undefined-call.ts +19 -0
  812. package/src/detectors/undefined-term.ts +103 -0
  813. package/src/detectors/unknown-word.ts +3 -3
  814. package/src/detectors/vague-deadline.ts +3 -3
  815. package/src/detectors/version-mismatch.ts +26 -5
  816. package/src/detectors/version-order.ts +50 -0
  817. package/src/detectors/warning-action.ts +49 -0
  818. package/src/facts/condition-pairs.ts +289 -0
  819. package/src/facts/event-dates.ts +63 -0
  820. package/src/facts/fact-scope.ts +6 -0
  821. package/src/facts/labelled-facts.ts +13 -1
  822. package/src/facts/table-facts.ts +3 -3
  823. package/src/grade/ai-score.ts +1 -1
  824. package/src/grade/text.ts +2 -2
  825. package/src/heading-numbering.ts +2 -2
  826. package/src/html/fetch-page.ts +64 -0
  827. package/src/html/fetched-text.ts +32 -0
  828. package/src/html/html-content-block.ts +107 -0
  829. package/src/html/html-elements.ts +127 -0
  830. package/src/html/html-footnote-marks.ts +20 -0
  831. package/src/html/html-heading-links.ts +93 -0
  832. package/src/html/html-lost-tags.ts +14 -0
  833. package/src/html/html-markdown.ts +481 -0
  834. package/src/html/html-preformatted.ts +110 -0
  835. package/src/html/html-reader-only.ts +82 -0
  836. package/src/html/html-run-in-headings.ts +43 -0
  837. package/src/html/html-tables.ts +76 -0
  838. package/src/html/html-widgets.ts +114 -0
  839. package/src/html/markup-text.ts +35 -0
  840. package/src/html/page-document.ts +22 -0
  841. package/src/inline-count.ts +146 -0
  842. package/src/kana-spelling.ts +7 -0
  843. package/src/location-part.ts +30 -0
  844. package/src/nado-closed-list.ts +106 -0
  845. package/src/name-cue.ts +35 -0
  846. package/src/name-variants.ts +57 -11
  847. package/src/paragraph-runs.ts +12 -2
  848. package/src/parameter-table.ts +208 -0
  849. package/src/phone-numbers.ts +98 -0
  850. package/src/place-names.ts +248 -0
  851. package/src/plugin.ts +4 -0
  852. package/src/prerequisite-order.ts +39 -0
  853. package/src/profile/parse.ts +10 -1
  854. package/src/reasons.ts +4 -0
  855. package/src/render/rules-json.ts +4 -0
  856. package/src/render/rules-table.ts +6 -3
  857. package/src/rule-genres.ts +5 -2
  858. package/src/rule-load.ts +3 -2
  859. package/src/run.ts +3 -1
  860. package/src/spelling.ts +8 -0
  861. package/src/structure/action-due.ts +179 -0
  862. package/src/structure/amount-range.ts +219 -0
  863. package/src/structure/amount-scale.ts +18 -0
  864. package/src/structure/cite.ts +21 -2
  865. package/src/structure/counted-amounts.ts +42 -0
  866. package/src/structure/date-order.ts +72 -22
  867. package/src/structure/date-outside-period.ts +127 -0
  868. package/src/structure/definition-use.ts +24 -3
  869. package/src/structure/due-date.ts +46 -0
  870. package/src/structure/heading-runs.ts +24 -0
  871. package/src/structure/install-pin.ts +115 -0
  872. package/src/structure/leg-times.ts +198 -0
  873. package/src/structure/line-amount-unit.ts +35 -0
  874. package/src/structure/line-amount.ts +162 -0
  875. package/src/structure/number-word-figure.ts +199 -0
  876. package/src/structure/numbering.ts +3 -0
  877. package/src/structure/ordinal-runs.ts +107 -0
  878. package/src/structure/percent-sum-prose.ts +46 -3
  879. package/src/structure/percent-sum.ts +16 -2
  880. package/src/structure/release-list.ts +69 -0
  881. package/src/structure/share-column.ts +25 -0
  882. package/src/structure/stated-period.ts +161 -0
  883. package/src/structure/tax.ts +114 -0
  884. package/src/structure/time-marks.ts +127 -0
  885. package/src/structure/time-order.ts +140 -0
  886. package/src/structure/title-lines.ts +33 -0
  887. package/src/structure/total.ts +5 -1
  888. package/src/structure/version-mismatch.ts +67 -13
  889. package/src/structure/version-order.ts +84 -0
  890. package/src/table-text.ts +39 -0
  891. package/src/ui-labels.ts +55 -0
  892. package/src/undefined-call.ts +65 -0
  893. package/src/unnamed-speaker.ts +224 -0
  894. package/src/warning-action.ts +73 -0
  895. package/styles/koyobun.yaml +7 -4
@@ -139,3 +139,9 @@ export const scopedFacts = (facts: readonly Fact[], tree: StructureNode, source:
139
139
  return { ...fact, ...scopeOf(fact, around.at(-1), at), part: partOf(around, tree, fact.value.start, summaryWords) };
140
140
  });
141
141
  };
142
+
143
+ /** 文書のその位置が、冒頭、要約の節、本文のどれか。 */
144
+ export const partsAt = (offsets: readonly number[], tree: StructureNode, summaryWords: readonly string[]): FactPart[] => {
145
+ const nodes = inDocumentOrder(tree).filter((node) => CONTAINERS.has(node.kind));
146
+ return offsets.map((offset) => partOf(containersAt(nodes, offset), tree, offset, summaryWords));
147
+ };
@@ -19,6 +19,8 @@ export type FactWords = {
19
19
  readonly determiners: readonly string[];
20
20
  /** 名前にならない語(それ、it)。 */
21
21
  readonly vague: readonly string[];
22
+ /** 名前の前に置かれる決定の前置き(協議の結果、, it was decided that)。読点を含んでも条件ではないので、外してから名前を読む。 */
23
+ readonly leads: readonly string[];
22
24
  readonly attributes: readonly AttributePhrase[];
23
25
  };
24
26
 
@@ -38,6 +40,7 @@ const LETTER = /\p{L}/u;
38
40
  /** 名前に書かない記号。コードや属性({style="…"}、"key"=)の中の値は、項目の値ではない。 */
39
41
  const CODE_MARK = /[{}<>=[\]"`]/u;
40
42
  const LATIN_WORD = /^[a-z ]+$/iu;
43
+ const LATIN_LETTER = /^[a-z]$/iu;
41
44
 
42
45
  const lineStartOf = (source: string, offset: number): number => source.lastIndexOf("\n", offset - 1) + 1;
43
46
 
@@ -54,6 +57,15 @@ const beforeSeparator = (head: string, separator: string): string | undefined =>
54
57
  return rest;
55
58
  };
56
59
 
60
+ /** 英字の前置きが語の途中で切れているか(「we agreed that」は「we agreed thatching」の頭ではない)。 */
61
+ const endsInsideWord = (text: string, length: number): boolean => LATIN_LETTER.test(text.charAt(length - 1)) && LATIN_LETTER.test(text.charAt(length));
62
+
63
+ /** 頭の決定の前置きを外した節。 */
64
+ const withoutLead = (clause: string, words: FactWords): string => {
65
+ const lead = words.leads.find((phrase) => clause.toLowerCase().startsWith(phrase.toLowerCase()) && !endsInsideWord(clause, phrase.length));
66
+ return lead === undefined ? clause : clause.slice(lead.length).trimStart();
67
+ };
68
+
57
69
  /** 最後の文の切れ目より後ろ。 */
58
70
  const afterLastBreak = (text: string): string => {
59
71
  const breaks = [...text.matchAll(SENTENCE_BREAK)];
@@ -97,7 +109,7 @@ const labelledFact = (source: string, value: FactValue, words: FactWords): Fact
97
109
  for (const separator of words.separators) {
98
110
  const before = beforeSeparator(head, separator);
99
111
  if (before === undefined) continue;
100
- const clause = afterLastBreak(before).replace(BLOCK_MARK, "").replace(ITEM_MARK, "");
112
+ const clause = withoutLead(afterLastBreak(before).replace(BLOCK_MARK, "").replace(ITEM_MARK, "").trimStart(), words);
101
113
  if (CLAUSE_COMMA.test(clause)) return undefined;
102
114
  const label = withoutEdgeMarks(clause);
103
115
  const key = keyOf(label, words);
@@ -11,12 +11,12 @@ import { withoutEdgeMarks } from "./trim-marks.ts";
11
11
  * 升に値だけを書いたときだけ読む。「3,000円(税込)」のように条件を書いた升は読まない。
12
12
  * 行の見出しが値を含むか字を含まない表(日付の列から始まる日程表)は、行に名前が無いので読まない。
13
13
  */
14
- type Cell = Span & { readonly text: string };
14
+ export type Cell = Span & { readonly text: string };
15
15
 
16
16
  const LETTER = /\p{L}/u;
17
17
  const TWO_COLUMNS = 2;
18
18
 
19
- const cellsOf = (line: Line): Cell[] => {
19
+ export const cellsOf = (line: Line): Cell[] => {
20
20
  const bounds = [-1, ...[...line.text.matchAll(CELL_SEPARATOR)].map((match) => match.index), line.text.length];
21
21
  const cells = bounds.slice(1).map((end, index) => {
22
22
  const from = (bounds[index] ?? 0) + 1;
@@ -29,7 +29,7 @@ const cellsOf = (line: Line): Cell[] => {
29
29
  const plain = withoutEdgeMarks;
30
30
 
31
31
  /** 区切り行(|---|)の前の行が見出し、後ろに続く | の行が本体。 */
32
- const tablesOf = (lines: readonly Line[]): { header: Line; rows: Line[] }[] =>
32
+ export const tablesOf = (lines: readonly Line[]): { header: Line; rows: Line[] }[] =>
33
33
  lines.flatMap((line, index) => {
34
34
  const header = lines[index - 1];
35
35
  if (!TABLE_RULE.test(line.text) || header === undefined || !header.text.includes("|")) return [];
@@ -8,7 +8,7 @@ export type GradeAiScore = {
8
8
  readonly notScored: NotScored["reason"] | null;
9
9
  readonly signs: number;
10
10
  readonly compared: number;
11
- /** The signs that counted: rule ids, and structure measures as structure:<id>. */
11
+ /** The signs that counted: rule ids, structure measures as structure:<id>, and ai-generated-composite:strict. */
12
12
  readonly shown: readonly string[];
13
13
  };
14
14
 
package/src/grade/text.ts CHANGED
@@ -103,7 +103,7 @@ const aside = (open: string, inner: string, close: string): string => (inner ===
103
103
  export const GRADE_TEXT: Texts<GradeText> = {
104
104
  ja: {
105
105
  usage:
106
- "使い方: chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <前の results.jsonl>] [--variant-key <欄の名前>] [--format text|json|markdown] [--json] [--compact] [--experimental] [--genre <ジャンル>]",
106
+ "使い方: chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <前の results.jsonl>] [--allow-stamp-mismatch] [--variant-key <欄の名前>] [--format text|json|markdown] [--json] [--compact] [--experimental] [--genre <ジャンル>]",
107
107
  noReference: "reference が無い(事実は reference と照らす)",
108
108
  noCitations: "citations が無い(chaff は出力から引用を推測しない)",
109
109
  noContexts: "contexts が無い(回答の事実は、検索で取った一節と照らす)",
@@ -135,7 +135,7 @@ export const GRADE_TEXT: Texts<GradeText> = {
135
135
  },
136
136
  en: {
137
137
  usage:
138
- "usage: chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <earlier results.jsonl>] [--variant-key <field>] [--format text|json|markdown] [--json] [--compact] [--experimental] [--genre <genre>]",
138
+ "usage: chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <earlier results.jsonl>] [--allow-stamp-mismatch] [--variant-key <field>] [--format text|json|markdown] [--json] [--compact] [--experimental] [--genre <genre>]",
139
139
  noReference: "no reference given (facts are checked against a reference)",
140
140
  noCitations: "no citations given (chaff does not guess quotations from the output)",
141
141
  noContexts: "no contexts given (the output's facts are checked against retrieved passages)",
@@ -11,8 +11,8 @@ const ARABIC = "[0-90-9]+";
11
11
  const KANJI = "[一二三四五六七八九十百]+";
12
12
  const ROMAN = "[IVXⅠ-Ⅻ]+";
13
13
 
14
- /** 番号の後ろに続く見出しの言葉の頭。字で始まる。「8.2.3 (2026-08-06)」の版や「3 reasons」の数量は番号と読まない。 */
15
- const WORDS_FOLLOW = "(?=\\s*[\\p{L}])";
14
+ /** 番号の後ろに続く見出しの言葉の頭。字か、コードや引用の開き(`check()`、「概要」)で始まる。「8.2.3 (2026-08-06)」の版や「3 reasons」の数量は番号と読まない。 */
15
+ const WORDS_FOLLOW = '(?=\\s*[\\p{L}`「『“"])';
16
16
 
17
17
  /**
18
18
  * 字だけで決まる書き方。上から順に試す。ラテン文字一字とローマ数字(A. と II.)は同じ書き方とする。どちらも番号の後ろに言葉が続くときだけ。
@@ -0,0 +1,64 @@
1
+ // Fetches a page as text, in the encoding it declares, with a timeout. A non-2xx answer throws an error whose cause
2
+ // carries the HTTP status, so a caller can tell a dead page (404) from a transient one (503). Every error names the URL.
3
+ import { decodeFetched } from "./fetched-text.ts";
4
+
5
+ export class HttpStatusError extends Error {
6
+ readonly status: number;
7
+
8
+ constructor(status: number) {
9
+ super(`HTTP ${String(status)}`);
10
+ this.status = status;
11
+ }
12
+ }
13
+
14
+ /** The page's text and the Content-Type it was sent with (null when it had none). */
15
+ export type FetchedPage = { readonly text: string; readonly contentType: string | null };
16
+
17
+ /** What fetches: the global fetch, or a stand-in in tests. */
18
+ export type Fetcher = (url: string, init: { readonly signal: AbortSignal }) => Promise<Response>;
19
+
20
+ export type FetchLimits = {
21
+ readonly timeout_ms: number;
22
+ /** A body longer than this is refused while it is read, before it is decoded. Undefined: no limit. */
23
+ readonly max_bytes?: number | undefined;
24
+ };
25
+
26
+ const tooLarge = (max_bytes: number): Error => new Error(`the page is larger than ${String(max_bytes)} bytes`);
27
+
28
+ /** A read that gave bytes; a finished read (done) is not one. */
29
+ const isChunk = (read: unknown): read is { readonly value: Uint8Array } =>
30
+ typeof read === "object" && read !== null && Reflect.get(read, "done") !== true && Reflect.get(read, "value") instanceof Uint8Array;
31
+
32
+ /** The body's bytes, stopping as soon as they pass max_bytes. */
33
+ const bodyBytes = async (response: Response, max_bytes: number | undefined): Promise<Uint8Array> => {
34
+ if (max_bytes === undefined || response.body === null) return new Uint8Array(await response.arrayBuffer());
35
+ const declared = Number(response.headers.get("content-length") ?? Number.NaN);
36
+ if (declared > max_bytes) throw tooLarge(max_bytes);
37
+ const reader = response.body.getReader();
38
+ const chunks: Uint8Array[] = [];
39
+ let size = 0;
40
+ for (let read: unknown = await reader.read(); isChunk(read); read = await reader.read()) {
41
+ size += read.value.byteLength;
42
+ if (size > max_bytes) {
43
+ await reader.cancel();
44
+ throw tooLarge(max_bytes);
45
+ }
46
+ chunks.push(read.value);
47
+ }
48
+ return Buffer.concat(chunks);
49
+ };
50
+
51
+ export const fetchPage = async (url: string, limits: FetchLimits, fetcher: Fetcher = fetch): Promise<FetchedPage> => {
52
+ const controller = new AbortController();
53
+ const timer = setTimeout(() => controller.abort(), limits.timeout_ms);
54
+ try {
55
+ const response = await fetcher(url, { signal: controller.signal });
56
+ if (!response.ok) throw new HttpStatusError(response.status);
57
+ const contentType = response.headers.get("content-type");
58
+ return { text: decodeFetched(await bodyBytes(response, limits.max_bytes), contentType), contentType };
59
+ } catch (err) {
60
+ throw new Error(`${url}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
61
+ } finally {
62
+ clearTimeout(timer);
63
+ }
64
+ };
@@ -0,0 +1,32 @@
1
+ // The text of a fetched body in the encoding it declares: the Content-Type header first, then a <meta charset> or an
2
+ // XML declaration near the top of an HTML or XML body, otherwise UTF-8. Many Japanese government pages are still
3
+ // Shift_JIS. Pure.
4
+
5
+ /** How far into the body a declaration is looked for; HTML requires <meta charset> within the first 1024 bytes. */
6
+ const DECLARATION_BYTES = 1024;
7
+
8
+ const CHARSET = /charset\s*=\s*["']?([\w.:-]+)/iu;
9
+
10
+ const declaredInHead = (head: string): string | undefined =>
11
+ /<meta\b[^>]*\bcharset\s*=\s*["']?([\w.:-]+)/iu.exec(head)?.[1] ?? /^\s*<\?xml\b[^>]*\bencoding\s*=\s*["']([\w.:-]+)["']/iu.exec(head)?.[1];
12
+
13
+ /** Only a markup body can declare its own encoding; Markdown or JSON that quotes a <meta> tag declares nothing. */
14
+ const isMarkup = (contentType: string | null): boolean => contentType === null || /html|xml/iu.test(contentType);
15
+
16
+ /** The label the body declares, lower-cased, or "utf-8" when it declares none. */
17
+ export const charsetOf = (contentType: string | null, head: string): string =>
18
+ (CHARSET.exec(contentType ?? "")?.[1] ?? (isMarkup(contentType) ? declaredInHead(head) : undefined) ?? "utf-8").toLowerCase();
19
+
20
+ const decoderFor = (label: string): TextDecoder => {
21
+ try {
22
+ return new TextDecoder(label);
23
+ } catch {
24
+ return new TextDecoder("utf-8");
25
+ }
26
+ };
27
+
28
+ /** An unknown label is read as UTF-8, as before a declaration was looked for. */
29
+ export const decodeFetched = (bytes: Uint8Array, contentType: string | null): string => {
30
+ const head = new TextDecoder("latin1").decode(bytes.subarray(0, DECLARATION_BYTES));
31
+ return decoderFor(charsetOf(contentType, head)).decode(bytes);
32
+ };
@@ -0,0 +1,107 @@
1
+ // The content of a page that marks none (no <main>, no role="main", no sole <article>): the innermost block that
2
+ // holds every heading (the <h1> title among them) and nearly all the text written in sentences. A site's menus, side columns and footer are
3
+ // labels and links, not sentences, so they fall outside; when the sentences are spread over blocks, no block
4
+ // qualifies and the whole page is read. Pure; a regular-expression reading.
5
+ import { CLOSED_SENTENCE, elementRanges, plainText, type ElementRange } from "./html-elements.ts";
6
+ import { decodeEntities } from "./markup-text.ts";
7
+
8
+ const TAG = /<\/?[a-z!][^>]*>/giu;
9
+
10
+ // Tags that end a line of text; inline tags (a link, a span, a <br> inside a paragraph) run on inside a sentence.
11
+ const LINE_BREAK = /^<\/?(?:p|div|li|dd|dt|td|th|h[1-6]|section|article|header|blockquote|ul|ol|dl|table|tr)\b/iu;
12
+
13
+ const SENTENCE_END = new RegExp(CLOSED_SENTENCE.source, "gu");
14
+
15
+ type Sentence = { readonly at: number; readonly text: string };
16
+
17
+ type Scan = { readonly start: number; readonly line: string; readonly found: Sentence[] };
18
+
19
+ /** A text between tags: each sentence closed in it is found with the text before it on its line; the rest runs on. */
20
+ const scanText = (scan: Scan, text: string, at: number): Scan => {
21
+ const start = scan.line === "" ? at : scan.start;
22
+ const ends = [...text.matchAll(SENTENCE_END)].map((end) => end.index + end[0].length);
23
+ if (ends.length === 0) return { start, line: scan.line + text, found: scan.found };
24
+ ends.forEach((end, index) => scan.found.push({ at: start, text: (index === 0 ? scan.line : "") + text.slice(ends[index - 1] ?? 0, end) }));
25
+ return { start: at, line: text.slice(ends.at(-1) ?? text.length), found: scan.found };
26
+ };
27
+
28
+ type TagScan = Scan & { readonly from: number };
29
+
30
+ /** The text before a tag, then the tag: a line break starts a new line. */
31
+ const scanTag = (html: string, scan: TagScan, tag: RegExpExecArray): TagScan => {
32
+ const before = html.slice(scan.from, tag.index);
33
+ const scanned = before === "" ? scan : scanText(scan, decodeEntities(before), scan.from);
34
+ const next = LINE_BREAK.test(tag[0]) ? { start: tag.index, line: "", found: scanned.found } : scanned;
35
+ return { ...next, from: tag.index + tag[0].length };
36
+ };
37
+
38
+ /** Each sentence on the page with the words before it on its line, and where that line starts; in document order. */
39
+ const sentences = (html: string): Sentence[] => {
40
+ const scan = [...html.matchAll(TAG)].reduce<TagScan>((state, tag) => scanTag(html, state, tag), { start: 0, line: "", found: [], from: 0 });
41
+ const rest = html.slice(scan.from);
42
+ return (rest === "" ? scan : scanText(scan, decodeEntities(rest), scan.from)).found;
43
+ };
44
+
45
+ const TITLE = /<h1\b[^>]*>([\s\S]*?)<\/h1\s*>/giu;
46
+
47
+ type Weighed = { readonly at: number; readonly weight: number };
48
+
49
+ /**
50
+ * How much text each sentence carries: its length, or nothing when it only repeats the page's title (a question set as
51
+ * the title and again in a breadcrumb), so that a short page's title does not outweigh its body.
52
+ */
53
+ const weighed = (html: string): Weighed[] => {
54
+ const titles = new Set([...html.matchAll(TITLE)].map((title) => plainText(title[1] ?? "")));
55
+ return sentences(html).map((sentence) => {
56
+ const text = sentence.text.replace(/\s+/gu, " ").trim();
57
+ return { at: sentence.at, weight: titles.has(text) ? 0 : text.length };
58
+ });
59
+ };
60
+
61
+ /** The total weight of the sentences whose line starts in [start, end), from running totals (totals[i] = before i). */
62
+ const weightWithin = (all: readonly Weighed[], totals: readonly number[], start: number, end: number): number => {
63
+ const firstAtOrAfter = (at: number, low = 0, high = all.length): number => {
64
+ if (low >= high) return low;
65
+ const middle = Math.floor((low + high) / 2);
66
+ return (all[middle]?.at ?? 0) < at ? firstAtOrAfter(at, middle + 1, high) : firstAtOrAfter(at, low, middle);
67
+ };
68
+ return (totals[firstAtOrAfter(end)] ?? 0) - (totals[firstAtOrAfter(start)] ?? 0);
69
+ };
70
+
71
+ const runningTotals = (all: readonly Weighed[]): number[] =>
72
+ all.reduce<number[]>(
73
+ (sums, sentence) => {
74
+ sums.push((sums.at(-1) ?? 0) + sentence.weight);
75
+ return sums;
76
+ },
77
+ [0],
78
+ );
79
+
80
+ // Share of the page's sentence text the block must hold: a line in the footer may fall outside it, a section of the
81
+ // document may not.
82
+ const CONTENT_SHARE = 0.9;
83
+
84
+ const CONTENT_BLOCKS = ["div", "section"];
85
+
86
+ /**
87
+ * The inside of the content block, or undefined when the page has no sentence, no block to single out, or no <h1>:
88
+ * without a marked title, a title set in a plain block (and its byline) could fall outside.
89
+ */
90
+ export const contentBlock = (html: string): string | undefined => {
91
+ if (!/<h1\b/iu.test(html)) return undefined;
92
+ const headings = [...html.matchAll(/<h[1-6]\b/giu)].map((heading) => heading.index);
93
+ const all = weighed(html);
94
+ const totals = runningTotals(all);
95
+ const whole = totals.at(-1) ?? 0;
96
+ if (whole === 0) return undefined;
97
+ // Every heading is the document's (a list under "Members" has no sentence), and nothing written in sentences may
98
+ // stand before the block ("Updated." above the title): only a footer's line after it.
99
+ const holdsContent = (range: ElementRange): boolean =>
100
+ headings.every((heading) => heading > range.start && heading < range.end) &&
101
+ weightWithin(all, totals, 0, range.start) === 0 &&
102
+ weightWithin(all, totals, range.start, range.end) >= whole * CONTENT_SHARE;
103
+ const smallest = CONTENT_BLOCKS.flatMap((tag) => elementRanges(html, tag))
104
+ .filter(holdsContent)
105
+ .toSorted((left, right) => left.end - left.start - (right.end - right.start))[0];
106
+ return smallest?.inner;
107
+ };
@@ -0,0 +1,127 @@
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.ts";
4
+
5
+ // In a tag a quote opens a value only after "=", and the value ends only at its matching quote, whatever it holds.
6
+ const TAG_BODY = String.raw`(?:[^>=]|=\s*"[^"]*"|=\s*'[^']*'|=(?!\s*["']))*`;
7
+
8
+ // A comment, a processing instruction, a script and a style are matched whole, so that no tag is read inside them
9
+ // (the converter drops them anyway), and a "<!--" inside a value is escaped before comments are looked for.
10
+ 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");
11
+
12
+ const QUOTED_VALUE = /=(\s*)("[^"]*"|'[^']*')/gu;
13
+
14
+ const withValuesEscaped = (tag: string): string =>
15
+ tag.replace(QUOTED_VALUE, (_whole: string, space: string, value: string) => `=${space}${value.replaceAll("<", "&lt;").replaceAll(">", "&gt;")}`);
16
+
17
+ /**
18
+ * Each "<" and ">" inside a quoted attribute value (title="published under the <span>…</span>") as a character
19
+ * reference, which means the same in a value, so that a scanner reading a tag up to its first ">" reads all of it.
20
+ */
21
+ export const withAttributeMarkupEscaped = (html: string): string => html.replace(TAG, (tag: string) => withValuesEscaped(tag));
22
+
23
+ /** Apply step until the text stops changing: nested elements are removed from the inside out. */
24
+ export const untilStable = (text: string, step: (text: string) => string): string => {
25
+ const next = step(text);
26
+ return next === text ? text : untilStable(next, step);
27
+ };
28
+
29
+ export const stripTags = (html: string): string => html.replace(/<\/?[a-z!][^>]*>/giu, "");
30
+
31
+ export const plainText = (html: string): string => decodeEntities(stripTags(html)).replace(/\s+/gu, " ").trim();
32
+
33
+ /** Text put back into markup, so that decoding it again gives the same text. */
34
+ export const asMarkup = (text: string): string => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;");
35
+
36
+ /** A full stop, question or exclamation mark closing a sentence, also before a closing quote or bracket; not the point in "3.5". */
37
+ export const CLOSED_SENTENCE = /[。.!?]|[.!?][)\]"'”’]*(?=\s|$)/u;
38
+
39
+ /** Whether the markup closes a sentence, each tag read as a space so that "Done.</li><li>Next" ends one. */
40
+ export const hasSentence = (html: string): boolean => CLOSED_SENTENCE.test(plainText(html.replace(/<\/?[a-z!][^>]*>/giu, " ")));
41
+
42
+ export const hasNoWords = (text: string): boolean => !/[\p{L}\p{N}]/u.test(text);
43
+
44
+ export const ANY_LINK = /<a\b[^>]*>[\s\S]*?<\/a\s*>/giu;
45
+
46
+ const HREF = /\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))/iu;
47
+
48
+ const PAGE_EXTENSION = /^(?:[sx]?html?|php|aspx?|jsp|cgi)$/iu;
49
+
50
+ // The host is not part of the path: "https://example.com" names a site, not a file ending in .com.
51
+ const SCHEME_AND_HOST = /^(?:[a-z][a-z0-9+.-]*:)?\/\/[^/?#]*/iu;
52
+
53
+ // A link that opens no page (tel:, mailto:, sms:) carries its own content, a number or an address.
54
+ const OTHER_SCHEME = /^\s*(?!https?:)[a-z][a-z0-9+.-]*:(?!\/\/)/iu;
55
+
56
+ const hrefOf = (link: string): string => {
57
+ const href = HREF.exec(link);
58
+ return href?.[1] ?? href?.[2] ?? href?.[3] ?? "";
59
+ };
60
+
61
+ /** The extension of the file a link opens ("pdf", "mp3"), or undefined for a page or a site. */
62
+ export const fileExtension = (link: string): string | undefined => {
63
+ const path = hrefOf(link).replace(SCHEME_AND_HOST, "").split(/[?#]/u)[0] ?? "";
64
+ const extension = /\.([a-z0-9]{1,5})$/iu.exec(path.split("/").at(-1) ?? "")?.[1];
65
+ return extension !== undefined && !PAGE_EXTENSION.test(extension) ? extension : undefined;
66
+ };
67
+
68
+ /** A link to a file (an appendix as PDF, a table as .xlsx), or one that opens no page, is part of the document. */
69
+ export const isFileLink = (link: string): boolean => OTHER_SCHEME.test(hrefOf(link)) || fileExtension(link) !== undefined;
70
+
71
+ /** Attributes before a given one, each skipped whole so that a quoted value (title="x role=main") is not read as one. */
72
+ export const ATTRIBUTES = String.raw`(?:\s+[^\s"'>=/]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'>]+))?)*?`;
73
+
74
+ export type ElementRange = { readonly start: number; readonly end: number; readonly openTag: string; readonly inner: string };
75
+
76
+ type RangeScan = { readonly open: readonly RegExpExecArray[]; readonly ranges: readonly ElementRange[] };
77
+
78
+ const closeLast = (html: string, scan: RangeScan, close: RegExpExecArray): RangeScan => {
79
+ const opener = scan.open.at(-1);
80
+ if (opener === undefined) return scan;
81
+ const range = {
82
+ start: opener.index,
83
+ end: close.index + close[0].length,
84
+ openTag: opener[0],
85
+ inner: html.slice(opener.index + opener[0].length, close.index),
86
+ };
87
+ return { open: scan.open.slice(0, -1), ranges: [...scan.ranges, range] };
88
+ };
89
+
90
+ /** Every <tag>…</tag>, nested ones matched to their own closing tag, in document order (outer before inner). */
91
+ export const elementRanges = (html: string, tag: string): ElementRange[] =>
92
+ [...html.matchAll(new RegExp(`<(/?)${tag}\\b[^>]*>`, "giu"))]
93
+ .reduce<RangeScan>((scan, match) => (match[1] === "/" ? closeLast(html, scan, match) : { open: [...scan.open, match], ranges: scan.ranges }), {
94
+ open: [],
95
+ ranges: [],
96
+ })
97
+ .ranges.toSorted((left, right) => left.start - right.start);
98
+
99
+ export const isInside = (outer: ElementRange, inner: ElementRange): boolean => outer.start < inner.start && inner.end <= outer.end;
100
+
101
+ /** The ranges (in document order) each replaced by a space; one inside another cut one goes with it. */
102
+ export const withoutRanges = (html: string, ranges: readonly ElementRange[]): string => {
103
+ const chosen = ranges.reduce<ElementRange[]>((kept, range) => {
104
+ const insideKept = (kept.at(-1)?.end ?? 0) > range.start;
105
+ if (!insideKept) kept.push(range);
106
+ return kept;
107
+ }, []);
108
+ const cut = chosen.reduce<{ readonly parts: readonly string[]; readonly from: number }>(
109
+ (acc, range) => ({ parts: [...acc.parts, html.slice(acc.from, range.start), " "], from: range.end }),
110
+ { parts: [], from: 0 },
111
+ );
112
+ return [...cut.parts, html.slice(cut.from)].join("");
113
+ };
114
+
115
+ /** The <tag> elements that are chrome, each replaced by a space; one inside another dropped one goes with it. */
116
+ export const withoutElementsWhere = (html: string, tag: string, isChrome: (range: ElementRange) => boolean): string =>
117
+ withoutRanges(html, elementRanges(html, tag).filter(isChrome));
118
+
119
+ /** Every <tag> whose opening matches, for each tag that opens that way, replaced by a space. */
120
+ export const withoutElementsOpening = (html: string, opening: RegExp, isChrome: (range: ElementRange) => boolean): string => {
121
+ const tags = new Set([...html.matchAll(opening)].map((match) => (match[1] ?? "").toLowerCase()));
122
+ return [...tags].reduce((text, tag) => withoutElementsWhere(text, tag, isChrome), html);
123
+ };
124
+
125
+ export const HEADING_TAGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
126
+
127
+ export const headingRanges = (html: string): ElementRange[] => HEADING_TAGS.flatMap((tag) => elementRanges(html, tag));
@@ -0,0 +1,20 @@
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
+
8
+ const LINK_IN_SUPERSCRIPT = /<sup\b[^>]*>\s*<a\b[^>]*>[^<]*<\/a\s*>\s*<\/sup\s*>/giu;
9
+
10
+ const SUPERSCRIPT_LINK = /<a\b([^>]*)>\s*<sup\b[^>]*>([^<]*)<\/sup\s*>\s*<\/a\s*>/giu;
11
+
12
+ // The fragment must name something: href="#" alone goes nowhere and is a control.
13
+ const IN_PAGE_HREF = /\shref\s*=\s*(?:"#[^"\s]+"|'#[^'\s]+'|#[^\s"'>]+)/iu;
14
+
15
+ const isFootnoteLink = (attributes: string, mark: string): boolean => IN_PAGE_HREF.test(attributes) && mark.trim() !== "";
16
+
17
+ export const withoutFootnoteMarks = (html: string): string =>
18
+ html
19
+ .replace(LINK_IN_SUPERSCRIPT, "")
20
+ .replace(SUPERSCRIPT_LINK, (link: string, attributes: string, mark: string) => (isFootnoteLink(attributes, mark) ? "" : link));
@@ -0,0 +1,93 @@
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, type ElementRange } from "./html-elements.ts";
3
+ import { decodeEntities } from "./markup-text.ts";
4
+
5
+ const ID = new RegExp(String.raw`<([a-z][a-z0-9-]*)${ATTRIBUTES}\s+id\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))`, "giu");
6
+
7
+ type IdTarget = { readonly start: number; readonly tag: string };
8
+
9
+ /** Where each id's element opens, and which element it is; the first one when an id is repeated. */
10
+ const idTargets = (html: string): Map<string, IdTarget> =>
11
+ [...html.matchAll(ID)].reduce((targets, match) => {
12
+ const id = decodeEntities(match[2] ?? match[3] ?? match[4] ?? "");
13
+ return targets.has(id) ? targets : targets.set(id, { start: match.index, tag: (match[1] ?? "").toLowerCase() });
14
+ }, new Map<string, IdTarget>());
15
+
16
+ const FRAGMENT = /^<a\b[^>]*\bhref\s*=\s*["']?[^"'#\s>]*#([^"'\s>]+)/iu;
17
+
18
+ /** The id a link's fragment names, its character references and percent escapes undone. */
19
+ const fragmentId = (link: string): string | undefined => {
20
+ const fragment = FRAGMENT.exec(link)?.[1];
21
+ if (fragment === undefined) return undefined;
22
+ const decoded = decodeEntities(fragment);
23
+ try {
24
+ return decodeURIComponent(decoded);
25
+ } catch {
26
+ return decoded;
27
+ }
28
+ };
29
+
30
+ const HEADING_OPENING = /<h[1-6]\b/iu;
31
+
32
+ type PageIds = {
33
+ readonly ids: ReadonlyMap<string, IdTarget>;
34
+ readonly html: string;
35
+ readonly rangesOf: (tag: string) => readonly ElementRange[];
36
+ };
37
+
38
+ type HeadingPlace = PageIds & { readonly start: number; readonly end: number };
39
+
40
+ /** The target opens before the heading and closes after it, with no other heading opening in between. */
41
+ const isSectionOf = (target: IdTarget, place: HeadingPlace): boolean =>
42
+ place.rangesOf(target.tag).some((range) => range.start === target.start && range.end >= place.end) &&
43
+ !HEADING_OPENING.test(place.html.slice(target.start, place.start));
44
+
45
+ /** A link to the heading's own section: the heading, something inside it, or the block it opens (a permalink, "Copy link to Context"). */
46
+ const isSelfLink = (link: string, place: HeadingPlace): boolean => {
47
+ const id = fragmentId(link);
48
+ const target = id === undefined ? undefined : place.ids.get(id);
49
+ if (target === undefined || target.start >= place.end) return false;
50
+ return target.start >= place.start || isSectionOf(target, place);
51
+ };
52
+
53
+ /** A permalink mark inside the heading (¶, #, an icon); a self-link with words is the title, or part of it. */
54
+ const isPermalinkMark = (link: string, place: HeadingPlace): boolean => hasNoWords(plainText(link)) && isSelfLink(link, place);
55
+
56
+ const HEADING_THEN_LINK = /(<h([1-6])\b[^>]*>)([\s\S]*?)(<\/h\2\s*>)(\s*<a\b[^>]*>[\s\S]*?<\/a\s*>)?/giu;
57
+
58
+ /** The heading as matched, without its permalink marks or the self-link standing after it. */
59
+ const headingWithoutSelfLinks = (match: RegExpExecArray, page: PageIds): string => {
60
+ const [, open = "", , inside = "", close = "", after] = match;
61
+ const place = { ...page, start: match.index, end: match.index + open.length + inside.length + close.length };
62
+ const kept = inside.replace(ANY_LINK, (link: string) => (isPermalinkMark(link, place) ? " " : link));
63
+ const next = after === undefined || isSelfLink(after.trim(), place) ? "" : after;
64
+ return `${open}${kept}${close}${next}`;
65
+ };
66
+
67
+ /** elementRanges for each tag, computed once. */
68
+ const rangesByTag = (html: string): ((tag: string) => readonly ElementRange[]) => {
69
+ const cache = new Map<string, readonly ElementRange[]>();
70
+ return (tag: string) => {
71
+ const known = cache.get(tag);
72
+ if (known !== undefined) return known;
73
+ const ranges = elementRanges(html, tag);
74
+ cache.set(tag, ranges);
75
+ return ranges;
76
+ };
77
+ };
78
+
79
+ /**
80
+ * A heading's link to its own section goes when it stands just after the heading ("Copy link to Context"), or inside
81
+ * it as a mark without words ("Scope ¶"). A link with words inside the heading is its title and stays.
82
+ */
83
+ export const withoutHeadingSelfLinks = (html: string): string => {
84
+ const page = { ids: idTargets(html), html, rangesOf: rangesByTag(html) };
85
+ const cut = [...html.matchAll(HEADING_THEN_LINK)].reduce<{ readonly parts: readonly string[]; readonly from: number }>(
86
+ (acc, match) => ({
87
+ parts: [...acc.parts, html.slice(acc.from, match.index), headingWithoutSelfLinks(match, page)],
88
+ from: match.index + match[0].length,
89
+ }),
90
+ { parts: [], from: 0 },
91
+ );
92
+ return [...cut.parts, html.slice(cut.from)].join("");
93
+ };
@@ -0,0 +1,14 @@
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
+
7
+ const LOST_PARAGRAPH_TAG = /(?<=[.;:][)"'”’]?[ \t])[Pp](?:&gt;|>)(?=\([0-9A-Za-z]{1,4}\)[ \t]\p{Lu})/gu;
8
+
9
+ /** Whether at is inside a tag. An attribute's ">" is escaped by then (withAttributeMarkupEscaped), so a tag has none before its end. */
10
+ const isInsideTag = (html: string, at: number): boolean => html.lastIndexOf("<", at) > html.lastIndexOf(">", at - 1);
11
+
12
+ /** The HTML with each lost paragraph start tag in its text put back as <p>. */
13
+ export const withLostParagraphTagsRestored = (html: string): string =>
14
+ html.replace(LOST_PARAGRAPH_TAG, (lost: string, at: number) => (isInsideTag(html, at) ? lost : "<p>"));