chaffjs 0.34.0 → 0.36.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 (976) hide show
  1. package/README.ja.md +12 -0
  2. package/README.md +15 -0
  3. package/dist/announced-count.d.ts +2 -0
  4. package/dist/announced-count.d.ts.map +1 -1
  5. package/dist/announced-count.js +29 -7
  6. package/dist/announced-count.js.map +1 -1
  7. package/dist/capitals-passage.d.ts +3 -0
  8. package/dist/capitals-passage.d.ts.map +1 -0
  9. package/dist/capitals-passage.js +26 -0
  10. package/dist/capitals-passage.js.map +1 -0
  11. package/dist/chronology-rows.d.ts +9 -0
  12. package/dist/chronology-rows.d.ts.map +1 -0
  13. package/dist/chronology-rows.js +79 -0
  14. package/dist/chronology-rows.js.map +1 -0
  15. package/dist/coined-hyphen-name.d.ts +13 -0
  16. package/dist/coined-hyphen-name.d.ts.map +1 -0
  17. package/dist/coined-hyphen-name.js +21 -0
  18. package/dist/coined-hyphen-name.js.map +1 -0
  19. package/dist/company-name-run.d.ts +8 -0
  20. package/dist/company-name-run.d.ts.map +1 -0
  21. package/dist/company-name-run.js +30 -0
  22. package/dist/company-name-run.js.map +1 -0
  23. package/dist/company-names.d.ts +6 -1
  24. package/dist/company-names.d.ts.map +1 -1
  25. package/dist/company-names.js +22 -3
  26. package/dist/company-names.js.map +1 -1
  27. package/dist/compound-head.d.ts +7 -0
  28. package/dist/compound-head.d.ts.map +1 -0
  29. package/dist/compound-head.js +19 -0
  30. package/dist/compound-head.js.map +1 -0
  31. package/dist/date-format.d.ts +8 -3
  32. package/dist/date-format.d.ts.map +1 -1
  33. package/dist/date-format.js +36 -3
  34. package/dist/date-format.js.map +1 -1
  35. package/dist/derived/count-per-period.d.ts +23 -0
  36. package/dist/derived/count-per-period.d.ts.map +1 -0
  37. package/dist/derived/count-per-period.js +14 -0
  38. package/dist/derived/count-per-period.js.map +1 -0
  39. package/dist/detectors/acronym-context.d.ts +5 -1
  40. package/dist/detectors/acronym-context.d.ts.map +1 -1
  41. package/dist/detectors/acronym-context.js +32 -4
  42. package/dist/detectors/acronym-context.js.map +1 -1
  43. package/dist/detectors/acronym-definition.d.ts +13 -0
  44. package/dist/detectors/acronym-definition.d.ts.map +1 -0
  45. package/dist/detectors/acronym-definition.js +90 -0
  46. package/dist/detectors/acronym-definition.js.map +1 -0
  47. package/dist/detectors/acronym-expansion.d.ts +5 -1
  48. package/dist/detectors/acronym-expansion.d.ts.map +1 -1
  49. package/dist/detectors/acronym-expansion.js +35 -3
  50. package/dist/detectors/acronym-expansion.js.map +1 -1
  51. package/dist/detectors/acronym-known.d.ts +19 -0
  52. package/dist/detectors/acronym-known.d.ts.map +1 -0
  53. package/dist/detectors/acronym-known.js +32 -0
  54. package/dist/detectors/acronym-known.js.map +1 -0
  55. package/dist/detectors/acronym-link.d.ts +14 -0
  56. package/dist/detectors/acronym-link.d.ts.map +1 -0
  57. package/dist/detectors/acronym-link.js +32 -0
  58. package/dist/detectors/acronym-link.js.map +1 -0
  59. package/dist/detectors/acronym-lone.d.ts +13 -0
  60. package/dist/detectors/acronym-lone.d.ts.map +1 -0
  61. package/dist/detectors/acronym-lone.js +22 -0
  62. package/dist/detectors/acronym-lone.js.map +1 -0
  63. package/dist/detectors/acronym-name.d.ts +62 -0
  64. package/dist/detectors/acronym-name.d.ts.map +1 -0
  65. package/dist/detectors/acronym-name.js +94 -0
  66. package/dist/detectors/acronym-name.js.map +1 -0
  67. package/dist/detectors/addressee-edge.d.ts +13 -0
  68. package/dist/detectors/addressee-edge.d.ts.map +1 -0
  69. package/dist/detectors/addressee-edge.js +13 -0
  70. package/dist/detectors/addressee-edge.js.map +1 -0
  71. package/dist/detectors/announced-count.d.ts.map +1 -1
  72. package/dist/detectors/announced-count.js +1 -0
  73. package/dist/detectors/announced-count.js.map +1 -1
  74. package/dist/detectors/bare-comparative.d.ts +4 -0
  75. package/dist/detectors/bare-comparative.d.ts.map +1 -1
  76. package/dist/detectors/bare-comparative.js +28 -3
  77. package/dist/detectors/bare-comparative.js.map +1 -1
  78. package/dist/detectors/blank-structure.d.ts +7 -1
  79. package/dist/detectors/blank-structure.d.ts.map +1 -1
  80. package/dist/detectors/blank-structure.js +13 -8
  81. package/dist/detectors/blank-structure.js.map +1 -1
  82. package/dist/detectors/bracket-specified.d.ts +6 -0
  83. package/dist/detectors/bracket-specified.d.ts.map +1 -0
  84. package/dist/detectors/bracket-specified.js +23 -0
  85. package/dist/detectors/bracket-specified.js.map +1 -0
  86. package/dist/detectors/broken-link.d.ts +6 -0
  87. package/dist/detectors/broken-link.d.ts.map +1 -1
  88. package/dist/detectors/broken-link.js +23 -2
  89. package/dist/detectors/broken-link.js.map +1 -1
  90. package/dist/detectors/capitalised-term.d.ts +14 -2
  91. package/dist/detectors/capitalised-term.d.ts.map +1 -1
  92. package/dist/detectors/capitalised-term.js +115 -4
  93. package/dist/detectors/capitalised-term.js.map +1 -1
  94. package/dist/detectors/caps-caption.d.ts +12 -0
  95. package/dist/detectors/caps-caption.d.ts.map +1 -0
  96. package/dist/detectors/caps-caption.js +89 -0
  97. package/dist/detectors/caps-caption.js.map +1 -0
  98. package/dist/detectors/caps-phrase.d.ts +6 -0
  99. package/dist/detectors/caps-phrase.d.ts.map +1 -0
  100. package/dist/detectors/caps-phrase.js +16 -0
  101. package/dist/detectors/caps-phrase.js.map +1 -0
  102. package/dist/detectors/char-shape.d.ts +1 -0
  103. package/dist/detectors/char-shape.d.ts.map +1 -1
  104. package/dist/detectors/char-shape.js +72 -30
  105. package/dist/detectors/char-shape.js.map +1 -1
  106. package/dist/detectors/cited-title.d.ts +3 -2
  107. package/dist/detectors/cited-title.d.ts.map +1 -1
  108. package/dist/detectors/cited-title.js +14 -3
  109. package/dist/detectors/cited-title.js.map +1 -1
  110. package/dist/detectors/clause-shape.d.ts +1 -1
  111. package/dist/detectors/clause-shape.d.ts.map +1 -1
  112. package/dist/detectors/clause-shape.js +9 -4
  113. package/dist/detectors/clause-shape.js.map +1 -1
  114. package/dist/detectors/concrete-evidence.d.ts +13 -1
  115. package/dist/detectors/concrete-evidence.d.ts.map +1 -1
  116. package/dist/detectors/concrete-evidence.js +59 -0
  117. package/dist/detectors/concrete-evidence.js.map +1 -1
  118. package/dist/detectors/contraction-minority.d.ts +11 -0
  119. package/dist/detectors/contraction-minority.d.ts.map +1 -0
  120. package/dist/detectors/contraction-minority.js +10 -0
  121. package/dist/detectors/contraction-minority.js.map +1 -0
  122. package/dist/detectors/counter-edge.d.ts +7 -1
  123. package/dist/detectors/counter-edge.d.ts.map +1 -1
  124. package/dist/detectors/counter-edge.js +40 -2
  125. package/dist/detectors/counter-edge.js.map +1 -1
  126. package/dist/detectors/date-any-year.d.ts +12 -5
  127. package/dist/detectors/date-any-year.d.ts.map +1 -1
  128. package/dist/detectors/date-any-year.js +69 -12
  129. package/dist/detectors/date-any-year.js.map +1 -1
  130. package/dist/detectors/date-format.d.ts.map +1 -1
  131. package/dist/detectors/date-format.js +2 -1
  132. package/dist/detectors/date-format.js.map +1 -1
  133. package/dist/detectors/date-heading-year.d.ts +18 -0
  134. package/dist/detectors/date-heading-year.d.ts.map +1 -0
  135. package/dist/detectors/date-heading-year.js +38 -0
  136. package/dist/detectors/date-heading-year.js.map +1 -0
  137. package/dist/detectors/date-year.d.ts +19 -3
  138. package/dist/detectors/date-year.d.ts.map +1 -1
  139. package/dist/detectors/date-year.js +69 -8
  140. package/dist/detectors/date-year.js.map +1 -1
  141. package/dist/detectors/deadline-unit.d.ts +20 -0
  142. package/dist/detectors/deadline-unit.d.ts.map +1 -0
  143. package/dist/detectors/deadline-unit.js +19 -0
  144. package/dist/detectors/deadline-unit.js.map +1 -0
  145. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  146. package/dist/detectors/defined-term-form.js +59 -12
  147. package/dist/detectors/defined-term-form.js.map +1 -1
  148. package/dist/detectors/definition-use.d.ts.map +1 -1
  149. package/dist/detectors/definition-use.js +6 -3
  150. package/dist/detectors/definition-use.js.map +1 -1
  151. package/dist/detectors/derived-numbers.d.ts.map +1 -1
  152. package/dist/detectors/derived-numbers.js +17 -4
  153. package/dist/detectors/derived-numbers.js.map +1 -1
  154. package/dist/detectors/doubled-across-aside.d.ts +9 -0
  155. package/dist/detectors/doubled-across-aside.d.ts.map +1 -0
  156. package/dist/detectors/doubled-across-aside.js +27 -0
  157. package/dist/detectors/doubled-across-aside.js.map +1 -0
  158. package/dist/detectors/doubled-punctuation.d.ts +3 -3
  159. package/dist/detectors/doubled-punctuation.d.ts.map +1 -1
  160. package/dist/detectors/doubled-punctuation.js +23 -4
  161. package/dist/detectors/doubled-punctuation.js.map +1 -1
  162. package/dist/detectors/doubled-word.d.ts.map +1 -1
  163. package/dist/detectors/doubled-word.js +2 -1
  164. package/dist/detectors/doubled-word.js.map +1 -1
  165. package/dist/detectors/due-date.d.ts.map +1 -1
  166. package/dist/detectors/due-date.js +6 -0
  167. package/dist/detectors/due-date.js.map +1 -1
  168. package/dist/detectors/ellipsis.d.ts.map +1 -1
  169. package/dist/detectors/ellipsis.js +13 -1
  170. package/dist/detectors/ellipsis.js.map +1 -1
  171. package/dist/detectors/email-letter.d.ts +31 -1
  172. package/dist/detectors/email-letter.d.ts.map +1 -1
  173. package/dist/detectors/email-letter.js +76 -14
  174. package/dist/detectors/email-letter.js.map +1 -1
  175. package/dist/detectors/en-shape.d.ts.map +1 -1
  176. package/dist/detectors/en-shape.js +5 -1
  177. package/dist/detectors/en-shape.js.map +1 -1
  178. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  179. package/dist/detectors/fact-consistency.js +3 -2
  180. package/dist/detectors/fact-consistency.js.map +1 -1
  181. package/dist/detectors/field-label.d.ts +7 -0
  182. package/dist/detectors/field-label.d.ts.map +1 -0
  183. package/dist/detectors/field-label.js +23 -0
  184. package/dist/detectors/field-label.js.map +1 -0
  185. package/dist/detectors/footnote-mismatch.d.ts +6 -1
  186. package/dist/detectors/footnote-mismatch.d.ts.map +1 -1
  187. package/dist/detectors/footnote-mismatch.js +28 -7
  188. package/dist/detectors/footnote-mismatch.js.map +1 -1
  189. package/dist/detectors/graded-step.d.ts +20 -0
  190. package/dist/detectors/graded-step.d.ts.map +1 -0
  191. package/dist/detectors/graded-step.js +33 -0
  192. package/dist/detectors/graded-step.js.map +1 -0
  193. package/dist/detectors/gram-openers.d.ts +8 -0
  194. package/dist/detectors/gram-openers.d.ts.map +1 -0
  195. package/dist/detectors/gram-openers.js +16 -0
  196. package/dist/detectors/gram-openers.js.map +1 -0
  197. package/dist/detectors/gram-passages.d.ts +11 -0
  198. package/dist/detectors/gram-passages.d.ts.map +1 -0
  199. package/dist/detectors/gram-passages.js +26 -0
  200. package/dist/detectors/gram-passages.js.map +1 -0
  201. package/dist/detectors/gram-place.d.ts +3 -1
  202. package/dist/detectors/gram-place.d.ts.map +1 -1
  203. package/dist/detectors/gram-place.js +8 -0
  204. package/dist/detectors/gram-place.js.map +1 -1
  205. package/dist/detectors/gram-predicate.d.ts.map +1 -1
  206. package/dist/detectors/gram-predicate.js +37 -3
  207. package/dist/detectors/gram-predicate.js.map +1 -1
  208. package/dist/detectors/heading-echo.d.ts.map +1 -1
  209. package/dist/detectors/heading-echo.js +28 -2
  210. package/dist/detectors/heading-echo.js.map +1 -1
  211. package/dist/detectors/heading-end-mark.d.ts +8 -3
  212. package/dist/detectors/heading-end-mark.d.ts.map +1 -1
  213. package/dist/detectors/heading-end-mark.js +18 -8
  214. package/dist/detectors/heading-end-mark.js.map +1 -1
  215. package/dist/detectors/heading-names.d.ts +7 -0
  216. package/dist/detectors/heading-names.d.ts.map +1 -0
  217. package/dist/detectors/heading-names.js +24 -0
  218. package/dist/detectors/heading-names.js.map +1 -0
  219. package/dist/detectors/heading-numbering.d.ts.map +1 -1
  220. package/dist/detectors/heading-numbering.js +7 -2
  221. package/dist/detectors/heading-numbering.js.map +1 -1
  222. package/dist/detectors/ime-residue.d.ts +1 -1
  223. package/dist/detectors/ime-residue.d.ts.map +1 -1
  224. package/dist/detectors/ime-residue.js +4 -3
  225. package/dist/detectors/ime-residue.js.map +1 -1
  226. package/dist/detectors/inch-mark.d.ts +10 -0
  227. package/dist/detectors/inch-mark.d.ts.map +1 -0
  228. package/dist/detectors/inch-mark.js +48 -0
  229. package/dist/detectors/inch-mark.js.map +1 -0
  230. package/dist/detectors/kanji-compound-slip.d.ts +3 -0
  231. package/dist/detectors/kanji-compound-slip.d.ts.map +1 -0
  232. package/dist/detectors/kanji-compound-slip.js +50 -0
  233. package/dist/detectors/kanji-compound-slip.js.map +1 -0
  234. package/dist/detectors/kutoten-consistency.d.ts +10 -2
  235. package/dist/detectors/kutoten-consistency.d.ts.map +1 -1
  236. package/dist/detectors/kutoten-consistency.js +76 -12
  237. package/dist/detectors/kutoten-consistency.js.map +1 -1
  238. package/dist/detectors/lexicon.d.ts +0 -1
  239. package/dist/detectors/lexicon.d.ts.map +1 -1
  240. package/dist/detectors/lexicon.js +37 -25
  241. package/dist/detectors/lexicon.js.map +1 -1
  242. package/dist/detectors/link-shape.d.ts.map +1 -1
  243. package/dist/detectors/link-shape.js +9 -3
  244. package/dist/detectors/link-shape.js.map +1 -1
  245. package/dist/detectors/list-item-ending.d.ts +18 -0
  246. package/dist/detectors/list-item-ending.d.ts.map +1 -0
  247. package/dist/detectors/list-item-ending.js +35 -0
  248. package/dist/detectors/list-item-ending.js.map +1 -0
  249. package/dist/detectors/list-parallel.d.ts +18 -5
  250. package/dist/detectors/list-parallel.d.ts.map +1 -1
  251. package/dist/detectors/list-parallel.js +116 -36
  252. package/dist/detectors/list-parallel.js.map +1 -1
  253. package/dist/detectors/list-sentence.d.ts +4 -0
  254. package/dist/detectors/list-sentence.d.ts.map +1 -1
  255. package/dist/detectors/list-sentence.js +1 -1
  256. package/dist/detectors/list-sentence.js.map +1 -1
  257. package/dist/detectors/mark-shape.d.ts +15 -5
  258. package/dist/detectors/mark-shape.d.ts.map +1 -1
  259. package/dist/detectors/mark-shape.js +64 -10
  260. package/dist/detectors/mark-shape.js.map +1 -1
  261. package/dist/detectors/mentioned-phrase.d.ts +9 -0
  262. package/dist/detectors/mentioned-phrase.d.ts.map +1 -0
  263. package/dist/detectors/mentioned-phrase.js +25 -0
  264. package/dist/detectors/mentioned-phrase.js.map +1 -0
  265. package/dist/detectors/middle-dot.d.ts +2 -2
  266. package/dist/detectors/middle-dot.d.ts.map +1 -1
  267. package/dist/detectors/middle-dot.js +4 -2
  268. package/dist/detectors/middle-dot.js.map +1 -1
  269. package/dist/detectors/modal-conflict.d.ts.map +1 -1
  270. package/dist/detectors/modal-conflict.js +5 -2
  271. package/dist/detectors/modal-conflict.js.map +1 -1
  272. package/dist/detectors/name-variant-apart.d.ts +27 -0
  273. package/dist/detectors/name-variant-apart.d.ts.map +1 -0
  274. package/dist/detectors/name-variant-apart.js +51 -0
  275. package/dist/detectors/name-variant-apart.js.map +1 -0
  276. package/dist/detectors/name-variant.d.ts.map +1 -1
  277. package/dist/detectors/name-variant.js +18 -11
  278. package/dist/detectors/name-variant.js.map +1 -1
  279. package/dist/detectors/notice-paragraph.d.ts +9 -0
  280. package/dist/detectors/notice-paragraph.d.ts.map +1 -0
  281. package/dist/detectors/notice-paragraph.js +21 -0
  282. package/dist/detectors/notice-paragraph.js.map +1 -0
  283. package/dist/detectors/number-style.d.ts.map +1 -1
  284. package/dist/detectors/number-style.js +15 -2
  285. package/dist/detectors/number-style.js.map +1 -1
  286. package/dist/detectors/number-unit.d.ts.map +1 -1
  287. package/dist/detectors/number-unit.js +24 -1
  288. package/dist/detectors/number-unit.js.map +1 -1
  289. package/dist/detectors/numeral-opener.d.ts +6 -0
  290. package/dist/detectors/numeral-opener.d.ts.map +1 -1
  291. package/dist/detectors/numeral-opener.js +24 -1
  292. package/dist/detectors/numeral-opener.js.map +1 -1
  293. package/dist/detectors/numeral-word.d.ts +15 -0
  294. package/dist/detectors/numeral-word.d.ts.map +1 -0
  295. package/dist/detectors/numeral-word.js +26 -0
  296. package/dist/detectors/numeral-word.js.map +1 -0
  297. package/dist/detectors/obligation-without-deadline.d.ts +5 -1
  298. package/dist/detectors/obligation-without-deadline.d.ts.map +1 -1
  299. package/dist/detectors/obligation-without-deadline.js +44 -23
  300. package/dist/detectors/obligation-without-deadline.js.map +1 -1
  301. package/dist/detectors/open-end-class.d.ts +16 -0
  302. package/dist/detectors/open-end-class.d.ts.map +1 -0
  303. package/dist/detectors/open-end-class.js +65 -0
  304. package/dist/detectors/open-end-class.js.map +1 -0
  305. package/dist/detectors/open-end-condition.d.ts +7 -0
  306. package/dist/detectors/open-end-condition.d.ts.map +1 -0
  307. package/dist/detectors/open-end-condition.js +35 -0
  308. package/dist/detectors/open-end-condition.js.map +1 -0
  309. package/dist/detectors/open-end-names.d.ts +9 -3
  310. package/dist/detectors/open-end-names.d.ts.map +1 -1
  311. package/dist/detectors/open-end-names.js +5 -2
  312. package/dist/detectors/open-end-names.js.map +1 -1
  313. package/dist/detectors/open-end-question.d.ts +15 -0
  314. package/dist/detectors/open-end-question.d.ts.map +1 -0
  315. package/dist/detectors/open-end-question.js +37 -0
  316. package/dist/detectors/open-end-question.js.map +1 -0
  317. package/dist/detectors/open-end-scope.d.ts +16 -0
  318. package/dist/detectors/open-end-scope.d.ts.map +1 -0
  319. package/dist/detectors/open-end-scope.js +47 -0
  320. package/dist/detectors/open-end-scope.js.map +1 -0
  321. package/dist/detectors/opening-date.d.ts +10 -0
  322. package/dist/detectors/opening-date.d.ts.map +1 -0
  323. package/dist/detectors/opening-date.js +33 -0
  324. package/dist/detectors/opening-date.js.map +1 -0
  325. package/dist/detectors/ordinary-phrase.d.ts +20 -0
  326. package/dist/detectors/ordinary-phrase.d.ts.map +1 -0
  327. package/dist/detectors/ordinary-phrase.js +54 -0
  328. package/dist/detectors/ordinary-phrase.js.map +1 -0
  329. package/dist/detectors/organisation-run.d.ts +18 -0
  330. package/dist/detectors/organisation-run.d.ts.map +1 -0
  331. package/dist/detectors/organisation-run.js +80 -0
  332. package/dist/detectors/organisation-run.js.map +1 -0
  333. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  334. package/dist/detectors/orthographic-variant.js +65 -21
  335. package/dist/detectors/orthographic-variant.js.map +1 -1
  336. package/dist/detectors/orthography.d.ts.map +1 -1
  337. package/dist/detectors/orthography.js +6 -1
  338. package/dist/detectors/orthography.js.map +1 -1
  339. package/dist/detectors/outline-label.d.ts +14 -0
  340. package/dist/detectors/outline-label.d.ts.map +1 -0
  341. package/dist/detectors/outline-label.js +32 -0
  342. package/dist/detectors/outline-label.js.map +1 -0
  343. package/dist/detectors/oxford-comma.d.ts.map +1 -1
  344. package/dist/detectors/oxford-comma.js +38 -1
  345. package/dist/detectors/oxford-comma.js.map +1 -1
  346. package/dist/detectors/page-marker.d.ts +6 -0
  347. package/dist/detectors/page-marker.d.ts.map +1 -0
  348. package/dist/detectors/page-marker.js +19 -0
  349. package/dist/detectors/page-marker.js.map +1 -0
  350. package/dist/detectors/parallel-definition.d.ts +16 -0
  351. package/dist/detectors/parallel-definition.d.ts.map +1 -0
  352. package/dist/detectors/parallel-definition.js +51 -0
  353. package/dist/detectors/parallel-definition.js.map +1 -0
  354. package/dist/detectors/person-consistency.d.ts +2 -1
  355. package/dist/detectors/person-consistency.d.ts.map +1 -1
  356. package/dist/detectors/person-consistency.js +5 -3
  357. package/dist/detectors/person-consistency.js.map +1 -1
  358. package/dist/detectors/phrase-match.d.ts +2 -0
  359. package/dist/detectors/phrase-match.d.ts.map +1 -1
  360. package/dist/detectors/phrase-match.js +11 -4
  361. package/dist/detectors/phrase-match.js.map +1 -1
  362. package/dist/detectors/placeholder-text.d.ts.map +1 -1
  363. package/dist/detectors/placeholder-text.js +18 -3
  364. package/dist/detectors/placeholder-text.js.map +1 -1
  365. package/dist/detectors/placeholder.d.ts +3 -1
  366. package/dist/detectors/placeholder.d.ts.map +1 -1
  367. package/dist/detectors/placeholder.js +8 -3
  368. package/dist/detectors/placeholder.js.map +1 -1
  369. package/dist/detectors/postcode-end.d.ts +3 -0
  370. package/dist/detectors/postcode-end.d.ts.map +1 -0
  371. package/dist/detectors/postcode-end.js +15 -0
  372. package/dist/detectors/postcode-end.js.map +1 -0
  373. package/dist/detectors/prose-total-words.d.ts +5 -0
  374. package/dist/detectors/prose-total-words.d.ts.map +1 -0
  375. package/dist/detectors/prose-total-words.js +14 -0
  376. package/dist/detectors/prose-total-words.js.map +1 -0
  377. package/dist/detectors/reference-text.d.ts.map +1 -1
  378. package/dist/detectors/reference-text.js +1 -0
  379. package/dist/detectors/reference-text.js.map +1 -1
  380. package/dist/detectors/registry/kanji-compound-slip.d.ts +3 -0
  381. package/dist/detectors/registry/kanji-compound-slip.d.ts.map +1 -0
  382. package/dist/detectors/registry/kanji-compound-slip.js +3 -0
  383. package/dist/detectors/registry/kanji-compound-slip.js.map +1 -0
  384. package/dist/detectors/registry/phrase-in-use.d.ts +3 -0
  385. package/dist/detectors/registry/phrase-in-use.d.ts.map +1 -0
  386. package/dist/detectors/registry/phrase-in-use.js +3 -0
  387. package/dist/detectors/registry/phrase-in-use.js.map +1 -0
  388. package/dist/detectors/registry/unfilled-placeholder.d.ts.map +1 -1
  389. package/dist/detectors/registry/unfilled-placeholder.js +2 -2
  390. package/dist/detectors/registry/unfilled-placeholder.js.map +1 -1
  391. package/dist/detectors/registry/vague-density.js +1 -1
  392. package/dist/detectors/registry/vague-density.js.map +1 -1
  393. package/dist/detectors/request-owner.d.ts +6 -2
  394. package/dist/detectors/request-owner.d.ts.map +1 -1
  395. package/dist/detectors/request-owner.js +57 -7
  396. package/dist/detectors/request-owner.js.map +1 -1
  397. package/dist/detectors/requirement-smell.d.ts.map +1 -1
  398. package/dist/detectors/requirement-smell.js +39 -7
  399. package/dist/detectors/requirement-smell.js.map +1 -1
  400. package/dist/detectors/scaled-figure-unit.d.ts +28 -0
  401. package/dist/detectors/scaled-figure-unit.d.ts.map +1 -0
  402. package/dist/detectors/scaled-figure-unit.js +78 -0
  403. package/dist/detectors/scaled-figure-unit.js.map +1 -0
  404. package/dist/detectors/sentence-counts.d.ts +2 -0
  405. package/dist/detectors/sentence-counts.d.ts.map +1 -1
  406. package/dist/detectors/sentence-counts.js +18 -7
  407. package/dist/detectors/sentence-counts.js.map +1 -1
  408. package/dist/detectors/sentence-ending.d.ts +2 -0
  409. package/dist/detectors/sentence-ending.d.ts.map +1 -1
  410. package/dist/detectors/sentence-ending.js +10 -3
  411. package/dist/detectors/sentence-ending.js.map +1 -1
  412. package/dist/detectors/sentence-length.d.ts.map +1 -1
  413. package/dist/detectors/sentence-length.js +24 -16
  414. package/dist/detectors/sentence-length.js.map +1 -1
  415. package/dist/detectors/sentence-load.d.ts +4 -1
  416. package/dist/detectors/sentence-load.d.ts.map +1 -1
  417. package/dist/detectors/sentence-load.js +9 -2
  418. package/dist/detectors/sentence-load.js.map +1 -1
  419. package/dist/detectors/sentence-rhythm.d.ts.map +1 -1
  420. package/dist/detectors/sentence-rhythm.js +6 -3
  421. package/dist/detectors/sentence-rhythm.js.map +1 -1
  422. package/dist/detectors/series-label.d.ts +2 -1
  423. package/dist/detectors/series-label.d.ts.map +1 -1
  424. package/dist/detectors/series-label.js +10 -4
  425. package/dist/detectors/series-label.js.map +1 -1
  426. package/dist/detectors/signals.d.ts +4 -0
  427. package/dist/detectors/signals.d.ts.map +1 -1
  428. package/dist/detectors/signals.js +91 -52
  429. package/dist/detectors/signals.js.map +1 -1
  430. package/dist/detectors/structure-tree.d.ts.map +1 -1
  431. package/dist/detectors/structure-tree.js +21 -19
  432. package/dist/detectors/structure-tree.js.map +1 -1
  433. package/dist/detectors/structure.d.ts.map +1 -1
  434. package/dist/detectors/structure.js +2 -1
  435. package/dist/detectors/structure.js.map +1 -1
  436. package/dist/detectors/subject-name-line.d.ts +8 -0
  437. package/dist/detectors/subject-name-line.d.ts.map +1 -0
  438. package/dist/detectors/subject-name-line.js +53 -0
  439. package/dist/detectors/subject-name-line.js.map +1 -0
  440. package/dist/detectors/table-header.d.ts.map +1 -1
  441. package/dist/detectors/table-header.js +13 -1
  442. package/dist/detectors/table-header.js.map +1 -1
  443. package/dist/detectors/technical-docs.d.ts.map +1 -1
  444. package/dist/detectors/technical-docs.js +4 -1
  445. package/dist/detectors/technical-docs.js.map +1 -1
  446. package/dist/detectors/template-sections.d.ts +14 -0
  447. package/dist/detectors/template-sections.d.ts.map +1 -0
  448. package/dist/detectors/template-sections.js +25 -0
  449. package/dist/detectors/template-sections.js.map +1 -0
  450. package/dist/detectors/term-mention-sentence.d.ts +4 -0
  451. package/dist/detectors/term-mention-sentence.d.ts.map +1 -0
  452. package/dist/detectors/term-mention-sentence.js +28 -0
  453. package/dist/detectors/term-mention-sentence.js.map +1 -0
  454. package/dist/detectors/titled-run.d.ts +23 -0
  455. package/dist/detectors/titled-run.d.ts.map +1 -0
  456. package/dist/detectors/titled-run.js +39 -0
  457. package/dist/detectors/titled-run.js.map +1 -0
  458. package/dist/detectors/token-shape.d.ts.map +1 -1
  459. package/dist/detectors/token-shape.js +13 -5
  460. package/dist/detectors/token-shape.js.map +1 -1
  461. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
  462. package/dist/detectors/unbalanced-bracket.js +4 -0
  463. package/dist/detectors/unbalanced-bracket.js.map +1 -1
  464. package/dist/detectors/undefined-term.d.ts.map +1 -1
  465. package/dist/detectors/undefined-term.js +8 -0
  466. package/dist/detectors/undefined-term.js.map +1 -1
  467. package/dist/detectors/unfilled-placeholder.d.ts +4 -0
  468. package/dist/detectors/unfilled-placeholder.d.ts.map +1 -0
  469. package/dist/detectors/unfilled-placeholder.js +9 -0
  470. package/dist/detectors/unfilled-placeholder.js.map +1 -0
  471. package/dist/detectors/vague-density.d.ts +8 -0
  472. package/dist/detectors/vague-density.d.ts.map +1 -0
  473. package/dist/detectors/vague-density.js +65 -0
  474. package/dist/detectors/vague-density.js.map +1 -0
  475. package/dist/document-paragraphs.d.ts +4 -0
  476. package/dist/document-paragraphs.d.ts.map +1 -0
  477. package/dist/document-paragraphs.js +24 -0
  478. package/dist/document-paragraphs.js.map +1 -0
  479. package/dist/document.d.ts.map +1 -1
  480. package/dist/document.js +2 -19
  481. package/dist/document.js.map +1 -1
  482. package/dist/facts/fact-scope.d.ts +10 -1
  483. package/dist/facts/fact-scope.d.ts.map +1 -1
  484. package/dist/facts/fact-scope.js +34 -3
  485. package/dist/facts/fact-scope.js.map +1 -1
  486. package/dist/facts/table-facts.d.ts +12 -2
  487. package/dist/facts/table-facts.d.ts.map +1 -1
  488. package/dist/facts/table-facts.js +22 -4
  489. package/dist/facts/table-facts.js.map +1 -1
  490. package/dist/figure-references.d.ts +3 -0
  491. package/dist/figure-references.d.ts.map +1 -1
  492. package/dist/figure-references.js +6 -2
  493. package/dist/figure-references.js.map +1 -1
  494. package/dist/format-template.d.ts +3 -0
  495. package/dist/format-template.d.ts.map +1 -0
  496. package/dist/format-template.js +13 -0
  497. package/dist/format-template.js.map +1 -0
  498. package/dist/formula-brackets.d.ts +7 -0
  499. package/dist/formula-brackets.d.ts.map +1 -0
  500. package/dist/formula-brackets.js +29 -0
  501. package/dist/formula-brackets.js.map +1 -0
  502. package/dist/grade-api.d.ts +9 -2
  503. package/dist/grade-api.d.ts.map +1 -1
  504. package/dist/grade-api.js +31 -15
  505. package/dist/grade-api.js.map +1 -1
  506. package/dist/heading-numbering.d.ts +5 -2
  507. package/dist/heading-numbering.d.ts.map +1 -1
  508. package/dist/heading-numbering.js +27 -6
  509. package/dist/heading-numbering.js.map +1 -1
  510. package/dist/html/html-markdown.d.ts.map +1 -1
  511. package/dist/html/html-markdown.js +2 -1
  512. package/dist/html/html-markdown.js.map +1 -1
  513. package/dist/html/html-site-chrome.d.ts +5 -0
  514. package/dist/html/html-site-chrome.d.ts.map +1 -0
  515. package/dist/html/html-site-chrome.js +33 -0
  516. package/dist/html/html-site-chrome.js.map +1 -0
  517. package/dist/joined-view.d.ts.map +1 -1
  518. package/dist/joined-view.js +1 -0
  519. package/dist/joined-view.js.map +1 -1
  520. package/dist/kanji-compound-slip.d.ts +32 -0
  521. package/dist/kanji-compound-slip.d.ts.map +1 -0
  522. package/dist/kanji-compound-slip.js +63 -0
  523. package/dist/kanji-compound-slip.js.map +1 -0
  524. package/dist/latin-company-form.d.ts +6 -0
  525. package/dist/latin-company-form.d.ts.map +1 -0
  526. package/dist/latin-company-form.js +32 -0
  527. package/dist/latin-company-form.js.map +1 -0
  528. package/dist/latin-word-boundary.d.ts +15 -0
  529. package/dist/latin-word-boundary.d.ts.map +1 -0
  530. package/dist/latin-word-boundary.js +40 -0
  531. package/dist/latin-word-boundary.js.map +1 -0
  532. package/dist/lexicon-genres.d.ts +2 -0
  533. package/dist/lexicon-genres.d.ts.map +1 -1
  534. package/dist/lexicon-genres.js +1 -1
  535. package/dist/lexicon-genres.js.map +1 -1
  536. package/dist/link-shape.d.ts +5 -0
  537. package/dist/link-shape.d.ts.map +1 -1
  538. package/dist/link-shape.js +18 -0
  539. package/dist/link-shape.js.map +1 -1
  540. package/dist/link-title.d.ts +4 -0
  541. package/dist/link-title.d.ts.map +1 -0
  542. package/dist/link-title.js +33 -0
  543. package/dist/link-title.js.map +1 -0
  544. package/dist/list-item-paragraphs.d.ts +15 -0
  545. package/dist/list-item-paragraphs.d.ts.map +1 -0
  546. package/dist/list-item-paragraphs.js +19 -0
  547. package/dist/list-item-paragraphs.js.map +1 -0
  548. package/dist/literal-quote.d.ts +12 -0
  549. package/dist/literal-quote.d.ts.map +1 -0
  550. package/dist/literal-quote.js +43 -0
  551. package/dist/literal-quote.js.map +1 -0
  552. package/dist/nado-closed-list.d.ts.map +1 -1
  553. package/dist/nado-closed-list.js +39 -5
  554. package/dist/nado-closed-list.js.map +1 -1
  555. package/dist/name-end-letter.d.ts +5 -0
  556. package/dist/name-end-letter.d.ts.map +1 -1
  557. package/dist/name-end-letter.js +8 -0
  558. package/dist/name-end-letter.js.map +1 -1
  559. package/dist/name-given-before.d.ts +15 -0
  560. package/dist/name-given-before.d.ts.map +1 -0
  561. package/dist/name-given-before.js +30 -0
  562. package/dist/name-given-before.js.map +1 -0
  563. package/dist/name-separator.d.ts +2 -2
  564. package/dist/name-separator.d.ts.map +1 -1
  565. package/dist/name-separator.js +79 -5
  566. package/dist/name-separator.js.map +1 -1
  567. package/dist/name-variants.d.ts +3 -1
  568. package/dist/name-variants.d.ts.map +1 -1
  569. package/dist/name-variants.js +8 -7
  570. package/dist/name-variants.js.map +1 -1
  571. package/dist/name-word-order.d.ts +9 -5
  572. package/dist/name-word-order.d.ts.map +1 -1
  573. package/dist/name-word-order.js +47 -15
  574. package/dist/name-word-order.js.map +1 -1
  575. package/dist/nominal-stem.d.ts +26 -0
  576. package/dist/nominal-stem.d.ts.map +1 -0
  577. package/dist/nominal-stem.js +70 -0
  578. package/dist/nominal-stem.js.map +1 -0
  579. package/dist/person-forms.d.ts +8 -0
  580. package/dist/person-forms.d.ts.map +1 -1
  581. package/dist/person-forms.js +12 -0
  582. package/dist/person-forms.js.map +1 -1
  583. package/dist/plugin.d.ts +5 -0
  584. package/dist/plugin.d.ts.map +1 -1
  585. package/dist/preamble-paragraphs.d.ts +3 -2
  586. package/dist/preamble-paragraphs.d.ts.map +1 -1
  587. package/dist/preamble-paragraphs.js +8 -2
  588. package/dist/preamble-paragraphs.js.map +1 -1
  589. package/dist/sentence-load.d.ts +2 -1
  590. package/dist/sentence-load.d.ts.map +1 -1
  591. package/dist/sentence-load.js +6 -2
  592. package/dist/sentence-load.js.map +1 -1
  593. package/dist/spacing-code.d.ts +1 -0
  594. package/dist/spacing-code.d.ts.map +1 -1
  595. package/dist/spacing-code.js +4 -1
  596. package/dist/spacing-code.js.map +1 -1
  597. package/dist/split-noun.d.ts +10 -0
  598. package/dist/split-noun.d.ts.map +1 -0
  599. package/dist/split-noun.js +50 -0
  600. package/dist/split-noun.js.map +1 -0
  601. package/dist/structure/attached-parts.d.ts +11 -0
  602. package/dist/structure/attached-parts.d.ts.map +1 -0
  603. package/dist/structure/attached-parts.js +31 -0
  604. package/dist/structure/attached-parts.js.map +1 -0
  605. package/dist/structure/build.d.ts.map +1 -1
  606. package/dist/structure/build.js +7 -4
  607. package/dist/structure/build.js.map +1 -1
  608. package/dist/structure/cited-document-section.d.ts +7 -0
  609. package/dist/structure/cited-document-section.d.ts.map +1 -0
  610. package/dist/structure/cited-document-section.js +33 -0
  611. package/dist/structure/cited-document-section.js.map +1 -0
  612. package/dist/structure/contents-lines.d.ts +7 -0
  613. package/dist/structure/contents-lines.d.ts.map +1 -0
  614. package/dist/structure/contents-lines.js +51 -0
  615. package/dist/structure/contents-lines.js.map +1 -0
  616. package/dist/structure/defining-names.d.ts +37 -0
  617. package/dist/structure/defining-names.d.ts.map +1 -0
  618. package/dist/structure/defining-names.js +122 -0
  619. package/dist/structure/defining-names.js.map +1 -0
  620. package/dist/structure/definition-use.d.ts +3 -2
  621. package/dist/structure/definition-use.d.ts.map +1 -1
  622. package/dist/structure/definition-use.js +99 -31
  623. package/dist/structure/definition-use.js.map +1 -1
  624. package/dist/structure/html-text-blocks.d.ts +8 -0
  625. package/dist/structure/html-text-blocks.d.ts.map +1 -0
  626. package/dist/structure/html-text-blocks.js +47 -0
  627. package/dist/structure/html-text-blocks.js.map +1 -0
  628. package/dist/structure/issues.d.ts +5 -2
  629. package/dist/structure/issues.d.ts.map +1 -1
  630. package/dist/structure/issues.js +24 -6
  631. package/dist/structure/issues.js.map +1 -1
  632. package/dist/structure/labelled-date-order.d.ts +4 -1
  633. package/dist/structure/labelled-date-order.d.ts.map +1 -1
  634. package/dist/structure/labelled-date-order.js +2 -2
  635. package/dist/structure/labelled-date-order.js.map +1 -1
  636. package/dist/structure/labelled-order.d.ts +3 -0
  637. package/dist/structure/labelled-order.d.ts.map +1 -1
  638. package/dist/structure/labelled-order.js +8 -3
  639. package/dist/structure/labelled-order.js.map +1 -1
  640. package/dist/structure/list-lead-in.d.ts +19 -0
  641. package/dist/structure/list-lead-in.d.ts.map +1 -0
  642. package/dist/structure/list-lead-in.js +85 -0
  643. package/dist/structure/list-lead-in.js.map +1 -0
  644. package/dist/structure/list-numbering.d.ts +20 -4
  645. package/dist/structure/list-numbering.d.ts.map +1 -1
  646. package/dist/structure/list-numbering.js +65 -9
  647. package/dist/structure/list-numbering.js.map +1 -1
  648. package/dist/structure/listed-paragraph.d.ts +16 -0
  649. package/dist/structure/listed-paragraph.d.ts.map +1 -0
  650. package/dist/structure/listed-paragraph.js +37 -0
  651. package/dist/structure/listed-paragraph.js.map +1 -0
  652. package/dist/structure/modal-conflict.d.ts +7 -2
  653. package/dist/structure/modal-conflict.d.ts.map +1 -1
  654. package/dist/structure/modal-conflict.js +36 -7
  655. package/dist/structure/modal-conflict.js.map +1 -1
  656. package/dist/structure/negated-act.d.ts +17 -0
  657. package/dist/structure/negated-act.d.ts.map +1 -0
  658. package/dist/structure/negated-act.js +32 -0
  659. package/dist/structure/negated-act.js.map +1 -0
  660. package/dist/structure/numbering.d.ts +5 -2
  661. package/dist/structure/numbering.d.ts.map +1 -1
  662. package/dist/structure/numbering.js +49 -12
  663. package/dist/structure/numbering.js.map +1 -1
  664. package/dist/structure/prose-total.d.ts +4 -0
  665. package/dist/structure/prose-total.d.ts.map +1 -1
  666. package/dist/structure/prose-total.js +16 -6
  667. package/dist/structure/prose-total.js.map +1 -1
  668. package/dist/structure/reference-text.d.ts +9 -1
  669. package/dist/structure/reference-text.d.ts.map +1 -1
  670. package/dist/structure/reference-text.js +21 -3
  671. package/dist/structure/reference-text.js.map +1 -1
  672. package/dist/structure/repeated-number.d.ts +24 -0
  673. package/dist/structure/repeated-number.d.ts.map +1 -0
  674. package/dist/structure/repeated-number.js +89 -0
  675. package/dist/structure/repeated-number.js.map +1 -0
  676. package/dist/structure/rounded-amount.d.ts +8 -0
  677. package/dist/structure/rounded-amount.d.ts.map +1 -0
  678. package/dist/structure/rounded-amount.js +48 -0
  679. package/dist/structure/rounded-amount.js.map +1 -0
  680. package/dist/structure/section-names.d.ts +12 -0
  681. package/dist/structure/section-names.d.ts.map +1 -0
  682. package/dist/structure/section-names.js +26 -0
  683. package/dist/structure/section-names.js.map +1 -0
  684. package/dist/structure/side-step.d.ts +8 -0
  685. package/dist/structure/side-step.d.ts.map +1 -0
  686. package/dist/structure/side-step.js +21 -0
  687. package/dist/structure/side-step.js.map +1 -0
  688. package/dist/structure/spanned-label-blank.d.ts +8 -0
  689. package/dist/structure/spanned-label-blank.d.ts.map +1 -0
  690. package/dist/structure/spanned-label-blank.js +37 -0
  691. package/dist/structure/spanned-label-blank.js.map +1 -0
  692. package/dist/structure/universal.d.ts +3 -1
  693. package/dist/structure/universal.d.ts.map +1 -1
  694. package/dist/structure/universal.js +9 -2
  695. package/dist/structure/universal.js.map +1 -1
  696. package/dist/structure/unspaced-heading.d.ts +10 -0
  697. package/dist/structure/unspaced-heading.d.ts.map +1 -0
  698. package/dist/structure/unspaced-heading.js +24 -0
  699. package/dist/structure/unspaced-heading.js.map +1 -0
  700. package/dist/structure/versioned-label.d.ts +16 -0
  701. package/dist/structure/versioned-label.d.ts.map +1 -0
  702. package/dist/structure/versioned-label.js +48 -0
  703. package/dist/structure/versioned-label.js.map +1 -0
  704. package/dist/structure/written-headings.d.ts +31 -0
  705. package/dist/structure/written-headings.d.ts.map +1 -0
  706. package/dist/structure/written-headings.js +119 -0
  707. package/dist/structure/written-headings.js.map +1 -0
  708. package/dist/structure/written-list-path.d.ts +10 -0
  709. package/dist/structure/written-list-path.d.ts.map +1 -0
  710. package/dist/structure/written-list-path.js +37 -0
  711. package/dist/structure/written-list-path.js.map +1 -0
  712. package/dist/structure/written-resolve.d.ts +12 -0
  713. package/dist/structure/written-resolve.d.ts.map +1 -0
  714. package/dist/structure/written-resolve.js +55 -0
  715. package/dist/structure/written-resolve.js.map +1 -0
  716. package/dist/title-line.d.ts +21 -0
  717. package/dist/title-line.d.ts.map +1 -0
  718. package/dist/title-line.js +27 -0
  719. package/dist/title-line.js.map +1 -0
  720. package/package.json +3 -3
  721. package/rules/all-caps-shouting.yaml +2 -2
  722. package/rules/announced-count-mismatch.yaml +2 -2
  723. package/rules/bare-url-mix.yaml +2 -2
  724. package/rules/bracket-nesting.yaml +2 -2
  725. package/rules/bracket-width-consistency.yaml +2 -2
  726. package/rules/broken-link.yaml +2 -2
  727. package/rules/cliche.yaml +4 -3
  728. package/rules/code-fence-language-mix.yaml +2 -2
  729. package/rules/comparative-without-baseline.yaml +2 -2
  730. package/rules/concrete-evidence-density.yaml +2 -2
  731. package/rules/contraction-consistency.yaml +13 -13
  732. package/rules/dangling-figure-reference.yaml +2 -2
  733. package/rules/dangling-reference.yaml +2 -2
  734. package/rules/date-without-year.yaml +10 -2
  735. package/rules/defined-name-repeated.yaml +2 -2
  736. package/rules/defined-term-form.yaml +2 -2
  737. package/rules/doubled-punctuation.yaml +4 -4
  738. package/rules/doubled-word.yaml +2 -2
  739. package/rules/duplicate-definition.yaml +2 -2
  740. package/rules/duration-mismatch.yaml +2 -2
  741. package/rules/email-greeting-closing.yaml +2 -2
  742. package/rules/email-subject-length.yaml +2 -2
  743. package/rules/empty-table-cell.yaml +2 -2
  744. package/rules/fact-conflict.yaml +2 -2
  745. package/rules/footnote-mismatch.yaml +2 -2
  746. package/rules/heading-echo.yaml +2 -2
  747. package/rules/heading-end-punctuation-mix.yaml +2 -2
  748. package/rules/heading-numbering-mix.yaml +2 -2
  749. package/rules/ime-residue.yaml +2 -2
  750. package/rules/kanji-compound-slip.yaml +67 -0
  751. package/rules/kutoten-consistency.yaml +4 -4
  752. package/rules/latin-spacing.yaml +4 -4
  753. package/rules/list-item-form-mix.yaml +2 -2
  754. package/rules/max-kanji-continuous.yaml +7 -3
  755. package/rules/max-sentence-length.yaml +3 -2
  756. package/rules/modal-conflict.yaml +1 -0
  757. package/rules/nado-closed-list.yaml +2 -2
  758. package/rules/name-variant.yaml +2 -2
  759. package/rules/ngram-repetition.yaml +2 -2
  760. package/rules/no-doubled-joshi.yaml +2 -2
  761. package/rules/no-mixed-desumasu.yaml +3 -3
  762. package/rules/no-nakaguro-parallel.yaml +2 -0
  763. package/rules/number-without-unit.yaml +9 -4
  764. package/rules/numbering-gap.yaml +7 -2
  765. package/rules/numeral-sentence-start.yaml +2 -2
  766. package/rules/obligation-without-deadline.yaml +2 -2
  767. package/rules/orthographic-variant.yaml +2 -2
  768. package/rules/oxford-comma-consistency.yaml +3 -3
  769. package/rules/preamble-length.yaml +2 -2
  770. package/rules/reference-title-mismatch.yaml +2 -2
  771. package/rules/repeated-sentence-ending.yaml +3 -2
  772. package/rules/request-without-deadline.yaml +2 -2
  773. package/rules/requirement-smell.yaml +3 -3
  774. package/rules/sentence-rhythm.yaml +2 -2
  775. package/rules/table-header-variant.yaml +2 -2
  776. package/rules/teki-overuse.yaml +3 -2
  777. package/rules/title-case-consistency.yaml +2 -2
  778. package/rules/total-mismatch.yaml +2 -2
  779. package/rules/translationese-density.yaml +2 -2
  780. package/rules/unbalanced-bracket.yaml +2 -2
  781. package/rules/undefined-acronym.yaml +15 -4
  782. package/rules/undefined-term.yaml +2 -2
  783. package/rules/unfilled-placeholder.yaml +4 -4
  784. package/rules/use-before-definition.yaml +2 -2
  785. package/rules/vague-word-density.yaml +2 -2
  786. package/skills/chaff/SKILL.md +7 -1
  787. package/src/announced-count.ts +35 -8
  788. package/src/capitals-passage.ts +31 -0
  789. package/src/chronology-rows.ts +86 -0
  790. package/src/coined-hyphen-name.ts +27 -0
  791. package/src/company-name-run.ts +37 -0
  792. package/src/company-names.ts +24 -3
  793. package/src/compound-head.ts +25 -0
  794. package/src/date-format.ts +43 -4
  795. package/src/derived/count-per-period.ts +28 -0
  796. package/src/detectors/acronym-context.ts +34 -6
  797. package/src/detectors/acronym-definition.ts +123 -0
  798. package/src/detectors/acronym-expansion.ts +47 -6
  799. package/src/detectors/acronym-known.ts +40 -0
  800. package/src/detectors/acronym-link.ts +37 -0
  801. package/src/detectors/acronym-lone.ts +26 -0
  802. package/src/detectors/acronym-name.ts +140 -0
  803. package/src/detectors/addressee-edge.ts +16 -0
  804. package/src/detectors/announced-count.ts +1 -0
  805. package/src/detectors/bare-comparative.ts +44 -3
  806. package/src/detectors/blank-structure.ts +21 -10
  807. package/src/detectors/bracket-specified.ts +25 -0
  808. package/src/detectors/broken-link.ts +26 -2
  809. package/src/detectors/capitalised-term.ts +154 -4
  810. package/src/detectors/caps-caption.ts +103 -0
  811. package/src/detectors/caps-phrase.ts +17 -0
  812. package/src/detectors/char-shape.ts +99 -26
  813. package/src/detectors/cited-title.ts +15 -3
  814. package/src/detectors/clause-shape.ts +14 -4
  815. package/src/detectors/concrete-evidence.ts +77 -1
  816. package/src/detectors/contraction-minority.ts +11 -0
  817. package/src/detectors/counter-edge.ts +40 -2
  818. package/src/detectors/date-any-year.ts +79 -12
  819. package/src/detectors/date-format.ts +2 -1
  820. package/src/detectors/date-heading-year.ts +55 -0
  821. package/src/detectors/date-year.ts +107 -14
  822. package/src/detectors/deadline-unit.ts +40 -0
  823. package/src/detectors/defined-term-form.ts +58 -17
  824. package/src/detectors/definition-use.ts +7 -3
  825. package/src/detectors/derived-numbers.ts +19 -4
  826. package/src/detectors/doubled-across-aside.ts +36 -0
  827. package/src/detectors/doubled-punctuation.ts +28 -7
  828. package/src/detectors/doubled-word.ts +2 -1
  829. package/src/detectors/due-date.ts +10 -1
  830. package/src/detectors/ellipsis.ts +16 -1
  831. package/src/detectors/email-letter.ts +97 -21
  832. package/src/detectors/en-shape.ts +5 -1
  833. package/src/detectors/fact-consistency.ts +3 -2
  834. package/src/detectors/field-label.ts +25 -0
  835. package/src/detectors/footnote-mismatch.ts +39 -7
  836. package/src/detectors/graded-step.ts +52 -0
  837. package/src/detectors/gram-openers.ts +21 -0
  838. package/src/detectors/gram-passages.ts +36 -0
  839. package/src/detectors/gram-place.ts +10 -1
  840. package/src/detectors/gram-predicate.ts +43 -3
  841. package/src/detectors/heading-echo.ts +31 -3
  842. package/src/detectors/heading-end-mark.ts +23 -10
  843. package/src/detectors/heading-names.ts +31 -0
  844. package/src/detectors/heading-numbering.ts +7 -2
  845. package/src/detectors/ime-residue.ts +4 -3
  846. package/src/detectors/inch-mark.ts +49 -0
  847. package/src/detectors/kanji-compound-slip.ts +61 -0
  848. package/src/detectors/kutoten-consistency.ts +93 -14
  849. package/src/detectors/lexicon.ts +44 -24
  850. package/src/detectors/link-shape.ts +10 -3
  851. package/src/detectors/list-item-ending.ts +51 -0
  852. package/src/detectors/list-parallel.ts +158 -33
  853. package/src/detectors/list-sentence.ts +5 -1
  854. package/src/detectors/mark-shape.ts +70 -10
  855. package/src/detectors/mentioned-phrase.ts +38 -0
  856. package/src/detectors/middle-dot.ts +7 -2
  857. package/src/detectors/modal-conflict.ts +5 -2
  858. package/src/detectors/name-variant-apart.ts +63 -0
  859. package/src/detectors/name-variant.ts +30 -12
  860. package/src/detectors/notice-paragraph.ts +33 -0
  861. package/src/detectors/number-style.ts +14 -2
  862. package/src/detectors/number-unit.ts +28 -1
  863. package/src/detectors/numeral-opener.ts +27 -1
  864. package/src/detectors/numeral-word.ts +33 -0
  865. package/src/detectors/obligation-without-deadline.ts +29 -4
  866. package/src/detectors/open-end-class.ts +78 -0
  867. package/src/detectors/open-end-condition.ts +40 -0
  868. package/src/detectors/open-end-names.ts +9 -3
  869. package/src/detectors/open-end-question.ts +50 -0
  870. package/src/detectors/open-end-scope.ts +62 -0
  871. package/src/detectors/opening-date.ts +47 -0
  872. package/src/detectors/ordinary-phrase.ts +62 -0
  873. package/src/detectors/organisation-run.ts +97 -0
  874. package/src/detectors/orthographic-variant.ts +103 -27
  875. package/src/detectors/orthography.ts +10 -1
  876. package/src/detectors/outline-label.ts +48 -0
  877. package/src/detectors/oxford-comma.ts +40 -1
  878. package/src/detectors/page-marker.ts +26 -0
  879. package/src/detectors/parallel-definition.ts +64 -0
  880. package/src/detectors/person-consistency.ts +5 -3
  881. package/src/detectors/phrase-match.ts +16 -5
  882. package/src/detectors/placeholder-text.ts +18 -3
  883. package/src/detectors/placeholder.ts +10 -3
  884. package/src/detectors/postcode-end.ts +16 -0
  885. package/src/detectors/prose-total-words.ts +18 -0
  886. package/src/detectors/reference-text.ts +1 -0
  887. package/src/detectors/registry/kanji-compound-slip.ts +4 -0
  888. package/src/detectors/registry/phrase-in-use.ts +4 -0
  889. package/src/detectors/registry/unfilled-placeholder.ts +2 -2
  890. package/src/detectors/registry/vague-density.ts +1 -1
  891. package/src/detectors/request-owner.ts +71 -8
  892. package/src/detectors/requirement-smell.ts +53 -7
  893. package/src/detectors/scaled-figure-unit.ts +103 -0
  894. package/src/detectors/sentence-counts.ts +24 -8
  895. package/src/detectors/sentence-ending.ts +12 -3
  896. package/src/detectors/sentence-length.ts +14 -6
  897. package/src/detectors/sentence-load.ts +9 -2
  898. package/src/detectors/sentence-rhythm.ts +8 -4
  899. package/src/detectors/series-label.ts +13 -4
  900. package/src/detectors/signals.ts +105 -55
  901. package/src/detectors/structure-tree.ts +22 -20
  902. package/src/detectors/structure.ts +2 -1
  903. package/src/detectors/subject-name-line.ts +66 -0
  904. package/src/detectors/table-header.ts +15 -1
  905. package/src/detectors/technical-docs.ts +5 -1
  906. package/src/detectors/template-sections.ts +37 -0
  907. package/src/detectors/term-mention-sentence.ts +31 -0
  908. package/src/detectors/titled-run.ts +48 -0
  909. package/src/detectors/token-shape.ts +14 -5
  910. package/src/detectors/unbalanced-bracket.ts +3 -0
  911. package/src/detectors/undefined-term.ts +8 -0
  912. package/src/detectors/unfilled-placeholder.ts +10 -0
  913. package/src/detectors/vague-density.ts +84 -0
  914. package/src/document-paragraphs.ts +27 -0
  915. package/src/document.ts +3 -23
  916. package/src/facts/fact-scope.ts +53 -4
  917. package/src/facts/table-facts.ts +43 -6
  918. package/src/figure-references.ts +7 -2
  919. package/src/format-template.ts +15 -0
  920. package/src/formula-brackets.ts +36 -0
  921. package/src/grade-api.ts +38 -16
  922. package/src/heading-numbering.ts +35 -8
  923. package/src/html/html-markdown.ts +2 -1
  924. package/src/html/html-site-chrome.ts +47 -0
  925. package/src/joined-view.ts +1 -0
  926. package/src/kanji-compound-slip.ts +98 -0
  927. package/src/latin-company-form.ts +38 -0
  928. package/src/latin-word-boundary.ts +46 -0
  929. package/src/lexicon-genres.ts +1 -1
  930. package/src/link-shape.ts +19 -0
  931. package/src/link-title.ts +38 -0
  932. package/src/list-item-paragraphs.ts +22 -0
  933. package/src/literal-quote.ts +55 -0
  934. package/src/nado-closed-list.ts +48 -5
  935. package/src/name-end-letter.ts +9 -0
  936. package/src/name-given-before.ts +40 -0
  937. package/src/name-separator.ts +91 -5
  938. package/src/name-variants.ts +21 -11
  939. package/src/name-word-order.ts +62 -17
  940. package/src/nominal-stem.ts +93 -0
  941. package/src/person-forms.ts +15 -0
  942. package/src/plugin.ts +5 -0
  943. package/src/preamble-paragraphs.ts +13 -3
  944. package/src/sentence-load.ts +7 -2
  945. package/src/spacing-code.ts +5 -1
  946. package/src/split-noun.ts +63 -0
  947. package/src/structure/attached-parts.ts +32 -0
  948. package/src/structure/build.ts +7 -4
  949. package/src/structure/cited-document-section.ts +42 -0
  950. package/src/structure/contents-lines.ts +63 -0
  951. package/src/structure/defining-names.ts +155 -0
  952. package/src/structure/definition-use.ts +116 -25
  953. package/src/structure/html-text-blocks.ts +45 -0
  954. package/src/structure/issues.ts +26 -7
  955. package/src/structure/labelled-date-order.ts +5 -2
  956. package/src/structure/labelled-order.ts +12 -3
  957. package/src/structure/list-lead-in.ts +94 -0
  958. package/src/structure/list-numbering.ts +100 -11
  959. package/src/structure/listed-paragraph.ts +45 -0
  960. package/src/structure/modal-conflict.ts +42 -7
  961. package/src/structure/negated-act.ts +49 -0
  962. package/src/structure/numbering.ts +70 -26
  963. package/src/structure/prose-total.ts +20 -6
  964. package/src/structure/reference-text.ts +25 -3
  965. package/src/structure/repeated-number.ts +110 -0
  966. package/src/structure/rounded-amount.ts +55 -0
  967. package/src/structure/section-names.ts +32 -0
  968. package/src/structure/side-step.ts +21 -0
  969. package/src/structure/spanned-label-blank.ts +39 -0
  970. package/src/structure/universal.ts +11 -2
  971. package/src/structure/unspaced-heading.ts +27 -0
  972. package/src/structure/versioned-label.ts +52 -0
  973. package/src/structure/written-headings.ts +137 -0
  974. package/src/structure/written-list-path.ts +46 -0
  975. package/src/structure/written-resolve.ts +64 -0
  976. package/src/title-line.ts +52 -0
