chaffjs 0.29.0 → 0.31.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 (681) hide show
  1. package/dist/announced-count.d.ts +2 -0
  2. package/dist/announced-count.d.ts.map +1 -1
  3. package/dist/announced-count.js +4 -3
  4. package/dist/announced-count.js.map +1 -1
  5. package/dist/contacts/addresses.d.ts +21 -0
  6. package/dist/contacts/addresses.d.ts.map +1 -0
  7. package/dist/contacts/addresses.js +144 -0
  8. package/dist/contacts/addresses.js.map +1 -0
  9. package/dist/contacts/emails.d.ts +11 -0
  10. package/dist/contacts/emails.d.ts.map +1 -0
  11. package/dist/contacts/emails.js +51 -0
  12. package/dist/contacts/emails.js.map +1 -0
  13. package/dist/contacts/variants.d.ts +14 -0
  14. package/dist/contacts/variants.d.ts.map +1 -0
  15. package/dist/contacts/variants.js +25 -0
  16. package/dist/contacts/variants.js.map +1 -0
  17. package/dist/derived/battery-runtime.d.ts +85 -0
  18. package/dist/derived/battery-runtime.d.ts.map +1 -0
  19. package/dist/derived/battery-runtime.js +217 -0
  20. package/dist/derived/battery-runtime.js.map +1 -0
  21. package/dist/derived/period-counts.d.ts +48 -0
  22. package/dist/derived/period-counts.d.ts.map +1 -0
  23. package/dist/derived/period-counts.js +128 -0
  24. package/dist/derived/period-counts.js.map +1 -0
  25. package/dist/derived/session-hours.d.ts +26 -0
  26. package/dist/derived/session-hours.d.ts.map +1 -0
  27. package/dist/derived/session-hours.js +29 -0
  28. package/dist/derived/session-hours.js.map +1 -0
  29. package/dist/derived/time-lengths.d.ts +37 -0
  30. package/dist/derived/time-lengths.d.ts.map +1 -0
  31. package/dist/derived/time-lengths.js +171 -0
  32. package/dist/derived/time-lengths.js.map +1 -0
  33. package/dist/derived/unit-counts.d.ts +7 -0
  34. package/dist/derived/unit-counts.d.ts.map +1 -0
  35. package/dist/derived/unit-counts.js +13 -0
  36. package/dist/derived/unit-counts.js.map +1 -0
  37. package/dist/derived/use-interval.d.ts +33 -0
  38. package/dist/derived/use-interval.d.ts.map +1 -0
  39. package/dist/derived/use-interval.js +93 -0
  40. package/dist/derived/use-interval.js.map +1 -0
  41. package/dist/derived/working-hours.d.ts +36 -0
  42. package/dist/derived/working-hours.d.ts.map +1 -0
  43. package/dist/derived/working-hours.js +55 -0
  44. package/dist/derived/working-hours.js.map +1 -0
  45. package/dist/detectors/acronym-expansion.d.ts +1 -1
  46. package/dist/detectors/acronym-expansion.d.ts.map +1 -1
  47. package/dist/detectors/acronym-expansion.js +46 -2
  48. package/dist/detectors/acronym-expansion.js.map +1 -1
  49. package/dist/detectors/announced-count.d.ts.map +1 -1
  50. package/dist/detectors/announced-count.js +1 -0
  51. package/dist/detectors/announced-count.js.map +1 -1
  52. package/dist/detectors/capacity-runtime.d.ts +7 -0
  53. package/dist/detectors/capacity-runtime.d.ts.map +1 -0
  54. package/dist/detectors/capacity-runtime.js +98 -0
  55. package/dist/detectors/capacity-runtime.js.map +1 -0
  56. package/dist/detectors/capitalised-term.d.ts +44 -0
  57. package/dist/detectors/capitalised-term.d.ts.map +1 -0
  58. package/dist/detectors/capitalised-term.js +101 -0
  59. package/dist/detectors/capitalised-term.js.map +1 -0
  60. package/dist/detectors/contact-variant.d.ts +3 -0
  61. package/dist/detectors/contact-variant.d.ts.map +1 -0
  62. package/dist/detectors/contact-variant.js +21 -0
  63. package/dist/detectors/contact-variant.js.map +1 -0
  64. package/dist/detectors/count-over-capacity.d.ts +4 -0
  65. package/dist/detectors/count-over-capacity.d.ts.map +1 -0
  66. package/dist/detectors/count-over-capacity.js +26 -0
  67. package/dist/detectors/count-over-capacity.js.map +1 -0
  68. package/dist/detectors/date-outside-period.d.ts.map +1 -1
  69. package/dist/detectors/date-outside-period.js +5 -1
  70. package/dist/detectors/date-outside-period.js.map +1 -1
  71. package/dist/detectors/date-stamp-order.d.ts +3 -0
  72. package/dist/detectors/date-stamp-order.d.ts.map +1 -0
  73. package/dist/detectors/date-stamp-order.js +24 -0
  74. package/dist/detectors/date-stamp-order.js.map +1 -0
  75. package/dist/detectors/defined-term-form.d.ts.map +1 -1
  76. package/dist/detectors/defined-term-form.js +57 -7
  77. package/dist/detectors/defined-term-form.js.map +1 -1
  78. package/dist/detectors/definition-use.d.ts +1 -1
  79. package/dist/detectors/definition-use.d.ts.map +1 -1
  80. package/dist/detectors/definition-use.js +4 -2
  81. package/dist/detectors/definition-use.js.map +1 -1
  82. package/dist/detectors/derived-numbers.d.ts +11 -1
  83. package/dist/detectors/derived-numbers.d.ts.map +1 -1
  84. package/dist/detectors/derived-numbers.js +74 -20
  85. package/dist/detectors/derived-numbers.js.map +1 -1
  86. package/dist/detectors/due-date.d.ts.map +1 -1
  87. package/dist/detectors/due-date.js +6 -0
  88. package/dist/detectors/due-date.js.map +1 -1
  89. package/dist/detectors/en-shape.d.ts.map +1 -1
  90. package/dist/detectors/en-shape.js +7 -4
  91. package/dist/detectors/en-shape.js.map +1 -1
  92. package/dist/detectors/event-deadline.d.ts +3 -0
  93. package/dist/detectors/event-deadline.d.ts.map +1 -0
  94. package/dist/detectors/event-deadline.js +24 -0
  95. package/dist/detectors/event-deadline.js.map +1 -0
  96. package/dist/detectors/fact-consistency.d.ts +1 -1
  97. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  98. package/dist/detectors/fact-consistency.js +52 -3
  99. package/dist/detectors/fact-consistency.js.map +1 -1
  100. package/dist/detectors/heading-case.d.ts +5 -2
  101. package/dist/detectors/heading-case.d.ts.map +1 -1
  102. package/dist/detectors/heading-case.js +12 -4
  103. package/dist/detectors/heading-case.js.map +1 -1
  104. package/dist/detectors/heading-echo.d.ts +5 -0
  105. package/dist/detectors/heading-echo.d.ts.map +1 -1
  106. package/dist/detectors/heading-echo.js +14 -1
  107. package/dist/detectors/heading-echo.js.map +1 -1
  108. package/dist/detectors/layout-code.d.ts +5 -0
  109. package/dist/detectors/layout-code.d.ts.map +1 -0
  110. package/dist/detectors/layout-code.js +124 -0
  111. package/dist/detectors/layout-code.js.map +1 -0
  112. package/dist/detectors/measured-facts.d.ts +8 -0
  113. package/dist/detectors/measured-facts.d.ts.map +1 -0
  114. package/dist/detectors/measured-facts.js +18 -0
  115. package/dist/detectors/measured-facts.js.map +1 -0
  116. package/dist/detectors/name-variant-model-codes.d.ts +11 -0
  117. package/dist/detectors/name-variant-model-codes.d.ts.map +1 -0
  118. package/dist/detectors/name-variant-model-codes.js +21 -0
  119. package/dist/detectors/name-variant-model-codes.js.map +1 -0
  120. package/dist/detectors/name-variant.d.ts.map +1 -1
  121. package/dist/detectors/name-variant.js +78 -10
  122. package/dist/detectors/name-variant.js.map +1 -1
  123. package/dist/detectors/orthographic-variant.d.ts.map +1 -1
  124. package/dist/detectors/orthographic-variant.js +62 -7
  125. package/dist/detectors/orthographic-variant.js.map +1 -1
  126. package/dist/detectors/orthography.d.ts.map +1 -1
  127. package/dist/detectors/orthography.js +12 -6
  128. package/dist/detectors/orthography.js.map +1 -1
  129. package/dist/detectors/party-order.d.ts +3 -0
  130. package/dist/detectors/party-order.d.ts.map +1 -0
  131. package/dist/detectors/party-order.js +46 -0
  132. package/dist/detectors/party-order.js.map +1 -0
  133. package/dist/detectors/quantity-range.d.ts +3 -0
  134. package/dist/detectors/quantity-range.d.ts.map +1 -0
  135. package/dist/detectors/quantity-range.js +35 -0
  136. package/dist/detectors/quantity-range.js.map +1 -0
  137. package/dist/detectors/range-band.d.ts +5 -0
  138. package/dist/detectors/range-band.d.ts.map +1 -0
  139. package/dist/detectors/range-band.js +80 -0
  140. package/dist/detectors/range-band.js.map +1 -0
  141. package/dist/detectors/registry/capacity-runtime-mismatch.d.ts +3 -0
  142. package/dist/detectors/registry/capacity-runtime-mismatch.d.ts.map +1 -0
  143. package/dist/detectors/registry/capacity-runtime-mismatch.js +3 -0
  144. package/dist/detectors/registry/capacity-runtime-mismatch.js.map +1 -0
  145. package/dist/detectors/registry/connection-time-short.d.ts +3 -0
  146. package/dist/detectors/registry/connection-time-short.d.ts.map +1 -0
  147. package/dist/detectors/registry/connection-time-short.js +3 -0
  148. package/dist/detectors/registry/connection-time-short.js.map +1 -0
  149. package/dist/detectors/registry/contact-variant.d.ts +3 -0
  150. package/dist/detectors/registry/contact-variant.d.ts.map +1 -0
  151. package/dist/detectors/registry/contact-variant.js +3 -0
  152. package/dist/detectors/registry/contact-variant.js.map +1 -0
  153. package/dist/detectors/registry/count-over-capacity.d.ts +3 -0
  154. package/dist/detectors/registry/count-over-capacity.d.ts.map +1 -0
  155. package/dist/detectors/registry/count-over-capacity.js +3 -0
  156. package/dist/detectors/registry/count-over-capacity.js.map +1 -0
  157. package/dist/detectors/registry/date-stamp-order.d.ts +3 -0
  158. package/dist/detectors/registry/date-stamp-order.d.ts.map +1 -0
  159. package/dist/detectors/registry/date-stamp-order.js +3 -0
  160. package/dist/detectors/registry/date-stamp-order.js.map +1 -0
  161. package/dist/detectors/registry/duration-product-mismatch.d.ts +3 -0
  162. package/dist/detectors/registry/duration-product-mismatch.d.ts.map +1 -0
  163. package/dist/detectors/registry/duration-product-mismatch.js +3 -0
  164. package/dist/detectors/registry/duration-product-mismatch.js.map +1 -0
  165. package/dist/detectors/registry/event-deadline.d.ts +3 -0
  166. package/dist/detectors/registry/event-deadline.d.ts.map +1 -0
  167. package/dist/detectors/registry/event-deadline.js +3 -0
  168. package/dist/detectors/registry/event-deadline.js.map +1 -0
  169. package/dist/detectors/registry/interval-count-mismatch.d.ts +3 -0
  170. package/dist/detectors/registry/interval-count-mismatch.d.ts.map +1 -0
  171. package/dist/detectors/registry/interval-count-mismatch.js +3 -0
  172. package/dist/detectors/registry/interval-count-mismatch.js.map +1 -0
  173. package/dist/detectors/registry/layout-code-mismatch.d.ts +3 -0
  174. package/dist/detectors/registry/layout-code-mismatch.d.ts.map +1 -0
  175. package/dist/detectors/registry/layout-code-mismatch.js +3 -0
  176. package/dist/detectors/registry/layout-code-mismatch.js.map +1 -0
  177. package/dist/detectors/registry/party-order.d.ts +3 -0
  178. package/dist/detectors/registry/party-order.d.ts.map +1 -0
  179. package/dist/detectors/registry/party-order.js +3 -0
  180. package/dist/detectors/registry/party-order.js.map +1 -0
  181. package/dist/detectors/registry/quantity-range.d.ts +3 -0
  182. package/dist/detectors/registry/quantity-range.d.ts.map +1 -0
  183. package/dist/detectors/registry/quantity-range.js +3 -0
  184. package/dist/detectors/registry/quantity-range.js.map +1 -0
  185. package/dist/detectors/registry/range-band-mismatch.d.ts +3 -0
  186. package/dist/detectors/registry/range-band-mismatch.d.ts.map +1 -0
  187. package/dist/detectors/registry/range-band-mismatch.js +3 -0
  188. package/dist/detectors/registry/range-band-mismatch.js.map +1 -0
  189. package/dist/detectors/registry/rent-multiple-mismatch.d.ts +3 -0
  190. package/dist/detectors/registry/rent-multiple-mismatch.d.ts.map +1 -0
  191. package/dist/detectors/registry/rent-multiple-mismatch.js +3 -0
  192. package/dist/detectors/registry/rent-multiple-mismatch.js.map +1 -0
  193. package/dist/detectors/registry/requirement-lists.d.ts +3 -0
  194. package/dist/detectors/registry/requirement-lists.d.ts.map +1 -0
  195. package/dist/detectors/registry/requirement-lists.js +3 -0
  196. package/dist/detectors/registry/requirement-lists.js.map +1 -0
  197. package/dist/detectors/registry/return-type.d.ts +3 -0
  198. package/dist/detectors/registry/return-type.d.ts.map +1 -0
  199. package/dist/detectors/registry/return-type.js +3 -0
  200. package/dist/detectors/registry/return-type.js.map +1 -0
  201. package/dist/detectors/registry/scaled-quantity-mismatch.d.ts +3 -0
  202. package/dist/detectors/registry/scaled-quantity-mismatch.d.ts.map +1 -0
  203. package/dist/detectors/registry/scaled-quantity-mismatch.js +3 -0
  204. package/dist/detectors/registry/scaled-quantity-mismatch.js.map +1 -0
  205. package/dist/detectors/registry/step-time-sum-mismatch.d.ts +3 -0
  206. package/dist/detectors/registry/step-time-sum-mismatch.d.ts.map +1 -0
  207. package/dist/detectors/registry/step-time-sum-mismatch.js +3 -0
  208. package/dist/detectors/registry/step-time-sum-mismatch.js.map +1 -0
  209. package/dist/detectors/registry/time-range-reversed.d.ts +3 -0
  210. package/dist/detectors/registry/time-range-reversed.d.ts.map +1 -0
  211. package/dist/detectors/registry/time-range-reversed.js +3 -0
  212. package/dist/detectors/registry/time-range-reversed.js.map +1 -0
  213. package/dist/detectors/registry/unlisted-item-used.d.ts +3 -0
  214. package/dist/detectors/registry/unlisted-item-used.d.ts.map +1 -0
  215. package/dist/detectors/registry/unlisted-item-used.js +3 -0
  216. package/dist/detectors/registry/unlisted-item-used.js.map +1 -0
  217. package/dist/detectors/registry/walk-time-distance-mismatch.d.ts +3 -0
  218. package/dist/detectors/registry/walk-time-distance-mismatch.d.ts.map +1 -0
  219. package/dist/detectors/registry/walk-time-distance-mismatch.js +3 -0
  220. package/dist/detectors/registry/walk-time-distance-mismatch.js.map +1 -0
  221. package/dist/detectors/rent-multiple-mismatch.d.ts +3 -0
  222. package/dist/detectors/rent-multiple-mismatch.d.ts.map +1 -0
  223. package/dist/detectors/rent-multiple-mismatch.js +39 -0
  224. package/dist/detectors/rent-multiple-mismatch.js.map +1 -0
  225. package/dist/detectors/requirement-lists.d.ts +3 -0
  226. package/dist/detectors/requirement-lists.d.ts.map +1 -0
  227. package/dist/detectors/requirement-lists.js +46 -0
  228. package/dist/detectors/requirement-lists.js.map +1 -0
  229. package/dist/detectors/return-type.d.ts +3 -0
  230. package/dist/detectors/return-type.d.ts.map +1 -0
  231. package/dist/detectors/return-type.js +24 -0
  232. package/dist/detectors/return-type.js.map +1 -0
  233. package/dist/detectors/scaled-quantity.d.ts +3 -0
  234. package/dist/detectors/scaled-quantity.d.ts.map +1 -0
  235. package/dist/detectors/scaled-quantity.js +37 -0
  236. package/dist/detectors/scaled-quantity.js.map +1 -0
  237. package/dist/detectors/signals.d.ts.map +1 -1
  238. package/dist/detectors/signals.js +3 -1
  239. package/dist/detectors/signals.js.map +1 -1
  240. package/dist/detectors/step-time-sum.d.ts +3 -0
  241. package/dist/detectors/step-time-sum.d.ts.map +1 -0
  242. package/dist/detectors/step-time-sum.js +46 -0
  243. package/dist/detectors/step-time-sum.js.map +1 -0
  244. package/dist/detectors/structure-tree.d.ts +2 -0
  245. package/dist/detectors/structure-tree.d.ts.map +1 -1
  246. package/dist/detectors/structure-tree.js +31 -6
  247. package/dist/detectors/structure-tree.js.map +1 -1
  248. package/dist/detectors/structure.js +1 -1
  249. package/dist/detectors/structure.js.map +1 -1
  250. package/dist/detectors/technical-docs.d.ts +5 -0
  251. package/dist/detectors/technical-docs.d.ts.map +1 -1
  252. package/dist/detectors/technical-docs.js +12 -0
  253. package/dist/detectors/technical-docs.js.map +1 -1
  254. package/dist/detectors/time-order.d.ts +2 -0
  255. package/dist/detectors/time-order.d.ts.map +1 -1
  256. package/dist/detectors/time-order.js +33 -5
  257. package/dist/detectors/time-order.js.map +1 -1
  258. package/dist/detectors/undefined-term.d.ts.map +1 -1
  259. package/dist/detectors/undefined-term.js +19 -3
  260. package/dist/detectors/undefined-term.js.map +1 -1
  261. package/dist/detectors/unit-consistency.d.ts +1 -1
  262. package/dist/detectors/unit-consistency.d.ts.map +1 -1
  263. package/dist/detectors/unit-consistency.js +46 -38
  264. package/dist/detectors/unit-consistency.js.map +1 -1
  265. package/dist/detectors/unlisted-items.d.ts +3 -0
  266. package/dist/detectors/unlisted-items.d.ts.map +1 -0
  267. package/dist/detectors/unlisted-items.js +57 -0
  268. package/dist/detectors/unlisted-items.js.map +1 -0
  269. package/dist/detectors/use-count-words.d.ts +8 -0
  270. package/dist/detectors/use-count-words.d.ts.map +1 -0
  271. package/dist/detectors/use-count-words.js +20 -0
  272. package/dist/detectors/use-count-words.js.map +1 -0
  273. package/dist/detectors/use-interval.d.ts +3 -0
  274. package/dist/detectors/use-interval.d.ts.map +1 -0
  275. package/dist/detectors/use-interval.js +39 -0
  276. package/dist/detectors/use-interval.js.map +1 -0
  277. package/dist/detectors/walk-time-distance-mismatch.d.ts +4 -0
  278. package/dist/detectors/walk-time-distance-mismatch.d.ts.map +1 -0
  279. package/dist/detectors/walk-time-distance-mismatch.js +38 -0
  280. package/dist/detectors/walk-time-distance-mismatch.js.map +1 -0
  281. package/dist/document.d.ts.map +1 -1
  282. package/dist/document.js +4 -1
  283. package/dist/document.js.map +1 -1
  284. package/dist/facts/approximate-tolerance.d.ts +7 -0
  285. package/dist/facts/approximate-tolerance.d.ts.map +1 -0
  286. package/dist/facts/approximate-tolerance.js +16 -0
  287. package/dist/facts/approximate-tolerance.js.map +1 -0
  288. package/dist/facts/item-amounts.d.ts +18 -0
  289. package/dist/facts/item-amounts.d.ts.map +1 -0
  290. package/dist/facts/item-amounts.js +67 -0
  291. package/dist/facts/item-amounts.js.map +1 -0
  292. package/dist/facts/labelled-facts.d.ts +4 -0
  293. package/dist/facts/labelled-facts.d.ts.map +1 -1
  294. package/dist/facts/labelled-facts.js +21 -6
  295. package/dist/facts/labelled-facts.js.map +1 -1
  296. package/dist/facts/measure-units.d.ts +5 -0
  297. package/dist/facts/measure-units.d.ts.map +1 -0
  298. package/dist/facts/measure-units.js +28 -0
  299. package/dist/facts/measure-units.js.map +1 -0
  300. package/dist/facts/measures.d.ts +23 -4
  301. package/dist/facts/measures.d.ts.map +1 -1
  302. package/dist/facts/measures.js +68 -19
  303. package/dist/facts/measures.js.map +1 -1
  304. package/dist/facts/retention-periods.d.ts +51 -0
  305. package/dist/facts/retention-periods.d.ts.map +1 -0
  306. package/dist/facts/retention-periods.js +148 -0
  307. package/dist/facts/retention-periods.js.map +1 -0
  308. package/dist/facts/table-facts.d.ts +2 -0
  309. package/dist/facts/table-facts.d.ts.map +1 -1
  310. package/dist/facts/table-facts.js +2 -0
  311. package/dist/facts/table-facts.js.map +1 -1
  312. package/dist/facts/unit-conflicts.d.ts +3 -2
  313. package/dist/facts/unit-conflicts.d.ts.map +1 -1
  314. package/dist/facts/unit-conflicts.js +15 -7
  315. package/dist/facts/unit-conflicts.js.map +1 -1
  316. package/dist/facts/unit-equivalents.d.ts +13 -0
  317. package/dist/facts/unit-equivalents.d.ts.map +1 -0
  318. package/dist/facts/unit-equivalents.js +56 -0
  319. package/dist/facts/unit-equivalents.js.map +1 -0
  320. package/dist/facts/unit-tolerance.d.ts +4 -0
  321. package/dist/facts/unit-tolerance.d.ts.map +1 -0
  322. package/dist/facts/unit-tolerance.js +13 -0
  323. package/dist/facts/unit-tolerance.js.map +1 -0
  324. package/dist/facts/unit-word.d.ts +8 -0
  325. package/dist/facts/unit-word.d.ts.map +1 -0
  326. package/dist/facts/unit-word.js +34 -0
  327. package/dist/facts/unit-word.js.map +1 -0
  328. package/dist/facts/written-precision.d.ts +10 -0
  329. package/dist/facts/written-precision.d.ts.map +1 -0
  330. package/dist/facts/written-precision.js +20 -0
  331. package/dist/facts/written-precision.js.map +1 -0
  332. package/dist/kana-spelling.d.ts +12 -0
  333. package/dist/kana-spelling.d.ts.map +1 -1
  334. package/dist/kana-spelling.js +23 -0
  335. package/dist/kana-spelling.js.map +1 -1
  336. package/dist/model-codes.d.ts +23 -0
  337. package/dist/model-codes.d.ts.map +1 -0
  338. package/dist/model-codes.js +81 -0
  339. package/dist/model-codes.js.map +1 -0
  340. package/dist/name-spelling-chars.d.ts +16 -0
  341. package/dist/name-spelling-chars.d.ts.map +1 -0
  342. package/dist/name-spelling-chars.js +14 -0
  343. package/dist/name-spelling-chars.js.map +1 -0
  344. package/dist/name-variants.d.ts +8 -2
  345. package/dist/name-variants.d.ts.map +1 -1
  346. package/dist/name-variants.js +72 -7
  347. package/dist/name-variants.js.map +1 -1
  348. package/dist/name-word-order.d.ts +49 -0
  349. package/dist/name-word-order.d.ts.map +1 -0
  350. package/dist/name-word-order.js +114 -0
  351. package/dist/name-word-order.js.map +1 -0
  352. package/dist/phone-numbers.d.ts.map +1 -1
  353. package/dist/phone-numbers.js +22 -5
  354. package/dist/phone-numbers.js.map +1 -1
  355. package/dist/place-names.d.ts +12 -5
  356. package/dist/place-names.d.ts.map +1 -1
  357. package/dist/place-names.js +34 -14
  358. package/dist/place-names.js.map +1 -1
  359. package/dist/plugin.d.ts +12 -0
  360. package/dist/plugin.d.ts.map +1 -1
  361. package/dist/preamble-paragraphs.d.ts +2 -1
  362. package/dist/preamble-paragraphs.d.ts.map +1 -1
  363. package/dist/preamble-paragraphs.js +16 -1
  364. package/dist/preamble-paragraphs.js.map +1 -1
  365. package/dist/profile/parse.d.ts.map +1 -1
  366. package/dist/profile/parse.js +11 -0
  367. package/dist/profile/parse.js.map +1 -1
  368. package/dist/return-type.d.ts +33 -0
  369. package/dist/return-type.d.ts.map +1 -0
  370. package/dist/return-type.js +302 -0
  371. package/dist/return-type.js.map +1 -0
  372. package/dist/spacing-code.d.ts +6 -0
  373. package/dist/spacing-code.d.ts.map +1 -0
  374. package/dist/spacing-code.js +16 -0
  375. package/dist/spacing-code.js.map +1 -0
  376. package/dist/structure/amount-range.d.ts +2 -2
  377. package/dist/structure/amount-range.d.ts.map +1 -1
  378. package/dist/structure/amount-range.js +12 -5
  379. package/dist/structure/amount-range.js.map +1 -1
  380. package/dist/structure/capacity-count.d.ts +59 -0
  381. package/dist/structure/capacity-count.d.ts.map +1 -0
  382. package/dist/structure/capacity-count.js +118 -0
  383. package/dist/structure/capacity-count.js.map +1 -0
  384. package/dist/structure/connection-times.d.ts +56 -0
  385. package/dist/structure/connection-times.d.ts.map +1 -0
  386. package/dist/structure/connection-times.js +165 -0
  387. package/dist/structure/connection-times.js.map +1 -0
  388. package/dist/structure/counted-amounts.d.ts +6 -0
  389. package/dist/structure/counted-amounts.d.ts.map +1 -1
  390. package/dist/structure/counted-amounts.js +4 -4
  391. package/dist/structure/counted-amounts.js.map +1 -1
  392. package/dist/structure/date-order-tie.d.ts +13 -0
  393. package/dist/structure/date-order-tie.d.ts.map +1 -0
  394. package/dist/structure/date-order-tie.js +61 -0
  395. package/dist/structure/date-order-tie.js.map +1 -0
  396. package/dist/structure/date-order.d.ts +2 -2
  397. package/dist/structure/date-order.d.ts.map +1 -1
  398. package/dist/structure/date-order.js +26 -9
  399. package/dist/structure/date-order.js.map +1 -1
  400. package/dist/structure/date-outside-period.d.ts +8 -0
  401. package/dist/structure/date-outside-period.d.ts.map +1 -1
  402. package/dist/structure/date-outside-period.js +52 -3
  403. package/dist/structure/date-outside-period.js.map +1 -1
  404. package/dist/structure/date-range.d.ts +6 -2
  405. package/dist/structure/date-range.d.ts.map +1 -1
  406. package/dist/structure/date-range.js +37 -9
  407. package/dist/structure/date-range.js.map +1 -1
  408. package/dist/structure/deadline-after-event.d.ts +23 -0
  409. package/dist/structure/deadline-after-event.d.ts.map +1 -0
  410. package/dist/structure/deadline-after-event.js +42 -0
  411. package/dist/structure/deadline-after-event.js.map +1 -0
  412. package/dist/structure/definition-use.d.ts +1 -1
  413. package/dist/structure/definition-use.d.ts.map +1 -1
  414. package/dist/structure/definition-use.js +55 -2
  415. package/dist/structure/definition-use.js.map +1 -1
  416. package/dist/structure/due-date.d.ts.map +1 -1
  417. package/dist/structure/due-date.js +5 -27
  418. package/dist/structure/due-date.js.map +1 -1
  419. package/dist/structure/labelled-date-order.d.ts +38 -0
  420. package/dist/structure/labelled-date-order.d.ts.map +1 -0
  421. package/dist/structure/labelled-date-order.js +41 -0
  422. package/dist/structure/labelled-date-order.js.map +1 -0
  423. package/dist/structure/layout-codes.d.ts +68 -0
  424. package/dist/structure/layout-codes.d.ts.map +1 -0
  425. package/dist/structure/layout-codes.js +161 -0
  426. package/dist/structure/layout-codes.js.map +1 -0
  427. package/dist/structure/leg-times.d.ts +2 -0
  428. package/dist/structure/leg-times.d.ts.map +1 -1
  429. package/dist/structure/leg-times.js +13 -0
  430. package/dist/structure/leg-times.js.map +1 -1
  431. package/dist/structure/measured-amounts.d.ts +17 -0
  432. package/dist/structure/measured-amounts.d.ts.map +1 -0
  433. package/dist/structure/measured-amounts.js +110 -0
  434. package/dist/structure/measured-amounts.js.map +1 -0
  435. package/dist/structure/party-order.d.ts +33 -0
  436. package/dist/structure/party-order.d.ts.map +1 -0
  437. package/dist/structure/party-order.js +79 -0
  438. package/dist/structure/party-order.js.map +1 -0
  439. package/dist/structure/quantity-range.d.ts +8 -0
  440. package/dist/structure/quantity-range.d.ts.map +1 -0
  441. package/dist/structure/quantity-range.js +36 -0
  442. package/dist/structure/quantity-range.js.map +1 -0
  443. package/dist/structure/range-bands.d.ts +75 -0
  444. package/dist/structure/range-bands.d.ts.map +1 -0
  445. package/dist/structure/range-bands.js +244 -0
  446. package/dist/structure/range-bands.js.map +1 -0
  447. package/dist/structure/rent-multiple.d.ts +76 -0
  448. package/dist/structure/rent-multiple.d.ts.map +1 -0
  449. package/dist/structure/rent-multiple.js +186 -0
  450. package/dist/structure/rent-multiple.js.map +1 -0
  451. package/dist/structure/requirement-lists.d.ts +37 -0
  452. package/dist/structure/requirement-lists.d.ts.map +1 -0
  453. package/dist/structure/requirement-lists.js +89 -0
  454. package/dist/structure/requirement-lists.js.map +1 -0
  455. package/dist/structure/scaled-quantities.d.ts +50 -0
  456. package/dist/structure/scaled-quantities.d.ts.map +1 -0
  457. package/dist/structure/scaled-quantities.js +153 -0
  458. package/dist/structure/scaled-quantities.js.map +1 -0
  459. package/dist/structure/stamp-order.d.ts +16 -0
  460. package/dist/structure/stamp-order.d.ts.map +1 -0
  461. package/dist/structure/stamp-order.js +78 -0
  462. package/dist/structure/stamp-order.js.map +1 -0
  463. package/dist/structure/step-times.d.ts +49 -0
  464. package/dist/structure/step-times.d.ts.map +1 -0
  465. package/dist/structure/step-times.js +128 -0
  466. package/dist/structure/step-times.js.map +1 -0
  467. package/dist/structure/term-deadline.d.ts +19 -0
  468. package/dist/structure/term-deadline.d.ts.map +1 -0
  469. package/dist/structure/term-deadline.js +28 -0
  470. package/dist/structure/term-deadline.js.map +1 -0
  471. package/dist/structure/time-order.d.ts +21 -0
  472. package/dist/structure/time-order.d.ts.map +1 -1
  473. package/dist/structure/time-order.js +5 -6
  474. package/dist/structure/time-order.js.map +1 -1
  475. package/dist/structure/time-range.d.ts +16 -0
  476. package/dist/structure/time-range.d.ts.map +1 -0
  477. package/dist/structure/time-range.js +57 -0
  478. package/dist/structure/time-range.js.map +1 -0
  479. package/dist/structure/total-line.d.ts +16 -0
  480. package/dist/structure/total-line.d.ts.map +1 -0
  481. package/dist/structure/total-line.js +44 -0
  482. package/dist/structure/total-line.js.map +1 -0
  483. package/dist/structure/total.d.ts +7 -1
  484. package/dist/structure/total.d.ts.map +1 -1
  485. package/dist/structure/total.js +28 -5
  486. package/dist/structure/total.js.map +1 -1
  487. package/dist/structure/unlisted-items.d.ts +70 -0
  488. package/dist/structure/unlisted-items.d.ts.map +1 -0
  489. package/dist/structure/unlisted-items.js +152 -0
  490. package/dist/structure/unlisted-items.js.map +1 -0
  491. package/dist/structure/version-order.d.ts +2 -0
  492. package/dist/structure/version-order.d.ts.map +1 -1
  493. package/dist/structure/version-order.js +10 -0
  494. package/dist/structure/version-order.js.map +1 -1
  495. package/dist/structure/walk-time.d.ts +87 -0
  496. package/dist/structure/walk-time.d.ts.map +1 -0
  497. package/dist/structure/walk-time.js +195 -0
  498. package/dist/structure/walk-time.js.map +1 -0
  499. package/dist/surname-near.d.ts +6 -0
  500. package/dist/surname-near.d.ts.map +1 -0
  501. package/dist/surname-near.js +31 -0
  502. package/dist/surname-near.js.map +1 -0
  503. package/dist/table-cells.d.ts +13 -0
  504. package/dist/table-cells.d.ts.map +1 -0
  505. package/dist/table-cells.js +36 -0
  506. package/dist/table-cells.js.map +1 -0
  507. package/dist/table-names.d.ts +42 -0
  508. package/dist/table-names.d.ts.map +1 -0
  509. package/dist/table-names.js +94 -0
  510. package/dist/table-names.js.map +1 -0
  511. package/package.json +3 -3
  512. package/profiles/listing.yaml +20 -0
  513. package/rules/announced-count-mismatch.yaml +2 -2
  514. package/rules/capacity-runtime-mismatch.yaml +66 -0
  515. package/rules/connection-time-short.yaml +52 -0
  516. package/rules/contact-variant.yaml +76 -0
  517. package/rules/count-over-capacity.yaml +55 -0
  518. package/rules/date-outside-period.yaml +4 -4
  519. package/rules/date-stamp-order.yaml +82 -0
  520. package/rules/deadline-after-event.yaml +67 -0
  521. package/rules/defined-name-repeated.yaml +2 -2
  522. package/rules/due-before-issue.yaml +11 -7
  523. package/rules/duration-mismatch.yaml +7 -4
  524. package/rules/duration-product-mismatch.yaml +73 -0
  525. package/rules/fact-conflict.yaml +9 -4
  526. package/rules/heading-echo.yaml +2 -2
  527. package/rules/interval-count-mismatch.yaml +54 -0
  528. package/rules/latin-spacing.yaml +2 -2
  529. package/rules/layout-code-mismatch.yaml +68 -0
  530. package/rules/name-variant.yaml +14 -2
  531. package/rules/no-em-dash.yaml +2 -2
  532. package/rules/party-order.yaml +84 -0
  533. package/rules/preamble-length.yaml +2 -2
  534. package/rules/quantity-range-reversed.yaml +53 -0
  535. package/rules/range-band-mismatch.yaml +70 -0
  536. package/rules/rent-multiple-mismatch.yaml +61 -0
  537. package/rules/required-listed-as-preferred.yaml +102 -0
  538. package/rules/return-type-mismatch.yaml +79 -0
  539. package/rules/scaled-quantity-mismatch.yaml +69 -0
  540. package/rules/step-time-sum-mismatch.yaml +65 -0
  541. package/rules/time-range-reversed.yaml +48 -0
  542. package/rules/title-case-consistency.yaml +2 -2
  543. package/rules/total-mismatch.yaml +2 -2
  544. package/rules/undefined-term.yaml +21 -7
  545. package/rules/unit-mismatch.yaml +12 -4
  546. package/rules/unlisted-item-used.yaml +90 -0
  547. package/rules/unused-definition.yaml +2 -2
  548. package/rules/use-before-definition.yaml +2 -2
  549. package/rules/walk-time-distance-mismatch.yaml +55 -0
  550. package/src/announced-count.ts +6 -3
  551. package/src/contacts/addresses.ts +179 -0
  552. package/src/contacts/emails.ts +63 -0
  553. package/src/contacts/variants.ts +33 -0
  554. package/src/derived/battery-runtime.ts +284 -0
  555. package/src/derived/period-counts.ts +178 -0
  556. package/src/derived/session-hours.ts +62 -0
  557. package/src/derived/time-lengths.ts +229 -0
  558. package/src/derived/unit-counts.ts +18 -0
  559. package/src/derived/use-interval.ts +151 -0
  560. package/src/derived/working-hours.ts +97 -0
  561. package/src/detectors/acronym-expansion.ts +57 -2
  562. package/src/detectors/announced-count.ts +1 -0
  563. package/src/detectors/capacity-runtime.ts +128 -0
  564. package/src/detectors/capitalised-term.ts +147 -0
  565. package/src/detectors/contact-variant.ts +24 -0
  566. package/src/detectors/count-over-capacity.ts +37 -0
  567. package/src/detectors/date-outside-period.ts +5 -1
  568. package/src/detectors/date-stamp-order.ts +28 -0
  569. package/src/detectors/defined-term-form.ts +63 -7
  570. package/src/detectors/definition-use.ts +6 -2
  571. package/src/detectors/derived-numbers.ts +97 -24
  572. package/src/detectors/due-date.ts +10 -2
  573. package/src/detectors/en-shape.ts +11 -4
  574. package/src/detectors/event-deadline.ts +29 -0
  575. package/src/detectors/fact-consistency.ts +64 -3
  576. package/src/detectors/heading-case.ts +13 -4
  577. package/src/detectors/heading-echo.ts +17 -1
  578. package/src/detectors/layout-code.ts +174 -0
  579. package/src/detectors/measured-facts.ts +20 -0
  580. package/src/detectors/name-variant-model-codes.ts +27 -0
  581. package/src/detectors/name-variant.ts +99 -15
  582. package/src/detectors/orthographic-variant.ts +78 -9
  583. package/src/detectors/orthography.ts +16 -6
  584. package/src/detectors/party-order.ts +50 -0
  585. package/src/detectors/quantity-range.ts +47 -0
  586. package/src/detectors/range-band.ts +125 -0
  587. package/src/detectors/registry/capacity-runtime-mismatch.ts +4 -0
  588. package/src/detectors/registry/connection-time-short.ts +4 -0
  589. package/src/detectors/registry/contact-variant.ts +4 -0
  590. package/src/detectors/registry/count-over-capacity.ts +4 -0
  591. package/src/detectors/registry/date-stamp-order.ts +4 -0
  592. package/src/detectors/registry/duration-product-mismatch.ts +4 -0
  593. package/src/detectors/registry/event-deadline.ts +4 -0
  594. package/src/detectors/registry/interval-count-mismatch.ts +4 -0
  595. package/src/detectors/registry/layout-code-mismatch.ts +4 -0
  596. package/src/detectors/registry/party-order.ts +4 -0
  597. package/src/detectors/registry/quantity-range.ts +4 -0
  598. package/src/detectors/registry/range-band-mismatch.ts +4 -0
  599. package/src/detectors/registry/rent-multiple-mismatch.ts +4 -0
  600. package/src/detectors/registry/requirement-lists.ts +4 -0
  601. package/src/detectors/registry/return-type.ts +4 -0
  602. package/src/detectors/registry/scaled-quantity-mismatch.ts +4 -0
  603. package/src/detectors/registry/step-time-sum-mismatch.ts +4 -0
  604. package/src/detectors/registry/time-range-reversed.ts +4 -0
  605. package/src/detectors/registry/unlisted-item-used.ts +4 -0
  606. package/src/detectors/registry/walk-time-distance-mismatch.ts +4 -0
  607. package/src/detectors/rent-multiple-mismatch.ts +56 -0
  608. package/src/detectors/requirement-lists.ts +65 -0
  609. package/src/detectors/return-type.ts +30 -0
  610. package/src/detectors/scaled-quantity.ts +49 -0
  611. package/src/detectors/signals.ts +3 -1
  612. package/src/detectors/step-time-sum.ts +55 -0
  613. package/src/detectors/structure-tree.ts +42 -6
  614. package/src/detectors/structure.ts +1 -1
  615. package/src/detectors/technical-docs.ts +12 -0
  616. package/src/detectors/time-order.ts +45 -6
  617. package/src/detectors/undefined-term.ts +20 -3
  618. package/src/detectors/unit-consistency.ts +50 -38
  619. package/src/detectors/unlisted-items.ts +72 -0
  620. package/src/detectors/use-count-words.ts +32 -0
  621. package/src/detectors/use-interval.ts +51 -0
  622. package/src/detectors/walk-time-distance-mismatch.ts +45 -0
  623. package/src/document.ts +4 -1
  624. package/src/facts/approximate-tolerance.ts +19 -0
  625. package/src/facts/item-amounts.ts +94 -0
  626. package/src/facts/labelled-facts.ts +29 -7
  627. package/src/facts/measure-units.ts +31 -0
  628. package/src/facts/measures.ts +113 -25
  629. package/src/facts/retention-periods.ts +216 -0
  630. package/src/facts/table-facts.ts +3 -0
  631. package/src/facts/unit-conflicts.ts +22 -9
  632. package/src/facts/unit-equivalents.ts +70 -0
  633. package/src/facts/unit-tolerance.ts +17 -0
  634. package/src/facts/unit-word.ts +35 -0
  635. package/src/facts/written-precision.ts +23 -0
  636. package/src/kana-spelling.ts +25 -0
  637. package/src/model-codes.ts +104 -0
  638. package/src/name-spelling-chars.ts +34 -0
  639. package/src/name-variants.ts +83 -7
  640. package/src/name-word-order.ts +149 -0
  641. package/src/phone-numbers.ts +26 -6
  642. package/src/place-names.ts +53 -14
  643. package/src/plugin.ts +7 -0
  644. package/src/preamble-paragraphs.ts +21 -2
  645. package/src/profile/parse.ts +10 -0
  646. package/src/return-type.ts +361 -0
  647. package/src/spacing-code.ts +26 -0
  648. package/src/structure/amount-range.ts +16 -7
  649. package/src/structure/capacity-count.ts +196 -0
  650. package/src/structure/connection-times.ts +226 -0
  651. package/src/structure/counted-amounts.ts +5 -4
  652. package/src/structure/date-order-tie.ts +86 -0
  653. package/src/structure/date-order.ts +41 -14
  654. package/src/structure/date-outside-period.ts +77 -7
  655. package/src/structure/date-range.ts +45 -9
  656. package/src/structure/deadline-after-event.ts +67 -0
  657. package/src/structure/definition-use.ts +59 -2
  658. package/src/structure/due-date.ts +8 -32
  659. package/src/structure/labelled-date-order.ts +84 -0
  660. package/src/structure/layout-codes.ts +210 -0
  661. package/src/structure/leg-times.ts +15 -0
  662. package/src/structure/measured-amounts.ts +138 -0
  663. package/src/structure/party-order.ts +115 -0
  664. package/src/structure/quantity-range.ts +54 -0
  665. package/src/structure/range-bands.ts +316 -0
  666. package/src/structure/rent-multiple.ts +277 -0
  667. package/src/structure/requirement-lists.ts +145 -0
  668. package/src/structure/scaled-quantities.ts +225 -0
  669. package/src/structure/stamp-order.ts +100 -0
  670. package/src/structure/step-times.ts +169 -0
  671. package/src/structure/term-deadline.ts +35 -0
  672. package/src/structure/time-order.ts +8 -7
  673. package/src/structure/time-range.ts +64 -0
  674. package/src/structure/total-line.ts +63 -0
  675. package/src/structure/total.ts +41 -6
  676. package/src/structure/unlisted-items.ts +207 -0
  677. package/src/structure/version-order.ts +10 -0
  678. package/src/structure/walk-time.ts +285 -0
  679. package/src/surname-near.ts +31 -0
  680. package/src/table-cells.ts +41 -0
  681. package/src/table-names.ts +113 -0
