chaffjs 0.16.0 → 0.18.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 (939) hide show
  1. package/dist/announced-count.d.ts +26 -0
  2. package/dist/announced-count.d.ts.map +1 -0
  3. package/dist/announced-count.js +104 -0
  4. package/dist/announced-count.js.map +1 -0
  5. package/dist/bare-url.d.ts +14 -0
  6. package/dist/bare-url.d.ts.map +1 -0
  7. package/dist/bare-url.js +28 -0
  8. package/dist/bare-url.js.map +1 -0
  9. package/dist/baseline.d.ts +5 -0
  10. package/dist/baseline.d.ts.map +1 -1
  11. package/dist/baseline.js +16 -1
  12. package/dist/baseline.js.map +1 -1
  13. package/dist/body-section.d.ts +7 -0
  14. package/dist/body-section.d.ts.map +1 -0
  15. package/dist/body-section.js +6 -0
  16. package/dist/body-section.js.map +1 -0
  17. package/dist/calendar-number.d.ts +9 -2
  18. package/dist/calendar-number.d.ts.map +1 -1
  19. package/dist/calendar-number.js +18 -4
  20. package/dist/calendar-number.js.map +1 -1
  21. package/dist/cli-args.d.ts +4 -0
  22. package/dist/cli-args.d.ts.map +1 -1
  23. package/dist/cli-args.js +5 -0
  24. package/dist/cli-args.js.map +1 -1
  25. package/dist/cli-text.d.ts.map +1 -1
  26. package/dist/cli-text.js +8 -4
  27. package/dist/cli-text.js.map +1 -1
  28. package/dist/cli.js +33 -30
  29. package/dist/cli.js.map +1 -1
  30. package/dist/closing-numbers.d.ts +20 -0
  31. package/dist/closing-numbers.d.ts.map +1 -0
  32. package/dist/closing-numbers.js +56 -0
  33. package/dist/closing-numbers.js.map +1 -0
  34. package/dist/commands/compare.d.ts +8 -0
  35. package/dist/commands/compare.d.ts.map +1 -0
  36. package/dist/commands/compare.js +72 -0
  37. package/dist/commands/compare.js.map +1 -0
  38. package/dist/commands/eval.d.ts.map +1 -1
  39. package/dist/commands/eval.js +17 -9
  40. package/dist/commands/eval.js.map +1 -1
  41. package/dist/commands/feedback.d.ts +5 -2
  42. package/dist/commands/feedback.d.ts.map +1 -1
  43. package/dist/commands/feedback.js +11 -5
  44. package/dist/commands/feedback.js.map +1 -1
  45. package/dist/commands/test.d.ts.map +1 -1
  46. package/dist/commands/test.js +13 -13
  47. package/dist/commands/test.js.map +1 -1
  48. package/dist/commands/tree.d.ts +13 -0
  49. package/dist/commands/tree.d.ts.map +1 -1
  50. package/dist/commands/tree.js +35 -5
  51. package/dist/commands/tree.js.map +1 -1
  52. package/dist/compare/atom.d.ts +31 -0
  53. package/dist/compare/atom.d.ts.map +1 -0
  54. package/dist/compare/atom.js +4 -0
  55. package/dist/compare/atom.js.map +1 -0
  56. package/dist/compare/clock-time.d.ts +8 -0
  57. package/dist/compare/clock-time.d.ts.map +1 -0
  58. package/dist/compare/clock-time.js +65 -0
  59. package/dist/compare/clock-time.js.map +1 -0
  60. package/dist/compare/extract.d.ts +15 -0
  61. package/dist/compare/extract.d.ts.map +1 -0
  62. package/dist/compare/extract.js +58 -0
  63. package/dist/compare/extract.js.map +1 -0
  64. package/dist/compare/fact-text.d.ts +23 -0
  65. package/dist/compare/fact-text.d.ts.map +1 -0
  66. package/dist/compare/fact-text.js +47 -0
  67. package/dist/compare/fact-text.js.map +1 -0
  68. package/dist/compare/markup-atoms.d.ts +11 -0
  69. package/dist/compare/markup-atoms.d.ts.map +1 -0
  70. package/dist/compare/markup-atoms.js +23 -0
  71. package/dist/compare/markup-atoms.js.map +1 -0
  72. package/dist/compare/match.d.ts +19 -0
  73. package/dist/compare/match.d.ts.map +1 -0
  74. package/dist/compare/match.js +84 -0
  75. package/dist/compare/match.js.map +1 -0
  76. package/dist/compare/outcome.d.ts +33 -0
  77. package/dist/compare/outcome.d.ts.map +1 -0
  78. package/dist/compare/outcome.js +40 -0
  79. package/dist/compare/outcome.js.map +1 -0
  80. package/dist/compare/proper-nouns.d.ts +19 -0
  81. package/dist/compare/proper-nouns.d.ts.map +1 -0
  82. package/dist/compare/proper-nouns.js +44 -0
  83. package/dist/compare/proper-nouns.js.map +1 -0
  84. package/dist/compare/render.d.ts +9 -0
  85. package/dist/compare/render.d.ts.map +1 -0
  86. package/dist/compare/render.js +64 -0
  87. package/dist/compare/render.js.map +1 -0
  88. package/dist/compare/spans.d.ts +9 -0
  89. package/dist/compare/spans.d.ts.map +1 -0
  90. package/dist/compare/spans.js +11 -0
  91. package/dist/compare/spans.js.map +1 -0
  92. package/dist/compare/text-atoms.d.ts +24 -0
  93. package/dist/compare/text-atoms.d.ts.map +1 -0
  94. package/dist/compare/text-atoms.js +67 -0
  95. package/dist/compare/text-atoms.js.map +1 -0
  96. package/dist/compare/text.d.ts +24 -0
  97. package/dist/compare/text.d.ts.map +1 -0
  98. package/dist/compare/text.js +90 -0
  99. package/dist/compare/text.js.map +1 -0
  100. package/dist/compare/tree-atoms.d.ts +20 -0
  101. package/dist/compare/tree-atoms.d.ts.map +1 -0
  102. package/dist/compare/tree-atoms.js +58 -0
  103. package/dist/compare/tree-atoms.js.map +1 -0
  104. package/dist/compare/written-names.d.ts +8 -0
  105. package/dist/compare/written-names.d.ts.map +1 -0
  106. package/dist/compare/written-names.js +24 -0
  107. package/dist/compare/written-names.js.map +1 -0
  108. package/dist/config/load.d.ts +15 -0
  109. package/dist/config/load.d.ts.map +1 -1
  110. package/dist/config/load.js +5 -0
  111. package/dist/config/load.js.map +1 -1
  112. package/dist/config/option-problems.d.ts +16 -0
  113. package/dist/config/option-problems.d.ts.map +1 -0
  114. package/dist/config/option-problems.js +58 -0
  115. package/dist/config/option-problems.js.map +1 -0
  116. package/dist/config/read.d.ts +4 -0
  117. package/dist/config/read.d.ts.map +1 -0
  118. package/dist/config/read.js +8 -0
  119. package/dist/config/read.js.map +1 -0
  120. package/dist/config/rule-problems.d.ts +2 -4
  121. package/dist/config/rule-problems.d.ts.map +1 -1
  122. package/dist/config/rule-problems.js +7 -1
  123. package/dist/config/rule-problems.js.map +1 -1
  124. package/dist/config/style.d.ts +16 -0
  125. package/dist/config/style.d.ts.map +1 -0
  126. package/dist/config/style.js +36 -0
  127. package/dist/config/style.js.map +1 -0
  128. package/dist/config/warnings.d.ts +6 -0
  129. package/dist/config/warnings.d.ts.map +1 -0
  130. package/dist/config/warnings.js +10 -0
  131. package/dist/config/warnings.js.map +1 -0
  132. package/dist/config/write.d.ts.map +1 -1
  133. package/dist/config/write.js +17 -4
  134. package/dist/config/write.js.map +1 -1
  135. package/dist/custom/bounded-match.d.ts +15 -0
  136. package/dist/custom/bounded-match.d.ts.map +1 -0
  137. package/dist/custom/bounded-match.js +43 -0
  138. package/dist/custom/bounded-match.js.map +1 -0
  139. package/dist/custom/load.d.ts +8 -0
  140. package/dist/custom/load.d.ts.map +1 -0
  141. package/dist/custom/load.js +11 -0
  142. package/dist/custom/load.js.map +1 -0
  143. package/dist/custom/parse.d.ts +70 -0
  144. package/dist/custom/parse.d.ts.map +1 -0
  145. package/dist/custom/parse.js +215 -0
  146. package/dist/custom/parse.js.map +1 -0
  147. package/dist/custom/problems.d.ts +5 -0
  148. package/dist/custom/problems.d.ts.map +1 -0
  149. package/dist/custom/problems.js +78 -0
  150. package/dist/custom/problems.js.map +1 -0
  151. package/dist/custom/regex-safety.d.ts +11 -0
  152. package/dist/custom/regex-safety.d.ts.map +1 -0
  153. package/dist/custom/regex-safety.js +110 -0
  154. package/dist/custom/regex-safety.js.map +1 -0
  155. package/dist/custom/token-pattern.d.ts +8 -0
  156. package/dist/custom/token-pattern.d.ts.map +1 -0
  157. package/dist/custom/token-pattern.js +75 -0
  158. package/dist/custom/token-pattern.js.map +1 -0
  159. package/dist/detect.d.ts.map +1 -1
  160. package/dist/detect.js +24 -2
  161. package/dist/detect.js.map +1 -1
  162. package/dist/detectors/acronym-context.d.ts +4 -0
  163. package/dist/detectors/acronym-context.d.ts.map +1 -1
  164. package/dist/detectors/acronym-context.js +25 -4
  165. package/dist/detectors/acronym-context.js.map +1 -1
  166. package/dist/detectors/acronym-expansion.d.ts +2 -0
  167. package/dist/detectors/acronym-expansion.d.ts.map +1 -1
  168. package/dist/detectors/acronym-expansion.js +104 -1
  169. package/dist/detectors/acronym-expansion.js.map +1 -1
  170. package/dist/detectors/agreement-slip.d.ts +32 -0
  171. package/dist/detectors/agreement-slip.d.ts.map +1 -0
  172. package/dist/detectors/agreement-slip.js +137 -0
  173. package/dist/detectors/agreement-slip.js.map +1 -0
  174. package/dist/detectors/ai-phrasing.d.ts +20 -0
  175. package/dist/detectors/ai-phrasing.d.ts.map +1 -0
  176. package/dist/detectors/ai-phrasing.js +112 -0
  177. package/dist/detectors/ai-phrasing.js.map +1 -0
  178. package/dist/detectors/announced-count.d.ts +4 -0
  179. package/dist/detectors/announced-count.d.ts.map +1 -0
  180. package/dist/detectors/announced-count.js +20 -0
  181. package/dist/detectors/announced-count.js.map +1 -0
  182. package/dist/detectors/broken-link.d.ts +17 -0
  183. package/dist/detectors/broken-link.d.ts.map +1 -0
  184. package/dist/detectors/broken-link.js +66 -0
  185. package/dist/detectors/broken-link.js.map +1 -0
  186. package/dist/detectors/cited-name.d.ts.map +1 -1
  187. package/dist/detectors/cited-name.js +4 -4
  188. package/dist/detectors/cited-name.js.map +1 -1
  189. package/dist/detectors/cited-title.d.ts +11 -0
  190. package/dist/detectors/cited-title.d.ts.map +1 -0
  191. package/dist/detectors/cited-title.js +75 -0
  192. package/dist/detectors/cited-title.js.map +1 -0
  193. package/dist/detectors/concrete-evidence.d.ts +1 -1
  194. package/dist/detectors/concrete-evidence.d.ts.map +1 -1
  195. package/dist/detectors/concrete-evidence.js +2 -1
  196. package/dist/detectors/concrete-evidence.js.map +1 -1
  197. package/dist/detectors/content-morphemes.d.ts +4 -0
  198. package/dist/detectors/content-morphemes.d.ts.map +1 -0
  199. package/dist/detectors/content-morphemes.js +12 -0
  200. package/dist/detectors/content-morphemes.js.map +1 -0
  201. package/dist/detectors/contrast-frame.d.ts +17 -0
  202. package/dist/detectors/contrast-frame.d.ts.map +1 -0
  203. package/dist/detectors/contrast-frame.js +32 -0
  204. package/dist/detectors/contrast-frame.js.map +1 -0
  205. package/dist/detectors/custom.d.ts +8 -0
  206. package/dist/detectors/custom.d.ts.map +1 -0
  207. package/dist/detectors/custom.js +71 -0
  208. package/dist/detectors/custom.js.map +1 -0
  209. package/dist/detectors/dangling-figure.d.ts +4 -0
  210. package/dist/detectors/dangling-figure.d.ts.map +1 -0
  211. package/dist/detectors/dangling-figure.js +18 -0
  212. package/dist/detectors/dangling-figure.js.map +1 -0
  213. package/dist/detectors/doubled-punctuation.d.ts +9 -0
  214. package/dist/detectors/doubled-punctuation.d.ts.map +1 -0
  215. package/dist/detectors/doubled-punctuation.js +33 -0
  216. package/dist/detectors/doubled-punctuation.js.map +1 -0
  217. package/dist/detectors/doubled-word.d.ts +5 -0
  218. package/dist/detectors/doubled-word.d.ts.map +1 -1
  219. package/dist/detectors/doubled-word.js +24 -11
  220. package/dist/detectors/doubled-word.js.map +1 -1
  221. package/dist/detectors/en-shape.d.ts +0 -1
  222. package/dist/detectors/en-shape.d.ts.map +1 -1
  223. package/dist/detectors/en-shape.js +0 -235
  224. package/dist/detectors/en-shape.js.map +1 -1
  225. package/dist/detectors/enumerated-runs.d.ts +1 -1
  226. package/dist/detectors/enumerated-runs.d.ts.map +1 -1
  227. package/dist/detectors/enumerated-runs.js +15 -4
  228. package/dist/detectors/enumerated-runs.js.map +1 -1
  229. package/dist/detectors/gram-furniture.d.ts +6 -0
  230. package/dist/detectors/gram-furniture.d.ts.map +1 -0
  231. package/dist/detectors/gram-furniture.js +21 -0
  232. package/dist/detectors/gram-furniture.js.map +1 -0
  233. package/dist/detectors/gram-place.d.ts +2 -0
  234. package/dist/detectors/gram-place.d.ts.map +1 -1
  235. package/dist/detectors/gram-place.js +9 -7
  236. package/dist/detectors/gram-place.js.map +1 -1
  237. package/dist/detectors/gram-windows.d.ts +9 -0
  238. package/dist/detectors/gram-windows.d.ts.map +1 -0
  239. package/dist/detectors/gram-windows.js +27 -0
  240. package/dist/detectors/gram-windows.js.map +1 -0
  241. package/dist/detectors/heading-case.d.ts +2 -0
  242. package/dist/detectors/heading-case.d.ts.map +1 -1
  243. package/dist/detectors/heading-case.js +29 -2
  244. package/dist/detectors/heading-case.js.map +1 -1
  245. package/dist/detectors/heading-code-words.d.ts +6 -0
  246. package/dist/detectors/heading-code-words.d.ts.map +1 -0
  247. package/dist/detectors/heading-code-words.js +29 -0
  248. package/dist/detectors/heading-code-words.js.map +1 -0
  249. package/dist/detectors/heading-echo.d.ts.map +1 -1
  250. package/dist/detectors/heading-echo.js +17 -20
  251. package/dist/detectors/heading-echo.js.map +1 -1
  252. package/dist/detectors/heading-level-skip.d.ts +12 -0
  253. package/dist/detectors/heading-level-skip.d.ts.map +1 -0
  254. package/dist/detectors/heading-level-skip.js +11 -0
  255. package/dist/detectors/heading-level-skip.js.map +1 -0
  256. package/dist/detectors/heading-overlap.d.ts +13 -0
  257. package/dist/detectors/heading-overlap.d.ts.map +1 -0
  258. package/dist/detectors/heading-overlap.js +52 -0
  259. package/dist/detectors/heading-overlap.js.map +1 -0
  260. package/dist/detectors/image-alt-text.d.ts +3 -0
  261. package/dist/detectors/image-alt-text.d.ts.map +1 -0
  262. package/dist/detectors/image-alt-text.js +9 -0
  263. package/dist/detectors/image-alt-text.js.map +1 -0
  264. package/dist/detectors/index.d.ts.map +1 -1
  265. package/dist/detectors/index.js +40 -2
  266. package/dist/detectors/index.js.map +1 -1
  267. package/dist/detectors/kutoten-consistency.d.ts +24 -0
  268. package/dist/detectors/kutoten-consistency.d.ts.map +1 -0
  269. package/dist/detectors/kutoten-consistency.js +77 -0
  270. package/dist/detectors/kutoten-consistency.js.map +1 -0
  271. package/dist/detectors/lead-in.d.ts +1 -0
  272. package/dist/detectors/lead-in.d.ts.map +1 -1
  273. package/dist/detectors/lead-in.js +2 -1
  274. package/dist/detectors/lead-in.js.map +1 -1
  275. package/dist/detectors/letter-joined-name.d.ts +13 -0
  276. package/dist/detectors/letter-joined-name.d.ts.map +1 -0
  277. package/dist/detectors/letter-joined-name.js +11 -0
  278. package/dist/detectors/letter-joined-name.js.map +1 -0
  279. package/dist/detectors/lexicon-match.d.ts +4 -0
  280. package/dist/detectors/lexicon-match.d.ts.map +1 -1
  281. package/dist/detectors/lexicon-match.js +7 -2
  282. package/dist/detectors/lexicon-match.js.map +1 -1
  283. package/dist/detectors/lexicon.d.ts.map +1 -1
  284. package/dist/detectors/lexicon.js +5 -2
  285. package/dist/detectors/lexicon.js.map +1 -1
  286. package/dist/detectors/list-item.d.ts +45 -0
  287. package/dist/detectors/list-item.d.ts.map +1 -0
  288. package/dist/detectors/list-item.js +88 -0
  289. package/dist/detectors/list-item.js.map +1 -0
  290. package/dist/detectors/list-items.d.ts +31 -0
  291. package/dist/detectors/list-items.d.ts.map +1 -0
  292. package/dist/detectors/list-items.js +113 -0
  293. package/dist/detectors/list-items.js.map +1 -0
  294. package/dist/detectors/list-lead-in.d.ts +7 -0
  295. package/dist/detectors/list-lead-in.d.ts.map +1 -0
  296. package/dist/detectors/list-lead-in.js +28 -0
  297. package/dist/detectors/list-lead-in.js.map +1 -0
  298. package/dist/detectors/list-sentence.d.ts +65 -0
  299. package/dist/detectors/list-sentence.d.ts.map +1 -0
  300. package/dist/detectors/list-sentence.js +105 -0
  301. package/dist/detectors/list-sentence.js.map +1 -0
  302. package/dist/detectors/list-view.d.ts +34 -0
  303. package/dist/detectors/list-view.d.ts.map +1 -0
  304. package/dist/detectors/list-view.js +137 -0
  305. package/dist/detectors/list-view.js.map +1 -0
  306. package/dist/detectors/long-vowel.d.ts +7 -0
  307. package/dist/detectors/long-vowel.d.ts.map +1 -0
  308. package/dist/detectors/long-vowel.js +57 -0
  309. package/dist/detectors/long-vowel.js.map +1 -0
  310. package/dist/detectors/markup-finding.d.ts +6 -0
  311. package/dist/detectors/markup-finding.d.ts.map +1 -0
  312. package/dist/detectors/markup-finding.js +19 -0
  313. package/dist/detectors/markup-finding.js.map +1 -0
  314. package/dist/detectors/name-numeral.d.ts +1 -1
  315. package/dist/detectors/name-numeral.d.ts.map +1 -1
  316. package/dist/detectors/name-numeral.js +2 -7
  317. package/dist/detectors/name-numeral.js.map +1 -1
  318. package/dist/detectors/orthography.d.ts.map +1 -1
  319. package/dist/detectors/orthography.js +16 -12
  320. package/dist/detectors/orthography.js.map +1 -1
  321. package/dist/detectors/oxford-comma.d.ts +9 -0
  322. package/dist/detectors/oxford-comma.d.ts.map +1 -0
  323. package/dist/detectors/oxford-comma.js +246 -0
  324. package/dist/detectors/oxford-comma.js.map +1 -0
  325. package/dist/detectors/place-run.d.ts.map +1 -1
  326. package/dist/detectors/place-run.js +10 -6
  327. package/dist/detectors/place-run.js.map +1 -1
  328. package/dist/detectors/placeholder-text.d.ts +9 -0
  329. package/dist/detectors/placeholder-text.d.ts.map +1 -0
  330. package/dist/detectors/placeholder-text.js +18 -0
  331. package/dist/detectors/placeholder-text.js.map +1 -0
  332. package/dist/detectors/quote-around.d.ts +3 -0
  333. package/dist/detectors/quote-around.d.ts.map +1 -0
  334. package/dist/detectors/quote-around.js +8 -0
  335. package/dist/detectors/quote-around.js.map +1 -0
  336. package/dist/detectors/register.d.ts +11 -3
  337. package/dist/detectors/register.d.ts.map +1 -1
  338. package/dist/detectors/register.js +28 -9
  339. package/dist/detectors/register.js.map +1 -1
  340. package/dist/detectors/roman-numeral.d.ts +2 -0
  341. package/dist/detectors/roman-numeral.d.ts.map +1 -1
  342. package/dist/detectors/roman-numeral.js +2 -0
  343. package/dist/detectors/roman-numeral.js.map +1 -1
  344. package/dist/detectors/sentence-ending.d.ts +17 -1
  345. package/dist/detectors/sentence-ending.d.ts.map +1 -1
  346. package/dist/detectors/sentence-ending.js +13 -7
  347. package/dist/detectors/sentence-ending.js.map +1 -1
  348. package/dist/detectors/sentence-length.d.ts.map +1 -1
  349. package/dist/detectors/sentence-length.js +13 -4
  350. package/dist/detectors/sentence-length.js.map +1 -1
  351. package/dist/detectors/signals.d.ts +8 -0
  352. package/dist/detectors/signals.d.ts.map +1 -1
  353. package/dist/detectors/signals.js +94 -54
  354. package/dist/detectors/signals.js.map +1 -1
  355. package/dist/detectors/stacked-hedge.d.ts +0 -7
  356. package/dist/detectors/stacked-hedge.d.ts.map +1 -1
  357. package/dist/detectors/stacked-hedge.js +6 -3
  358. package/dist/detectors/stacked-hedge.js.map +1 -1
  359. package/dist/detectors/stray-space.d.ts +7 -0
  360. package/dist/detectors/stray-space.d.ts.map +1 -0
  361. package/dist/detectors/stray-space.js +34 -0
  362. package/dist/detectors/stray-space.js.map +1 -0
  363. package/dist/detectors/structure-tree.d.ts +6 -0
  364. package/dist/detectors/structure-tree.d.ts.map +1 -1
  365. package/dist/detectors/structure-tree.js +37 -1
  366. package/dist/detectors/structure-tree.js.map +1 -1
  367. package/dist/detectors/structure.d.ts +4 -4
  368. package/dist/detectors/structure.d.ts.map +1 -1
  369. package/dist/detectors/structure.js +7 -6
  370. package/dist/detectors/structure.js.map +1 -1
  371. package/dist/detectors/superlative-name.d.ts.map +1 -1
  372. package/dist/detectors/superlative-name.js +8 -5
  373. package/dist/detectors/superlative-name.js.map +1 -1
  374. package/dist/detectors/superlative-scope.d.ts.map +1 -1
  375. package/dist/detectors/superlative-scope.js +9 -4
  376. package/dist/detectors/superlative-scope.js.map +1 -1
  377. package/dist/detectors/token-column.d.ts +46 -0
  378. package/dist/detectors/token-column.d.ts.map +1 -0
  379. package/dist/detectors/token-column.js +95 -0
  380. package/dist/detectors/token-column.js.map +1 -0
  381. package/dist/detectors/unbalanced-bracket.d.ts +22 -0
  382. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -0
  383. package/dist/detectors/unbalanced-bracket.js +119 -0
  384. package/dist/detectors/unbalanced-bracket.js.map +1 -0
  385. package/dist/detectors/url-run-on.d.ts +9 -0
  386. package/dist/detectors/url-run-on.d.ts.map +1 -0
  387. package/dist/detectors/url-run-on.js +19 -0
  388. package/dist/detectors/url-run-on.js.map +1 -0
  389. package/dist/document-sections.d.ts +13 -0
  390. package/dist/document-sections.d.ts.map +1 -0
  391. package/dist/document-sections.js +32 -0
  392. package/dist/document-sections.js.map +1 -0
  393. package/dist/document.d.ts +11 -4
  394. package/dist/document.d.ts.map +1 -1
  395. package/dist/document.js +99 -95
  396. package/dist/document.js.map +1 -1
  397. package/dist/email-parts.d.ts +28 -0
  398. package/dist/email-parts.d.ts.map +1 -0
  399. package/dist/email-parts.js +230 -0
  400. package/dist/email-parts.js.map +1 -0
  401. package/dist/eval.d.ts +2 -1
  402. package/dist/eval.d.ts.map +1 -1
  403. package/dist/eval.js +16 -4
  404. package/dist/eval.js.map +1 -1
  405. package/dist/figure-references.d.ts +30 -0
  406. package/dist/figure-references.d.ts.map +1 -0
  407. package/dist/figure-references.js +76 -0
  408. package/dist/figure-references.js.map +1 -0
  409. package/dist/files.d.ts +2 -0
  410. package/dist/files.d.ts.map +1 -1
  411. package/dist/files.js +4 -0
  412. package/dist/files.js.map +1 -1
  413. package/dist/genre-parse.d.ts +5 -1
  414. package/dist/genre-parse.d.ts.map +1 -1
  415. package/dist/genre-parse.js +16 -3
  416. package/dist/genre-parse.js.map +1 -1
  417. package/dist/genre-suggest.d.ts.map +1 -1
  418. package/dist/genre-suggest.js +15 -1
  419. package/dist/genre-suggest.js.map +1 -1
  420. package/dist/heading-label.d.ts +22 -0
  421. package/dist/heading-label.d.ts.map +1 -0
  422. package/dist/heading-label.js +50 -0
  423. package/dist/heading-label.js.map +1 -0
  424. package/dist/in-page-nav.d.ts +4 -1
  425. package/dist/in-page-nav.d.ts.map +1 -1
  426. package/dist/in-page-nav.js +53 -18
  427. package/dist/in-page-nav.js.map +1 -1
  428. package/dist/joined-view.d.ts.map +1 -1
  429. package/dist/joined-view.js +1 -0
  430. package/dist/joined-view.js.map +1 -1
  431. package/dist/levels.d.ts +5 -1
  432. package/dist/levels.d.ts.map +1 -1
  433. package/dist/levels.js +9 -0
  434. package/dist/levels.js.map +1 -1
  435. package/dist/line-paragraphs.d.ts +8 -0
  436. package/dist/line-paragraphs.d.ts.map +1 -1
  437. package/dist/line-paragraphs.js +36 -11
  438. package/dist/line-paragraphs.js.map +1 -1
  439. package/dist/long-vowel.d.ts +35 -0
  440. package/dist/long-vowel.d.ts.map +1 -0
  441. package/dist/long-vowel.js +71 -0
  442. package/dist/long-vowel.js.map +1 -0
  443. package/dist/markdown-node.d.ts +19 -0
  444. package/dist/markdown-node.d.ts.map +1 -0
  445. package/dist/markdown-node.js +6 -0
  446. package/dist/markdown-node.js.map +1 -0
  447. package/dist/markdown-read.d.ts +17 -0
  448. package/dist/markdown-read.d.ts.map +1 -0
  449. package/dist/markdown-read.js +37 -0
  450. package/dist/markdown-read.js.map +1 -0
  451. package/dist/markup.d.ts +22 -0
  452. package/dist/markup.d.ts.map +1 -0
  453. package/dist/markup.js +180 -0
  454. package/dist/markup.js.map +1 -0
  455. package/dist/mask.d.ts.map +1 -1
  456. package/dist/mask.js +10 -16
  457. package/dist/mask.js.map +1 -1
  458. package/dist/number-name.d.ts +21 -5
  459. package/dist/number-name.d.ts.map +1 -1
  460. package/dist/number-name.js +120 -18
  461. package/dist/number-name.js.map +1 -1
  462. package/dist/opening-line.d.ts +3 -0
  463. package/dist/opening-line.d.ts.map +1 -0
  464. package/dist/opening-line.js +14 -0
  465. package/dist/opening-line.js.map +1 -0
  466. package/dist/orthography.d.ts +7 -1
  467. package/dist/orthography.d.ts.map +1 -1
  468. package/dist/orthography.js +16 -5
  469. package/dist/orthography.js.map +1 -1
  470. package/dist/page-furniture.d.ts +5 -2
  471. package/dist/page-furniture.d.ts.map +1 -1
  472. package/dist/page-furniture.js +8 -2
  473. package/dist/page-furniture.js.map +1 -1
  474. package/dist/paragraph-length.d.ts +7 -0
  475. package/dist/paragraph-length.d.ts.map +1 -0
  476. package/dist/paragraph-length.js +10 -0
  477. package/dist/paragraph-length.js.map +1 -0
  478. package/dist/plain-source.d.ts +1 -0
  479. package/dist/plain-source.d.ts.map +1 -1
  480. package/dist/plain-source.js +2 -1
  481. package/dist/plain-source.js.map +1 -1
  482. package/dist/plugin.d.ts +121 -0
  483. package/dist/plugin.d.ts.map +1 -1
  484. package/dist/profile/for-file.d.ts.map +1 -1
  485. package/dist/profile/for-file.js +3 -1
  486. package/dist/profile/for-file.js.map +1 -1
  487. package/dist/quoted-span.d.ts +0 -2
  488. package/dist/quoted-span.d.ts.map +1 -1
  489. package/dist/quoted-span.js +9 -4
  490. package/dist/quoted-span.js.map +1 -1
  491. package/dist/reasons.d.ts +3 -0
  492. package/dist/reasons.d.ts.map +1 -1
  493. package/dist/reasons.js +6 -0
  494. package/dist/reasons.js.map +1 -1
  495. package/dist/reference-lists.d.ts +3 -0
  496. package/dist/reference-lists.d.ts.map +1 -0
  497. package/dist/reference-lists.js +75 -0
  498. package/dist/reference-lists.js.map +1 -0
  499. package/dist/render/explain.d.ts +7 -1
  500. package/dist/render/explain.d.ts.map +1 -1
  501. package/dist/render/explain.js +36 -12
  502. package/dist/render/explain.js.map +1 -1
  503. package/dist/render/friendly.d.ts.map +1 -1
  504. package/dist/render/friendly.js +19 -9
  505. package/dist/render/friendly.js.map +1 -1
  506. package/dist/render/options.d.ts +7 -0
  507. package/dist/render/options.d.ts.map +1 -0
  508. package/dist/render/options.js +50 -0
  509. package/dist/render/options.js.map +1 -0
  510. package/dist/render/rules-json.d.ts +4 -1
  511. package/dist/render/rules-json.d.ts.map +1 -1
  512. package/dist/render/rules-json.js +102 -12
  513. package/dist/render/rules-json.js.map +1 -1
  514. package/dist/render/rules-table.d.ts +4 -0
  515. package/dist/render/rules-table.d.ts.map +1 -0
  516. package/dist/render/rules-table.js +70 -0
  517. package/dist/render/rules-table.js.map +1 -0
  518. package/dist/render/sarif.js +4 -4
  519. package/dist/render/sarif.js.map +1 -1
  520. package/dist/render/semantic.js +3 -3
  521. package/dist/render/semantic.js.map +1 -1
  522. package/dist/render/severity-name.d.ts +6 -0
  523. package/dist/render/severity-name.d.ts.map +1 -0
  524. package/dist/render/severity-name.js +7 -0
  525. package/dist/render/severity-name.js.map +1 -0
  526. package/dist/render/text.d.ts +7 -2
  527. package/dist/render/text.d.ts.map +1 -1
  528. package/dist/render/text.js +15 -4
  529. package/dist/render/text.js.map +1 -1
  530. package/dist/resolve-genre.d.ts +1 -1
  531. package/dist/resolve-genre.d.ts.map +1 -1
  532. package/dist/resolve-genre.js +4 -1
  533. package/dist/resolve-genre.js.map +1 -1
  534. package/dist/rule-genres.d.ts +24 -0
  535. package/dist/rule-genres.d.ts.map +1 -0
  536. package/dist/rule-genres.js +11 -0
  537. package/dist/rule-genres.js.map +1 -0
  538. package/dist/rule-guide.d.ts +54 -0
  539. package/dist/rule-guide.d.ts.map +1 -0
  540. package/dist/rule-guide.js +81 -0
  541. package/dist/rule-guide.js.map +1 -0
  542. package/dist/rule-load.d.ts.map +1 -1
  543. package/dist/rule-load.js +94 -32
  544. package/dist/rule-load.js.map +1 -1
  545. package/dist/rule-options.d.ts +50 -0
  546. package/dist/rule-options.d.ts.map +1 -0
  547. package/dist/rule-options.js +106 -0
  548. package/dist/rule-options.js.map +1 -0
  549. package/dist/run-semantic.d.ts +3 -1
  550. package/dist/run-semantic.d.ts.map +1 -1
  551. package/dist/run-semantic.js +8 -3
  552. package/dist/run-semantic.js.map +1 -1
  553. package/dist/run.d.ts +15 -0
  554. package/dist/run.d.ts.map +1 -1
  555. package/dist/run.js +57 -10
  556. package/dist/run.js.map +1 -1
  557. package/dist/semantic.d.ts +1 -1
  558. package/dist/semantic.d.ts.map +1 -1
  559. package/dist/semantic.js +10 -3
  560. package/dist/semantic.js.map +1 -1
  561. package/dist/sentence-shape.d.ts.map +1 -1
  562. package/dist/sentence-shape.js +4 -4
  563. package/dist/sentence-shape.js.map +1 -1
  564. package/dist/setting-problems.d.ts +2 -1
  565. package/dist/setting-problems.d.ts.map +1 -1
  566. package/dist/setting-problems.js +6 -1
  567. package/dist/setting-problems.js.map +1 -1
  568. package/dist/span-cut.d.ts +6 -0
  569. package/dist/span-cut.d.ts.map +1 -0
  570. package/dist/span-cut.js +22 -0
  571. package/dist/span-cut.js.map +1 -0
  572. package/dist/span-merge.d.ts +4 -0
  573. package/dist/span-merge.d.ts.map +1 -0
  574. package/dist/span-merge.js +12 -0
  575. package/dist/span-merge.js.map +1 -0
  576. package/dist/speaker-labels.d.ts +4 -0
  577. package/dist/speaker-labels.d.ts.map +1 -0
  578. package/dist/speaker-labels.js +106 -0
  579. package/dist/speaker-labels.js.map +1 -0
  580. package/dist/stray-space.d.ts +17 -0
  581. package/dist/stray-space.d.ts.map +1 -0
  582. package/dist/stray-space.js +66 -0
  583. package/dist/stray-space.js.map +1 -0
  584. package/dist/structure/aside-depth.d.ts +21 -0
  585. package/dist/structure/aside-depth.d.ts.map +1 -0
  586. package/dist/structure/aside-depth.js +65 -0
  587. package/dist/structure/aside-depth.js.map +1 -0
  588. package/dist/structure/build.d.ts +5 -1
  589. package/dist/structure/build.d.ts.map +1 -1
  590. package/dist/structure/build.js +29 -17
  591. package/dist/structure/build.js.map +1 -1
  592. package/dist/structure/closed-pairs.d.ts +8 -0
  593. package/dist/structure/closed-pairs.d.ts.map +1 -0
  594. package/dist/structure/closed-pairs.js +22 -0
  595. package/dist/structure/closed-pairs.js.map +1 -0
  596. package/dist/structure/date-range.d.ts +21 -0
  597. package/dist/structure/date-range.d.ts.map +1 -0
  598. package/dist/structure/date-range.js +45 -0
  599. package/dist/structure/date-range.js.map +1 -0
  600. package/dist/structure/known-mentions.d.ts +18 -0
  601. package/dist/structure/known-mentions.d.ts.map +1 -0
  602. package/dist/structure/known-mentions.js +78 -0
  603. package/dist/structure/known-mentions.js.map +1 -0
  604. package/dist/structure/numbering.d.ts +1 -0
  605. package/dist/structure/numbering.d.ts.map +1 -1
  606. package/dist/structure/numbering.js +11 -6
  607. package/dist/structure/numbering.js.map +1 -1
  608. package/dist/structure/of.d.ts +3 -1
  609. package/dist/structure/of.d.ts.map +1 -1
  610. package/dist/structure/of.js +5 -1
  611. package/dist/structure/of.js.map +1 -1
  612. package/dist/structure/percent-sum.d.ts +16 -0
  613. package/dist/structure/percent-sum.d.ts.map +1 -0
  614. package/dist/structure/percent-sum.js +104 -0
  615. package/dist/structure/percent-sum.js.map +1 -0
  616. package/dist/structure/quoted-number.d.ts +8 -0
  617. package/dist/structure/quoted-number.d.ts.map +1 -0
  618. package/dist/structure/quoted-number.js +34 -0
  619. package/dist/structure/quoted-number.js.map +1 -0
  620. package/dist/structure/relative-find.d.ts.map +1 -1
  621. package/dist/structure/relative-find.js +34 -46
  622. package/dist/structure/relative-find.js.map +1 -1
  623. package/dist/structure/relative-resolve.d.ts.map +1 -1
  624. package/dist/structure/relative-resolve.js +94 -42
  625. package/dist/structure/relative-resolve.js.map +1 -1
  626. package/dist/structure/runs.d.ts +2 -0
  627. package/dist/structure/runs.d.ts.map +1 -1
  628. package/dist/structure/runs.js +2 -2
  629. package/dist/structure/runs.js.map +1 -1
  630. package/dist/structure/sexp.d.ts +1 -1
  631. package/dist/structure/sexp.d.ts.map +1 -1
  632. package/dist/structure/sexp.js +18 -6
  633. package/dist/structure/sexp.js.map +1 -1
  634. package/dist/structure/total.d.ts +3 -0
  635. package/dist/structure/total.d.ts.map +1 -1
  636. package/dist/structure/total.js +2 -2
  637. package/dist/structure/total.js.map +1 -1
  638. package/dist/structure/universal.d.ts +14 -2
  639. package/dist/structure/universal.d.ts.map +1 -1
  640. package/dist/structure/universal.js +17 -2
  641. package/dist/structure/universal.js.map +1 -1
  642. package/dist/structure/wrapped-tail.d.ts +14 -7
  643. package/dist/structure/wrapped-tail.d.ts.map +1 -1
  644. package/dist/structure/wrapped-tail.js +33 -8
  645. package/dist/structure/wrapped-tail.js.map +1 -1
  646. package/dist/style-load.d.ts +4 -0
  647. package/dist/style-load.d.ts.map +1 -0
  648. package/dist/style-load.js +28 -0
  649. package/dist/style-load.js.map +1 -0
  650. package/dist/style-parse.d.ts +19 -0
  651. package/dist/style-parse.d.ts.map +1 -0
  652. package/dist/style-parse.js +60 -0
  653. package/dist/style-parse.js.map +1 -0
  654. package/dist/subheading-line.d.ts +6 -0
  655. package/dist/subheading-line.d.ts.map +1 -0
  656. package/dist/subheading-line.js +57 -0
  657. package/dist/subheading-line.js.map +1 -0
  658. package/dist/team-names.d.ts.map +1 -1
  659. package/dist/team-names.js +11 -14
  660. package/dist/team-names.js.map +1 -1
  661. package/dist/template-syntax.d.ts +17 -0
  662. package/dist/template-syntax.d.ts.map +1 -0
  663. package/dist/template-syntax.js +140 -0
  664. package/dist/template-syntax.js.map +1 -0
  665. package/dist/text-above.d.ts +19 -0
  666. package/dist/text-above.d.ts.map +1 -0
  667. package/dist/text-above.js +43 -0
  668. package/dist/text-above.js.map +1 -0
  669. package/dist/text-figures.d.ts +10 -0
  670. package/dist/text-figures.d.ts.map +1 -0
  671. package/dist/text-figures.js +131 -0
  672. package/dist/text-figures.js.map +1 -0
  673. package/dist/trailing-aside.d.ts +2 -0
  674. package/dist/trailing-aside.d.ts.map +1 -0
  675. package/dist/trailing-aside.js +53 -0
  676. package/dist/trailing-aside.js.map +1 -0
  677. package/dist/tree-walk.d.ts +18 -0
  678. package/dist/tree-walk.d.ts.map +1 -0
  679. package/dist/tree-walk.js +45 -0
  680. package/dist/tree-walk.js.map +1 -0
  681. package/genres.yaml +60 -2
  682. package/package.json +5 -3
  683. package/reference-headings.yaml +17 -0
  684. package/rules/adverb-overuse.yaml +19 -0
  685. package/rules/agentless-passive.yaml +19 -0
  686. package/rules/agreement-slip.yaml +49 -0
  687. package/rules/ai-generated-composite.yaml +102 -0
  688. package/rules/ai-tell.yaml +23 -0
  689. package/rules/announced-count-mismatch.yaml +57 -0
  690. package/rules/announcing-opener.yaml +51 -0
  691. package/rules/assistant-residue.yaml +52 -0
  692. package/rules/bold-density.yaml +31 -0
  693. package/rules/broken-link.yaml +65 -0
  694. package/rules/closing-cliche.yaml +33 -0
  695. package/rules/colon-lead-in.yaml +59 -0
  696. package/rules/concrete-evidence-density.yaml +41 -0
  697. package/rules/contraction-consistency.yaml +18 -0
  698. package/rules/contrast-framing.yaml +57 -0
  699. package/rules/cushion-phrase-density.yaml +25 -0
  700. package/rules/dangling-figure-reference.yaml +61 -0
  701. package/rules/dangling-reference.yaml +53 -1
  702. package/rules/date-order.yaml +33 -1
  703. package/rules/date-range-reversed.yaml +46 -0
  704. package/rules/date-weekday-mismatch.yaml +17 -1
  705. package/rules/double-keigo.yaml +16 -0
  706. package/rules/doubled-punctuation.yaml +45 -0
  707. package/rules/doubled-word.yaml +17 -1
  708. package/rules/duplicate-definition.yaml +59 -1
  709. package/rules/emoji-density.yaml +25 -0
  710. package/rules/empty-conclusion.yaml +29 -0
  711. package/rules/empty-intensifier.yaml +19 -0
  712. package/rules/excessive-hedging.yaml +19 -0
  713. package/rules/expletive-construction.yaml +19 -0
  714. package/rules/heading-echo.yaml +32 -0
  715. package/rules/heading-level-skip.yaml +78 -0
  716. package/rules/hiragana-fukushi.yaml +16 -0
  717. package/rules/image-alt-text.yaml +54 -0
  718. package/rules/internal-jargon.yaml +21 -0
  719. package/rules/katakana-long-vowel.yaml +98 -0
  720. package/rules/kutoten-consistency.yaml +53 -0
  721. package/rules/latin-spacing.yaml +23 -4
  722. package/rules/max-kanji-continuous.yaml +16 -0
  723. package/rules/max-paragraph-length.yaml +42 -2
  724. package/rules/max-sentence-length.yaml +36 -0
  725. package/rules/ngram-repetition.yaml +29 -2
  726. package/rules/no-doubled-joshi.yaml +16 -0
  727. package/rules/no-em-dash.yaml +25 -0
  728. package/rules/no-mixed-desumasu.yaml +27 -2
  729. package/rules/no-nakaguro-parallel.yaml +20 -0
  730. package/rules/numbering-gap.yaml +53 -1
  731. package/rules/oxford-comma-consistency.yaml +19 -1
  732. package/rules/padded-intro.yaml +19 -0
  733. package/rules/paragraph-length-variance.yaml +49 -0
  734. package/rules/percent-sum-mismatch.yaml +58 -0
  735. package/rules/preamble-length.yaml +56 -0
  736. package/rules/preferred-term.yaml +27 -0
  737. package/rules/proper-noun-density.yaml +26 -0
  738. package/rules/repeated-conjunction.yaml +47 -0
  739. package/rules/repeated-sentence-head.yaml +23 -0
  740. package/rules/required-sections.yaml +49 -0
  741. package/rules/risk-disclosure.yaml +22 -0
  742. package/rules/rule-of-three.yaml +97 -0
  743. package/rules/sasete-itadaku.yaml +18 -0
  744. package/rules/section-length-uniformity.yaml +89 -0
  745. package/rules/sentence-initial-conjunction-run.yaml +18 -0
  746. package/rules/sentence-rhythm.yaml +25 -0
  747. package/rules/stock-transition.yaml +55 -0
  748. package/rules/stray-space.yaml +56 -0
  749. package/rules/taigen-dome-in-prose.yaml +19 -0
  750. package/rules/title-case-consistency.yaml +42 -0
  751. package/rules/total-mismatch.yaml +37 -1
  752. package/rules/unbalanced-bracket.yaml +56 -0
  753. package/rules/undefined-acronym.yaml +23 -0
  754. package/rules/unfilled-placeholder.yaml +50 -0
  755. package/rules/unqualified-superlative.yaml +19 -0
  756. package/rules/unsourced-number.yaml +16 -0
  757. package/rules/url-run-on.yaml +45 -0
  758. package/skills/chaff/SKILL.md +70 -0
  759. package/src/announced-count.ts +148 -0
  760. package/src/bare-url.ts +35 -0
  761. package/src/baseline.ts +17 -1
  762. package/src/body-section.ts +7 -0
  763. package/src/calendar-number.ts +33 -10
  764. package/src/cli-args.ts +6 -0
  765. package/src/cli-text.ts +8 -4
  766. package/src/cli.ts +37 -37
  767. package/src/closing-numbers.ts +72 -0
  768. package/src/commands/compare.ts +80 -0
  769. package/src/commands/eval.ts +19 -8
  770. package/src/commands/feedback.ts +12 -6
  771. package/src/commands/test.ts +20 -17
  772. package/src/commands/tree.ts +41 -5
  773. package/src/compare/atom.ts +33 -0
  774. package/src/compare/clock-time.ts +86 -0
  775. package/src/compare/extract.ts +78 -0
  776. package/src/compare/fact-text.ts +68 -0
  777. package/src/compare/markup-atoms.ts +29 -0
  778. package/src/compare/match.ts +105 -0
  779. package/src/compare/outcome.ts +70 -0
  780. package/src/compare/proper-nouns.ts +65 -0
  781. package/src/compare/render.ts +102 -0
  782. package/src/compare/spans.ts +17 -0
  783. package/src/compare/text-atoms.ts +95 -0
  784. package/src/compare/text.ts +120 -0
  785. package/src/compare/tree-atoms.ts +80 -0
  786. package/src/compare/written-names.ts +26 -0
  787. package/src/config/load.ts +21 -0
  788. package/src/config/option-problems.ts +70 -0
  789. package/src/config/read.ts +8 -0
  790. package/src/config/rule-problems.ts +12 -2
  791. package/src/config/style.ts +42 -0
  792. package/src/config/warnings.ts +13 -0
  793. package/src/config/write.ts +18 -4
  794. package/src/custom/bounded-match.ts +58 -0
  795. package/src/custom/load.ts +15 -0
  796. package/src/custom/parse.ts +274 -0
  797. package/src/custom/problems.ts +89 -0
  798. package/src/custom/regex-safety.ts +118 -0
  799. package/src/custom/token-pattern.ts +84 -0
  800. package/src/detect.ts +28 -2
  801. package/src/detectors/acronym-context.ts +32 -4
  802. package/src/detectors/acronym-expansion.ts +132 -1
  803. package/src/detectors/agreement-slip.ts +191 -0
  804. package/src/detectors/ai-phrasing.ts +137 -0
  805. package/src/detectors/announced-count.ts +25 -0
  806. package/src/detectors/broken-link.ts +90 -0
  807. package/src/detectors/cited-name.ts +6 -5
  808. package/src/detectors/cited-title.ts +96 -0
  809. package/src/detectors/concrete-evidence.ts +3 -2
  810. package/src/detectors/content-morphemes.ts +19 -0
  811. package/src/detectors/contrast-frame.ts +54 -0
  812. package/src/detectors/custom.ts +89 -0
  813. package/src/detectors/dangling-figure.ts +22 -0
  814. package/src/detectors/doubled-punctuation.ts +49 -0
  815. package/src/detectors/doubled-word.ts +19 -4
  816. package/src/detectors/en-shape.ts +0 -269
  817. package/src/detectors/enumerated-runs.ts +13 -4
  818. package/src/detectors/gram-furniture.ts +30 -0
  819. package/src/detectors/gram-place.ts +9 -5
  820. package/src/detectors/gram-windows.ts +31 -0
  821. package/src/detectors/heading-case.ts +30 -2
  822. package/src/detectors/heading-code-words.ts +35 -0
  823. package/src/detectors/heading-echo.ts +18 -22
  824. package/src/detectors/heading-level-skip.ts +19 -0
  825. package/src/detectors/heading-overlap.ts +65 -0
  826. package/src/detectors/image-alt-text.ts +11 -0
  827. package/src/detectors/index.ts +49 -2
  828. package/src/detectors/kutoten-consistency.ts +96 -0
  829. package/src/detectors/lead-in.ts +3 -1
  830. package/src/detectors/letter-joined-name.ts +15 -0
  831. package/src/detectors/lexicon-match.ts +9 -2
  832. package/src/detectors/lexicon.ts +6 -2
  833. package/src/detectors/list-item.ts +122 -0
  834. package/src/detectors/list-items.ts +163 -0
  835. package/src/detectors/list-lead-in.ts +33 -0
  836. package/src/detectors/list-sentence.ts +157 -0
  837. package/src/detectors/list-view.ts +157 -0
  838. package/src/detectors/long-vowel.ts +66 -0
  839. package/src/detectors/markup-finding.ts +24 -0
  840. package/src/detectors/name-numeral.ts +4 -2
  841. package/src/detectors/orthography.ts +24 -18
  842. package/src/detectors/oxford-comma.ts +297 -0
  843. package/src/detectors/place-run.ts +7 -4
  844. package/src/detectors/placeholder-text.ts +27 -0
  845. package/src/detectors/quote-around.ts +9 -0
  846. package/src/detectors/register.ts +37 -10
  847. package/src/detectors/roman-numeral.ts +3 -0
  848. package/src/detectors/sentence-ending.ts +14 -7
  849. package/src/detectors/sentence-length.ts +16 -5
  850. package/src/detectors/signals.ts +110 -53
  851. package/src/detectors/stacked-hedge.ts +6 -3
  852. package/src/detectors/stray-space.ts +40 -0
  853. package/src/detectors/structure-tree.ts +45 -1
  854. package/src/detectors/structure.ts +13 -6
  855. package/src/detectors/superlative-name.ts +7 -4
  856. package/src/detectors/superlative-scope.ts +8 -3
  857. package/src/detectors/token-column.ts +149 -0
  858. package/src/detectors/unbalanced-bracket.ts +153 -0
  859. package/src/detectors/url-run-on.ts +27 -0
  860. package/src/document-sections.ts +46 -0
  861. package/src/document.ts +116 -127
  862. package/src/email-parts.ts +269 -0
  863. package/src/eval.ts +14 -4
  864. package/src/figure-references.ts +112 -0
  865. package/src/files.ts +5 -0
  866. package/src/genre-parse.ts +30 -5
  867. package/src/genre-suggest.ts +15 -2
  868. package/src/heading-label.ts +55 -0
  869. package/src/in-page-nav.ts +48 -19
  870. package/src/joined-view.ts +1 -0
  871. package/src/levels.ts +14 -1
  872. package/src/line-paragraphs.ts +56 -10
  873. package/src/long-vowel.ts +99 -0
  874. package/src/markdown-node.ts +19 -0
  875. package/src/markdown-read.ts +44 -0
  876. package/src/markup.ts +210 -0
  877. package/src/mask.ts +10 -19
  878. package/src/number-name.ts +152 -25
  879. package/src/opening-line.ts +17 -0
  880. package/src/orthography.ts +20 -5
  881. package/src/page-furniture.ts +11 -2
  882. package/src/paragraph-length.ts +9 -0
  883. package/src/plain-source.ts +2 -1
  884. package/src/plugin.ts +107 -1
  885. package/src/profile/for-file.ts +3 -1
  886. package/src/quoted-span.ts +10 -4
  887. package/src/reasons.ts +9 -0
  888. package/src/reference-lists.ts +91 -0
  889. package/src/render/explain.ts +47 -13
  890. package/src/render/friendly.ts +20 -9
  891. package/src/render/options.ts +58 -0
  892. package/src/render/rules-json.ts +130 -14
  893. package/src/render/rules-table.ts +91 -0
  894. package/src/render/sarif.ts +4 -4
  895. package/src/render/semantic.ts +3 -3
  896. package/src/render/severity-name.ts +10 -0
  897. package/src/render/text.ts +21 -7
  898. package/src/resolve-genre.ts +4 -1
  899. package/src/rule-genres.ts +25 -0
  900. package/src/rule-guide.ts +135 -0
  901. package/src/rule-load.ts +98 -33
  902. package/src/rule-options.ts +131 -0
  903. package/src/run-semantic.ts +28 -20
  904. package/src/run.ts +78 -11
  905. package/src/semantic.ts +11 -3
  906. package/src/sentence-shape.ts +4 -5
  907. package/src/setting-problems.ts +7 -1
  908. package/src/span-cut.ts +28 -0
  909. package/src/span-merge.ts +13 -0
  910. package/src/speaker-labels.ts +129 -0
  911. package/src/stray-space.ts +81 -0
  912. package/src/structure/aside-depth.ts +67 -0
  913. package/src/structure/build.ts +38 -19
  914. package/src/structure/closed-pairs.ts +20 -0
  915. package/src/structure/date-range.ts +69 -0
  916. package/src/structure/known-mentions.ts +96 -0
  917. package/src/structure/numbering.ts +9 -5
  918. package/src/structure/of.ts +11 -3
  919. package/src/structure/percent-sum.ts +135 -0
  920. package/src/structure/quoted-number.ts +36 -0
  921. package/src/structure/relative-find.ts +34 -47
  922. package/src/structure/relative-resolve.ts +104 -42
  923. package/src/structure/runs.ts +2 -2
  924. package/src/structure/sexp.ts +17 -5
  925. package/src/structure/total.ts +2 -2
  926. package/src/structure/universal.ts +24 -4
  927. package/src/structure/wrapped-tail.ts +38 -13
  928. package/src/style-load.ts +28 -0
  929. package/src/style-parse.ts +77 -0
  930. package/src/subheading-line.ts +68 -0
  931. package/src/team-names.ts +13 -13
  932. package/src/template-syntax.ts +164 -0
  933. package/src/text-above.ts +49 -0
  934. package/src/text-figures.ts +147 -0
  935. package/src/trailing-aside.ts +50 -0
  936. package/src/tree-walk.ts +48 -0
  937. package/styles/bunkacho.yaml +25 -0
  938. package/styles/ieice.yaml +29 -0
  939. package/styles/jis-z8301-2011.yaml +25 -0
