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
@@ -4,31 +4,120 @@ import type { Span } from "../plugin.ts";
4
4
  import type { StructureIssue } from "./issues.ts";
5
5
 
6
6
  const ITEM_NUMBER = /^(?<number>\d{1,9})(?<delimiter>[.)])[ \t]/u;
7
+ const TAB_WIDTH = 4;
7
8
 
8
- /** One item's written number: where the item starts, the number and the number as written (「4.」). */
9
- export type WrittenNumber = { readonly offset: number; readonly number: number; readonly label: string };
9
+ /** One item's written number: where the item starts and ends, its column, the number and the number as written (「4.」). */
10
+ export type WrittenNumber = {
11
+ readonly offset: number;
12
+ readonly number: number;
13
+ readonly label: string;
14
+ readonly indent?: number;
15
+ readonly end?: number;
16
+ };
17
+
18
+ /** The column an offset sits at, a tab counted to the next stop of four as CommonMark counts it. */
19
+ const columnAt = (source: string, offset: number): number =>
20
+ Array.from(source.slice(source.lastIndexOf("\n", offset - 1) + 1, offset)).reduce(
21
+ (column, char) => (char === "\t" ? column + TAB_WIDTH - (column % TAB_WIDTH) : column + 1),
22
+ 0,
23
+ );
24
+
25
+ const numberAt = (source: string, span: Span): { number: number; label: string } | undefined => {
26
+ const found = ITEM_NUMBER.exec(source.slice(span.start, span.end))?.groups;
27
+ return found === undefined ? undefined : { number: Number(found["number"]), label: `${found["number"] ?? ""}${found["delimiter"] ?? ""}` };
28
+ };
10
29
 
11
30
  /** The number written at the start of each item, or undefined when an item has none (a bulleted list). */
12
31
  export const writtenNumbers = (source: string, itemSpans: readonly Span[]): WrittenNumber[] | undefined => {
13
32
  const numbers = itemSpans.map((span) => {
14
- const found = ITEM_NUMBER.exec(source.slice(span.start, span.end))?.groups;
15
- return found === undefined
16
- ? undefined
17
- : { offset: span.start, number: Number(found["number"]), label: `${found["number"] ?? ""}${found["delimiter"] ?? ""}` };
33
+ const found = numberAt(source, span);
34
+ return found === undefined ? undefined : { offset: span.start, end: span.end, ...found, indent: columnAt(source, span.start) };
18
35
  });
19
36
  return numbers.every((entry) => entry !== undefined) ? numbers : undefined;
20
37
  };
21
38
 
39
+ /** The last number of an ordered list nested in an item, if there is one. */
40
+ export type NestedLast = (item: WrittenNumber) => number | undefined;
41
+
42
+ type OrderedList = { readonly start: number; readonly end: number; readonly last: number };
43
+
44
+ const orderedListOf = (source: string, spans: readonly Span[]): OrderedList[] => {
45
+ const first = spans[0];
46
+ const last = writtenNumbers(source, spans)?.at(-1);
47
+ return first === undefined || last === undefined ? [] : [{ start: first.start, end: last.end ?? last.offset, last: last.number }];
48
+ };
49
+
50
+ /**
51
+ * For an item, the last number of the ordered list inside it that ends last (the outermost one, when lists nested in
52
+ * each other end together). lists are the item spans of every list in the document; bulleted lists are left out.
53
+ */
54
+ export const nestedLastFinder = (source: string, lists: readonly (readonly Span[])[]): NestedLast => {
55
+ const ordered = lists.flatMap((spans) => orderedListOf(source, spans));
56
+ return (item) =>
57
+ ordered
58
+ .filter((list) => list.start > item.offset && list.end <= (item.end ?? item.offset))
59
+ .reduce<OrderedList | undefined>(
60
+ (best, list) => (best === undefined || list.end > best.end || (list.end === best.end && list.start < best.start) ? list : best),
61
+ undefined,
62
+ )?.last;
63
+ };
64
+
65
+ type Compared = { readonly item: WrittenNumber; readonly previous: WrittenNumber | undefined };
66
+
67
+ const indentOf = (item: WrittenNumber): number => item.indent ?? 0;
68
+
22
69
  /**
23
- * Each item whose number is not one more than the item before it. A list that writes one number on every item (「1.」 on
24
- * each, which Markdown counts up) is numbered by the renderer, not by the writer, and is not read. An item numbered 1
70
+ * Which item each item's number follows. An item at the same indentation follows the last one there. An item indented
71
+ * deeper starts a nested count (CommonMark can still put it in the same list, when the indentation falls short of the
72
+ * parent's text), unless it carries on the count above it: the parent's number plus one (a slip of indentation), or
73
+ * one past the last number of the list nested in the parent (that list, carried on at a different indentation).
74
+ */
75
+ const comparedPairs = (items: readonly WrittenNumber[], nestedLast: NestedLast): Compared[] => {
76
+ const open: WrittenNumber[] = [];
77
+ return items.map((item) => {
78
+ const popped: WrittenNumber[] = [];
79
+ for (let top = open.at(-1); top !== undefined && indentOf(top) > indentOf(item); top = open.at(-1)) {
80
+ popped.push(top);
81
+ open.pop();
82
+ }
83
+ const parent = open.at(-1);
84
+ if (parent !== undefined && indentOf(parent) === indentOf(item)) {
85
+ open[open.length - 1] = item;
86
+ return { item, previous: parent };
87
+ }
88
+ if (parent === undefined) {
89
+ open.push(item);
90
+ return { item, previous: popped.at(-1) };
91
+ }
92
+ if (item.number === parent.number + 1) {
93
+ open[open.length - 1] = { ...item, indent: indentOf(parent) };
94
+ return { item, previous: parent };
95
+ }
96
+ open.push(item);
97
+ return { item, previous: item.number === 1 || item.number === (nestedLast(parent) ?? 0) + 1 ? undefined : parent };
98
+ });
99
+ };
100
+
101
+ /**
102
+ * Each item whose number is not one more than the item it follows. A list that writes one number on every item (「1.」
103
+ * on each, which Markdown counts up) is numbered by the renderer, not by the writer, and is not read. An item numbered 1
25
104
  * starts a new count, as the structure rule reads a 1 that follows other items.
26
105
  */
