chaffjs 0.35.0 → 0.37.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 (823) 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/chronology-rows.d.ts +9 -0
  8. package/dist/chronology-rows.d.ts.map +1 -0
  9. package/dist/chronology-rows.js +79 -0
  10. package/dist/chronology-rows.js.map +1 -0
  11. package/dist/company-name-run.d.ts +8 -0
  12. package/dist/company-name-run.d.ts.map +1 -0
  13. package/dist/company-name-run.js +30 -0
  14. package/dist/company-name-run.js.map +1 -0
  15. package/dist/compound-head.d.ts +7 -0
  16. package/dist/compound-head.d.ts.map +1 -0
  17. package/dist/compound-head.js +19 -0
  18. package/dist/compound-head.js.map +1 -0
  19. package/dist/date-format.d.ts +8 -3
  20. package/dist/date-format.d.ts.map +1 -1
  21. package/dist/date-format.js +36 -3
  22. package/dist/date-format.js.map +1 -1
  23. package/dist/derived/count-per-period.d.ts +23 -0
  24. package/dist/derived/count-per-period.d.ts.map +1 -0
  25. package/dist/derived/count-per-period.js +14 -0
  26. package/dist/derived/count-per-period.js.map +1 -0
  27. package/dist/detectors/acronym-context.d.ts +4 -0
  28. package/dist/detectors/acronym-context.d.ts.map +1 -1
  29. package/dist/detectors/acronym-context.js +29 -1
  30. package/dist/detectors/acronym-context.js.map +1 -1
  31. package/dist/detectors/acronym-expansion.d.ts +5 -1
  32. package/dist/detectors/acronym-expansion.d.ts.map +1 -1
  33. package/dist/detectors/acronym-expansion.js +42 -3
  34. package/dist/detectors/acronym-expansion.js.map +1 -1
  35. package/dist/detectors/acronym-known.d.ts +19 -0
  36. package/dist/detectors/acronym-known.d.ts.map +1 -0
  37. package/dist/detectors/acronym-known.js +32 -0
  38. package/dist/detectors/acronym-known.js.map +1 -0
  39. package/dist/detectors/acronym-link.d.ts +19 -0
  40. package/dist/detectors/acronym-link.d.ts.map +1 -0
  41. package/dist/detectors/acronym-link.js +65 -0
  42. package/dist/detectors/acronym-link.js.map +1 -0
  43. package/dist/detectors/acronym-mention.d.ts +5 -0
  44. package/dist/detectors/acronym-mention.d.ts.map +1 -0
  45. package/dist/detectors/acronym-mention.js +34 -0
  46. package/dist/detectors/acronym-mention.js.map +1 -0
  47. package/dist/detectors/acronym-name.d.ts +8 -1
  48. package/dist/detectors/acronym-name.d.ts.map +1 -1
  49. package/dist/detectors/acronym-name.js +25 -6
  50. package/dist/detectors/acronym-name.js.map +1 -1
  51. package/dist/detectors/addressee-edge.d.ts +13 -0
  52. package/dist/detectors/addressee-edge.d.ts.map +1 -0
  53. package/dist/detectors/addressee-edge.js +13 -0
  54. package/dist/detectors/addressee-edge.js.map +1 -0
  55. package/dist/detectors/addressee-title-edge.d.ts +21 -0
  56. package/dist/detectors/addressee-title-edge.d.ts.map +1 -0
  57. package/dist/detectors/addressee-title-edge.js +22 -0
  58. package/dist/detectors/addressee-title-edge.js.map +1 -0
  59. package/dist/detectors/announced-count.d.ts.map +1 -1
  60. package/dist/detectors/announced-count.js +1 -0
  61. package/dist/detectors/announced-count.js.map +1 -1
  62. package/dist/detectors/bare-comparative.d.ts +4 -0
  63. package/dist/detectors/bare-comparative.d.ts.map +1 -1
  64. package/dist/detectors/bare-comparative.js +28 -3
  65. package/dist/detectors/bare-comparative.js.map +1 -1
  66. package/dist/detectors/blank-structure.d.ts +7 -1
  67. package/dist/detectors/blank-structure.d.ts.map +1 -1
  68. package/dist/detectors/blank-structure.js +13 -8
  69. package/dist/detectors/blank-structure.js.map +1 -1
  70. package/dist/detectors/bracket-specified.d.ts +6 -0
  71. package/dist/detectors/bracket-specified.d.ts.map +1 -0
  72. package/dist/detectors/bracket-specified.js +23 -0
  73. package/dist/detectors/bracket-specified.js.map +1 -0
  74. package/dist/detectors/broken-link.d.ts +6 -0
  75. package/dist/detectors/broken-link.d.ts.map +1 -1
  76. package/dist/detectors/broken-link.js +23 -2
  77. package/dist/detectors/broken-link.js.map +1 -1
  78. package/dist/detectors/capitalised-term.d.ts +4 -0
  79. package/dist/detectors/capitalised-term.d.ts.map +1 -1
  80. package/dist/detectors/capitalised-term.js +18 -1
  81. package/dist/detectors/capitalised-term.js.map +1 -1
  82. package/dist/detectors/caps-caption.d.ts +17 -6
  83. package/dist/detectors/caps-caption.d.ts.map +1 -1
  84. package/dist/detectors/caps-caption.js +65 -0
  85. package/dist/detectors/caps-caption.js.map +1 -1
  86. package/dist/detectors/caps-phrase.d.ts +6 -0
  87. package/dist/detectors/caps-phrase.d.ts.map +1 -0
  88. package/dist/detectors/caps-phrase.js +16 -0
  89. package/dist/detectors/caps-phrase.js.map +1 -0
  90. package/dist/detectors/char-shape.d.ts +1 -0
  91. package/dist/detectors/char-shape.d.ts.map +1 -1
  92. package/dist/detectors/char-shape.js +56 -20
  93. package/dist/detectors/char-shape.js.map +1 -1
  94. package/dist/detectors/citation-sentence.d.ts +8 -0
  95. package/dist/detectors/citation-sentence.d.ts.map +1 -0
  96. package/dist/detectors/citation-sentence.js +40 -0
  97. package/dist/detectors/citation-sentence.js.map +1 -0
  98. package/dist/detectors/cited-title.d.ts +3 -2
  99. package/dist/detectors/cited-title.d.ts.map +1 -1
  100. package/dist/detectors/cited-title.js +14 -3
  101. package/dist/detectors/cited-title.js.map +1 -1
  102. package/dist/detectors/contraction-mention.d.ts +3 -0
  103. package/dist/detectors/contraction-mention.d.ts.map +1 -0
  104. package/dist/detectors/contraction-mention.js +22 -0
  105. package/dist/detectors/contraction-mention.js.map +1 -0
  106. package/dist/detectors/counter-edge.d.ts +2 -1
  107. package/dist/detectors/counter-edge.d.ts.map +1 -1
  108. package/dist/detectors/counter-edge.js +17 -2
  109. package/dist/detectors/counter-edge.js.map +1 -1
  110. package/dist/detectors/dash-break.d.ts +7 -0
  111. package/dist/detectors/dash-break.d.ts.map +1 -0
  112. package/dist/detectors/dash-break.js +30 -0
  113. package/dist/detectors/dash-break.js.map +1 -0
  114. package/dist/detectors/date-any-year.d.ts +7 -3
  115. package/dist/detectors/date-any-year.d.ts.map +1 -1
  116. package/dist/detectors/date-any-year.js +30 -8
  117. package/dist/detectors/date-any-year.js.map +1 -1
  118. package/dist/detectors/date-format.d.ts.map +1 -1
  119. package/dist/detectors/date-format.js +2 -1
  120. package/dist/detectors/date-format.js.map +1 -1
  121. package/dist/detectors/date-year.d.ts +9 -3
  122. package/dist/detectors/date-year.d.ts.map +1 -1
  123. package/dist/detectors/date-year.js +45 -9
  124. package/dist/detectors/date-year.js.map +1 -1
  125. package/dist/detectors/deadline-unit.d.ts +20 -0
  126. package/dist/detectors/deadline-unit.d.ts.map +1 -0
  127. package/dist/detectors/deadline-unit.js +19 -0
  128. package/dist/detectors/deadline-unit.js.map +1 -0
  129. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  130. package/dist/detectors/defined-term-form.js +33 -7
  131. package/dist/detectors/defined-term-form.js.map +1 -1
  132. package/dist/detectors/definition-use.d.ts.map +1 -1
  133. package/dist/detectors/definition-use.js +14 -6
  134. package/dist/detectors/definition-use.js.map +1 -1
  135. package/dist/detectors/derived-numbers.d.ts.map +1 -1
  136. package/dist/detectors/derived-numbers.js +17 -4
  137. package/dist/detectors/derived-numbers.js.map +1 -1
  138. package/dist/detectors/document-shape.d.ts +5 -0
  139. package/dist/detectors/document-shape.d.ts.map +1 -1
  140. package/dist/detectors/document-shape.js +15 -1
  141. package/dist/detectors/document-shape.js.map +1 -1
  142. package/dist/detectors/doubled-across-aside.d.ts +9 -0
  143. package/dist/detectors/doubled-across-aside.d.ts.map +1 -0
  144. package/dist/detectors/doubled-across-aside.js +27 -0
  145. package/dist/detectors/doubled-across-aside.js.map +1 -0
  146. package/dist/detectors/doubled-punctuation.d.ts +3 -3
  147. package/dist/detectors/doubled-punctuation.d.ts.map +1 -1
  148. package/dist/detectors/doubled-punctuation.js +23 -4
  149. package/dist/detectors/doubled-punctuation.js.map +1 -1
  150. package/dist/detectors/doubled-word.d.ts.map +1 -1
  151. package/dist/detectors/doubled-word.js +2 -1
  152. package/dist/detectors/doubled-word.js.map +1 -1
  153. package/dist/detectors/duplicate-heading.d.ts +1 -0
  154. package/dist/detectors/duplicate-heading.d.ts.map +1 -1
  155. package/dist/detectors/duplicate-heading.js +25 -3
  156. package/dist/detectors/duplicate-heading.js.map +1 -1
  157. package/dist/detectors/ellipsis.d.ts.map +1 -1
  158. package/dist/detectors/ellipsis.js +13 -1
  159. package/dist/detectors/ellipsis.js.map +1 -1
  160. package/dist/detectors/email-letter.d.ts +40 -3
  161. package/dist/detectors/email-letter.d.ts.map +1 -1
  162. package/dist/detectors/email-letter.js +110 -17
  163. package/dist/detectors/email-letter.js.map +1 -1
  164. package/dist/detectors/field-label.d.ts +7 -0
  165. package/dist/detectors/field-label.d.ts.map +1 -0
  166. package/dist/detectors/field-label.js +23 -0
  167. package/dist/detectors/field-label.js.map +1 -0
  168. package/dist/detectors/footnote-mismatch.d.ts +6 -1
  169. package/dist/detectors/footnote-mismatch.d.ts.map +1 -1
  170. package/dist/detectors/footnote-mismatch.js +28 -7
  171. package/dist/detectors/footnote-mismatch.js.map +1 -1
  172. package/dist/detectors/fullwidth-alnum.d.ts.map +1 -1
  173. package/dist/detectors/fullwidth-alnum.js +7 -1
  174. package/dist/detectors/fullwidth-alnum.js.map +1 -1
  175. package/dist/detectors/graded-step.d.ts +20 -0
  176. package/dist/detectors/graded-step.d.ts.map +1 -0
  177. package/dist/detectors/graded-step.js +33 -0
  178. package/dist/detectors/graded-step.js.map +1 -0
  179. package/dist/detectors/gram-openers.d.ts +9 -0
  180. package/dist/detectors/gram-openers.d.ts.map +1 -0
  181. package/dist/detectors/gram-openers.js +40 -0
  182. package/dist/detectors/gram-openers.js.map +1 -0
  183. package/dist/detectors/gram-place.d.ts +3 -1
  184. package/dist/detectors/gram-place.d.ts.map +1 -1
  185. package/dist/detectors/gram-place.js +8 -0
  186. package/dist/detectors/gram-place.js.map +1 -1
  187. package/dist/detectors/gram-predicate.d.ts.map +1 -1
  188. package/dist/detectors/gram-predicate.js +37 -3
  189. package/dist/detectors/gram-predicate.js.map +1 -1
  190. package/dist/detectors/heading-echo.d.ts.map +1 -1
  191. package/dist/detectors/heading-echo.js +28 -2
  192. package/dist/detectors/heading-echo.js.map +1 -1
  193. package/dist/detectors/heading-record-rhythm.d.ts +9 -0
  194. package/dist/detectors/heading-record-rhythm.d.ts.map +1 -0
  195. package/dist/detectors/heading-record-rhythm.js +57 -0
  196. package/dist/detectors/heading-record-rhythm.js.map +1 -0
  197. package/dist/detectors/ime-residue.d.ts +1 -1
  198. package/dist/detectors/ime-residue.d.ts.map +1 -1
  199. package/dist/detectors/ime-residue.js +4 -3
  200. package/dist/detectors/ime-residue.js.map +1 -1
  201. package/dist/detectors/kanji-compound-slip.d.ts +3 -0
  202. package/dist/detectors/kanji-compound-slip.d.ts.map +1 -0
  203. package/dist/detectors/kanji-compound-slip.js +50 -0
  204. package/dist/detectors/kanji-compound-slip.js.map +1 -0
  205. package/dist/detectors/kutoten-consistency.d.ts +10 -2
  206. package/dist/detectors/kutoten-consistency.d.ts.map +1 -1
  207. package/dist/detectors/kutoten-consistency.js +83 -12
  208. package/dist/detectors/kutoten-consistency.js.map +1 -1
  209. package/dist/detectors/lexicon.d.ts.map +1 -1
  210. package/dist/detectors/lexicon.js +13 -4
  211. package/dist/detectors/lexicon.js.map +1 -1
  212. package/dist/detectors/link-shape.d.ts.map +1 -1
  213. package/dist/detectors/link-shape.js +9 -3
  214. package/dist/detectors/link-shape.js.map +1 -1
  215. package/dist/detectors/list-item-ending.d.ts +18 -0
  216. package/dist/detectors/list-item-ending.d.ts.map +1 -0
  217. package/dist/detectors/list-item-ending.js +35 -0
  218. package/dist/detectors/list-item-ending.js.map +1 -0
  219. package/dist/detectors/list-parallel.d.ts +18 -5
  220. package/dist/detectors/list-parallel.d.ts.map +1 -1
  221. package/dist/detectors/list-parallel.js +116 -36
  222. package/dist/detectors/list-parallel.js.map +1 -1
  223. package/dist/detectors/list-sentence.d.ts +4 -0
  224. package/dist/detectors/list-sentence.d.ts.map +1 -1
  225. package/dist/detectors/list-sentence.js +1 -1
  226. package/dist/detectors/list-sentence.js.map +1 -1
  227. package/dist/detectors/mark-shape.d.ts +13 -4
  228. package/dist/detectors/mark-shape.d.ts.map +1 -1
  229. package/dist/detectors/mark-shape.js +73 -10
  230. package/dist/detectors/mark-shape.js.map +1 -1
  231. package/dist/detectors/mentioned-phrase.d.ts +9 -0
  232. package/dist/detectors/mentioned-phrase.d.ts.map +1 -0
  233. package/dist/detectors/mentioned-phrase.js +25 -0
  234. package/dist/detectors/mentioned-phrase.js.map +1 -0
  235. package/dist/detectors/middle-dot.d.ts +2 -2
  236. package/dist/detectors/middle-dot.d.ts.map +1 -1
  237. package/dist/detectors/middle-dot.js +4 -2
  238. package/dist/detectors/middle-dot.js.map +1 -1
  239. package/dist/detectors/modal-conflict.d.ts.map +1 -1
  240. package/dist/detectors/modal-conflict.js +5 -2
  241. package/dist/detectors/modal-conflict.js.map +1 -1
  242. package/dist/detectors/name-variant.d.ts.map +1 -1
  243. package/dist/detectors/name-variant.js +6 -0
  244. package/dist/detectors/name-variant.js.map +1 -1
  245. package/dist/detectors/notice-paragraph.d.ts +9 -0
  246. package/dist/detectors/notice-paragraph.d.ts.map +1 -0
  247. package/dist/detectors/notice-paragraph.js +21 -0
  248. package/dist/detectors/notice-paragraph.js.map +1 -0
  249. package/dist/detectors/number-style.d.ts.map +1 -1
  250. package/dist/detectors/number-style.js +15 -2
  251. package/dist/detectors/number-style.js.map +1 -1
  252. package/dist/detectors/number-unit.d.ts.map +1 -1
  253. package/dist/detectors/number-unit.js +24 -1
  254. package/dist/detectors/number-unit.js.map +1 -1
  255. package/dist/detectors/numeral-opener.d.ts +6 -0
  256. package/dist/detectors/numeral-opener.d.ts.map +1 -1
  257. package/dist/detectors/numeral-opener.js +24 -1
  258. package/dist/detectors/numeral-opener.js.map +1 -1
  259. package/dist/detectors/obligation-without-deadline.d.ts +5 -1
  260. package/dist/detectors/obligation-without-deadline.d.ts.map +1 -1
  261. package/dist/detectors/obligation-without-deadline.js +44 -23
  262. package/dist/detectors/obligation-without-deadline.js.map +1 -1
  263. package/dist/detectors/open-end-class.d.ts +16 -0
  264. package/dist/detectors/open-end-class.d.ts.map +1 -0
  265. package/dist/detectors/open-end-class.js +65 -0
  266. package/dist/detectors/open-end-class.js.map +1 -0
  267. package/dist/detectors/open-end-condition.d.ts +7 -0
  268. package/dist/detectors/open-end-condition.d.ts.map +1 -0
  269. package/dist/detectors/open-end-condition.js +35 -0
  270. package/dist/detectors/open-end-condition.js.map +1 -0
  271. package/dist/detectors/open-end-names.d.ts +9 -3
  272. package/dist/detectors/open-end-names.d.ts.map +1 -1
  273. package/dist/detectors/open-end-names.js +5 -2
  274. package/dist/detectors/open-end-names.js.map +1 -1
  275. package/dist/detectors/open-end-question.d.ts +15 -0
  276. package/dist/detectors/open-end-question.d.ts.map +1 -0
  277. package/dist/detectors/open-end-question.js +37 -0
  278. package/dist/detectors/open-end-question.js.map +1 -0
  279. package/dist/detectors/open-end-scope.d.ts +16 -0
  280. package/dist/detectors/open-end-scope.d.ts.map +1 -0
  281. package/dist/detectors/open-end-scope.js +47 -0
  282. package/dist/detectors/open-end-scope.js.map +1 -0
  283. package/dist/detectors/opening-date.d.ts +10 -0
  284. package/dist/detectors/opening-date.d.ts.map +1 -0
  285. package/dist/detectors/opening-date.js +33 -0
  286. package/dist/detectors/opening-date.js.map +1 -0
  287. package/dist/detectors/ordinary-phrase.d.ts +20 -0
  288. package/dist/detectors/ordinary-phrase.d.ts.map +1 -0
  289. package/dist/detectors/ordinary-phrase.js +54 -0
  290. package/dist/detectors/ordinary-phrase.js.map +1 -0
  291. package/dist/detectors/organisation-run.d.ts +5 -7
  292. package/dist/detectors/organisation-run.d.ts.map +1 -1
  293. package/dist/detectors/organisation-run.js +10 -0
  294. package/dist/detectors/organisation-run.js.map +1 -1
  295. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  296. package/dist/detectors/orthographic-variant.js +85 -20
  297. package/dist/detectors/orthographic-variant.js.map +1 -1
  298. package/dist/detectors/orthography.d.ts.map +1 -1
  299. package/dist/detectors/orthography.js +9 -2
  300. package/dist/detectors/orthography.js.map +1 -1
  301. package/dist/detectors/oxford-comma.d.ts.map +1 -1
  302. package/dist/detectors/oxford-comma.js +70 -3
  303. package/dist/detectors/oxford-comma.js.map +1 -1
  304. package/dist/detectors/person-consistency.d.ts +2 -1
  305. package/dist/detectors/person-consistency.d.ts.map +1 -1
  306. package/dist/detectors/person-consistency.js +5 -3
  307. package/dist/detectors/person-consistency.js.map +1 -1
  308. package/dist/detectors/phrase-match.d.ts +2 -0
  309. package/dist/detectors/phrase-match.d.ts.map +1 -1
  310. package/dist/detectors/phrase-match.js +11 -4
  311. package/dist/detectors/phrase-match.js.map +1 -1
  312. package/dist/detectors/placeholder-text.d.ts.map +1 -1
  313. package/dist/detectors/placeholder-text.js +18 -3
  314. package/dist/detectors/placeholder-text.js.map +1 -1
  315. package/dist/detectors/placeholder.d.ts +3 -1
  316. package/dist/detectors/placeholder.d.ts.map +1 -1
  317. package/dist/detectors/placeholder.js +8 -3
  318. package/dist/detectors/placeholder.js.map +1 -1
  319. package/dist/detectors/postcode-end.d.ts +3 -0
  320. package/dist/detectors/postcode-end.d.ts.map +1 -0
  321. package/dist/detectors/postcode-end.js +15 -0
  322. package/dist/detectors/postcode-end.js.map +1 -0
  323. package/dist/detectors/prose-total-words.d.ts +5 -0
  324. package/dist/detectors/prose-total-words.d.ts.map +1 -0
  325. package/dist/detectors/prose-total-words.js +14 -0
  326. package/dist/detectors/prose-total-words.js.map +1 -0
  327. package/dist/detectors/range-notation.d.ts +2 -2
  328. package/dist/detectors/range-notation.d.ts.map +1 -1
  329. package/dist/detectors/range-notation.js +18 -7
  330. package/dist/detectors/range-notation.js.map +1 -1
  331. package/dist/detectors/registry/kanji-compound-slip.d.ts +3 -0
  332. package/dist/detectors/registry/kanji-compound-slip.d.ts.map +1 -0
  333. package/dist/detectors/registry/kanji-compound-slip.js +3 -0
  334. package/dist/detectors/registry/kanji-compound-slip.js.map +1 -0
  335. package/dist/detectors/registry/phrase-in-use.d.ts +3 -0
  336. package/dist/detectors/registry/phrase-in-use.d.ts.map +1 -0
  337. package/dist/detectors/registry/phrase-in-use.js +3 -0
  338. package/dist/detectors/registry/phrase-in-use.js.map +1 -0
  339. package/dist/detectors/requirement-smell.d.ts.map +1 -1
  340. package/dist/detectors/requirement-smell.js +35 -7
  341. package/dist/detectors/requirement-smell.js.map +1 -1
  342. package/dist/detectors/scaled-figure-unit.d.ts +28 -0
  343. package/dist/detectors/scaled-figure-unit.d.ts.map +1 -0
  344. package/dist/detectors/scaled-figure-unit.js +78 -0
  345. package/dist/detectors/scaled-figure-unit.js.map +1 -0
  346. package/dist/detectors/sentence-counts.d.ts +12 -2
  347. package/dist/detectors/sentence-counts.d.ts.map +1 -1
  348. package/dist/detectors/sentence-counts.js +52 -11
  349. package/dist/detectors/sentence-counts.js.map +1 -1
  350. package/dist/detectors/sentence-ending.d.ts +2 -0
  351. package/dist/detectors/sentence-ending.d.ts.map +1 -1
  352. package/dist/detectors/sentence-ending.js +10 -3
  353. package/dist/detectors/sentence-ending.js.map +1 -1
  354. package/dist/detectors/sentence-length.d.ts.map +1 -1
  355. package/dist/detectors/sentence-length.js +13 -4
  356. package/dist/detectors/sentence-length.js.map +1 -1
  357. package/dist/detectors/sentence-load.d.ts +4 -1
  358. package/dist/detectors/sentence-load.d.ts.map +1 -1
  359. package/dist/detectors/sentence-load.js +9 -2
  360. package/dist/detectors/sentence-load.js.map +1 -1
  361. package/dist/detectors/signals.d.ts.map +1 -1
  362. package/dist/detectors/signals.js +44 -52
  363. package/dist/detectors/signals.js.map +1 -1
  364. package/dist/detectors/structure-tree.d.ts.map +1 -1
  365. package/dist/detectors/structure-tree.js +14 -13
  366. package/dist/detectors/structure-tree.js.map +1 -1
  367. package/dist/detectors/structure.d.ts.map +1 -1
  368. package/dist/detectors/structure.js +2 -1
  369. package/dist/detectors/structure.js.map +1 -1
  370. package/dist/detectors/subject-name-line.d.ts +8 -0
  371. package/dist/detectors/subject-name-line.d.ts.map +1 -0
  372. package/dist/detectors/subject-name-line.js +53 -0
  373. package/dist/detectors/subject-name-line.js.map +1 -0
  374. package/dist/detectors/superlative-name.d.ts +5 -0
  375. package/dist/detectors/superlative-name.d.ts.map +1 -1
  376. package/dist/detectors/superlative-name.js +9 -0
  377. package/dist/detectors/superlative-name.js.map +1 -1
  378. package/dist/detectors/table-header.d.ts.map +1 -1
  379. package/dist/detectors/table-header.js +13 -1
  380. package/dist/detectors/table-header.js.map +1 -1
  381. package/dist/detectors/technical-docs.d.ts.map +1 -1
  382. package/dist/detectors/technical-docs.js +4 -1
  383. package/dist/detectors/technical-docs.js.map +1 -1
  384. package/dist/detectors/term-mention-sentence.d.ts +4 -0
  385. package/dist/detectors/term-mention-sentence.d.ts.map +1 -0
  386. package/dist/detectors/term-mention-sentence.js +28 -0
  387. package/dist/detectors/term-mention-sentence.js.map +1 -0
  388. package/dist/detectors/titled-run.d.ts +2 -1
  389. package/dist/detectors/titled-run.d.ts.map +1 -1
  390. package/dist/detectors/titled-run.js +9 -4
  391. package/dist/detectors/titled-run.js.map +1 -1
  392. package/dist/detectors/token-shape.d.ts.map +1 -1
  393. package/dist/detectors/token-shape.js +15 -5
  394. package/dist/detectors/token-shape.js.map +1 -1
  395. package/dist/detectors/undefined-term.d.ts.map +1 -1
  396. package/dist/detectors/undefined-term.js +5 -0
  397. package/dist/detectors/undefined-term.js.map +1 -1
  398. package/dist/detectors/unknown-word.d.ts +4 -1
  399. package/dist/detectors/unknown-word.d.ts.map +1 -1
  400. package/dist/detectors/unknown-word.js +1 -1
  401. package/dist/detectors/unknown-word.js.map +1 -1
  402. package/dist/detectors/vague-density.d.ts +5 -2
  403. package/dist/detectors/vague-density.d.ts.map +1 -1
  404. package/dist/detectors/vague-density.js +17 -4
  405. package/dist/detectors/vague-density.js.map +1 -1
  406. package/dist/document-paragraphs.d.ts +4 -0
  407. package/dist/document-paragraphs.d.ts.map +1 -0
  408. package/dist/document-paragraphs.js +24 -0
  409. package/dist/document-paragraphs.js.map +1 -0
  410. package/dist/document.d.ts.map +1 -1
  411. package/dist/document.js +2 -19
  412. package/dist/document.js.map +1 -1
  413. package/dist/figure-references.d.ts +3 -0
  414. package/dist/figure-references.d.ts.map +1 -1
  415. package/dist/figure-references.js +6 -2
  416. package/dist/figure-references.js.map +1 -1
  417. package/dist/format-template.d.ts +3 -0
  418. package/dist/format-template.d.ts.map +1 -0
  419. package/dist/format-template.js +13 -0
  420. package/dist/format-template.js.map +1 -0
  421. package/dist/formula-brackets.d.ts +7 -0
  422. package/dist/formula-brackets.d.ts.map +1 -0
  423. package/dist/formula-brackets.js +29 -0
  424. package/dist/formula-brackets.js.map +1 -0
  425. package/dist/html/html-markdown.d.ts.map +1 -1
  426. package/dist/html/html-markdown.js +2 -1
  427. package/dist/html/html-markdown.js.map +1 -1
  428. package/dist/html/html-site-chrome.d.ts +5 -0
  429. package/dist/html/html-site-chrome.d.ts.map +1 -0
  430. package/dist/html/html-site-chrome.js +56 -0
  431. package/dist/html/html-site-chrome.js.map +1 -0
  432. package/dist/joined-view.d.ts.map +1 -1
  433. package/dist/joined-view.js +1 -0
  434. package/dist/joined-view.js.map +1 -1
  435. package/dist/kanji-compound-slip.d.ts +32 -0
  436. package/dist/kanji-compound-slip.d.ts.map +1 -0
  437. package/dist/kanji-compound-slip.js +63 -0
  438. package/dist/kanji-compound-slip.js.map +1 -0
  439. package/dist/latin-company-form.d.ts +6 -0
  440. package/dist/latin-company-form.d.ts.map +1 -0
  441. package/dist/latin-company-form.js +32 -0
  442. package/dist/latin-company-form.js.map +1 -0
  443. package/dist/latin-word-boundary.d.ts +20 -0
  444. package/dist/latin-word-boundary.d.ts.map +1 -0
  445. package/dist/latin-word-boundary.js +57 -0
  446. package/dist/latin-word-boundary.js.map +1 -0
  447. package/dist/leading-label.d.ts +4 -0
  448. package/dist/leading-label.d.ts.map +1 -0
  449. package/dist/leading-label.js +14 -0
  450. package/dist/leading-label.js.map +1 -0
  451. package/dist/lexicon-genres.d.ts +2 -0
  452. package/dist/lexicon-genres.d.ts.map +1 -1
  453. package/dist/lexicon-genres.js +1 -1
  454. package/dist/lexicon-genres.js.map +1 -1
  455. package/dist/link-shape.d.ts +6 -0
  456. package/dist/link-shape.d.ts.map +1 -1
  457. package/dist/link-shape.js +27 -0
  458. package/dist/link-shape.js.map +1 -1
  459. package/dist/link-title.d.ts +4 -0
  460. package/dist/link-title.d.ts.map +1 -0
  461. package/dist/link-title.js +33 -0
  462. package/dist/link-title.js.map +1 -0
  463. package/dist/list-item-paragraphs.d.ts +15 -0
  464. package/dist/list-item-paragraphs.d.ts.map +1 -0
  465. package/dist/list-item-paragraphs.js +19 -0
  466. package/dist/list-item-paragraphs.js.map +1 -0
  467. package/dist/literal-quote.d.ts +12 -0
  468. package/dist/literal-quote.d.ts.map +1 -0
  469. package/dist/literal-quote.js +43 -0
  470. package/dist/literal-quote.js.map +1 -0
  471. package/dist/nado-closed-list.d.ts.map +1 -1
  472. package/dist/nado-closed-list.js +39 -5
  473. package/dist/nado-closed-list.js.map +1 -1
  474. package/dist/name-misspelt-usual.d.ts +5 -0
  475. package/dist/name-misspelt-usual.d.ts.map +1 -0
  476. package/dist/name-misspelt-usual.js +19 -0
  477. package/dist/name-misspelt-usual.js.map +1 -0
  478. package/dist/name-separator.d.ts.map +1 -1
  479. package/dist/name-separator.js +25 -2
  480. package/dist/name-separator.js.map +1 -1
  481. package/dist/nominal-stem.d.ts +14 -1
  482. package/dist/nominal-stem.d.ts.map +1 -1
  483. package/dist/nominal-stem.js +42 -4
  484. package/dist/nominal-stem.js.map +1 -1
  485. package/dist/notice-header.d.ts +19 -0
  486. package/dist/notice-header.d.ts.map +1 -0
  487. package/dist/notice-header.js +31 -0
  488. package/dist/notice-header.js.map +1 -0
  489. package/dist/person-forms.d.ts +8 -0
  490. package/dist/person-forms.d.ts.map +1 -1
  491. package/dist/person-forms.js +12 -0
  492. package/dist/person-forms.js.map +1 -1
  493. package/dist/plugin.d.ts +5 -0
  494. package/dist/plugin.d.ts.map +1 -1
  495. package/dist/preamble-paragraphs.d.ts +3 -2
  496. package/dist/preamble-paragraphs.d.ts.map +1 -1
  497. package/dist/preamble-paragraphs.js +8 -2
  498. package/dist/preamble-paragraphs.js.map +1 -1
  499. package/dist/sentence-load.d.ts +2 -1
  500. package/dist/sentence-load.d.ts.map +1 -1
  501. package/dist/sentence-load.js +11 -3
  502. package/dist/sentence-load.js.map +1 -1
  503. package/dist/spacing-code.d.ts +1 -0
  504. package/dist/spacing-code.d.ts.map +1 -1
  505. package/dist/spacing-code.js +4 -1
  506. package/dist/spacing-code.js.map +1 -1
  507. package/dist/split-noun.d.ts +10 -0
  508. package/dist/split-noun.d.ts.map +1 -0
  509. package/dist/split-noun.js +50 -0
  510. package/dist/split-noun.js.map +1 -0
  511. package/dist/structure/attached-parts.d.ts +12 -0
  512. package/dist/structure/attached-parts.d.ts.map +1 -0
  513. package/dist/structure/attached-parts.js +44 -0
  514. package/dist/structure/attached-parts.js.map +1 -0
  515. package/dist/structure/build.d.ts.map +1 -1
  516. package/dist/structure/build.js +7 -4
  517. package/dist/structure/build.js.map +1 -1
  518. package/dist/structure/contents-lines.d.ts +7 -0
  519. package/dist/structure/contents-lines.d.ts.map +1 -0
  520. package/dist/structure/contents-lines.js +51 -0
  521. package/dist/structure/contents-lines.js.map +1 -0
  522. package/dist/structure/defining-names.d.ts +37 -0
  523. package/dist/structure/defining-names.d.ts.map +1 -0
  524. package/dist/structure/defining-names.js +122 -0
  525. package/dist/structure/defining-names.js.map +1 -0
  526. package/dist/structure/definition-use.d.ts +8 -4
  527. package/dist/structure/definition-use.d.ts.map +1 -1
  528. package/dist/structure/definition-use.js +123 -38
  529. package/dist/structure/definition-use.js.map +1 -1
  530. package/dist/structure/gerund-phrase.d.ts +8 -0
  531. package/dist/structure/gerund-phrase.d.ts.map +1 -0
  532. package/dist/structure/gerund-phrase.js +30 -0
  533. package/dist/structure/gerund-phrase.js.map +1 -0
  534. package/dist/structure/issues.d.ts +4 -1
  535. package/dist/structure/issues.d.ts.map +1 -1
  536. package/dist/structure/issues.js +5 -2
  537. package/dist/structure/issues.js.map +1 -1
  538. package/dist/structure/list-lead-in.d.ts +19 -0
  539. package/dist/structure/list-lead-in.d.ts.map +1 -0
  540. package/dist/structure/list-lead-in.js +85 -0
  541. package/dist/structure/list-lead-in.js.map +1 -0
  542. package/dist/structure/modal-conflict.d.ts +7 -2
  543. package/dist/structure/modal-conflict.d.ts.map +1 -1
  544. package/dist/structure/modal-conflict.js +36 -7
  545. package/dist/structure/modal-conflict.js.map +1 -1
  546. package/dist/structure/negated-act.d.ts +17 -0
  547. package/dist/structure/negated-act.d.ts.map +1 -0
  548. package/dist/structure/negated-act.js +32 -0
  549. package/dist/structure/negated-act.js.map +1 -0
  550. package/dist/structure/numbering.d.ts +3 -1
  551. package/dist/structure/numbering.d.ts.map +1 -1
  552. package/dist/structure/numbering.js +20 -8
  553. package/dist/structure/numbering.js.map +1 -1
  554. package/dist/structure/prose-total.d.ts +4 -0
  555. package/dist/structure/prose-total.d.ts.map +1 -1
  556. package/dist/structure/prose-total.js +16 -6
  557. package/dist/structure/prose-total.js.map +1 -1
  558. package/dist/structure/repeated-number.d.ts +24 -0
  559. package/dist/structure/repeated-number.d.ts.map +1 -0
  560. package/dist/structure/repeated-number.js +89 -0
  561. package/dist/structure/repeated-number.js.map +1 -0
  562. package/dist/structure/rounded-amount.d.ts +8 -0
  563. package/dist/structure/rounded-amount.d.ts.map +1 -0
  564. package/dist/structure/rounded-amount.js +48 -0
  565. package/dist/structure/rounded-amount.js.map +1 -0
  566. package/dist/structure/side-step.d.ts +8 -0
  567. package/dist/structure/side-step.d.ts.map +1 -0
  568. package/dist/structure/side-step.js +21 -0
  569. package/dist/structure/side-step.js.map +1 -0
  570. package/dist/structure/spanned-label-blank.d.ts +8 -0
  571. package/dist/structure/spanned-label-blank.d.ts.map +1 -0
  572. package/dist/structure/spanned-label-blank.js +37 -0
  573. package/dist/structure/spanned-label-blank.js.map +1 -0
  574. package/dist/structure/universal.d.ts +10 -4
  575. package/dist/structure/universal.d.ts.map +1 -1
  576. package/dist/structure/universal.js +26 -7
  577. package/dist/structure/universal.js.map +1 -1
  578. package/dist/structure/unspaced-heading.d.ts +10 -0
  579. package/dist/structure/unspaced-heading.d.ts.map +1 -0
  580. package/dist/structure/unspaced-heading.js +24 -0
  581. package/dist/structure/unspaced-heading.js.map +1 -0
  582. package/dist/structure/written-list-path.d.ts +10 -0
  583. package/dist/structure/written-list-path.d.ts.map +1 -0
  584. package/dist/structure/written-list-path.js +37 -0
  585. package/dist/structure/written-list-path.js.map +1 -0
  586. package/dist/structure/written-resolve.d.ts +1 -1
  587. package/dist/structure/written-resolve.d.ts.map +1 -1
  588. package/dist/structure/written-resolve.js +15 -9
  589. package/dist/structure/written-resolve.js.map +1 -1
  590. package/dist/title-line.d.ts +23 -0
  591. package/dist/title-line.d.ts.map +1 -0
  592. package/dist/title-line.js +28 -0
  593. package/dist/title-line.js.map +1 -0
  594. package/dist/topic-clause.d.ts +7 -0
  595. package/dist/topic-clause.d.ts.map +1 -0
  596. package/dist/topic-clause.js +87 -0
  597. package/dist/topic-clause.js.map +1 -0
  598. package/dist/uncounted-particles.d.ts +18 -0
  599. package/dist/uncounted-particles.d.ts.map +1 -0
  600. package/dist/uncounted-particles.js +47 -0
  601. package/dist/uncounted-particles.js.map +1 -0
  602. package/package.json +3 -3
  603. package/rules/adversative-ga-repeat.yaml +1 -0
  604. package/rules/all-caps-shouting.yaml +2 -2
  605. package/rules/announced-count-mismatch.yaml +2 -2
  606. package/rules/bare-url-mix.yaml +2 -2
  607. package/rules/bracket-nesting.yaml +2 -2
  608. package/rules/bracket-width-consistency.yaml +2 -2
  609. package/rules/broken-link.yaml +2 -2
  610. package/rules/cliche.yaml +4 -3
  611. package/rules/code-fence-language-mix.yaml +2 -2
  612. package/rules/comparative-without-baseline.yaml +2 -2
  613. package/rules/concrete-evidence-density.yaml +1 -0
  614. package/rules/contraction-consistency.yaml +2 -2
  615. package/rules/dangling-figure-reference.yaml +2 -2
  616. package/rules/date-without-year.yaml +10 -2
  617. package/rules/defined-term-form.yaml +2 -2
  618. package/rules/doubled-punctuation.yaml +4 -4
  619. package/rules/doubled-word.yaml +2 -2
  620. package/rules/duplicate-definition.yaml +2 -2
  621. package/rules/duplicate-heading.yaml +2 -2
  622. package/rules/duration-mismatch.yaml +2 -2
  623. package/rules/email-greeting-closing.yaml +2 -2
  624. package/rules/email-subject-length.yaml +2 -2
  625. package/rules/empty-table-cell.yaml +2 -2
  626. package/rules/footnote-mismatch.yaml +2 -2
  627. package/rules/fullwidth-alnum-consistency.yaml +2 -2
  628. package/rules/heading-echo.yaml +2 -2
  629. package/rules/ime-residue.yaml +2 -2
  630. package/rules/kanji-compound-slip.yaml +67 -0
  631. package/rules/kutoten-consistency.yaml +4 -4
  632. package/rules/latin-spacing.yaml +2 -2
  633. package/rules/list-item-form-mix.yaml +2 -2
  634. package/rules/max-kanji-continuous.yaml +6 -4
  635. package/rules/max-sentence-length.yaml +2 -2
  636. package/rules/modal-conflict.yaml +1 -0
  637. package/rules/nado-closed-list.yaml +2 -2
  638. package/rules/ngram-repetition.yaml +2 -2
  639. package/rules/no-doubled-joshi.yaml +2 -2
  640. package/rules/no-mixed-desumasu.yaml +3 -3
  641. package/rules/no-nakaguro-parallel.yaml +2 -0
  642. package/rules/number-without-unit.yaml +9 -4
  643. package/rules/numbering-gap.yaml +7 -2
  644. package/rules/numeral-sentence-start.yaml +2 -2
  645. package/rules/obligation-without-deadline.yaml +2 -2
  646. package/rules/orthographic-variant.yaml +2 -2
  647. package/rules/oxford-comma-consistency.yaml +3 -3
  648. package/rules/preamble-length.yaml +3 -2
  649. package/rules/range-notation-consistency.yaml +2 -2
  650. package/rules/requirement-smell.yaml +3 -3
  651. package/rules/table-header-variant.yaml +2 -2
  652. package/rules/teki-overuse.yaml +3 -2
  653. package/rules/title-length.yaml +2 -2
  654. package/rules/topic-predicate-distance.yaml +2 -2
  655. package/rules/total-mismatch.yaml +2 -2
  656. package/rules/translationese-density.yaml +2 -2
  657. package/rules/undefined-acronym.yaml +5 -2
  658. package/rules/undefined-term.yaml +2 -2
  659. package/rules/unfilled-placeholder.yaml +4 -4
  660. package/rules/unqualified-superlative.yaml +1 -1
  661. package/rules/unused-definition.yaml +2 -2
  662. package/rules/use-before-definition.yaml +2 -2
  663. package/rules/vague-word-density.yaml +2 -2
  664. package/skills/chaff/SKILL.md +7 -1
  665. package/src/announced-count.ts +35 -8
  666. package/src/chronology-rows.ts +86 -0
  667. package/src/company-name-run.ts +37 -0
  668. package/src/compound-head.ts +25 -0
  669. package/src/date-format.ts +43 -4
  670. package/src/derived/count-per-period.ts +28 -0
  671. package/src/detectors/acronym-context.ts +30 -1
  672. package/src/detectors/acronym-expansion.ts +54 -6
  673. package/src/detectors/acronym-known.ts +40 -0
  674. package/src/detectors/acronym-link.ts +75 -0
  675. package/src/detectors/acronym-mention.ts +44 -0
  676. package/src/detectors/acronym-name.ts +29 -6
  677. package/src/detectors/addressee-edge.ts +16 -0
  678. package/src/detectors/addressee-title-edge.ts +39 -0
  679. package/src/detectors/announced-count.ts +1 -0
  680. package/src/detectors/bare-comparative.ts +44 -3
  681. package/src/detectors/blank-structure.ts +21 -10
  682. package/src/detectors/bracket-specified.ts +25 -0
  683. package/src/detectors/broken-link.ts +26 -2
  684. package/src/detectors/capitalised-term.ts +26 -2
  685. package/src/detectors/caps-caption.ts +76 -0
  686. package/src/detectors/caps-phrase.ts +17 -0
  687. package/src/detectors/char-shape.ts +73 -14
  688. package/src/detectors/citation-sentence.ts +44 -0
  689. package/src/detectors/cited-title.ts +15 -3
  690. package/src/detectors/contraction-mention.ts +24 -0
  691. package/src/detectors/counter-edge.ts +17 -2
  692. package/src/detectors/dash-break.ts +45 -0
  693. package/src/detectors/date-any-year.ts +34 -9
  694. package/src/detectors/date-format.ts +2 -1
  695. package/src/detectors/date-year.ts +64 -16
  696. package/src/detectors/deadline-unit.ts +40 -0
  697. package/src/detectors/defined-term-form.ts +32 -12
  698. package/src/detectors/definition-use.ts +17 -9
  699. package/src/detectors/derived-numbers.ts +19 -4
  700. package/src/detectors/document-shape.ts +20 -1
  701. package/src/detectors/doubled-across-aside.ts +36 -0
  702. package/src/detectors/doubled-punctuation.ts +28 -7
  703. package/src/detectors/doubled-word.ts +2 -1
  704. package/src/detectors/duplicate-heading.ts +26 -3
  705. package/src/detectors/ellipsis.ts +16 -1
  706. package/src/detectors/email-letter.ts +142 -23
  707. package/src/detectors/field-label.ts +25 -0
  708. package/src/detectors/footnote-mismatch.ts +39 -7
  709. package/src/detectors/fullwidth-alnum.ts +9 -1
  710. package/src/detectors/graded-step.ts +52 -0
  711. package/src/detectors/gram-openers.ts +50 -0
  712. package/src/detectors/gram-place.ts +10 -1
  713. package/src/detectors/gram-predicate.ts +43 -3
  714. package/src/detectors/heading-echo.ts +31 -3
  715. package/src/detectors/heading-record-rhythm.ts +57 -0
  716. package/src/detectors/ime-residue.ts +4 -3
  717. package/src/detectors/kanji-compound-slip.ts +61 -0
  718. package/src/detectors/kutoten-consistency.ts +102 -14
  719. package/src/detectors/lexicon.ts +18 -5
  720. package/src/detectors/link-shape.ts +10 -3
  721. package/src/detectors/list-item-ending.ts +51 -0
  722. package/src/detectors/list-parallel.ts +158 -33
  723. package/src/detectors/list-sentence.ts +5 -1
  724. package/src/detectors/mark-shape.ts +89 -10
  725. package/src/detectors/mentioned-phrase.ts +38 -0
  726. package/src/detectors/middle-dot.ts +7 -2
  727. package/src/detectors/modal-conflict.ts +5 -2
  728. package/src/detectors/name-variant.ts +6 -0
  729. package/src/detectors/notice-paragraph.ts +33 -0
  730. package/src/detectors/number-style.ts +14 -2
  731. package/src/detectors/number-unit.ts +28 -1
  732. package/src/detectors/numeral-opener.ts +27 -1
  733. package/src/detectors/obligation-without-deadline.ts +29 -4
  734. package/src/detectors/open-end-class.ts +78 -0
  735. package/src/detectors/open-end-condition.ts +40 -0
  736. package/src/detectors/open-end-names.ts +9 -3
  737. package/src/detectors/open-end-question.ts +50 -0
  738. package/src/detectors/open-end-scope.ts +62 -0
  739. package/src/detectors/opening-date.ts +47 -0
  740. package/src/detectors/ordinary-phrase.ts +62 -0
  741. package/src/detectors/organisation-run.ts +18 -2
  742. package/src/detectors/orthographic-variant.ts +124 -25
  743. package/src/detectors/orthography.ts +15 -2
  744. package/src/detectors/oxford-comma.ts +74 -3
  745. package/src/detectors/person-consistency.ts +5 -3
  746. package/src/detectors/phrase-match.ts +16 -5
  747. package/src/detectors/placeholder-text.ts +18 -3
  748. package/src/detectors/placeholder.ts +10 -3
  749. package/src/detectors/postcode-end.ts +16 -0
  750. package/src/detectors/prose-total-words.ts +18 -0
  751. package/src/detectors/range-notation.ts +26 -6
  752. package/src/detectors/registry/kanji-compound-slip.ts +4 -0
  753. package/src/detectors/registry/phrase-in-use.ts +4 -0
  754. package/src/detectors/requirement-smell.ts +45 -8
  755. package/src/detectors/scaled-figure-unit.ts +103 -0
  756. package/src/detectors/sentence-counts.ts +64 -12
  757. package/src/detectors/sentence-ending.ts +12 -3
  758. package/src/detectors/sentence-length.ts +17 -4
  759. package/src/detectors/sentence-load.ts +9 -2
  760. package/src/detectors/signals.ts +50 -53
  761. package/src/detectors/structure-tree.ts +14 -14
  762. package/src/detectors/structure.ts +2 -1
  763. package/src/detectors/subject-name-line.ts +66 -0
  764. package/src/detectors/superlative-name.ts +10 -0
  765. package/src/detectors/table-header.ts +15 -1
  766. package/src/detectors/technical-docs.ts +5 -1
  767. package/src/detectors/term-mention-sentence.ts +31 -0
  768. package/src/detectors/titled-run.ts +9 -4
  769. package/src/detectors/token-shape.ts +16 -5
  770. package/src/detectors/undefined-term.ts +8 -0
  771. package/src/detectors/unknown-word.ts +1 -1
  772. package/src/detectors/vague-density.ts +20 -4
  773. package/src/document-paragraphs.ts +27 -0
  774. package/src/document.ts +3 -23
  775. package/src/figure-references.ts +7 -2
  776. package/src/format-template.ts +15 -0
  777. package/src/formula-brackets.ts +36 -0
  778. package/src/html/html-markdown.ts +2 -1
  779. package/src/html/html-site-chrome.ts +104 -0
  780. package/src/joined-view.ts +1 -0
  781. package/src/kanji-compound-slip.ts +98 -0
  782. package/src/latin-company-form.ts +38 -0
  783. package/src/latin-word-boundary.ts +64 -0
  784. package/src/leading-label.ts +15 -0
  785. package/src/lexicon-genres.ts +1 -1
  786. package/src/link-shape.ts +31 -0
  787. package/src/link-title.ts +38 -0
  788. package/src/list-item-paragraphs.ts +22 -0
  789. package/src/literal-quote.ts +55 -0
  790. package/src/nado-closed-list.ts +48 -5
  791. package/src/name-misspelt-usual.ts +25 -0
  792. package/src/name-separator.ts +27 -2
  793. package/src/nominal-stem.ts +62 -5
  794. package/src/notice-header.ts +57 -0
  795. package/src/person-forms.ts +15 -0
  796. package/src/plugin.ts +5 -0
  797. package/src/preamble-paragraphs.ts +13 -3
  798. package/src/sentence-load.ts +14 -3
  799. package/src/spacing-code.ts +5 -1
  800. package/src/split-noun.ts +63 -0
  801. package/src/structure/attached-parts.ts +47 -0
  802. package/src/structure/build.ts +7 -4
  803. package/src/structure/contents-lines.ts +63 -0
  804. package/src/structure/defining-names.ts +155 -0
  805. package/src/structure/definition-use.ts +149 -32
  806. package/src/structure/gerund-phrase.ts +31 -0
  807. package/src/structure/issues.ts +7 -3
  808. package/src/structure/list-lead-in.ts +94 -0
  809. package/src/structure/modal-conflict.ts +42 -7
  810. package/src/structure/negated-act.ts +49 -0
  811. package/src/structure/numbering.ts +24 -9
  812. package/src/structure/prose-total.ts +20 -6
  813. package/src/structure/repeated-number.ts +110 -0
  814. package/src/structure/rounded-amount.ts +55 -0
  815. package/src/structure/side-step.ts +21 -0
  816. package/src/structure/spanned-label-blank.ts +39 -0
  817. package/src/structure/universal.ts +33 -9
  818. package/src/structure/unspaced-heading.ts +27 -0
  819. package/src/structure/written-list-path.ts +46 -0
  820. package/src/structure/written-resolve.ts +16 -9
  821. package/src/title-line.ts +53 -0
  822. package/src/topic-clause.ts +109 -0
  823. package/src/uncounted-particles.ts +72 -0
