chaffjs 0.33.0 → 0.35.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 (802) hide show
  1. package/dist/api.d.ts +7 -1
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js.map +1 -1
  4. package/dist/capitals-passage.d.ts +3 -0
  5. package/dist/capitals-passage.d.ts.map +1 -0
  6. package/dist/capitals-passage.js +26 -0
  7. package/dist/capitals-passage.js.map +1 -0
  8. package/dist/cli-text.d.ts.map +1 -1
  9. package/dist/cli-text.js +4 -2
  10. package/dist/cli-text.js.map +1 -1
  11. package/dist/coined-hyphen-name.d.ts +13 -0
  12. package/dist/coined-hyphen-name.d.ts.map +1 -0
  13. package/dist/coined-hyphen-name.js +21 -0
  14. package/dist/coined-hyphen-name.js.map +1 -0
  15. package/dist/commands/grade.d.ts.map +1 -1
  16. package/dist/commands/grade.js +66 -21
  17. package/dist/commands/grade.js.map +1 -1
  18. package/dist/company-kana-spelling.d.ts +6 -1
  19. package/dist/company-kana-spelling.d.ts.map +1 -1
  20. package/dist/company-kana-spelling.js +19 -2
  21. package/dist/company-kana-spelling.js.map +1 -1
  22. package/dist/company-name-ending.d.ts +7 -0
  23. package/dist/company-name-ending.d.ts.map +1 -0
  24. package/dist/company-name-ending.js +44 -0
  25. package/dist/company-name-ending.js.map +1 -0
  26. package/dist/company-names.d.ts +17 -4
  27. package/dist/company-names.d.ts.map +1 -1
  28. package/dist/company-names.js +49 -17
  29. package/dist/company-names.js.map +1 -1
  30. package/dist/custom/no-rewrite.d.ts +3 -0
  31. package/dist/custom/no-rewrite.d.ts.map +1 -0
  32. package/dist/custom/no-rewrite.js +3 -0
  33. package/dist/custom/no-rewrite.js.map +1 -0
  34. package/dist/custom/parse.d.ts.map +1 -1
  35. package/dist/custom/parse.js +14 -2
  36. package/dist/custom/parse.js.map +1 -1
  37. package/dist/detectors/acronym-context.d.ts +1 -1
  38. package/dist/detectors/acronym-context.d.ts.map +1 -1
  39. package/dist/detectors/acronym-context.js +4 -4
  40. package/dist/detectors/acronym-context.js.map +1 -1
  41. package/dist/detectors/acronym-definition.d.ts +13 -0
  42. package/dist/detectors/acronym-definition.d.ts.map +1 -0
  43. package/dist/detectors/acronym-definition.js +90 -0
  44. package/dist/detectors/acronym-definition.js.map +1 -0
  45. package/dist/detectors/acronym-lone.d.ts +13 -0
  46. package/dist/detectors/acronym-lone.d.ts.map +1 -0
  47. package/dist/detectors/acronym-lone.js +22 -0
  48. package/dist/detectors/acronym-lone.js.map +1 -0
  49. package/dist/detectors/acronym-name.d.ts +55 -0
  50. package/dist/detectors/acronym-name.d.ts.map +1 -0
  51. package/dist/detectors/acronym-name.js +75 -0
  52. package/dist/detectors/acronym-name.js.map +1 -0
  53. package/dist/detectors/age-words.d.ts +5 -0
  54. package/dist/detectors/age-words.d.ts.map +1 -0
  55. package/dist/detectors/age-words.js +8 -0
  56. package/dist/detectors/age-words.js.map +1 -0
  57. package/dist/detectors/annual-pay-mismatch.d.ts.map +1 -1
  58. package/dist/detectors/annual-pay-mismatch.js +2 -12
  59. package/dist/detectors/annual-pay-mismatch.js.map +1 -1
  60. package/dist/detectors/blank-structure.d.ts.map +1 -1
  61. package/dist/detectors/blank-structure.js +4 -3
  62. package/dist/detectors/blank-structure.js.map +1 -1
  63. package/dist/detectors/capitalised-term.d.ts +14 -2
  64. package/dist/detectors/capitalised-term.d.ts.map +1 -1
  65. package/dist/detectors/capitalised-term.js +115 -4
  66. package/dist/detectors/capitalised-term.js.map +1 -1
  67. package/dist/detectors/caps-caption.d.ts +11 -0
  68. package/dist/detectors/caps-caption.d.ts.map +1 -0
  69. package/dist/detectors/caps-caption.js +51 -0
  70. package/dist/detectors/caps-caption.js.map +1 -0
  71. package/dist/detectors/char-shape.d.ts.map +1 -1
  72. package/dist/detectors/char-shape.js +47 -18
  73. package/dist/detectors/char-shape.js.map +1 -1
  74. package/dist/detectors/clause-shape.d.ts +1 -1
  75. package/dist/detectors/clause-shape.d.ts.map +1 -1
  76. package/dist/detectors/clause-shape.js +9 -4
  77. package/dist/detectors/clause-shape.js.map +1 -1
  78. package/dist/detectors/closing-balance-mismatch.d.ts.map +1 -1
  79. package/dist/detectors/closing-balance-mismatch.js +1 -0
  80. package/dist/detectors/closing-balance-mismatch.js.map +1 -1
  81. package/dist/detectors/code-fences.d.ts +5 -0
  82. package/dist/detectors/code-fences.d.ts.map +1 -1
  83. package/dist/detectors/code-fences.js +9 -0
  84. package/dist/detectors/code-fences.js.map +1 -1
  85. package/dist/detectors/concrete-evidence.d.ts +13 -1
  86. package/dist/detectors/concrete-evidence.d.ts.map +1 -1
  87. package/dist/detectors/concrete-evidence.js +59 -0
  88. package/dist/detectors/concrete-evidence.js.map +1 -1
  89. package/dist/detectors/condition-toki.d.ts +16 -0
  90. package/dist/detectors/condition-toki.d.ts.map +1 -0
  91. package/dist/detectors/condition-toki.js +42 -0
  92. package/dist/detectors/condition-toki.js.map +1 -0
  93. package/dist/detectors/conjugated-entry.d.ts +17 -0
  94. package/dist/detectors/conjugated-entry.d.ts.map +1 -0
  95. package/dist/detectors/conjugated-entry.js +50 -0
  96. package/dist/detectors/conjugated-entry.js.map +1 -0
  97. package/dist/detectors/content-morphemes.d.ts +2 -0
  98. package/dist/detectors/content-morphemes.d.ts.map +1 -1
  99. package/dist/detectors/content-morphemes.js +1 -1
  100. package/dist/detectors/content-morphemes.js.map +1 -1
  101. package/dist/detectors/contraction-minority.d.ts +11 -0
  102. package/dist/detectors/contraction-minority.d.ts.map +1 -0
  103. package/dist/detectors/contraction-minority.js +10 -0
  104. package/dist/detectors/contraction-minority.js.map +1 -0
  105. package/dist/detectors/counter-edge.d.ts +5 -0
  106. package/dist/detectors/counter-edge.d.ts.map +1 -1
  107. package/dist/detectors/counter-edge.js +23 -0
  108. package/dist/detectors/counter-edge.js.map +1 -1
  109. package/dist/detectors/cross-facts.d.ts.map +1 -1
  110. package/dist/detectors/cross-facts.js +2 -1
  111. package/dist/detectors/cross-facts.js.map +1 -1
  112. package/dist/detectors/custom.d.ts.map +1 -1
  113. package/dist/detectors/custom.js +8 -2
  114. package/dist/detectors/custom.js.map +1 -1
  115. package/dist/detectors/date-any-year.d.ts +6 -3
  116. package/dist/detectors/date-any-year.d.ts.map +1 -1
  117. package/dist/detectors/date-any-year.js +47 -10
  118. package/dist/detectors/date-any-year.js.map +1 -1
  119. package/dist/detectors/date-heading-year.d.ts +18 -0
  120. package/dist/detectors/date-heading-year.d.ts.map +1 -0
  121. package/dist/detectors/date-heading-year.js +38 -0
  122. package/dist/detectors/date-heading-year.js.map +1 -0
  123. package/dist/detectors/date-year.d.ts +12 -2
  124. package/dist/detectors/date-year.d.ts.map +1 -1
  125. package/dist/detectors/date-year.js +31 -6
  126. package/dist/detectors/date-year.js.map +1 -1
  127. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  128. package/dist/detectors/defined-term-form.js +26 -5
  129. package/dist/detectors/defined-term-form.js.map +1 -1
  130. package/dist/detectors/document-shape.d.ts.map +1 -1
  131. package/dist/detectors/document-shape.js +6 -0
  132. package/dist/detectors/document-shape.js.map +1 -1
  133. package/dist/detectors/due-date.d.ts.map +1 -1
  134. package/dist/detectors/due-date.js +18 -2
  135. package/dist/detectors/due-date.js.map +1 -1
  136. package/dist/detectors/en-shape.d.ts.map +1 -1
  137. package/dist/detectors/en-shape.js +5 -1
  138. package/dist/detectors/en-shape.js.map +1 -1
  139. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  140. package/dist/detectors/fact-consistency.js +15 -15
  141. package/dist/detectors/fact-consistency.js.map +1 -1
  142. package/dist/detectors/form-line.d.ts +9 -0
  143. package/dist/detectors/form-line.d.ts.map +1 -0
  144. package/dist/detectors/form-line.js +36 -0
  145. package/dist/detectors/form-line.js.map +1 -0
  146. package/dist/detectors/formula-amount.d.ts.map +1 -1
  147. package/dist/detectors/formula-amount.js +2 -12
  148. package/dist/detectors/formula-amount.js.map +1 -1
  149. package/dist/detectors/gram-passages.d.ts +11 -0
  150. package/dist/detectors/gram-passages.d.ts.map +1 -0
  151. package/dist/detectors/gram-passages.js +26 -0
  152. package/dist/detectors/gram-passages.js.map +1 -0
  153. package/dist/detectors/heading-claim.d.ts +14 -0
  154. package/dist/detectors/heading-claim.d.ts.map +1 -0
  155. package/dist/detectors/heading-claim.js +49 -0
  156. package/dist/detectors/heading-claim.js.map +1 -0
  157. package/dist/detectors/heading-echo.d.ts.map +1 -1
  158. package/dist/detectors/heading-echo.js +29 -1
  159. package/dist/detectors/heading-echo.js.map +1 -1
  160. package/dist/detectors/heading-end-mark.d.ts +8 -3
  161. package/dist/detectors/heading-end-mark.d.ts.map +1 -1
  162. package/dist/detectors/heading-end-mark.js +18 -8
  163. package/dist/detectors/heading-end-mark.js.map +1 -1
  164. package/dist/detectors/heading-names.d.ts +7 -0
  165. package/dist/detectors/heading-names.d.ts.map +1 -0
  166. package/dist/detectors/heading-names.js +24 -0
  167. package/dist/detectors/heading-names.js.map +1 -0
  168. package/dist/detectors/heading-numbering.d.ts.map +1 -1
  169. package/dist/detectors/heading-numbering.js +7 -2
  170. package/dist/detectors/heading-numbering.js.map +1 -1
  171. package/dist/detectors/inch-mark.d.ts +10 -0
  172. package/dist/detectors/inch-mark.d.ts.map +1 -0
  173. package/dist/detectors/inch-mark.js +48 -0
  174. package/dist/detectors/inch-mark.js.map +1 -0
  175. package/dist/detectors/installment-total-mismatch.d.ts.map +1 -1
  176. package/dist/detectors/installment-total-mismatch.js +2 -12
  177. package/dist/detectors/installment-total-mismatch.js.map +1 -1
  178. package/dist/detectors/lexicon.d.ts +0 -1
  179. package/dist/detectors/lexicon.d.ts.map +1 -1
  180. package/dist/detectors/lexicon.js +29 -23
  181. package/dist/detectors/lexicon.js.map +1 -1
  182. package/dist/detectors/list-parallel.d.ts +5 -2
  183. package/dist/detectors/list-parallel.d.ts.map +1 -1
  184. package/dist/detectors/list-parallel.js +45 -7
  185. package/dist/detectors/list-parallel.js.map +1 -1
  186. package/dist/detectors/mark-shape.d.ts +6 -3
  187. package/dist/detectors/mark-shape.d.ts.map +1 -1
  188. package/dist/detectors/mark-shape.js +12 -6
  189. package/dist/detectors/mark-shape.js.map +1 -1
  190. package/dist/detectors/name-variant-apart.d.ts +27 -0
  191. package/dist/detectors/name-variant-apart.d.ts.map +1 -0
  192. package/dist/detectors/name-variant-apart.js +51 -0
  193. package/dist/detectors/name-variant-apart.js.map +1 -0
  194. package/dist/detectors/name-variant.d.ts.map +1 -1
  195. package/dist/detectors/name-variant.js +51 -17
  196. package/dist/detectors/name-variant.js.map +1 -1
  197. package/dist/detectors/number-unit.d.ts +10 -0
  198. package/dist/detectors/number-unit.d.ts.map +1 -1
  199. package/dist/detectors/number-unit.js +28 -8
  200. package/dist/detectors/number-unit.js.map +1 -1
  201. package/dist/detectors/numeral-word.d.ts +15 -0
  202. package/dist/detectors/numeral-word.d.ts.map +1 -0
  203. package/dist/detectors/numeral-word.js +26 -0
  204. package/dist/detectors/numeral-word.js.map +1 -0
  205. package/dist/detectors/organisation-run.d.ts +14 -0
  206. package/dist/detectors/organisation-run.d.ts.map +1 -0
  207. package/dist/detectors/organisation-run.js +73 -0
  208. package/dist/detectors/organisation-run.js.map +1 -0
  209. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  210. package/dist/detectors/orthographic-variant.js +13 -5
  211. package/dist/detectors/orthographic-variant.js.map +1 -1
  212. package/dist/detectors/orthography.d.ts.map +1 -1
  213. package/dist/detectors/orthography.js +16 -7
  214. package/dist/detectors/orthography.js.map +1 -1
  215. package/dist/detectors/outline-label.d.ts +14 -0
  216. package/dist/detectors/outline-label.d.ts.map +1 -0
  217. package/dist/detectors/outline-label.js +32 -0
  218. package/dist/detectors/outline-label.js.map +1 -0
  219. package/dist/detectors/page-marker.d.ts +6 -0
  220. package/dist/detectors/page-marker.d.ts.map +1 -0
  221. package/dist/detectors/page-marker.js +19 -0
  222. package/dist/detectors/page-marker.js.map +1 -0
  223. package/dist/detectors/parallel-definition.d.ts +16 -0
  224. package/dist/detectors/parallel-definition.d.ts.map +1 -0
  225. package/dist/detectors/parallel-definition.js +51 -0
  226. package/dist/detectors/parallel-definition.js.map +1 -0
  227. package/dist/detectors/per-unit-words.d.ts +7 -0
  228. package/dist/detectors/per-unit-words.d.ts.map +1 -0
  229. package/dist/detectors/per-unit-words.js +17 -0
  230. package/dist/detectors/per-unit-words.js.map +1 -0
  231. package/dist/detectors/period-multiple-mismatch.d.ts.map +1 -1
  232. package/dist/detectors/period-multiple-mismatch.js +2 -12
  233. package/dist/detectors/period-multiple-mismatch.js.map +1 -1
  234. package/dist/detectors/reference-number-variant.d.ts.map +1 -1
  235. package/dist/detectors/reference-number-variant.js +21 -3
  236. package/dist/detectors/reference-number-variant.js.map +1 -1
  237. package/dist/detectors/reference-text.d.ts.map +1 -1
  238. package/dist/detectors/reference-text.js +1 -0
  239. package/dist/detectors/reference-text.js.map +1 -1
  240. package/dist/detectors/registry/condition-toki.d.ts +3 -0
  241. package/dist/detectors/registry/condition-toki.d.ts.map +1 -0
  242. package/dist/detectors/registry/condition-toki.js +3 -0
  243. package/dist/detectors/registry/condition-toki.js.map +1 -0
  244. package/dist/detectors/registry/unfilled-placeholder.d.ts.map +1 -1
  245. package/dist/detectors/registry/unfilled-placeholder.js +2 -2
  246. package/dist/detectors/registry/unfilled-placeholder.js.map +1 -1
  247. package/dist/detectors/registry/vague-density.js +1 -1
  248. package/dist/detectors/registry/vague-density.js.map +1 -1
  249. package/dist/detectors/rent-multiple-mismatch.d.ts.map +1 -1
  250. package/dist/detectors/rent-multiple-mismatch.js +2 -12
  251. package/dist/detectors/rent-multiple-mismatch.js.map +1 -1
  252. package/dist/detectors/request-owner.d.ts +6 -2
  253. package/dist/detectors/request-owner.d.ts.map +1 -1
  254. package/dist/detectors/request-owner.js +57 -7
  255. package/dist/detectors/request-owner.js.map +1 -1
  256. package/dist/detectors/requirement-smell.d.ts.map +1 -1
  257. package/dist/detectors/requirement-smell.js +10 -2
  258. package/dist/detectors/requirement-smell.js.map +1 -1
  259. package/dist/detectors/row-sentence-amounts.d.ts.map +1 -1
  260. package/dist/detectors/row-sentence-amounts.js +5 -10
  261. package/dist/detectors/row-sentence-amounts.js.map +1 -1
  262. package/dist/detectors/sentence-length.d.ts.map +1 -1
  263. package/dist/detectors/sentence-length.js +24 -16
  264. package/dist/detectors/sentence-length.js.map +1 -1
  265. package/dist/detectors/sentence-rhythm.d.ts.map +1 -1
  266. package/dist/detectors/sentence-rhythm.js +6 -3
  267. package/dist/detectors/sentence-rhythm.js.map +1 -1
  268. package/dist/detectors/series-label.d.ts +2 -1
  269. package/dist/detectors/series-label.d.ts.map +1 -1
  270. package/dist/detectors/series-label.js +10 -4
  271. package/dist/detectors/series-label.js.map +1 -1
  272. package/dist/detectors/signals.d.ts +4 -0
  273. package/dist/detectors/signals.d.ts.map +1 -1
  274. package/dist/detectors/signals.js +95 -36
  275. package/dist/detectors/signals.js.map +1 -1
  276. package/dist/detectors/stated-amounts.d.ts +4 -0
  277. package/dist/detectors/stated-amounts.d.ts.map +1 -0
  278. package/dist/detectors/stated-amounts.js +12 -0
  279. package/dist/detectors/stated-amounts.js.map +1 -0
  280. package/dist/detectors/step-time-sum.d.ts.map +1 -1
  281. package/dist/detectors/step-time-sum.js +2 -1
  282. package/dist/detectors/step-time-sum.js.map +1 -1
  283. package/dist/detectors/structure-tree.d.ts.map +1 -1
  284. package/dist/detectors/structure-tree.js +11 -7
  285. package/dist/detectors/structure-tree.js.map +1 -1
  286. package/dist/detectors/team.d.ts.map +1 -1
  287. package/dist/detectors/team.js +10 -6
  288. package/dist/detectors/team.js.map +1 -1
  289. package/dist/detectors/template-sections.d.ts +14 -0
  290. package/dist/detectors/template-sections.d.ts.map +1 -0
  291. package/dist/detectors/template-sections.js +25 -0
  292. package/dist/detectors/template-sections.js.map +1 -0
  293. package/dist/detectors/time-order.d.ts.map +1 -1
  294. package/dist/detectors/time-order.js +17 -13
  295. package/dist/detectors/time-order.js.map +1 -1
  296. package/dist/detectors/titled-run.d.ts +22 -0
  297. package/dist/detectors/titled-run.d.ts.map +1 -0
  298. package/dist/detectors/titled-run.js +34 -0
  299. package/dist/detectors/titled-run.js.map +1 -0
  300. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
  301. package/dist/detectors/unbalanced-bracket.js +4 -0
  302. package/dist/detectors/unbalanced-bracket.js.map +1 -1
  303. package/dist/detectors/undefined-term.d.ts.map +1 -1
  304. package/dist/detectors/undefined-term.js +8 -0
  305. package/dist/detectors/undefined-term.js.map +1 -1
  306. package/dist/detectors/unfilled-placeholder.d.ts +4 -0
  307. package/dist/detectors/unfilled-placeholder.d.ts.map +1 -0
  308. package/dist/detectors/unfilled-placeholder.js +9 -0
  309. package/dist/detectors/unfilled-placeholder.js.map +1 -0
  310. package/dist/detectors/unknown-word.d.ts +4 -1
  311. package/dist/detectors/unknown-word.d.ts.map +1 -1
  312. package/dist/detectors/unknown-word.js +18 -2
  313. package/dist/detectors/unknown-word.js.map +1 -1
  314. package/dist/detectors/use-interval.d.ts +1 -0
  315. package/dist/detectors/use-interval.d.ts.map +1 -1
  316. package/dist/detectors/use-interval.js +15 -10
  317. package/dist/detectors/use-interval.js.map +1 -1
  318. package/dist/detectors/use-maximum.d.ts.map +1 -1
  319. package/dist/detectors/use-maximum.js +3 -1
  320. package/dist/detectors/use-maximum.js.map +1 -1
  321. package/dist/detectors/vague-density.d.ts +5 -0
  322. package/dist/detectors/vague-density.d.ts.map +1 -0
  323. package/dist/detectors/vague-density.js +52 -0
  324. package/dist/detectors/vague-density.js.map +1 -0
  325. package/dist/extension/document-view.d.ts +2 -2
  326. package/dist/extension/document-view.d.ts.map +1 -1
  327. package/dist/extension/document-view.js +17 -8
  328. package/dist/extension/document-view.js.map +1 -1
  329. package/dist/extension/entry-genres.d.ts +5 -0
  330. package/dist/extension/entry-genres.d.ts.map +1 -0
  331. package/dist/extension/entry-genres.js +13 -0
  332. package/dist/extension/entry-genres.js.map +1 -0
  333. package/dist/extension/module-detector.d.ts.map +1 -1
  334. package/dist/extension/module-detector.js +4 -4
  335. package/dist/extension/module-detector.js.map +1 -1
  336. package/dist/extension/plugin-parse.d.ts +1 -1
  337. package/dist/extension/plugin-parse.d.ts.map +1 -1
  338. package/dist/extension/plugin-parse.js +24 -7
  339. package/dist/extension/plugin-parse.js.map +1 -1
  340. package/dist/extension/problem-text.d.ts.map +1 -1
  341. package/dist/extension/problem-text.js +2 -0
  342. package/dist/extension/problem-text.js.map +1 -1
  343. package/dist/facts/age-values.d.ts.map +1 -1
  344. package/dist/facts/age-values.js +20 -2
  345. package/dist/facts/age-values.js.map +1 -1
  346. package/dist/facts/column-units.d.ts +31 -0
  347. package/dist/facts/column-units.d.ts.map +1 -0
  348. package/dist/facts/column-units.js +37 -0
  349. package/dist/facts/column-units.js.map +1 -0
  350. package/dist/facts/fact-scope.d.ts +10 -1
  351. package/dist/facts/fact-scope.d.ts.map +1 -1
  352. package/dist/facts/fact-scope.js +34 -3
  353. package/dist/facts/fact-scope.js.map +1 -1
  354. package/dist/facts/fact-values.d.ts +4 -0
  355. package/dist/facts/fact-values.d.ts.map +1 -1
  356. package/dist/facts/fact-values.js +3 -1
  357. package/dist/facts/fact-values.js.map +1 -1
  358. package/dist/facts/labelled-facts.d.ts +10 -0
  359. package/dist/facts/labelled-facts.d.ts.map +1 -1
  360. package/dist/facts/labelled-facts.js +6 -1
  361. package/dist/facts/labelled-facts.js.map +1 -1
  362. package/dist/facts/per-unit.d.ts +36 -0
  363. package/dist/facts/per-unit.d.ts.map +1 -0
  364. package/dist/facts/per-unit.js +56 -0
  365. package/dist/facts/per-unit.js.map +1 -0
  366. package/dist/facts/row-sentence-amounts.d.ts +3 -12
  367. package/dist/facts/row-sentence-amounts.d.ts.map +1 -1
  368. package/dist/facts/row-sentence-amounts.js +1 -15
  369. package/dist/facts/row-sentence-amounts.js.map +1 -1
  370. package/dist/facts/table-facts.d.ts +13 -3
  371. package/dist/facts/table-facts.d.ts.map +1 -1
  372. package/dist/facts/table-facts.js +35 -13
  373. package/dist/facts/table-facts.js.map +1 -1
  374. package/dist/facts/term-values.d.ts +13 -1
  375. package/dist/facts/term-values.d.ts.map +1 -1
  376. package/dist/facts/term-values.js +71 -12
  377. package/dist/facts/term-values.js.map +1 -1
  378. package/dist/grade/baseline.d.ts +4 -2
  379. package/dist/grade/baseline.d.ts.map +1 -1
  380. package/dist/grade/baseline.js +13 -11
  381. package/dist/grade/baseline.js.map +1 -1
  382. package/dist/grade/expect-read.d.ts +16 -0
  383. package/dist/grade/expect-read.d.ts.map +1 -0
  384. package/dist/grade/expect-read.js +52 -0
  385. package/dist/grade/expect-read.js.map +1 -0
  386. package/dist/grade/expect.d.ts +50 -0
  387. package/dist/grade/expect.d.ts.map +1 -0
  388. package/dist/grade/expect.js +53 -0
  389. package/dist/grade/expect.js.map +1 -0
  390. package/dist/grade/grade-item.d.ts +1 -1
  391. package/dist/grade/grade-item.d.ts.map +1 -1
  392. package/dist/grade/grade-item.js +13 -3
  393. package/dist/grade/grade-item.js.map +1 -1
  394. package/dist/grade/item.d.ts +9 -1
  395. package/dist/grade/item.d.ts.map +1 -1
  396. package/dist/grade/item.js +32 -7
  397. package/dist/grade/item.js.map +1 -1
  398. package/dist/grade/result.d.ts +5 -0
  399. package/dist/grade/result.d.ts.map +1 -1
  400. package/dist/grade/results-read.d.ts.map +1 -1
  401. package/dist/grade/results-read.js +4 -2
  402. package/dist/grade/results-read.js.map +1 -1
  403. package/dist/grade/rubric-file.d.ts +23 -0
  404. package/dist/grade/rubric-file.d.ts.map +1 -0
  405. package/dist/grade/rubric-file.js +35 -0
  406. package/dist/grade/rubric-file.js.map +1 -0
  407. package/dist/grade/rubric.d.ts +2 -0
  408. package/dist/grade/rubric.d.ts.map +1 -1
  409. package/dist/grade/rubric.js +75 -47
  410. package/dist/grade/rubric.js.map +1 -1
  411. package/dist/grade/setup.d.ts +2 -1
  412. package/dist/grade/setup.d.ts.map +1 -1
  413. package/dist/grade/setup.js +2 -2
  414. package/dist/grade/setup.js.map +1 -1
  415. package/dist/grade/stamp.d.ts +2 -0
  416. package/dist/grade/stamp.d.ts.map +1 -1
  417. package/dist/grade/stamp.js +8 -2
  418. package/dist/grade/stamp.js.map +1 -1
  419. package/dist/grade/task-rubric.d.ts +16 -0
  420. package/dist/grade/task-rubric.d.ts.map +1 -0
  421. package/dist/grade/task-rubric.js +34 -0
  422. package/dist/grade/task-rubric.js.map +1 -0
  423. package/dist/grade/text.d.ts +5 -1
  424. package/dist/grade/text.d.ts.map +1 -1
  425. package/dist/grade/text.js +16 -4
  426. package/dist/grade/text.js.map +1 -1
  427. package/dist/grade-api.d.ts +9 -2
  428. package/dist/grade-api.d.ts.map +1 -1
  429. package/dist/grade-api.js +31 -15
  430. package/dist/grade-api.js.map +1 -1
  431. package/dist/heading-numbering.d.ts +5 -2
  432. package/dist/heading-numbering.d.ts.map +1 -1
  433. package/dist/heading-numbering.js +27 -6
  434. package/dist/heading-numbering.js.map +1 -1
  435. package/dist/name-char-reading.d.ts +5 -0
  436. package/dist/name-char-reading.d.ts.map +1 -1
  437. package/dist/name-char-reading.js +15 -0
  438. package/dist/name-char-reading.js.map +1 -1
  439. package/dist/name-end-letter.d.ts +24 -0
  440. package/dist/name-end-letter.d.ts.map +1 -0
  441. package/dist/name-end-letter.js +45 -0
  442. package/dist/name-end-letter.js.map +1 -0
  443. package/dist/name-given-before.d.ts +15 -0
  444. package/dist/name-given-before.d.ts.map +1 -0
  445. package/dist/name-given-before.js +30 -0
  446. package/dist/name-given-before.js.map +1 -0
  447. package/dist/name-neighbours.d.ts.map +1 -1
  448. package/dist/name-neighbours.js +2 -1
  449. package/dist/name-neighbours.js.map +1 -1
  450. package/dist/name-separator.d.ts +6 -0
  451. package/dist/name-separator.d.ts.map +1 -1
  452. package/dist/name-separator.js +80 -0
  453. package/dist/name-separator.js.map +1 -1
  454. package/dist/name-variants.d.ts +8 -3
  455. package/dist/name-variants.d.ts.map +1 -1
  456. package/dist/name-variants.js +40 -12
  457. package/dist/name-variants.js.map +1 -1
  458. package/dist/name-word-order.d.ts +9 -5
  459. package/dist/name-word-order.d.ts.map +1 -1
  460. package/dist/name-word-order.js +47 -15
  461. package/dist/name-word-order.js.map +1 -1
  462. package/dist/nominal-stem.d.ts +13 -0
  463. package/dist/nominal-stem.d.ts.map +1 -0
  464. package/dist/nominal-stem.js +32 -0
  465. package/dist/nominal-stem.js.map +1 -0
  466. package/dist/number-name.d.ts.map +1 -1
  467. package/dist/number-name.js +11 -2
  468. package/dist/number-name.js.map +1 -1
  469. package/dist/profile/cue-lines.d.ts +6 -0
  470. package/dist/profile/cue-lines.d.ts.map +1 -0
  471. package/dist/profile/cue-lines.js +13 -0
  472. package/dist/profile/cue-lines.js.map +1 -0
  473. package/dist/profile/parse.d.ts +1 -1
  474. package/dist/profile/parse.d.ts.map +1 -1
  475. package/dist/profile/parse.js +3 -2
  476. package/dist/profile/parse.js.map +1 -1
  477. package/dist/reference-numbers.d.ts +2 -0
  478. package/dist/reference-numbers.d.ts.map +1 -1
  479. package/dist/reference-numbers.js +1 -1
  480. package/dist/reference-numbers.js.map +1 -1
  481. package/dist/sentence-load.d.ts +2 -1
  482. package/dist/sentence-load.d.ts.map +1 -1
  483. package/dist/sentence-load.js +6 -2
  484. package/dist/sentence-load.js.map +1 -1
  485. package/dist/spaced-person-name.d.ts.map +1 -1
  486. package/dist/spaced-person-name.js +26 -1
  487. package/dist/spaced-person-name.js.map +1 -1
  488. package/dist/spacing-code.d.ts.map +1 -1
  489. package/dist/spacing-code.js +10 -1
  490. package/dist/spacing-code.js.map +1 -1
  491. package/dist/spacing-minority.d.ts +7 -0
  492. package/dist/spacing-minority.d.ts.map +1 -1
  493. package/dist/spacing-minority.js +14 -0
  494. package/dist/spacing-minority.js.map +1 -1
  495. package/dist/structure/cited-document-section.d.ts +7 -0
  496. package/dist/structure/cited-document-section.d.ts.map +1 -0
  497. package/dist/structure/cited-document-section.js +33 -0
  498. package/dist/structure/cited-document-section.js.map +1 -0
  499. package/dist/structure/closing-balance.d.ts +9 -0
  500. package/dist/structure/closing-balance.d.ts.map +1 -1
  501. package/dist/structure/closing-balance.js +34 -7
  502. package/dist/structure/closing-balance.js.map +1 -1
  503. package/dist/structure/definition-use.d.ts.map +1 -1
  504. package/dist/structure/definition-use.js +20 -1
  505. package/dist/structure/definition-use.js.map +1 -1
  506. package/dist/structure/document-context.d.ts +2 -0
  507. package/dist/structure/document-context.d.ts.map +1 -0
  508. package/dist/structure/document-context.js +42 -0
  509. package/dist/structure/document-context.js.map +1 -0
  510. package/dist/structure/fenced-lines.d.ts +7 -0
  511. package/dist/structure/fenced-lines.d.ts.map +1 -0
  512. package/dist/structure/fenced-lines.js +27 -0
  513. package/dist/structure/fenced-lines.js.map +1 -0
  514. package/dist/structure/html-text-blocks.d.ts +8 -0
  515. package/dist/structure/html-text-blocks.d.ts.map +1 -0
  516. package/dist/structure/html-text-blocks.js +47 -0
  517. package/dist/structure/html-text-blocks.js.map +1 -0
  518. package/dist/structure/issues.d.ts +1 -1
  519. package/dist/structure/issues.d.ts.map +1 -1
  520. package/dist/structure/issues.js +19 -4
  521. package/dist/structure/issues.js.map +1 -1
  522. package/dist/structure/labelled-date-order.d.ts +34 -9
  523. package/dist/structure/labelled-date-order.d.ts.map +1 -1
  524. package/dist/structure/labelled-date-order.js +60 -15
  525. package/dist/structure/labelled-date-order.js.map +1 -1
  526. package/dist/structure/labelled-order.d.ts +10 -1
  527. package/dist/structure/labelled-order.d.ts.map +1 -1
  528. package/dist/structure/labelled-order.js +18 -6
  529. package/dist/structure/labelled-order.js.map +1 -1
  530. package/dist/structure/line-amount-label.d.ts.map +1 -1
  531. package/dist/structure/line-amount-label.js +2 -1
  532. package/dist/structure/line-amount-label.js.map +1 -1
  533. package/dist/structure/line-amount.d.ts +0 -5
  534. package/dist/structure/line-amount.d.ts.map +1 -1
  535. package/dist/structure/line-amount.js +1 -10
  536. package/dist/structure/line-amount.js.map +1 -1
  537. package/dist/structure/list-numbering.d.ts +20 -4
  538. package/dist/structure/list-numbering.d.ts.map +1 -1
  539. package/dist/structure/list-numbering.js +65 -9
  540. package/dist/structure/list-numbering.js.map +1 -1
  541. package/dist/structure/listed-paragraph.d.ts +16 -0
  542. package/dist/structure/listed-paragraph.d.ts.map +1 -0
  543. package/dist/structure/listed-paragraph.js +37 -0
  544. package/dist/structure/listed-paragraph.js.map +1 -0
  545. package/dist/structure/numbering.d.ts +3 -2
  546. package/dist/structure/numbering.d.ts.map +1 -1
  547. package/dist/structure/numbering.js +31 -6
  548. package/dist/structure/numbering.js.map +1 -1
  549. package/dist/structure/prose-total.d.ts +8 -0
  550. package/dist/structure/prose-total.d.ts.map +1 -1
  551. package/dist/structure/prose-total.js +70 -2
  552. package/dist/structure/prose-total.js.map +1 -1
  553. package/dist/structure/reference-text.d.ts +9 -1
  554. package/dist/structure/reference-text.d.ts.map +1 -1
  555. package/dist/structure/reference-text.js +21 -3
  556. package/dist/structure/reference-text.js.map +1 -1
  557. package/dist/structure/runs.d.ts.map +1 -1
  558. package/dist/structure/runs.js +9 -1
  559. package/dist/structure/runs.js.map +1 -1
  560. package/dist/structure/section-names.d.ts +12 -0
  561. package/dist/structure/section-names.d.ts.map +1 -0
  562. package/dist/structure/section-names.js +26 -0
  563. package/dist/structure/section-names.js.map +1 -0
  564. package/dist/structure/signed-date-line.d.ts +15 -0
  565. package/dist/structure/signed-date-line.d.ts.map +1 -0
  566. package/dist/structure/signed-date-line.js +68 -0
  567. package/dist/structure/signed-date-line.js.map +1 -0
  568. package/dist/structure/tax.d.ts.map +1 -1
  569. package/dist/structure/tax.js +5 -3
  570. package/dist/structure/tax.js.map +1 -1
  571. package/dist/structure/total-line.d.ts.map +1 -1
  572. package/dist/structure/total-line.js +10 -6
  573. package/dist/structure/total-line.js.map +1 -1
  574. package/dist/structure/total.d.ts +2 -0
  575. package/dist/structure/total.d.ts.map +1 -1
  576. package/dist/structure/total.js +34 -3
  577. package/dist/structure/total.js.map +1 -1
  578. package/dist/structure/versioned-label.d.ts +16 -0
  579. package/dist/structure/versioned-label.d.ts.map +1 -0
  580. package/dist/structure/versioned-label.js +48 -0
  581. package/dist/structure/versioned-label.js.map +1 -0
  582. package/dist/structure/written-headings.d.ts +31 -0
  583. package/dist/structure/written-headings.d.ts.map +1 -0
  584. package/dist/structure/written-headings.js +119 -0
  585. package/dist/structure/written-headings.js.map +1 -0
  586. package/dist/structure/written-resolve.d.ts +12 -0
  587. package/dist/structure/written-resolve.d.ts.map +1 -0
  588. package/dist/structure/written-resolve.js +49 -0
  589. package/dist/structure/written-resolve.js.map +1 -0
  590. package/dist/subject-codes.d.ts +21 -0
  591. package/dist/subject-codes.d.ts.map +1 -0
  592. package/dist/subject-codes.js +79 -0
  593. package/dist/subject-codes.js.map +1 -0
  594. package/dist/unlabelled-references.d.ts +6 -2
  595. package/dist/unlabelled-references.d.ts.map +1 -1
  596. package/dist/unlabelled-references.js +11 -10
  597. package/dist/unlabelled-references.js.map +1 -1
  598. package/genres.yaml +17 -0
  599. package/package.json +3 -3
  600. package/profiles/listing.yaml +1 -1
  601. package/rules/all-caps-shouting.yaml +2 -2
  602. package/rules/closing-balance-mismatch.yaml +3 -3
  603. package/rules/concrete-evidence-density.yaml +2 -2
  604. package/rules/contraction-consistency.yaml +13 -13
  605. package/rules/dangling-reference.yaml +2 -2
  606. package/rules/date-without-year.yaml +2 -2
  607. package/rules/defined-name-repeated.yaml +2 -2
  608. package/rules/due-before-issue.yaml +9 -5
  609. package/rules/fact-conflict.yaml +2 -2
  610. package/rules/heading-echo.yaml +2 -2
  611. package/rules/heading-end-punctuation-mix.yaml +2 -2
  612. package/rules/heading-numbering-mix.yaml +2 -2
  613. package/rules/internal-jargon.yaml +2 -2
  614. package/rules/latin-spacing.yaml +4 -4
  615. package/rules/list-item-form-mix.yaml +1 -1
  616. package/rules/max-kanji-continuous.yaml +5 -3
  617. package/rules/max-sentence-length.yaml +3 -2
  618. package/rules/name-variant.yaml +5 -2
  619. package/rules/ngram-repetition.yaml +2 -2
  620. package/rules/no-lead.yaml +2 -2
  621. package/rules/number-without-unit.yaml +2 -2
  622. package/rules/numbering-gap.yaml +2 -2
  623. package/rules/orthographic-variant.yaml +2 -2
  624. package/rules/reference-number-variant.yaml +3 -3
  625. package/rules/reference-title-mismatch.yaml +2 -2
  626. package/rules/repeated-sentence-ending.yaml +3 -2
  627. package/rules/request-without-deadline.yaml +2 -2
  628. package/rules/requirement-smell.yaml +2 -2
  629. package/rules/sentence-rhythm.yaml +2 -2
  630. package/rules/title-case-consistency.yaml +2 -2
  631. package/rules/toki-as-condition.yaml +71 -0
  632. package/rules/total-mismatch.yaml +4 -4
  633. package/rules/unbalanced-bracket.yaml +2 -2
  634. package/rules/undefined-acronym.yaml +11 -2
  635. package/rules/undefined-term.yaml +2 -2
  636. package/rules/unfilled-placeholder.yaml +2 -2
  637. package/rules/unknown-word.yaml +2 -2
  638. package/rules/use-before-definition.yaml +2 -2
  639. package/rules/vague-word-density.yaml +2 -2
  640. package/src/api.ts +11 -2
  641. package/src/capitals-passage.ts +31 -0
  642. package/src/cli-text.ts +4 -2
  643. package/src/coined-hyphen-name.ts +27 -0
  644. package/src/commands/grade.ts +75 -23
  645. package/src/company-kana-spelling.ts +22 -2
  646. package/src/company-name-ending.ts +50 -0
  647. package/src/company-names.ts +76 -20
  648. package/src/custom/no-rewrite.ts +2 -0
  649. package/src/custom/parse.ts +18 -2
  650. package/src/detectors/acronym-context.ts +5 -6
  651. package/src/detectors/acronym-definition.ts +123 -0
  652. package/src/detectors/acronym-lone.ts +26 -0
  653. package/src/detectors/acronym-name.ts +117 -0
  654. package/src/detectors/age-words.ts +12 -0
  655. package/src/detectors/annual-pay-mismatch.ts +3 -18
  656. package/src/detectors/blank-structure.ts +4 -3
  657. package/src/detectors/capitalised-term.ts +154 -4
  658. package/src/detectors/caps-caption.ts +61 -0
  659. package/src/detectors/char-shape.ts +74 -22
  660. package/src/detectors/clause-shape.ts +14 -4
  661. package/src/detectors/closing-balance-mismatch.ts +1 -0
  662. package/src/detectors/code-fences.ts +10 -0
  663. package/src/detectors/concrete-evidence.ts +77 -1
  664. package/src/detectors/condition-toki.ts +60 -0
  665. package/src/detectors/conjugated-entry.ts +53 -0
  666. package/src/detectors/content-morphemes.ts +2 -1
  667. package/src/detectors/contraction-minority.ts +11 -0
  668. package/src/detectors/counter-edge.ts +23 -0
  669. package/src/detectors/cross-facts.ts +2 -1
  670. package/src/detectors/custom.ts +9 -2
  671. package/src/detectors/date-any-year.ts +56 -10
  672. package/src/detectors/date-heading-year.ts +55 -0
  673. package/src/detectors/date-year.ts +54 -9
  674. package/src/detectors/defined-term-form.ts +26 -5
  675. package/src/detectors/document-shape.ts +8 -0
  676. package/src/detectors/due-date.ts +26 -7
  677. package/src/detectors/en-shape.ts +5 -1
  678. package/src/detectors/fact-consistency.ts +16 -19
  679. package/src/detectors/form-line.ts +47 -0
  680. package/src/detectors/formula-amount.ts +2 -18
  681. package/src/detectors/gram-passages.ts +36 -0
  682. package/src/detectors/heading-claim.ts +76 -0
  683. package/src/detectors/heading-echo.ts +32 -1
  684. package/src/detectors/heading-end-mark.ts +23 -10
  685. package/src/detectors/heading-names.ts +31 -0
  686. package/src/detectors/heading-numbering.ts +7 -2
  687. package/src/detectors/inch-mark.ts +49 -0
  688. package/src/detectors/installment-total-mismatch.ts +3 -18
  689. package/src/detectors/lexicon.ts +32 -21
  690. package/src/detectors/list-parallel.ts +46 -7
  691. package/src/detectors/mark-shape.ts +12 -6
  692. package/src/detectors/name-variant-apart.ts +63 -0
  693. package/src/detectors/name-variant.ts +73 -18
  694. package/src/detectors/number-unit.ts +35 -9
  695. package/src/detectors/numeral-word.ts +33 -0
  696. package/src/detectors/organisation-run.ts +86 -0
  697. package/src/detectors/orthographic-variant.ts +22 -6
  698. package/src/detectors/orthography.ts +17 -8
  699. package/src/detectors/outline-label.ts +48 -0
  700. package/src/detectors/page-marker.ts +26 -0
  701. package/src/detectors/parallel-definition.ts +64 -0
  702. package/src/detectors/per-unit-words.ts +24 -0
  703. package/src/detectors/period-multiple-mismatch.ts +2 -18
  704. package/src/detectors/reference-number-variant.ts +27 -5
  705. package/src/detectors/reference-text.ts +1 -0
  706. package/src/detectors/registry/condition-toki.ts +4 -0
  707. package/src/detectors/registry/unfilled-placeholder.ts +2 -2
  708. package/src/detectors/registry/vague-density.ts +1 -1
  709. package/src/detectors/rent-multiple-mismatch.ts +2 -18
  710. package/src/detectors/request-owner.ts +71 -8
  711. package/src/detectors/requirement-smell.ts +15 -2
  712. package/src/detectors/row-sentence-amounts.ts +5 -20
  713. package/src/detectors/sentence-length.ts +14 -6
  714. package/src/detectors/sentence-rhythm.ts +8 -4
  715. package/src/detectors/series-label.ts +13 -4
  716. package/src/detectors/signals.ts +94 -26
  717. package/src/detectors/stated-amounts.ts +20 -0
  718. package/src/detectors/step-time-sum.ts +2 -1
  719. package/src/detectors/structure-tree.ts +13 -8
  720. package/src/detectors/team.ts +13 -7
  721. package/src/detectors/template-sections.ts +37 -0
  722. package/src/detectors/time-order.ts +6 -3
  723. package/src/detectors/titled-run.ts +43 -0
  724. package/src/detectors/unbalanced-bracket.ts +3 -0
  725. package/src/detectors/undefined-term.ts +8 -0
  726. package/src/detectors/unfilled-placeholder.ts +10 -0
  727. package/src/detectors/unknown-word.ts +20 -2
  728. package/src/detectors/use-interval.ts +8 -4
  729. package/src/detectors/use-maximum.ts +3 -1
  730. package/src/detectors/vague-density.ts +68 -0
  731. package/src/extension/document-view.ts +18 -9
  732. package/src/extension/entry-genres.ts +15 -0
  733. package/src/extension/module-detector.ts +9 -4
  734. package/src/extension/plugin-parse.ts +29 -7
  735. package/src/extension/problem-text.ts +4 -0
  736. package/src/facts/age-values.ts +24 -2
  737. package/src/facts/column-units.ts +67 -0
  738. package/src/facts/fact-scope.ts +53 -4
  739. package/src/facts/fact-values.ts +11 -1
  740. package/src/facts/labelled-facts.ts +16 -2
  741. package/src/facts/per-unit.ts +105 -0
  742. package/src/facts/row-sentence-amounts.ts +4 -26
  743. package/src/facts/table-facts.ts +50 -10
  744. package/src/facts/term-values.ts +94 -13
  745. package/src/grade/baseline.ts +20 -12
  746. package/src/grade/expect-read.ts +65 -0
  747. package/src/grade/expect.ts +74 -0
  748. package/src/grade/grade-item.ts +14 -3
  749. package/src/grade/item.ts +48 -8
  750. package/src/grade/result.ts +5 -0
  751. package/src/grade/results-read.ts +7 -2
  752. package/src/grade/rubric-file.ts +46 -0
  753. package/src/grade/rubric.ts +77 -47
  754. package/src/grade/setup.ts +3 -3
  755. package/src/grade/stamp.ts +10 -2
  756. package/src/grade/task-rubric.ts +39 -0
  757. package/src/grade/text.ts +27 -5
  758. package/src/grade-api.ts +38 -16
  759. package/src/heading-numbering.ts +35 -8
  760. package/src/name-char-reading.ts +16 -0
  761. package/src/name-end-letter.ts +61 -0
  762. package/src/name-given-before.ts +40 -0
  763. package/src/name-neighbours.ts +2 -1
  764. package/src/name-separator.ts +93 -0
  765. package/src/name-variants.ts +69 -18
  766. package/src/name-word-order.ts +62 -17
  767. package/src/nominal-stem.ts +36 -0
  768. package/src/number-name.ts +12 -3
  769. package/src/profile/cue-lines.ts +14 -0
  770. package/src/profile/parse.ts +3 -2
  771. package/src/reference-numbers.ts +1 -1
  772. package/src/sentence-load.ts +7 -2
  773. package/src/spaced-person-name.ts +27 -2
  774. package/src/spacing-code.ts +13 -2
  775. package/src/spacing-minority.ts +17 -0
  776. package/src/structure/cited-document-section.ts +42 -0
  777. package/src/structure/closing-balance.ts +46 -8
  778. package/src/structure/definition-use.ts +24 -1
  779. package/src/structure/document-context.ts +46 -0
  780. package/src/structure/fenced-lines.ts +28 -0
  781. package/src/structure/html-text-blocks.ts +45 -0
  782. package/src/structure/issues.ts +19 -4
  783. package/src/structure/labelled-date-order.ts +108 -21
  784. package/src/structure/labelled-order.ts +33 -13
  785. package/src/structure/line-amount-label.ts +2 -1
  786. package/src/structure/line-amount.ts +1 -11
  787. package/src/structure/list-numbering.ts +100 -11
  788. package/src/structure/listed-paragraph.ts +45 -0
  789. package/src/structure/numbering.ts +48 -19
  790. package/src/structure/prose-total.ts +81 -2
  791. package/src/structure/reference-text.ts +25 -3
  792. package/src/structure/runs.ts +10 -1
  793. package/src/structure/section-names.ts +32 -0
  794. package/src/structure/signed-date-line.ts +78 -0
  795. package/src/structure/tax.ts +6 -3
  796. package/src/structure/total-line.ts +12 -6
  797. package/src/structure/total.ts +42 -3
  798. package/src/structure/versioned-label.ts +52 -0
  799. package/src/structure/written-headings.ts +137 -0
  800. package/src/structure/written-resolve.ts +57 -0
  801. package/src/subject-codes.ts +105 -0
  802. package/src/unlabelled-references.ts +24 -16