@@ -0,0 +1,99 @@
1
+ // The final long-vowel mark (ー) of katakana loanwords: how long a word is, and which written forms go against the chosen way.
2
+ // Pure: the words come in already picked from the document's tokens.
3
+
4
+ /** Small kana that join the kana before them into one mora (キャ, ファ, ウィ). ッ, ン and ー are morae of their own. */
5
+ const JOINING: ReadonlySet<string> = new Set(Array.from("ァィゥェォャュョヮぁぃぅぇぉゃゅょゎ"));
6
+
7
+ /** The number of morae (音) in a kana word: コンピューター is コ・ン・ピュ・ー・タ・ー, six. */
8
+ export const moraCount = (word: string): number => Array.from(word).filter((char) => !JOINING.has(char)).length;
9
+
10
+ const LONG_VOWEL = "ー";
11
+ const KATAKANA_WORD = /^[ァ-ヺー]+$/u;
12
+
13
+ /** A katakana word without its final ー: the part both ways of writing it share (コンピュータ for コンピューター). */
14
+ export const stemOf = (surface: string): string => {
15
+ const chars = Array.from(surface);
16
+ return chars.slice(0, chars.findLastIndex((char) => char !== LONG_VOWEL) + 1).join("");
17
+ };
18
+
19
+ /** Whether the surface is a katakana word with something besides ー in it. */
20
+ export const isKatakanaWord = (surface: string): boolean => KATAKANA_WORD.test(surface) && stemOf(surface) !== "";
21
+
22
+ /** A katakana word the rule reads: where it is, how it is written, and whether a final ー could be written or dropped. */
23
+ export type KanaWord = {
24
+ readonly surface: string;
25
+ readonly offset: number;
26
+ /** Written with a final ー. */
27
+ readonly long: boolean;
28
+ /** Written without one, and the dictionary knows the form with one (the language adapter's LongVowelEnding=Dropped). */
29
+ readonly dropped: boolean;
30
+ };
31
+
32
+ /** The morae of the word written with its final ー: カー is two, コンピューター six. The guidelines count the word that way. */
33
+ export const longFormMorae = (surface: string): number => moraCount(stemOf(surface)) + 1;
34
+
35
+ export type Ending = "consistent" | "drop" | "keep";
36
+
37
+ export type Odd = {
38
+ readonly word: KanaWord;
39
+ /** How the rule found it: same-word (one word written both ways), drop or keep (against the setting). */
40
+ readonly variant: "same-word" | "drop" | "keep";
41
+ /** The form the rule asks for. */
42
+ readonly preferred: string;
43
+ /** For same-word: how many times the word is written the way this one is, and how many times in all. */
44
+ readonly count: number;
45
+ readonly of: number;
46
+ };
47
+
48
+ const otherForm = (word: KanaWord): string => (word.long ? stemOf(word.surface) : `${word.surface}${LONG_VOWEL}`);
49
+
50
+ /** The side written less; on a tie, the side the document did not use first. undefined when only one side is used. */
51
+ const minorityLong = (words: readonly KanaWord[]): boolean | undefined => {
52
+ const long = words.filter((word) => word.long).length;
53
+ const short = words.length - long;
54
+ if (long === 0 || short === 0) return undefined;
55
+ if (long !== short) return long < short;
56
+ return !(words[0]?.long ?? false);
57
+ };
58
+
59
+ const minorityOf = (words: readonly KanaWord[], variant: Odd["variant"]): Odd[] => {
60
+ const minority = minorityLong(words);
61
+ if (minority === undefined) return [];
62
+ const odd = words.filter((word) => word.long === minority);
63
+ return odd.map((word) => ({ word, variant, preferred: otherForm(word), count: odd.length, of: words.length }));
64
+ };
65
+
66
+ /** The document's words grouped by the part both ways share (コンピュータ with コンピューター). */
67
+ const sameWordGroups = (words: readonly KanaWord[]): KanaWord[][] => {
68
+ const groups = new Map<string, KanaWord[]>();
69
+ words.forEach((word) => {
70
+ const stem = stemOf(word.surface);
71
+ const group = groups.get(stem);
72
+ if (group === undefined) groups.set(stem, [word]);
73
+ else group.push(word);
74
+ });
75
+ return [...groups.values()];
76
+ };
77
+
78
+ /**
79
+ * With no side taken: a word written both ways (コンピュータ and コンピューター), at its fewer form. Different words are not compared:
80
+ * a document may write サーバー and ブラウザ by each word's usual spelling, and no guideline makes that a mistake.
81
+ */
82
+ const inconsistent = (words: readonly KanaWord[]): Odd[] => sameWordGroups(words).flatMap((group) => minorityOf(group, "same-word"));
83
+
84
+ /**
85
+ * The words that go against the chosen way. drop: a word of minMorae or more written with its final ー. keep: a word written
86
+ * without one where the dictionary, or the document itself, has the form with one. consistent: see inconsistent.
87
+ * Words shorter than minMorae are left alone whichever way: the guidelines that drop the ー keep it on them (カー).
88
+ */
89
+ export const oddLongVowels = (words: readonly KanaWord[], ending: Ending, minMorae: number): Odd[] => {
90
+ const counted = words.filter((word) => longFormMorae(word.surface) >= minMorae);
91
+ if (ending === "drop") return counted.filter((word) => word.long).map((word) => ({ word, variant: "drop", preferred: otherForm(word), count: 0, of: 0 }));
92
+ if (ending === "keep") {
93
+ const longStems = new Set(counted.filter((word) => word.long).map((word) => stemOf(word.surface)));
94
+ return counted
95
+ .filter((word) => !word.long && (word.dropped || longStems.has(word.surface)))
96
+ .map((word) => ({ word, variant: "keep", preferred: otherForm(word), count: 0, of: 0 }));
97
+ }
98
+ return inconsistent(counted).toSorted((left, right) => left.word.offset - right.word.offset);
99
+ };
@@ -0,0 +1,19 @@
1
+ import type { Span } from "./plugin.ts";
2
+
3
+ type Place = { readonly offset?: number | undefined };
4
+
5
+ /** The part of an mdast node chaff reads. */
6
+ export type MarkdownNode = {
7
+ readonly type: string;
8
+ readonly url?: string | undefined;
9
+ readonly value?: string | undefined;
10
+ readonly identifier?: string | undefined;
11
+ readonly position?: { readonly start: Place; readonly end: Place } | undefined;
12
+ readonly children?: readonly MarkdownNode[] | undefined;
13
+ };
14
+
15
+ export const spanOf = (node: MarkdownNode): Span | undefined => {
16
+ const start = node.position?.start.offset;
17
+ const end = node.position?.end.offset;
18
+ return start === undefined || end === undefined ? undefined : { start, end };
19
+ };
@@ -0,0 +1,44 @@
1
+ import { fromMarkdown } from "mdast-util-from-markdown";
2
+ import { gfmTable } from "micromark-extension-gfm-table";
3
+ import { gfmTableFromMarkdown } from "mdast-util-gfm-table";
4
+ import { frontmatter } from "micromark-extension-frontmatter";
5
+ import { frontmatterFromMarkdown } from "mdast-util-frontmatter";
6
+ import { maskSpans } from "./mask.ts";
7
+ import { spanOf, type MarkdownNode } from "./markdown-node.ts";
8
+ import { componentLines, moduleBlocks, templateSpans } from "./template-syntax.ts";
9
+ import { eachPreOrder } from "./tree-walk.ts";
10
+ import type { Span } from "./plugin.ts";
11
+
12
+ export const parse = (source: string): MarkdownNode =>
13
+ fromMarkdown(source, { extensions: [gfmTable(), frontmatter(["yaml"])], mdastExtensions: [gfmTableFromMarkdown(), frontmatterFromMarkdown(["yaml"])] });
14
+
15
+ export const spansOfType = (root: MarkdownNode, type: string, keep: (node: MarkdownNode) => boolean = () => true): Span[] => {
16
+ const found: Span[] = [];
17
+ eachPreOrder(root, (node) => {
18
+ if (node.type !== type || !keep(node)) return;
19
+ const span = spanOf(node);
20
+ if (span !== undefined) found.push(span);
21
+ });
22
+ return found;
23
+ };
24
+
25
+ /** 番号を探してはいけない範囲。コードの中の「第3条」は条ではなく、参照でもない。 */
26
+ const OPAQUE = ["code", "inlineCode", "html", "yaml", "toml"];
27
+
28
+ export const opaqueSpans = (root: MarkdownNode): Span[] => OPAQUE.flatMap((type) => spansOfType(root, type));
29
+
30
+ /** Template syntax outside code: a `{{` in backticks is code, and does not open a tag that runs to the next `}}`. */
31
+ const templateOf = (root: MarkdownNode, source: string): Span[] => (source.includes("{") ? templateSpans(maskSpans(source, opaqueSpans(root))) : []);
32
+
33
+ type MarkdownRead = { readonly root: MarkdownNode; readonly syntax: readonly Span[] };
34
+
35
+ /**
36
+ * Markdown as MDX reads it: a line of nothing but JSX tags is a block of its own, not the start of an HTML block.
37
+ * `syntax` is the site generator's markup in it (those lines, MDX's imports and exports, and template tags outside
38
+ * code), which is neither prose nor structure.
39
+ */
40
+ export const readMarkdown = (source: string): MarkdownRead => {
41
+ const components = source.includes("<") ? componentLines(source) : [];
42
+ const root = parse(components.length === 0 ? source : maskSpans(source, components));
43
+ return { root, syntax: [...components, ...moduleBlocks(root, source), ...templateOf(root, source)] };
44
+ };
package/src/markup.ts ADDED
@@ -0,0 +1,210 @@
1
+ import { spanOf, type MarkdownNode } from "./markdown-node.ts";
2
+ import { headingText } from "./heading-text.ts";
3
+ import { eachPreOrder } from "./tree-walk.ts";
4
+ import { alertReader } from "./template-syntax.ts";
5
+ import { cutSpans } from "./span-cut.ts";
6
+ import { mergeSpans } from "./span-merge.ts";
7
+ import { firstEndingAfter } from "./soft-break.ts";
8
+ import type { Markup, MarkupHeading, MarkupImage, MarkupLink, Span } from "./plugin.ts";
9
+
10
+ /** mdast の節のうち、ここで読む値。MarkdownNode の型には無いものを、型を見て取り出す。 */
11
+ const fieldOf = (node: MarkdownNode, field: string): unknown => (field in node ? Reflect.get(node, field) : undefined);
12
+
13
+ const numberField = (node: MarkdownNode, field: string): number | undefined => {
14
+ const value = fieldOf(node, field);
15
+ return typeof value === "number" ? value : undefined;
16
+ };
17
+
18
+ const stringField = (node: MarkdownNode, field: string): string | undefined => {
19
+ const value = fieldOf(node, field);
20
+ return typeof value === "string" ? value : undefined;
21
+ };
22
+
23
+ // 見出しの末尾に付けた名前。属性(`{#step1 .class}`)と、MDX のコメント(`{/*step1*/}`)。
24
+ type NamedHeading = { readonly text: string; readonly id: string | undefined };
25
+
26
+ const MDX_COMMENT_OPEN = "/*";
27
+ const MDX_COMMENT_CLOSE = "*/";
28
+
29
+ /** 見出しの言葉(textOf の結果)から、末尾の名前を外す。名前が無ければ id は undefined。 */
30
+ export const namedHeading = (written: string): NamedHeading => {
31
+ const trimmed = written.trim();
32
+ const open = trimmed.lastIndexOf("{");
33
+ if (!trimmed.endsWith("}") || open === -1) return { text: trimmed, id: undefined };
34
+ const inner = trimmed.slice(open + 1, -1).trim();
35
+ const before = trimmed.slice(0, open).trim();
36
+ if (inner.startsWith("#")) return { text: before, id: inner.slice(1).split(/\s/u)[0] };
37
+ const isComment = inner.startsWith(MDX_COMMENT_OPEN) && inner.endsWith(MDX_COMMENT_CLOSE);
38
+ return isComment ? { text: before, id: inner.slice(MDX_COMMENT_OPEN.length, -MDX_COMMENT_CLOSE.length).trim() } : { text: trimmed, id: undefined };
39
+ };
40
+
41
+ /** HTML の id・name 属性の値。属性の前は空白なので、data-id は数えない。 */
42
+ const HTML_ID = /\s(?:id|name)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))/giu;
43
+
44
+ /** `<img …>`。引用符の中の `>`(title="2 > 1")では閉じない。 */
45
+ const IMG_TAG = /<img\b(?:"[^"]*"|'[^']*'|[^"'>])*>/giu;
46
+ const ALT_ATTRIBUTE = /\salt\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))?/iu;
47
+
48
+ /** 中の字が、字のまま見える範囲にならない節。リンクの字はリンクで(中の画像は読む)。 */
49
+ const LINKS = new Set(["link", "linkReference"]);
50
+
51
+ type Walk = {
52
+ readonly headings: MarkupHeading[];
53
+ readonly images: MarkupImage[];
54
+ readonly links: MarkupLink[];
55
+ readonly ids: Set<string>;
56
+ readonly texts: Span[];
57
+ /** 参照の定義(`[label]: url`)を名前ごとに。使われた定義だけが、読み手の押すリンクになる。 */
58
+ readonly definitions: Map<string, MarkupLink>;
59
+ /** 参照の形のリンクと画像が使った名前。 */
60
+ readonly referenced: Set<string>;
61
+ };
62
+
63
+ const plainText = (node: MarkdownNode, source: string): string => {
64
+ const parts: string[] = [];
65
+ eachPreOrder(node, (child) => {
66
+ const span = spanOf(child);
67
+ if ((child.type === "text" || child.type === "inlineCode") && span !== undefined) parts.push(source.slice(span.start, span.end));
68
+ });
69
+ return parts.join("");
70
+ };
71
+
72
+ /** ATX の見出しの閉じの `#`。 */
73
+ const ATX_CLOSING = /\s#+\s*$/u;
74
+
75
+ /** MDX のコメントの `*` を強調の印として外した後に残る `{/…/}` を外す。 */
76
+ const withoutMdxComment = (text: string): string => {
77
+ const open = text.lastIndexOf("{/");
78
+ return text.endsWith("/}") && open !== -1 ? text.slice(0, open).trimEnd() : text;
79
+ };
80
+
81
+ const firstLineOf = (text: string): string => text.split("\n", 1)[0] ?? "";
82
+
83
+ const readHeading = (node: MarkdownNode, span: Span, source: string, walk: Walk): void => {
84
+ // 名前は書いたままの行から読む。MDX のコメントの `*` は、解析すると強調の印になって消える。
85
+ const { id } = namedHeading(firstLineOf(source.slice(span.start, span.end)).replace(ATX_CLOSING, ""));
86
+ if (id !== undefined && id !== "") walk.ids.add(id);
87
+ const text = withoutMdxComment(headingText(plainText(node, source)));
88
+ walk.headings.push({ depth: numberField(node, "depth") ?? 1, text, start: span.start, end: span.end });
89
+ };
90
+
91
+ /** 属性の値の文字参照のうち、名前に書かれるもの。ほかの名前の参照は id にまず現れない。 */
92
+ const NAMED_REFERENCES: Readonly<Record<string, string>> = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
93
+
94
+ const CHARACTER_REFERENCE = /&(?:#(\d+)|#x([\da-f]+)|([a-z]+));/giu;
95
+
96
+ const HEX = 16;
97
+
98
+ /** Unicode の字の番号の上限。 */
99
+ const LAST_CODE_POINT = 0x10ffff;
100
+
101
+ /** 番号の字。字の番号でなければ(&#999999999;)undefined で、参照は書いたまま残す。 */
102
+ const characterOf = (codePoint: number): string | undefined =>
103
+ Number.isSafeInteger(codePoint) && codePoint > 0 && codePoint <= LAST_CODE_POINT ? String.fromCodePoint(codePoint) : undefined;
104
+
105
+ /** 属性の値の文字参照(&amp;、&#38;、&#x26;)を字に戻す。ブラウザが名前として読むのは戻した字。 */
106
+ export const decodedAttribute = (value: string): string =>
107
+ value.replace(CHARACTER_REFERENCE, (whole: string, decimal?: string, hex?: string, name?: string) => {
108
+ if (decimal !== undefined) return characterOf(Number(decimal)) ?? whole;
109
+ if (hex !== undefined) return characterOf(Number.parseInt(hex, HEX)) ?? whole;
110
+ return NAMED_REFERENCES[(name ?? "").toLowerCase()] ?? whole;
111
+ });
112
+
113
+ /** HTML のコメント。中の要素は表示されない。 */
114
+ const HTML_COMMENT = /<!--[\s\S]*?-->/gu;
115
+
116
+ /** コメントを同じ長さの空白にする。位置は変えない。 */
117
+ const withoutComments = (html: string): string => html.replace(HTML_COMMENT, (comment) => " ".repeat(comment.length));
118
+
119
+ /** 中身が表示されない要素(`<script>`、`<style>`)で始まる HTML。中の `<img>` や id は字の並びで、ページの要素ではない。 */
120
+ const SOURCE_ELEMENT = /^\s*<(?:script|style)\b/iu;
121
+
122
+ const readHtml = (written: string, span: Span, walk: Walk): void => {
123
+ if (SOURCE_ELEMENT.test(written)) return;
124
+ const value = withoutComments(written);
125
+ [...value.matchAll(HTML_ID)].forEach((match) => walk.ids.add(decodedAttribute(match[1] ?? match[2] ?? match[3] ?? "")));
126
+ [...value.matchAll(IMG_TAG)].forEach((match) => {
127
+ const alt = ALT_ATTRIBUTE.exec(match[0]);
128
+ const start = span.start + match.index;
129
+ walk.images.push({ alt: alt === null ? undefined : (alt[1] ?? alt[2] ?? alt[3] ?? ""), start, end: start + match[0].length });
130
+ });
131
+ };
132
+
133
+ /** 同じ名前の定義が二つあれば、CommonMark は先のものを使う。後のものは使われない。 */
134
+ const defineOnce = (walk: Walk, name: string, link: MarkupLink): void => {
135
+ if (!walk.definitions.has(name)) walk.definitions.set(name, link);
136
+ };
137
+
138
+ /** リンクと参照の定義。定義は、使われたかを最後に見るので別に持つ。 */
139
+ const readLink = (node: MarkdownNode, span: Span, walk: Walk): void => {
140
+ if (node.type === "link") walk.links.push({ destination: node.url ?? "", ...span });
141
+ else if (node.type === "definition") defineOnce(walk, node.identifier ?? "", { destination: node.url ?? "", ...span });
142
+ else if (node.type === "linkReference") walk.referenced.add(node.identifier ?? "");
143
+ };
144
+
145
+ const LINK_NODES = new Set(["link", "definition", "linkReference"]);
146
+
147
+ const readNode = (node: MarkdownNode, span: Span, source: string, walk: Walk, inLink: boolean): void => {
148
+ if (node.type === "heading") readHeading(node, span, source, walk);
149
+ else if (node.type === "image" || node.type === "imageReference") walk.images.push({ alt: stringField(node, "alt") ?? "", ...span });
150
+ else if (LINK_NODES.has(node.type)) readLink(node, span, walk);
151
+ else if (node.type === "html") readHtml(node.value ?? "", span, walk);
152
+ else if (node.type === "text" && !inLink) walk.texts.push(span);
153
+ };
154
+
155
+ /** sorted(昇順・重ならない)のどれかの中で始まるか。記法の範囲が何千あっても、節ごとに全部をなめない。 */
156
+ const startsInside = (span: Span, sorted: readonly Span[]): boolean => {
157
+ const region = sorted[firstEndingAfter(sorted, span.start)];
158
+ return region !== undefined && region.start <= span.start;
159
+ };
160
+
161
+ type Pending = { readonly node: MarkdownNode; readonly inLink: boolean };
162
+
163
+ /**
164
+ * Markdown の記法の手がかりを集める。outside(メールの引用した返信と、MDX の import やテンプレートの記法)と、
165
+ * 引用(`>`)の中は読まない。返信と引用はほかの人の文書で、記法は読み手に見えない。
166
+ * GitHub の注記(`> [!NOTE]`)は書き手の言葉なので読む。本文の組み立て(document.ts)と同じ線引き。
167
+ */
168
+ export const markdownMarkup = (root: MarkdownNode, source: string, outside: readonly Span[] = []): Markup => {
169
+ const walk: Walk = { headings: [], images: [], links: [], ids: new Set(), texts: [], definitions: new Map(), referenced: new Set() };
170
+ const alertOf = alertReader(source);
171
+ const skipped = mergeSpans(outside, false);
172
+ const pending: Pending[] = [{ node: root, inLink: false }];
173
+ while (pending.length > 0) {
174
+ const next = pending.pop();
175
+ if (next === undefined) break;
176
+ const { node, inLink } = next;
177
+ const span = spanOf(node);
178
+ if (span !== undefined && startsInside(span, skipped)) continue;
179
+ if (node.type === "blockquote" && alertOf(node) === undefined) continue;
180
+ if (span !== undefined) readNode(node, span, source, walk, inLink);
181
+ const childInLink = inLink || LINKS.has(node.type);
182
+ (node.children ?? []).toReversed().forEach((child) => pending.push({ node: child, inLink: childInLink }));
183
+ }
184
+ const { definitions, referenced, ...found } = walk;
185
+ const used = [...definitions].filter(([name]) => referenced.has(name)).map(([, link]) => link);
186
+ // 字の節の途中から始まる記法(`{{ … }}`)も、字のまま見える範囲から切り取る。
187
+ const texts = cutSpans(found.texts, skipped);
188
+ return { markdown: true, ...found, texts, links: [...found.links, ...used].toSorted((left, right) => left.start - right.start) };
189
+ };
190
+
191
+ /** Markdown でない文書。記法は無く、文書全体が字のまま見える。 */
192
+ export const plainMarkup = (source: string): Markup => ({
193
+ markdown: false,
194
+ headings: [],
195
+ images: [],
196
+ links: [],
197
+ ids: new Set(),
198
+ texts: [{ start: 0, end: source.length }],
199
+ });
200
+
201
+ const built = new WeakMap<MarkdownNode, Markup>();
202
+
203
+ /** 文書の記法を、文書ごとに一度だけ作る。root は文書を解析した木で、文書ごとに一つ。 */
204
+ export const documentMarkup = (root: MarkdownNode, source: string, markdown: boolean, outside: readonly Span[]): Markup => {
205
+ const cached = built.get(root);
206
+ if (cached !== undefined) return cached;
207
+ const markup = markdown ? markdownMarkup(root, source, outside) : plainMarkup(source);
208
+ built.set(root, markup);
209
+ return markup;
210
+ };
package/src/mask.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Span } from "./plugin.ts";
2
+ import { mergeSpans } from "./span-merge.ts";
2
3
 
