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,198 @@
1
+ import type { StructureIssue } from "./issues.ts";
2
+ import { TABLE_RULE } from "./runs.ts";
3
+ import {
4
+ crossesZones,
5
+ dayShiftOf,
6
+ markBefore,
7
+ markRightAfter,
8
+ wordOffsets,
9
+ zonesIn,
10
+ SECONDS_PER_DAY,
11
+ type DateSpan,
12
+ type Mark,
13
+ type TimeSpan,
14
+ type TimeWords,
15
+ } from "./time-marks.ts";
16
+
17
+ /**
18
+ * 一つの行(箇条書きの項目、表の行、文の一行)に書いた発と着の時刻。着が発より前なら、どちらかの書き間違い。
19
+ * 発・着は、時刻のすぐ後ろの印(「08:00発」)か、時刻の少し前の印(「departs Boston 7:30 AM」「dep 10:30」)、
20
+ * または表の列の見出し(出発、到着、Departs、Arrives。語彙表 leg-column)で読む。
21
+ * 着に翌日の印(翌、+1、next day)があれば一日足す。発と着の両方に日付があれば日付で比べ、片方だけなら比べない。
22
+ * 違う時間帯の印が二つある行と、「現地時間」のようにどこの時刻かを言わない印のある行は、時刻をそのまま比べられないので言わない。
23
+ */
24
+
25
+ /** 発か着の時刻。date はその時刻の前に書いた日付、shift は翌日(1)か前日(-1)の印、zone は時刻の後ろに書いた時間帯(無ければ空)。 */
26
+ type LegTime = {
27
+ readonly offset: number;
28
+ readonly end: number;
29
+ readonly written: string;
30
+ readonly seconds: number;
31
+ readonly shift: number;
32
+ readonly date: string | undefined;
33
+ readonly zone: string;
34
+ };
35
+
36
+ type Leg = LegTime & { readonly side: string };
37
+
38
+ const DEPARTURE = "departure";
39
+ const ARRIVAL = "arrival";
40
+
41
+ /** 「departs Washington Reagan 1:30 PM」のように、発着の語と時刻の間に挟んでよい字の数(地名)。 */
42
+ const LEG_WORD_GAP = 32;
43
+ /** 発着の語と時刻の間に来れば、その語は時刻にかからない(文や句の切れ目)。 */
44
+ const BREAK = /[。.;;!?!?]|\.\s/u;
45
+
46
+ type Inputs = { readonly source: string; readonly times: readonly TimeSpan[]; readonly dates: readonly DateSpan[]; readonly words: TimeWords };
47
+
48
+ const timesWithin = (times: readonly TimeSpan[], start: number, end: number): TimeSpan[] => times.filter((time) => time.start >= start && time.end <= end);
49
+
50
+ /** 時刻の日付と読む、時刻の前に書いた日付までの字の数(「Feb 8, 1:00 PM」「2月8日 13:00」)。 */
51
+ const DATE_WINDOW = 4;
52
+
53
+ /** 時刻の後ろで、その時刻の時間帯の印(17:00 JST)を探す字の数。 */
54
+ const ZONE_WINDOW = 12;
55
+
56
+ /** 時刻を、from から to までの原文(前の時刻の後ろから次の時刻の前まで、表なら升)の中で読む。 */
57
+ const legTimeOf = (time: TimeSpan, from: number, to: number, inputs: Inputs): LegTime => {
58
+ const head = inputs.source.slice(from, time.start);
59
+ const date = inputs.dates.filter((span) => span.start >= from && span.end <= time.start && time.start - span.end <= DATE_WINDOW).at(-1)?.value;
60
+ const shift = dayShiftOf(head, inputs.source, time.end, inputs.words);
61
+ const zone = zonesIn(inputs.source.slice(time.end, Math.min(to, time.end + ZONE_WINDOW)), inputs.words)[0]?.text ?? "";
62
+ return { offset: time.start, end: time.end, written: inputs.source.slice(time.start, time.end), seconds: time.seconds, shift, date, zone };
63
+ };
64
+
65
+ /** 時刻の前の語(departs、dep)。間に句の切れ目があれば、その語はこの時刻のものではない。 */
66
+ const sideBefore = (head: string, legs: readonly Mark[]): string | undefined => {
67
+ const mark = markBefore(head, legs, LEG_WORD_GAP);
68
+ if (mark === undefined) return undefined;
69
+ const at = Math.max(...wordOffsets(head, mark.pattern));
70
+ return BREAK.test(head.slice(at + mark.pattern.length)) ? undefined : mark.group;
71
+ };
72
+
73
+ /** 一行の中の発着の時刻を、書いた順に。前の時刻から後ろだけを、その時刻の前置きとして読む。 */
74
+ const legsInLine = (start: number, end: number, inputs: Inputs): Leg[] =>
75
+ timesWithin(inputs.times, start, end).flatMap((time, index, all) => {
76
+ const from = all[index - 1]?.end ?? start;
77
+ const to = all[index + 1]?.start ?? end;
78
+ const side = markRightAfter(inputs.source, time.end, inputs.words.legs)?.group ?? sideBefore(inputs.source.slice(from, time.start), inputs.words.legs);
79
+ return side === DEPARTURE || side === ARRIVAL ? [{ ...legTimeOf(time, from, to, inputs), side }] : [];
80
+ });
81
+
82
+ /** 発のあとに来た最初の着を、その発の組にする。間に文の切れ目があれば、着は別の文のもので組にしない。 */
83
+ const pairsOf = (source: string, legs: readonly Leg[]): [LegTime, LegTime][] =>
84
+ legs.reduce<{ pending: LegTime | undefined; pairs: [LegTime, LegTime][] }>(
85
+ (found, leg) => {
86
+ if (leg.side === DEPARTURE) return { ...found, pending: leg };
87
+ if (found.pending === undefined || BREAK.test(source.slice(found.pending.end, leg.offset))) return { ...found, pending: undefined };
88
+ return { pending: undefined, pairs: [...found.pairs, [found.pending, leg]] };
89
+ },
90
+ { pending: undefined, pairs: [] },
91
+ ).pairs;
92
+
93
+ /** 年月日、年月、月日は、同じ書き方どうしでしか比べない。 */
94
+ const sameShape = (left: string, right: string): boolean => left.length === right.length;
95
+
96
+ /**
97
+ * 着が発より前か。両方に日付があれば日付で、日付が同じなら時刻で比べる。片方だけに日付があれば、もう片方の日が分からない。
98
+ * 時間帯の印が発と着で違えば(片方だけに書いたときも)、時刻をそのまま比べられない。
99
+ */
100
+ export const arrivesFirst = (departure: LegTime, arrival: LegTime): boolean => {
101
+ if ((departure.date === undefined) !== (arrival.date === undefined) || departure.zone !== arrival.zone) return false;
102
+ if (departure.date !== undefined && arrival.date !== undefined) {
103
+ if (!sameShape(departure.date, arrival.date)) return false;
104
+ if (departure.date !== arrival.date) return arrival.date < departure.date;
105
+ }
106
+ return arrival.shift * SECONDS_PER_DAY + arrival.seconds < departure.shift * SECONDS_PER_DAY + departure.seconds;
107
+ };
108
+
109
+ const issueOf = ([departure, arrival]: [LegTime, LegTime]): StructureIssue => ({
110
+ offset: arrival.offset,
111
+ values: { arrival: arrival.written, departure: departure.written },
112
+ });
113
+
114
+ const linesOf = (source: string): { start: number; end: number }[] =>
115
+ source.split("\n").reduce<{ start: number; end: number }[]>((lines, text) => {
116
+ const start = (lines.at(-1)?.end ?? -1) + 1;
117
+ return [...lines, { start, end: start + text.length }];
118
+ }, []);
119
+
120
+ /** 行の中で発と着の印から読む組。 */
121
+ const inlinePairs = (inputs: Inputs, zonesOf: (start: number, end: number) => boolean): [LegTime, LegTime][] =>
122
+ linesOf(inputs.source).flatMap((line) => (zonesOf(line.start, line.end) ? [] : pairsOf(inputs.source, legsInLine(line.start, line.end, inputs))));
123
+
124
+ type Cell = { readonly start: number; readonly end: number };
125
+
126
+ /** 表の一行を、| で区切った升に分ける。先頭と末尾の | の外は升ではない。 */
127
+ export const cellsOf = (source: string, start: number, end: number): Cell[] => {
128
+ const text = source.slice(start, end);
129
+ const bars = [...text.matchAll(/(?<!\\)\|/gu)].map((match) => start + match.index);
130
+ const edges = [text.trimStart().startsWith("|") ? undefined : start - 1, ...bars, text.trimEnd().endsWith("|") ? undefined : end].filter(
131
+ (edge) => edge !== undefined,
132
+ );
133
+ return edges.slice(1).map((edge, index) => ({ start: (edges[index] ?? start) + 1, end: edge }));
134
+ };
135
+
136
+ /** 見出しの升の後ろの括弧書き(「出発(現地時間)」「Departs (JST)」)。列の名前はその前まで。 */
137
+ const NOTE_OPENER = /[(([[]/u;
138
+
139
+ const columnName = (heading: string): string => {
140
+ const note = heading.search(NOTE_OPENER);
141
+ return (note === -1 ? heading : heading.slice(0, note)).trim();
142
+ };
143
+
144
+ /** 見出しの升の名前が、発着の列の名前(語彙表 leg-column)と同じ最初の列。 */
145
+ const columnOf = (source: string, header: readonly Cell[], columns: readonly Mark[], side: string): number =>
146
+ header.findIndex((cell) => {
147
+ const name = columnName(source.slice(cell.start, cell.end));
148
+ return columns.some((mark) => mark.group === side && mark.pattern === name);
149
+ });
150
+
151
+ /** 升の中の最初の時刻を、発か着として読む。 */
152
+ const cellTime = (cell: Cell | undefined, inputs: Inputs): LegTime | undefined => {
153
+ if (cell === undefined) return undefined;
154
+ const time = timesWithin(inputs.times, cell.start, cell.end)[0];
155
+ return time === undefined ? undefined : legTimeOf(time, cell.start, cell.end, inputs);
156
+ };
157
+
158
+ type Table = { readonly header: Cell[]; readonly rows: { start: number; end: number }[] };
159
+
160
+ /** 見出しの行、区切りの行、| のある行が続くあいだを一つの表にする。 */
161
+ const tablesOf = (source: string): Table[] => {
162
+ const lines = linesOf(source);
163
+ return lines.flatMap((line, index) => {
164
+ const header = lines[index - 1];
165
+ if (header === undefined || !TABLE_RULE.test(source.slice(line.start, line.end))) return [];
166
+ const after = lines.slice(index + 1);
167
+ const stop = after.findIndex((row) => !source.slice(row.start, row.end).includes("|"));
168
+ return [{ header: cellsOf(source, header.start, header.end), rows: stop === -1 ? after : after.slice(0, stop) }];
169
+ });
170
+ };
171
+
172
+ /** 発の列と着の列を見出しから読む表の組。見出しに時間帯の印があれば、行と合わせて時間帯を見る。 */
173
+ const columnPairs = (inputs: Inputs, zonesOf: (start: number, end: number) => boolean): [LegTime, LegTime][] =>
174
+ tablesOf(inputs.source).flatMap((table) => {
175
+ const departs = columnOf(inputs.source, table.header, inputs.words.columns, DEPARTURE);
176
+ const arrives = columnOf(inputs.source, table.header, inputs.words.columns, ARRIVAL);
177
+ const headerLine = { start: table.header[0]?.start ?? 0, end: table.header.at(-1)?.end ?? 0 };
178
+ if (departs === -1 || arrives === -1) return [];
179
+ return table.rows.flatMap((row): [LegTime, LegTime][] => {
180
+ const cells = cellsOf(inputs.source, row.start, row.end);
181
+ const departure = cellTime(cells[departs], inputs);
182
+ const arrival = cellTime(cells[arrives], inputs);
183
+ const zoned = zonesOf(row.start, row.end) || zonesOf(headerLine.start, headerLine.end);
184
+ return departure === undefined || arrival === undefined || zoned ? [] : [[departure, arrival]];
185
+ });
186
+ });
187
+
188
+ /** 着が発より前の組。同じ着を表の列と行の中の印の両方から読んでも、一度だけ言う。 */
189
+ export const arrivalsBeforeDeparture = (source: string, times: readonly TimeSpan[], dates: readonly DateSpan[], words: TimeWords): StructureIssue[] => {
190
+ const inputs = { source, times, dates, words };
191
+ const zonesOf = (start: number, end: number): boolean => crossesZones(zonesIn(source.slice(start, end), words));
192
+ const issues = [...inlinePairs(inputs, zonesOf), ...columnPairs(inputs, zonesOf)]
193
+ .filter(([departure, arrival]) => arrivesFirst(departure, arrival))
194
+ .map(issueOf);
195
+ return issues
196
+ .filter((issue, index) => issues.findIndex((other) => other.offset === issue.offset) === index)
197
+ .toSorted((left, right) => left.offset - right.offset);
198
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 明細の一行で、数量と単価が同じ単位を数えているか。単価が何かあたり($100/hour、月額、Rate の列)なら、数量はその単位で
3
+ * 書かれているか単位の無い数でなければ、掛けても金額にならない。語はすべて語彙表から来る。Pure.
4
+ */
5
+ export type UnitWord = { readonly pattern: string; readonly unit: string };
6
+
7
+ /** The marks of a price cell with its per-unit mark taken off, and the unit it named. */
8
+ export type PerUnitPrice = { readonly before: string; readonly after: string; readonly unit: string };
9
+
10
+ const longestFirst = (words: readonly UnitWord[]): UnitWord[] => words.toSorted((left, right) => right.pattern.length - left.pattern.length);
11
+
12
+ const lower = (text: string): string => text.normalize("NFKC").toLowerCase();
13
+
14
+ /** "$" "/hour" → "$" "" hour; "月額" "円" → "" "円" month. Undefined when neither mark says a unit. */
15
+ export const perUnitPrice = (before: string, after: string, marks: readonly UnitWord[]): PerUnitPrice | undefined => {
16
+ const sorted = longestFirst(marks);
17
+ const ending = sorted.find((mark) => lower(after).endsWith(lower(mark.pattern)));
18
+ if (ending !== undefined) return { before, after: after.slice(0, after.length - ending.pattern.length).trim(), unit: ending.unit };
19
+ const opening = sorted.find((mark) => lower(before).startsWith(lower(mark.pattern)));
20
+ return opening === undefined ? undefined : { before: before.slice(opening.pattern.length).trim(), after, unit: opening.unit };
21
+ };
22
+
23
+ /** The unit of a quantity's word ("days" → day), "" when the cell has no word after its number, undefined when the word is not a unit. */
24
+ export const quantityUnit = (word: string, units: readonly UnitWord[]): string | undefined => {
25
+ const wanted = lower(word).trim().replace(/\.$/u, "");
26
+ if (wanted === "") return "";
27
+ return units.find((unit) => lower(unit.pattern) === wanted)?.unit;
28
+ };
29
+
30
+ /**
31
+ * Whether quantity × price is meaningful. A price that is per no unit is per whatever the quantity counts. A price per a
32
+ * unit goes with a bare number (a count of that unit) or a quantity in that unit, and with nothing else.
33
+ */
34
+ export const unitsAgree = (quantity: string | undefined, pricePer: string | undefined): boolean =>
35
+ pricePer === undefined || quantity === "" || quantity === pricePer;
@@ -0,0 +1,162 @@
1
+ import type { StructureIssue } from "./issues.ts";
2
+ import { linesOf, type Line } from "./lines.ts";
3
+ import { CELL_SEPARATOR } from "./bare-numbers.ts";
4
+ import { TABLE_RULE } from "./runs.ts";
5
+ import { roundedMatches } from "./tax.ts";
6
+ import { perUnitPrice, quantityUnit, unitsAgree, type UnitWord } from "./line-amount-unit.ts";
7
+
8
+ /**
9
+ * 明細の表で、数量 × 単価が金額と合わない行。見出しの行から数量・単価・金額の列を語(quantity-column、unit-price-column、
10
+ * line-amount-column)で見つけ、本体の行ごとに数量の升の頭の数と単価の升の数を掛け、金額の升の数と比べる。
11
+ * 単価と金額は、数の前後に書いた印($、円、万円)が同じときだけ比べる。端数は切り捨て・四捨五入・切り上げのどれでもよい。
12
+ * 単価が何かあたり($100/hour、月額、Rate の列)なら、数量がその単位か単位の無い数のときだけ比べる。Pure.
13
+ */
14
+ export type LineAmountWords = {
15
+ readonly quantity: readonly string[];
16
+ readonly unitPrice: readonly string[];
17
+ readonly amount: readonly string[];
18
+ /** Unit words of a quantity (rate-unit). */
19
+ readonly units: readonly UnitWord[];
20
+ /** Marks saying a price is per a unit (per-unit-mark). */
21
+ readonly perUnitMarks: readonly UnitWord[];
22
+ /** Column headings that say the unit of their column (Hours, Rate). */
23
+ readonly headerUnits: readonly UnitWord[];
24
+ };
25
+
26
+ type Cell = { readonly start: number; readonly text: string };
27
+
28
+ /** A number with what is written before and after it in one cell: "$1,500.00" is $ 1500 "", "15万円" is "" 15 万円. */
29
+ type CellNumber = {
30
+ readonly before: string;
31
+ readonly value: number;
32
+ readonly after: string;
33
+ readonly offset: number;
34
+ readonly written: string;
35
+ readonly grouped: boolean;
36
+ readonly decimals: number;
37
+ };
38
+
39
+ const CENTS = 100;
40
+ const ONE_NUMBER = /^([^\d]*?)(\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?([^\d]*)$/u;
41
+ const LEADING_NUMBER = /^(\d{1,3}(?:,\d{3})+|\d+)(\.\d+)?(?![\d,])/u;
42
+ const NEGATIVE = /[-−▲△((]/u;
43
+
44
+ const cellsOf = (line: Line): Cell[] => {
45
+ const bounds = [-1, ...[...line.text.matchAll(CELL_SEPARATOR)].map((match) => match.index), line.text.length];
46
+ const cells = bounds.slice(1).map((end, index) => {
47
+ const from = (bounds[index] ?? 0) + 1;
48
+ return { start: line.start + from, text: line.text.slice(from, end) };
49
+ });
50
+ const trimmed = line.text.trim();
51
+ return cells.slice(trimmed.startsWith("|") ? 1 : 0, trimmed.endsWith("|") ? cells.length - 1 : cells.length);
52
+ };
53
+
54
+ const plain = (text: string): string => text.normalize("NFKC").replace(/[*_`]/gu, "").trim();
55
+
56
+ /** The one number of a price cell with its marks, undefined when the cell holds none, more, or a negative one. */
57
+ export const cellNumber = (cell: Cell): CellNumber | undefined => {
58
+ const text = plain(cell.text);
59
+ const match = ONE_NUMBER.exec(text);
60
+ if (match === null) return undefined;
61
+ const [, before = "", whole = "", fraction = "", after = ""] = match;
62
+ if (NEGATIVE.test(before) || NEGATIVE.test(after)) return undefined;
63
+ return {
64
+ before: before.trim(),
65
+ value: Number(`${whole.replaceAll(",", "")}${fraction}`),
66
+ after: after.trim(),
67
+ offset: cell.start + (cell.text.length - cell.text.trimStart().length),
68
+ written: text,
69
+ grouped: whole.includes(","),
70
+ decimals: Math.max(0, fraction.length - 1),
71
+ };
72
+ };
73
+
74
+ /** The number a quantity cell starts with ("4", "3人日", "2.5 hours"), undefined when it does not, or holds another ("2 x 3"). */
75
+ export const quantityOf = (cell: Cell): number | undefined => {
76
+ const text = plain(cell.text);
77
+ const match = LEADING_NUMBER.exec(text);
78
+ if (match === null || /\d/u.test(text.slice(match[0].length))) return undefined;
79
+ return Number(`${(match[1] ?? "").replaceAll(",", "")}${match[2] ?? ""}`);
80
+ };
81
+
82
+ /** What a quantity cell writes after its number ("days" in "2 days"). */
83
+ const quantityWord = (cell: Cell): string => plain(cell.text).replace(LEADING_NUMBER, "").trim();
84
+
85
+ const columnNamed = (header: readonly Cell[], names: readonly string[]): number => {
86
+ const wanted = names.map((name) => name.toLowerCase());
87
+ return header.findIndex((cell) => wanted.includes(plain(cell.text).toLowerCase()));
88
+ };
89
+
90
+ type Columns = { readonly quantity: number; readonly unitPrice: number; readonly amount: number };
91
+
92
+ /** A table's columns, and the units its quantity and price headings say (undefined when they say none). */
93
+ type Table = { readonly columns: Columns; readonly quantityUnit: string | undefined; readonly priceUnit: string | undefined };
94
+
95
+ const headerUnit = (cell: Cell | undefined, words: LineAmountWords): string | undefined =>
96
+ cell === undefined ? undefined : words.headerUnits.find((word) => word.pattern.toLowerCase() === plain(cell.text).toLowerCase())?.unit;
97
+
98
+ const tableOf = (header: readonly Cell[], words: LineAmountWords): Table | undefined => {
99
+ const columns = { quantity: columnNamed(header, words.quantity), unitPrice: columnNamed(header, words.unitPrice), amount: columnNamed(header, words.amount) };
100
+ if (Object.values(columns).some((index) => index < 0) || new Set(Object.values(columns)).size < 3) return undefined;
101
+ return { columns, quantityUnit: headerUnit(header[columns.quantity], words), priceUnit: headerUnit(header[columns.unitPrice], words) };
102
+ };
103
+
104
+ /** The unit the quantity cell counts: its own word, else its heading's ("Hours"). */
105
+ const rowQuantityUnit = (cell: Cell, table: Table, words: LineAmountWords): string | undefined => {
106
+ const unit = quantityUnit(quantityWord(cell), words.units);
107
+ return unit === "" && table.quantityUnit !== undefined ? table.quantityUnit : unit;
108
+ };
109
+
110
+ /** quantity × price, written the way the amount cell writes its number (grouping, decimals, marks). */
111
+ const shownExpected = (amount: CellNumber, exactCents: number): string => {
112
+ const exact = exactCents / CENTS;
113
+ const decimals = Number.isInteger(Math.round(exact * CENTS) / CENTS) && amount.decimals === 0 ? 0 : Math.max(amount.decimals, 2);
114
+ const number = exact.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals, useGrouping: amount.grouped });
115
+ return `${amount.before}${number}${amount.after}`;
116
+ };
117
+
118
+ /** Another cell than the item name with a number in it (a discount, a tax rate): the amount may not be quantity × price alone. */
119
+ const hasOtherNumber = (cells: readonly Cell[], columns: Columns): boolean =>
120
+ cells.some((cell, index) => index > 0 && !Object.values(columns).includes(index) && /\d/u.test(plain(cell.text)));
121
+
122
+ const rowIssue = (row: Line, table: Table, words: LineAmountWords): StructureIssue[] => {
123
+ const { columns } = table;
124
+ const cells = cellsOf(row);
125
+ if (hasOtherNumber(cells, columns)) return [];
126
+ const quantityCell = cells[columns.quantity];
127
+ const priceCell = cells[columns.unitPrice];
128
+ const amountCell = cells[columns.amount];
129
+ if (quantityCell === undefined || priceCell === undefined || amountCell === undefined) return [];
130
+ const quantity = quantityOf(quantityCell);
131
+ const price = cellNumber(priceCell);
132
+ const amount = cellNumber(amountCell);
133
+ if (quantity === undefined || price === undefined || amount === undefined) return [];
134
+ const perUnit = perUnitPrice(price.before, price.after, words.perUnitMarks);
135
+ const marks = perUnit ?? price;
136
+ if (marks.before !== amount.before || marks.after !== amount.after) return [];
137
+ if (!unitsAgree(rowQuantityUnit(quantityCell, table, words), perUnit?.unit ?? table.priceUnit)) return [];
138
+ const exactCents = quantity * price.value * CENTS;
139
+ if (roundedMatches(Math.round(amount.value * CENTS), exactCents, amount.decimals === 0)) return [];
140
+ return [
141
+ {
142
+ offset: amount.offset,
143
+ values: { written: amount.written, quantity: plain(quantityCell.text), price: price.written, expected: shownExpected(amount, exactCents) },
144
+ },
145
+ ];
146
+ };
147
+
148
+ /** Each table: its header row and its body rows. */
149
+ const tablesOf = (lines: readonly Line[]): { header: Line; rows: Line[] }[] =>
150
+ lines.flatMap((line, index) => {
151
+ const header = lines[index - 1];
152
+ if (!TABLE_RULE.test(line.text) || header === undefined || !header.text.includes("|")) return [];
153
+ const after = lines.slice(index + 1);
154
+ const end = after.findIndex((row) => !row.text.includes("|"));
155
+ return [{ header, rows: end === -1 ? after : after.slice(0, end) }];
156
+ });
157
+
158
+ export const lineAmountMismatches = (source: string, words: LineAmountWords): StructureIssue[] =>
159
+ tablesOf(linesOf(source)).flatMap(({ header, rows }) => {
160
+ const table = tableOf(cellsOf(header), words);
161
+ return table === undefined ? [] : rows.flatMap((row) => rowIssue(row, table, words));
162
+ });
@@ -0,0 +1,199 @@
1
+ // number-word-figure-mismatch: the reading half. A number written in words and then in figures in brackets ("six (7)
2
+ // months", 「金参拾万円(30,000円)」) is read on both sides; the words come from the lexicon number-word, the marks that may
3
+ // stand around the figure from currency-notation and amount-multiplier.
4
+
5
+ export type NumberWordKind = "digit" | "place" | "scale" | "joiner" | "lead" | "unit";
6
+
7
+ export type NumberWord = { readonly word: string; readonly kind: NumberWordKind; readonly value: number };
8
+
9
+ /** What the scan needs: the number words, the marks that may stand before or after the figure, and the words of scale. */
10
+ export type NumberVocabulary = {
11
+ readonly words: readonly NumberWord[];
12
+ readonly marksBefore: readonly string[];
13
+ readonly marksAfter: readonly string[];
14
+ readonly multipliers: readonly { readonly word: string; readonly value: number }[];
15
+ };
16
+
17
+ export type WordFigureSlip = { readonly offset: number; readonly end: number; readonly written: string; readonly words: number; readonly figure: number };
18
+
19
+ type Reading = {
20
+ readonly done: number;
21
+ readonly total: number;
22
+ readonly current: number;
23
+ readonly hasCurrent: boolean;
24
+ readonly lastPlace: number;
25
+ readonly lastScale: number;
26
+ };
27
+
28
+ const START: Reading = { done: 0, total: 0, current: 0, hasCurrent: false, lastPlace: Infinity, lastScale: Infinity };
29
+ const TENS_MIN = 20;
30
+ const TENS_MAX = 90;
31
+ const TEN = 10;
32
+
33
+ /** "twenty" then "one" is 21; any other digit after a digit ("five five", 二〇) is not one number. */
34
+ const joinsDigit = (reading: Reading, value: number): boolean =>
35
+ !reading.hasCurrent || (reading.current >= TENS_MIN && reading.current <= TENS_MAX && reading.current % TEN === 0 && value > 0 && value < TEN);
36
+
37
+ const stepWord = (reading: Reading | undefined, word: NumberWord): Reading | undefined => {
38
+ if (reading === undefined) return undefined;
39
+ if (word.kind === "digit") return joinsDigit(reading, word.value) ? { ...reading, current: reading.current + word.value, hasCurrent: true } : undefined;
40
+ if (word.kind === "place") {
41
+ if (word.value >= reading.lastPlace) return undefined;
42
+ return { ...reading, total: reading.total + (reading.hasCurrent ? reading.current : 1) * word.value, current: 0, hasCurrent: false, lastPlace: word.value };
43
+ }
44
+ const group = reading.total + reading.current;
45
+ if (word.kind !== "scale" || word.value >= reading.lastScale || (group === 0 && !reading.hasCurrent)) return undefined;
46
+ return { ...START, done: reading.done + group * word.value, lastScale: word.value };
47
+ };
48
+
49
+ const CLOSES_GROUP: ReadonlySet<NumberWordKind> = new Set(["place", "scale"]);
50
+
51
+ /** Whether each joiner ("and") stands after a place or scale and before a digit: one hundred and five, not one and hundred. */
52
+ const joinersInside = (words: readonly NumberWord[]): boolean =>
53
+ words.every((word, index) => word.kind !== "joiner" || (CLOSES_GROUP.has(words[index - 1]?.kind ?? "joiner") && words[index + 1]?.kind === "digit"));
54
+
55
+ /**
56
+ * The value of a number written in words, read left to right: digits add, a place multiplies the digits before it (five
57
+ * hundred, 三千), a scale multiplies everything before it (fifty thousand, 参拾万). undefined when the words are not one
58
+ * well-formed number: empty, starting with a scale, a digit after a digit, places or scales out of order.
59
+ */
60
+ export const numberOfWords = (words: readonly NumberWord[]): number | undefined => {
61
+ if (words.length === 0 || words[0]?.kind === "scale" || !joinersInside(words)) return undefined;
62
+ const reading = words.filter((word) => word.kind !== "joiner").reduce<Reading | undefined>(stepWord, START);
63
+ return reading === undefined ? undefined : reading.done + reading.total + reading.current;
64
+ };
65
+
66
+ const FULLWIDTH_ZERO = 0xff10;
67
+ const halfWidth = (text: string): string =>
68
+ text
69
+ .replace(/[0-9]/gu, (char) => String(char.charCodeAt(0) - FULLWIDTH_ZERO))
70
+ .replace(/./gu, ".")
71
+ .replace(/,/gu, ",");
72
+
73
+ const FIGURE = /^(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?/u;
74
+
75
+ /** The longest of the words the text starts with, compared without regard to case. */
76
+ const leadingWord = (text: string, words: readonly string[]): string =>
77
+ words
78
+ .filter((word) => word !== "" && text.toLowerCase().startsWith(word.toLowerCase()))
79
+ .reduce((longest, word) => (word.length > longest.length ? word : longest), "");
80
+
81
+ /**
82
+ * The value of a figure in brackets: digits with separators, a currency mark before ($5,000) or after (300,000円), a word of
83
+ * scale ($5 million), a unit after (5%). undefined when the bracket holds anything else (Section 6, a name, a date).
84
+ */
85
+ export const figureValue = (content: string, vocabulary: NumberVocabulary): number | undefined => {
86
+ const trimmed = halfWidth(content).trim();
87
+ const afterMark = trimmed.slice(leadingWord(trimmed, vocabulary.marksBefore).length).trimStart();
88
+ const figure = FIGURE.exec(afterMark)?.[0];
89
+ if (figure === undefined) return undefined;
90
+ const rest = afterMark.slice(figure.length).trimStart();
91
+ const multiplier = leadingWord(
92
+ rest,
93
+ vocabulary.multipliers.map((entry) => entry.word),
94
+ );
95
+ const tail = rest.slice(multiplier.length).trimStart();
96
+ if (tail.slice(leadingWord(tail, vocabulary.marksAfter).length).trim() !== "") return undefined;
97
+ const scale = vocabulary.multipliers.find((entry) => entry.word === multiplier)?.value ?? 1;
98
+ return Number(figure.replace(/,/gu, "")) * scale;
99
+ };
100
+
101
+ const BRACKET = /[((]([^()()\n]{1,40})[))]/gu;
102
+ const SEPARATOR = " \t-";
103
+ const SPACE = " \t";
104
+ /** How far back spaces are skipped, and how many words one number in words may have (one million two hundred and five is six). */
105
+ const SKIP_REACH = 40;
106
+ const MAX_RUN_WORDS = 16;
107
+ const RUN_KINDS: ReadonlySet<NumberWordKind> = new Set(["digit", "place", "scale", "joiner"]);
108
+ const SCRIPTS = [/\p{Script=Han}/u, /\p{Script=Latin}/u, /\p{Script=Hiragana}/u, /\p{Script=Katakana}/u, /\p{Script=Cyrillic}/u, /\p{Script=Greek}/u];
109
+
110
+ /** Whether two letters are of one script: 統 before 一 makes one word (統一), は before 三 does not. */
111
+ const sameScript = (a: string, b: string): boolean => SCRIPTS.some((script) => script.test(a) && script.test(b));
112
+
113
+ /** The longest of the words the text ends with at `end`, compared without regard to case. */
114
+ const endingWord = <T extends { readonly word: string }>(text: string, end: number, words: readonly T[]): T | undefined =>
115
+ words
116
+ .filter((entry) => entry.word !== "" && text.slice(Math.max(0, end - entry.word.length), end).toLowerCase() === entry.word.toLowerCase())
117
+ .reduce<T | undefined>((longest, entry) => (longest === undefined || entry.word.length > longest.word.length ? entry : longest), undefined);
118
+
119
+ /** Where the run of `chars` (spaces, hyphens) that ends at `end` starts, looking back no further than SKIP_REACH. */
120
+ const skipBack = (text: string, end: number, chars: string): number => {
121
+ const window = text.slice(Math.max(0, end - SKIP_REACH), end).split("");
122
+ const lastOther = window.findLastIndex((char) => !chars.includes(char));
123
+ return end - (window.length - (lastOther + 1));
124
+ };
125
+
126
+ type Placed = { readonly word: NumberWord; readonly start: number };
127
+
128
+ /**
129
+ * The number words that end at `end`, read backwards: the first right at `end`, the others past spaces or hyphens. A run
130
+ * longer than any number in words is not one number, and gives none.
131
+ */
132
+ const placedBefore = (text: string, end: number, words: readonly NumberWord[], found: readonly Placed[] = []): readonly Placed[] => {
133
+ const from = found.length === 0 ? end : skipBack(text, end, SEPARATOR);
134
+ const word = endingWord(text, from, words);
135
+ if (word === undefined) return found;
136
+ if (found.length >= MAX_RUN_WORDS) return [];
137
+ const start = from - word.word.length;
138
+ return placedBefore(text, start, words, [{ word, start }, ...found]);
139
+ };
140
+
141
+ /** The run of number words before `end`, without the joiners it starts with ("and one" is "one"). */
142
+ const runBefore = (text: string, end: number, words: readonly NumberWord[]): readonly Placed[] => {
143
+ const placed = placedBefore(text, end, words);
144
+ const first = placed.findIndex((entry) => entry.word.kind !== "joiner");
145
+ return first < 0 ? [] : placed.slice(first);
146
+ };
147
+
148
+ /** Numerals written one character to a word and two or more in a row (契約期間十二) are a number even right after a word. */
149
+ const isSolidNumeral = (run: readonly Placed[]): boolean => run.length > 1 && run[0]?.word.word.length === 1;
150
+
151
+ /**
152
+ * Whether the run is a number of its own: the letter before it is of another script, it is a solid numeral, or a lead stands
153
+ * before it (金参, 年五). A single numeral after a word of its script is part of that word (統一, 唯一, often).
154
+ */
155
+ const startsWord = (text: string, run: readonly Placed[], vocabulary: NumberVocabulary): boolean => {
156
+ const start = run[0]?.start ?? 0;
157
+ const before = text.charAt(start - 1);
158
+ const leads = vocabulary.words.filter((word) => word.kind === "lead");
159
+ return before === "" || !sameScript(before, text.charAt(start)) || isSolidNumeral(run) || endingWord(text, start, leads) !== undefined;
160
+ };
161
+
162
+ const YEAR = /^\s*[12]\d{3}\s*$/u;
163
+ const YEAR_WORDS_BELOW = 1000;
164
+
165
+ /** A bare four-digit figure after a small number in words is a year in brackets ("two (2026)"), not the same number again. */
166
+ const isYear = (content: string, words: number): boolean => YEAR.test(halfWidth(content)) && words < YEAR_WORDS_BELOW;
167
+
168
+ /** Where the words before a bracket end: past the spaces and one unit or currency word ("Dollars", 円, percent). */
169
+ const wordsEnd = (text: string, bracket: number, vocabulary: NumberVocabulary): number => {
170
+ const spaced = skipBack(text, bracket, SPACE);
171
+ const unit = endingWord(
172
+ text,
173
+ spaced,
174
+ vocabulary.marksAfter.map((word) => ({ word })),
175
+ );
176
+ return unit === undefined ? spaced : skipBack(text, spaced - unit.word.length, SPACE);
177
+ };
178
+
179
+ const RELATIVE_TOLERANCE = 1e-9;
180
+ const differ = (a: number, b: number): boolean => Math.abs(a - b) > RELATIVE_TOLERANCE * Math.max(1, Math.abs(a), Math.abs(b));
181
+
182
+ const slipAt = (text: string, match: RegExpExecArray, vocabulary: NumberVocabulary, runWords: readonly NumberWord[]): WordFigureSlip | undefined => {
183
+ const content = match[1] ?? "";
184
+ const run = runBefore(text, wordsEnd(text, match.index, vocabulary), runWords);
185
+ const start = run[0]?.start;
186
+ if (start === undefined || !startsWord(text, run, vocabulary)) return undefined;
187
+ const words = numberOfWords(run.map((entry) => entry.word));
188
+ const figure = figureValue(content, vocabulary);
189
+ if (words === undefined || figure === undefined || !differ(words, figure) || isYear(content, words)) return undefined;
190
+ const end = match.index + match[0].length;
191
+ return { offset: start, end, written: text.slice(start, end), words, figure };
192
+ };
193
+
194
+ /** Every number written in words whose figure in brackets right after it says another number. */
195
+ export const wordFigureSlips = (text: string, vocabulary: NumberVocabulary): WordFigureSlip[] => {
196
+ const runWords = vocabulary.words.filter((word) => RUN_KINDS.has(word.kind));
197
+ if (runWords.length === 0) return [];
198
+ return [...text.matchAll(BRACKET)].flatMap((match) => slipAt(text, match, vocabulary, runWords) ?? []);
199
+ };
@@ -1,6 +1,7 @@
1
1
  import type { StructureNode } from "../plugin.ts";
2
2
  import { inDocumentOrder, type StructureIssue } from "./issues.ts";
3
3
  import { numbersQuotedInside } from "./quoted-number.ts";
4
+ import { isVersionHistory } from "./version-order.ts";
4
5
 
5
6
  const labelOf = (node: StructureNode): string => String(node.attrs["label"] ?? node.address);
6
7
 
@@ -43,11 +44,13 @@ const breaksIn = (sequence: readonly Ordered[]): StructureIssue[] =>
43
44
  * 文書全体の通し番号として比べると抜けに見える。最初の番号は見ない。日本語の項は 2 から番号を振る。
44
45
  * 1 に戻った番号は新しい並びの始まりとして扱うので、「(a) の後の (a)」の重なりは見逃す。
45
46
  * 同じ番号の節を中に持つ節(ほかの文書の条を引いた手本の見出し)は、並びに入れない。
47
+ * 変更履歴の版の見出し(## 3.1.0)は番号の並びではない。版の順番は version-order が見る。
46
48
  */
47
49
  export const numberingBreaks = (tree: StructureNode): StructureIssue[] => {
48
50
  const quoting = numbersQuotedInside(tree);
49
51
  return inDocumentOrder(tree)
50
52
  .flatMap((parent) => sequencesOf(parent, quoting))
53
+ .filter((sequence) => !isVersionHistory(sequence.map((ordered) => labelOf(ordered.node))))
51
54
  .flatMap(breaksIn)
52
55
  .toSorted((left, right) => left.offset - right.offset);
53
56
  };