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
package/src/run.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DETECTORS } from "./detectors/index.ts";
|
|
2
|
-
import { resolve } from "./levels.ts";
|
|
3
|
-
import type { AdapterNeeds, Finding, Level, ProseDocument, RuleDefinition } from "./plugin.ts";
|
|
2
|
+
import { resolve, severityAt } from "./levels.ts";
|
|
3
|
+
import type { AdapterNeeds, Detector, DetectorOptions, Finding, Level, ProseDocument, RuleDefinition } from "./plugin.ts";
|
|
4
4
|
import { lineStarts, placeOf } from "./position.ts";
|
|
5
5
|
import { REASONS, type Reasons } from "./reasons.ts";
|
|
6
6
|
import { joinWords } from "./detectors/word-list.ts";
|
|
@@ -11,6 +11,9 @@ import { maskSpans } from "./mask.ts";
|
|
|
11
11
|
import { textOutline } from "./page-furniture.ts";
|
|
12
12
|
import { uiLanguageOf } from "./ui.ts";
|
|
13
13
|
import { presetLevels } from "./genre-load.ts";
|
|
14
|
+
import { bodySectionOf } from "./body-section.ts";
|
|
15
|
+
import { optionValues, settleOptions, type OptionLayer } from "./rule-options.ts";
|
|
16
|
+
import { PatternTimeout } from "./custom/bounded-match.ts";
|
|
14
17
|
|
|
15
18
|
export type Skipped = { readonly rule: string; readonly why: string };
|
|
16
19
|
|
|
@@ -68,7 +71,7 @@ const treeProblem = (doc: ProseDocument): string | undefined => {
|
|
|
68
71
|
|
|
69
72
|
/** 木が読んだのと同じ本文。Markdown はコードを覆ったもの、.txt はページの飾りだけを覆ったもの(.txt の字下げはコードではない)。 */
|
|
70
73
|
const textTheTreeRead = (doc: ProseDocument): string =>
|
|
71
|
-
isMarkdownPath(doc.path) ? (doc.prose ?? doc.source) : maskSpans(doc.source, textOutline(doc.source).opaque);
|
|
74
|
+
isMarkdownPath(doc.path) ? (doc.prose ?? doc.source) : maskSpans(doc.source, textOutline(doc.source, doc.replyQuotes).opaque);
|
|
72
75
|
|
|
73
76
|
const unreadByDocument = new WeakMap<ProseDocument, Unread | undefined>();
|
|
74
77
|
|
|
@@ -78,6 +81,15 @@ const unreadOf = (doc: ProseDocument): Unread | undefined => {
|
|
|
78
81
|
return unreadByDocument.get(doc);
|
|
79
82
|
};
|
|
80
83
|
|
|
84
|
+
/** 見出しを読む rule の要求。表題より下の見出しが無い文書では、本題の前を測れない。0 件を「前置きが短い」に見せない。 */
|
|
85
|
+
/** 記法を読む rule の要求(markdown)。.txt には見出しの記法も画像もリンクの記法も無いので、0 件を「問題なし」に見せない。 */
|
|
86
|
+
const DOCUMENT_NEEDS: ReadonlySet<string> = new Set(["headings", "markdown"]);
|
|
87
|
+
|
|
88
|
+
const documentNeed = (rule: RuleDefinition, doc: ProseDocument): string | undefined => {
|
|
89
|
+
if (rule.requires.includes("markdown") && !isMarkdownPath(doc.path)) return reasonsFor(doc).notMarkdown;
|
|
90
|
+
return rule.requires.includes("headings") && bodySectionOf(doc.sections) === undefined ? reasonsFor(doc).noHeadings : undefined;
|
|
91
|
+
};
|
|
92
|
+
|
|
81
93
|
/** 知らない要求は満たされていないものとして扱う。黙って無視すると、要求なしで動いてしまう。 */
|
|
82
94
|
const has = (capabilities: ProseDocument["capabilities"], need: string): boolean => {
|
|
83
95
|
if (need === "pos") return capabilities.pos;
|
|
@@ -97,7 +109,7 @@ const hasTokens = (doc: ProseDocument): boolean => doc.sentences.length === 0 ||
|
|
|
97
109
|
/** 要求を満たさない rule は動かせない。満たさないまま動かすと「指摘 0 件」が保証に見える。 */
|
|
98
110
|
const unmet = (rule: RuleDefinition, doc: ProseDocument): string | undefined => {
|
|
99
111
|
if (rule.languages !== undefined && !rule.languages.includes(doc.language)) return reasonsFor(doc).otherLanguage(doc.language);
|
|
100
|
-
const missing = rule.requires.filter((need) => !TREE_NEEDS.has(need)).find((need) => !has(doc.capabilities, need));
|
|
112
|
+
const missing = rule.requires.filter((need) => !TREE_NEEDS.has(need) && !DOCUMENT_NEEDS.has(need)).find((need) => !has(doc.capabilities, need));
|
|
101
113
|
if (missing !== undefined) return reasonsFor(doc).noCapability(missing);
|
|
102
114
|
return undefined;
|
|
103
115
|
};
|
|
@@ -112,16 +124,36 @@ const untagged = (rule: RuleDefinition, doc: ProseDocument): string | undefined
|
|
|
112
124
|
const forGenre = (rules: readonly RuleDefinition[], genre: string): RuleDefinition[] =>
|
|
113
125
|
rules.filter((rule) => rule.use_for.some((target) => genre.startsWith(target)));
|
|
114
126
|
|
|
127
|
+
/** rule が品詞か見出し語を要求するか、使えるなら使うか。 */
|
|
128
|
+
export const wantsTags = (rule: RuleDefinition): boolean => [...rule.requires, ...rule.uses].some((need) => need === "pos" || need === "lemma");
|
|
129
|
+
|
|
115
130
|
/**
|
|
116
131
|
* 解析器の初期化に払う代金を決める。動く rule が 1 本も要求しないなら読み込まない。
|
|
117
132
|
* capabilities は「払えばできる」の宣言なので、ここでは見ない。
|
|
118
133
|
*/
|
|
119
|
-
export const neededBy = (rules: readonly RuleDefinition[], settings: Settings, experimental: boolean, genre: string, language: string): AdapterNeeds =>
|
|
120
|
-
|
|
134
|
+
export const neededBy = (rules: readonly RuleDefinition[], settings: Settings, experimental: boolean, genre: string, language: string): AdapterNeeds => {
|
|
135
|
+
const running = forGenre(rules, genre)
|
|
121
136
|
.filter((rule) => rule.layer !== "L4" && levelFor(rule, settings, experimental, presetLevels(genre)) !== "off")
|
|
122
|
-
.filter((rule) => rule.languages === undefined || rule.languages.includes(language))
|
|
123
|
-
|
|
124
|
-
}
|
|
137
|
+
.filter((rule) => rule.languages === undefined || rule.languages.includes(language));
|
|
138
|
+
return { pos: running.some(wantsTags), features: tokenFeaturesOf(running) };
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/** The token features the rules read (RuleDefinition.token_features), each once. */
|
|
142
|
+
export const tokenFeaturesOf = (rules: readonly RuleDefinition[]): string[] => [...new Set(rules.flatMap((rule) => rule.token_features ?? []))];
|
|
143
|
+
|
|
144
|
+
/** A detector's findings, or how long it ran before a team's pattern was stopped (bounded-match.ts). Other errors are chaff's bugs and propagate. */
|
|
145
|
+
const runDetector = (
|
|
146
|
+
detector: Detector,
|
|
147
|
+
doc: ProseDocument,
|
|
148
|
+
options: DetectorOptions,
|
|
149
|
+
): { readonly findings: readonly Finding[] } | { readonly timedOut: number } => {
|
|
150
|
+
try {
|
|
151
|
+
return { findings: detector(doc, options) };
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof PatternTimeout) return { timedOut: error.budget_ms };
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
125
157
|
|
|
126
158
|
const place = (starts: readonly number[], finding: Finding): Finding => {
|
|
127
159
|
const offset = finding.values["offset"];
|
|
@@ -157,6 +189,29 @@ export type Limits = Readonly<Record<string, number>>;
|
|
|
157
189
|
|
|
158
190
|
const limitFor = (rule: RuleDefinition, level: Level, genre: string, limits: Limits): number => limits[rule.id] ?? resolve(rule, level, genre).limit;
|
|
159
191
|
|
|
192
|
+
/** 文書と違う言語で書いた文の上限。chaff.yaml の数値は文書の言語の単位で書いたものなので、ここには効かせない。 */
|
|
193
|
+
const embeddedLimitsFor = (rule: RuleDefinition, level: Level, genre: string, embedded: readonly string[]): Record<string, number> =>
|
|
194
|
+
Object.fromEntries(
|
|
195
|
+
embedded.flatMap((language) => {
|
|
196
|
+
const tables = rule.other_languages?.[language];
|
|
197
|
+
return tables === undefined ? [] : [[language, resolve({ ...rule, ...tables }, level, genre).limit] as const];
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const embeddedLanguagesOf = (doc: ProseDocument): string[] => [
|
|
202
|
+
...new Set(doc.sentences.flatMap((sentence) => (sentence.embeddedLanguage === undefined ? [] : [sentence.embeddedLanguage.id]))),
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
/** What a run is set to: the levels chaff.yaml names, whether experimental rules run, the genre, and the numbers and options set. */
|
|
206
|
+
export type RunContext = {
|
|
207
|
+
readonly settings: Settings;
|
|
208
|
+
readonly experimental: boolean;
|
|
209
|
+
readonly genre: string;
|
|
210
|
+
readonly limits?: Limits;
|
|
211
|
+
/** Where rule options come from, strongest first (chaff.yaml). An option no layer sets is at its default. */
|
|
212
|
+
readonly optionLayers?: readonly OptionLayer[];
|
|
213
|
+
};
|
|
214
|
+
|
|
160
215
|
export const runRules = (
|
|
161
216
|
doc: ProseDocument,
|
|
162
217
|
rules: readonly RuleDefinition[],
|
|
@@ -164,10 +219,14 @@ export const runRules = (
|
|
|
164
219
|
experimental: boolean,
|
|
165
220
|
genre: string,
|
|
166
221
|
limits: Limits = {},
|
|
167
|
-
): RunResult => {
|
|
222
|
+
): RunResult => runRulesWith(doc, rules, { settings, experimental, genre, limits });
|
|
223
|
+
|
|
224
|
+
export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[], context: RunContext): RunResult => {
|
|
225
|
+
const { settings, experimental, genre, limits = {}, optionLayers = [] } = context;
|
|
168
226
|
const preset = presetLevels(genre);
|
|
169
227
|
const starts = lineStarts(doc.source);
|
|
170
228
|
const applicable = forGenre(rules, genre);
|
|
229
|
+
const embedded = embeddedLanguagesOf(doc);
|
|
171
230
|
const experimentalOn = applicable.filter((rule) => rule.status === "experimental" && levelFor(rule, settings, experimental, preset) !== "off");
|
|
172
231
|
const forced = experimentalOn.filter((rule) => settings[rule.id] !== undefined).map((rule) => rule.id);
|
|
173
232
|
const presetOn = experimentalOn.filter((rule) => settings[rule.id] === undefined && preset[rule.id] !== undefined).map((rule) => rule.id);
|
|
@@ -188,6 +247,8 @@ export const runRules = (
|
|
|
188
247
|
// 段階を見た後で聞く。doc.structure は触れたときに木を作るので、止めている rule のために作らない。
|
|
189
248
|
const noTree = treeNeed(rule, doc);
|
|
190
249
|
if (noTree !== undefined) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: noTree }] };
|
|
250
|
+
const noDocumentNeed = documentNeed(rule, doc);
|
|
251
|
+
if (noDocumentNeed !== undefined) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: noDocumentNeed }] };
|
|
191
252
|
// 複合シグナルは二段目で扱う。一段目では「検出器が無い」と言わせない。
|
|
192
253
|
if (rule.from.length > 0) return acc;
|
|
193
254
|
const detector = DETECTORS[rule.how_to_find];
|
|
@@ -201,8 +262,14 @@ export const runRules = (
|
|
|
201
262
|
limit: limitFor(rule, level, genre, limits),
|
|
202
263
|
lexicon: rule.word_list === undefined ? undefined : doc.lexicons[rule.word_list],
|
|
203
264
|
where: rule.where,
|
|
265
|
+
fullSentence: rule.full_sentence,
|
|
266
|
+
embeddedLimits: embeddedLimitsFor(rule, level, genre, embedded),
|
|
267
|
+
...(rule.options === undefined ? {} : { settings: optionValues(settleOptions(rule.id, rule.options, optionLayers)) }),
|
|
268
|
+
...(rule.custom === undefined ? {} : { custom: rule.custom }),
|
|
204
269
|
};
|
|
205
|
-
const
|
|
270
|
+
const ran = runDetector(detector, doc, options);
|
|
271
|
+
if ("timedOut" in ran) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: reasonsFor(doc).patternTimeout(ran.timedOut) }] };
|
|
272
|
+
const found = ran.findings.map((finding) => place(starts, { ...finding, rule: rule.id, severity: severityAt(rule, level, genre) }));
|
|
206
273
|
return { findings: [...acc.findings, ...found], skipped: acc.skipped };
|
|
207
274
|
},
|
|
208
275
|
{ findings: [], skipped: [] },
|
package/src/semantic.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { calendarUnitsOf } from "./calendar-number.ts";
|
|
2
|
+
import { closingAndEarlier, newNumbers } from "./closing-numbers.ts";
|
|
1
3
|
import type { ProseDocument, Section } from "./plugin.ts";
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -27,17 +29,23 @@ export const riskDisclosure: Filter = (doc) => {
|
|
|
27
29
|
return [{ text: body.slice(0, 4000), offset: doc.sentences[0]?.span.start ?? 0 }];
|
|
28
30
|
};
|
|
29
31
|
|
|
30
|
-
const EVIDENCE =
|
|
32
|
+
const EVIDENCE = /`|https?:\/\//u;
|
|
33
|
+
|
|
34
|
+
/** 結びに、前に書いていない数があるか。本文の数を繰り返すだけ(「以上のように、9月は…」)なら具体物ではない。 */
|
|
35
|
+
const hasNewNumber = (doc: ProseDocument, last: Section): boolean => {
|
|
36
|
+
const { closing, earlier } = closingAndEarlier(doc, last);
|
|
37
|
+
return newNumbers(closing, earlier, calendarUnitsOf(doc)).length > 0;
|
|
38
|
+
};
|
|
31
39
|
|
|
32
40
|
/**
|
|
33
41
|
* 結びが本文の要約でしかないか。
|
|
34
|
-
*
|
|
42
|
+
* 最後の節だけを見て、そこに具体物(前に書いていない数、コード、リンク)が無いときにだけ問い合わせる。
|
|
35
43
|
*/
|
|
36
44
|
export const emptyConclusion: Filter = (doc) => {
|
|
37
45
|
const last = doc.sections.at(-1);
|
|
38
46
|
if (last === undefined || last.sentences.length === 0) return [];
|
|
39
47
|
const text = sectionText(doc, last);
|
|
40
|
-
if (EVIDENCE.test(text)) return [];
|
|
48
|
+
if (EVIDENCE.test(text) || hasNewNumber(doc, last)) return [];
|
|
41
49
|
return [{ text: text.slice(0, 2000), offset: last.sentences[0]?.span.start ?? last.span.start }];
|
|
42
50
|
};
|
|
43
51
|
|
package/src/sentence-shape.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Sentence, Token } from "./plugin.ts";
|
|
2
|
+
import { ownEnd } from "./trailing-aside.ts";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 「これは文か」の判定を 1 箇所に置く。
|
|
@@ -21,13 +22,11 @@ const SKIP = new Set(["PUNCT", "PART", "SYM"]);
|
|
|
21
22
|
* 「これを最優先制約とする(§17)。」の述語は「とする」であって「17」ではない。
|
|
22
23
|
* 仕様書は相互参照を括弧で添えるので、これを数えると文末が全部そこになる。
|
|
23
24
|
*/
|
|
24
|
-
const TRAILING = /[((][^((]*[))][\s。.!?!?]*$/u;
|
|
25
|
-
|
|
26
25
|
const beforeTrailing = (sentence: Sentence): readonly Token[] => {
|
|
27
26
|
const tokens = sentence.tokens ?? [];
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
const cut = sentence.span.start +
|
|
27
|
+
const end = ownEnd(sentence.text);
|
|
28
|
+
if (end === sentence.text.length) return tokens;
|
|
29
|
+
const cut = sentence.span.start + end;
|
|
31
30
|
const kept = tokens.filter((token) => token.span.end <= cut);
|
|
32
31
|
// 括弧を外したら何も残らない文は、括弧そのものが中身。そのまま見る。
|
|
33
32
|
return kept.length === 0 ? tokens : kept;
|
package/src/setting-problems.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Config } from "./config/load.ts";
|
|
2
2
|
import type { CliText } from "./cli-text.ts";
|
|
3
|
+
import type { UiLanguage } from "./ui.ts";
|
|
4
|
+
import { styleProblems } from "./config/style.ts";
|
|
5
|
+
import { loadStyles } from "./style-load.ts";
|
|
6
|
+
import { customRuleProblems } from "./custom/problems.ts";
|
|
3
7
|
import { GENRES } from "./genre.ts";
|
|
4
8
|
import { unknownGenres, writtenGenres } from "./genre-check.ts";
|
|
5
9
|
import { loadProfiles } from "./profile/load.ts";
|
|
@@ -18,7 +22,9 @@ const profileProblems = (command: string, config: Config, text: CliText): string
|
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
/** Settings that name something chaff does not have. Each would silently check less than was asked, so the run stops on them. */
|
|
21
|
-
export const settingProblems = (command: string, genreFlag: string | undefined, config: Config, text: CliText): string[] => [
|
|
25
|
+
export const settingProblems = (command: string, genreFlag: string | undefined, config: Config, text: CliText, ui: UiLanguage = "en"): string[] => [
|
|
22
26
|
...genreProblems(command, genreFlag, config, text),
|
|
23
27
|
...profileProblems(command, config, text),
|
|
28
|
+
...styleProblems(config, loadStyles(), ui),
|
|
29
|
+
...customRuleProblems(config, ui),
|
|
24
30
|
];
|
package/src/span-cut.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Span } from "./plugin.ts";
|
|
2
|
+
import { mergeSpans } from "./span-merge.ts";
|
|
3
|
+
import { firstEndingAfter } from "./soft-break.ts";
|
|
4
|
+
|
|
5
|
+
const piecesOutside = (span: Span, sortedCuts: readonly Span[]): Span[] => {
|
|
6
|
+
const overlapping = sortedCuts
|
|
7
|
+
.slice(firstEndingAfter(sortedCuts, span.start), firstEndingAfter(sortedCuts, span.end) + 1)
|
|
8
|
+
.filter((cut) => cut.start < span.end);
|
|
9
|
+
const { pieces, cursor } = overlapping.reduce<{ pieces: Span[]; cursor: number }>(
|
|
10
|
+
(acc, cut) => ({
|
|
11
|
+
pieces: cut.start > acc.cursor ? [...acc.pieces, { start: acc.cursor, end: cut.start }] : acc.pieces,
|
|
12
|
+
cursor: Math.max(acc.cursor, cut.end),
|
|
13
|
+
}),
|
|
14
|
+
{ pieces: [], cursor: span.start },
|
|
15
|
+
);
|
|
16
|
+
return cursor < span.end ? [...pieces, { start: cursor, end: span.end }] : pieces;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** The parts of each span that no cut covers, in order. Cuts may overlap one another and come in any order. */
|
|
20
|
+
export const cutSpans = (spans: readonly Span[], cuts: readonly Span[]): Span[] => {
|
|
21
|
+
if (cuts.length === 0) return [...spans];
|
|
22
|
+
const sortedCuts = mergeSpans(cuts, true);
|
|
23
|
+
return spans.flatMap((span) => piecesOutside(span, sortedCuts));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** cutSpans, less the pieces of `source` that hold only white space. */
|
|
27
|
+
export const cutTextSpans = (spans: readonly Span[], cuts: readonly Span[], source: string): Span[] =>
|
|
28
|
+
cuts.length === 0 ? [...spans] : cutSpans(spans, cuts).filter((piece) => source.slice(piece.start, piece.end).trim() !== "");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Span } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
/** 重なる範囲を 1 つにまとめ、始まりの順に並べる。joinTouching なら、接するだけの範囲(前の end が次の start)もまとめる。 */
|
|
4
|
+
export const mergeSpans = (spans: readonly Span[], joinTouching: boolean): Span[] =>
|
|
5
|
+
spans
|
|
6
|
+
.toSorted((left, right) => left.start - right.start)
|
|
7
|
+
.reduce<Span[]>((acc, span) => {
|
|
8
|
+
const last = acc.at(-1);
|
|
9
|
+
if (last !== undefined && (joinTouching ? span.start <= last.end : span.start < last.end))
|
|
10
|
+
acc[acc.length - 1] = { start: last.start, end: Math.max(last.end, span.end) };
|
|
11
|
+
else acc.push(span);
|
|
12
|
+
return acc;
|
|
13
|
+
}, []);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Span } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 戯曲・台本・議事録・書き起こしの、話し手の名前(`ALGERNON.`、行頭の `夫` と全角空白、`○事務局`)。
|
|
5
|
+
* 名前は誰が話すかの印であって本文ではない。文として数えると、名前だけの文が増え、名前が固有名詞と言い回しの繰り返しに入る。
|
|
6
|
+
*
|
|
7
|
+
* 形だけで決める。同じ形の行頭の名前が、MIN_SPEAKERS 人以上それぞれ MIN_TURNS 回以上繰り返され、どれも後に発言が続き、
|
|
8
|
+
* その形の行が文書の段落の多くを始める。1 つの名前の繰り返しは見出し(○ と全角空白の後の「注意事項」)、
|
|
9
|
+
* 繰り返されない名前は偶然、ときどき出るだけの `NOTE:` `WARNING:` は注記なので、話し手と読まない。
|
|
10
|
+
* そう読めた形では、1 度しか話さない人の名前も話し手の名前とする(議事録の委員)。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** 話し手と読むのに要る、繰り返す名前の数。 */
|
|
14
|
+
const MIN_SPEAKERS = 2;
|
|
15
|
+
/** 名前が繰り返されたと読む回数。 */
|
|
16
|
+
const MIN_TURNS = 3;
|
|
17
|
+
/** 対話と読むのに要る、その形の行の数。数回の注記(NOTE: と WARNING:)は対話ではない。 */
|
|
18
|
+
const MIN_DIALOGUE_TURNS = 10;
|
|
19
|
+
/** その形の行が始める段落の割合の下限。会議録は長い発言が何段落も続くので、戯曲より低い。 */
|
|
20
|
+
const MIN_TURN_SHARE = 0.1;
|
|
21
|
+
|
|
22
|
+
type Candidate = { readonly shape: string; readonly name: string; readonly span: Span };
|
|
23
|
+
|
|
24
|
+
/** 名前の後の発言が、同じ行にあるか(inline)、次の行にあるか(alone)。 */
|
|
25
|
+
type Shape = { readonly id: string; readonly pattern: RegExp; readonly alone: boolean };
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 英語の名前は大文字で書いたものだけ(ALGERNON、LADY BRACKNELL、Mr. SMITH)。
|
|
29
|
+
* 大文字小文字まじりの「Title:」「Notes:」「Content-Type:」は、記録や表の項目の名前と形が同じで、見分けられない。
|
|
30
|
+
*/
|
|
31
|
+
const CAPS_WORD = String.raw`[A-Z][A-Z'’&-]*\.?`;
|
|
32
|
+
const CAPS_NAME = String.raw`(?:[A-Z][a-z]{1,3}\. )?${CAPS_WORD}(?: ${CAPS_WORD}){0,3}`;
|
|
33
|
+
/** 日本語の名前に入らない文字。空白、括弧、句読点、かぎ括弧、コロン。 */
|
|
34
|
+
const JA_NAME = String.raw`[^\s\u3000()()、。,.「」『』::]`;
|
|
35
|
+
|
|
36
|
+
/** 各 pattern の 1 番目の組が行頭の空白、2 番目が覆う範囲、`name` の組が名前。 */
|
|
37
|
+
const SHAPES: readonly Shape[] = [
|
|
38
|
+
{ id: "caps", pattern: new RegExp(String.raw`^(\s*)((?<name>${CAPS_NAME})[.:]?)\s*$`, "u"), alone: true },
|
|
39
|
+
{ id: "caps", pattern: new RegExp(String.raw`^(\s*)((?<name>${CAPS_NAME})[.:])\s+\S`, "u"), alone: false },
|
|
40
|
+
{ id: "mark", pattern: new RegExp(String.raw`^([ \t\u3000]*)([○◯〇](?<name>${JA_NAME}{1,20})(?:([^)\n]*))?)[ \t\u3000]*$`, "u"), alone: true },
|
|
41
|
+
{ id: "mark", pattern: new RegExp(String.raw`^([ \t\u3000]*)([○◯〇](?<name>${JA_NAME}{1,20})(?:([^)\n]*))?\u3000+)\S`, "u"), alone: false },
|
|
42
|
+
{ id: "spaced", pattern: new RegExp(String.raw`^([ \t]*)((?<name>${JA_NAME}{1,10})\u3000+)\S`, "u"), alone: false },
|
|
43
|
+
{ id: "quote", pattern: new RegExp(String.raw`^([ \t]*)((?<name>${JA_NAME}{1,10}))[ \t]*「`, "u"), alone: false },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 名前でないもの。番号(数字・漢数字・ローマ数字・「第」で始まる序数・1 字の仮名)は見出しや項目の印で、話し手ではない。
|
|
48
|
+
* 助詞で終わる語は地の文の主語(「私は「…」」)。英字 1 字は、名前より略語や項目の印が多い。
|
|
49
|
+
*/
|
|
50
|
+
const NUMERAL = /^[\d0-9一二三四五六七八九十百千〇IVXLCDM]+(?:の[\d0-9一二三四五六七八九十百千〇]+)*$/u;
|
|
51
|
+
const ORDINAL = /^第[\d0-9一二三四五六七八九十百千〇]/u;
|
|
52
|
+
const DIGIT = /[\d0-9]/u;
|
|
53
|
+
const SINGLE_KANA = /^[\p{Script=Hiragana}\p{Script=Katakana}]$/u;
|
|
54
|
+
const LETTER = /\p{L}/u;
|
|
55
|
+
const PARTICLE_END = /[はがもをにへとでやの]$/u;
|
|
56
|
+
|
|
57
|
+
const isName = (shape: string, name: string): boolean =>
|
|
58
|
+
LETTER.test(name) &&
|
|
59
|
+
!NUMERAL.test(name.replace(/[\s.'’&-]/gu, "")) &&
|
|
60
|
+
!ORDINAL.test(name) &&
|
|
61
|
+
!DIGIT.test(name) &&
|
|
62
|
+
!SINGLE_KANA.test(name) &&
|
|
63
|
+
!(shape === "quote" && PARTICLE_END.test(name)) &&
|
|
64
|
+
!(shape === "caps" && name.replace(/[^A-Z]/gu, "").length < 2);
|
|
65
|
+
|
|
66
|
+
type Line = { readonly start: number; readonly text: string };
|
|
67
|
+
|
|
68
|
+
const linesOf = (text: string): Line[] => {
|
|
69
|
+
const scan = { start: 0 };
|
|
70
|
+
return text.split("\n").map((raw) => {
|
|
71
|
+
const line = { start: scan.start, text: raw.replace(/\r$/u, "") };
|
|
72
|
+
scan.start += raw.length + 1;
|
|
73
|
+
return line;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const isBlank = (line: Line | undefined): boolean => line === undefined || line.text.trim() === "";
|
|
78
|
+
|
|
79
|
+
/** 名前だけの行は、次の行に発言があるときだけ話し手の名前(空行の後の大文字の行は見出し)。 */
|
|
80
|
+
const candidateOf = (lines: readonly Line[], index: number): Candidate | undefined => {
|
|
81
|
+
const line = lines[index];
|
|
82
|
+
if (line === undefined) return undefined;
|
|
83
|
+
return SHAPES.flatMap((shape) => {
|
|
84
|
+
const match = shape.pattern.exec(line.text);
|
|
85
|
+
const lead = match?.[1];
|
|
86
|
+
const label = match?.[2];
|
|
87
|
+
const name = match?.groups?.["name"]?.replace(/[.:]$/u, "");
|
|
88
|
+
if (lead === undefined || label === undefined || name === undefined || !isName(shape.id, name)) return [];
|
|
89
|
+
if (shape.alone && isBlank(lines[index + 1])) return [];
|
|
90
|
+
const start = line.start + lead.length;
|
|
91
|
+
return [{ shape: shape.id, name, span: { start, end: start + label.length } }];
|
|
92
|
+
})[0];
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const countBy = <T>(items: readonly T[], keyOf: (item: T) => string): Map<string, number> =>
|
|
96
|
+
items.reduce((counts, item) => counts.set(keyOf(item), (counts.get(keyOf(item)) ?? 0) + 1), new Map<string, number>());
|
|
97
|
+
|
|
98
|
+
const speakerKey = (candidate: Candidate): string => `${candidate.shape}\n${candidate.name}`;
|
|
99
|
+
|
|
100
|
+
/** 形ごとに、MIN_TURNS 回以上出る名前が MIN_SPEAKERS 人以上いるか。 */
|
|
101
|
+
const speakerShapes = (candidates: readonly Candidate[]): Set<string> => {
|
|
102
|
+
const turns = countBy(candidates, speakerKey);
|
|
103
|
+
const speakers = [...new Map(candidates.map((candidate) => [speakerKey(candidate), candidate])).values()];
|
|
104
|
+
const repeated = speakers.filter((speaker) => (turns.get(speakerKey(speaker)) ?? 0) >= MIN_TURNS);
|
|
105
|
+
const perShape = countBy(repeated, (speaker) => speaker.shape);
|
|
106
|
+
return new Set([...perShape].filter(([, count]) => count >= MIN_SPEAKERS).map(([shape]) => shape));
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** 空行の後から始まる、空でない行のまとまり(段落)の数。 */
|
|
110
|
+
const paragraphCount = (lines: readonly Line[]): number => lines.filter((line, index) => !isBlank(line) && (index === 0 || isBlank(lines[index - 1]))).length;
|
|
111
|
+
|
|
112
|
+
/** 話し手の形のうち、その形の行が MIN_DIALOGUE_TURNS 以上あり、段落の MIN_TURN_SHARE 以上を始めるもの。 */
|
|
113
|
+
const dialogueShapes = (candidates: readonly Candidate[], paragraphs: number): Set<string> => {
|
|
114
|
+
const turns = countBy(candidates, (candidate) => candidate.shape);
|
|
115
|
+
return new Set(
|
|
116
|
+
[...speakerShapes(candidates)].filter((shape) => {
|
|
117
|
+
const count = turns.get(shape) ?? 0;
|
|
118
|
+
return count >= MIN_DIALOGUE_TURNS && count >= paragraphs * MIN_TURN_SHARE;
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** text の中の話し手の名前の範囲。発言は含まない。 */
|
|
124
|
+
export const speakerLabels = (text: string): Span[] => {
|
|
125
|
+
const lines = linesOf(text);
|
|
126
|
+
const candidates = lines.flatMap((_, index) => candidateOf(lines, index) ?? []);
|
|
127
|
+
const shapes = dialogueShapes(candidates, paragraphCount(lines));
|
|
128
|
+
return candidates.filter((candidate) => shapes.has(candidate.shape)).map((candidate) => candidate.span);
|
|
129
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// 日本語の語と語のあいだの空白。どの境目を数えるかを品詞で決める。
|
|
2
|
+
import type { Sentence, Span, Token } from "./plugin.ts";
|
|
3
|
+
import { isJapanese } from "./orthography.ts";
|
|
4
|
+
import { isWithinAny, quotedIn } from "./quoted-span.ts";
|
|
5
|
+
|
|
6
|
+
/** between-phrases は助詞の後ろ(文節の切れ目)、inside-phrase は文節を始められない語の前(助詞・助動詞・名詞に続く「する」)。 */
|
|
7
|
+
export type JointKind = "between-phrases" | "inside-phrase";
|
|
8
|
+
|
|
9
|
+
/** offset は前の語の終わり(文書の座標)。before / after は境目の両側の語。 */
|
|
10
|
+
export type Joint = { readonly offset: number; readonly kind: JointKind; readonly spaced: boolean; readonly before: string; readonly after: string };
|
|
11
|
+
|
|
12
|
+
const SPACES = /^[ \u3000]+$/u;
|
|
13
|
+
const PARTICLE = new Set(["ADP", "SCONJ"]);
|
|
14
|
+
// 文節の頭に立てない語。「確認 しました」の「する」は名詞の後ろのときだけ(「し始める」の「し」は動詞の頭に立つ)。
|
|
15
|
+
const BOUND = new Set(["ADP", "SCONJ", "PART", "AUX"]);
|
|
16
|
+
const LIGHT_VERB = "する";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 空白の後ろの「が」を、解析器は文頭の接続詞(「が、」)と読む。一字の接続詞(が・と・や・か)は助詞として扱う。
|
|
20
|
+
* 二字以上(また・なお)は文節を始める接続詞。
|
|
21
|
+
*/
|
|
22
|
+
const isBound = (token: Token): boolean => BOUND.has(token.pos) || (token.pos === "CCONJ" && [...token.surface].length === 1);
|
|
23
|
+
|
|
24
|
+
const kindOf = (left: Token, right: Token): JointKind | undefined => {
|
|
25
|
+
if (isBound(right) || (right.lemma === LIGHT_VERB && left.pos === "NOUN")) return "inside-phrase";
|
|
26
|
+
// 名詞どうし(担当 田中、赤坂 文弥、フルデスクトップ モード)は名札・名前・複合語の書き方で、数えない。
|
|
27
|
+
return PARTICLE.has(left.pos) ? "between-phrases" : undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 行(か文)の頭の語か。助詞は前の語に付くので、行頭の「助詞」(「ヘ」)は項目の記号を読み違えたもので、後ろの空白は記号と本文の区切り。
|
|
32
|
+
* 行頭の内容語(折り返した「確認 しました」の「確認」)は語句の頭なので、ここでは外さない。
|
|
33
|
+
*/
|
|
34
|
+
const isLineHead = (text: string, at: number): boolean => text.slice(text.lastIndexOf("\n", at - 1) + 1, at).trim() === "";
|
|
35
|
+
|
|
36
|
+
const isWord = (token: Token): boolean => token.surface.trim() !== "";
|
|
37
|
+
|
|
38
|
+
type Pair = { readonly left: Token; readonly right: Token };
|
|
39
|
+
|
|
40
|
+
const pairsOf = (tokens: readonly Token[]): Pair[] =>
|
|
41
|
+
tokens.filter(isWord).flatMap((right, index, words) => {
|
|
42
|
+
const left = words[index - 1];
|
|
43
|
+
return left === undefined ? [] : [{ left, right }];
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// 強調とリンクの括弧。読み手には見えない。
|
|
47
|
+
const CHROME = /[*_~[\]]/gu;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 空けたか詰めたか。間が何も無いか強調・リンクの括弧だけなら詰めた、書き手が書いた空白(半角・全角)だけなら空けた。
|
|
51
|
+
* 括弧の隣の空白(「**…こと** とする」「手順は [README]」)は、日本語の隣で強調が効かない Markdown のための空白なので数えない。
|
|
52
|
+
* 改行(Markdown の改行や、行の折り返し)や、見える字を覆った空白(コード)をまたぐ語も、境目に数えない。
|
|
53
|
+
*/
|
|
54
|
+
const spacing = (sentence: Sentence, written: string, pair: Pair): boolean | undefined => {
|
|
55
|
+
const [from, to] = [pair.left.span.end - sentence.span.start, pair.right.span.start - sentence.span.start];
|
|
56
|
+
const gap = written.slice(from, to);
|
|
57
|
+
if (gap.replace(CHROME, "") === "") return false;
|
|
58
|
+
return SPACES.test(gap) ? true : undefined;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const jointOf = (sentence: Sentence, written: string, quoted: readonly Span[], pair: Pair): Joint | undefined => {
|
|
62
|
+
const { left, right } = pair;
|
|
63
|
+
if (!isJapanese(left.surface.at(-1)) || !isJapanese(right.surface.at(0))) return undefined;
|
|
64
|
+
const spaced = spacing(sentence, written, pair);
|
|
65
|
+
if (spaced === undefined || isWithinAny(quoted, { start: left.span.start, end: right.span.end })) return undefined;
|
|
66
|
+
const kind = kindOf(left, right);
|
|
67
|
+
if (kind === undefined || (kind === "between-phrases" && isLineHead(sentence.text, left.span.start - sentence.span.start))) return undefined;
|
|
68
|
+
return { offset: left.span.end, kind, spaced, before: left.surface, after: right.surface };
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 文の中の、日本語の語と語の境目のうち、空けるか詰めるかを数えるもの。written は本文でないものを覆う前の、文と同じ範囲。
|
|
73
|
+
* 英字・数字との境目は latin-spacing が見るので入れない。
|
|
74
|
+
*/
|
|
75
|
+
export const phraseJoints = (sentence: Sentence, written: string): Joint[] => {
|
|
76
|
+
const quoted = quotedIn(sentence);
|
|
77
|
+
return pairsOf(sentence.tokens ?? []).flatMap((pair) => {
|
|
78
|
+
const joint = jointOf(sentence, written, quoted, pair);
|
|
79
|
+
return joint === undefined ? [] : [joint];
|
|
80
|
+
});
|
|
81
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { RelativeVocabulary } from "../plugin.ts";
|
|
2
|
+
|
|
3
|
+
type Aside = RelativeVocabulary["aside"];
|
|
4
|
+
|
|
5
|
+
/** 文字と、その位置(UTF-16 の単位で)。絵文字のような 2 単位の文字も 1 文字として読む。 */
|
|
6
|
+
export const characters = (text: string): { readonly char: string; readonly at: number }[] => {
|
|
7
|
+
const found: { char: string; at: number }[] = [];
|
|
8
|
+
let at = 0;
|
|
9
|
+
for (const char of text) {
|
|
10
|
+
found.push({ char, at });
|
|
11
|
+
at += char.length;
|
|
12
|
+
}
|
|
13
|
+
return found;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** at の位置で開いたままの括弧書きの開きの位置。text の頭から at まで読む。 */
|
|
17
|
+
export const openAsidesAt = (text: string, at: number, aside: Aside): number[] => {
|
|
18
|
+
const opens: number[] = [];
|
|
19
|
+
if (aside === undefined) return opens;
|
|
20
|
+
characters(text.slice(0, at)).forEach(({ char, at: position }) => {
|
|
21
|
+
if (char === aside.open) opens.push(position);
|
|
22
|
+
if (char === aside.close) opens.pop();
|
|
23
|
+
});
|
|
24
|
+
return opens;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** at で開いたままの括弧書きの数(depth)と、一番内側の開きの位置(innermost)。 */
|
|
28
|
+
export type AsideDepth = { readonly depth: (at: number) => number; readonly innermost: (at: number) => number | undefined };
|
|
29
|
+
|
|
30
|
+
/** 文字の切れ目でない位置(2 単位の文字の途中)の印。 */
|
|
31
|
+
const UNREAD = -2;
|
|
32
|
+
const NO_OPEN = -1;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 本文を一度だけ読み、文字の切れ目ごとに openAsidesAt の答えを覚える。参照ごとに頭から読み直すと、参照の数と行の長さの積になる。
|
|
36
|
+
* 覚えていない位置(2 単位の文字の途中)は openAsidesAt で読む。
|
|
37
|
+
*/
|
|
38
|
+
export const asideDepth = (text: string, aside: Aside): AsideDepth => {
|
|
39
|
+
if (aside === undefined) return { depth: () => 0, innermost: () => undefined };
|
|
40
|
+
const depths = new Int32Array(text.length + 1).fill(UNREAD);
|
|
41
|
+
const innermosts = new Int32Array(text.length + 1).fill(UNREAD);
|
|
42
|
+
const opens: number[] = [];
|
|
43
|
+
depths[0] = 0;
|
|
44
|
+
innermosts[0] = NO_OPEN;
|
|
45
|
+
characters(text).forEach(({ char, at }) => {
|
|
46
|
+
if (char === aside.open) opens.push(at);
|
|
47
|
+
if (char === aside.close) opens.pop();
|
|
48
|
+
depths[at + char.length] = opens.length;
|
|
49
|
+
innermosts[at + char.length] = opens.at(-1) ?? NO_OPEN;
|
|
50
|
+
});
|
|
51
|
+
// text.slice(0, at) が切る位置。負の数は後ろから数え、本文の外は端に寄せる。文字の途中なら覚えていない。
|
|
52
|
+
const cut = (at: number): number => {
|
|
53
|
+
const whole = Math.trunc(Number.isNaN(at) ? 0 : at);
|
|
54
|
+
return whole < 0 ? Math.max(text.length + whole, 0) : Math.min(whole, text.length);
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
depth: (at) => {
|
|
58
|
+
const depth = depths[cut(at)] ?? UNREAD;
|
|
59
|
+
return depth === UNREAD ? openAsidesAt(text, at, aside).length : depth;
|
|
60
|
+
},
|
|
61
|
+
innermost: (at) => {
|
|
62
|
+
const open = innermosts[cut(at)] ?? UNREAD;
|
|
63
|
+
if (open === UNREAD) return openAsidesAt(text, at, aside).at(-1);
|
|
64
|
+
return open === NO_OPEN ? undefined : open;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
};
|