3
4
  /**
4
5
  * 非 prose(コードブロック・インラインコード・表・見出し・URL)を、
@@ -16,24 +17,14 @@ import type { Span } from "./plugin.ts";
16
17
  */
17
18
  const blankOut = (text: string): string => text.replace(/[^\n]/gu, (char) => " ".repeat(char.length));
18
19
 
19
- const merge = (spans: readonly Span[]): Span[] =>
20
- spans
21
- .toSorted((left, right) => left.start - right.start)
22
- .reduce<Span[]>((acc, span) => {
23
- const last = acc.at(-1);
24
- if (last !== undefined && span.start <= last.end) acc[acc.length - 1] = { start: last.start, end: Math.max(last.end, span.end) };
25
- else acc.push(span);
26
- return acc;
27
- }, []);
28
-
29
20
  export const maskSpans = (source: string, spans: readonly Span[]): string => {
30
- const merged = merge(spans);
31
- const { parts, cursor } = merged.reduce<{ parts: string[]; cursor: number }>(
32
- (acc, span) => ({
33
- parts: [...acc.parts, source.slice(acc.cursor, span.start), blankOut(source.slice(span.start, span.end))],
34
- cursor: span.end,
35
- }),
36
- { parts: [], cursor: 0 },
37
- );
38
- return [...parts, source.slice(cursor)].join("");
21
+ const merged = mergeSpans(spans, true);
22
+ // 部品は配列に足していく。範囲ごとに配列を作り直すと、範囲が何万もある文書で二乗に遅くなる。
23
+ const parts: string[] = [];
24
+ const cursor = merged.reduce((at, span) => {
25
+ parts.push(source.slice(at, span.start), blankOut(source.slice(span.start, span.end)));
26
+ return span.end;
27
+ }, 0);
28
+ parts.push(source.slice(cursor));
29
+ return parts.join("");
39
30
  };