@@ -67,18 +67,21 @@ const cellLabel = (rowLabel: string, column: string, headings: readonly string[]
67
67
  return headings.length > TWO_COLUMNS ? `${rowLabel} ${column}` : rowLabel;
68
68
  };
69
69
 
70
- /** 列が三つ以上の表の升は、行の見出し(row)と列の見出し(column)の二つで名前になる。 */
71
- export type TableFact = Fact & { readonly cell?: { readonly row: string; readonly column: string } };
70
+ /**
71
+ * 列が三つ以上の表の升は、行の見出し(row)と列の見出し(column)の二つで名前になる。
72
+ * columnGroup: 見出しの並びを繰り返す表(Day | Hours | Day | Hours の、第1週と第2週を横に並べた表)の、何番目の並びの升か。
73
+ */
74
+ export type TableFact = Fact & { readonly cell?: { readonly row: string; readonly column: string }; readonly columnGroup?: number };
72
75
 
73
76
  const rowFacts = (
74
- row: Line,
77
+ cells: readonly Cell[],
75
78
  headings: readonly string[],
76
79
  values: readonly FactValue[],
77
80
  source: string,
78
81
  totals?: TotalColumns,
79
82
  counts?: CountLabelWords,
80
83
  ): TableFact[] => {
81
- const [first, ...rest] = cellsOf(row);
84
+ const [first, ...rest] = cells;
82
85
  if (first === undefined) return [];
83
86
  const rowLabel = plain(first.text);
84
87
  const isCountHead = (value: FactValue): boolean => counts !== undefined && isCountLabelHead(source, first, value, counts);
@@ -94,11 +97,45 @@ const rowFacts = (
94
97
  });
