chaffjs 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/announced-count.d.ts +26 -0
- package/dist/announced-count.d.ts.map +1 -0
- package/dist/announced-count.js +104 -0
- package/dist/announced-count.js.map +1 -0
- package/dist/bare-url.d.ts +14 -0
- package/dist/bare-url.d.ts.map +1 -0
- package/dist/bare-url.js +28 -0
- package/dist/bare-url.js.map +1 -0
- package/dist/baseline.d.ts +5 -0
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +16 -1
- package/dist/baseline.js.map +1 -1
- package/dist/body-section.d.ts +7 -0
- package/dist/body-section.d.ts.map +1 -0
- package/dist/body-section.js +6 -0
- package/dist/body-section.js.map +1 -0
- package/dist/calendar-number.d.ts +9 -2
- package/dist/calendar-number.d.ts.map +1 -1
- package/dist/calendar-number.js +18 -4
- package/dist/calendar-number.js.map +1 -1
- package/dist/cli-args.d.ts +4 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +5 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +8 -4
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.js +33 -30
- package/dist/cli.js.map +1 -1
- package/dist/closing-numbers.d.ts +20 -0
- package/dist/closing-numbers.d.ts.map +1 -0
- package/dist/closing-numbers.js +56 -0
- package/dist/closing-numbers.js.map +1 -0
- package/dist/commands/compare.d.ts +8 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +72 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +17 -9
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/feedback.d.ts +5 -2
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +11 -5
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +13 -13
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/tree.d.ts +13 -0
- package/dist/commands/tree.d.ts.map +1 -1
- package/dist/commands/tree.js +35 -5
- package/dist/commands/tree.js.map +1 -1
- package/dist/compare/atom.d.ts +31 -0
- package/dist/compare/atom.d.ts.map +1 -0
- package/dist/compare/atom.js +4 -0
- package/dist/compare/atom.js.map +1 -0
- package/dist/compare/clock-time.d.ts +8 -0
- package/dist/compare/clock-time.d.ts.map +1 -0
- package/dist/compare/clock-time.js +65 -0
- package/dist/compare/clock-time.js.map +1 -0
- package/dist/compare/extract.d.ts +15 -0
- package/dist/compare/extract.d.ts.map +1 -0
- package/dist/compare/extract.js +58 -0
- package/dist/compare/extract.js.map +1 -0
- package/dist/compare/fact-text.d.ts +23 -0
- package/dist/compare/fact-text.d.ts.map +1 -0
- package/dist/compare/fact-text.js +47 -0
- package/dist/compare/fact-text.js.map +1 -0
- package/dist/compare/markup-atoms.d.ts +11 -0
- package/dist/compare/markup-atoms.d.ts.map +1 -0
- package/dist/compare/markup-atoms.js +23 -0
- package/dist/compare/markup-atoms.js.map +1 -0
- package/dist/compare/match.d.ts +19 -0
- package/dist/compare/match.d.ts.map +1 -0
- package/dist/compare/match.js +84 -0
- package/dist/compare/match.js.map +1 -0
- package/dist/compare/outcome.d.ts +33 -0
- package/dist/compare/outcome.d.ts.map +1 -0
- package/dist/compare/outcome.js +40 -0
- package/dist/compare/outcome.js.map +1 -0
- package/dist/compare/proper-nouns.d.ts +19 -0
- package/dist/compare/proper-nouns.d.ts.map +1 -0
- package/dist/compare/proper-nouns.js +44 -0
- package/dist/compare/proper-nouns.js.map +1 -0
- package/dist/compare/render.d.ts +9 -0
- package/dist/compare/render.d.ts.map +1 -0
- package/dist/compare/render.js +64 -0
- package/dist/compare/render.js.map +1 -0
- package/dist/compare/spans.d.ts +9 -0
- package/dist/compare/spans.d.ts.map +1 -0
- package/dist/compare/spans.js +11 -0
- package/dist/compare/spans.js.map +1 -0
- package/dist/compare/text-atoms.d.ts +24 -0
- package/dist/compare/text-atoms.d.ts.map +1 -0
- package/dist/compare/text-atoms.js +67 -0
- package/dist/compare/text-atoms.js.map +1 -0
- package/dist/compare/text.d.ts +24 -0
- package/dist/compare/text.d.ts.map +1 -0
- package/dist/compare/text.js +90 -0
- package/dist/compare/text.js.map +1 -0
- package/dist/compare/tree-atoms.d.ts +20 -0
- package/dist/compare/tree-atoms.d.ts.map +1 -0
- package/dist/compare/tree-atoms.js +58 -0
- package/dist/compare/tree-atoms.js.map +1 -0
- package/dist/compare/written-names.d.ts +8 -0
- package/dist/compare/written-names.d.ts.map +1 -0
- package/dist/compare/written-names.js +24 -0
- package/dist/compare/written-names.js.map +1 -0
- package/dist/config/load.d.ts +15 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +5 -0
- package/dist/config/load.js.map +1 -1
- package/dist/config/option-problems.d.ts +16 -0
- package/dist/config/option-problems.d.ts.map +1 -0
- package/dist/config/option-problems.js +58 -0
- package/dist/config/option-problems.js.map +1 -0
- package/dist/config/read.d.ts +4 -0
- package/dist/config/read.d.ts.map +1 -0
- package/dist/config/read.js +8 -0
- package/dist/config/read.js.map +1 -0
- package/dist/config/rule-problems.d.ts +2 -4
- package/dist/config/rule-problems.d.ts.map +1 -1
- package/dist/config/rule-problems.js +7 -1
- package/dist/config/rule-problems.js.map +1 -1
- package/dist/config/style.d.ts +16 -0
- package/dist/config/style.d.ts.map +1 -0
- package/dist/config/style.js +36 -0
- package/dist/config/style.js.map +1 -0
- package/dist/config/warnings.d.ts +6 -0
- package/dist/config/warnings.d.ts.map +1 -0
- package/dist/config/warnings.js +10 -0
- package/dist/config/warnings.js.map +1 -0
- package/dist/config/write.d.ts.map +1 -1
- package/dist/config/write.js +17 -4
- package/dist/config/write.js.map +1 -1
- package/dist/custom/bounded-match.d.ts +15 -0
- package/dist/custom/bounded-match.d.ts.map +1 -0
- package/dist/custom/bounded-match.js +43 -0
- package/dist/custom/bounded-match.js.map +1 -0
- package/dist/custom/load.d.ts +8 -0
- package/dist/custom/load.d.ts.map +1 -0
- package/dist/custom/load.js +11 -0
- package/dist/custom/load.js.map +1 -0
- package/dist/custom/parse.d.ts +70 -0
- package/dist/custom/parse.d.ts.map +1 -0
- package/dist/custom/parse.js +215 -0
- package/dist/custom/parse.js.map +1 -0
- package/dist/custom/problems.d.ts +5 -0
- package/dist/custom/problems.d.ts.map +1 -0
- package/dist/custom/problems.js +78 -0
- package/dist/custom/problems.js.map +1 -0
- package/dist/custom/regex-safety.d.ts +11 -0
- package/dist/custom/regex-safety.d.ts.map +1 -0
- package/dist/custom/regex-safety.js +110 -0
- package/dist/custom/regex-safety.js.map +1 -0
- package/dist/custom/token-pattern.d.ts +8 -0
- package/dist/custom/token-pattern.d.ts.map +1 -0
- package/dist/custom/token-pattern.js +75 -0
- package/dist/custom/token-pattern.js.map +1 -0
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +24 -2
- package/dist/detect.js.map +1 -1
- package/dist/detectors/acronym-context.d.ts +4 -0
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +25 -4
- package/dist/detectors/acronym-context.js.map +1 -1
- package/dist/detectors/acronym-expansion.d.ts +2 -0
- package/dist/detectors/acronym-expansion.d.ts.map +1 -1
- package/dist/detectors/acronym-expansion.js +104 -1
- package/dist/detectors/acronym-expansion.js.map +1 -1
- package/dist/detectors/agreement-slip.d.ts +32 -0
- package/dist/detectors/agreement-slip.d.ts.map +1 -0
- package/dist/detectors/agreement-slip.js +137 -0
- package/dist/detectors/agreement-slip.js.map +1 -0
- package/dist/detectors/ai-phrasing.d.ts +20 -0
- package/dist/detectors/ai-phrasing.d.ts.map +1 -0
- package/dist/detectors/ai-phrasing.js +112 -0
- package/dist/detectors/ai-phrasing.js.map +1 -0
- package/dist/detectors/announced-count.d.ts +4 -0
- package/dist/detectors/announced-count.d.ts.map +1 -0
- package/dist/detectors/announced-count.js +20 -0
- package/dist/detectors/announced-count.js.map +1 -0
- package/dist/detectors/broken-link.d.ts +17 -0
- package/dist/detectors/broken-link.d.ts.map +1 -0
- package/dist/detectors/broken-link.js +66 -0
- package/dist/detectors/broken-link.js.map +1 -0
- package/dist/detectors/cited-name.d.ts.map +1 -1
- package/dist/detectors/cited-name.js +4 -4
- package/dist/detectors/cited-name.js.map +1 -1
- package/dist/detectors/cited-title.d.ts +11 -0
- package/dist/detectors/cited-title.d.ts.map +1 -0
- package/dist/detectors/cited-title.js +75 -0
- package/dist/detectors/cited-title.js.map +1 -0
- package/dist/detectors/concrete-evidence.d.ts +1 -1
- package/dist/detectors/concrete-evidence.d.ts.map +1 -1
- package/dist/detectors/concrete-evidence.js +2 -1
- package/dist/detectors/concrete-evidence.js.map +1 -1
- package/dist/detectors/content-morphemes.d.ts +4 -0
- package/dist/detectors/content-morphemes.d.ts.map +1 -0
- package/dist/detectors/content-morphemes.js +12 -0
- package/dist/detectors/content-morphemes.js.map +1 -0
- package/dist/detectors/contrast-frame.d.ts +17 -0
- package/dist/detectors/contrast-frame.d.ts.map +1 -0
- package/dist/detectors/contrast-frame.js +32 -0
- package/dist/detectors/contrast-frame.js.map +1 -0
- package/dist/detectors/custom.d.ts +8 -0
- package/dist/detectors/custom.d.ts.map +1 -0
- package/dist/detectors/custom.js +71 -0
- package/dist/detectors/custom.js.map +1 -0
- package/dist/detectors/dangling-figure.d.ts +4 -0
- package/dist/detectors/dangling-figure.d.ts.map +1 -0
- package/dist/detectors/dangling-figure.js +18 -0
- package/dist/detectors/dangling-figure.js.map +1 -0
- package/dist/detectors/doubled-punctuation.d.ts +9 -0
- package/dist/detectors/doubled-punctuation.d.ts.map +1 -0
- package/dist/detectors/doubled-punctuation.js +33 -0
- package/dist/detectors/doubled-punctuation.js.map +1 -0
- package/dist/detectors/doubled-word.d.ts +5 -0
- package/dist/detectors/doubled-word.d.ts.map +1 -1
- package/dist/detectors/doubled-word.js +24 -11
- package/dist/detectors/doubled-word.js.map +1 -1
- package/dist/detectors/en-shape.d.ts +0 -1
- package/dist/detectors/en-shape.d.ts.map +1 -1
- package/dist/detectors/en-shape.js +0 -235
- package/dist/detectors/en-shape.js.map +1 -1
- package/dist/detectors/enumerated-runs.d.ts +1 -1
- package/dist/detectors/enumerated-runs.d.ts.map +1 -1
- package/dist/detectors/enumerated-runs.js +15 -4
- package/dist/detectors/enumerated-runs.js.map +1 -1
- package/dist/detectors/gram-furniture.d.ts +6 -0
- package/dist/detectors/gram-furniture.d.ts.map +1 -0
- package/dist/detectors/gram-furniture.js +21 -0
- package/dist/detectors/gram-furniture.js.map +1 -0
- package/dist/detectors/gram-place.d.ts +2 -0
- package/dist/detectors/gram-place.d.ts.map +1 -1
- package/dist/detectors/gram-place.js +9 -7
- package/dist/detectors/gram-place.js.map +1 -1
- package/dist/detectors/gram-windows.d.ts +9 -0
- package/dist/detectors/gram-windows.d.ts.map +1 -0
- package/dist/detectors/gram-windows.js +27 -0
- package/dist/detectors/gram-windows.js.map +1 -0
- package/dist/detectors/heading-case.d.ts +2 -0
- package/dist/detectors/heading-case.d.ts.map +1 -1
- package/dist/detectors/heading-case.js +29 -2
- package/dist/detectors/heading-case.js.map +1 -1
- package/dist/detectors/heading-code-words.d.ts +6 -0
- package/dist/detectors/heading-code-words.d.ts.map +1 -0
- package/dist/detectors/heading-code-words.js +29 -0
- package/dist/detectors/heading-code-words.js.map +1 -0
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +17 -20
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/heading-level-skip.d.ts +12 -0
- package/dist/detectors/heading-level-skip.d.ts.map +1 -0
- package/dist/detectors/heading-level-skip.js +11 -0
- package/dist/detectors/heading-level-skip.js.map +1 -0
- package/dist/detectors/heading-overlap.d.ts +13 -0
- package/dist/detectors/heading-overlap.d.ts.map +1 -0
- package/dist/detectors/heading-overlap.js +52 -0
- package/dist/detectors/heading-overlap.js.map +1 -0
- package/dist/detectors/image-alt-text.d.ts +3 -0
- package/dist/detectors/image-alt-text.d.ts.map +1 -0
- package/dist/detectors/image-alt-text.js +9 -0
- package/dist/detectors/image-alt-text.js.map +1 -0
- package/dist/detectors/index.d.ts.map +1 -1
- package/dist/detectors/index.js +40 -2
- package/dist/detectors/index.js.map +1 -1
- package/dist/detectors/kutoten-consistency.d.ts +24 -0
- package/dist/detectors/kutoten-consistency.d.ts.map +1 -0
- package/dist/detectors/kutoten-consistency.js +77 -0
- package/dist/detectors/kutoten-consistency.js.map +1 -0
- package/dist/detectors/lead-in.d.ts +1 -0
- package/dist/detectors/lead-in.d.ts.map +1 -1
- package/dist/detectors/lead-in.js +2 -1
- package/dist/detectors/lead-in.js.map +1 -1
- package/dist/detectors/letter-joined-name.d.ts +13 -0
- package/dist/detectors/letter-joined-name.d.ts.map +1 -0
- package/dist/detectors/letter-joined-name.js +11 -0
- package/dist/detectors/letter-joined-name.js.map +1 -0
- package/dist/detectors/lexicon-match.d.ts +4 -0
- package/dist/detectors/lexicon-match.d.ts.map +1 -1
- package/dist/detectors/lexicon-match.js +7 -2
- package/dist/detectors/lexicon-match.js.map +1 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +5 -2
- package/dist/detectors/lexicon.js.map +1 -1
- package/dist/detectors/list-item.d.ts +45 -0
- package/dist/detectors/list-item.d.ts.map +1 -0
- package/dist/detectors/list-item.js +88 -0
- package/dist/detectors/list-item.js.map +1 -0
- package/dist/detectors/list-items.d.ts +31 -0
- package/dist/detectors/list-items.d.ts.map +1 -0
- package/dist/detectors/list-items.js +113 -0
- package/dist/detectors/list-items.js.map +1 -0
- package/dist/detectors/list-lead-in.d.ts +7 -0
- package/dist/detectors/list-lead-in.d.ts.map +1 -0
- package/dist/detectors/list-lead-in.js +28 -0
- package/dist/detectors/list-lead-in.js.map +1 -0
- package/dist/detectors/list-sentence.d.ts +65 -0
- package/dist/detectors/list-sentence.d.ts.map +1 -0
- package/dist/detectors/list-sentence.js +105 -0
- package/dist/detectors/list-sentence.js.map +1 -0
- package/dist/detectors/list-view.d.ts +34 -0
- package/dist/detectors/list-view.d.ts.map +1 -0
- package/dist/detectors/list-view.js +137 -0
- package/dist/detectors/list-view.js.map +1 -0
- package/dist/detectors/long-vowel.d.ts +7 -0
- package/dist/detectors/long-vowel.d.ts.map +1 -0
- package/dist/detectors/long-vowel.js +57 -0
- package/dist/detectors/long-vowel.js.map +1 -0
- package/dist/detectors/markup-finding.d.ts +6 -0
- package/dist/detectors/markup-finding.d.ts.map +1 -0
- package/dist/detectors/markup-finding.js +19 -0
- package/dist/detectors/markup-finding.js.map +1 -0
- package/dist/detectors/name-numeral.d.ts +1 -1
- package/dist/detectors/name-numeral.d.ts.map +1 -1
- package/dist/detectors/name-numeral.js +2 -7
- package/dist/detectors/name-numeral.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +16 -12
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts +9 -0
- package/dist/detectors/oxford-comma.d.ts.map +1 -0
- package/dist/detectors/oxford-comma.js +246 -0
- package/dist/detectors/oxford-comma.js.map +1 -0
- package/dist/detectors/place-run.d.ts.map +1 -1
- package/dist/detectors/place-run.js +10 -6
- package/dist/detectors/place-run.js.map +1 -1
- package/dist/detectors/placeholder-text.d.ts +9 -0
- package/dist/detectors/placeholder-text.d.ts.map +1 -0
- package/dist/detectors/placeholder-text.js +18 -0
- package/dist/detectors/placeholder-text.js.map +1 -0
- package/dist/detectors/quote-around.d.ts +3 -0
- package/dist/detectors/quote-around.d.ts.map +1 -0
- package/dist/detectors/quote-around.js +8 -0
- package/dist/detectors/quote-around.js.map +1 -0
- package/dist/detectors/register.d.ts +11 -3
- package/dist/detectors/register.d.ts.map +1 -1
- package/dist/detectors/register.js +28 -9
- package/dist/detectors/register.js.map +1 -1
- package/dist/detectors/roman-numeral.d.ts +2 -0
- package/dist/detectors/roman-numeral.d.ts.map +1 -1
- package/dist/detectors/roman-numeral.js +2 -0
- package/dist/detectors/roman-numeral.js.map +1 -1
- package/dist/detectors/sentence-ending.d.ts +17 -1
- package/dist/detectors/sentence-ending.d.ts.map +1 -1
- package/dist/detectors/sentence-ending.js +13 -7
- package/dist/detectors/sentence-ending.js.map +1 -1
- package/dist/detectors/sentence-length.d.ts.map +1 -1
- package/dist/detectors/sentence-length.js +13 -4
- package/dist/detectors/sentence-length.js.map +1 -1
- package/dist/detectors/signals.d.ts +8 -0
- package/dist/detectors/signals.d.ts.map +1 -1
- package/dist/detectors/signals.js +94 -54
- package/dist/detectors/signals.js.map +1 -1
- package/dist/detectors/stacked-hedge.d.ts +0 -7
- package/dist/detectors/stacked-hedge.d.ts.map +1 -1
- package/dist/detectors/stacked-hedge.js +6 -3
- package/dist/detectors/stacked-hedge.js.map +1 -1
- package/dist/detectors/stray-space.d.ts +7 -0
- package/dist/detectors/stray-space.d.ts.map +1 -0
- package/dist/detectors/stray-space.js +34 -0
- package/dist/detectors/stray-space.js.map +1 -0
- package/dist/detectors/structure-tree.d.ts +6 -0
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +37 -1
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/structure.d.ts +4 -4
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +7 -6
- package/dist/detectors/structure.js.map +1 -1
- package/dist/detectors/superlative-name.d.ts.map +1 -1
- package/dist/detectors/superlative-name.js +8 -5
- package/dist/detectors/superlative-name.js.map +1 -1
- package/dist/detectors/superlative-scope.d.ts.map +1 -1
- package/dist/detectors/superlative-scope.js +9 -4
- package/dist/detectors/superlative-scope.js.map +1 -1
- package/dist/detectors/token-column.d.ts +46 -0
- package/dist/detectors/token-column.d.ts.map +1 -0
- package/dist/detectors/token-column.js +95 -0
- package/dist/detectors/token-column.js.map +1 -0
- package/dist/detectors/unbalanced-bracket.d.ts +22 -0
- package/dist/detectors/unbalanced-bracket.d.ts.map +1 -0
- package/dist/detectors/unbalanced-bracket.js +119 -0
- package/dist/detectors/unbalanced-bracket.js.map +1 -0
- package/dist/detectors/url-run-on.d.ts +9 -0
- package/dist/detectors/url-run-on.d.ts.map +1 -0
- package/dist/detectors/url-run-on.js +19 -0
- package/dist/detectors/url-run-on.js.map +1 -0
- package/dist/document-sections.d.ts +13 -0
- package/dist/document-sections.d.ts.map +1 -0
- package/dist/document-sections.js +32 -0
- package/dist/document-sections.js.map +1 -0
- package/dist/document.d.ts +11 -4
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +99 -95
- package/dist/document.js.map +1 -1
- package/dist/email-parts.d.ts +28 -0
- package/dist/email-parts.d.ts.map +1 -0
- package/dist/email-parts.js +230 -0
- package/dist/email-parts.js.map +1 -0
- package/dist/eval.d.ts +2 -1
- package/dist/eval.d.ts.map +1 -1
- package/dist/eval.js +16 -4
- package/dist/eval.js.map +1 -1
- package/dist/figure-references.d.ts +30 -0
- package/dist/figure-references.d.ts.map +1 -0
- package/dist/figure-references.js +76 -0
- package/dist/figure-references.js.map +1 -0
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +4 -0
- package/dist/files.js.map +1 -1
- package/dist/genre-parse.d.ts +5 -1
- package/dist/genre-parse.d.ts.map +1 -1
- package/dist/genre-parse.js +16 -3
- package/dist/genre-parse.js.map +1 -1
- package/dist/genre-suggest.d.ts.map +1 -1
- package/dist/genre-suggest.js +15 -1
- package/dist/genre-suggest.js.map +1 -1
- package/dist/heading-label.d.ts +22 -0
- package/dist/heading-label.d.ts.map +1 -0
- package/dist/heading-label.js +50 -0
- package/dist/heading-label.js.map +1 -0
- package/dist/in-page-nav.d.ts +4 -1
- package/dist/in-page-nav.d.ts.map +1 -1
- package/dist/in-page-nav.js +53 -18
- package/dist/in-page-nav.js.map +1 -1
- package/dist/joined-view.d.ts.map +1 -1
- package/dist/joined-view.js +1 -0
- package/dist/joined-view.js.map +1 -1
- package/dist/levels.d.ts +5 -1
- package/dist/levels.d.ts.map +1 -1
- package/dist/levels.js +9 -0
- package/dist/levels.js.map +1 -1
- package/dist/line-paragraphs.d.ts +8 -0
- package/dist/line-paragraphs.d.ts.map +1 -1
- package/dist/line-paragraphs.js +36 -11
- package/dist/line-paragraphs.js.map +1 -1
- package/dist/long-vowel.d.ts +35 -0
- package/dist/long-vowel.d.ts.map +1 -0
- package/dist/long-vowel.js +71 -0
- package/dist/long-vowel.js.map +1 -0
- package/dist/markdown-node.d.ts +19 -0
- package/dist/markdown-node.d.ts.map +1 -0
- package/dist/markdown-node.js +6 -0
- package/dist/markdown-node.js.map +1 -0
- package/dist/markdown-read.d.ts +17 -0
- package/dist/markdown-read.d.ts.map +1 -0
- package/dist/markdown-read.js +37 -0
- package/dist/markdown-read.js.map +1 -0
- package/dist/markup.d.ts +22 -0
- package/dist/markup.d.ts.map +1 -0
- package/dist/markup.js +180 -0
- package/dist/markup.js.map +1 -0
- package/dist/mask.d.ts.map +1 -1
- package/dist/mask.js +10 -16
- package/dist/mask.js.map +1 -1
- package/dist/number-name.d.ts +21 -5
- package/dist/number-name.d.ts.map +1 -1
- package/dist/number-name.js +120 -18
- package/dist/number-name.js.map +1 -1
- package/dist/opening-line.d.ts +3 -0
- package/dist/opening-line.d.ts.map +1 -0
- package/dist/opening-line.js +14 -0
- package/dist/opening-line.js.map +1 -0
- package/dist/orthography.d.ts +7 -1
- package/dist/orthography.d.ts.map +1 -1
- package/dist/orthography.js +16 -5
- package/dist/orthography.js.map +1 -1
- package/dist/page-furniture.d.ts +5 -2
- package/dist/page-furniture.d.ts.map +1 -1
- package/dist/page-furniture.js +8 -2
- package/dist/page-furniture.js.map +1 -1
- package/dist/paragraph-length.d.ts +7 -0
- package/dist/paragraph-length.d.ts.map +1 -0
- package/dist/paragraph-length.js +10 -0
- package/dist/paragraph-length.js.map +1 -0
- package/dist/plain-source.d.ts +1 -0
- package/dist/plain-source.d.ts.map +1 -1
- package/dist/plain-source.js +2 -1
- package/dist/plain-source.js.map +1 -1
- package/dist/plugin.d.ts +121 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/profile/for-file.d.ts.map +1 -1
- package/dist/profile/for-file.js +3 -1
- package/dist/profile/for-file.js.map +1 -1
- package/dist/quoted-span.d.ts +0 -2
- package/dist/quoted-span.d.ts.map +1 -1
- package/dist/quoted-span.js +9 -4
- package/dist/quoted-span.js.map +1 -1
- package/dist/reasons.d.ts +3 -0
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +6 -0
- package/dist/reasons.js.map +1 -1
- package/dist/reference-lists.d.ts +3 -0
- package/dist/reference-lists.d.ts.map +1 -0
- package/dist/reference-lists.js +75 -0
- package/dist/reference-lists.js.map +1 -0
- package/dist/render/explain.d.ts +7 -1
- package/dist/render/explain.d.ts.map +1 -1
- package/dist/render/explain.js +36 -12
- package/dist/render/explain.js.map +1 -1
- package/dist/render/friendly.d.ts.map +1 -1
- package/dist/render/friendly.js +19 -9
- package/dist/render/friendly.js.map +1 -1
- package/dist/render/options.d.ts +7 -0
- package/dist/render/options.d.ts.map +1 -0
- package/dist/render/options.js +50 -0
- package/dist/render/options.js.map +1 -0
- package/dist/render/rules-json.d.ts +4 -1
- package/dist/render/rules-json.d.ts.map +1 -1
- package/dist/render/rules-json.js +102 -12
- package/dist/render/rules-json.js.map +1 -1
- package/dist/render/rules-table.d.ts +4 -0
- package/dist/render/rules-table.d.ts.map +1 -0
- package/dist/render/rules-table.js +70 -0
- package/dist/render/rules-table.js.map +1 -0
- package/dist/render/sarif.js +4 -4
- package/dist/render/sarif.js.map +1 -1
- package/dist/render/semantic.js +3 -3
- package/dist/render/semantic.js.map +1 -1
- package/dist/render/severity-name.d.ts +6 -0
- package/dist/render/severity-name.d.ts.map +1 -0
- package/dist/render/severity-name.js +7 -0
- package/dist/render/severity-name.js.map +1 -0
- package/dist/render/text.d.ts +7 -2
- package/dist/render/text.d.ts.map +1 -1
- package/dist/render/text.js +15 -4
- package/dist/render/text.js.map +1 -1
- package/dist/resolve-genre.d.ts +1 -1
- package/dist/resolve-genre.d.ts.map +1 -1
- package/dist/resolve-genre.js +4 -1
- package/dist/resolve-genre.js.map +1 -1
- package/dist/rule-genres.d.ts +24 -0
- package/dist/rule-genres.d.ts.map +1 -0
- package/dist/rule-genres.js +11 -0
- package/dist/rule-genres.js.map +1 -0
- package/dist/rule-guide.d.ts +54 -0
- package/dist/rule-guide.d.ts.map +1 -0
- package/dist/rule-guide.js +81 -0
- package/dist/rule-guide.js.map +1 -0
- package/dist/rule-load.d.ts.map +1 -1
- package/dist/rule-load.js +94 -32
- package/dist/rule-load.js.map +1 -1
- package/dist/rule-options.d.ts +50 -0
- package/dist/rule-options.d.ts.map +1 -0
- package/dist/rule-options.js +106 -0
- package/dist/rule-options.js.map +1 -0
- package/dist/run-semantic.d.ts +3 -1
- package/dist/run-semantic.d.ts.map +1 -1
- package/dist/run-semantic.js +8 -3
- package/dist/run-semantic.js.map +1 -1
- package/dist/run.d.ts +15 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +57 -10
- package/dist/run.js.map +1 -1
- package/dist/semantic.d.ts +1 -1
- package/dist/semantic.d.ts.map +1 -1
- package/dist/semantic.js +10 -3
- package/dist/semantic.js.map +1 -1
- package/dist/sentence-shape.d.ts.map +1 -1
- package/dist/sentence-shape.js +4 -4
- package/dist/sentence-shape.js.map +1 -1
- package/dist/setting-problems.d.ts +2 -1
- package/dist/setting-problems.d.ts.map +1 -1
- package/dist/setting-problems.js +6 -1
- package/dist/setting-problems.js.map +1 -1
- package/dist/span-cut.d.ts +6 -0
- package/dist/span-cut.d.ts.map +1 -0
- package/dist/span-cut.js +22 -0
- package/dist/span-cut.js.map +1 -0
- package/dist/span-merge.d.ts +4 -0
- package/dist/span-merge.d.ts.map +1 -0
- package/dist/span-merge.js +12 -0
- package/dist/span-merge.js.map +1 -0
- package/dist/speaker-labels.d.ts +4 -0
- package/dist/speaker-labels.d.ts.map +1 -0
- package/dist/speaker-labels.js +106 -0
- package/dist/speaker-labels.js.map +1 -0
- package/dist/stray-space.d.ts +17 -0
- package/dist/stray-space.d.ts.map +1 -0
- package/dist/stray-space.js +66 -0
- package/dist/stray-space.js.map +1 -0
- package/dist/structure/aside-depth.d.ts +21 -0
- package/dist/structure/aside-depth.d.ts.map +1 -0
- package/dist/structure/aside-depth.js +65 -0
- package/dist/structure/aside-depth.js.map +1 -0
- package/dist/structure/build.d.ts +5 -1
- package/dist/structure/build.d.ts.map +1 -1
- package/dist/structure/build.js +29 -17
- package/dist/structure/build.js.map +1 -1
- package/dist/structure/closed-pairs.d.ts +8 -0
- package/dist/structure/closed-pairs.d.ts.map +1 -0
- package/dist/structure/closed-pairs.js +22 -0
- package/dist/structure/closed-pairs.js.map +1 -0
- package/dist/structure/date-range.d.ts +21 -0
- package/dist/structure/date-range.d.ts.map +1 -0
- package/dist/structure/date-range.js +45 -0
- package/dist/structure/date-range.js.map +1 -0
- package/dist/structure/known-mentions.d.ts +18 -0
- package/dist/structure/known-mentions.d.ts.map +1 -0
- package/dist/structure/known-mentions.js +78 -0
- package/dist/structure/known-mentions.js.map +1 -0
- package/dist/structure/numbering.d.ts +1 -0
- package/dist/structure/numbering.d.ts.map +1 -1
- package/dist/structure/numbering.js +11 -6
- package/dist/structure/numbering.js.map +1 -1
- package/dist/structure/of.d.ts +3 -1
- package/dist/structure/of.d.ts.map +1 -1
- package/dist/structure/of.js +5 -1
- package/dist/structure/of.js.map +1 -1
- package/dist/structure/percent-sum.d.ts +16 -0
- package/dist/structure/percent-sum.d.ts.map +1 -0
- package/dist/structure/percent-sum.js +104 -0
- package/dist/structure/percent-sum.js.map +1 -0
- package/dist/structure/quoted-number.d.ts +8 -0
- package/dist/structure/quoted-number.d.ts.map +1 -0
- package/dist/structure/quoted-number.js +34 -0
- package/dist/structure/quoted-number.js.map +1 -0
- package/dist/structure/relative-find.d.ts.map +1 -1
- package/dist/structure/relative-find.js +34 -46
- package/dist/structure/relative-find.js.map +1 -1
- package/dist/structure/relative-resolve.d.ts.map +1 -1
- package/dist/structure/relative-resolve.js +94 -42
- package/dist/structure/relative-resolve.js.map +1 -1
- package/dist/structure/runs.d.ts +2 -0
- package/dist/structure/runs.d.ts.map +1 -1
- package/dist/structure/runs.js +2 -2
- package/dist/structure/runs.js.map +1 -1
- package/dist/structure/sexp.d.ts +1 -1
- package/dist/structure/sexp.d.ts.map +1 -1
- package/dist/structure/sexp.js +18 -6
- package/dist/structure/sexp.js.map +1 -1
- package/dist/structure/total.d.ts +3 -0
- package/dist/structure/total.d.ts.map +1 -1
- package/dist/structure/total.js +2 -2
- package/dist/structure/total.js.map +1 -1
- package/dist/structure/universal.d.ts +14 -2
- package/dist/structure/universal.d.ts.map +1 -1
- package/dist/structure/universal.js +17 -2
- package/dist/structure/universal.js.map +1 -1
- package/dist/structure/wrapped-tail.d.ts +14 -7
- package/dist/structure/wrapped-tail.d.ts.map +1 -1
- package/dist/structure/wrapped-tail.js +33 -8
- package/dist/structure/wrapped-tail.js.map +1 -1
- package/dist/style-load.d.ts +4 -0
- package/dist/style-load.d.ts.map +1 -0
- package/dist/style-load.js +28 -0
- package/dist/style-load.js.map +1 -0
- package/dist/style-parse.d.ts +19 -0
- package/dist/style-parse.d.ts.map +1 -0
- package/dist/style-parse.js +60 -0
- package/dist/style-parse.js.map +1 -0
- package/dist/subheading-line.d.ts +6 -0
- package/dist/subheading-line.d.ts.map +1 -0
- package/dist/subheading-line.js +57 -0
- package/dist/subheading-line.js.map +1 -0
- package/dist/team-names.d.ts.map +1 -1
- package/dist/team-names.js +11 -14
- package/dist/team-names.js.map +1 -1
- package/dist/template-syntax.d.ts +17 -0
- package/dist/template-syntax.d.ts.map +1 -0
- package/dist/template-syntax.js +140 -0
- package/dist/template-syntax.js.map +1 -0
- package/dist/text-above.d.ts +19 -0
- package/dist/text-above.d.ts.map +1 -0
- package/dist/text-above.js +43 -0
- package/dist/text-above.js.map +1 -0
- package/dist/text-figures.d.ts +10 -0
- package/dist/text-figures.d.ts.map +1 -0
- package/dist/text-figures.js +131 -0
- package/dist/text-figures.js.map +1 -0
- package/dist/trailing-aside.d.ts +2 -0
- package/dist/trailing-aside.d.ts.map +1 -0
- package/dist/trailing-aside.js +53 -0
- package/dist/trailing-aside.js.map +1 -0
- package/dist/tree-walk.d.ts +18 -0
- package/dist/tree-walk.d.ts.map +1 -0
- package/dist/tree-walk.js +45 -0
- package/dist/tree-walk.js.map +1 -0
- package/genres.yaml +60 -2
- package/package.json +5 -3
- package/reference-headings.yaml +17 -0
- package/rules/adverb-overuse.yaml +19 -0
- package/rules/agentless-passive.yaml +19 -0
- package/rules/agreement-slip.yaml +49 -0
- package/rules/ai-generated-composite.yaml +102 -0
- package/rules/ai-tell.yaml +23 -0
- package/rules/announced-count-mismatch.yaml +57 -0
- package/rules/announcing-opener.yaml +51 -0
- package/rules/assistant-residue.yaml +52 -0
- package/rules/bold-density.yaml +31 -0
- package/rules/broken-link.yaml +65 -0
- package/rules/closing-cliche.yaml +33 -0
- package/rules/colon-lead-in.yaml +59 -0
- package/rules/concrete-evidence-density.yaml +41 -0
- package/rules/contraction-consistency.yaml +18 -0
- package/rules/contrast-framing.yaml +57 -0
- package/rules/cushion-phrase-density.yaml +25 -0
- package/rules/dangling-figure-reference.yaml +61 -0
- package/rules/dangling-reference.yaml +53 -1
- package/rules/date-order.yaml +33 -1
- package/rules/date-range-reversed.yaml +46 -0
- package/rules/date-weekday-mismatch.yaml +17 -1
- package/rules/double-keigo.yaml +16 -0
- package/rules/doubled-punctuation.yaml +45 -0
- package/rules/doubled-word.yaml +17 -1
- package/rules/duplicate-definition.yaml +59 -1
- package/rules/emoji-density.yaml +25 -0
- package/rules/empty-conclusion.yaml +29 -0
- package/rules/empty-intensifier.yaml +19 -0
- package/rules/excessive-hedging.yaml +19 -0
- package/rules/expletive-construction.yaml +19 -0
- package/rules/heading-echo.yaml +32 -0
- package/rules/heading-level-skip.yaml +78 -0
- package/rules/hiragana-fukushi.yaml +16 -0
- package/rules/image-alt-text.yaml +54 -0
- package/rules/internal-jargon.yaml +21 -0
- package/rules/katakana-long-vowel.yaml +98 -0
- package/rules/kutoten-consistency.yaml +53 -0
- package/rules/latin-spacing.yaml +23 -4
- package/rules/max-kanji-continuous.yaml +16 -0
- package/rules/max-paragraph-length.yaml +42 -2
- package/rules/max-sentence-length.yaml +36 -0
- package/rules/ngram-repetition.yaml +29 -2
- package/rules/no-doubled-joshi.yaml +16 -0
- package/rules/no-em-dash.yaml +25 -0
- package/rules/no-mixed-desumasu.yaml +27 -2
- package/rules/no-nakaguro-parallel.yaml +20 -0
- package/rules/numbering-gap.yaml +53 -1
- package/rules/oxford-comma-consistency.yaml +19 -1
- package/rules/padded-intro.yaml +19 -0
- package/rules/paragraph-length-variance.yaml +49 -0
- package/rules/percent-sum-mismatch.yaml +58 -0
- package/rules/preamble-length.yaml +56 -0
- package/rules/preferred-term.yaml +27 -0
- package/rules/proper-noun-density.yaml +26 -0
- package/rules/repeated-conjunction.yaml +47 -0
- package/rules/repeated-sentence-head.yaml +23 -0
- package/rules/required-sections.yaml +49 -0
- package/rules/risk-disclosure.yaml +22 -0
- package/rules/rule-of-three.yaml +97 -0
- package/rules/sasete-itadaku.yaml +18 -0
- package/rules/section-length-uniformity.yaml +89 -0
- package/rules/sentence-initial-conjunction-run.yaml +18 -0
- package/rules/sentence-rhythm.yaml +25 -0
- package/rules/stock-transition.yaml +55 -0
- package/rules/stray-space.yaml +56 -0
- package/rules/taigen-dome-in-prose.yaml +19 -0
- package/rules/title-case-consistency.yaml +42 -0
- package/rules/total-mismatch.yaml +37 -1
- package/rules/unbalanced-bracket.yaml +56 -0
- package/rules/undefined-acronym.yaml +23 -0
- package/rules/unfilled-placeholder.yaml +50 -0
- package/rules/unqualified-superlative.yaml +19 -0
- package/rules/unsourced-number.yaml +16 -0
- package/rules/url-run-on.yaml +45 -0
- package/skills/chaff/SKILL.md +70 -0
- package/src/announced-count.ts +148 -0
- package/src/bare-url.ts +35 -0
- package/src/baseline.ts +17 -1
- package/src/body-section.ts +7 -0
- package/src/calendar-number.ts +33 -10
- package/src/cli-args.ts +6 -0
- package/src/cli-text.ts +8 -4
- package/src/cli.ts +37 -37
- package/src/closing-numbers.ts +72 -0
- package/src/commands/compare.ts +80 -0
- package/src/commands/eval.ts +19 -8
- package/src/commands/feedback.ts +12 -6
- package/src/commands/test.ts +20 -17
- package/src/commands/tree.ts +41 -5
- package/src/compare/atom.ts +33 -0
- package/src/compare/clock-time.ts +86 -0
- package/src/compare/extract.ts +78 -0
- package/src/compare/fact-text.ts +68 -0
- package/src/compare/markup-atoms.ts +29 -0
- package/src/compare/match.ts +105 -0
- package/src/compare/outcome.ts +70 -0
- package/src/compare/proper-nouns.ts +65 -0
- package/src/compare/render.ts +102 -0
- package/src/compare/spans.ts +17 -0
- package/src/compare/text-atoms.ts +95 -0
- package/src/compare/text.ts +120 -0
- package/src/compare/tree-atoms.ts +80 -0
- package/src/compare/written-names.ts +26 -0
- package/src/config/load.ts +21 -0
- package/src/config/option-problems.ts +70 -0
- package/src/config/read.ts +8 -0
- package/src/config/rule-problems.ts +12 -2
- package/src/config/style.ts +42 -0
- package/src/config/warnings.ts +13 -0
- package/src/config/write.ts +18 -4
- package/src/custom/bounded-match.ts +58 -0
- package/src/custom/load.ts +15 -0
- package/src/custom/parse.ts +274 -0
- package/src/custom/problems.ts +89 -0
- package/src/custom/regex-safety.ts +118 -0
- package/src/custom/token-pattern.ts +84 -0
- package/src/detect.ts +28 -2
- package/src/detectors/acronym-context.ts +32 -4
- package/src/detectors/acronym-expansion.ts +132 -1
- package/src/detectors/agreement-slip.ts +191 -0
- package/src/detectors/ai-phrasing.ts +137 -0
- package/src/detectors/announced-count.ts +25 -0
- package/src/detectors/broken-link.ts +90 -0
- package/src/detectors/cited-name.ts +6 -5
- package/src/detectors/cited-title.ts +96 -0
- package/src/detectors/concrete-evidence.ts +3 -2
- package/src/detectors/content-morphemes.ts +19 -0
- package/src/detectors/contrast-frame.ts +54 -0
- package/src/detectors/custom.ts +89 -0
- package/src/detectors/dangling-figure.ts +22 -0
- package/src/detectors/doubled-punctuation.ts +49 -0
- package/src/detectors/doubled-word.ts +19 -4
- package/src/detectors/en-shape.ts +0 -269
- package/src/detectors/enumerated-runs.ts +13 -4
- package/src/detectors/gram-furniture.ts +30 -0
- package/src/detectors/gram-place.ts +9 -5
- package/src/detectors/gram-windows.ts +31 -0
- package/src/detectors/heading-case.ts +30 -2
- package/src/detectors/heading-code-words.ts +35 -0
- package/src/detectors/heading-echo.ts +18 -22
- package/src/detectors/heading-level-skip.ts +19 -0
- package/src/detectors/heading-overlap.ts +65 -0
- package/src/detectors/image-alt-text.ts +11 -0
- package/src/detectors/index.ts +49 -2
- package/src/detectors/kutoten-consistency.ts +96 -0
- package/src/detectors/lead-in.ts +3 -1
- package/src/detectors/letter-joined-name.ts +15 -0
- package/src/detectors/lexicon-match.ts +9 -2
- package/src/detectors/lexicon.ts +6 -2
- package/src/detectors/list-item.ts +122 -0
- package/src/detectors/list-items.ts +163 -0
- package/src/detectors/list-lead-in.ts +33 -0
- package/src/detectors/list-sentence.ts +157 -0
- package/src/detectors/list-view.ts +157 -0
- package/src/detectors/long-vowel.ts +66 -0
- package/src/detectors/markup-finding.ts +24 -0
- package/src/detectors/name-numeral.ts +4 -2
- package/src/detectors/orthography.ts +24 -18
- package/src/detectors/oxford-comma.ts +297 -0
- package/src/detectors/place-run.ts +7 -4
- package/src/detectors/placeholder-text.ts +27 -0
- package/src/detectors/quote-around.ts +9 -0
- package/src/detectors/register.ts +37 -10
- package/src/detectors/roman-numeral.ts +3 -0
- package/src/detectors/sentence-ending.ts +14 -7
- package/src/detectors/sentence-length.ts +16 -5
- package/src/detectors/signals.ts +110 -53
- package/src/detectors/stacked-hedge.ts +6 -3
- package/src/detectors/stray-space.ts +40 -0
- package/src/detectors/structure-tree.ts +45 -1
- package/src/detectors/structure.ts +13 -6
- package/src/detectors/superlative-name.ts +7 -4
- package/src/detectors/superlative-scope.ts +8 -3
- package/src/detectors/token-column.ts +149 -0
- package/src/detectors/unbalanced-bracket.ts +153 -0
- package/src/detectors/url-run-on.ts +27 -0
- package/src/document-sections.ts +46 -0
- package/src/document.ts +116 -127
- package/src/email-parts.ts +269 -0
- package/src/eval.ts +14 -4
- package/src/figure-references.ts +112 -0
- package/src/files.ts +5 -0
- package/src/genre-parse.ts +30 -5
- package/src/genre-suggest.ts +15 -2
- package/src/heading-label.ts +55 -0
- package/src/in-page-nav.ts +48 -19
- package/src/joined-view.ts +1 -0
- package/src/levels.ts +14 -1
- package/src/line-paragraphs.ts +56 -10
- package/src/long-vowel.ts +99 -0
- package/src/markdown-node.ts +19 -0
- package/src/markdown-read.ts +44 -0
- package/src/markup.ts +210 -0
- package/src/mask.ts +10 -19
- package/src/number-name.ts +152 -25
- package/src/opening-line.ts +17 -0
- package/src/orthography.ts +20 -5
- package/src/page-furniture.ts +11 -2
- package/src/paragraph-length.ts +9 -0
- package/src/plain-source.ts +2 -1
- package/src/plugin.ts +107 -1
- package/src/profile/for-file.ts +3 -1
- package/src/quoted-span.ts +10 -4
- package/src/reasons.ts +9 -0
- package/src/reference-lists.ts +91 -0
- package/src/render/explain.ts +47 -13
- package/src/render/friendly.ts +20 -9
- package/src/render/options.ts +58 -0
- package/src/render/rules-json.ts +130 -14
- package/src/render/rules-table.ts +91 -0
- package/src/render/sarif.ts +4 -4
- package/src/render/semantic.ts +3 -3
- package/src/render/severity-name.ts +10 -0
- package/src/render/text.ts +21 -7
- package/src/resolve-genre.ts +4 -1
- package/src/rule-genres.ts +25 -0
- package/src/rule-guide.ts +135 -0
- package/src/rule-load.ts +98 -33
- package/src/rule-options.ts +131 -0
- package/src/run-semantic.ts +28 -20
- package/src/run.ts +78 -11
- package/src/semantic.ts +11 -3
- package/src/sentence-shape.ts +4 -5
- package/src/setting-problems.ts +7 -1
- package/src/span-cut.ts +28 -0
- package/src/span-merge.ts +13 -0
- package/src/speaker-labels.ts +129 -0
- package/src/stray-space.ts +81 -0
- package/src/structure/aside-depth.ts +67 -0
- package/src/structure/build.ts +38 -19
- package/src/structure/closed-pairs.ts +20 -0
- package/src/structure/date-range.ts +69 -0
- package/src/structure/known-mentions.ts +96 -0
- package/src/structure/numbering.ts +9 -5
- package/src/structure/of.ts +11 -3
- package/src/structure/percent-sum.ts +135 -0
- package/src/structure/quoted-number.ts +36 -0
- package/src/structure/relative-find.ts +34 -47
- package/src/structure/relative-resolve.ts +104 -42
- package/src/structure/runs.ts +2 -2
- package/src/structure/sexp.ts +17 -5
- package/src/structure/total.ts +2 -2
- package/src/structure/universal.ts +24 -4
- package/src/structure/wrapped-tail.ts +38 -13
- package/src/style-load.ts +28 -0
- package/src/style-parse.ts +77 -0
- package/src/subheading-line.ts +68 -0
- package/src/team-names.ts +13 -13
- package/src/template-syntax.ts +164 -0
- package/src/text-above.ts +49 -0
- package/src/text-figures.ts +147 -0
- package/src/trailing-aside.ts +50 -0
- package/src/tree-walk.ts +48 -0
- package/styles/bunkacho.yaml +25 -0
- package/styles/ieice.yaml +29 -0
- package/styles/jis-z8301-2011.yaml +25 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { Detector, Finding, Lexicon, Token } from "../plugin.ts";
|
|
2
|
+
import { isPartOfLongerWord } from "./doubled-word.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 語の形が合っていない(a significant changes / one of the most important feature / Your can check)。
|
|
6
|
+
* 書き換えで片方の語だけ直した跡。解析器の読みが一通りに決まる形だけを数える。語はすべてアダプタの語彙表から来る。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type AgreementLists = {
|
|
10
|
+
/** 一つを数える限定詞(a / each)。 */
|
|
11
|
+
readonly singular: Lexicon;
|
|
12
|
+
/** 複数を数える限定詞と句(these / one of the)。 */
|
|
13
|
+
readonly plural: Lexicon;
|
|
14
|
+
/** 単数と複数が同じ綴りの名詞(series / data)。 */
|
|
15
|
+
readonly invariant: ReadonlySet<string>;
|
|
16
|
+
/** 単数の限定詞で複数を数える形容詞(a few days)。 */
|
|
17
|
+
readonly count: ReadonlySet<string>;
|
|
18
|
+
/** 名詞の前にしか立たない所有の語(your / their)。 */
|
|
19
|
+
readonly possessive: ReadonlySet<string>;
|
|
20
|
+
/** 名詞にならない be / have の形(is / has)。 */
|
|
21
|
+
readonly finite: ReadonlySet<string>;
|
|
22
|
+
/** 単数で書く所を複数で書いた句(ones of the most)。 */
|
|
23
|
+
readonly misnumbered: Lexicon;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type Slip = { readonly variant: "number" | "possessive"; readonly first: Token; readonly last: Token; readonly word: string };
|
|
27
|
+
|
|
28
|
+
const SPACE_ONLY = /^\s+$/u;
|
|
29
|
+
const UPPER_START = /^\p{Lu}/u;
|
|
30
|
+
const LETTER = /\p{L}/u;
|
|
31
|
+
const LOWER = /\p{Ll}/u;
|
|
32
|
+
/** 名詞句を閉じる記号。読点・括弧の始まり・ハイフンは、名詞を重ねた語(a sales, marketing and support team)の途中にも立つ。 */
|
|
33
|
+
const CLOSING_MARK = new Set([".", ";", ":", "?", "!", ")"]);
|
|
34
|
+
/**
|
|
35
|
+
* 名詞の後ろに来れば、名詞句はそこで終わっている品詞。名詞・形容詞・接続詞・所有の印は、名詞を重ねた語の途中。
|
|
36
|
+
* 動詞は、名詞にならない be / have の形(is / has)だけ。解析器は複数の名詞の後ろの名詞を動詞と読む(a sales team の team が VBP)。
|
|
37
|
+
*/
|
|
38
|
+
const PHRASE_END = new Set(["AUX", "ADP", "SCONJ", "PRON", "DET", "ADV"]);
|
|
39
|
+
const PREDICATE_TAIL = new Set(["DET", "ADJ", "PRON", "NUM"]);
|
|
40
|
+
|
|
41
|
+
const lower = (token: Token): string => token.surface.toLowerCase();
|
|
42
|
+
|
|
43
|
+
const isParticiple = (token: Token): boolean => token.features?.["VerbForm"] === "Part" || token.features?.["VerbForm"] === "Ger";
|
|
44
|
+
|
|
45
|
+
const isArticle = (token: Token): boolean => token.features?.["PronType"] === "Art";
|
|
46
|
+
|
|
47
|
+
const isPlural = (token: Token): boolean => token.features?.["Number"] === "Plur";
|
|
48
|
+
|
|
49
|
+
/** 名詞の後ろの語で、名詞句が終わるか。分詞(a data driven approach)も名詞を重ねた語の途中。 */
|
|
50
|
+
export const endsNounPhrase = (next: Token | undefined, finite: ReadonlySet<string>): boolean => {
|
|
51
|
+
if (next === undefined || finite.has(lower(next))) return true;
|
|
52
|
+
return next.pos === "PUNCT" ? CLOSING_MARK.has(next.surface) : PHRASE_END.has(next.pos);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const wordsOf = (entry: Lexicon[number]): readonly string[] =>
|
|
56
|
+
entry.tokens === undefined ? entry.pattern.toLowerCase().split(/\s+/u) : entry.tokens.map((token) => token.surface.toLowerCase());
|
|
57
|
+
|
|
58
|
+
/** tokens の at 語目から始まる語彙表の句の長さ。無ければ 0。 */
|
|
59
|
+
const phraseAt = (tokens: readonly Token[], at: number, phrases: Lexicon): number => {
|
|
60
|
+
const matched = phrases.map(wordsOf).find((words) => words.every((word, k) => tokens[at + k]?.surface.toLowerCase() === word));
|
|
61
|
+
return matched?.length ?? 0;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** first から last まで、語のあいだが空白だけ。コードの印やリンクを挟めば別々の語。 */
|
|
65
|
+
const joinedBySpace = (source: string, tokens: readonly Token[]): boolean =>
|
|
66
|
+
tokens.slice(1).every((token, k) => SPACE_ONLY.test(source.slice(tokens[k]?.span.end ?? token.span.start, token.span.start)));
|
|
67
|
+
|
|
68
|
+
const opensSentence = (tokens: readonly Token[], at: number): boolean => !tokens.slice(0, at).some((token) => LETTER.test(token.surface));
|
|
69
|
+
|
|
70
|
+
/** 文の途中の大文字の限定詞は、名前の一部(Plan A users)。 */
|
|
71
|
+
const isNamePart = (tokens: readonly Token[], at: number): boolean => UPPER_START.test(tokens[at]?.surface ?? "") && !opensSentence(tokens, at);
|
|
72
|
+
|
|
73
|
+
const isModifier = (token: Token): boolean => token.pos === "ADJ" || token.pos === "ADV" || (token.pos === "VERB" && isParticiple(token));
|
|
74
|
+
|
|
75
|
+
/** 限定詞の後ろの修飾語。数の形容詞(a few days)が挟まれば、単数の限定詞でも複数を数えるので undefined。 */
|
|
76
|
+
const modifiersAfter = (tokens: readonly Token[], from: number, count: ReadonlySet<string>): readonly Token[] | undefined => {
|
|
77
|
+
const end = tokens.findIndex((token, index) => index >= from && !isModifier(token));
|
|
78
|
+
const modifiers = tokens.slice(from, end === -1 ? tokens.length : end);
|
|
79
|
+
return modifiers.some((token) => count.has(lower(token))) ? undefined : modifiers;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const isGuessed = (token: Token): boolean => token.features?.["Guess"] === "Yes";
|
|
83
|
+
|
|
84
|
+
/** 単数と複数が同じ綴りの語、複数と付いても原形が同じ語(lens)、解析器が形から当てた語(stimuli)は、どちらの数とも決まらない。 */
|
|
85
|
+
const hasOneNumber = (noun: Token, invariant: ReadonlySet<string>): boolean =>
|
|
86
|
+
!invariant.has(lower(noun)) && !isGuessed(noun) && !(isPlural(noun) && noun.lemma?.toLowerCase() === lower(noun));
|
|
87
|
+
|
|
88
|
+
const isCommonNoun = (token: Token | undefined): token is Token => token?.pos === "NOUN" && !UPPER_START.test(token.surface);
|
|
89
|
+
|
|
90
|
+
type Determiner = { readonly head: Token; readonly length: number; readonly plural: boolean };
|
|
91
|
+
|
|
92
|
+
const determinerAt = (tokens: readonly Token[], at: number, lists: AgreementLists): Determiner | undefined => {
|
|
93
|
+
const head = tokens[at];
|
|
94
|
+
const plural = phraseAt(tokens, at, lists.plural);
|
|
95
|
+
const singular = phraseAt(tokens, at, lists.singular);
|
|
96
|
+
if (head === undefined || plural + singular === 0) return undefined;
|
|
97
|
+
return plural > 0 ? { head, length: plural, plural: true } : { head, length: singular, plural: false };
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 冠詞と句でない限定詞(this / these)は代名詞にもなる。This results in a loss の results は動詞なので、
|
|
102
|
+
* 形容詞を挟んだ名詞(this new rules)だけを数える。
|
|
103
|
+
*/
|
|
104
|
+
const standsAlone = (determiner: Determiner): boolean => determiner.length === 1 && !isArticle(determiner.head);
|
|
105
|
+
|
|
106
|
+
const readsAsDeterminer = (determiner: Determiner, modifiers: readonly Token[]): boolean =>
|
|
107
|
+
!standsAlone(determiner) || modifiers.some((token) => token.pos === "ADJ");
|
|
108
|
+
|
|
109
|
+
const mayBeNoun = (token: Token): boolean => token.features?.["AlsoNoun"] === "Yes" || isGuessed(token);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 名詞が動詞にも読め(works)、その前に名詞句の頭になれる語があれば、限定詞と名詞ではなく主語と動詞かもしれない。
|
|
113
|
+
* an individual works(individual は名詞にもなる)/ Those responsible report to the board(those は代名詞にもなる)。
|
|
114
|
+
* 後ろが is / has なら、名詞は動詞ではない(these key result is)。
|
|
115
|
+
*/
|
|
116
|
+
const mayBeVerb = (determiner: Determiner, modifiers: readonly Token[], noun: Token, next: Token | undefined, finite: ReadonlySet<string>): boolean =>
|
|
117
|
+
noun.features?.["AlsoVerb"] === "Yes" && !(next !== undefined && finite.has(lower(next))) && (standsAlone(determiner) || modifiers.some(mayBeNoun));
|
|
118
|
+
|
|
119
|
+
const numberSlipAt = (source: string, tokens: readonly Token[], at: number, lists: AgreementLists): Slip | undefined => {
|
|
120
|
+
const determiner = determinerAt(tokens, at, lists);
|
|
121
|
+
if (determiner === undefined || isNamePart(tokens, at)) return undefined;
|
|
122
|
+
const modifiers = modifiersAfter(tokens, at + determiner.length, lists.count);
|
|
123
|
+
if (modifiers === undefined || !readsAsDeterminer(determiner, modifiers)) return undefined;
|
|
124
|
+
const nounAt = at + determiner.length + modifiers.length;
|
|
125
|
+
const noun = tokens[nounAt];
|
|
126
|
+
if (!isCommonNoun(noun) || !hasOneNumber(noun, lists.invariant) || isPlural(noun) === determiner.plural) return undefined;
|
|
127
|
+
if (mayBeVerb(determiner, modifiers, noun, tokens[nounAt + 1], lists.finite)) return undefined;
|
|
128
|
+
const span = tokens.slice(at, nounAt + 1);
|
|
129
|
+
if (!endsNounPhrase(tokens[nounAt + 1], lists.finite) || !joinedBySpace(source, span) || isPartOfLongerWord(source, determiner.head, noun)) return undefined;
|
|
130
|
+
return slipOf("number", source, determiner.head, noun);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const slipOf = (variant: Slip["variant"], source: string, first: Token, last: Token): Slip => ({
|
|
134
|
+
variant,
|
|
135
|
+
first,
|
|
136
|
+
last,
|
|
137
|
+
word: source.slice(first.span.start, last.span.end).replace(/\s+/gu, " "),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const isBaseVerb = (token: Token | undefined): boolean => token?.pos === "VERB" && token.features?.["VerbForm"] === undefined;
|
|
141
|
+
|
|
142
|
+
/** 所有の語の直後の be(their is)か、助動詞 + 動詞の原形(Your can check)。名詞にもなる助動詞(your will)は動詞が続くときだけ。 */
|
|
143
|
+
const possessiveSlipAt = (source: string, tokens: readonly Token[], at: number, lists: AgreementLists): Slip | undefined => {
|
|
144
|
+
const [possessive, verb] = [tokens[at], tokens[at + 1]];
|
|
145
|
+
if (possessive === undefined || verb === undefined || !lists.possessive.has(lower(possessive))) return undefined;
|
|
146
|
+
// 大文字だけの語は略語(Your AM = account manager)。
|
|
147
|
+
const verbal = LOWER.test(verb.surface) && (lists.finite.has(lower(verb)) || (verb.pos === "AUX" && isBaseVerb(tokens[at + 2])));
|
|
148
|
+
if (!verbal || !joinedBySpace(source, [possessive, verb]) || isPartOfLongerWord(source, possessive, verb)) return undefined;
|
|
149
|
+
return slipOf("possessive", source, possessive, verb);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/** ones of the most。前に限定詞・形容詞・代名詞があれば、ones は代名詞(the ones of the most use)。 */
|
|
153
|
+
const misnumberedAt = (source: string, tokens: readonly Token[], at: number, lists: AgreementLists): Slip | undefined => {
|
|
154
|
+
const span = tokens.slice(at, at + phraseAt(tokens, at, lists.misnumbered));
|
|
155
|
+
const [first, last, previous] = [span[0], span.at(-1), tokens[at - 1]];
|
|
156
|
+
if (first === undefined || last === undefined || (previous !== undefined && PREDICATE_TAIL.has(previous.pos))) return undefined;
|
|
157
|
+
return joinedBySpace(source, span) ? slipOf("number", source, first, last) : undefined;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export const agreementIn = (source: string, tokens: readonly Token[], lists: AgreementLists): Slip[] =>
|
|
161
|
+
tokens.flatMap((_, at) => {
|
|
162
|
+
const slip = numberSlipAt(source, tokens, at, lists) ?? possessiveSlipAt(source, tokens, at, lists) ?? misnumberedAt(source, tokens, at, lists);
|
|
163
|
+
return slip === undefined ? [] : [slip];
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const setOf = (lexicon: Lexicon | undefined): ReadonlySet<string> => new Set((lexicon ?? []).map((entry) => entry.pattern.toLowerCase()));
|
|
167
|
+
|
|
168
|
+
const listsOf = (lexicons: Readonly<Record<string, Lexicon>>): AgreementLists => ({
|
|
169
|
+
singular: lexicons["singular-determiner"] ?? [],
|
|
170
|
+
plural: lexicons["plural-determiner"] ?? [],
|
|
171
|
+
invariant: setOf(lexicons["invariant-noun"]),
|
|
172
|
+
count: setOf(lexicons["count-adjective"]),
|
|
173
|
+
possessive: setOf(lexicons["dependent-possessive"]),
|
|
174
|
+
finite: setOf(lexicons["finite-auxiliary"]),
|
|
175
|
+
misnumbered: lexicons["misnumbered-phrase"] ?? [],
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export const agreementSlip: Detector = (doc): Finding[] => {
|
|
179
|
+
const lists = listsOf(doc.lexicons);
|
|
180
|
+
return doc.sentences.flatMap((sentence) =>
|
|
181
|
+
agreementIn(doc.source, sentence.tokens ?? [], lists).map((slip): Finding => ({
|
|
182
|
+
rule: "agreement-slip",
|
|
183
|
+
severity: "warning",
|
|
184
|
+
line: 0,
|
|
185
|
+
column: 0,
|
|
186
|
+
quote: sentence.text.trim(),
|
|
187
|
+
values: { word: slip.word, offset: slip.first.span.start },
|
|
188
|
+
variant: slip.variant,
|
|
189
|
+
})),
|
|
190
|
+
);
|
|
191
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { Detector, Finding, Lexicon, LexiconEntry, ProseDocument, Sentence } from "../plugin.ts";
|
|
2
|
+
import { wordsOf } from "./structure.ts";
|
|
3
|
+
import { MIN_DOCUMENT_LENGTH } from "./signals.ts";
|
|
4
|
+
import { entryIn, entryOpens } from "./lexicon-match.ts";
|
|
5
|
+
import { contrastSentences, type ContrastWords } from "./contrast-frame.ts";
|
|
6
|
+
import { placeholderSpans } from "./placeholder-text.ts";
|
|
7
|
+
import { colonLeadIns } from "./list-lead-in.ts";
|
|
8
|
+
|
|
9
|
+
// 生成文に多い形。語はどれも言語パッケージの語彙表が持ち、ここは形だけを知る。
|
|
10
|
+
|
|
11
|
+
const PER = 1000;
|
|
12
|
+
/** 密度は小数 1 桁まで。日本語の 1000 字あたりは 1 と 2 の間で人と生成文が分かれる。 */
|
|
13
|
+
const TENTHS = 10;
|
|
14
|
+
/** 重みの合計を 10 倍した点で比べる(ai-tell と同じ)。重み 0.5 の言い回し 2 つで 10。 */
|
|
15
|
+
const SCORE_SCALE = 10;
|
|
16
|
+
/** 1 つは重なりではない。短い文書では 1 つでも密度が上限を超えるので、数でも止める。 */
|
|
17
|
+
const PILE = 2;
|
|
18
|
+
|
|
19
|
+
/** 当たった文と語。offset は指摘する位置で、無ければ文の頭。 */
|
|
20
|
+
type Hit = { readonly sentence: Sentence; readonly matched: string; readonly offset?: number };
|
|
21
|
+
|
|
22
|
+
const findingOf = (hit: Hit, values: Readonly<Record<string, number>>): Finding => ({
|
|
23
|
+
rule: "",
|
|
24
|
+
severity: "info",
|
|
25
|
+
line: 0,
|
|
26
|
+
column: 0,
|
|
27
|
+
quote: hit.sentence.text.trim(),
|
|
28
|
+
values: { matched: hit.matched, ...values, offset: hit.offset ?? hit.sentence.span.start },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/** 1000 語(日本語は 1000 字)あたりの数が上限を超えたら、当たった文をすべて言う。短い文書は密度が暴れるので測らない。 */
|
|
32
|
+
const densityFindings = (doc: ProseDocument, hits: readonly Hit[], limit: number): Finding[] => {
|
|
33
|
+
const length = wordsOf(doc);
|
|
34
|
+
if (hits.length < PILE || length < MIN_DOCUMENT_LENGTH[doc.lengthUnit]) return [];
|
|
35
|
+
const density = Math.round((hits.length / length) * PER * TENTHS) / TENTHS;
|
|
36
|
+
return density <= limit ? [] : hits.map((hit) => findingOf(hit, { count: hits.length, density, limit }));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const firstIn = (sentence: Sentence, lexicon: Lexicon): LexiconEntry | undefined => lexicon.find((entry) => entryIn(sentence, entry));
|
|
40
|
+
|
|
41
|
+
const contrastWordsOf = (doc: ProseDocument, frames: Lexicon): ContrastWords => ({
|
|
42
|
+
frames,
|
|
43
|
+
leads: doc.lexicons["contrast-lead"] ?? [],
|
|
44
|
+
turns: doc.lexicons["contrast-turn"] ?? [],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/** 対比の枠(It's not X, it's Y、単なる X ではなく)。1 つなら論点の整理だが、重なると言い回しの癖になる。 */
|
|
48
|
+
export const contrastFraming: Detector = (doc, options): Finding[] => {
|
|
49
|
+
const words = contrastWordsOf(doc, options.lexicon ?? []);
|
|
50
|
+
const hits = contrastSentences(doc.sentences, words).map((sentence) => ({
|
|
51
|
+
sentence,
|
|
52
|
+
matched: (firstIn(sentence, words.frames) ?? firstIn(sentence, words.leads))?.pattern ?? "",
|
|
53
|
+
}));
|
|
54
|
+
return densityFindings(doc, hits, options.limit);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** 語彙表の語で始まる文。 */
|
|
58
|
+
const openerHits = (doc: ProseDocument, lexicon: Lexicon): Hit[] =>
|
|
59
|
+
doc.sentences.flatMap((sentence) => {
|
|
60
|
+
const opener = lexicon.find((entry) => entryOpens(sentence, entry));
|
|
61
|
+
return opener === undefined ? [] : [{ sentence, matched: opener.pattern }];
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/** 文頭の決まった接ぎ(Moreover、さらに)の密度。話を運ぶ語(However、また)は語彙表に入れない。 */
|
|
65
|
+
export const openerDensity: Detector = (doc, options): Finding[] => densityFindings(doc, openerHits(doc, options.lexicon ?? []), options.limit);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 予告の文頭(重要なのは、Here's the thing)の数。limit は指摘に要る数。
|
|
69
|
+
* 密度ではなく数で見る。人の記事も長さによらず 1 つ 2 つは書き、生成文は短い記事にも重ねる。
|
|
70
|
+
*/
|
|
71
|
+
export const openerPile: Detector = (doc, options): Finding[] => {
|
|
72
|
+
const hits = openerHits(doc, options.lexicon ?? []);
|
|
73
|
+
return hits.length === 0 || hits.length < options.limit ? [] : hits.map((hit) => findingOf(hit, { count: hits.length, limit: options.limit }));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** コロンで箇条書きへ渡す文(以下の通りです:)。1 つなら案内だが、節ごとに続くと説明が箇条書きの前置きだけになる。 */
|
|
77
|
+
export const colonLeadIn: Detector = (doc, options): Finding[] => {
|
|
78
|
+
const hits = colonLeadIns(doc.sentences, doc.lists, doc.listSpans, doc.source).map((sentence) => ({ sentence, matched: sentence.text.trim() }));
|
|
79
|
+
return densityFindings(doc, hits, options.limit);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const distinct = (lexicon: Lexicon): LexiconEntry[] => [...new Map(lexicon.map((entry) => [entry.pattern.toLowerCase(), entry])).values()];
|
|
83
|
+
|
|
84
|
+
const weightOf = (entry: LexiconEntry): number => entry.weight ?? 1;
|
|
85
|
+
|
|
86
|
+
const keyOf = (entry: LexiconEntry): string => entry.pattern.toLowerCase();
|
|
87
|
+
|
|
88
|
+
type Tally = { readonly score: number; readonly counted: ReadonlySet<string>; readonly hits: readonly Hit[] };
|
|
89
|
+
|
|
90
|
+
const NOTHING: Tally = { score: 0, counted: new Set(), hits: [] };
|
|
91
|
+
|
|
92
|
+
/** 1 つの文を足す。重みは、まだ数えていない語のうち最も重いもの。文の語はすべて数えたことにする。 */
|
|
93
|
+
const withSentence = (tally: Tally, sentence: Sentence, inSentence: readonly LexiconEntry[]): Tally => {
|
|
94
|
+
const fresh = inSentence.filter((entry) => !tally.counted.has(keyOf(entry)));
|
|
95
|
+
const added = fresh.length === 0 ? 0 : Math.max(...fresh.map(weightOf));
|
|
96
|
+
const matched = (fresh[0] ?? inSentence[0])?.pattern ?? "";
|
|
97
|
+
return {
|
|
98
|
+
score: tally.score + added,
|
|
99
|
+
counted: new Set([...tally.counted, ...inSentence.map(keyOf)]),
|
|
100
|
+
hits: [...tally.hits, { sentence, matched }],
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 1 つの文は 1 つの言い回しとして数える(Let me know if you'd like a more detailed breakdown は礼 1 つ)。
|
|
106
|
+
* 前の文で数えた語は、別の文にあっても数えない(I hope this helps を 2 回書いても礼 1 つ)。
|
|
107
|
+
*/
|
|
108
|
+
const tallyOf = (sentences: readonly Sentence[], entries: readonly LexiconEntry[]): Tally =>
|
|
109
|
+
sentences.reduce<Tally>((tally, sentence) => {
|
|
110
|
+
const inSentence = entries.filter((entry) => entryIn(sentence, entry));
|
|
111
|
+
return inSentence.length === 0 ? tally : withSentence(tally, sentence, inSentence);
|
|
112
|
+
}, NOTHING);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 会話の返事の名残(As of my last knowledge update、私の知識は)。重みを足した点が上限に届いたら、当たった文をすべて言う。
|
|
116
|
+
* 名残そのもの(知識の期限、AI としての断り)は 1 つで届き、人も書く礼(I hope this helps)は 2 つ重なって届く。
|
|
117
|
+
*/
|
|
118
|
+
export const assistantResidue: Detector = (doc, options): Finding[] => {
|
|
119
|
+
const tally = tallyOf(doc.sentences, distinct(options.lexicon ?? []));
|
|
120
|
+
const score = Math.round(tally.score * SCORE_SCALE);
|
|
121
|
+
if (tally.hits.length === 0 || score < options.limit) return [];
|
|
122
|
+
return tally.hits.map((hit) => findingOf(hit, { count: tally.counted.size, density: score, limit: options.limit }));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** 埋め忘れた雛形の空欄([Your Name]、【会社名】)。limit は指摘に要る数。 */
|
|
126
|
+
export const unfilledPlaceholder: Detector = (doc, options): Finding[] => {
|
|
127
|
+
const words = options.lexicon ?? [];
|
|
128
|
+
const blanks = doc.sentences.flatMap((sentence) =>
|
|
129
|
+
placeholderSpans(sentence.text, words).map((span) => ({
|
|
130
|
+
sentence,
|
|
131
|
+
matched: sentence.text.slice(span.start, span.end),
|
|
132
|
+
offset: sentence.span.start + span.start,
|
|
133
|
+
})),
|
|
134
|
+
);
|
|
135
|
+
if (blanks.length === 0 || blanks.length < options.limit) return [];
|
|
136
|
+
return blanks.map((blank) => findingOf(blank, { count: blanks.length, limit: options.limit }));
|
|
137
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
2
|
+
import { announcedCountMismatches, type CountWords } from "../announced-count.ts";
|
|
3
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
4
|
+
|
|
5
|
+
const patternsOf = (doc: ProseDocument, id: string, position?: "before" | "after"): string[] =>
|
|
6
|
+
(doc.lexicons[id] ?? []).filter((entry) => position === undefined || entry.position === position).map((entry) => entry.pattern);
|
|
7
|
+
|
|
8
|
+
const countWordsOf = (doc: ProseDocument): CountWords => ({
|
|
9
|
+
anchors: patternsOf(doc, "count-anchor"),
|
|
10
|
+
numbers: patternsOf(doc, "count-number"),
|
|
11
|
+
counters: patternsOf(doc, "count-counter"),
|
|
12
|
+
hedgesBefore: patternsOf(doc, "count-hedge", "before"),
|
|
13
|
+
hedgesAfter: patternsOf(doc, "count-hedge", "after"),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/** 予告の数(以下の3点)と、すぐ下の箇条書きの項目の数が違う。 */
|
|
17
|
+
export const announcedCount: Detector = (doc): Finding[] =>
|
|
18
|
+
announcedCountMismatches(doc.source, doc.lists, countWordsOf(doc)).map((mismatch) => ({
|
|
19
|
+
rule: "announced-count-mismatch",
|
|
20
|
+
severity: "warning",
|
|
21
|
+
line: 0,
|
|
22
|
+
column: 0,
|
|
23
|
+
quote: quoteAt(doc.source, mismatch.offset),
|
|
24
|
+
values: { phrase: mismatch.phrase, announced: mismatch.announced, listed: mismatch.listed, offset: mismatch.offset },
|
|
25
|
+
}));
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Detector, Finding, Markup, ProseDocument, Span } from "../plugin.ts";
|
|
2
|
+
import { findingAt, markupOf, quoteOf } from "./markup-finding.ts";
|
|
3
|
+
|
|
4
|
+
/** ページの先頭を指す書き方。見出しが無くても行き先がある。 */
|
|
5
|
+
const PAGE_TOP = new Set(["", "top"]);
|
|
6
|
+
|
|
7
|
+
/** 名前を比べる形。字と数字だけを小文字で残す。見出しから名前を作る決まりは表示するものごとに違う(空白を - にする・記号を消す)ので、その違いを畳む。 */
|
|
8
|
+
export const anchorKey = (name: string): string => name.toLowerCase().replace(/[^\p{L}\p{N}]/gu, "");
|
|
9
|
+
|
|
10
|
+
/** 同じ見出しが二つあると、表示するものは二つ目以降に -1、-2 を付ける。 */
|
|
11
|
+
const DUPLICATE_SUFFIX = /-(\d+)$/u;
|
|
12
|
+
|
|
13
|
+
const decoded = (fragment: string): string => {
|
|
14
|
+
try {
|
|
15
|
+
return decodeURIComponent(fragment);
|
|
16
|
+
} catch {
|
|
17
|
+
return fragment;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** 「&」を and と読んで名前を作るもの(M&IE → m-and-ie)もある。 */
|
|
22
|
+
const namesOf = (text: string): string[] => [...new Set([text, text.replaceAll("&", " and ")])];
|
|
23
|
+
|
|
24
|
+
const keysOf = (name: string): string[] => [...new Set(namesOf(name).map(anchorKey))];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 文書の中の名前を持つところ。headings は見出しから作る名前の形ごとの数(-1、-2 は見出しだけに付く)。
|
|
28
|
+
* ids は書き手が付けた名前そのもの。見出しと違って作り方の違いが無いので、書いたとおりに比べる。
|
|
29
|
+
*/
|
|
30
|
+
export type Anchors = { readonly ids: ReadonlySet<string>; readonly headings: ReadonlyMap<string, number> };
|
|
31
|
+
|
|
32
|
+
export const anchorsOf = (markup: Markup): Anchors => ({
|
|
33
|
+
ids: markup.ids,
|
|
34
|
+
headings: markup.headings
|
|
35
|
+
.flatMap((heading) => keysOf(heading.text))
|
|
36
|
+
.reduce((counts, key) => counts.set(key, (counts.get(key) ?? 0) + 1), new Map<string, number>()),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** `#setup-2` は、同じ形の見出しが 3 つ以上あるときだけ行き先がある(二つ目が -1)。 */
|
|
40
|
+
const reachesDuplicate = (fragment: string, headings: ReadonlyMap<string, number>): boolean => {
|
|
41
|
+
const suffix = DUPLICATE_SUFFIX.exec(fragment);
|
|
42
|
+
if (suffix === null) return false;
|
|
43
|
+
return (headings.get(anchorKey(fragment.slice(0, suffix.index))) ?? 0) > Number(suffix[1]);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** `#…` の行き先が、文書の中の見出しか id を指しているか。 */
|
|
47
|
+
export const reachesAnchor = (destination: string, anchors: Anchors): boolean => {
|
|
48
|
+
const fragment = decoded(destination.slice(1));
|
|
49
|
+
if (PAGE_TOP.has(fragment.toLowerCase())) return true;
|
|
50
|
+
return anchors.ids.has(fragment) || anchors.headings.has(anchorKey(fragment)) || reachesDuplicate(fragment, anchors.headings);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 参照の形で書いたのに名前の定義(`[label]: url`)が無いもの(`[text][label]`、`[text][]`)。字のまま表示される。
|
|
55
|
+
* 定義があれば CommonMark はリンクにするので、字のまま残った参照の形は定義が無い。英数字のすぐ後ろの括弧(A[i][j])は配列の添字。
|
|
56
|
+
*/
|
|
57
|
+
const REFERENCE_LIKE = /(?<![\\A-Za-z0-9_\]])\[([^[\]\n]+)\]\[([^[\]\n]*)\]/gu;
|
|
58
|
+
|
|
59
|
+
/** 数だけの括弧([1][2]、[3, 4])は、参照の記法ではなく文献の番号を並べたもの。 */
|
|
60
|
+
const CITATION_NUMBERS = /^[\d\s,,、–-]+$/u;
|
|
61
|
+
|
|
62
|
+
/** 画像の参照(`![alt][label]`)の頭の印。指摘の範囲に含める。 */
|
|
63
|
+
const IMAGE_MARK = "!";
|
|
64
|
+
|
|
65
|
+
export const unresolvedReferences = (source: string, markup: Markup): Span[] =>
|
|
66
|
+
markup.texts.flatMap((text) =>
|
|
67
|
+
[...source.slice(text.start, text.end).matchAll(REFERENCE_LIKE)]
|
|
68
|
+
.filter((match) => !CITATION_NUMBERS.test(match[1] ?? ""))
|
|
69
|
+
.map((match) => ({ start: text.start + match.index, end: text.start + match.index + match[0].length }))
|
|
70
|
+
.map((span) => (source.charAt(span.start - 1) === IMAGE_MARK ? { start: span.start - 1, end: span.end } : span)),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const emptyLinks = (doc: ProseDocument, markup: Markup): Finding[] =>
|
|
74
|
+
markup.links.filter((link) => link.destination.trim() === "").map((link) => findingAt(doc, link, { link: quoteOf(doc.source, link) }, "empty"));
|
|
75
|
+
|
|
76
|
+
const missingAnchors = (doc: ProseDocument, markup: Markup): Finding[] => {
|
|
77
|
+
const anchors = anchorsOf(markup);
|
|
78
|
+
return markup.links
|
|
79
|
+
.filter((link) => link.destination.startsWith("#") && !reachesAnchor(link.destination, anchors))
|
|
80
|
+
.map((link) => findingAt(doc, link, { link: quoteOf(doc.source, link), target: link.destination }, "anchor"));
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const brokenLink: Detector = (doc): Finding[] => {
|
|
84
|
+
const markup = markupOf(doc);
|
|
85
|
+
if (markup === undefined) return [];
|
|
86
|
+
const references = unresolvedReferences(doc.source, markup).map((span) => findingAt(doc, span, { link: quoteOf(doc.source, span) }, "reference"));
|
|
87
|
+
return [...emptyLinks(doc, markup), ...missingAnchors(doc, markup), ...references].toSorted(
|
|
88
|
+
(left, right) => Number(left.values["offset"]) - Number(right.values["offset"]),
|
|
89
|
+
);
|
|
90
|
+
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { StructureNode, Token } from "../plugin.ts";
|
|
2
|
+
import { preOrder } from "../tree-walk.ts";
|
|
2
3
|
|
|
3
4
|
/** 他の文書を指す参照(民法第709条の第709条)の始まりの位置から、その文書の名前(民法)へ。 */
|
|
4
5
|
export type CitedNames = ReadonlyMap<number, string>;
|
|
5
6
|
|
|
6
|
-
const namedReferences = (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
7
|
+
const namedReferences = (root: StructureNode): (readonly [number, string])[] =>
|
|
8
|
+
preOrder(root).flatMap((node) => {
|
|
9
|
+
const document = node.attrs["document"];
|
|
10
|
+
return node.kind === "reference" && typeof document === "string" ? [[node.span.start, document] as const] : [];
|
|
11
|
+
});
|
|
11
12
|
|
|
12
13
|
export const citedNamesOf = (structure: StructureNode | undefined): CitedNames => new Map(structure === undefined ? [] : namedReferences(structure));
|
|
13
14
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Token } from "../plugin.ts";
|
|
2
|
+
import { MINOR_WORDS } from "./heading-case.ts";
|
|
3
|
+
import { columnOf, firstIn, lastIn, type Column } from "./token-column.ts";
|
|
4
|
+
|
|
5
|
+
// 引用した題名(誌名・論文名・書名)。題名の中の読点は題名を付けた人のもので、書き手が並べかたを選んだものではない。
|
|
6
|
+
|
|
7
|
+
const isCapitalised = (token: Token): boolean => /^\p{Lu}/u.test(token.surface);
|
|
8
|
+
|
|
9
|
+
/** 題名の中でつなぐ記号。ハイフン(Low-Inflation)と、副題の前のコロン(Maximum Employment: A Shortfalls Approach)。 */
|
|
10
|
+
const TITLE_JOINERS: ReadonlySet<string> = new Set(["-", ":"]);
|
|
11
|
+
|
|
12
|
+
/** 題名の中の語。大文字で始まる語と、Title Case でも小文字のままの語(of, and, a)と、つなぐ記号。 */
|
|
13
|
+
const isTitleWord = (token: Token): boolean => isCapitalised(token) || MINOR_WORDS.has(token.surface) || TITLE_JOINERS.has(token.surface);
|
|
14
|
+
|
|
15
|
+
/** 題名の中の区切り。左は読点もまたぐ(Journal of Money, Credit)。 */
|
|
16
|
+
const inLeftRun = (token: Token): boolean => isTitleWord(token) || token.surface === ",";
|
|
17
|
+
|
|
18
|
+
/** 2 つの語の間が空白だけか。覆った強調の印(*Journal)や記号を挟めば、題名の語の続きはそこで切れる。 */
|
|
19
|
+
const adjoins = (source: string, left: Token | undefined, right: Token | undefined): boolean =>
|
|
20
|
+
left === undefined || right === undefined || source.slice(left.span.end, right.span.start).trim() === "";
|
|
21
|
+
|
|
22
|
+
const LIST_CONJUNCTIONS: ReadonlySet<string> = new Set(["and", "or"]);
|
|
23
|
+
|
|
24
|
+
const isPhraseWord = (token: Token): boolean => (isCapitalised(token) || MINOR_WORDS.has(token.surface)) && !LIST_CONJUNCTIONS.has(token.surface);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 題名の語の続きの切れ目。左の続きは、題名の語でも読点でもない語か、次の語との間に空白以外を挟む語で切れる。
|
|
28
|
+
* 右の続きは、題名の語でない語か、前の語との間に空白以外を挟む語で切れる。
|
|
29
|
+
*/
|
|
30
|
+
type Runs = { readonly leftBreak: Column; readonly rightBreak: Column; readonly capital: Column; readonly phrasePair: Column };
|
|
31
|
+
|
|
32
|
+
const runsOf = (tokens: readonly Token[], source: string): Runs => ({
|
|
33
|
+
leftBreak: columnOf(tokens, (token, index) => !inLeftRun(token) || !adjoins(source, token, tokens[index + 1])),
|
|
34
|
+
rightBreak: columnOf(tokens, (token, index) => !isTitleWord(token) || !adjoins(source, tokens[index - 1], token)),
|
|
35
|
+
capital: columnOf(tokens, isCapitalised),
|
|
36
|
+
phrasePair: columnOf(tokens, (token, index) => index > 0 && isPhraseWord(token) && isPhraseWord(tokens[index - 1] ?? token)),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* and / or の左の、題名の語の続きの頭。最初の大文字の語から。小文字の語から始めると、引用符の中の並び(‘the UK, France and
|
|
41
|
+
* Spain’)や、論文名のあとの編者の並び(," in Heather Boushey, Ryan Nunn, and Jay Shambaugh, eds.)まで題名と読む。
|
|
42
|
+
*/
|
|
43
|
+
const leftStart = (runs: Runs, at: number): number | undefined => {
|
|
44
|
+
const stop = lastIn(runs.leftBreak, { start: 0, end: at });
|
|
45
|
+
const start = firstIn(runs.capital, { start: stop + 1, end: at });
|
|
46
|
+
return start === -1 ? undefined : start;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** and / or の右の、題名の語の続きの最後の大文字の語。 */
|
|
50
|
+
const rightEnd = (runs: Runs, at: number, length: number): number | undefined => {
|
|
51
|
+
const stop = firstIn(runs.rightBreak, { start: at + 1, end: length });
|
|
52
|
+
const last = lastIn(runs.capital, { start: at + 1, end: stop === -1 ? length : stop });
|
|
53
|
+
return last === -1 ? undefined : last;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** 印を探す幅。いちばん長い印(***)と、読点・引用符・空白が収まる。 */
|
|
57
|
+
const MARK_REACH = 8;
|
|
58
|
+
|
|
59
|
+
/** 題名の最初の語にくっついた開きの印(“ ‘ " ' * _)。 */
|
|
60
|
+
const OPENING = /(?:["'“‘]|\*{1,3}|_{1,3})$/u;
|
|
61
|
+
/** 題名の直後の閉じの印。句読点を挟んでよい(Employment,”)。印の後ろが語なら、語の中の字(TO_CHAR、Madrid’s)。 */
|
|
62
|
+
const CLOSING = /^[,.;:!?]?(?:["'”’]|\*{1,3}|_{1,3})(?![\p{L}\p{N}])/u;
|
|
63
|
+
/** 引用した論文名のあとの読点と閉じる引用符。そのあとの題名は誌名("Three Lessons," Journal of Money, Credit and Banking)。 */
|
|
64
|
+
const AFTER_QUOTED_TITLE = /,\s*["'”’]\s*$/u;
|
|
65
|
+
/** 誌名のあとは、巻号や頁へ続く読点か文の終わり。述語が続けば(“Done,” Smith, Jones and Brown argued)主語の並び。 */
|
|
66
|
+
const VENUE_END = /^\s*(?:[,;.]|$)/u;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 語の続きに、2 語以上の句があるか(Journal of Money、Their Nature、The Update)。1 語ずつの名前の並び
|
|
70
|
+
* (‘Paris, Rome and Madrid’)は、引用符の中でも書き手が並べたもの。
|
|
71
|
+
*/
|
|
72
|
+
const holdsPhrase = (runs: Runs, start: number, end: number): boolean => firstIn(runs.phrasePair, { start: start + 1, end: end + 1 }) !== -1;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 文の and / or が、引用した題名の中にあるか。and / or の両隣が Title Case の語の続きで、2 語以上の句を含み、その続きが
|
|
76
|
+
* 引用符か強調の印で囲まれているか、引用符で閉じた論文名のすぐ後ろにあって読点か文の終わりが続く(誌名)とき。
|
|
77
|
+
* 本文の固有名詞の並び(Login.gov, TTS Engineering and USAi)や著者の並びは囲まれていないので、題名と読まない。
|
|
78
|
+
* 文を一度だけ読み、どの位置の問いにも続きを読み直さずに答える。
|
|
79
|
+
*/
|
|
80
|
+
export const citedTitles = (tokens: readonly Token[], source: string): ((at: number) => boolean) => {
|
|
81
|
+
const runs = runsOf(tokens, source);
|
|
82
|
+
return (at) => {
|
|
83
|
+
const start = leftStart(runs, at);
|
|
84
|
+
const end = rightEnd(runs, at, tokens.length);
|
|
85
|
+
const first = start === undefined ? undefined : tokens[start];
|
|
86
|
+
const last = end === undefined ? undefined : tokens[end];
|
|
87
|
+
if (start === undefined || end === undefined || first === undefined || last === undefined) return false;
|
|
88
|
+
if (!holdsPhrase(runs, start, end)) return false;
|
|
89
|
+
const before = source.slice(Math.max(0, first.span.start - MARK_REACH), first.span.start);
|
|
90
|
+
const after = source.slice(last.span.end, last.span.end + MARK_REACH);
|
|
91
|
+
return (OPENING.test(before) && CLOSING.test(after)) || (AFTER_QUOTED_TITLE.test(before) && VENUE_END.test(after));
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/** at の and / or が、引用した題名の中にあるか。 */
|
|
96
|
+
export const inCitedTitle = (tokens: readonly Token[], at: number, source: string): boolean => citedTitles(tokens, source)(at);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Span, StructureKind, StructureNode, Token } from "../plugin.ts";
|
|
2
|
+
import { preOrder } from "../tree-walk.ts";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 形態素解析が数と読んだ語(UD の NumType=Card)。漢数字の「二割」「十五分」も、算用数字と同じ具体的な数。
|
|
@@ -27,5 +28,5 @@ export const startsWithin = (section: Span, spans: readonly Span[]): boolean =>
|
|
|
27
28
|
/** 構造の木が読んだ参照(第3条・Section VI)・数量・日付。どれも読み手が確かめに行ける具体物。 */
|
|
28
29
|
const EVIDENCE: ReadonlySet<StructureKind> = new Set(["reference", "quantity", "date"]);
|
|
29
30
|
|
|
30
|
-
export const evidenceSpans = (
|
|
31
|
-
|
|
31
|
+
export const evidenceSpans = (root: StructureNode | undefined): Span[] =>
|
|
32
|
+
root === undefined ? [] : preOrder(root).flatMap((node) => (EVIDENCE.has(node.kind) ? [node.span] : []));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// What a sentence adds to a heading, counted in content morphemes: words that stand by themselves and name something.
|
|
2
|
+
// Pure; heading-echo measures a language written without spaces with it, where a character count says nothing
|
|
3
|
+
// (「会社に勤めています」 carries two new words, 「について説明します」 one, in the same nine characters).
|
|
4
|
+
import type { Token } from "../plugin.ts";
|
|
5
|
+
|
|
6
|
+
/** 代名詞・連体詞・接続詞は、すでに書いたものを指すかつなぐだけで、中身を足さない。 */
|
|
7
|
+
const CONTENT_POS = new Set(["NOUN", "PROPN", "NUM", "VERB", "ADJ", "ADV"]);
|
|
8
|
+
|
|
9
|
+
/** 接頭詞・接尾・非自立の語(Bound)と、動詞にするだけの「する」(VerbType=Light)は、付いた語が中身を持つ。 */
|
|
10
|
+
const isContent = (token: Token): boolean => CONTENT_POS.has(token.pos) && token.features?.["Bound"] !== "Yes" && token.features?.["VerbType"] !== "Light";
|
|
11
|
+
|
|
12
|
+
/** 原形で照らす(変えました → 変える)。原形の無い語は書いた形で。 */
|
|
13
|
+
const baseForm = (token: Token): string => (token.lemma ?? token.surface).toLowerCase();
|
|
14
|
+
|
|
15
|
+
/** The sentence's content morphemes whose base form is not one of the heading's content morphemes, every occurrence counted. */
|
|
16
|
+
export const newContentMorphemes = (heading: readonly Token[], sentence: readonly Token[]): number => {
|
|
17
|
+
const said = new Set(heading.filter(isContent).map(baseForm));
|
|
18
|
+
return sentence.filter((token) => isContent(token) && !said.has(baseForm(token))).length;
|
|
19
|
+
};
|