@@ -1,14 +1,16 @@
1
1
  import type { ScopedFact } from "./fact-scope.ts";
2
2
  import { sameMeasure, type Measured } from "./measures.ts";
3
+ import { toleranceOf } from "./unit-tolerance.ts";
4
+ import { precisionTolerance, writtenHalfStep } from "./written-precision.ts";
5
+ import { approximateTolerance } from "./approximate-tolerance.ts";
3
6
 
4
7
  /**
5
8
  * 同じ名前の量を、違う単位で書いて、換算すると合わない(「距離:5 km」と「距離:3000 m」)。比べるのは同じ範囲の、同じ種類の量で、
6
- * 単位が違うものだけ。同じ単位どうしの食い違いは fact-conflict が見る。丸めた書き方(1 mile と 1.6 km)は、差が TOLERANCE 以内なら合う。
9
+ * 単位が違うものだけ。同じ単位どうしの食い違いは fact-conflict が見る。丸めた書き方(1 mile と 1.6 km)は、差が量の種類ごとの許す差(unit-tolerance)以内なら合う。
10
+ * 小数で書いた量は、書いた桁の半分までの差も合う(1.2 kg と 1,250 g)。目安の量(約1 kg)は整数でも書いた桁の半分まで合う。
7
11
  */
8
12
  export type UnitConflict = { readonly fact: ScopedFact; readonly measured: Measured; readonly other: Measured };
