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
@@ -7,7 +7,7 @@ import { lookalikeSlipsIn, type LookalikeChars } from "../name-lookalike-chars.t
7
7
  import { givenNameReadingOf, readingOfWords, type CharReadings } from "../name-char-reading.ts";
8
8
  import { nameCueAt, type NameCues } from "../name-cue.ts";
9
9
  import { quoteAt } from "./structure-tree.ts";
10
- import { companyMentionsIn, companyVariants, type CompanyForm, type IsProper, type PredicateEnds } from "../company-names.ts";
10
+ import { companyMentionsIn, companyVariants, type CompanyForm, type CompanyMention, type IsProper, type PredicateEnds } from "../company-names.ts";
11
11
  import { kanaSpelledCompanies, type ReadWord } from "../company-kana-spelling.ts";
12
12
  import { proseAndTablesOf } from "../table-text.ts";
13
13
  import { tableBodyCells } from "../facts/table-facts.ts";
@@ -23,6 +23,7 @@ import { spacedPersonNamesIn } from "../spaced-person-name.ts";
23
23
  import { isOrdinaryToken, withOrdinaryWords } from "../name-ordinary-word.ts";
24
24
  import { isInPersonField } from "../person-field.ts";
25
25
  import { labelledSpans, orderNamesOf, quotedSpans, stemOf, titleCaseSpans, wordOrderVariants, type OrderWord } from "../name-word-order.ts";
26
+ import { isGroupPairOf, notDefinedTerms, outsideCapitals, sentenceIndexOf, withGivenNames } from "./name-variant-apart.ts";
26
27
 
27
28
  // 人の名前と読ませる敬称(様、さん)は語彙表 person-suffix、人を指す前置き(担当の)は person-lead、名前のすぐ後ろに来る語
28
29
  // (です、まで)は name-particle、字体の違う同じ字(斎・斉・齋)は name-variant-char が組(group)ごとに言う。
@@ -145,20 +146,22 @@ const predicateEndsOf = (doc: ProseDocument): PredicateEnds =>
145
146
  const readWordsOf = (doc: ProseDocument): ReadWord[] =>
146
147
  tokensOf(doc).map((token) => ({ start: token.span.start, end: token.span.end, surface: token.surface, reading: token.reading }));
147
148
 
149
+ /** 会社の名前の現れ。大文字で書いた一節の中のものは除く。 */
150
+ const companyMentionsOf = (doc: ProseDocument, prose: string): CompanyMention[] =>
151
+ outsideCapitals(prose, companyMentionsIn(prose, [...companyFormsOf(doc), ...foreignFormsOf(doc)], properOf(doc), kanaStopsOf(doc), predicateEndsOf(doc)));
152
+
148
153
  /**
149
154
  * 会社の名前の書き分けと、名前の漢字一字をその読みのかなで書いた所(みどり野 と みどりの)。名前の見方がすでに指した所と重なる
150
155
  * ものは除く。
151
156
  */