95
98
  };
96
99
 
100
+ const MIN_GROUPS = 2;
101
+
102
+ /** 見出しが同じ並びを二度以上繰り返すなら、その並びの幅。並びごとに別の表として読む。 */
103
+ export const columnGroupWidth = (headings: readonly string[]): number | undefined => {
104
+ const keys = headings.map(keyOf);
105
+ const widths = Array.from({ length: Math.floor(keys.length / MIN_GROUPS) - 1 }, (_, index) => index + TWO_COLUMNS);
106
+ return widths.find((width) => keys.length % width === 0 && keys[0] !== "" && keys.every((key, index) => key === keys[index % width]));
107
+ };
108
+
109
+ const groupsOf = <T>(items: readonly T[], width: number | undefined): T[][] =>
110
+ width === undefined ? [[...items]] : Array.from({ length: Math.ceil(items.length / width) }, (_, index) => items.slice(index * width, (index + 1) * width));
111
+
112
+ /** columnGroups: 見出しを繰り返す表を、並びごとに読む(並びの升には columnGroup が付く)。 */
113
+ export type TableReading = { readonly columnGroups?: boolean };
114
+
115
+ type RowReading = { readonly values: readonly FactValue[]; readonly source: string; readonly totals?: TotalColumns; readonly counts?: CountLabelWords };
116
+
117
+ /** 一つの行の升の値。見出しを繰り返す表(width がある)は、並びごとに読んで columnGroup を付ける。 */
118
+ const groupedRowFacts = (row: Line, headings: readonly string[], width: number | undefined, at: RowReading): TableFact[] => {
119
+ const headingGroups = groupsOf(headings, width);
120
+ return groupsOf(cellsOf(row), width).flatMap((cells, group) => {
121
+ const facts = rowFacts(cells, headingGroups[group] ?? [], at.values, at.source, at.totals, at.counts);
122
+ return width === undefined ? facts : facts.map((fact) => ({ ...fact, columnGroup: group }));
123
+ });
124
+ };
125
+
97
126
  /** 文書の表すべての升の値。 */
