chaffjs 0.17.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 (840) 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 +2 -0
  18. package/dist/calendar-number.d.ts.map +1 -1
  19. package/dist/calendar-number.js +9 -2
  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/commands/compare.d.ts +8 -0
  31. package/dist/commands/compare.d.ts.map +1 -0
  32. package/dist/commands/compare.js +72 -0
  33. package/dist/commands/compare.js.map +1 -0
  34. package/dist/commands/eval.d.ts.map +1 -1
  35. package/dist/commands/eval.js +17 -9
  36. package/dist/commands/eval.js.map +1 -1
  37. package/dist/commands/feedback.d.ts +5 -2
  38. package/dist/commands/feedback.d.ts.map +1 -1
  39. package/dist/commands/feedback.js +11 -5
  40. package/dist/commands/feedback.js.map +1 -1
  41. package/dist/commands/test.d.ts.map +1 -1
  42. package/dist/commands/test.js +2 -4
  43. package/dist/commands/test.js.map +1 -1
  44. package/dist/commands/tree.d.ts +13 -0
  45. package/dist/commands/tree.d.ts.map +1 -1
  46. package/dist/commands/tree.js +35 -5
  47. package/dist/commands/tree.js.map +1 -1
  48. package/dist/compare/atom.d.ts +31 -0
  49. package/dist/compare/atom.d.ts.map +1 -0
  50. package/dist/compare/atom.js +4 -0
  51. package/dist/compare/atom.js.map +1 -0
  52. package/dist/compare/clock-time.d.ts +8 -0
  53. package/dist/compare/clock-time.d.ts.map +1 -0
  54. package/dist/compare/clock-time.js +65 -0
  55. package/dist/compare/clock-time.js.map +1 -0
  56. package/dist/compare/extract.d.ts +15 -0
  57. package/dist/compare/extract.d.ts.map +1 -0
  58. package/dist/compare/extract.js +58 -0
  59. package/dist/compare/extract.js.map +1 -0
  60. package/dist/compare/fact-text.d.ts +23 -0
  61. package/dist/compare/fact-text.d.ts.map +1 -0
  62. package/dist/compare/fact-text.js +47 -0
  63. package/dist/compare/fact-text.js.map +1 -0
  64. package/dist/compare/markup-atoms.d.ts +11 -0
  65. package/dist/compare/markup-atoms.d.ts.map +1 -0
  66. package/dist/compare/markup-atoms.js +23 -0
  67. package/dist/compare/markup-atoms.js.map +1 -0
  68. package/dist/compare/match.d.ts +19 -0
  69. package/dist/compare/match.d.ts.map +1 -0
  70. package/dist/compare/match.js +84 -0
  71. package/dist/compare/match.js.map +1 -0
  72. package/dist/compare/outcome.d.ts +33 -0
  73. package/dist/compare/outcome.d.ts.map +1 -0
  74. package/dist/compare/outcome.js +40 -0
  75. package/dist/compare/outcome.js.map +1 -0
  76. package/dist/compare/proper-nouns.d.ts +19 -0
  77. package/dist/compare/proper-nouns.d.ts.map +1 -0
  78. package/dist/compare/proper-nouns.js +44 -0
  79. package/dist/compare/proper-nouns.js.map +1 -0
  80. package/dist/compare/render.d.ts +9 -0
  81. package/dist/compare/render.d.ts.map +1 -0
  82. package/dist/compare/render.js +64 -0
  83. package/dist/compare/render.js.map +1 -0
  84. package/dist/compare/spans.d.ts +9 -0
  85. package/dist/compare/spans.d.ts.map +1 -0
  86. package/dist/compare/spans.js +11 -0
  87. package/dist/compare/spans.js.map +1 -0
  88. package/dist/compare/text-atoms.d.ts +24 -0
  89. package/dist/compare/text-atoms.d.ts.map +1 -0
  90. package/dist/compare/text-atoms.js +67 -0
  91. package/dist/compare/text-atoms.js.map +1 -0
  92. package/dist/compare/text.d.ts +24 -0
  93. package/dist/compare/text.d.ts.map +1 -0
  94. package/dist/compare/text.js +90 -0
  95. package/dist/compare/text.js.map +1 -0
  96. package/dist/compare/tree-atoms.d.ts +20 -0
  97. package/dist/compare/tree-atoms.d.ts.map +1 -0
  98. package/dist/compare/tree-atoms.js +58 -0
  99. package/dist/compare/tree-atoms.js.map +1 -0
  100. package/dist/compare/written-names.d.ts +8 -0
  101. package/dist/compare/written-names.d.ts.map +1 -0
  102. package/dist/compare/written-names.js +24 -0
  103. package/dist/compare/written-names.js.map +1 -0
  104. package/dist/config/load.d.ts +15 -0
  105. package/dist/config/load.d.ts.map +1 -1
  106. package/dist/config/load.js +5 -0
  107. package/dist/config/load.js.map +1 -1
  108. package/dist/config/option-problems.d.ts +16 -0
  109. package/dist/config/option-problems.d.ts.map +1 -0
  110. package/dist/config/option-problems.js +58 -0
  111. package/dist/config/option-problems.js.map +1 -0
  112. package/dist/config/read.d.ts +4 -0
  113. package/dist/config/read.d.ts.map +1 -0
  114. package/dist/config/read.js +8 -0
  115. package/dist/config/read.js.map +1 -0
  116. package/dist/config/rule-problems.d.ts +2 -4
  117. package/dist/config/rule-problems.d.ts.map +1 -1
  118. package/dist/config/rule-problems.js +7 -1
  119. package/dist/config/rule-problems.js.map +1 -1
  120. package/dist/config/style.d.ts +16 -0
  121. package/dist/config/style.d.ts.map +1 -0
  122. package/dist/config/style.js +36 -0
  123. package/dist/config/style.js.map +1 -0
  124. package/dist/config/warnings.d.ts +6 -0
  125. package/dist/config/warnings.d.ts.map +1 -0
  126. package/dist/config/warnings.js +10 -0
  127. package/dist/config/warnings.js.map +1 -0
  128. package/dist/config/write.d.ts.map +1 -1
  129. package/dist/config/write.js +17 -4
  130. package/dist/config/write.js.map +1 -1
  131. package/dist/custom/bounded-match.d.ts +15 -0
  132. package/dist/custom/bounded-match.d.ts.map +1 -0
  133. package/dist/custom/bounded-match.js +43 -0
  134. package/dist/custom/bounded-match.js.map +1 -0
  135. package/dist/custom/load.d.ts +8 -0
  136. package/dist/custom/load.d.ts.map +1 -0
  137. package/dist/custom/load.js +11 -0
  138. package/dist/custom/load.js.map +1 -0
  139. package/dist/custom/parse.d.ts +70 -0
  140. package/dist/custom/parse.d.ts.map +1 -0
  141. package/dist/custom/parse.js +215 -0
  142. package/dist/custom/parse.js.map +1 -0
  143. package/dist/custom/problems.d.ts +5 -0
  144. package/dist/custom/problems.d.ts.map +1 -0
  145. package/dist/custom/problems.js +78 -0
  146. package/dist/custom/problems.js.map +1 -0
  147. package/dist/custom/regex-safety.d.ts +11 -0
  148. package/dist/custom/regex-safety.d.ts.map +1 -0
  149. package/dist/custom/regex-safety.js +110 -0
  150. package/dist/custom/regex-safety.js.map +1 -0
  151. package/dist/custom/token-pattern.d.ts +8 -0
  152. package/dist/custom/token-pattern.d.ts.map +1 -0
  153. package/dist/custom/token-pattern.js +75 -0
  154. package/dist/custom/token-pattern.js.map +1 -0
  155. package/dist/detect.d.ts.map +1 -1
  156. package/dist/detect.js +24 -2
  157. package/dist/detect.js.map +1 -1
  158. package/dist/detectors/acronym-context.d.ts +2 -0
  159. package/dist/detectors/acronym-context.d.ts.map +1 -1
  160. package/dist/detectors/acronym-context.js +12 -4
  161. package/dist/detectors/acronym-context.js.map +1 -1
  162. package/dist/detectors/ai-phrasing.d.ts +20 -0
  163. package/dist/detectors/ai-phrasing.d.ts.map +1 -0
  164. package/dist/detectors/ai-phrasing.js +112 -0
  165. package/dist/detectors/ai-phrasing.js.map +1 -0
  166. package/dist/detectors/announced-count.d.ts +4 -0
  167. package/dist/detectors/announced-count.d.ts.map +1 -0
  168. package/dist/detectors/announced-count.js +20 -0
  169. package/dist/detectors/announced-count.js.map +1 -0
  170. package/dist/detectors/broken-link.d.ts +17 -0
  171. package/dist/detectors/broken-link.d.ts.map +1 -0
  172. package/dist/detectors/broken-link.js +66 -0
  173. package/dist/detectors/broken-link.js.map +1 -0
  174. package/dist/detectors/cited-name.d.ts.map +1 -1
  175. package/dist/detectors/cited-name.js +4 -4
  176. package/dist/detectors/cited-name.js.map +1 -1
  177. package/dist/detectors/cited-title.d.ts +11 -0
  178. package/dist/detectors/cited-title.d.ts.map +1 -0
  179. package/dist/detectors/cited-title.js +75 -0
  180. package/dist/detectors/cited-title.js.map +1 -0
  181. package/dist/detectors/concrete-evidence.d.ts +1 -1
  182. package/dist/detectors/concrete-evidence.d.ts.map +1 -1
  183. package/dist/detectors/concrete-evidence.js +2 -1
  184. package/dist/detectors/concrete-evidence.js.map +1 -1
  185. package/dist/detectors/contrast-frame.d.ts +17 -0
  186. package/dist/detectors/contrast-frame.d.ts.map +1 -0
  187. package/dist/detectors/contrast-frame.js +32 -0
  188. package/dist/detectors/contrast-frame.js.map +1 -0
  189. package/dist/detectors/custom.d.ts +8 -0
  190. package/dist/detectors/custom.d.ts.map +1 -0
  191. package/dist/detectors/custom.js +71 -0
  192. package/dist/detectors/custom.js.map +1 -0
  193. package/dist/detectors/dangling-figure.d.ts +4 -0
  194. package/dist/detectors/dangling-figure.d.ts.map +1 -0
  195. package/dist/detectors/dangling-figure.js +18 -0
  196. package/dist/detectors/dangling-figure.js.map +1 -0
  197. package/dist/detectors/doubled-punctuation.d.ts +9 -0
  198. package/dist/detectors/doubled-punctuation.d.ts.map +1 -0
  199. package/dist/detectors/doubled-punctuation.js +33 -0
  200. package/dist/detectors/doubled-punctuation.js.map +1 -0
  201. package/dist/detectors/doubled-word.d.ts +5 -0
  202. package/dist/detectors/doubled-word.d.ts.map +1 -1
  203. package/dist/detectors/doubled-word.js +24 -11
  204. package/dist/detectors/doubled-word.js.map +1 -1
  205. package/dist/detectors/enumerated-runs.d.ts +1 -1
  206. package/dist/detectors/enumerated-runs.d.ts.map +1 -1
  207. package/dist/detectors/enumerated-runs.js +15 -4
  208. package/dist/detectors/enumerated-runs.js.map +1 -1
  209. package/dist/detectors/gram-furniture.d.ts +6 -0
  210. package/dist/detectors/gram-furniture.d.ts.map +1 -0
  211. package/dist/detectors/gram-furniture.js +21 -0
  212. package/dist/detectors/gram-furniture.js.map +1 -0
  213. package/dist/detectors/gram-place.d.ts +2 -0
  214. package/dist/detectors/gram-place.d.ts.map +1 -1
  215. package/dist/detectors/gram-place.js +9 -7
  216. package/dist/detectors/gram-place.js.map +1 -1
  217. package/dist/detectors/gram-windows.d.ts +9 -0
  218. package/dist/detectors/gram-windows.d.ts.map +1 -0
  219. package/dist/detectors/gram-windows.js +27 -0
  220. package/dist/detectors/gram-windows.js.map +1 -0
  221. package/dist/detectors/heading-case.d.ts +2 -0
  222. package/dist/detectors/heading-case.d.ts.map +1 -1
  223. package/dist/detectors/heading-case.js +29 -2
  224. package/dist/detectors/heading-case.js.map +1 -1
  225. package/dist/detectors/heading-code-words.d.ts +6 -0
  226. package/dist/detectors/heading-code-words.d.ts.map +1 -0
  227. package/dist/detectors/heading-code-words.js +29 -0
  228. package/dist/detectors/heading-code-words.js.map +1 -0
  229. package/dist/detectors/heading-echo.d.ts.map +1 -1
  230. package/dist/detectors/heading-echo.js +7 -4
  231. package/dist/detectors/heading-echo.js.map +1 -1
  232. package/dist/detectors/heading-level-skip.d.ts +12 -0
  233. package/dist/detectors/heading-level-skip.d.ts.map +1 -0
  234. package/dist/detectors/heading-level-skip.js +11 -0
  235. package/dist/detectors/heading-level-skip.js.map +1 -0
  236. package/dist/detectors/image-alt-text.d.ts +3 -0
  237. package/dist/detectors/image-alt-text.d.ts.map +1 -0
  238. package/dist/detectors/image-alt-text.js +9 -0
  239. package/dist/detectors/image-alt-text.js.map +1 -0
  240. package/dist/detectors/index.d.ts.map +1 -1
  241. package/dist/detectors/index.js +34 -1
  242. package/dist/detectors/index.js.map +1 -1
  243. package/dist/detectors/kutoten-consistency.d.ts +24 -0
  244. package/dist/detectors/kutoten-consistency.d.ts.map +1 -0
  245. package/dist/detectors/kutoten-consistency.js +77 -0
  246. package/dist/detectors/kutoten-consistency.js.map +1 -0
  247. package/dist/detectors/lead-in.d.ts +1 -0
  248. package/dist/detectors/lead-in.d.ts.map +1 -1
  249. package/dist/detectors/lead-in.js +2 -1
  250. package/dist/detectors/lead-in.js.map +1 -1
  251. package/dist/detectors/lexicon-match.d.ts +4 -0
  252. package/dist/detectors/lexicon-match.d.ts.map +1 -1
  253. package/dist/detectors/lexicon-match.js +7 -2
  254. package/dist/detectors/lexicon-match.js.map +1 -1
  255. package/dist/detectors/list-item.d.ts +45 -0
  256. package/dist/detectors/list-item.d.ts.map +1 -0
  257. package/dist/detectors/list-item.js +88 -0
  258. package/dist/detectors/list-item.js.map +1 -0
  259. package/dist/detectors/list-items.d.ts +31 -0
  260. package/dist/detectors/list-items.d.ts.map +1 -0
  261. package/dist/detectors/list-items.js +113 -0
  262. package/dist/detectors/list-items.js.map +1 -0
  263. package/dist/detectors/list-lead-in.d.ts +7 -0
  264. package/dist/detectors/list-lead-in.d.ts.map +1 -0
  265. package/dist/detectors/list-lead-in.js +28 -0
  266. package/dist/detectors/list-lead-in.js.map +1 -0
  267. package/dist/detectors/list-sentence.d.ts +65 -0
  268. package/dist/detectors/list-sentence.d.ts.map +1 -0
  269. package/dist/detectors/list-sentence.js +105 -0
  270. package/dist/detectors/list-sentence.js.map +1 -0
  271. package/dist/detectors/list-view.d.ts +34 -0
  272. package/dist/detectors/list-view.d.ts.map +1 -0
  273. package/dist/detectors/list-view.js +137 -0
  274. package/dist/detectors/list-view.js.map +1 -0
  275. package/dist/detectors/long-vowel.d.ts +7 -0
  276. package/dist/detectors/long-vowel.d.ts.map +1 -0
  277. package/dist/detectors/long-vowel.js +57 -0
  278. package/dist/detectors/long-vowel.js.map +1 -0
  279. package/dist/detectors/markup-finding.d.ts +6 -0
  280. package/dist/detectors/markup-finding.d.ts.map +1 -0
  281. package/dist/detectors/markup-finding.js +19 -0
  282. package/dist/detectors/markup-finding.js.map +1 -0
  283. package/dist/detectors/name-numeral.d.ts +1 -1
  284. package/dist/detectors/name-numeral.d.ts.map +1 -1
  285. package/dist/detectors/name-numeral.js +2 -7
  286. package/dist/detectors/name-numeral.js.map +1 -1
  287. package/dist/detectors/orthography.d.ts.map +1 -1
  288. package/dist/detectors/orthography.js +14 -10
  289. package/dist/detectors/orthography.js.map +1 -1
  290. package/dist/detectors/oxford-comma.d.ts +7 -1
  291. package/dist/detectors/oxford-comma.d.ts.map +1 -1
  292. package/dist/detectors/oxford-comma.js +135 -229
  293. package/dist/detectors/oxford-comma.js.map +1 -1
  294. package/dist/detectors/place-run.d.ts.map +1 -1
  295. package/dist/detectors/place-run.js +10 -6
  296. package/dist/detectors/place-run.js.map +1 -1
  297. package/dist/detectors/placeholder-text.d.ts +9 -0
  298. package/dist/detectors/placeholder-text.d.ts.map +1 -0
  299. package/dist/detectors/placeholder-text.js +18 -0
  300. package/dist/detectors/placeholder-text.js.map +1 -0
  301. package/dist/detectors/quote-around.d.ts +3 -0
  302. package/dist/detectors/quote-around.d.ts.map +1 -0
  303. package/dist/detectors/quote-around.js +8 -0
  304. package/dist/detectors/quote-around.js.map +1 -0
  305. package/dist/detectors/register.d.ts +11 -3
  306. package/dist/detectors/register.d.ts.map +1 -1
  307. package/dist/detectors/register.js +28 -9
  308. package/dist/detectors/register.js.map +1 -1
  309. package/dist/detectors/roman-numeral.d.ts +2 -0
  310. package/dist/detectors/roman-numeral.d.ts.map +1 -1
  311. package/dist/detectors/roman-numeral.js +2 -0
  312. package/dist/detectors/roman-numeral.js.map +1 -1
  313. package/dist/detectors/sentence-ending.d.ts +17 -1
  314. package/dist/detectors/sentence-ending.d.ts.map +1 -1
  315. package/dist/detectors/sentence-ending.js +13 -7
  316. package/dist/detectors/sentence-ending.js.map +1 -1
  317. package/dist/detectors/sentence-length.d.ts.map +1 -1
  318. package/dist/detectors/sentence-length.js +13 -4
  319. package/dist/detectors/sentence-length.js.map +1 -1
  320. package/dist/detectors/signals.d.ts +8 -0
  321. package/dist/detectors/signals.d.ts.map +1 -1
  322. package/dist/detectors/signals.js +67 -46
  323. package/dist/detectors/signals.js.map +1 -1
  324. package/dist/detectors/structure-tree.d.ts +6 -0
  325. package/dist/detectors/structure-tree.d.ts.map +1 -1
  326. package/dist/detectors/structure-tree.js +37 -1
  327. package/dist/detectors/structure-tree.js.map +1 -1
  328. package/dist/detectors/structure.d.ts +1 -3
  329. package/dist/detectors/structure.d.ts.map +1 -1
  330. package/dist/detectors/structure.js +3 -4
  331. package/dist/detectors/structure.js.map +1 -1
  332. package/dist/detectors/superlative-name.d.ts.map +1 -1
  333. package/dist/detectors/superlative-name.js +8 -5
  334. package/dist/detectors/superlative-name.js.map +1 -1
  335. package/dist/detectors/superlative-scope.d.ts.map +1 -1
  336. package/dist/detectors/superlative-scope.js +9 -4
  337. package/dist/detectors/superlative-scope.js.map +1 -1
  338. package/dist/detectors/token-column.d.ts +46 -0
  339. package/dist/detectors/token-column.d.ts.map +1 -0
  340. package/dist/detectors/token-column.js +95 -0
  341. package/dist/detectors/token-column.js.map +1 -0
  342. package/dist/detectors/unbalanced-bracket.d.ts +22 -0
  343. package/dist/detectors/unbalanced-bracket.d.ts.map +1 -0
  344. package/dist/detectors/unbalanced-bracket.js +119 -0
  345. package/dist/detectors/unbalanced-bracket.js.map +1 -0
  346. package/dist/detectors/url-run-on.d.ts +9 -0
  347. package/dist/detectors/url-run-on.d.ts.map +1 -0
  348. package/dist/detectors/url-run-on.js +19 -0
  349. package/dist/detectors/url-run-on.js.map +1 -0
  350. package/dist/document-sections.d.ts +13 -0
  351. package/dist/document-sections.d.ts.map +1 -0
  352. package/dist/document-sections.js +32 -0
  353. package/dist/document-sections.js.map +1 -0
  354. package/dist/document.d.ts +11 -4
  355. package/dist/document.d.ts.map +1 -1
  356. package/dist/document.js +90 -98
  357. package/dist/document.js.map +1 -1
  358. package/dist/email-parts.d.ts +28 -0
  359. package/dist/email-parts.d.ts.map +1 -0
  360. package/dist/email-parts.js +230 -0
  361. package/dist/email-parts.js.map +1 -0
  362. package/dist/eval.d.ts +2 -1
  363. package/dist/eval.d.ts.map +1 -1
  364. package/dist/eval.js +16 -4
  365. package/dist/eval.js.map +1 -1
  366. package/dist/figure-references.d.ts +30 -0
  367. package/dist/figure-references.d.ts.map +1 -0
  368. package/dist/figure-references.js +76 -0
  369. package/dist/figure-references.js.map +1 -0
  370. package/dist/files.d.ts +2 -0
  371. package/dist/files.d.ts.map +1 -1
  372. package/dist/files.js +4 -0
  373. package/dist/files.js.map +1 -1
  374. package/dist/heading-label.d.ts +22 -0
  375. package/dist/heading-label.d.ts.map +1 -0
  376. package/dist/heading-label.js +50 -0
  377. package/dist/heading-label.js.map +1 -0
  378. package/dist/in-page-nav.d.ts +4 -1
  379. package/dist/in-page-nav.d.ts.map +1 -1
  380. package/dist/in-page-nav.js +53 -18
  381. package/dist/in-page-nav.js.map +1 -1
  382. package/dist/joined-view.d.ts.map +1 -1
  383. package/dist/joined-view.js +1 -0
  384. package/dist/joined-view.js.map +1 -1
  385. package/dist/levels.d.ts +5 -1
  386. package/dist/levels.d.ts.map +1 -1
  387. package/dist/levels.js +9 -0
  388. package/dist/levels.js.map +1 -1
  389. package/dist/line-paragraphs.d.ts +8 -0
  390. package/dist/line-paragraphs.d.ts.map +1 -1
  391. package/dist/line-paragraphs.js +33 -10
  392. package/dist/line-paragraphs.js.map +1 -1
  393. package/dist/long-vowel.d.ts +35 -0
  394. package/dist/long-vowel.d.ts.map +1 -0
  395. package/dist/long-vowel.js +71 -0
  396. package/dist/long-vowel.js.map +1 -0
  397. package/dist/markdown-node.d.ts +19 -0
  398. package/dist/markdown-node.d.ts.map +1 -0
  399. package/dist/markdown-node.js +6 -0
  400. package/dist/markdown-node.js.map +1 -0
  401. package/dist/markdown-read.d.ts +17 -0
  402. package/dist/markdown-read.d.ts.map +1 -0
  403. package/dist/markdown-read.js +37 -0
  404. package/dist/markdown-read.js.map +1 -0
  405. package/dist/markup.d.ts +22 -0
  406. package/dist/markup.d.ts.map +1 -0
  407. package/dist/markup.js +180 -0
  408. package/dist/markup.js.map +1 -0
  409. package/dist/mask.js +8 -5
  410. package/dist/mask.js.map +1 -1
  411. package/dist/number-name.d.ts +21 -5
  412. package/dist/number-name.d.ts.map +1 -1
  413. package/dist/number-name.js +119 -17
  414. package/dist/number-name.js.map +1 -1
  415. package/dist/orthography.d.ts +2 -0
  416. package/dist/orthography.d.ts.map +1 -1
  417. package/dist/orthography.js +9 -4
  418. package/dist/orthography.js.map +1 -1
  419. package/dist/page-furniture.d.ts +5 -2
  420. package/dist/page-furniture.d.ts.map +1 -1
  421. package/dist/page-furniture.js +8 -2
  422. package/dist/page-furniture.js.map +1 -1
  423. package/dist/plain-source.d.ts +1 -0
  424. package/dist/plain-source.d.ts.map +1 -1
  425. package/dist/plain-source.js +2 -1
  426. package/dist/plain-source.js.map +1 -1
  427. package/dist/plugin.d.ts +115 -0
  428. package/dist/plugin.d.ts.map +1 -1
  429. package/dist/profile/for-file.d.ts.map +1 -1
  430. package/dist/profile/for-file.js +3 -1
  431. package/dist/profile/for-file.js.map +1 -1
  432. package/dist/quoted-span.d.ts.map +1 -1
  433. package/dist/quoted-span.js +8 -3
  434. package/dist/quoted-span.js.map +1 -1
  435. package/dist/reasons.d.ts +3 -0
  436. package/dist/reasons.d.ts.map +1 -1
  437. package/dist/reasons.js +6 -0
  438. package/dist/reasons.js.map +1 -1
  439. package/dist/reference-lists.d.ts +3 -0
  440. package/dist/reference-lists.d.ts.map +1 -0
  441. package/dist/reference-lists.js +75 -0
  442. package/dist/reference-lists.js.map +1 -0
  443. package/dist/render/explain.d.ts +7 -1
  444. package/dist/render/explain.d.ts.map +1 -1
  445. package/dist/render/explain.js +36 -12
  446. package/dist/render/explain.js.map +1 -1
  447. package/dist/render/friendly.d.ts.map +1 -1
  448. package/dist/render/friendly.js +19 -9
  449. package/dist/render/friendly.js.map +1 -1
  450. package/dist/render/options.d.ts +7 -0
  451. package/dist/render/options.d.ts.map +1 -0
  452. package/dist/render/options.js +50 -0
  453. package/dist/render/options.js.map +1 -0
  454. package/dist/render/rules-json.d.ts +4 -1
  455. package/dist/render/rules-json.d.ts.map +1 -1
  456. package/dist/render/rules-json.js +102 -12
  457. package/dist/render/rules-json.js.map +1 -1
  458. package/dist/render/rules-table.d.ts +4 -0
  459. package/dist/render/rules-table.d.ts.map +1 -0
  460. package/dist/render/rules-table.js +70 -0
  461. package/dist/render/rules-table.js.map +1 -0
  462. package/dist/render/sarif.js +4 -4
  463. package/dist/render/sarif.js.map +1 -1
  464. package/dist/render/semantic.js +3 -3
  465. package/dist/render/semantic.js.map +1 -1
  466. package/dist/render/severity-name.d.ts +6 -0
  467. package/dist/render/severity-name.d.ts.map +1 -0
  468. package/dist/render/severity-name.js +7 -0
  469. package/dist/render/severity-name.js.map +1 -0
  470. package/dist/render/text.d.ts +7 -2
  471. package/dist/render/text.d.ts.map +1 -1
  472. package/dist/render/text.js +15 -4
  473. package/dist/render/text.js.map +1 -1
  474. package/dist/resolve-genre.d.ts +1 -1
  475. package/dist/resolve-genre.d.ts.map +1 -1
  476. package/dist/resolve-genre.js +4 -1
  477. package/dist/resolve-genre.js.map +1 -1
  478. package/dist/rule-genres.d.ts +24 -0
  479. package/dist/rule-genres.d.ts.map +1 -0
  480. package/dist/rule-genres.js +11 -0
  481. package/dist/rule-genres.js.map +1 -0
  482. package/dist/rule-guide.d.ts +54 -0
  483. package/dist/rule-guide.d.ts.map +1 -0
  484. package/dist/rule-guide.js +81 -0
  485. package/dist/rule-guide.js.map +1 -0
  486. package/dist/rule-load.d.ts.map +1 -1
  487. package/dist/rule-load.js +87 -33
  488. package/dist/rule-load.js.map +1 -1
  489. package/dist/rule-options.d.ts +50 -0
  490. package/dist/rule-options.d.ts.map +1 -0
  491. package/dist/rule-options.js +106 -0
  492. package/dist/rule-options.js.map +1 -0
  493. package/dist/run.d.ts +13 -0
  494. package/dist/run.d.ts.map +1 -1
  495. package/dist/run.js +54 -10
  496. package/dist/run.js.map +1 -1
  497. package/dist/sentence-shape.d.ts.map +1 -1
  498. package/dist/sentence-shape.js +4 -4
  499. package/dist/sentence-shape.js.map +1 -1
  500. package/dist/setting-problems.d.ts +2 -1
  501. package/dist/setting-problems.d.ts.map +1 -1
  502. package/dist/setting-problems.js +6 -1
  503. package/dist/setting-problems.js.map +1 -1
  504. package/dist/span-cut.d.ts +6 -0
  505. package/dist/span-cut.d.ts.map +1 -0
  506. package/dist/span-cut.js +22 -0
  507. package/dist/span-cut.js.map +1 -0
  508. package/dist/structure/aside-depth.d.ts +21 -0
  509. package/dist/structure/aside-depth.d.ts.map +1 -0
  510. package/dist/structure/aside-depth.js +65 -0
  511. package/dist/structure/aside-depth.js.map +1 -0
  512. package/dist/structure/build.d.ts +5 -1
  513. package/dist/structure/build.d.ts.map +1 -1
  514. package/dist/structure/build.js +29 -17
  515. package/dist/structure/build.js.map +1 -1
  516. package/dist/structure/closed-pairs.d.ts +8 -0
  517. package/dist/structure/closed-pairs.d.ts.map +1 -0
  518. package/dist/structure/closed-pairs.js +22 -0
  519. package/dist/structure/closed-pairs.js.map +1 -0
  520. package/dist/structure/date-range.d.ts +21 -0
  521. package/dist/structure/date-range.d.ts.map +1 -0
  522. package/dist/structure/date-range.js +45 -0
  523. package/dist/structure/date-range.js.map +1 -0
  524. package/dist/structure/known-mentions.d.ts +18 -0
  525. package/dist/structure/known-mentions.d.ts.map +1 -0
  526. package/dist/structure/known-mentions.js +78 -0
  527. package/dist/structure/known-mentions.js.map +1 -0
  528. package/dist/structure/numbering.d.ts +1 -0
  529. package/dist/structure/numbering.d.ts.map +1 -1
  530. package/dist/structure/numbering.js +11 -6
  531. package/dist/structure/numbering.js.map +1 -1
  532. package/dist/structure/of.d.ts +3 -1
  533. package/dist/structure/of.d.ts.map +1 -1
  534. package/dist/structure/of.js +5 -1
  535. package/dist/structure/of.js.map +1 -1
  536. package/dist/structure/percent-sum.d.ts +16 -0
  537. package/dist/structure/percent-sum.d.ts.map +1 -0
  538. package/dist/structure/percent-sum.js +104 -0
  539. package/dist/structure/percent-sum.js.map +1 -0
  540. package/dist/structure/quoted-number.d.ts +8 -0
  541. package/dist/structure/quoted-number.d.ts.map +1 -0
  542. package/dist/structure/quoted-number.js +34 -0
  543. package/dist/structure/quoted-number.js.map +1 -0
  544. package/dist/structure/relative-find.d.ts.map +1 -1
  545. package/dist/structure/relative-find.js +34 -46
  546. package/dist/structure/relative-find.js.map +1 -1
  547. package/dist/structure/relative-resolve.d.ts.map +1 -1
  548. package/dist/structure/relative-resolve.js +76 -30
  549. package/dist/structure/relative-resolve.js.map +1 -1
  550. package/dist/structure/runs.d.ts +2 -0
  551. package/dist/structure/runs.d.ts.map +1 -1
  552. package/dist/structure/runs.js +2 -2
  553. package/dist/structure/runs.js.map +1 -1
  554. package/dist/structure/sexp.d.ts +1 -1
  555. package/dist/structure/sexp.d.ts.map +1 -1
  556. package/dist/structure/sexp.js +18 -6
  557. package/dist/structure/sexp.js.map +1 -1
  558. package/dist/structure/total.d.ts +3 -0
  559. package/dist/structure/total.d.ts.map +1 -1
  560. package/dist/structure/total.js +2 -2
  561. package/dist/structure/total.js.map +1 -1
  562. package/dist/structure/universal.d.ts +14 -2
  563. package/dist/structure/universal.d.ts.map +1 -1
  564. package/dist/structure/universal.js +17 -2
  565. package/dist/structure/universal.js.map +1 -1
  566. package/dist/structure/wrapped-tail.d.ts +14 -7
  567. package/dist/structure/wrapped-tail.d.ts.map +1 -1
  568. package/dist/structure/wrapped-tail.js +33 -8
  569. package/dist/structure/wrapped-tail.js.map +1 -1
  570. package/dist/style-load.d.ts +4 -0
  571. package/dist/style-load.d.ts.map +1 -0
  572. package/dist/style-load.js +28 -0
  573. package/dist/style-load.js.map +1 -0
  574. package/dist/style-parse.d.ts +19 -0
  575. package/dist/style-parse.d.ts.map +1 -0
  576. package/dist/style-parse.js +60 -0
  577. package/dist/style-parse.js.map +1 -0
  578. package/dist/subheading-line.d.ts +6 -0
  579. package/dist/subheading-line.d.ts.map +1 -0
  580. package/dist/subheading-line.js +57 -0
  581. package/dist/subheading-line.js.map +1 -0
  582. package/dist/template-syntax.d.ts +17 -0
  583. package/dist/template-syntax.d.ts.map +1 -0
  584. package/dist/template-syntax.js +140 -0
  585. package/dist/template-syntax.js.map +1 -0
  586. package/dist/text-above.d.ts +19 -0
  587. package/dist/text-above.d.ts.map +1 -0
  588. package/dist/text-above.js +43 -0
  589. package/dist/text-above.js.map +1 -0
  590. package/dist/text-figures.d.ts +10 -0
  591. package/dist/text-figures.d.ts.map +1 -0
  592. package/dist/text-figures.js +131 -0
  593. package/dist/text-figures.js.map +1 -0
  594. package/dist/trailing-aside.d.ts +2 -0
  595. package/dist/trailing-aside.d.ts.map +1 -0
  596. package/dist/trailing-aside.js +53 -0
  597. package/dist/trailing-aside.js.map +1 -0
  598. package/dist/tree-walk.d.ts +18 -0
  599. package/dist/tree-walk.d.ts.map +1 -0
  600. package/dist/tree-walk.js +45 -0
  601. package/dist/tree-walk.js.map +1 -0
  602. package/genres.yaml +26 -0
  603. package/package.json +5 -3
  604. package/reference-headings.yaml +17 -0
  605. package/rules/adverb-overuse.yaml +19 -0
  606. package/rules/agentless-passive.yaml +19 -0
  607. package/rules/agreement-slip.yaml +14 -1
  608. package/rules/ai-generated-composite.yaml +102 -0
  609. package/rules/ai-tell.yaml +23 -0
  610. package/rules/announced-count-mismatch.yaml +57 -0
  611. package/rules/announcing-opener.yaml +51 -0
  612. package/rules/assistant-residue.yaml +52 -0
  613. package/rules/bold-density.yaml +31 -0
  614. package/rules/broken-link.yaml +65 -0
  615. package/rules/closing-cliche.yaml +33 -0
  616. package/rules/colon-lead-in.yaml +59 -0
  617. package/rules/concrete-evidence-density.yaml +41 -0
  618. package/rules/contraction-consistency.yaml +18 -0
  619. package/rules/contrast-framing.yaml +57 -0
  620. package/rules/cushion-phrase-density.yaml +25 -0
  621. package/rules/dangling-figure-reference.yaml +61 -0
  622. package/rules/dangling-reference.yaml +53 -1
  623. package/rules/date-order.yaml +33 -1
  624. package/rules/date-range-reversed.yaml +46 -0
  625. package/rules/date-weekday-mismatch.yaml +17 -1
  626. package/rules/double-keigo.yaml +16 -0
  627. package/rules/doubled-punctuation.yaml +45 -0
  628. package/rules/doubled-word.yaml +17 -1
  629. package/rules/duplicate-definition.yaml +59 -1
  630. package/rules/emoji-density.yaml +25 -0
  631. package/rules/empty-conclusion.yaml +28 -0
  632. package/rules/empty-intensifier.yaml +19 -0
  633. package/rules/excessive-hedging.yaml +19 -0
  634. package/rules/expletive-construction.yaml +19 -0
  635. package/rules/heading-echo.yaml +31 -0
  636. package/rules/heading-level-skip.yaml +78 -0
  637. package/rules/hiragana-fukushi.yaml +16 -0
  638. package/rules/image-alt-text.yaml +54 -0
  639. package/rules/internal-jargon.yaml +21 -0
  640. package/rules/katakana-long-vowel.yaml +98 -0
  641. package/rules/kutoten-consistency.yaml +53 -0
  642. package/rules/latin-spacing.yaml +23 -4
  643. package/rules/max-kanji-continuous.yaml +16 -0
  644. package/rules/max-paragraph-length.yaml +33 -0
  645. package/rules/max-sentence-length.yaml +32 -0
  646. package/rules/ngram-repetition.yaml +29 -2
  647. package/rules/no-doubled-joshi.yaml +16 -0
  648. package/rules/no-em-dash.yaml +25 -0
  649. package/rules/no-mixed-desumasu.yaml +27 -2
  650. package/rules/no-nakaguro-parallel.yaml +20 -0
  651. package/rules/numbering-gap.yaml +53 -1
  652. package/rules/oxford-comma-consistency.yaml +18 -0
  653. package/rules/padded-intro.yaml +19 -0
  654. package/rules/paragraph-length-variance.yaml +49 -0
  655. package/rules/percent-sum-mismatch.yaml +58 -0
  656. package/rules/preamble-length.yaml +56 -0
  657. package/rules/preferred-term.yaml +27 -0
  658. package/rules/proper-noun-density.yaml +26 -0
  659. package/rules/repeated-conjunction.yaml +47 -0
  660. package/rules/repeated-sentence-head.yaml +23 -0
  661. package/rules/required-sections.yaml +49 -0
  662. package/rules/risk-disclosure.yaml +22 -0
  663. package/rules/rule-of-three.yaml +97 -0
  664. package/rules/sasete-itadaku.yaml +18 -0
  665. package/rules/section-length-uniformity.yaml +89 -0
  666. package/rules/sentence-initial-conjunction-run.yaml +18 -0
  667. package/rules/sentence-rhythm.yaml +25 -0
  668. package/rules/stock-transition.yaml +55 -0
  669. package/rules/stray-space.yaml +18 -0
  670. package/rules/taigen-dome-in-prose.yaml +19 -0
  671. package/rules/title-case-consistency.yaml +42 -0
  672. package/rules/total-mismatch.yaml +37 -1
  673. package/rules/unbalanced-bracket.yaml +56 -0
  674. package/rules/undefined-acronym.yaml +22 -0
  675. package/rules/unfilled-placeholder.yaml +50 -0
  676. package/rules/unqualified-superlative.yaml +19 -0
  677. package/rules/unsourced-number.yaml +16 -0
  678. package/rules/url-run-on.yaml +45 -0
  679. package/skills/chaff/SKILL.md +70 -0
  680. package/src/announced-count.ts +148 -0
  681. package/src/bare-url.ts +35 -0
  682. package/src/baseline.ts +17 -1
  683. package/src/body-section.ts +7 -0
  684. package/src/calendar-number.ts +18 -4
  685. package/src/cli-args.ts +6 -0
  686. package/src/cli-text.ts +8 -4
  687. package/src/cli.ts +37 -37
  688. package/src/commands/compare.ts +80 -0
  689. package/src/commands/eval.ts +19 -8
  690. package/src/commands/feedback.ts +12 -6
  691. package/src/commands/test.ts +2 -4
  692. package/src/commands/tree.ts +41 -5
  693. package/src/compare/atom.ts +33 -0
  694. package/src/compare/clock-time.ts +86 -0
  695. package/src/compare/extract.ts +78 -0
  696. package/src/compare/fact-text.ts +68 -0
  697. package/src/compare/markup-atoms.ts +29 -0
  698. package/src/compare/match.ts +105 -0
  699. package/src/compare/outcome.ts +70 -0
  700. package/src/compare/proper-nouns.ts +65 -0
  701. package/src/compare/render.ts +102 -0
  702. package/src/compare/spans.ts +17 -0
  703. package/src/compare/text-atoms.ts +95 -0
  704. package/src/compare/text.ts +120 -0
  705. package/src/compare/tree-atoms.ts +80 -0
  706. package/src/compare/written-names.ts +26 -0
  707. package/src/config/load.ts +21 -0
  708. package/src/config/option-problems.ts +70 -0
  709. package/src/config/read.ts +8 -0
  710. package/src/config/rule-problems.ts +12 -2
  711. package/src/config/style.ts +42 -0
  712. package/src/config/warnings.ts +13 -0
  713. package/src/config/write.ts +18 -4
  714. package/src/custom/bounded-match.ts +58 -0
  715. package/src/custom/load.ts +15 -0
  716. package/src/custom/parse.ts +274 -0
  717. package/src/custom/problems.ts +89 -0
  718. package/src/custom/regex-safety.ts +118 -0
  719. package/src/custom/token-pattern.ts +84 -0
  720. package/src/detect.ts +28 -2
  721. package/src/detectors/acronym-context.ts +16 -4
  722. package/src/detectors/ai-phrasing.ts +137 -0
  723. package/src/detectors/announced-count.ts +25 -0
  724. package/src/detectors/broken-link.ts +90 -0
  725. package/src/detectors/cited-name.ts +6 -5
  726. package/src/detectors/cited-title.ts +96 -0
  727. package/src/detectors/concrete-evidence.ts +3 -2
  728. package/src/detectors/contrast-frame.ts +54 -0
  729. package/src/detectors/custom.ts +89 -0
  730. package/src/detectors/dangling-figure.ts +22 -0
  731. package/src/detectors/doubled-punctuation.ts +49 -0
  732. package/src/detectors/doubled-word.ts +19 -4
  733. package/src/detectors/enumerated-runs.ts +13 -4
  734. package/src/detectors/gram-furniture.ts +30 -0
  735. package/src/detectors/gram-place.ts +9 -5
  736. package/src/detectors/gram-windows.ts +31 -0
  737. package/src/detectors/heading-case.ts +30 -2
  738. package/src/detectors/heading-code-words.ts +35 -0
  739. package/src/detectors/heading-echo.ts +8 -4
  740. package/src/detectors/heading-level-skip.ts +19 -0
  741. package/src/detectors/image-alt-text.ts +11 -0
  742. package/src/detectors/index.ts +43 -1
  743. package/src/detectors/kutoten-consistency.ts +96 -0
  744. package/src/detectors/lead-in.ts +3 -1
  745. package/src/detectors/lexicon-match.ts +9 -2
  746. package/src/detectors/list-item.ts +122 -0
  747. package/src/detectors/list-items.ts +163 -0
  748. package/src/detectors/list-lead-in.ts +33 -0
  749. package/src/detectors/list-sentence.ts +157 -0
  750. package/src/detectors/list-view.ts +157 -0
  751. package/src/detectors/long-vowel.ts +66 -0
  752. package/src/detectors/markup-finding.ts +24 -0
  753. package/src/detectors/name-numeral.ts +4 -2
  754. package/src/detectors/orthography.ts +23 -17
  755. package/src/detectors/oxford-comma.ts +178 -283
  756. package/src/detectors/place-run.ts +7 -4
  757. package/src/detectors/placeholder-text.ts +27 -0
  758. package/src/detectors/quote-around.ts +9 -0
  759. package/src/detectors/register.ts +37 -10
  760. package/src/detectors/roman-numeral.ts +3 -0
  761. package/src/detectors/sentence-ending.ts +14 -7
  762. package/src/detectors/sentence-length.ts +16 -5
  763. package/src/detectors/signals.ts +80 -46
  764. package/src/detectors/structure-tree.ts +45 -1
  765. package/src/detectors/structure.ts +3 -4
  766. package/src/detectors/superlative-name.ts +7 -4
  767. package/src/detectors/superlative-scope.ts +8 -3
  768. package/src/detectors/token-column.ts +149 -0
  769. package/src/detectors/unbalanced-bracket.ts +153 -0
  770. package/src/detectors/url-run-on.ts +27 -0
  771. package/src/document-sections.ts +46 -0
  772. package/src/document.ts +106 -138
  773. package/src/email-parts.ts +269 -0
  774. package/src/eval.ts +14 -4
  775. package/src/figure-references.ts +112 -0
  776. package/src/files.ts +5 -0
  777. package/src/heading-label.ts +55 -0
  778. package/src/in-page-nav.ts +48 -19
  779. package/src/joined-view.ts +1 -0
  780. package/src/levels.ts +14 -1
  781. package/src/line-paragraphs.ts +52 -9
  782. package/src/long-vowel.ts +99 -0
  783. package/src/markdown-node.ts +19 -0
  784. package/src/markdown-read.ts +44 -0
  785. package/src/markup.ts +210 -0
  786. package/src/mask.ts +8 -8
  787. package/src/number-name.ts +151 -24
  788. package/src/orthography.ts +10 -3
  789. package/src/page-furniture.ts +11 -2
  790. package/src/plain-source.ts +2 -1
  791. package/src/plugin.ts +101 -1
  792. package/src/profile/for-file.ts +3 -1
  793. package/src/quoted-span.ts +9 -3
  794. package/src/reasons.ts +9 -0
  795. package/src/reference-lists.ts +91 -0
  796. package/src/render/explain.ts +47 -13
  797. package/src/render/friendly.ts +20 -9
  798. package/src/render/options.ts +58 -0
  799. package/src/render/rules-json.ts +130 -14
  800. package/src/render/rules-table.ts +91 -0
  801. package/src/render/sarif.ts +4 -4
  802. package/src/render/semantic.ts +3 -3
  803. package/src/render/severity-name.ts +10 -0
  804. package/src/render/text.ts +21 -7
  805. package/src/resolve-genre.ts +4 -1
  806. package/src/rule-genres.ts +25 -0
  807. package/src/rule-guide.ts +135 -0
  808. package/src/rule-load.ts +91 -34
  809. package/src/rule-options.ts +131 -0
  810. package/src/run.ts +74 -11
  811. package/src/sentence-shape.ts +4 -5
  812. package/src/setting-problems.ts +7 -1
  813. package/src/span-cut.ts +28 -0
  814. package/src/structure/aside-depth.ts +67 -0
  815. package/src/structure/build.ts +38 -19
  816. package/src/structure/closed-pairs.ts +20 -0
  817. package/src/structure/date-range.ts +69 -0
  818. package/src/structure/known-mentions.ts +96 -0
  819. package/src/structure/numbering.ts +9 -5
  820. package/src/structure/of.ts +11 -3
  821. package/src/structure/percent-sum.ts +135 -0
  822. package/src/structure/quoted-number.ts +36 -0
  823. package/src/structure/relative-find.ts +34 -47
  824. package/src/structure/relative-resolve.ts +77 -30
  825. package/src/structure/runs.ts +2 -2
  826. package/src/structure/sexp.ts +17 -5
  827. package/src/structure/total.ts +2 -2
  828. package/src/structure/universal.ts +24 -4
  829. package/src/structure/wrapped-tail.ts +38 -13
  830. package/src/style-load.ts +28 -0
  831. package/src/style-parse.ts +77 -0
  832. package/src/subheading-line.ts +68 -0
  833. package/src/template-syntax.ts +164 -0
  834. package/src/text-above.ts +49 -0
  835. package/src/text-figures.ts +147 -0
  836. package/src/trailing-aside.ts +50 -0
  837. package/src/tree-walk.ts +48 -0
  838. package/styles/bunkacho.yaml +25 -0
  839. package/styles/ieice.yaml +29 -0
  840. package/styles/jis-z8301-2011.yaml +25 -0
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
@@ -19,12 +19,12 @@ const blankOut = (text: string): string => text.replace(/[^\n]/gu, (char) => " "
19
19
 
20
20
  export const maskSpans = (source: string, spans: readonly Span[]): string => {
21
21
  const merged = mergeSpans(spans, true);
22
- const { parts, cursor } = merged.reduce<{ parts: string[]; cursor: number }>(
23
- (acc, span) => ({
24
- parts: [...acc.parts, source.slice(acc.cursor, span.start), blankOut(source.slice(span.start, span.end))],
25
- cursor: span.end,
26
- }),
27
- { parts: [], cursor: 0 },
28
- );
29
- return [...parts, source.slice(cursor)].join("");
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("");
30
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
  /**
@@ -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
+ };
@@ -140,7 +140,9 @@ const isOrdinalRun = (chars: readonly string[], index: number): boolean => {
140
140
  const MIN_CODE_GROUPS = 3;
141
141
 
142
142
  // 通達の「5-1-1」は全角の「-」でつなぐ。ハイフン「‐」やマイナス「−」も同じに読む。長音「ー」は仮名の一部なので入れない。
143
- const HYPHEN = /[-‐‑−-]/u;
143
+ /** 正規表現の文字クラスに入れるハイフンの字。- は範囲の記号にならないよう \ を付ける。 */
144
+ export const HYPHEN_CHARS = "\\-‐‑−-";
145
+ const HYPHEN = new RegExp(`[${HYPHEN_CHARS}]`, "u");
144
146
 
145
147
  /** 数字をつなぐハイフンか。半角の - のほか、全角・和文のハイフンも。 */
146
148
  export const isHyphen = (char: string | undefined): boolean => char !== undefined && HYPHEN.test(char);
@@ -166,8 +168,7 @@ const isUncountedNumber = (chars: readonly string[], index: number): boolean =>
166
168
  return left === ORDINAL_PREFIX || (isJapanese(left) && isCode(chars, next));
167
169
  };
168
170
 
169
- const boundaryAt = (chars: readonly string[], index: number): Omit<Boundary, "offset"> | undefined => {
170
- if (isUncountedNumber(chars, index)) return undefined;
171
+ const candidateAt = (chars: readonly string[], index: number): Omit<Boundary, "offset"> | undefined => {
171
172
  const [left, right, after] = [chars[index], chars[index + 1], chars[index + 2]];
172
173
  const touching = latinBeside(left, right, "before-digit") ?? leftRunBeside(chars, index, right);
173
174
  if (touching !== undefined) return { kind: touching, spaced: false };
@@ -176,6 +177,12 @@ const boundaryAt = (chars: readonly string[], index: number): Omit<Boundary, "of
176
177
  return spaced === undefined ? undefined : { kind: spaced, spaced: true };
177
178
  };
178
179
 
180
+ // isUncountedNumber は数字の並びを端まで読む。境目の候補でだけ聞けば、並びの字ごとではなく並びごとに一度で済む。
181
+ const boundaryAt = (chars: readonly string[], index: number): Omit<Boundary, "offset"> | undefined => {
182
+ const candidate = candidateAt(chars, index);
183
+ return candidate === undefined || isUncountedNumber(chars, index) ? undefined : candidate;
184
+ };
185
+
179
186
  /**
180
187
  * 文の中の境目を全部。offset は境目の位置(左の字の直後、UTF-16)。配列を作り直さずに一度なめる。
181
188
  * text は本文でないものを空白で覆った文、written は覆う前の同じ範囲。覆ってできた空白(リンクの「[」など)は
@@ -1,5 +1,7 @@
1
1
  import type { Span } from "./plugin.ts";
2
2
  import { NO_OUTLINE, type Outline } from "./structure/build.ts";
3
+ import { markdownFigures, textFigures } from "./text-figures.ts";
4
+ import type { MarkdownNode } from "./markdown-node.ts";
3
5
 
4
6
  /** 改ページから、飾りの行を探しにいく行数。飾りと改ページのあいだには空行が数行入る。 */
5
7
  const REACH = 3;
@@ -41,5 +43,12 @@ export const pageFurniture = (source: string): Span[] => {
41
43
  });
42
44
  };
