chaffjs 0.33.0 → 0.34.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 (467) hide show
  1. package/dist/api.d.ts +7 -1
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js.map +1 -1
  4. package/dist/cli-text.d.ts.map +1 -1
  5. package/dist/cli-text.js +4 -2
  6. package/dist/cli-text.js.map +1 -1
  7. package/dist/commands/grade.d.ts.map +1 -1
  8. package/dist/commands/grade.js +66 -21
  9. package/dist/commands/grade.js.map +1 -1
  10. package/dist/company-kana-spelling.d.ts +6 -1
  11. package/dist/company-kana-spelling.d.ts.map +1 -1
  12. package/dist/company-kana-spelling.js +19 -2
  13. package/dist/company-kana-spelling.js.map +1 -1
  14. package/dist/company-name-ending.d.ts +7 -0
  15. package/dist/company-name-ending.d.ts.map +1 -0
  16. package/dist/company-name-ending.js +44 -0
  17. package/dist/company-name-ending.js.map +1 -0
  18. package/dist/company-names.d.ts +11 -3
  19. package/dist/company-names.d.ts.map +1 -1
  20. package/dist/company-names.js +27 -14
  21. package/dist/company-names.js.map +1 -1
  22. package/dist/custom/no-rewrite.d.ts +3 -0
  23. package/dist/custom/no-rewrite.d.ts.map +1 -0
  24. package/dist/custom/no-rewrite.js +3 -0
  25. package/dist/custom/no-rewrite.js.map +1 -0
  26. package/dist/custom/parse.d.ts.map +1 -1
  27. package/dist/custom/parse.js +14 -2
  28. package/dist/custom/parse.js.map +1 -1
  29. package/dist/detectors/age-words.d.ts +5 -0
  30. package/dist/detectors/age-words.d.ts.map +1 -0
  31. package/dist/detectors/age-words.js +8 -0
  32. package/dist/detectors/age-words.js.map +1 -0
  33. package/dist/detectors/annual-pay-mismatch.d.ts.map +1 -1
  34. package/dist/detectors/annual-pay-mismatch.js +2 -12
  35. package/dist/detectors/annual-pay-mismatch.js.map +1 -1
  36. package/dist/detectors/blank-structure.d.ts.map +1 -1
  37. package/dist/detectors/blank-structure.js +4 -3
  38. package/dist/detectors/blank-structure.js.map +1 -1
  39. package/dist/detectors/closing-balance-mismatch.d.ts.map +1 -1
  40. package/dist/detectors/closing-balance-mismatch.js +1 -0
  41. package/dist/detectors/closing-balance-mismatch.js.map +1 -1
  42. package/dist/detectors/code-fences.d.ts +5 -0
  43. package/dist/detectors/code-fences.d.ts.map +1 -1
  44. package/dist/detectors/code-fences.js +9 -0
  45. package/dist/detectors/code-fences.js.map +1 -1
  46. package/dist/detectors/condition-toki.d.ts +16 -0
  47. package/dist/detectors/condition-toki.d.ts.map +1 -0
  48. package/dist/detectors/condition-toki.js +42 -0
  49. package/dist/detectors/condition-toki.js.map +1 -0
  50. package/dist/detectors/conjugated-entry.d.ts +17 -0
  51. package/dist/detectors/conjugated-entry.d.ts.map +1 -0
  52. package/dist/detectors/conjugated-entry.js +50 -0
  53. package/dist/detectors/conjugated-entry.js.map +1 -0
  54. package/dist/detectors/content-morphemes.d.ts +2 -0
  55. package/dist/detectors/content-morphemes.d.ts.map +1 -1
  56. package/dist/detectors/content-morphemes.js +1 -1
  57. package/dist/detectors/content-morphemes.js.map +1 -1
  58. package/dist/detectors/cross-facts.d.ts.map +1 -1
  59. package/dist/detectors/cross-facts.js +2 -1
  60. package/dist/detectors/cross-facts.js.map +1 -1
  61. package/dist/detectors/custom.d.ts.map +1 -1
  62. package/dist/detectors/custom.js +8 -2
  63. package/dist/detectors/custom.js.map +1 -1
  64. package/dist/detectors/document-shape.d.ts.map +1 -1
  65. package/dist/detectors/document-shape.js +6 -0
  66. package/dist/detectors/document-shape.js.map +1 -1
  67. package/dist/detectors/due-date.d.ts.map +1 -1
  68. package/dist/detectors/due-date.js +12 -2
  69. package/dist/detectors/due-date.js.map +1 -1
  70. package/dist/detectors/fact-consistency.d.ts.map +1 -1
  71. package/dist/detectors/fact-consistency.js +12 -13
  72. package/dist/detectors/fact-consistency.js.map +1 -1
  73. package/dist/detectors/form-line.d.ts +9 -0
  74. package/dist/detectors/form-line.d.ts.map +1 -0
  75. package/dist/detectors/form-line.js +36 -0
  76. package/dist/detectors/form-line.js.map +1 -0
  77. package/dist/detectors/formula-amount.d.ts.map +1 -1
  78. package/dist/detectors/formula-amount.js +2 -12
  79. package/dist/detectors/formula-amount.js.map +1 -1
  80. package/dist/detectors/heading-claim.d.ts +14 -0
  81. package/dist/detectors/heading-claim.d.ts.map +1 -0
  82. package/dist/detectors/heading-claim.js +49 -0
  83. package/dist/detectors/heading-claim.js.map +1 -0
  84. package/dist/detectors/heading-echo.d.ts.map +1 -1
  85. package/dist/detectors/heading-echo.js +29 -1
  86. package/dist/detectors/heading-echo.js.map +1 -1
  87. package/dist/detectors/installment-total-mismatch.d.ts.map +1 -1
  88. package/dist/detectors/installment-total-mismatch.js +2 -12
  89. package/dist/detectors/installment-total-mismatch.js.map +1 -1
  90. package/dist/detectors/list-parallel.d.ts +5 -2
  91. package/dist/detectors/list-parallel.d.ts.map +1 -1
  92. package/dist/detectors/list-parallel.js +45 -7
  93. package/dist/detectors/list-parallel.js.map +1 -1
  94. package/dist/detectors/name-variant.d.ts.map +1 -1
  95. package/dist/detectors/name-variant.js +34 -7
  96. package/dist/detectors/name-variant.js.map +1 -1
  97. package/dist/detectors/number-unit.d.ts +10 -0
  98. package/dist/detectors/number-unit.d.ts.map +1 -1
  99. package/dist/detectors/number-unit.js +28 -8
  100. package/dist/detectors/number-unit.js.map +1 -1
  101. package/dist/detectors/orthography.d.ts.map +1 -1
  102. package/dist/detectors/orthography.js +16 -7
  103. package/dist/detectors/orthography.js.map +1 -1
  104. package/dist/detectors/per-unit-words.d.ts +7 -0
  105. package/dist/detectors/per-unit-words.d.ts.map +1 -0
  106. package/dist/detectors/per-unit-words.js +17 -0
  107. package/dist/detectors/per-unit-words.js.map +1 -0
  108. package/dist/detectors/period-multiple-mismatch.d.ts.map +1 -1
  109. package/dist/detectors/period-multiple-mismatch.js +2 -12
  110. package/dist/detectors/period-multiple-mismatch.js.map +1 -1
  111. package/dist/detectors/reference-number-variant.d.ts.map +1 -1
  112. package/dist/detectors/reference-number-variant.js +21 -3
  113. package/dist/detectors/reference-number-variant.js.map +1 -1
  114. package/dist/detectors/registry/condition-toki.d.ts +3 -0
  115. package/dist/detectors/registry/condition-toki.d.ts.map +1 -0
  116. package/dist/detectors/registry/condition-toki.js +3 -0
  117. package/dist/detectors/registry/condition-toki.js.map +1 -0
  118. package/dist/detectors/rent-multiple-mismatch.d.ts.map +1 -1
  119. package/dist/detectors/rent-multiple-mismatch.js +2 -12
  120. package/dist/detectors/rent-multiple-mismatch.js.map +1 -1
  121. package/dist/detectors/row-sentence-amounts.d.ts.map +1 -1
  122. package/dist/detectors/row-sentence-amounts.js +5 -10
  123. package/dist/detectors/row-sentence-amounts.js.map +1 -1
  124. package/dist/detectors/stated-amounts.d.ts +4 -0
  125. package/dist/detectors/stated-amounts.d.ts.map +1 -0
  126. package/dist/detectors/stated-amounts.js +12 -0
  127. package/dist/detectors/stated-amounts.js.map +1 -0
  128. package/dist/detectors/step-time-sum.d.ts.map +1 -1
  129. package/dist/detectors/step-time-sum.js +2 -1
  130. package/dist/detectors/step-time-sum.js.map +1 -1
  131. package/dist/detectors/structure-tree.d.ts.map +1 -1
  132. package/dist/detectors/structure-tree.js +3 -0
  133. package/dist/detectors/structure-tree.js.map +1 -1
  134. package/dist/detectors/team.d.ts.map +1 -1
  135. package/dist/detectors/team.js +10 -6
  136. package/dist/detectors/team.js.map +1 -1
  137. package/dist/detectors/time-order.d.ts.map +1 -1
  138. package/dist/detectors/time-order.js +17 -13
  139. package/dist/detectors/time-order.js.map +1 -1
  140. package/dist/detectors/unknown-word.d.ts +4 -1
  141. package/dist/detectors/unknown-word.d.ts.map +1 -1
  142. package/dist/detectors/unknown-word.js +18 -2
  143. package/dist/detectors/unknown-word.js.map +1 -1
  144. package/dist/detectors/use-interval.d.ts +1 -0
  145. package/dist/detectors/use-interval.d.ts.map +1 -1
  146. package/dist/detectors/use-interval.js +15 -10
  147. package/dist/detectors/use-interval.js.map +1 -1
  148. package/dist/detectors/use-maximum.d.ts.map +1 -1
  149. package/dist/detectors/use-maximum.js +3 -1
  150. package/dist/detectors/use-maximum.js.map +1 -1
  151. package/dist/extension/document-view.d.ts +2 -2
  152. package/dist/extension/document-view.d.ts.map +1 -1
  153. package/dist/extension/document-view.js +17 -8
  154. package/dist/extension/document-view.js.map +1 -1
  155. package/dist/extension/entry-genres.d.ts +5 -0
  156. package/dist/extension/entry-genres.d.ts.map +1 -0
  157. package/dist/extension/entry-genres.js +13 -0
  158. package/dist/extension/entry-genres.js.map +1 -0
  159. package/dist/extension/module-detector.d.ts.map +1 -1
  160. package/dist/extension/module-detector.js +4 -4
  161. package/dist/extension/module-detector.js.map +1 -1
  162. package/dist/extension/plugin-parse.d.ts +1 -1
  163. package/dist/extension/plugin-parse.d.ts.map +1 -1
  164. package/dist/extension/plugin-parse.js +24 -7
  165. package/dist/extension/plugin-parse.js.map +1 -1
  166. package/dist/extension/problem-text.d.ts.map +1 -1
  167. package/dist/extension/problem-text.js +2 -0
  168. package/dist/extension/problem-text.js.map +1 -1
  169. package/dist/facts/age-values.d.ts.map +1 -1
  170. package/dist/facts/age-values.js +20 -2
  171. package/dist/facts/age-values.js.map +1 -1
  172. package/dist/facts/column-units.d.ts +31 -0
  173. package/dist/facts/column-units.d.ts.map +1 -0
  174. package/dist/facts/column-units.js +37 -0
  175. package/dist/facts/column-units.js.map +1 -0
  176. package/dist/facts/fact-values.d.ts +4 -0
  177. package/dist/facts/fact-values.d.ts.map +1 -1
  178. package/dist/facts/fact-values.js +3 -1
  179. package/dist/facts/fact-values.js.map +1 -1
  180. package/dist/facts/labelled-facts.d.ts +10 -0
  181. package/dist/facts/labelled-facts.d.ts.map +1 -1
  182. package/dist/facts/labelled-facts.js +6 -1
  183. package/dist/facts/labelled-facts.js.map +1 -1
  184. package/dist/facts/per-unit.d.ts +36 -0
  185. package/dist/facts/per-unit.d.ts.map +1 -0
  186. package/dist/facts/per-unit.js +56 -0
  187. package/dist/facts/per-unit.js.map +1 -0
  188. package/dist/facts/row-sentence-amounts.d.ts +3 -12
  189. package/dist/facts/row-sentence-amounts.d.ts.map +1 -1
  190. package/dist/facts/row-sentence-amounts.js +1 -15
  191. package/dist/facts/row-sentence-amounts.js.map +1 -1
  192. package/dist/facts/table-facts.d.ts +1 -1
  193. package/dist/facts/table-facts.d.ts.map +1 -1
  194. package/dist/facts/table-facts.js +13 -9
  195. package/dist/facts/table-facts.js.map +1 -1
  196. package/dist/facts/term-values.d.ts +13 -1
  197. package/dist/facts/term-values.d.ts.map +1 -1
  198. package/dist/facts/term-values.js +71 -12
  199. package/dist/facts/term-values.js.map +1 -1
  200. package/dist/grade/baseline.d.ts +4 -2
  201. package/dist/grade/baseline.d.ts.map +1 -1
  202. package/dist/grade/baseline.js +13 -11
  203. package/dist/grade/baseline.js.map +1 -1
  204. package/dist/grade/expect-read.d.ts +16 -0
  205. package/dist/grade/expect-read.d.ts.map +1 -0
  206. package/dist/grade/expect-read.js +52 -0
  207. package/dist/grade/expect-read.js.map +1 -0
  208. package/dist/grade/expect.d.ts +50 -0
  209. package/dist/grade/expect.d.ts.map +1 -0
  210. package/dist/grade/expect.js +53 -0
  211. package/dist/grade/expect.js.map +1 -0
  212. package/dist/grade/grade-item.d.ts +1 -1
  213. package/dist/grade/grade-item.d.ts.map +1 -1
  214. package/dist/grade/grade-item.js +13 -3
  215. package/dist/grade/grade-item.js.map +1 -1
  216. package/dist/grade/item.d.ts +9 -1
  217. package/dist/grade/item.d.ts.map +1 -1
  218. package/dist/grade/item.js +32 -7
  219. package/dist/grade/item.js.map +1 -1
  220. package/dist/grade/result.d.ts +5 -0
  221. package/dist/grade/result.d.ts.map +1 -1
  222. package/dist/grade/results-read.d.ts.map +1 -1
  223. package/dist/grade/results-read.js +4 -2
  224. package/dist/grade/results-read.js.map +1 -1
  225. package/dist/grade/rubric-file.d.ts +23 -0
  226. package/dist/grade/rubric-file.d.ts.map +1 -0
  227. package/dist/grade/rubric-file.js +35 -0
  228. package/dist/grade/rubric-file.js.map +1 -0
  229. package/dist/grade/rubric.d.ts +2 -0
  230. package/dist/grade/rubric.d.ts.map +1 -1
  231. package/dist/grade/rubric.js +75 -47
  232. package/dist/grade/rubric.js.map +1 -1
  233. package/dist/grade/setup.d.ts +2 -1
  234. package/dist/grade/setup.d.ts.map +1 -1
  235. package/dist/grade/setup.js +2 -2
  236. package/dist/grade/setup.js.map +1 -1
  237. package/dist/grade/stamp.d.ts +2 -0
  238. package/dist/grade/stamp.d.ts.map +1 -1
  239. package/dist/grade/stamp.js +8 -2
  240. package/dist/grade/stamp.js.map +1 -1
  241. package/dist/grade/task-rubric.d.ts +16 -0
  242. package/dist/grade/task-rubric.d.ts.map +1 -0
  243. package/dist/grade/task-rubric.js +34 -0
  244. package/dist/grade/task-rubric.js.map +1 -0
  245. package/dist/grade/text.d.ts +5 -1
  246. package/dist/grade/text.d.ts.map +1 -1
  247. package/dist/grade/text.js +16 -4
  248. package/dist/grade/text.js.map +1 -1
  249. package/dist/name-char-reading.d.ts +5 -0
  250. package/dist/name-char-reading.d.ts.map +1 -1
  251. package/dist/name-char-reading.js +15 -0
  252. package/dist/name-char-reading.js.map +1 -1
  253. package/dist/name-end-letter.d.ts +19 -0
  254. package/dist/name-end-letter.d.ts.map +1 -0
  255. package/dist/name-end-letter.js +37 -0
  256. package/dist/name-end-letter.js.map +1 -0
  257. package/dist/name-neighbours.d.ts.map +1 -1
  258. package/dist/name-neighbours.js +2 -1
  259. package/dist/name-neighbours.js.map +1 -1
  260. package/dist/name-separator.d.ts +6 -0
  261. package/dist/name-separator.d.ts.map +1 -1
  262. package/dist/name-separator.js +29 -0
  263. package/dist/name-separator.js.map +1 -1
  264. package/dist/name-variants.d.ts +6 -3
  265. package/dist/name-variants.d.ts.map +1 -1
  266. package/dist/name-variants.js +37 -10
  267. package/dist/name-variants.js.map +1 -1
  268. package/dist/number-name.d.ts.map +1 -1
  269. package/dist/number-name.js +11 -2
  270. package/dist/number-name.js.map +1 -1
  271. package/dist/profile/cue-lines.d.ts +6 -0
  272. package/dist/profile/cue-lines.d.ts.map +1 -0
  273. package/dist/profile/cue-lines.js +13 -0
  274. package/dist/profile/cue-lines.js.map +1 -0
  275. package/dist/profile/parse.d.ts +1 -1
  276. package/dist/profile/parse.d.ts.map +1 -1
  277. package/dist/profile/parse.js +3 -2
  278. package/dist/profile/parse.js.map +1 -1
  279. package/dist/reference-numbers.d.ts +2 -0
  280. package/dist/reference-numbers.d.ts.map +1 -1
  281. package/dist/reference-numbers.js +1 -1
  282. package/dist/reference-numbers.js.map +1 -1
  283. package/dist/spaced-person-name.d.ts.map +1 -1
  284. package/dist/spaced-person-name.js +26 -1
  285. package/dist/spaced-person-name.js.map +1 -1
  286. package/dist/spacing-code.d.ts.map +1 -1
  287. package/dist/spacing-code.js +10 -1
  288. package/dist/spacing-code.js.map +1 -1
  289. package/dist/spacing-minority.d.ts +7 -0
  290. package/dist/spacing-minority.d.ts.map +1 -1
  291. package/dist/spacing-minority.js +14 -0
  292. package/dist/spacing-minority.js.map +1 -1
  293. package/dist/structure/closing-balance.d.ts +9 -0
  294. package/dist/structure/closing-balance.d.ts.map +1 -1
  295. package/dist/structure/closing-balance.js +34 -7
  296. package/dist/structure/closing-balance.js.map +1 -1
  297. package/dist/structure/definition-use.d.ts.map +1 -1
  298. package/dist/structure/definition-use.js +20 -1
  299. package/dist/structure/definition-use.js.map +1 -1
  300. package/dist/structure/document-context.d.ts +2 -0
  301. package/dist/structure/document-context.d.ts.map +1 -0
  302. package/dist/structure/document-context.js +42 -0
  303. package/dist/structure/document-context.js.map +1 -0
  304. package/dist/structure/fenced-lines.d.ts +7 -0
  305. package/dist/structure/fenced-lines.d.ts.map +1 -0
  306. package/dist/structure/fenced-lines.js +27 -0
  307. package/dist/structure/fenced-lines.js.map +1 -0
  308. package/dist/structure/labelled-date-order.d.ts +31 -9
  309. package/dist/structure/labelled-date-order.d.ts.map +1 -1
  310. package/dist/structure/labelled-date-order.js +60 -15
  311. package/dist/structure/labelled-date-order.js.map +1 -1
  312. package/dist/structure/labelled-order.d.ts +7 -1
  313. package/dist/structure/labelled-order.d.ts.map +1 -1
  314. package/dist/structure/labelled-order.js +10 -3
  315. package/dist/structure/labelled-order.js.map +1 -1
  316. package/dist/structure/line-amount-label.d.ts.map +1 -1
  317. package/dist/structure/line-amount-label.js +2 -1
  318. package/dist/structure/line-amount-label.js.map +1 -1
  319. package/dist/structure/line-amount.d.ts +0 -5
  320. package/dist/structure/line-amount.d.ts.map +1 -1
  321. package/dist/structure/line-amount.js +1 -10
  322. package/dist/structure/line-amount.js.map +1 -1
  323. package/dist/structure/prose-total.d.ts +8 -0
  324. package/dist/structure/prose-total.d.ts.map +1 -1
  325. package/dist/structure/prose-total.js +70 -2
  326. package/dist/structure/prose-total.js.map +1 -1
  327. package/dist/structure/runs.d.ts.map +1 -1
  328. package/dist/structure/runs.js +9 -1
  329. package/dist/structure/runs.js.map +1 -1
  330. package/dist/structure/signed-date-line.d.ts +15 -0
  331. package/dist/structure/signed-date-line.d.ts.map +1 -0
  332. package/dist/structure/signed-date-line.js +68 -0
  333. package/dist/structure/signed-date-line.js.map +1 -0
  334. package/dist/structure/tax.d.ts.map +1 -1
  335. package/dist/structure/tax.js +5 -3
  336. package/dist/structure/tax.js.map +1 -1
  337. package/dist/structure/total-line.d.ts.map +1 -1
  338. package/dist/structure/total-line.js +10 -6
  339. package/dist/structure/total-line.js.map +1 -1
  340. package/dist/structure/total.d.ts +2 -0
  341. package/dist/structure/total.d.ts.map +1 -1
  342. package/dist/structure/total.js +34 -3
  343. package/dist/structure/total.js.map +1 -1
  344. package/dist/subject-codes.d.ts +21 -0
  345. package/dist/subject-codes.d.ts.map +1 -0
  346. package/dist/subject-codes.js +79 -0
  347. package/dist/subject-codes.js.map +1 -0
  348. package/dist/unlabelled-references.d.ts +6 -2
  349. package/dist/unlabelled-references.d.ts.map +1 -1
  350. package/dist/unlabelled-references.js +11 -10
  351. package/dist/unlabelled-references.js.map +1 -1
  352. package/genres.yaml +17 -0
  353. package/package.json +3 -3
  354. package/profiles/listing.yaml +1 -1
  355. package/rules/closing-balance-mismatch.yaml +3 -3
  356. package/rules/due-before-issue.yaml +9 -5
  357. package/rules/fact-conflict.yaml +2 -2
  358. package/rules/heading-echo.yaml +2 -2
  359. package/rules/internal-jargon.yaml +2 -2
  360. package/rules/latin-spacing.yaml +4 -4
  361. package/rules/list-item-form-mix.yaml +1 -1
  362. package/rules/name-variant.yaml +5 -2
  363. package/rules/no-lead.yaml +2 -2
  364. package/rules/number-without-unit.yaml +2 -2
  365. package/rules/reference-number-variant.yaml +3 -3
  366. package/rules/toki-as-condition.yaml +71 -0
  367. package/rules/total-mismatch.yaml +4 -4
  368. package/rules/unknown-word.yaml +2 -2
  369. package/rules/use-before-definition.yaml +2 -2
  370. package/src/api.ts +11 -2
  371. package/src/cli-text.ts +4 -2
  372. package/src/commands/grade.ts +75 -23
  373. package/src/company-kana-spelling.ts +22 -2
  374. package/src/company-name-ending.ts +50 -0
  375. package/src/company-names.ts +52 -17
  376. package/src/custom/no-rewrite.ts +2 -0
  377. package/src/custom/parse.ts +18 -2
  378. package/src/detectors/age-words.ts +12 -0
  379. package/src/detectors/annual-pay-mismatch.ts +3 -18
  380. package/src/detectors/blank-structure.ts +4 -3
  381. package/src/detectors/closing-balance-mismatch.ts +1 -0
  382. package/src/detectors/code-fences.ts +10 -0
  383. package/src/detectors/condition-toki.ts +60 -0
  384. package/src/detectors/conjugated-entry.ts +53 -0
  385. package/src/detectors/content-morphemes.ts +2 -1
  386. package/src/detectors/cross-facts.ts +2 -1
  387. package/src/detectors/custom.ts +9 -2
  388. package/src/detectors/document-shape.ts +8 -0
  389. package/src/detectors/due-date.ts +17 -7
  390. package/src/detectors/fact-consistency.ts +13 -17
  391. package/src/detectors/form-line.ts +47 -0
  392. package/src/detectors/formula-amount.ts +2 -18
  393. package/src/detectors/heading-claim.ts +76 -0
  394. package/src/detectors/heading-echo.ts +32 -1
  395. package/src/detectors/installment-total-mismatch.ts +3 -18
  396. package/src/detectors/list-parallel.ts +46 -7
  397. package/src/detectors/name-variant.ts +45 -8
  398. package/src/detectors/number-unit.ts +35 -9
  399. package/src/detectors/orthography.ts +17 -8
  400. package/src/detectors/per-unit-words.ts +24 -0
  401. package/src/detectors/period-multiple-mismatch.ts +2 -18
  402. package/src/detectors/reference-number-variant.ts +27 -5
  403. package/src/detectors/registry/condition-toki.ts +4 -0
  404. package/src/detectors/rent-multiple-mismatch.ts +2 -18
  405. package/src/detectors/row-sentence-amounts.ts +5 -20
  406. package/src/detectors/stated-amounts.ts +20 -0
  407. package/src/detectors/step-time-sum.ts +2 -1
  408. package/src/detectors/structure-tree.ts +3 -0
  409. package/src/detectors/team.ts +13 -7
  410. package/src/detectors/time-order.ts +6 -3
  411. package/src/detectors/unknown-word.ts +20 -2
  412. package/src/detectors/use-interval.ts +8 -4
  413. package/src/detectors/use-maximum.ts +3 -1
  414. package/src/extension/document-view.ts +18 -9
  415. package/src/extension/entry-genres.ts +15 -0
  416. package/src/extension/module-detector.ts +9 -4
  417. package/src/extension/plugin-parse.ts +29 -7
  418. package/src/extension/problem-text.ts +4 -0
  419. package/src/facts/age-values.ts +24 -2
  420. package/src/facts/column-units.ts +67 -0
  421. package/src/facts/fact-values.ts +11 -1
  422. package/src/facts/labelled-facts.ts +16 -2
  423. package/src/facts/per-unit.ts +105 -0
  424. package/src/facts/row-sentence-amounts.ts +4 -26
  425. package/src/facts/table-facts.ts +7 -4
  426. package/src/facts/term-values.ts +94 -13
  427. package/src/grade/baseline.ts +20 -12
  428. package/src/grade/expect-read.ts +65 -0
  429. package/src/grade/expect.ts +74 -0
  430. package/src/grade/grade-item.ts +14 -3
  431. package/src/grade/item.ts +48 -8
  432. package/src/grade/result.ts +5 -0
  433. package/src/grade/results-read.ts +7 -2
  434. package/src/grade/rubric-file.ts +46 -0
  435. package/src/grade/rubric.ts +77 -47
  436. package/src/grade/setup.ts +3 -3
  437. package/src/grade/stamp.ts +10 -2
  438. package/src/grade/task-rubric.ts +39 -0
  439. package/src/grade/text.ts +27 -5
  440. package/src/name-char-reading.ts +16 -0
  441. package/src/name-end-letter.ts +52 -0
  442. package/src/name-neighbours.ts +2 -1
  443. package/src/name-separator.ts +32 -0
  444. package/src/name-variants.ts +54 -13
  445. package/src/number-name.ts +12 -3
  446. package/src/profile/cue-lines.ts +14 -0
  447. package/src/profile/parse.ts +3 -2
  448. package/src/reference-numbers.ts +1 -1
  449. package/src/spaced-person-name.ts +27 -2
  450. package/src/spacing-code.ts +13 -2
  451. package/src/spacing-minority.ts +17 -0
  452. package/src/structure/closing-balance.ts +46 -8
  453. package/src/structure/definition-use.ts +24 -1
  454. package/src/structure/document-context.ts +46 -0
  455. package/src/structure/fenced-lines.ts +28 -0
  456. package/src/structure/labelled-date-order.ts +105 -21
  457. package/src/structure/labelled-order.ts +21 -10
  458. package/src/structure/line-amount-label.ts +2 -1
  459. package/src/structure/line-amount.ts +1 -11
  460. package/src/structure/prose-total.ts +81 -2
  461. package/src/structure/runs.ts +10 -1
  462. package/src/structure/signed-date-line.ts +78 -0
  463. package/src/structure/tax.ts +6 -3
  464. package/src/structure/total-line.ts +12 -6
  465. package/src/structure/total.ts +42 -3
  466. package/src/subject-codes.ts +105 -0
  467. package/src/unlabelled-references.ts +24 -16