27
- export const listNumberBreaks = (items: readonly WrittenNumber[]): StructureIssue[] => {
106
+ export const listNumberBreaks = (items: readonly WrittenNumber[], nestedLast: NestedLast = () => undefined): StructureIssue[] => {
28
107
  if (new Set(items.map((item) => item.number)).size < 2) return [];
29
- return items.flatMap((item, index) => {
30
- const previous = items[index - 1];
108
+ return comparedPairs(items, nestedLast).flatMap(({ item, previous }) => {
31
109
  if (previous === undefined || item.number === previous.number + 1 || item.number === 1) return [];
32
110
  return [{ offset: item.offset, values: { previous: previous.label, label: item.label, expected: previous.number + 1, found: item.number } }];
33
111
  });
34
112
  };
113
+
114
+ type ListSpans = { readonly span: Span; readonly itemSpans: readonly Span[] };
115
+
116
+ /** The breaks in the document's lists that are checked; every list, checked or not, tells which ordered list sits inside an item. */
117
+ export const listsNumberBreaks = (source: string, lists: readonly ListSpans[], isChecked: (list: ListSpans) => boolean): StructureIssue[] => {
118
+ const nestedLast = nestedLastFinder(
119
+ source,
120
+ lists.map((list) => list.itemSpans),
121
+ );
122
+ return lists.filter(isChecked).flatMap((list) => listNumberBreaks(writtenNumbers(source, list.itemSpans) ?? [], nestedLast));
123
+ };
@@ -0,0 +1,45 @@
1
+ import type { StructureNode } from "../plugin.ts";
2
+
3
+ // 箇条書きで書いた項。規程は条の下の項を「1. 」「2.」の箇条書きで書くことがあり、木はそれを項として読まない。
4
+
5
+ /** 行頭の箇条書きの番号(「1. 」「2.」)。前の空白(全角も)を飛ばし、全角の数字と点も読む。 */
6
+ const LIST_MARK = /^[ \t\u3000]*(?<n>[0-90-9]{1,3})[..]/u;
7
+
8
+ /** 本文の行頭に箇条書きで書かれた番号。全角は半角の数にする(「2.」は 2)。Pure. */
9
+ export const listedNumbers = (body: string): ReadonlySet<number> =>
10
+ new Set(
11
+ body.split("\n").flatMap((line) => {
12
+ const written = LIST_MARK.exec(line)?.groups?.["n"];
13
+ return written === undefined ? [] : [Number(written.normalize("NFKC"))];
14
+ }),
15
+ );
16
+
17
+ /** 「3.3」を条の番地「3」と項の番号 3 に分ける。項の先まで指す(3.3.1)か、項が数でなければ undefined。Pure. */
18
+ export const articleParagraph = (target: string): { readonly article: string; readonly paragraph: number } | undefined => {
19
+ const parts = target.split(".");
20
+ const [article, paragraph] = parts;
21
+ if (parts.length !== 2 || article === undefined || paragraph === undefined || !/^\d{1,3}$/u.test(paragraph)) return undefined;
22
+ return { article, paragraph: Number(paragraph) };
23
+ };
24
+
25
+ /**
26
+ * 木が項を一つも読まなかった条ごとの、箇条書きの番号。条の本文は一度だけ読む。同じ番地の条が二つあれば、どちらかに書いてあればよい。
27
+ * nodes は木を平らにしたもの。Pure.
28
+ */
29
+ export const listedParagraphsByArticle = (nodes: readonly StructureNode[], source: string): ReadonlyMap<string, ReadonlySet<number>> => {
30
+ const byArticle = new Map<string, Set<number>>();
31
+ nodes
32
+ .filter((node) => node.kind === "article" && !node.children.some((child) => child.kind === "item"))
33
+ .forEach((article) => {
34
+ const numbers = byArticle.get(article.address) ?? new Set<number>();
35
+ listedNumbers(source.slice(article.span.start, article.span.end)).forEach((number) => numbers.add(number));
36
+ byArticle.set(article.address, numbers);
37
+ });
38
+ return byArticle;
39
+ };
40
+
41
+ /** 参照(第3条第3項)の項を、その条の箇条書きが書いているか。Pure. */
42
+ export const isListedParagraph = (target: string, listed: ReadonlyMap<string, ReadonlySet<number>>): boolean => {
43
+ const wanted = articleParagraph(target);
44
+ return wanted !== undefined && listed.get(wanted.article)?.has(wanted.paragraph) === true;
45
+ };
@@ -1,4 +1,4 @@
1
- import type { StructureNode } from "../plugin.ts";
1
+ import type { Span, StructureNode } from "../plugin.ts";
2
2
  import { inDocumentOrder, type StructureIssue } from "./issues.ts";
3
3
  import { numbersQuotedInside } from "./quoted-number.ts";
4
4
  import { isVersionHistory } from "./version-order.ts";
@@ -7,15 +7,21 @@ const labelOf = (node: StructureNode): string => String(node.attrs["label"] ?? n
7
7
 
8
8
  type Ordered = { readonly node: StructureNode; readonly ordinal: number; readonly last: number };
9
9
 
10
+ const OPENING_BRACKET = /^[([{〔【〈《]/u;
11
+
12
+ /** 括弧で囲んだ番号((1)、(a))か。全角と半角は同じに見る。 */
13
+ const isBracketed = (label: string): boolean => OPENING_BRACKET.test(label.normalize("NFKC"));
14
+
10
15
  /**
11
- * 同じ親の子のうち、番号の付いたものを種類と深さごとに分ける。条と項は別の並び、項と号も別の並び。
16
+ * 同じ親の子のうち、番号の付いたものを種類と深さと書き方ごとに分ける。条と項は別の並び、項と号も別の並び。
12
17
  * 法令の第 1 項は番号が無いので、その号(一、二)と第 2 項(2)は同じ条の直下に並ぶ。深さで分けないと「二の次が2」に見える。
18
+ * 社内規程は号の(1)(2)と第 2 項の「2」を同じ深さに読むことがあるので、括弧で囲んだ番号は囲まない番号と別の並びにする。
13
19
  */
14
20
  const sequencesOf = (parent: StructureNode, quoting: ReadonlySet<StructureNode>): Ordered[][] => {
15
21
  const groups = new Map<string, Ordered[]>();
16
22
  parent.children.forEach((node) => {
17
23
  if (node.ordinal === undefined || quoting.has(node)) return;
18
- const key = `${node.kind}/${String(node.level ?? "")}`;
24
+ const key = `${node.kind}/${String(node.level ?? "")}/${isBracketed(labelOf(node)) ? "bracketed" : "bare"}`;
19
25
  // 配列を作り直さずに足す。条が何千もある法令で二乗にしない。
20
26
  const group = groups.get(key) ?? [];
21
27
  group.push({ node, ordinal: node.ordinal, last: node.ordinalTo ?? node.ordinal });
@@ -24,20 +30,42 @@ const sequencesOf = (parent: StructureNode, quoting: ReadonlySet<StructureNode>)
24
30
  return [...groups.values()];
25
31
  };
26
32
 
27
- /** 隣り合う二つの番号が、1 つ進んでいなければ指摘する。同じ番号なら重なり、飛べば抜け。 */
28
- const breaksIn = (sequence: readonly Ordered[]): StructureIssue[] =>
29
- sequence.flatMap((current, index) => {
30
- const previous = sequence[index - 1];
31
- // 1 に戻ったら新しい並び。一つの条に (a)(b) の箇条書きが二つある、附則が第1条から振り直す、のどちらも誤りではない。
32
- // 範囲をまとめた行(第四十三条から第五十五条まで)の次は、範囲の最後から数える。
33
- if (previous === undefined || current.ordinal === previous.last + 1 || current.ordinal === 1) return [];
34
- return [
35
- {
36
- offset: current.node.span.start,
37
- values: { previous: labelOf(previous.node), label: labelOf(current.node), expected: previous.last + 1, found: current.ordinal },
38
- },
39
- ];
40
- });
33
+ /** start が after より後ろの最初の範囲。unread は始まりの順に並ぶ。 */
34
+ const firstStartingAfter = (unread: readonly Span[], after: number): number => {
35
+ let low = 0;
36
+ let high = unread.length;
37
+ while (low < high) {
38
+ const middle = Math.floor((low + high) / 2);
39
+ if ((unread[middle]?.start ?? Infinity) > after) high = middle;
40
+ else low = middle + 1;
41
+ }
42
+ return low;
43
+ };
44
+
45
+ /** 二つの番号のあいだに、読めなかった範囲が始まるか。 */
46
+ const unreadBetween = (unread: readonly Span[], previous: Ordered, current: Ordered): boolean =>
47
+ (unread[firstStartingAfter(unread, previous.node.span.start)]?.start ?? Infinity) < current.node.span.start;
48
+
49
+ /**
50
+ * 隣り合う二つの番号が、1 つ進んでいなければ指摘する。同じ番号なら重なり、飛べば抜け。
51
+ * あいだに読めなかった範囲(unread)があれば、抜けた番号はそこにあるかもしれないので言わない。重なりは言う。
52
+ */
53
+ const breaksIn =
54
+ (unread: readonly Span[]) =>
55
+ (sequence: readonly Ordered[]): StructureIssue[] =>
56
+ sequence.flatMap((current, index) => {
57
+ const previous = sequence[index - 1];
58
+ // 1 に戻ったら新しい並び。一つの条に (a)(b) の箇条書きが二つある、附則が第1条から振り直す、のどちらも誤りではない。
59
+ // 範囲をまとめた行(第四十三条から第五十五条まで)の次は、範囲の最後から数える。
60
+ if (previous === undefined || current.ordinal === previous.last + 1 || current.ordinal === 1) return [];
61
+ if (current.ordinal > previous.last + 1 && unreadBetween(unread, previous, current)) return [];
62
+ return [
63
+ {
64
+ offset: current.node.span.start,
65
+ values: { previous: labelOf(previous.node), label: labelOf(current.node), expected: previous.last + 1, found: current.ordinal },
66
+ },
67
+ ];
68
+ });
41
69
 
42
70
  /**
43
71
  * 番号の抜けと重なり。比べるのは同じ親の子どうしだけ。英米の法令は章ごとに Section 101、201 と百の位を変えるので、
@@ -45,12 +73,13 @@ const breaksIn = (sequence: readonly Ordered[]): StructureIssue[] =>
45
73
  * 1 に戻った番号は新しい並びの始まりとして扱うので、「(a) の後の (a)」の重なりは見逃す。
46
74
  * 同じ番号の節を中に持つ節(ほかの文書の条を引いた手本の見出し)は、並びに入れない。
47
75
  * 変更履歴の版の見出し(## 3.1.0)は番号の並びではない。版の順番は version-order が見る。
76
+ * unread は、読み手には見えるが木に入らない範囲(Markdown の HTML ブロックの中の文字)を、始まりの順に並べたもの。
48
77
  */
49
- export const numberingBreaks = (tree: StructureNode): StructureIssue[] => {
78
+ export const numberingBreaks = (tree: StructureNode, unread: readonly Span[] = []): StructureIssue[] => {
50
79
  const quoting = numbersQuotedInside(tree);
51
80
  return inDocumentOrder(tree)
52
81
  .flatMap((parent) => sequencesOf(parent, quoting))
53
82
  .filter((sequence) => !isVersionHistory(sequence.map((ordered) => labelOf(ordered.node))))
54
- .flatMap(breaksIn)
83
+ .flatMap(breaksIn(unread))
55
84
  .toSorted((left, right) => left.offset - right.offset);
56
85
  };
@@ -5,6 +5,8 @@ import { shownTotal, type Amount } from "./total.ts";
5
5
  * 文の中で書いた合計と内訳。表や箇条書きでなく、一つの文に並べた金額を読む。二つの形がある。
6
6
  * 内訳のあとに合計: 「保守費60,000円、運用費30,000円とし、合計100,000円とする」 "$6,000 for hosting and $3,000 for support, for a total of $9,000"
7
7
  * 合計のあとに内訳: 「月額150,000円(内訳:保守費90,000円、運用費60,000円)」 "costs $8 per month, made up of a base fee of $6 and a storage fee of $2"
8
+ * 合計の語のあとに内訳: 「総額12,000円:設計5,000円、開発6,000円」 "a total of $12,000: $5,000 for design and $6,000 for development"
9
+ * (内訳を始める記号や語 total-breakdown-lead が合計の金額のすぐ後ろにあるか、合計で終わる文の次の文が内訳の語で始まるとき)
8
10
  * 合計の語(total-phrase)はすぐ後ろに合計の金額が来る語、内訳の語(breakdown-phrase)はすぐ後ろから内訳が始まる語。
9
11
  * 内訳は合計と同じ単位の金額で、二つ以上。合計の語のすぐ前(内訳の語のすぐ後ろ)から続く並びのどれかの和が合計と合えば
10
12
  * 合っているとみなし、どれとも合わないときだけ言う。文の中のほかの金額(単価・上限・遅延損害金)を内訳に数えて誤って言わないため。
@@ -16,6 +18,12 @@ export type TotalWords = {
16
18
  readonly breakdowns: readonly string[];
17
19
  readonly discounts: readonly string[];
18
20
  readonly joiners: readonly string[];
21
+ /** 合計の金額のすぐ後ろに書いて、そこから内訳のすべてが続くことを言う記号や語(": $5,000 for design and …")。 */
22
+ readonly leads: readonly string[];
23
+ /** 合計と内訳のあいだにあれば、後ろの金額は合計の内訳のすべてとは限らないと読む語(including、うち、or)。 */
24
+ readonly partials: readonly string[];
25
+ /** 次の文で内訳の語の前に書いて、前の文の合計を指す語(This、It、その)。何も書かなくてもよい。 */
26
+ readonly backReferences: readonly string[];
19
27
  };
20
28
 
21
29
  type Span = { readonly start: number; readonly end: number };
@@ -124,12 +132,83 @@ const totalsBeforeParts = (source: string, sentence: Span, amounts: readonly Amo
124
132
  });
125
133
  };
126
134
 
135
+ /** 合計の金額と、後ろに続く内訳を始める記号や語のあいだに書いてよいもの: 空白と、読点一つ。 */
136
+ const isLeadGap = (gap: string): boolean => /^[、,,]?$/u.test(gap.trim());
137
+ /** 割合(40%)を並べた内訳は、金額が合計のどの部分かを言わないので比べない。 */
138
+ const PERCENT = /[%%]/u;
139
+ /** 合計の文と内訳の文のあいだに空行があれば、別の段落で、続く内訳とは読まない。 */
140
+ const PARAGRAPH_BREAK = /\n\s*\n/u;
141
+
142
+ /** 合計の語のすぐ後ろの金額。 */
143
+ const totalsAt = (source: string, markers: readonly Span[], amounts: readonly Amount[]): Amount[] =>
144
+ markers.flatMap((marker) => amounts.find((amount) => amount.offset >= marker.end && isTotalGap(gapBefore(source, marker.end, amount))) ?? []);
145
+
146
+ /**
147
+ * 合計の後ろから始まる内訳のすべてを合計と比べる。内訳の金額がどれも合計と同じ単位で、合計から内訳の終わりまでに
148
+ * 一部だけを言う語(including、うち)も割合も無いときだけ。
149
+ */
150
+ const fullBreakdown = (source: string, total: Amount, listed: readonly Amount[], from: number, words: TotalWords): StructureIssue[] => {
151
+ const last = listed.at(-1);
152
+ if (last === undefined || listed.some((part) => part.unit !== total.unit)) return [];
153
+ const between = source.slice(total.end, last.offset);
154
+ if (PERCENT.test(between) || phraseSpans(between, total.end, words.partials).length > 0) return [];
155
+ return mismatch(source, { total, parts: listed, from, nearEnd: false }, words.discounts);
156
+ };
157
+
158
+ /** 文の中で、合計の語の金額のすぐ後ろに内訳を始める記号や語(": ")があれば、その後ろから文の終わりか次の記号までが内訳。 */
159
+ const totalsThenLead = (source: string, sentence: Span, amounts: readonly Amount[], words: TotalWords): StructureIssue[] => {
160
+ const text = source.slice(sentence.start, sentence.end);
161
+ const markers = phraseSpans(text, sentence.start, words.totals);
162
+ const leads = phraseSpans(text, sentence.start, words.leads);
163
+ return totalsAt(source, markers, amounts).flatMap((total) => {
164
+ const lead = leads.find((span) => span.start >= total.end && isLeadGap(source.slice(total.end, span.start)));
165
+ if (lead === undefined) return [];
166
+ const end = Math.min(sentence.end, ...[...leads, ...markers].filter((span) => span.start >= lead.end).map((span) => span.start));
167
+ return fullBreakdown(source, total, inside(amounts, lead.end, end), lead.end, words);
168
+ });
169
+ };
170
+
171
+ /** 文の最後の金額が合計の語のすぐ後ろの金額なら、その金額。 */
172
+ const closingTotal = (source: string, sentence: Span, amounts: readonly Amount[], words: TotalWords): Amount | undefined => {
173
+ const last = inside(amounts, sentence.start, sentence.end).at(-1);
174
+ const markers = phraseSpans(source.slice(sentence.start, sentence.end), sentence.start, words.totals);
175
+ return totalsAt(source, markers, amounts).find((total) => total === last);
176
+ };
177
+
178
+ /** 内訳の語の前に書いたものが、何も無いか前の合計を指す語だけ("This consists of" 「内訳は」「その内訳は」)。 */
179
+ const refersBack = (opening: string, backReferences: readonly string[]): boolean => {
180
+ const subject = opening.trim().toLowerCase();
181
+ return subject === "" || backReferences.some((word) => word.toLowerCase() === subject);
182
+ };
183
+
184
+ /** 合計で終わる文のすぐ次の文が、前の合計を指して内訳の語で始まれば(内訳は、This consists of)、その後ろの金額が内訳。 */
185
+ const totalThenNextSentence = (source: string, pair: readonly [Span, Span], amounts: readonly Amount[], words: TotalWords): StructureIssue[] => {
186
+ const [previous, next] = pair;
187
+ const total = closingTotal(source, previous, amounts, words);
188
+ if (total === undefined || PARAGRAPH_BREAK.test(source.slice(previous.end, next.start))) return [];
189
+ const text = source.slice(next.start, next.end);
190
+ const marker = phraseSpans(text, next.start, words.breakdowns)[0];
191
+ if (marker === undefined || !refersBack(source.slice(next.start, marker.start), words.backReferences)) return [];
192
+ const inNext = inside(amounts, next.start, next.end);
193
+ const end = phraseSpans(text, next.start, words.totals).find((span) => span.start >= marker.end)?.start ?? next.end;
194
+ return fullBreakdown(source, total, inside(inNext, marker.end, end), marker.end, words);
195
+ };
196
+
127
197
  /** 文ごとに、書いた合計が内訳の和と合わない所。一つの金額は一度だけ言う。 */
128
198
  export const proseTotalMismatches = (source: string, sentences: readonly Span[], amounts: readonly Amount[], words: TotalWords): StructureIssue[] => {
129
- const issues = sentences.flatMap((sentence) => {
199
+ const inSentences = sentences.flatMap((sentence) => {
130
200
  const inSentence = inside(amounts, sentence.start, sentence.end);
131
201
  if (inSentence.length <= MIN_PARTS) return [];
132
- return [...totalsAfterParts(source, sentence, inSentence, words), ...totalsBeforeParts(source, sentence, inSentence, words)];
202
+ return [
203
+ ...totalsAfterParts(source, sentence, inSentence, words),
204
+ ...totalsBeforeParts(source, sentence, inSentence, words),
205
+ ...totalsThenLead(source, sentence, inSentence, words),
206
+ ];
207
+ });
208
+ const acrossSentences = sentences.flatMap((previous, index) => {
209
+ const next = sentences[index + 1];
210
+ return next === undefined ? [] : totalThenNextSentence(source, [previous, next], amounts, words);
133
211
  });
212
+ const issues = [...inSentences, ...acrossSentences];
134
213
  return issues.filter((issue, index) => issues.findIndex((other) => other.offset === issue.offset) === index);
135
214
  };
@@ -16,6 +16,8 @@ export type ReferenceWords = {
16
16
  readonly topicLinks: readonly string[];
17
17
  /** 話題にならない語(詳細、内容、details)。どの節にも当てはまる。 */
18
18
  readonly vagueTopics: readonly string[];
19
+ /** 二つの参照を一つの並びにする語(及び、から、and、to)。並びの後ろの括弧は並び全体の名前。 */
20
+ readonly listJoints: readonly string[];
19
21
  };
20
22
 
21
23
  export type ReferenceInput = {
@@ -70,17 +72,37 @@ export const holdsAside = (name: string, aside: string): boolean => {
70
72
  return aside.trim() !== "" && words.includes(` ${aside.trim().toLowerCase()} `);
71
73
  };
72
74
 
75
+ /** 句点で終わる括弧や引用符の中は名前でなく文(範囲の断り「…を除く。」、引いた条文)。見出しは句点で終わらない。 */
76
+ const SENTENCE_STOP = /[。.]$/u;
77
+
78
+ export const endsAsSentence = (name: string): boolean => SENTENCE_STOP.test(name);
79
+
73
80
  const isName = (name: string, words: ReferenceWords): boolean =>
74
- LETTER.test(name) && !DIGIT.test(name) && !ITEM_LABEL.test(name.normalize("NFKC")) && !words.asides.some((aside) => holdsAside(name, aside));
81
+ LETTER.test(name) &&
82
+ !DIGIT.test(name) &&
83
+ !ITEM_LABEL.test(name.normalize("NFKC")) &&
84
+ !endsAsSentence(name) &&
85
+ !words.asides.some((aside) => holdsAside(name, aside));
75
86
 
76
87
  const agrees = (name: string, heading: string): boolean => {
77
88
  const [a, b] = [normalized(name), normalized(heading)];
78
89
  return a.includes(b) || b.includes(a);
79
90
  };
80
91
 
81
- /** 名前を添えた参照で、名前が参照先の見出しと合わない。 */
92
+ /**
93
+ * The reference ends a list or range of references ("sections 162 and 164", "sections 9 to 11"): only a joint stands
94
+ * between it and the reference before it.
95
+ */
96
+ export const endsList = (between: string, joints: readonly string[]): boolean => {
97
+ const joint = between.normalize("NFKC").trim().toLowerCase();
98
+ return joint !== "" && joints.some((candidate) => candidate.normalize("NFKC").trim().toLowerCase() === joint);
99
+ };
100
+
101
+ /** 名前を添えた参照で、名前が参照先の見出しと合わない。並びの後ろの括弧は並び全体の名前なので、どの見出しとも比べない。 */
82
102
  export const titleMismatches = (input: ReferenceInput): StructureIssue[] =>
83
- input.references.flatMap((reference) => {
103
+ input.references.flatMap((reference, index) => {
104
+ const previous = input.references[index - 1];
105
+ if (previous !== undefined && endsList(input.source.slice(previous.span.end, reference.span.start), input.words.listJoints)) return [];
84
106
  const target = input.targetOf(reference);
85
107
  const heading = target === undefined ? "" : headingOf(target);
86
108
  const found = nameAfter(input.source, reference.span.end);
@@ -1,3 +1,5 @@
1
+ import { fencedLineIndexes } from "./fenced-lines.ts";
2
+
1
3
  /**
2
4
  * 箇条書きと表の行の並び。続いた箇条書きの同じ深さの項目か、続いた表の行を一つの並びとして読む。
3
5
  * 並びの中の値(日付、金額)を比べる rule が共通に使う。
@@ -29,14 +31,21 @@ const pipelessTableLines = (texts: readonly string[]): Set<number> => {
29
31
  return inTable;
30
32
  };
31
33
 
34
+ /** コードブロックの中の箇条書きや表は例なので、並びにしない。 */
35
+ const kindAt = (texts: readonly string[], index: number, pipeless: ReadonlySet<number>, fenced: ReadonlySet<number>): Kind | undefined => {
36
+ if (fenced.has(index)) return undefined;
37
+ return pipeless.has(index) ? "table" : kindOf(texts[index] ?? "");
38
+ };
39
+
32
40
  const linesOf = (source: string): Line[] => {
33
41
  const texts = source.split("\n");
34
42
  const pipeless = pipelessTableLines(texts);
43
+ const fenced = fencedLineIndexes(texts);
35
44
  const found: Line[] = [];
36
45
  let start = 0;
37
46
  texts.forEach((text, index) => {
38
47
  const indent = INDENT.exec(text)?.[0].length ?? 0;
39
- const kind = pipeless.has(index) ? "table" : kindOf(text);
48
+ const kind = kindAt(texts, index, pipeless, fenced);
40
49
  found.push({ start, end: start + text.length, kind, indent, rule: TABLE_RULE.test(text) });
41
50
  start += text.length + 1;
42
51
  });
@@ -0,0 +1,32 @@
1
+ import type { StructureNode } from "../plugin.ts";
2
+
3
+ // 番号で呼ぶ他の法律の手続き。英国の「section 21 notice」は Housing Act 1988 の section 21 の通知で、この文書の section 21 ではない。
4
+
5
+ /** 参照のすぐ後ろの語。 */
6
+ const NEXT_WORD = /^[ \t]+(?<word>\p{L}+)/u;
7
+ const LOWER_START = /^\p{Ll}/u;
8
+ /** 後ろの語を読む長さ。名前を作る語は短い。 */
9
+ const NEXT_WORD_LENGTH = 24;
10
+
11
+ /**
12
+ * 名前の一部として書かれた番号(「section 21 notice」)の行き先。小文字で書いた参照の後ろに、名前を作る語(語彙表)が続くもの。
13
+ * 大文字の「Section 5 notice」は契約が自分の条を指す書き方なので当たらない。Pure.
14
+ */
15
+ export const namedTargets = (references: readonly StructureNode[], source: string, nouns: readonly string[]): ReadonlySet<string> => {
16
+ if (nouns.length === 0) return new Set();
17
+ const names = new Set(nouns);
18
+ return new Set(
19
+ references.flatMap((reference) => {
20
+ const label = String(reference.attrs["label"] ?? "");
21
+ const word = NEXT_WORD.exec(source.slice(reference.span.end, reference.span.end + NEXT_WORD_LENGTH))?.groups?.["word"];
22
+ return LOWER_START.test(label) && word !== undefined && names.has(word) ? [String(reference.attrs["target"] ?? "")] : [];
23
+ }),
24
+ );
25
+ };
26
+
27
+ /**
28
+ * 名前として書かれた番号を指す参照か。小文字で書いた参照(「under section 21」)だけ。同じ文書の大文字の「Section 21」は、
29
+ * 文書が自分の section を指す書き方なので、名前があっても探す。Pure.
30
+ */
31
+ export const pointsToNamedSection = (reference: StructureNode, named: ReadonlySet<string>): boolean =>
32
+ LOWER_START.test(String(reference.attrs["label"] ?? "")) && named.has(String(reference.attrs["target"] ?? ""));
@@ -0,0 +1,78 @@
1
+ import { escapeRegExp } from "../orthography.ts";
2
+
3
+ /**
4
+ * A signature line that dates what its signer did: one date, one role word and the signer's name, and nothing else
5
+ * (2026年4月12日 会計監査 戸川 隆; Jane Doe, Honorary Auditor, April 12, 2026). A sentence (2026年3月26日の定期総会で承認),
6
+ * a line without a name, or a line naming two people is not one. Pure.
7
+ */
8
+
9
+ const SEPARATOR = /[\s,、,::]/u;
10
+ const MARK = /[,、,::]/u;
11
+ const SPACES = /\s+/u;
12
+ /** A Japanese name is one or two parts (戸川 隆, 戸川隆); an English one two or three (Jane Doe, Jane Q. Doe). */
13
+ const MAX_JA_NAME_PARTS = 2;
14
+ const MIN_EN_NAME_PARTS = 2;
15
+ const MAX_EN_NAME_PARTS = 3;
16
+ /** A Japanese name part is kanji or katakana: hiragana is a particle or a verb (田中が確認, に監査を受け). */
17
+ const JA_NAME_PART = /^[\p{Script=Han}\p{Script=Katakana}ー]{1,5}$/u;
18
+ /** An English name part is capitalised, or an initial with its full stop. */
19
+ const EN_NAME_PART = /^\p{Lu}(?:\.|[\p{L}'’-]+)$/u;
20
+
21
+ /** Where a date sits on the line: from start to end, counted from the line's start. */
22
+ export type LineSpan = { readonly start: number; readonly end: number };
23
+
24
+ const isEdge = (text: string, index: number): boolean => index < 0 || index >= text.length || SEPARATOR.test(text.charAt(index));
25
+
26
+ const standsAlone = (text: string, start: number, end: number): boolean => isEdge(text, start - 1) && isEdge(text, end);
27
+
28
+ const occurrences = (text: string, word: string): number[] => [...text.matchAll(new RegExp(escapeRegExp(word), "gu"))].map((match) => match.index);
29
+
30
+ /** The role word of roles standing alone on the line (between separators or at an edge), the longest first. */
31
+ export const signerRoleOf = (text: string, roles: readonly string[]): string | undefined =>
32
+ [...roles]
33
+ .sort((one, other) => other.length - one.length)
34
+ .find((role) => occurrences(text, role).some((start) => standsAlone(text, start, start + role.length)));
35
+
36
+ const isJaName = (parts: readonly string[]): boolean => parts.length <= MAX_JA_NAME_PARTS && parts.every((part) => JA_NAME_PART.test(part));
37
+
38
+ const isEnName = (parts: readonly string[]): boolean =>
39
+ parts.length >= MIN_EN_NAME_PARTS && parts.length <= MAX_EN_NAME_PARTS && parts.every((part) => EN_NAME_PART.test(part));
40
+
41
+ const blanked = (text: string, span: LineSpan): string => `${text.slice(0, span.start)}${" ".repeat(span.end - span.start)}${text.slice(span.end)}`;
42
+
43
+ /** Where the text that is not a separator starts and ends; undefined when there is none. */
44
+ const contentOf = (text: string): LineSpan | undefined => {
45
+ const units = text.split("");
46
+ const start = units.findIndex((unit) => !SEPARATOR.test(unit));
47
+ if (start < 0) return undefined;
48
+ const end = units.findLastIndex((unit) => !SEPARATOR.test(unit)) + 1;
49
+ return { start, end };
50
+ };
51
+
52
+ /** The text between the role and the name: the name sits wholly on one side of the role. */
53
+ const gapOf = (text: string, role: LineSpan, name: LineSpan): string | undefined => {
54
+ if (name.end <= role.start) return text.slice(name.end, role.start);
55
+ return name.start >= role.end ? text.slice(role.end, name.start) : undefined;
56
+ };
57
+
58
+ /**
59
+ * The line is a signature: the date and the role each stand alone, and what is left is one name, in one piece on one side
60
+ * of the role (山田太郎、佐藤花子 is two). An English name is set off from its role by a comma or a colon (Jane Doe, Auditor),
61
+ * so a title (Auditor Annual Report) is not one. The role is found once the date is blanked out, so a role word inside the
62
+ * date's text is not read.
63
+ */
64
+ export const isSignedDateLine = (text: string, role: string, date: LineSpan): boolean => {
65
+ if (!standsAlone(text, date.start, date.end)) return false;
66
+ const withoutDate = blanked(text, date);
67
+ const roleStart = occurrences(withoutDate, role).find((start) => standsAlone(withoutDate, start, start + role.length));
68
+ if (roleStart === undefined) return false;
69
+ const roleSpan = { start: roleStart, end: roleStart + role.length };
70
+ const rest = blanked(withoutDate, roleSpan);
71
+ const name = contentOf(rest);
72
+ const gap = name === undefined ? undefined : gapOf(withoutDate, roleSpan, name);
73
+ if (name === undefined || gap === undefined) return false;
74
+ const nameText = rest.slice(name.start, name.end);
75
+ if (MARK.test(nameText)) return false;
76
+ const parts = nameText.split(SPACES);
77
+ return isJaName(parts) || (isEnName(parts) && MARK.test(gap));
78
+ };
@@ -1,6 +1,6 @@
1
1
  import type { StructureIssue } from "./issues.ts";
2
2
  import { runsOf, type Line } from "./runs.ts";
3
- import { columnOf, isTotalLabel, shownTotal, type Amount } from "./total.ts";
3
+ import { columnOf, isTotalLabel, shownTotal, withoutLeadingBlankCells, type Amount } from "./total.ts";
4
4
 
5
5
  /**
6
6
  * 税の行と、その上の金額に率を掛けた額。表か箇条書きの並びで、税の語(消費税・Sales tax)で始まり率(10%)を書いた行の
@@ -42,8 +42,11 @@ const rateOf = (text: string): number | undefined => {
42
42
  return Number.isFinite(rate) && rate > 0 && rate < MAX_RATE ? rate : undefined;
43
43
  };
44
44
 
45
+ /** A tax or total row may leave its first cells blank and put its word in the first cell that is not (| | 小計 | 12,000円 |). */
46
+ const startsWithLabel = (row: Row, labels: readonly string[]): boolean => isTotalLabel(withoutLeadingBlankCells(row.text), labels);
47
+
45
48
  const isTaxRow = (row: Row, words: TaxWords): boolean =>
46
- isTotalLabel(row.text, words.labels) && !words.included.some((word) => row.text.toLowerCase().includes(word.toLowerCase()));
49
+ startsWithLabel(row, words.labels) && !words.included.some((word) => row.text.toLowerCase().includes(word.toLowerCase()));
47
50
 
48
51
  const isChargeRow = (row: Row, words: TaxWords): boolean => isTotalLabel(row.text, words.charges) && rateOf(row.text) !== undefined;
49
52
 
@@ -89,7 +92,7 @@ const basesOf = (source: string, above: readonly Row[], tax: Amount, column: num
89
92
  const charges = valuesAt(source, above.slice(chargeStart), column, tax.unit);
90
93
  if (charges === undefined) return [];
91
94
  const before = above.slice(0, chargeStart);
92
- const lastTotalIndex = before.findLastIndex((row) => isTotalLabel(row.text, words.totals));
95
+ const lastTotalIndex = before.findLastIndex((row) => startsWithLabel(row, words.totals));
93
96
  const lastTotal = before[lastTotalIndex];
94
97
  if (lastTotal !== undefined) {
95
98
  const total = amountAt(source, lastTotal, column, tax.unit);