9
13
 
10
- const TOLERANCE = 0.02;
11
-
12
14
  const groupKey = (fact: ScopedFact): string => `${fact.scope}\u0000${fact.key}`;
13
15
 
14
16
  type Read = { readonly fact: ScopedFact; readonly measured: Measured };
@@ -17,22 +19,33 @@ type Read = { readonly fact: ScopedFact; readonly measured: Measured };
17
19
  * 一つの種類(長さなら長さ)の量のうち、前にある単位の違う量のどれとも換算して合わないもの。どれか一つと合えば、食い違いは同じ単位
18
20
  * どうし(3 km と 5 km)の側にあり、fact-conflict が見る。
19
21
  */
20
- const conflictsInDimension = (reads: readonly Read[]): UnitConflict[] =>
22
+ const conflictsInDimension = (reads: readonly Read[], halfStepOf: (measured: Measured) => number): UnitConflict[] =>
21
23
  reads.flatMap(({ fact, measured }, index) => {
22
24
  const others = reads.slice(0, index).filter((earlier) => earlier.measured.unit !== measured.unit);
23
25
  const [first] = others;
24
- if (first === undefined || others.some((earlier) => sameMeasure(earlier.measured, measured, TOLERANCE))) return [];
26
+ const agrees = (earlier: Read): boolean => {
27
+ const written = precisionTolerance(toleranceOf(measured.dimension), [halfStepOf(earlier.measured), halfStepOf(measured)]);
28
+ const approximate = [earlier, { fact, measured }].filter((read) => read.fact.approximate === true).map((read) => read.measured);
29
+ return sameMeasure(earlier.measured, measured, approximateTolerance(written, approximate));
30
+ };
31
+ if (first === undefined || others.some(agrees)) return [];
25
32
  return [{ fact, measured, other: first.measured }];
26
33
  });