@@ -0,0 +1,105 @@
1
+ import type { FactValue } from "./fact-values.ts";
2
+ import { columnUnitAt, columnUnits, UNIT_PRICE, type HeadingUnitWords } from "./column-units.ts";
3
+
4
+ /**
5
+ * 値が何あたりか(1kmあたり15円、毎月5,000円、$0.45 per mile、日額5,000円)。単位が量(時間、日、月、km、mile。語彙表 rate-unit)の
6
+ * 値は、その量を掛けて金額になる単価なので、同じ単位あたりの値とだけ比べる。1kmあたり15円 と 表の 1,650円 は別の量。
7
+ * 件や回ごと(1件につき220円、for each transfer)は量ではない。手数料の表は 1件分 を印なしで書く(| 振込手数料 | 165円 |)ので、
8
+ * 何あたりとは読まず、これまでどおり比べる。決まった印(日額、/km、a day)は語彙表 per-unit-mark が単位まで言う。
9
+ * 型(*あたり、毎*、per *)は * に rate-unit の単位の語(日 は day)を入れた句だけを読む。型の position は値のどちら側に書くか。
10
+ */
11
+ export type PerUnitMark = { readonly pattern: string; readonly group: string };
12
+
13
+ export type PerUnitTemplate = { readonly pattern: string; readonly position: "before" | "after" };
14
+
15
+ export type PerUnitWords = {
16
+ /** 単位まで決まった印(日額、/km、a day)。group が単位。 */
17
+ readonly marks: readonly PerUnitMark[];
18
+ /** * が単位の語の型(*あたり、毎*、per *)。 */
19
+ readonly templates: readonly PerUnitTemplate[];
20
+ /** 量の単位の語と、それが数える単位(日 は day)。ここに無い語(件、回)は何あたりとは読まない。 */
21
+ readonly units: readonly PerUnitMark[];
22
+ /** 百分率の単位(%)。率の期間(年4.8%)は率の基準(rate-values)が見て、期間を書かない率とも比べるので、ここでは読まない。 */
23
+ readonly percentUnits: readonly string[];
24
+ /** 単価の列の見出し(単価、Unit price、時給)。その列の升は、見出しの単位あたりの値(column-units.ts)。 */
25
+ readonly priceHeadings: readonly { readonly pattern: string; readonly group?: string }[];
26
+ };
27
+
28
+ const PLACEHOLDER = "*";
29
+ /** 印を探す、値の前と後ろの字数。「日額」「1日あたり」が値の前の数字の前に書かれる。 */
30
+ const MARK_REACH = 24;
31
+ /** 値の前の型と値のあいだに置ける字(空白、読点。畳んだ後の字)。1kmあたり、15円。 */
32
+ const GAP_CHARS: ReadonlySet<string> = new Set([" ", "、", ","]);
33
+ const LETTER_OR_DIGIT = /[\p{L}\p{N}]/u;
34
+ const LETTER = /\p{L}/u;
35
+
36
+ const folded = (text: string): string => text.normalize("NFKC").toLowerCase().replace(/\s+/gu, " ");
37
+
38
+ const withoutGapAtEnd = (text: string): string => (GAP_CHARS.has(text.slice(-1)) ? withoutGapAtEnd(text.slice(0, -1)) : text);
39
+
40
+ /** 型の * に単位の語を入れた句と、その単位。* の無い型は単位を言わないので、句にならない。 */
41
+ type Phrase = { readonly text: string; readonly group: string; readonly unitFirst: boolean };
42
+
43
+ const phrasesOf = (template: PerUnitTemplate, units: readonly PerUnitMark[]): Phrase[] => {
44
+ const pattern = folded(template.pattern);
45
+ const at = pattern.indexOf(PLACEHOLDER);
46
+ if (at === -1) return [];
47
+ return units.map((unit) => ({ text: `${pattern.slice(0, at)}${folded(unit.pattern)}${pattern.slice(at + 1)}`, group: unit.group, unitFirst: at === 0 }));
48
+ };
49
+
50
+ /** 印がちょうど値の後ろに始まり、語の途中で切れていない(per mile は per milestone の頭ではない)。 */
51
+ const startsAfter = (after: string, text: string): boolean => after.startsWith(text) && !LETTER_OR_DIGIT.test(after.charAt(text.length));
52
+
53
+ /** 印がちょうど値の前で終わる。単位の語で始まる句は、前が字でない(1日につき の 日。利用日につき の 日 ではない)。 */
54
+ const endsBefore = (before: string, text: string, unitFirst: boolean): boolean =>
55
+ before.endsWith(text) && !(unitFirst && LETTER.test(before.charAt(before.length - text.length - 1)));
56
+
57
+ const longest = (groups: readonly { readonly length: number; readonly group: string }[]): string | undefined =>
58
+ groups.reduce<{ readonly length: number; readonly group: string } | undefined>(
59
+ (best, match) => (best === undefined || match.length > best.length ? match : best),
60
+ undefined,
61
+ )?.group;
62
+
63
+ /** 値のすぐ後ろ($100 a day、5,000円/日)かすぐ前(日額5,000円)の、決まった印の単位。 */
64
+ const markOf = (before: string, after: string, marks: readonly PerUnitMark[]): string | undefined =>
65
+ marks.find((mark) => startsAfter(after, folded(mark.pattern)))?.group ?? marks.find((mark) => before.endsWith(folded(mark.pattern)))?.group;
66
+
67
+ /** 値の前(1kmあたり15円、毎月5,000円)か後ろ($0.45 per mile)の型の単位。当たる句が二つあれば長いほう(か月 と 月)。 */
68
+ const templateOf = (before: string, after: string, words: PerUnitWords): string | undefined =>
69
+ longest(
70
+ words.templates.flatMap((template) =>
71
+ phrasesOf(template, words.units)
72
+ .filter((phrase) => (template.position === "before" ? endsBefore(before, phrase.text, phrase.unitFirst) : startsAfter(after, phrase.text)))
73
+ .map((phrase) => ({ length: phrase.text.length, group: phrase.group })),
74
+ ),
75
+ );
76
+
77
+ /** 値が何の量あたりか。量あたりでなければ(件ごと、印なし)undefined。 */
78
+ export const perUnitOf = (source: string, value: FactValue, words: PerUnitWords): string | undefined => {
79
+ const after = folded(source.slice(value.end, value.end + MARK_REACH)).trimStart();
80
+ const before = withoutGapAtEnd(folded(source.slice(Math.max(0, value.start - MARK_REACH), value.start)));
81
+ return markOf(before, after, words.marks) ?? templateOf(before, after, words);
82
+ };
83
+
84
+ /** 列の見出しを読む語: 単価の列の語と、見出しに書く何あたりの句(決まった印と、型に単位の語を入れた句)。 */
85
+ const headingWordsOf = (words: PerUnitWords): HeadingUnitWords => ({
86
+ headings: words.priceHeadings.map((heading) => ({ pattern: heading.pattern, group: heading.group ?? UNIT_PRICE })),
87
+ phrases: [...words.marks, ...words.templates.flatMap((template) => phrasesOf(template, words.units).map(({ text, group }) => ({ pattern: text, group })))],
88
+ });
89
+
90
+ /** 値の書き方と表の列から読む、何あたりか(per)と、表の升ならその列の見出しの単位(column)。 */
91
+ const unitsOf = (source: string, value: FactValue, words: PerUnitWords, column: string | undefined): Pick<FactValue, "per" | "column"> => {
92
+ const percent = words.percentUnits.some((unit) => folded(unit) === folded(value.unit));
93
+ if (value.kind !== "quantity" || percent) return {};
94
+ const per = perUnitOf(source, value, words);
95
+ return { ...(per === undefined ? {} : { per }), ...(column === undefined ? {} : { column }) };
96
+ };
97
+
98
+ /** 数量の値に、何あたりか(1kmあたり15円 の km)と、表の升ならその列の見出しの単位(単価の列)を付ける。 */
99
+ export const withPerUnits = <T extends FactValue>(source: string, values: readonly T[], words: PerUnitWords): T[] => {
100
+ const columns = columnUnits(source, headingWordsOf(words));
101
+ return values.map((value) => {
102
+ const units = unitsOf(source, value, words, columnUnitAt(columns, value));
103
+ return units.per === undefined && units.column === undefined ? value : { ...value, ...units };
104
+ });
105
+ };
@@ -5,18 +5,15 @@ import { withoutEdgeMarks } from "./trim-marks.ts";
5
5
  * 表の行の金額と、その行の見出しを主語に書いた文の金額(| 治療・救援費用 | 3,000万円 | と「治療・救援費用は、5,000万円を限度に」)。