@@ -1,4 +1,4 @@
1
- import { hyphenGroups, isHyphen } from "./orthography.ts";
1
+ import { HYPHEN_CHARS, hyphenGroups, isHyphen } from "./orthography.ts";
2
2
  import type { Span, Token } from "./plugin.ts";
3
3
 
4
4
  /**
@@ -6,8 +6,9 @@ import type { Span, Token } from "./plugin.ts";
6
6
  * 「〒100-8916 東京都」の郵便番号、「紀尾井町1-3 東京ガーデンテラス」の番地は、後ろの空白が番号と題・項目の区切りで、「3回」「3 回」のような空け方の好みではない。
7
7
  * 空け方を数える材料にしない。
8
8
  *
9
- * 形で名前と読むのは五つだけ。0 で始まる組を含むハイフンつなぎの番号、※・〒や鉤括弧のすぐ後ろの番号、市・区・町まで下りた地名のすぐ後ろのハイフンつなぎの番号、
10
- * 文頭の階層つきの節番号(2.1、3.1.2)、続き番号になった行の頭の番号(白書の注)。文頭でも「223 言語」「1ターン」は数量なので、階層の無い数は文頭というだけでは名前と読まない。
9
+ * 形で名前と読むのは六つだけ。0 で始まる組を含むハイフンつなぎの番号、※・〒や鉤括弧のすぐ後ろの番号、市・区・町まで下りた地名のすぐ後ろのハイフンつなぎの番号、
10
+ * 文頭の階層つきの節番号(2.1、3.1.2)、続き番号になった行や番号の並ぶ箇条書きの頭の番号(白書の注、関連コード)、「問3」のように番号の前に書く語のすぐ後ろの番号。
11
+ * 文頭でも「223 言語」「1ターン」は数量なので、階層の無い数は文頭というだけでは名前と読まない。
11
12
  * そのうえで、すぐ後ろ(空白 1 つまで)の語が数につく語(助数詞・数・助詞・助動詞)なら数量として数え続ける(「3-5 日」「26.7 万行」)。
12
13
  * 品詞が無ければ判断せず、名前とは読まない。
13
14
  */
