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,127 @@
1
+ import { escapeRegExp } from "../orthography.ts";
2
+
3
+ /**
4
+ * 時刻のまわりに書く印を読む。発・着(departs、arr)、翌日(翌、+1、next day)、時間帯(JST、現地時間)。
5
+ * 語は言語パッケージの語彙表(leg-mark、leg-column、day-shift-mark、time-zone、local-time-mark)から来る。ここは字面を照らすだけで、語を知らない。
6
+ */
7
+
8
+ /** 語彙表の一語。position は時刻のどちら側に書くか、group は語の組(departure と arrival、next と previous、local)。 */
9
+ export type Mark = { readonly pattern: string; readonly position?: "before" | "after" | undefined; readonly group?: string | undefined };
10
+
11
+ /** 時刻と、その原文の範囲。seconds は 0 時からの秒。 */
12
+ export type TimeSpan = { readonly start: number; readonly end: number; readonly seconds: number };
13
+
14
+ /** 日付と、その原文の範囲。value は年月日、年月、月日のいずれか(2026-04-01、04-01)。 */
15
+ export type DateSpan = { readonly start: number; readonly end: number; readonly value: string };
16
+
17
+ /** legs は時刻の前後に書く発着の印、columns は表の発着の列の名前、dayShifts は翌日・前日の印、zones は時間帯の印。 */
18
+ export type TimeWords = {
19
+ readonly legs: readonly Mark[];
20
+ readonly columns: readonly Mark[];
21
+ readonly dayShifts: readonly Mark[];
22
+ readonly zones: readonly Mark[];
23
+ };
24
+
25
+ export const SECONDS_PER_DAY = 86_400;
26
+ const SECONDS_PER_HOUR = 3600;
27
+ const SECONDS_PER_MINUTE = 60;
28
+
29
+ /** 「09:30」「21:05:10」の鍵を 0 時からの秒にする。 */
30
+ export const secondsOf = (key: string): number => {
31
+ const [hour = 0, minute = 0, second = 0] = key.split(":").map(Number);
32
+ return hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;
33
+ };
34
+
35
+ /** 語の端の字の種類。英字は英字と、数字は数字と続けば一つの語(dep と department、+1 と +10)。 */
36
+ const KINDS = [/[A-Za-z]/u, /[0-90-9]/u];
37
+
38
+ const joins = (edge: string, beside: string): boolean => KINDS.some((kind) => kind.test(edge) && kind.test(beside));
39
+
40
+ /** text の at から pattern が、前後の字と続かない一語として書かれているか。 */
41
+ export const isWordAt = (text: string, at: number, pattern: string): boolean => {
42
+ if (pattern === "" || !text.startsWith(pattern, at)) return false;
43
+ return !joins(pattern.charAt(0), text.charAt(at - 1)) && !joins(pattern.charAt(pattern.length - 1), text.charAt(at + pattern.length));
44
+ };
45
+
46
+ /** text の中で pattern が語として書かれた位置。 */
47
+ export const wordOffsets = (text: string, pattern: string): number[] =>
48
+ [...text.matchAll(new RegExp(escapeRegExp(pattern), "gu"))].flatMap((match) => (isWordAt(text, match.index, pattern) ? [match.index] : []));
49
+
50
+ const sidesOf = (marks: readonly Mark[], side: "before" | "after"): Mark[] => marks.filter((mark) => mark.position === side);
51
+
52
+ /** 長い語から照らす(「翌日」を「翌」より先に)。 */
53
+ const longestFirst = (marks: readonly Mark[]): Mark[] => marks.toSorted((left, right) => right.pattern.length - left.pattern.length);
54
+
55
+ /** 時刻のすぐ後ろ(間を空けない)に書いた印。「08:00発」の「発」。 */
56
+ export const markRightAfter = (text: string, end: number, marks: readonly Mark[]): Mark | undefined =>
57
+ longestFirst(sidesOf(marks, "after")).find((mark) => isWordAt(text, end, mark.pattern));
58
+
59
+ /** 時刻の前の、間に letters 字までしか挟まない印。「departs Boston 7:30」の departs、「翌 0:15」の翌。 */
60
+ export const markBefore = (head: string, marks: readonly Mark[], letters: number): Mark | undefined => {
61
+ const found = longestFirst(sidesOf(marks, "before")).flatMap((mark) =>
62
+ wordOffsets(head, mark.pattern).map((at) => ({ mark, gap: head.length - at - mark.pattern.length })),
63
+ );
64
+ const nearest = found.filter((entry) => entry.gap >= 0 && entry.gap <= letters).toSorted((left, right) => left.gap - right.gap)[0];
65
+ return nearest?.mark;
66
+ };
67
+
68
+ /** 時刻の後ろで、空白と開き括弧と発着の印を飛ばした所に書いた印。「0:15(翌日)」「9:50着 +1」。 */
69
+ const SKIPPED_AFTER = /^[\s(([[]*/u;
70
+
71
+ export const markSoonAfter = (text: string, end: number, marks: readonly Mark[], skipped: readonly Mark[]): Mark | undefined => {
72
+ const leg = markRightAfter(text, end, skipped);
73
+ const from = end + (leg?.pattern.length ?? 0);
74
+ const gap = SKIPPED_AFTER.exec(text.slice(from))?.[0].length ?? 0;
75
+ return markRightAfter(text, from + gap, marks);
76
+ };
77
+
78
+ /** 日をまたぐ印の向き。翌日なら 1、前日なら -1、無ければ 0。 */
79
+ const shiftOf = (mark: Mark | undefined): number => {
80
+ if (mark === undefined) return 0;
81
+ return mark.group === "previous" ? -1 : 1;
82
+ };
83
+
84
+ /** 「翌 0:15」のように前に書く翌日は、間に空白一つまで。 */
85
+ const DAY_SHIFT_GAP = 1;
86
+
87
+ /** 時刻の前置きから、時刻の直前に書いた翌日・前日の印(「翌 」)を除いたもの。印が無ければそのまま。 */
88
+ export const withoutDayShiftBefore = (head: string, words: TimeWords): string => {
89
+ const mark = markBefore(head, words.dayShifts, DAY_SHIFT_GAP);
90
+ return mark === undefined ? head : head.slice(0, head.lastIndexOf(mark.pattern));
91
+ };
92
+
93
+ /** 時刻に付けた翌日・前日の印。head は時刻の前の原文、text と end は時刻の後ろを読むため。 */
94
+ export const dayShiftOf = (head: string, text: string, end: number, words: TimeWords): number =>
95
+ shiftOf(markBefore(head, words.dayShifts, DAY_SHIFT_GAP) ?? markSoonAfter(text, end, words.dayShifts, words.legs));
96
+
97
+ /** 時間帯の印に続けて書いた時差(UTC+9、GMT-5:00)。時差まで含めて一つの時間帯と読む。 */
98
+ const ZONE_OFFSET = /^[+\-−+]\d{1,2}(?::?\d{2})?/u;
99
+
100
+ /** 書かれた時間帯。text は時差まで含めた字面。 */
101
+ export type Zone = { readonly text: string; readonly group?: string | undefined };
102
+
103
+ type ZoneSpan = Zone & { readonly start: number; readonly end: number };
104
+
105
+ const zoneSpansOf = (text: string, mark: Mark): ZoneSpan[] =>
106
+ wordOffsets(text, mark.pattern).map((start) => {
107
+ const after = start + mark.pattern.length;
108
+ const offset = ZONE_OFFSET.exec(text.slice(after))?.[0] ?? "";
109
+ return { start, end: after + offset.length, text: mark.pattern + offset, group: mark.group };
110
+ });
111
+
112
+ /** text に書かれた時間帯の印(JST、UTC+9、現地時間)。同じ字面は一度だけ。長い語から照らし、短い語が長い語の中で重ねて読まれない。 */
113
+ export const zonesIn = (text: string, words: TimeWords): Zone[] => {
114
+ const spans = longestFirst(words.zones).reduce<ZoneSpan[]>(
115
+ (taken, mark) => [...taken, ...zoneSpansOf(text, mark).filter((span) => !taken.some((other) => span.start < other.end && other.start < span.end))],
116
+ [],
117
+ );
118
+ return spans
119
+ .filter((span, index) => spans.findIndex((other) => other.text === span.text) === index)
120
+ .map(({ text: written, group }) => ({ text: written, group }));
121
+ };
122
+
123
+ /**
124
+ * 時間帯をまたぐ行か。違う時間帯の印が二つ以上あるか、「現地時間」のように時間帯がどこかを言わない印(組 local)があれば、
125
+ * 時刻をそのまま比べられない。
126
+ */
127
+ export const crossesZones = (zones: readonly Zone[]): boolean => zones.length >= 2 || zones.some((mark) => mark.group === "local");
@@ -0,0 +1,140 @@
1
+ import type { StructureIssue } from "./issues.ts";
2
+ import { runsOf, type Line } from "./runs.ts";
3
+ import { longestInOrder, outOfPlace } from "./date-order.ts";
4
+ import { crossesZones, dayShiftOf, withoutDayShiftBefore, zonesIn, SECONDS_PER_DAY, type DateSpan, type TimeSpan, type TimeWords } from "./time-marks.ts";
5
+
6
+ /**
7
+ * 一日の予定として並べた時刻の順番。箇条書きの続いた項目と表の続いた行のうち、頭に時刻を書いたもの(「- 09:00 集合」
8
+ * 「| 2月9日 09:30 | 受付 |」)を並びとして読む。一日の予定は早い順に並ぶので、向きは決めずに早い順と見る。
9
+ * 日付の見出しが変われば並びは切れる。行の頭に書いた日付が変わるところ(表の日付の列)、時間帯の印が変わるところでも切る。
10
+ * 23:30 の次の 0:15 は、翌日の印(翌、+1、next day)があれば翌日の時刻と読む。印が無くても、半日より大きく戻る時刻は
11
+ * 夜をまたいだものと読み、言わない。打ち間違いの多くは数時間の戻りで、半日を超えて戻る予定は夜通しの予定のほうが多い。
12
+ * 早い順に並ぶ時刻が半分以下の並びは、時刻で並べた一覧ではないとして何も言わない。
13
+ */
14
+
15
+ /** 頭に時刻を書いた項目。seconds は 0 時からの秒、shift は翌日の印(1)か無印(0)。 */
16
+ type Stop = {
17
+ readonly offset: number;
18
+ readonly written: string;
19
+ readonly seconds: number;
20
+ readonly shift: number;
21
+ readonly date: string | undefined;
22
+ readonly zone: string;
23
+ /** 「09:00–10:30」のように範囲で書いた時刻の終わり。範囲でなければ無い。 */
24
+ readonly until: number | undefined;
25
+ };
26
+
27
+ /** 並びとして言うのに要る時刻の数。二つでは、どちらが外れたかも、並べたものかどうかも決められない。 */
28
+ const MIN_STOPS = 3;
29
+ /** 印の無い戻りを夜をまたいだと読む幅。 */
30
+ const HALF_DAY = SECONDS_PER_DAY / 2;
31
+ /** 頭の日付と時刻の間に挟んでよい字(曜日「Monday,」「(火)」)。 */
32
+ const LEAD_BESIDE_DATE = 12;
33
+
34
+ const ITEM_OPENER = /^[ \t]*(?:(?:[-*+]|\d{1,3}[.)])[ \t]+|\|)?/u;
35
+ const MARKS_ONLY = /^[\s\p{P}\p{S}]*$/u;
36
+ const DIGIT = /[0-90-9]/u;
37
+
38
+ /** 頭に書いた日付を除いた残り。日付があれば短い曜日まで、無ければ記号と空白だけなら、時刻が項目の頭にある。 */
39
+ const leadsWithTime = (lead: string, leadStart: number, dates: readonly DateSpan[]): boolean => {
40
+ if (lead.includes("|")) return false;
41
+ const inLead = dates.filter((date) => date.start >= leadStart && date.end <= leadStart + lead.length);
42
+ const rest = inLead.reduceRight((text, date) => text.slice(0, date.start - leadStart) + text.slice(date.end - leadStart), lead).trim();
43
+ if (inLead.length === 0) return MARKS_ONLY.test(rest);
44
+ return !DIGIT.test(rest) && rest.length <= LEAD_BESIDE_DATE;
45
+ };
46
+
47
+ const zoneKeyOf = (text: string, words: TimeWords): string | undefined => {
48
+ const zones = zonesIn(text, words);
49
+ if (zones.length >= 2) return undefined;
50
+ return crossesZones(zones) ? `local:${zones[0]?.text ?? ""}` : (zones[0]?.text ?? "");
51
+ };
52
+
53
+ type Inputs = { readonly source: string; readonly times: readonly TimeSpan[]; readonly dates: readonly DateSpan[]; readonly words: TimeWords };
54
+
55
+ /** 時刻と時刻の間が範囲の印だけなら、後ろの時刻は範囲の終わり。 */
56
+ const RANGE_GAP = /^\s?[-–—~〜~]\s?$/u;
57
+
58
+ const rangeEndOf = (source: string, time: TimeSpan, times: readonly TimeSpan[]): number | undefined => {
59
+ const next = times.find((candidate) => candidate.start >= time.end);
60
+ return next !== undefined && RANGE_GAP.test(source.slice(time.end, next.start)) ? next.seconds : undefined;
61
+ };
62
+
63
+ /** 行の頭の時刻。頭に時刻が無い行、時間帯の印が二つある行、前日の印の付いた時刻は並びに入れない。 */
64
+ const stopOf = (line: Line, inputs: Inputs): Stop | undefined => {
65
+ const { source, times, dates, words } = inputs;
66
+ const text = source.slice(line.start, line.end);
67
+ const time = times.find((candidate) => candidate.start >= line.start && candidate.end <= line.end);
68
+ const leadStart = line.start + (ITEM_OPENER.exec(text)?.[0].length ?? 0);
69
+ if (time === undefined || !leadsWithTime(withoutDayShiftBefore(source.slice(leadStart, time.start), words), leadStart, dates)) return undefined;
70
+ const zone = zoneKeyOf(text, words);
71
+ const shift = dayShiftOf(source.slice(line.start, time.start), source, time.end, words);
72
+ if (zone === undefined || shift < 0) return undefined;
73
+ const date = dates.filter((span) => span.start >= leadStart && span.end <= time.start).at(-1)?.value;
74
+ const until = rangeEndOf(source, time, times);
75
+ return { offset: time.start, written: source.slice(time.start, time.end), seconds: time.seconds, shift, date, zone, until };
76
+ };
77
+
78
+ /** 一日の並びを切る所: 頭の日付が前と違う、時間帯の印が前と違う。 */
79
+ const startsNewDay = (stop: Stop, day: readonly Stop[]): boolean => {
80
+ const last = day.at(-1);
81
+ if (last === undefined) return false;
82
+ const lastDate = day.findLast((earlier) => earlier.date !== undefined)?.date;
83
+ return (stop.date !== undefined && lastDate !== undefined && stop.date !== lastDate) || stop.zone !== last.zone;
84
+ };
85
+
86
+ const daysOf = (stops: readonly Stop[]): Stop[][] =>
87
+ stops.reduce<Stop[][]>((days, stop) => {
88
+ const day = days.at(-1) ?? [];
89
+ return startsNewDay(stop, day) ? [...days, [stop]] : [...days.slice(0, -1), [...day, stop]];
90
+ }, []);
91
+
92
+ /**
93
+ * 並びの中の、日をまたいだ秒。翌日の印のある時刻は翌日、印の無い時刻は前の時刻と同じ日。
94
+ * 前の時刻より半日を超えて戻る無印の時刻は、夜をまたいだ翌日の時刻。
95
+ */
96
+ export const elapsedSeconds = (stops: readonly { readonly seconds: number; readonly shift: number }[]): number[] =>
97
+ stops
98
+ .reduce<{ day: number; seconds: number }[]>((placed, stop) => {
99
+ const previous = placed.at(-1);
100
+ const rolled = previous !== undefined && previous.seconds - stop.seconds > HALF_DAY ? previous.day + 1 : (previous?.day ?? 0);
101
+ return [...placed, { day: stop.shift > 0 ? Math.max(rolled, stop.shift) : rolled, seconds: stop.seconds }];
102
+ }, [])
103
+ .map((placed) => placed.day * SECONDS_PER_DAY + placed.seconds);
104
+
105
+ /** 文字の並びで比べられるよう、秒を桁をそろえた文字にする。 */
106
+ const PADDED = 8;
107
+ const sortable = (seconds: number): string => String(seconds).padStart(PADDED, "0");
108
+
109
+ /** 外れた時刻に、前の時刻を添える。先頭の時刻には前が無いので、次の時刻を添える。 */
110
+ const issueAt = (day: readonly Stop[], at: number): StructureIssue[] => {
111
+ const stop = day[at];
112
+ if (stop === undefined) return [];
113
+ const neighbour = at === 0 ? { next: day[1]?.written ?? "" } : { previous: day[at - 1]?.written ?? "" };
114
+ return [{ offset: stop.offset, values: { time: stop.written, ...neighbour } }];
115
+ };
116
+
117
+ /**
118
+ * 範囲で書いた時刻の並びで、前の範囲が終わる前に次が始まる一歩が半分を超えるもの。曜日ごとの営業時間(9:00–18:00 が続く)
119
+ * のように時刻で並べたものではない一覧で、一日の予定ではない。
120
+ */
121
+ export const isOverlappingRanges = (ranges: readonly { readonly seconds: number; readonly until: number | undefined }[]): boolean => {
122
+ const steps = ranges.slice(1).map((range, index) => ranges[index]?.until !== undefined && range.seconds < (ranges[index]?.until ?? 0));
123
+ return steps.length > 0 && steps.filter(Boolean).length * 2 > steps.length;
124
+ };
125
+
126
+ /** 早い順に逆らう一歩ごとに、並びから外れた時刻を指す。早い順に並ぶ時刻が半分以下の並びと、重なる範囲の並びは言わない。 */
127
+ const breaksIn = (day: readonly Stop[]): StructureIssue[] => {
128
+ const values = elapsedSeconds(day).map(sortable);
129
+ if (values.length < MIN_STOPS || longestInOrder(values, 1) * 2 <= values.length || isOverlappingRanges(day)) return [];
130
+ return values.slice(1).flatMap((value, index) => (value < (values[index] ?? "") ? issueAt(day, outOfPlace(values, index + 1, 1)) : []));
131
+ };
132
+
133
+ /** 一日の予定の時刻のうち、早い順から外れたもの。 */
134
+ export const timeOrderBreaks = (source: string, times: readonly TimeSpan[], dates: readonly DateSpan[], words: TimeWords): StructureIssue[] => {
135
+ const inputs = { source, times, dates, words };
136
+ return runsOf(source).flatMap((run) => {
137
+ const stops = run.flatMap((line) => stopOf(line, inputs) ?? []);
138
+ return daysOf(stops).flatMap(breaksIn);
139
+ });
140
+ };
@@ -0,0 +1,33 @@
1
+ import type { MarkupHeading, StructureNode } from "../plugin.ts";
2
+ import { inDocumentOrder } from "./issues.ts";
3
+ import { lineNumberAt, type Line } from "./lines.ts";
4
+
5
+ // 題・見出しの行。見出しは節の中身に名前を付けるだけで、本文の文ではない。純関数: 木と行と Markdown の見出しを受け取る。
6
+
7
+ /** 見出しの行に、見出しの言葉のほかにあってよい字(括弧と空白)。法令の「(解雇の予告)」。 */
8
+ const CAPTION_MARKS = /[\s()()[][\]【】〔〕]/gu;
9
+
10
+ /** 条の前の行が、その条の見出しだけの行か。 */
11
+ const isCaptionLine = (line: Line | undefined, heading: string): boolean =>
12
+ line !== undefined && heading !== "" && line.text.replaceAll(CAPTION_MARKS, "") === heading.replaceAll(CAPTION_MARKS, "");
13
+
14
+ const lineNumbersOfTree = (tree: StructureNode, lines: readonly Line[]): number[] =>
15
+ inDocumentOrder(tree).flatMap((node) => {
16
+ if (node.kind === "chapter" || node.kind === "section") return [node.line];
17
+ if (node.kind !== "article") return [];
18
+ const caption = node.line - 1;
19
+ return isCaptionLine(lines[caption - 1], String(node.attrs["heading"] ?? "")) ? [caption] : [];
20
+ });
21
+
22
+ /**
23
+ * 題・見出しの行の番号(1 始まり)。Markdown の見出しの行、木の章・節の行、条の前に置いた見出しだけの行。
24
+ * 条の行の中の見出し(第一条(目的))は条の本文と同じ行なので入れない。
25
+ */
26
+ export const titleLineNumbers = (tree: StructureNode | undefined, lines: readonly Line[], headings: readonly MarkupHeading[]): ReadonlySet<number> =>
27
+ new Set([
28
+ ...(tree === undefined ? [] : lineNumbersOfTree(tree, lines)),
29
+ ...headings.flatMap((heading) => {
30
+ const line = lineNumberAt(lines, heading.start);
31
+ return line === undefined ? [] : [line];
32
+ }),
33
+ ]);
@@ -142,6 +142,10 @@ const SIGN_REACH = 2;
142
142
  const signBefore = (source: string, total: Placed, start: number): string =>
143
143
  total.cents !== undefined && total.cents < 0 ? (SIGN_BEFORE.exec(source.slice(Math.max(0, start - SIGN_REACH), start))?.[0] ?? "") : "";
144
144
 
145
+ /** 数の後ろに書いた単位。単位の組の名前(credit)と書いた語(credits)が違えば、書いた語を見せる。 */
146
+ const unitAfterNumber = (written: string, unit: string): string =>
147
+ written.endsWith(unit) ? unit : written.slice(written.split("").findLastIndex((char) => char >= "0" && char <= "9") + 1);
148
+
145
149
  /** 合計の行に書いた金額と、上の和を、同じ書き方で見せる。負の和には、合計に書いた印(無ければ -)を付ける。 */
146
150
  const shownAmounts = (source: string, total: Placed, sumCents: number): Record<string, string> => {
147
151
  const unitStart = unitStartBefore(source, total);
@@ -151,7 +155,7 @@ const shownAmounts = (source: string, total: Placed, sumCents: number): Record<s
151
155
  const sumSign = sumCents < 0 ? sign || "-" : "";
152
156
  const sum = formatCents(Math.abs(sumCents), written);
153
157
  if (unitStart !== undefined) return { written, sum: `${sumSign}${source.slice(unitStart, total.offset)}${sum}` };
154
- return { written, sum: `${sumSign}${sum}${written.endsWith(total.unit) ? total.unit : ""}` };
158
+ return { written, sum: `${sumSign}${sum}${unitAfterNumber(written, total.unit)}` };
155
159
  };
156
160
 
157
161
  /** 文の中の合計の金額(符号の無い、単位付きの金額)と和を、合計の書き方で見せる。 */
@@ -1,5 +1,6 @@
1
1
  // A version written in the lead-in to a code block ("Install version 2.3.0 from npm:") that the block itself does not
2
2
  // show (npm install tidyq@2.4.0). Pure: reads the source, the code blocks, and the prose with code covered.
3
+ import { escapeRegExp } from "../orthography.ts";
3
4
  import type { Span } from "../plugin.ts";
4
5
  import type { StructureIssue } from "./issues.ts";
5
6
 
@@ -85,19 +86,72 @@ const leadInOf = (source: string, blockStart: number): Span | undefined => {
85
86
  return text === "" || NOT_PROSE.test(text) || !LETTER.test(words) ? undefined : { start, end: lines.length };
86
87
  };
87
88
 
89
+ /** A pin with the version it pins, of any number of parts: redis 7.4 in redis:7.4-alpine and in library/redis:7.4. */
90
+ const PIN_VERSION = /^([\w.-]+)(?:@|==|=|:)[v^~]?(\d+(?:\.\d+)*)/u;
91
+ const HAS_LETTER = /[A-Za-z]/u;
92
+
93
+ /** Each name the block pins, with the one version it pins it to; a name pinned to two versions is left out. */
94
+ const pinnedVersions = (code: string): Map<string, string> => {
95
+ const byName = new Map<string, Set<string>>();
96
+ codeWords(code).forEach((word) => {
97
+ const match = PIN_VERSION.exec(word.slice(word.lastIndexOf("/") + 1));
98
+ if (match?.[1] === undefined || match[2] === undefined || !HAS_LETTER.test(match[1])) return;
99
+ const name = match[1].toLowerCase();
100
+ byName.set(name, new Set([...(byName.get(name) ?? []), match[2]]));
101
+ });
102
+ const single = new Map<string, string>();
103
+ byName.forEach((versions, name) => {
104
+ const [only] = versions;
105
+ if (versions.size === 1 && only !== undefined) single.set(name, only);
106
+ });
107
+ return single;
108
+ };
109
+
110
+ /** 7 and 7.4, or 7.4 and 7.4.1: one names the other's series, so they agree. */
111
+ const sameSeries = (written: string, pinned: string): boolean => {
112
+ const [shorter, longer] = [written.split("."), pinned.split(".")].toSorted((left, right) => left.length - right.length);
113
+ return (shorter ?? []).every((part, index) => part === longer?.[index]);
114
+ };
115
+
88
116
  /**
89
- * Each version in a code block's lead-in that differs from the one version the block shows. A block with no version, or
90
- * with two (an upgrade from one to the other), says nothing to compare; a version marked as a bound, or named after another
91
- * program, is not the one installed.
117
+ * Each version written right after the name of a program the block pins ("We run Redis 7.2" over redis:7.4) that is not of
118
+ * the pinned version's series. The name says whose version it is, so a version of two parts is read here, where a bare 7.2
119
+ * is too often a decimal; one part (port 6379, Node 20) is too often another number.
92
120
  */
93
- export const versionMismatches = (source: string, prose: string, blocks: readonly CodeBlock[], words: VersionWords): StructureIssue[] =>
94
- blocks.flatMap((block) => {
95
- const shown = [...new Set(versionsIn(block.code).map((found) => found.version))];
96
- const leadIn = leadInOf(source, block.start);
97
- const [code] = shown;
98
- if (shown.length !== 1 || code === undefined || leadIn === undefined) return [];
99
- const names = pinnedNames(block.code);
100
- return versionsIn(prose.slice(leadIn.start, leadIn.end), leadIn.start)
101
- .filter((found) => found.version !== code && !isBound(prose, found, words.ranges) && isAboutBlock(prose, found, names, words.versionWords))
102
- .map((found) => ({ offset: found.start, values: { written: found.version, code } }));
121
+ const namedMismatches = (prose: string, leadIn: Span, code: string, ranges: readonly RangeWord[]): StructureIssue[] =>
122
+ [...pinnedVersions(code)].flatMap(([name, pinned]) => {
123
+ const pattern = new RegExp(`(?<![\\w.-])${escapeRegExp(name)}\\s+v?(\\d+(?:\\.\\d+){1,2})(?![\\w.]|\\.\\d)`, "giu");
124
+ return [...prose.slice(leadIn.start, leadIn.end).matchAll(pattern)].flatMap((match) => {
125
+ const written = match[1] ?? "";
126
+ const span = { start: leadIn.start + match.index, end: leadIn.start + match.index + match[0].length };
127
+ if (sameSeries(written, pinned) || isBound(prose, span, ranges)) return [];
128
+ return [{ offset: span.end - written.length, values: { written, code: pinned } }];
129
+ });
103
130
  });
131
+
132
+ /**
133
+ * Each version in the lead-in that differs from the one version the block shows. A block with no version, or with two (an
134
+ * upgrade from one to the other), says nothing to compare; a version marked as a bound, or named after another program, is
135
+ * not the one installed.
136
+ */
137
+ const shownMismatches = (prose: string, leadIn: Span, code: string, words: VersionWords): StructureIssue[] => {
138
+ const shown = [...new Set(versionsIn(code).map((found) => found.version))];
139
+ const [only] = shown;
140
+ if (shown.length !== 1 || only === undefined) return [];
141
+ const names = pinnedNames(code);
142
+ return versionsIn(prose.slice(leadIn.start, leadIn.end), leadIn.start)
143
+ .filter((found) => found.version !== only && !isBound(prose, found, words.ranges) && isAboutBlock(prose, found, names, words.versionWords))
144
+ .map((found) => ({ offset: found.start, values: { written: found.version, code: only } }));
145
+ };
146
+
147
+ /** Both readings of one block; a version both report is reported once, against the pin of the program it names. */
148
+ const blockMismatches = (source: string, prose: string, block: CodeBlock, words: VersionWords): StructureIssue[] => {
149
+ const leadIn = leadInOf(source, block.start);
150
+ if (leadIn === undefined) return [];
151
+ const issues = [...namedMismatches(prose, leadIn, block.code, words.ranges), ...shownMismatches(prose, leadIn, block.code, words)];
152
+ return issues.filter((issue, index) => issues.findIndex((other) => other.offset === issue.offset) === index);
153
+ };
154
+
155
+ /** Each version in a code block's lead-in that differs from the version the block installs. */
156
+ export const versionMismatches = (source: string, prose: string, blocks: readonly CodeBlock[], words: VersionWords): StructureIssue[] =>
157
+ blocks.flatMap((block) => blockMismatches(source, prose, block, words));
@@ -0,0 +1,84 @@
1
+ import type { StructureIssue } from "./issues.ts";
2
+
3
+ /**
4
+ * Versions listed in order, a changelog's headings or a list of releases, with one out of place. The direction (newest or
5
+ * oldest first) is taken from most of the steps, and a version that fits in no longest run along it is pointed out.
6
+ */
7
+ export type VersionPoint = { readonly offset: number; readonly label: string };
8
+
9
+ type Version = { readonly parts: readonly number[]; readonly prerelease: string };
10
+
11
+ /** A version at the start of a heading or an item: 3.2.0, v3.2.0, [3.2.0], 3.2.0-beta.1. */
12
+ const VERSION_START = /^\[?v?(\d{1,4})\.(\d{1,4})\.(\d{1,4})(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?\]?(?![\w.])/u;
13
+
14
+ /** The version a heading or an item starts with, as written; undefined when it does not start with one. */
15
+ export const leadingVersion = (text: string): string | undefined => VERSION_START.exec(text.trim())?.[0];
16
+
17
+ const parse = (label: string): Version | undefined => {
18
+ const match = VERSION_START.exec(label);
19
+ if (match === null) return undefined;
20
+ return { parts: [match[1], match[2], match[3]].map(Number), prerelease: match[4] ?? "" };
21
+ };
22
+
23
+ /** A prerelease (3.0.0-beta.1) comes before its release (3.0.0). */
24
+ const comparePrerelease = (left: string, right: string): number => {
25
+ if (left === right) return 0;
26
+ if (left === "") return 1;
27
+ return right === "" ? -1 : Math.sign(left.localeCompare(right, "en", { numeric: true }));
28
+ };
29
+
30
+ const compareVersions = (left: Version, right: Version): number => {
31
+ const differing = left.parts.findIndex((part, index) => part !== right.parts[index]);
32
+ return differing === -1 ? comparePrerelease(left.prerelease, right.prerelease) : Math.sign((left.parts[differing] ?? 0) - (right.parts[differing] ?? 0));
33
+ };
34
+
35
+ /** The longest run along direction ending at each version (equal versions do not break it). */
36
+ const longestEndingAt = (versions: readonly Version[], direction: number): number[] =>
37
+ versions.reduce<number[]>((lengths, version, index) => {
38
+ const along = versions.slice(0, index).map((earlier, at) => (compareVersions(version, earlier) === -direction ? 0 : (lengths[at] ?? 0)));
39
+ return [...lengths, 1 + Math.max(0, ...along)];
40
+ }, []);
41
+
42
+ const majorityOf = (versions: readonly Version[]): number =>
43
+ Math.sign(versions.slice(1).reduce((sum, version, index) => sum + compareVersions(version, versions[index] ?? version), 0));
44
+
45
+ /** The fewest versions an order is read from: with two, either one could be the one out of place. */
46
+ const MIN_VERSIONS = 3;
47
+
48
+ /**
49
+ * The versions that belong to no longest run along the majority direction. A run that holds no more than half of them is
50
+ * taken as sorted by something else, and nothing is said.
51
+ */
52
+ export const versionOrderBreaks = (points: readonly VersionPoint[]): StructureIssue[] => {
53
+ const parsed = points.flatMap((point) => {
54
+ const version = parse(point.label);
55
+ return version === undefined ? [] : [{ point, version }];
56
+ });
57
+ const versions = parsed.map((entry) => entry.version);
58
+ const direction = majorityOf(versions);
59
+ if (versions.length < MIN_VERSIONS || direction === 0) return [];
60
+ const forward = longestEndingAt(versions, direction);
61
+ const backward = longestEndingAt(versions.toReversed(), -direction).toReversed();
62
+ const longest = Math.max(...forward);
63
+ if (longest * 2 <= versions.length) return [];
64
+ return parsed.flatMap((entry, index) =>
65
+ (forward[index] ?? 0) + (backward[index] ?? 0) - 1 === longest
66
+ ? []
67
+ : [{ offset: entry.point.offset, values: { version: entry.point.label, previous: parsed[index - 1]?.point.label ?? "" } }],
68
+ );
69
+ };
70
+
71
+ /** A version whose last part is zero (3.1.0) is no section number: the sections under 3.1 count from 3.1.1. */
72
+ const endsInZero = (version: Version): boolean => version.parts.at(-1) === 0;
73
+
74
+ /**
75
+ * Whether dotted labels (1.2.1, 1.2.2) are a version history rather than section numbers: all of them versions, and
76
+ * either one ends in zero or most steps go down (newest first). Section numbers only go up. version-order checks the
77
+ * histories and numbering-gap the rest, so a sequence is never reported by both.
78
+ */
79
+ export const isVersionHistory = (labels: readonly string[]): boolean => {
80
+ const versions = labels.map(parse);
81
+ const parsed = versions.filter((version) => version !== undefined);
82
+ if (labels.length < 2 || parsed.length !== labels.length) return false;
83
+ return parsed.some(endsInZero) || majorityOf(parsed) < 0;
84
+ };
@@ -0,0 +1,39 @@
1
+ // The prose with its Markdown tables read back in. The prose masks tables, but a quote or an invoice keeps most of its
2
+ // amounts in one, and a rule comparing how amounts are written has to see them.
3
+ import type { ProseDocument, Span } from "./plugin.ts";
4
+ import { maskSpans } from "./mask.ts";
5
+ import { opaqueSpans, readMarkdown, spansOfType } from "./markdown-read.ts";
6
+ import { TABLE_RULE } from "./structure/runs.ts";
7
+
8
+ const within = (inner: Span, outer: Span): boolean => inner.start >= outer.start && inner.end <= outer.end;
9
+
10
+ /**
11
+ * The prose, with each table span as the source writes it, except what stays hidden inside it (code in a cell). Offsets
12
+ * are kept. Pure.
13
+ */
14
+ export const proseWithTables = (prose: string, source: string, tables: readonly Span[], hidden: readonly Span[]): string => {
15
+ if (tables.length === 0) return prose;
16
+ const shown = maskSpans(source, hidden);
17
+ const pieces: string[] = [];
18
+ const end = tables
19
+ .toSorted((left, right) => left.start - right.start)
20
+ .reduce((from, table) => {
21
+ if (table.start < from) return from;
22
+ pieces.push(prose.slice(from, table.start), shown.slice(table.start, table.end));
23
+ return table.end;
24
+ }, 0);
25
+ pieces.push(prose.slice(end));
26
+ return pieces.join("");
27
+ };
28
+
29
+ const hasTableRule = (source: string): boolean => source.split("\n").some((line) => TABLE_RULE.test(line) && line.includes("-"));
30
+
31
+ /** The document's prose with its tables, outside code and quoted replies. A document that is not Markdown keeps its prose. */
32
+ export const proseAndTablesOf = (doc: ProseDocument): string => {
33
+ const prose = doc.prose ?? doc.source;
34
+ if (doc.prose === undefined || doc.markup?.markdown !== true || !hasTableRule(doc.source)) return prose;
35
+ const { root } = readMarkdown(doc.source);
36
+ const quoted = [...spansOfType(root, "blockquote"), ...(doc.replyQuotes ?? [])];
37
+ const tables = spansOfType(root, "table").filter((table) => !quoted.some((quote) => within(table, quote)));
38
+ return proseWithTables(doc.prose, doc.source, tables, opaqueSpans(root));
39
+ };
@@ -0,0 +1,55 @@
1
+ // The same label on the screen written two ways in one manual (**Start Restore** and **Start restore**, [復元を開始] and
2
+ // [復元開始]). Pure: reads the labels a manual marks as labels, bold or in [], and points at the form written less often.
3
+
4
+ import { escapeRegExp } from "./orthography.ts";
5
+
6
+ export type Label = { readonly surface: string; readonly offset: number };
7
+ export type LabelVariant = { readonly label: Label; readonly usual: string };
8
+
9
+ /** What a manual marks as a label on the screen: bold (** or __), or the full-width brackets Japanese manuals use. */
10
+ const MARKED = /\*\*([^*\n]{1,40})\*\*|__([^_\n]{1,40})__|[([^]\n]{1,40})]/gu;
11
+ const SPACES = /\s+/gu;
12
+ const LETTER = /\p{L}/u;
13
+
14
+ /** Each label marked in the source whose text is prose (not covered as code in prose) and holds a letter. */
15
+ export const labelsIn = (source: string, prose: string): Label[] =>
16
+ [...source.matchAll(MARKED)].flatMap((match) => {
17
+ const surface = (match[1] ?? match[2] ?? match[3] ?? "").trim();
18
+ const inner = match.index + match[0].indexOf(surface);
19
+ const covered = prose.slice(inner, inner + surface.length) !== surface;
20
+ return covered || !LETTER.test(surface) ? [] : [{ surface, offset: inner }];
21
+ });
22
+
23
+ /**
24
+ * Two forms of one label differ only in case, spaces, or a word a label is written with or without (the label-particle
25
+ * lexicon: 復元を開始 and 復元開始).
26
+ */
27
+ const keyOf = (surface: string, particles: readonly string[]): string =>
28
+ particles.reduce((text, particle) => text.replace(joining(particle), ""), surface.replace(SPACES, "")).toLowerCase();
29
+
30
+ /** A particle between two kanji or katakana (復元を開始), not one inside a word (その他). */
31
+ const joining = (particle: string): RegExp =>
32
+ new RegExp(`(?<=[\\p{Script=Han}\\p{Script=Katakana}ー])${escapeRegExp(particle)}(?=[\\p{Script=Han}\\p{Script=Katakana}])`, "gu");
33
+
34
+ /** Two forms that differ only in the case of their first letter (Note and note): emphasis at a sentence's start, not two labels. */
35
+ const onlyFirstLetterDiffers = (forms: readonly string[]): boolean =>
36
+ new Set(forms.map((form) => `${form.charAt(0).toLowerCase()}${form.slice(1)}`)).size === 1;
37
+
38
+ const groupBy = (labels: readonly Label[], keyFor: (label: Label) => string): Map<string, Label[]> =>
39
+ labels.reduce((groups, label) => groups.set(keyFor(label), [...(groups.get(keyFor(label)) ?? []), label]), new Map<string, Label[]>());
40
+
41
+ /**
42
+ * Each label written in a form other than the one its key is written in most; on a tie, the later form. A label written
43
+ * one way only says nothing.
44
+ */
45
+ export const labelVariants = (labels: readonly Label[], particles: readonly string[] = []): LabelVariant[] => {
46
+ const byKey = groupBy(labels, (label) => keyOf(label.surface, particles));
47
+ return [...byKey.values()].flatMap((group) => {
48
+ const counts = groupBy(group, (label) => label.surface);
49
+ if (counts.size < 2 || onlyFirstLetterDiffers([...counts.keys()])) return [];
50
+ const [first] = counts;
51
+ if (first === undefined) return [];
52
+ const usual = [...counts].reduce((best, entry) => (entry[1].length > best[1].length ? entry : best), first)[0];
53
+ return group.filter((label) => label.surface !== usual).map((label) => ({ label, usual }));
54
+ });
55
+ };