27
34
 
28
- const conflictsIn = (reads: readonly Read[]): UnitConflict[] => {
35
+ const conflictsIn = (reads: readonly Read[], halfStepOf: (measured: Measured) => number): UnitConflict[] => {
29
36
  if (reads.some(({ fact }) => fact.record)) return [];
30
37
  const dimensions = [...new Set(reads.map(({ measured }) => measured.dimension))];
31
- return dimensions.flatMap((dimension) => conflictsInDimension(reads.filter(({ measured }) => measured.dimension === dimension)));
38
+ return dimensions.flatMap((dimension) =>
39
+ conflictsInDimension(
40
+ reads.filter(({ measured }) => measured.dimension === dimension),
41
+ halfStepOf,
42
+ ),
43
+ );
32
44
  };
33
45
 
34
46
  /** 範囲と名前ごとに、最初の量と単位の違う量を換算して比べる。 */
35
- export const unitConflicts = (facts: readonly ScopedFact[], measuredOf: (fact: ScopedFact) => Measured | undefined): UnitConflict[] => {
47
+ export const unitConflicts = (facts: readonly ScopedFact[], measuredOf: (fact: ScopedFact) => Measured | undefined, source: string): UnitConflict[] => {
48
+ const halfStepOf = (measured: Measured): number => writtenHalfStep(source.slice(measured.start, measured.end), measured.factors);
36
49
  const groups = new Map<string, Read[]>();
37
50
  facts.forEach((fact) => {
38
51
  const measured = measuredOf(fact);
@@ -41,5 +54,5 @@ export const unitConflicts = (facts: readonly ScopedFact[], measuredOf: (fact: S
41
54
  if (group === undefined) groups.set(groupKey(fact), [{ fact, measured }]);
42
55
  else group.push({ fact, measured });
43
56
  });
44
- return [...groups.values()].flatMap(conflictsIn);
57
+ return [...groups.values()].flatMap((reads) => conflictsIn(reads, halfStepOf));
45
58
  };
@@ -0,0 +1,70 @@
1
+ import { sameMeasure, sameUnit, type Measured, type Tolerance } from "./measures.ts";
2
+ import { toleranceOf } from "./unit-tolerance.ts";
3
+
4
+ /**
5
+ * 一つの量を二つの単位で並べて書いた所(180℃(350°F)、300 kPa (about 44 psi))。括弧の中の量は、外の量を換算して丸めたもの。
6
+ * 括弧は量のすぐ後ろ(空白一つまで)で、中は前置き(約、about)を一つまで挟んですぐ量。量の後ろに字や数が続く括弧は、換算ではない。
7
+ * どちらが元の量かは分からないので、二つの数をそれぞれの桁で丸めたものとして比べる。
8
+ */
9
+ export type UnitPair = { readonly measured: Measured; readonly other: Measured };
10
+
11
+ const OPENERS = ["(", "("];
12
+ const LETTER_OR_DIGIT = /[\p{L}\p{N}]/u;
13
+ const LATIN_LETTER = /\p{Script=Latin}/u;
14
+ const DECIMALS = /[..]([0-90-9]+)/u;
15
+ const DIGITS = /[0-90-9]+/u;
16
+ const HALF = 0.5;
17
+ const DECIMAL_BASE = 10;
18
+
19
+ const skipSpace = (source: string, offset: number): number => (source.charAt(offset) === " " ? offset + 1 : offset);
20
+
21
+ /** 前置きの後ろ。英字で終わる前置き(about)は、後ろに英字が続けば前置きではない(aboutness)。 */
22
+ const afterHedge = (source: string, offset: number, hedges: readonly string[]): number => {
23
+ const rest = source.slice(offset).toLowerCase();
24
+ const hedge = hedges.find(
25
+ (word) => rest.startsWith(word.toLowerCase()) && !(LATIN_LETTER.test(word.slice(-1)) && LATIN_LETTER.test(rest.charAt(word.length))),
26
+ );
27
+ return hedge === undefined ? offset : skipSpace(source, offset + hedge.length);
28
+ };
29
+
30
+ /** 量の後ろの括弧の中で、換算した量が始まる所。括弧が無ければ undefined。 */
31
+ const insideBracket = (source: string, end: number, hedges: readonly string[]): number | undefined => {
32
+ const open = skipSpace(source, end);
33
+ return OPENERS.includes(source.charAt(open)) ? afterHedge(source, open + 1, hedges) : undefined;
34
+ };
35
+
36
+ /**
37
+ * 書いた数を丸めた桁の半分を、基準の単位で(44 psi なら 0.5 psi、1.6 km なら 0.05 km)。0 で終わる整数は、最後の 0 の一つ上の桁で
38
+ * 丸めたとみなす(100 miles は 10 の位で ±5)。0 一つ(60、180)は 1 の位のまま。
39
+ */
40
+ const trailingZeros = (digits: string): number => {
41
+ const reversed = [...digits.normalize("NFKC")].reverse();
42
+ const nonZero = reversed.findIndex((digit) => digit !== "0");
43
+ return nonZero === -1 ? reversed.length : nonZero;
44
+ };
45
+
46
+ const halfRoundingStep = (source: string, measured: Measured): number => {
47
+ const written = source.slice(measured.start, measured.end).replace(/,/gu, "");
48
+ const decimals = DECIMALS.exec(written)?.[1]?.length;
49
+ const zeros = trailingZeros(DIGITS.exec(written)?.[0] ?? "");
50
+ const exponent = decimals === undefined ? Math.max(0, zeros - 1) : -decimals;
51
+ return HALF * DECIMAL_BASE ** exponent * Math.min(...measured.factors);
52
+ };
53
+
54
+ /** 二つの数が、同じ値をそれぞれの桁で丸めたものでありうるなら合う。温度は、オーブンの目盛りの差(unit-tolerance)までも合う。 */
55
+ const pairTolerance = (source: string, first: Measured, second: Measured): Tolerance => {
56
+ const tolerance = toleranceOf(second.dimension);
57
+ return { relative: tolerance.relative, absolute: Math.max(tolerance.absolute, halfRoundingStep(source, first) + halfRoundingStep(source, second)) };
58
+ };
59
+
60
+ /** 二つの単位で並べた量のうち、換算すると合わないもの。 */
61
+ export const unitPairs = (source: string, measured: readonly Measured[], hedges: readonly string[]): UnitPair[] => {
62
+ const byStart = new Map(measured.map((value) => [value.start, value]));
63
+ return measured.flatMap((other): UnitPair[] => {
64
+ const start = insideBracket(source, other.end, hedges);
65
+ const value = start === undefined ? undefined : byStart.get(start);
66
+ if (value === undefined || value.dimension !== other.dimension || sameUnit(value, other)) return [];
67
+ if (LETTER_OR_DIGIT.test(source.charAt(value.end))) return [];
68
+ return sameMeasure(other, value, pairTolerance(source, other, value)) ? [] : [{ measured: value, other }];
69
+ });
70
+ };
@@ -0,0 +1,17 @@
1
+ import type { Tolerance } from "./measures.ts";
2
+
3
+ /** 丸めた書き方(1 mile と 1.6 km、300 kPa と 44 psi)を合うとみなす差。大きいほうの値の 2%。 */
4
+ const ROUNDING_SHARE = 0.02;
5
+
6
+ /**
7
+ * 温度は割合では比べられない(0 ℃ の 2% は 0)。オーブンの換算表は 25 °F 刻みの目盛りに丸める(170 ℃ と 325 °F は 13 °F 違う)ので、
8
+ * 一目盛りより小さい 15 °F までの差は合うとみなす。
9
+ */
10
+ const OVEN_ROUNDING_FAHRENHEIT = 15;
11
+ const CELSIUS_PER_FAHRENHEIT_DEGREE = 5 / 9;
12
+
13
+ const DEFAULT_TOLERANCE: Tolerance = { relative: ROUNDING_SHARE, absolute: 0 };
14
+ const TEMPERATURE_TOLERANCE: Tolerance = { relative: 0, absolute: OVEN_ROUNDING_FAHRENHEIT * CELSIUS_PER_FAHRENHEIT_DEGREE };
15
+
16
+ /** 量の種類(語彙表の id)ごとの、換算して合うとみなす差。 */
17
+ export const toleranceOf = (dimension: string): Tolerance => (dimension === "unit-temperature" ? TEMPERATURE_TOLERANCE : DEFAULT_TOLERANCE);
@@ -0,0 +1,35 @@
1
+ const LATIN_WORD = /^\p{Script=Latin}+$/u;
2
+ const WORD_CHAR = /[\p{L}\p{N}]/u;
3
+ /** 単位のすぐ後ろに、数(空白一つまで)か、ハイフンでつながる語が続く。 */
4
+ const CONTINUED = /^(?:[ \t]?[0-90-9]|-[\p{L}\p{N}])/u;
5
+
6
+ const isLatinWord = (word: string): boolean => LATIN_WORD.test(word);
7
+
8
+ /** 英字の語が、語として行にあるか("x" は "box" の中では数えない)。 */
9
+ const hasWord = (line: string, word: string): boolean => {
10
+ let from = line.indexOf(word);
11
+ while (from !== -1) {
12
+ const end = from + word.length;
13
+ if (!WORD_CHAR.test(line.charAt(from - 1)) && !WORD_CHAR.test(line.charAt(end))) return true;
14
+ from = line.indexOf(word, from + 1);
15
+ }
16
+ return false;
17
+ };
18
+
19
+ /** 単位に要る文脈の語が、行にどれかあるか。英字の語は語として探し、ほかの字(オーブン、×)は字の並びとして探す。大文字と小文字は区別しない。 */
20
+ export const lineHasContext = (line: string, words: readonly string[]): boolean => {
21
+ const lowered = line.toLowerCase();
22
+ return words.some((word) => {
23
+ const target = word.toLowerCase();
24
+ return isLatinWord(target) ? hasWord(lowered, target) : lowered.includes(target);
25
+ });
26
+ };
27
+
28
+ /**
29
+ * 文脈の要る英字の単位("in")は、その言語のふつうの語でもある。単位として読むのは、語がそこで終わり("5 interns" の in ではない)、
30
+ * 後ろに数もハイフンでつながる語も続かない("1 in 3"、"2-in-1")ときだけ。文脈の要らない単位と、英字でない単位(度)は、この形を見ない。
31
+ */
32
+ export const standsAsUnitWord = (pattern: string, needsContext: boolean, after: string): boolean => {
33
+ if (!needsContext || !isLatinWord(pattern)) return true;
34
+ return !WORD_CHAR.test(after.charAt(0)) && !CONTINUED.test(after);
35
+ };
@@ -0,0 +1,23 @@
1
+ import type { Tolerance } from "./measures.ts";
2
+
3
+ const HALF = 0.5;
4
+ const DECIMAL_BASE = 10;
5
+ const DECIMALS = /[..]([0-90-9]+)/u;
6
+ /** 端の値(1.2 kg と 1,250 g)が浮動小数の誤差で外れないための余り。 */
7
+ const FLOAT_SLACK = 1 + 1e-9;
8
+
9
+ /**
10
+ * 小数で書いた量が言える幅の半分を、基準の単位で(1.2 kg は 1.15〜1.25 kg なので 0.05 kg)。書き手は小数点の後ろの最後の桁で丸めて
11
+ * 書いている。整数(410 g、1 mile)は 0:末尾の 0 が丸めか(1,200 g)は書き方から分からず、仕様の整数はふつう書いたとおりの値なので、
12
+ * 量の種類ごとの差(unit-tolerance)だけで比べる。
13
+ */
14
+ export const writtenHalfStep = (written: string, factors: readonly number[]): number => {
15
+ const decimals = DECIMALS.exec(written)?.[1]?.length;
16
+ return decimals === undefined || factors.length === 0 ? 0 : HALF * DECIMAL_BASE ** -decimals * Math.max(...factors) * FLOAT_SLACK;
17
+ };
18
+
19
+ /** 二つの量を比べるときの、合うとみなす差。粗いほうの量の書いた桁の半分が、量の種類ごとの差より広ければそちら。 */
20
+ export const precisionTolerance = (tolerance: Tolerance, halfSteps: readonly number[]): Tolerance => ({
21
+ relative: tolerance.relative,
22
+ absolute: Math.max(tolerance.absolute, ...halfSteps),
23
+ });
@@ -22,6 +22,31 @@ export const kanjiSkeleton = (text: string): string => [...text.matchAll(KANJI)]
22
22
  export const dropsOkurigana = (spelling: string, spellings: readonly string[]): boolean =>
23
23
  spelling !== "" && kanjiSkeleton(spelling) === spelling && spellings.some((other) => other !== spelling && kanjiSkeleton(other) === spelling);
24
24
 
25
+ const KANJI_OR_KANA_RUN = /[\p{Script=Han}々]|[^\p{Script=Han}々]+/gu;
26
+
27
+ /**
28
+ * Whether a spelling writes in kana part of the word another spells with more kanji (かたくり粉 beside 片栗粉, とり扱い beside
29
+ * 取り扱い): every kanji it keeps stands where the other has it, each kana run stands for something there, and the other keeps
30
+ * more kanji. Only the letters are compared; the caller has already matched the readings.
31
+ */
32
+ export const isKanaForKanji = (partial: string, full: string): boolean => {
33
+ const kept = kanjiSkeleton(partial);
34
+ if (kept === "" || kept === partial || [...kanjiSkeleton(full)].length <= [...kept].length) return false;
35
+ const pattern = [...partial.matchAll(KANJI_OR_KANA_RUN)].map(([part]) => (kanjiSkeleton(part) === part ? part : ".+")).join("");
36
+ return new RegExp(`^${pattern}$`, "u").test(full);
37
+ };
38
+
39
+ /**
40
+ * The kanji a spelling is keyed by among spellings of one reading: its own, or, when it writes part of the word in kana
41
+ * (かたくり粉), the kanji of the spelling with more kanji it stands for (片栗粉). When it could stand for two (two words of one
42
+ * reading), its own.
43
+ */
44
+ export const kanjiKeyAmong = (spelling: string, spellings: readonly string[]): string => {
45
+ const fuller = new Set(spellings.filter((other) => isKanaForKanji(spelling, other)).map(kanjiSkeleton));
46
+ const [only] = fuller;
47
+ return fuller.size === 1 && only !== undefined ? only : kanjiSkeleton(spelling);
48
+ };
49
+
25
50
  /** The length, in UTF-16 units, of the start both strings share, compared character by character (𠮟 is one character, two units). */
26
51
  const sharedPrefixLength = (left: string, right: string): number => {
27
52
  const [leftChars, rightChars] = [[...left], [...right]];
@@ -0,0 +1,104 @@
1
+ // 型番の書き分け(KM-SP300 と KM-SP-300、KMSP300、km-sp300)。型番と読むのは、文書の題か型番の欄(語彙表 model-code-label)の後ろに
2
+ // 書いた、英大文字と数字を合わせた語だけ。ハイフン・空白・大小・幅を除いて同じ字の並びになるものを同じ型番と見る。字や数の違う
3
+ // 型番(KM-SP300 と KM-SP310)は別の型番なので比べない。
4
+
5
+ export type ModelCode = { readonly offset: number; readonly surface: string };
6
+ export type ModelCodeVariant = { readonly code: ModelCode; readonly usual: string };
7
+
8
+ /** 型番と読む字の数(ハイフンと空白を除く)の下限。S3 や v2 は短すぎて型番か分からない。 */
9
+ const MIN_KEY_LENGTH = 4;
10
+
11
+ const ALNUM = "A-Za-z0-9A-Za-z0-9";
12
+ const HYPHENS = "\\-‐‑-";
13
+ /** 型番の字の間に書いてよい区切り。 */
14
+ const SEPARATOR = `[${HYPHENS} ]?`;
15
+ /** 型番の前に来れば、より長い語・パス・URL・ファイル名・色(#FF0000)の一部。 */
16
+ const BEFORE_OTHER = new RegExp(`[${ALNUM}${HYPHENS}_./\\\\@=#]$`, "u");
17
+ /** 型番の後ろに来れば、より長い語・パス・ファイル名(.pdf)・版(.2)の一部。 */
18
+ const AFTER_OTHER = new RegExp(`^(?:[${ALNUM}${HYPHENS}_/\\\\]|\\.[${ALNUM}])`, "u");
19
+ const CODE_SHAPE = new RegExp(`[${ALNUM}]+(?:[${HYPHENS}][${ALNUM}]+)*`, "gu");
20
+ const URL = /(?:https?:\/\/|www\.)[^\s<>"'))」]+/gu;
21
+
22
+ /** ハイフン・空白・大小・幅を除いた字の並び。同じ並びなら同じ型番。 */
23
+ export const modelCodeKey = (surface: string): string =>
24
+ surface
25
+ .normalize("NFKC")
26
+ .toLowerCase()
27
+ .replaceAll(/[\s\-‐‑]/gu, "");
28
+
29
+ /** 英大文字と数字を両方含み、英小文字を含まない、短すぎない語。iOS17 や v1 は型番と読まない。 */
30
+ export const isModelCodeShape = (surface: string): boolean => {
31
+ const key = modelCodeKey(surface);
32
+ const ascii = surface.normalize("NFKC");
33
+ return key.length >= MIN_KEY_LENGTH && /[A-Z]/u.test(ascii) && /\d/u.test(ascii) && !/[a-z]/u.test(ascii);
34
+ };
35
+
36
+ const standsAlone = (text: string, start: number, end: number): boolean =>
37
+ !BEFORE_OTHER.test(text.slice(Math.max(0, start - 1), start)) && !AFTER_OTHER.test(text.slice(end, end + 2));
38
+
39
+ /** 範囲の中の、型番の形をした語。 */
40
+ export const codesInTitle = (text: string, start: number, end: number): ModelCode[] =>
41
+ [...text.slice(start, end).matchAll(CODE_SHAPE)]
42
+ .map((match) => ({ offset: start + match.index, surface: match[0] }))
43
+ .filter((code) => isModelCodeShape(code.surface) && standsAlone(text, code.offset, code.offset + code.surface.length));
44
+
45
+ const escaped = (pattern: string): string => pattern.replaceAll(/[.*+?^${}()|[\]\\]/gu, "\\$&");
46
+
47
+ /** 欄の語の直後(「:」や空白を挟んでよい)に書いた、型番の形をした語。英字の欄の語は大小を問わず、語の途中からは読まない。 */
48
+ export const codesAfterLabels = (text: string, labels: readonly string[]): ModelCode[] => {
49
+ if (labels.length === 0) return [];
50
+ const alternatives = labels.toSorted((left, right) => right.length - left.length).map(escaped);
51
+ const pattern = new RegExp(
52
+ `(?<![A-Za-z])(?:${alternatives.join("|")})(?![A-Za-z])[ \\t]*[::]?[ \\t\\u3000]*([${ALNUM}]+(?:[${HYPHENS}][${ALNUM}]+)*)`,
53
+ "giu",
54
+ );
55
+ return [...text.matchAll(pattern)]
56
+ .map((match) => ({ offset: match.index + match[0].length - (match[1] ?? "").length, surface: match[1] ?? "" }))
57
+ .filter((code) => isModelCodeShape(code.surface) && standsAlone(text, code.offset, code.offset + code.surface.length));
58
+ };
59
+
60
+ /** 一つの字の、大小と全角の形。 */
61
+ const charClass = (char: string): string => {
62
+ const forms = new Set([char, char.toUpperCase(), char.toLowerCase()].flatMap((form) => [form, String.fromCodePoint((form.codePointAt(0) ?? 0) + 0xfee0)]));
63
+ return `[${[...forms].join("")}]`;
64
+ };
65
+
66
+ const urlSpans = (text: string): { start: number; end: number }[] =>
67
+ [...text.matchAll(URL)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
68
+
69
+ /** 字の並びが key と同じになる語のすべて。字の間にはハイフンか空白を一つまで挟んでよい。URL の中は読まない。 */
70
+ export const codesWithKey = (text: string, key: string): ModelCode[] => {
71
+ const pattern = new RegExp([...key].map(charClass).join(SEPARATOR), "gu");
72
+ const urls = urlSpans(text);
73
+ return [...text.matchAll(pattern)]
74
+ .map((match) => ({ offset: match.index, surface: match[0] }))
75
+ .filter((code) => standsAlone(text, code.offset, code.offset + code.surface.length))
76
+ .filter((code) => !urls.some((url) => url.start <= code.offset && code.offset < url.end));
77
+ };
78
+
79
+ const countsOf = (codes: readonly ModelCode[]): Map<string, number> =>
80
+ codes.reduce((counts, code) => counts.set(code.surface, (counts.get(code.surface) ?? 0) + 1), new Map<string, number>());
81
+
82
+ /** 一番多く書いた形。数が同じなら、題か欄に先に書いた形。 */
83
+ const usualOf = (codes: readonly ModelCode[], anchor: string): string => {
84
+ const counts = countsOf(codes);
85
+ const most = Math.max(...counts.values());
86
+ return (counts.get(anchor) ?? 0) === most ? anchor : ([...counts].find(([, count]) => count === most)?.[0] ?? anchor);
87
+ };
88
+
89
+ /** 一つの型番の、少ないほうの形。型番が二度以上出てこなければ、比べるものが無い。 */
90
+ const variantsOfKey = (text: string, anchor: ModelCode): ModelCodeVariant[] => {
91
+ const codes = codesWithKey(text, modelCodeKey(anchor.surface));
92
+ if (codes.length < 2) return [];
93
+ const usual = usualOf(codes, anchor.surface);
94
+ return codes.filter((code) => code.surface !== usual).map((code) => ({ code, usual }));
95
+ };
96
+
97
+ /**
98
+ * 文書の型番(題か欄に書いたもの)を、ほかの所で別の形に書いた所。anchors は文書の順。同じ字の並びの型番は一度だけ見る。
99
+ */
100
+ export const modelCodeVariants = (text: string, anchors: readonly ModelCode[]): ModelCodeVariant[] => {
101
+ const keys = anchors.map((anchor) => modelCodeKey(anchor.surface));
102
+ const firstPerKey = anchors.filter((_, index) => keys.indexOf(keys[index] ?? "") === index);
103
+ return firstPerKey.flatMap((anchor) => variantsOfKey(text, anchor)).toSorted((left, right) => left.code.offset - right.code.offset);
104
+ };
@@ -0,0 +1,34 @@
1
+ import type { NameMention } from "./name-variants.ts";
2
+
3
+ // 一語の名前の中で、同じ音を二通りに書く字(桜ヶ丘・桜ケ丘・桜が丘、霞ヶ関・霞が関)。どの字が同じかは語彙表 name-spelling-char が
4
+ // 組(group)ごとに言う。漢字に挟まれた字だけを寄せる。かなの語の中の字は寄せない。名前は解析器が一語と読んだもの
5
+ // (霞が関)に限る。桜・が・丘 と読む書き方を本文にそのまま探すと、助詞の が(桜が丘を彩る)を名前と取り違える。
6
+
7
+ /** 字から、その組の代表の字へ。 */
8
+ export type SpellingChars = ReadonlyMap<string, string>;
9
+
10
+ /**
11
+ * 名前の中の同じ音の字を比べる材料。chars はその字の組。alsoWritten は、この比べ方にだけ加える名前の現れ(表の升の名前)。升の名前をほかの見方に加えると、表の識別子(contentType)を本文の名前(Content-Type)と比べてしまう。
12
+ */
13
+ export type SpellingInput = { readonly chars: SpellingChars; readonly alsoWritten: readonly NameMention[] };
14
+
15
+ export const NO_SPELLING: SpellingInput = { chars: new Map(), alsoWritten: [] };
16
+
17
+ const HAN = /^\p{Script=Han}$/u;
18
+
19
+ const isBetweenHan = (chars: readonly string[], index: number): boolean => HAN.test(chars[index - 1] ?? "") && HAN.test(chars[index + 1] ?? "");
20
+
21
+ /** 漢字に挟まれた、組のある字の位置。 */
22
+ const foldableAt = (chars: readonly string[], spelling: SpellingChars): number[] =>
23
+ chars.flatMap((char, index) => (spelling.has(char) && isBetweenHan(chars, index) ? [index] : []));
24
+
25
+ /** 漢字に挟まれた組の字を、組の代表に寄せた形。寄せる字が無ければ書いたまま。 */
26
+ export const foldSpelling = (surface: string, spelling: SpellingChars): string => {
27
+ const chars = [...surface];
28
+ const at = new Set(foldableAt(chars, spelling));
29
+ return chars.map((char, index) => (at.has(index) ? (spelling.get(char) ?? char) : char)).join("");
30
+ };
31
+
32
+ /** 比べる形。漢字に挟まれた組の字を含む名前だけが、寄せた形を一つ持つ。含まない名前(Content-Type)はこの比べ方に入らない。 */
33
+ export const foldedKeysOf = (surface: string, spelling: SpellingChars): string[] =>
34
+ foldableAt([...surface], spelling).length > 0 ? [foldSpelling(surface, spelling)] : [];
@@ -1,6 +1,8 @@
1
1
  import type { Token } from "./plugin.ts";
2
2
  import { escapeRegExp } from "./orthography.ts";
3
3
  import { nameCueAt, type NameCue, type NameCues } from "./name-cue.ts";
4
+ import { isNearSurname } from "./surname-near.ts";
5
+ import { foldedKeysOf, NO_SPELLING, type SpellingInput } from "./name-spelling-chars.ts";
4
6
 
5
7
  // 同じ名前(人・会社・製品)を、文書の中で少しだけ違う形に書いた所。どの形が正しいかは決めず、少ないほうを指す。
6
8
  // 三通りで同じ名前と見る。書き方の違いだけ(GitHub と Github、Mac OS と macOS)、読みが同じ(山田太郎 と 山田太朗)、
@@ -19,7 +21,11 @@ export type NameMention = {
19
21
  readonly cue?: NameCue;
20
22
  };
21
23
 
22
- export type NameVariant = { readonly mention: NameMention; readonly usual: string; readonly kind: "spelling" | "reading" | "near" | "character" };
24
+ export type NameVariant = {
25
+ readonly mention: NameMention;
26
+ readonly usual: string;
27
+ readonly kind: "spelling" | "kana" | "reading" | "near" | "surname" | "character";
28
+ };
23
29
 
24
30
  /** 字体の違う同じ字(斎・斉・齋)。字から、その組の代表の字へ。 */
25
31
  export type VariantChars = ReadonlyMap<string, string>;
@@ -99,6 +105,61 @@ export const mentionsIn = (tokens: readonly Token[], source: string, personSuffi
99
105
  return [{ surface, offset: first.span.start, reading, words: words.map((token) => token.surface), person }];
100
106
  });
101
107
 
108
+ /** 隣の語を探す範囲(UTF-16 の単位)。 */
109
+ const NEIGHBOUR_LOOKBACK = 40;
110
+ /** 隣の語の外側の記号((Rachel、Floyd.)。名前の側の記号(Rachel, Whitford の ,)は語を切るので残す。 */
111
+ const MARK = /\p{P}/u;
112
+ const withoutLeadingMarks = (word: string): string => {
113
+ const chars = [...word];
114
+ const start = chars.findIndex((char) => !MARK.test(char));
115
+ return start < 0 ? "" : chars.slice(start).join("");
116
+ };
117
+ const withoutTrailingMarks = (word: string): string => {
118
+ const chars = [...word];
119
+ return chars.slice(0, chars.findLastIndex((char) => !MARK.test(char)) + 1).join("");
120
+ };
121
+
122
+ const wordBeforeAt = (source: string, offset: number): string | undefined => {
123
+ if (source.charAt(offset - 1) !== " ") return undefined;
124
+ const from = Math.max(0, offset - 1 - NEIGHBOUR_LOOKBACK);
125
+ const parts = source.slice(from, offset - 1).split(/\s/u);
126
+ const word = withoutLeadingMarks(parts.at(-1) ?? "");
127
+ return word === "" || (from > 0 && parts.length === 1) ? undefined : word;
128
+ };
129
+
130
+ const wordAfterAt = (source: string, end: number): string | undefined => {
131
+ if (source.charAt(end) !== " ") return undefined;
132
+ const word = withoutTrailingMarks(source.slice(end + 1, end + 1 + NEIGHBOUR_LOOKBACK).split(/\s/u)[0] ?? "");
133
+ return word === "" ? undefined : word;
134
+ };
135
+
136
+ /**
137
+ * 解析器が名前の一語を名前と読まなかった所(to Rachel Whitford の Rachel を動詞と読む)。空白一つで隣の語と合わせた形を、ほかの所で
138
+ * 名前と読めていれば、その形の現れと見る。隣の語がほかの名前の現れに入るなら合わせない。
139
+ */
140
+ export const withKnownNeighbours = (mentions: readonly NameMention[], source: string): NameMention[] => {
141
+ const known = new Set(mentions.filter((mention) => mention.words.length >= 2).map((mention) => mention.surface));
142
+ const taken = (start: number, end: number): boolean => mentions.some((mention) => mention.offset < end && start < mention.offset + mention.surface.length);
143
+ return mentions.map((mention) => {
144
+ const end = mention.offset + mention.surface.length;
145
+ const before = wordBeforeAt(source, mention.offset);
146
+ const after = wordAfterAt(source, end);
147
+ if (before !== undefined && known.has(`${before} ${mention.surface}`) && !taken(mention.offset - 1 - before.length, mention.offset - 1)) {
148
+ return {
149
+ ...mention,
150
+ surface: `${before} ${mention.surface}`,
151
+ offset: mention.offset - 1 - before.length,
152
+ reading: undefined,
153
+ words: [before, ...mention.words],
154
+ };
155
+ }
156
+ if (after !== undefined && known.has(`${mention.surface} ${after}`) && !taken(end + 1, end + 1 + after.length)) {
157
+ return { ...mention, surface: `${mention.surface} ${after}`, reading: undefined, words: [...mention.words, after] };
158
+ }
159
+ return mention;
160
+ });
161
+ };
162
+
102
163
  /** 敬称の前の名前の字数(髙橋、髙橋太郎)。長い漢字の連なり(株式会社髙橋)は名前だけを切り出せない。 */
103
164
  const MAX_SUFFIXED_NAME = 4;
104
165
  const MIN_SUFFIXED_NAME = 2;
@@ -283,6 +344,20 @@ const isSlipOf = (tally: Tally, other: Tally): boolean => {
283
344
 
284
345
  const nearVariants = (tallies: readonly Tally[]): NameVariant[] => variantsIn(groupBy(tallies, maskedKeys), "near", isSlipOf);
285
346
 
347
+ /**
348
+ * 名が同じで姓だけが二字ほど違う人の名前(Rachel Whitford と Rachel Whitfield)。一字違い(near)より遠いので、名と姓の二語以上
349
+ * で、違うのが最後の語のときに限る。相手が二度以上、こちらが一度だけ。名の違う二人(Sara Whitford と Rachel Whitfield)は比べない。
350
+ */
351
+ const isSurnameSlipOf = (tally: Tally, other: Tally): boolean => {
352
+ if (tally.count !== 1 || other.count < 2) return false;
353
+ const [words, others] = [wordsOf(tally.surface), wordsOf(other.surface)];
354
+ const last = words.length - 1;
355
+ const sameBefore = words.slice(0, last).every((word, index) => word === others[index]);
356
+ return last >= 1 && words.length === others.length && sameBefore && isNearSurname(words[last] ?? "", others[last] ?? "");
357
+ };
358
+
359
+ const surnameVariants = (tallies: readonly Tally[]): NameVariant[] => variantsIn(groupBy(tallies, maskedKeys), "surname", isSurnameSlipOf);
360
+
286
361
  /** 字体の違う字(斎と斉)を組の代表の字に寄せた形。 */
287
362
  const characterKey = (tally: Tally, chars: VariantChars): string => [...tally.surface].map((letter) => chars.get(letter) ?? letter).join("");
288
363
 
@@ -331,28 +406,29 @@ const personReadingVariants = (tallies: readonly Tally[]): NameVariant[] =>
331
406
  * 同じ名前の、少ないほうの書き方。書き方ごとに最初の現れを一つ。同じ現れを二つの見方が言えば、先の見方だけ。chars は字体の
332
407
  * 違う同じ字の組(語彙表 name-variant-char)。
333
408
  */
334
- export const nameVariants = (mentions: readonly NameMention[], chars: VariantChars = new Map()): NameVariant[] => {
409
+ export const nameVariants = (mentions: readonly NameMention[], chars: VariantChars = new Map(), spelling: SpellingInput = NO_SPELLING): NameVariant[] => {
335
410
  const tallies = talliesOf(mentions);
336
411
  const found = [
337
412
  ...variantsIn(
338
413
  groupBy(tallies, (tally) => [nameKey(tally.surface)]),
339
414
  "spelling",
340
415
  ),
416
+ ...variantsIn(
417
+ groupBy(talliesOf([...mentions, ...spelling.alsoWritten]), (tally) => foldedKeysOf(tally.surface, spelling.chars).map(nameKey)),
418
+ "kana",
419
+ ),
341
420
  ...variantsIn(
342
421
  groupBy(tallies, (tally) => (tally.first.reading === undefined ? [] : [tally.first.reading])),
343
422
  "reading",
344
423
  oneWordApart,
345
424
  ),
346
425
  ...nearVariants(tallies),
426
+ ...surnameVariants(tallies),
347
427
  ...characterVariants(tallies, chars),
348
428
  ...personReadingVariants(tallies),
349
429
  ];
350
430
  const reported = new Set<string>();
351
431
  return found
352
- .filter((variant) => {
353
- if (reported.has(variant.mention.surface)) return false;
354
- reported.add(variant.mention.surface);
355
- return true;
356
- })
432
+ .filter((variant) => !reported.has(variant.mention.surface) && reported.add(variant.mention.surface).size > 0)
357
433
  .toSorted((left, right) => left.mention.offset - right.mention.offset);
358
434
  };