43
45
 
44
- /** テキストの文書の外形。見出しもコードも無く、ページの飾りだけを覆う。木を作る入口はどれもこれを使う。 */
45
- export const textOutline = (source: string): Outline => ({ ...NO_OUTLINE, opaque: pageFurniture(source) });
46
+ /** テキストの文書の外形。見出しもコードも無く、ページの飾り・線で描いた図・メールの引用した返信だけを覆う。木を作る入口はどれもこれを使う。 */
47
+ export const textOutline = (source: string, replyQuotes: readonly Span[] = []): Outline => ({
48
+ ...NO_OUTLINE,
49
+ opaque: [...pageFurniture(source), ...textFigures(source), ...replyQuotes],
50
+ });
51
+
52
+ /** 紙面の形で本文でないもの: テキストの文書のページの飾り(Markdown には改ページが無い)と、線で描いた図。 */
53
+ export const layoutMasks = (root: MarkdownNode, source: string, markdown: boolean): Span[] =>
54
+ markdown ? markdownFigures(root, source) : [...pageFurniture(source), ...textFigures(source)];
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * The Markdown parser drops a leading BOM and reads a lone "\r" as a line break; the rest of chaff counts "\n" only.
3
3
  * Reading the file this way keeps every offset, line and column on the text the writer sees.
4
+ * Every leading BOM goes, so that running this twice (on reading, then in buildDocument) gives the same text as once.
4
5
  */
5
- export const plainSource = (raw: string): string => raw.replace(/^\uFEFF/u, "").replace(/\r\n?/gu, "\n");
6
+ export const plainSource = (raw: string): string => raw.replace(/^\uFEFF+/u, "").replace(/\r\n?/gu, "\n");