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,123 @@
1
+ import { escapeRegExp } from "../orthography.ts";
2
+ import { abbreviates } from "./acronym-expansion.ts";
3
+
4
+ /**
5
+ * 括弧の展開の形をとらずに、文書が略語を定義している所。契約書の定義の一覧(**"BAA"** means …、"Protected Health Information" or
6
+ * "PHI" has the meaning …)、当事者の呼び名の並び(("Buyer" or "PNC"))、名前の後ろの言い換え(“temporary duty,” also known as “TDY”)、
7
+ * 名前だけの行(発行者の行の HM Revenue & Customs と、本文の HMRC)。どれも文書の source から一度だけ集める。
8
+ */
9
+
10
+ /** 言語パッケージの語彙表から読む、定義を言う語(means、has the meaning)と、名前と略語の間に書く語(also known as、hereinafter)。 */
11
+ export type DefinitionStatementWords = { readonly statements: readonly string[]; readonly markers: readonly string[] };
12
+
13
+ const oneOf = (words: readonly string[]): string => (words.length === 0 ? "(?!)" : `(?:${words.map(escapeRegExp).join("|")})`);
14
+
15
+ const ACRONYM = String.raw`[A-Z][A-Z&-]*[A-Z]`;
16
+ const OPEN_QUOTE = `["“]`;
17
+ const CLOSE_QUOTE = `["”]`;
18
+ /** 引用符で囲んだ別の呼び名。 */
19
+ const QUOTED = String.raw`${OPEN_QUOTE}[^"“”()()\n]{1,80}${CLOSE_QUOTE}`;
20
+ /**
21
+ * 空白・区切り・強調の印(定義の一覧は語を太字にする: **"BAA"**)と、3 文字までの小文字の語(or、and、the)。語そのものは見ない。
22
+ * 長さに上限を置くのは、文書全体を走査するときに空白の長い並びで後戻りが膨らまないため。
23
+ */
24
+ const GAP = String.raw`[\s,;*_]{0,8}`;
25
+ const SHORT_WORD = String.raw`\p{Ll}{1,3}(?!\p{L})`;
26
+ const JOINER = String.raw`${GAP}(?:${SHORT_WORD}${GAP}){0,3}`;
27
+ /** 呼び名どうしの間。読点か短い語が要る。並べただけの引用("ABC" "Unrelated label")は呼び名の並びではない。 */
28
+ const LINK = String.raw`[\s*_]{0,8}(?:,|${SHORT_WORD})${GAP}(?:${SHORT_WORD}${GAP}){0,2}`;
29
+ const QUOTED_MAX = 6;
30
+
31
+ const captured = (text: string, pattern: RegExp): string[] => [...text.matchAll(pattern)].flatMap((match) => match.groups?.["acronym"] ?? []);
32
+
33
+ /** 引用符で囲んだ略語と、その後ろの定義の語("SOW" means、"PHI" has the meaning)。間に別の呼び名と 1 語(shall)を挟んでよい。 */
34
+ const statementDefinitions = (source: string, statements: readonly string[]): string[] =>
35
+ statements.length === 0
36
+ ? []
37
+ : captured(
38
+ source,
39
+ new RegExp(
40
+ String.raw`${OPEN_QUOTE}(?<acronym>${ACRONYM})${CLOSE_QUOTE}(?:${LINK}${QUOTED}){0,${QUOTED_MAX}}${JOINER}(?:\p{Ll}{1,12}\s{1,3})?${oneOf(statements)}(?![\p{L}])`,
41
+ "gu",
42
+ ),
43
+ );
44
+
45
+ /** 括弧の中が、引用符で囲んだ 2 つ以上の呼び名だけの並び(("Buyer" or "PNC")、(the "Company" and "ACME"))。1 つだけの (see "PNC") は呼び名の定義ではない。 */
46
+ const LABEL_LIST = new RegExp(String.raw`[((]${JOINER}${QUOTED}(?:${LINK}${QUOTED}){1,${QUOTED_MAX}}${GAP}[))]`, "gu");
47
+ const QUOTED_ACRONYM = new RegExp(String.raw`${OPEN_QUOTE}(?<acronym>${ACRONYM})${CLOSE_QUOTE}`, "gu");
48
+
49
+ const labelDefinitions = (source: string): string[] => [...source.matchAll(LABEL_LIST)].flatMap((list) => captured(list[0], QUOTED_ACRONYM));
50
+
51
+ /**
52
+ * 名前と、読点か引用符で区切った言い換えの語の後ろの、引用符で囲んだ略語(“temporary duty,” also known as “TDY”)。名前から略語の
53
+ * 文字が順に拾えるときだけ。区切りの無い所(the "TDY" office の the)は言い換えではない。
54
+ */
55
+ const NAME_BEFORE = String.raw`(?<name>(?:[\p{L}'’-]+\s+){0,7}[\p{L}'’-]+)[,"”]+`;
56
+
57
+ const markedDefinitions = (source: string, markers: readonly string[]): string[] =>
58
+ markers.length === 0
59
+ ? []
60
+ : [...source.matchAll(new RegExp(String.raw`${NAME_BEFORE}\s${oneOf(markers)}\s+${OPEN_QUOTE}(?<acronym>${ACRONYM})${CLOSE_QUOTE}`, "gu"))]
61
+ .filter((match) => abbreviates(match.groups?.["name"] ?? "", match.groups?.["acronym"] ?? ""))
62
+ .flatMap((match) => match.groups?.["acronym"] ?? []);
63
+
64
+ /** 名前だけの行の語。強調の印を外した行が、大文字で始まる語と、その間の語・& だけ(HM Revenue & Customs)。見出しの行は名前の行ではない。 */
65
+ const LINE_MARKS = /[*_]/gu;
66
+ const HEADING = /^#{1,6}\s/u;
67
+ const NAME_LINE_WORD = /^(?:\p{L}[\p{L}'’.-]*|&)$/u;
68
+ const NAME_LINE_WORDS_MAX = 8;
69
+ const CAPITALS_WORD = /^\p{Lu}+$/u;
70
+ const CAPITALISED = /^\p{Lu}/u;
71
+ /** 文の終わりの記号で終わる行(Tell HMRC first.)は文で、名前の行ではない。 */
72
+ const SENTENCE_END = /[.!?:;]$/u;
73
+
74
+ const nameLineWords = (line: string): string[] => {
75
+ const text = line.replaceAll(LINE_MARKS, " ").trim();
76
+ if (HEADING.test(line) || SENTENCE_END.test(text)) return [];
77
+ const words = text.split(/\s+/u);
78
+ const isName =
79
+ words.length >= 2 && words.length <= NAME_LINE_WORDS_MAX && CAPITALISED.test(words[0] ?? "") && words.every((word) => NAME_LINE_WORD.test(word));
80
+ return isName ? words : [];
81
+ };
82
+
83
+ /** 名前の頭文字。大文字だけの語(HM)は全部の文字を、大文字で始まる語は頭の 1 文字を使い、小文字の語と & は飛ばす。 */
84
+ const initialsOf = (words: readonly string[]): string =>
85
+ words
86
+ .filter((word) => CAPITALISED.test(word))
87
+ .map((word) => (CAPITALS_WORD.test(word) ? word : word.charAt(0)))
88
+ .join("");
89
+
90
+ /**
91
+ * 名前の行と読むのは、コロンで終わる短い項目名の行(From:、Published by:)のすぐ後ろの、発行者や当事者の名前の行だけ。
92
+ * 大文字で始まり小文字が続く語が 2 つ以上あり、頭文字が 3 文字以上のもの。見出しや本文の行(## Area Forecast Discussion、
93
+ * Advance Purchase)は、名前と略語を結ぶ書き手の印が無いので展開と読まない。
94
+ */
95
+ const FIELD_LABEL = /^\p{Lu}[\p{L} ]{0,30}:$/u;
96
+ const NAME_LINE_INITIALS_MIN = 3;
97
+ const TITLE_WORDS_MIN = 2;
98
+
99
+ const initialsOfNameLine = (line: string): string => {
100
+ const words = nameLineWords(line);
101
+ const titleWords = words.filter((word) => CAPITALISED.test(word) && !CAPITALS_WORD.test(word)).length;
102
+ const initials = initialsOf(words);
103
+ return titleWords >= TITLE_WORDS_MIN && initials.length >= NAME_LINE_INITIALS_MIN ? initials : "";
104
+ };
105
+
106
+ const nameLineDefinitions = (source: string): string[] => {
107
+ const lines = source
108
+ .split(/\r?\n/u)
109
+ .map((line) => line.trim())
110
+ .filter((line) => line !== "");
111
+ return lines
112
+ .flatMap((line, index) => (index > 0 && FIELD_LABEL.test(lines[index - 1] ?? "") ? [initialsOfNameLine(line)] : []))
113
+ .filter((initials) => initials !== "");
114
+ };
115
+
116
+ /** 文書が括弧の展開の形をとらずに定義した略語。 */
117
+ export const statedAcronyms = (source: string, words: DefinitionStatementWords): ReadonlySet<string> =>
118
+ new Set([
119
+ ...statementDefinitions(source, words.statements),
120
+ ...labelDefinitions(source),
121
+ ...markedDefinitions(source, words.markers),
122
+ ...nameLineDefinitions(source),
123
+ ]);
@@ -0,0 +1,26 @@
1
+ // 説明のない略語が上限に届かない文書で、それでも 1 つを指してよいかを決める手がかり。
2
+
3
+ /** 大文字で始まり小文字が続く語(International、Treasury)。名前を作る語の形。 */
4
+ const TITLE_WORD_AFTER = /^[\s–-]+\p{Lu}\p{Ll}/u;
5
+ const TITLE_WORD_BEFORE = /\p{Lu}\p{Ll}+[\s–-]+$/u;
6
+ /** 文の頭の語は、名前でなくても大文字で始まる(The CFR)。 */
7
+ const FIRST_WORD = /^\P{L}*\p{L}+[\s–-]+$/u;
8
+
9
+ /**
10
+ * 略語が、大文字で始まる語と並んで 1 つの名前を作っているか(SRI International、HM Treasury、Math FMA)。
11
+ * 名前の一部の略語は、読み手が名前として受け取るもので、展開を待つ略語とは言い切れない。start と end は文の中の略語の位置。
12
+ */
13
+ export const isNamePart = (sentence: string, start: number, end: number): boolean => {
14
+ const before = sentence.slice(0, start);
15
+ return TITLE_WORD_AFTER.test(sentence.slice(end)) || (TITLE_WORD_BEFORE.test(before) && !FIRST_WORD.test(before));
16
+ };
17
+
18
+ /**
19
+ * 略語だけを括弧に入れた所があるか(National Vulnerability Database (NVD))。書き手が名前を書いて略語を添えた、いちばん確かな展開の形。
20
+ * 略語の後ろの括弧(README ([#1455](…)))はリンクや注記にも使うので、書き手が展開する人かを測るときは数えない。
21
+ */
22
+ export const isBracketed = (text: string, acronym: string): boolean => new RegExp(String.raw`[((]\s?["“「]?${acronym}["”」]?\s?[))]`, "u").test(text);
23
+
24
+ /** 見出しに出る略語は、その文書が扱う相手の名前(NASA Selects …)。読み手はそれを知って読みに来る。 */
25
+ export const isInHeading = (headings: readonly string[], acronym: string): boolean =>
26
+ headings.some((heading) => new RegExp(String.raw`(?<![A-Za-z0-9_&])${acronym}(?![A-Za-z0-9_&])`, "u").test(heading));
@@ -0,0 +1,117 @@
1
+ import { escapeRegExp } from "../orthography.ts";
2
+
3
+ /**
4
+ * 大文字で書いた名前の部品と決まり文句で、展開を待つ略語ではないもの(JVLS, LLC、TRATON SE、AU$10、45 CFR §164、
5
+ * Federal Express, UPS, DHL、HM Revenue & Customs、512 Bayshore DR、NOW, THEREFORE、AND/OR)。どれも語彙表の語が決まった形の中に
6
+ * あるときだけ認める。語は言語パッケージの語彙表から読み、ここには形の組み立てだけを置く。
7
+ */
8
+
9
+ type Span = { readonly start: number; readonly end: number };
10
+
11
+ /** 言語パッケージの語彙表から読む、名前の部品の語と決まり文句。字面どおりに照らす。 */
12
+ export type NameWords = {
13
+ /** 会社名の後ろに大文字で書く法人の形(LLC、INC、SE、PTE、PTY)。 */
14
+ readonly legalForms: readonly string[];
15
+ /** 名詞の前に置く限定の語(the、this、each)。文の頭で大文字になっても(The SE team)名前の語ではない。大小を問わずに照らす。 */
16
+ readonly determiners: readonly string[];
17
+ /** 法令・官報の引用の大文字の部分(45 CFR §164、21 USC §301、94/820/EC)。 */
18
+ readonly citationSeries: readonly string[];
19
+ /** 運送会社の名前(UPS、DHL、Federal Express)。2 社以上を並べたときだけ名前と読む。 */
20
+ readonly carriers: readonly string[];
21
+ /** 大文字で始まる語の前に置いて名前を作る語(HM Revenue & Customs、HMS Victory)。 */
22
+ readonly namePrefixes: readonly string[];
23
+ /** 番地と通りの名前の後ろに書く、通りの種類の略し(512 Bayshore DR)。 */
24
+ readonly streetSuffixes: readonly string[];
25
+ /** 大文字で書く決まり文句(NOW, THEREFORE、AND/OR)。句のままでだけ外す。OR だけなら Oregon でもある。 */
26
+ readonly capitalPhrases: readonly string[];
27
+ };
28
+
29
+ const EDGE_BEFORE = String.raw`(?<![\p{L}\p{N}_&])`;
30
+ const EDGE_AFTER = String.raw`(?![\p{L}\p{N}_&])`;
31
+
32
+ /**
33
+ * 語彙表の語のどれか。空の語彙表は「その書き方が無い」。空の選択肢 (?:) は至る所で空文字に当たるので、何にも当たらない形にする。
34
+ * 長い語から試す。短い語が先だと、それを頭に持つ長い語(PTE と PTE. のような書き分け)が丸ごと当たらない。
35
+ */
36
+ export const oneOf = (words: readonly string[]): string =>
37
+ words.length === 0
38
+ ? "(?!)"
39
+ : `(?:${words
40
+ .toSorted((left, right) => right.length - left.length)
41
+ .map(escapeRegExp)
42
+ .join("|")})`;
43
+
44
+ const spansOf = (text: string, pattern: RegExp): Span[] =>
45
+ [...text.matchAll(pattern)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
46
+
47
+ /** 名前の語。大文字で始まり、点・& ・アポストロフィ・ハイフンを含んでよい(BorrowMoney.com、PTE.、O'Neil)。 */
48
+ const NAME_WORD = String.raw`\p{Lu}[\p{L}\p{N}&.'’-]*`;
49
+ /** 法人の形の前に並ぶ名前の語の数の上限(CNH INDUSTRIAL SOUTH DAKOTA, INC.)。文の頭まで遡って別の語を名前に入れないため。 */
50
+ const NAME_WORDS_MAX = 5;
51
+
52
+ /**
53
+ * 名前の語のすぐ後ろ(読点を挟んでもよい)の法人の形と、その前の名前(JVLS, LLC、CPM Medical Consultants LLC、TRATON SE、
54
+ * GitLab Singapore PTE. LTD.)。名前の語は空白だけで続くものを数え、読点で切れた先(CENTENE CORPORATION, MAYFLOWER …)は入れない。
55
+ * 名前に続けて書いた括弧のすぐ後ろの形(SUNCALL(Guangzhou)CO.,LTD.)も名前の終わり。空白を挟んだ括弧(Section (A) LLC)は名前の一部ではない。形のすぐ前が限定の語なら名前ではない(The SE team)。
56
+ */
57
+ export const companyNameSpans = (text: string, forms: readonly string[], determiners: readonly string[]): Span[] => {
58
+ if (forms.length === 0) return [];
59
+ const single = `${oneOf(forms)}${EDGE_AFTER}`;
60
+ // 形を重ねて書く(PTE. LTD.、CO.,LTD.)。
61
+ const form = String.raw`${single}(?:\.?,?[ \t]*${single})*`;
62
+ const named = new RegExp(String.raw`${EDGE_BEFORE}(?:${NAME_WORD}[ \t]+){0,${NAME_WORDS_MAX - 1}}(?<last>${NAME_WORD})(?:,[ \t]*|[ \t]+)${form}`, "gu");
63
+ const bracketed = new RegExp(String.raw`(?<=${NAME_WORD}[((][\p{L} ]+[))][ \t]*)${form}`, "gu");
64
+ const determiner = new Set(determiners.map((word) => word.toLowerCase()));
65
+ const names = [...text.matchAll(named)].filter((match) => !determiner.has((match.groups?.["last"] ?? "").toLowerCase()));
66
+ return [...names.map((match) => ({ start: match.index, end: match.index + match[0].length })), ...spansOf(text, bracketed)];
67
+ };
68
+
69
+ /** 通貨の記号に付けた大文字(USD$、AU$10、US$ 5)。国や通貨の印で、略語ではない。 */
70
+ const CURRENCY_PREFIX = new RegExp(String.raw`${EDGE_BEFORE}\p{Lu}{1,3}(?=[$€£¥])`, "gu");
71
+
72
+ export const currencySymbolSpans = (text: string): Span[] => spansOf(text, CURRENCY_PREFIX);
73
+
74
+ /**
75
+ * 引用の形の中の、法令の名前(45 CFR Parts 160、CFR §164.524、21 USC §301、22 CCR §§ 12701、94/820/EC)。後ろに条(§、Part、
76
+ * 番号)があるか、/ で繋いだ番号の後ろのときだけ。法令集そのものを言う所(the CFR title、the 2 CFR export)は略語のまま数える。
77
+ */
78
+ export const citationSpans = (text: string, series: readonly string[]): Span[] => {
79
+ if (series.length === 0) return [];
80
+ const name = oneOf(series);
81
+ return spansOf(text, new RegExp(String.raw`(?<=\d/)${name}${EDGE_AFTER}|${EDGE_BEFORE}${name}(?=[ \t]*(?:§|[Pp]arts?[ \t]+\d|\d))`, "gu"));
82
+ };
83
+
84
+ /** 運送会社の名前。同じ文に 2 社以上を並べた所(Federal Express, UPS, DHL)だけ、どれも名前と読む。1 社だけの UPS は電源装置でもある。 */
85
+ export const carrierListSpans = (text: string, carriers: readonly string[]): Span[] => {
86
+ if (carriers.length === 0) return [];
87
+ const pattern = new RegExp(`${EDGE_BEFORE}${oneOf(carriers)}${EDGE_AFTER}`, "gu");
88
+ const spans = spansOf(text, pattern);
89
+ return new Set(spans.map((span) => text.slice(span.start, span.end))).size < 2 ? [] : spans;
90
+ };
91
+
92
+ /** 大文字で始まる語の前に置いた、名前を作る語(HM Revenue & Customs、HM Treasury)。 */
93
+ export const namePrefixSpans = (text: string, prefixes: readonly string[]): Span[] =>
94
+ prefixes.length === 0 ? [] : spansOf(text, new RegExp(String.raw`${EDGE_BEFORE}${oneOf(prefixes)}(?=[ \t]+\p{Lu}\p{Ll})`, "gu"));
95
+
96
+ /** 番地と、大文字で始まり小文字が続く通りの名前の後ろの、通りの種類(512 Bayshore DR、4060 Johns Creek PKWY)。3 AI CT は住所ではない。 */
97
+ export const streetSuffixSpans = (text: string, suffixes: readonly string[]): Span[] =>
98
+ suffixes.length === 0
99
+ ? []
100
+ : spansOf(text, new RegExp(String.raw`(?<=${EDGE_BEFORE}\d+[A-Z]?[ \t]+(?:\p{Lu}\p{Ll}[\p{L}'’.-]*[ \t]+){1,3})${oneOf(suffixes)}${EDGE_AFTER}`, "gu"));
101
+
102
+ /** 大文字で書く決まり文句(NOW, THEREFORE、AND/OR)。 */
103
+ export const capitalPhraseSpans = (text: string, phrases: readonly string[]): Span[] =>
104
+ phrases.length === 0 ? [] : spansOf(text, new RegExp(`${EDGE_BEFORE}${oneOf(phrases)}${EDGE_AFTER}`, "gu"));
105
+
106
+ /** 文の中で、名前の部品と決まり文句として略語から外す大文字を含む範囲。語彙表から一度だけ組み立てて、文ごとに呼ぶ。 */
107
+ export const nameSpansOf =
108
+ (words: NameWords) =>
109
+ (text: string): Span[] => [
110
+ ...companyNameSpans(text, words.legalForms, words.determiners),
111
+ ...currencySymbolSpans(text),
112
+ ...citationSpans(text, words.citationSeries),
113
+ ...carrierListSpans(text, words.carriers),
114
+ ...namePrefixSpans(text, words.namePrefixes),
115
+ ...streetSuffixSpans(text, words.streetSuffixes),
116
+ ...capitalPhraseSpans(text, words.capitalPhrases),
117
+ ];
@@ -0,0 +1,12 @@
1
+ import type { ProseDocument } from "../plugin.ts";
2
+ import type { AgeWord, AgeWords } from "../facts/age-values.ts";
3
+
4
+ const ageWordsAt = (doc: ProseDocument, id: string): AgeWord[] =>
5
+ (doc.lexicons[id] ?? []).map((entry): AgeWord => ({ pattern: entry.pattern, position: entry.position ?? "before" }));
6
+
7
+ /** 年齢の語: 印(fact-age-mark)、上限の印(fact-age-limit)、範囲をつなぐ語(fact-age-joiner)。 */
8
+ export const ageWordsOf = (doc: ProseDocument): AgeWords => ({
9
+ marks: ageWordsAt(doc, "fact-age-mark"),
10
+ limits: ageWordsAt(doc, "fact-age-limit"),
11
+ joiners: (doc.lexicons["fact-age-joiner"] ?? []).map((entry) => entry.pattern),
12
+ });
@@ -3,9 +3,8 @@
3
3
  // are annual-pay-label, the other words annual-pay-word, approximate-marker, duration-month, number-word (digit),
4
4
  // range-connector and amount-range-word.
5
5
  import type { Detector, Finding, Lexicon, ProseDocument } from "../plugin.ts";
6
- import { annualPayMismatches, type AnnualPayWords, type PayAmount, type PositionedWord } from "../structure/annual-pay.ts";
7
- import { scaledAmountOf, scaleWordsOf } from "./amount-scale.ts";
8
- import { amountsIn, formsOf } from "./currency-notation.ts";
6
+ import { annualPayMismatches, type AnnualPayWords, type PositionedWord } from "../structure/annual-pay.ts";
7
+ import { statedAmountsOf } from "./stated-amounts.ts";
9
8
  import { proseAndTablesOf } from "../table-text.ts";
10
9
  import { quoteAround } from "./quote-around.ts";
11
10
 
@@ -44,23 +43,9 @@ const wordsOf = (doc: ProseDocument): AnnualPayWords => ({
44
43
  numberWords: numberWordsOf(doc),
45
44
  });
46
45
 
47
- const amountsOf = (text: string, doc: ProseDocument): PayAmount[] => {
48
- const scales = scaleWordsOf(doc);
49
- return amountsIn(
50
- text,
51
- formsOf(doc),
52
- scales.map((scale) => scale.word),
53
- ).flatMap((amount) => {
54
- const read = scaledAmountOf(text, amount, scales);
55
- return read === undefined
56
- ? []
57
- : [{ offset: read.offset, end: amount.offset + amount.written.length, currency: read.currency, value: read.value, scale: read.unit }];
58
- });
59
- };
60
-
61
46
  export const annualPayMismatch: Detector = (doc): Finding[] => {
62
47
  const text = proseAndTablesOf(doc);
63
- return annualPayMismatches(text, amountsOf(text, doc), wordsOf(doc)).map((issue) => ({
48
+ return annualPayMismatches(text, statedAmountsOf(text, doc), wordsOf(doc)).map((issue) => ({
64
49
  rule: "annual-pay-mismatch",
65
50
  severity: "warning",
66
51
  line: 0,
@@ -7,7 +7,7 @@ import { eachPreOrder, foldPostOrder } from "../tree-walk.ts";
7
7
  import { quoteAt } from "./structure-tree.ts";
8
8
  import { amountColumnOf, isTotalRowGap, type BodyRow } from "../structure/total-row-blank.ts";
9
9
  import { isAmountNameLine, isTotalLine } from "../structure/total-line.ts";
10
- import { isTotalLabel } from "../structure/total.ts";
10
+ import { isTotalLabel, withoutLeadingBlankCells } from "../structure/total.ts";
11
11
 
12
12
  /** Fewer body rows than this, and one blank is as likely a choice as a gap. */
13
13
  const MIN_BODY_ROWS = 3;
@@ -178,7 +178,8 @@ const patternsOf = (doc: ProseDocument, lexicon: string): string[] => (doc.lexic
178
178
 
179
179
  /**
180
180
  * A total row starts with a total word (total-label, with total-label-qualifier or total-period-qualifier: Week total),
181
- * a tax word (tax-label), or is named by a computed amount (net-amount-label: Gross pay, Net pay).
181
+ * a tax word (tax-label), or is named by a computed amount (net-amount-label: Gross pay, Net pay). The word may sit in the
182
+ * first cell that is not blank (| | Total | $1,200 |): the cells before it are left blank on purpose.
182
183
  */
183
184
  const totalRowOf = (doc: ProseDocument): IsTotalRow => {
184
185
  const totals = {
@@ -188,7 +189,7 @@ const totalRowOf = (doc: ProseDocument): IsTotalRow => {
188
189
  amountNames: patternsOf(doc, "net-amount-label"),
189
190
  };
190
191
  const taxes = patternsOf(doc, "tax-label");
191
- return (rowText) => isTotalLine(rowText, totals) || isAmountNameLine(rowText, totals) || isTotalLabel(rowText, taxes);
192
+ return (rowText) => isTotalLine(rowText, totals) || isAmountNameLine(rowText, totals) || isTotalLabel(withoutLeadingBlankCells(rowText), taxes);
192
193
  };
193
194
 
194
195
  export const emptyTableCell: Detector = findingsOf("empty-table-cell", (doc) => tableBlanks(doc.source, doc.replyQuotes ?? [], totalRowOf(doc)));
@@ -16,6 +16,18 @@ export type CapitalisedWords = {
16
16
  readonly divisions: readonly string[];
17
17
  /** Small words inside one name (Statement of Work, Trials and Betas). */
18
18
  readonly joiners: readonly string[];
19
+ /** Words that end a longer name the run only starts (Federal Food, Drug, and Cosmetic Act). */
20
+ readonly nameEnds: readonly string[];
21
+ /** Company forms and places, which end a name right after a comma too (Post Holdings, Inc.; Canton, Ohio). */
22
+ readonly formEnds: readonly string[];
23
+ /** Words before the quoted label in brackets that define the run ((the "FDA")). */
24
+ readonly definitionMarkers: readonly string[];
25
+ /** Words opening brackets that say where the run is defined ((as defined in the Merger Agreement)). */
26
+ readonly definedElsewhere: readonly string[];
27
+ /** Words before a party's capacity after its name (Citibank, N.A., as Administrative Agent). */
28
+ readonly capacityMarkers: readonly string[];
29
+ /** Articles, which may stand between a capacity word and the capacity (as the Borrower). */
30
+ readonly articles: readonly string[];
19
31
  };
20
32
 
21
33
  /** A term the document defines; bare is a definition with no defining word (("GPC")), which names more than it defines. */
@@ -100,15 +112,144 @@ const writtenInLowerCase = (text: string, term: string): boolean => {
100
112
  return new RegExp(String.raw`(?<!\p{L})${words}(?:e?s)?(?!\p{L})`, "u").test(text);
101
113
  };
102
114
 
115
+ /** How many tokens past a run a longer name may still end (’s Investors Service, Inc: five). */
116
+ const NAME_REACH = 8;
117
+ /** Marks inside one name: Post Holdings, Inc; Davis Polk & Wardwell LLP; Moody’s Investors Service. */
118
+ const NAME_GLUE = new Set([",", "&", ".", "'s", "’s"]);
119
+ const DIGIT_START = /^\d/u;
120
+
121
+ /** The last word of each name-ending entry (Kingdom of United Kingdom), without a closing full stop. */
122
+ const lastWordsOf = (entries: readonly string[]): Set<string> =>
123
+ new Set(
124
+ entries
125
+ .flatMap((entry) =>
126
+ entry
127
+ .split(/[\s,]+/u)
128
+ .filter((word) => word !== "")
129
+ .slice(-1),
130
+ )
131
+ .map((word) => word.replace(/\.$/u, "")),
132
+ );
133
+
134
+ /** Commas in a serial name's list (Federal Food, Drug, and Cosmetic Act). */
135
+ const SERIAL_COMMAS = 2;
136
+
137
+ type NameEnds = { readonly names: ReadonlySet<string>; readonly forms: ReadonlySet<string>; readonly formEntries: ReadonlySet<string> };
138
+
139
+ /**
140
+ * Across a comma, a company form or a place ends the run's name only as the whole of what follows the comma (Post
141
+ * Holdings, Inc; London, United Kingdom), and a name word only at the end of a serial list of two commas, the last
142
+ * followed by a joiner (Federal Food, Drug, and Cosmetic Act): Confidential Information, Receiving Party and Servicer,
143
+ * Navistar Securities Corporation are two things each.
144
+ */
145
+ const endsName = (glued: readonly Token[], at: number, ends: NameEnds, joiners: ReadonlySet<string>): boolean => {
146
+ const surface = glued[at]?.surface ?? "";
147
+ const before = glued.slice(0, at);
148
+ const surfaces = before.map((token) => token.surface);
149
+ const comma = surfaces.lastIndexOf(",");
150
+ if (comma === -1) return ends.forms.has(surface) || ends.names.has(surface);
151
+ const afterComma = glued.slice(comma + 1, at + 1);
152
+ if (ends.formEntries.has(afterComma.map((token) => token.surface).join(" "))) return true;
153
+ const commas = surfaces.filter((each) => each === ",").length;
154
+ return ends.names.has(surface) && commas >= SERIAL_COMMAS && joiners.has(afterComma[0]?.surface ?? "");
155
+ };
156
+
157
+ /** The run only starts a longer name: the words after it, joined by commas, ampersands and joiners, reach a word that ends a name. */
158
+ const startsLongerName = (tokens: readonly Token[], end: number, ends: NameEnds, joiners: ReadonlySet<string>): boolean => {
159
+ const reach = tokens.slice(end, end + NAME_REACH);
160
+ const stop = reach.findIndex((token, at) => {
161
+ const before = tokens[end + at - 1];
162
+ return before === undefined || !adjacent(before, token) || !(NAME_GLUE.has(token.surface) || joiners.has(token.surface) || continues(token));
163
+ });
164
+ const glued = reach.slice(0, stop === -1 ? reach.length : stop);
165
+ return glued.some((_, at) => endsName(glued, at, ends, joiners));
166
+ };
167
+
168
+ /** A number right after the run makes it a numbered name (Proposition 65, Vaccines 2Go) or a contents line's page. */
169
+ const numberedName = (last: Token, after: Token | undefined): boolean => after !== undefined && adjacent(last, after) && DIGIT_START.test(after.surface);
170
+
171
+ /** The words as written and with their first letter capitalised (the, The), as one alternation. */
172
+ const alternativesOf = (words: readonly string[]): string =>
173
+ words
174
+ .filter((word) => word !== "")
175
+ .flatMap((word) => [word, word.charAt(0).toUpperCase() + word.slice(1)])
176
+ .map(escapeRegExp)
177
+ .join("|");
178
+
179
+ /** A quoted label: a capitalised word or more in quotes, closing the brackets or followed by another label ("Buyer" or "PNC"). */
180
+ const QUOTED_LABEL = String.raw`["“]\p{Lu}[^"“”\n]{0,60}["”][ \t]*(?:\)|,|;|or[ \t]|and[ \t])`;
181
+
182
+ /**
183
+ * Brackets right after a run that define it, so the run is what a definition names, not a term in use: a quoted label
184
+ * (Food and Drug Administration (the "FDA"), Certificate of Analysis ("COA")) or a pointer to where it is defined
185
+ * (Closing (as defined in the Merger Agreement)). A quoted phrase in lower case (("including records")) is no label.
186
+ */
187
+ const definitionAfterPattern = (words: CapitalisedWords): RegExp => {
188
+ const markers = alternativesOf(words.definitionMarkers);
189
+ const elsewhere = alternativesOf(words.definedElsewhere);
190
+ const label = markers === "" ? QUOTED_LABEL : String.raw`(?:(?:${markers})[ \t]+)*${QUOTED_LABEL}`;
191
+ const opening = elsewhere === "" ? label : String.raw`(?:${label}|(?:${elsewhere})(?!\p{L}))`;
192
+ return new RegExp(String.raw`^[ \t]*\([ \t]*${opening}`, "u");
193
+ };
194
+
195
+ /** How much text after a run the bracket check reads. */
196
+ const DEFINITION_AFTER_CHARS = 120;
197
+
198
+ /** The initials of a run's words, with and without its joiners (PFHOF and PFHF for Pro Football Hall of Fame). */
199
+ const initialsOf = (term: string, joiners: ReadonlySet<string>): string[] => {
200
+ const words = term.split(/[\s-]+/u).filter((word) => word !== "");
201
+ const initials = (kept: readonly string[]): string => kept.map((word) => word.charAt(0).toUpperCase()).join("");
202
+ return words.length < 2 ? [] : [initials(words), initials(words.filter((word) => !joiners.has(word)))];
203
+ };
204
+
205
+ /**
206
+ * The run names the capacity a named party acts in, in a list of parties to some agreement (Citibank, N.A., as
207
+ * Administrative Agent; the Company, as the Borrower): the name, a comma, a capacity word and perhaps an article.
208
+ */
209
+ const capacityOfAName = (tokens: readonly Token[], start: number, words: CapitalisedWords): boolean => {
210
+ const before = tokens[start - 1];
211
+ const at = before !== undefined && words.articles.includes(before.surface) ? start - 2 : start - 1;
212
+ const marker = tokens[at];
213
+ const comma = tokens[at - 1];
214
+ const name = tokens[at - 2];
215
+ if (marker === undefined || comma?.surface !== "," || name === undefined) return false;
216
+ return words.capacityMarkers.includes(marker.surface) && (continues(name) || name.surface === ".");
217
+ };
218
+
219
+ /**
220
+ * Whether a run is a name by what surrounds it: a number after it, a longer name it starts, brackets after it that
221
+ * define it, initials that spell a term the document defines (“IRS” means the Internal Revenue Service), or a capacity.
222
+ */
223
+ type NameCue = (tokens: readonly Token[], start: number, end: number, term: string) => boolean;
224
+
225
+ const nameCues = (input: CapitalisedInput, joiners: ReadonlySet<string>): NameCue => {
226
+ const words = input.words;
227
+ const ends = { names: lastWordsOf(words.nameEnds), forms: lastWordsOf(words.formEnds), formEntries: new Set(words.formEnds) };
228
+ const definitionAfter = definitionAfterPattern(words);
229
+ const abbreviations = new Set([...input.defined.map((definition) => definition.term), ...input.named].filter((term) => ACRONYM.test(term)));
230
+ return (tokens, start, end, term) => {
231
+ const last = tokens[end - 1];
232
+ if (last === undefined) return false;
233
+ return (
234
+ numberedName(last, tokens[end]) ||
235
+ startsLongerName(tokens, end, ends, joiners) ||
236
+ definitionAfter.test(input.source.slice(last.span.end, last.span.end + DEFINITION_AFTER_CHARS)) ||
237
+ initialsOf(term, joiners).some((initials) => abbreviations.has(initials)) ||
238
+ capacityOfAName(tokens, start, words)
239
+ );
240
+ };
241
+ };
242
+
103
243
  /**
104
244
  * The first use of each capitalised run used inside a sentence like a defined term that names nothing the language
105
245
  * package lists, is not set apart by markup, is never written in lower case, and neither is nor holds a defined or named
106
- * term in any case.
246
+ * term in any case. A run that starts a longer name, carries a number, or is defined by the brackets after it is a name.
107
247
  */
108
248
  export const capitalisedTerms = (input: CapitalisedInput): CapitalisedTerm[] => {
109
249
  const defining = input.defined.filter((definition) => definition.bare !== true && DEFINED_FORM.test(definition.term));
110
250
  if (defining.length < MIN_DEFINED) return [];
111
251
  const joiners = new Set(input.words.joiners);
252
+ const isName = nameCues(input, joiners);
112
253
  const divisions = new Set(input.words.divisions.flatMap(formsOf));
113
254
  const known = new Set([...input.defined.map((definition) => definition.term), ...input.named, ...input.words.names].flatMap(formsOf));
114
255
  const isKnown = (term: string): boolean => partsOf(term).some((part) => formsOf(part).some((form) => known.has(form)));
@@ -119,7 +260,8 @@ export const capitalisedTerms = (input: CapitalisedInput): CapitalisedTerm[] =>
119
260
  if (first === undefined || last === undefined || !placedLikeATerm(tokens[start - 1], tokens[end])) return [];
120
261
  if (inside(first.span.start, input.marked) || formsOf(first.surface).some((form) => divisions.has(form))) return [];
121
262
  const term = input.source.slice(first.span.start, last.span.end);
122
- return isKnown(term) || writtenInLowerCase(input.readable, term) ? [] : [{ offset: first.span.start, term }];
263
+ if (isKnown(term) || isName(tokens, start, end, term)) return [];
264
+ return writtenInLowerCase(input.readable, term) ? [] : [{ offset: first.span.start, term }];
123
265
  }),
124
266
  );
125
267
  return uses.filter((use, index) => uses.findIndex((other) => formsOf(other.term).some((form) => formsOf(use.term).includes(form))) === index);
@@ -130,12 +272,20 @@ const QUOTED = /["“]([^"“”\n]{1,80}?)[,.]?["”]/gu;
130
272
  const HTML_ELEMENT = /<([a-z][a-z0-9]*)\b[^>]*>[^<]*<\/\1>/giu;
131
273
  const TABLE_ROW = /^[ \t]*\|.*$/gmu;
132
274
  const ITEM_LABEL = /^[ \t]*(?:[*+-]|\d+[.)])[ \t]+[^:\n]{1,80}:/gmu;
275
+ const CAPTION_WORD = String.raw`\p{Lu}[\p{L}'’-]*`;
276
+ const CAPTION_SMALL = String.raw`(?:of|and|or|to|the|for|with|in|on|a|an|by|from|under|upon|as|at|not)[ \t]+`;
277
+ /** A clause's run-in caption: its number, then capitalised words up to a full stop or colon (5.8 No Representation or Warranty.). */
278
+ const CAPTION = new RegExp(
279
+ String.raw`(?:^|(?<=[.;:][ \t]+))[ \t]*(?:(?:Section|Article|SECTION|ARTICLE)[ \t]+)?(?:\d+(?:\.\d+)*\.?|\([a-z\d]{1,4}\))[ \t]+` +
280
+ String.raw`${CAPTION_WORD}(?:(?:[ \t]+|[;,][ \t]*)(?:${CAPTION_SMALL})*${CAPTION_WORD}){0,10}(?=[.:](?:\s|$))`,
281
+ "gmu",
282
+ );
133
283
 
134
284
  const spansOf = (source: string, pattern: RegExp): Span[] =>
135
285
  [...source.matchAll(pattern)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
136
286
 
137
- /** Bold, HTML elements, table rows and list items' labels in a Markdown source: labels and cells, not running text. */
138
- export const setApartSpans = (source: string): Span[] => [BOLD, HTML_ELEMENT, TABLE_ROW, ITEM_LABEL].flatMap((pattern) => spansOf(source, pattern));
287
+ /** Bold, HTML elements, table rows, list items' labels and clauses' run-in captions: labels and cells, not running text. */
288
+ export const setApartSpans = (source: string): Span[] => [BOLD, HTML_ELEMENT, TABLE_ROW, ITEM_LABEL, CAPTION].flatMap((pattern) => spansOf(source, pattern));
139
289
 
140
290
  const LINK_DESTINATION = /\]\([^)\n]*\)|<?https?:\/\/[^\s)>]+>?/gu;
141
291
 
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Captions set in capitals: a capital run that opens a paragraph and ends in a colon ("AGENCY:", "DIRECT HIRE AUTHORITY:
3
+ * This position is …"), or that is a paragraph of its own ("WORKING GROUP MEMBERS"). Notices, forms and reports set their
4
+ * captions this way by convention, and prose that names one ("the FOR FURTHER INFORMATION CONTACT section") repeats it.
5
+ * A line of a hard-wrapped paragraph in capitals (a disclaimer) has text above it, so it is no caption.
6
+ */
7
+
8
+ /** Markdown heading or list marks and spaces that may stand before a caption on its line. */
9
+ const LINE_LEAD = /^[ \t]*(?:#{1,6}[ \t]+|[-*+][ \t]+)?$/u;
10
+ const BLANK_LINE = /^[ \t\r]*$/u;
11
+ const LINE_END = /^[ \t\r]*(?:\n|$)/u;
12
+ const LEAD = /^[ \t]*(?:#{1,6}[ \t]+|[-*+][ \t]+)?/u;
13
+ const CAPITAL_RUN = /^[A-Z][A-Z']*(?:,? [A-Z][A-Z']*)*/u;
14
+
15
+ /** The line before the one that starts at lineStart, or undefined at the start of the source. */
16
+ const lineBefore = (source: string, lineStart: number): string | undefined =>
17
+ lineStart === 0 ? undefined : source.slice(source.lastIndexOf("\n", lineStart - 2) + 1, lineStart - 1);
18
+
19
+ const opensParagraph = (source: string, lineStart: number): boolean => {
20
+ const above = lineBefore(source, lineStart);
21
+ return above === undefined || BLANK_LINE.test(above);
22
+ };
23
+
24
+ /** Whether the text after a run ends the caption: a colon, or the end of a paragraph. */
25
+ const endsCaption = (rest: string): boolean => {
26
+ if (rest.startsWith(":")) return true;
27
+ if (!LINE_END.test(rest)) return false;
28
+ const next = rest.slice(rest.indexOf("\n") + 1).split("\n", 1)[0] ?? "";
29
+ return !rest.includes("\n") || BLANK_LINE.test(next);
30
+ };
31
+
32
+ /** Whether the capital run at [start, end) of the source is a caption: it opens its paragraph and ends in a colon or the paragraph's end. */
33
+ export const isCaptionAt = (source: string, start: number, end: number): boolean => {
34
+ const lineStart = source.lastIndexOf("\n", start - 1) + 1;
35
+ return LINE_LEAD.test(source.slice(lineStart, start)) && opensParagraph(source, lineStart) && endsCaption(source.slice(end));
36
+ };
37
+
38
+ /** The capital run that opens a line, after its heading or list mark, with where it starts in the source. */
39
+ const runOpening = (line: string, lineStart: number): { readonly words: string; readonly start: number } | undefined => {
40
+ const lead = LEAD.exec(line)?.[0].length ?? 0;
41
+ const words = CAPITAL_RUN.exec(line.slice(lead))?.[0];
42
+ return words === undefined ? undefined : { words, start: lineStart + lead };
43
+ };
44
+
45
+ /** The captions a source sets in capitals, each as its words ("FOR FURTHER INFORMATION CONTACT"). */
46
+ export const captionsOf = (source: string): ReadonlySet<string> => {
47
+ const lines = source.split("\n");
48
+ const starts = lines.reduce<number[]>(
49
+ (acc, line) => {
50
+ acc.push((acc.at(-1) ?? 0) + line.length + 1);
51
+ return acc;
52
+ },
53
+ [0],
54
+ );
55
+ return new Set(
56
+ lines.flatMap((line, at) => {
57
+ const run = runOpening(line, starts[at] ?? 0);
58
+ return run !== undefined && isCaptionAt(source, run.start, run.start + run.words.length) ? [run.words] : [];
59
+ }),
60
+ );
61
+ };