chaffjs 0.33.0 → 0.35.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.
- package/dist/api.d.ts +7 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js.map +1 -1
- package/dist/capitals-passage.d.ts +3 -0
- package/dist/capitals-passage.d.ts.map +1 -0
- package/dist/capitals-passage.js +26 -0
- package/dist/capitals-passage.js.map +1 -0
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +4 -2
- package/dist/cli-text.js.map +1 -1
- package/dist/coined-hyphen-name.d.ts +13 -0
- package/dist/coined-hyphen-name.d.ts.map +1 -0
- package/dist/coined-hyphen-name.js +21 -0
- package/dist/coined-hyphen-name.js.map +1 -0
- package/dist/commands/grade.d.ts.map +1 -1
- package/dist/commands/grade.js +66 -21
- package/dist/commands/grade.js.map +1 -1
- package/dist/company-kana-spelling.d.ts +6 -1
- package/dist/company-kana-spelling.d.ts.map +1 -1
- package/dist/company-kana-spelling.js +19 -2
- package/dist/company-kana-spelling.js.map +1 -1
- package/dist/company-name-ending.d.ts +7 -0
- package/dist/company-name-ending.d.ts.map +1 -0
- package/dist/company-name-ending.js +44 -0
- package/dist/company-name-ending.js.map +1 -0
- package/dist/company-names.d.ts +17 -4
- package/dist/company-names.d.ts.map +1 -1
- package/dist/company-names.js +49 -17
- package/dist/company-names.js.map +1 -1
- package/dist/custom/no-rewrite.d.ts +3 -0
- package/dist/custom/no-rewrite.d.ts.map +1 -0
- package/dist/custom/no-rewrite.js +3 -0
- package/dist/custom/no-rewrite.js.map +1 -0
- package/dist/custom/parse.d.ts.map +1 -1
- package/dist/custom/parse.js +14 -2
- package/dist/custom/parse.js.map +1 -1
- package/dist/detectors/acronym-context.d.ts +1 -1
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +4 -4
- package/dist/detectors/acronym-context.js.map +1 -1
- package/dist/detectors/acronym-definition.d.ts +13 -0
- package/dist/detectors/acronym-definition.d.ts.map +1 -0
- package/dist/detectors/acronym-definition.js +90 -0
- package/dist/detectors/acronym-definition.js.map +1 -0
- package/dist/detectors/acronym-lone.d.ts +13 -0
- package/dist/detectors/acronym-lone.d.ts.map +1 -0
- package/dist/detectors/acronym-lone.js +22 -0
- package/dist/detectors/acronym-lone.js.map +1 -0
- package/dist/detectors/acronym-name.d.ts +55 -0
- package/dist/detectors/acronym-name.d.ts.map +1 -0
- package/dist/detectors/acronym-name.js +75 -0
- package/dist/detectors/acronym-name.js.map +1 -0
- package/dist/detectors/age-words.d.ts +5 -0
- package/dist/detectors/age-words.d.ts.map +1 -0
- package/dist/detectors/age-words.js +8 -0
- package/dist/detectors/age-words.js.map +1 -0
- package/dist/detectors/annual-pay-mismatch.d.ts.map +1 -1
- package/dist/detectors/annual-pay-mismatch.js +2 -12
- package/dist/detectors/annual-pay-mismatch.js.map +1 -1
- package/dist/detectors/blank-structure.d.ts.map +1 -1
- package/dist/detectors/blank-structure.js +4 -3
- package/dist/detectors/blank-structure.js.map +1 -1
- package/dist/detectors/capitalised-term.d.ts +14 -2
- package/dist/detectors/capitalised-term.d.ts.map +1 -1
- package/dist/detectors/capitalised-term.js +115 -4
- package/dist/detectors/capitalised-term.js.map +1 -1
- package/dist/detectors/caps-caption.d.ts +11 -0
- package/dist/detectors/caps-caption.d.ts.map +1 -0
- package/dist/detectors/caps-caption.js +51 -0
- package/dist/detectors/caps-caption.js.map +1 -0
- package/dist/detectors/char-shape.d.ts.map +1 -1
- package/dist/detectors/char-shape.js +47 -18
- package/dist/detectors/char-shape.js.map +1 -1
- package/dist/detectors/clause-shape.d.ts +1 -1
- package/dist/detectors/clause-shape.d.ts.map +1 -1
- package/dist/detectors/clause-shape.js +9 -4
- package/dist/detectors/clause-shape.js.map +1 -1
- package/dist/detectors/closing-balance-mismatch.d.ts.map +1 -1
- package/dist/detectors/closing-balance-mismatch.js +1 -0
- package/dist/detectors/closing-balance-mismatch.js.map +1 -1
- package/dist/detectors/code-fences.d.ts +5 -0
- package/dist/detectors/code-fences.d.ts.map +1 -1
- package/dist/detectors/code-fences.js +9 -0
- package/dist/detectors/code-fences.js.map +1 -1
- package/dist/detectors/concrete-evidence.d.ts +13 -1
- package/dist/detectors/concrete-evidence.d.ts.map +1 -1
- package/dist/detectors/concrete-evidence.js +59 -0
- package/dist/detectors/concrete-evidence.js.map +1 -1
- package/dist/detectors/condition-toki.d.ts +16 -0
- package/dist/detectors/condition-toki.d.ts.map +1 -0
- package/dist/detectors/condition-toki.js +42 -0
- package/dist/detectors/condition-toki.js.map +1 -0
- package/dist/detectors/conjugated-entry.d.ts +17 -0
- package/dist/detectors/conjugated-entry.d.ts.map +1 -0
- package/dist/detectors/conjugated-entry.js +50 -0
- package/dist/detectors/conjugated-entry.js.map +1 -0
- package/dist/detectors/content-morphemes.d.ts +2 -0
- package/dist/detectors/content-morphemes.d.ts.map +1 -1
- package/dist/detectors/content-morphemes.js +1 -1
- package/dist/detectors/content-morphemes.js.map +1 -1
- package/dist/detectors/contraction-minority.d.ts +11 -0
- package/dist/detectors/contraction-minority.d.ts.map +1 -0
- package/dist/detectors/contraction-minority.js +10 -0
- package/dist/detectors/contraction-minority.js.map +1 -0
- package/dist/detectors/counter-edge.d.ts +5 -0
- package/dist/detectors/counter-edge.d.ts.map +1 -1
- package/dist/detectors/counter-edge.js +23 -0
- package/dist/detectors/counter-edge.js.map +1 -1
- package/dist/detectors/cross-facts.d.ts.map +1 -1
- package/dist/detectors/cross-facts.js +2 -1
- package/dist/detectors/cross-facts.js.map +1 -1
- package/dist/detectors/custom.d.ts.map +1 -1
- package/dist/detectors/custom.js +8 -2
- package/dist/detectors/custom.js.map +1 -1
- package/dist/detectors/date-any-year.d.ts +6 -3
- package/dist/detectors/date-any-year.d.ts.map +1 -1
- package/dist/detectors/date-any-year.js +47 -10
- package/dist/detectors/date-any-year.js.map +1 -1
- package/dist/detectors/date-heading-year.d.ts +18 -0
- package/dist/detectors/date-heading-year.d.ts.map +1 -0
- package/dist/detectors/date-heading-year.js +38 -0
- package/dist/detectors/date-heading-year.js.map +1 -0
- package/dist/detectors/date-year.d.ts +12 -2
- package/dist/detectors/date-year.d.ts.map +1 -1
- package/dist/detectors/date-year.js +31 -6
- package/dist/detectors/date-year.js.map +1 -1
- package/dist/detectors/defined-term-form.d.ts.map +1 -1
- package/dist/detectors/defined-term-form.js +26 -5
- package/dist/detectors/defined-term-form.js.map +1 -1
- package/dist/detectors/document-shape.d.ts.map +1 -1
- package/dist/detectors/document-shape.js +6 -0
- package/dist/detectors/document-shape.js.map +1 -1
- package/dist/detectors/due-date.d.ts.map +1 -1
- package/dist/detectors/due-date.js +18 -2
- package/dist/detectors/due-date.js.map +1 -1
- package/dist/detectors/en-shape.d.ts.map +1 -1
- package/dist/detectors/en-shape.js +5 -1
- package/dist/detectors/en-shape.js.map +1 -1
- package/dist/detectors/fact-consistency.d.ts.map +1 -1
- package/dist/detectors/fact-consistency.js +15 -15
- package/dist/detectors/fact-consistency.js.map +1 -1
- package/dist/detectors/form-line.d.ts +9 -0
- package/dist/detectors/form-line.d.ts.map +1 -0
- package/dist/detectors/form-line.js +36 -0
- package/dist/detectors/form-line.js.map +1 -0
- package/dist/detectors/formula-amount.d.ts.map +1 -1
- package/dist/detectors/formula-amount.js +2 -12
- package/dist/detectors/formula-amount.js.map +1 -1
- package/dist/detectors/gram-passages.d.ts +11 -0
- package/dist/detectors/gram-passages.d.ts.map +1 -0
- package/dist/detectors/gram-passages.js +26 -0
- package/dist/detectors/gram-passages.js.map +1 -0
- package/dist/detectors/heading-claim.d.ts +14 -0
- package/dist/detectors/heading-claim.d.ts.map +1 -0
- package/dist/detectors/heading-claim.js +49 -0
- package/dist/detectors/heading-claim.js.map +1 -0
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +29 -1
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/heading-end-mark.d.ts +8 -3
- package/dist/detectors/heading-end-mark.d.ts.map +1 -1
- package/dist/detectors/heading-end-mark.js +18 -8
- package/dist/detectors/heading-end-mark.js.map +1 -1
- package/dist/detectors/heading-names.d.ts +7 -0
- package/dist/detectors/heading-names.d.ts.map +1 -0
- package/dist/detectors/heading-names.js +24 -0
- package/dist/detectors/heading-names.js.map +1 -0
- package/dist/detectors/heading-numbering.d.ts.map +1 -1
- package/dist/detectors/heading-numbering.js +7 -2
- package/dist/detectors/heading-numbering.js.map +1 -1
- package/dist/detectors/inch-mark.d.ts +10 -0
- package/dist/detectors/inch-mark.d.ts.map +1 -0
- package/dist/detectors/inch-mark.js +48 -0
- package/dist/detectors/inch-mark.js.map +1 -0
- package/dist/detectors/installment-total-mismatch.d.ts.map +1 -1
- package/dist/detectors/installment-total-mismatch.js +2 -12
- package/dist/detectors/installment-total-mismatch.js.map +1 -1
- package/dist/detectors/lexicon.d.ts +0 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +29 -23
- package/dist/detectors/lexicon.js.map +1 -1
- package/dist/detectors/list-parallel.d.ts +5 -2
- package/dist/detectors/list-parallel.d.ts.map +1 -1
- package/dist/detectors/list-parallel.js +45 -7
- package/dist/detectors/list-parallel.js.map +1 -1
- package/dist/detectors/mark-shape.d.ts +6 -3
- package/dist/detectors/mark-shape.d.ts.map +1 -1
- package/dist/detectors/mark-shape.js +12 -6
- package/dist/detectors/mark-shape.js.map +1 -1
- package/dist/detectors/name-variant-apart.d.ts +27 -0
- package/dist/detectors/name-variant-apart.d.ts.map +1 -0
- package/dist/detectors/name-variant-apart.js +51 -0
- package/dist/detectors/name-variant-apart.js.map +1 -0
- package/dist/detectors/name-variant.d.ts.map +1 -1
- package/dist/detectors/name-variant.js +51 -17
- package/dist/detectors/name-variant.js.map +1 -1
- package/dist/detectors/number-unit.d.ts +10 -0
- package/dist/detectors/number-unit.d.ts.map +1 -1
- package/dist/detectors/number-unit.js +28 -8
- package/dist/detectors/number-unit.js.map +1 -1
- package/dist/detectors/numeral-word.d.ts +15 -0
- package/dist/detectors/numeral-word.d.ts.map +1 -0
- package/dist/detectors/numeral-word.js +26 -0
- package/dist/detectors/numeral-word.js.map +1 -0
- package/dist/detectors/organisation-run.d.ts +14 -0
- package/dist/detectors/organisation-run.d.ts.map +1 -0
- package/dist/detectors/organisation-run.js +73 -0
- package/dist/detectors/organisation-run.js.map +1 -0
- package/dist/detectors/orthographic-variant.d.ts.map +1 -1
- package/dist/detectors/orthographic-variant.js +13 -5
- package/dist/detectors/orthographic-variant.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +16 -7
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/outline-label.d.ts +14 -0
- package/dist/detectors/outline-label.d.ts.map +1 -0
- package/dist/detectors/outline-label.js +32 -0
- package/dist/detectors/outline-label.js.map +1 -0
- package/dist/detectors/page-marker.d.ts +6 -0
- package/dist/detectors/page-marker.d.ts.map +1 -0
- package/dist/detectors/page-marker.js +19 -0
- package/dist/detectors/page-marker.js.map +1 -0
- package/dist/detectors/parallel-definition.d.ts +16 -0
- package/dist/detectors/parallel-definition.d.ts.map +1 -0
- package/dist/detectors/parallel-definition.js +51 -0
- package/dist/detectors/parallel-definition.js.map +1 -0
- package/dist/detectors/per-unit-words.d.ts +7 -0
- package/dist/detectors/per-unit-words.d.ts.map +1 -0
- package/dist/detectors/per-unit-words.js +17 -0
- package/dist/detectors/per-unit-words.js.map +1 -0
- package/dist/detectors/period-multiple-mismatch.d.ts.map +1 -1
- package/dist/detectors/period-multiple-mismatch.js +2 -12
- package/dist/detectors/period-multiple-mismatch.js.map +1 -1
- package/dist/detectors/reference-number-variant.d.ts.map +1 -1
- package/dist/detectors/reference-number-variant.js +21 -3
- package/dist/detectors/reference-number-variant.js.map +1 -1
- package/dist/detectors/reference-text.d.ts.map +1 -1
- package/dist/detectors/reference-text.js +1 -0
- package/dist/detectors/reference-text.js.map +1 -1
- package/dist/detectors/registry/condition-toki.d.ts +3 -0
- package/dist/detectors/registry/condition-toki.d.ts.map +1 -0
- package/dist/detectors/registry/condition-toki.js +3 -0
- package/dist/detectors/registry/condition-toki.js.map +1 -0
- package/dist/detectors/registry/unfilled-placeholder.d.ts.map +1 -1
- package/dist/detectors/registry/unfilled-placeholder.js +2 -2
- package/dist/detectors/registry/unfilled-placeholder.js.map +1 -1
- package/dist/detectors/registry/vague-density.js +1 -1
- package/dist/detectors/registry/vague-density.js.map +1 -1
- package/dist/detectors/rent-multiple-mismatch.d.ts.map +1 -1
- package/dist/detectors/rent-multiple-mismatch.js +2 -12
- package/dist/detectors/rent-multiple-mismatch.js.map +1 -1
- package/dist/detectors/request-owner.d.ts +6 -2
- package/dist/detectors/request-owner.d.ts.map +1 -1
- package/dist/detectors/request-owner.js +57 -7
- package/dist/detectors/request-owner.js.map +1 -1
- package/dist/detectors/requirement-smell.d.ts.map +1 -1
- package/dist/detectors/requirement-smell.js +10 -2
- package/dist/detectors/requirement-smell.js.map +1 -1
- package/dist/detectors/row-sentence-amounts.d.ts.map +1 -1
- package/dist/detectors/row-sentence-amounts.js +5 -10
- package/dist/detectors/row-sentence-amounts.js.map +1 -1
- package/dist/detectors/sentence-length.d.ts.map +1 -1
- package/dist/detectors/sentence-length.js +24 -16
- package/dist/detectors/sentence-length.js.map +1 -1
- package/dist/detectors/sentence-rhythm.d.ts.map +1 -1
- package/dist/detectors/sentence-rhythm.js +6 -3
- package/dist/detectors/sentence-rhythm.js.map +1 -1
- package/dist/detectors/series-label.d.ts +2 -1
- package/dist/detectors/series-label.d.ts.map +1 -1
- package/dist/detectors/series-label.js +10 -4
- package/dist/detectors/series-label.js.map +1 -1
- package/dist/detectors/signals.d.ts +4 -0
- package/dist/detectors/signals.d.ts.map +1 -1
- package/dist/detectors/signals.js +95 -36
- package/dist/detectors/signals.js.map +1 -1
- package/dist/detectors/stated-amounts.d.ts +4 -0
- package/dist/detectors/stated-amounts.d.ts.map +1 -0
- package/dist/detectors/stated-amounts.js +12 -0
- package/dist/detectors/stated-amounts.js.map +1 -0
- package/dist/detectors/step-time-sum.d.ts.map +1 -1
- package/dist/detectors/step-time-sum.js +2 -1
- package/dist/detectors/step-time-sum.js.map +1 -1
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +11 -7
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/team.d.ts.map +1 -1
- package/dist/detectors/team.js +10 -6
- package/dist/detectors/team.js.map +1 -1
- package/dist/detectors/template-sections.d.ts +14 -0
- package/dist/detectors/template-sections.d.ts.map +1 -0
- package/dist/detectors/template-sections.js +25 -0
- package/dist/detectors/template-sections.js.map +1 -0
- package/dist/detectors/time-order.d.ts.map +1 -1
- package/dist/detectors/time-order.js +17 -13
- package/dist/detectors/time-order.js.map +1 -1
- package/dist/detectors/titled-run.d.ts +22 -0
- package/dist/detectors/titled-run.d.ts.map +1 -0
- package/dist/detectors/titled-run.js +34 -0
- package/dist/detectors/titled-run.js.map +1 -0
- package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
- package/dist/detectors/unbalanced-bracket.js +4 -0
- package/dist/detectors/unbalanced-bracket.js.map +1 -1
- package/dist/detectors/undefined-term.d.ts.map +1 -1
- package/dist/detectors/undefined-term.js +8 -0
- package/dist/detectors/undefined-term.js.map +1 -1
- package/dist/detectors/unfilled-placeholder.d.ts +4 -0
- package/dist/detectors/unfilled-placeholder.d.ts.map +1 -0
- package/dist/detectors/unfilled-placeholder.js +9 -0
- package/dist/detectors/unfilled-placeholder.js.map +1 -0
- package/dist/detectors/unknown-word.d.ts +4 -1
- package/dist/detectors/unknown-word.d.ts.map +1 -1
- package/dist/detectors/unknown-word.js +18 -2
- package/dist/detectors/unknown-word.js.map +1 -1
- package/dist/detectors/use-interval.d.ts +1 -0
- package/dist/detectors/use-interval.d.ts.map +1 -1
- package/dist/detectors/use-interval.js +15 -10
- package/dist/detectors/use-interval.js.map +1 -1
- package/dist/detectors/use-maximum.d.ts.map +1 -1
- package/dist/detectors/use-maximum.js +3 -1
- package/dist/detectors/use-maximum.js.map +1 -1
- package/dist/detectors/vague-density.d.ts +5 -0
- package/dist/detectors/vague-density.d.ts.map +1 -0
- package/dist/detectors/vague-density.js +52 -0
- package/dist/detectors/vague-density.js.map +1 -0
- package/dist/extension/document-view.d.ts +2 -2
- package/dist/extension/document-view.d.ts.map +1 -1
- package/dist/extension/document-view.js +17 -8
- package/dist/extension/document-view.js.map +1 -1
- package/dist/extension/entry-genres.d.ts +5 -0
- package/dist/extension/entry-genres.d.ts.map +1 -0
- package/dist/extension/entry-genres.js +13 -0
- package/dist/extension/entry-genres.js.map +1 -0
- package/dist/extension/module-detector.d.ts.map +1 -1
- package/dist/extension/module-detector.js +4 -4
- package/dist/extension/module-detector.js.map +1 -1
- package/dist/extension/plugin-parse.d.ts +1 -1
- package/dist/extension/plugin-parse.d.ts.map +1 -1
- package/dist/extension/plugin-parse.js +24 -7
- package/dist/extension/plugin-parse.js.map +1 -1
- package/dist/extension/problem-text.d.ts.map +1 -1
- package/dist/extension/problem-text.js +2 -0
- package/dist/extension/problem-text.js.map +1 -1
- package/dist/facts/age-values.d.ts.map +1 -1
- package/dist/facts/age-values.js +20 -2
- package/dist/facts/age-values.js.map +1 -1
- package/dist/facts/column-units.d.ts +31 -0
- package/dist/facts/column-units.d.ts.map +1 -0
- package/dist/facts/column-units.js +37 -0
- package/dist/facts/column-units.js.map +1 -0
- package/dist/facts/fact-scope.d.ts +10 -1
- package/dist/facts/fact-scope.d.ts.map +1 -1
- package/dist/facts/fact-scope.js +34 -3
- package/dist/facts/fact-scope.js.map +1 -1
- package/dist/facts/fact-values.d.ts +4 -0
- package/dist/facts/fact-values.d.ts.map +1 -1
- package/dist/facts/fact-values.js +3 -1
- package/dist/facts/fact-values.js.map +1 -1
- package/dist/facts/labelled-facts.d.ts +10 -0
- package/dist/facts/labelled-facts.d.ts.map +1 -1
- package/dist/facts/labelled-facts.js +6 -1
- package/dist/facts/labelled-facts.js.map +1 -1
- package/dist/facts/per-unit.d.ts +36 -0
- package/dist/facts/per-unit.d.ts.map +1 -0
- package/dist/facts/per-unit.js +56 -0
- package/dist/facts/per-unit.js.map +1 -0
- package/dist/facts/row-sentence-amounts.d.ts +3 -12
- package/dist/facts/row-sentence-amounts.d.ts.map +1 -1
- package/dist/facts/row-sentence-amounts.js +1 -15
- package/dist/facts/row-sentence-amounts.js.map +1 -1
- package/dist/facts/table-facts.d.ts +13 -3
- package/dist/facts/table-facts.d.ts.map +1 -1
- package/dist/facts/table-facts.js +35 -13
- package/dist/facts/table-facts.js.map +1 -1
- package/dist/facts/term-values.d.ts +13 -1
- package/dist/facts/term-values.d.ts.map +1 -1
- package/dist/facts/term-values.js +71 -12
- package/dist/facts/term-values.js.map +1 -1
- package/dist/grade/baseline.d.ts +4 -2
- package/dist/grade/baseline.d.ts.map +1 -1
- package/dist/grade/baseline.js +13 -11
- package/dist/grade/baseline.js.map +1 -1
- package/dist/grade/expect-read.d.ts +16 -0
- package/dist/grade/expect-read.d.ts.map +1 -0
- package/dist/grade/expect-read.js +52 -0
- package/dist/grade/expect-read.js.map +1 -0
- package/dist/grade/expect.d.ts +50 -0
- package/dist/grade/expect.d.ts.map +1 -0
- package/dist/grade/expect.js +53 -0
- package/dist/grade/expect.js.map +1 -0
- package/dist/grade/grade-item.d.ts +1 -1
- package/dist/grade/grade-item.d.ts.map +1 -1
- package/dist/grade/grade-item.js +13 -3
- package/dist/grade/grade-item.js.map +1 -1
- package/dist/grade/item.d.ts +9 -1
- package/dist/grade/item.d.ts.map +1 -1
- package/dist/grade/item.js +32 -7
- package/dist/grade/item.js.map +1 -1
- package/dist/grade/result.d.ts +5 -0
- package/dist/grade/result.d.ts.map +1 -1
- package/dist/grade/results-read.d.ts.map +1 -1
- package/dist/grade/results-read.js +4 -2
- package/dist/grade/results-read.js.map +1 -1
- package/dist/grade/rubric-file.d.ts +23 -0
- package/dist/grade/rubric-file.d.ts.map +1 -0
- package/dist/grade/rubric-file.js +35 -0
- package/dist/grade/rubric-file.js.map +1 -0
- package/dist/grade/rubric.d.ts +2 -0
- package/dist/grade/rubric.d.ts.map +1 -1
- package/dist/grade/rubric.js +75 -47
- package/dist/grade/rubric.js.map +1 -1
- package/dist/grade/setup.d.ts +2 -1
- package/dist/grade/setup.d.ts.map +1 -1
- package/dist/grade/setup.js +2 -2
- package/dist/grade/setup.js.map +1 -1
- package/dist/grade/stamp.d.ts +2 -0
- package/dist/grade/stamp.d.ts.map +1 -1
- package/dist/grade/stamp.js +8 -2
- package/dist/grade/stamp.js.map +1 -1
- package/dist/grade/task-rubric.d.ts +16 -0
- package/dist/grade/task-rubric.d.ts.map +1 -0
- package/dist/grade/task-rubric.js +34 -0
- package/dist/grade/task-rubric.js.map +1 -0
- package/dist/grade/text.d.ts +5 -1
- package/dist/grade/text.d.ts.map +1 -1
- package/dist/grade/text.js +16 -4
- package/dist/grade/text.js.map +1 -1
- package/dist/grade-api.d.ts +9 -2
- package/dist/grade-api.d.ts.map +1 -1
- package/dist/grade-api.js +31 -15
- package/dist/grade-api.js.map +1 -1
- package/dist/heading-numbering.d.ts +5 -2
- package/dist/heading-numbering.d.ts.map +1 -1
- package/dist/heading-numbering.js +27 -6
- package/dist/heading-numbering.js.map +1 -1
- package/dist/name-char-reading.d.ts +5 -0
- package/dist/name-char-reading.d.ts.map +1 -1
- package/dist/name-char-reading.js +15 -0
- package/dist/name-char-reading.js.map +1 -1
- package/dist/name-end-letter.d.ts +24 -0
- package/dist/name-end-letter.d.ts.map +1 -0
- package/dist/name-end-letter.js +45 -0
- package/dist/name-end-letter.js.map +1 -0
- package/dist/name-given-before.d.ts +15 -0
- package/dist/name-given-before.d.ts.map +1 -0
- package/dist/name-given-before.js +30 -0
- package/dist/name-given-before.js.map +1 -0
- package/dist/name-neighbours.d.ts.map +1 -1
- package/dist/name-neighbours.js +2 -1
- package/dist/name-neighbours.js.map +1 -1
- package/dist/name-separator.d.ts +6 -0
- package/dist/name-separator.d.ts.map +1 -1
- package/dist/name-separator.js +80 -0
- package/dist/name-separator.js.map +1 -1
- package/dist/name-variants.d.ts +8 -3
- package/dist/name-variants.d.ts.map +1 -1
- package/dist/name-variants.js +40 -12
- package/dist/name-variants.js.map +1 -1
- package/dist/name-word-order.d.ts +9 -5
- package/dist/name-word-order.d.ts.map +1 -1
- package/dist/name-word-order.js +47 -15
- package/dist/name-word-order.js.map +1 -1
- package/dist/nominal-stem.d.ts +13 -0
- package/dist/nominal-stem.d.ts.map +1 -0
- package/dist/nominal-stem.js +32 -0
- package/dist/nominal-stem.js.map +1 -0
- package/dist/number-name.d.ts.map +1 -1
- package/dist/number-name.js +11 -2
- package/dist/number-name.js.map +1 -1
- package/dist/profile/cue-lines.d.ts +6 -0
- package/dist/profile/cue-lines.d.ts.map +1 -0
- package/dist/profile/cue-lines.js +13 -0
- package/dist/profile/cue-lines.js.map +1 -0
- package/dist/profile/parse.d.ts +1 -1
- package/dist/profile/parse.d.ts.map +1 -1
- package/dist/profile/parse.js +3 -2
- package/dist/profile/parse.js.map +1 -1
- package/dist/reference-numbers.d.ts +2 -0
- package/dist/reference-numbers.d.ts.map +1 -1
- package/dist/reference-numbers.js +1 -1
- package/dist/reference-numbers.js.map +1 -1
- package/dist/sentence-load.d.ts +2 -1
- package/dist/sentence-load.d.ts.map +1 -1
- package/dist/sentence-load.js +6 -2
- package/dist/sentence-load.js.map +1 -1
- package/dist/spaced-person-name.d.ts.map +1 -1
- package/dist/spaced-person-name.js +26 -1
- package/dist/spaced-person-name.js.map +1 -1
- package/dist/spacing-code.d.ts.map +1 -1
- package/dist/spacing-code.js +10 -1
- package/dist/spacing-code.js.map +1 -1
- package/dist/spacing-minority.d.ts +7 -0
- package/dist/spacing-minority.d.ts.map +1 -1
- package/dist/spacing-minority.js +14 -0
- package/dist/spacing-minority.js.map +1 -1
- package/dist/structure/cited-document-section.d.ts +7 -0
- package/dist/structure/cited-document-section.d.ts.map +1 -0
- package/dist/structure/cited-document-section.js +33 -0
- package/dist/structure/cited-document-section.js.map +1 -0
- package/dist/structure/closing-balance.d.ts +9 -0
- package/dist/structure/closing-balance.d.ts.map +1 -1
- package/dist/structure/closing-balance.js +34 -7
- package/dist/structure/closing-balance.js.map +1 -1
- package/dist/structure/definition-use.d.ts.map +1 -1
- package/dist/structure/definition-use.js +20 -1
- package/dist/structure/definition-use.js.map +1 -1
- package/dist/structure/document-context.d.ts +2 -0
- package/dist/structure/document-context.d.ts.map +1 -0
- package/dist/structure/document-context.js +42 -0
- package/dist/structure/document-context.js.map +1 -0
- package/dist/structure/fenced-lines.d.ts +7 -0
- package/dist/structure/fenced-lines.d.ts.map +1 -0
- package/dist/structure/fenced-lines.js +27 -0
- package/dist/structure/fenced-lines.js.map +1 -0
- package/dist/structure/html-text-blocks.d.ts +8 -0
- package/dist/structure/html-text-blocks.d.ts.map +1 -0
- package/dist/structure/html-text-blocks.js +47 -0
- package/dist/structure/html-text-blocks.js.map +1 -0
- package/dist/structure/issues.d.ts +1 -1
- package/dist/structure/issues.d.ts.map +1 -1
- package/dist/structure/issues.js +19 -4
- package/dist/structure/issues.js.map +1 -1
- package/dist/structure/labelled-date-order.d.ts +34 -9
- package/dist/structure/labelled-date-order.d.ts.map +1 -1
- package/dist/structure/labelled-date-order.js +60 -15
- package/dist/structure/labelled-date-order.js.map +1 -1
- package/dist/structure/labelled-order.d.ts +10 -1
- package/dist/structure/labelled-order.d.ts.map +1 -1
- package/dist/structure/labelled-order.js +18 -6
- package/dist/structure/labelled-order.js.map +1 -1
- package/dist/structure/line-amount-label.d.ts.map +1 -1
- package/dist/structure/line-amount-label.js +2 -1
- package/dist/structure/line-amount-label.js.map +1 -1
- package/dist/structure/line-amount.d.ts +0 -5
- package/dist/structure/line-amount.d.ts.map +1 -1
- package/dist/structure/line-amount.js +1 -10
- package/dist/structure/line-amount.js.map +1 -1
- package/dist/structure/list-numbering.d.ts +20 -4
- package/dist/structure/list-numbering.d.ts.map +1 -1
- package/dist/structure/list-numbering.js +65 -9
- package/dist/structure/list-numbering.js.map +1 -1
- package/dist/structure/listed-paragraph.d.ts +16 -0
- package/dist/structure/listed-paragraph.d.ts.map +1 -0
- package/dist/structure/listed-paragraph.js +37 -0
- package/dist/structure/listed-paragraph.js.map +1 -0
- package/dist/structure/numbering.d.ts +3 -2
- package/dist/structure/numbering.d.ts.map +1 -1
- package/dist/structure/numbering.js +31 -6
- package/dist/structure/numbering.js.map +1 -1
- package/dist/structure/prose-total.d.ts +8 -0
- package/dist/structure/prose-total.d.ts.map +1 -1
- package/dist/structure/prose-total.js +70 -2
- package/dist/structure/prose-total.js.map +1 -1
- package/dist/structure/reference-text.d.ts +9 -1
- package/dist/structure/reference-text.d.ts.map +1 -1
- package/dist/structure/reference-text.js +21 -3
- package/dist/structure/reference-text.js.map +1 -1
- package/dist/structure/runs.d.ts.map +1 -1
- package/dist/structure/runs.js +9 -1
- package/dist/structure/runs.js.map +1 -1
- package/dist/structure/section-names.d.ts +12 -0
- package/dist/structure/section-names.d.ts.map +1 -0
- package/dist/structure/section-names.js +26 -0
- package/dist/structure/section-names.js.map +1 -0
- package/dist/structure/signed-date-line.d.ts +15 -0
- package/dist/structure/signed-date-line.d.ts.map +1 -0
- package/dist/structure/signed-date-line.js +68 -0
- package/dist/structure/signed-date-line.js.map +1 -0
- package/dist/structure/tax.d.ts.map +1 -1
- package/dist/structure/tax.js +5 -3
- package/dist/structure/tax.js.map +1 -1
- package/dist/structure/total-line.d.ts.map +1 -1
- package/dist/structure/total-line.js +10 -6
- package/dist/structure/total-line.js.map +1 -1
- package/dist/structure/total.d.ts +2 -0
- package/dist/structure/total.d.ts.map +1 -1
- package/dist/structure/total.js +34 -3
- package/dist/structure/total.js.map +1 -1
- package/dist/structure/versioned-label.d.ts +16 -0
- package/dist/structure/versioned-label.d.ts.map +1 -0
- package/dist/structure/versioned-label.js +48 -0
- package/dist/structure/versioned-label.js.map +1 -0
- package/dist/structure/written-headings.d.ts +31 -0
- package/dist/structure/written-headings.d.ts.map +1 -0
- package/dist/structure/written-headings.js +119 -0
- package/dist/structure/written-headings.js.map +1 -0
- package/dist/structure/written-resolve.d.ts +12 -0
- package/dist/structure/written-resolve.d.ts.map +1 -0
- package/dist/structure/written-resolve.js +49 -0
- package/dist/structure/written-resolve.js.map +1 -0
- package/dist/subject-codes.d.ts +21 -0
- package/dist/subject-codes.d.ts.map +1 -0
- package/dist/subject-codes.js +79 -0
- package/dist/subject-codes.js.map +1 -0
- package/dist/unlabelled-references.d.ts +6 -2
- package/dist/unlabelled-references.d.ts.map +1 -1
- package/dist/unlabelled-references.js +11 -10
- package/dist/unlabelled-references.js.map +1 -1
- package/genres.yaml +17 -0
- package/package.json +3 -3
- package/profiles/listing.yaml +1 -1
- package/rules/all-caps-shouting.yaml +2 -2
- package/rules/closing-balance-mismatch.yaml +3 -3
- package/rules/concrete-evidence-density.yaml +2 -2
- package/rules/contraction-consistency.yaml +13 -13
- package/rules/dangling-reference.yaml +2 -2
- package/rules/date-without-year.yaml +2 -2
- package/rules/defined-name-repeated.yaml +2 -2
- package/rules/due-before-issue.yaml +9 -5
- package/rules/fact-conflict.yaml +2 -2
- package/rules/heading-echo.yaml +2 -2
- package/rules/heading-end-punctuation-mix.yaml +2 -2
- package/rules/heading-numbering-mix.yaml +2 -2
- package/rules/internal-jargon.yaml +2 -2
- package/rules/latin-spacing.yaml +4 -4
- package/rules/list-item-form-mix.yaml +1 -1
- package/rules/max-kanji-continuous.yaml +5 -3
- package/rules/max-sentence-length.yaml +3 -2
- package/rules/name-variant.yaml +5 -2
- package/rules/ngram-repetition.yaml +2 -2
- package/rules/no-lead.yaml +2 -2
- package/rules/number-without-unit.yaml +2 -2
- package/rules/numbering-gap.yaml +2 -2
- package/rules/orthographic-variant.yaml +2 -2
- package/rules/reference-number-variant.yaml +3 -3
- package/rules/reference-title-mismatch.yaml +2 -2
- package/rules/repeated-sentence-ending.yaml +3 -2
- package/rules/request-without-deadline.yaml +2 -2
- package/rules/requirement-smell.yaml +2 -2
- package/rules/sentence-rhythm.yaml +2 -2
- package/rules/title-case-consistency.yaml +2 -2
- package/rules/toki-as-condition.yaml +71 -0
- package/rules/total-mismatch.yaml +4 -4
- package/rules/unbalanced-bracket.yaml +2 -2
- package/rules/undefined-acronym.yaml +11 -2
- package/rules/undefined-term.yaml +2 -2
- package/rules/unfilled-placeholder.yaml +2 -2
- package/rules/unknown-word.yaml +2 -2
- package/rules/use-before-definition.yaml +2 -2
- package/rules/vague-word-density.yaml +2 -2
- package/src/api.ts +11 -2
- package/src/capitals-passage.ts +31 -0
- package/src/cli-text.ts +4 -2
- package/src/coined-hyphen-name.ts +27 -0
- package/src/commands/grade.ts +75 -23
- package/src/company-kana-spelling.ts +22 -2
- package/src/company-name-ending.ts +50 -0
- package/src/company-names.ts +76 -20
- package/src/custom/no-rewrite.ts +2 -0
- package/src/custom/parse.ts +18 -2
- package/src/detectors/acronym-context.ts +5 -6
- package/src/detectors/acronym-definition.ts +123 -0
- package/src/detectors/acronym-lone.ts +26 -0
- package/src/detectors/acronym-name.ts +117 -0
- package/src/detectors/age-words.ts +12 -0
- package/src/detectors/annual-pay-mismatch.ts +3 -18
- package/src/detectors/blank-structure.ts +4 -3
- package/src/detectors/capitalised-term.ts +154 -4
- package/src/detectors/caps-caption.ts +61 -0
- package/src/detectors/char-shape.ts +74 -22
- package/src/detectors/clause-shape.ts +14 -4
- package/src/detectors/closing-balance-mismatch.ts +1 -0
- package/src/detectors/code-fences.ts +10 -0
- package/src/detectors/concrete-evidence.ts +77 -1
- package/src/detectors/condition-toki.ts +60 -0
- package/src/detectors/conjugated-entry.ts +53 -0
- package/src/detectors/content-morphemes.ts +2 -1
- package/src/detectors/contraction-minority.ts +11 -0
- package/src/detectors/counter-edge.ts +23 -0
- package/src/detectors/cross-facts.ts +2 -1
- package/src/detectors/custom.ts +9 -2
- package/src/detectors/date-any-year.ts +56 -10
- package/src/detectors/date-heading-year.ts +55 -0
- package/src/detectors/date-year.ts +54 -9
- package/src/detectors/defined-term-form.ts +26 -5
- package/src/detectors/document-shape.ts +8 -0
- package/src/detectors/due-date.ts +26 -7
- package/src/detectors/en-shape.ts +5 -1
- package/src/detectors/fact-consistency.ts +16 -19
- package/src/detectors/form-line.ts +47 -0
- package/src/detectors/formula-amount.ts +2 -18
- package/src/detectors/gram-passages.ts +36 -0
- package/src/detectors/heading-claim.ts +76 -0
- package/src/detectors/heading-echo.ts +32 -1
- package/src/detectors/heading-end-mark.ts +23 -10
- package/src/detectors/heading-names.ts +31 -0
- package/src/detectors/heading-numbering.ts +7 -2
- package/src/detectors/inch-mark.ts +49 -0
- package/src/detectors/installment-total-mismatch.ts +3 -18
- package/src/detectors/lexicon.ts +32 -21
- package/src/detectors/list-parallel.ts +46 -7
- package/src/detectors/mark-shape.ts +12 -6
- package/src/detectors/name-variant-apart.ts +63 -0
- package/src/detectors/name-variant.ts +73 -18
- package/src/detectors/number-unit.ts +35 -9
- package/src/detectors/numeral-word.ts +33 -0
- package/src/detectors/organisation-run.ts +86 -0
- package/src/detectors/orthographic-variant.ts +22 -6
- package/src/detectors/orthography.ts +17 -8
- package/src/detectors/outline-label.ts +48 -0
- package/src/detectors/page-marker.ts +26 -0
- package/src/detectors/parallel-definition.ts +64 -0
- package/src/detectors/per-unit-words.ts +24 -0
- package/src/detectors/period-multiple-mismatch.ts +2 -18
- package/src/detectors/reference-number-variant.ts +27 -5
- package/src/detectors/reference-text.ts +1 -0
- package/src/detectors/registry/condition-toki.ts +4 -0
- package/src/detectors/registry/unfilled-placeholder.ts +2 -2
- package/src/detectors/registry/vague-density.ts +1 -1
- package/src/detectors/rent-multiple-mismatch.ts +2 -18
- package/src/detectors/request-owner.ts +71 -8
- package/src/detectors/requirement-smell.ts +15 -2
- package/src/detectors/row-sentence-amounts.ts +5 -20
- package/src/detectors/sentence-length.ts +14 -6
- package/src/detectors/sentence-rhythm.ts +8 -4
- package/src/detectors/series-label.ts +13 -4
- package/src/detectors/signals.ts +94 -26
- package/src/detectors/stated-amounts.ts +20 -0
- package/src/detectors/step-time-sum.ts +2 -1
- package/src/detectors/structure-tree.ts +13 -8
- package/src/detectors/team.ts +13 -7
- package/src/detectors/template-sections.ts +37 -0
- package/src/detectors/time-order.ts +6 -3
- package/src/detectors/titled-run.ts +43 -0
- package/src/detectors/unbalanced-bracket.ts +3 -0
- package/src/detectors/undefined-term.ts +8 -0
- package/src/detectors/unfilled-placeholder.ts +10 -0
- package/src/detectors/unknown-word.ts +20 -2
- package/src/detectors/use-interval.ts +8 -4
- package/src/detectors/use-maximum.ts +3 -1
- package/src/detectors/vague-density.ts +68 -0
- package/src/extension/document-view.ts +18 -9
- package/src/extension/entry-genres.ts +15 -0
- package/src/extension/module-detector.ts +9 -4
- package/src/extension/plugin-parse.ts +29 -7
- package/src/extension/problem-text.ts +4 -0
- package/src/facts/age-values.ts +24 -2
- package/src/facts/column-units.ts +67 -0
- package/src/facts/fact-scope.ts +53 -4
- package/src/facts/fact-values.ts +11 -1
- package/src/facts/labelled-facts.ts +16 -2
- package/src/facts/per-unit.ts +105 -0
- package/src/facts/row-sentence-amounts.ts +4 -26
- package/src/facts/table-facts.ts +50 -10
- package/src/facts/term-values.ts +94 -13
- package/src/grade/baseline.ts +20 -12
- package/src/grade/expect-read.ts +65 -0
- package/src/grade/expect.ts +74 -0
- package/src/grade/grade-item.ts +14 -3
- package/src/grade/item.ts +48 -8
- package/src/grade/result.ts +5 -0
- package/src/grade/results-read.ts +7 -2
- package/src/grade/rubric-file.ts +46 -0
- package/src/grade/rubric.ts +77 -47
- package/src/grade/setup.ts +3 -3
- package/src/grade/stamp.ts +10 -2
- package/src/grade/task-rubric.ts +39 -0
- package/src/grade/text.ts +27 -5
- package/src/grade-api.ts +38 -16
- package/src/heading-numbering.ts +35 -8
- package/src/name-char-reading.ts +16 -0
- package/src/name-end-letter.ts +61 -0
- package/src/name-given-before.ts +40 -0
- package/src/name-neighbours.ts +2 -1
- package/src/name-separator.ts +93 -0
- package/src/name-variants.ts +69 -18
- package/src/name-word-order.ts +62 -17
- package/src/nominal-stem.ts +36 -0
- package/src/number-name.ts +12 -3
- package/src/profile/cue-lines.ts +14 -0
- package/src/profile/parse.ts +3 -2
- package/src/reference-numbers.ts +1 -1
- package/src/sentence-load.ts +7 -2
- package/src/spaced-person-name.ts +27 -2
- package/src/spacing-code.ts +13 -2
- package/src/spacing-minority.ts +17 -0
- package/src/structure/cited-document-section.ts +42 -0
- package/src/structure/closing-balance.ts +46 -8
- package/src/structure/definition-use.ts +24 -1
- package/src/structure/document-context.ts +46 -0
- package/src/structure/fenced-lines.ts +28 -0
- package/src/structure/html-text-blocks.ts +45 -0
- package/src/structure/issues.ts +19 -4
- package/src/structure/labelled-date-order.ts +108 -21
- package/src/structure/labelled-order.ts +33 -13
- package/src/structure/line-amount-label.ts +2 -1
- package/src/structure/line-amount.ts +1 -11
- package/src/structure/list-numbering.ts +100 -11
- package/src/structure/listed-paragraph.ts +45 -0
- package/src/structure/numbering.ts +48 -19
- package/src/structure/prose-total.ts +81 -2
- package/src/structure/reference-text.ts +25 -3
- package/src/structure/runs.ts +10 -1
- package/src/structure/section-names.ts +32 -0
- package/src/structure/signed-date-line.ts +78 -0
- package/src/structure/tax.ts +6 -3
- package/src/structure/total-line.ts +12 -6
- package/src/structure/total.ts +42 -3
- package/src/structure/versioned-label.ts +52 -0
- package/src/structure/written-headings.ts +137 -0
- package/src/structure/written-resolve.ts +57 -0
- package/src/subject-codes.ts +105 -0
- package/src/unlabelled-references.ts +24 -16
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Whether a first sentence says something about its heading's subject, rather than announcing or restating it. Pure;
|
|
2
|
+
// heading-echo reads it. The words that only announce or point (covers, below, 説明, 以下), the copulas and the
|
|
3
|
+
// negations come from the language package's heading-announcer lexicon.
|
|
4
|
+
import { isContent } from "./content-morphemes.ts";
|
|
5
|
+
import type { LexiconEntry, Token } from "../plugin.ts";
|
|
6
|
+
|
|
7
|
+
type Side = "before" | "after";
|
|
8
|
+
|
|
9
|
+
export type AnnouncerWords = {
|
|
10
|
+
/** Words that announce the section or point at it: they carry no claim of their own. */
|
|
11
|
+
readonly announcing: ReadonlySet<string>;
|
|
12
|
+
/** Copulas (be, です), each with the side its complement stands on. */
|
|
13
|
+
readonly copulas: ReadonlyMap<string, Side>;
|
|
14
|
+
/** Words that deny what a copula links (There are no issues, is not in the manual): the denial is the claim. */
|
|
15
|
+
readonly negations: ReadonlySet<string>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const patternsOf = (entries: readonly LexiconEntry[], group: string | undefined): Set<string> =>
|
|
19
|
+
new Set(entries.filter((entry) => entry.group === group).map((entry) => entry.pattern.toLowerCase()));
|
|
20
|
+
|
|
21
|
+
export const announcerWords = (entries: readonly LexiconEntry[]): AnnouncerWords => ({
|
|
22
|
+
announcing: patternsOf(entries, undefined),
|
|
23
|
+
copulas: new Map(entries.flatMap((entry): [string, Side][] => (entry.group === "copula" ? [[entry.pattern.toLowerCase(), entry.position ?? "after"]] : []))),
|
|
24
|
+
negations: patternsOf(entries, "negation"),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const baseForm = (token: Token): string => (token.lemma ?? token.surface).toLowerCase();
|
|
28
|
+
|
|
29
|
+
/** Between a copula and its complement: not, very, the (is not the, are very). */
|
|
30
|
+
const BRIDGING_POS = new Set(["ADV", "PART", "DET"]);
|
|
31
|
+
|
|
32
|
+
/** What a copula at `at` links to, on its complement's side: the bridging words, then the complement when there is one. */
|
|
33
|
+
const linkedBy = (tokens: readonly Token[], at: number, side: Side): Token[] => {
|
|
34
|
+
const outward = side === "after" ? tokens.slice(at + 1) : tokens.slice(0, at).reverse();
|
|
35
|
+
const complementAt = outward.findIndex((token) => !BRIDGING_POS.has(token.pos));
|
|
36
|
+
return complementAt === -1 ? outward : outward.slice(0, complementAt + 1);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** An -ing form or a past participle names or modifies (Moving through the process, An object representing a server); it predicates only after a copula. */
|
|
40
|
+
const NON_FINITE = new Set(["Ger", "Part"]);
|
|
41
|
+
|
|
42
|
+
const isFiniteVerb = (token: Token): boolean => token.pos === "VERB" && !NON_FINITE.has(token.features?.["VerbForm"] ?? "");
|
|
43
|
+
|
|
44
|
+
type Predicate = { readonly words: readonly Token[]; readonly negations: readonly Token[] };
|
|
45
|
+
|
|
46
|
+
const copulaPredicate = (tokens: readonly Token[], at: number, side: Side, words: AnnouncerWords): Predicate => {
|
|
47
|
+
const linked = linkedBy(tokens, at, side);
|
|
48
|
+
return { words: linked.filter((word) => !BRIDGING_POS.has(word.pos)), negations: linked.filter((word) => words.negations.has(baseForm(word))) };
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** A finite verb that is no copula, a word turned into a verb by a light verb (変更し), or a copula's complement. */
|
|
52
|
+
const predicatesOf = (tokens: readonly Token[], words: AnnouncerWords): Predicate[] =>
|
|
53
|
+
tokens.flatMap((token, index): Predicate[] => {
|
|
54
|
+
const side = words.copulas.get(baseForm(token));
|
|
55
|
+
if (side !== undefined) return [copulaPredicate(tokens, index, side, words)];
|
|
56
|
+
const lightVerbNext = tokens[index + 1]?.features?.["VerbType"] === "Light";
|
|
57
|
+
return isFiniteVerb(token) || lightVerbNext ? [{ words: [token], negations: [] }] : [];
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The sentence has a predicate of its own: a word that is not one of the heading's words and does not only announce or
|
|
62
|
+
* point (covers, below, 説明, 以下), or a denial the heading does not make. "All charges include sales tax." says
|
|
63
|
+
* something about charges; "This section covers installation." and "The full reference is in the manual." do not.
|
|
64
|
+
*/
|
|
65
|
+
/** A code name in a heading holds words of its own (restoreFixtures, cache_key, dry-run): the sentence that spells them out repeats them. */
|
|
66
|
+
const CODE_NAME_PART = /\p{Lu}?[\p{Ll}\p{Nd}]+|\p{Lu}+(?!\p{Ll})/gu;
|
|
67
|
+
|
|
68
|
+
const headingWords = (heading: readonly Token[]): Set<string> =>
|
|
69
|
+
new Set(heading.flatMap((token) => [baseForm(token), ...(token.surface.match(CODE_NAME_PART) ?? []).map((part) => part.toLowerCase())]));
|
|
70
|
+
|
|
71
|
+
export const makesClaim = (heading: readonly Token[], sentence: readonly Token[], words: AnnouncerWords): boolean => {
|
|
72
|
+
const said = headingWords(heading);
|
|
73
|
+
const unsaid = (token: Token): boolean => !said.has(baseForm(token));
|
|
74
|
+
const ownWord = (token: Token): boolean => isContent(token) && unsaid(token) && !words.announcing.has(baseForm(token)) && !words.copulas.has(baseForm(token));
|
|
75
|
+
return predicatesOf(sentence, words).some((predicate) => predicate.negations.some(unsaid) || predicate.words.some(ownWord));
|
|
76
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { lengthOf, proseText } from "../measure.ts";
|
|
2
2
|
import { newContentMorphemes } from "./content-morphemes.ts";
|
|
3
3
|
import { echoedHeadingUnits, trigrams } from "./heading-overlap.ts";
|
|
4
|
+
import { formValueTokens, isFormBlock } from "./form-line.ts";
|
|
4
5
|
import { titleTokens } from "../heading-label.ts";
|
|
6
|
+
import { announcerWords, makesClaim } from "./heading-claim.ts";
|
|
5
7
|
import { handsOver } from "./lead-in.ts";
|
|
6
8
|
import { holdsLink, namesLocation } from "./location-pointer.ts";
|
|
7
9
|
import { withoutQuotedVariants } from "./quoted-variant.ts";
|
|
@@ -65,6 +67,17 @@ const pointsElsewhere = (doc: ProseDocument, section: Section): boolean => {
|
|
|
65
67
|
return first !== undefined && (holdsLink(doc.source, first.span, doc.links) || namesLocation(doc.source.slice(first.span.start, first.span.end)));
|
|
66
68
|
};
|
|
67
69
|
|
|
70
|
+
/**
|
|
71
|
+
* 最初の文が、見出しに無い述語で見出しの主題について何かを述べている(## Charges → All charges include sales tax.)。
|
|
72
|
+
* 予告や指示の語(covers, below, 説明, 以下)だけを述語にする文は、見出しを言い直しているだけで繰り返し。
|
|
73
|
+
*/
|
|
74
|
+
const statesClaim = (doc: ProseDocument, section: Section): boolean => {
|
|
75
|
+
const first = section.firstSentence;
|
|
76
|
+
if (first?.tokens === undefined || section.headingTokens === undefined) return false;
|
|
77
|
+
const heading = titleTokens(section.heading, measuredHeading(section), section.headingTokens);
|
|
78
|
+
return makesClaim(heading, first.tokens, announcerWords(doc.lexicons["heading-announcer"] ?? []));
|
|
79
|
+
};
|
|
80
|
+
|
|
68
81
|
/** A figure, with its thousands separators (1,320,000), compared without them. */
|
|
69
82
|
const FIGURE = /\p{Nd}+(?:[,,]\p{Nd}{3})*/gu;
|
|
70
83
|
/** Note marks are not figures: [^1], ※1, <sup>1</sup>. */
|
|
@@ -81,6 +94,17 @@ export const statesFigure = (heading: string, sentence: string): boolean => {
|
|
|
81
94
|
return figuresOf(sentence).some((figure) => !inHeading.has(figure));
|
|
82
95
|
};
|
|
83
96
|
|
|
97
|
+
/**
|
|
98
|
+
* 最初の文が、見出しに無い名前や値を書いた、名前だけの行(レターヘッド)か項目と値の行(Customer: Laura Pennington)。
|
|
99
|
+
* 書式の頭で、見出しを言い直す文ではない。見出しをそのまま写した行(### 環境情報学研究科 → 環境情報学研究科、詳細:〈見出し〉)は繰り返し。
|
|
100
|
+
*/
|
|
101
|
+
const opensForm = (section: Section): boolean => {
|
|
102
|
+
const first = section.firstSentence;
|
|
103
|
+
if (first?.tokens === undefined || section.headingTokens === undefined || !isFormBlock(first.text, first.span.start, first.tokens)) return false;
|
|
104
|
+
const heading = titleTokens(section.heading, measuredHeading(section), section.headingTokens);
|
|
105
|
+
return newContentMorphemes(heading, formValueTokens(first.text, first.span.start, first.tokens)) > 0;
|
|
106
|
+
};
|
|
107
|
+
|
|
84
108
|
/** 見出しとの重なりを測る文。用語集や表記の手引きは見出しの語の別の書き方を引用する(Not “datacentre”)ので、それは数えない。 */
|
|
85
109
|
const echoedText = (section: Section): string => withoutQuotedVariants(section.firstSentence?.text ?? "", measuredHeading(section));
|
|
86
110
|
|
|
@@ -88,9 +112,16 @@ export const headingEcho: Detector = (doc, options): Finding[] => {
|
|
|
88
112
|
const leadIns = (doc.lexicons["lead-in"] ?? []).map((entry) => entry.pattern);
|
|
89
113
|
return doc.sections
|
|
90
114
|
.filter((section) => section.heading.length > 0 && section.firstSentence !== undefined && addsLittle(section, doc.lengthUnit))
|
|
91
|
-
.filter(
|
|
115
|
+
.filter(
|
|
116
|
+
(section) =>
|
|
117
|
+
!leadsIn(doc, section, leadIns) &&
|
|
118
|
+
!pointsElsewhere(doc, section) &&
|
|
119
|
+
!statesFigure(section.heading, section.firstSentence?.text ?? "") &&
|
|
120
|
+
!opensForm(section),
|
|
121
|
+
)
|
|
92
122
|
.map((section) => ({ section, overlap: Math.round(containment(trigrams(measuredHeading(section)), trigrams(echoedText(section))) * 100) }))
|
|
93
123
|
.filter(({ overlap }) => overlap >= options.limit)
|
|
124
|
+
.filter(({ section }) => !statesClaim(doc, section))
|
|
94
125
|
.map(({ section, overlap }) => ({
|
|
95
126
|
rule: "heading-echo",
|
|
96
127
|
severity: "warning",
|
|
@@ -39,8 +39,21 @@ export const endMarkOf = (heading: string, words: readonly string[] = []): strin
|
|
|
39
39
|
|
|
40
40
|
type Judged = { readonly heading: MarkupHeading; readonly mark: string };
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const LOWER_CASE = /\p{Ll}/u;
|
|
43
|
+
/** A word of this many capitals is a word set in capitals, not only an acronym (AGENCY, DATES; not FAQ). */
|
|
44
|
+
const CAPITALS_WORD = /\p{Lu}{4,}/u;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Whether a heading is set in capitals ("AGENCY:", "FOR FURTHER INFORMATION CONTACT:"). A notice's captions are one kind of
|
|
48
|
+
* heading and its sections in ordinary case ("Footnotes") another, so the two are compared apart.
|
|
49
|
+
*/
|
|
50
|
+
export const isCapitalsHeading = (heading: string): boolean => !LOWER_CASE.test(heading) && CAPITALS_WORD.test(heading);
|
|
51
|
+
|
|
52
|
+
/** Headings compared with one another: the same depth, and the same case (capitals or ordinary). */
|
|
53
|
+
const kindOf = (entry: Judged): string => `${String(entry.heading.depth)}:${String(isCapitalsHeading(entry.heading.text))}`;
|
|
54
|
+
|
|
55
|
+
/** The odd ones among headings of one kind, each with the usual side's first heading and count. */
|
|
56
|
+
const oddOfKind = (doc: ProseDocument, judged: readonly Judged[]): Finding[] => {
|
|
44
57
|
if (judged.length < MIN_HEADINGS) return [];
|
|
45
58
|
const odd = minorityWithin(judged, (entry) => entry.mark !== "", MINORITY_PERCENT);
|
|
46
59
|
const usual = judged.filter((entry) => !odd.includes(entry));
|
|
@@ -56,9 +69,9 @@ const oddAtDepth = (doc: ProseDocument, judged: readonly Judged[]): Finding[] =>
|
|
|
56
69
|
};
|
|
57
70
|
|
|
58
71
|
/**
|
|
59
|
-
* Headings that end with a colon or a full stop where most headings of the same depth do not, or the other way round.
|
|
60
|
-
* of one depth are one kind of heading; a depth of labels ("Optional:") is its own way
|
|
61
|
-
* that opens the document) is a name and is not compared.
|
|
72
|
+
* Headings that end with a colon or a full stop where most headings of the same depth and case do not, or the other way round.
|
|
73
|
+
* Headings of one depth are one kind of heading; a depth of labels ("Optional:") is its own way, and so are captions set in
|
|
74
|
+
* capitals. The page title (one top-level heading that opens the document) is a name and is not compared.
|
|
62
75
|
*/
|
|
63
76
|
export const headingEndMark: Detector = (doc, options): Finding[] => {
|
|
64
77
|
const words = (options.lexicon ?? []).map((entry) => entry.pattern);
|
|
@@ -70,12 +83,12 @@ export const headingEndMark: Detector = (doc, options): Finding[] => {
|
|
|
70
83
|
const mark = endMarkOf(heading.text, words);
|
|
71
84
|
return mark === undefined ? [] : [{ heading, mark }];
|
|
72
85
|
});
|
|
73
|
-
const
|
|
74
|
-
return
|
|
75
|
-
.flatMap((
|
|
76
|
-
|
|
86
|
+
const kinds = [...new Set(judged.map(kindOf))];
|
|
87
|
+
return kinds
|
|
88
|
+
.flatMap((kind) =>
|
|
89
|
+
oddOfKind(
|
|
77
90
|
doc,
|
|
78
|
-
judged.filter((entry) => entry
|
|
91
|
+
judged.filter((entry) => kindOf(entry) === kind),
|
|
79
92
|
),
|
|
80
93
|
)
|
|
81
94
|
.toSorted((left, right) => Number(left.values["offset"]) - Number(right.values["offset"]));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { straightApostrophes } from "../orthography.ts";
|
|
2
|
+
|
|
3
|
+
const WORD = /[A-Za-z][A-Za-z'-]*/gu;
|
|
4
|
+
const POSSESSIVE = /'s$/u;
|
|
5
|
+
/** 番号が続く語(Example 4、Layer 1)は番号の札で、名前ではない。札の語は流儀によらず大文字で書く。 */
|
|
6
|
+
const NUMBER_FOLLOWS = /^\s+\d/u;
|
|
7
|
+
/** 引用符の中("Wakayama's Food Ingredients and Food Culture")は題名や人の言葉で、題の語は名前でなくても大文字になる。 */
|
|
8
|
+
const QUOTE_MARK = /[“”]/gu;
|
|
9
|
+
|
|
10
|
+
const outsideQuotes = (text: string): string =>
|
|
11
|
+
text
|
|
12
|
+
.replace(QUOTE_MARK, '"')
|
|
13
|
+
.split('"')
|
|
14
|
+
.filter((_, index) => index % 2 === 0)
|
|
15
|
+
.join(" ");
|
|
16
|
+
|
|
17
|
+
const startsUpper = (word: string): boolean => /^[A-Z]/u.test(word);
|
|
18
|
+
|
|
19
|
+
const midSentenceNames = (sentence: string): string[] =>
|
|
20
|
+
[...outsideQuotes(straightApostrophes(sentence)).matchAll(WORD)]
|
|
21
|
+
.slice(1)
|
|
22
|
+
.filter((match) => startsUpper(match[0]) && !NUMBER_FOLLOWS.test(match.input.slice(match.index + match[0].length)))
|
|
23
|
+
.map((match) => match[0].replace(POSSESSIVE, ""));
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 文書が文の途中で大文字で書く語(NOAA、Flood Inundation Mapping、Alaska)。固有の名前なので、見出しに出ても
|
|
27
|
+
* どちらの流儀でも大文字のまま。見出しの流儀の証拠に数えないよう、所有格の形(NOAA's)も添えて返す。
|
|
28
|
+
* 文の頭の語は、名前でなくても大文字になるので数えない。
|
|
29
|
+
*/
|
|
30
|
+
export const namesWrittenMidSentence = (sentences: readonly string[]): ReadonlySet<string> =>
|
|
31
|
+
new Set(sentences.flatMap(midSentenceNames).flatMap((name) => [name, `${name}'s`]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Detector, Finding, LexiconEntry } from "../plugin.ts";
|
|
2
2
|
import { findingAt, writtenHeadings } from "./markup-finding.ts";
|
|
3
|
-
import { numberingMinorities, numberingStyleOf, UNNUMBERED, type NumberingMinority, type NumberLabel } from "../heading-numbering.ts";
|
|
3
|
+
import { numberingMinorities, numberingStyleOf, opensNumbering, UNNUMBERED, type NumberingMinority, type NumberLabel } from "../heading-numbering.ts";
|
|
4
4
|
|
|
5
5
|
const labelsOf = (entries: readonly LexiconEntry[]): NumberLabel[] =>
|
|
6
6
|
entries.map((entry) => ({ word: entry.pattern, position: entry.position === "after" ? "after" : "before" }));
|
|
@@ -28,7 +28,12 @@ export const headingNumbering: Detector = (doc): Finding[] => {
|
|
|
28
28
|
const labels = labelsOf(doc.lexicons["heading-number-label"] ?? []);
|
|
29
29
|
const matter = (doc.lexicons["unnumbered-heading"] ?? []).map((entry) => entry.pattern.toLowerCase());
|
|
30
30
|
const styles = headings.map((heading) => numberingStyleOf(heading.text, labels));
|
|
31
|
-
const read = headings.map((heading, at) => ({
|
|
31
|
+
const read = headings.map((heading, at) => ({
|
|
32
|
+
depth: heading.depth,
|
|
33
|
+
style: styles[at] ?? UNNUMBERED,
|
|
34
|
+
skipped: isFrontOrBackMatter(heading.text, matter),
|
|
35
|
+
opens: opensNumbering(heading.text, labels),
|
|
36
|
+
}));
|
|
32
37
|
return numberingMinorities(read).flatMap((minority) => {
|
|
33
38
|
const heading = headings[minority.at];
|
|
34
39
|
if (heading === undefined) return [];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A curly double quote written as the inch mark: a decimal number, then the mark, then a unit (".015 “Hg/hr",
|
|
3
|
+
* "29.92”Hg"). It quotes nothing, so it opens and closes nothing. text is the section, offset the mark's position.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A number with a decimal part right before the mark, with at most one space between. A year or a count never has one,
|
|
8
|
+
* so "In 1969 “Hurricane Camille struck" stays an unclosed quote.
|
|
9
|
+
*/
|
|
10
|
+
const DECIMAL_BEFORE = /\.\p{Nd}+[ \u00A0]?$/u;
|
|
11
|
+
|
|
12
|
+
/** A short run of letters right after the mark: the unit (Hg, in). */
|
|
13
|
+
const UNIT_AFTER = /^\p{L}{1,3}(?!\p{L})/u;
|
|
14
|
+
|
|
15
|
+
const LOOK_AROUND = 40;
|
|
16
|
+
const OPENING = "\u201C";
|
|
17
|
+
const CLOSING = "\u201D";
|
|
18
|
+
|
|
19
|
+
/** Where the paragraph holding offset ends: the next blank line, or the end of the text. */
|
|
20
|
+
const paragraphEnd = (text: string, offset: number): number => {
|
|
21
|
+
const blank = /\n[ \t\u3000]*\n/u.exec(text.slice(offset));
|
|
22
|
+
return blank === null ? text.length : offset + blank.index;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const betweenNumberAndUnit = (text: string, offset: number): boolean =>
|
|
26
|
+
DECIMAL_BEFORE.test(text.slice(Math.max(0, offset - LOOK_AROUND), offset)) && UNIT_AFTER.test(text.slice(offset + 1, offset + 1 + LOOK_AROUND));
|
|
27
|
+
|
|
28
|
+
/** A closing mark in rest that is not taken by an opening mark written after the start of rest. */
|
|
29
|
+
const closesEarlier = (rest: string): boolean => {
|
|
30
|
+
const depth = { open: 0, closed: false };
|
|
31
|
+
[...rest].forEach((mark) => {
|
|
32
|
+
if (depth.closed) return;
|
|
33
|
+
if (mark === OPENING) depth.open += 1;
|
|
34
|
+
else if (mark === CLOSING && depth.open === 0) depth.closed = true;
|
|
35
|
+
else if (mark === CLOSING) depth.open -= 1;
|
|
36
|
+
});
|
|
37
|
+
return depth.closed;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The mark at offset is an inch mark. An opening mark is one only when nothing in its paragraph closes it ("at 2.5
|
|
42
|
+
* “Hg” quotes something); a closing mark only when no quote is open.
|
|
43
|
+
*/
|
|
44
|
+
export const isInchMark = (text: string, offset: number, quoteOpen: boolean): boolean => {
|
|
45
|
+
const mark = text.charAt(offset);
|
|
46
|
+
if ((mark !== OPENING && mark !== CLOSING) || !betweenNumberAndUnit(text, offset)) return false;
|
|
47
|
+
if (mark === CLOSING) return !quoteOpen;
|
|
48
|
+
return !closesEarlier(text.slice(offset + 1, paragraphEnd(text, offset)));
|
|
49
|
+
};
|
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
// and amount-range-word.
|
|
5
5
|
import type { Detector, Finding, Lexicon, ProseDocument } from "../plugin.ts";
|
|
6
6
|
import { installmentFeeMismatches, type InstallmentSeriesWords } from "../structure/installment-fee.ts";
|
|
7
|
-
import { installmentTotalMismatches, type
|
|
8
|
-
import { scaledAmountOf, scaleWordsOf } from "./amount-scale.ts";
|
|
9
|
-
import { amountsIn, formsOf } from "./currency-notation.ts";
|
|
7
|
+
import { installmentTotalMismatches, type InstallmentWords, type PositionedWord } from "../structure/installment-total.ts";
|
|
10
8
|
import type { StructureIssue } from "../structure/issues.ts";
|
|
11
9
|
import { proseAndTablesOf } from "../table-text.ts";
|
|
12
10
|
import { quoteAround } from "./quote-around.ts";
|
|
11
|
+
import { statedAmountsOf } from "./stated-amounts.ts";
|
|
13
12
|
|
|
14
13
|
const entriesOf = (doc: ProseDocument, lexicon: string, group?: string): Lexicon =>
|
|
15
14
|
(doc.lexicons[lexicon] ?? []).filter((entry) => group === undefined || entry.group === group);
|
|
@@ -57,20 +56,6 @@ const seriesWordsOf = (doc: ProseDocument): InstallmentSeriesWords => ({
|
|
|
57
56
|
feeLinks: patternsOf(doc, "installment-word", "fee-link"),
|
|
58
57
|
});
|
|
59
58
|
|
|
60
|
-
const amountsOf = (text: string, doc: ProseDocument): InstallmentAmount[] => {
|
|
61
|
-
const scales = scaleWordsOf(doc);
|
|
62
|
-
return amountsIn(
|
|
63
|
-
text,
|
|
64
|
-
formsOf(doc),
|
|
65
|
-
scales.map((scale) => scale.word),
|
|
66
|
-
).flatMap((amount) => {
|
|
67
|
-
const read = scaledAmountOf(text, amount, scales);
|
|
68
|
-
return read === undefined
|
|
69
|
-
? []
|
|
70
|
-
: [{ offset: read.offset, end: amount.offset + amount.written.length, currency: read.currency, value: read.value, scale: read.unit }];
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
|
|
74
59
|
const findingOf = (text: string, issue: StructureIssue, variant?: string): Finding => ({
|
|
75
60
|
rule: "installment-total-mismatch",
|
|
76
61
|
severity: "warning",
|
|
@@ -83,7 +68,7 @@ const findingOf = (text: string, issue: StructureIssue, variant?: string): Findi
|
|
|
83
68
|
|
|
84
69
|
export const installmentTotalMismatch: Detector = (doc): Finding[] => {
|
|
85
70
|
const text = proseAndTablesOf(doc);
|
|
86
|
-
const amounts =
|
|
71
|
+
const amounts = statedAmountsOf(text, doc);
|
|
87
72
|
const words = wordsOf(doc);
|
|
88
73
|
const loans = installmentTotalMismatches(text, amounts, words);
|
|
89
74
|
const headings = (doc.markup?.headings ?? []).map((heading) => heading.start);
|
package/src/detectors/lexicon.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { joinWords } from "./word-list.ts";
|
|
2
|
+
import { pairMinority } from "./contraction-minority.ts";
|
|
2
3
|
import { straightApostrophes } from "../orthography.ts";
|
|
3
4
|
import { wordsOf } from "./structure.ts";
|
|
4
5
|
import type { Detector, Finding, Lexicon, LexiconEntry, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
|
|
@@ -68,7 +69,6 @@ const hedgingDensity = densityRule("excessive-hedging");
|
|
|
68
69
|
export const cushionDensity = densityRule("cushion-phrase-density", "at-floor");
|
|
69
70
|
/** 語彙表の語の密度だけを見る rule が共通で使う。rule の id は実行側が入れる。 */
|
|
70
71
|
export const phraseDensity = densityRule("");
|
|
71
|
-
export const vagueDensity = densityRule("vague-word-density");
|
|
72
72
|
|
|
73
73
|
/** 書いたとおりの字。行の折り返しをまたいでいたら空白 1 つに。 */
|
|
74
74
|
const writtenAt = (source: string, span: Span): string => source.slice(span.start, span.end).replace(/\s+/gu, " ").trim();
|
|
@@ -258,40 +258,51 @@ export const aiTell: Detector = (doc, options): Finding[] => {
|
|
|
258
258
|
* **どちらが正しいかは決めない。** 短縮形を使うかどうかは文体の選択で、
|
|
259
259
|
* 立場を取ると方針の違う書き手に rule ごと無視される。spec §12.3。
|
|
260
260
|
*
|
|
261
|
-
* 語彙表は対を持つ(`pattern` と `instead_of
|
|
262
|
-
*
|
|
261
|
+
* 語彙表は対を持つ(`pattern` と `instead_of`)。比べるのは対の中だけで、別の語どうしは比べない。
|
|
262
|
+
* GOV.UK の文体は「you're」を使い否定は「do not」と書く。語ごとに決めた書きかたで、混在ではない。
|
|
263
|
+
* 否定と代名詞+動詞の族にもまとめない。「don't」と「does not」を書き分ける文書もある。
|
|
263
264
|
*/
|
|
264
265
|
/**
|
|
265
266
|
* 語の境界で照合する。部分一致だと「it isn't」が「it is」を含んでしまい、
|
|
266
267
|
* 短縮形を使っている文が「使っていない」側に数えられる。
|
|
267
268
|
*/
|
|
268
|
-
const
|
|
269
|
+
const wordUses = (text: string, word: string): number => [...text.matchAll(new RegExp(`\\b${word.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}\\b`, "gu"))].length;
|
|
269
270
|
|
|
270
|
-
|
|
271
|
-
|
|
271
|
+
const containsWord = (text: string, word: string): boolean => wordUses(text, word) > 0;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* アポストロフィの形(don’t と don't)は短縮形かどうかを変えない。違うのは印刷の形で、文体ではない。
|
|
275
|
+
* 折り返した行(「do」で改行して「not」)も、空白 1 つと同じに読む。
|
|
276
|
+
*/
|
|
277
|
+
const comparableText = (sentence: Sentence): string => straightApostrophes(sentence.text).replace(/\s+/gu, " ").toLowerCase();
|
|
278
|
+
|
|
279
|
+
type MixedPair = { readonly minority: string; readonly majority: string; readonly count: number };
|
|
280
|
+
|
|
281
|
+
const mixedPair = (body: string, short: string, long: string): MixedPair | undefined => {
|
|
282
|
+
const uses = { short: wordUses(body, short), long: wordUses(body, long) };
|
|
283
|
+
const side = pairMinority(uses);
|
|
284
|
+
if (side === undefined) return undefined;
|
|
285
|
+
return side === "short" ? { minority: short, majority: long, count: uses.short } : { minority: long, majority: short, count: uses.long };
|
|
286
|
+
};
|
|
272
287
|
|
|
273
288
|
export const contractionMix: Detector = (doc, options): Finding[] => {
|
|
274
|
-
|
|
275
|
-
const body = doc.sentences.map(comparableText).join("
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const minorityIsShort = used.length <= spelled.length;
|
|
281
|
-
const few = minorityIsShort ? used : spelled;
|
|
282
|
-
if (few.length > options.limit) return [];
|
|
283
|
-
const wanted = few.map((pair) => (minorityIsShort ? pair.short : pair.long).toLowerCase());
|
|
289
|
+
// 文は改行でつなぐ。空白でつなぐと、箇条書きの「What we do」と次の項目「not every…」が「do not」と数えられる。
|
|
290
|
+
const body = doc.sentences.map(comparableText).join("\n");
|
|
291
|
+
const mixed = (options.lexicon ?? []).flatMap((entry) => {
|
|
292
|
+
const pair = entry.instead_of === undefined ? undefined : mixedPair(body, entry.pattern.toLowerCase(), entry.instead_of.toLowerCase());
|
|
293
|
+
return pair === undefined || pair.count > options.limit ? [] : [pair];
|
|
294
|
+
});
|
|
284
295
|
const hits = doc.sentences.flatMap((sentence) => {
|
|
285
296
|
const text = comparableText(sentence);
|
|
286
|
-
const
|
|
287
|
-
return
|
|
297
|
+
const pair = mixed.find((candidate) => containsWord(text, candidate.minority));
|
|
298
|
+
return pair === undefined ? [] : [{ sentence, pair }];
|
|
288
299
|
});
|
|
289
|
-
return hits.map((
|
|
300
|
+
return hits.map(({ sentence, pair }) => ({
|
|
290
301
|
rule: "contraction-consistency",
|
|
291
302
|
severity: "info",
|
|
292
303
|
line: 0,
|
|
293
304
|
column: 0,
|
|
294
|
-
quote:
|
|
295
|
-
values: { matched:
|
|
305
|
+
quote: sentence.text.trim(),
|
|
306
|
+
values: { matched: pair.minority, majority: pair.majority, count: pair.count, limit: options.limit, offset: sentence.span.start },
|
|
296
307
|
}));
|
|
297
308
|
};
|
|
@@ -63,18 +63,56 @@ const isTitleCase = (text: string): boolean =>
|
|
|
63
63
|
.split(/\s+/u)
|
|
64
64
|
.every((word) => TITLE_SMALL_WORDS.has(word) || /^\p{Lu}/u.test(word));
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
/** A determiner that opens an object (the, a, your): no noun phrase goes on from its head with one. */
|
|
67
|
+
const opensObject = (token: Token | undefined): boolean => token?.features?.["PronType"] === "Art" || token?.features?.["Poss"] === "Yes";
|
|
68
|
+
|
|
69
|
+
const AFTER_ADJECTIVE = new Set(["ADP", "PART"]);
|
|
70
|
+
|
|
71
|
+
/** A noun or adjective, or an ordinary word the tagger took for a name because it is capitalised (Toggle). */
|
|
72
|
+
const isNounOrAdjective = (token: Token): boolean =>
|
|
73
|
+
token.pos === "NOUN" || token.pos === "ADJ" || (token.pos === "PROPN" && token.features?.["OrdinaryWord"] === "Yes");
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The head of an item whose first two words overrule the first word's tag, or undefined when they do not. "Open the console"
|
|
77
|
+
* and "Press the button" open with a verb. "Clean up after closing" and "Bake in the oven" may open with a verb or an
|
|
78
|
+
* adjective phrase (Close to the station), and "Washing machine space" with a compound noun or a gerund and its object
|
|
79
|
+
* (Washing dishes): neither is judged.
|
|
80
|
+
*/
|
|
81
|
+
const headFromNextWord = (first: Token, next: Token | undefined): "verb" | "unjudged" | undefined => {
|
|
82
|
+
if (isNounOrAdjective(first) && opensObject(next)) return "verb";
|
|
83
|
+
if (first.pos === "ADJ" && AFTER_ADJECTIVE.has(next?.pos ?? "")) return "unjudged";
|
|
84
|
+
return first.features?.["VerbForm"] === "Ger" && next?.pos === "NOUN" ? "unjudged" : undefined;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** The head as the first word's tag gives it. */
|
|
88
|
+
const headFromTag = (first: Token): string | undefined => {
|
|
89
|
+
if (isUnsure(first)) return undefined;
|
|
69
90
|
// A participle (Generated files, Nested lists) modifies the noun after it; the item is a noun phrase, but the tag does not say so.
|
|
70
91
|
if (first.pos === "VERB") return first.features?.["VerbForm"] === "Part" ? undefined : "verb";
|
|
71
92
|
return NOUN_HEAD.has(first.pos) ? "noun" : undefined;
|
|
72
93
|
};
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
|
|
95
|
+
const englishHead = (sentences: readonly Sentence[], instructionVerbs: ReadonlySet<string>): string | undefined => {
|
|
96
|
+
const tokens = sentences[0]?.tokens ?? [];
|
|
97
|
+
const at = tokens.findIndex((token) => !SKIPPED_AT_END.has(token.pos));
|
|
98
|
+
const first = tokens[at];
|
|
99
|
+
if (at === -1 || first === undefined || isTitleCase(sentences[0]?.text ?? "")) return undefined;
|
|
100
|
+
// The word right after, punctuation included: in "Next, the candidate" the comma ends the opener.
|
|
101
|
+
const next = tokens[at + 1];
|
|
102
|
+
// Before a common noun the word may head a compound (Click fraud, Scroll bar), so its tag decides.
|
|
103
|
+
if (instructionVerbs.has(first.surface.toLowerCase()) && next?.pos !== "NOUN") return "verb";
|
|
104
|
+
const overruled = headFromNextWord(first, next);
|
|
105
|
+
if (overruled === undefined) return headFromTag(first);
|
|
106
|
+
return overruled === "verb" ? "verb" : undefined;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* An item's form on an axis, or undefined when its words do not tell. Japanese items have no head axis (the verb comes last).
|
|
111
|
+
* instructionVerbs: verbs the tagger does not know as verbs (click), from the adapter's instruction-verb word list.
|
|
112
|
+
*/
|
|
113
|
+
export const formOf = (axis: Axis, sentences: readonly Sentence[], language: string, instructionVerbs: ReadonlySet<string> = new Set()): string | undefined => {
|
|
76
114
|
if (language === "ja") return axis === "ending" ? japaneseEnding(sentences) : undefined;
|
|
77
|
-
return axis === "ending" ? englishEnding(sentences) : englishHead(sentences);
|
|
115
|
+
return axis === "ending" ? englishEnding(sentences) : englishHead(sentences, instructionVerbs);
|
|
78
116
|
};
|
|
79
117
|
|
|
80
118
|
const within = (inner: Span, outer: Span): boolean => inner.start >= outer.start && inner.end <= outer.end;
|
|
@@ -131,9 +169,10 @@ const listFindings = (doc: ProseDocument, list: BulletList, limit: number): Find
|
|
|
131
169
|
const span = list.itemSpans[index];
|
|
132
170
|
return span !== undefined && isJudged(doc.source.slice(span.start, sentences.at(-1)?.span.end ?? span.end), sentences);
|
|
133
171
|
});
|
|
172
|
+
const instructionVerbs = new Set((doc.lexicons["instruction-verb"] ?? []).map((entry) => entry.pattern.toLowerCase()));
|
|
134
173
|
return AXES.flatMap((axis) => {
|
|
135
174
|
const items = judged.flatMap((sentences) => {
|
|
136
|
-
const form = formOf(axis, sentences, doc.language);
|
|
175
|
+
const form = formOf(axis, sentences, doc.language, instructionVerbs);
|
|
137
176
|
return form === undefined ? [] : [{ sentences, form }];
|
|
138
177
|
});
|
|
139
178
|
const odd = minorityWithin(items, (item) => item.form === FORMS[axis][0], limit);
|
|
@@ -2,6 +2,7 @@ import type { Detector, Finding, Lexicon, ProseDocument, Sentence } from "../plu
|
|
|
2
2
|
import { escapeRegExp } from "../orthography.ts";
|
|
3
3
|
import { minorityReport } from "../spacing-minority.ts";
|
|
4
4
|
import { isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
5
|
+
import { captionsOf, isCaptionAt } from "./caps-caption.ts";
|
|
5
6
|
|
|
6
7
|
/** The letters a mark must touch to count as part of the document's text, by language. */
|
|
7
8
|
const SCRIPT: Readonly<Record<string, RegExp>> = {
|
|
@@ -41,12 +42,15 @@ const besideLetter = (text: string, at: number, step: number, script: RegExp): b
|
|
|
41
42
|
|
|
42
43
|
const touchesScript = (text: string, at: number, script: RegExp): boolean => besideLetter(text, at, -1, script) || besideLetter(text, at, 1, script);
|
|
43
44
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
45
|
+
/**
|
|
46
|
+
* The marks in a sentence that touch a letter of the document's script, outside 「」『』 quotations. spaced is the lexicon's pattern side.
|
|
47
|
+
* The letters beside a mark are read in the source, so a mark that opens a sentence (。(2)当社) counts wherever the sentence starts.
|
|
48
|
+
*/
|
|
49
|
+
export const marksIn = (source: string, sentence: Sentence, forms: ReadonlyMap<string, Form>, script: RegExp): Mark[] => {
|
|
46
50
|
const quoted = quotedSpans(sentence.text);
|
|
47
51
|
return sentence.text.split("").flatMap((char, at) => {
|
|
48
52
|
const form = forms.get(char);
|
|
49
|
-
if (form === undefined || !touchesScript(sentence.
|
|
53
|
+
if (form === undefined || !touchesScript(source, sentence.span.start + at, script)) return [];
|
|
50
54
|
if (isWithinAny(quoted, { start: at, end: at })) return [];
|
|
51
55
|
return [{ sentence, char, form, offset: sentence.span.start + at, spaced: form.side }];
|
|
52
56
|
});
|
|
@@ -88,7 +92,7 @@ export const markConsistency: Detector = (doc, options): Finding[] => {
|
|
|
88
92
|
const script = SCRIPT[doc.language];
|
|
89
93
|
if (script === undefined) return [];
|
|
90
94
|
const forms = formsOf(options.lexicon ?? []);
|
|
91
|
-
const marks = ownSentences(doc).flatMap((sentence) => marksIn(sentence, forms, script));
|
|
95
|
+
const marks = ownSentences(doc).flatMap((sentence) => marksIn(doc.source, sentence, forms, script));
|
|
92
96
|
const kinds = [...new Set(marks.map((mark) => mark.form.kind))];
|
|
93
97
|
return kinds.flatMap((kind) =>
|
|
94
98
|
minorityFindings(
|
|
@@ -210,10 +214,12 @@ export const isShouting = (run: string, known: ReadonlySet<string>, conventional
|
|
|
210
214
|
return long.length >= MIN_LONG_WORDS && ordinary.length * 2 > words.length;
|
|
211
215
|
};
|
|
212
216
|
|
|
213
|
-
/** Runs of three or more all-capital words that are ordinary words, not acronyms ("DO NOT DELETE THIS"). */
|
|
217
|
+
/** Runs of three or more all-capital words that are ordinary words, not acronyms ("DO NOT DELETE THIS"), and not a caption or a mention of one. */
|
|
214
218
|
export const capsShouting: Detector = (doc, options): Finding[] => {
|
|
215
219
|
const known = lowerCaseWords(doc.prose ?? doc.source);
|
|
216
220
|
const conventional = new Set((options.lexicon ?? []).map((entry) => entry.pattern));
|
|
217
|
-
const
|
|
221
|
+
const captions = captionsOf(doc.source);
|
|
222
|
+
const isCaption = (hit: Hit): boolean => captions.has(hit.matched) || isCaptionAt(doc.source, hit.offset, hit.offset + hit.matched.length);
|
|
223
|
+
const hits = hitsOf(ownSentences(doc), CAPS_RUN).filter((hit) => isShouting(hit.matched, known, conventional) && !isCaption(hit));
|
|
218
224
|
return reportFrom(hits, options.limit);
|
|
219
225
|
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ProseDocument, Token } from "../plugin.ts";
|
|
2
|
+
import { nameKey, type NameMention } from "../name-variants.ts";
|
|
3
|
+
import { companyGroupBases, type CompanyMention } from "../company-names.ts";
|
|
4
|
+
import type { OrderName } from "../name-word-order.ts";
|
|
5
|
+
import { isInCapitalsPassage } from "../capitals-passage.ts";
|
|
6
|
+
import { givenNameBefore } from "../name-given-before.ts";
|
|
7
|
+
import { definedTerms } from "../structure/definition-use.ts";
|
|
8
|
+
|
|
9
|
+
// name-variant が、似た形でも別のものと見る所。大文字で書いた一節、名の違う二人、会社のグループの一社ずつ、定義した語、同じ文に
|
|
10
|
+
// 並べた二つ。
|
|
11
|
+
|
|
12
|
+
/** 大文字で書いた一節(契約書の免責の段落、大文字の見出し)の中の名前(eGAIN SYSTEM)。その節の大文字で、名前の書き方ではない。 */
|
|
13
|
+
export const outsideCapitals = <Mention extends { readonly offset: number; readonly surface: string }>(
|
|
14
|
+
prose: string,
|
|
15
|
+
mentions: readonly Mention[],
|
|
16
|
+
): Mention[] => mentions.filter((mention) => !isInCapitalsPassage(prose, mention.offset, mention.offset + mention.surface.length));
|
|
17
|
+
|
|
18
|
+
/** 名前に、すぐ前に書いた名(Jeffrey D. Walker の Jeffrey)を付ける。tokens は文書の順の語。 */
|
|
19
|
+
export const withGivenNames = (tokens: readonly Token[], source: string, mentions: readonly NameMention[]): NameMention[] => {
|
|
20
|
+
const startAt = new Map(tokens.map((token, index) => [token.span.start, index]));
|
|
21
|
+
return mentions.map((mention) => {
|
|
22
|
+
const index = startAt.get(mention.offset);
|
|
23
|
+
const givenName = index === undefined ? undefined : givenNameBefore(tokens, index, source);
|
|
24
|
+
return givenName === undefined ? mention : { ...mention, givenName };
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 会社のグループ(companyGroupBases)の一社の名前どうし(GitLab Ltd (UK) と GitLab LTD (Ireland))か。形の語の書き方の違いも、
|
|
30
|
+
* 別の会社を言い分けている。forms は会社の形の語(Inc、Ltd)。
|
|
31
|
+
*/
|
|
32
|
+
export const isGroupPairOf = (
|
|
33
|
+
companies: readonly CompanyMention[],
|
|
34
|
+
forms: readonly string[],
|
|
35
|
+
): ((found: { readonly name: string; readonly usual: string }) => boolean) => {
|
|
36
|
+
const groups = [...companyGroupBases(companies)];
|
|
37
|
+
const formKeys = forms.map(nameKey);
|
|
38
|
+
const isGroupName = (surface: string): boolean => {
|
|
39
|
+
const key = nameKey(surface);
|
|
40
|
+
return groups.some((base) => formKeys.some((form) => key === base + form));
|
|
41
|
+
};
|
|
42
|
+
return ({ name, usual }) => isGroupName(name) && isGroupName(usual);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** 位置を含む文の番号。文の外(見出し、表)は、その前の文の番号。 */
|
|
46
|
+
export const sentenceIndexOf = (doc: ProseDocument): ((offset: number) => number) => {
|
|
47
|
+
const starts = doc.sentences.map((sentence) => sentence.span.start);
|
|
48
|
+
const search = (offset: number, low: number, high: number): number => {
|
|
49
|
+
if (low >= high) return low - 1;
|
|
50
|
+
const middle = Math.floor((low + high) / 2);
|
|
51
|
+
return (starts[middle] ?? 0) <= offset ? search(offset, middle + 1, high) : search(offset, low, middle);
|
|
52
|
+
};
|
|
53
|
+
return (offset) => search(offset, 0, starts.length);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 文書が定義した語(“Company Subsidiary” means …)でない名前。定義した語は文書が作った呼び名で、同じ語を違う順に並べた所
|
|
58
|
+
* (Subsidiary of the Company)はその中身を書いたふつうの言い方。
|
|
59
|
+
*/
|
|
60
|
+
export const notDefinedTerms = (doc: ProseDocument, names: readonly OrderName[]): OrderName[] => {
|
|
61
|
+
const terms = new Set(doc.structure === undefined ? [] : definedTerms(doc.structure).map(({ term }) => term.toLowerCase()));
|
|
62
|
+
return names.filter((name) => !terms.has(name.surface.toLowerCase()));
|
|
63
|
+
};
|