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
@@ -13,6 +13,9 @@ import { escapeRegExp } from "../orthography.ts";
13
13
  * 人事部(以下「HR」という。) 括弧の中が定義の語と略語だけ
14
14
  * overnight reverse repurchase agreement (ON RRP) 括弧の中が空白で繋いだ略語だけで、前の名前から文字が順に拾える
15
15
  * Partnership On Wide Energy and Resources Resilience Asia (POWERR Asia) 括弧の中が略語と添えた語で、前の名前の頭文字と揃う
16
+ * End User Technical Advisory Board (“End User TAB”) 括弧の中が名前の頭の語と略語で、前の名前の頭文字と揃う
17
+ * Special Interest Groups, or SIGs 名前の後ろの読点と言い換えの語(語彙表の definition-alternative)の後ろで、名前の頭文字と揃う
18
+ * 複数形の s を付けた略語(SIGs)の展開は、s の無い略語(SIG)の展開でもある。
16
19
  * 括弧と略語の間には、引用符((“MNDA”)、(「MNDA」))と空白だけを許す。
17
20
  */
18
21
  const WRAP = String.raw`[\s"“”'‘’「」『』]*`;
@@ -37,11 +40,14 @@ const DEFINITION_REACH = 60;
37
40
  /** 定義の語どうし、定義の語と略語の間に来てよいもの(以下、HR)。英字が続けば語の途中((theSLA))。 */
38
41
  const MARKER_GAP = String.raw`(?![A-Za-z])[\s、,]*`;
39
42
 
43
+ /** 複数形の略語の終わりの s(SIGs)。頭文字と比べる文字ではない。 */
44
+ const PLURAL_END = /(?<=[A-Z])s$/u;
45
+
40
46
  /**
41
47
  * 角括弧は引用の印にも使う([IANA]、[1])。直前の語のうち大文字で始まる語の頭文字が
42
48
  * 略語と揃うときだけ展開と見なす。見る語は略語の文字数の 2 倍まで(and や of を挟むため)。
43
49
  */
44
- const lettersOf = (acronym: string): string => acronym.replaceAll(/[&-]/gu, "");
50
+ const lettersOf = (acronym: string): string => acronym.replaceAll(/[&-]/gu, "").replace(PLURAL_END, "");
45
51
 
46
52
  const initialsOf = (words: readonly string[]): string =>
47
53
  words
@@ -92,16 +98,20 @@ const isNamedBeforeAt = (body: string, acronym: string, at: number): boolean =>
92
98
  return namesAcronym(named.groups?.["name"] ?? "", acronym);
93
99
  };
94
100
 
95
- /** 言語パッケージの語彙表から読む、括弧の中で略語の前に書く語(以下、hereinafter)と後ろに書く語(という)。 */
96
- export type DefinitionWords = { readonly markers: readonly string[]; readonly verbs: readonly string[] };
101
+ /**
102
+ * 言語パッケージの語彙表から読む、括弧の中で略語の前に書く語(以下、hereinafter)と後ろに書く語(という)、名前の後ろの読点に続けて
103
+ * 略語の前に書く言い換えの語(Special Interest Groups, or SIGs の or)。
104
+ */
105
+ export type DefinitionWords = { readonly markers: readonly string[]; readonly verbs: readonly string[]; readonly alternatives?: readonly string[] };
97
106
 
98
- type DefinitionPatterns = { readonly opened: RegExp; readonly closes: RegExp };
107
+ type DefinitionPatterns = { readonly opened: RegExp; readonly closes: RegExp; readonly alternative: RegExp };
99
108
 
100
109
  const oneOf = (words: readonly string[]): string => (words.length === 0 ? "(?!)" : words.map(escapeRegExp).join("|"));
101
110
 
102
111
  const definitionPatterns = (words: DefinitionWords): DefinitionPatterns => ({
103
112
  opened: new RegExp(String.raw`[((]\s*(?<markers>(?:(?:${oneOf(words.markers)})${MARKER_GAP})*)${WRAP}(?<![A-Za-z])$`, "iu"),
104
113
  closes: new RegExp(String.raw`^${WRAP}(?<verb>(?:${oneOf(words.verbs)})[。.]?)?${WRAP}[))]`, "iu"),
114
+ alternative: new RegExp(String.raw`[,,、]\s*(?:${oneOf(words.alternatives ?? [])})\s*["“'‘]?$`, "iu"),
105
115
  });
106
116
 