@@ -3,6 +3,7 @@
3
3
  // one list is reported. です/ます against plain endings inside a list is no-mixed-desumasu's, not this.
4
4
  import { minorityWithin } from "../orthography.ts";
5
5
  import { isQuotedAt } from "./bold-label.ts";
6
+ import { endsAsHeadline, markOrSkipped, withoutFootnoteReference, withoutTrailingMarks } from "./list-item-ending.ts";
6
7
  import type { BulletList, Detector, Finding, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
7
8
 
8
9
  /** What an item is made of: a phrase or a sentence (ending), and the word it opens with (head, English only). */
@@ -12,6 +13,7 @@ export type Axis = "ending" | "head";
12
13
  export const FORMS: Readonly<Record<Axis, readonly [string, string]>> = { ending: ["phrase", "sentence"], head: ["verb", "noun"] };
13
14
 
14
15
  const SKIPPED_AT_END = new Set(["PUNCT", "SYM", "X"]);
16
+ const isMark = markOrSkipped(SKIPPED_AT_END);
15
17
  const NOMINAL = new Set(["NOUN", "PROPN", "NUM", "PRON"]);
16
18
  const PREDICATE = new Set(["VERB", "AUX", "ADJ"]);
17
19
  const NOUN_HEAD = new Set(["NOUN", "ADJ", "DET", "NUM", "PRON", "PROPN"]);
@@ -33,12 +35,16 @@ const withoutClosingAside = (tokens: readonly Token[]): readonly Token[] => {
33
35
  return open <= 0 ? tokens : tokens.slice(0, open);
34
36
  };
35
37
 
36
- /** Japanese: a predicate at the end (出します, 済ませる, 早い) is a sentence; a noun (月末, 確認すること) is a phrase. */
37
- const japaneseEnding = (sentences: readonly Sentence[]): string | undefined => {
38
+ /**
39
+ * Japanese: a predicate at the end (出します, 済ませる, 早い) is a sentence; a noun (月末, 確認すること) or a headline's
40
+ * あり / なし after a noun (翻訳あり) is a phrase. Marks after the last word (!!, a footnote reference) are not words.
41
+ */
42
+ const japaneseEnding = (sentences: readonly Sentence[], headlineEndings: ReadonlySet<string>): string | undefined => {
38
43
  if (sentences.length > 1) return "sentence";
39
- const last = withoutClosingAside(sentences[0]?.tokens ?? []).findLast((token) => !SKIPPED_AT_END.has(token.pos));
44
+ const words = withoutTrailingMarks(withoutClosingAside(withoutFootnoteReference(sentences[0]?.tokens ?? [], isMark)), isMark);
45
+ const last = words.at(-1);
40
46
  if (last === undefined) return undefined;
41
- if (NOMINAL.has(last.pos)) return "phrase";
47
+ if (NOMINAL.has(last.pos) || endsAsHeadline(words, headlineEndings)) return "phrase";
42
48
  return PREDICATE.has(last.pos) ? "sentence" : undefined;
43
49
  };
44
50
 
@@ -72,47 +78,124 @@ const AFTER_ADJECTIVE = new Set(["ADP", "PART"]);
72
78
  const isNounOrAdjective = (token: Token): boolean =>
73
79
  token.pos === "NOUN" || token.pos === "ADJ" || (token.pos === "PROPN" && token.features?.["OrdinaryWord"] === "Yes");
74
80
 
81
+ /** A verb in the base form an instruction takes (describe), not a past or third-person form (described, describes). */
82
+ const isBaseVerb = (token: Token | undefined): boolean =>
83
+ token?.pos === "VERB" && token.features?.["VerbForm"] === undefined && token.lemma === token.surface.toLowerCase();
84
+
85
+ /**
86
+ * An -ed word the tagger left without VerbForm (decreased, agreed, unauthorized): like a participle, it may modify the noun
87
+ * after it. Proceed and need end in -ed too but are their own base forms.
88
+ */
89
+ const isPastForm = (token: Token): boolean =>
90
+ token.pos === "VERB" &&
91
+ token.features?.["VerbForm"] === undefined &&
92
+ /ed$/iu.test(token.surface) &&
93
+ (token.lemma !== token.surface.toLowerCase() || !/eed$/iu.test(token.surface));
94
+
95
+ /** An -s word read as a verb that the tagger could not take back to a base form (Revisions): a plural noun, misread. Discuss and Focus are verbs. */
96
+ const isMisreadPlural = (token: Token): boolean =>
97
+ token.pos === "VERB" && token.features?.["VerbForm"] === undefined && /[^su]s$/iu.test(token.surface) && token.lemma === token.surface.toLowerCase();
98
+
99
+ /** Participles (Generated files) and gerunds (Recovering from illness) open noun phrases and duties alike, so neither form. */
100
+ const NEITHER_FORM_VERB = new Set(["Part", "Ger"]);
101
+
102
+ /** The head as the first word's tag gives it. */
103
+ const headFromTag = (first: Token): string | undefined => {
104
+ if (isUnsure(first) || isPastForm(first) || isMisreadPlural(first)) return undefined;
105
+ if (first.pos === "VERB") return NEITHER_FORM_VERB.has(first.features?.["VerbForm"] ?? "") ? undefined : "verb";
106
+ return NOUN_HEAD.has(first.pos) ? "noun" : undefined;
107
+ };
108
+
109
+ /** What the axes read besides the item's own words: the adapter's word lists, and the nouns of the item's list. */
110
+ export type HeadContext = {
111
+ /** Verbs the tagger does not know as verbs (click), from the adapter's instruction-verb word list. */
112
+ readonly instructionVerbs: ReadonlySet<string>;
113
+ /** Words that open an instruction or an adjective phrase (Secure the server, Secure configuration), from verb-or-adjective. */
114
+ readonly verbOrAdjective: ReadonlySet<string>;
115
+ /** The lemmas the tagger read as nouns anywhere in the item's list. */
116
+ readonly nounsInList: ReadonlySet<string>;
117
+ /** Words that end a Japanese item as a headline does after a noun (翻訳あり), from headline-ending. */
118
+ readonly headlineEndings: ReadonlySet<string>;
119
+ };
120
+
121
+ export const NO_HEAD_CONTEXT: HeadContext = { instructionVerbs: new Set(), verbOrAdjective: new Set(), nounsInList: new Set(), headlineEndings: new Set() };
122
+
123
+ type HeadReading = "verb" | "noun" | "unjudged" | undefined;
124
+
125
+ /** Reads the head from the item's tokens, its first word at `at`; undefined leaves it to the next reader. */
126
+ type HeadReader = (tokens: readonly Token[], at: number, context: HeadContext) => HeadReading;
127
+
128
+ /** A subject and its verb in one word (you're, we've): the item opens with its subject, as "you love …" does. */
129
+ const SUBJECT_CONTRACTION = /^(?:i|you|we|they|he|she|it)['’]\p{L}+$/iu;
130
+
131
+ const subjectContraction: HeadReader = (tokens, at) => (SUBJECT_CONTRACTION.test(tokens[at]?.surface ?? "") ? "noun" : undefined);
132
+
133
+ /** Secure, Open: a verb before "the", "a" or "your" (Secure the server), else maybe an adjective (Secure configuration). */
134
+ const verbOrAdjective: HeadReader = (tokens, at, context) => {
135
+ if (!context.verbOrAdjective.has(tokens[at]?.surface.toLowerCase() ?? "")) return undefined;
136
+ return opensObject(tokens[at + 1]) ? "verb" : "unjudged";
137
+ };
138
+
139
+ /** A verb the tagger does not know. Before a common noun the word may head a compound (Click fraud, Scroll bar), so its tag decides. */
140
+ const instructionVerb: HeadReader = (tokens, at, context) =>
141
+ context.instructionVerbs.has(tokens[at]?.surface.toLowerCase() ?? "") && tokens[at + 1]?.pos !== "NOUN" ? "verb" : undefined;
142
+
143
+ const isSeriesJoint = (token: Token): boolean => token.surface === "," || token.pos === "CCONJ";
144
+
145
+ /** The single words of a series the item opens with: "Scope, estimate and describe tasks" gives Scope, estimate, describe. */
146
+ const openingSeries = (tokens: readonly Token[], at: number): readonly Token[] => {
147
+ const word = tokens[at];
148
+ if (word === undefined) return [];
149
+ const after = tokens.findIndex((token, index) => index > at && !isSeriesJoint(token));
150
+ return after === -1 || after === at + 1 ? [word] : [word, ...openingSeries(tokens, after)];
151
+ };
152
+
153
+ /** A series one of whose later words is a verb in its base form (Instrument, monitor and profile): it is a series of verbs. */
154
+ const seriesOfVerbs: HeadReader = (tokens, at) => (openingSeries(tokens, at).slice(1).some(isBaseVerb) ? "verb" : undefined);
155
+
75
156
  /**
76
- * The head of an item whose first two words overrule the first word's tag, or undefined when they do not. "Open the console"
77
- * and "Press the button" open with a verb. "Clean up after closing" and "Bake in the oven" may open with a verb or an
78
- * adjective phrase (Close to the station), and "Washing machine space" with a compound noun or a gerund and its object
79
- * (Washing dishes): neither is judged.
157
+ * The first two words overrule the first word's tag. "Open the console" and "Press the button" open with a verb. "Clean up
158
+ * after closing" and "Bake in the oven" may open with a verb or an adjective phrase (Close to the station), and "Washing
159
+ * machine space" with a compound noun or a gerund and its object (Washing dishes): neither is judged.
80
160
  */
81
- const headFromNextWord = (first: Token, next: Token | undefined): "verb" | "unjudged" | undefined => {
161
+ const nextWord: HeadReader = (tokens, at) => {
162
+ const first = tokens[at];
163
+ // The word right after, punctuation included: in "Next, the candidate" the comma ends the opener.
164
+ const next = tokens[at + 1];
165
+ if (first === undefined) return undefined;
82
166
  if (isNounOrAdjective(first) && opensObject(next)) return "verb";
83
167
  if (first.pos === "ADJ" && AFTER_ADJECTIVE.has(next?.pos ?? "")) return "unjudged";
84
168
  return first.features?.["VerbForm"] === "Ger" && next?.pos === "NOUN" ? "unjudged" : undefined;
85
169
  };
86
170
 
87
- /** The head as the first word's tag gives it. */
88
- const headFromTag = (first: Token): string | undefined => {
89
- if (isUnsure(first)) return undefined;
90
- // A participle (Generated files, Nested lists) modifies the noun after it; the item is a noun phrase, but the tag does not say so.
91
- if (first.pos === "VERB") return first.features?.["VerbForm"] === "Part" ? undefined : "verb";
92
- return NOUN_HEAD.has(first.pos) ? "noun" : undefined;
171
+ /** A verb that the same list uses as a noun (holiday pay … pay during your notice), with no object after it: either reading. */
172
+ const nounElsewhereInList: HeadReader = (tokens, at, context) => {
173
+ const first = tokens[at];
174
+ return first?.pos === "VERB" && context.nounsInList.has(first.lemma ?? "") && !opensObject(tokens[at + 1]) ? "unjudged" : undefined;
93
175
  };
94
176
 
95
- const englishHead = (sentences: readonly Sentence[], instructionVerbs: ReadonlySet<string>): string | undefined => {
177
+ const HEAD_READERS: readonly HeadReader[] = [subjectContraction, verbOrAdjective, instructionVerb, seriesOfVerbs, nextWord, nounElsewhereInList];
178
+
179
+ const englishHead = (sentences: readonly Sentence[], context: HeadContext): string | undefined => {
96
180
  const tokens = sentences[0]?.tokens ?? [];
97
181
  const at = tokens.findIndex((token) => !SKIPPED_AT_END.has(token.pos));
98
182
  const first = tokens[at];
99
183
  if (at === -1 || first === undefined || isTitleCase(sentences[0]?.text ?? "")) return undefined;
100
- // The word right after, punctuation included: in "Next, the candidate" the comma ends the opener.
101
- const next = tokens[at + 1];
102
- // Before a common noun the word may head a compound (Click fraud, Scroll bar), so its tag decides.
103
- if (instructionVerbs.has(first.surface.toLowerCase()) && next?.pos !== "NOUN") return "verb";
104
- const overruled = headFromNextWord(first, next);
105
- if (overruled === undefined) return headFromTag(first);
106
- return overruled === "verb" ? "verb" : undefined;
184
+ const reading = HEAD_READERS.reduce<HeadReading>((found, reader) => found ?? reader(tokens, at, context), undefined);
185
+ if (reading === undefined) return headFromTag(first);
186
+ return reading === "unjudged" ? undefined : reading;
107
187
  };
108
188
 
109
- /**
110
- * An item's form on an axis, or undefined when its words do not tell. Japanese items have no head axis (the verb comes last).
111
- * instructionVerbs: verbs the tagger does not know as verbs (click), from the adapter's instruction-verb word list.
112
- */
113
- export const formOf = (axis: Axis, sentences: readonly Sentence[], language: string, instructionVerbs: ReadonlySet<string> = new Set()): string | undefined => {
114
- if (language === "ja") return axis === "ending" ? japaneseEnding(sentences) : undefined;
115
- return axis === "ending" ? englishEnding(sentences) : englishHead(sentences, instructionVerbs);
189
+ /** An item's form on an axis, or undefined when its words do not tell. Japanese items have no head axis (the verb comes last). */
190
+ /** An item that ends in a colon (Other kinds of decisions:) leads into what follows it: its ending is not its own, its opening still is. */
191
+ const LEAD_IN = /[::]$/u;
192
+
193
+ const leadsIn = (sentences: readonly Sentence[]): boolean => LEAD_IN.test(sentences.at(-1)?.text.trim() ?? "");
194
+
195
+ export const formOf = (axis: Axis, sentences: readonly Sentence[], language: string, context: HeadContext = NO_HEAD_CONTEXT): string | undefined => {
196
+ if (axis === "ending" && leadsIn(sentences)) return undefined;
197
+ if (language === "ja") return axis === "ending" ? japaneseEnding(sentences, context.headlineEndings) : undefined;
198
+ return axis === "ending" ? englishEnding(sentences) : englishHead(sentences, context);
116
199
  };
117
200
 
118
201
  const within = (inner: Span, outer: Span): boolean => inner.start >= outer.start && inner.end <= outer.end;
@@ -123,6 +206,33 @@ export const itemSentences = (doc: ProseDocument, item: Span): Sentence[] => {
123
206
  return doc.sentences.filter((sentence) => within(sentence.span, item) && !nested.some((span) => within(sentence.span, span)));
124
207
  };
125
208
 
209
+ /**
210
+ * Where an item's own words end: before a line in it that opens, unindented, with a note lead (※応募書類は返却できません。,
211
+ * "Note: …"). Markdown reads such a line as the last item's, but the note is about the whole list.
212
+ */
213
+ export const itemOwnEnd = (source: string, item: Span, noteLeads: readonly string[]): number => {
214
+ const lineStarts = [...source.slice(item.start, item.end).matchAll(/\n/gu)].map((match) => item.start + match.index + 1);
215
+ const noteLine = lineStarts.find((start) => noteLeads.some((lead) => lead !== "" && source.startsWith(lead, start)));
216
+ return noteLine === undefined ? item.end : noteLine - 1;
217
+ };
218
+
219
+ /** The sentence up to `end`: a note line under the item is not part of the item's last sentence. */
220
+ const cutAt = (sentence: Sentence, end: number, source: string): Sentence =>
221
+ sentence.span.end <= end
222
+ ? sentence
223
+ : {
224
+ ...sentence,
225
+ span: { start: sentence.span.start, end },
226
+ text: source.slice(sentence.span.start, end),
227
+ ...(sentence.tokens === undefined ? {} : { tokens: sentence.tokens.filter((token) => token.span.end <= end) }),
228
+ };
229
+
230
+ /** The item's own sentences, up to a note line under it. */
231
+ const ownSentences = (doc: ProseDocument, item: Span, noteLeads: readonly string[]): Sentence[] => {
232
+ const end = itemOwnEnd(doc.source, item, noteLeads);
233
+ return itemSentences(doc, item).flatMap((sentence) => (sentence.span.start < end ? [cutAt(sentence, end, doc.source)] : []));
234
+ };
235
+
126
236
  type Item = { readonly sentences: readonly Sentence[]; readonly form: string };
127
237
 
128
238
  const findingOf = (axis: Axis, item: Item, count: number, of: number, limit: number): Finding => {
@@ -162,17 +272,32 @@ const isJudged = (written: string, sentences: readonly Sentence[]): boolean => {
162
272
 
163
273
  const runsOn = (sentences: readonly Sentence[]): boolean => RUNNING_ON.test(sentences.at(-1)?.text.trim() ?? "");
164
274
 
275
+ const wordsOf = (doc: ProseDocument, lexicon: string): ReadonlySet<string> =>
276
+ new Set((doc.lexicons[lexicon] ?? []).map((entry) => entry.pattern.toLowerCase()));
277
+
278
+ const headContext = (doc: ProseDocument, items: readonly (readonly Sentence[])[]): HeadContext => ({
279
+ instructionVerbs: wordsOf(doc, "instruction-verb"),
280
+ verbOrAdjective: wordsOf(doc, "verb-or-adjective"),
281
+ headlineEndings: wordsOf(doc, "headline-ending"),
282
+ nounsInList: new Set(
283
+ items.flatMap((sentences) =>
284
+ sentences.flatMap((sentence) => (sentence.tokens ?? []).flatMap((token) => (token.pos === "NOUN" && token.lemma !== undefined ? [token.lemma] : []))),
285
+ ),
286
+ ),
287
+ });
288
+
165
289
  const listFindings = (doc: ProseDocument, list: BulletList, limit: number): Finding[] => {
166
- const sentencesOf = list.itemSpans.map((span) => itemSentences(doc, span));
290
+ const noteLeads = (doc.lexicons["list-note-lead"] ?? []).map((entry) => entry.pattern);
291
+ const sentencesOf = list.itemSpans.map((span) => ownSentences(doc, span, noteLeads));
167
292
  if (sentencesOf.some(runsOn)) return [];
168
293
  const judged = sentencesOf.filter((sentences, index) => {
169
294
  const span = list.itemSpans[index];
170
295
  return span !== undefined && isJudged(doc.source.slice(span.start, sentences.at(-1)?.span.end ?? span.end), sentences);
171
296
  });
172
- const instructionVerbs = new Set((doc.lexicons["instruction-verb"] ?? []).map((entry) => entry.pattern.toLowerCase()));
297
+ const context = headContext(doc, judged);
173
298
  return AXES.flatMap((axis) => {
174
299
  const items = judged.flatMap((sentences) => {
175
- const form = formOf(axis, sentences, doc.language, instructionVerbs);
300
+ const form = formOf(axis, sentences, doc.language, context);
176
301
  return form === undefined ? [] : [{ sentences, form }];
177
302
  });
178
303
  const odd = minorityWithin(items, (item) => item.form === FORMS[axis][0], limit);
@@ -12,6 +12,10 @@ export type ListWords = {
12
12
  readonly example: Lexicon;
13
13
  readonly pair: ReadonlySet<string>;
14
14
  readonly region: Lexicon;
15
+ /** 題名を導く語(whose full title is、entitled)。すぐ後ろの Title Case の語の続きは題名で、その中の読点は題名を付けた人のもの。 */
16
+ readonly titleCue?: readonly string[];
17
+ /** 文頭で順番を言う一語(First, Next, Finally)。解析器が形容詞と読んでも、並びの項目ではなく導入の語。 */
18
+ readonly sequence?: ReadonlySet<string>;
15
19
  };
16
20
 
17
21
  const LIST_CONJUNCTION: ReadonlySet<string> = new Set(["and", "or"]);
@@ -193,6 +197,6 @@ export const listSentenceOf = (tokens: readonly Token[], words: ListWords, sourc
193
197
  exampleStarts: byDepth(depths, (index) => (exampleEnds[index]?.length ?? 0) > 0),
194
198
  pairOpeners: pairOpenersOf(tokens, depths, words.pair),
195
199
  commas: byDepth(depths, (index) => tokens[index]?.surface === "," && !regionCommas.has(index)),
196
- inCitedTitle: citedTitles(tokens, source),
200
+ inCitedTitle: citedTitles(tokens, source, words.titleCue),
197
201
  };
198
202
  };
@@ -1,8 +1,12 @@
1
1
  import type { Detector, Finding, Lexicon, ProseDocument, Sentence } from "../plugin.ts";
2
2
  import { escapeRegExp } from "../orthography.ts";
3
+ import { isConventionalPhrase } from "./caps-phrase.ts";
3
4
  import { minorityReport } from "../spacing-minority.ts";
5
+ import { externalLinkTitleSpans } from "../link-title.ts";
6
+ import { formulaBracketSpans } from "../formula-brackets.ts";
4
7
  import { isWithinAny, quotedSpans } from "../quoted-span.ts";
5
- import { captionsOf, isCaptionAt } from "./caps-caption.ts";
8
+ import { capitalLineSpans, captionsOf, isCaptionAt, isWithinSorted } from "./caps-caption.ts";
9
+ import { lineStarts } from "../position.ts";
6
10
 
7
11
  /** The letters a mark must touch to count as part of the document's text, by language. */
8
12
  const SCRIPT: Readonly<Record<string, RegExp>> = {
@@ -43,15 +47,17 @@ const besideLetter = (text: string, at: number, step: number, script: RegExp): b
43
47
  const touchesScript = (text: string, at: number, script: RegExp): boolean => besideLetter(text, at, -1, script) || besideLetter(text, at, 1, script);
44
48
 
45
49
  /**
46
- * The marks in a sentence that touch a letter of the document's script, outside 「」『』 quotations. spaced is the lexicon's pattern side.
50
+ * The marks in a sentence that touch a letter of the document's script, outside 「」『』 quotations and outside the brackets
51
+ * of a formula (× (1 - 時間 ÷ 月平均)), which follow the formula's notation. spaced is the lexicon's pattern side.
47
52
  * The letters beside a mark are read in the source, so a mark that opens a sentence (。(2)当社) counts wherever the sentence starts.
48
53
  */
49
54
  export const marksIn = (source: string, sentence: Sentence, forms: ReadonlyMap<string, Form>, script: RegExp): Mark[] => {
50
55
  const quoted = quotedSpans(sentence.text);
56
+ const formulas = formulaBracketSpans(sentence.text);
51
57
  return sentence.text.split("").flatMap((char, at) => {
52
58
  const form = forms.get(char);
53
59
  if (form === undefined || !touchesScript(source, sentence.span.start + at, script)) return [];
54
- if (isWithinAny(quoted, { start: at, end: at })) return [];
60
+ if (isWithinAny(quoted, { start: at, end: at }) || isWithinAny(formulas, { start: at, end: at + 1 })) return [];
55
61
  return [{ sentence, char, form, offset: sentence.span.start + at, spaced: form.side }];
56
62
  });
57
63
  };
@@ -83,20 +89,84 @@ const minorityFindings = <T extends Sided>(items: readonly T[], limit: number, v
83
89
  /** Sentences written in the document's own language; a quoted sentence in another language follows its own marks. */
84
90
  const ownSentences = (doc: ProseDocument): readonly Sentence[] => doc.sentences.filter((sentence) => sentence.embeddedLanguage === undefined);
85
91
 
92
+ /**
93
+ * A bracketed item number opening a line ((1)開催趣旨, (ア), (iv), a list bullet before it), both brackets of one width.
94
+ * It numbers the line, a style of its own: the brackets of the prose around it may be written the other width. A
95
+ * bracketed word at a line's head ((背景), (注)) is not a number, and an item number the prose refers to (次の(1)及び(2))
96
+ * is written in the prose; both stay with the prose's brackets.
97
+ */
98
+ const LINE_HEAD = /^\s*(?:[-*+] +)?/u;
99
+ const BRACKETED = /^([(([[])([^))\]]]{1,4})([))\]]])/u;
100
+ const NUMBERING = /^(?:[0-90-9]{1,3}|[一二三四五六七八九十]{1,3}|[A-Za-zA-Za-zァ-ヶぁ-んヲ-ン])$/u;
101
+ /** Roman numerals i to x, either case. */
102
+ const ROMAN = /^(?:i{2,3}|iv|vi{1,3}|ix|I{2,3}|IV|VI{1,3}|IX)$/u;
103
+ const CLOSER_OF: Readonly<Record<string, string>> = { "(": ")", "(": ")", "[": "]", "[": "]" };
104
+
105
+ const isItemNumber = (text: string): boolean => NUMBERING.test(text) || ROMAN.test(text);
106
+
107
+ /** The offsets in a line of its item number's opening and closing bracket, or none. */
108
+ const enumeratorIn = (line: string): readonly number[] => {
109
+ const head = LINE_HEAD.exec(line)?.[0].length ?? 0;
110
+ const found = BRACKETED.exec(line.slice(head));
111
+ if (found === null || CLOSER_OF[found[1] ?? ""] !== found[3] || !isItemNumber(found[2] ?? "")) return [];
112
+ return [head, head + found[0].length - 1];
113
+ };
114
+
115
+ /** The offsets in `source` of each line's item number's opening and closing bracket. */
116
+ export const enumeratorBracketOffsets = (source: string): ReadonlySet<number> => {
117
+ const starts = lineStarts(source);
118
+ return new Set(source.split("\n").flatMap((line, index) => enumeratorIn(line).map((at) => (starts[index] ?? 0) + at)));
119
+ };
120
+
121
+ /** Appended to a mark's kind for an item number's bracket. A lexicon's group, a word from YAML, never holds a NUL. */
122
+ const ENUMERATOR_KIND = "\u0000enumerator";
123
+
124
+ /** A line's item number's bracket is a kind of its own, compared only with the other item numbers' brackets. */
125
+ const withEnumeratorKind = (mark: Mark, enumerators: ReadonlySet<number>): Mark =>
126
+ enumerators.has(mark.offset) ? { ...mark, form: { ...mark.form, kind: `${mark.form.kind}${ENUMERATOR_KIND}` } } : mark;
127
+
128
+ /**
129
+ * A doubled parenthesis around text with no parenthesis inside, such as ((居住の用に供したとき等)) or ((注)): one mark written
130
+ * with two characters, as a directive sets an article's caption. Its width is that notation's, not the prose's.
131
+ */
132
+ const DOUBLED_PAREN = /\(\([^()()\n]*\)\)|(([^()()\n]*))/gu;
133
+ const PAIR_LENGTH = 2;
134
+
135
+ /** The offsets in `source` of every character of a doubled parenthesis. */
136
+ export const doubledParenOffsets = (source: string): ReadonlySet<number> =>
137
+ new Set(
138
+ [...source.matchAll(DOUBLED_PAREN)].flatMap((match) => {
139
+ const end = match.index + match[0].length;
140
+ return [match.index, match.index + 1, end - PAIR_LENGTH, end - 1];
141
+ }),
142
+ );
143
+
144
+ const DOUBLED_KIND = "\u0000doubled";
145
+
146
+ /** A doubled parenthesis is a kind of its own, compared only with the other doubled parentheses. */
147
+ const withDoubledKind = (mark: Mark, doubled: ReadonlySet<number>): Mark =>
148
+ doubled.has(mark.offset) ? { ...mark, form: { ...mark.form, kind: `${mark.form.kind}${DOUBLED_KIND}` } } : mark;
149
+
86
150
  /**
87
151
  * A mark written two ways in one document (( and (, “ and "), the less common way reported. The two ways come from the
88
152
  * lexicon; neither is called right. Only marks next to a letter of the document's script count, so a bracket in code-like
89
- * text (f(x)) or an English aside in a Japanese document does not.
153
+ * text (f(x)) or an English aside in a Japanese document does not. A line enumerator's brackets ((1)) are compared apart.
90
154
  */
91
155
  export const markConsistency: Detector = (doc, options): Finding[] => {
92
156
  const script = SCRIPT[doc.language];
93
157
  if (script === undefined) return [];
158
+ // A link that quotes an outside page's title keeps that page's marks ((コンテキスト内) in a WCAG title).
159
+ const titles = externalLinkTitleSpans(doc.source, doc.links);
94
160
  const forms = formsOf(options.lexicon ?? []);
95
- const marks = ownSentences(doc).flatMap((sentence) => marksIn(doc.source, sentence, forms, script));
161
+ const enumerators = enumeratorBracketOffsets(doc.source);
162
+ const doubled = doubledParenOffsets(doc.source);
163
+ const marks = ownSentences(doc).flatMap((sentence) =>
164
+ marksIn(doc.source, sentence, forms, script).map((mark) => withDoubledKind(withEnumeratorKind(mark, enumerators), doubled)),
165
+ );
96
166
  const kinds = [...new Set(marks.map((mark) => mark.form.kind))];
97
167
  return kinds.flatMap((kind) =>
98
168
  minorityFindings(
99
- marks.filter((mark) => mark.form.kind === kind),
169
+ marks.filter((mark) => mark.form.kind === kind && !isWithinAny(titles, { start: mark.offset, end: mark.offset + 1 })),
100
170
  options.limit,
101
171
  (mark) => ({ mark: mark.char, usual: mark.form.other }),
102
172
  ),
@@ -205,21 +275,30 @@ export const lowerCaseWords = (source: string): ReadonlySet<string> =>
205
275
 
206
276
  /**
207
277
  * Whether more than half the words of a capital run are also written elsewhere in lower case. Words the lexicon lists as
208
- * written in capitals by convention (MUST NOT in a specification) count like acronyms.
278
+ * written in capitals by convention (MUST NOT in a specification) count like acronyms, and a run made of its phrases
279
+ * (NOW, THEREFORE, BE IT RESOLVED) is not shouting.
209
280
  */
210
281
  export const isShouting = (run: string, known: ReadonlySet<string>, conventional: ReadonlySet<string>): boolean => {
282
+ if (isConventionalPhrase(run, conventional)) return false;
211
283
  const words = run.split(/,? /u);
212
284
  const ordinary = words.filter((word) => !conventional.has(word) && known.has(word.toLowerCase()));
213
285
  const long = words.filter((word) => word.length > 1);
214
286
  return long.length >= MIN_LONG_WORDS && ordinary.length * 2 > words.length;
215
287
  };
216
288
 
217
- /** Runs of three or more all-capital words that are ordinary words, not acronyms ("DO NOT DELETE THIS"), and not a caption or a mention of one. */
289
+ /**
290
+ * Runs of three or more all-capital words that are ordinary words, not acronyms ("DO NOT DELETE THIS"), and not a
291
+ * caption, a mention of one, a paragraph of capital lines that ends no sentence (a letterhead, a heading), or a roster name.
292
+ */
218
293
  export const capsShouting: Detector = (doc, options): Finding[] => {
219
294
  const known = lowerCaseWords(doc.prose ?? doc.source);
220
295
  const conventional = new Set((options.lexicon ?? []).map((entry) => entry.pattern));
221
296
  const captions = captionsOf(doc.source);
222
- const isCaption = (hit: Hit): boolean => captions.has(hit.matched) || isCaptionAt(doc.source, hit.offset, hit.offset + hit.matched.length);
223
- const hits = hitsOf(ownSentences(doc), CAPS_RUN).filter((hit) => isShouting(hit.matched, known, conventional) && !isCaption(hit));
297
+ const capitalLines = capitalLineSpans(doc.source);
298
+ const isCaptionOrLetterhead = (hit: Hit): boolean =>
299
+ captions.has(hit.matched) ||
300
+ isCaptionAt(doc.source, hit.offset, hit.offset + hit.matched.length) ||
301
+ isWithinSorted(capitalLines, { start: hit.offset, end: hit.offset + hit.matched.length });
302
+ const hits = hitsOf(ownSentences(doc), CAPS_RUN).filter((hit) => isShouting(hit.matched, known, conventional) && !isCaptionOrLetterhead(hit));
224
303
  return reportFrom(hits, options.limit);
225
304
  };
@@ -0,0 +1,38 @@
1
+ // A phrase that is mentioned rather than used: named as a term (when saying "raise the bar", the phrase "low-hanging
2
+ // fruit", 「徹底解説」という言い方). The writer is talking about the words, not leaning on them. The cue words come from the
3
+ // language's mention-cue word list: group before stands right before the phrase, group after right after it. Pure.
4
+ import type { LexiconEntry, Sentence, Token } from "../plugin.ts";
5
+ import { entryEndsAt, entryRanges, type TokenRange } from "./lexicon-match.ts";
6
+
7
+ const BEFORE = "before";
8
+ const AFTER = "after";
9
+
10
+ /** Quote marks and brackets that may stand between the cue and the phrase ("raise the bar", 「徹底解説」). */
11
+ const QUOTE_MARKS = new Set(["'", '"', "‘", "’", "“", "”", "「", "」", "『", "』", "(", ")", "(", ")"]);
12
+
13
+ export type MentionCues = { readonly before: readonly LexiconEntry[]; readonly after: readonly LexiconEntry[] };
14
+
15
+ export const mentionCuesOf = (entries: readonly LexiconEntry[]): MentionCues => ({
16
+ before: entries.filter((entry) => entry.group === BEFORE),
17
+ after: entries.filter((entry) => entry.group === AFTER),
18
+ });
19
+
20
+ const isQuoteMark = (token: Token | undefined): boolean => token !== undefined && QUOTE_MARKS.has(token.surface);
21
+
22
+ /** The index past the quote marks from `at` in direction `step`. */
23
+ const pastQuotes = (tokens: readonly Token[], at: number, step: 1 | -1): number => (isQuoteMark(tokens[at]) ? pastQuotes(tokens, at + step, step) : at);
24
+
25
+ const startsAt = (tokens: readonly Token[], entry: LexiconEntry, start: number): boolean => entryEndsAt(tokens, entry, start + (entry.tokens?.length ?? 0));
26
+
27
+ const isMention = (tokens: readonly Token[], range: TokenRange, cues: MentionCues): boolean => {
28
+ const before = pastQuotes(tokens, range.start - 1, -1) + 1;
29
+ const after = pastQuotes(tokens, range.end, 1);
30
+ return cues.before.some((cue) => entryEndsAt(tokens, cue, before)) || cues.after.some((cue) => startsAt(tokens, cue, after));
31
+ };
32
+
33
+ /** Whether every use of the entry in the sentence is a mention. Without tokens no use can be told apart, so none is. */
34
+ export const onlyMentioned = (sentence: Sentence, entry: LexiconEntry, cues: MentionCues): boolean => {
35
+ const tokens = sentence.tokens;
36
+ const ranges = entryRanges(sentence, entry);
37
+ return tokens !== undefined && ranges.length > 0 && ranges.every((range) => isMention(tokens, range, cues));
38
+ };
@@ -3,8 +3,13 @@ const MIDDLE_DOT = /・/gu;
3
3
  /** 文頭か行頭(前に空白だけ)の「・」。前に並べる項目が無いので、箇条書きの印。 */
4
4
  const BULLET_DOT = /(^|\n)[^\S\n]*・/gu;
5
5
 
6
+ /** 中黒を含めて 1 語の語(キャッシュ・フロー)を、中黒を除いた形にする。この中黒は語の切れ目で、項目を並べてはいない。 */
7
+ const withoutWordDots = (text: string, words: readonly string[]): string =>
8
+ words.reduce((joined, word) => joined.replaceAll(word, word.replaceAll("・", "")), text);
9
+
6
10
  /**
7
- * 項目を並べる中黒の数。箇条書きの印の「・」は数えない。
11
+ * 項目を並べる中黒の数。箇条書きの印の「・」と、中黒を含めて 1 語の語(words: キャッシュ・フロー)の中黒は数えない。
8
12
  * 「・ 水分を補給すること」が何行続いても、どこまでが 1 つの項目かは改行で読める。
9
13
  */
10
- export const parallelDotCount = (text: string): number => [...text.replace(BULLET_DOT, "$1").matchAll(MIDDLE_DOT)].length;
14
+ export const parallelDotCount = (text: string, words: readonly string[] = []): number =>
15
+ [...withoutWordDots(text, words).replace(BULLET_DOT, "$1").matchAll(MIDDLE_DOT)].length;
@@ -1,8 +1,10 @@
1
1
  import type { Detector, Finding, StructureNode } from "../plugin.ts";
2
2
  import { inDocumentOrder } from "../structure/issues.ts";
3
+ import { listLeadIns } from "../structure/list-lead-in.ts";
3
4
  import { modalConflicts, modalStatements, type Obligation } from "../structure/modal-conflict.ts";
4
5
  import { linesOf, lineNumberAt } from "../structure/lines.ts";
5
6
  import { quoteAt } from "./structure-tree.ts";
7
+ import { negationsMarked, negationWords } from "../structure/negated-act.ts";
6
8
 
7
9
  export const obligationsOf = (tree: StructureNode): Obligation[] =>
8
10
  inDocumentOrder(tree).flatMap((node) =>
@@ -12,10 +14,11 @@ export const obligationsOf = (tree: StructureNode): Obligation[] =>
12
14
  );
13
15
 
14
16
  /** 同じ主語と行為に、前の文と逆の様相(しなければならない と してはならない、may と must not)を書いた文。 */
15
- export const modalConflict: Detector = (doc): Finding[] => {
17
+ export const modalConflict: Detector = (written): Finding[] => {
18
+ const doc = { ...written, sentences: negationsMarked(written.sentences, negationWords(written.lexicons["negation-word"])) };
16
19
  if (doc.structure === undefined) return [];
17
20
  const lines = linesOf(doc.source);
18
- return modalConflicts(modalStatements(obligationsOf(doc.structure), doc.sentences)).map(({ statement, earlier }) => ({
21
+ return modalConflicts(modalStatements(obligationsOf(doc.structure), doc.sentences, listLeadIns(doc.source, doc.sentences))).map(({ statement, earlier }) => ({
19
22
  rule: "",
20
23
  severity: "warning",
21
24
  line: 0,
@@ -24,6 +24,9 @@ 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
26
  import { isGroupPairOf, notDefinedTerms, outsideCapitals, sentenceIndexOf, withGivenNames } from "./name-variant-apart.ts";
27
+ import { usualIsMisspelt } from "../name-misspelt-usual.ts";
28
+ import { spellerOf } from "./unknown-word.ts";
29
+ import { isKnownWord } from "../spelling.ts";
27
30
 
28
31
  // 人の名前と読ませる敬称(様、さん)は語彙表 person-suffix、人を指す前置き(担当の)は person-lead、名前のすぐ後ろに来る語
29
32
  // (です、まで)は name-particle、字体の違う同じ字(斎・斉・齋)は name-variant-char が組(group)ごとに言う。
@@ -387,7 +390,10 @@ export const nameVariant: Detector = (doc): Finding[] => {
387
390
  const withProducts = [...withPlaces, ...productFindings(doc, prose, withPlaces)];
388
391
  const withOrder = [...withProducts, ...orderFindings(doc, prose, withProducts)];
389
392
  const codes = modelCodeFindings(doc, prose).filter((code) => !overlapsAny(withOrder, code.offset, code.name.length));
393
+ const dictionary = doc.dictionary?.();
394
+ const speller = dictionary === undefined ? undefined : spellerOf(doc, dictionary);
390
395
  return [...withOrder, ...codes]
396
+ .filter(({ name, usual }) => speller === undefined || !usualIsMisspelt(name, usual, (word) => isKnownWord(word, speller)))
391
397
  .toSorted((left, right) => left.offset - right.offset)
392
398
  .map(({ offset, name, usual, kind }) => ({
393
399
  rule: "",
@@ -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)),