6
6
  * 文は値の前後に言い回し(入院1日につき、を限度に、is paid at)を書くので、名前付きの値(labelled-facts)としては読めない。
7
7
  * 主語が行の見出しとちょうど同じで、同じ範囲にあり、行と文のどちらにも同じ通貨の金額がちょうど一つのときだけ比べる。
8
- * 二つ以上あれば、どれがどれに当たるか(日額と上限)は読まないと分からないので比べない。期間あたりの印(日額、a day)が両方に
9
- * あって期間が違えば(日額と月額)、別の値なので比べない。
8
+ * 二つ以上あれば、どれがどれに当たるか(日額と上限)は読まないと分からないので比べない。何あたりの金額(日額、1kmあたり)は、
9
+ * 同じ何あたりの金額とだけ比べる(fact-values の comparable)。日額と月額、1kmあたりの単価とそれを掛けた金額は別の値。
10
10
  */
11
- /** period: 金額の前後に書いた期間あたりの印の期間(日額 の day)。 */
12
- export type Amount = FactValue & { readonly period?: string };
11
+ export type Amount = FactValue;
13
12
 
14
13
  export type AmountRow = { readonly label: string; readonly scope: string; readonly amounts: readonly Amount[] };
15
14
 
16
15
  export type SubjectSentence = { readonly text: string; readonly scope: string; readonly amounts: readonly Amount[] };