98
- export const tableFacts = (source: string, values: readonly FactValue[], totals?: TotalColumns, counts?: CountLabelWords): TableFact[] =>
127
+ export const tableFacts = (
128
+ source: string,
129
+ values: readonly FactValue[],
130
+ totals?: TotalColumns,
131
+ counts?: CountLabelWords,
132
+ reading: TableReading = {},
133
+ ): TableFact[] =>
99
134
  tablesOf(linesOf(source)).flatMap((table) => {
100
135
  const headings = cellsOf(table.header).map((cell) => plain(cell.text));
101
- return table.rows.flatMap((row) => rowFacts(row, headings, values, source, totals, counts));
136
+ const width = reading.columnGroups === true ? columnGroupWidth(headings) : undefined;
137
+ const at: RowReading = { values, source, ...(totals === undefined ? {} : { totals }), ...(counts === undefined ? {} : { counts }) };
138
+ return table.rows.flatMap((row) => groupedRowFacts(row, headings, width, at));
102
139
  });
103
140
 
104
141
  /** 文書の表すべての、本体の行の升(見出しの行を除く)。text は書いたまま。 */
@@ -1,6 +1,7 @@
1
1
  import { escapeRegExp } from "./orthography.ts";
2
2
  import { lowerBound } from "./detectors/token-column.ts";