@@ -36,12 +37,14 @@ const isHyphenIdentifier = (digits: string): boolean => {
36
37
  const DIGIT_OR_POINT = /[\d.]/u;
37
38
  const isRunChar = (char: string | undefined): boolean => DIGIT_OR_POINT.test(char ?? "") || isHyphen(char);
38
39
 
39
- /** at を含む、数字・小数点・ハイフン(全角の「-」なども)の並び。at が並びの中に無ければ undefined。 */
40
+ /** at を含む、数字・小数点・ハイフン(全角の「-」なども)の並び。at が並びの中に無ければ undefined。並びは本文ほど長くなれるので、1 字ずつ呼び直さずに進む。 */
40
41
  export const digitRunAround = (text: string, at: number): Span | undefined => {
41
42
  if (!isRunChar(text[at])) return undefined;
42
- const startAt = (index: number): number => (index > 0 && isRunChar(text[index - 1]) ? startAt(index - 1) : index);
43
- const endAt = (index: number): number => (index < text.length && isRunChar(text[index]) ? endAt(index + 1) : index);
44
- return { start: startAt(at), end: endAt(at) };
43
+ let start = at;
44
+ while (start > 0 && isRunChar(text[start - 1])) start -= 1;
45
+ let end = at;
46
+ while (end < text.length && isRunChar(text[end])) end += 1;
47
+ return { start, end };
45
48
  };
46
49
 
47
50
  /** 並びの後ろ(空白 1 つまで)で始まる語。 */
@@ -63,23 +66,123 @@ const CONJUNCTIONS = new Set(["CCONJ", "SCONJ"]);
63
66
  */
64
67
  const NUMBERED_LINE = /^[ \t]*(?:[-*+][ \t]+)?(?<number>\d{1,3})[ \t]+\S/gmu;
65
68
 
66
- export const sequenceLabelStarts = (text: string): ReadonlySet<number> => {
69
+ const noteSequenceStarts = (text: string): number[] => {
67
70
  const lines = [...text.matchAll(NUMBERED_LINE)].map((match) => {
68
71
  const number = match.groups?.["number"] ?? "";
69
72
  return { start: match.index + match[0].indexOf(number), value: Number(number) };
70
73
  });
71
74
  const continues = (index: number): boolean =>
72
75
  lines[index - 1]?.value === (lines[index]?.value ?? 0) - 1 || lines[index + 1]?.value === (lines[index]?.value ?? 0) + 1;
73
- return new Set(lines.flatMap((line, index) => (continues(index) ? [line.start] : [])));
76
+ return lines.flatMap((line, index) => (continues(index) ? [line.start] : []));
74
77
  };
75
78
 
79
+ /**
80
+ * 箇条書きの項目の頭の番号(- 1122 医療費控除…、- 3-1個人情報…)。番号の後ろに「.」を書く番号付きの箇条書き(1. 概要)は、番号が印なので入れない。
81
+ * 階層は「.」かハイフンでつなぐ。
82
+ */
83
+ const LIST_ITEM_NUMBER = new RegExp(`^[ \\t]*[-*+][ \\t]+(?<number>\\d+(?:[.${HYPHEN_CHARS}]\\d+)*)(?![\\d..])`, "gmu");
84
+ const LEVEL_SEPARATOR = new RegExp(`[.${HYPHEN_CHARS}]`, "u");
85
+
86
+ /** 番号の並び以外で、番号の付いた項目と数える最少の数。二つだけでは「3 言語」「5 ユーザー」のような数量の並びと見分けがつかない。 */
87
+ const MIN_LIST_ITEMS = 3;
88
+
89
+ /** 階層の無い番号だけの並びを、コードの並びと読む最少の桁。「- 3 ユーザー」「- 5 チーム」「- 8 アカウント」は数量の並び。 */
90
+ const MIN_CODE_DIGITS = 3;
91
+
92
+ /** コードの並びで、次の項目までに増える数の上限。コードは近い番号を並べ(1122、1124、1126)、数量の並びは飛ぶ(100、200、300)。 */
93
+ const MAX_CODE_STEP = 9;
94
+
95
+ type ListItem = {
96
+ readonly start: number;
97
+ readonly lineStart: number;
98
+ readonly lineEnd: number;
99
+ readonly number: string;
100
+ readonly levels: readonly number[];
101
+ };
102
+
103
+ const listItems = (text: string): ListItem[] =>
104
+ [...text.matchAll(LIST_ITEM_NUMBER)].map((match) => {
105
+ const number = match.groups?.["number"] ?? "";
106
+ const lineEnd = text.indexOf("\n", match.index);
107
+ return {
108
+ start: match.index + match[0].length - number.length,
109
+ lineStart: match.index,
110
+ lineEnd: lineEnd === -1 ? text.length : lineEnd,
111
+ number,
112
+ levels: number.split(LEVEL_SEPARATOR).map(Number),
113
+ };
114
+ });
115
+
116
+ /** 目次の順で earlier が later より前か(2-19 → 3 → 3-1 → 3-1-1)。 */
117
+ const comesBefore = (earlier: readonly number[], later: readonly number[]): boolean => {
118
+ const differs = earlier.findIndex((level, index) => level !== later[index]);
119
+ if (differs === -1) return earlier.length < later.length;
120
+ return (earlier[differs] ?? 0) < (later[differs] ?? -1);
121
+ };
122
+
123
+ /** 空行だけを挟んで次の項目が続き、番号が増えているか。 */
124
+ const followsItem = (text: string, previous: ListItem, item: ListItem): boolean =>
125
+ text.slice(previous.lineEnd, item.lineStart).trim() === "" && comesBefore(previous.levels, item.levels);
126
+
127
+ /**
128
+ * 前の項目と同じ見出しの下に次の番号が続くか(3 → 3-1、2-18 → 2-19)。並びの番号は増えていくので、頭が同じなら後ろは段を持つ。
129
+ * 「5 → 8-10」は範囲で、目次の段ではない。
130
+ */
131
+ const isOutlineStep = (previous: ListItem | undefined, item: ListItem): boolean => previous !== undefined && previous.levels[0] === item.levels[0];
132
+
133
+ /** 同じ桁数(MIN_CODE_DIGITS 以上)で、MAX_CODE_STEP までずつ増えていくコードの並び(1122、1124、1126)。 */
134
+ const isCodeRun = (run: readonly ListItem[]): boolean => {
135
+ const width = run[0]?.number.length ?? 0;
136
+ const closeToPrevious = (item: ListItem, index: number): boolean => index === 0 || (item.levels[0] ?? 0) - (run[index - 1]?.levels[0] ?? 0) <= MAX_CODE_STEP;
137
+ return width >= MIN_CODE_DIGITS && run.every((item, index) => item.number.length === width && closeToPrevious(item, index));
138
+ };
139
+
140
+ /**
141
+ * 番号の並びとして読める項目の並び。目次の段を含む並び(2-19、3、3-1)か、コードの並び(1122、1124)。
142
+ * 階層の無い数が増えていくだけの並び(3、5、8 や 100、200、300)は、数量を並べたものと見分けがつかない。
143
+ */
144
+ const isLabelRun = (run: readonly ListItem[]): boolean =>
145
+ run.length >= MIN_LIST_ITEMS && (run.some((item, index) => isOutlineStep(run[index - 1], item)) || isCodeRun(run));
146
+
147
+ /**
148
+ * 箇条書きの項目の頭に番号を置き、下へ番号が増えていく並び(国税庁の関連コード 1122、1124、…、ガイドラインの目次 2-19、3、3-1)。
149
+ * 番号は飛んでもよいが、isLabelRun の並びだけを番号と読む。
150
+ */
151
+ const numberedListStarts = (text: string): number[] =>
152
+ listItems(text)
153
+ .reduce<ListItem[][]>((runs, item) => {
154
+ const run = runs.at(-1);
155
+ const previous = run?.at(-1);
156
+ if (run !== undefined && previous !== undefined && followsItem(text, previous, item)) run.push(item);
157
+ else runs.push([item]);
158
+ return runs;
159
+ }, [])
160
+ .filter(isLabelRun)
161
+ .flatMap((run) => run.map((item) => item.start));
162
+
163
+ export const sequenceLabelStarts = (text: string): ReadonlySet<number> => new Set([...noteSequenceStarts(text), ...numberedListStarts(text)]);
164
+
76
165
  const isGeoUnit = (token: Token): boolean => token.features?.["NameType"] === "GeoUnit";
77
166
  const isPlaceWord = (token: Token): boolean => isGeoUnit(token) || token.features?.["NameType"] === "Geo";
78
167
 
79
- /** end で終わる、間を空けずに続く地名と地名の単位(東京都千代田区紀尾井町)。近いほうから。 */
168
+ /** 終わりの位置ごとの、その位置で終わる最初の地名の語。Map は NaN を NaN の鍵で引けるが、位置の NaN はどこにも等しくないので入れない。 */
169
+ const placesByEnd = (tokens: readonly Token[]): ReadonlyMap<number, Token> => {
170
+ const byEnd = new Map<number, Token>();
171
+ tokens.forEach((token) => {
172
+ if (isPlaceWord(token) && !Number.isNaN(token.span.end) && !byEnd.has(token.span.end)) byEnd.set(token.span.end, token);
173
+ });
174
+ return byEnd;
175
+ };
176
+
177
+ /**
178
+ * end で終わる、間を空けずに続く地名と地名の単位(東京都千代田区紀尾井町)。近いほうから。
179
+ * 連なりは本文ほど長くなれるので、語を 1 度だけ読む。同じ語に戻れば(幅の無い語。adapter が壊れているとき)そこで止める。
180
+ */
80
181
  export const placeChainBefore = (tokens: readonly Token[], end: number): Token[] => {
81
- const last = tokens.find((token) => token.span.end === end && isPlaceWord(token));
82
- return last === undefined ? [] : [last, ...placeChainBefore(tokens, last.span.start)];
182
+ const byEnd = placesByEnd(tokens);
183
+ const chain = new Set<Token>();
184
+ for (let last = byEnd.get(end); last !== undefined && !chain.has(last); last = byEnd.get(last.span.start)) chain.add(last);
185
+ return [...chain];
83
186
  };
84
187
 
85
188
  /**
@@ -88,7 +191,7 @@ export const placeChainBefore = (tokens: readonly Token[], end: number): Token[]
88
191
  * ハイフンの無い数(千代田区23 番)も読まない。topUnits は都道府県の単位(語彙表 prefecture-unit)。
89
192
  */
90
193
  const isAddressNumber = (text: string, run: Span, tokens: readonly Token[], base: number, topUnits: ReadonlySet<string>): boolean =>
91
- [...text.slice(run.start, run.end)].some(isHyphen) &&
194
+ Array.from(text.slice(run.start, run.end)).some(isHyphen) &&
92
195
  placeChainBefore(tokens, base + run.start).some((token) => isGeoUnit(token) && !topUnits.has(token.surface));
93
196
 
94
197
  /** ハイフンでつないだ識別子か、番号の立つ位置の番号か、文頭の節番号か。 */
@@ -97,22 +200,46 @@ const isNameShaped = (text: string, run: Span): boolean => {
97
200
  return isHyphenIdentifier(digits) || LABEL_LEAD.test(before) || (LINE_HEAD.test(before) && SECTION_NUMBER.test(digits));
98
201
  };
99
202
 
203
+ /** 「問3」「図2」: 番号のすぐ前(空白を挟まない)の語が、番号の前に書いて名前を付ける語。「質問3」の「問」は語ではない。 */
204
+ const followsLabelWord = (run: Span, tokens: readonly Token[], base: number, labelWords: ReadonlySet<string>): boolean =>
205
+ tokens.some((token) => token.span.end === base + run.start && labelWords.has(token.surface));
206
+
207
+ /**
208
+ * 文書全体で一度だけ読むもの。sequence は sequenceLabelStarts の結果、topUnits は都道府県の単位、
209
+ * labelWords は番号の前に書いて名前を付ける語(語彙表 numbered-label の before)。
210
+ */
211
+ export type NameContext = {
212
+ readonly sequence?: ReadonlySet<number>;
213
+ readonly topUnits?: ReadonlySet<string>;
214
+ readonly labelWords?: ReadonlySet<string>;
215
+ };
216
+
100
217
  /**
101
- * text の run が名前として書かれた数か。tokens は文書全体の座標で、base は text の先頭の位置。sequence は sequenceLabelStarts の結果、
102
- * topUnits は都道府県の単位。
218
+ * text の run が名前として書かれた数か。tokens は文書全体の座標で、base は text の先頭の位置。
103
219
  * 後ろの語が読めない(品詞が無い、語の切れ目が合わない)ときは、数量として数え続ける。
104
220
  */
105
- export const isNumberName = (
106
- text: string,
107
- run: Span,
108
- tokens: readonly Token[] | undefined,
109
- base: number,
110
- sequence: ReadonlySet<number> = new Set(),
111
- topUnits: ReadonlySet<string> = new Set(),
112
- ): boolean => {
113
- const inSequence = sequence.has(base + run.start);
114
- if (tokens === undefined || !(inSequence || isNameShaped(text, run) || isAddressNumber(text, run, tokens, base, topUnits))) return false;
221
+ export const isNumberName = (text: string, run: Span, tokens: readonly Token[] | undefined, base: number, context: NameContext = {}): boolean => {
222
+ const inSequence = context.sequence?.has(base + run.start) ?? false;
223
+ if (tokens === undefined) return false;
224
+ const shaped =
225
+ inSequence ||
226
+ isNameShaped(text, run) ||
227
+ isAddressNumber(text, run, tokens, base, context.topUnits ?? new Set()) ||
228
+ followsLabelWord(run, tokens, base, context.labelWords ?? new Set());
229
+ if (!shaped) return false;
115
230
  const next = wordAfter(tokens, text, run, base);
116
231
  if (next === undefined) return false;
117
232
  return !isBoundToNumber(next) || (inSequence && CONJUNCTIONS.has(next.pos));
118
233
  };
234
+
235
+ /** 「第」と番号の後ろに書く区切りの語(第1節、第 2 章)。 */
236
+ const DIVISION_LABEL = /第 ?\d+ ?(?<unit>[^\s\d第]+)$/u;
237
+
238
+ /**
239
+ * before が「第1節」「第4章第2節」のように、「第」と番号と区切りの語(語彙表 numbered-label の after)で終わるか。
240
+ * その後ろの空白は題との区切りで、空け方の好みではない(第1節 AI の…)。
241
+ */
242
+ export const endsWithDivisionLabel = (before: string, units: ReadonlySet<string>): boolean => {
243
+ const unit = DIVISION_LABEL.exec(before)?.groups?.["unit"];
244
+ return unit !== undefined && units.has(unit);
245
+ };