107
117
  /**
@@ -166,12 +176,46 @@ const isQualifiedAt = (body: string, acronym: string, at: number): boolean => {
166
176
  return spellsOut(name.endsWith(words) ? name.slice(0, -words.length) : name, acronym);
167
177
  };
168
178
 
179
+ /** 括弧の中で略語の前に置いた、大文字で始まる語((“End User TAB”) の End User)。 */
180
+ const PREFIX = new RegExp(String.raw`[((]${WRAP}(?<words>(?:[A-Z][a-z]+ )+)$`, "u");
181
+
182
+ /**
183
+ * 括弧の中が、前の名前の頭の語と略語だけの形(End User Technical Advisory Board (“End User TAB”))。添えた語が括弧の前の名前にあり、
184
+ * 名前の頭文字が略語と揃うときだけ展開と見なす。名前に無い語を添えた括弧(Review Board (“Community CRB”))は別の名前。
185
+ */
186
+ const isPrefixedAt = (body: string, acronym: string, at: number): boolean => {
187
+ const prefix = PREFIX.exec(body.slice(Math.max(0, at - DEFINITION_REACH), at));
188
+ if (prefix === null || !CLOSES.test(body.slice(at + acronym.length, at + acronym.length + NEAR))) return false;
189
+ const name = body.slice(0, at - prefix[0].length);
190
+ const words = (prefix.groups?.["words"] ?? "").trim();
191
+ return name.slice(-DEFINITION_REACH).includes(words) && spellsOut(name, acronym);
192
+ };
193
+
194
+ /** 引用符で囲んで書き終えた名前(‘abstract syntax tree’)。小文字の語でも、囲みが名前の始まりと終わりを決める。 */
195
+ const QUOTED_NAME_END = /(?:“(?<curly>[^“”\n]{1,60})”|‘(?<single>[^‘’\n]{1,60})’|"(?<straight>[^"\n]{1,60})")$/u;
196
+
197
+ /** 名前の後ろの読点と言い換えの語に続く略語(Special Interest Groups, or SIGs、‘abstract syntax tree’, or ‘AST’)。名前の頭文字が略語と揃うときだけ。 */
198
+ const isAlternativeAt = (patterns: DefinitionPatterns, body: string, acronym: string, at: number): boolean => {
199
+ const joined = patterns.alternative.exec(body.slice(Math.max(0, at - DEFINITION_REACH), at));
200
+ if (joined === null) return false;
201
+ const name = body.slice(0, at - joined[0].length);
202
+ const groups = QUOTED_NAME_END.exec(name)?.groups;
203
+ const quoted = groups?.["curly"] ?? groups?.["single"] ?? groups?.["straight"];
204
+ return spellsOut(name, acronym) || (quoted !== undefined && namesAcronym(quoted, acronym));
205
+ };
206
+
169
207
  const isBracketedAt = (body: string, acronym: string, at: number): boolean => {
170
208
  const after = body.slice(at + acronym.length, at + acronym.length + NEAR);
171
209
  const before = body.slice(Math.max(0, at - NEAR), at);
172
210
  if (OPENS.test(after) || (OPENED.test(before) && CLOSES.test(after))) return true;
173
211
  if (SQUARE_OPENED.test(before) && SQUARE_CLOSES.test(after) && spellsOut(body.slice(0, at), acronym)) return true;
174
- return isSeparatedAt(body, acronym, at) || isNamedBeforeAt(body, acronym, at) || isJointBracketedAt(body, acronym, at) || isQualifiedAt(body, acronym, at);
212
+ return (
213
+ isSeparatedAt(body, acronym, at) ||
214
+ isNamedBeforeAt(body, acronym, at) ||
215
+ isJointBracketedAt(body, acronym, at) ||
216
+ isQualifiedAt(body, acronym, at) ||
217
+ isPrefixedAt(body, acronym, at)
218
+ );
175
219
  };
176
220
 
177
221
  /**
@@ -358,5 +402,9 @@ export type ExpandedAt = (body: string, acronym: string, at: number) => boolean;
358
402
  /** body の at にある略語が、その場で展開・定義されているか。語彙表から一度だけ組み立てて、略語ごとに呼ぶ。 */
359
403
  export const expansionAt = (words: DefinitionWords): ExpandedAt => {
360
404
  const patterns = definitionPatterns(words);
361
- return (body, acronym, at) => isBracketedAt(body, acronym, at) || isDefinedAt(patterns, body, acronym, at) || isEqualsDefinedAt(body, acronym, at);
405
+ return (body, acronym, at) =>
406
+ isBracketedAt(body, acronym, at) ||
407
+ isDefinedAt(patterns, body, acronym, at) ||
408
+ isAlternativeAt(patterns, body, acronym, at) ||
409
+ isEqualsDefinedAt(body, acronym, at);
362
410
  };