3
3
  import type { DocumentNamer, Span } from "./plugin.ts";
4
+ import { isTitleLine, type TitleNotion } from "./title-line.ts";
4
5
 
5
6
  /**
6
7
  * 本文で番号を指した図・表・付録(図3、Table 2、Appendix B)と、それを行の頭に書いた所(キャプション、見出し)。
@@ -79,16 +80,20 @@ const HEADING = /^[ \t]{0,3}#/u;
79
80
  */
80
81
  const CAPTION_AFTER = /^(?:[ \t]*$|[::..—–\-|()()【】\]*_]|[ \t\u3000]+[^\p{Script=Hiragana}\p{Ll}])/u;
81
82
 
83
+ /** A caption's title (Exhibit A to Merger Agreement): every long word capitalised, since Figure 3 shows the trend is a sentence. */
84
+ export const CAPTION_TITLE: TitleNotion = { sentenceEnd: /[.!?。.?!]$/u, capitalised: true, edge: "any-whitespace" };
85
+
82
86
  /**
83
87
  * 行の頭に書いた番号。前にあるのが飾り(#、**、![、|、【、箇条書きの印)だけで、見出しの中か、後ろが題の区切りならキャプション。
84
- * 行の頭から始まる本文の文(図3の例では、…)は、図の置き場所ではない。
88
+ * 行の頭から始まる本文の文(図3の例では、…)は、図の置き場所ではない。題だけの行(Exhibit A to Merger Agreement)も見出し。
85
89
  */