152
- const companyFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[]): Reported[] => {
153
- const stops = kanaStopsOf(doc);
154
- const mentions = companyMentionsIn(prose, [...companyFormsOf(doc), ...foreignFormsOf(doc)], properOf(doc), stops, predicateEndsOf(doc));
157
+ const companyFindings = (doc: ProseDocument, prose: string, mentions: readonly CompanyMention[], reported: readonly Reported[]): Reported[] => {
155
158
  const variants = companyVariants(mentions).map(({ mention, usual, kind }) => ({
156
159
  offset: mention.offset,
157
160
  name: mention.surface,
158
161
  usual,
159
162
  kind: kind === "spelling" ? kind : `company-${kind}`,
160
163
  }));
161
- const kana = kanaSpelledCompanies(prose, mentions, readWordsOf(doc), stops.particles)
164
+ const kana = kanaSpelledCompanies(prose, mentions, readWordsOf(doc), kanaStopsOf(doc).particles)
162
165
  .map(({ surface, offset, usual }) => ({ offset, name: surface, usual, kind: "company-kana" }))
163
166
  .filter((found) => !overlapsAny(variants, found.offset, found.name.length));
164
167
  return [...variants, ...kana].filter(({ offset, name }) => !overlapsAny(reported, offset, name.length));
@@ -207,6 +210,9 @@ const orderWordsOf = (doc: ProseDocument): OrderWord[] => {
207
210
  .map((token) => ({ start: token.span.start, end: token.span.end, key: stemOf(token.surface, suffixes) }));
208
211
  };
209
212
 
213
+ /** 語彙表 name-title-joiner の、前置詞の後ろにだけ立つ冠詞(the)の組。 */
214
+ const ARTICLE = "article";
215
+
210
216
  /**
211
217
  * 語の順を入れ替えて書いた同じ名前(統計学基礎 と 基礎統計学)。名前と読める所は、括弧の中(name-quote)、大文字で始まる語の並び
212
218
  * (name-title-joiner を挟んでよい)、名前を書く欄の後ろ(name-label)。大文字の語の並びどうしは、片方が表の升まるごとに
@@ -214,13 +220,20 @@ const orderWordsOf = (doc: ProseDocument): OrderWord[] => {
214
220
  */
215
221
  const orderFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[]): Reported[] => {
216
222
  const starts = sentenceStartsOf(doc);
223
+ const joiners = doc.lexicons["name-title-joiner"] ?? [];
217
224
  const spans = [
218
225
  ...quotedSpans(prose, patternsOf(doc, "name-quote")),
219
- ...titleCaseSpans(prose, patternsOf(doc, "name-title-joiner"), (offset) => starts.has(offset)),
226
+ ...titleCaseSpans(
227
+ prose,
228
+ joiners.filter((entry) => entry.group !== ARTICLE).map((entry) => entry.pattern),
229
+ (offset) => starts.has(offset),
230
+ joiners.filter((entry) => entry.group === ARTICLE).map((entry) => entry.pattern),
231
+ ),
220
232
  ...labelledSpans(prose, patternsOf(doc, "name-label")),
221
233
  ];
222
234
  const cells = new Set(tableBodyCells(proseAndTablesOf(doc)).map((cell) => cell.text.trim()));
223
- return wordOrderVariants(orderNamesOf(doc.source, spans, orderWordsOf(doc), orderStopsOf(doc)), cells)
235
+ const names = notDefinedTerms(doc, orderNamesOf(doc.source, spans, orderWordsOf(doc), orderStopsOf(doc)));
236
+ return wordOrderVariants(names, cells, sentenceIndexOf(doc))
224
237
  .filter(({ name }) => !overlapsAny(reported, name.offset, name.surface.length))
225
238
  .map(({ name, usual }) => ({ offset: name.offset, name: name.surface, usual, kind: "order" }));
226
239
  };
@@ -270,7 +283,7 @@ const tokenRunsOf = (sentence: Sentence): readonly (readonly Token[])[] => {
270
283
  const nameMentionsOf = (doc: ProseDocument, prose: string, chars: VariantChars): NameMention[] => {
271
284
  const cues: NameCues = { leads: patternsOf(doc, "person-lead"), suffixes: patternsOf(doc, "person-suffix"), particles: patternsOf(doc, "name-particle") };
272
285
  const charReadings = charReadingsOf(doc);
273
- const tagged = doc.sentences.flatMap((sentence) => tokenRunsOf(sentence).flatMap((tokens) => mentionsIn(tokens, doc.source, cues.suffixes, charReadings)));
286
+ const tagged = doc.sentences.flatMap((sentence) => tokenRunsOf(sentence).flatMap((tokens) => mentionsIn(tokens, prose, cues.suffixes, charReadings)));
274
287
  const taggedOrSuffixed = [...tagged, ...suffixedNamesIn(prose, cues.suffixes, chars, tagged)];
275
288
  const cued = [...taggedOrSuffixed, ...cuedNamesIn(prose, cues, chars, taggedOrSuffixed)].map((mention): NameMention => {
276
289
  const cue = mention.cue ?? nameCueAt(prose, mention.offset, mention.surface, cues);
@@ -281,7 +294,7 @@ const nameMentionsOf = (doc: ProseDocument, prose: string, chars: VariantChars):
281
294
  const outside = joined.filter(
282
295
  (mention) => !spaced.some((name) => name.offset < mention.offset + mention.surface.length && mention.offset < name.offset + name.surface.length),
283
296
  );
284
- return withKnownNeighbours([...outside, ...spaced], prose).toSorted((left, right) => left.offset - right.offset);
297
+ return outsideCapitals(prose, withKnownNeighbours([...outside, ...spaced], prose)).toSorted((left, right) => left.offset - right.offset);
285
298
  };
286
299
 
287
300
  /** 人の名前で形の似た別の字(太 と 大)は語彙表 name-lookalike-char が組(group)ごとに言う。 */
@@ -352,10 +365,15 @@ const wordUseOf = (doc: ProseDocument): WordUse => {
352
365
  export const nameVariant: Detector = (doc): Finding[] => {
353
366
  const prose = doc.prose ?? doc.source;
354
367
  const chars = variantCharsOf(doc);
355
- const mentions = labelledNamesOf(doc, ordinaryNamesOf(doc, nameMentionsOf(doc, prose, chars)));
368
+ const mentions = labelledNamesOf(doc, ordinaryNamesOf(doc, withGivenNames(tokensOf(doc), doc.source, nameMentionsOf(doc, prose, chars))));
369
+ const companies = companyMentionsOf(doc, prose);
370
+ const inGroup = isGroupPairOf(
371
+ companies,
372
+ companyFormsOf(doc).map((form) => form.pattern),
373
+ );
356
374
  const variants = nameVariants(mentions, chars, spellingInputOf(doc), wordUseOf(doc))
357
375
  .map(({ mention, usual, kind }): Reported => ({ offset: mention.offset, name: mention.surface, usual, kind }))
358
- .filter(notSpacingOnly);
376
+ .filter((found) => notSpacingOnly(found) && !inGroup(found));
359
377
  const lookalikes = lookalikeSlipsIn(mentions, lookalikeCharsOf(doc)).map(({ mention, usual }) => ({
360
378
  offset: mention.offset,
361
379
  name: mention.surface,
@@ -363,7 +381,7 @@ export const nameVariant: Detector = (doc): Finding[] => {
363
381
  kind: "lookalike",
364
382
  }));
365
383
  const names = [...variants, ...lookalikes.filter((found) => !overlapsAny(variants, found.offset, found.name.length))];
366
- const namesAndCompanies = [...names, ...companyFindings(doc, prose, names)];
384
+ const namesAndCompanies = [...names, ...companyFindings(doc, prose, companies, names)];
367
385
  const withTables = [...namesAndCompanies, ...tableFindings(doc, prose, mentions, namesAndCompanies).filter(notSpacingOnly)];
368
386
  const withPlaces = [...withTables, ...placeFindings(doc, prose, withTables, chars)];
369
387
  const withProducts = [...withPlaces, ...productFindings(doc, prose, withPlaces)];
@@ -0,0 +1,33 @@
1
+ import { entryIn } from "./lexicon-match.ts";
2
+ import type { LexiconEntry, Paragraph, Sentence } from "../plugin.ts";
3
+
4
+ /** 一文だけの断りは本文の書き損じのことがある。段落ごと別の調子で揃えてあるときだけ、意図した別の声と読む。 */
5
+ const MIN_SENTENCES = 2;
6
+
7
+ /**
8
+ * 断り書きの段落(「…無償で提供します。…一切の責任を負いません。…ご了承ください。」)の文。
9
+ * 免責や変更の予告は、である調の文書でもですます調で書く決まり文句で、本文と文末の調子を比べるものではない。
10
+ * 断りの語(cues)を含み、調子を持つ文が MIN_SENTENCES 以上あって、それがみな同じ、文書の多いほう(majority)ではない調子の段落だけ。
11
+ * 調子が混ざった段落と、文書と同じ調子の段落は、本文と同じに数える。
12
+ */
13
+ export const noticeSentences = <R>(
14
+ paragraphs: readonly Paragraph[],
15
+ cues: readonly LexiconEntry[],
16
+ registerOf: (sentence: Sentence) => R | undefined,
17
+ majority: R | undefined,
18
+ ): Set<Sentence> =>
19
+ new Set(
20
+ paragraphs.flatMap((paragraph) => {
21
+ const registers = new Set(
22
+ paragraph.sentences.flatMap((sentence) => {
23
+ const register = registerOf(sentence);
24
+ return register === undefined ? [] : [register];
25
+ }),
26
+ );
27
+ const counted = paragraph.sentences.filter((sentence) => registerOf(sentence) !== undefined).length;
28
+ const [only] = registers;
29
+ const ownVoice = counted >= MIN_SENTENCES && registers.size === 1 && only !== majority;
30
+ const notice = ownVoice && paragraph.sentences.some((sentence) => cues.some((cue) => entryIn(sentence, cue)));
31
+ return notice ? paragraph.sentences : [];
32
+ }),
33
+ );
@@ -51,12 +51,24 @@ const MAGNITUDES = /^[一百千万億]+$/u;
51
51
 
52
52
  const isIdiomNumeral = (numeral: string): boolean => MAGNITUDES.test(numeral);
53
53
 
54
- const countMarks = (text: string, base: number, words: NumberWords): NumberMark[] => {
54
+ /**
55
+ * A number set off by a space from a word that only begins with a counter: 三, a space, 人事委員会 is the item number 三 of a list,
56
+ * not 三人. The tokenizer reads 人事 as one word there and 人 alone in 3 人が来た.
57
+ */
58
+ const isBeforeLongerWord = (numeral: string, written: string, offset: number, tokens: readonly Token[]): boolean => {
59
+ const counter = written.slice(numeral.length).trimStart();
60
+ if (counter.length === written.length - numeral.length) return false;
61
+ const word = tokens.find((token) => token.span.start === offset + written.length - counter.length);
62
+ return word !== undefined && word.surface.length > counter.length;
63
+ };
64
+
65
+ const countMarks = (text: string, base: number, words: NumberWords, tokens: readonly Token[]): NumberMark[] => {
55
66
  const pattern = countPattern(words);
56
67
  if (pattern === undefined) return [];
57
68
  return [...text.matchAll(pattern)].flatMap((match): NumberMark[] => {
58
69
  const [written, digits, kanji] = match;
59
70
  if (kanji !== undefined && isIdiomNumeral(kanji)) return [];
71
+ if (isBeforeLongerWord(digits ?? kanji ?? "", written, base + match.index, tokens)) return [];
60
72
  return [{ kind: "count", style: digits === undefined ? "kanji" : "digits", written, offset: base + match.index }];
61
73
  });
62
74
  };
@@ -176,7 +188,7 @@ const englishCountMarks = (sentence: Sentence, words: NumberWords): NumberMark[]
176
188
  export const numberMarksIn = (sentence: Sentence, words: NumberWords, language: string, source: string): NumberMark[] => {
177
189
  const base = sentence.span.start;
178
190
  const marks = [
179
- ...countMarks(sentence.text, base, words),
191
+ ...countMarks(sentence.text, base, words, sentence.tokens ?? []),
180
192
  ...groupingMarks(sentence.text, base, words, source),
181
193
  ...percentMarks(sentence.text, base, words),
182
194
  ...(language === "ja" ? [] : englishCountMarks(sentence, words)),
@@ -6,6 +6,8 @@ import { readMarkdown } from "../markdown-read.ts";
6
6
  import { spanOf, type MarkdownNode } from "../markdown-node.ts";
7
7
  import { eachPreOrder } from "../tree-walk.ts";
8
8
  import { quoteAt } from "./structure-tree.ts";
9
+ import { formsOf } from "./currency-notation.ts";
10
+ import { scaledFiguresIn, scaleGaps, type ScaleWords } from "./scaled-figure-unit.ts";
9
11
 
10
12
  /** One value of a kind: where its number starts, as written, and its unit ("" when bare). */
11
13
  export type Measured = { readonly kind: string; readonly name: string; readonly offset: number; readonly written: string; readonly unit: string };
@@ -157,7 +159,30 @@ const pieceCountOf = (doc: ProseDocument): PieceCount => {
157
159
  return { columns: patterns("column"), periods: patterns("period") };
158
160
  };
159
161
 
160
- export const numberWithoutUnit: Detector = (doc: ProseDocument): Finding[] => {
162
+ const patternsOf = (doc: ProseDocument, name: string): string[] => (doc.lexicons[name] ?? []).map((entry) => entry.pattern);
163
+
164
+ const scaleWordsOf = (doc: ProseDocument): ScaleWords => ({
165
+ scales: patternsOf(doc, "figure-scale-word"),
166
+ forms: formsOf(doc),
167
+ joiners: ["figure-scale-joiner", "range-connector", "enumeration-joiner"].flatMap((name) => patternsOf(doc, name)),
168
+ });
169
+
170
+ /** The one number in prose with a word of scale and no unit, where that word otherwise always carries one (83,494百万). */
171
+ const scaleFindings = (doc: ProseDocument): Finding[] => {
172
+ const prose = doc.prose ?? doc.source;
173
+ const words = scaleWordsOf(doc);
174
+ return scaleGaps(prose, scaledFiguresIn(prose, words), words.joiners).map(({ figure, unit }) => ({
175
+ rule: "number-without-unit",
176
+ severity: "warning",
177
+ line: 0,
178
+ column: 0,
179
+ variant: "scale",
180
+ quote: quoteAt(doc.source, figure.offset),
181
+ values: { value: figure.written, name: figure.scale, unit, offset: figure.offset },
182
+ }));
183
+ };
184
+
185
+ const columnFindings = (doc: ProseDocument): Finding[] => {
161
186
  const count = pieceCountOf(doc);
162
187
  return unitGaps(measuredValues(doc.source, doc.prose ?? doc.source, unitsOf(doc)))
163
188
  .filter((gap) => !isPieceCount(gap, count))
@@ -170,3 +195,5 @@ export const numberWithoutUnit: Detector = (doc: ProseDocument): Finding[] => {
170
195
  values: { value: gap.value.written, name: gap.value.name, unit: gap.unit, offset: gap.value.offset },
171
196
  }));
172
197
  };
198
+
199
+ export const numberWithoutUnit: Detector = (doc: ProseDocument): Finding[] => [...columnFindings(doc), ...scaleFindings(doc)];
@@ -1,3 +1,4 @@
1
+ import { escapeRegExp } from "../orthography.ts";
1
2
  import type { Detector, Finding, Sentence, Span } from "../plugin.ts";
2
3
 
3
4
  /**
@@ -56,6 +57,31 @@ export const followsSentenceEnd = (source: string, offset: number, labels: Reado
56
57
  return DIGITS.test(word) || (PLAIN_WORD.test(word) && !labels.has(word.toLowerCase()));
57
58
  };
58
59
 
60
+ const CLAUSE_NUMBER = /^(?<parent>\d{1,3})\.(?<child>\d{1,3})$/u;
61
+ const BLANK = /^[ \t]*$/u;
62
+
63
+ /** Whether offset is the first thing on its line, after spaces only. */
64
+ const startsLine = (source: string, offset: number): boolean => BLANK.test(source.slice(source.lastIndexOf("\n", offset - 1) + 1, offset));
65
+
66
+ /** Whether a line opens with this clause number (2.2) and a space. */
67
+ const opensLine = (source: string, clause: string): boolean => new RegExp(String.raw`(?:^|\n)[ \t]*${escapeRegExp(clause)}[ \t]`, "u").test(source);
68
+
69
+ /**
70
+ * A clause number that opens a numbered paragraph (2.1 the term starts on signing.), not a figure: it opens a line, and a
71
+ * clause next to it in the same numbering (2.0 or 2.2) opens a line too. A figure at a line's start (2.5 million units
72
+ * were sold.) has no such neighbour.
73
+ */
74
+ export const opensNumberedParagraph = (source: string, offset: number, numeral: string): boolean => {
75
+ const clause = CLAUSE_NUMBER.exec(numeral)?.groups;
76
+ if (clause === undefined || !startsLine(source, offset)) return false;
77
+ const child = clause["child"] ?? "";
78
+ // 3.10 sits next to 3.9 or, numbered with a zero, 3.09.
79
+ const neighbours = [Number(child) - 1, Number(child) + 1]
80
+ .filter((neighbour) => neighbour >= 0)
81
+ .flatMap((neighbour) => [String(neighbour), String(neighbour).padStart(child.length, "0")]);
82
+ return neighbours.some((neighbour) => opensLine(source, `${clause["parent"] ?? ""}.${neighbour}`));
83
+ };
84
+
59
85
  const inside = (spans: readonly Span[], offset: number): boolean => spans.some((span) => span.start <= offset && offset < span.end);
60
86
 
61
87
  const leadingSpace = (sentence: Sentence): number => sentence.text.length - sentence.text.trimStart().length;
@@ -66,7 +92,7 @@ export const numeralOpener: Detector = (doc): Finding[] => {
66
92
  const offset = sentence.span.start + leadingSpace(sentence);
67
93
  if (sentence.embeddedLanguage !== undefined || inside(doc.listSpans, offset)) return [];
68
94
  const numeral = openingNumeral(sentence.text);
69
- if (numeral === undefined || !followsSentenceEnd(doc.source, offset, labels)) return [];
95
+ if (numeral === undefined || !followsSentenceEnd(doc.source, offset, labels) || opensNumberedParagraph(doc.source, offset, numeral)) return [];
70
96
  return [{ rule: "", severity: "warning", line: 0, column: 0, quote: sentence.text.trim(), values: { numeral, offset } }];
71
97
  });
72
98
  };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 大文字の並びでも略語として書かれないもの。どれも字の形だけで決まる。
3
+ * - I だけのローマ数字(II、III)。名前の後ろでなくても番号で(Doswell, III、1964: II Structure)、この形の略語は使われない。
4
+ * IV や VI のように V・X を含む数字は略語(静脈注射の IV)でもあるので、名前の番号(name-numeral.ts)の位置でだけ外す。
5
+ * - 大文字で始まる語に - で繋いだ I・V・X の数字(Association-IV)。名前の番号を空白でなく - で書いた形。
6
+ * - X を 3 つ以上並べた伏せ字(the Secretary of State for XXX)や X の数で書く染色体の型(XXX症候群)。KKK や WWW のような他の字の繰り返しは略語のまま数える。
7
+ */
8
+
9
+ type Span = { readonly start: number; readonly end: number };
10
+
11
+ // 略語の切り出しと同じ境目。日本語の文字(XXX症候群)は語の続きではない。
12
+ const NOT_BEFORE = String.raw`(?<![A-Za-z0-9_&])`;
13
+ const NOT_AFTER = String.raw`(?![A-Za-z0-9_&])`;
14
+
15
+ const ONES_NUMERAL = new RegExp(`${NOT_BEFORE}I{2,3}${NOT_AFTER}`, "gu");
16
+ const MASK = new RegExp(`${NOT_BEFORE}X{3,}${NOT_AFTER}`, "gu");
17
+ const SMALL_NUMERAL = "(?=[IVX])X{0,3}(?:IX|IV|V?I{0,3})";
18
+ const JOINED_NUMERAL = new RegExp(String.raw`(?<![A-Za-z0-9_-])\p{Lu}\p{Ll}+-(?<numeral>${SMALL_NUMERAL})${NOT_AFTER}`, "gu");
19
+
20
+ const spanOf = (match: RegExpExecArray): Span => ({ start: match.index, end: match.index + match[0].length });
21
+
22
+ const joinedSpans = (text: string): Span[] =>
23
+ [...text.matchAll(JOINED_NUMERAL)].map((match) => {
24
+ const end = match.index + match[0].length;
25
+ return { start: end - (match.groups?.["numeral"] ?? "").length, end };
26
+ });
27
+
28
+ /** 文の中の、番号か伏せ字と読む大文字の範囲。 */
29
+ export const numeralWordSpans = (text: string): Span[] => [
30
+ ...[...text.matchAll(ONES_NUMERAL)].map(spanOf),
31
+ ...[...text.matchAll(MASK)].map(spanOf),
32
+ ...joinedSpans(text),
33
+ ];
@@ -6,14 +6,19 @@
6
6
  // duty-marker (shall, will), duty-ending (う, するものとする: what may follow a Japanese act at the sentence end),
7
7
  // stated-deadline (by the, までに) with concrete-deadline and vague-deadline, deadline-permission and currency-notation. Pure.
8
8
  import { quoteAt } from "./structure-tree.ts";
9
+ import { actsTimedAt, type NamedDeadline, type Units } from "./deadline-unit.ts";
10
+ import { inDocumentOrder } from "../structure/issues.ts";
9
11
  import { escapeRegExp } from "../orthography.ts";
10
12
  import { grantsRight, statesConcrete, vagueIn } from "./vague-deadline.ts";
11
13
  import type { Detector, Finding, LexiconEntry, ProseDocument } from "../plugin.ts";
12
14
 
13
15
  export type UntimedDuty = { readonly offset: number; readonly act: string };
14
16
 
15
- /** sameLine: the sentence goes on the line of the one before it (no line break between them). */
16
- type Text = { readonly start: number; readonly text: string; readonly sameLine?: boolean };
17
+ /**
18
+ * sameLine: the sentence goes on the line of the one before it (no line break between them). timedActs: the acts whose
19
+ * dated deadline (支払期日 for 支払) its article, else its list or paragraph, names; a duty to do one of them is timed.
20
+ */
21
+ type Text = { readonly start: number; readonly text: string; readonly sameLine?: boolean; readonly timedActs?: readonly string[] };
17
22
 
18
23
  /** What the word lists give the decision. */
19
24
  export type DutyWords = {
@@ -155,6 +160,7 @@ export const untimedDuties = (texts: readonly Text[], words: DutyWords): Untimed
155
160
  if (grantsRight(text, words.permissions) || statesAmount(text.text, words.currencies)) return [];
156
161
  const act = actIn(text.text, words);
157
162
  if (act === undefined || (LATIN.test(act.act) && !isWordStart(text.text, act.at))) return [];
163
+ if (text.timedActs?.some((timed) => timed.toLowerCase() === act.act.toLowerCase()) === true) return [];
158
164
  return [{ offset: text.start + act.at, act: text.text.slice(act.at, act.at + act.act.length) }];
159
165
  });
160
166
  const limitedSentences = texts.filter((text) => statesLimit(text, words)).length;
@@ -163,12 +169,30 @@ export const untimedDuties = (texts: readonly Text[], words: DutyWords): Untimed
163
169
 
164
170
  const patternsOf = (doc: ProseDocument, lexicon: string): string[] => (doc.lexicons[lexicon] ?? []).map((entry) => entry.pattern);
165
171
 
166
- export const obligationWithoutDeadline: Detector = (doc): Finding[] =>
167
- untimedDuties(
172
+ const unitsOf = (doc: ProseDocument): Units => ({
173
+ articles: doc.structure === undefined ? [] : inDocumentOrder(doc.structure).flatMap((node) => (node.kind === "article" ? [node.span] : [])),
174
+ lists: doc.lists.map((list) => list.span),
175
+ paragraphs: doc.paragraphs.map((paragraph) => paragraph.span),
176
+ });
177
+
178
+ /** The acts a sentence's unit names a dated deadline for (named-deadline: the name, and the act as its group). */
179
+ const timedActsReader = (doc: ProseDocument): ((offset: number) => string[]) => {
180
+ const deadlines: NamedDeadline[] = (doc.lexicons["named-deadline"] ?? []).flatMap((entry) =>
181
+ entry.group === undefined ? [] : [{ name: entry.pattern, act: entry.group }],
182
+ );
183
+ if (deadlines.length === 0) return () => [];
184
+ const units = unitsOf(doc);
185
+ return (offset) => actsTimedAt(doc.source, units, offset, deadlines, phraseIn);
186
+ };
187
+
188
+ export const obligationWithoutDeadline: Detector = (doc): Finding[] => {
189
+ const timedActs = timedActsReader(doc);
190
+ return untimedDuties(
168
191
  doc.sentences.map((sentence, index) => ({
169
192
  start: sentence.span.start,
170
193
  text: sentence.text,
171
194
  sameLine: index > 0 && !doc.source.slice(doc.sentences[index - 1]?.span.end ?? 0, sentence.span.start).includes("\n"),
195
+ timedActs: timedActs(sentence.span.start),
172
196
  })),
173
197
  {
174
198
  acts: patternsOf(doc, "timed-duty"),
@@ -190,3 +214,4 @@ export const obligationWithoutDeadline: Detector = (doc): Finding[] =>
190
214
  quote: quoteAt(doc.source, duty.offset),
191
215
  values: { word: duty.act, offset: duty.offset },
192
216
  }));
217
+ };
@@ -0,0 +1,78 @@
1
+ import type { LexiconEntry, Token } from "../plugin.ts";
2
+ import type { TokenRange } from "./lexicon-match.ts";
3
+
4
+ // An open-end word on a list of acts that gives examples of a kind of act named right after it: 印刷等、二次的に利用される
5
+ // 場合 and 印刷等の二次的利用 say "secondary use, such as printing". The kind bounds the list, so it leaves nothing open.
6
+ // A list followed by the manner of the act the requirement asks for (ログ等、具体的に保存すること) names no kind and stays
7
+ // open. The link (、 の) and the suffix that makes a word name a kind (的) come from the language's requirement-open-end
8
+ // lexicon. Pure.
9
+
10
+ /** The lexicon groups: a link right after the open word, and a suffix that makes the noun after it name a kind. */
11
+ const LINK = "class-link";
12
+ const CLASS_SUFFIX = "class-suffix";
13
+ const NAME_POS: ReadonlySet<string> = new Set(["NOUN", "PROPN"]);
14
+ /** The tagger's mark of a noun that names an act (印刷, 利用: a verbal noun). */
15
+ const ACT_NOUN = "Vnoun";
16
+ const PUNCT = "PUNCT";
17
+ /** The parts of speech a phrase about the act ends in before its comma (場合、 には、). */
18
+ const PHRASE_END_POS: ReadonlySet<string> = new Set(["NOUN", "PROPN", "ADP"]);
19
+ /** How many tokens may stand between the suffix and the act it qualifies (二次的に利用: に). */
20
+ const SUFFIX_REACH = 2;
21
+
22
+ export type ClassWords = { readonly links: ReadonlySet<string>; readonly suffixes: ReadonlySet<string> };
23
+
24
+ const patternsIn = (entries: readonly LexiconEntry[], group: string): ReadonlySet<string> =>
25
+ new Set(entries.filter((entry) => entry.group === group).map((entry) => entry.pattern));
26
+
27
+ export const classWordsOf = (entries: readonly LexiconEntry[]): ClassWords => ({
28
+ links: patternsIn(entries, LINK),
29
+ suffixes: patternsIn(entries, CLASS_SUFFIX),
30
+ });
31
+
32
+ /** Whether an entry is one of the class cues rather than an open-end word. */
33
+ export const isClassCue = (entry: LexiconEntry): boolean => entry.group === LINK || entry.group === CLASS_SUFFIX;
34
+
35
+ const isActNoun = (token: Token | undefined): boolean => token !== undefined && token.features?.VerbForm === ACT_NOUN;
36
+
37
+ const attached = (left: Token | undefined, right: Token | undefined): boolean =>
38
+ left !== undefined && right !== undefined && left.span.end === right.span.start;
39
+
40
+ /** The index of the last noun written one after another from index on, or index - 1 when no noun stands there. */
41
+ const nounRunEnd = (tokens: readonly Token[], index: number): number => {
42
+ const token = tokens[index];
43
+ if (token === undefined || !NAME_POS.has(token.pos)) return index - 1;
44
+ return attached(token, tokens[index + 1]) ? nounRunEnd(tokens, index + 1) : index;
45
+ };
46
+
47
+ /**
48
+ * Whether the act at index heads a phrase the requirement is about (利用される場合、 二次的利用には、): its clause ends in
49
+ * a noun or a particle before a comma inside the sentence. An act whose clause runs to the end of the sentence, or ends
50
+ * in a verb (保存すること。 保存し、), is what the requirement asks for, and the list before it stays open.
51
+ */
52
+ const headsPhrase = (tokens: readonly Token[], index: number): boolean => {
53
+ const comma = tokens.findIndex((token, at) => at > index && token.pos === PUNCT);
54
+ const last = tokens[comma - 1];
55
+ const goesOn = tokens.slice(comma + 1).some((token) => token.pos !== PUNCT && token.surface.trim() !== "");
56
+ return comma !== -1 && goesOn && last !== undefined && PHRASE_END_POS.has(last.pos);
57
+ };
58
+
59
+ /** Whether the noun run that starts at index holds a class suffix (二次的, 営利的) and an act that heads a phrase follows within reach. */
60
+ const kindOfActAt = (tokens: readonly Token[], index: number, words: ClassWords): boolean => {
61
+ const end = nounRunEnd(tokens, index);
62
+ const suffix = tokens.slice(index + 1, end + 1).findIndex((token) => words.suffixes.has(token.surface));
63
+ if (suffix === -1) return false;
64
+ const afterSuffix = index + 1 + suffix + 1;
65
+ const act = tokens.slice(afterSuffix, afterSuffix + SUFFIX_REACH).findIndex((token) => isActNoun(token));
66
+ return act !== -1 && headsPhrase(tokens, afterSuffix + act);
67
+ };
68
+
69
+ /**
70
+ * Whether the open word ends a list of acts that gives examples of a kind of act named right after it: the item before
71
+ * the word is an act (印刷), a link follows (、 の), then a noun built with a class suffix (二次的) and an act (利用).
72
+ * range: the tokens the open word covers.
73
+ */
74
+ export const namesClassAfter = (tokens: readonly Token[], range: TokenRange, words: ClassWords): boolean => {
75
+ const link = tokens[range.end];
76
+ if (!isActNoun(tokens[range.start - 1]) || link === undefined || !words.links.has(link.surface)) return false;
77
+ return kindOfActAt(tokens, range.end + 1, words);
78
+ };
@@ -0,0 +1,40 @@
1
+ import type { Sentence } from "../plugin.ts";
2
+
3
+ // An open list inside brackets that gloss a condition (必要ない場合(単一テーブルへの SELECT 等)も付与すること): the list
4
+ // gives examples of when the duty applies, not what the duty covers, so leaving it open is no smell. The condition words
5
+ // come from the language's requirement-open-condition lexicon. Pure.
6
+
7
+ /** Each closing bracket and the opening bracket it closes. */
8
+ const PAIRS: ReadonlyMap<string, string> = new Map([
9
+ [")", "("],
10
+ [")", "("],
11
+ ]);
12
+ const OPENING: ReadonlySet<string> = new Set(PAIRS.values());
13
+
14
+ type Open = { readonly char: string; readonly index: number };
15
+
16
+ /**
17
+ * The brackets still open before `end` of `text`, outermost first. A closing bracket closes only its own kind, so a
18
+ * stray half-width ")" leaves a full-width "(" open. One pass, no recursion: a statute's sentence is long.
19
+ */
20
+ const openBracketsBefore = (text: string, end: number): Open[] => {
21
+ const open: Open[] = [];
22
+ text
23
+ .slice(0, Math.max(0, end))
24
+ .split("")
25
+ .forEach((char, index) => {
26
+ if (OPENING.has(char)) open.push({ char, index });
27
+ else if (PAIRS.has(char) && open.at(-1)?.char === PAIRS.get(char)) open.pop();
28
+ });
29
+ return open;
30
+ };
31
+
32
+ /**
33
+ * Whether the open word starting at document offset `start` stands inside brackets, at any depth, that open right after
34
+ * a condition word (場合(…等), とき(…など), 場合(A(B 等))).
35
+ */
36
+ export const glossesCondition = (sentence: Sentence, start: number, conditions: readonly string[]): boolean =>
37
+ openBracketsBefore(sentence.text, start - sentence.span.start).some((bracket) => {
38
+ const before = sentence.text.slice(0, bracket.index).trimEnd();
39
+ return conditions.some((word) => word !== "" && before.endsWith(word));
40
+ });
@@ -135,6 +135,12 @@ const isNamed = (source: string, occurrence: Occurrence, names: OpenEndNames): b
135
135
  inQuotedName(source, occurrence, names.quoted) ||
136
136
  partsHoldingWord(source, occurrence).some((part) => names.defined.has(part) || names.heads.some((head) => head.startsWith(part)));
137
137
 
138
- /** Where the word first stands outside a name the document gives (its document offset), or undefined when it never does. */
139
- export const openEndAt = (doc: ProseDocument, sentence: Sentence, word: LexiconEntry, names: OpenEndNames): number | undefined =>
140
- occurrencesIn(sentence, word).find((occurrence) => !isNamed(doc.source, occurrence, names))?.start;
138
+ /** Whether the words around an occurrence bound its list; range: the tokens the word covers. */
139
+ export type BoundedAfter = (tokens: readonly Token[], range: TokenRange) => boolean;
140
+
141
+ /**
142
+ * Where the word first stands outside a name the document gives and is not bounded by the words after it (its document
143
+ * offset), or undefined when it never does.
144
+ */
145
+ export const openEndAt = (doc: ProseDocument, sentence: Sentence, word: LexiconEntry, names: OpenEndNames, boundedAfter: BoundedAfter): number | undefined =>
146
+ occurrencesIn(sentence, word).find((occurrence) => !isNamed(doc.source, occurrence, names) && !boundedAfter(occurrence.tokens, occurrence.range))?.start;
@@ -0,0 +1,50 @@
1
+ import type { LexiconEntry, Sentence } from "../plugin.ts";
2
+
3
+ // An open list right before a question that asks the reader to choose (…措置など、どのような措置を求めるのかを記載する):
4
+ // the list gives example answers, and leaving it open is the point. The question's words come from the language's
5
+ // requirement-open-question lexicon. Pure.
6
+
7
+ const INTERROGATIVE = "interrogative";
8
+ const QUESTION_END = "question-end";
9
+ /** Words that start like an interrogative and ask how instead (どのように), which offers no list of answers. */
10
+ const NOT_INTERROGATIVE = "not-interrogative";
11
+ /** A particle that turns the interrogative into "any" (どの部署でも, 何をも): no question follows. */
12
+ const UNIVERSAL_MARK = "universal-mark";
13
+ /** The marks that may stand between the list's last word and the question (、). */
14
+ const LINK = /^[\s、,,]*/u;
15
+ const PARTICLE = "PART";
16
+
17
+ export type QuestionWords = {
18
+ readonly interrogatives: readonly string[];
19
+ readonly notInterrogatives: readonly string[];
20
+ readonly ends: ReadonlySet<string>;
21
+ readonly universalMarks: ReadonlySet<string>;
22
+ };
23
+
24
+ const patternsIn = (entries: readonly LexiconEntry[], group: string): string[] =>
25
+ entries.filter((entry) => entry.group === group && entry.pattern !== "").map((entry) => entry.pattern);
26
+
27
+ export const questionWordsOf = (entries: readonly LexiconEntry[]): QuestionWords => ({
28
+ interrogatives: patternsIn(entries, INTERROGATIVE),
29
+ notInterrogatives: patternsIn(entries, NOT_INTERROGATIVE),
30
+ ends: new Set(patternsIn(entries, QUESTION_END)),
31
+ universalMarks: new Set(patternsIn(entries, UNIVERSAL_MARK)),
32
+ });
33
+
34
+ /**
35
+ * Whether a question starts right after the open word that ends at document offset end, and closes later in the
36
+ * sentence with a question particle, before any particle that makes the interrogative mean "any" (どの部署でも): the list
37
+ * before the word gives examples of what the question asks for.
38
+ */
39
+ export const asksAfter = (sentence: Sentence, end: number, words: QuestionWords): boolean => {
40
+ const rest = sentence.text.slice(end - sentence.span.start);
41
+ const link = LINK.exec(rest)?.[0].length ?? 0;
42
+ const question = rest.slice(link);
43
+ const startsWithAny = (patterns: readonly string[]): boolean => patterns.some((word) => question.startsWith(word));
44
+ const asks = startsWithAny(words.interrogatives) && !startsWithAny(words.notInterrogatives);
45
+ const questionStart = end + link;
46
+ const after = (sentence.tokens ?? []).filter((token) => token.span.start >= questionStart);
47
+ const close = after.findIndex((token) => token.pos === PARTICLE && words.ends.has(token.surface));
48
+ const universal = after.slice(0, close).some((token) => words.universalMarks.has(token.surface));
49
+ return asks && close !== -1 && !universal;
50
+ };
@@ -0,0 +1,62 @@
1
+ import type { LexiconEntry, Token } from "../plugin.ts";
2
+ import { entryEndsAt, type TokenRange } from "./lexicon-match.ts";
3
+
4
+ // An open-end word in a requirement is a smell only when its list is part of what the reader is asked to do (ログ等を保存
5
+ // すること): the reader cannot tell when the duty is met. A list in the condition the duty depends on (訂正等を行った際に、
6
+ // 通知する), in a right the writer grants (投稿データ等を消去できるものとします), or in what is forbidden or excluded
7
+ // (複製、転載等をしてはならない, 事情などにより責任を負わないものとします) is left open on purpose, and is the usual way a
8
+ // contract is drafted. The words that tell the four apart come from the language's requirement-open-end lexicon, in the
9
+ // groups below. Pure.
10
+
11
+ /** The lexicon groups, in the order a tie at one token is decided: a duty word wins over the words that open a list on purpose. */
12
+ const DUTY = "scope-duty";
13
+ const ON_PURPOSE = ["scope-permission", "scope-prohibition"] as const;
14
+ const CONDITION = "scope-condition";
15
+ const SCOPE_GROUPS: ReadonlySet<string> = new Set([DUTY, CONDITION, ...ON_PURPOSE]);
16
+
17
+ /** The parts of speech that end a clause with its own predicate before a comma (消去し、 行い、). */
18
+ const PREDICATE_POS: ReadonlySet<string> = new Set(["VERB", "AUX", "ADJ"]);
19
+ const PUNCT = "PUNCT";
20
+
21
+ export type ScopeWords = { readonly duty: readonly LexiconEntry[]; readonly onPurpose: readonly LexiconEntry[]; readonly condition: readonly LexiconEntry[] };
22
+
23
+ const inGroup = (entries: readonly LexiconEntry[], groups: readonly string[]): LexiconEntry[] => entries.filter((entry) => groups.includes(entry.group ?? ""));
24
+
25
+ export const scopeWordsOf = (entries: readonly LexiconEntry[]): ScopeWords => ({
26
+ duty: inGroup(entries, [DUTY]),
27
+ onPurpose: inGroup(entries, ON_PURPOSE),
28
+ condition: inGroup(entries, [CONDITION]),
29
+ });
30
+
31
+ /** Whether an entry is one of the scope cues rather than an open-end word. */
32
+ export const isScopeCue = (entry: LexiconEntry): boolean => SCOPE_GROUPS.has(entry.group ?? "");
33
+
34
+ const startsAt = (tokens: readonly Token[], entries: readonly LexiconEntry[], index: number): boolean =>
35
+ entries.some((entry) => entryEndsAt(tokens, entry, index + (entry.tokens?.length ?? 0)));
36
+
37
+ /** A comma right after a predicate closes the clause the list stands in (消去し、). */
38
+ const closesClause = (tokens: readonly Token[], index: number): boolean => tokens[index]?.pos === PUNCT && PREDICATE_POS.has(tokens[index - 1]?.pos ?? "");
39
+
40
+ /** A condition word that closes a clause about an act (行った際, 判断される場合): it follows a predicate. */
41
+ const conditionAt = (tokens: readonly Token[], index: number, words: ScopeWords): boolean =>
42
+ PREDICATE_POS.has(tokens[index - 1]?.pos ?? "") && startsAt(tokens, words.condition, index);
43
+
44
+ type Scope = "duty" | "on-purpose" | undefined;
45
+
46
+ /**
47
+ * What the list belongs to: the first duty, permission or prohibition word after it, or a condition word before the
48
+ * clause the list stands in closes. undefined when none follows (the sentence's own ending decides: こと。).
49
+ */
50
+ const scopeFrom = (tokens: readonly Token[], index: number, words: ScopeWords, inClause: boolean): Scope => {
51
+ if (index >= tokens.length) return undefined;
52
+ if (startsAt(tokens, words.duty, index)) return "duty";
53
+ if (startsAt(tokens, words.onPurpose, index) || (inClause && conditionAt(tokens, index, words))) return "on-purpose";
54
+ return scopeFrom(tokens, index + 1, words, inClause && !closesClause(tokens, index));
55
+ };
56
+
57
+ /**
58
+ * Whether the open word at range ends a list that is open on purpose: a condition, a permission or a prohibition holds
59
+ * it, not the duty the requirement states. range: the tokens the open word covers.
60
+ */
61
+ export const openOnPurpose = (tokens: readonly Token[], range: TokenRange, words: ScopeWords): boolean =>
62
+ scopeFrom(tokens, range.end, words, true) === "on-purpose";