@@ -57,6 +57,9 @@ messages:
57
57
  company-near:
58
58
  ja: 「{name}」は、ほかの所で書いた会社名「{usual}」と一字違いです
59
59
  en: '"{name}" is one letter away from the company name "{usual}" written elsewhere in the document'
60
+ company-ending:
61
+ ja: 「{name}」は、ほかの所で何度も書いた会社名「{usual}」と、語の終わりだけが違います
62
+ en: '"{name}" differs only at the end of a word from the company name "{usual}", which the document uses more than once'
60
63
  company-kana:
61
64
  ja: 「{name}」は、ほかの所では「{usual}」と書いています(名前の漢字一字を、その読みのかなで書いた違い)
62
65
  en: '"{name}" is written "{usual}" elsewhere in the document (one kanji of the name written in kana)'
@@ -97,8 +100,8 @@ example:
97
100
  The code lives on GitHub. Reviews happen on GitHub, and releases are tagged on GitHub.
98
101
 
99
102
  not_flagged:
100
- ja: 品詞解析が固有名詞と読んだ語だけを見ます。大文字だけの名前(ACME INC、NASA)は見ません。一字違いの英字の名前は、6 字以上で、多いほうが二度以上、少ないほうが一度だけのときに限ります(Iran と Iraq は別の名前)。人の名前どうしは、字体の違う同じ字(斎藤 と 斉藤、渡辺 と 渡邊)か、読みが同じで一字だけ違い、多いほうが二度以上、少ないほうが一度だけのとき(松本 と 松元)に限ります(伊藤 と 伊東 は別の人のことがある)。解析器が読みを持たない名前の字(健汰 の 汰)は、語彙表 name-char-reading の読みで読みます(健太 と 健汰。表の升の名前も同じ)。人の名前とは、品詞解析が人名と読んだ語か、「様」「さん」「氏」の付いた名前です(解析器が名前と読めない字体の字を含む名前は、敬称の前の 2〜4 字の漢字を名前と読みます)。敬称は名前とのあいだの空白を越えて見ます。品詞解析が名と読まない語も、姓のあとに空白を挟んで書き、敬称が付けば名と読みます(森下 千尋 様)。敬称の無い名前も、前後に漢字が続かない 2〜4 字の漢字で、片方の書き方に「担当の」「私、」などの前置きか敬称が付き、もう片方が「です」「が」「までご連絡」などの前にあれば比べます(担当の斎藤です と 斉藤までご連絡ください)。地名にも同じ組がある(鹿島 と 鹿嶋)ので、どちらにも前置きも敬称も無いときは比べません。会社の名前は、語彙表の会社の種類の語(株式会社、(株)、有限会社)の隣にあるものを、品詞と関係なく比べます。名前が同じで種類の語が違うもの(株式会社 と 有限会社)、種類の語を名前の反対側に置いたもの(株式会社アオバ と アオバ株式会社)、記号・幅だけが違うものを指します。同じ種類の語の略した形(株式会社 と (株))、種類の語を省いた呼び名(アオバシステム、以下「アオバ」)は指しません。名前の一字違いは、7 字以上の名前で、違う字が漢字でないときに限ります(日本電気 と 日本電機 は別の会社のことがある)。漢字を含む名前は、7 字に満たなくても、4 字以上のかなの語の中のかな一字違いを、多いほうが二度以上、少ないほうが一度だけのときに指します(コモレビ電機 と コモレピ電機)。名前の漢字一字を、品詞解析が言うその読みのかなで書いた所(みどり野生命 と みどりの生命)も、多いほうが二度以上、かなのほうが一度だけのときに指します。読みは、かなと漢字一字の語からだけ取ります。漢字だけの名前は、品詞解析が固有名詞と読んだときだけ会社の名前と見ます(清算株式会社、当該株式会社)。場所の名前は、語彙表の場所の語(口、駅、センター、ホール)で終わる名前を、品詞と関係なく比べます。記号・幅だけが違うもの(コンベンションセンター と コンベンション・センター)を指し、名前の読みが同じかかなで書いた読みのもの(筑紫口 と ちくし口)と、固有名詞の字の一字違い(八重洲中央口 と 八重州中央口)は、多いほうが二度以上、少ないほうが一度だけのときに限ります。方角や数字の違い(北口 と 南口、第1会議室 と 第2会議室)は別の所なので指しません。表の升は升ごとに品詞解析し、名前の形をした升(空白を挟んだ二つか三つの漢字・カタカナの語)を本文の名前と比べます。記号・幅だけの違い(佐々木 美穂 と 佐々木 美穂)と、本文と同じく読みが同じで一語だけ違うもの(佐々木 美穂 と 佐々木 美保)を指し、後者は本文の形が二度以上、升の形が一度だけのときに限ります。読みの違う一字違い(佐藤 太郎 と 佐藤 次郎)は別の人のことが多いので指しません(英字の名前は一字違いも指します)。場所の名前は表の升の中のものも比べます。英字の人の名前は、名が同じで、7 字以上の姓の頭 4 字以上がそろい、あいだの 2 字(長いほうは 3 字)までだけ違うもの(Rachel Whitford と Rachel Whitfield)も、多いほうが二度以上、少ないほうが一度だけのときに指します。語の順を入れ替えた名前(統計学基礎 と 基礎統計学)は、同じ語(形態素)を違う順に並べ、どちらも他方を含まず、どちらかが括弧の中か「前提科目:」のような欄の後ろか表の升まるごとに書いた名前のときだけ指します(統計学基礎 と 統計学応用 は別の名前)。製品の名前は、語彙表の製品の形の語(錠、カプセル、クリーム)のすぐ前の 4 字以上のカタカナを、品詞と関係なく比べます(見出しと表の升の中のものも数えます)。形の語が同じで、名前が一字の置き換えか長音の記号一つの有る無しだけ違い(ミナモール錠 と ミナモル錠)、多いほうが二度以上、少ないほうが一度だけのときに指します。名前が同じで形の語だけが違うもの(ミナモール錠 と ミナモール顆粒)は、同じ製品の別の形のことが多いので指しません。一語の名前の中で同じ音を書く字(桜ヶ丘・桜ケ丘、霞ヶ関・霞が関)は、漢字に挟まれたときだけ同じ字と見ます。品詞解析が一語と読まない書き方(桜・が・丘)は見ません。字を抜いた形(桜丘)や、違う漢字の名前(桜ヶ岡)は別の名前です。この違いだけは、表の升の中の名前とも比べます。型番(英大文字と数字を合わせた 4 字以上の語)は、文書の題か、語彙表の型番の欄の語(型番、品番、型式)の後ろに書いたものだけを文書の型番と読み、文書の中に二度以上出てくるとき、ハイフン・空白・字の大小・幅だけを変えた形(KM-SP300 と KM-SP-300、KMSP300、km-sp300)を指します。字や数の違う型番(KM-SP300 と KM-SP310、比べる表の兄弟機種、部品表の品番)は別の型番なので指しません。英小文字を含む語(iOS17)、版(v1.2 と v1.20)、より長い型番・URL・パス・ファイル名の一部(KM-SP300-B、km-sp300.pdf)は型番と読みません。空白で区切って書く規格の番号(JIS C 8714)は一つの語でないので、題や欄に書いても型番と読みません。一度ずつ書いた二つの形は、片方だけが人を書く欄(語彙表 person-label の語と「:」の後ろで、名前で行が終わるもの。氏名:山下 美咲)にあれば、欄の形を正しい形と見て、もう片方を同じ決まりで比べます(山下 美咲 と 山下 未咲)。どちらも欄にあるか、どちらも欄に無ければ比べません。欄に書いた名と同じ名を空白の後ろに書いたもの(受託者:西村 亮 の文書の 西邑 亮が)は、敬称が無くても人の名前と読みます。読みの違う一字違いでも、姓と名のそろった名前で、違う二字が語彙表 name-lookalike-char の形の似た字の組(太 と 大、未 と 末)なら、多いほうが二度以上、少ないほうが一度だけのときに指します(山本 健太 と 山本 健大。名だけの名前は兄弟のことがあるので比べません)。
101
- en: Only words the tagger reads as proper nouns are checked. Names in capitals only (ACME INC, NASA) are left out. Names one letter apart are reported only when six letters or longer, with the usual form used at least twice and the other once (Iran and Iraq are different names). Two Japanese person names are compared only when written with another form of the same character (斎藤 and 斉藤), or read the same with one character different, the usual form used at least twice and the other once (松本 and 松元); 伊藤 and 伊東 can be two people. A name character the tagger has no reading for (汰 in 健汰) is read with its reading from the lexicon name-char-reading (健太 and 健汰), in table cells as well. A person's name is one the tagger reads as such, or one followed by 様, さん or 氏 (when a name holds a character form the tagger cannot read, the two to four kanji before the honorific are taken as the name). The honorific may follow the name after a space. A word the tagger does not read as a given name is taken as one when it follows a surname after a space and carries an honorific (森下 千尋 様). A name without an honorific is compared too when it is two to four kanji standing alone, one form has a lead such as 担当の or 私、 or an honorific, and the other stands before a word such as です, が or までご連絡 (担当の斎藤です and 斉藤までご連絡ください). Places have such pairs as well (鹿島 and 鹿嶋), so two forms with neither a lead nor an honorific are not compared. A company name is one next to a company form from the lexicon (Inc., Ltd., Co., Ltd., LLC), whatever the tagger reads it as. The same name with forms of two kinds (Inc. and Ltd.), and the same name written with other punctuation or width, are reported. The short and long spelling of one form (Inc and Incorporated) and a name written without its form (Aoba Systems, the "Company") are not. Two names one letter apart are reported only when seven letters or longer, with the same form, and the letter is not a kanji. A name holding kanji is compared when shorter too, for one kana apart inside a kana word of four or more (コモレビ電機 and コモレピ電機), with the usual form used at least twice and the other once. One kanji of a name written in its kana reading (みどり野生命 and みどりの生命) is reported the same way; the reading is the tagger's, taken only from a word of kana and one kanji. A place name is one ending in a place word from the lexicon (Street, St., Avenue, Station, Center), whatever the tagger reads it as. The same place written with other punctuation (King's Cross and Kings Cross) or with the place word short and long (11th Street and 11th St.) is reported; a place whose name is one letter away (Union Station and Unoin Station) only when the usual form is used at least twice and the other once. Other numbers and other names (1st Street and 2nd Street, North Hall and South Hall) are different places. Table cells are tagged cell by cell, and a cell holding only a name (two to four capitalised words, or two or three kanji or katakana words with a space) is compared with the names read in the prose. Reported are the same name with other punctuation or case, or one word different with the other words the same, either a letter away (Sofia Mendes in the text, Sofia Mendez in the table) or, for a Japanese name, read the same as the prose name (佐々木 美穂 and 佐々木 美保); these only when the prose form is used at least twice and the cell form once. Place names inside table cells are compared too. A word next to a name that the tagger did not read as a name (to Rachel Whitford, with Rachel read as a verb) is read with it when the two together are read as a name elsewhere. Two names with the same given name and a surname of seven letters or more, whose first four letters match and which differ in at most two letters between the shared start and end (three in the longer one), are reported when the usual form is used at least twice and the other once (Rachel Whitford and Rachel Whitfield). A different given name (Daniel Whitfield) or a surname alone is not compared this way. A name with its words in another order (Foundations of Statistics and Statistical Foundations) is reported only when both hold the same words (by stem) and neither contains the other, and one of them is written as a name, in quotation marks, after a label such as "Prerequisite" and a colon, or as a whole table cell. Two Title Case runs alone are not compared (Florida Supreme Court and Supreme Court of Florida), nor are two names joined by "and". In Japanese, a product name is four or more katakana right before a product-form word from the lexicon (錠, カプセル, クリーム), whatever the tagger reads it as, counted in headings and table cells as well. Two such names with the same form word, differing by one replaced kana or one long-vowel mark (ミナモール錠 and ミナモル錠), are reported when the usual form is used at least twice and the other once. The same name with another form word (ミナモール錠 and ミナモール顆粒) is not, as a product line often has both. In a Japanese name, a character for the same sound (桜ヶ丘 and 桜ケ丘, 霞ヶ関 and 霞が関) is the same only between two kanji, in a name the tagger reads as one word (not 桜が丘, read as 桜, が, 丘). A name without it (桜丘) or with other kanji (桜ヶ岡) is another name. This difference alone is also looked for in the names inside table cells. A model number (four or more capitals and digits, as one word) is read as the document's model only when it is in the title or after a model label from the lexicon (Model, Model No., Part No.); when it appears twice or more, a form that changes only hyphens, spaces, case or width (KM-SP300 and KM-SP-300, KMSP300, km-sp300) is reported. Codes with other letters or digits (KM-SP300 and KM-SP310, a sibling model in a comparison table, the part numbers of a parts list) are different models and are not compared. A word with small letters (iOS17), a version (v1.2 and v1.20), and a code inside a longer code, a URL, a path or a file name (KM-SP300-B, km-sp300.pdf) are not read as model numbers. A standard number written with spaces (JIS C 8714) is not one word, so it is not read as a model even in the title or after a label. Two forms written once each are compared when exactly one of them is in a field that names a person (a label from the lexicon person-label and a colon, with the name ending the line, as in "Contractor:" followed by Priya Raman); the field's form is taken as the usual one and the other is held to the same rules (Priya Raman and Priya Rahman). Two forms both in such fields, or neither, are not compared. Read differently, two full names (surname and given name) are still reported when they differ by one character and the two characters are a lookalike pair from the lexicon name-lookalike-char (太 and 大, 未 and 末), with the usual form used at least twice and the other once (山本 健太 and 山本 健大); a given name alone is not compared this way, as siblings can have such names.
103
+ ja: 品詞解析が固有名詞と読んだ語だけを見ます。大文字だけの名前(ACME INC、NASA)は見ません。一字違いの英字の名前は、6 字以上で、多いほうが二度以上、少ないほうが一度だけのときに限ります(Iran と Iraq は別の名前)。人の名前どうしは、字体の違う同じ字(斎藤 と 斉藤、渡辺 と 渡邊)か、読みが同じで一字だけ違い、多いほうが二度以上、少ないほうが一度だけのとき(松本 と 松元)に限ります(伊藤 と 伊東 は別の人のことがある)。解析器が読みを持たない名前の字(健汰 の 汰)は、語彙表 name-char-reading の読みで読みます(健太 と 健汰。表の升の名前も同じ)。人の名前とは、品詞解析が人名と読んだ語か、「様」「さん」「氏」の付いた名前です(解析器が名前と読めない字体の字を含む名前は、敬称の前の 2〜4 字の漢字を名前と読みます)。敬称は名前とのあいだの空白を越えて見ます。品詞解析が名と読まない語も、姓のあとに空白を挟んで書き、敬称が付けば名と読みます(森下 千尋 様)。姓の後ろに空白を挟んでかなで書いた名も、敬称か肩書きが付くか、人を書く欄の行の終わりにあれば、姓とつないで一つの名前と読みます(松本 あかり 様)。敬称の無い名前も、前後に漢字が続かない 2〜4 字の漢字で、片方の書き方に「担当の」「私、」などの前置きか敬称が付き、もう片方が「です」「が」「までご連絡」などの前にあれば比べます(担当の斎藤です と 斉藤までご連絡ください)。地名にも同じ組がある(鹿島 と 鹿嶋)ので、どちらにも前置きも敬称も無いときは比べません。会社の名前は、語彙表の会社の種類の語(株式会社、(株)、有限会社)の隣にあるものを、品詞と関係なく比べます。名前が同じで種類の語が違うもの(株式会社 と 有限会社)、種類の語を名前の反対側に置いたもの(株式会社アオバ と アオバ株式会社)、記号・幅だけが違うものを指します。同じ種類の語の略した形(株式会社 と (株))、種類の語を省いた呼び名(アオバシステム、以下「アオバ」)は指しません。名前の一字違いは、7 字以上の名前で、違う字が漢字でないときに限ります(日本電気 と 日本電機 は別の会社のことがある)。漢字を含む名前は、7 字に満たなくても、4 字以上のかなの語の中のかな一字違いを、多いほうが二度以上、少ないほうが一度だけのときに指します(コモレビ電機 と コモレピ電機)。名前の漢字一字を、品詞解析が言うその読みのかなで書いた所(みどり野生命 と みどりの生命)も、多いほうが二度以上、かなのほうが一度だけのときに指します。読みは、かなと漢字一字の語からだけ取ります。名前の頭でない字は、頭の音を濁らせた読みで書いたもの(こむぎ畑 と こむぎばたけ)も同じに指します。漢字だけの名前は、品詞解析が固有名詞と読んだときだけ会社の名前と見ます(清算株式会社、当該株式会社)。場所の名前は、語彙表の場所の語(口、駅、センター、ホール)で終わる名前を、品詞と関係なく比べます。記号・幅だけが違うもの(コンベンションセンター と コンベンション・センター)を指し、名前の読みが同じかかなで書いた読みのもの(筑紫口 と ちくし口)と、固有名詞の字の一字違い(八重洲中央口 と 八重州中央口)は、多いほうが二度以上、少ないほうが一度だけのときに限ります。方角や数字の違い(北口 と 南口、第1会議室 と 第2会議室)は別の所なので指しません。表の升は升ごとに品詞解析し、名前の形をした升(空白を挟んだ二つか三つの漢字・カタカナの語)を本文の名前と比べます。記号・幅だけの違い(佐々木 美穂 と 佐々木 美穂)と、本文と同じく読みが同じで一語だけ違うもの(佐々木 美穂 と 佐々木 美保)を指し、後者は本文の形が二度以上、升の形が一度だけのときに限ります。読みの違う一字違い(佐藤 太郎 と 佐藤 次郎)は別の人のことが多いので指しません(英字の名前は一字違いも指します)。場所の名前は表の升の中のものも比べます。英字の人の名前は、名が同じで、7 字以上の姓の頭 4 字以上がそろい、あいだの 2 字(長いほうは 3 字)までだけ違うもの(Rachel Whitford と Rachel Whitfield)も、多いほうが二度以上、少ないほうが一度だけのときに指します。語の順を入れ替えた名前(統計学基礎 と 基礎統計学)は、同じ語(形態素)を違う順に並べ、どちらも他方を含まず、どちらかが括弧の中か「前提科目:」のような欄の後ろか表の升まるごとに書いた名前のときだけ指します(統計学基礎 と 統計学応用 は別の名前)。製品の名前は、語彙表の製品の形の語(錠、カプセル、クリーム)のすぐ前の 4 字以上のカタカナを、品詞と関係なく比べます(見出しと表の升の中のものも数えます)。形の語が同じで、名前が一字の置き換えか長音の記号一つの有る無しだけ違い(ミナモール錠 と ミナモル錠)、多いほうが二度以上、少ないほうが一度だけのときに指します。名前が同じで形の語だけが違うもの(ミナモール錠 と ミナモール顆粒)は、同じ製品の別の形のことが多いので指しません。一語の名前の中で同じ音を書く字(桜ヶ丘・桜ケ丘、霞ヶ関・霞が関)は、漢字に挟まれたときだけ同じ字と見ます。品詞解析が一語と読まない書き方(桜・が・丘)は見ません。字を抜いた形(桜丘)や、違う漢字の名前(桜ヶ岡)は別の名前です。この違いだけは、表の升の中の名前とも比べます。型番(英大文字と数字を合わせた 4 字以上の語)は、文書の題か、語彙表の型番の欄の語(型番、品番、型式)の後ろに書いたものだけを文書の型番と読み、文書の中に二度以上出てくるとき、ハイフン・空白・字の大小・幅だけを変えた形(KM-SP300 と KM-SP-300、KMSP300、km-sp300)を指します。字や数の違う型番(KM-SP300 と KM-SP310、比べる表の兄弟機種、部品表の品番)は別の型番なので指しません。英小文字を含む語(iOS17)、版(v1.2 と v1.20)、より長い型番・URL・パス・ファイル名の一部(KM-SP300-B、km-sp300.pdf)は型番と読みません。空白で区切って書く規格の番号(JIS C 8714)は一つの語でないので、題や欄に書いても型番と読みません。一度ずつ書いた二つの形は、片方だけが人を書く欄(語彙表 person-label の語と「:」の後ろで、名前で行が終わるもの。氏名:山下 美咲)にあれば、欄の形を正しい形と見て、もう片方を同じ決まりで比べます(山下 美咲 と 山下 未咲)。どちらも欄にあるか、どちらも欄に無ければ比べません。欄に書いた名と同じ名を空白の後ろに書いたもの(受託者:西村 亮 の文書の 西邑 亮が)は、敬称が無くても人の名前と読みます。読みの違う一字違いでも、姓と名のそろった名前で、違う二字が語彙表 name-lookalike-char の形の似た字の組(太 と 大、未 と 末)なら、多いほうが二度以上、少ないほうが一度だけのときに指します(山本 健太 と 山本 健大。名だけの名前は兄弟のことがあるので比べません)。英字の名前で、ほかの語が同じ二語以上の名前の一語が、終わりの一字の抜けか足しだけ違うもの(Rachel Whitmore と Rachel Whitmor)も、多いほうが二度以上か人を書く欄にあり、少ないほうが一度だけのときに指します。違うのが最後の語(姓)なら、前の語がどれも、文書の中で小文字でも普通名詞としても書かない語のときに限り(Hurricane Hanna と Hurricane Hannah は別の嵐)、4 字の姓の一字違いも指します(Daniel Reyes と Daniel Reys。Reyes と Reyna は別の姓)。最後でない語は、8 字以上で、名前の最後の語がふつうの語のときに限ります(Hollybrook Residences と Hollybrooke Residences。人の名の Christian と Christiane は別の人)。足した字が s(複数)か母音の後ろの n(Korea と Korean)のもの、違う語のどちらかがふつうの語のもの(Green と Greene)は指しません。会社の名前は、形の語も側も同じで、一語だけが、8 字以上の語の終わりの 2 字まで違うもの(Brightmoor と Brightmore)か、最後の語の単数と複数(Water Utility と Water Utilities)も、多いほうが二度以上、少ないほうが一度だけのときに指します。
104
+ en: Only words the tagger reads as proper nouns are checked. Names in capitals only (ACME INC, NASA) are left out. Names one letter apart are reported only when six letters or longer, with the usual form used at least twice and the other once (Iran and Iraq are different names). Two Japanese person names are compared only when written with another form of the same character (斎藤 and 斉藤), or read the same with one character different, the usual form used at least twice and the other once (松本 and 松元); 伊藤 and 伊東 can be two people. A name character the tagger has no reading for (汰 in 健汰) is read with its reading from the lexicon name-char-reading (健太 and 健汰), in table cells as well. A person's name is one the tagger reads as such, or one followed by 様, さん or 氏 (when a name holds a character form the tagger cannot read, the two to four kanji before the honorific are taken as the name). The honorific may follow the name after a space. A word the tagger does not read as a given name is taken as one when it follows a surname after a space and carries an honorific (森下 千尋 様). A given name written in kana after a surname and a space is joined with the surname when an honorific or a title follows it, or when it ends a line in a field that names a person (松本 あかり 様). A name without an honorific is compared too when it is two to four kanji standing alone, one form has a lead such as 担当の or 私、 or an honorific, and the other stands before a word such as です, が or までご連絡 (担当の斎藤です and 斉藤までご連絡ください). Places have such pairs as well (鹿島 and 鹿嶋), so two forms with neither a lead nor an honorific are not compared. A company name is one next to a company form from the lexicon (Inc., Ltd., Co., Ltd., LLC), whatever the tagger reads it as. The same name with forms of two kinds (Inc. and Ltd.), and the same name written with other punctuation or width, are reported. The short and long spelling of one form (Inc and Incorporated) and a name written without its form (Aoba Systems, the "Company") are not. Two names one letter apart are reported only when seven letters or longer, with the same form, and the letter is not a kanji. A name holding kanji is compared when shorter too, for one kana apart inside a kana word of four or more (コモレビ電機 and コモレピ電機), with the usual form used at least twice and the other once. One kanji of a name written in its kana reading (みどり野生命 and みどりの生命) is reported the same way; the reading is the tagger's, taken only from a word of kana and one kanji. A kanji that does not start the name is also matched with its reading voiced at the start (こむぎ畑 and こむぎばたけ). A place name is one ending in a place word from the lexicon (Street, St., Avenue, Station, Center), whatever the tagger reads it as. The same place written with other punctuation (King's Cross and Kings Cross) or with the place word short and long (11th Street and 11th St.) is reported; a place whose name is one letter away (Union Station and Unoin Station) only when the usual form is used at least twice and the other once. Other numbers and other names (1st Street and 2nd Street, North Hall and South Hall) are different places. Table cells are tagged cell by cell, and a cell holding only a name (two to four capitalised words, or two or three kanji or katakana words with a space) is compared with the names read in the prose. Reported are the same name with other punctuation or case, or one word different with the other words the same, either a letter away (Sofia Mendes in the text, Sofia Mendez in the table) or, for a Japanese name, read the same as the prose name (佐々木 美穂 and 佐々木 美保); these only when the prose form is used at least twice and the cell form once. Place names inside table cells are compared too. A word next to a name that the tagger did not read as a name (to Rachel Whitford, with Rachel read as a verb) is read with it when the two together are read as a name elsewhere. Two names with the same given name and a surname of seven letters or more, whose first four letters match and which differ in at most two letters between the shared start and end (three in the longer one), are reported when the usual form is used at least twice and the other once (Rachel Whitford and Rachel Whitfield). A different given name (Daniel Whitfield) or a surname alone is not compared this way. A name with its words in another order (Foundations of Statistics and Statistical Foundations) is reported only when both hold the same words (by stem) and neither contains the other, and one of them is written as a name, in quotation marks, after a label such as "Prerequisite" and a colon, or as a whole table cell. Two Title Case runs alone are not compared (Florida Supreme Court and Supreme Court of Florida), nor are two names joined by "and". In Japanese, a product name is four or more katakana right before a product-form word from the lexicon (錠, カプセル, クリーム), whatever the tagger reads it as, counted in headings and table cells as well. Two such names with the same form word, differing by one replaced kana or one long-vowel mark (ミナモール錠 and ミナモル錠), are reported when the usual form is used at least twice and the other once. The same name with another form word (ミナモール錠 and ミナモール顆粒) is not, as a product line often has both. In a Japanese name, a character for the same sound (桜ヶ丘 and 桜ケ丘, 霞ヶ関 and 霞が関) is the same only between two kanji, in a name the tagger reads as one word (not 桜が丘, read as 桜, が, 丘). A name without it (桜丘) or with other kanji (桜ヶ岡) is another name. This difference alone is also looked for in the names inside table cells. A model number (four or more capitals and digits, as one word) is read as the document's model only when it is in the title or after a model label from the lexicon (Model, Model No., Part No.); when it appears twice or more, a form that changes only hyphens, spaces, case or width (KM-SP300 and KM-SP-300, KMSP300, km-sp300) is reported. Codes with other letters or digits (KM-SP300 and KM-SP310, a sibling model in a comparison table, the part numbers of a parts list) are different models and are not compared. A word with small letters (iOS17), a version (v1.2 and v1.20), and a code inside a longer code, a URL, a path or a file name (KM-SP300-B, km-sp300.pdf) are not read as model numbers. A standard number written with spaces (JIS C 8714) is not one word, so it is not read as a model even in the title or after a label. Two forms written once each are compared when exactly one of them is in a field that names a person (a label from the lexicon person-label and a colon, with the name ending the line, as in "Contractor:" followed by Priya Raman); the field's form is taken as the usual one and the other is held to the same rules (Priya Raman and Priya Rahman). Two forms both in such fields, or neither, are not compared. Read differently, two full names (surname and given name) are still reported when they differ by one character and the two characters are a lookalike pair from the lexicon name-lookalike-char (太 and 大, 未 and 末), with the usual form used at least twice and the other once (山本 健太 and 山本 健大); a given name alone is not compared this way, as siblings can have such names. In a Latin-script name of two or more words with the other words the same, one word with its last letter dropped or added (Rachel Whitmore and Rachel Whitmor) is reported when the usual form is used at least twice, or is in a field that names the person, and the other once. When that word is the last one (the surname), only if no word before it is written in lower case, or read as a common noun, anywhere in the document (Hurricane Hanna and Hurricane Hannah are two storms); a surname of four letters is then also compared for one letter apart (Daniel Reyes and Daniel Reys; Reyes and Reyna are different surnames). Another word is compared only when eight letters or longer and the name ends in an ordinary word (Hollybrook Residences and Hollybrooke Residences; the given names Christian and Christiane belong to different people). An added s (a plural) or an n after a vowel (Korea and Korean), and a pair where either word is an ordinary word (Green and Greene), are not reported. Two company names with the same form on the same side, differing in one word only, by at most its last two letters in a word of eight or more (Brightmoor and Brightmore) or as the singular and plural of the last word (Water Utility and Water Utilities), are reported when the usual form is used at least twice and the other once.
102
105
  rewrite:
103
106
  depth: light
104
107
  ja:
@@ -57,8 +57,8 @@ example:
57
57
  From next month every store counts its stock on one screen, and a stocktake takes half a day.
58
58
 
59
59
  not_flagged:
60
- ja: 題の文字の並びの半分以上を繰り返していない段落(日付、書き手の名前、別の話題で始まるリード)は言いません。題のすぐ下が箇条書き・表・画像なら、リードが無いものとして見ません。題(最初の # 見出し)だけを見ます。法務・文学・話し言葉のジャンルでは見ません。
61
- en: A paragraph that repeats less than half of the title's character sequence (a date, a byline, a lead on another point) is not reported. When a list, a table or an image comes right under the title, there is no lead to check. Only the title (the first top-level heading) is checked. Legal, literary and speech genres do not run this rule.
60
+ ja: 題の文字の並びの半分以上を繰り返していない段落(日付、書き手の名前、別の話題で始まるリード)は言いません。題のすぐ下が箇条書き・表・画像なら、リードが無いものとして見ません。題(最初の # 見出し)だけを見ます。法務・文学・話し言葉のジャンルでは見ません。題のすぐ下が項目と値の行(請求番号:INV-1)や名前だけの行(レターヘッド)なら、書式の頭で、リードではないので見ません。
61
+ en: A paragraph that repeats less than half of the title's character sequence (a date, a byline, a lead on another point) is not reported. When a list, a table or an image comes right under the title, there is no lead to check. Only the title (the first top-level heading) is checked. Legal, literary and speech genres do not run this rule. When the lines right under the title are fields (an invoice number and its value) or a name alone (a letterhead), the document is a form and has no lead to check.
62
62
  level_meaning:
63
63
  ja: 題に無い内容語が {limit} 個より少ないとき指摘
64
64
  en: reported when the lead adds fewer than {limit} content words the title does not have
@@ -65,8 +65,8 @@ example:
65
65
  | Taxi | $100 |
66
66
 
67
67
  not_flagged:
68
- ja: ほかの値に二つ以上、同じ一つの単位が付いているときだけ指します。単位の無い値のほうが多い列、単位が混ざる列(分と時間)、数でない値(未定)は見ません。表の見出しの単位(「金額(円)」)は読みません。
69
- en: Reported only when at least two other values carry one and the same unit. A column where bare numbers are the majority, one that mixes units (minutes and hours), and values that are not numbers (TBD) are not checked. A unit written in the header ("Amount ($)") is not read.
68
+ ja: ほかの値に二つ以上、同じ一つの単位が付いているときだけ指します。単位の無い値のほうが多い列、単位が混ざる列(分と時間)、数でない値(未定)は見ません。表の見出しの単位(「金額(円)」)は読みません。数量の列で、ほかの値が借りる期間(4日、2泊)のとき、単位の無い整数(チャイルドシート 1)は個数なので指しません。
69
+ en: Reported only when at least two other values carry one and the same unit. A column where bare numbers are the majority, one that mixes units (minutes and hours), and values that are not numbers (TBD) are not checked. A unit written in the header ("Amount ($)") is not read. In a Quantity column whose other values are a hired period (4 days, 2 nights), a bare whole number (Child seat | 1) is a count of pieces and is not reported.
70
70
  rewrite:
71
71
  depth: light
72
72
  ja:
@@ -34,7 +34,7 @@ levels: { strict: error, normal: warning, relaxed: warning }
34
34
  options:
35
35
  listed_kinds:
36
36
  kind: words
37
- default: [item]
37
+ default: [item, model]
38
38
  about:
39
39
  ja: 文書が多くを並べる番号の種類(reference-label の group)。この種類の、語の後ろや表にある番号どうしは比べず、語の無い番号だけを比べる
40
40
  en: Kinds of number a document lists many of (reference-label groups). Two labelled or tabled numbers of such a kind are never compared; only one with no label is
@@ -77,5 +77,5 @@ example:
77
77
  When you call, please give your booking number, MN-48215.
78
78
 
79
79
  not_flagged:
80
- ja: 「予約番号」「受付番号」「予約確認番号」「お問い合わせ番号」「社員番号」「学籍番号」「発注番号」「見積番号」「請求書番号」「患者番号」「契約番号」「登録番号」「口座番号」「証券番号」のような語のすぐ後ろ(間は空白と「:」「、」や開き括弧だけ)にある、数字を4つ以上含む英数字の並びだけを番号と見ます。発注番号は取引先の番号を書き写すこともありますが、同じ種類の語の番号どうしで隣り合う二文字だけが入れ違ったものしか指さないので、別の注文の番号は指しません。「原契約番号」「基本契約番号」「旧契約番号」「変更契約番号」「親契約番号」は別の契約の番号を引く語なので、文書自身の「契約番号」とは比べません。「登録番号」「受講番号」は参加者の登録の番号、「申込番号」は申込みの番号として、互いに比べません。「振込先口座番号」「振込元口座番号」は振込の相手の口座の番号を書く語なので、口座自身の「口座番号」とは比べません。「契約者番号」は契約者その人の番号で、証券番号とは見ません。語の無い番号(下に書く品番の形のものを除く)、種類の違う番号(学籍番号と社員番号、予約番号と受付番号、請求書番号と注文番号、見積番号と注文番号や請求書番号、登録番号と申込番号)、一文字だけ違う番号、離れた文字の入れ違い、二か所以上入れ違った番号は指しません。自動車のナンバー(ひばり野 330 ね 48-15)の形に合う並びは、語が「登録番号」でも自動車のナンバーとして読みます。ナンバーだけは、文書が一台の車のことを書いているとき(その車のナンバーを「登録番号:」のような語と番号だけの行に一つだけ書き、ほかのナンバーは一つだけで、その語が文の初めにあるとき。「代車の登録番号」のように語の前に語があれば別の車と見ます)に限って、地名・分類番号・かなが同じで一連番号が一文字だけ違うものも指します。「ナンバー」だけの語や英語の「Registration」だけの語は、ナンバーの語として読みません。「品番」「商品コード」「品目コード」は商品の番号の語です。表の行や列の見出しにこの語を書いた升の品番も、語の後ろの品番と同じに読みます。語の無い品番(「GP-0521の替芯」)は、英字と「-」と数字4つ以上の形(GP-0521)のときだけ、語の後ろか表にある品番のちょうど一つと隣り合う二文字だけが入れ違っていれば指します。その書き方の品番が文書のどこかで語の後ろか表にあれば、別の商品の品番と見て指しません(カタログの表に並ぶ AB-1234 と AB-1243 は二つの商品です)。語の後ろや表にある品番どうしも、別の商品の品番として比べません(この扱いをする種類は listed_kinds で決めます)。二つ以上の品番のどれとも読めるもの、英字や「-」の無い番号(48251)も指しません。「会員番号」「会員ID」の会員の番号と、「お客様番号」の番号は、別の番号になり得るので比べません。語のすぐ後ろの番号を「HM 5520 8137」のように空白一つずつで区切って書いたときは、続く並びがどれも4文字以上の大文字と数字で数字を含む間を一つの番号と読み、行の終わりや、語(「の方」「2名」)の前で止めます。
81
- en: "Only letters and digits right after a label (booking number, reservation number, confirmation number, reference number, employee number, student number, PO number, quote or estimate number, invoice number, patient number, contract or agreement number, registration number, account number, policy number), with nothing but spaces, a colon, a comma or an opening bracket between, are read, and only when they hold four digits or more. A PO number may be the buyer's, copied from another document, but only two numbers of one kind that differ by two neighbours swapped are reported, so a different order's number is not. An original, master, former, amended or parent contract number (and an amendment number) cites another contract, so it is never compared with the document's own contract number. A registration number labels an attendee's registration and an application number an application, so the two are never compared. A payee's, beneficiary's, payer's or sender's account number labels the other side of a transfer, so it is never compared with the account's own account number; a policyholder number is not read as a policy number. Unlabelled codes (but for item codes, below), numbers of different kinds (a student number and an employee number, a booking number and an order number, an invoice number and an order number, a quote number and an order or invoice number, a registration number and an application number), numbers that differ in one character, swaps of characters that are not neighbours and numbers with more than one swap are not reported. A bare quote is not read as a label, since it is also a verb (quote your PO number). A plate number, number plate or licence plate is a vehicle's and is never compared with a registration number; a bare Registration label is not read as a plate, since an attendee's registration is written so too. An item code, item no., SKU or product code labels an item; a code in a table under such a label, in its row or its column, is read as if written after it. A code with no label (Refills for GP-0521) is reported only in the shape letters, a hyphen and four digits or more, and only when it is exactly one labelled or tabled code with two neighbours swapped. When the document labels or tables that writing itself anywhere, it is another item and is not reported (a catalog's AB-1234 and AB-1243 are two items), and two labelled or tabled item codes are never compared with each other (listed_kinds names the kinds read so); nor is a code two labelled codes swap to, or a number with no letters or hyphen (48251). A member number or member ID and a customer number may be different numbers, so they are never compared. A number written in groups one space apart (HM 5520 8137) is read as one while each further group is four or more capitals and digits holding a digit, stopping at the line's end or before a word or a short count (expires, 100 copies)."
80
+ ja: 「予約番号」「受付番号」「予約確認番号」「お問い合わせ番号」「社員番号」「学籍番号」「発注番号」「見積番号」「請求書番号」「患者番号」「契約番号」「登録番号」「口座番号」「証券番号」のような語のすぐ後ろ(間は空白と「:」「、」や開き括弧だけ)にある、数字を4つ以上含む英数字の並びだけを番号と見ます。発注番号は取引先の番号を書き写すこともありますが、同じ種類の語の番号どうしで隣り合う二文字だけが入れ違ったものしか指さないので、別の注文の番号は指しません。「原契約番号」「基本契約番号」「旧契約番号」「変更契約番号」「親契約番号」は別の契約の番号を引く語なので、文書自身の「契約番号」とは比べません。「登録番号」「受講番号」は参加者の登録の番号、「申込番号」は申込みの番号として、互いに比べません。「振込先口座番号」「振込元口座番号」は振込の相手の口座の番号を書く語なので、口座自身の「口座番号」とは比べません。「契約者番号」は契約者その人の番号で、証券番号とは見ません。語の無い番号(下に書く品番の形のものを除く)、種類の違う番号(学籍番号と社員番号、予約番号と受付番号、請求書番号と注文番号、見積番号と注文番号や請求書番号、登録番号と申込番号)、一文字だけ違う番号、離れた文字の入れ違い、二か所以上入れ違った番号は指しません。自動車のナンバー(ひばり野 330 ね 48-15)の形に合う並びは、語が「登録番号」でも自動車のナンバーとして読みます。ナンバーだけは、文書が一台の車のことを書いているとき(その車のナンバーを「登録番号:」のような語と番号だけの行に一つだけ書き、ほかのナンバーは一つだけで、その語が文の初めにあるとき。「代車の登録番号」のように語の前に語があれば別の車と見ます)に限って、地名・分類番号・かなが同じで一連番号が一文字だけ違うものも指します。「ナンバー」だけの語や英語の「Registration」だけの語は、ナンバーの語として読みません。「品番」「商品コード」「品目コード」は商品の番号の語です。表の行や列の見出しにこの語を書いた升の品番も、語の後ろの品番と同じに読みます。語の無い品番(「GP-0521の替芯」)は、英字と「-」と数字4つ以上の形(GP-0521)のときだけ、語の後ろか表にある品番のちょうど一つと隣り合う二文字だけが入れ違っていれば指します。その書き方の品番が文書のどこかで語の後ろか表にあれば、別の商品の品番と見て指しません(カタログの表に並ぶ AB-1234 と AB-1243 は二つの商品です)。語の後ろや表にある品番どうしも、別の商品の品番として比べません(この扱いをする種類は listed_kinds で決めます)。二つ以上の品番のどれとも読めるもの、英字や「-」の無い番号(48251)も指しません。「会員番号」「会員ID」の会員の番号と、「お客様番号」の番号は、別の番号になり得るので比べません。語のすぐ後ろの番号を「HM 5520 8137」のように空白一つずつで区切って書いたときは、続く並びがどれも4文字以上の大文字と数字で数字を含む間を一つの番号と読み、行の終わりや、語(「の方」「2名」)の前で止めます。「型番」は製品の型番の語で、品番と同じく、語の後ろや表にある型番どうしは比べません。製品の文書(回収のお知らせや保証書)が自分の製品として名指す番号(題名にある番号、「型番:」「商品コード:」のような語と番号だけの行の番号、表で型番や品番の語を書いた升の番号)がちょうど一つのときに限り、「-」の前に英字が二つ以上あり、数字が二つ以上の短い番号(NH-805、FT-38)も読み、文書に一度だけ書いた、その番号の隣り合う二文字が入れ違った番号(NH-850)を指します。そう名指す番号が二つ以上ある文書(カタログ)、表にある番号、二度以上書いた番号、その番号と同じ行にある番号(「NH-805 と NH-850」)、「予約番号」のような別の種類の語の後ろの番号、英字一つの番号(A-12)は指しません。
81
+ en: "Only letters and digits right after a label (booking number, reservation number, confirmation number, reference number, employee number, student number, PO number, quote or estimate number, invoice number, patient number, contract or agreement number, registration number, account number, policy number), with nothing but spaces, a colon, a comma or an opening bracket between, are read, and only when they hold four digits or more. A PO number may be the buyer's, copied from another document, but only two numbers of one kind that differ by two neighbours swapped are reported, so a different order's number is not. An original, master, former, amended or parent contract number (and an amendment number) cites another contract, so it is never compared with the document's own contract number. A registration number labels an attendee's registration and an application number an application, so the two are never compared. A payee's, beneficiary's, payer's or sender's account number labels the other side of a transfer, so it is never compared with the account's own account number; a policyholder number is not read as a policy number. Unlabelled codes (but for item codes, below), numbers of different kinds (a student number and an employee number, a booking number and an order number, an invoice number and an order number, a quote number and an order or invoice number, a registration number and an application number), numbers that differ in one character, swaps of characters that are not neighbours and numbers with more than one swap are not reported. A bare quote is not read as a label, since it is also a verb (quote your PO number). A plate number, number plate or licence plate is a vehicle's and is never compared with a registration number; a bare Registration label is not read as a plate, since an attendee's registration is written so too. An item code, item no., SKU or product code labels an item; a code in a table under such a label, in its row or its column, is read as if written after it. A code with no label (Refills for GP-0521) is reported only in the shape letters, a hyphen and four digits or more, and only when it is exactly one labelled or tabled code with two neighbours swapped. When the document labels or tables that writing itself anywhere, it is another item and is not reported (a catalog's AB-1234 and AB-1243 are two items), and two labelled or tabled item codes are never compared with each other (listed_kinds names the kinds read so); nor is a code two labelled codes swap to, or a number with no letters or hyphen (48251). A member number or member ID and a customer number may be different numbers, so they are never compared. A number written in groups one space apart (HM 5520 8137) is read as one while each further group is four or more capitals and digits holding a digit, stopping at the line's end or before a word or a short count (expires, 100 copies). A model, model number or model no. labels a product's model, and, as with item codes, two labelled or tabled models are never compared. When a product document (a recall, a warranty) names exactly one code as its own (in its title, on a line holding only a model or item label and the code, as Model: SH-710, or in a table under such a label), a shorter code is read too (two letters or more before a hyphen, and two digits or more: SH-710, FT-38), and a code written once that is that code with two neighbours swapped (SH-701) is reported. Not when the document names two codes so (a catalog), nor a code in a table, one written twice or more, one on a line that also names the document's code (the SH-710 replaces the SH-701), one after a label of another kind (booking number), or one with a single letter (A-12)."
@@ -0,0 +1,71 @@
1
+ id: toki-as-condition
2
+ layer: L3
3
+ status: stable
4
+ how_to_find: condition-toki
5
+ word_list: condition-toki
6
+ extra_word_lists: [condition-follower]
7
+ requires: [pos]
8
+ languages: [ja]
9
+ severity: info
10
+
11
+ name:
12
+ ja: 条件を言う「時」
13
+ en: 時 written for a condition (法令用語の「とき」)
14
+
15
+ why:
16
+ ja: 法令の文では、「時」は時点(相続開始の時から)、「とき」は条件(認定を受けたときは)を言います。「認定を受けた時は」と書くと、読み手は「受けた時点で」の意味か「受けた場合に」の意味かを考えます。契約書や規程は法令の書き方にそろえるので、同じ使い分けをします。動詞や助動詞で終わる節の後ろの「時」に、「は」「には」「も」が続くときだけ指します。
17
+ en: Japanese legal drafting writes 時 for a point in time (相続開始の時から, "from the time the succession opens") and とき for a condition (認定を受けたときは, "if the approval is given"). With 認定を受けた時は the reader has to decide whether a moment or a condition is meant. Contracts and internal rules follow the statutes' usage. chaff reports 時 only after a clause that ends in a verb or an auxiliary and before は, には or も.
18
+
19
+ message:
20
+ ja: 条件を言うなら「{matched}」は「{preferred}」と書きます
21
+ en: 'For a condition, legal Japanese writes "{matched}" as "{preferred}"'
22
+
23
+ how_to_fix:
24
+ ja: 条件なら「とき」にしてください(認定を受けた時は → 認定を受けたときは)。時点を言うなら「時から」「時に」のように書けば、時点と読めます。
25
+ en: For a condition, write とき (認定を受けた時は → 認定を受けたときは). For a point in time, write 時から or 時に so that it reads as one.
26
+
27
+ placeholders:
28
+ matched:
29
+ ja: 見つけた語
30
+ en: the word found
31
+ preferred:
32
+ ja: 条件を言う書き方
33
+ en: the word for a condition
34
+
35
+ levels: { strict: warning, normal: info, relaxed: info }
36
+
37
+ use_for: [legal, docs, academic, literature, speech]
38
+ off_for:
39
+ docs: "The 時 / とき split is a convention of legal drafting: outside it, 時は for a condition is not a slip."
40
+ academic: "The 時 / とき split is a convention of legal drafting: outside it, 時は for a condition is not a slip."
41
+ literature: "The 時 / とき split is a convention of legal drafting: outside it, 時は for a condition is not a slip."
42
+ speech: "The 時 / とき split is a convention of legal drafting: outside it, 時は for a condition is not a slip."
43
+
44
+ group: wording
45
+ summary:
46
+ ja: 「認定を受けた時は」のように、条件を「とき」でなく「時」で書いた所
47
+ en: 時 written for a condition (受けた時は) where legal Japanese writes とき
48
+ example:
49
+ ja:
50
+ config: { genre: legal/contract }
51
+ before: |
52
+ 第5条 乙は、許可の取消しを受けた時は、直ちに甲に通知しなければならない。
53
+ after: |
54
+ 第5条 乙は、許可の取消しを受けたときは、直ちに甲に通知しなければならない。
55
+
56
+ not_flagged:
57
+ ja: 時点を言う「時」(相続開始の時から、死亡した時に、契約の終了の時まで)、名詞や「その」「ある」の後ろの「時」(事故の時は、その時は)、「時効」「時間」「同時」「随時」「臨時」「当時」「時点」「時期」のような語、鉤括弧で引いた中は指しません。法務のジャンルだけで動きます。
58
+ en: 時 for a point in time (相続開始の時から, 死亡した時に, 契約の終了の時まで), 時 after a noun or after その and ある (事故の時は, その時は), words such as 時効, 時間, 同時, 随時, 臨時, 当時, 時点 and 時期, and anything quoted in 「」 are not reported. Only the legal genres run this rule.
59
+ rewrite:
60
+ depth: light
61
+ ja:
62
+ direction: 条件を言う「時」を「とき」に替えてください。替えるのはその一語だけです。
63
+ pairs:
64
+ - before: 乙は、許可の取消しを受けた時は、直ちに甲に通知しなければならない。
65
+ after: 乙は、許可の取消しを受けたときは、直ちに甲に通知しなければならない。
66
+ - before: 支払期日を過ぎる時には、年三パーセントの遅延損害金を支払う。
67
+ after: 支払期日を過ぎるときには、年三パーセントの遅延損害金を支払う。
68
+ keep:
69
+ - 条の番号と中身
70
+ avoid:
71
+ - 時点を言う「時」(時から、時まで、時に)まで替える
@@ -10,8 +10,8 @@ name:
10
10
  en: A total that is not the sum of its items
11
11
 
12
12
  why:
13
- ja: 見積や請求の「合計」が、上に並べた金額の和と合わないと、読み手はどちらが正しいのかを計算し直すことになります。行を足したり消したりしたあとに、合計だけ直し忘れると起きます。箇条書きか表で、合計の語(合計・小計)で始まる行を、同じ単位で同じ列の金額の和と比べます。表の最初の列の見出しか、合計の行が数を書いた列の見出しが名指す語を付けた合計(見出しが「控除項目」の表の「控除合計」、「単位数」の列の「修得単位合計」)も合計の行と読みます。合計が足す期間を頭に付けた合計(年間合計、年計、通年合計)も合計の行と読みます。見出しが「項目」の表でも、最後の行の差引合計・控除合計は、上に合計のような行が無く金額の列が一つなら合計の行と読みます。契約書のように一つの文に書いた合計(「保守費60,000円、運用費30,000円とし、合計100,000円とする」「月額150,000円(内訳:…)」)も、その文に並べた同じ単位の金額の和と比べます。小計のあとの総計のように、足し方が何通りかあるときは、どの足し方でも合わないときだけ指します。
14
- en: When the total of a quote or an invoice is not the sum of the amounts listed above it, the reader has to add them up again to find out which is right. It happens when a line is added or removed and the total is not updated. In a list or a table, a line starting with a total word (Total, Subtotal) is compared with the sum of the amounts in the same unit and column above it. A total with a word that the header of the table's first column, or of the column the total holds its number in, names ("Total deductions" under "Deduction", "Total credits earned" in the "Credits" column) is read as a total line too, and so is a total naming the span it covers ("Total for the year", "Year total", "Annual total"). Under a header that names nothing ("Item"), a "Total deductions" on the table's last row is read too, when no row above it is a total or a gross or net amount and the table has one column of amounts. A total written in a sentence, as contracts do ("$6,000 for hosting and $3,000 for support, for a total of $9,000", "$8 per month, made up of …"), is compared with the amounts in the same unit listed in that sentence. When there is more than one way to add them up, such as a grand total after a subtotal and tax, it is pointed out only when none of them matches.
13
+ ja: 見積や請求の「合計」が、上に並べた金額の和と合わないと、読み手はどちらが正しいのかを計算し直すことになります。行を足したり消したりしたあとに、合計だけ直し忘れると起きます。箇条書きか表で、合計の語(合計・小計)で始まる行を、同じ単位で同じ列の金額の和と比べます。表の最初の列の見出しか、合計の行が数を書いた列の見出しが名指す語を付けた合計(見出しが「控除項目」の表の「控除合計」、「単位数」の列の「修得単位合計」)も合計の行と読みます。合計が足す期間を頭に付けた合計(年間合計、年計、通年合計)も合計の行と読みます。見出しが「項目」の表でも、最後の行の差引合計・控除合計は、上に合計のような行が無く金額の列が一つなら合計の行と読みます。契約書のように一つの文に書いた合計(「保守費60,000円、運用費30,000円とし、合計100,000円とする」「月額150,000円(内訳:…)」「総額12,000円:設計5,000円、開発6,000円」)も、その文に並べた同じ単位の金額の和と比べます。合計で終わる文の次の文が「内訳は」で始まるときは、その文の金額と比べます。小計のあとの総計のように、足し方が何通りかあるときは、どの足し方でも合わないときだけ指します。
14
+ en: When the total of a quote or an invoice is not the sum of the amounts listed above it, the reader has to add them up again to find out which is right. It happens when a line is added or removed and the total is not updated. In a list or a table, a line starting with a total word (Total, Subtotal) is compared with the sum of the amounts in the same unit and column above it. A total with a word that the header of the table's first column, or of the column the total holds its number in, names ("Total deductions" under "Deduction", "Total credits earned" in the "Credits" column) is read as a total line too, and so is a total naming the span it covers ("Total for the year", "Year total", "Annual total"). Under a header that names nothing ("Item"), a "Total deductions" on the table's last row is read too, when no row above it is a total or a gross or net amount and the table has one column of amounts. A total written in a sentence, as contracts do ("$6,000 for hosting and $3,000 for support, for a total of $9,000", "$8 per month, made up of …", "a total of $12,000 — $5,000 for design and $6,000 for development"), is compared with the amounts in the same unit listed in that sentence, and with the amounts of the next sentence when it opens with a breakdown phrase ("This consists of …"). When there is more than one way to add them up, such as a grand total after a subtotal and tax, it is pointed out only when none of them matches.
15
15
 
16
16
  message:
17
17
  ja: 合計「{written}」が、内訳の金額の和({sum})と合いません
@@ -61,5 +61,5 @@ example:
61
61
  | Total | $8,000 |
62
62
 
63
63
  not_flagged:
64
- ja: 単位や列の違う金額は足しません。合計の語に表の見出しが名指さない語を付けた行(見出しが「項目」の表の「消費税合計」)は、別の種類の合計かもしれないので比べません。差引合計・控除合計も、表の最後の行でないとき、上に合計の行や総支給額・支給合計の行があるとき、金額の列が二つ以上あるときは比べず、下から続けた行の和か、その上の行の和からそれを引いた額と合えば指しません。面積のように、上の行の和とは限らない量の合計(面積合計)も比べません。前の期間の合計(前年合計)は読まず、期間を付けた合計が内訳の和を一年に直した額(ちょうど4倍・12倍・52倍。月額の内訳に年間合計)なら比べません。重さ・容量・長さ(mg、g、mL、L、cm、km)は、列のどの行も同じ種類の量なら換算して足します(500mg と 0.5g は 1g)。何あたりかを書いた量(300mg/錠)、目安の量(約300mg)、範囲(300〜400mg)がある列は足しません。足し方が何通りもあるとき(小計と税のあとの総計など)は、どれとも合わないときだけ指します。文の中では、合計の語(合計・総額)のすぐ後ろの金額か内訳の語(内訳は)のすぐ前の金額だけを合計と読み、内訳の金額が二つ以上あるときだけ比べます。並びの一部(単価や上限など、合計の語から離れた金額を除いた並び)の和か、一つを引いた額(値引き)と合えば指しません。
65
- en: Amounts in another unit or column are not added. A total with a word the table's header does not name ("Total tax" under "Item") is not compared, as it may be a total of another kind, nor is a total of a quantity that need not be the sum of the rows (Total area). Under such a header, "Total deductions" is not compared when it is not the last row, when a total or a gross or net amount (Gross pay) is above it, or when the table has two columns of amounts; it is not reported when it matches the last few rows, or the rows above those less them. A total for another span ("Prior-year total") is not read, and a total naming its span that is the items scaled to a year (exactly 4, 12 or 52 times their sum, as monthly items under an annual total) is not compared. Mass, volume and length (mg, g, mL, L, cm, km) are converted and added when every row of the column is the same kind of measure (500 mg and 0.5 g make 1 g); a column with an amount per something (300 mg/tablet), a rough amount (about 300 mg) or a range (300-400 mg) is not added. Where there is more than one way to add them up, it is reported only when none matches. In a sentence, only the amount right after a total phrase (a total of) or right before a breakdown phrase (made up of) is read as a total, and only when two or more items in its unit are listed. It is not reported when the items nearest the phrase add up to it, or when it matches with one item taken away (a discount).
64
+ ja: 単位や列の違う金額は足しません。合計の語に表の見出しが名指さない語を付けた行(見出しが「項目」の表の「消費税合計」)は、別の種類の合計かもしれないので比べません。差引合計・控除合計も、表の最後の行でないとき、上に合計の行や総支給額・支給合計の行があるとき、金額の列が二つ以上あるときは比べず、下から続けた行の和か、その上の行の和からそれを引いた額と合えば指しません。面積のように、上の行の和とは限らない量の合計(面積合計)も比べません。前の期間の合計(前年合計)は読まず、期間を付けた合計が内訳の和を一年に直した額(ちょうど4倍・12倍・52倍。月額の内訳に年間合計)なら比べません。重さ・容量・長さ(mg、g、mL、L、cm、km)は、列のどの行も同じ種類の量なら換算して足します(500mg と 0.5g は 1g)。何あたりかを書いた量(300mg/錠)、目安の量(約300mg)、範囲(300〜400mg)がある列は足しません。足し方が何通りもあるとき(小計と税のあとの総計など)は、どれとも合わないときだけ指します。文の中では、合計の語(合計・総額)のすぐ後ろの金額か内訳の語(内訳は)のすぐ前の金額だけを合計と読み、内訳の金額が二つ以上あるときだけ比べます。並びの一部(単価や上限など、合計の語から離れた金額を除いた並び)の和か、一つを引いた額(値引き)と合えば指しません。合計のすぐ後ろの「:」から続く内訳は、「うち」「または」「最大」のように内訳のすべてとは限らない語があるとき、ほかの単位の金額や割合を並べたときは比べません。
65
+ en: Amounts in another unit or column are not added. A total with a word the table's header does not name ("Total tax" under "Item") is not compared, as it may be a total of another kind, nor is a total of a quantity that need not be the sum of the rows (Total area). Under such a header, "Total deductions" is not compared when it is not the last row, when a total or a gross or net amount (Gross pay) is above it, or when the table has two columns of amounts; it is not reported when it matches the last few rows, or the rows above those less them. A total for another span ("Prior-year total") is not read, and a total naming its span that is the items scaled to a year (exactly 4, 12 or 52 times their sum, as monthly items under an annual total) is not compared. Mass, volume and length (mg, g, mL, L, cm, km) are converted and added when every row of the column is the same kind of measure (500 mg and 0.5 g make 1 g); a column with an amount per something (300 mg/tablet), a rough amount (about 300 mg) or a range (300-400 mg) is not added. Where there is more than one way to add them up, it is reported only when none matches. In a sentence, only the amount right after a total phrase (a total of) or right before a breakdown phrase (made up of) is read as a total, and only when two or more items in its unit are listed. It is not reported when the items nearest the phrase add up to it, or when it matches with one item taken away (a discount). Items after a colon or a dash right after a total are not compared when "including", "or" or "up to" shows they may not be every item, when one of them is in another unit, or when they are percentages.
@@ -47,8 +47,8 @@ example:
47
47
  The report is attached to this email.
48
48
 
49
49
  not_flagged:
50
- ja: 大文字を含む語、四字より短い語、コード・URL・メールアドレスの中の語、強調や角括弧で頭の字を分けた語の残り(**G**lobally の lobally、[e]xpressions の xpressions)、文書で二度以上使う語、一字違いの辞書の語が無い語、chaff.yaml の names に並べた語、語彙表 known-misspelling が別に言う語は指しません。
51
- en: Words with a capital letter, words shorter than four letters, words in code, URLs and email addresses, the rest of a word whose first letter is set apart by emphasis or brackets (lobally in **G**lobally, xpressions in [e]xpressions), words used twice or more in the document, words with no dictionary word one letter away, words listed under names in chaff.yaml, and the misspellings known-misspelling reports are not reported.
50
+ ja: 大文字を含む語、四字より短い語、コード・URL・メールアドレスの中の語、強調や角括弧で頭の字を分けた語の残り(**G**lobally の lobally、[e]xpressions の xpressions)、文書で二度以上使う語、一字違いの辞書の語が無い語、chaff.yaml の names に並べた語、語彙表 known-misspelling が別に言う語は指しません。同じ文書がコード(`tidyq check` やコードの区画)にも書いた語も、その文書の名前なので指しません。
51
+ en: Words with a capital letter, words shorter than four letters, words in code, URLs and email addresses, the rest of a word whose first letter is set apart by emphasis or brackets (lobally in **G**lobally, xpressions in [e]xpressions), words used twice or more in the document, words with no dictionary word one letter away, words listed under names in chaff.yaml, and the misspellings known-misspelling reports are not reported. Nor is a word the document also writes in code (`tidyq check`, a code block), since it is a name the document uses.
52
52
  rewrite:
53
53
  depth: light
54
54
  en:
@@ -50,8 +50,8 @@ example:
50
50
  This agreement is between Harbour Ltd (the "Seller") and Hill Ltd (the "Buyer"). The Seller ships within five days.
51
51
 
52
52
  not_flagged:
53
- ja: 定義の条(「X」とは…をいう)で定義した語は、前で使っても言いません。定義の条は文書の頭にも終わりにも置く書き方があるためです。規約やポリシーの丁寧な形(以下「X」といいます)も、法令の形と同じに読みます。見出しの行(章・節の行、条の前の「(買主の義務)」のような見出し)の語と、漢字で終わる語にさらに漢字が続く長い語(「監査委員会」の「監査委員」)と、定義の括弧の前の長い名前をそのまま書いた所(「…作成の手引き(以下「手引き」という。)」より前の「…作成の手引き」)は、使った所に数えません。最初の一か所だけを指します。
54
- en: Terms defined in a definitions clause ("X" means ...) are not checked, since a definitions clause may come first or last. A heading line (a chapter or section line, or the caption above an article) does not count as a use, nor does a longer word that runs on in kanji past a term ending in kanji, nor an earlier copy of the long name written just before the definition's bracket. The polite Japanese form (以下「X」といいます) is read like the statute form. Only the first early use is pointed at.
53
+ ja: 定義の条(「X」とは…をいう)で定義した語は、前で使っても言いません。定義の条は文書の頭にも終わりにも置く書き方があるためです。規約やポリシーの丁寧な形(以下「X」といいます)も、法令の形と同じに読みます。見出しの行(章・節の行、条の前の「(買主の義務)」のような見出し)の語と、漢字で終わる語にさらに漢字が続く長い語(「監査委員会」の「監査委員」)と、定義の括弧の前の長い名前をそのまま書いた所(「…作成の手引き(以下「手引き」という。)」より前の「…作成の手引き」)は、使った所に数えません。最初の一か所だけを指します。別の語を定義する括弧の前の名前の中(This Services Agreement (this "Agreement") の Services、本サービス利用契約(以下「本契約」という。)の本サービス)も、使った所に数えません。
54
+ en: Terms defined in a definitions clause ("X" means ...) are not checked, since a definitions clause may come first or last. A heading line (a chapter or section line, or the caption above an article) does not count as a use, nor does a longer word that runs on in kanji past a term ending in kanji, nor an earlier copy of the long name written just before the definition's bracket. The polite Japanese form (以下「X」といいます) is read like the statute form. Only the first early use is pointed at. A word inside the name written right before another term's defining bracket (Services in This Services Agreement (this "Agreement")) is not a use either.
55
55
  rewrite:
56
56
  depth: structure
57
57
  ja:
package/src/api.ts CHANGED
@@ -31,8 +31,17 @@ export type Section = { readonly depth: number; readonly heading: string; readon
31
31
  /** One bulleted or numbered list, with the length of each item in characters. */
32
32
  export type List = { readonly span: Span; readonly itemLengths: readonly number[] };
33
33
 
34
- /** One entry of a word list. instead_of is another way to write the same thing, for rules that check a document is consistent. */
35
- export type LexiconEntry = { readonly pattern: string; readonly instead_of?: string };
34
+ /**
35
+ * One entry of a word list. instead_of is another way to write the same thing, for rules that check a document is
36
+ * consistent; rewrite, how to rewrite this phrase. genres: the genres or groups it holds in (legal, blog/tech); without
37
+ * them, every genre. options.lexicon and doc.lexicons hold only the entries for the document's genre.
38
+ */
39
+ export type LexiconEntry = {
40
+ readonly pattern: string;
41
+ readonly instead_of?: string;
42
+ readonly rewrite?: string;
43
+ readonly genres?: readonly string[];
44
+ };
36
45
 
37
46
  export type Lexicon = readonly LexiconEntry[];
38
47
 
package/src/cli-text.ts CHANGED
@@ -49,9 +49,10 @@ const USAGE_JA = `chaff — 文章の読みにくいところを見つけます
49
49
  chaff ai-score <file>... [--format text|json] [--json] [--compact]
50
50
  AI らしさの簡易判定(低・中・高)。生成文に多い目印を、同じジャンルの人の文書と比べる(書いたのが AI かは判定しない)
51
51
  --json は --format json と同じ。--compact はファイルごとに 1 行
52
- chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <前の results.jsonl>] [--allow-stamp-mismatch]
52
+ chaff grade <items.jsonl> [--rubric <rubric.yaml|.json>] [--out <results.jsonl>] [--baseline <前の results.jsonl>] [--allow-stamp-mismatch]
53
53
  [--variant-key <欄>] [--format text|json|markdown] [--json] [--compact]
54
54
  AI の出力を JSONL でまとめて採点する(指摘の率・事実・引用・合否。何も送らない)
55
+ --rubric はその回だけ chaff.yaml の grade: の代わりにそのファイル(grade: と同じ形の YAML か JSON)で採点する
55
56
  --allow-stamp-mismatch はルールか設定が前の回と違っても比べる(そのことを先に出す)
56
57
  --variant-key は variant の欄の代わりにその欄で出力を分けて並べる。--json は --format json と同じ。markdown は PR のコメント向け
57
58
  chaff fix-plan <file> [--depth light|structure|register] [--json]
@@ -108,9 +109,10 @@ const USAGE_EN = `chaff — finds what makes writing hard to read. It never rewr
108
109
  chaff ai-score <file>... [--format text|json] [--json] [--compact]
109
110
  quick AI-likeness score (low, medium, high): signs common in generated text against human documents of the genre (not a verdict on who wrote it)
110
111
  --json is --format json; --compact prints one line per file
111
- chaff grade <items.jsonl> [--out <results.jsonl>] [--baseline <earlier results.jsonl>] [--allow-stamp-mismatch]
112
+ chaff grade <items.jsonl> [--rubric <rubric.yaml|.json>] [--out <results.jsonl>] [--baseline <earlier results.jsonl>] [--allow-stamp-mismatch]
112
113
  [--variant-key <field>] [--format text|json|markdown] [--json] [--compact]
113
114
  grade a JSONL file of model outputs (finding rates, facts, quotations, pass or fail; sends nothing)
115
+ --rubric grades by that file (YAML or JSON, shaped like grade:) instead of chaff.yaml's grade: for this run
114
116
  --allow-stamp-mismatch compares with the baseline even when its rules or settings differ, saying so first
115
117
  --variant-key splits the outputs by that field instead of variant; --json is --format json; markdown is for a PR comment
116
118
  chaff fix-plan <file> [--depth light|structure|register] [--json]
@@ -1,10 +1,11 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
1
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
3
  import { packageFor } from "../adapter-load.ts";
4
4
  import type { Config } from "../config/load.ts";
5
5
  import { readDocumentFile } from "../files.ts";
6
6
  import { GENRES } from "../genre.ts";
7
7
  import { gradeItem, type GradeSetup } from "../grade/grade-item.ts";
8
+ import { expectProblems } from "../grade/expect-read.ts";
8
9
  import { DEFAULT_VARIANT_FIELD, ITEM_FIELDS, parseItems, type GradeItem, type VariantField } from "../grade/item.ts";
9
10
  import { renderMarkdown } from "../grade/render-markdown.ts";
10
11
  import { renderVariants, renderVariantsCompact } from "../grade/render-variants.ts";
@@ -14,6 +15,8 @@ import { renderCompact, renderSummary } from "../grade/render.ts";
14
15
  import type { GradeResult } from "../grade/result.ts";
15
16
  import { gradeSetup } from "../grade/setup.ts";
16
17
  import { parseRubric, type Rubric } from "../grade/rubric.ts";
18
+ import { parseRubricFile, type RubricFileProblem } from "../grade/rubric-file.ts";
19
+ import { rubricRuleEntries, taskNamesOf, taskRuleIds } from "../grade/task-rubric.ts";
17
20
  import { rulesOf } from "../custom/load.ts";
18
21
  import { summaryOf } from "../grade/summary.ts";
19
22
  import { GRADE_TEXT, type GradeText } from "../grade/text.ts";
@@ -26,7 +29,7 @@ import { chooseBaseline } from "./grade-baseline.ts";
26
29
  /** Exit codes (spec §29.3). 2 keeps "the grader did not run" apart from "an output is bad" at a CI gate. */
27
30
  export const GRADE_EXIT = { passed: 0, failed: 1, unreadable: 2 } as const;
28
31
 
29
- const VALUED: ReadonlySet<string> = new Set(["--out", "--genre", "--baseline", "--format", "--variant-key"]);
32
+ const VALUED: ReadonlySet<string> = new Set(["--out", "--genre", "--baseline", "--format", "--variant-key", "--rubric"]);
30
33
 
31
34
  const FORMATS = ["text", "json", "markdown"] as const;
32
35
 
@@ -56,11 +59,13 @@ export type GradeContext = {
56
59
  readonly ui: UiLanguage;
57
60
  };
58
61
 
59
- const readItems = async (path: string, variantField: VariantField, text: GradeText): Promise<readonly GradeItem[] | undefined> => {
62
+ type ReadItems = { readonly items: readonly GradeItem[]; readonly lines: readonly number[] };
63
+
64
+ const readItems = async (path: string, variantField: VariantField, tasks: readonly string[], text: GradeText): Promise<ReadItems | undefined> => {
60
65
  try {
61
- const vocabulary = { isLanguage: (language: string) => packageFor(language) !== undefined, genres: GENRES };
66
+ const vocabulary = { isLanguage: (language: string) => packageFor(language) !== undefined, genres: GENRES, tasks };
62
67
  const parsed = parseItems(await readDocumentFile(path), vocabulary, variantField);
63
- if ("items" in parsed) return parsed.items;
68
+ if ("items" in parsed) return parsed;
64
69
  parsed.problems.forEach((problem) => console.error(`${path}: ${text.problem(problem)}`));
65
70
  } catch (error) {
66
71
  console.error(text.unreadable(path, error instanceof Error ? error.message : String(error)));
@@ -68,39 +73,75 @@ const readItems = async (path: string, variantField: VariantField, text: GradeTe
68
73
  return undefined;
69
74
  };
70
75
 
71
- /** The `grade:` rubric, or undefined after saying what is wrong with it. `rubric: undefined` is a run with no rubric. */
72
- const readRubric = (config: Config, text: GradeText): { readonly rubric: Rubric | undefined } | undefined => {
76
+ /** The rubric a run grades by, and the --rubric file it came from when it came from one. */
77
+ type RubricRead = { readonly rubric: Rubric | undefined; readonly file?: { readonly path: string; readonly digest: string } | undefined };
78
+
79
+ /** chaff.yaml's `grade:` rubric, or undefined after saying what is wrong with it. `rubric: undefined` is a run with no rubric. */
80
+ const readConfigRubric = (config: Config, text: GradeText): RubricRead | undefined => {
73
81
  const parsed = parseRubric(config.grade);
74
82
  if ("rubric" in parsed) return parsed;
75
83
  parsed.problems.forEach((problem) => console.error(`chaff: ${text.rubricProblem(problem)}`));
76
84
  return undefined;
77
85
  };
78
86
 
79
- /** A rule id under grade.rules that chaff does not know. Said once here; each result also lists it as not run. */
80
- const warnUnknownRules = (rubric: Rubric | undefined, config: Config, text: GradeText): void => {
87
+ const fileProblemText = (path: string, problem: RubricFileProblem, text: GradeText): string => {
88
+ if (problem.kind === "format") return text.rubricFormat(path);
89
+ if (problem.kind === "syntax") return text.rubricSyntax(path, problem.why);
90
+ return text.rubricProblem(problem.problem, path);
91
+ };
92
+
93
+ /** A --rubric file's rubric, which replaces chaff.yaml's `grade:`, or undefined after saying why it cannot be read. */
94
+ const readRubricFile = (path: string, text: GradeText): RubricRead | undefined => {
95
+ try {
96
+ const parsed = parseRubricFile(path, readFileSync(path, "utf8"));
97
+ if ("rubric" in parsed) return { rubric: parsed.rubric, file: { path, digest: parsed.digest } };
98
+ parsed.problems.forEach((problem) => console.error(fileProblemText(path, problem, text)));
99
+ } catch (error) {
100
+ console.error(text.unreadable(path, error instanceof Error ? error.message : String(error)));
101
+ }
102
+ return undefined;
103
+ };
104
+
105
+ const readRubric = (rubricPath: string | undefined, config: Config, text: GradeText): RubricRead | undefined =>
106
+ rubricPath === undefined ? readConfigRubric(config, text) : readRubricFile(rubricPath, text);
107
+
108
+ /** A rule id under the rubric's rules that chaff does not know. Said once here; each result also lists it as not run. */
109
+ const warnUnknownRules = (rubric: RubricRead, config: Config, text: GradeText): void => {
81
110
  const known = new Set(rulesOf(config.language ?? "en", config).map((rule) => rule.id));
82
- Object.keys(rubric?.rules ?? {})
83
- .filter((id) => !known.has(id))
84
- .forEach((id) => console.error(`chaff: grade.rules.${id}: ${text.unknownRule}`));
111
+ const where = rubric.file === undefined ? "chaff: grade." : `${rubric.file.path}: `;
112
+ rubricRuleEntries(rubric.rubric)
113
+ .filter((entry) => !known.has(entry.id))
114
+ .forEach((entry) => console.error(`${where}${entry.path}.${entry.id}: ${text.unknownRule}`));
85
115
  };
86
116
 
87
117
  const setupFor = async (
88
118
  items: readonly GradeItem[],
89
- rubric: Rubric | undefined,
119
+ rubric: RubricRead,
90
120
  argv: readonly string[],
91
121
  context: GradeContext,
92
122
  text: GradeText,
93
123
  ): Promise<GradeSetup | undefined> => {
94
124
  const languages = items.flatMap((item) => (item.language === undefined ? [] : [item.language]));
95
- const run = { experimental: context.config.experimental || argv.includes("--experimental"), genre: context.flag(argv, "--genre") };
125
+ const run = {
126
+ experimental: context.config.experimental || argv.includes("--experimental"),
127
+ genre: context.flag(argv, "--genre"),
128
+ rubricFile: rubric.file?.digest,
129
+ };
96
130
  try {
97
- return await gradeSetup(context.config, run, languages, rubric);
131
+ return await gradeSetup(context.config, run, languages, rubric.rubric);
98
132
  } catch (error) {
99
133
  console.error(text.cannotLoad(error instanceof Error ? error.message : String(error)));
100
134
  return undefined;
101
135
  }
102
136
  };
103
137
 
138
+ /** Whether every expect entry is one fact; else says which are not, on their lines, before anything is graded. */
139
+ const expectReadable = async (path: string, read: ReadItems, setup: GradeSetup, text: GradeText): Promise<boolean> => {
140
+ const problems = (await Promise.all(read.items.map((item, index) => expectProblems(item, read.lines[index] ?? 0, setup)))).flat();
141
+ problems.forEach((problem) => console.error(`${path}: ${text.problem(problem)}`));
142
+ return problems.length === 0;
143
+ };
144
+
104
145
  /** One output after another, in the file's order: the results file lines up with the input. */
105
146
  const gradeInOrder = (items: readonly GradeItem[], setup: GradeSetup): Promise<GradeResult[]> =>
106
147
  items.reduce<Promise<GradeResult[]>>(async (previous, item) => [...(await previous), await gradeItem(item, setup)], Promise.resolve([]));
@@ -144,14 +185,24 @@ const printSummary = (path: string, results: readonly GradeResult[], compared: C
144
185
  } else printText(path, results, variants, compared, printing);
145
186
  };
146
187
 
147
- type RunOptions = { readonly path: string; readonly format: Format; readonly variantField: VariantField };
188
+ type RunOptions = { readonly path: string; readonly format: Format; readonly variantField: VariantField; readonly rubric: string | undefined };
189
+
190
+ /** --rubric's file: undefined when not given, null when given without one (a usage error, not a quiet fall back to chaff.yaml). */
191
+ const rubricPathOf = (argv: readonly string[], context: GradeContext): string | undefined | null => {
192
+ if (!argv.includes("--rubric")) return undefined;
193
+ const path = context.flag(argv, "--rubric");
194
+ return path === undefined || path === "" || path.startsWith("--") ? null : path;
195
+ };
148
196
 
149
197
  /** The file to grade and how to read and print it, or undefined after printing the usage. */
150
198
  const runOptionsOf = (argv: readonly string[], context: GradeContext): RunOptions | undefined => {
151
199
  const [path, ...extra] = gradeTargets(argv);
152
200
  const format = formatOf(argv, context);
153
201
  const variantField = variantFieldOf(argv, context);
154
- if (path !== undefined && extra.length === 0 && format !== undefined && variantField !== undefined) return { path, format, variantField };
202
+ const rubric = rubricPathOf(argv, context);
203
+ if (path !== undefined && extra.length === 0 && format !== undefined && variantField !== undefined && rubric !== null) {
204
+ return { path, format, variantField, rubric };
205
+ }
155
206
  console.error(GRADE_TEXT[context.ui].usage);
156
207
  return undefined;
157
208
  };
@@ -171,16 +222,17 @@ export const runGrade = async (argv: readonly string[], context: GradeContext):
171
222
  const options = runOptionsOf(argv, context);
172
223
  if (options === undefined) return GRADE_EXIT.unreadable;
173
224
  const { path } = options;
174
- const rubric = readRubric(context.config, host);
175
- const items = rubric === undefined ? undefined : await readItems(path, options.variantField, host);
176
- const setup = items === undefined || rubric === undefined ? undefined : await setupFor(items, rubric.rubric, argv, context, host);
177
- if (setup === undefined || items === undefined) return GRADE_EXIT.unreadable;
225
+ const rubric = readRubric(options.rubric, context.config, host);
226
+ const read = rubric === undefined ? undefined : await readItems(path, options.variantField, taskNamesOf(rubric.rubric), host);
227
+ const setup = read === undefined || rubric === undefined ? undefined : await setupFor(read.items, rubric, argv, context, host);
228
+ if (setup === undefined || read === undefined || rubric === undefined || !(await expectReadable(path, read, setup, host))) return GRADE_EXIT.unreadable;
229
+ const { items } = read;
178
230
  const baseline = await chooseBaseline(context.flag(argv, "--baseline"), setup.stamp, argv.includes("--allow-stamp-mismatch"), context.ui);
179
231
  if (baseline.kind === "stop") return GRADE_EXIT.unreadable;
180
- warnUnknownRules(setup.rubric, context.config, host);
232
+ warnUnknownRules(rubric, context.config, host);
181
233
  const results = await gradeInOrder(items, setup);
182
234
  writeResults(context.flag(argv, "--out"), results, host);
183
- const rubricRules = new Set(Object.keys(setup.rubric?.rules ?? {}));
235
+ const rubricRules = (result: GradeResult): ReadonlySet<string> => taskRuleIds(setup.rubric, result.task);
184
236
  const compared = baseline.kind === "compare" ? { path: baseline.path, comparison: compareRuns(baseline.before, results, rubricRules) } : undefined;
185
237
  const ui = sharedLanguage(
186
238
  results.map((result) => result.language),
@@ -42,7 +42,26 @@ export const kanjiReadingOf = (
42
42
  const baseStartOf = (mention: CompanyMention): number =>
43
43
  mention.position === "after" ? mention.offset : mention.offset + mention.surface.length - mention.base.length;
44
44
 
45
- /** 会社の名前の、漢字一字をその読みのひらがなかカタカナで書いた形(みどりの生命保険株式会社、みどりノ生命保険株式会社)。 */
45
+ /** 濁る頭の音(カ行、サ行、タ行、ハ行)。 */
46
+ const VOICEABLE = /^[カキクケコサシスセソタチツテトハヒフヘホ]/u;
47
+ const VOICED_MARK = "゙";
48
+
49
+ /** 名前の中ほどの字の読みは、頭の音を濁らせて書くことがある(こむぎ畑 ハタケ を こむぎばたけ)。頭の音が濁らない読みには無い。 */
50
+ export const voicedReadingOf = (reading: string): string | undefined => {
51
+ const first = VOICEABLE.exec(reading)?.[0];
52
+ return first === undefined ? undefined : `${(first + VOICED_MARK).normalize("NFC")}${reading.slice(first.length)}`;
53
+ };
54
+
55
+ /** 名前の字の読みの、かなの書き方。名前の頭でない字は、頭の音を濁らせた読みも。 */
56
+ const readingsAt = (reading: string, inside: boolean): string[] => {
57
+ const voiced = inside ? voicedReadingOf(reading) : undefined;
58
+ return voiced === undefined ? [reading] : [reading, voiced];
59
+ };
60
+
61
+ /**
62
+ * 会社の名前の、漢字一字をその読みのひらがなかカタカナで書いた形(みどりの生命保険株式会社、みどりノ生命保険株式会社)。
63
+ * 名前の頭でない字は、頭の音を濁らせた読みでも(こむぎばたけベーカリー)。
64
+ */
46
65
  export const kanaSpellingsOf = (mention: CompanyMention, words: readonly ReadWord[]): string[] => {
47
66
  const baseStart = baseStartOf(mention);
48
67
  const baseEnd = baseStart + mention.base.length;
@@ -53,7 +72,8 @@ export const kanaSpellingsOf = (mention: CompanyMention, words: readonly ReadWor
53
72
  if (read === undefined) return [];
54
73
  const at = word.start - mention.offset + read.index;
55
74
  const [before, after] = [mention.surface.slice(0, at), mention.surface.slice(at + read.kanji.length)];
56
- return [toHiragana(read.reading), read.reading].map((kana) => `${before}${kana}${after}`);
75
+ const inside = word.start + read.index > baseStart;
76
+ return readingsAt(read.reading, inside).flatMap((reading) => [toHiragana(reading), reading].map((kana) => `${before}${kana}${after}`));
57
77
  });
58
78
  };
59
79