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,135 @@
|
|
|
1
|
+
import type { Localized } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
/** How the rule reference groups rules for a reader who is not an engineer, in the order it lists them. */
|
|
4
|
+
export const RULE_GROUPS = ["readability", "wording", "slips", "consistency", "structure", "facts", "ai-tells", "team"] as const;
|
|
5
|
+
|
|
6
|
+
export type RuleGroup = (typeof RULE_GROUPS)[number];
|
|
7
|
+
|
|
8
|
+
/** A group's name and one line on what is in it, as the reference and chaff rules show them. */
|
|
9
|
+
export type GroupText = { readonly name: string; readonly note: string };
|
|
10
|
+
|
|
11
|
+
const GROUP_TEXT: Readonly<Record<"ja" | "en", Readonly<Record<RuleGroup, GroupText>>>> = {
|
|
12
|
+
ja: {
|
|
13
|
+
readability: { name: "読みやすさ", note: "長すぎる文、詰めすぎた段落、読み手がつまずく書き方。" },
|
|
14
|
+
wording: { name: "言葉づかい", note: "中身を言わずに強める言い方、決まり文句、誰がしたのかを書かない受け身。" },
|
|
15
|
+
slips: { name: "書き損じ", note: "書き換えの途中で残った語や空白。" },
|
|
16
|
+
consistency: {
|
|
17
|
+
name: "表記の揃え",
|
|
18
|
+
note: "どちらで書いても正しいものが、一つの文書の中で混ざっている所。chaff はどちらが正しいかを決めず、少ないほうを指します。",
|
|
19
|
+
},
|
|
20
|
+
structure: { name: "構造", note: "番号の抜け、無い条への参照、同じ語の二重定義、長い前置き。" },
|
|
21
|
+
facts: { name: "事実の食い違い", note: "日付と曜日、日付の順番、合計と内訳のように、暦や計算で確かめられる食い違い。" },
|
|
22
|
+
"ai-tells": {
|
|
23
|
+
name: "AIっぽさ",
|
|
24
|
+
note: "生成された文章にありがちな特徴。どれも、それだけで生成されたとは言いません。読み返す場所の目印です。",
|
|
25
|
+
},
|
|
26
|
+
team: {
|
|
27
|
+
name: "チームの表記",
|
|
28
|
+
note: "chaff.yaml にチームが書いた表記・社内用語・必須の見出しだけを見るルール。書かなければ何も言いません。",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
en: {
|
|
32
|
+
readability: { name: "Readability", note: "Sentences that run too long, packed paragraphs, and other places a reader stumbles." },
|
|
33
|
+
wording: { name: "Wording", note: "Emphasis that says nothing, stock phrases, and passives that never say who acted." },
|
|
34
|
+
slips: { name: "Slips", note: "Words and spaces left over from an edit." },
|
|
35
|
+
consistency: {
|
|
36
|
+
name: "Consistency",
|
|
37
|
+
note: "Two ways of writing that are both right, mixed in one document. chaff does not pick a side; it points at whichever the document uses less.",
|
|
38
|
+
},
|
|
39
|
+
structure: {
|
|
40
|
+
name: "Structure",
|
|
41
|
+
note: "Skipped numbers, references to provisions that are not there, terms defined twice, long preambles.",
|
|
42
|
+
},
|
|
43
|
+
facts: {
|
|
44
|
+
name: "Facts that disagree",
|
|
45
|
+
note: "A date and its weekday, dates out of order, a total and its items: disagreements a calendar or a sum can settle.",
|
|
46
|
+
},
|
|
47
|
+
"ai-tells": {
|
|
48
|
+
name: "Signs of generated text",
|
|
49
|
+
note: "Traits common in generated text. None of them alone says the text was generated; they mark places to reread.",
|
|
50
|
+
},
|
|
51
|
+
team: {
|
|
52
|
+
name: "Your team's words",
|
|
53
|
+
note: "Rules that check only what your team lists in chaff.yaml: spellings, jargon, required headings. With nothing listed, they say nothing.",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** In Japanese for "ja", in English for any other language. */
|
|
59
|
+
export const groupTextOf = (language: string, group: RuleGroup): GroupText => GROUP_TEXT[language === "ja" ? "ja" : "en"][group];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A short text the rule flags and the same text fixed, with the chaff.yaml it needs (jargon, prefer, a level).
|
|
63
|
+
* pad: the rule measures a whole document of some length (per 1000 words), so the example is tried after an ordinary passage.
|
|
64
|
+
*/
|
|
65
|
+
export type RuleExample = {
|
|
66
|
+
readonly before: string;
|
|
67
|
+
readonly after: string;
|
|
68
|
+
readonly config?: Readonly<Record<string, unknown>>;
|
|
69
|
+
readonly pad?: boolean;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/** One finding of the rule itself on its example, as the command line reported it. */
|
|
73
|
+
export type ExampleFinding = { readonly line: number; readonly column: number; readonly message: string };
|
|
74
|
+
|
|
75
|
+
/** What the command line said about a rule on its example, before and after the fix (scripts/rule-examples.ts). */
|
|
76
|
+
export type ExampleOutcome = {
|
|
77
|
+
readonly rule: string;
|
|
78
|
+
readonly language: string;
|
|
79
|
+
readonly before: readonly ExampleFinding[];
|
|
80
|
+
readonly after: readonly ExampleFinding[];
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** The plain-language part of a rule file: what the reference tells a reader, apart from the texts chaff prints. */
|
|
84
|
+
export type RuleGuide = {
|
|
85
|
+
readonly group: RuleGroup | undefined;
|
|
86
|
+
/** What the rule finds, in one line. */
|
|
87
|
+
readonly summary: Localized;
|
|
88
|
+
/** By language. A rule that runs in one language has an example in that language only. */
|
|
89
|
+
readonly examples: Readonly<Record<string, RuleExample>>;
|
|
90
|
+
/** What the rule leaves alone on purpose, so a reader does not take silence for a miss. */
|
|
91
|
+
readonly notFlagged: Localized;
|
|
92
|
+
/** What a level's number means, with {limit} for the number ("一文 {limit} 字まで"). None when every level is the same. */
|
|
93
|
+
readonly levelMeaning: Localized;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
97
|
+
|
|
98
|
+
const isText = (value: unknown): value is string => typeof value === "string" && value.trim() !== "";
|
|
99
|
+
|
|
100
|
+
const localizedOf = (value: unknown): Localized =>
|
|
101
|
+
isRecord(value) ? Object.fromEntries(Object.entries(value).filter((entry): entry is [string, string] => isText(entry[1]))) : {};
|
|
102
|
+
|
|
103
|
+
const exampleOf = (value: unknown): RuleExample | undefined => {
|
|
104
|
+
if (!isRecord(value) || !isText(value["before"]) || !isText(value["after"])) return undefined;
|
|
105
|
+
const config = value["config"];
|
|
106
|
+
return {
|
|
107
|
+
before: value["before"],
|
|
108
|
+
after: value["after"],
|
|
109
|
+
...(isRecord(config) ? { config } : {}),
|
|
110
|
+
...(value["pad"] === true ? { pad: true } : {}),
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const examplesOf = (value: unknown): Readonly<Record<string, RuleExample>> =>
|
|
115
|
+
isRecord(value)
|
|
116
|
+
? Object.fromEntries(
|
|
117
|
+
Object.entries(value).flatMap(([language, entry]) => {
|
|
118
|
+
const example = exampleOf(entry);
|
|
119
|
+
return example === undefined ? [] : [[language, example] as const];
|
|
120
|
+
}),
|
|
121
|
+
)
|
|
122
|
+
: {};
|
|
123
|
+
|
|
124
|
+
/** A field that is missing or malformed reads as empty; the test on rule files names what a rule lacks. */
|
|
125
|
+
export const ruleGuideOf = (raw: Readonly<Record<string, unknown>>): RuleGuide => ({
|
|
126
|
+
group: RULE_GROUPS.find((group) => group === raw["group"]),
|
|
127
|
+
summary: localizedOf(raw["summary"]),
|
|
128
|
+
examples: examplesOf(raw["example"]),
|
|
129
|
+
notFlagged: localizedOf(raw["not_flagged"]),
|
|
130
|
+
levelMeaning: localizedOf(raw["level_meaning"]),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/** The rules in each group, in the order the reference lists them. A rule with no group is in none, which the test on rule files reports. */
|
|
134
|
+
export const rulesByGroup = <T>(rules: readonly T[], groupOf: (rule: T) => RuleGroup | undefined): { group: RuleGroup; rules: T[] }[] =>
|
|
135
|
+
RULE_GROUPS.map((group) => ({ group, rules: rules.filter((rule) => groupOf(rule) === group) }));
|
package/src/rule-load.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { readFileSync, readdirSync } from "node:fs";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
|
-
import type { LevelTable, RuleDefinition, Severity } from "./plugin.ts";
|
|
5
|
+
import type { LanguageLevels, LevelSets, LevelTable, RuleDefinition, Severity } from "./plugin.ts";
|
|
6
|
+
import { rankOfSeverity, severityAt } from "./levels.ts";
|
|
7
|
+
import { optionsOf } from "./rule-options.ts";
|
|
8
|
+
import { ruleGuideOf } from "./rule-guide.ts";
|
|
6
9
|
|
|
7
10
|
const RULES_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "rules");
|
|
8
11
|
|
|
@@ -10,13 +13,8 @@ const isRecord = (value: unknown): value is Record<string, unknown> => typeof va
|
|
|
10
13
|
|
|
11
14
|
const isLocalized = (value: unknown): value is Record<string, string> => isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/** L4 は件数ではなく深刻度を段で持つ。error/warning/info を数に写して同じ器に入れる。 */
|
|
16
|
-
const asNumber = (entry: unknown): number | undefined => {
|
|
17
|
-
if (typeof entry === "number") return entry;
|
|
18
|
-
return typeof entry === "string" ? SEVERITY_BY_NAME[entry] : undefined;
|
|
19
|
-
};
|
|
16
|
+
/** 数えるものの無い rule(L4、番号の抜け)は件数ではなく重さを段で持つ。error/warning/info を数に写して同じ器に入れる。 */
|
|
17
|
+
const asNumber = (entry: unknown): number | undefined => (typeof entry === "number" ? entry : rankOfSeverity(entry));
|
|
20
18
|
|
|
21
19
|
const isLevelTable = (value: unknown): value is LevelTable =>
|
|
22
20
|
isRecord(value) && Object.entries(value).every(([key, entry]) => ["strict", "normal", "relaxed"].includes(key) && asNumber(entry) !== undefined);
|
|
@@ -41,6 +39,20 @@ const genreTables = (raw: unknown, language: string): Readonly<Record<string, Le
|
|
|
41
39
|
return Object.fromEntries(entries);
|
|
42
40
|
};
|
|
43
41
|
|
|
42
|
+
/** levels を言語別に書いた rule の、loaded 以外の言語の段。言語で分けていない rule は空。 */
|
|
43
|
+
const otherLanguages = (raw: Record<string, unknown>, loaded: string): Record<string, LanguageLevels> => {
|
|
44
|
+
const levels = raw["levels"];
|
|
45
|
+
if (!isRecord(levels) || isLevelTable(levels)) return {};
|
|
46
|
+
return Object.fromEntries(
|
|
47
|
+
Object.keys(levels)
|
|
48
|
+
.filter((language) => language !== loaded && language !== "default")
|
|
49
|
+
.flatMap((language) => {
|
|
50
|
+
const table = flattenLevels(levels, language);
|
|
51
|
+
return table === undefined ? [] : [[language, { levels: table, by_genre: genreTables(raw["by_genre"], language) }] as const];
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
44
56
|
const SEVERITIES: readonly Severity[] = ["error", "warning", "info"];
|
|
45
57
|
const isSeverity = (value: unknown): value is Severity => SEVERITIES.some((entry) => entry === value);
|
|
46
58
|
|
|
@@ -68,8 +80,8 @@ const missingFields = (raw: Record<string, unknown>, levels: LevelTable | undefi
|
|
|
68
80
|
|
|
69
81
|
const localizedOf = (value: unknown): Record<string, string> => (isLocalized(value) ? value : {});
|
|
70
82
|
|
|
71
|
-
/** 見つけ方ごとの message
|
|
72
|
-
const
|
|
83
|
+
/** 見つけ方ごとの message、置き場所ごとの読みかた。読めないものは捨てる。 */
|
|
84
|
+
const localizedByKey = (value: unknown): Record<string, Record<string, string>> =>
|
|
73
85
|
isRecord(value) ? Object.fromEntries(Object.entries(value).flatMap(([variant, text]) => (isLocalized(text) ? [[variant, text]] : []))) : {};
|
|
74
86
|
|
|
75
87
|
/**
|
|
@@ -83,39 +95,92 @@ const severityOf = (raw: unknown, language: string): Severity => {
|
|
|
83
95
|
return isSeverity(picked) ? picked : "warning";
|
|
84
96
|
};
|
|
85
97
|
|
|
98
|
+
/** 言語で単位が違う数(日本語は文字、英語は語)。その言語のぶんだけを取る。無い言語では undefined。 */
|
|
99
|
+
const numberFor = (raw: unknown, language: string): number | undefined => {
|
|
100
|
+
if (typeof raw === "number") return raw;
|
|
101
|
+
const picked: unknown = isRecord(raw) ? (raw[language] ?? raw["default"]) : undefined;
|
|
102
|
+
return typeof picked === "number" ? picked : undefined;
|
|
103
|
+
};
|
|
104
|
+
|
|
86
105
|
const stringList = (value: unknown): string[] | undefined => (Array.isArray(value) ? value.map((entry) => String(entry)) : undefined);
|
|
87
106
|
|
|
107
|
+
/** What only some rules declare: options beyond the level, and token features the adapter computes on request. */
|
|
108
|
+
const extrasOf = (raw: Record<string, unknown>, file: string): Pick<RuleDefinition, "options" | "token_features"> => ({
|
|
109
|
+
...(raw["options"] === undefined ? {} : { options: optionsOf(raw["options"], file) }),
|
|
110
|
+
...(raw["token_features"] === undefined ? {} : { token_features: stringList(raw["token_features"]) ?? [] }),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/** The table flattenLevels reads, before its severities become numbers. */
|
|
114
|
+
const writtenTable = (raw: unknown, language: string): unknown => {
|
|
115
|
+
if (isLevelTable(raw) || !isRecord(raw)) return raw;
|
|
116
|
+
return raw[language] ?? raw["default"];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/** Every level value written for a language: the rule's own table and each genre's. */
|
|
120
|
+
const writtenValues = (raw: Record<string, unknown>, language: string): unknown[] => {
|
|
121
|
+
const genres = isRecord(raw["by_genre"]) ? Object.values(raw["by_genre"]) : [];
|
|
122
|
+
return [raw["levels"], ...genres].flatMap((written) => {
|
|
123
|
+
const table = writtenTable(written, language);
|
|
124
|
+
return isRecord(table) ? Object.values(table) : [];
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/** Levels written as severities set the severity; a rule that mixes the two would say both. */
|
|
129
|
+
const levelSetsOf = (raw: Record<string, unknown>, language: string, file: string): LevelSets => {
|
|
130
|
+
const values = writtenValues(raw, language);
|
|
131
|
+
const severities = values.filter((value) => typeof value === "string").length;
|
|
132
|
+
if (severities === 0) return "limit";
|
|
133
|
+
if (severities < values.length) throw new Error(`${file}: levels と by_genre に重さ(error / warning / info)と数を混ぜて書けません`);
|
|
134
|
+
// A genre's table would give the rule a default severity other than its severity field.
|
|
135
|
+
if (isRecord(raw["by_genre"])) throw new Error(`${file}: 重さを段に持つ rule は by_genre を持てません`);
|
|
136
|
+
return "severity";
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/** severity は normal の段の重さそのもの。食い違うと、段を書かないときと normal と書いたときで重さが変わる。 */
|
|
140
|
+
const checkedSeverity = (rule: RuleDefinition, file: string): RuleDefinition => {
|
|
141
|
+
if (rule.level_sets === "limit" || severityAt(rule, "normal") === rule.severity) return rule;
|
|
142
|
+
throw new Error(`${file}: severity ${rule.severity} が levels の normal(${severityAt(rule, "normal")})と違います`);
|
|
143
|
+
};
|
|
144
|
+
|
|
88
145
|
const toRule = (raw: unknown, language: string, file: string): RuleDefinition => {
|
|
89
146
|
if (!isRecord(raw)) throw new Error(`${file}: rule は object であること`);
|
|
90
147
|
const levels = flattenLevels(raw["levels"], language);
|
|
91
148
|
const missing = missingFields(raw, levels);
|
|
92
149
|
if (missing.length > 0) throw new Error(`${file}: 必須フィールドがありません: ${missing.join(", ")}`);
|
|
93
150
|
if (levels === undefined) throw new Error(`${file}: levels を解決できません`);
|
|
94
|
-
return
|
|
95
|
-
id: String(raw["id"]),
|
|
96
|
-
layer: pick(raw["layer"], LAYERS) ?? "L1",
|
|
97
|
-
status: pick(raw["status"], STATUSES) ?? "experimental",
|
|
98
|
-
name: localizedOf(raw["name"]),
|
|
99
|
-
why: localizedOf(raw["why"]),
|
|
100
|
-
how_to_fix: localizedOf(raw["how_to_fix"]),
|
|
101
|
-
message: localizedOf(raw["message"]),
|
|
102
|
-
messages: messagesOf(raw["messages"]),
|
|
103
|
-
levels,
|
|
104
|
-
by_genre: genreTables(raw["by_genre"], language),
|
|
105
|
-
how_to_find: String(raw["how_to_find"]),
|
|
106
|
-
word_list: typeof raw["word_list"] === "string" ? raw["word_list"] : undefined,
|
|
107
|
-
extra_word_lists: stringList(raw["extra_word_lists"]) ?? [],
|
|
108
|
-
what_to_check: isLocalized(raw["what_to_check"]) ? raw["what_to_check"] : undefined,
|
|
109
|
-
where: typeof raw["where"] === "string" ? raw["where"] : undefined,
|
|
110
|
-
requires: stringList(raw["requires"]) ?? [],
|
|
111
|
-
uses: stringList(raw["uses"]) ?? [],
|
|
112
|
-
from: stringList(raw["from"]) ?? [],
|
|
113
|
-
languages: stringList(raw["languages"]),
|
|
114
|
-
use_for: Array.isArray(raw["use_for"]) ? raw["use_for"].map((entry) => String(entry)) : [],
|
|
115
|
-
severity: severityOf(raw["severity"], language),
|
|
116
|
-
};
|
|
151
|
+
return checkedSeverity(ruleOf(raw, levels, levelSetsOf(raw, language, file), language, file), file);
|
|
117
152
|
};
|
|
118
153
|
|
|
154
|
+
const ruleOf = (raw: Record<string, unknown>, levels: LevelTable, levelSets: LevelSets, language: string, file: string): RuleDefinition => ({
|
|
155
|
+
id: String(raw["id"]),
|
|
156
|
+
layer: pick(raw["layer"], LAYERS) ?? "L1",
|
|
157
|
+
status: pick(raw["status"], STATUSES) ?? "experimental",
|
|
158
|
+
name: localizedOf(raw["name"]),
|
|
159
|
+
why: localizedOf(raw["why"]),
|
|
160
|
+
how_to_fix: localizedOf(raw["how_to_fix"]),
|
|
161
|
+
message: localizedOf(raw["message"]),
|
|
162
|
+
messages: localizedByKey(raw["messages"]),
|
|
163
|
+
placeholders: localizedByKey(raw["placeholders"]),
|
|
164
|
+
levels,
|
|
165
|
+
level_sets: levelSets,
|
|
166
|
+
by_genre: genreTables(raw["by_genre"], language),
|
|
167
|
+
other_languages: otherLanguages(raw, language),
|
|
168
|
+
how_to_find: String(raw["how_to_find"]),
|
|
169
|
+
word_list: typeof raw["word_list"] === "string" ? raw["word_list"] : undefined,
|
|
170
|
+
extra_word_lists: stringList(raw["extra_word_lists"]) ?? [],
|
|
171
|
+
what_to_check: isLocalized(raw["what_to_check"]) ? raw["what_to_check"] : undefined,
|
|
172
|
+
where: typeof raw["where"] === "string" ? raw["where"] : undefined,
|
|
173
|
+
full_sentence: numberFor(raw["full_sentence"], language),
|
|
174
|
+
requires: stringList(raw["requires"]) ?? [],
|
|
175
|
+
uses: stringList(raw["uses"]) ?? [],
|
|
176
|
+
from: stringList(raw["from"]) ?? [],
|
|
177
|
+
languages: stringList(raw["languages"]),
|
|
178
|
+
use_for: Array.isArray(raw["use_for"]) ? raw["use_for"].map((entry) => String(entry)) : [],
|
|
179
|
+
severity: severityOf(raw["severity"], language),
|
|
180
|
+
...extrasOf(raw, file),
|
|
181
|
+
guide: ruleGuideOf(raw),
|
|
182
|
+
});
|
|
183
|
+
|
|
119
184
|
/**
|
|
120
185
|
* 読めない rule ファイルは、どれが何で読めないかを言う。
|
|
121
186
|
* yaml の例外をそのまま投げると、スタックトレースだけが出てファイル名が出ない。
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { Localized, OptionValue, RuleOption } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
// A rule's options: what its YAML declares, whether a written value fits, and which setting decides each one.
|
|
4
|
+
// Pure: no file is read here. The settings come in as layers, strongest first (chaff.yaml, then a style, then the default).
|
|
5
|
+
|
|
6
|
+
const KINDS: readonly RuleOption["kind"][] = ["choice", "count", "words"];
|
|
7
|
+
|
|
8
|
+
const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
|
|
10
|
+
const isLocalized = (value: unknown): value is Localized =>
|
|
11
|
+
isRecord(value) && Object.keys(value).length > 0 && Object.values(value).every((entry) => typeof entry === "string" && entry !== "");
|
|
12
|
+
|
|
13
|
+
const isCount = (value: unknown): value is number => typeof value === "number" && Number.isInteger(value) && value >= 1;
|
|
14
|
+
|
|
15
|
+
const isWords = (value: unknown): value is string[] => Array.isArray(value) && value.every((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
16
|
+
|
|
17
|
+
/** Whether value fits the option: one of the choices, a whole number of 1 or more, or a list of words. */
|
|
18
|
+
export const fitsOption = (option: RuleOption, value: unknown): value is OptionValue => {
|
|
19
|
+
if (option.kind === "count") return isCount(value);
|
|
20
|
+
if (option.kind === "words") return isWords(value);
|
|
21
|
+
return typeof value === "string" && option.choices.includes(value);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** What a value must look like, for a problem message: the choices, or the kind. */
|
|
25
|
+
export const expectedOf = (option: RuleOption): string => (option.kind === "choice" ? option.choices.join(" / ") : option.kind);
|
|
26
|
+
|
|
27
|
+
const kindOf = (raw: Record<string, unknown>, where: string): RuleOption["kind"] => {
|
|
28
|
+
const kind = KINDS.find((entry) => entry === raw["kind"]);
|
|
29
|
+
if (kind === undefined) throw new Error(`${where}: kind must be one of ${KINDS.join(", ")}`);
|
|
30
|
+
return kind;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const choicesOf = (raw: Record<string, unknown>, kind: RuleOption["kind"], where: string): string[] => {
|
|
34
|
+
if (kind !== "choice") return [];
|
|
35
|
+
const choices = raw["choices"];
|
|
36
|
+
if (!isRecord(choices) || Object.keys(choices).length < 2) throw new Error(`${where}: a choice needs two or more choices, each with its meaning`);
|
|
37
|
+
return Object.keys(choices);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const choiceNamesOf = (raw: Record<string, unknown>, where: string): Record<string, Localized> => {
|
|
41
|
+
const choices = raw["choices"];
|
|
42
|
+
if (!isRecord(choices)) return {};
|
|
43
|
+
return Object.fromEntries(
|
|
44
|
+
Object.entries(choices).map(([choice, meaning]) => {
|
|
45
|
+
if (!isLocalized(meaning)) throw new Error(`${where}: choice ${choice} needs its meaning in ja and/or en`);
|
|
46
|
+
return [choice, meaning];
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const optionOf = (name: string, raw: unknown, file: string): RuleOption => {
|
|
52
|
+
const where = `${file}: options.${name}`;
|
|
53
|
+
if (!isRecord(raw)) throw new Error(`${where} must be a map`);
|
|
54
|
+
const kind = kindOf(raw, where);
|
|
55
|
+
const about = raw["about"];
|
|
56
|
+
if (!isLocalized(about)) throw new Error(`${where}: about needs what the option decides, in ja and/or en`);
|
|
57
|
+
const option: RuleOption = {
|
|
58
|
+
kind,
|
|
59
|
+
choices: choicesOf(raw, kind, where),
|
|
60
|
+
default: kind === "words" ? [] : 0,
|
|
61
|
+
about,
|
|
62
|
+
choiceNames: kind === "choice" ? choiceNamesOf(raw, where) : {},
|
|
63
|
+
};
|
|
64
|
+
const fallback: unknown = raw["default"] ?? (kind === "words" ? [] : undefined);
|
|
65
|
+
if (!fitsOption(option, fallback)) throw new Error(`${where}: default must be ${expectedOf(option)}`);
|
|
66
|
+
return { ...option, default: fallback };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** The options a rule's YAML declares. A wrong declaration is chaff's own bug, so it throws with the file and the option. */
|
|
70
|
+
export const optionsOf = (raw: unknown, file: string): Record<string, RuleOption> => {
|
|
71
|
+
if (raw === undefined) return {};
|
|
72
|
+
if (!isRecord(raw)) throw new Error(`${file}: options must be a map of option names`);
|
|
73
|
+
return Object.fromEntries(Object.entries(raw).map(([name, option]) => [name, optionOf(name, option, file)]));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** One place settings come from, and what it sets: { rule id: { option: value } }. */
|
|
77
|
+
export type OptionLayer = { readonly from: string; readonly values: Readonly<Record<string, unknown>> };
|
|
78
|
+
|
|
79
|
+
export type SettledOption = { readonly value: OptionValue; readonly from: string };
|
|
80
|
+
|
|
81
|
+
/** The source name of an option left at its default. */
|
|
82
|
+
export const DEFAULT_SOURCE = "default";
|
|
83
|
+
|
|
84
|
+
const optionMap = (layer: OptionLayer, ruleId: string): Readonly<Record<string, unknown>> => {
|
|
85
|
+
const values = layer.values[ruleId];
|
|
86
|
+
return isRecord(values) ? values : {};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Each option of a rule at the value of the strongest layer that sets it with a value that fits, and where that came from.
|
|
91
|
+
* A value that does not fit falls through to the next layer; optionProblems says so, so it is never silent.
|
|
92
|
+
*/
|
|
93
|
+
export const settleOptions = (ruleId: string, options: Readonly<Record<string, RuleOption>>, layers: readonly OptionLayer[]): Record<string, SettledOption> =>
|
|
94
|
+
Object.fromEntries(
|
|
95
|
+
Object.entries(options).map(([name, option]) => {
|
|
96
|
+
const fitting = layers.flatMap((layer): SettledOption[] => {
|
|
97
|
+
const value = optionMap(layer, ruleId)[name];
|
|
98
|
+
return fitsOption(option, value) ? [{ value, from: layer.from }] : [];
|
|
99
|
+
});
|
|
100
|
+
return [name, fitting[0] ?? { value: option.default, from: DEFAULT_SOURCE }];
|
|
101
|
+
}),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
/** The values alone, as the detector gets them. */
|
|
105
|
+
export const optionValues = (settled: Readonly<Record<string, SettledOption>>): Record<string, OptionValue> =>
|
|
106
|
+
Object.fromEntries(Object.entries(settled).map(([name, entry]) => [name, entry.value]));
|
|
107
|
+
|
|
108
|
+
/** What a layer sets that has no effect: an unknown rule, a rule with no options, an unknown option, or a value that does not fit. */
|
|
109
|
+
export type OptionProblem =
|
|
110
|
+
| { readonly kind: "unknown-rule"; readonly rule: string }
|
|
111
|
+
| { readonly kind: "no-options"; readonly rule: string }
|
|
112
|
+
| { readonly kind: "not-a-map"; readonly rule: string }
|
|
113
|
+
| { readonly kind: "unknown-option"; readonly rule: string; readonly option: string; readonly known: readonly string[] }
|
|
114
|
+
| { readonly kind: "bad-value"; readonly rule: string; readonly option: string; readonly value: string; readonly expected: string };
|
|
115
|
+
|
|
116
|
+
const printed = (value: unknown): string => JSON.stringify(value) ?? String(value);
|
|
117
|
+
|
|
118
|
+
const problemsOfRule = (ruleId: string, options: Readonly<Record<string, RuleOption>> | undefined, written: unknown): OptionProblem[] => {
|
|
119
|
+
if (options === undefined) return [{ kind: "unknown-rule", rule: ruleId }];
|
|
120
|
+
if (Object.keys(options).length === 0) return [{ kind: "no-options", rule: ruleId }];
|
|
121
|
+
if (!isRecord(written)) return [{ kind: "not-a-map", rule: ruleId }];
|
|
122
|
+
return Object.entries(written).flatMap(([name, value]): OptionProblem[] => {
|
|
123
|
+
const option = options[name];
|
|
124
|
+
if (option === undefined) return [{ kind: "unknown-option", rule: ruleId, option: name, known: Object.keys(options) }];
|
|
125
|
+
return fitsOption(option, value) ? [] : [{ kind: "bad-value", rule: ruleId, option: name, value: printed(value), expected: expectedOf(option) }];
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** Every problem in what a layer sets, given each known rule's options (a rule with none maps to {}). */
|
|
130
|
+
export const optionProblems = (layer: OptionLayer, known: Readonly<Record<string, Readonly<Record<string, RuleOption>>>>): OptionProblem[] =>
|
|
131
|
+
Object.entries(layer.values).flatMap(([ruleId, written]) => problemsOfRule(ruleId, known[ruleId], written));
|
package/src/run-semantic.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { ask, type JudgeOptions } from "./judge.ts";
|
|
|
3
3
|
import { FILTERS, type Candidate } from "./semantic.ts";
|
|
4
4
|
import { narrow, type Narrowing } from "./look-at.ts";
|
|
5
5
|
import { localized } from "./render/text.ts";
|
|
6
|
-
import type { Finding, Level, ProseDocument, RuleDefinition, Severity } from "./plugin.ts";
|
|
6
|
+
import type { AdapterNeeds, Finding, Level, ProseDocument, RuleDefinition, Severity } from "./plugin.ts";
|
|
7
7
|
import { lineStarts, placeOf } from "./position.ts";
|
|
8
|
+
import { wantsTags } from "./run.ts";
|
|
8
9
|
|
|
9
10
|
export type SemanticResult = {
|
|
10
11
|
readonly findings: readonly Finding[];
|
|
@@ -39,26 +40,33 @@ const severityFromLevel = (rule: RuleDefinition, level: Level): Severity => {
|
|
|
39
40
|
return SEVERITY_BY_VALUE[Math.min(3, Math.max(1, Math.round(value)))] ?? "warning";
|
|
40
41
|
};
|
|
41
42
|
|
|
43
|
+
/** この文書で動かす、意味を読む rule。 */
|
|
44
|
+
const semanticRules = (rules: readonly RuleDefinition[], settings: Readonly<Record<string, Level>>, genre: string): RuleDefinition[] =>
|
|
45
|
+
rules.filter((rule) => rule.layer === "L4" && rule.use_for.some((target) => genre.startsWith(target)) && settings[rule.id] !== "off");
|
|
46
|
+
|
|
47
|
+
/** 意味を読む rule の絞り込みが品詞を使うか。chaff test はこれで解析器を読み込む(neededBy は L4 を数えない)。 */
|
|
48
|
+
export const semanticNeeds = (rules: readonly RuleDefinition[], settings: Readonly<Record<string, Level>>, genre: string): AdapterNeeds => ({
|
|
49
|
+
pos: semanticRules(rules, settings, genre).some(wantsTags),
|
|
50
|
+
});
|
|
51
|
+
|
|
42
52
|
const builtInJobs = (doc: ProseDocument, rules: readonly RuleDefinition[], settings: Readonly<Record<string, Level>>, genre: string): Job[] =>
|
|
43
|
-
rules
|
|
44
|
-
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
];
|
|
61
|
-
});
|
|
53
|
+
semanticRules(rules, settings, genre).flatMap((rule) => {
|
|
54
|
+
const rubric = rule.what_to_check === undefined ? undefined : localized(rule.what_to_check, doc.language);
|
|
55
|
+
if (rubric === undefined || rubric.length === 0) return [];
|
|
56
|
+
// 絞り込みが無い rule は動かさない。黙って落とさず、下の skipped に出す。
|
|
57
|
+
const filter = filterFor(rule.how_to_find);
|
|
58
|
+
if (filter === undefined) return [];
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
rule: rule.id,
|
|
62
|
+
name: localized(rule.name, doc.language),
|
|
63
|
+
rubric,
|
|
64
|
+
howToFix: localized(rule.how_to_fix, doc.language),
|
|
65
|
+
severity: severityFromLevel(rule, settings[rule.id] ?? "normal"),
|
|
66
|
+
candidates: filter(doc),
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
});
|
|
62
70
|
|
|
63
71
|
const userJobs = (doc: ProseDocument, checks: readonly UserCheck[], genre: string): Job[] =>
|
|
64
72
|
checks
|