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
@@ -1,6 +1,6 @@
1
1
  // A work email or letter's own parts: a greeting and a closing, a subject line, and an attachment the text mentions.
2
2
  // Pure. The words (お世話になっております, Dear, Best regards, 件名, attached) come from the language's email-greeting,
3
- // email-closing, email-sentence-end, email-subject-field, attachment-mention, attachment-not-mention and attachment-line lexicons. The
3
+ // email-closing, email-sentence-end, memo-header-label, email-subject-field, attachment-mention, attachment-not-mention and attachment-line lexicons. The
4
4
  // header and the signature are masked in doc.prose; a quoted reply is someone else's words and is left out.
5
5
  import { escapeRegExp } from "../orthography.ts";
6
6
  import { quoteAt } from "./structure-tree.ts";
@@ -141,13 +141,49 @@ export const frameSlips = (
141
141
  ];
142
142
  };
143
143
 
144
+ /** The marks around a label line: a heading's #, emphasis, 【】. */
145
+ const LINE_MARKS = new Set("#*_【】 \t\u3000");
146
+
147
+ const withoutMarks = (line: string): string => {
148
+ const chars = [...line];
149
+ const first = chars.findIndex((char) => !LINE_MARKS.has(char));
150
+ return first === -1 ? "" : chars.slice(first, chars.findLastIndex((char) => !LINE_MARKS.has(char)) + 1).join("");
151
+ };
152
+
153
+ const LABEL_END = /^(?:[::]|$)/u;
154
+
155
+ /** An inline HTML tag around a label (<h3> FROM: <br/>, <b>TO</b>:), dropped so the colon still follows the label. */
156
+ const INLINE_HTML_TAG = /<\/?[A-Za-z][A-Za-z0-9-]*(?:\s[^<>]*)?\/?>/gu;
157
+
158
+ /**
159
+ * Whether a line is a memo's header label (TO:, SUBJECT:, MEMORANDUM, 発信者:): a label as the lexicon writes it, case
160
+ * included, then a colon or the line's end. A memo sets its labels in capitals; a mail program writes "To:" and "Subject:".
161
+ */
162
+ export const isMemoLabel = (line: string, labels: readonly string[]): boolean => {
163
+ const bare = withoutMarks(line.replace(INLINE_HTML_TAG, ""));
164
+ return labels.some((label) => bare.startsWith(label) && LABEL_END.test(bare.slice(label.length)));
165
+ };
166
+
167
+ /**
168
+ * A memo: one of its header labels among the source's lines before the first sentence (the first lines, when no line ends
169
+ * one). The source, not the body, since a block of TO: / FROM: lines is masked as an email's header. A memo takes no
170
+ * greeting and no closing.
171
+ */
172
+ export const isMemo = (source: string, labels: readonly string[], sentenceEnds: readonly string[]): boolean => {
173
+ const lines = source.split("\n").filter((line) => line.trim() !== "" && !line.trimStart().startsWith(">"));
174
+ const firstSentence = lines.findIndex((line) => endsSentence(line, sentenceEnds));
175
+ return lines.slice(0, firstSentence === -1 ? HEADER_LINES : firstSentence).some((line) => isMemoLabel(line, labels));
176
+ };
177
+
178
+ const frameSlipsOf = (doc: ProseDocument): FrameSlip[] => {
179
+ const sentenceEnds = patternsOf(doc, "email-sentence-end");
180
+ if (isMemo(doc.source, patternsOf(doc, "memo-header-label"), sentenceEnds)) return [];
181
+ const lines = bodyLines(doc.source, doc.prose ?? doc.source, doc.replyQuotes ?? []);
182
+ return frameSlips(lines, patternsOf(doc, "email-greeting"), patternsOf(doc, "email-closing"), sentenceEnds);
183
+ };
184
+
144
185
  export const emailFrame: Detector = (doc): Finding[] =>