86
90
  const isLabelled = (source: string, mention: Mention): boolean => {
87
91
  const lineStart = source.lastIndexOf("\n", mention.start - 1) + 1;
88
92
  const lineEnd = source.indexOf("\n", mention.end);
89
93
  const before = source.slice(lineStart, mention.start);
90
94
  if (LETTER.test(outsideMarkup(before))) return false;
91
- return HEADING.test(before) || CAPTION_AFTER.test(source.slice(mention.end, lineEnd === -1 ? source.length : lineEnd));
95
+ const rest = source.slice(mention.end, lineEnd === -1 ? source.length : lineEnd);
96
+ return HEADING.test(before) || CAPTION_AFTER.test(rest) || isTitleLine(source, lineStart, lineEnd, rest, CAPTION_TITLE);
92
97
  };
93
98
 
94
99
  const LATIN_WORD = /^[A-Za-z]/u;
@@ -0,0 +1,15 @@
1
+ // A code block that holds only a format template: named placeholders joined by separators (<MAJOR>.<MINOR>.<PATCH>,
2
+ // {year}-{month}). It shows the shape of a value, not code in any language, so it has no language to name. Pure.
3
+
4
+ const PLACEHOLDER = /<[A-Za-z][\w-]*>|\{[A-Za-z][\w-]*\}/gu;
5
+ const SEPARATORS = /^\s*[.,:;/_+\-|][\s.,:;/_+\-|]*$/u;
6
+ /** A lone tag (`<div>`) or two tags side by side are markup; a template joins two or more parts with a separator. */
7
+ const MIN_PARTS = 2;
8
+
9
+ const isTemplateLine = (line: string): boolean => (line.match(PLACEHOLDER) ?? []).length >= MIN_PARTS && SEPARATORS.test(line.replace(PLACEHOLDER, ""));
10
+
11
+ /** Whether every non-blank line is two or more placeholders joined by separators, with at least one such line. */
12
+ export const isFormatTemplate = (lines: readonly string[]): boolean => {
13
+ const filled = lines.filter((line) => line.trim() !== "");
14
+ return filled.length > 0 && filled.every(isTemplateLine);
15
+ };
@@ -0,0 +1,36 @@
1
+ import type { Span } from "./plugin.ts";
2
+
3
+ // Round brackets that group an arithmetic formula (賃金 × (1 - 時間 ÷ 月平均)) rather than set off an aside in prose.
4
+
5
+ const OPENING = new Set(["(", "("]);
6
+ const CLOSING = new Set([")", ")"]);
7
+ /** Inside the brackets: a multiplication or division sign, or a plus, minus or equals sign with a space on each side. Unspaced, - and = are hyphens and labels (A-1, 2026-04). */
8
+ const OPERATOR_INSIDE = /[×÷]|[ \u3000][++\-−-==][ \u3000]/u;
9
+ /** Just before the opening bracket, past spaces: a multiplication or division sign, or a spaced sign. */
10
+ const OPERATOR_BEFORE = /(?:[×÷]|[ \u3000][++\-−-==])[ \u3000]*$/u;
11
+ /** Just after the closing bracket, past spaces. An asterisk is not a sign here: in prose it marks a note (*(注)). */
12
+ const OPERATOR_AFTER = /^[ \u3000]*(?:[×÷]|[++\-−-==][ \u3000])/u;
13
+
14
+ type Scan = { readonly open: number[]; readonly pairs: Span[] };
15
+
16
+ const step = (scan: Scan, char: string, at: number): Scan => {
17
+ if (OPENING.has(char)) scan.open.push(at);
18
+ const start = CLOSING.has(char) ? scan.open.pop() : undefined;
19
+ if (start !== undefined) scan.pairs.push({ start, end: at + 1 });
20
+ return scan;
21
+ };
22
+
23
+ const isFormula = (text: string, pair: Span): boolean =>
24
+ OPERATOR_INSIDE.test(text.slice(pair.start + 1, pair.end - 1)) ||
25
+ OPERATOR_BEFORE.test(text.slice(0, pair.start)) ||
26
+ OPERATOR_AFTER.test(text.slice(pair.end));
27
+
28
+ /**
29
+ * The bracket pairs in text that belong to a formula, each span covering both brackets. Full-width and half-width brackets
30
+ * pair with each other. A bracket left unclosed or closing nothing is not part of any pair. Positions count from 0 in text.
31
+ */
32
+ export const formulaBracketSpans = (text: string): Span[] =>
33
+ text
34
+ .split("")
35
+ .reduce<Scan>(step, { open: [], pairs: [] })
36
+ .pairs.filter((pair) => isFormula(text, pair));
package/src/grade-api.ts CHANGED
@@ -11,10 +11,13 @@ import { withStyle } from "./config/style.ts";
11
11
  import { withExtensions } from "./extension/load.ts";
12
12
  import { GENRES } from "./genre.ts";
13
13
  import { gradeItem, type GradeSetup } from "./grade/grade-item.ts";
14
- import { readItem } from "./grade/item.ts";
14
+ import { expectProblems } from "./grade/expect-read.ts";
15
+ import type { GradeExpect } from "./grade/expect.ts";
16
+ import { readItem, type GradeItem } from "./grade/item.ts";
15
17
  import type { GradeResult } from "./grade/result.ts";
16
18
  import { parseRubric, type Rubric } from "./grade/rubric.ts";
17
19
  import { gradeSetup } from "./grade/setup.ts";
20
+ import { taskNamesOf } from "./grade/task-rubric.ts";
18
21
  import { GRADE_TEXT } from "./grade/text.ts";
19
22
  import { compareVariantGroups, type VariantComparison } from "./grade/variants.ts";
20
23
  import { variantGroupsOf, type VariantInput } from "./grade/variants-input.ts";
@@ -36,6 +39,7 @@ export type {
36
39
  SupportedFact,
37
40
  } from "./grade/result.ts";
38
41
  export type { OutputSize } from "./grade/rates.ts";
42
+ export type { GradeExpect } from "./grade/expect.ts";
39
43
  export type { AiLevelCounts, GradeAiScore } from "./grade/ai-score.ts";
40
44
  export { toScorer, type ChaffScore } from "./grade/scorer.ts";
41
45
  export type { Disagreement, VariantColumn, VariantComparison, VariantRates } from "./grade/variants.ts";