@@ -0,0 +1,40 @@
1
+ // Words in capitals that a document itself makes known without spelling them out: a keyword of its code, a cited venue. Pure.
2
+ import { codeFences, codeSpans, withoutCodeBlocks } from "./code-fences.ts";
3
+
4
+ type Span = { readonly start: number; readonly end: number };
5
+
6
+ /** A piece of code between spaces and brackets: a hyphen, a dot, a slash or an underscore keeps a name in one piece. */
7
+ const CODE_TOKEN = /[\w./-]+/gu;
8
+ /** A keyword: a token of letters only (select, from), not a name with parts (net-http-sspi, gsa.gov, --yjit, api_key). */
9
+ const KEYWORD = /^[A-Za-z]+$/u;
10
+ /** The text of an inline link ([text](url)) or of a reference link ([text][label]). */
11
+ const LINK_TEXT = /^\[([^\]]*)\][([]/u;
12
+ /** Capitals followed by a year: a venue and when it was held (FOSDEM 2024). */
13
+ const VENUE_YEAR = /(?<![\w&])([A-Z][A-Z\d]+) (?:19|20)\d{2}(?!\d)/gu;
14
+
15
+ /**
16
+ * The keywords a document's code (fenced blocks and inline code) writes in lower case, in capitals. Prose that writes a
17
+ * keyword of that code in capitals (a SELECT, the WHERE clause, with select and where in the code) names the keyword; it is
18
+ * not an acronym. A word the code too writes in capitals (`TTS`) is the acronym set as code, and gives nothing.
19
+ */
20
+ export const codeWords = (source: string): Set<string> => {
21
+ const blocks = codeFences(source).flatMap((fence) => fence.lines);
22
+ const inline = codeSpans(withoutCodeBlocks(source)).map((span) => span.text);
23
+ const tokens = [...blocks, ...inline].flatMap((code) => code.match(CODE_TOKEN) ?? []);
24
+ return new Set(tokens.filter((token) => KEYWORD.test(token) && token !== token.toUpperCase()).map((token) => token.toUpperCase()));
25
+ };
26
+
27
+ /**
28
+ * Capitals followed by a year in a link's text (([Jane Roe, FOSDEM 2024, 18:10](https://…))): the venue of a cited talk or
29
+ * paper, as a reference list names one, and the link leads to it. Outside a link, a year after capitals is not read so.
30
+ */
31
+ export const citedVenues = (source: string, links: readonly Span[]): Set<string> =>
32
+ new Set(
33
+ links.flatMap((link) => {
34
+ const text = LINK_TEXT.exec(source.slice(link.start, link.end))?.[1] ?? "";
35
+ return [...text.matchAll(VENUE_YEAR)].flatMap((match) => (match[1] === undefined ? [] : [match[1]]));
36
+ }),
37
+ );
38
+
39
+ /** Both: the capitals a document makes known, which undefined-acronym does not ask to spell out. */
40
+ export const knownByDocument = (source: string, links: readonly Span[]): string[] => [...codeWords(source), ...citedVenues(source, links)];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * 外のページへのリンクを 1 行に 1 つ並べた一覧(参考の一覧、謝辞)の、リンクの文字。リンク先のページの題名
3
+ * (- [NASA Fprime AI Policy](https://…)、- [User Timing API - Web APIs | MDN](https://…))で、書き手が展開を書き足せない。
4
+ * 文の中のリンク(following [NIST SP 800-61](https://…), as …)は書き手の言葉なので、略語をそのまま数える。
5
+ * 文書の中や手元のファイルへのリンク([README](./README.md))も題名ではない。
6
+ */
7
+
8
+ type Span = { readonly start: number; readonly end: number };
9
+
10
+ const EXTERNAL = /^<?https?:\/\//iu;
11
+ const TEXT_END = "](";
12
+ /** リンクの前に書いてよいもの: 行頭の空白と、箇条書きの印。 */
13
+ const LINE_HEAD = /^[ \t]*(?:(?:[-*+]|\d+[.)])[ \t]+)?$/u;
14
+ /** リンクの後ろに書いてよいもの: 行末までの空白と句読点。 */
15
+ const LINE_TAIL = /^[ \t.,;。、]*(?:\n|$)/u;
16
+
17
+ /** リンクの文字の範囲。[文字](行き先) の形で、行き先が外のページのものだけ。 */
18
+ const externalTextOf = (source: string, link: Span): Span | undefined => {
19
+ const written = source.slice(link.start, link.end);
20
+ const end = written.lastIndexOf(TEXT_END);
21
+ if (!written.startsWith("[") || end === -1 || !EXTERNAL.test(written.slice(end + TEXT_END.length))) return undefined;
22
+ return { start: link.start + 1, end: link.start + end };
23
+ };
24
+
25
+ const standsAlone = (source: string, link: Span): boolean => {
26
+ const lineStart = source.lastIndexOf("\n", link.start - 1) + 1;
27
+ const lineEnd = source.indexOf("\n", link.end);
28
+ const tail = lineEnd === -1 ? source.slice(link.end) : source.slice(link.end, lineEnd + 1);
29
+ return LINE_HEAD.test(source.slice(lineStart, link.start)) && LINE_TAIL.test(tail);
30
+ };
31
+
32
+ /** 1 行に 1 つ並べた外のページへのリンクの、文字の範囲。位置は source の上。 */
33
+ export const linkTitleSpans = (source: string, links: readonly Span[]): Span[] =>
34
+ links.flatMap((link) => {
35
+ const text = externalTextOf(source, link);
36
+ return text !== undefined && standsAlone(source, link) ? [text] : [];
37
+ });
38
+
39
+ /** 語だけの箇条書きの項目(- GPL)と、その下に入れ子にした、外のページへのリンクだけの項目( - [GNU General Public License …](https://…))。 */
40
+ const TERM_ITEM = /^(?<indent>[ \t]*)(?:[-*+]|\d+[.)])[ \t]+(?<term>[A-Z][A-Za-z\d&-]*[A-Z\d])[ \t]*$/u;
41
+ const LINK_ITEM = /^(?<indent>[ \t]*)(?:[-*+]|\d+[.)])[ \t]+\[(?<title>[^\]\n]+)\]\(<?https?:\/\/[^)\s]+>?\)[ \t]*$/u;
42
+ /** 題名の名前の終わり。サイトの名前を添える区切り( | Open Source Initiative、 — CC BY 4.0)。 */
43
+ const TITLE_PART_END = /\s[|—–-]\s/u;
44
+ const CAPITALIZED = /^[A-Z]/u;
45
+
46
+ const wordsOf = (text: string): string[] => text.split(/[\s-]+/u).filter((word) => word !== "");
47
+
48
+ /** 題名が語そのものを含む(About the WTFPL、… — CC BY 4.0)か、題名の名前の大文字で始まる語の頭文字が語の字で終わる(GNU General Public License)。 */
49
+ const titleNames = (title: string, term: string): boolean => {
50
+ const termWords = wordsOf(term.toUpperCase());
51
+ const titleWords = wordsOf(title.toUpperCase());
52
+ const contains = titleWords.some((_, start) => termWords.every((word, offset) => titleWords[start + offset] === word));
53
+ const initials = wordsOf(title.split(TITLE_PART_END)[0] ?? "")
54
+ .filter((word) => CAPITALIZED.test(word))
55
+ .map((word) => word.charAt(0))
56
+ .join("");
57
+ return contains || initials.endsWith(term.replaceAll(/[&-]/gu, ""));
58
+ };
59
+
60
+ /**
61
+ * 名前を並べた一覧で、語だけの項目のすぐ下に、その語を名指す外のページへのリンクを入れ子にした語(ライセンスの一覧の GPL、WTFPL)。
62
+ * 語はリンク先のページの名前で、読み手はリンクから中身に行ける。題名が語を名指さないリンク(- AWS / - [Console](…))では数えない。
63
+ */
64
+ export const linkedListTerms = (source: string): Set<string> => {
65
+ const lines = source.split(/\r?\n/u);
66
+ return new Set(
67
+ lines.flatMap((line, index) => {
68
+ const term = TERM_ITEM.exec(line)?.groups;
69
+ const link = LINK_ITEM.exec(lines[index + 1] ?? "")?.groups;
70
+ if (term?.["term"] === undefined || link?.["title"] === undefined) return [];
71
+ const nested = (link["indent"] ?? "").length > (term["indent"] ?? "").length;
72
+ return nested && titleNames(link["title"], term["term"]) ? [term["term"]] : [];
73
+ }),
74
+ );
75
+ };
@@ -0,0 +1,44 @@
1
+ // Acronyms a sentence about abbreviations spells out in words (the abbreviation DOB … spell out the field to date of birth),
2
+ // and the other capitalisations of an acronym that a text writes (TCoP beside TCOP). Pure; the mention words come from the
3
+ // abbreviation-mention lexicon.
4
+ import { escapeRegExp } from "../orthography.ts";
5
+
6
+ const ACRONYM = /(?<![\p{L}\p{N}])[A-Z][A-Z&-]*[A-Z](?![\p{L}\p{N}])/gu;
7
+ /** A word of two letters or more: the letters of a dotted form (B.B.C.) spell nothing out. */
8
+ const LATIN_WORD = /[A-Za-z]{2,}/gu;
9
+ const CAPITAL = /\p{Lu}/gu;
10
+ /** A capitalisation of an acronym keeps at least this many capitals (TCoP); fewer is a word (Tcop). */
11
+ const MIN_CAPITALS = 2;
12
+
13
+ const mentionsAbbreviation = (sentence: string, mentions: readonly string[]): boolean => {
14
+ const lowered = sentence.toLowerCase();
15
+ return mentions.some((mention) => lowered.includes(mention.toLowerCase()));
16
+ };
17
+
18
+ /** Whether some run of consecutive words, other than the acronym itself, has the acronym's letters as its initials. */
19
+ const spellsOutInWords = (sentence: string, acronym: string): boolean => {
20
+ const letters = acronym.replaceAll(/[&-]/gu, "").toLowerCase();
21
+ const words = (sentence.match(LATIN_WORD) ?? []).filter((word) => word !== acronym.replaceAll(/[&-]/gu, ""));
22
+ return words.some(
23
+ (_, start) =>
24
+ words
25
+ .slice(start, start + letters.length)
26
+ .map((word) => word.charAt(0).toLowerCase())
27
+ .join("") === letters,
28
+ );
29
+ };
30
+
31
+ /** The acronyms that a sentence naming an abbreviation also writes out in full. */
32
+ export const spelledOutAcronyms = (sentences: readonly string[], mentions: readonly string[]): Set<string> =>
33
+ new Set(
34
+ sentences
35
+ .filter((sentence) => mentionsAbbreviation(sentence, mentions))
36
+ .flatMap((sentence) => (sentence.match(ACRONYM) ?? []).filter((acronym) => spellsOutInWords(sentence, acronym))),
37
+ );
38
+
39
+ /** The other ways the text capitalises an acronym (TCoP for TCOP, TCOP for TCoP), each with two capitals or more. */
40
+ export const caseVariantsIn = (text: string, acronym: string): string[] => {
41
+ const written = new RegExp(String.raw`(?<![\p{L}\p{N}])${escapeRegExp(acronym)}(?![\p{L}\p{N}])`, "giu");
42
+ const variants = [...text.matchAll(written)].map((match) => match[0]);
43
+ return [...new Set(variants)].filter((variant) => variant !== acronym && (variant.match(CAPITAL) ?? []).length >= MIN_CAPITALS);
44
+ };
@@ -12,6 +12,8 @@ type Span = { readonly start: number; readonly end: number };
12
12
  export type NameWords = {
13
13
  /** 会社名の後ろに大文字で書く法人の形(LLC、INC、SE、PTE、PTY)。 */
14
14
  readonly legalForms: readonly string[];
15
+ /** 日本の会社の形(株式会社、㈱。語彙表 company-form)。すぐ隣の英字の語は会社の名前(㈱ADEKA、DOWAホールディングス㈱)。 */
16
+ readonly companyForms: readonly string[];
15
17
  /** 名詞の前に置く限定の語(the、this、each)。文の頭で大文字になっても(The SE team)名前の語ではない。大小を問わずに照らす。 */
16
18
  readonly determiners: readonly string[];
17
19
  /** 法令・官報の引用の大文字の部分(45 CFR §164、21 USC §301、94/820/EC)。 */
@@ -44,28 +46,48 @@ export const oneOf = (words: readonly string[]): string =>
44
46
  const spansOf = (text: string, pattern: RegExp): Span[] =>
45
47
  [...text.matchAll(pattern)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
46
48
 
47
- /** 名前の語。大文字で始まり、点・& ・アポストロフィ・ハイフンを含んでよい(BorrowMoney.com、PTE.、O'Neil)。 */
48
- const NAME_WORD = String.raw`\p{Lu}[\p{L}\p{N}&.'’-]*`;
49
+ /** 名前の語。大文字か、数字に続く字で始まり(37signals)、点・& ・アポストロフィ・ハイフンを含んでよい(BorrowMoney.com、PTE.、O'Neil)。 */
50
+ const NAME_WORD = String.raw`(?:\p{Lu}|\p{N}+\p{L})[\p{L}\p{N}&.'’-]*`;
49
51
  /** 法人の形の前に並ぶ名前の語の数の上限(CNH INDUSTRIAL SOUTH DAKOTA, INC.)。文の頭まで遡って別の語を名前に入れないため。 */
50
52
  const NAME_WORDS_MAX = 5;
51
53
 
52
54
  /**
53
55
  * 名前の語のすぐ後ろ(読点を挟んでもよい)の法人の形と、その前の名前(JVLS, LLC、CPM Medical Consultants LLC、TRATON SE、
54
56
  * GitLab Singapore PTE. LTD.)。名前の語は空白だけで続くものを数え、読点で切れた先(CENTENE CORPORATION, MAYFLOWER …)は入れない。
55
- * 名前に続けて書いた括弧のすぐ後ろの形(SUNCALL(Guangzhou)CO.,LTD.)も名前の終わり。空白を挟んだ括弧(Section (A) LLC)は名前の一部ではない。形のすぐ前が限定の語なら名前ではない(The SE team)。
57
+ * 名前に続けて書いた括弧のすぐ後ろの形(SUNCALL(Guangzhou)CO.,LTD.、SUNCALL CO.,(H.K.)LTD.)も名前の終わり。日本語の文の中の「,」も区切り(JCI(THAILAND)CO.,LTD.)。空白を挟んだ括弧(Section (A) LLC)は名前の一部ではない。形のすぐ前が限定の語なら名前ではない(The SE team)。
56
58
  */
57
59
  export const companyNameSpans = (text: string, forms: readonly string[], determiners: readonly string[]): Span[] => {
58
60
  if (forms.length === 0) return [];
59
61
  const single = `${oneOf(forms)}${EDGE_AFTER}`;
60
62
  // 形を重ねて書く(PTE. LTD.、CO.,LTD.)。
61
- const form = String.raw`${single}(?:\.?,?[ \t]*${single})*`;
62
- const named = new RegExp(String.raw`${EDGE_BEFORE}(?:${NAME_WORD}[ \t]+){0,${NAME_WORDS_MAX - 1}}(?<last>${NAME_WORD})(?:,[ \t]*|[ \t]+)${form}`, "gu");
63
- const bracketed = new RegExp(String.raw`(?<=${NAME_WORD}[((][\p{L} ]+[))][ \t]*)${form}`, "gu");
63
+ const form = String.raw`${single}(?:\.?[,,]?[ \t]*${single})*`;
64
+ const named = new RegExp(String.raw`${EDGE_BEFORE}(?:${NAME_WORD}[ \t]+){0,${NAME_WORDS_MAX - 1}}(?<last>${NAME_WORD})(?:[,,][ \t]*|[ \t]+)${form}`, "gu");
65
+ const bracketed = new RegExp(String.raw`(?<=${NAME_WORD}[,,]?[((][\p{L}. ]+[))][ \t]*)${form}`, "gu");
64
66
  const determiner = new Set(determiners.map((word) => word.toLowerCase()));
65
67
  const names = [...text.matchAll(named)].filter((match) => !determiner.has((match.groups?.["last"] ?? "").toLowerCase()));
66
68
  return [...names.map((match) => ({ start: match.index, end: match.index + match[0].length })), ...spansOf(text, bracketed)];
67
69
  };
68
70
 
71
+ /** 日本の会社の名前の英字の語(ADEKA、DOWA)。英字の語と形のあいだに書く名前の続きの片仮名(DOWAホールディングス㈱ の ホールディングス)。 */
72
+ const LATIN_NAME = "[A-Za-zA-Za-z][A-Za-zA-Za-z0-90-9&&]*";
73
+ const KATAKANA_TAIL = "[ァ-ヺー・]*";
74
+
75
+ /** 英字だけの形(英語の Ltd)は英字の語に続けて書かれず、続いて見えれば語の一部。漢字か片仮名を含む形だけを読む。 */
76
+ const NOT_LATIN = /[^\p{Script=Latin}\p{P}\s]/u;
77
+
78
+ /**
79
+ * 日本の会社の形のすぐ後ろの英字の語(㈱ADEKA、株式会社ADEKA)と、片仮名を挟んですぐ前の英字の語(ADEKA株式会社、
80
+ * DOWAホールディングス㈱)。名前の英字で、説明を待つ略語ではない。範囲は英字の語だけ。
81
+ */
82
+ export const japaneseCompanyNameSpans = (text: string, forms: readonly string[]): Span[] => {
83
+ const japanese = forms.filter((form) => NOT_LATIN.test(form));
84
+ if (japanese.length === 0) return [];
85
+ const form = oneOf(japanese);
86
+ const after = new RegExp(`(?<=${form})${LATIN_NAME}`, "gu");
87
+ const before = new RegExp(`(?<![A-Za-zA-Za-z])${LATIN_NAME}(?=${KATAKANA_TAIL}${form})`, "gu");
88
+ return [...spansOf(text, after), ...spansOf(text, before)];
89
+ };
90
+
69
91
  /** 通貨の記号に付けた大文字(USD$、AU$10、US$ 5)。国や通貨の印で、略語ではない。 */
70
92
  const CURRENCY_PREFIX = new RegExp(String.raw`${EDGE_BEFORE}\p{Lu}{1,3}(?=[$€£¥])`, "gu");
71
93
 
@@ -108,6 +130,7 @@ export const nameSpansOf =
108
130
  (words: NameWords) =>
109
131
  (text: string): Span[] => [
110
132
  ...companyNameSpans(text, words.legalForms, words.determiners),
133
+ ...japaneseCompanyNameSpans(text, words.companyForms),
111
134
  ...currencySymbolSpans(text),
112
135
  ...citationSpans(text, words.citationSeries),
113
136
  ...carrierListSpans(text, words.carriers),
@@ -0,0 +1,16 @@
1
+ import type { Token } from "../plugin.ts";
2
+
3
+ /** 連なりの尻の、宛先に付く語。surface はその語、start は文書全体の座標でその語の始まり。 */
4
+ export type AddresseeSuffix = { readonly surface: string; readonly start: number };
5
+
6
+ /**
7
+ * 漢字の連なり run(文書全体の座標で end に終わる)の尻が、宛先の名前に付く語(志木市役所市政情報課宛ての「宛」、御中)なら、
8
+ * その語。その語は名前の後ろに付くもので、名前の一部ではない。語の切れ目で始まるときだけ(宛ての語の頭が「宛」)。
9
+ * 折り返しをまたぐ語(御\n中)は span が surface より長いので、end から字数を引かず、end の直前の字を覆う語の始まりを使う。
10
+ */
11
+ export const trailingAddressee = (tokens: readonly Token[], end: number, run: string, suffixes: readonly string[]): AddresseeSuffix | undefined => {
12
+ const suffix = suffixes.find((word) => word !== "" && run.length > word.length && run.endsWith(word));
13
+ if (suffix === undefined) return undefined;
14
+ const token = tokens.find((candidate) => candidate.span.start < end && end <= candidate.span.end);
15
+ return token !== undefined && token.surface.startsWith(suffix) ? { surface: suffix, start: token.span.start } : undefined;
16
+ };
@@ -0,0 +1,39 @@
1
+ import type { Token } from "../plugin.ts";
2
+
3
+ /**
4
+ * 宛名の並び(各国公私立高等専門学校長、公益財団法人日本博物館協会会長)の、名前の外の語。頭の「各」(語彙表 addressee-prefix)と、
5
+ * 尻の役職(addressee-title: 長、会長、教育長)。endings は組織の名前を閉じる語(organisation-unit)、forms は法人格(organisation-form)。
6
+ */
7
+ export type AddresseeWords = {
8
+ readonly prefixes: readonly string[];
9
+ readonly titles: readonly string[];
10
+ readonly endings: readonly string[];
11
+ readonly forms: readonly string[];
12
+ };
13
+
14
+ /** 組織の語の前に要る字数。1 字なら、普通の語の一部(本部、学校)と見分けられない。 */
15
+ const MIN_BODY_LENGTH = 2;
16
+
17
+ const charLength = (text: string): number => [...text].length;
18
+
19
+ /** 名前が組織の語(2 字以上の名の後ろの協会、学校)か法人格(独立行政法人)で閉じるか。 */
20
+ export const endsInOrganisation = (name: string, words: AddresseeWords): boolean =>
21
+ words.forms.some((form) => name.endsWith(form)) ||
22
+ words.endings.some((unit) => name.endsWith(unit) && charLength(name) - charLength(unit) >= MIN_BODY_LENGTH);
23
+
24
+ /** 尻の役職のうち、残りが組織の名前で閉じる最も長いもの(機構長 > 長)。役職だけの連なりや、組織で閉じないもの(延長、成長)は undefined。 */
25
+ export const trailingTitle = (run: string, words: AddresseeWords): string | undefined =>
26
+ words.titles
27
+ .filter((title) => run.length > title.length && run.endsWith(title) && endsInOrganisation(run.slice(0, run.length - title.length), words))
28
+ .reduce<string | undefined>((longest, title) => (title.length > (longest?.length ?? 0) ? title : longest), undefined);
29
+
30
+ /**
31
+ * 連なり(文書全体の座標で start から始まる)の頭の「各」の語。その語が連なりの頭にあり、残り(name: 役職を外した連なり)が
32
+ * 組織の名前で閉じるときだけ。各国の「各」のような語の一部は、解析が別の語に分けたときしか外さない。
33
+ */
34
+ export const leadingPrefix = (tokens: readonly Token[], start: number, name: string, words: AddresseeWords): Token | undefined => {
35
+ const token = tokens.find((candidate) => candidate.span.start === start);
36
+ if (token === undefined || !words.prefixes.includes(token.surface)) return undefined;
37
+ const rest = name.slice(token.surface.length);
38
+ return name.startsWith(token.surface) && rest !== "" && endsInOrganisation(rest, words) ? token : undefined;
39
+ };
@@ -13,6 +13,7 @@ const countWordsOf = (doc: ProseDocument): CountWords => ({
13
13
  frames: patternsOf(doc, "count-frame"),
14
14
  hedgesBefore: patternsOf(doc, "count-hedge", "before"),
15
15
  hedgesAfter: patternsOf(doc, "count-hedge", "after"),
16
+ titles: patternsOf(doc, "count-title"),
16
17
  });
17
18
 
18
19
  const memberGroup = (doc: ProseDocument, group: string): string[] =>
@@ -1,12 +1,15 @@
1
1
  import type { Detector, Finding, Lexicon, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
2
2
  import { quotedIn } from "../quoted-span.ts";
3
3
  import { followsInlineCode } from "./code-before.ts";
4
+ import { isNamedStep, plainStepKeys } from "./graded-step.ts";
4
5
 
5
6
  /**
6
7
  * 比べる相手の無い比較(より良い結果、さらに高速に、The new engine is faster.)。何より良いのか、何より速いのかが書かれていない。
7
8
  * 語は語彙表 comparative-baseline が言う。group marker は日本語の比べる副詞(より、さらに)、more は英語の比べる語、comparative は比べた形の語
8
9
  * (faster、better)、baseline は相手を言う語(従来、以前、than、previous)、exempt は比較でない決まった言い方(より多くの、より詳しく)、
9
10
  * condition は比較を条件や仮定の下に置く語(使うと、if、would)。条件を書いた比較は、その条件の無い場合と比べている。
11
+ * beyond は比べた形のすぐ前で、いま述べたものを越えると言う語(even better、still faster)。相手はその直前に書いてある。
12
+ * aim は比べた語の後ろで、今より良くする目当てを言う語(より良い社会、より良いものにする)。比べる相手は今の状態。
10
13
  * 同じ文か前の二文に相手を言う語があれば、相手は書いてある。
11
14
  */
12
15
 
@@ -17,6 +20,8 @@ export type ComparativeLists = {
17
20
  readonly baselines: readonly string[];
18
21
  readonly exempt: ReadonlySet<string>;
19
22
  readonly conditions: ReadonlySet<string>;
23
+ readonly beyond: ReadonlySet<string>;
24
+ readonly aims: ReadonlySet<string>;
20
25
  };
21
26
 
22
27
  export type BareComparative = { readonly first: Token; readonly last: Token };
@@ -44,13 +49,35 @@ const isGradable = (tokens: readonly Token[], at: number): boolean => {
44
49
  /** 比べる副詞が語の頭に立つか。前が助詞・記号・接続の語か文の頭のときだけ(「学年だより等」の「より」は語の一部)。 */
45
50
  const OPENS_WORD = new Set(["ADP", "PUNCT", "SCONJ", "CCONJ", "ADV"]);
46
51
 
47
- /** 日本語: 副詞の「より」「さらに」の直後の、程度を言える語。比較の決まった言い方(より多くの)は除く。 */
52
+ /** 語から続く語をつないだもの(もの、ものに、ものにする)と、それぞれの後ろの語の位置。 */
53
+ const MAX_AIM_TOKENS = 3;
54
+ const runsFrom = (tokens: readonly Token[], at: number): { readonly run: string; readonly after: number }[] =>
55
+ tokens
56
+ .slice(at, at + MAX_AIM_TOKENS)
57
+ .reduce<{ run: string; after: number }[]>(
58
+ (runs, token, index) => [...runs, { run: `${runs.at(-1)?.run ?? ""}${token.surface}`, after: at + index + 1 }],
59
+ [],
60
+ );
61
+
62
+ /** 続く語に名詞が付いて、より長い語の頭になっているか(社会保障の「社会」)。 */
63
+ const headsCompound = (tokens: readonly Token[], after: number): boolean => {
64
+ const [last, next] = [tokens[after - 1], tokens[after]];
65
+ return last?.pos === "NOUN" && next?.pos === "NOUN" && last.span.end === next.span.start;
66
+ };
67
+
68
+ /** 程度を言う語(at)の後ろが、今より良くする目当てか(より良い社会、より豊かな暮らし、より良いものにする)。 */
69
+ const namesAim = (tokens: readonly Token[], at: number, aims: ReadonlySet<string>): boolean => {
70
+ const next = tokens[at]?.pos === "NOUN" && ADJECTIVAL_TAIL.has(tokens[at + 1]?.surface ?? "") ? at + 2 : at + 1;
71
+ return runsFrom(tokens, next).some(({ run, after }) => aims.has(run) && !headsCompound(tokens, after));
72
+ };
73
+
74
+ /** 日本語: 副詞の「より」「さらに」の直後の、程度を言える語。比較の決まった言い方(より多くの)と、今より良くする目当て(より良い社会)は除く。 */
48
75
  const markedAt = (tokens: readonly Token[], at: number, lists: ComparativeLists): BareComparative | undefined => {
49
76
  const [marker, word] = [tokens[at], tokens[at + 1]];
50
77
  if (marker?.pos !== "ADV" || !lists.markers.has(marker.surface) || word === undefined || lists.exempt.has(word.surface)) return undefined;
51
78
  const previous = tokens[at - 1];
52
79
  if (previous !== undefined && !OPENS_WORD.has(previous.pos)) return undefined;
53
- return isGradable(tokens, at + 1) ? { first: marker, last: word } : undefined;
80
+ return isGradable(tokens, at + 1) && !namesAim(tokens, at + 1, lists.aims) ? { first: marker, last: word } : undefined;
54
81
  };
55
82
 
56
83
  /** 比べた形の後ろで節が終わるか。読点の後ろに形容詞が続けば、名詞の前に並べた修飾語(better, more predictable results)。 */
@@ -87,10 +114,16 @@ const predicateAt = (tokens: readonly Token[], at: number, lists: ComparativeLis
87
114
  const isConditional = (tokens: readonly Token[], found: BareComparative, conditions: ReadonlySet<string>): boolean =>
88
115
  tokens.some((token) => token.span.start < found.first.span.start && token.pos !== "CCONJ" && conditions.has(lower(token)));
89
116
 
117
+ /** 比べた形のすぐ前が、いま述べたものを越えると言う語か(performed even better)。 */
118
+ const goesBeyond = (tokens: readonly Token[], found: BareComparative, beyond: ReadonlySet<string>): boolean => {
119
+ const before = tokens.findLastIndex((token) => token.span.end <= found.first.span.start);
120
+ return beyond.has(lower(tokens[before]));
121
+ };
122
+
90
123
  export const bareComparativesIn = (tokens: readonly Token[], lists: ComparativeLists): BareComparative[] =>
91
124
  tokens
92
125
  .flatMap((_, at) => markedAt(tokens, at, lists) ?? predicateAt(tokens, at, lists) ?? [])
93
- .filter((found) => !isConditional(tokens, found, lists.conditions));
126
+ .filter((found) => !isConditional(tokens, found, lists.conditions) && !goesBeyond(tokens, found, lists.beyond));
94
127
 
95
128
  /**
96
129
  * 語が比べる相手を言う語か。語の形か原形で照らし、一字の語(旧)は語の頭だけ(旧版は相手、復旧は相手でない)。
@@ -128,6 +161,8 @@ export const listsOf = (lexicon: Lexicon): ComparativeLists => ({
128
161
  baselines: groupOf(lexicon, "baseline"),
129
162
  exempt: new Set(groupOf(lexicon, "exempt")),
130
163
  conditions: new Set(groupOf(lexicon, "condition")),
164
+ beyond: new Set(groupOf(lexicon, "beyond")),
165
+ aims: new Set(groupOf(lexicon, "aim")),
131
166
  });
132
167
 
133
168
  /** 鉤括弧の中の比較(「給与所得の確定申告がさらに簡単に!」ページ)は題や語を挙げたもので、書き手の比較ではない。 */
@@ -139,12 +174,18 @@ const isThanAfterCode = (doc: ProseDocument, found: BareComparative): boolean =>
139
174
 
140
175
  export const bareComparative: Detector = (doc): Finding[] => {
141
176
  const lists = listsOf(doc.lexicons["comparative-baseline"] ?? []);
177
+ const steps = plainStepKeys(
178
+ doc.sentences.map((sentence) => ({ tokens: sentence.tokens ?? [], quoted: quotedIn(sentence) })),
179
+ lists.markers,
180
+ isGradable,
181
+ );
142
182
  return doc.sentences.flatMap((sentence, at) => {
143
183
  const nearby = doc.sentences.slice(Math.max(0, at - BASELINE_REACH), at + 1);
144
184
  if (sentence.embeddedLanguage !== undefined || nearby.some((near) => namesBaseline(near, lists.baselines))) return [];
145
185
  const quoted = quotedIn(sentence);
146
186
  return bareComparativesIn(sentence.tokens ?? [], lists)
147
187
  .filter((found) => !quoted.some((span) => insideSpan(found, span)) && !isThanAfterCode(doc, found))
188
+ .filter((found) => !lists.markers.has(found.first.surface) || !isNamedStep(sentence.tokens ?? [], found.last, steps))
148
189
  .map((found) => ({
149
190
  rule: "",
150
191
  severity: "info",
@@ -8,6 +8,7 @@ import { quoteAt } from "./structure-tree.ts";
8
8
  import { amountColumnOf, isTotalRowGap, type BodyRow } from "../structure/total-row-blank.ts";
9
9
  import { isAmountNameLine, isTotalLine } from "../structure/total-line.ts";
10
10
  import { isTotalLabel, withoutLeadingBlankCells } from "../structure/total.ts";
11
+ import { isSpannedLabelGap } from "../structure/spanned-label-blank.ts";
11
12
 
12
13
  /** Fewer body rows than this, and one blank is as likely a choice as a gap. */
13
14
  const MIN_BODY_ROWS = 3;
@@ -67,8 +68,6 @@ const cellOffset = (cell: MarkdownNode | undefined, row: MarkdownNode | undefine
67
68
  /** Whether a row is a total, subtotal or tax row, judged from the row's source text. */
68
69
  export type IsTotalRow = (rowText: string) => boolean;
69
70
 
70
- const NO_TOTAL_ROWS: IsTotalRow = () => false;
71
-
72
71
  const rowSource = (source: string, row: MarkdownNode): string => {
73
72
  const span = spanOf(row);
74
73
  return span === undefined ? "" : source.slice(span.start, span.end);
@@ -79,30 +78,40 @@ const bodyRowOf = (source: string, row: MarkdownNode, isTotalRow: IsTotalRow): B
79
78
  cells: (row.children ?? []).map((cell) => (shows(cell) ? sourceOf(source, cell) : undefined)),
80
79
  });
81
80
 
81
+ /** How a table's rows are read: which rows are totals, and the total words that make a cell a row label (Total score). */
82
+ type TableReading = { readonly isTotalRow: IsTotalRow; readonly totalWords: readonly string[] };
83
+
84
+ const NO_TOTALS: TableReading = { isTotalRow: () => false, totalWords: [] };
85
+
82
86
  /**
83
87
  * The one blank body cell of a column whose other body rows are all filled, unless it is a total row's blank beside its
84
- * amount. Such a blank still counts as a second blank, so the rows it shares a column with stay as unreported as before.
88
+ * amount, or the second column of a label that spans two (| Total score | | 5 |). Such a blank still counts as a second
89
+ * blank, so the rows it shares a column with stay as unreported as before.
85
90
  */
86
- const columnBlank = (source: string, header: MarkdownNode, body: readonly MarkdownNode[], rows: readonly BodyRow[], column: number): Blank[] => {
91
+ const columnBlank = (source: string, table: TableRows, totalWords: readonly string[], column: number): Blank[] => {
92
+ const { header, body, rows } = table;
87
93
  const blanks = rows.flatMap((row, index) => (row.cells[column] === undefined ? [index] : []));
88
94
  const at = blanks[0];
89
95
  const row = at === undefined ? undefined : rows[at];
90
96
  if (blanks.length !== 1 || at === undefined || row === undefined) return [];
91
97
  if (isTotalRowGap(row, column, amountColumnOf(rows, header.children?.length ?? 0))) return [];
98
+ if (isSpannedLabelGap(row.cells, column, totalWords)) return [];
92
99
  const offset = cellOffset(body[at]?.children?.[column], body[at]);
93
100
  const name = sourceOf(source, header.children?.[column]);
94
101
  return offset === undefined || name === "" ? [] : [{ offset, name }];
95
102
  };
96
103
 
104
+ type TableRows = { readonly header: MarkdownNode; readonly body: readonly MarkdownNode[]; readonly rows: readonly BodyRow[] };
105
+
97
106
  /** The first column is skipped: a blank there often means "same as above". */
98
- const tableBlanksOf = (source: string, table: MarkdownNode, isTotalRow: IsTotalRow): Blank[] => {
107
+ const tableBlanksOf = (source: string, table: MarkdownNode, reading: TableReading): Blank[] => {
99
108
  const [header, ...body] = table.children ?? [];
100
109
  if (header === undefined || body.length < MIN_BODY_ROWS) return [];
101
- const rows = body.map((row) => bodyRowOf(source, row, isTotalRow));
110
+ const rows = body.map((row) => bodyRowOf(source, row, reading.isTotalRow));
102
111
  const columns = header.children?.length ?? 0;
103
112
  return Array.from({ length: columns }, (_unused, column) => column)
104
113
  .slice(1)
105
- .flatMap((column) => columnBlank(source, header, body, rows, column));
114
+ .flatMap((column) => columnBlank(source, { header, body, rows }, reading.totalWords, column));
106
115
  };
107
116
 
108
117
  /** Quoted material is someone else's: email replies the document model found, and every Markdown blockquote. */
@@ -118,8 +127,8 @@ const blocksOutsideQuotes = (source: string, type: string, replies: readonly Spa
118
127
  };
119
128
 
120
129
  /** Blank cells in every table outside quotes. */
121
- export const tableBlanks = (source: string, replies: readonly Span[] = [], isTotalRow: IsTotalRow = NO_TOTAL_ROWS): Blank[] =>
122
- blocksOutsideQuotes(source, "table", replies).flatMap((table) => tableBlanksOf(source, table, isTotalRow));
130
+ export const tableBlanks = (source: string, replies: readonly Span[] = [], reading: TableReading = NO_TOTALS): Blank[] =>
131
+ blocksOutsideQuotes(source, "table", replies).flatMap((table) => tableBlanksOf(source, table, reading));
123
132
 
124
133
  type Item = { readonly node: MarkdownNode; readonly text: string | undefined; readonly empty: boolean };
125
134
 
@@ -192,5 +201,7 @@ const totalRowOf = (doc: ProseDocument): IsTotalRow => {
192
201
  return (rowText) => isTotalLine(rowText, totals) || isAmountNameLine(rowText, totals) || isTotalLabel(withoutLeadingBlankCells(rowText), taxes);
193
202
  };
194
203
 
195
- export const emptyTableCell: Detector = findingsOf("empty-table-cell", (doc) => tableBlanks(doc.source, doc.replyQuotes ?? [], totalRowOf(doc)));
204
+ export const emptyTableCell: Detector = findingsOf("empty-table-cell", (doc) =>
205
+ tableBlanks(doc.source, doc.replyQuotes ?? [], { isTotalRow: totalRowOf(doc), totalWords: patternsOf(doc, "total-label") }),
206
+ );
196
207
  export const emptyListItem: Detector = findingsOf("empty-list-item", (doc) => listBlanks(doc.source, doc.replyQuotes ?? []));
@@ -0,0 +1,25 @@
1
+ import { asideAt } from "./open-end-names.ts";
2
+
3
+ // A vague word pinned down by the bracket right after it: 一定の事項(インボイスに記載が必要な事項), a reasonable fee (USD 50).
4
+ // The aside says what the word leaves open, so the word is not vague there. An aside that only gives the phrase a name
5
+ // (以下「措置」という, hereinafter the "Fee") pins nothing down. Pure: the words that start a name come in.
6
+
7
+ /** What may stand between the vague word and the bracket: the noun it qualifies (事項, fee), no punctuation. */
8
+ const BEFORE_BRACKET = /^[\p{L}\p{N}\p{M} ]{0,12}?(?=[((])/u;
9
+
10
+ const startsWithName = (aside: string, nameMarkers: readonly string[]): boolean => {
11
+ const lower = aside.trimStart().toLowerCase();
12
+ return nameMarkers.some((marker) => marker !== "" && lower.startsWith(marker.toLowerCase()));
13
+ };
14
+
15
+ /**
16
+ * Whether the words right after end (an offset in text) are pinned down by a bracket: at most a short noun, then an
17
+ * aside that opens and closes and holds more than a name. nameMarkers: the words that start a name (以下, hereinafter).
18
+ */
19
+ export const specifiedByBracket = (text: string, end: number, nameMarkers: readonly string[]): boolean => {
20
+ const rest = text.slice(end);
21
+ const before = BEFORE_BRACKET.exec(rest);
22
+ if (before === null) return false;
23
+ const aside = asideAt(text, end + before[0].length);
24
+ return aside !== undefined && aside.trim() !== "" && !startsWithName(aside, nameMarkers);
25
+ };