145
- frameSlips(
146
- bodyLines(doc.source, doc.prose ?? doc.source, doc.replyQuotes ?? []),
147
- patternsOf(doc, "email-greeting"),
148
- patternsOf(doc, "email-closing"),
149
- patternsOf(doc, "email-sentence-end"),
150
- ).map((slip) => ({
186
+ frameSlipsOf(doc).map((slip) => ({
151
187
  rule: "email-greeting-closing",
152
188
  severity: "info",
153
189
  line: 0,
@@ -180,14 +216,53 @@ export const fieldOf = (line: string): { readonly name: string; readonly value:
180
216
  };
181
217
  };
182
218
 
219
+ /** The subject field's names and reply marks, and what tells the body's first line from a subject: a greeting, a sentence's end. */
220
+ export type SubjectVocabulary = {
221
+ readonly fields: readonly string[];
222
+ readonly replyMarks: readonly string[];
223
+ readonly headerFields: readonly string[];
224
+ readonly greetings: readonly string[];
225
+ readonly sentenceEnds: readonly string[];
226
+ };
227
+
228
+ /** The text of the first line with text after `index`, trimmed. Scans only the blank lines between, so many empty subjects stay linear. */
229
+ const nextText = (lines: readonly SourceLine[], index: number): string => {
230
+ for (let at = index + 1; at < lines.length; at += 1) {
231
+ const text = lines[at]?.text.trim() ?? "";
232
+ if (text !== "") return text;
233
+ }
234
+ return "";
235
+ };
236
+
237
+ /** A header field's line (From: Ann). Not any colon: a subject may hold one (Re: Lunch, 10:00 meeting, Q3: budget). */
238
+ const isHeaderField = (line: string, headerFields: readonly string[]): boolean => {
239
+ const name = fieldOf(line)?.name.toLowerCase();
240
+ return name !== undefined && headerFields.some((field) => field.toLowerCase() === name);
241
+ };
242
+
243
+ /**
244
+ * The value under a subject label with nothing after its colon: the next line with text, as a form that sets the label and
245
+ * the value in two columns reads once it is text ("SUBJECT:" over "Car park repairs"). A quoted line, a header field, a
246
+ * greeting or a sentence there is the body, and the subject stays empty.
247
+ */
248
+ export const valueBelow = (lines: readonly SourceLine[], index: number, vocabulary: SubjectVocabulary): string => {
249
+ const text = nextText(lines, index);
250
+ const isBody =
251
+ text.startsWith(">") || isHeaderField(text, vocabulary.headerFields) || lineHas(text, vocabulary.greetings) || endsSentence(text, vocabulary.sentenceEnds);
252
+ return isBody ? "" : text;
253
+ };
254
+
183
255
  /** The subject lines (Subject: …, 件名:…), outside a quoted reply, with reply and forward marks (Re:, Fwd:) taken off the value. */
184
- export const subjectLines = (source: string, fields: readonly string[], replyMarks: readonly string[], replyQuotes: readonly Span[]): SubjectLine[] => {
185
- const names = new Set(fields.map((field) => field.toLowerCase()));
256
+ export const subjectLines = (source: string, vocabulary: SubjectVocabulary, replyQuotes: readonly Span[]): SubjectLine[] => {
257
+ const names = new Set(vocabulary.fields.map((field) => field.toLowerCase()));
186
258
  const quoted = insideCursor(replyQuotes);
187
- return linesWithOffsets(source).flatMap(({ start, text }): SubjectLine[] => {
259
+ const lines = linesWithOffsets(source);
260
+ return lines.flatMap(({ start, text }, index): SubjectLine[] => {
188
261
  const field = fieldOf(text);
189
262
  const inQuote = quoted(start);
190
- return field === undefined || inQuote || !names.has(field.name.toLowerCase()) ? [] : [{ start, subject: withoutReplyMarks(field.value, replyMarks) }];
263
+ if (field === undefined || inQuote || !names.has(field.name.toLowerCase())) return [];
264
+ const value = field.value === "" ? valueBelow(lines, index, vocabulary) : field.value;
265
+ return [{ start, subject: withoutReplyMarks(value, vocabulary.replyMarks) }];
191
266
  });
192
267
  };
193
268
 
@@ -201,7 +276,17 @@ export const withoutReplyMarks = (subject: string, marks: readonly string[]): st
201
276
  };
202
277
 
203
278
  export const emailSubject: Detector = (doc, options): Finding[] =>
204
- subjectLines(doc.source, patternsOf(doc, "email-subject-field"), patternsOf(doc, "email-reply-mark"), doc.replyQuotes ?? []).flatMap((line): Finding[] => {
279
+ subjectLines(
280
+ doc.source,
281
+ {
282
+ fields: patternsOf(doc, "email-subject-field"),
283
+ replyMarks: patternsOf(doc, "email-reply-mark"),
284
+ headerFields: patternsOf(doc, "email-header-field"),
285
+ greetings: patternsOf(doc, "email-greeting"),
286
+ sentenceEnds: patternsOf(doc, "email-sentence-end"),
287
+ },
288
+ doc.replyQuotes ?? [],
289
+ ).flatMap((line): Finding[] => {
205
290
  const length = [...line.subject].length;
206
291
  if (length > 0 && length <= options.limit) return [];
207
292
  return [
@@ -228,15 +313,6 @@ export const firstMention = (lines: readonly BodyLine[], mentions: readonly stri
228
313
  return line === undefined ? undefined : line.start + line.text.length - line.text.trimStart().length;
229
314
  };
230
315
 
231
- /** The marks around a label line: a heading's #, emphasis, 【】. */
232
- const LINE_MARKS = new Set("#*_【】 \t\u3000");
233
-
234
- const withoutMarks = (line: string): string => {
235
- const chars = [...line];
236
- const first = chars.findIndex((char) => !LINE_MARKS.has(char));
237
- return first === -1 ? "" : chars.slice(first, chars.findLastIndex((char) => !LINE_MARKS.has(char)) + 1).join("");
238
- };
239
-
240
316
  /** A line that labels what is attached: the label and a colon (Attachment: quote.pdf), or the label alone (### Enclosures, 【添付資料】). */
241
317
  const labelsAttachment = (line: string, labels: readonly string[]): boolean => {
242
318
  const bare = withoutMarks(line).toLowerCase();
@@ -1,6 +1,7 @@
1
1
  import { lengthOf } from "../measure.ts";
2
2
  import { isClosed } from "../sentence-shape.ts";
3
3
  import { isTitleCase, minorityCase, pageTitleOf } from "./heading-case.ts";
4
+ import { namesWrittenMidSentence } from "./heading-names.ts";
4
5
  import type { Detector, Finding, Lexicon, ProseDocument, Section, Sentence, Token } from "../plugin.ts";
5
6
  import { entryOpens } from "./lexicon-match.ts";
6
7
 
@@ -137,7 +138,10 @@ const headingsOf = (sections: readonly Section[], fixedCase: ReadonlySet<string>
137
138
  * 見るのは文書の中で揃っているかだけで、少数派のほうを指摘する。題名は指摘しない(minorityCase)。
138
139
  */
139
140
  export const titleCaseMix: Detector = (doc, options): Finding[] => {
140
- const fixedCase = new Set(FIXED_CASE_LISTS.flatMap((id) => (doc.lexicons[id] ?? []).map((entry) => entry.pattern)));
141
+ const fixedCase = new Set([
142
+ ...FIXED_CASE_LISTS.flatMap((id) => (doc.lexicons[id] ?? []).map((entry) => entry.pattern)),
143
+ ...namesWrittenMidSentence(doc.sentences.map((sentence) => sentence.text)),
144
+ ]);
141
145
  const pageTitle = pageTitleOf(doc.sections);
142
146
  const judged = headingsOf(
143
147
  doc.sections.filter((section) => section !== pageTitle),
@@ -140,9 +140,10 @@ const readFacts = (doc: ProseDocument, tree: StructureNode): ScopedFact[] => {
140
140
  );
141
141
  const read = new Set([...termed, ...labelled.map((fact) => fact.value.start)]);
142
142
  const verbs = verbQuantityFacts(doc.source, values, verbQuantityWordsOf(doc)).filter((fact) => !read.has(fact.value.start));
143
- const tabled = tableFacts(doc.source, values, totalColumnsOf(doc), countLabelWordsOf(doc.lexicons));
143
+ const tabled = tableFacts(doc.source, values, totalColumnsOf(doc), countLabelWordsOf(doc.lexicons), { columnGroups: true });
144
144
  const facts = withQualifiedKeys(doc, [...labelled, ...terms, ...verbs, ...tabled]);
145
- return withCellKeys(scopedFacts(facts, tree, doc.source, patternsOf(doc, "summary-heading")), qualifierWordsOf(doc));
145
+ const scoped = scopedFacts(facts, tree, doc.source, patternsOf(doc, "summary-heading"), { paragraphHeads: true });
146
+ return withCellKeys(scoped, qualifierWordsOf(doc));
146
147
  };
147
148
 
148
149
  /** 文書の名前付きの値。二つの rule が読むので、文書ごとに一度だけ読む。 */
@@ -0,0 +1,25 @@
1
+ // The label of a field that opens a line ("Current project status: Ongoing", 「現在の状況:継続中」). Pure.
2
+
3
+ /** A label is a short name, not a clause: this many words at most. */
4
+ const MAX_LABEL_WORDS = 5;
5
+ const MAX_LABEL_CHARS = 40;
6
+ const LIST_MARKER = /^\s*(?:[-*+]|\d+[.)])\s+/u;
7
+ const FIELD = /^([^::\n]+)[::](?!\/\/)/u;
8
+ const HAS_LETTER = /\p{L}/u;
9
+ /** A sentence ends before the colon, so what precedes it is not a label. */
10
+ const SENTENCE_END = /[.!?。!?]/u;
11
+
12
+ const isLabel = (label: string): boolean =>
13
+ HAS_LETTER.test(label) && !SENTENCE_END.test(label) && label.length <= MAX_LABEL_CHARS && label.trim().split(/\s+/u).length <= MAX_LABEL_WORDS;
14
+
15
+ /**
16
+ * Where the value of a field on the text's first line starts, just past the colon (the value may be blank), or undefined
17
+ * when the first line opens with no label. Whether the label is a name and not a clause ("The following apply:") is the
18
+ * caller's to judge from the parts of speech.
19
+ */
20
+ export const fieldValueStart = (text: string): number | undefined => {
21
+ const marker = LIST_MARKER.exec(text)?.[0] ?? "";
22
+ const field = FIELD.exec(text.slice(marker.length));
23
+ if (field?.[1] === undefined || !isLabel(field[1].replaceAll("**", ""))) return undefined;
24
+ return marker.length + field[0].length;
25
+ };
@@ -26,9 +26,12 @@ const markdownMarks = (text: string): NoteMark[] =>
26
26
  return { offset: match.index, label: `[^${match.groups?.["key"] ?? ""}]`, kind: MARKDOWN, key: (match.groups?.["key"] ?? "").toLowerCase(), note };
27
27
  });
28
28
 
29
- /** 印と一桁か二桁の番号。後ろに数字や小数が続けば年や数(※2018年度、※1.2倍)で、注の番号ではない。 */
29
+ /** 番号の後ろに続くと、番号が英語の序数(1st、2nd、23rd)になるもの。 */
30
+ const ORDINAL_SUFFIX = "(?:[sS][tT]|[nN][dD]|[rR][dD]|[tT][hH])(?![A-Za-z])";
31
+
32
+ /** 印と一桁か二桁の番号。後ろに数字や小数が続けば年や数(※2018年度、※1.2倍)、序数が続けば英語の語(※1st Party)で、注の番号ではない。 */
30
33
  const wordMarks = (text: string, mark: string): NoteMark[] =>
31
- [...text.matchAll(new RegExp(`${escapeRegExp(mark)}(?<key>[0-90-9]{1,2})(?![0-90-9]|[..,,][0-90-9])`, "gu"))].map((match) => ({
34
+ [...text.matchAll(new RegExp(`${escapeRegExp(mark)}(?<key>[0-90-9]{1,2})(?![0-90-9]|[..,,][0-90-9]|${ORDINAL_SUFFIX})`, "gu"))].map((match) => ({
32
35
  offset: match.index,
33
36
  label: match[0],
34
37
  kind: mark,
@@ -36,11 +39,38 @@ const wordMarks = (text: string, mark: string): NoteMark[] =>
36
39
  note: NOTE_LINE_HEAD.test(lineHeadOf(text, match.index)),
37
40
  }));
38
41
 
42
+ const QUOTE_LINE = /^[ \t]{0,3}>/u;
43
+ const QUOTE_MARKS = /^(?:[ \t]{0,3}>)+/u;
44
+ /** 引用の段落を終わらせる行(見出し、コード、箇条書き、脚注の定義)。これ以外の空でない行は、引用の段落の続き(CommonMark の lazy continuation)。 */
45
+ const BLOCK_START = /^[ \t]{0,3}(?:[#`~]|[-*+][ \t]|\d{1,9}[.)][ \t]|\[\^)/u;
46
+ const CODE_SPAN = /(`+)[\s\S]*?\1/gu;
47
+
48
+ const quotedLines = (source: string): string[] =>
49
+ source.split("\n").reduce<{ lines: string[]; open: boolean }>(
50
+ (state, line) => {
51
+ const open = QUOTE_LINE.test(line) || (state.open && line.trim() !== "" && !BLOCK_START.test(line));
52
+ return { lines: open ? [...state.lines, line.replace(QUOTE_MARKS, "")] : state.lines, open };
53
+ },
54
+ { lines: [], open: false },
55
+ ).lines;
56
+
57
+ /**
58
+ * 引用(`>`)の中の Markdown の脚注の印の番号。引用は本文から覆われるが、引用の中の印も注を指している。
59
+ * 引用の中の印に注が無くても言わない(引用元の注かもしれない)。注が指されているかだけに使う。
60
+ */
61
+ export const quotedFootnoteKeys = (source: string): ReadonlySet<string> =>
62
+ new Set(
63
+ markdownMarks(quotedLines(source).join("\n").replace(CODE_SPAN, ""))
64
+ .filter((mark) => !mark.note)
65
+ .map((mark) => mark.key),
66
+ );
67
+
39
68
  /** 一つの種類の印のうち、合わないもの。印の語(※)は、その種類の注が一つも無ければ注を別に置いた文書と読んで言わない。 */
40
- const slipsOfKind = (marks: readonly NoteMark[], kind: string): NoteSlip[] => {
69
+ const slipsOfKind = (marks: readonly NoteMark[], kind: string, quotedKeys: ReadonlySet<string>): NoteSlip[] => {
41
70
  const ofKind = marks.filter((mark) => mark.kind === kind);
42
71
  const notes = new Set(ofKind.filter((mark) => mark.note).map((mark) => mark.key));
43
- const referenced = new Set(ofKind.filter((mark) => !mark.note).map((mark) => mark.key));
72
+ const quoted = kind === MARKDOWN ? [...quotedKeys] : [];
73
+ const referenced = new Set([...ofKind.filter((mark) => !mark.note).map((mark) => mark.key), ...quoted]);
44
74
  if (notes.size === 0 && kind !== MARKDOWN) return [];
45
75
  const missing = ofKind
46
76
  .filter((mark) => !mark.note && !notes.has(mark.key))
@@ -52,15 +82,17 @@ const slipsOfKind = (marks: readonly NoteMark[], kind: string): NoteSlip[] => {
52
82
  };
53
83
 
54
84
  /** 文字列の中の、注の無い印と印の無い注。 */
55
- export const noteSlips = (text: string, words: readonly string[]): NoteSlip[] => {
85
+ export const noteSlips = (text: string, words: readonly string[], quotedKeys: ReadonlySet<string> = new Set()): NoteSlip[] => {
56
86
  const marks = [...markdownMarks(text), ...words.flatMap((word) => wordMarks(text, word))];
57
- return [...new Set(marks.map((mark) => mark.kind))].flatMap((kind) => slipsOfKind(marks, kind)).toSorted((left, right) => left.offset - right.offset);
87
+ return [...new Set(marks.map((mark) => mark.kind))]
88
+ .flatMap((kind) => slipsOfKind(marks, kind, quotedKeys))
89
+ .toSorted((left, right) => left.offset - right.offset);
58
90
  };
59
91
 
60
92
  export const footnoteMismatch: Detector = (doc): Finding[] => {
61
93
  const text = doc.prose ?? doc.source;
62
94
  const words = (doc.lexicons["note-mark"] ?? []).map((entry) => entry.pattern);
63
- return noteSlips(text, words).map((slip) => ({
95
+ return noteSlips(text, words, quotedFootnoteKeys(doc.source)).map((slip) => ({
64
96
  rule: "",
65
97
  severity: "warning",
66
98
  line: 0,
@@ -0,0 +1,52 @@
1
+ import type { Span, Token } from "../plugin.ts";
2
+ import { isWithinAny } from "../quoted-span.ts";
3
+
4
+ /**
5
+ * 段階の一つとしての比較(より良い(BESTな)改善 と 良い(BETTERな)改善、より良い実装例1 と 良い実装例2)。文書が同じ語を
6
+ * 比べる副詞なしでも書いていれば(良い改善)、「より良い」の相手はその一段下の段で、相手は書いてある。
7
+ * 段は、程度を言う語の原形と、その後ろの名詞で見分ける。間の括弧の添え書き((BESTな))は飛ばす。
8
+ */
9
+
10
+ /** 程度を言う語が語の位置 at で始まるか。bare-comparative.ts の判定を受け取る。 */
11
+ export type IsGradable = (tokens: readonly Token[], at: number) => boolean;
12
+
13
+ /** 形容動詞の語幹の後ろに来る語(豊かな)。この語の後ろから名詞を探す。 */
14
+ const ADJECTIVAL_TAIL = new Set(["な", "に", "だ", "です", "で"]);
15
+ const OPENING = new Set(["(", "("]);
16
+ const CLOSING = new Set([")", ")"]);
17
+
18
+ /** 程度を言う語(at)の後ろの最初の語の位置。形容動詞の語尾と、括弧の添え書きを飛ばす。 */
19
+ const afterWord = (tokens: readonly Token[], at: number): number => {
20
+ const next = tokens[at]?.pos === "NOUN" && ADJECTIVAL_TAIL.has(tokens[at + 1]?.surface ?? "") ? at + 2 : at + 1;
21
+ if (!OPENING.has(tokens[next]?.surface ?? "")) return next;
22
+ const close = tokens.findIndex((token, index) => index > next && CLOSING.has(token.surface));
23
+ return close === -1 ? next : close + 1;
24
+ };
25
+
26
+ /** 段の名前: 程度を言う語の原形と、後ろの名詞。後ろが名詞でなければ段ではない。 */
27
+ export const stepKeyAt = (tokens: readonly Token[], at: number): string | undefined => {
28
+ const [word, noun] = [tokens[at], tokens[afterWord(tokens, at)]];
29
+ if (word === undefined || noun === undefined || noun.pos !== "NOUN") return undefined;
30
+ return `${word.lemma ?? word.surface}|${noun.surface}`;
31
+ };
32
+
33
+ /** 文の語と、引いたもの(鉤括弧の中)の範囲。引いた語(「良い対応」という表現)は文書が書いた段ではない。 */
34
+ export type StepSentence = { readonly tokens: readonly Token[]; readonly quoted: readonly Span[] };
35
+
36
+ /** 文書が比べる副詞(markers)なしで書いた、程度を言う語と名詞の段の名前。 */
37
+ export const plainStepKeys = (sentences: readonly StepSentence[], markers: ReadonlySet<string>, isGradable: IsGradable): ReadonlySet<string> =>
38
+ new Set(
39
+ sentences.flatMap(({ tokens, quoted }) =>
40
+ tokens.flatMap((token, at) => {
41
+ if (markers.has(tokens[at - 1]?.surface ?? "") || isWithinAny(quoted, token.span) || !isGradable(tokens, at)) return [];
42
+ const key = stepKeyAt(tokens, at);
43
+ return key === undefined ? [] : [key];
44
+ }),
45
+ ),
46
+ );
47
+
48
+ /** 比べた語(word)が、文書が一段下を書いた段の一つか。 */
49
+ export const isNamedStep = (tokens: readonly Token[], word: Token, steps: ReadonlySet<string>): boolean => {
50
+ const key = stepKeyAt(tokens, tokens.indexOf(word));
51
+ return key !== undefined && steps.has(key);
52
+ };
@@ -0,0 +1,21 @@
1
+ import type { Section, Sentence } from "../plugin.ts";
2
+
3
+ /** A list item or a table row on a line after the sentence: what the sentence leads into. */
4
+ const LIST_OR_TABLE_NEXT = /^[ \t]*\n\s*(?:[-*+]\s|\d{1,3}[.)]\s|\|)/u;
5
+
6
+ /** How far past the sentence to look for that line: blank lines between, never the rest of a long document. */
7
+ const LOOKAHEAD = 200;
8
+
9
+ /**
10
+ * 見出しのある節の最初の文のうち、次の行から箇条書きか表が続くもの。参照用の文書は、節ごとに同じ書き出しで一覧を導く
11
+ * (「…によると以下の制約である。」の後ろに制約の箇条書き)。言い回しがどれもこの文にだけ出るなら節のひな形で、書き手が言い直したのではない。
12
+ * 後ろが本文の文なら、節ごとの口癖(正直なところ、…)と見分けられないので入れない。導入部(見出しの前)は節ではない。
13
+ */
14
+ export const sectionOpeners = (sections: readonly Pick<Section, "depth" | "sentences">[], source: string): Set<Sentence> =>
15
+ new Set(
16
+ sections.flatMap((section) => {
17
+ const first = section.sentences[0];
18
+ if (section.depth === 0 || first === undefined) return [];
19
+ return LIST_OR_TABLE_NEXT.test(source.slice(first.span.end, first.span.end + LOOKAHEAD)) ? [first] : [];
20
+ }),
21
+ );
@@ -0,0 +1,36 @@
1
+ import type { Section, Sentence } from "../plugin.ts";
2
+
3
+ /**
4
+ * 問いの印で終わる見出し。後ろに括弧の注記((updated Nov. 14, 2024))が付いてもよい。
5
+ * 「Q1」の札だけでは問いと見ない。四半期(Q1 2024)の見出しと見分けられない。
6
+ */
7
+ const QUESTION_END = /[??]\s*(?:[((][^()()]*[))])?$/u;
8
+
9
+ export const isQuestionHeading = (heading: string): boolean => QUESTION_END.test(heading.trim());
10
+
11
+ /** 範囲を決めるのに見るのは、見出しと深さと文だけ。 */
12
+ type Heading = Pick<Section, "depth" | "heading" | "sentences">;
13
+
14
+ type Answer = { readonly depth: number; readonly sentences: Sentence[] };
15
+ type Passages = { readonly rest: Sentence[]; readonly answers: Answer[]; readonly open: readonly Answer[] };
16
+
17
+ /** 節は、それを囲む一番内側の問いの答えに入る。同じ深さか浅い見出しが来れば、その問いは閉じている。 */
18
+ const place = (passages: Passages, section: Heading): Passages => {
19
+ const open = passages.open.filter((answer) => answer.depth < section.depth);
20
+ if (isQuestionHeading(section.heading)) {
21
+ const answer = { depth: section.depth, sentences: [...section.sentences] };
22
+ return { ...passages, answers: [...passages.answers, answer], open: [...open, answer] };
23
+ }
24
+ const owner = open.at(-1);
25
+ (owner?.sentences ?? passages.rest).push(...section.sentences);
26
+ return { ...passages, open };
27
+ };
28
+
29
+ /**
30
+ * 言い回しを数える範囲。問いの見出しの下(より深い見出しの「A1」も含む)はそれぞれ一つの答えで、読み手は答えを一つずつ読む。
31
+ * 別の答えで同じ案内(〜をご覧ください)を繰り返しても、書き手が言い直したのではない。問いでない節は、文書全体で一つの範囲。
32
+ */
33
+ export const gramPassagesOf = (sections: readonly Heading[]): Sentence[][] => {
34
+ const passages = sections.reduce<Passages>(place, { rest: [], answers: [], open: [] });
35
+ return [passages.rest, ...passages.answers.map((answer) => answer.sentences)].filter((sentences) => sentences.length > 0);
36
+ };
@@ -1,5 +1,5 @@
1
1
  import { softBreaks } from "../soft-break.ts";
2
- import type { LengthUnit, Span } from "../plugin.ts";
2
+ import type { LengthUnit, ProseDocument, Sentence, Span } from "../plugin.ts";
3
3
 
4
4
  /** 数えるために詰めた文と、詰めた文の各文字が元の文のどこにあったか。 */
5
5
  export type Compacted = { readonly text: string; readonly offsets: readonly number[] };
@@ -50,3 +50,12 @@ export const placeOf = (source: Compacted, gram: string): Span | undefined => {
50
50
  const at = source.text.indexOf(gram);
51
51
  return at === -1 ? undefined : placeAt(source, { start: at, end: at + gram.length });
52
52
  };
53
+
54
+ /** 詰めた文の index 番目の文字が、リンクの文字か。 */
55
+ export const linkedIn = (doc: ProseDocument, sentence: Sentence, source: Compacted): ((index: number) => boolean) => {
56
+ const links = doc.links.filter((link) => link.start < sentence.span.end && sentence.span.start < link.end);
57
+ return (index) => {
58
+ const at = sentence.span.start + (source.offsets[index] ?? -1);
59
+ return links.some((link) => link.start <= at && at < link.end);
60
+ };
61
+ };
@@ -9,12 +9,28 @@ const NOUNS = new Set(["NOUN", "PROPN", "ADJ"]);
9
9
  /** 中身を持たない語。名前の前後に付いても、名前の繰り返しを言い回しに変えない。 */
10
10
  const FUNCTION_POS = new Set(["ADP", "DET", "CCONJ", "SCONJ", "PART", "PUNCT", "SYM", "X"]);
11
11
 
12
+ /** 形式名詞(とき、こと)。動詞が節を名詞にしているだけで、用語は作らない(承認又は断るとき)。 */
13
+ const isDependentNoun = (token: Token | undefined): boolean => token?.features?.["NounType"] === "Dependent";
14
+
15
+ /**
16
+ * 日本語で、名詞と接続詞(又は、及び)のすぐ後ろで名詞を飾る動詞(行為又は怠る事実)は、名詞を並べた一つの用語の中にあり、述語ではない。
17
+ * 用語は言い換えられないので、繰り返して当たり前。名詞に「する」が付いた動詞(承認又は拒否する)は、行為を並べた述語と見分けられないので外さない。
18
+ */
19
+ const inCoordinatedNoun = (tokens: readonly Token[], index: number, unit: LengthUnit): boolean =>
20
+ unit === "char" &&
21
+ tokens[index]?.pos === "VERB" &&
22
+ tokens[index]?.features?.["VerbType"] !== "Light" &&
23
+ tokens[index - 1]?.pos === "CCONJ" &&
24
+ NOUNS.has(tokens[index - 2]?.pos ?? "") &&
25
+ NOUNS.has(tokens[index + 1]?.pos ?? "") &&
26
+ !isDependentNoun(tokens[index + 1]);
27
+
12
28
  /**
13
29
  * 英語で名詞のすぐ前の動詞は、名詞を飾る語(形容詞を挟んでも同じ)(the upcoming fiscal year、the Disclosing Party、the borrow checker)で、
14
- * 述語ではない。日本語の名詞の前の動詞(〜にあるコンポーネント)は言い回しの一部になるので、word 単位だけで見る。
30
+ * 述語ではない。日本語の名詞の前の動詞(〜にあるコンポーネント)は言い回しの一部になるので、接続詞の後ろの用語の中(inCoordinatedNoun)だけを外す。
15
31
  */
16
32
  const modifiesNoun = (tokens: readonly Token[], index: number, unit: LengthUnit): boolean =>
17
- unit === "word" && tokens[index]?.pos === "VERB" && NOUNS.has(tokens[index + 1]?.pos ?? "");
33
+ (unit === "word" && tokens[index]?.pos === "VERB" && NOUNS.has(tokens[index + 1]?.pos ?? "")) || inCoordinatedNoun(tokens, index, unit);
18
34
 
19
35
  /** 英語で大文字の名前の一部になった動詞(Procedures Guide、the Location Object)も、述語ではない。 */
20
36
  const namePartAt = (tokens: readonly Token[], index: number, unit: LengthUnit): boolean => unit === "word" && isNamePart(tokens, index);
@@ -40,10 +56,34 @@ const onlyNamesBeside = (tokens: readonly Token[], predicate: number, window: Sp
40
56
  return names.length > 0 && rest.every((index) => FUNCTION_POS.has(tokens[index]?.pos ?? ""));
41
57
  };
42
58
 
59
+ const COMPOUND_POS = new Set(["NOUN", "PROPN", "ADJ", "NUM"]);
60
+ /** 動詞の前の名詞句がこれだけの語を持てば、動詞はその名詞句の最後の名詞。the contract says は 1 語なので述語のまま。 */
61
+ const MIN_COMPOUND_WORDS = 2;
62
+
63
+ /** 語形を変えていない動詞(rate)か -ing 形(subcontracting)。名詞と同じ形で、名詞の読み違いになりうる。described や says は述語の形。 */
64
+ const isNounShaped = (token: Token): boolean =>
65
+ token.features?.["VerbForm"] === "Ger" || (token.lemma !== undefined && token.lemma === token.surface.toLowerCase());
66
+
67
+ /** 動詞の目的語の始まり(models generate the text の the)。後ろにこれが続く動詞は述語。 */
68
+ const OBJECT_START = new Set(["DET", "PRON", "NUM"]);
69
+
70
+ /**
71
+ * 英語で、窓の最後の名詞の形の動詞の前が名詞と形容詞だけ(先頭の冠詞は許す)で、後ろに目的語が続かなければ、動詞は名詞の続きの
72
+ * 読み違い(the federal funds rate の rate、small business subcontracting)。窓の中に機能語があれば言い回し(your contract says)。
73
+ */
74
+ const endsNounCompound = (tokens: readonly Token[], index: number, window: Span, unit: LengthUnit): boolean => {
75
+ const verb = tokens[index];
76
+ if (unit !== "word" || verb?.pos !== "VERB" || !isNounShaped(verb) || OBJECT_START.has(tokens[index + 1]?.pos ?? "")) return false;
77
+ const touched = tokens.flatMap((token, at) => (overlaps(token, window) ? [at] : []));
78
+ if (touched.at(-1) !== index) return false;
79
+ const before = touched.slice(0, -1).filter((at, order) => !(order === 0 && tokens[at]?.pos === "DET"));
80
+ return before.length >= MIN_COMPOUND_WORDS && before.every((at) => COMPOUND_POS.has(tokens[at]?.pos ?? ""));
81
+ };
82
+
43
83
  const countsAsPredicate = (tokens: readonly Token[], index: number, window: Span, unit: LengthUnit): boolean => {
44
84
  const token = tokens[index];
45
85
  if (token === undefined || !PREDICATE_POS.has(token.pos) || !overlaps(token, window)) return false;
46
- if (modifiesNoun(tokens, index, unit) || namePartAt(tokens, index, unit)) return false;
86
+ if (modifiesNoun(tokens, index, unit) || namePartAt(tokens, index, unit) || endsNounCompound(tokens, index, window, unit)) return false;
47
87
  return !isCut(token, window) || !onlyNamesBeside(tokens, index, window, unit);
48
88
  };
49
89
 
@@ -1,13 +1,15 @@
1
1
  import { lengthOf, proseText } from "../measure.ts";
2
2
  import { newContentMorphemes } from "./content-morphemes.ts";
3
3
  import { echoedHeadingUnits, trigrams } from "./heading-overlap.ts";
4
+ import { fieldValueStart } from "./field-label.ts";
4
5
  import { formValueTokens, isFormBlock } from "./form-line.ts";
5
6
  import { titleTokens } from "../heading-label.ts";
6
7
  import { announcerWords, makesClaim } from "./heading-claim.ts";
7
8
  import { handsOver } from "./lead-in.ts";
8
9
  import { holdsLink, namesLocation } from "./location-pointer.ts";
9
10
  import { withoutQuotedVariants } from "./quoted-variant.ts";
10
- import type { Detector, Finding, LengthUnit, ProseDocument, Section } from "../plugin.ts";
11
+ import { namesHeadingSubject } from "./subject-name-line.ts";
12
+ import type { Detector, Finding, LengthUnit, ProseDocument, Section, Sentence } from "../plugin.ts";
11
13
 
12
14
  /** 見出しが短すぎると、偶然の一致で 100% になる。これ未満の見出しは見ない。 */
13
15
  const MIN_GRAMS = 4;
@@ -105,8 +107,33 @@ const opensForm = (section: Section): boolean => {
105
107
  return newContentMorphemes(heading, formValueTokens(first.text, first.span.start, first.tokens)) > 0;
106
108
  };
107
109
 
110
+ /** 最初の行が、見出しが扱うものの名前だけ(リンクや添付の札、見出しの名の一覧)。見出しを言い直す文ではない。 */
111
+ const namesSubject = (doc: ProseDocument, section: Section): boolean => {
112
+ const first = section.firstSentence;
113
+ if (first?.tokens === undefined || section.headingTokens === undefined) return false;
114
+ const heading = titleTokens(section.heading, measuredHeading(section), section.headingTokens);
115
+ const announcing = announcerWords(doc.lexicons["heading-announcer"] ?? []).announcing;
116
+ return namesHeadingSubject(measuredHeading(section), heading, first.text, first.span.start, first.tokens, announcing);
117
+ };
118
+
119
+ /** 述語の品詞。項目名にあれば、コロンの前は名前ではなく文の頭(The following expenses require receipts:)。 */
120
+ const PREDICATE_POS: ReadonlySet<string> = new Set(["VERB", "AUX"]);
121
+
122
+ /**
123
+ * 行頭の項目名(Current project status: Ongoing)を除いた文。報告の書式が見出しの語で項目を立てるのは書式で、書き手が言ったのは値。
124
+ * 品詞が読めなければ、項目名かどうか決められないので除かない。
125
+ */
126
+ const withoutFieldLabel = (sentence: Sentence): string => {
127
+ const valueStart = fieldValueStart(sentence.text);
128
+ if (valueStart === undefined || sentence.tokens === undefined) return sentence.text;
129
+ const labelEnd = sentence.span.start + valueStart;
130
+ const isClause = sentence.tokens.some((token) => token.span.start < labelEnd && PREDICATE_POS.has(token.pos));
131
+ return isClause ? sentence.text : sentence.text.slice(valueStart);
132
+ };
133
+
108
134
  /** 見出しとの重なりを測る文。用語集や表記の手引きは見出しの語の別の書き方を引用する(Not “datacentre”)ので、それは数えない。 */
109
- const echoedText = (section: Section): string => withoutQuotedVariants(section.firstSentence?.text ?? "", measuredHeading(section));
135
+ const echoedText = (section: Section): string =>
136
+ section.firstSentence === undefined ? "" : withoutQuotedVariants(withoutFieldLabel(section.firstSentence), measuredHeading(section));
110
137
 
111
138
  export const headingEcho: Detector = (doc, options): Finding[] => {
112
139
  const leadIns = (doc.lexicons["lead-in"] ?? []).map((entry) => entry.pattern);
@@ -117,7 +144,8 @@ export const headingEcho: Detector = (doc, options): Finding[] => {
117
144
  !leadsIn(doc, section, leadIns) &&
118
145
  !pointsElsewhere(doc, section) &&
119
146
  !statesFigure(section.heading, section.firstSentence?.text ?? "") &&
120
- !opensForm(section),
147
+ !opensForm(section) &&
148
+ !namesSubject(doc, section),
121
149
  )
122
150
  .map((section) => ({ section, overlap: Math.round(containment(trigrams(measuredHeading(section)), trigrams(echoedText(section))) * 100) }))
123
151
  .filter(({ overlap }) => overlap >= options.limit)
@@ -39,8 +39,21 @@ export const endMarkOf = (heading: string, words: readonly string[] = []): strin
39
39
 
40
40
  type Judged = { readonly heading: MarkupHeading; readonly mark: string };
41
41
 
42
- /** The odd ones among headings of one depth, each with the usual side's first heading and count. */
43
- const oddAtDepth = (doc: ProseDocument, judged: readonly Judged[]): Finding[] => {
42
+ const LOWER_CASE = /\p{Ll}/u;
43
+ /** A word of this many capitals is a word set in capitals, not only an acronym (AGENCY, DATES; not FAQ). */
44
+ const CAPITALS_WORD = /\p{Lu}{4,}/u;
45
+
46
+ /**
47
+ * Whether a heading is set in capitals ("AGENCY:", "FOR FURTHER INFORMATION CONTACT:"). A notice's captions are one kind of
48
+ * heading and its sections in ordinary case ("Footnotes") another, so the two are compared apart.
49
+ */
50
+ export const isCapitalsHeading = (heading: string): boolean => !LOWER_CASE.test(heading) && CAPITALS_WORD.test(heading);
51
+
52
+ /** Headings compared with one another: the same depth, and the same case (capitals or ordinary). */
53
+ const kindOf = (entry: Judged): string => `${String(entry.heading.depth)}:${String(isCapitalsHeading(entry.heading.text))}`;
54
+
55
+ /** The odd ones among headings of one kind, each with the usual side's first heading and count. */
56
+ const oddOfKind = (doc: ProseDocument, judged: readonly Judged[]): Finding[] => {
44
57
  if (judged.length < MIN_HEADINGS) return [];
45
58
  const odd = minorityWithin(judged, (entry) => entry.mark !== "", MINORITY_PERCENT);
46
59
  const usual = judged.filter((entry) => !odd.includes(entry));
@@ -56,9 +69,9 @@ const oddAtDepth = (doc: ProseDocument, judged: readonly Judged[]): Finding[] =>
56
69
  };
57
70
 
58
71
  /**
59
- * Headings that end with a colon or a full stop where most headings of the same depth do not, or the other way round. Headings
60
- * of one depth are one kind of heading; a depth of labels ("Optional:") is its own way. The page title (one top-level heading
61
- * that opens the document) is a name and is not compared.
72
+ * Headings that end with a colon or a full stop where most headings of the same depth and case do not, or the other way round.
73
+ * Headings of one depth are one kind of heading; a depth of labels ("Optional:") is its own way, and so are captions set in
74
+ * capitals. The page title (one top-level heading that opens the document) is a name and is not compared.
62
75
  */
63
76
  export const headingEndMark: Detector = (doc, options): Finding[] => {
64
77
  const words = (options.lexicon ?? []).map((entry) => entry.pattern);
@@ -70,12 +83,12 @@ export const headingEndMark: Detector = (doc, options): Finding[] => {
70
83
  const mark = endMarkOf(heading.text, words);
71
84
  return mark === undefined ? [] : [{ heading, mark }];
72
85
  });
73
- const depths = [...new Set(judged.map((entry) => entry.heading.depth))];
74
- return depths
75
- .flatMap((depth) =>
76
- oddAtDepth(
86
+ const kinds = [...new Set(judged.map(kindOf))];
87
+ return kinds
88
+ .flatMap((kind) =>
89
+ oddOfKind(
77
90
  doc,
78
- judged.filter((entry) => entry.heading.depth === depth),
91
+ judged.filter((entry) => kindOf(entry) === kind),
79
92
  ),
80
93
  )
81
94
  .toSorted((left, right) => Number(left.values["offset"]) - Number(right.values["offset"]));