@@ -56,6 +60,10 @@ export type GradeOptions = {
56
60
  readonly genre?: string;
57
61
  /** The prompt, model or setting that produced the output, kept on the result for compareVariants(). */
58
62
  readonly variant?: string;
63
+ /** The rubric task to grade under: one of chaff.yaml's `grade.tasks`. The top-level rubric when left out. */
64
+ readonly task?: string;
65
+ /** Facts the output must state (`facts`) and must not (`absent`), each one fact as `chaff compare` reads it. */
66
+ readonly expect?: Partial<GradeExpect>;
59
67
  /** Run the experimental rules too, as --experimental does. chaff.yaml's `experimental` when left out. */
60
68
  readonly experimental?: boolean;
61
69
  /** chaff.yaml's path, or settings already read. Without it chaff's defaults apply and no file is read. */
@@ -125,36 +133,32 @@ const rubricOf = (config: Config): Rubric | undefined => {
125
133
  */
126
134
  const setups = new WeakMap<Config, Map<string, Promise<GradeSetup>>>();
127
135
 
128
- const setupFor = (config: Config, experimental: boolean, languages: readonly string[]): Promise<GradeSetup> => {
136
+ const setupFor = (config: Config, rubric: Rubric | undefined, experimental: boolean, languages: readonly string[]): Promise<GradeSetup> => {
129
137
  const run = { experimental, genre: undefined };
130
138
  const own = setups.get(config) ?? new Map<string, Promise<GradeSetup>>();
131
139
  setups.set(config, own);
132
- const key = `${String(experimental)}\n${languages.join(",")}`;
140
+ // The rubric is in the key: an item's task was checked against this rubric, so the setup must grade by the same one.
141
+ const key = `${String(experimental)}\n${languages.join(",")}\n${JSON.stringify(rubric) ?? ""}`;
133
142
  const known = own.get(key);
134
143
  if (known !== undefined) return known;
135
- const made = remember(own, key, gradeSetup(config, run, languages, rubricOf(config)));
144
+ const made = remember(own, key, gradeSetup(config, run, languages, rubric));
136
145
  // A language package that failed to load may be installed before the next call: do not keep the failure.
137
146
  made.catch(() => own.delete(key));
138
147
  return made;
139
148
  };
140
149
 
141
150
  /** The setup, or GradeInputError when a language package cannot be loaded, as `chaff grade` ends with 2 then. */
142
- const loadedSetup = async (config: Config, experimental: boolean, languages: readonly string[]): Promise<GradeSetup> => {
151
+ const loadedSetup = async (config: Config, rubric: Rubric | undefined, experimental: boolean, languages: readonly string[]): Promise<GradeSetup> => {
143
152
  try {
144
- return await setupFor(config, experimental, languages);
153
+ return await setupFor(config, rubric, experimental, languages);
145
154
  } catch (error) {
146
155
  if (error instanceof GradeInputError) throw error;
147
156
  throw new GradeInputError([TEXT.cannotLoad(error instanceof Error ? error.message : String(error))]);
148
157
  }
149
158
  };
150
159
 
151
- /**
152
- * Grades one output (spec §29.6): its findings and rates, its facts against `reference`, its `citations` against
153
- * `sources`, and pass or fail by chaff.yaml's `grade:` or the default. Reads a file only when `config` is a path, and
154
- * never writes one. Throws GradeInputError for an input or a chaff.yaml `chaff grade` would refuse with exit 2.
155
- */
156
- export const grade = async (output: string, options: GradeOptions = {}): Promise<GradeResult> => {
157
- const config = await configOf(options.config);
160
+ /** The options read as one line of `chaff grade`'s input, refused as that line would be. `tasks`: those the rubric defines. */
161
+ const itemOf = (output: string, options: GradeOptions, tasks: readonly string[]): GradeItem => {
158
162
  const raw = {
159
163
  id: options.id ?? "output",
160
164
  output,
@@ -165,11 +169,29 @@ export const grade = async (output: string, options: GradeOptions = {}): Promise
165
169
  language: options.language,
166
170
  genre: options.genre,
167
171
  variant: options.variant,
172
+ task: options.task,
173
+ expect: options.expect,
168
174
  };
169
- const read = readItem(raw, { isLanguage: (language) => packageFor(language) !== undefined, genres: GENRES });
175
+ const read = readItem(raw, { isLanguage: (language) => packageFor(language) !== undefined, genres: GENRES, tasks });
170
176
  if ("problem" in read) throw new GradeInputError([TEXT.problem(read.problem)]);
171
- const languages = read.item.language === undefined ? [] : [read.item.language];
172
- return gradeItem(read.item, await loadedSetup(config, options.experimental ?? config.experimental, languages));
177
+ return read.item;
178
+ };
179
+
180
+ /**
181
+ * Grades one output (spec §29.6): its findings and rates, its facts against `reference`, its `citations` against
182
+ * `sources`, its `expect` facts, and pass or fail by chaff.yaml's `grade:` (its `task`'s rubric when named) or the
183
+ * default. Reads a file only when `config` is a path, and never writes one. Throws GradeInputError for an input or a
184
+ * chaff.yaml `chaff grade` would refuse with exit 2, an unknown `task` or an `expect` entry that is not one fact among them.
185
+ */
186
+ export const grade = async (output: string, options: GradeOptions = {}): Promise<GradeResult> => {
187
+ const config = await configOf(options.config);
188
+ const rubric = rubricOf(config);
189
+ const item = itemOf(output, options, taskNamesOf(rubric));
190
+ const languages = item.language === undefined ? [] : [item.language];
191
+ const setup = await loadedSetup(config, rubric, options.experimental ?? config.experimental, languages);
192
+ const problems = await expectProblems(item, 0, setup);
193
+ if (problems.length > 0) throw new GradeInputError(problems.map((problem) => TEXT.problem(problem)));
194
+ return gradeItem(item, setup);
173
195
  };
174
196
 
175
197
  /**
@@ -41,16 +41,31 @@ const labelPattern = (label: NumberLabel): RegExp =>
41
41
  /** 見出しの頭の強調の印と空白。「**1. 概要**」も「1. 概要」と読む。 */
42
42
  const LEAD = /^[\s*_]+/u;
43
43
 
44
- /** 見出しの言葉から、番号の書き方を読む。番号を持つ語(第1章)を先に、字だけの形(1.)を後に見る。 */
45
- export const numberingStyleOf = (heading: string, labels: readonly NumberLabel[]): string => {
44
+ type NumberMark = { readonly style: string; readonly mark: string };
45
+
46
+ const markOf = (heading: string, labels: readonly NumberLabel[]): NumberMark => {
46
47
  const text = heading.replace(LEAD, "");
47
48
  const label = labels.find((candidate) => labelPattern(candidate).test(text));
48
- if (label !== undefined) return `label:${label.word.toLowerCase()}`;
49
- return SHAPES.find(([, shape]) => shape.test(text))?.[0] ?? UNNUMBERED;
49
+ if (label !== undefined) return { style: `label:${label.word.toLowerCase()}`, mark: labelPattern(label).exec(text)?.[0] ?? "" };
50
+ const shape = SHAPES.find(([, pattern]) => pattern.test(text));
51
+ return shape === undefined ? { style: UNNUMBERED, mark: "" } : { style: shape[0], mark: shape[1].exec(text)?.[0] ?? "" };
52
+ };
53
+
54
+ /** 見出しの言葉から、番号の書き方を読む。番号を持つ語(第1章)を先に、字だけの形(1.)を後に見る。 */
55
+ export const numberingStyleOf = (heading: string, labels: readonly NumberLabel[]): string => markOf(heading, labels).style;
56
+
57
+ /** 番号の中の数の一つ一つ(「7.1」の 7 と 1、「Chapter II」の II)。番号は印の最後に来るので、語の頭の大文字(Chapter の C)は最後にならない。 */
58
+ const NUMBER_TOKEN = /[0-90-9]+|[A-ZⅠ-Ⅻ①-⑳一二三四五六七八九十百]+/gu;
59
+ const FIRST_NUMBERS: ReadonlySet<string> = new Set(["1", "1", "I", "Ⅰ", "A", "①", "一"]);
60
+
61
+ /** 番号が並びの最初(1.、1.1、第1章、A.、①)か。最後の数が最初の数のときで、番号の無い見出しは並びを始めない。 */
62
+ export const opensNumbering = (heading: string, labels: readonly NumberLabel[]): boolean => {
63
+ const last = markOf(heading, labels).mark.match(NUMBER_TOKEN)?.at(-1);
64
+ return last !== undefined && FIRST_NUMBERS.has(last);
50
65
  };
51
66
 
52
- /** 見出し 1 つ。depth は深さ(#の数)、style は番号の書き方、skipped は番号を付けない前後の見出し(目次・参考文献)。 */
53
- export type NumberedHeading = { readonly depth: number; readonly style: string; readonly skipped: boolean };
67
+ /** 見出し 1 つ。depth は深さ(#の数)、style は番号の書き方、skipped は番号を付けない前後の見出し(目次・参考文献)、opens は番号が 1 から始まるか。 */
68
+ export type NumberedHeading = { readonly depth: number; readonly style: string; readonly skipped: boolean; readonly opens: boolean };
54
69
 
55
70
  /** 親(直前の浅い見出し)と深さが同じ見出しの組。番号は兄弟の見出しのあいだで揃える。位置は渡した並びの添え字。 */
56
71
  export const siblingGroups = (headings: readonly NumberedHeading[]): number[][] => {
@@ -87,13 +102,25 @@ const minorityBy = (members: readonly number[], keyOf: (at: number) => string):
87
102
  const minoritiesOf = (split: Split | undefined, kind: NumberingMinority["kind"]): NumberingMinority[] =>
88
103
  split === undefined ? [] : split.minority.map((at) => ({ at, kind, majority: split.majority, count: split.count, example: split.example }));
89
104
 
105
+ /** 番号の並びの最初の兄弟が 1 から始まるとき、その前の番号の無い兄弟(文書の題、「Applies to England」)は並びの外。番号付きの兄弟が二つ以上あるときだけ。 */
106
+ const MIN_NUMBERED_RUN = 2;
107
+
108
+ const leadingFrontMatter = (members: readonly number[], headings: readonly NumberedHeading[]): ReadonlySet<number> => {
109
+ const numbered = members.filter((at) => (headings[at]?.style ?? UNNUMBERED) !== UNNUMBERED);
110
+ const first = numbered[0];
111
+ if (first === undefined || numbered.length < MIN_NUMBERED_RUN || headings[first]?.opens !== true) return new Set();
112
+ return new Set(members.filter((at) => at < first));
113
+ };
114
+
90
115
  /**
91
116
  * 兄弟の見出しのうち、少ないほうの書き方のもの。先に番号の有無を比べ(「1. 概要」「2. 手順」「まとめ」の「まとめ」)、
92
- * 番号の付いた見出しのあいだで書き方を比べる(「1.」「2.」「3)」の「3)」)。同じ数なら言わない(二つだけの兄弟は必ず同じ数か一つの書き方)。前後の見出し(目次・参考文献)は数えない。
117
+ * 番号の付いた見出しのあいだで書き方を比べる(「1.」「2.」「3)」の「3)」)。同じ数なら言わない(二つだけの兄弟は必ず同じ数か一つの書き方)。前後の見出し(目次・参考文献)と、1 から始まる番号の前の見出しは数えない。
93
118
  */
94
119
  export const numberingMinorities = (headings: readonly NumberedHeading[]): NumberingMinority[] =>
95
120
  siblingGroups(headings).flatMap((group) => {
96
- const members = group.filter((at) => headings[at]?.skipped !== true);
121
+ const listed = group.filter((at) => headings[at]?.skipped !== true);
122
+ const front = leadingFrontMatter(listed, headings);
123
+ const members = listed.filter((at) => !front.has(at));
97
124
  const styleOf = (at: number): string => headings[at]?.style ?? UNNUMBERED;
98
125
  const numbered = members.filter((at) => styleOf(at) !== UNNUMBERED);
99
126
  return [
@@ -37,6 +37,7 @@ import { withoutFootnoteMarks } from "./html-footnote-marks.ts";
37
37
  import { withoutHeadingSelfLinks } from "./html-heading-links.ts";
38
38
  import { withLostParagraphTagsRestored } from "./html-lost-tags.ts";
39
39
  import { withoutReaderOnlyText } from "./html-reader-only.ts";
40
+ import { withoutSiteChrome } from "./html-site-chrome.ts";
40
41
  import { withRunInHeadingsRead } from "./html-run-in-headings.ts";
41
42
  import { withoutWidgets } from "./html-widgets.ts";
42
43
  import { withPreformattedRestored, withPreformattedStashed } from "./html-preformatted.ts";
@@ -465,7 +466,7 @@ export const htmlToMarkdown = (html: string): string => {
465
466
  const uncommented = withLostParagraphTagsRestored(withAttributeMarkupEscaped(html).replace(/<!--[\s\S]*?-->|<\?[\s\S]*?\?>/gu, ""));
466
467
  const preformatted = withPreformattedStashed(withTablesRead(DROPPED.reduce(withoutElement, withoutRubyText(uncommented))));
467
468
  const kept = withoutFootnoteMarks(
468
- withoutHeadingSelfLinks(withoutWidgets(withoutButtons(withoutReaderOnlyText(withoutHiddenElements(mainContent(preformatted.html)))))),
469
+ withoutHeadingSelfLinks(withoutWidgets(withoutButtons(withoutReaderOnlyText(withoutHiddenElements(mainContent(withoutSiteChrome(preformatted.html))))))),
469
470
  ).replace(MARKUP_SPACE, " ");
470
471
  const content = withoutClosingLinks(
471
472
  withoutLinkGroups(withoutNavigation(withoutIconMenus(withoutSiteHeader(withoutNavigationLandmarks(withoutClosingAddress(kept)))))),
@@ -0,0 +1,47 @@
1
+ // The site's own chrome around a page, read from what the markup says a block is rather than from
2
+ // any site's wording. A landmark role (banner, search, contentinfo), a <search> element, a <header> that belongs to the
3
+ // page rather than to a section, and a block named by a convention CMSs share: a breadcrumb trail (breadcrumb, pankuzu,
4
+ // topicpath), a search box, the header or footer block (id or class exactly "header" or "footer"), and the U.S.
5
+ // government's ".gov" banner (usa-banner). A block holding the page's <h1> is never chrome. Pure; a regular-expression
6
+ // reading, not a parser.
7
+ import { ATTRIBUTES, elementRanges, isInside, withoutElementsOpening, withoutRanges, type ElementRange } from "./html-elements.ts";
8
+
9
+ const CHROME_ROLES = new Set(["banner", "search", "contentinfo"]);
10
+
11
+ // A name segment, so that "pankuzu_wrap", "foot_pankuzu" and "cse-search-box" match and "research" does not.
12
+ const CHROME_NAME = /(?:^|[-_])(?:breadcrumbs?|pankuzu|topic-?path|search)(?:[-_\d]|$)/iu;
13
+
14
+ const REGION_NAME = /^(?:header|footer|usa-banner)$/iu;
15
+
16
+ const NAMED_OPENING = /<([a-z][a-z0-9-]*)\b[^>]*\s(?:class|id|role)\s*=/giu;
17
+
18
+ const attributeValue = (openTag: string, name: string): string => {
19
+ const value = new RegExp(String.raw`^<[a-z][a-z0-9-]*${ATTRIBUTES}\s+${name}\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))`, "iu").exec(openTag);
20
+ return value?.[1] ?? value?.[2] ?? value?.[3] ?? "";
21
+ };
22
+
23
+ const tokens = (value: string): string[] => value.split(/\s+/u).filter((token) => token !== "");
24
+
25
+ const holdsTitle = (range: ElementRange): boolean => /<h1\b/iu.test(range.inner);
26
+
27
+ /** A role is a list of tokens and the first one counts, as for role="main". */
28
+ const hasChromeRole = (openTag: string): boolean => CHROME_ROLES.has((tokens(attributeValue(openTag, "role"))[0] ?? "").toLowerCase());
29
+
30
+ const hasChromeName = (openTag: string): boolean =>
31
+ [...tokens(attributeValue(openTag, "class")), ...tokens(attributeValue(openTag, "id"))].some((name) => CHROME_NAME.test(name) || REGION_NAME.test(name));
32
+
33
+ /** A block the markup names or marks as the site's chrome, unless it holds the page's title. */
34
+ export const isSiteChrome = (range: ElementRange): boolean => !holdsTitle(range) && (hasChromeRole(range.openTag) || hasChromeName(range.openTag));
35
+
36
+ const SECTIONING = ["article", "section", "main", "aside", "nav"];
37
+
38
+ /** A <header> inside an article or a section heads that part; one outside them is the page's banner. */
39
+ const withoutPageHeaders = (html: string): string => {
40
+ const sections = SECTIONING.flatMap((tag) => elementRanges(html, tag));
41
+ const banners = elementRanges(html, "header").filter((header) => !holdsTitle(header) && !sections.some((section) => isInside(section, header)));
42
+ return withoutRanges(html, banners);
43
+ };
44
+
45
+ const withoutSearchElements = (html: string): string => withoutRanges(html, elementRanges(html, "search"));
46
+
47
+ export const withoutSiteChrome = (html: string): string => withoutPageHeaders(withoutSearchElements(withoutElementsOpening(html, NAMED_OPENING, isSiteChrome)));
@@ -62,6 +62,7 @@ const sentenceInSource =
62
62
  text: text.slice(span.start, span.end),
63
63
  ...(sentence.tokens === undefined ? {} : { tokens: sentence.tokens.map(tokenInSource(view)) }),
64
64
  ...(sentence.embeddedLanguage === undefined ? {} : { embeddedLanguage: sentence.embeddedLanguage }),
65
+ ...(sentence.listItem === undefined ? {} : { listItem: sentence.listItem }),
65
66
  };
66
67
  };
67
68
 
@@ -0,0 +1,98 @@
1
+ // A long kanji compound the document writes several times, and once or twice with one kanji changed (就職氷河期世代 ×5,
2
+ // 就職永河期世代 ×2). Pure: the compounds come in with the words the analyser cut them into; which kanji may differ by
3
+ // design (一, 第, 条) comes from a word list.
4
+
5
+ /** One word of the analyser inside a compound, by kanji index: [start, end). `known` is false for a word not in its dictionary. */
6
+ export type CompoundWord = {
7
+ readonly start: number;
8
+ readonly end: number;
9
+ readonly known: boolean;
10
+ /** The word reaches past the run (並びに after 受遺者); only its part inside is given. */
11
+ readonly crossesRun?: boolean;
12
+ };
13
+
14
+ export type CompoundUse = {
15
+ readonly compound: string;
16
+ readonly offset: number;
17
+ /** Absent where nothing was analysed. */
18
+ readonly words?: readonly CompoundWord[] | undefined;
19
+ };
20
+
21
+ type CompoundSlip = {
22
+ readonly written: string;
23
+ readonly usual: string;
24
+ readonly usualCount: number;
25
+ readonly offset: number;
26
+ readonly index: number;
27
+ };
28
+
29
+ const MIN_COMPOUND_LENGTH = 4;
30
+ const MIN_USUAL_COUNT = 3;
31
+ /** A slip copied once (a link and its twin) is still a slip; the usual form must then be written more than twice as often. */
32
+ const MAX_SLIP_COUNT = 2;
33
+
34
+ /** The one position where two compounds of the same length differ, or undefined when they differ in none or several. */
35
+ export const singleDifference = (left: readonly string[], right: readonly string[]): number | undefined => {
36
+ if (left.length !== right.length) return undefined;
37
+ const differing = left.flatMap((char, index) => (char === right[index] ? [] : [index]));
38
+ return differing.length === 1 ? differing[0] : undefined;
39
+ };
40
+
41
+ /** The first and last kanji of a run are where a suffix (等, 者) or a conjunction written in kanji (及, 又) joins, not where a word is mistyped. */
42
+ const isInside = (index: number, length: number): boolean => index > 0 && index < length - 1;
43
+
44
+ const wordAt = (use: CompoundUse, index: number): CompoundWord | undefined => use.words?.find((word) => word.start <= index && index < word.end);
45
+
46
+ const isLooseWithin = (word: CompoundWord | undefined, outer: CompoundWord): boolean =>
47
+ word !== undefined && word.crossesRun !== true && (!word.known || word.end - word.start === 1) && word.start >= outer.start && word.end <= outer.end;
48
+
49
+ /**
50
+ * The analyser cannot read the changed word: where the usual form holds the kanji inside one word (氷河期), the slip
51
+ * falls apart there into single kanji or words it does not know (永 / 河 / 期). Returns the slip's kanji over that word.
52
+ */
53
+ export const fallenWord = (slip: CompoundUse, usualUses: readonly CompoundUse[], index: number): string | undefined => {
54
+ const usualWord = usualUses.map((use) => wordAt(use, index)).find((word) => word !== undefined && word.end - word.start > 1);
55
+ if (usualWord === undefined) return undefined;
56
+ const positions = Array.from({ length: usualWord.end - usualWord.start }, (_, offset) => usualWord.start + offset);
57
+ const apart = positions.every((position) => isLooseWithin(wordAt(slip, position), usualWord));
58
+ return apart ? Array.from(slip.compound).slice(usualWord.start, usualWord.end).join("") : undefined;
59
+ };
60
+
61
+ /** The changed word written in another kanji run (質権 in 質権者は beside 当該質権者): a word the document knows. */
62
+ const isWrittenElsewhere = (word: string, slip: string, uses: readonly CompoundUse[]): boolean =>
63
+ uses.some((use) => use.compound !== slip && use.compound.includes(word));
64
+
65
+ type SlipContext = { readonly ignored: ReadonlySet<string>; readonly uses: readonly CompoundUse[] };
66
+
67
+ type Usual = { readonly compound: string; readonly count: number; readonly uses: readonly CompoundUse[] };
68
+
69
+ const countsOf = (uses: readonly CompoundUse[]): ReadonlyMap<string, number> =>
70
+ uses.reduce((counts, use) => counts.set(use.compound, (counts.get(use.compound) ?? 0) + 1), new Map<string, number>());
71
+
72
+ const usualsOf = (uses: readonly CompoundUse[], counts: ReadonlyMap<string, number>): Usual[] =>
73
+ [...counts]
74
+ .filter(([compound, count]) => count >= MIN_USUAL_COUNT && Array.from(compound).length >= MIN_COMPOUND_LENGTH)
75
+ .map(([compound, count]) => ({ compound, count, uses: uses.filter((use) => use.compound === compound) }));
76
+
77
+ const slipAgainst = (use: CompoundUse, count: number, usual: Usual, context: SlipContext): CompoundSlip | undefined => {
78
+ const [written, other] = [Array.from(use.compound), Array.from(usual.compound)];
79
+ const index = usual.count > count * 2 ? singleDifference(written, other) : undefined;
80
+ if (index === undefined || !isInside(index, written.length)) return undefined;
81
+ if (context.ignored.has(written[index] ?? "") || context.ignored.has(other[index] ?? "")) return undefined;
82
+ const fallen = fallenWord(use, usual.uses, index);
83
+ if (fallen === undefined || isWrittenElsewhere(fallen, use.compound, context.uses)) return undefined;
84
+ return { written: use.compound, usual: usual.compound, usualCount: usual.count, offset: use.offset, index };
85
+ };
86
+
87
+ /** Each compound written once or twice that differs in one kanji from a compound of the same length written at least three times. */
88
+ export const compoundSlipsIn = (uses: readonly CompoundUse[], ignored: ReadonlySet<string>): CompoundSlip[] => {
89
+ const counts = countsOf(uses);
90
+ const usuals = usualsOf(uses, counts);
91
+ if (usuals.length === 0) return [];
92
+ return uses.flatMap((use) => {
93
+ const count = counts.get(use.compound) ?? 0;
94
+ if (count > MAX_SLIP_COUNT || Array.from(use.compound).length < MIN_COMPOUND_LENGTH) return [];
95
+ const slips = usuals.flatMap((usual) => slipAgainst(use, count, usual, { ignored, uses }) ?? []);
96
+ return slips.length === 1 ? slips : [];
97
+ });
98
+ };
@@ -0,0 +1,38 @@
1
+ import type { Span } from "./plugin.ts";
2
+
3
+ const FULLWIDTH_OFFSET = 0xfee0;
4
+ const LATIN_LETTER = /[A-Za-z]/u;
5
+ const SPACE = "[\\s\\u3000]";
6
+
7
+ /**
8
+ * 形は名前の後ろに立つ。前は大文字か数字で始まる名前の語か括弧で、あいだは空白か「,」だけ(AOBA INC.、AOBA,INC.、
9
+ * (THAILAND) CO.,LTD.)。語の中(Zinc の inc)、略語の中(U.S.A. の S.A.)、名前の無い所(the LLC)の同じ字は形ではない。
10
+ */
11
+ const NAME_WORD = "(?<![A-Za-zA-Za-z])[A-ZA-Z0-90-9][A-Za-zA-Za-z0-90-9&&]*";
12
+ const BEFORE = `(?<=${NAME_WORD}(?:${SPACE}|[,,]${SPACE}?)|[))]${SPACE}?)`;
13
+ const AFTER = "(?![A-Za-zA-Za-z0-90-9&&])";
14
+
15
+ const escaped = (char: string): string => char.replace(/[.*+?^${}()|[\]\\]/u, "\\$&");
16
+
17
+ const widths = (char: string): string[] => [char, String.fromCodePoint((char.codePointAt(0) ?? 0) + FULLWIDTH_OFFSET)];
18
+
19
+ /** 一字の形。英字は大文字・小文字と全角・半角のどれでも、点と「,」は全角・半角のどちらでも合う。空白は無くても合う。 */
20
+ const charPattern = (char: string): string => {
21
+ if (char === " ") return `${SPACE}?`;
22
+ if (LATIN_LETTER.test(char)) return `[${[char.toUpperCase(), char.toLowerCase()].flatMap(widths).join("")}]`;
23
+ return /[.,]/u.test(char) ? `[${widths(char).map(escaped).join("")}]` : escaped(char);
24
+ };
25
+
26
+ /** 形は点まで書いたとおりに照らす。点の無い LTD(the LTD fund)は形と読まない。英字で終わる形(LLC)は語の終わりで閉じる。 */
27
+ const formPattern = (form: string): string => [...form].map(charPattern).join("") + (LATIN_LETTER.test(form.slice(-1)) ? AFTER : "");
28
+
29
+ /** 形の語彙表を、一つの正規表現にする。長い形を先に試す。名前の語は大文字で始まるので、大文字・小文字は形の側だけで問わない。 */
30
+ export const latinCompanyFormRegExp = (forms: readonly string[]): RegExp | undefined => {
31
+ if (forms.length === 0) return undefined;
32
+ const longestFirst = [...forms].sort((a, b) => b.length - a.length);
33
+ return new RegExp(`${BEFORE}(?:${longestFirst.map(formPattern).join("|")})`, "gu");
34
+ };
35
+
36
+ /** text の中の、英字の会社の名前の後ろに立つ形(CO.,LTD.、Inc.)の位置。大文字・小文字と全角・半角を問わない。 */
37
+ export const latinCompanyFormSpans = (text: string, pattern: RegExp | undefined): Span[] =>
38
+ pattern === undefined ? [] : [...text.matchAll(pattern)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
@@ -0,0 +1,46 @@
1
+ import type { Boundary } from "./orthography.ts";
2
+ import type { Span, Token } from "./plugin.ts";
3
+
4
+ // 英字の語の側で決まる、空け方の好みでない境目。pure: 語は語彙表から受け取る。
5
+
6
+ /** 英字の語を作る字。vs. の点も語の一部。 */
7
+ const LATIN_WORD_CHAR = /[A-Za-z.]/u;
8
+ const LATIN_WORD_AFTER = /^[A-Za-z.]+/u;
9
+ const JAPANESE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}ー]/u;
10
+
11
+ /** 境目の英字の側の語の範囲(「名前 or 任意」の or)。 */
12
+ const latinWordAt = (text: string, boundary: Boundary): Span => {
13
+ if (LATIN_WORD_CHAR.test(text[boundary.offset - 1] ?? "")) {
14
+ const reversed = Array.from(text.slice(0, boundary.offset)).toReversed().join("");
15
+ return { start: boundary.offset - (LATIN_WORD_AFTER.exec(reversed)?.[0].length ?? 0), end: boundary.offset };
16
+ }
17
+ const start = boundary.offset + (boundary.spaced ? 1 : 0);
18
+ return { start, end: start + (LATIN_WORD_AFTER.exec(text.slice(start))?.[0].length ?? 0) };
19
+ };
20
+
21
+ /** 語の前後が空白一つで、その外がどちらも日本語の字。 */
22
+ const standsBetweenJapanese = (text: string, word: Span): boolean =>
23
+ text[word.start - 1] === " " && text[word.end] === " " && JAPANESE.test(text[word.start - 2] ?? "") && JAPANESE.test(text[word.end + 1] ?? "");
24
+
25
+ /**
26
+ * 日本語の句と句をつなぐ英語の語(「名前 or メッセージ」「甲案 vs. 乙案」の or、vs.)の前後の空白。or を詰めて書くことは無く、
27
+ * 語を区切る空白で、日本語と英字のあいだの空け方の票ではない。片側が英字の語(A or 任意、名前 or API)なら数える。
28
+ * joiners は語彙表 latin-joiner の語(小文字)。
29
+ */
30
+ export const isJoinerSpace = (text: string, boundary: Boundary, joiners: ReadonlySet<string>): boolean => {
31
+ if (boundary.kind !== "letter" || !boundary.spaced) return false;
32
+ const word = latinWordAt(text, boundary);
33
+ return joiners.has(text.slice(word.start, word.end).toLowerCase()) && standsBetweenJapanese(text, word);
34
+ };
35
+
36
+ /**
37
+ * 英字の語に付けて一つの語にする日本語の接尾の語(PDF版、IT化、Apple製)の前の境目。空けて書くことはほとんど無く、
38
+ * 詰めたのは空け方の好みではない。語の頭の字が同じでも別の語(製品、型番)なら数える。suffixes は語彙表 latin-bound-suffix の語。
39
+ * tokens は文書全体の座標で、base は text の先頭の位置。
40
+ */
41
+ export const isBoundSuffix = (text: string, boundary: Boundary, tokens: readonly Token[] | undefined, base: number, suffixes: ReadonlySet<string>): boolean => {
42
+ if (tokens === undefined || boundary.kind !== "letter" || !LATIN_WORD_CHAR.test(text[boundary.offset - 1] ?? "")) return false;
43
+ const start = base + boundary.offset + (boundary.spaced ? 1 : 0);
44
+ const suffix = tokens.find((token) => token.span.start === start);
45
+ return suffix !== undefined && suffixes.has(suffix.surface);
46
+ };
@@ -1,7 +1,7 @@
1
1
  import type { Lexicon } from "./plugin.ts";
2
2
 
3
3
  /** A genre is in a target when it is the target or one of its genres (legal/contract is in legal). */
4
- const isIn = (genre: string, target: string): boolean => genre === target || genre.startsWith(`${target}/`);
4
+ export const isIn = (genre: string, target: string): boolean => genre === target || genre.startsWith(`${target}/`);
5
5
 
6
6
  /**
7
7
  * The entries of a word list that hold for the document's genre: an entry without genres holds everywhere, one with genres only
package/src/link-shape.ts CHANGED
@@ -60,3 +60,22 @@ export const isFileNameAlt = (alt: string, prefixes: readonly string[]): boolean
60
60
  const lowered = written.toLowerCase();
61
61
  return prefixes.some((prefix) => lowered.startsWith(prefix.toLowerCase()) && COUNTER.test(written.slice(prefix.length)));
62
62
  };
63
+
64
+ /** A list item's marker before a line's text (`- `, `* `, `1. `). */
65
+ const LIST_MARKER = /^\s*(?:[-*+]|\d{1,3}[.)])\s+/u;
66
+ /**
67
+ * A field's label: a few words in bold (`**Licence text**`, a colon after it or not), or ending in a colon (`Website:`).
68
+ * Sentence punctuation or a comma in it makes it prose (`For example, visit:`).
69
+ */
70
+ const BOLD_LABEL = /^(?:\*\*[^*\n.!?。!?,,、::]{1,40}\*\*|__[^_\n.!?。!?,,、::]{1,40}__)\s*[::]?$/u;
71
+ const COLON_LABEL = /^[^.!?。!?,,、::]{1,40}[::]$/u;
72
+
73
+ /**
74
+ * Whether a URL is the value of a field (`**Licence text** https://…`, `Website: https://…`): on its line only a label comes
75
+ * before it and nothing after. There the address is the content, as in a table cell, so writing it bare is right.
76
+ */
77
+ export const isFieldValueUrl = (lineBefore: string, lineAfter: string): boolean => {
78
+ if (lineAfter.trim() !== "") return false;
79
+ const label = lineBefore.replace(LIST_MARKER, "").trim();
80
+ return BOLD_LABEL.test(label) || COLON_LABEL.test(label);
81
+ };