17
16
 
18
- export type PeriodMark = { readonly pattern: string; readonly group: string };
19
-
20
17
  export type SubjectWords = {
21
18
  /** 主語と述べる部分の区切り(は、は、、is、are)。英字だけの区切りは、前が空白で後ろが語の切れ目のときだけ。 */
22
19
  readonly separators: readonly string[];
@@ -28,8 +25,6 @@ export type SubjectWords = {
28
25
 
29
26
  export type RowSentenceConflict = { readonly label: string; readonly value: FactValue; readonly other: FactValue };
30
27
 
31
- const SPACE = /^[ \t]?/u;
32
- const MARK_REACH = 16;
33
28
  const STRONG_MARK = /\*\*|__/gu;
34
29
  const LATIN_WORD = /^[a-z ]+$/iu;
35
30
  const LATIN_LETTER = /[a-z]/iu;
@@ -38,20 +33,6 @@ const ITEM_MARK = /^(?:[-*+]|\d{1,3}[.)])[ \t]+/u;
38
33
 
39
34
  const folded = (text: string): string => text.normalize("NFKC").toLowerCase().replace(/\s+/gu, " ");
40
35
 
41
- const markAt = (text: string, marks: readonly PeriodMark[]): string | undefined => {
42
- const lowered = folded(text);
43
- return marks.find((mark) => lowered.startsWith(folded(mark.pattern)))?.group;
44
- };
45
-
46
- const markBefore = (text: string, marks: readonly PeriodMark[]): string | undefined => {
47
- const lowered = folded(text).trimEnd();
48
- return marks.find((mark) => lowered.endsWith(folded(mark.pattern)))?.group;
49
- };
50
-
51
- /** 金額のすぐ前(日額5,000円)かすぐ後ろ($100 a day、5,000円/日)の期間あたりの印の期間。 */
52
- export const periodOf = (source: string, value: FactValue, marks: readonly PeriodMark[]): string | undefined =>
53
- markAt(source.slice(value.end).replace(SPACE, ""), marks) ?? markBefore(source.slice(Math.max(0, value.start - MARK_REACH), value.start), marks);
54
-
55
36
  const withoutDeterminer = (text: string, determiners: readonly string[]): string => {
56
37
  const word = determiners.map(folded).find((determiner) => LATIN_WORD.test(determiner) && text.startsWith(`${determiner} `));
57
38
  return word === undefined ? text : text.slice(word.length + 1);
@@ -87,13 +68,10 @@ const onlyPair = (row: AmountRow, sentence: SubjectSentence, value: Amount): Amo
87
68
  return inRow.length === 1 && inSentence.length === 1 ? inRow[0] : undefined;
88
69
  };
89
70
 
90
- /** 期間の違う金額(日額と月額)は別の値。片方にしか印が無ければ比べる(1日につき は語彙表に無い書き方)。 */
91
- const samePeriod = (left: Amount, right: Amount): boolean => left.period === undefined || right.period === undefined || left.period === right.period;
92
-
93
71
  const conflictsWith = (row: AmountRow, sentence: SubjectSentence): RowSentenceConflict[] =>
94
72
  sentence.amounts.flatMap((value) => {
95
73
  const other = onlyPair(row, sentence, value);
96
- return other === undefined || sameValue(other, value) || !samePeriod(other, value) ? [] : [{ label: row.label, value, other }];
74
+ return other === undefined || sameValue(other, value) ? [] : [{ label: row.label, value, other }];
97
75
  });
98
76
 
99
77
  const rowsByScope = (rows: readonly AmountRow[]): ReadonlyMap<string, AmountRow[]> =>
@@ -1,6 +1,7 @@
1
1
  import type { Span } from "../plugin.ts";
2
2
  import { linesOf, type Line } from "../structure/lines.ts";
3
3
  import { TABLE_RULE } from "../structure/runs.ts";
4
+ import { fencedLineIndexes } from "../structure/fenced-lines.ts";
4
5
  import { CELL_SEPARATOR } from "../structure/bare-numbers.ts";
5
6
  import type { FactValue } from "./fact-values.ts";
6
7
  import type { Fact } from "./labelled-facts.ts";
@@ -29,15 +30,17 @@ export const cellsOf = (line: Line): Cell[] => {
29
30
 
30
31
  const plain = withoutEdgeMarks;
31
32
 
32
- /** 区切り行(|---|)の前の行が見出し、後ろに続く | の行が本体。 */
33
- export const tablesOf = (lines: readonly Line[]): { header: Line; rows: Line[] }[] =>
34
- lines.flatMap((line, index) => {
33
+ /** 区切り行(|---|)の前の行が見出し、後ろに続く | の行が本体。コードブロックの中の表は例なので読まない。 */
34
+ export const tablesOf = (lines: readonly Line[]): { header: Line; rows: Line[] }[] => {
35
+ const fenced = fencedLineIndexes(lines.map((line) => line.text));
36
+ return lines.flatMap((line, index) => {
35
37
  const header = lines[index - 1];
36
- if (!TABLE_RULE.test(line.text) || header === undefined || !header.text.includes("|")) return [];
38
+ if (fenced.has(index) || !TABLE_RULE.test(line.text) || header === undefined || !header.text.includes("|")) return [];
37
39
  const after = lines.slice(index + 1);
38
40
  const end = after.findIndex((row) => !row.text.includes("|"));
39
41
  return [{ header, rows: end === -1 ? after : after.slice(0, end) }];
40
42
  });
43
+ };
41
44
 
42
45
  const inside = (cell: Span, value: FactValue): boolean => value.start >= cell.start && value.end <= cell.end;
43
46
 
@@ -64,18 +67,21 @@ const cellLabel = (rowLabel: string, column: string, headings: readonly string[]
64
67
  return headings.length > TWO_COLUMNS ? `${rowLabel} ${column}` : rowLabel;
65
68
  };
66
69
 
67
- /** 列が三つ以上の表の升は、行の見出し(row)と列の見出し(column)の二つで名前になる。 */
68
- export type TableFact = Fact & { readonly cell?: { readonly row: string; readonly column: string } };
70
+ /**
71
+ * 列が三つ以上の表の升は、行の見出し(row)と列の見出し(column)の二つで名前になる。
72
+ * columnGroup: 見出しの並びを繰り返す表(Day | Hours | Day | Hours の、第1週と第2週を横に並べた表)の、何番目の並びの升か。
73
+ */
74
+ export type TableFact = Fact & { readonly cell?: { readonly row: string; readonly column: string }; readonly columnGroup?: number };
69
75
 
70
76
  const rowFacts = (
71
- row: Line,
77
+ cells: readonly Cell[],
72
78
  headings: readonly string[],
73
79
  values: readonly FactValue[],
74
80
  source: string,
75
81
  totals?: TotalColumns,
76
82
  counts?: CountLabelWords,
77
83
  ): TableFact[] => {
78
- const [first, ...rest] = cellsOf(row);
84
+ const [first, ...rest] = cells;
79
85
  if (first === undefined) return [];
80
86
  const rowLabel = plain(first.text);
81
87
  const isCountHead = (value: FactValue): boolean => counts !== undefined && isCountLabelHead(source, first, value, counts);
@@ -91,11 +97,45 @@ const rowFacts = (
91
97
  });
92
98
  };
93
99
 
100
+ const MIN_GROUPS = 2;
101
+
102
+ /** 見出しが同じ並びを二度以上繰り返すなら、その並びの幅。並びごとに別の表として読む。 */
103
+ export const columnGroupWidth = (headings: readonly string[]): number | undefined => {
104
+ const keys = headings.map(keyOf);
105
+ const widths = Array.from({ length: Math.floor(keys.length / MIN_GROUPS) - 1 }, (_, index) => index + TWO_COLUMNS);
106
+ return widths.find((width) => keys.length % width === 0 && keys[0] !== "" && keys.every((key, index) => key === keys[index % width]));
107
+ };
108
+
109
+ const groupsOf = <T>(items: readonly T[], width: number | undefined): T[][] =>
110
+ width === undefined ? [[...items]] : Array.from({ length: Math.ceil(items.length / width) }, (_, index) => items.slice(index * width, (index + 1) * width));
111
+
112
+ /** columnGroups: 見出しを繰り返す表を、並びごとに読む(並びの升には columnGroup が付く)。 */
113
+ export type TableReading = { readonly columnGroups?: boolean };
114
+
115
+ type RowReading = { readonly values: readonly FactValue[]; readonly source: string; readonly totals?: TotalColumns; readonly counts?: CountLabelWords };
116
+
117
+ /** 一つの行の升の値。見出しを繰り返す表(width がある)は、並びごとに読んで columnGroup を付ける。 */
118
+ const groupedRowFacts = (row: Line, headings: readonly string[], width: number | undefined, at: RowReading): TableFact[] => {
119
+ const headingGroups = groupsOf(headings, width);
120
+ return groupsOf(cellsOf(row), width).flatMap((cells, group) => {
121
+ const facts = rowFacts(cells, headingGroups[group] ?? [], at.values, at.source, at.totals, at.counts);
122
+ return width === undefined ? facts : facts.map((fact) => ({ ...fact, columnGroup: group }));
123
+ });
124
+ };
125
+
94
126
  /** 文書の表すべての升の値。 */
95
- export const tableFacts = (source: string, values: readonly FactValue[], totals?: TotalColumns, counts?: CountLabelWords): TableFact[] =>
127
+ export const tableFacts = (
128
+ source: string,
129
+ values: readonly FactValue[],
130
+ totals?: TotalColumns,
131
+ counts?: CountLabelWords,
132
+ reading: TableReading = {},
133
+ ): TableFact[] =>
96
134
  tablesOf(linesOf(source)).flatMap((table) => {
97
135
  const headings = cellsOf(table.header).map((cell) => plain(cell.text));
98
- return table.rows.flatMap((row) => rowFacts(row, headings, values, source, totals, counts));
136
+ const width = reading.columnGroups === true ? columnGroupWidth(headings) : undefined;
137
+ const at: RowReading = { values, source, ...(totals === undefined ? {} : { totals }), ...(counts === undefined ? {} : { counts }) };
138
+ return table.rows.flatMap((row) => groupedRowFacts(row, headings, width, at));
99
139
  });
100
140
 
101
141
  /** 文書の表すべての、本体の行の升(見出しの行を除く)。text は書いたまま。 */
@@ -2,6 +2,7 @@ import { sameValue, type FactValue } from "./fact-values.ts";
2
2
  import type { Fact } from "./labelled-facts.ts";
3
3
  import type { TermWord } from "./document-terms.ts";
4
4
  import { withoutEdgeMarks } from "./trim-marks.ts";
5
+ import { qualifiedKeyOf, type QualifierWords } from "./qualified-labels.ts";
5
6
 
6
7
  /**
7
8
  * 文書全体で一つの値を持つ項目(保証期間、warranty period)を主語にした文の期間。名前付きの値の読み(labelled-facts)は、区切りの
@@ -24,6 +25,14 @@ export type TermValueWords = {
24
25
  /** 起算の句の印(から は値の前の句の終わり、from は値の後ろの句の頭)。 */
25
26
  readonly starts: readonly PlacedWord[];
26
27
  readonly valueEnds: readonly string[];
28
+ /** 名前のすぐ後ろで、その値を何に使ったかを言う句の頭(used for the)。後ろの句ごと落としても同じ項目。 */
29
+ readonly restating?: readonly string[];
30
+ /** 名前と値を囲む型(を*として)。* が値。型の値は、期間でなくても読む。 */
31
+ readonly frames?: readonly string[];
32
+ /** 文の値に条件を付ける語(場合、if)。型の前の句にあれば読まない。 */
33
+ readonly conditions?: readonly string[];
34
+ /** 名前に条件を付ける型(*の、for *)。 */
35
+ readonly qualifiers?: QualifierWords;
27
36
  };
28
37
 
29
38
  const folded = (text: string): string => text.normalize("NFKC").toLowerCase().replace(/\s+/gu, " ").trim();
@@ -73,12 +82,35 @@ const withoutSelf = (key: string, words: TermValueWords): string => {
73
82
  return (self.position === "before" ? key.slice(length) : key.slice(0, key.length - length)).trim();
74
83
  };
75
84
 
76
- /** 名前が語彙表の項目なら、その語の形。 */
77
- export const termKeyOf = (label: string, words: TermValueWords): string | undefined => {
85
+ /** 語彙表の項目の形。語彙表の語は条件の付いた名前の形(扶養親族の数 は 数 (扶養親族))なので、名前もその形にして比べる。 */
86
+ const termOf = (key: string, words: TermValueWords): string | undefined => {
87
+ const qualified = words.qualifiers === undefined ? key : qualifiedKeyOf(key, words.qualifiers);
88
+ return words.terms.map((word) => folded(word.pattern)).find((pattern) => pattern === key || pattern === qualified);
89
+ };
90
+
91
+ /** 何に使ったかを言う句から後ろを落とした名前(number of dependants used for the allowance の number of dependants)。 */
92
+ const withoutRestating = (key: string, words: TermValueWords): string | undefined =>
93
+ (words.restating ?? [])
94
+ .flatMap((word) => {
95
+ const mark = ` ${folded(word)}`;
96
+ const at = key.indexOf(mark);
97
+ const next = key.charAt(at + mark.length);
98
+ return at > 0 && (next === "" || next === " ") ? [key.slice(0, at)] : [];
99
+ })
100
+ .find((head) => termOf(head, words) !== undefined);
101
+
102
+ /** 名前が語彙表の項目なら、その語の形。restated: 何に使ったかを言う句を落として、項目になった。 */
103
+ const termKeyWith = (label: string, words: TermValueWords): { readonly key: string; readonly restated: boolean } | undefined => {
78
104
  const key = withoutSelf(withoutDeterminer(folded(withoutEdgeMarks(label)), words), words);
79
- return words.terms.map((word) => folded(word.pattern)).find((pattern) => pattern === key);
105
+ const term = termOf(key, words);
106
+ if (term !== undefined) return { key: term, restated: false };
107
+ const restated = withoutRestating(key, words);
108
+ return restated === undefined ? undefined : { key: restated, restated: true };
80
109
  };
81
110
 
111
+ /** 名前が語彙表の項目なら、その語の形。 */
112
+ export const termKeyOf = (label: string, words: TermValueWords): string | undefined => termKeyWith(label, words)?.key;
113
+
82
114
  type Span = { readonly start: number; readonly end: number };
83
115
 
84
116
  const valuesIn = (values: readonly FactValue[], span: Span): FactValue[] => values.filter((value) => span.start <= value.start && value.end <= span.end);
@@ -91,7 +123,7 @@ const separatorsIn = (text: string, separator: string): number[] =>
91
123
  .map((match) => match.index)
92
124
  .filter((index) => !isLatin(separator) || (text.charAt(index - 1) === " " && [" ", ""].includes(text.charAt(index + separator.length))));
93
125
 
94
- type Subject = { readonly key: string; readonly label: string; readonly lead: Span | undefined; readonly restStart: number };
126
+ type Subject = { readonly key: string; readonly label: string; readonly lead: Span | undefined; readonly restStart: number; readonly restated: boolean };
95
127
 
96
128
  /** 文の頭から区切りまでの主語。読点の前は条件の句。 */
97
129
  const subjectOf = (source: string, from: number, to: number, words: TermValueWords): Subject | undefined => {
@@ -101,9 +133,10 @@ const subjectOf = (source: string, from: number, to: number, words: TermValueWor
101
133
  const head = clause.slice(0, index);
102
134
  const comma = [...head.matchAll(CLAUSE_COMMAS)].at(-1)?.index;
103
135
  const label = withoutEdgeMarks(comma === undefined ? head : head.slice(comma + 1));
104
- const key = termKeyOf(label, words);
105
- if (key === undefined) continue;
106
- return { key, label, lead: comma === undefined ? undefined : { start: from, end: from + comma }, restStart: from + index + separator.length };
136
+ const term = termKeyWith(label, words);
137
+ if (term === undefined) continue;
138
+ const lead = comma === undefined ? undefined : { start: from, end: from + comma };
139
+ return { ...term, label, lead, restStart: from + index + separator.length };
107
140
  }
108
141
  }
109
142
  return undefined;
@@ -170,10 +203,10 @@ const isWorkedExample = (lead: Span, starts: readonly Span[], values: readonly F
170
203
  return starts.some((span) => valuesIn(values, span).some((value) => value.kind === "date" && sameValue(date, value)));
171
204
  };
172
205
 
173
- /** 主語と区切りの後ろの期間(保証期間は、お買い上げ日から24か月です)。 */
174
- const subjectFact = (source: string, value: FactValue, values: readonly FactValue[], words: TermValueWords): Fact | undefined => {
206
+ /** 主語と区切りの後ろの期間(保証期間は、お買い上げ日から24か月です)。restatedOnly: 何に使ったかを言う句の付いた主語だけ。 */
207
+ const subjectFact = (source: string, value: FactValue, values: readonly FactValue[], words: TermValueWords, restatedOnly = false): Fact | undefined => {
175
208
  const subject = subjectOf(source, clauseStartOf(source, value.start), value.start, words);
176
- if (subject === undefined) return undefined;
209
+ if (subject === undefined || (restatedOnly && !subject.restated)) return undefined;
177
210
  const before = startBeforeValue(source, { start: subject.restStart, end: value.start }, values, words);
178
211
  if (before === undefined) return undefined;
179
212
  const after = startAfterValue(source, value.end, values, words);
@@ -226,11 +259,59 @@ const unitNamedFact = (source: string, value: FactValue, words: TermValueWords):
226
259
 
227
260
  const DURATION_UNITS = new Set(["day", "week", "month", "year"]);
228
261
 
229
- /** 語彙表の項目を主語にした文の、期間の値。values は文書の中の順の値(日付を含む)。 */
262
+ /** 型の前と後ろの字(を*として の を と として)。 */
263
+ const frameParts = (frame: string): readonly [string, string] | undefined => {
264
+ const at = frame.indexOf("*");
265
+ return at <= 0 || at === frame.length - 1 ? undefined : [frame.slice(0, at), frame.slice(at + 1)];
266
+ };
267
+
268
+ /** 型の前の句(扶養控除は、)が、値も条件の語も含まないか。条件の句(登録された場合、)の後ろの値は、その場合の値。 */
269
+ const isPlainLead = (source: string, lead: Span, values: readonly FactValue[], words: TermValueWords): boolean => {
270
+ const written = folded(source.slice(lead.start, lead.end));
271
+ return valuesIn(values, lead).length === 0 && !(words.conditions ?? []).some((word) => written.includes(folded(word)));
272
+ };
273
+
274
+ /** 型の名前(扶養親族の数を2人として の 扶養親族の数)。名前は読点の後ろから。 */
275
+ const framedFact = (
276
+ source: string,
277
+ value: FactValue,
278
+ values: readonly FactValue[],
279
+ words: TermValueWords,
280
+ [open, close]: readonly [string, string],
281
+ ): Fact | undefined => {
282
+ const from = clauseStartOf(source, value.start);
283
+ const labelEnd = value.start - open.length;
284
+ if (labelEnd <= from || source.slice(labelEnd, value.start) !== open || !source.startsWith(close, value.end)) return undefined;
285
+ const head = source.slice(from, labelEnd);
286
+ const comma = [...head.matchAll(CLAUSE_COMMAS)].at(-1)?.index ?? -1;
287
+ const label = withoutEdgeMarks(head.slice(comma + 1));
288
+ const key = termKeyOf(label, words);
289
+ if (key === undefined || !isPlainLead(source, { start: from, end: from + Math.max(comma, 0) }, values, words)) return undefined;
290
+ return { label, key, value };
291
+ };
292
+
293
+ /** 名前と値を囲む型の値(扶養控除は、扶養親族の数を2人として計算しています)。 */
294
+ const frameFact = (source: string, value: FactValue, values: readonly FactValue[], words: TermValueWords): Fact | undefined =>
295
+ (words.frames ?? [])
296
+ .flatMap((frame) => {
297
+ const parts = frameParts(frame);
298
+ const fact = parts === undefined ? undefined : framedFact(source, value, values, words, parts);
299
+ return fact === undefined ? [] : [fact];
300
+ })
301
+ .at(0);
302
+
303
+ const durationFact = (source: string, value: FactValue, values: readonly FactValue[], words: TermValueWords): Fact | undefined =>
304
+ bracketFact(source, value, words) ?? subjectFact(source, value, values, words) ?? unitNamedFact(source, value, words);
305
+
306
+ /**
307
+ * 語彙表の項目を主語にした文の、期間の値。期間でない数は、何に使ったかを言う句の付いた主語(the number of dependants used for the
308
+ * allowance is 2)か、名前と値を囲む型(扶養親族の数を2人として)のときだけ。values は文書の中の順の値(日付を含む)。
309
+ */
230
310
  export const termValues = (source: string, values: readonly FactValue[], words: TermValueWords): Fact[] =>
231
311
  values
232
- .filter((value) => value.kind === "quantity" && DURATION_UNITS.has(value.unit))
312
+ .filter((value) => value.kind === "quantity")
233
313
  .flatMap((value) => {
234
- const fact = bracketFact(source, value, words) ?? subjectFact(source, value, values, words) ?? unitNamedFact(source, value, words);
314
+ const read = DURATION_UNITS.has(value.unit) ? durationFact(source, value, values, words) : subjectFact(source, value, values, words, true);
315
+ const fact = read ?? frameFact(source, value, values, words);
235
316
  return fact === undefined ? [] : [fact];
236
317
  });
@@ -60,13 +60,22 @@ type Pair = { readonly before: GradeResult; readonly after: GradeResult };
60
60
 
61
61
  const countIn = (result: GradeResult, rule: string): number => result.findings.filter((finding) => finding.rule === rule).length;
62
62
 
63
- const movementsOf = (pairs: readonly Pair[], rubricRules: ReadonlySet<string>): RuleMovement[] =>
63
+ /** The rules the rubric names for one output: with rubric tasks, its task's rules over the top level's. */
64
+ export type RubricRulesOf = (result: GradeResult) => ReadonlySet<string>;
65
+
66
+ /** A rule's movement, and the outputs it rose in whose own rubric names it: only those are a regression. */
67
+ type Moved = { readonly movement: RuleMovement; readonly regressedIn: readonly string[] };
68
+
69
+ const movementsOf = (pairs: readonly Pair[], rubricRulesOf: RubricRulesOf): Moved[] =>
64
70
  rateRows([pairs.map((pair) => pair.before), pairs.map((pair) => pair.after)]).flatMap(({ rule, unit, rates: [before = 0, after = 0] }) => {
65
71
  const inUnit = pairs.filter((pair) => pair.after.size.unit === unit);
66
- const increasedIn = inUnit.filter((pair) => countIn(pair.after, rule) > countIn(pair.before, rule)).map((pair) => resultName(pair.after));
72
+ const increased = inUnit.filter((pair) => countIn(pair.after, rule) > countIn(pair.before, rule));
73
+ const increasedIn = increased.map((pair) => resultName(pair.after));
67
74
  const decreasedIn = inUnit.filter((pair) => countIn(pair.after, rule) < countIn(pair.before, rule)).map((pair) => resultName(pair.after));
68
75
  if (increasedIn.length === 0 && decreasedIn.length === 0 && before === after) return [];
69
- return [{ rule, unit, before, after, increasedIn, decreasedIn, inRubric: rubricRules.has(rule) }];
76
+ const graded = (pair: Pair): boolean => rubricRulesOf(pair.after).has(rule);
77
+ const regressedIn = increased.filter(graded).map((pair) => resultName(pair.after));
78
+ return [{ movement: { rule, unit, before, after, increasedIn, decreasedIn, inRubric: inUnit.some(graded) }, regressedIn }];
70
79
  });
71
80
 
72
81
  const factKey = (fact: GradeFact): string => `${fact.kind}\n${fact.key}`;
@@ -100,11 +109,9 @@ const penaltyOf = (results: readonly GradeResult[]): number => results.reduce((s
100
109
 
101
110
  const scored = (pairs: readonly Pair[]): boolean => pairs.some((pair) => pair.after.score !== undefined);
102
111
 
103
- const regressionsOf = (newlyFailed: readonly string[], movements: readonly RuleMovement[], penalty: Comparison["penalty"]): string[] => [
112
+ const regressionsOf = (newlyFailed: readonly string[], moved: readonly Moved[], penalty: Comparison["penalty"]): string[] => [
104
113
  ...newlyFailed.map((id) => `${id}: passed, now fails`),
105
- ...movements
106
- .filter((movement) => movement.inRubric && movement.increasedIn.length > 0)
107
- .map((movement) => `rules.${movement.rule}: more findings in ${movement.increasedIn.join(", ")}`),
114
+ ...moved.filter((entry) => entry.regressedIn.length > 0).map((entry) => `rules.${entry.movement.rule}: more findings in ${entry.regressedIn.join(", ")}`),
108
115
  ...(penalty !== undefined && penalty.after > penalty.before ? [`score.penalty ${String(penalty.before)} → ${String(penalty.after)}`] : []),
109
116
  ];
110
117
 
@@ -112,9 +119,10 @@ const pairRead = (pair: Pair): boolean => sameReading([pair.before, pair.after])
112
119
 
113
120
  /**
114
121
  * `after` compared with `before`, output by output: an output is paired with the earlier one of its id and variant.
115
- * `rubricRules`: the rules the rubric names, whose increase is a regression.
122
+ * `rubricRules`: the rules the rubric names, whose increase is a regression; per output when the rubric has tasks.
116
123
  */
117
- export const compareRuns = (before: readonly GradeResult[], after: readonly GradeResult[], rubricRules: ReadonlySet<string>): Comparison => {
124
+ export const compareRuns = (before: readonly GradeResult[], after: readonly GradeResult[], rubricRules: ReadonlySet<string> | RubricRulesOf): Comparison => {
125
+ const rubricRulesOf: RubricRulesOf = typeof rubricRules === "function" ? rubricRules : () => rubricRules;
118
126
  const earlier = new Map(before.map((result) => [resultKey(result), result]));
119
127
  const keys = new Set(after.map(resultKey));
120
128
  const matched = after.flatMap((result) => {
@@ -122,7 +130,7 @@ export const compareRuns = (before: readonly GradeResult[], after: readonly Grad
122
130
  return match === undefined ? [] : [{ before: match, after: result }];
123
131
  });
124
132
  const pairs = matched.filter(pairRead);
125
- const rules = movementsOf(pairs, rubricRules);
133
+ const moved = movementsOf(pairs, rubricRulesOf);
126
134
  const newlyFailed = pairs.filter((pair) => pair.before.pass && !pair.after.pass).map((pair) => resultName(pair.after));
127
135
  const penalty = scored(pairs) ? { before: penaltyOf(pairs.map((pair) => pair.before)), after: penaltyOf(pairs.map((pair) => pair.after)) } : undefined;
128
136
  return {
@@ -130,11 +138,11 @@ export const compareRuns = (before: readonly GradeResult[], after: readonly Grad
130
138
  onlyBefore: before.filter((result) => !keys.has(resultKey(result))).map(resultName),
131
139
  onlyAfter: after.filter((result) => !earlier.has(resultKey(result))).map(resultName),
132
140
  readOtherwise: matched.filter((pair) => !pairRead(pair)).map((pair) => resultName(pair.after)),
133
- rules,
141
+ rules: moved.map((entry) => entry.movement),
134
142
  newlyFailed,
135
143
  newlyPassed: pairs.filter((pair) => !pair.before.pass && pair.after.pass).map((pair) => resultName(pair.after)),
136
144
  items: pairs.map(itemChange).filter((change) => change.dropped.length + change.added.length + change.citations.length > 0),
137
145
  ...(penalty === undefined ? {} : { penalty }),
138
- regressions: regressionsOf(newlyFailed, rules, penalty),
146
+ regressions: regressionsOf(newlyFailed, moved, penalty),
139
147
  };
140
148
  };
@@ -0,0 +1,65 @@
1
+ import { documentLanguage } from "../check-source.ts";
2
+ import { factsOf } from "../commands/compare.ts";
3
+ import { documentFromSource } from "../commands/read-document.ts";
4
+ import type { Compared } from "../compare/outcome.ts";
5
+ import { resolveGenre } from "../resolve-genre.ts";
6
+ import { OUTPUT_PATH, type ItemReading } from "./checks.ts";
7
+ import { EXPECT_LISTS, entryPath, expectAgainst, factOfEntry, type GradeExpect, type GradeExpectResult, type ReadEntry } from "./expect.ts";
8
+ import type { GradeItem, ItemProblem } from "./item.ts";
9
+
10
+ // An item's `expect` entries read as compare reads a document, in the output's language and genre, so an entry and
11
+ // the output spell one fact alike.
12
+
13
+ const ENTRY_PATH = "expect.md";
14
+
15
+ type EntryRead = { readonly entry: ReadEntry } | { readonly problem: Omit<ItemProblem, "line"> };
16
+
17
+ const readEntry = async (list: ReadEntry["list"], index: number, entry: string, reading: ItemReading & { readonly language: string }): Promise<EntryRead> => {
18
+ const prose = await documentFromSource(ENTRY_PATH, entry, { language: reading.language, genre: reading.genre }, reading.config, true);
19
+ const facts = factsOf(ENTRY_PATH, prose, reading.config.names ?? []);
20
+ const found = factOfEntry(entry, facts.extraction.atoms);
21
+ if ("unread" in found)
22
+ return { problem: { kind: found.unread === "no-fact" ? "expect-no-fact" : "expect-several-facts", detail: `${entryPath(list, index)} ${entry}` } };
23
+ return { entry: { list, index, entry, read: { path: ENTRY_PATH, extraction: { ...facts.extraction, atoms: [found.fact] } } } };
24
+ };
25
+
26
+ const readEntries = (expect: GradeExpect, reading: ItemReading & { readonly language: string }): Promise<EntryRead[]> =>
27
+ Promise.all(EXPECT_LISTS.flatMap((list) => expect[list].map((entry, index) => readEntry(list, index, entry, reading))));
28
+
29
+ /** The output's own facts, read as `chaff compare` reads the document after. */
30
+ const outputFacts = async (output: string, reading: ItemReading & { readonly language: string }): Promise<Compared> => {
31
+ const prose = await documentFromSource(OUTPUT_PATH, output, { language: reading.language, genre: reading.genre }, reading.config, true);
32
+ return factsOf(OUTPUT_PATH, prose, reading.config.names ?? []);
33
+ };
34
+
35
+ /** The language and genre the output is graded in, as checkSource chooses them. */
36
+ const itemReading = (item: GradeItem, setup: { readonly config: ItemReading["config"]; readonly genre?: string | undefined }) => ({
37
+ config: setup.config,
38
+ language: item.language ?? documentLanguage(OUTPUT_PATH, item.output, setup.config),
39
+ genre: resolveGenre(OUTPUT_PATH, item.output, setup.config, item.genre ?? setup.genre).genre,
40
+ });
41
+
42
+ /** Each entry chaff cannot read as exactly one fact, on the item's line: the run stops before grading (exit 2). */
43
+ export const expectProblems = async (
44
+ item: GradeItem,
45
+ line: number,
46
+ setup: { readonly config: ItemReading["config"]; readonly genre?: string | undefined },
47
+ ): Promise<ItemProblem[]> => {
48
+ if (item.expect === undefined) return [];
49
+ const read = await readEntries(item.expect, itemReading(item, setup));
50
+ return read.flatMap((entry) => ("problem" in entry ? [{ ...entry.problem, line }] : []));
51
+ };
52
+
53
+ /**
54
+ * The output against the item's expect, read in the language and genre it was graded in. Throws for an entry that is
55
+ * not one fact: `chaff grade` refuses such an item before grading (expectProblems), so none reaches here.
56
+ */
57
+ export const expectOfItem = async (item: GradeItem, reading: ItemReading & { readonly language: string }): Promise<GradeExpectResult | undefined> => {
58
+ if (item.expect === undefined) return undefined;
59
+ const read = await readEntries(item.expect, reading);
60
+ const entries = read.flatMap((entry) => {
61
+ if ("problem" in entry) throw new Error(`${item.id}: ${entry.problem.detail ?? ""} is not one fact`);
62
+ return [entry.entry];
63
+ });
64
+ return expectAgainst(entries, await outputFacts(item.output, reading));
65
+ };