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,66 @@
|
|
|
1
|
+
import type { Detector, Finding, OptionValue, ProseDocument, Sentence } from "../plugin.ts";
|
|
2
|
+
import { isKatakanaWord, oddLongVowels, stemOf, type Ending, type KanaWord } from "../long-vowel.ts";
|
|
3
|
+
import { nameSpans, touchesAny } from "../team-names.ts";
|
|
4
|
+
|
|
5
|
+
const ENDINGS: readonly Ending[] = ["consistent", "drop", "keep"];
|
|
6
|
+
|
|
7
|
+
const endingOf = (value: OptionValue | undefined): Ending => ENDINGS.find((ending) => ending === value) ?? "consistent";
|
|
8
|
+
|
|
9
|
+
const wordsOf = (value: OptionValue | undefined): readonly string[] =>
|
|
10
|
+
Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === "string") : [];
|
|
11
|
+
|
|
12
|
+
/** The minimum when no setting gives one: three morae, as the guidelines that drop the ー count it. */
|
|
13
|
+
const DEFAULT_MIN_MORAE = 3;
|
|
14
|
+
|
|
15
|
+
/** A listed word is exempt written either way: listing コンピューター exempts コンピュータ too. */
|
|
16
|
+
const exemptStems = (except: readonly string[]): ReadonlySet<string> => new Set(except.map((word) => stemOf(word.trim())));
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The katakana nouns of a sentence, as the language adapter split them: ユーザー inside ユーザーインターフェース is its own word.
|
|
20
|
+
* Proper nouns (PROPN) and the team's names keep their own spelling (ディズニー).
|
|
21
|
+
*/
|
|
22
|
+
const kanaWordsOf = (sentence: Sentence, names: readonly string[], exempt: ReadonlySet<string>): KanaWord[] => {
|
|
23
|
+
const named = nameSpans(sentence.text, names);
|
|
24
|
+
return (sentence.tokens ?? [])
|
|
25
|
+
.filter((token) => token.pos === "NOUN" && isKatakanaWord(token.surface) && !exempt.has(stemOf(token.surface)))
|
|
26
|
+
.filter((token) => !touchesAny(named, token.span.start - sentence.span.start, token.span.end - sentence.span.start))
|
|
27
|
+
.map((token) => ({
|
|
28
|
+
surface: token.surface,
|
|
29
|
+
offset: token.span.start,
|
|
30
|
+
long: token.surface.endsWith("ー"),
|
|
31
|
+
dropped: token.features?.["LongVowelEnding"] === "Dropped",
|
|
32
|
+
}));
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const quoteAt = (doc: ProseDocument, offset: number): string =>
|
|
36
|
+
doc.sentences.find((sentence) => sentence.span.start <= offset && offset < sentence.span.end)?.text.trim() ?? "";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The final ー of katakana loanwords (コンピューター / コンピュータ). With no setting, it takes no side: it points at a word written
|
|
40
|
+
* both ways, and at the way the document writes less. Set to drop or keep, it points at every word the other way.
|
|
41
|
+
*/
|
|
42
|
+
export const katakanaLongVowel: Detector = (doc, options): Finding[] => {
|
|
43
|
+
const settings = options.settings ?? {};
|
|
44
|
+
const minMorae = typeof settings["min_morae"] === "number" ? settings["min_morae"] : DEFAULT_MIN_MORAE;
|
|
45
|
+
const exempt = exemptStems(wordsOf(settings["except"]));
|
|
46
|
+
const words = doc.sentences.flatMap((sentence) => kanaWordsOf(sentence, doc.names ?? [], exempt));
|
|
47
|
+
const odd = oddLongVowels(words, endingOf(settings["ending"]), minMorae);
|
|
48
|
+
if (odd.length === 0 || odd.length < options.limit) return [];
|
|
49
|
+
return odd.map((entry) => ({
|
|
50
|
+
rule: "",
|
|
51
|
+
severity: "warning",
|
|
52
|
+
line: 0,
|
|
53
|
+
column: 0,
|
|
54
|
+
quote: quoteAt(doc, entry.word.offset),
|
|
55
|
+
variant: entry.variant,
|
|
56
|
+
values: {
|
|
57
|
+
matched: entry.word.surface,
|
|
58
|
+
preferred: entry.preferred,
|
|
59
|
+
count: entry.count,
|
|
60
|
+
of: entry.of,
|
|
61
|
+
min_morae: minMorae,
|
|
62
|
+
limit: options.limit,
|
|
63
|
+
offset: entry.word.offset,
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Finding, Markup, ProseDocument, Span } from "../plugin.ts";
|
|
2
|
+
|
|
3
|
+
// 記法の rule(見出し・画像・リンク・URL)が指摘を作る形。
|
|
4
|
+
|
|
5
|
+
/** 引いて見せる記法の長さの上限。長い URL をまるごと見せても、どこが悪いかは伝わらない。 */
|
|
6
|
+
const QUOTE_LIMIT = 80;
|
|
7
|
+
|
|
8
|
+
export const quoteOf = (source: string, span: Span): string => {
|
|
9
|
+
const written = source.slice(span.start, span.end).replace(/\s+/gu, " ").trim();
|
|
10
|
+
return written.length > QUOTE_LIMIT ? `${written.slice(0, QUOTE_LIMIT)}…` : written;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const findingAt = (doc: ProseDocument, span: Span, values: Readonly<Record<string, string | number>>, variant?: string): Finding => ({
|
|
14
|
+
rule: "",
|
|
15
|
+
severity: "warning",
|
|
16
|
+
line: 0,
|
|
17
|
+
column: 0,
|
|
18
|
+
quote: quoteOf(doc.source, span),
|
|
19
|
+
values: { ...values, offset: span.start },
|
|
20
|
+
...(variant === undefined ? {} : { variant }),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/** Markdown の文書の記法。Markdown でなければ undefined。 */
|
|
24
|
+
export const markupOf = (doc: ProseDocument): Markup | undefined => (doc.markup?.markdown === true ? doc.markup : undefined);
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { romanRangeOf } from "./roman-numeral.ts";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* 大文字で始まる語のすぐ後ろの、I・V・X だけで書いたローマ数字(Engineer II、Leopold III、World War II)。名前に付く
|
|
3
5
|
* 番号で、略語ではない。語の前に文字が無ければ(文の頭、箇条書きの番号の後ろ)、大文字は名前の印ではなく文頭の書き方なので
|
|
4
6
|
* 外さない(Start IV fluids、1. Give IV fluids)。
|
|
5
|
-
* CD、MD、DC、CI、MIX のように C・D・L・M を含む数字は略語であることが多いので、この位置でも略語のまま数える。
|
|
7
|
+
* 範囲(Reactions II-VI)も同じ。CD、MD、DC、CI、MIX のように C・D・L・M を含む数字は略語であることが多いので、この位置でも略語のまま数える。
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
type Span = { readonly start: number; readonly end: number };
|
|
9
11
|
|
|
10
12
|
const SMALL_NUMERAL = "(?=[IVX])X{0,3}(?:IX|IV|V?I{0,3})";
|
|
11
|
-
const NAMED_NUMERAL = new RegExp(String.raw`(?<![\p{L}\p{N}_])\p{Lu}\p{Ll}+\s+(?<numeral>${SMALL_NUMERAL})(?![\p{L}\p{N}_&])`, "gu");
|
|
13
|
+
const NAMED_NUMERAL = new RegExp(String.raw`(?<![\p{L}\p{N}_])\p{Lu}\p{Ll}+\s+(?<numeral>${romanRangeOf(SMALL_NUMERAL)})(?![\p{L}\p{N}_&])`, "gu");
|
|
12
14
|
const LETTER = /\p{L}/u;
|
|
13
15
|
|
|
14
16
|
/** 文の中の、名前の後ろの番号の範囲(数字だけ)。 */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Detector, Finding, ProseDocument, Sentence, Span } from "../plugin.ts";
|
|
2
|
-
import { calendarRuns,
|
|
2
|
+
import { calendarRuns, calendarUnitsOf, type CalendarUnits } from "../calendar-number.ts";
|
|
3
3
|
import { latinBoundaries, minorityStyle, occurrencesOutside, type Boundary, type SpacingKind } from "../orthography.ts";
|
|
4
4
|
import { isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
5
|
-
import { digitRunAround, isNumberName, sequenceLabelStarts } from "../number-name.ts";
|
|
5
|
+
import { digitRunAround, endsWithDivisionLabel, isNumberName, sequenceLabelStarts, type NameContext } from "../number-name.ts";
|
|
6
6
|
|
|
7
7
|
/** チームが chaff.yaml の prefer に書いた「使わない書き方」。書いていなければ何も言わない。 */
|
|
8
8
|
export const preferredTerm: Detector = (doc, options): Finding[] => {
|
|
@@ -32,32 +32,36 @@ const digitBeside = (boundary: Boundary): number => {
|
|
|
32
32
|
return boundary.spaced ? boundary.offset + 1 : boundary.offset;
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* 文書全体で一度だけ読むもの(number-name.ts の NameContext に加えて)。calendar は日付・時刻の単位、
|
|
37
|
+
* divisions は「第1節」のように「第」と番号の後ろに書く区切りの語。
|
|
38
|
+
*/
|
|
39
|
+
type NumberContext = NameContext & { readonly calendar: CalendarUnits; readonly divisions: ReadonlySet<string> };
|
|
37
40
|
|
|
38
|
-
/**
|
|
39
|
-
const
|
|
40
|
-
new
|
|
41
|
+
/** 文の中の日付・時刻の数の、並びの頭の位置。 */
|
|
42
|
+
const calendarStarts = (sentence: Sentence, units: CalendarUnits): ReadonlySet<number> =>
|
|
43
|
+
new Set(calendarRuns(sentence.text, sentence.tokens, sentence.span.start, units).map(({ run }) => run.start));
|
|
41
44
|
|
|
42
45
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
46
|
+
* 番号・識別子として書かれた数(number-name.ts)、日付・時刻の数、「第1節」の後ろの境目は、空け方の好みではないので数えない。
|
|
47
|
+
* 日付・時刻は前の境目(「は 9月」「午後3時」「令和 3 年」)も数えない。日付はまとめて一つの書き方で、数量の空け方の票にはしない。
|
|
45
48
|
*/
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/** 番号・識別子として書かれた数(number-name.ts)と日付・時刻の中の境目は、空け方の好みではないので数えない。 */
|
|
50
|
-
const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContext, calendar: ReadonlyMap<number, CalendarRun["place"]>): boolean => {
|
|
49
|
+
const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContext, calendar: ReadonlySet<number>): boolean => {
|
|
50
|
+
if (boundary.kind !== "after-digit" && endsWithDivisionLabel(sentence.text.slice(0, boundary.offset), context.divisions)) return false;
|
|
51
51
|
if (boundary.kind === "letter") return true;
|
|
52
52
|
const run = digitRunAround(sentence.text, digitBeside(boundary));
|
|
53
53
|
if (run === undefined) return true;
|
|
54
|
-
if (
|
|
55
|
-
return !isNumberName(sentence.text, run, sentence.tokens, sentence.span.start, context
|
|
54
|
+
if (calendar.has(run.start)) return false;
|
|
55
|
+
return !isNumberName(sentence.text, run, sentence.tokens, sentence.span.start, context);
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const patternList = (doc: ProseDocument, id: string): string[] => (doc.lexicons[id] ?? []).map((entry) => entry.pattern);
|
|
59
59
|
const patternsOf = (doc: ProseDocument, id: string): ReadonlySet<string> => new Set(patternList(doc, id));
|
|
60
60
|
|
|
61
|
+
/** 語彙表 numbered-label のうち、番号の position 側に書く語。 */
|
|
62
|
+
const labelsAt = (doc: ProseDocument, position: "before" | "after"): ReadonlySet<string> =>
|
|
63
|
+
new Set((doc.lexicons["numbered-label"] ?? []).filter((entry) => entry.position === position).map((entry) => entry.pattern));
|
|
64
|
+
|
|
61
65
|
/**
|
|
62
66
|
* 鉤括弧で引いた題名や発言(「…ガイドライン ver. 1.1」)の中の境目。空け方は引いた元のもので、書き手の書き方ではない。
|
|
63
67
|
* 括弧は日本語の字でも英数字でもないので、境目はまるごと括弧の中か外にある。
|
|
@@ -73,11 +77,13 @@ export const latinSpacing: Detector = (doc, options): Finding[] => {
|
|
|
73
77
|
const context: NumberContext = {
|
|
74
78
|
sequence: sequenceLabelStarts(doc.prose ?? doc.source),
|
|
75
79
|
topUnits: patternsOf(doc, "prefecture-unit"),
|
|
76
|
-
|
|
80
|
+
labelWords: labelsAt(doc, "before"),
|
|
81
|
+
calendar: calendarUnitsOf(doc),
|
|
82
|
+
divisions: labelsAt(doc, "after"),
|
|
77
83
|
};
|
|
78
84
|
const located: Located[] = doc.sentences.flatMap((sentence) => {
|
|
79
85
|
const quoted = quotedSpans(sentence.text);
|
|
80
|
-
const calendar =
|
|
86
|
+
const calendar = calendarStarts(sentence, context.calendar);
|
|
81
87
|
return latinBoundaries(sentence.text, doc.source.slice(sentence.span.start, sentence.span.end))
|
|
82
88
|
.filter((boundary) => !isQuoted(quoted, boundary) && isCounted(sentence, boundary, context, calendar))
|
|
83
89
|
.map((boundary) => ({ sentence, ...boundary }));
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import type { Detector, Finding, Lexicon, Token } from "../plugin.ts";
|
|
2
|
+
import {
|
|
3
|
+
contentCount,
|
|
4
|
+
exampleEnd,
|
|
5
|
+
firstAt,
|
|
6
|
+
firstContent,
|
|
7
|
+
firstNoun,
|
|
8
|
+
hasAdposition,
|
|
9
|
+
hasContent,
|
|
10
|
+
hasDeterminer,
|
|
11
|
+
hasListConjunction,
|
|
12
|
+
hasParticiple,
|
|
13
|
+
hasVerb,
|
|
14
|
+
isClause,
|
|
15
|
+
isModifiedNoun,
|
|
16
|
+
isModifier,
|
|
17
|
+
isParticiple,
|
|
18
|
+
isPluralNounPhrase,
|
|
19
|
+
itemAfter,
|
|
20
|
+
lastContent,
|
|
21
|
+
lastNoun,
|
|
22
|
+
leadShape,
|
|
23
|
+
openingKind,
|
|
24
|
+
openingOf,
|
|
25
|
+
participleOpening,
|
|
26
|
+
shapeOf,
|
|
27
|
+
} from "./list-item.ts";
|
|
28
|
+
import { listReader, type ItemList } from "./list-items.ts";
|
|
29
|
+
import { APPOSITIVE_ANCHOR, isListConjunction, listSentenceOf, VERBAL, type ItemScope, type ListWords } from "./list-sentence.ts";
|
|
30
|
+
import {
|
|
31
|
+
after,
|
|
32
|
+
contentOnlyWith,
|
|
33
|
+
every,
|
|
34
|
+
findAfterFirst,
|
|
35
|
+
findLast,
|
|
36
|
+
firstOf,
|
|
37
|
+
lastOf,
|
|
38
|
+
sameShapes,
|
|
39
|
+
secondLastOf,
|
|
40
|
+
secondOf,
|
|
41
|
+
sizeOf,
|
|
42
|
+
some,
|
|
43
|
+
wholeList,
|
|
44
|
+
withoutFirst,
|
|
45
|
+
type View,
|
|
46
|
+
} from "./list-view.ts";
|
|
47
|
+
import { lowerBound, type TokenRange } from "./token-column.ts";
|
|
48
|
+
|
|
49
|
+
const EMPTY: TokenRange = { start: 0, end: 0 };
|
|
50
|
+
|
|
51
|
+
const commaBefore = (scope: ItemScope, at: number): boolean => scope.sentence.tokens[at - 1]?.surface === ",";
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 導入の句(After the review, / If it fails, / Finally, / To test it, / Based on the review,)は並列の項目ではない。
|
|
55
|
+
* 節の最初の項目が前置詞・接続詞・副詞・to・過去分詞で始まり、次の項目と頭の形が違えば外す。
|
|
56
|
+
* Quickly, quietly and carefully は残る。For managers, engineers and designers, も外れるが、前置詞のあとの名詞を
|
|
57
|
+
* 項目と読むと、Over this period, the subcommittees and the full committee ... を並びと誤る。こちらのほうが多い。
|
|
58
|
+
*/
|
|
59
|
+
const LEAD_POS = new Set(["ADP", "SCONJ", "ADV", "PART"]);
|
|
60
|
+
|
|
61
|
+
const withoutLead = (view: View): View => {
|
|
62
|
+
const { scope } = view.list;
|
|
63
|
+
const [first, second] = [firstOf(view), secondOf(view)];
|
|
64
|
+
const opening = first === undefined ? undefined : openingOf(scope, first.item);
|
|
65
|
+
if (first === undefined || second === undefined || opening === undefined) return view;
|
|
66
|
+
if (!LEAD_POS.has(opening.pos) && !isParticiple(opening)) return view;
|
|
67
|
+
return openingKind(scope, first.item) === openingKind(scope, second.item) ? view : withoutFirst(view);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* and / or で始まる項目で、前の並びは閉じている(offering, giving, or receiving, directly or indirectly)。
|
|
72
|
+
* 次の並びはその項目から始まる。項目が動詞で始まれば、その目的語から(Develop, maintain, and track courses, materials and events)。
|
|
73
|
+
* 項目が残らなければ、後ろは新しい句の頭。導入の句(directly or indirectly,)を外す。
|
|
74
|
+
*/
|
|
75
|
+
const afterClosedList = (view: View): View => {
|
|
76
|
+
const closing = findLast(view, "closed");
|
|
77
|
+
if (closing === undefined) return view;
|
|
78
|
+
const { scope } = view.list;
|
|
79
|
+
const conjunction = firstAt(scope, "conjunction", closing.item);
|
|
80
|
+
const body = { start: conjunction === -1 ? closing.item.start : conjunction + 1, end: closing.item.end };
|
|
81
|
+
const head = firstAt(scope, "content", body);
|
|
82
|
+
const rest = VERBAL.has(scope.sentence.tokens[head]?.pos ?? "") ? { start: head + 1, end: body.end } : body;
|
|
83
|
+
return hasContent(scope, rest) ? { ...after(view, closing), pre: rest } : withoutLead(after(view, closing));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 例の句(such as / including / e.g.)のあとが並び。句の前の項目は並びではない(the screen lock on your phone, such as a PIN or
|
|
88
|
+
* phone-based fingerprint は 2 つ)。句の中の項目の形が揃わなければ句で切らない(materials such as green steel, utilizing ..., and
|
|
89
|
+
* adopting ... / (e.g., by location, contract type, or contract preference))。句の中に and / or があれば句はもう閉じていて、
|
|
90
|
+
* 句ごと 1 つの項目(apples, oranges such as navels and mandarins, and pears)。
|
|
91
|
+
*/
|
|
92
|
+
const fromExample = (view: View): View => {
|
|
93
|
+
const phrase = findLast(view, "example");
|
|
94
|
+
if (phrase === undefined) return view;
|
|
95
|
+
const { scope } = view.list;
|
|
96
|
+
const examples = { start: exampleEnd(scope, phrase.item), end: phrase.item.end };
|
|
97
|
+
if (hasListConjunction(scope, examples)) return view;
|
|
98
|
+
const inPhrase = contentOnlyWith(after(view, phrase), examples);
|
|
99
|
+
return sameShapes(inPhrase) ? inPhrase : view;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** 解析器は過去形と過去分詞(fixed)を見分けられない。動詞のある項目のあとの「過去分詞」の並びは、述語の並びと読む。 */
|
|
103
|
+
const pastPredicates = (scope: ItemScope, first: TokenRange, form: string, afterItem: TokenRange): boolean =>
|
|
104
|
+
form === "Part" && participleOpening(scope, afterItem)?.form === "Part" && hasVerb(scope, first);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 最初より後ろの項目が分詞で始まるとき。最初の項目にも同じ形の分詞があれば分詞の並び
|
|
108
|
+
* (are hiring engineers, buying laptops and renting desks / Tested, reviewed and approved)。後ろの項目が動詞で始まれば述語の並びで、
|
|
109
|
+
* 分詞は解析器の読み違い(the jury, cross-examined the witnesses, presented witnesses, and made)。そうでなければ分詞の句
|
|
110
|
+
* (from Latin, meaning ship or boat / the judge, sitting without a jury, and sentenced)で、並びがあるならその句の中から始まる。
|
|
111
|
+
* 分詞より前の項目と分詞そのものは項目ではない(programs, including the office, the desk and the team)。句の中の項目の形が揃わなければ
|
|
112
|
+
* 句は挿入で、並びは句の後ろだけ(relief, including an injunction, in any court ... and without / including before the date, to a
|
|
113
|
+
* Recipient ... “confidential”, “proprietary”, or the like)。
|
|
114
|
+
*/
|
|
115
|
+
const fromParticiplePhrase = (view: View, afterItem: TokenRange): View => {
|
|
116
|
+
const { scope } = view.list;
|
|
117
|
+
const [first, phrase] = [firstOf(view), findAfterFirst(view, "participle")];
|
|
118
|
+
const opening = phrase === undefined ? undefined : participleOpening(scope, phrase.item);
|
|
119
|
+
if (first === undefined || phrase === undefined || opening === undefined) return view;
|
|
120
|
+
const rest = after(view, phrase);
|
|
121
|
+
const predicates = some(rest, "verbalShape") || pastPredicates(scope, first.item, opening.form, afterItem);
|
|
122
|
+
if (hasParticiple(scope, first.item, opening.form) || predicates) return view;
|
|
123
|
+
const inPhrase = withoutLead(contentOnlyWith(rest, { start: opening.at + 1, end: phrase.item.end }));
|
|
124
|
+
return sameShapes(inPhrase) ? inPhrase : rest;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 名詞のすぐ後ろの、読点で挟まれた X and Y は同格(two HPV types, HPV16 and HPV18, that account / Governments, both state and
|
|
129
|
+
* federal, spend)。項目が 2 つに見え、and の前に読点が無く、and の後ろの項目が読点で閉じ、後ろの 2 つに動詞が無いときに同格と読む。
|
|
130
|
+
* 2 つを結ぶ同格に Oxford comma は打たないので、and の前に読点があれば 3 つの並び(the subcommittee, full committee, and
|
|
131
|
+
* chamber levels, as well as)。読点の無い本当の並び(apples, pears and plums, then ...)はこの形と見分けられず、判定から外れる。
|
|
132
|
+
* 閉じた読点のあとに and / or が続くなら、並びのあとに節をつないでいる(apples, pears and plums, and went home)。
|
|
133
|
+
*/
|
|
134
|
+
const isAppositive = (scope: ItemScope, at: number, view: View, afterItem: TokenRange): boolean => {
|
|
135
|
+
const [anchor, head] = [firstOf(view), secondOf(view)];
|
|
136
|
+
if (sizeOf(view) !== 2 || anchor === undefined || head === undefined || commaBefore(scope, at)) return false;
|
|
137
|
+
const end = afterItem.end;
|
|
138
|
+
const joinsClause = isListConjunction(scope.sentence.tokens[end + 1]);
|
|
139
|
+
const closed = scope.sentence.tokens[end]?.surface === "," && scope.sentence.depths[end] === scope.sentence.depths[at] && !joinsClause;
|
|
140
|
+
return closed && APPOSITIVE_ANCHOR.has(lastContent(scope, anchor.item)?.pos ?? "") && !hasVerb(scope, head.item) && !hasVerb(scope, afterItem);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* and の後ろの項目に読点と、同じ形の項目を連れた and / or が続くなら、この and は項目の中にある(searches and seizures, and
|
|
145
|
+
* the Eighth's ban)。頭の形か、節かどうかが違えば別の節をつなぐ and で、この and までが並び(apples, pears and plums, and went home / and figs fell)。
|
|
146
|
+
*/
|
|
147
|
+
const listContinues = (scope: ItemScope, afterItem: TokenRange): boolean => {
|
|
148
|
+
const next = afterItem.end;
|
|
149
|
+
if (scope.sentence.tokens[next]?.surface !== "," || !isListConjunction(scope.sentence.tokens[next + 1])) return false;
|
|
150
|
+
const following = itemAfter(scope, next + 1);
|
|
151
|
+
const shape = leadShape(scope, following);
|
|
152
|
+
return shape !== undefined && shape === leadShape(scope, afterItem) && isClause(scope, following) === isClause(scope, afterItem);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 語のあとが複数形の名詞句なら、語は名詞にかかる語で、2 つはもう揃っている(the renderer in both modes and the exporter)。
|
|
157
|
+
* and の後ろも冠詞の無い複数形の名詞句なら、2 つを結ぶ語(both project goals and business goals)。
|
|
158
|
+
*/
|
|
159
|
+
const pairComplete = (scope: ItemScope, member: TokenRange, afterItem: TokenRange): boolean => {
|
|
160
|
+
const end = firstAt(scope, "conjunction", afterItem);
|
|
161
|
+
const partner = end === -1 ? afterItem : { start: afterItem.start, end };
|
|
162
|
+
return isPluralNounPhrase(scope, member) && !(isPluralNounPhrase(scope, partner) && !hasDeterminer(scope, partner));
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 最後の項目に 2 つだけを結ぶ語(between / either)があり、この接続詞がその語の相手で(between … and / either … or)、そのあとに
|
|
167
|
+
* and / or がまだ無く、読点も無ければ、この and / or はその 2 つを結ぶ(the Key Terms between Provider and Customer, and any policies)。
|
|
168
|
+
* 相手でなければ語は名詞にかかるだけ(the impact of either option and implementation)。括弧の中の語は外の接続詞と組まない。
|
|
169
|
+
*/
|
|
170
|
+
const pairsInLastItem = (scope: ItemScope, at: number, view: View, afterItem: TokenRange): boolean => {
|
|
171
|
+
const last = lastOf(view)?.item ?? EMPTY;
|
|
172
|
+
const conjunction = scope.sentence.tokens[at]?.surface.toLowerCase() ?? "";
|
|
173
|
+
const openers = scope.sentence.pairOpeners.get(conjunction)?.get(scope.sentence.depths[at] ?? 0) ?? [];
|
|
174
|
+
const opener = openers[lowerBound(openers, last.end) - 1] ?? -1;
|
|
175
|
+
if (opener < last.start || commaBefore(scope, at)) return false;
|
|
176
|
+
const member = { start: opener + 1, end: last.end };
|
|
177
|
+
return !pairComplete(scope, member, afterItem) && !hasListConjunction(scope, member);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 修飾語 1 つだけの項目と、修飾語で始まる名詞句を結ぶ and / or は、2 つの修飾語が名詞を共有している(natural and artificial flavor /
|
|
182
|
+
* registered or certified mail)。前の項目も修飾語で終われば、修飾語の並び(red, white and blue flags)。and / or の前に読点があれば、
|
|
183
|
+
* 項目の区切り(Federal government, military, and agricultural workers)。
|
|
184
|
+
*/
|
|
185
|
+
const sharesNoun = (scope: ItemScope, at: number, view: View, afterItem: TokenRange): boolean => {
|
|
186
|
+
const [previous, last] = [secondLastOf(view), lastOf(view)];
|
|
187
|
+
if (commaBefore(scope, at) || previous === undefined || last === undefined || contentCount(scope, last.item) !== 1) return false;
|
|
188
|
+
return isModifier(firstContent(scope, last.item)) && !isModifier(lastContent(scope, previous.item)) && isModifiedNoun(scope, afterItem);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* and / or の後ろの最初の名詞が、最後の項目の前置詞の目的語と同じ品詞で、どの項目の頭とも違う(chat in Slack or Google Hangouts /
|
|
193
|
+
* Teams (beta): 固有名詞どうし)。頭と同じ品詞なら項目とも読める(petitions for waivers and appeals)ので、並びのまま。
|
|
194
|
+
*/
|
|
195
|
+
const likeLastObject = (scope: ItemScope, view: View, afterItem: TokenRange): boolean => {
|
|
196
|
+
const kind = firstNoun(scope, afterItem)?.pos;
|
|
197
|
+
if (kind === undefined) return false;
|
|
198
|
+
return lastNoun(scope, lastOf(view)?.item ?? EMPTY)?.pos === kind && every(view, kind === "NOUN" ? "notNounHead" : "notProperNounHead");
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* どの項目も前置詞の句を連れ、and / or の後ろだけが連れておらず、その目的語に似ていれば、and / or は最後の項目の前置詞の目的語を結ぶ
|
|
203
|
+
* (updates on the Google Doc, chat in Slack or Google Hangouts は 2 つ)。and / or の前に読点があれば、項目の区切りなので並び。
|
|
204
|
+
*/
|
|
205
|
+
const joinsObjects = (scope: ItemScope, at: number, view: View, afterItem: TokenRange): boolean =>
|
|
206
|
+
!commaBefore(scope, at) &&
|
|
207
|
+
every(view, "prepositionalTail") &&
|
|
208
|
+
!hasAdposition(scope, afterItem) &&
|
|
209
|
+
!hasVerb(scope, afterItem) &&
|
|
210
|
+
likeLastObject(scope, view, afterItem);
|
|
211
|
+
|
|
212
|
+
/** and / or が並びの最後の継ぎ目ではなく、最後の項目の中にある。 */
|
|
213
|
+
const insideLastItem = (scope: ItemScope, at: number, view: View, afterItem: TokenRange): boolean =>
|
|
214
|
+
pairsInLastItem(scope, at, view, afterItem) || sharesNoun(scope, at, view, afterItem) || joinsObjects(scope, at, view, afterItem);
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 節を並べるなら、どの項目も節。Additionally, others can learn, and the mistake is rarer. の Additionally は項目ではなく、
|
|
218
|
+
* and の前の読点は節をつなぐ読点。名詞の並びは最初の項目に前置き(We shipped the parser)を抱えるので、この確かめは節の並びだけにする。
|
|
219
|
+
* and の後ろだけが節なのは主語の並び(The parser, the renderer and the exporter shipped.)なので外さない。
|
|
220
|
+
* 動詞で始まる項目を並べるなら、どの項目にも動詞がある。The scope, in contrast, is larger, and covers ... の The scope は項目ではない。
|
|
221
|
+
*/
|
|
222
|
+
const itemsAgree = (scope: ItemScope, view: View, afterItem: TokenRange, shape: string): boolean => {
|
|
223
|
+
const last = lastOf(view);
|
|
224
|
+
const clausesAgree = last === undefined || !isClause(scope, last.item) || (isClause(scope, afterItem) && every(view, "isClause"));
|
|
225
|
+
return clausesAgree && (!VERBAL.has(shape) || every(view, "hasVerb"));
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* 読点で区切った項目が and / or の前に 2 つ以上あり、最後の項目と and の後ろが同じ形のときだけ並列。
|
|
230
|
+
* 導入の読点(After the review, the team fixed the bug and shipped it.)や、節をつなぐ読点
|
|
231
|
+
* (We tested it, and the team shipped it.)は、Oxford comma を打つかどうかの選択を見せない。
|
|
232
|
+
* 題名の読点は題名を付けた人のもの。書き手の流儀の票にしない。
|
|
233
|
+
*/
|
|
234
|
+
const listAt = (list: ItemList, at: number): boolean | undefined => {
|
|
235
|
+
const { scope } = list;
|
|
236
|
+
const afterItem = itemAfter(scope, at);
|
|
237
|
+
const items = fromParticiplePhrase(fromExample(afterClosedList(withoutLead(wholeList(list)))), afterItem);
|
|
238
|
+
if (listContinues(scope, afterItem) || isAppositive(scope, at, items, afterItem) || insideLastItem(scope, at, items, afterItem)) return undefined;
|
|
239
|
+
const last = lastOf(items);
|
|
240
|
+
const shape = last === undefined ? undefined : shapeOf(scope, last.item);
|
|
241
|
+
if (sizeOf(items) < 2 || shape === undefined || shape !== shapeOf(scope, afterItem)) return undefined;
|
|
242
|
+
return itemsAgree(scope, items, afterItem, shape) ? commaBefore(scope, at) : undefined;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const isJudgedConjunction = (token: Token, at: number): boolean => at > 0 && isListConjunction(token);
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 文の and / or ごとの、並びの判定(読点を打てば true、打たなければ false、並びでなければ undefined)。文は一度だけ読み、
|
|
249
|
+
* 項目は and / or の位置まで読み進めた並びから取る。
|
|
250
|
+
*/
|
|
251
|
+
export const listVerdicts = (tokens: readonly Token[], words: ListWords, source: string): (boolean | undefined)[] => {
|
|
252
|
+
if (!tokens.some(isJudgedConjunction)) return [];
|
|
253
|
+
const sentence = listSentenceOf(tokens, words, source);
|
|
254
|
+
const readItems = listReader(sentence);
|
|
255
|
+
return tokens.flatMap((token, at) => {
|
|
256
|
+
if (!isJudgedConjunction(token, at)) return [];
|
|
257
|
+
return [sentence.inCitedTitle(at) ? undefined : listAt(readItems(at), at)];
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 3 つ以上の並列の最後の and / or の前に読点を打つか。Oxford comma。
|
|
263
|
+
*
|
|
264
|
+
* どちらが正しいかは決めない。スタイルガイドで割れる論点に立場を取ると rule ごと無視される。
|
|
265
|
+
* 見るのは 1 つの文書で揃っているかだけ。spec §12.3。最初に判定できた並びで決める。
|
|
266
|
+
*/
|
|
267
|
+
const oxfordIn = (tokens: readonly Token[], words: ListWords, source: string): boolean | undefined =>
|
|
268
|
+
listVerdicts(tokens, words, source).find((verdict) => verdict !== undefined);
|
|
269
|
+
|
|
270
|
+
const patternsOf = (lexicon: Lexicon | undefined): ReadonlySet<string> => new Set((lexicon ?? []).map((entry) => entry.pattern.toLowerCase()));
|
|
271
|
+
|
|
272
|
+
export const oxfordComma: Detector = (doc, options): Finding[] => {
|
|
273
|
+
const words = {
|
|
274
|
+
participle: patternsOf(doc.lexicons["participle-word"]),
|
|
275
|
+
example: doc.lexicons["example-marker"] ?? [],
|
|
276
|
+
pair: patternsOf(doc.lexicons["pair-opener"]),
|
|
277
|
+
};
|
|
278
|
+
const judged = doc.sentences.flatMap((sentence) => {
|
|
279
|
+
const oxford = oxfordIn(sentence.tokens ?? [], words, doc.source);
|
|
280
|
+
return oxford === undefined ? [] : [{ sentence, oxford }];
|
|
281
|
+
});
|
|
282
|
+
const withComma = judged.filter((entry) => entry.oxford).length;
|
|
283
|
+
const minorityUsesComma = withComma <= judged.length - withComma;
|
|
284
|
+
const few = minorityUsesComma ? withComma : judged.length - withComma;
|
|
285
|
+
// 同数なら少数派は無い。
|
|
286
|
+
if (few === 0 || few * 2 === judged.length || few > options.limit) return [];
|
|
287
|
+
return judged
|
|
288
|
+
.filter((entry) => entry.oxford === minorityUsesComma)
|
|
289
|
+
.map(({ sentence }) => ({
|
|
290
|
+
rule: "oxford-comma-consistency",
|
|
291
|
+
severity: "info",
|
|
292
|
+
line: 0,
|
|
293
|
+
column: 0,
|
|
294
|
+
quote: sentence.text.trim(),
|
|
295
|
+
values: { count: few, limit: options.limit, offset: sentence.span.start },
|
|
296
|
+
}));
|
|
297
|
+
};
|
|
@@ -20,10 +20,13 @@ type Run = { readonly tokens: readonly Token[]; readonly last: number; readonly
|
|
|
20
20
|
* 閉じれば、そこまでが 1 つの地名。連なりの外(「に」「の」も 1 字)までは読まない。
|
|
21
21
|
*/
|
|
22
22
|
const closedByUnit = (run: Run, index: number): boolean => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
for (let at = index; at <= run.last; at += 1) {
|
|
24
|
+
const token = run.tokens[at];
|
|
25
|
+
if (token === undefined) return false;
|
|
26
|
+
if (isGeoUnit(token)) return !run.topUnits.has(token.surface);
|
|
27
|
+
if (!isNamePiece(token)) return false;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
/**
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Lexicon } from "../plugin.ts";
|
|
2
|
+
|
|
3
|
+
type Span = { readonly start: number; readonly end: number };
|
|
4
|
+
|
|
5
|
+
/** 雛形の空欄を囲む括弧。記号の形で、どの言語でも同じ。 */
|
|
6
|
+
const BRACKETED = /\[([^[\]\n]{1,60})\]|【([^【】\n]{1,30})】|[([^[]\n]{1,30})]/gu;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 括弧のすぐ後ろ。Markdown のリンク([text](url)、[text][ref])と参照の定義([ref]: url)、
|
|
10
|
+
* 値が続く見出しの札(【氏名】山田、【日付】2024年)は空欄ではない。助詞(【会社名】の)や空白・句読点が続くなら空欄。
|
|
11
|
+
*/
|
|
12
|
+
const FILLED_AFTER = /^[([::\p{Script=Han}\p{Script=Katakana}\p{Script=Latin}\p{N}]/u;
|
|
13
|
+
|
|
14
|
+
const innerOf = (match: RegExpExecArray): string => (match[1] ?? match[2] ?? match[3] ?? "").trim().toLowerCase();
|
|
15
|
+
|
|
16
|
+
/** 括弧の中身が語彙表の語そのものか、その語で始まって空白・アポストロフィが続くか([Your Name]、[Insert Date])。 */
|
|
17
|
+
const holdsWord = (inner: string, words: Lexicon): boolean =>
|
|
18
|
+
words.some((word) => {
|
|
19
|
+
const pattern = word.pattern.toLowerCase();
|
|
20
|
+
return inner === pattern || (inner.startsWith(pattern) && /^[\s'’]/u.test(inner.slice(pattern.length)));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/** 文の中の、埋め忘れた雛形の空欄([Your Name]、【会社名】)の範囲。words は空欄に書く語。 */
|
|
24
|
+
export const placeholderSpans = (text: string, words: Lexicon): Span[] =>
|
|
25
|
+
[...text.matchAll(BRACKETED)]
|
|
26
|
+
.filter((match) => !FILLED_AFTER.test(text.slice(match.index + match[0].length)) && holdsWord(innerOf(match), words))
|
|
27
|
+
.map((match) => ({ start: match.index, end: match.index + match[0].length }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** 見せる前後の字数。記号 1 つの指摘は、周りの言葉が無いとどこか分からない。 */
|
|
2
|
+
const QUOTE_REACH = 20;
|
|
3
|
+
|
|
4
|
+
/** text の start から end の前後を、空白をならして引く。 */
|
|
5
|
+
export const quoteAround = (text: string, start: number, end: number = start + 1): string =>
|
|
6
|
+
text
|
|
7
|
+
.slice(Math.max(0, start - QUOTE_REACH), end + QUOTE_REACH)
|
|
8
|
+
.replace(/\s+/gu, " ")
|
|
9
|
+
.trim();
|
|
@@ -15,21 +15,32 @@ const chainAtEnd = (preceding: readonly Token[]): readonly Token[] => {
|
|
|
15
15
|
return preceding.slice(Math.max(head, 0));
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
/** 語彙表 neutral-ending の語(「こと」)か。書いた形か原形で照らす。 */
|
|
19
|
+
const isNeutralWord = (token: Token | undefined, neutral: readonly LexiconEntry[]): boolean =>
|
|
20
|
+
token !== undefined && neutral.some((entry) => token.surface === entry.pattern || token.lemma === entry.pattern);
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
23
|
+
* 非自立名詞で終わる文末は、手前の述語の連なりまで見る。「使っているのかな?」は手前の述語が調子を持つ。
|
|
24
|
+
* 「以下のとおり。」は手前も述語でないので、調子を持たないまま。
|
|
25
|
+
* 語彙表 neutral-ending の語(「こと」)で終わる文末は手前を見ない。「〜を保持すること。」は体言止めで、要件や規程の箇条書きは
|
|
26
|
+
* ですます調の文書でもである調の文書でもこの形で書く。
|
|
21
27
|
*/
|
|
22
|
-
const withPreceding = (ending: readonly Token[], preceding: readonly Token[]): readonly Token[] =>
|
|
23
|
-
isDependent(ending[0]) ? [...chainAtEnd(preceding), ...ending] : ending;
|
|
28
|
+
const withPreceding = (ending: readonly Token[], preceding: readonly Token[], neutral: readonly LexiconEntry[]): readonly Token[] =>
|
|
29
|
+
isDependent(ending[0]) && !isNeutralWord(ending[0], neutral) ? [...chainAtEnd(preceding), ...ending] : ending;
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
|
-
* 文末の語の調子。preceding は文末の語より前の語。
|
|
32
|
+
* 文末の語の調子。preceding は文末の語より前の語。neutral は調子を持たない文末の語(語彙表 neutral-ending)。
|
|
27
33
|
* 文末に述語(動詞・形容詞・助動詞)が無ければ、ですます調でもである調でもないので undefined。
|
|
28
34
|
* 「以下の通り。」「円錐形の麦わら帽子。」のような名詞で終わる文を数えると、そのままである調の少数派になっていた。
|
|
29
35
|
* 書いた形でも原形でも読みでも当てる(polite-word.ts)。「ください」の原形は「くださる」で、原形だけを見ると丁寧な文末を見落とす。
|
|
30
36
|
*/
|
|
31
|
-
export const registerOf = (
|
|
32
|
-
|
|
37
|
+
export const registerOf = (
|
|
38
|
+
ending: readonly Token[],
|
|
39
|
+
preceding: readonly Token[],
|
|
40
|
+
polite: readonly LexiconEntry[],
|
|
41
|
+
neutral: readonly LexiconEntry[] = [],
|
|
42
|
+
): Register | undefined => {
|
|
43
|
+
const judged = withPreceding(ending, preceding, neutral);
|
|
33
44
|
if (!judged.some(isPredicate)) return undefined;
|
|
34
45
|
return judged.some((token) => isPoliteWord(token, polite)) ? "polite" : "plain";
|
|
35
46
|
};
|
|
@@ -56,21 +67,36 @@ export const groupOf = (offset: number, lists: readonly Span[], runs: readonly S
|
|
|
56
67
|
/** group: 文が入っているまとまり(groupOf の値)。本文なら undefined。 */
|
|
57
68
|
export type Judged = { readonly register: Register; readonly group: number | undefined };
|
|
58
69
|
|
|
59
|
-
/**
|
|
70
|
+
/** 混ざった文と、その文が属するまとまり(本文、または箇条書き 1 つ)の中の少数派の数。文書全体の数ではない。 */
|
|
60
71
|
export type Slip<T extends Judged> = { readonly entry: T; readonly count: number };
|
|
61
72
|
|
|
62
73
|
const countIn = (judged: readonly Judged[], register: Register): number => judged.filter((entry) => entry.register === register).length;
|
|
63
74
|
|
|
75
|
+
/** 多いほう。同数なら undefined。 */
|
|
76
|
+
export const majorityOf = (judged: readonly Judged[]): Register | undefined => {
|
|
77
|
+
const difference = countIn(judged, "polite") - countIn(judged, "plain");
|
|
78
|
+
if (difference === 0) return undefined;
|
|
79
|
+
return difference > 0 ? "polite" : "plain";
|
|
80
|
+
};
|
|
81
|
+
|
|
64
82
|
/** 少ないほう。同数なら文書全体で少ないほう、それも同数なら丁寧体。 */
|
|
65
83
|
const minorityOf = (group: readonly Judged[], whole: readonly Judged[]): Register => {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
84
|
+
const majority = majorityOf(group);
|
|
85
|
+
if (majority !== undefined) return majority === "polite" ? "plain" : "polite";
|
|
68
86
|
return countIn(whole, "polite") <= countIn(whole, "plain") ? "polite" : "plain";
|
|
69
87
|
};
|
|
70
88
|
|
|
89
|
+
/**
|
|
90
|
+
* 箇条書きの中の少数派が、文書全体では多数派か。それなら箇条書きの中で文書の調子に寄せた側なので、直す側ではない。
|
|
91
|
+
* 常体の多い箇条書きにですます調の文が混ざっても、ですます調の文書なら「多いほうに揃えて」は文書の少数派へ揃えることになる。
|
|
92
|
+
*/
|
|
93
|
+
export const followsDocument = (group: number | undefined, minority: Register, whole: readonly Judged[]): boolean =>
|
|
94
|
+
group !== undefined && majorityOf(whole) === minority;
|
|
95
|
+
|
|
71
96
|
const slipsInGroup = <T extends Judged>(judged: readonly T[], group: number | undefined, limit: number): Slip<T>[] => {
|
|
72
97
|
const members = judged.filter((entry) => entry.group === group);
|
|
73
98
|
const minority = minorityOf(members, judged);
|
|
99
|
+
if (followsDocument(group, minority, judged)) return [];
|
|
74
100
|
const slips = members.filter((entry) => entry.register === minority);
|
|
75
101
|
// 片方しか無ければ揃っている。少数派が閾値を超えて多ければ、混在ではなく別の文体。
|
|
76
102
|
if (slips.length === 0 || slips.length > limit) return [];
|
|
@@ -80,6 +106,7 @@ const slipsInGroup = <T extends Judged>(judged: readonly T[], group: number | un
|
|
|
80
106
|
/**
|
|
81
107
|
* 調子が混ざった文を、judged の順で。本文は本文どうし、箇条書きと番号で始まる段落の並びは 1 つずつ、その中で揃っているかを見る。
|
|
82
108
|
* ですます調の本文に常体の箇条書きを置くのはよくある書き方で、箇条書きが丸ごと揃っていれば混在ではない。
|
|
109
|
+
* 箇条書きの中で混ざっていても、少数派が文書全体の多数派なら指さない(followsDocument)。
|
|
83
110
|
*/
|
|
84
111
|
export const slipsOf = <T extends Judged>(judged: readonly T[], limit: number): Slip<T>[] => {
|
|
85
112
|
const slips = [...new Set(judged.map((entry) => entry.group))].flatMap((group) => slipsInGroup(judged, group, limit));
|
|
@@ -3,3 +3,6 @@
|
|
|
3
3
|
* 各桁が省けるので空文字にも当たる。1 文字目があることを先読みで求める。
|
|
4
4
|
*/
|
|
5
5
|
export const ROMAN_NUMERAL = "(?=[MDCLXVI])M{0,4}(?:CM|CD|D?C{0,3})(?:XC|XL|L?X{0,3})(?:IX|IV|V?I{0,3})";
|
|
6
|
+
|
|
7
|
+
/** ハイフンかダッシュで繋いだ数字の範囲(II-VI、I–III)も、一つの番号として読む。 */
|
|
8
|
+
export const romanRangeOf = (numeral: string): string => `${numeral}(?:[-–]${numeral})?`;
|