chaffjs 0.18.0 → 0.19.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/README.md +52 -56
- package/bin/chaff.js +17 -2
- package/dist/acronym-expansions.d.ts +26 -0
- package/dist/acronym-expansions.d.ts.map +1 -0
- package/dist/acronym-expansions.js +88 -0
- package/dist/acronym-expansions.js.map +1 -0
- package/dist/announced-count.d.ts.map +1 -1
- package/dist/announced-count.js +44 -10
- package/dist/announced-count.js.map +1 -1
- package/dist/announced-list.d.ts +30 -0
- package/dist/announced-list.d.ts.map +1 -0
- package/dist/announced-list.js +95 -0
- package/dist/announced-list.js.map +1 -0
- package/dist/api.d.ts +168 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +10 -0
- package/dist/api.js.map +1 -0
- package/dist/cli-text.d.ts +0 -1
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +6 -14
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +58 -62
- package/dist/cli.js.map +1 -1
- package/dist/closing-paragraph.d.ts +7 -0
- package/dist/closing-paragraph.d.ts.map +1 -0
- package/dist/closing-paragraph.js +22 -0
- package/dist/closing-paragraph.js.map +1 -0
- package/dist/commands/compare.d.ts +8 -1
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +9 -17
- package/dist/commands/compare.js.map +1 -1
- package/dist/commands/document-commands.d.ts +9 -0
- package/dist/commands/document-commands.d.ts.map +1 -0
- package/dist/commands/document-commands.js +17 -0
- package/dist/commands/document-commands.js.map +1 -0
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +3 -2
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/facts.d.ts +8 -0
- package/dist/commands/facts.d.ts.map +1 -0
- package/dist/commands/facts.js +30 -0
- package/dist/commands/facts.js.map +1 -0
- package/dist/commands/feedback.d.ts +10 -0
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +25 -1
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/fix-plan.d.ts +13 -0
- package/dist/commands/fix-plan.d.ts.map +1 -0
- package/dist/commands/fix-plan.js +44 -0
- package/dist/commands/fix-plan.js.map +1 -0
- package/dist/commands/outline.d.ts +8 -0
- package/dist/commands/outline.d.ts.map +1 -0
- package/dist/commands/outline.js +43 -0
- package/dist/commands/outline.js.map +1 -0
- package/dist/commands/read-document.d.ts +14 -0
- package/dist/commands/read-document.d.ts.map +1 -0
- package/dist/commands/read-document.js +21 -0
- package/dist/commands/read-document.js.map +1 -0
- package/dist/commands/suppressions.d.ts +7 -0
- package/dist/commands/suppressions.d.ts.map +1 -0
- package/dist/commands/suppressions.js +9 -0
- package/dist/commands/suppressions.js.map +1 -0
- package/dist/commands/test.js +1 -1
- package/dist/commands/test.js.map +1 -1
- package/dist/compare/clock-time.d.ts.map +1 -1
- package/dist/compare/clock-time.js +5 -2
- package/dist/compare/clock-time.js.map +1 -1
- package/dist/compare/distinct.d.ts +9 -0
- package/dist/compare/distinct.d.ts.map +1 -0
- package/dist/compare/distinct.js +12 -0
- package/dist/compare/distinct.js.map +1 -0
- package/dist/compare/extract.d.ts.map +1 -1
- package/dist/compare/extract.js +7 -5
- package/dist/compare/extract.js.map +1 -1
- package/dist/compare/fact-key.d.ts +17 -0
- package/dist/compare/fact-key.d.ts.map +1 -0
- package/dist/compare/fact-key.js +25 -0
- package/dist/compare/fact-key.js.map +1 -0
- package/dist/compare/fact-text.d.ts +5 -0
- package/dist/compare/fact-text.d.ts.map +1 -1
- package/dist/compare/fact-text.js +16 -2
- package/dist/compare/fact-text.js.map +1 -1
- package/dist/compare/facts-render.d.ts +17 -0
- package/dist/compare/facts-render.d.ts.map +1 -0
- package/dist/compare/facts-render.js +43 -0
- package/dist/compare/facts-render.js.map +1 -0
- package/dist/compare/facts-text.d.ts +15 -0
- package/dist/compare/facts-text.d.ts.map +1 -0
- package/dist/compare/facts-text.js +27 -0
- package/dist/compare/facts-text.js.map +1 -0
- package/dist/compare/match.d.ts +1 -0
- package/dist/compare/match.d.ts.map +1 -1
- package/dist/compare/match.js +1 -1
- package/dist/compare/match.js.map +1 -1
- package/dist/compare/outcome.d.ts +4 -1
- package/dist/compare/outcome.d.ts.map +1 -1
- package/dist/compare/outcome.js +10 -4
- package/dist/compare/outcome.js.map +1 -1
- package/dist/compare/proper-nouns.d.ts +3 -3
- package/dist/compare/proper-nouns.d.ts.map +1 -1
- package/dist/compare/proper-nouns.js +2 -3
- package/dist/compare/proper-nouns.js.map +1 -1
- package/dist/compare/render.d.ts +4 -0
- package/dist/compare/render.d.ts.map +1 -1
- package/dist/compare/render.js +2 -2
- package/dist/compare/render.js.map +1 -1
- package/dist/compare/text-atoms.d.ts +5 -2
- package/dist/compare/text-atoms.d.ts.map +1 -1
- package/dist/compare/text-atoms.js +7 -5
- package/dist/compare/text-atoms.js.map +1 -1
- package/dist/compare/text.d.ts.map +1 -1
- package/dist/compare/text.js +2 -2
- package/dist/compare/text.js.map +1 -1
- package/dist/config/load.d.ts +8 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +1 -0
- package/dist/config/load.js.map +1 -1
- package/dist/config/option-problems.d.ts +3 -2
- package/dist/config/option-problems.d.ts.map +1 -1
- package/dist/config/option-problems.js +4 -3
- package/dist/config/option-problems.js.map +1 -1
- package/dist/config/style.d.ts +5 -0
- package/dist/config/style.d.ts.map +1 -1
- package/dist/config/style.js +13 -1
- package/dist/config/style.js.map +1 -1
- package/dist/custom/load.d.ts +6 -3
- package/dist/custom/load.d.ts.map +1 -1
- package/dist/custom/load.js +10 -2
- package/dist/custom/load.js.map +1 -1
- package/dist/custom/module-path.d.ts +11 -0
- package/dist/custom/module-path.d.ts.map +1 -0
- package/dist/custom/module-path.js +15 -0
- package/dist/custom/module-path.js.map +1 -0
- package/dist/custom/parse.d.ts +17 -3
- package/dist/custom/parse.d.ts.map +1 -1
- package/dist/custom/parse.js +57 -14
- package/dist/custom/parse.js.map +1 -1
- package/dist/custom/problems.d.ts +4 -1
- package/dist/custom/problems.d.ts.map +1 -1
- package/dist/custom/problems.js +56 -39
- package/dist/custom/problems.js.map +1 -1
- package/dist/detect-language.js +1 -1
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +9 -3
- package/dist/detect.js.map +1 -1
- package/dist/detectors/ai-phrasing.d.ts +4 -1
- package/dist/detectors/ai-phrasing.d.ts.map +1 -1
- package/dist/detectors/ai-phrasing.js +6 -2
- package/dist/detectors/ai-phrasing.js.map +1 -1
- package/dist/detectors/bold-label.d.ts +10 -0
- package/dist/detectors/bold-label.d.ts.map +1 -0
- package/dist/detectors/bold-label.js +44 -0
- package/dist/detectors/bold-label.js.map +1 -0
- package/dist/detectors/dangling-figure.d.ts +5 -2
- package/dist/detectors/dangling-figure.d.ts.map +1 -1
- package/dist/detectors/dangling-figure.js +5 -3
- package/dist/detectors/dangling-figure.js.map +1 -1
- package/dist/detectors/definition-use.d.ts +8 -0
- package/dist/detectors/definition-use.d.ts.map +1 -0
- package/dist/detectors/definition-use.js +32 -0
- package/dist/detectors/definition-use.js.map +1 -0
- package/dist/detectors/doubled-punctuation.d.ts.map +1 -1
- package/dist/detectors/doubled-punctuation.js +4 -2
- package/dist/detectors/doubled-punctuation.js.map +1 -1
- package/dist/detectors/duplicate-heading.d.ts +14 -0
- package/dist/detectors/duplicate-heading.d.ts.map +1 -0
- package/dist/detectors/duplicate-heading.js +39 -0
- package/dist/detectors/duplicate-heading.js.map +1 -0
- package/dist/detectors/empty-section.d.ts +8 -0
- package/dist/detectors/empty-section.d.ts.map +1 -0
- package/dist/detectors/empty-section.js +16 -0
- package/dist/detectors/empty-section.js.map +1 -0
- package/dist/detectors/fullwidth-alnum.d.ts +24 -0
- package/dist/detectors/fullwidth-alnum.d.ts.map +1 -0
- package/dist/detectors/fullwidth-alnum.js +88 -0
- package/dist/detectors/fullwidth-alnum.js.map +1 -0
- package/dist/detectors/hankaku-kana.d.ts +9 -0
- package/dist/detectors/hankaku-kana.d.ts.map +1 -0
- package/dist/detectors/hankaku-kana.js +27 -0
- package/dist/detectors/hankaku-kana.js.map +1 -0
- package/dist/detectors/heading-code-words.js +2 -2
- package/dist/detectors/heading-code-words.js.map +1 -1
- package/dist/detectors/index.d.ts.map +1 -1
- package/dist/detectors/index.js +36 -0
- package/dist/detectors/index.js.map +1 -1
- package/dist/detectors/invisible-character.d.ts +20 -0
- package/dist/detectors/invisible-character.d.ts.map +1 -0
- package/dist/detectors/invisible-character.js +143 -0
- package/dist/detectors/invisible-character.js.map +1 -0
- package/dist/detectors/kutoten-consistency.js +2 -2
- package/dist/detectors/kutoten-consistency.js.map +1 -1
- package/dist/detectors/lexicon-match.d.ts +10 -1
- package/dist/detectors/lexicon-match.d.ts.map +1 -1
- package/dist/detectors/lexicon-match.js +26 -1
- package/dist/detectors/lexicon-match.js.map +1 -1
- package/dist/detectors/lexicon.d.ts +6 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +31 -13
- package/dist/detectors/lexicon.js.map +1 -1
- package/dist/detectors/list-sentence.d.ts +3 -1
- package/dist/detectors/list-sentence.d.ts.map +1 -1
- package/dist/detectors/list-sentence.js +26 -1
- package/dist/detectors/list-sentence.js.map +1 -1
- package/dist/detectors/long-vowel.d.ts.map +1 -1
- package/dist/detectors/long-vowel.js +18 -4
- package/dist/detectors/long-vowel.js.map +1 -1
- package/dist/detectors/markup-finding.d.ts +3 -1
- package/dist/detectors/markup-finding.d.ts.map +1 -1
- package/dist/detectors/markup-finding.js +10 -0
- package/dist/detectors/markup-finding.js.map +1 -1
- package/dist/detectors/modal-conflict.d.ts +4 -0
- package/dist/detectors/modal-conflict.d.ts.map +1 -0
- package/dist/detectors/modal-conflict.js +22 -0
- package/dist/detectors/modal-conflict.js.map +1 -0
- package/dist/detectors/name-variant.d.ts +4 -0
- package/dist/detectors/name-variant.d.ts.map +1 -0
- package/dist/detectors/name-variant.js +13 -0
- package/dist/detectors/name-variant.js.map +1 -0
- package/dist/detectors/nominalization.d.ts +11 -0
- package/dist/detectors/nominalization.d.ts.map +1 -0
- package/dist/detectors/nominalization.js +56 -0
- package/dist/detectors/nominalization.js.map +1 -0
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +59 -28
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/outside-announced-list.d.ts +4 -0
- package/dist/detectors/outside-announced-list.d.ts.map +1 -0
- package/dist/detectors/outside-announced-list.js +24 -0
- package/dist/detectors/outside-announced-list.js.map +1 -0
- package/dist/detectors/oxford-comma.d.ts.map +1 -1
- package/dist/detectors/oxford-comma.js +1 -0
- package/dist/detectors/oxford-comma.js.map +1 -1
- package/dist/detectors/phrase-match.d.ts +4 -1
- package/dist/detectors/phrase-match.d.ts.map +1 -1
- package/dist/detectors/phrase-match.js +26 -7
- package/dist/detectors/phrase-match.js.map +1 -1
- package/dist/detectors/ra-nuki.d.ts +9 -0
- package/dist/detectors/ra-nuki.d.ts.map +1 -0
- package/dist/detectors/ra-nuki.js +30 -0
- package/dist/detectors/ra-nuki.js.map +1 -0
- package/dist/detectors/requirement-modal.d.ts +5 -0
- package/dist/detectors/requirement-modal.d.ts.map +1 -0
- package/dist/detectors/requirement-modal.js +54 -0
- package/dist/detectors/requirement-modal.js.map +1 -0
- package/dist/detectors/requirement-smell.d.ts +4 -0
- package/dist/detectors/requirement-smell.d.ts.map +1 -0
- package/dist/detectors/requirement-smell.js +41 -0
- package/dist/detectors/requirement-smell.js.map +1 -0
- package/dist/detectors/space-before-punctuation.d.ts +8 -0
- package/dist/detectors/space-before-punctuation.d.ts.map +1 -0
- package/dist/detectors/space-before-punctuation.js +24 -0
- package/dist/detectors/space-before-punctuation.js.map +1 -0
- package/dist/detectors/spelling-variety.d.ts +23 -0
- package/dist/detectors/spelling-variety.d.ts.map +1 -0
- package/dist/detectors/spelling-variety.js +59 -0
- package/dist/detectors/spelling-variety.js.map +1 -0
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +3 -1
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +16 -2
- package/dist/detectors/structure.js.map +1 -1
- package/dist/detectors/superlative-comparison.d.ts +20 -0
- package/dist/detectors/superlative-comparison.d.ts.map +1 -0
- package/dist/detectors/superlative-comparison.js +32 -0
- package/dist/detectors/superlative-comparison.js.map +1 -0
- package/dist/detectors/url-run-on.d.ts.map +1 -1
- package/dist/detectors/url-run-on.js +6 -1
- package/dist/detectors/url-run-on.js.map +1 -1
- package/dist/detectors/vague-figure-pointer.d.ts +10 -0
- package/dist/detectors/vague-figure-pointer.d.ts.map +1 -0
- package/dist/detectors/vague-figure-pointer.js +46 -0
- package/dist/detectors/vague-figure-pointer.js.map +1 -0
- package/dist/detectors/word-list.d.ts +2 -0
- package/dist/detectors/word-list.d.ts.map +1 -1
- package/dist/detectors/word-list.js +4 -1
- package/dist/detectors/word-list.js.map +1 -1
- package/dist/document.d.ts +9 -3
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +55 -32
- package/dist/document.js.map +1 -1
- package/dist/extension/document-view.d.ts +7 -0
- package/dist/extension/document-view.d.ts.map +1 -0
- package/dist/extension/document-view.js +91 -0
- package/dist/extension/document-view.js.map +1 -0
- package/dist/extension/failure-text.d.ts +5 -0
- package/dist/extension/failure-text.d.ts.map +1 -0
- package/dist/extension/failure-text.js +33 -0
- package/dist/extension/failure-text.js.map +1 -0
- package/dist/extension/import-default.d.ts +7 -0
- package/dist/extension/import-default.d.ts.map +1 -0
- package/dist/extension/import-default.js +21 -0
- package/dist/extension/import-default.js.map +1 -0
- package/dist/extension/load.d.ts +28 -0
- package/dist/extension/load.d.ts.map +1 -0
- package/dist/extension/load.js +51 -0
- package/dist/extension/load.js.map +1 -0
- package/dist/extension/module-detector.d.ts +21 -0
- package/dist/extension/module-detector.d.ts.map +1 -0
- package/dist/extension/module-detector.js +49 -0
- package/dist/extension/module-detector.js.map +1 -0
- package/dist/extension/plugin-load.d.ts +9 -0
- package/dist/extension/plugin-load.d.ts.map +1 -0
- package/dist/extension/plugin-load.js +68 -0
- package/dist/extension/plugin-load.js.map +1 -0
- package/dist/extension/plugin-name.d.ts +8 -0
- package/dist/extension/plugin-name.d.ts.map +1 -0
- package/dist/extension/plugin-name.js +22 -0
- package/dist/extension/plugin-name.js.map +1 -0
- package/dist/extension/plugin-parse.d.ts +41 -0
- package/dist/extension/plugin-parse.d.ts.map +1 -0
- package/dist/extension/plugin-parse.js +156 -0
- package/dist/extension/plugin-parse.js.map +1 -0
- package/dist/extension/problem-text.d.ts +5 -0
- package/dist/extension/problem-text.d.ts.map +1 -0
- package/dist/extension/problem-text.js +74 -0
- package/dist/extension/problem-text.js.map +1 -0
- package/dist/extension/real-path.d.ts +3 -0
- package/dist/extension/real-path.d.ts.map +1 -0
- package/dist/extension/real-path.js +8 -0
- package/dist/extension/real-path.js.map +1 -0
- package/dist/extension/returned-findings.d.ts +17 -0
- package/dist/extension/returned-findings.d.ts.map +1 -0
- package/dist/extension/returned-findings.js +48 -0
- package/dist/extension/returned-findings.js.map +1 -0
- package/dist/extension/rule-export.d.ts +13 -0
- package/dist/extension/rule-export.d.ts.map +1 -0
- package/dist/extension/rule-export.js +16 -0
- package/dist/extension/rule-export.js.map +1 -0
- package/dist/feedback/draft.d.ts +2 -0
- package/dist/feedback/draft.d.ts.map +1 -1
- package/dist/feedback/draft.js +3 -0
- package/dist/feedback/draft.js.map +1 -1
- package/dist/figure-references.d.ts +11 -2
- package/dist/figure-references.d.ts.map +1 -1
- package/dist/figure-references.js +50 -13
- package/dist/figure-references.js.map +1 -1
- package/dist/finding-order.d.ts +9 -0
- package/dist/finding-order.d.ts.map +1 -0
- package/dist/finding-order.js +3 -0
- package/dist/finding-order.js.map +1 -0
- package/dist/fix-plan/mode.d.ts +21 -0
- package/dist/fix-plan/mode.d.ts.map +1 -0
- package/dist/fix-plan/mode.js +16 -0
- package/dist/fix-plan/mode.js.map +1 -0
- package/dist/fix-plan/plan.d.ts +77 -0
- package/dist/fix-plan/plan.d.ts.map +1 -0
- package/dist/fix-plan/plan.js +100 -0
- package/dist/fix-plan/plan.js.map +1 -0
- package/dist/fix-plan/render.d.ts +6 -0
- package/dist/fix-plan/render.d.ts.map +1 -0
- package/dist/fix-plan/render.js +101 -0
- package/dist/fix-plan/render.js.map +1 -0
- package/dist/fix-plan/text.d.ts +35 -0
- package/dist/fix-plan/text.d.ts.map +1 -0
- package/dist/fix-plan/text.js +95 -0
- package/dist/fix-plan/text.js.map +1 -0
- package/dist/language-sample.d.ts +2 -0
- package/dist/language-sample.d.ts.map +1 -0
- package/dist/language-sample.js +41 -0
- package/dist/language-sample.js.map +1 -0
- package/dist/link-line.d.ts +8 -0
- package/dist/link-line.d.ts.map +1 -0
- package/dist/link-line.js +12 -0
- package/dist/link-line.js.map +1 -0
- package/dist/long-vowel.d.ts +9 -6
- package/dist/long-vowel.d.ts.map +1 -1
- package/dist/long-vowel.js +15 -8
- package/dist/long-vowel.js.map +1 -1
- package/dist/markup.d.ts.map +1 -1
- package/dist/markup.js +4 -2
- package/dist/markup.js.map +1 -1
- package/dist/name-variants.d.ts +25 -0
- package/dist/name-variants.d.ts.map +1 -0
- package/dist/name-variants.js +181 -0
- package/dist/name-variants.js.map +1 -0
- package/dist/node-version.d.ts +7 -0
- package/dist/node-version.d.ts.map +1 -0
- package/dist/node-version.js +19 -0
- package/dist/node-version.js.map +1 -0
- package/dist/not-run.d.ts +14 -0
- package/dist/not-run.d.ts.map +1 -0
- package/dist/not-run.js +12 -0
- package/dist/not-run.js.map +1 -0
- package/dist/orthography.d.ts +8 -1
- package/dist/orthography.d.ts.map +1 -1
- package/dist/orthography.js +33 -12
- package/dist/orthography.js.map +1 -1
- package/dist/outline/render.d.ts +18 -0
- package/dist/outline/render.d.ts.map +1 -0
- package/dist/outline/render.js +60 -0
- package/dist/outline/render.js.map +1 -0
- package/dist/outline/shape.d.ts +26 -0
- package/dist/outline/shape.d.ts.map +1 -0
- package/dist/outline/shape.js +37 -0
- package/dist/outline/shape.js.map +1 -0
- package/dist/outline/text.d.ts +21 -0
- package/dist/outline/text.d.ts.map +1 -0
- package/dist/outline/text.js +30 -0
- package/dist/outline/text.js.map +1 -0
- package/dist/plugin.d.ts +24 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/reasons.d.ts +1 -0
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +2 -0
- package/dist/reasons.js.map +1 -1
- package/dist/render/compact.d.ts +3 -1
- package/dist/render/compact.d.ts.map +1 -1
- package/dist/render/compact.js +8 -2
- package/dist/render/compact.js.map +1 -1
- package/dist/render/explain.d.ts +3 -1
- package/dist/render/explain.d.ts.map +1 -1
- package/dist/render/explain.js +32 -15
- package/dist/render/explain.js.map +1 -1
- package/dist/render/rules-json.d.ts.map +1 -1
- package/dist/render/rules-json.js +16 -12
- package/dist/render/rules-json.js.map +1 -1
- package/dist/render/suppressions.d.ts +3 -0
- package/dist/render/suppressions.d.ts.map +1 -1
- package/dist/render/suppressions.js +20 -1
- package/dist/render/suppressions.js.map +1 -1
- package/dist/rule-guide.d.ts +19 -0
- package/dist/rule-guide.d.ts.map +1 -1
- package/dist/rule-guide.js +14 -0
- package/dist/rule-guide.js.map +1 -1
- package/dist/run-semantic.d.ts.map +1 -1
- package/dist/run-semantic.js +2 -1
- package/dist/run-semantic.js.map +1 -1
- package/dist/run.d.ts +5 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +31 -14
- package/dist/run.js.map +1 -1
- package/dist/setting-problems.d.ts.map +1 -1
- package/dist/setting-problems.js +3 -1
- package/dist/setting-problems.js.map +1 -1
- package/dist/spacing-minority.d.ts +16 -0
- package/dist/spacing-minority.d.ts.map +1 -0
- package/dist/spacing-minority.js +23 -0
- package/dist/spacing-minority.js.map +1 -0
- package/dist/stet-block.d.ts +5 -0
- package/dist/stet-block.d.ts.map +1 -0
- package/dist/stet-block.js +59 -0
- package/dist/stet-block.js.map +1 -0
- package/dist/stet.d.ts +4 -0
- package/dist/stet.d.ts.map +1 -1
- package/dist/stet.js +31 -11
- package/dist/stet.js.map +1 -1
- package/dist/structure/date-range.d.ts +10 -0
- package/dist/structure/date-range.d.ts.map +1 -1
- package/dist/structure/date-range.js +33 -1
- package/dist/structure/date-range.js.map +1 -1
- package/dist/structure/definition-use.d.ts +32 -0
- package/dist/structure/definition-use.d.ts.map +1 -0
- package/dist/structure/definition-use.js +102 -0
- package/dist/structure/definition-use.js.map +1 -0
- package/dist/structure/lazy-tree.d.ts +8 -0
- package/dist/structure/lazy-tree.d.ts.map +1 -0
- package/dist/structure/lazy-tree.js +14 -0
- package/dist/structure/lazy-tree.js.map +1 -0
- package/dist/structure/modal-conflict.d.ts +28 -0
- package/dist/structure/modal-conflict.d.ts.map +1 -0
- package/dist/structure/modal-conflict.js +74 -0
- package/dist/structure/modal-conflict.js.map +1 -0
- package/dist/structure/numbered-clauses.d.ts +4 -0
- package/dist/structure/numbered-clauses.d.ts.map +1 -0
- package/dist/structure/numbered-clauses.js +9 -0
- package/dist/structure/numbered-clauses.js.map +1 -0
- package/dist/structure/universal.d.ts.map +1 -1
- package/dist/structure/universal.js +8 -2
- package/dist/structure/universal.js.map +1 -1
- package/dist/style-parse.d.ts +6 -0
- package/dist/style-parse.d.ts.map +1 -1
- package/dist/style-parse.js +32 -4
- package/dist/style-parse.js.map +1 -1
- package/dist/subheading-line.d.ts +19 -2
- package/dist/subheading-line.d.ts.map +1 -1
- package/dist/subheading-line.js +39 -11
- package/dist/subheading-line.js.map +1 -1
- package/dist/tag-coverage.d.ts +8 -0
- package/dist/tag-coverage.d.ts.map +1 -0
- package/dist/tag-coverage.js +7 -0
- package/dist/tag-coverage.js.map +1 -0
- package/genres.yaml +42 -0
- package/package.json +7 -3
- package/rules/acronym-expansion-conflict.yaml +82 -0
- package/rules/adverb-overuse.yaml +2 -2
- package/rules/agentless-passive.yaml +28 -0
- package/rules/ai-tell.yaml +34 -0
- package/rules/announced-count-mismatch.yaml +2 -2
- package/rules/announcing-opener.yaml +31 -0
- package/rules/assistant-residue.yaml +30 -0
- package/rules/bold-density.yaml +28 -0
- package/rules/bold-label-list.yaml +81 -0
- package/rules/closing-cliche.yaml +27 -2
- package/rules/colon-lead-in.yaml +28 -4
- package/rules/contrast-framing.yaml +33 -2
- package/rules/cushion-phrase-density.yaml +32 -5
- package/rules/dangling-reference.yaml +1 -0
- package/rules/date-order.yaml +1 -0
- package/rules/date-range-reversed.yaml +2 -2
- package/rules/double-negative.yaml +51 -0
- package/rules/doubled-punctuation.yaml +2 -2
- package/rules/doubled-word.yaml +2 -2
- package/rules/duplicate-heading.yaml +78 -0
- package/rules/emoji-density.yaml +5 -4
- package/rules/empty-intensifier.yaml +25 -0
- package/rules/empty-section.yaml +74 -0
- package/rules/excessive-hedging.yaml +32 -4
- package/rules/fullwidth-alnum-consistency.yaml +53 -0
- package/rules/hankaku-kana.yaml +41 -0
- package/rules/image-alt-text.yaml +1 -1
- package/rules/invisible-character.yaml +63 -0
- package/rules/katakana-long-vowel.yaml +10 -9
- package/rules/latin-spacing.yaml +12 -5
- package/rules/max-kanji-continuous.yaml +1 -0
- package/rules/max-paragraph-length.yaml +1 -0
- package/rules/max-sentence-length.yaml +26 -0
- package/rules/modal-conflict.yaml +106 -0
- package/rules/name-variant.yaml +88 -0
- package/rules/no-doubled-joshi.yaml +1 -0
- package/rules/no-em-dash.yaml +26 -2
- package/rules/no-mixed-desumasu.yaml +1 -0
- package/rules/nominalization.yaml +89 -0
- package/rules/outside-announced-list.yaml +80 -0
- package/rules/padded-intro.yaml +25 -0
- package/rules/paragraph-length-variance.yaml +26 -2
- package/rules/preferred-term.yaml +1 -0
- package/rules/proper-noun-density.yaml +14 -5
- package/rules/ra-nuki.yaml +43 -0
- package/rules/requirement-modal.yaml +94 -0
- package/rules/requirement-smell.yaml +70 -0
- package/rules/rule-of-three.yaml +46 -0
- package/rules/section-length-uniformity.yaml +26 -2
- package/rules/sentence-rhythm.yaml +26 -0
- package/rules/space-before-punctuation.yaml +41 -0
- package/rules/spelling-consistency.yaml +47 -0
- package/rules/stock-transition.yaml +33 -2
- package/rules/taigen-dome-in-prose.yaml +14 -0
- package/rules/total-mismatch.yaml +1 -0
- package/rules/undefined-acronym.yaml +1 -0
- package/rules/unqualified-superlative.yaml +5 -4
- package/rules/unused-definition.yaml +75 -0
- package/rules/use-before-definition.yaml +77 -0
- package/rules/vague-figure-reference.yaml +66 -0
- package/skills/chaff/SKILL.md +108 -8
- package/src/acronym-expansions.ts +106 -0
- package/src/announced-count.ts +53 -11
- package/src/announced-list.ts +120 -0
- package/src/api.ts +154 -0
- package/src/cli-text.ts +6 -11
- package/src/cli.ts +64 -63
- package/src/closing-paragraph.ts +24 -0
- package/src/commands/compare.ts +11 -18
- package/src/commands/document-commands.ts +19 -0
- package/src/commands/eval.ts +3 -2
- package/src/commands/facts.ts +33 -0
- package/src/commands/feedback.ts +33 -1
- package/src/commands/fix-plan.ts +53 -0
- package/src/commands/outline.ts +49 -0
- package/src/commands/read-document.ts +24 -0
- package/src/commands/suppressions.ts +19 -0
- package/src/commands/test.ts +1 -1
- package/src/compare/clock-time.ts +5 -2
- package/src/compare/distinct.ts +13 -0
- package/src/compare/extract.ts +7 -5
- package/src/compare/fact-key.ts +31 -0
- package/src/compare/fact-text.ts +21 -2
- package/src/compare/facts-render.ts +63 -0
- package/src/compare/facts-text.ts +41 -0
- package/src/compare/match.ts +1 -1
- package/src/compare/outcome.ts +14 -4
- package/src/compare/proper-nouns.ts +4 -4
- package/src/compare/render.ts +2 -2
- package/src/compare/text-atoms.ts +7 -6
- package/src/compare/text.ts +3 -2
- package/src/config/load.ts +9 -0
- package/src/config/option-problems.ts +6 -4
- package/src/config/style.ts +14 -1
- package/src/custom/load.ts +11 -3
- package/src/custom/module-path.ts +23 -0
- package/src/custom/parse.ts +67 -18
- package/src/custom/problems.ts +63 -41
- package/src/detect-language.ts +1 -1
- package/src/detect.ts +10 -3
- package/src/detectors/ai-phrasing.ts +6 -2
- package/src/detectors/bold-label.ts +55 -0
- package/src/detectors/dangling-figure.ts +8 -4
- package/src/detectors/definition-use.ts +41 -0
- package/src/detectors/doubled-punctuation.ts +5 -2
- package/src/detectors/duplicate-heading.ts +47 -0
- package/src/detectors/empty-section.ts +21 -0
- package/src/detectors/fullwidth-alnum.ts +118 -0
- package/src/detectors/hankaku-kana.ts +38 -0
- package/src/detectors/heading-code-words.ts +2 -2
- package/src/detectors/index.ts +36 -0
- package/src/detectors/invisible-character.ts +190 -0
- package/src/detectors/kutoten-consistency.ts +2 -2
- package/src/detectors/lexicon-match.ts +33 -1
- package/src/detectors/lexicon.ts +40 -13
- package/src/detectors/list-sentence.ts +45 -4
- package/src/detectors/long-vowel.ts +20 -4
- package/src/detectors/markup-finding.ts +16 -1
- package/src/detectors/modal-conflict.ts +26 -0
- package/src/detectors/name-variant.ts +15 -0
- package/src/detectors/nominalization.ts +73 -0
- package/src/detectors/orthography.ts +77 -27
- package/src/detectors/outside-announced-list.ts +25 -0
- package/src/detectors/oxford-comma.ts +1 -0
- package/src/detectors/phrase-match.ts +27 -7
- package/src/detectors/ra-nuki.ts +38 -0
- package/src/detectors/requirement-modal.ts +67 -0
- package/src/detectors/requirement-smell.ts +52 -0
- package/src/detectors/space-before-punctuation.ts +32 -0
- package/src/detectors/spelling-variety.ts +81 -0
- package/src/detectors/structure-tree.ts +3 -1
- package/src/detectors/structure.ts +17 -3
- package/src/detectors/superlative-comparison.ts +47 -0
- package/src/detectors/url-run-on.ts +7 -1
- package/src/detectors/vague-figure-pointer.ts +58 -0
- package/src/detectors/word-list.ts +6 -1
- package/src/document.ts +88 -41
- package/src/extension/document-view.ts +109 -0
- package/src/extension/failure-text.ts +46 -0
- package/src/extension/import-default.ts +13 -0
- package/src/extension/load.ts +97 -0
- package/src/extension/module-detector.ts +61 -0
- package/src/extension/plugin-load.ts +82 -0
- package/src/extension/plugin-name.ts +26 -0
- package/src/extension/plugin-parse.ts +229 -0
- package/src/extension/problem-text.ts +103 -0
- package/src/extension/real-path.ts +10 -0
- package/src/extension/returned-findings.ts +62 -0
- package/src/extension/rule-export.ts +23 -0
- package/src/feedback/draft.ts +6 -0
- package/src/figure-references.ts +73 -12
- package/src/finding-order.ts +3 -0
- package/src/fix-plan/mode.ts +34 -0
- package/src/fix-plan/plan.ts +181 -0
- package/src/fix-plan/render.ts +128 -0
- package/src/fix-plan/text.ts +133 -0
- package/src/language-sample.ts +48 -0
- package/src/link-line.ts +13 -0
- package/src/long-vowel.ts +18 -8
- package/src/markup.ts +4 -2
- package/src/name-variants.ts +217 -0
- package/src/node-version.ts +22 -0
- package/src/not-run.ts +16 -0
- package/src/orthography.ts +40 -11
- package/src/outline/render.ts +85 -0
- package/src/outline/shape.ts +72 -0
- package/src/outline/text.ts +50 -0
- package/src/plugin.ts +21 -4
- package/src/reasons.ts +3 -0
- package/src/render/compact.ts +13 -3
- package/src/render/explain.ts +47 -20
- package/src/render/rules-json.ts +18 -12
- package/src/render/suppressions.ts +30 -2
- package/src/rule-guide.ts +38 -0
- package/src/run-semantic.ts +2 -1
- package/src/run.ts +37 -17
- package/src/setting-problems.ts +3 -1
- package/src/spacing-minority.ts +27 -0
- package/src/stet-block.ts +60 -0
- package/src/stet.ts +41 -15
- package/src/structure/date-range.ts +49 -1
- package/src/structure/definition-use.ts +130 -0
- package/src/structure/lazy-tree.ts +15 -0
- package/src/structure/modal-conflict.ts +86 -0
- package/src/structure/numbered-clauses.ts +11 -0
- package/src/structure/universal.ts +10 -2
- package/src/style-parse.ts +38 -3
- package/src/subheading-line.ts +51 -13
- package/src/tag-coverage.ts +13 -0
- package/styles/ieice.yaml +5 -4
- package/styles/jis-z8301-2011.yaml +5 -2
- package/styles/jis-z8301-2019.yaml +31 -0
- package/styles/koyobun.yaml +35 -0
- package/dist/legal-address.d.ts +0 -2
- package/dist/legal-address.d.ts.map +0 -1
- package/dist/legal-address.js +0 -16
- package/dist/legal-address.js.map +0 -1
package/src/render/compact.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RuleDefinition } from "../plugin.ts";
|
|
1
|
+
import type { Finding, RuleDefinition } from "../plugin.ts";
|
|
2
2
|
import type { RunResult } from "../run.ts";
|
|
3
3
|
import { messageOf } from "./text.ts";
|
|
4
4
|
import { counted } from "./plural.ts";
|
|
@@ -12,14 +12,24 @@ const TALLY: Texts<{ readonly findings: (n: number) => string; readonly notRun:
|
|
|
12
12
|
en: { findings: (n) => counted(n, "finding"), notRun: (n) => `${counted(n, "rule")} not run`, separator: ", " },
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const POSITION_MIN_WIDTH = 8;
|
|
16
|
+
const SEVERITY_WIDTH = 8;
|
|
17
|
+
|
|
18
|
+
const positionOf = (finding: Finding): string => `${String(finding.line)}:${String(finding.column)}`;
|
|
19
|
+
|
|
20
|
+
/** 「行:桁」の列の幅。一番長い位置の後ろにも空白を 1 つ残す。grep や awk が重さの語と区切れるように。 */
|
|
21
|
+
export const positionWidthOf = (findings: readonly Finding[]): number =>
|
|
22
|
+
findings.reduce((width, finding) => Math.max(width, positionOf(finding).length + 1), POSITION_MIN_WIDTH);
|
|
23
|
+
|
|
15
24
|
/** エンジニア向け。1 件 2 行。 */
|
|
16
25
|
export const renderCompact = (header: string, result: RunResult, rules: readonly RuleDefinition[], language: string): string => {
|
|
17
26
|
const byId = new Map(rules.map((rule) => [rule.id, rule]));
|
|
27
|
+
const width = positionWidthOf(result.findings);
|
|
18
28
|
const lines = result.findings.flatMap((finding) => {
|
|
19
29
|
const rule = byId.get(finding.rule);
|
|
20
30
|
if (rule === undefined) return [];
|
|
21
|
-
const
|
|
22
|
-
return [
|
|
31
|
+
const message = ` ${positionOf(finding).padEnd(width)}${finding.severity.padEnd(SEVERITY_WIDTH)}${messageOf(rule, finding, language)}`;
|
|
32
|
+
return [message, ` ${" ".repeat(width + SEVERITY_WIDTH)}${finding.rule}`];
|
|
23
33
|
});
|
|
24
34
|
const text = TALLY[uiLanguageOf(language)];
|
|
25
35
|
const tail = [text.findings(result.findings.length), result.skipped.length > 0 ? text.notRun(result.skipped.length) : undefined].filter(
|
package/src/render/explain.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { definedLevels, resolve, severityAt } from "../levels.ts";
|
|
2
|
-
import { readableText } from "./text.ts";
|
|
2
|
+
import { fill, localized, readableText } from "./text.ts";
|
|
3
3
|
import { SEVERITY_NAME } from "./severity-name.ts";
|
|
4
|
-
import { uiLanguageOf, type Texts
|
|
4
|
+
import { uiLanguageOf, type Texts } from "../ui.ts";
|
|
5
5
|
import type { Level, RuleDefinition } from "../plugin.ts";
|
|
6
6
|
import { optionLines } from "./options.ts";
|
|
7
7
|
import type { OptionLayer } from "../rule-options.ts";
|
|
@@ -13,10 +13,12 @@ const TEXT: Texts<{
|
|
|
13
13
|
readonly experimental: string;
|
|
14
14
|
readonly howToFix: string;
|
|
15
15
|
readonly example: string;
|
|
16
|
-
readonly definedIn: string;
|
|
17
|
-
readonly values:
|
|
16
|
+
readonly definedIn: (plugin: string | undefined) => string;
|
|
17
|
+
readonly values: string;
|
|
18
|
+
readonly times: string;
|
|
18
19
|
readonly severities: string;
|
|
19
20
|
readonly now: (level: string) => string;
|
|
21
|
+
readonly nowNumber: (limit: string) => string;
|
|
20
22
|
readonly from: (source: string) => string;
|
|
21
23
|
readonly change: (id: string) => string;
|
|
22
24
|
}> = {
|
|
@@ -27,10 +29,13 @@ const TEXT: Texts<{
|
|
|
27
29
|
experimental: "このルールはまだ試験中で、既定では動きません(--experimental で動きます)。",
|
|
28
30
|
howToFix: "直しかた",
|
|
29
31
|
example: "例",
|
|
30
|
-
definedIn:
|
|
31
|
-
|
|
32
|
+
definedIn: (plugin) =>
|
|
33
|
+
plugin === undefined ? "このルールはチームが chaff.yaml の custom_rules で決めたものです。" : `このルールはプラグイン ${plugin} のものです。`,
|
|
34
|
+
values: "設定できる値:",
|
|
35
|
+
times: "回",
|
|
32
36
|
severities: "設定できる値(数える上限は無く、指摘の重さが変わります):",
|
|
33
37
|
now: (level) => `いまは ${level} です。`,
|
|
38
|
+
nowNumber: (limit) => `いまは段階ではなく数です: ${limit}。`,
|
|
34
39
|
from: (source) => `(${source} で決めています)`,
|
|
35
40
|
change: (id) => `変える: npx chaff relax ${id} --why "理由"`,
|
|
36
41
|
},
|
|
@@ -41,23 +46,38 @@ const TEXT: Texts<{
|
|
|
41
46
|
experimental: "This rule is still experimental and does not run by default (--experimental runs it).",
|
|
42
47
|
howToFix: "How to fix",
|
|
43
48
|
example: "Example",
|
|
44
|
-
definedIn:
|
|
45
|
-
|
|
49
|
+
definedIn: (plugin) =>
|
|
50
|
+
plugin === undefined ? "The team defined this rule under custom_rules in chaff.yaml." : `This rule comes from the plugin ${plugin}.`,
|
|
51
|
+
values: "Levels:",
|
|
52
|
+
times: "times",
|
|
46
53
|
severities: "Levels (there is no limit to count to; a level sets how a finding is marked):",
|
|
47
54
|
now: (level) => `Now: ${level}.`,
|
|
55
|
+
nowNumber: (limit) => `Now: ${limit}, set as a number rather than a level.`,
|
|
48
56
|
from: (source) => ` (set by ${source})`,
|
|
49
57
|
change: (id) => `Change it: npx chaff relax ${id} --why "reason"`,
|
|
50
58
|
},
|
|
51
59
|
};
|
|
52
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A limit in the rule's words for what it counts ("up to 8 emoji per 1000 words"), as the rule reference shows it.
|
|
63
|
+
* A rule that says nothing (a team's custom rule) counts matches, so its limit is a number of times.
|
|
64
|
+
*/
|
|
65
|
+
const limitText = (rule: RuleDefinition, limit: number, language: string): string => {
|
|
66
|
+
const meaning = localized(rule.guide?.levelMeaning ?? {}, language);
|
|
67
|
+
return meaning === "" ? `${String(limit)} ${TEXT[uiLanguageOf(language)].times}` : fill(meaning, { limit });
|
|
68
|
+
};
|
|
69
|
+
|
|
53
70
|
/** What a level holds: the limit a detector counts to, or the severity a rule with nothing to count gives. */
|
|
54
|
-
const valueAt = (rule: RuleDefinition, level: Exclude<Level, "off">, genre: string | undefined,
|
|
55
|
-
rule.level_sets === "severity"
|
|
71
|
+
const valueAt = (rule: RuleDefinition, level: Exclude<Level, "off">, genre: string | undefined, language: string): string =>
|
|
72
|
+
rule.level_sets === "severity"
|
|
73
|
+
? SEVERITY_NAME[uiLanguageOf(language)][severityAt(rule, level, genre)]
|
|
74
|
+
: limitText(rule, resolve(rule, level, genre).limit, language);
|
|
56
75
|
|
|
57
|
-
|
|
76
|
+
/** current is undefined when a number, not a level, sets the limit: no level is marked. */
|
|
77
|
+
const levelLine = (rule: RuleDefinition, level: Level, current: Level | undefined, genre: string | undefined, language: string): string => {
|
|
58
78
|
const mark = level === current ? "→" : " ";
|
|
59
79
|
const name = level.padEnd(9);
|
|
60
|
-
return level === "off" ? ` ${mark} ${name}${TEXT[
|
|
80
|
+
return level === "off" ? ` ${mark} ${name}${TEXT[uiLanguageOf(language)].off}` : ` ${mark} ${name}${valueAt(rule, level, genre, language)}`;
|
|
61
81
|
};
|
|
62
82
|
|
|
63
83
|
/** ジャンルで数字が変わる rule は、それを言わないと「設定したのに効かない」に見える。 */
|
|
@@ -72,17 +92,24 @@ const exampleLines = (rule: RuleDefinition, language: string, text: (typeof TEXT
|
|
|
72
92
|
const examples = rule.guide?.examples ?? {};
|
|
73
93
|
const example = examples[language] ?? examples["en"] ?? Object.values(examples)[0];
|
|
74
94
|
if (rule.custom === undefined || example === undefined) return [];
|
|
75
|
-
return ["", ` ${text.example}: ${example.before}`, ` → ${example.after}`, "", ` ${text.definedIn}`];
|
|
95
|
+
return ["", ` ${text.example}: ${example.before}`, ` → ${example.after}`, "", ` ${text.definedIn(rule.plugin)}`];
|
|
76
96
|
};
|
|
77
97
|
|
|
78
98
|
/** Where the rule's settings come from: the option layers, strongest first, and the source of its level when a style set it. */
|
|
79
|
-
|
|
99
|
+
/** limit: a number chaff.yaml or its style set for the rule (rules: { id: 80 }, a style's limits), which a level does not show. */
|
|
100
|
+
export type ExplainSettings = {
|
|
101
|
+
readonly optionLayers?: readonly OptionLayer[];
|
|
102
|
+
readonly levelFrom?: string | undefined;
|
|
103
|
+
readonly limit?: number | undefined;
|
|
104
|
+
};
|
|
80
105
|
|
|
81
106
|
/** rule の意図と根拠を読む。指摘に納得できないときの入口。 */
|
|
82
|
-
export const renderExplain = (rule: RuleDefinition, current: Level, language: string,
|
|
107
|
+
export const renderExplain = (rule: RuleDefinition, current: Level, language: string, genre?: string, settings: ExplainSettings = {}): string => {
|
|
83
108
|
const { optionLayers = [], levelFrom } = settings;
|
|
84
|
-
|
|
85
|
-
const
|
|
109
|
+
// A rule with nothing to count has no number to set; chaff.yaml's number on it is reported as a problem and ignored.
|
|
110
|
+
const limit = rule.level_sets === "severity" ? undefined : settings.limit;
|
|
111
|
+
const marked = limit === undefined ? current : undefined;
|
|
112
|
+
const text = TEXT[uiLanguageOf(language)];
|
|
86
113
|
const experimental = rule.status === "experimental" ? [` ${text.experimental}`] : [];
|
|
87
114
|
return [
|
|
88
115
|
"",
|
|
@@ -93,12 +120,12 @@ export const renderExplain = (rule: RuleDefinition, current: Level, language: st
|
|
|
93
120
|
` ${text.howToFix}: ${readableText(rule, rule.how_to_fix, language)}`,
|
|
94
121
|
...exampleLines(rule, language, text),
|
|
95
122
|
"",
|
|
96
|
-
` ${rule.level_sets === "severity" ? text.severities : text.values
|
|
97
|
-
...definedLevels(rule).map((level) => levelLine(rule, level,
|
|
123
|
+
` ${rule.level_sets === "severity" ? text.severities : text.values}`,
|
|
124
|
+
...definedLevels(rule).map((level) => levelLine(rule, level, marked, genre, language)),
|
|
98
125
|
...genreNote(rule, genre, text),
|
|
99
126
|
...optionLines(rule, optionLayers, language),
|
|
100
127
|
"",
|
|
101
|
-
` ${text.now(current)}${levelFrom === undefined ? "" : text.from(levelFrom)}`,
|
|
128
|
+
` ${limit === undefined ? text.now(current) : text.nowNumber(limitText(rule, limit, language))}${levelFrom === undefined ? "" : text.from(levelFrom)}`,
|
|
102
129
|
...experimental,
|
|
103
130
|
"",
|
|
104
131
|
` ${text.change(rule.id)}`,
|
package/src/render/rules-json.ts
CHANGED
|
@@ -8,9 +8,10 @@ import { presetLevelsOf, type PresetLevels } from "../genre-parse.ts";
|
|
|
8
8
|
import { RULE_GROUPS, groupTextOf } from "../rule-guide.ts";
|
|
9
9
|
import { standingIn } from "../rule-genres.ts";
|
|
10
10
|
import { optionsJson } from "./options.ts";
|
|
11
|
-
import { styleLevelSource } from "../config/style.ts";
|
|
11
|
+
import { limitsFor, styleLevelSource } from "../config/style.ts";
|
|
12
12
|
import { loadStyles } from "../style-load.ts";
|
|
13
13
|
import type { OptionLayer } from "../rule-options.ts";
|
|
14
|
+
import { CUSTOM_TYPES } from "../custom/parse.ts";
|
|
14
15
|
|
|
15
16
|
const TEXT: Texts<{
|
|
16
17
|
readonly offBySetting: string;
|
|
@@ -59,13 +60,15 @@ const TEXT: Texts<{
|
|
|
59
60
|
},
|
|
60
61
|
};
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
type Limits = Readonly<Record<string, number>>;
|
|
64
|
+
|
|
65
|
+
const now = (rule: RuleDefinition, config: Config, limits: Limits, genre: string, text: (typeof TEXT)["ja"], preset: PresetLevels): Record<string, unknown> => {
|
|
63
66
|
// A run leaves out a rule whose use_for does not cover the genre before it reads any level.
|
|
64
67
|
if (standingIn(rule, genre, {}).kind === "unsuited") return { level: "off", why_off: text.offUnsuited(genre) };
|
|
65
68
|
const explicit = config.rules[rule.id] ?? preset[rule.id];
|
|
66
69
|
if (explicit === "off" && config.rules[rule.id] === undefined) return { level: "off", why_off: text.offByGenre(genre) };
|
|
67
70
|
if (explicit === "off") return { level: "off", why_off: text.offBySetting };
|
|
68
|
-
const limit = rule.level_sets === "severity" ? undefined :
|
|
71
|
+
const limit = rule.level_sets === "severity" ? undefined : limits[rule.id];
|
|
69
72
|
if (limit !== undefined) return { level: "normal", limit, set_as: "number" };
|
|
70
73
|
if (explicit !== undefined) return { level: explicit, ...effectAt(rule, explicit, genre) };
|
|
71
74
|
if (rule.status === "experimental" && !config.experimental) {
|
|
@@ -76,23 +79,23 @@ const now = (rule: RuleDefinition, config: Config, genre: string, text: (typeof
|
|
|
76
79
|
|
|
77
80
|
/** The level a rule runs at now, and why it is off when it is: what `chaff rules` shows in its table. */
|
|
78
81
|
export const nowFor = (rule: RuleDefinition, config: Config, language: string, genre: string): Record<string, unknown> =>
|
|
79
|
-
now(rule, config, genre, TEXT[uiLanguageOf(language)], presetLevels(genre));
|
|
82
|
+
now(rule, config, limitsFor(config, language), genre, TEXT[uiLanguageOf(language)], presetLevels(genre));
|
|
80
83
|
|
|
81
84
|
/** What a level does to a rule: the limit it counts to, or, with nothing to count, the severity of its findings. */
|
|
82
85
|
const effectAt = (rule: RuleDefinition, level: Exclude<Level, "off">, genre: string): Record<string, unknown> =>
|
|
83
86
|
rule.level_sets === "severity" ? { severity: severityAt(rule, level, genre) } : { limit: resolve(rule, level, genre).limit };
|
|
84
87
|
|
|
85
|
-
const yourSetting = (rule: RuleDefinition, config: Config): Record<string, unknown> | null => {
|
|
88
|
+
const yourSetting = (rule: RuleDefinition, config: Config, limits: Limits): Record<string, unknown> | null => {
|
|
86
89
|
const level = config.rules[rule.id];
|
|
87
90
|
if (level === undefined) return null;
|
|
88
91
|
const from = styleLevelSource(config, rule.id) ?? config.path;
|
|
89
|
-
const limit = rule.level_sets === "severity" ? undefined :
|
|
92
|
+
const limit = rule.level_sets === "severity" ? undefined : limits[rule.id];
|
|
90
93
|
return limit === undefined ? { level, from } : { level, limit, from };
|
|
91
94
|
};
|
|
92
95
|
|
|
93
96
|
/** The house style chaff.yaml names: what it decides and the guideline it follows, so an AI can say where a setting came from. */
|
|
94
97
|
const styleOf = (config: Config): Record<string, unknown> | null => {
|
|
95
|
-
const style = loadStyles().find((entry) => entry.id === config.applied?.style);
|
|
98
|
+
const style = [...loadStyles(), ...(config.extensions?.styles ?? [])].find((entry) => entry.id === config.applied?.style);
|
|
96
99
|
return style === undefined ? null : { id: style.id, name: style.name, summary: style.summary, source: style.source };
|
|
97
100
|
};
|
|
98
101
|
|
|
@@ -153,11 +156,11 @@ const groupsOf = (): Record<string, unknown>[] =>
|
|
|
153
156
|
|
|
154
157
|
/**
|
|
155
158
|
* What the local-rules release adds. Named now so an AI reading the JSON knows they are coming and does not invent them.
|
|
156
|
-
* Filled in
|
|
159
|
+
* Filled in as they ship: the style presets under style:, each rule's options. The custom_rules types have shipped.
|
|
157
160
|
*/
|
|
158
161
|
const COMING = {
|
|
159
162
|
style_presets: { status: "coming", presets: [] },
|
|
160
|
-
custom_rule_types: { status: "
|
|
163
|
+
custom_rule_types: { status: "available", types: CUSTOM_TYPES },
|
|
161
164
|
rule_options: { status: "coming", note: "Each rule's options (with their types and allowed values) will be listed under options." },
|
|
162
165
|
};
|
|
163
166
|
|
|
@@ -171,6 +174,7 @@ export const rulesJson = (
|
|
|
171
174
|
): string => {
|
|
172
175
|
const text = TEXT[uiLanguageOf(language)];
|
|
173
176
|
const preset = presetLevels(genre);
|
|
177
|
+
const limits = limitsFor(config, language);
|
|
174
178
|
return JSON.stringify(
|
|
175
179
|
{
|
|
176
180
|
// 2: rules gained group, summary, example, not_flagged, level_meaning, languages, requires and genres,
|
|
@@ -194,10 +198,12 @@ export const rulesJson = (
|
|
|
194
198
|
level_sets: rule.level_sets,
|
|
195
199
|
...levelsOf(rule, genre),
|
|
196
200
|
levels_you_can_set: definedLevels(rule),
|
|
197
|
-
your_setting: yourSetting(rule, config),
|
|
198
|
-
now: now(rule, config, genre, text, preset),
|
|
201
|
+
your_setting: yourSetting(rule, config, limits),
|
|
202
|
+
now: now(rule, config, limits, genre, text, preset),
|
|
199
203
|
...(rule.options === undefined ? {} : { options: optionsJson(rule, optionLayers) }),
|
|
200
|
-
...(rule.custom === undefined
|
|
204
|
+
...(rule.custom === undefined
|
|
205
|
+
? {}
|
|
206
|
+
: { defined_in: rule.plugin === undefined ? "chaff.yaml custom_rules" : `plugin ${rule.plugin}`, custom: rule.custom }),
|
|
201
207
|
...guideOf(rule),
|
|
202
208
|
})),
|
|
203
209
|
how_to_write_settings_from_a_style_note: text.fromStyleNote,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Suppressed, Suppression } from "../stet.ts";
|
|
2
|
+
import type { NotRun } from "../not-run.ts";
|
|
2
3
|
import type { Texts, UiLanguage } from "../ui.ts";
|
|
3
4
|
import { counted } from "./plural.ts";
|
|
4
5
|
|
|
@@ -11,6 +12,8 @@ const TEXT: Texts<{
|
|
|
11
12
|
readonly none: string;
|
|
12
13
|
readonly total: (n: number) => string;
|
|
13
14
|
readonly reasonless: (n: number) => string;
|
|
15
|
+
readonly notRun: string;
|
|
16
|
+
readonly runExperimental: string;
|
|
14
17
|
}> = {
|
|
15
18
|
ja: {
|
|
16
19
|
nudge: " ← 設定の見直しを検討してください",
|
|
@@ -21,6 +24,8 @@ const TEXT: Texts<{
|
|
|
21
24
|
none: "\n 抑制されている指摘はありません。\n",
|
|
22
25
|
total: (n) => `抑制されている指摘: ${n} 件`,
|
|
23
26
|
reasonless: (n) => `理由が書かれていない抑制: ${n} 件`,
|
|
27
|
+
notRun: "stet はあるが、今回動いていない rule(数えていません):",
|
|
28
|
+
runExperimental: "試験中の rule は --experimental を付けると数えます。",
|
|
24
29
|
},
|
|
25
30
|
en: {
|
|
26
31
|
nudge: " <- consider changing the setting instead",
|
|
@@ -31,10 +36,18 @@ const TEXT: Texts<{
|
|
|
31
36
|
none: "\n No findings are silenced.\n",
|
|
32
37
|
total: (n) => `Silenced findings: ${n}`,
|
|
33
38
|
reasonless: (n) => `Silenced without a reason: ${n}`,
|
|
39
|
+
notRun: "Rules with a stet that did not run in this check (not counted):",
|
|
40
|
+
runExperimental: "Experimental rules are counted with --experimental.",
|
|
34
41
|
},
|
|
35
42
|
};
|
|
36
43
|
|
|
37
|
-
export type PerFile = {
|
|
44
|
+
export type PerFile = {
|
|
45
|
+
readonly path: string;
|
|
46
|
+
readonly suppressed: readonly Suppressed[];
|
|
47
|
+
readonly reasonless: readonly Suppression[];
|
|
48
|
+
/** Rules a stet in the file names that did not run, so their silenced findings could not be counted. */
|
|
49
|
+
readonly notRun: readonly NotRun[];
|
|
50
|
+
};
|
|
38
51
|
|
|
39
52
|
/** これを超えたら、その rule は (b) ではなく (c) にすべきというサイン。 */
|
|
40
53
|
const NUDGE_AT = 5;
|
|
@@ -72,6 +85,19 @@ const groupLines = (group: Group, ui: UiLanguage): string[] => {
|
|
|
72
85
|
];
|
|
73
86
|
};
|
|
74
87
|
|
|
88
|
+
/** The rules whose stets were not counted because the rule did not run, one line each, with why and where. */
|
|
89
|
+
const notRunLines = (files: readonly PerFile[], ui: UiLanguage): string[] => {
|
|
90
|
+
const text = TEXT[ui];
|
|
91
|
+
const rows = files.flatMap((file) => file.notRun.map((entry) => ({ ...entry, path: file.path })));
|
|
92
|
+
if (rows.length === 0) return [];
|
|
93
|
+
const rules = [...new Set(rows.map((row) => row.rule))];
|
|
94
|
+
const lines = rules.map((rule) => {
|
|
95
|
+
const mine = rows.filter((row) => row.rule === rule);
|
|
96
|
+
return ` ${rule.padEnd(26)}${mine[0]?.why ?? ""} ${[...new Set(mine.map((row) => row.path))].join(", ")}`;
|
|
97
|
+
});
|
|
98
|
+
return ["", ` ${text.notRun}`, ...lines, ...(rows.some((row) => row.needsExperimental) ? [` ${text.runExperimental}`] : [])];
|
|
99
|
+
};
|
|
100
|
+
|
|
75
101
|
/**
|
|
76
102
|
* 抑制が溜まったことに気づけないと、規範と現実の乖離が静かに進む。
|
|
77
103
|
* 同じ rule を何度も黙らせているなら、それは (b) ではなく (c) のサイン。
|
|
@@ -81,13 +107,15 @@ export const renderSuppressions = (files: readonly PerFile[], ui: UiLanguage = "
|
|
|
81
107
|
const text = TEXT[ui];
|
|
82
108
|
const groups = groupByRule(files);
|
|
83
109
|
const total = groups.reduce((sum, group) => sum + group.count, 0);
|
|
84
|
-
|
|
110
|
+
const notRun = notRunLines(files, ui);
|
|
111
|
+
if (total === 0) return notRun.length === 0 ? text.none : [text.none.trimEnd(), ...notRun, ""].join("\n");
|
|
85
112
|
const reasonless = files.flatMap((file) => file.reasonless.map(() => file.path));
|
|
86
113
|
return [
|
|
87
114
|
"",
|
|
88
115
|
` ${text.total(total)}`,
|
|
89
116
|
...groups.flatMap((group) => groupLines(group, ui)),
|
|
90
117
|
...(reasonless.length > 0 ? ["", ` ${text.reasonless(reasonless.length)}`, ` ${[...new Set(reasonless)].join(", ")}`] : []),
|
|
118
|
+
...notRun,
|
|
91
119
|
"",
|
|
92
120
|
].join("\n");
|
|
93
121
|
};
|
package/src/rule-guide.ts
CHANGED
|
@@ -80,6 +80,20 @@ export type ExampleOutcome = {
|
|
|
80
80
|
readonly after: readonly ExampleFinding[];
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
/** One spot written the way the rule flags it, and the same spot rewritten without adding a fact. */
|
|
84
|
+
export type RewritePair = { readonly before: string; readonly after: string };
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* How to rewrite a spot the rule flags, for an AI or a person doing the fix (chaff fix-plan prints it).
|
|
88
|
+
* direction: what to do; keep: what must not change; avoid: the mistakes a rewriter makes here.
|
|
89
|
+
*/
|
|
90
|
+
export type RuleRewrite = {
|
|
91
|
+
readonly direction: string;
|
|
92
|
+
readonly pairs: readonly RewritePair[];
|
|
93
|
+
readonly keep: readonly string[];
|
|
94
|
+
readonly avoid: readonly string[];
|
|
95
|
+
};
|
|
96
|
+
|
|
83
97
|
/** The plain-language part of a rule file: what the reference tells a reader, apart from the texts chaff prints. */
|
|
84
98
|
export type RuleGuide = {
|
|
85
99
|
readonly group: RuleGroup | undefined;
|
|
@@ -91,6 +105,10 @@ export type RuleGuide = {
|
|
|
91
105
|
readonly notFlagged: Localized;
|
|
92
106
|
/** What a level's number means, with {limit} for the number ("一文 {limit} 字まで"). None when every level is the same. */
|
|
93
107
|
readonly levelMeaning: Localized;
|
|
108
|
+
/** The bibliography entries the rule rests on: the anchors of site/src/content/guide/{ja,en}/bibliography.md. */
|
|
109
|
+
readonly sources: readonly string[];
|
|
110
|
+
/** By language, optional per rule. */
|
|
111
|
+
readonly rewrite: Readonly<Record<string, RuleRewrite>>;
|
|
94
112
|
};
|
|
95
113
|
|
|
96
114
|
const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -121,6 +139,24 @@ const examplesOf = (value: unknown): Readonly<Record<string, RuleExample>> =>
|
|
|
121
139
|
)
|
|
122
140
|
: {};
|
|
123
141
|
|
|
142
|
+
const textsOf = (value: unknown): string[] => (Array.isArray(value) ? value.filter(isText) : []);
|
|
143
|
+
|
|
144
|
+
const pairOf = (value: unknown): RewritePair[] =>
|
|
145
|
+
isRecord(value) && isText(value["before"]) && isText(value["after"]) ? [{ before: value["before"], after: value["after"] }] : [];
|
|
146
|
+
|
|
147
|
+
/** A block that is written reads field by field; what is missing reads as empty, and the test on rule files names it. */
|
|
148
|
+
const rewriteOf = (value: Readonly<Record<string, unknown>>): RuleRewrite => ({
|
|
149
|
+
direction: isText(value["direction"]) ? value["direction"] : "",
|
|
150
|
+
pairs: Array.isArray(value["pairs"]) ? value["pairs"].flatMap(pairOf) : [],
|
|
151
|
+
keep: textsOf(value["keep"]),
|
|
152
|
+
avoid: textsOf(value["avoid"]),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const rewritesOf = (value: unknown): Readonly<Record<string, RuleRewrite>> =>
|
|
156
|
+
isRecord(value)
|
|
157
|
+
? Object.fromEntries(Object.entries(value).flatMap(([language, entry]) => (isRecord(entry) ? [[language, rewriteOf(entry)] as const] : [])))
|
|
158
|
+
: {};
|
|
159
|
+
|
|
124
160
|
/** A field that is missing or malformed reads as empty; the test on rule files names what a rule lacks. */
|
|
125
161
|
export const ruleGuideOf = (raw: Readonly<Record<string, unknown>>): RuleGuide => ({
|
|
126
162
|
group: RULE_GROUPS.find((group) => group === raw["group"]),
|
|
@@ -128,6 +164,8 @@ export const ruleGuideOf = (raw: Readonly<Record<string, unknown>>): RuleGuide =
|
|
|
128
164
|
examples: examplesOf(raw["example"]),
|
|
129
165
|
notFlagged: localizedOf(raw["not_flagged"]),
|
|
130
166
|
levelMeaning: localizedOf(raw["level_meaning"]),
|
|
167
|
+
sources: textsOf(raw["sources"]),
|
|
168
|
+
rewrite: rewritesOf(raw["rewrite"]),
|
|
131
169
|
});
|
|
132
170
|
|
|
133
171
|
/** 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. */
|
package/src/run-semantic.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { localized } from "./render/text.ts";
|
|
|
6
6
|
import type { AdapterNeeds, Finding, Level, ProseDocument, RuleDefinition, Severity } from "./plugin.ts";
|
|
7
7
|
import { lineStarts, placeOf } from "./position.ts";
|
|
8
8
|
import { wantsTags } from "./run.ts";
|
|
9
|
+
import { byPosition } from "./finding-order.ts";
|
|
9
10
|
|
|
10
11
|
export type SemanticResult = {
|
|
11
12
|
readonly findings: readonly Finding[];
|
|
@@ -137,7 +138,7 @@ export const runSemantic = async (
|
|
|
137
138
|
),
|
|
138
139
|
);
|
|
139
140
|
return {
|
|
140
|
-
findings: answers.filter((finding) => finding !== undefined).toSorted(
|
|
141
|
+
findings: answers.filter((finding) => finding !== undefined).toSorted(byPosition),
|
|
141
142
|
skipped,
|
|
142
143
|
asked: live.reduce((sum, job) => sum + job.candidates.length, 0),
|
|
143
144
|
sentencesSeen: doc.sentences.length,
|
package/src/run.ts
CHANGED
|
@@ -13,9 +13,18 @@ import { uiLanguageOf } from "./ui.ts";
|
|
|
13
13
|
import { presetLevels } from "./genre-load.ts";
|
|
14
14
|
import { bodySectionOf } from "./body-section.ts";
|
|
15
15
|
import { optionValues, settleOptions, type OptionLayer } from "./rule-options.ts";
|
|
16
|
+
import { byPosition } from "./finding-order.ts";
|
|
16
17
|
import { PatternTimeout } from "./custom/bounded-match.ts";
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
import { PluginRuleFailure } from "./extension/module-detector.ts";
|
|
19
|
+
import { failureReason } from "./extension/failure-text.ts";
|
|
20
|
+
import { tagCoverage } from "./tag-coverage.ts";
|
|
21
|
+
|
|
22
|
+
export type Skipped = {
|
|
23
|
+
readonly rule: string;
|
|
24
|
+
readonly why: string;
|
|
25
|
+
/** Off only because it is experimental: --experimental (or chaff.yaml's experimental) would run it. */
|
|
26
|
+
readonly offUntilExperimental?: true;
|
|
27
|
+
};
|
|
19
28
|
|
|
20
29
|
export type RunResult = {
|
|
21
30
|
readonly findings: readonly Finding[];
|
|
@@ -40,9 +49,10 @@ const levelFor = (rule: RuleDefinition, settings: Settings, experimental: boolea
|
|
|
40
49
|
};
|
|
41
50
|
|
|
42
51
|
/** Why a rule at off did not run: chaff.yaml turned it off, the genre's preset did, or it is experimental. */
|
|
43
|
-
const
|
|
44
|
-
if (settings[rule.id] !== undefined) return reasons.turnedOff;
|
|
45
|
-
|
|
52
|
+
const offSkip = (rule: RuleDefinition, settings: Settings, preset: Settings, genre: string, reasons: Reasons): Skipped => {
|
|
53
|
+
if (settings[rule.id] !== undefined) return { rule: rule.id, why: reasons.turnedOff };
|
|
54
|
+
if (preset[rule.id] !== undefined) return { rule: rule.id, why: reasons.presetOff(genre) };
|
|
55
|
+
return { rule: rule.id, why: reasons.experimental, offUntilExperimental: true };
|
|
46
56
|
};
|
|
47
57
|
|
|
48
58
|
const reasonsFor = (doc: ProseDocument): Reasons => REASONS[uiLanguageOf(doc.language)];
|
|
@@ -102,9 +112,13 @@ const has = (capabilities: ProseDocument["capabilities"], need: string): boolean
|
|
|
102
112
|
*
|
|
103
113
|
* `capabilities.pos: true` と言いながら token を返さないアダプタでも、rule は
|
|
104
114
|
* `sentence.tokens ?? []` を見るので**例外にならず、指摘 0 件で終わる**。
|
|
105
|
-
* 0
|
|
115
|
+
* 0 件は「問題なし」と見分けがつかない。一部の文にだけ token が無いとき(解析器が読めなかった段落)も、その段落の 0 件が同じく保証に見える。
|
|
106
116
|
*/
|
|
107
|
-
const
|
|
117
|
+
const tagReason = (doc: ProseDocument): string | undefined => {
|
|
118
|
+
const coverage = tagCoverage(doc.sentences);
|
|
119
|
+
if (coverage === "all") return undefined;
|
|
120
|
+
return coverage === "none" ? reasonsFor(doc).noTags : reasonsFor(doc).unreadTags;
|
|
121
|
+
};
|
|
108
122
|
|
|
109
123
|
/** 要求を満たさない rule は動かせない。満たさないまま動かすと「指摘 0 件」が保証に見える。 */
|
|
110
124
|
const unmet = (rule: RuleDefinition, doc: ProseDocument): string | undefined => {
|
|
@@ -119,7 +133,7 @@ const unmet = (rule: RuleDefinition, doc: ProseDocument): string | undefined =>
|
|
|
119
133
|
* 先に聞くと、止めている rule まで「アダプタが品詞を返さなかった」と、違う理由で出る。
|
|
120
134
|
*/
|
|
121
135
|
const untagged = (rule: RuleDefinition, doc: ProseDocument): string | undefined =>
|
|
122
|
-
rule.requires.some((need) => need === "pos" || need === "lemma")
|
|
136
|
+
rule.requires.some((need) => need === "pos" || need === "lemma") ? tagReason(doc) : undefined;
|
|
123
137
|
|
|
124
138
|
const forGenre = (rules: readonly RuleDefinition[], genre: string): RuleDefinition[] =>
|
|
125
139
|
rules.filter((rule) => rule.use_for.some((target) => genre.startsWith(target)));
|
|
@@ -141,16 +155,21 @@ export const neededBy = (rules: readonly RuleDefinition[], settings: Settings, e
|
|
|
141
155
|
/** The token features the rules read (RuleDefinition.token_features), each once. */
|
|
142
156
|
export const tokenFeaturesOf = (rules: readonly RuleDefinition[]): string[] => [...new Set(rules.flatMap((rule) => rule.token_features ?? []))];
|
|
143
157
|
|
|
144
|
-
/**
|
|
158
|
+
/**
|
|
159
|
+
* A detector's findings, or why the rule did not run: a team's pattern stopped at its time limit (bounded-match.ts), or a
|
|
160
|
+
* plugin's detector that threw or returned something else than findings (module-detector.ts). Other errors are chaff's
|
|
161
|
+
* bugs and propagate.
|
|
162
|
+
*/
|
|
145
163
|
const runDetector = (
|
|
146
164
|
detector: Detector,
|
|
147
165
|
doc: ProseDocument,
|
|
148
166
|
options: DetectorOptions,
|
|
149
|
-
): { readonly findings: readonly Finding[] } | { readonly
|
|
167
|
+
): { readonly findings: readonly Finding[] } | { readonly notRun: string } => {
|
|
150
168
|
try {
|
|
151
169
|
return { findings: detector(doc, options) };
|
|
152
170
|
} catch (error) {
|
|
153
|
-
if (error instanceof PatternTimeout) return {
|
|
171
|
+
if (error instanceof PatternTimeout) return { notRun: reasonsFor(doc).patternTimeout(error.budget_ms) };
|
|
172
|
+
if (error instanceof PluginRuleFailure) return { notRun: failureReason(error.origin, error.failure, uiLanguageOf(doc.language)) };
|
|
154
173
|
throw error;
|
|
155
174
|
}
|
|
156
175
|
};
|
|
@@ -210,6 +229,8 @@ export type RunContext = {
|
|
|
210
229
|
readonly limits?: Limits;
|
|
211
230
|
/** Where rule options come from, strongest first (chaff.yaml). An option no layer sets is at its default. */
|
|
212
231
|
readonly optionLayers?: readonly OptionLayer[];
|
|
232
|
+
/** The detectors loaded from the code chaff.yaml names, by rule id. They come before chaff's own table. */
|
|
233
|
+
readonly detectors?: Readonly<Record<string, Detector>>;
|
|
213
234
|
};
|
|
214
235
|
|
|
215
236
|
export const runRules = (
|
|
@@ -222,7 +243,7 @@ export const runRules = (
|
|
|
222
243
|
): RunResult => runRulesWith(doc, rules, { settings, experimental, genre, limits });
|
|
223
244
|
|
|
224
245
|
export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[], context: RunContext): RunResult => {
|
|
225
|
-
const { settings, experimental, genre, limits = {}, optionLayers = [] } = context;
|
|
246
|
+
const { settings, experimental, genre, limits = {}, optionLayers = [], detectors = {} } = context;
|
|
226
247
|
const preset = presetLevels(genre);
|
|
227
248
|
const starts = lineStarts(doc.source);
|
|
228
249
|
const applicable = forGenre(rules, genre);
|
|
@@ -239,8 +260,7 @@ export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[
|
|
|
239
260
|
const blocked = unmet(rule, doc);
|
|
240
261
|
if (blocked !== undefined) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: blocked }] };
|
|
241
262
|
const level = levelFor(rule, settings, experimental, preset);
|
|
242
|
-
if (level === "off")
|
|
243
|
-
return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: offReason(rule, settings, preset, genre, reasonsFor(doc)) }] };
|
|
263
|
+
if (level === "off") return { findings: acc.findings, skipped: [...acc.skipped, offSkip(rule, settings, preset, genre, reasonsFor(doc))] };
|
|
244
264
|
const noTags = untagged(rule, doc);
|
|
245
265
|
if (noTags !== undefined) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: noTags }] };
|
|
246
266
|
// 木は capability ではなく、adapter が structure を持つかで決まる。持たない言語で動かすと「参照先が無い」が 0 件に見える。
|
|
@@ -251,7 +271,7 @@ export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[
|
|
|
251
271
|
if (noDocumentNeed !== undefined) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: noDocumentNeed }] };
|
|
252
272
|
// 複合シグナルは二段目で扱う。一段目では「検出器が無い」と言わせない。
|
|
253
273
|
if (rule.from.length > 0) return acc;
|
|
254
|
-
const detector = DETECTORS[rule.how_to_find];
|
|
274
|
+
const detector = detectors[rule.id] ?? DETECTORS[rule.how_to_find];
|
|
255
275
|
if (detector === undefined)
|
|
256
276
|
return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: reasonsFor(doc).noDetector(rule.how_to_find) }] };
|
|
257
277
|
// 語彙表を要求する rule で、その言語に語彙表が無ければ動かせない。黙って通さない。
|
|
@@ -268,7 +288,7 @@ export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[
|
|
|
268
288
|
...(rule.custom === undefined ? {} : { custom: rule.custom }),
|
|
269
289
|
};
|
|
270
290
|
const ran = runDetector(detector, doc, options);
|
|
271
|
-
if ("
|
|
291
|
+
if ("notRun" in ran) return { findings: acc.findings, skipped: [...acc.skipped, { rule: rule.id, why: ran.notRun }] };
|
|
272
292
|
const found = ran.findings.map((finding) => place(starts, { ...finding, rule: rule.id, severity: severityAt(rule, level, genre) }));
|
|
273
293
|
return { findings: [...acc.findings, ...found], skipped: acc.skipped };
|
|
274
294
|
},
|
|
@@ -280,5 +300,5 @@ export const runRulesWith = (doc: ProseDocument, rules: readonly RuleDefinition[
|
|
|
280
300
|
compositeOf(rule, outcome.findings, limitFor(rule, levelFor(rule, settings, experimental, preset), genre, limits), starts, doc.language),
|
|
281
301
|
);
|
|
282
302
|
const all = [...outcome.findings, ...composites];
|
|
283
|
-
return { ...outcome, findings: all.toSorted(
|
|
303
|
+
return { ...outcome, findings: all.toSorted(byPosition), forcedExperimental: forced, presetExperimental: presetOn };
|
|
284
304
|
};
|
package/src/setting-problems.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { UiLanguage } from "./ui.ts";
|
|
|
4
4
|
import { styleProblems } from "./config/style.ts";
|
|
5
5
|
import { loadStyles } from "./style-load.ts";
|
|
6
6
|
import { customRuleProblems } from "./custom/problems.ts";
|
|
7
|
+
import { extensionProblems } from "./extension/problem-text.ts";
|
|
7
8
|
import { GENRES } from "./genre.ts";
|
|
8
9
|
import { unknownGenres, writtenGenres } from "./genre-check.ts";
|
|
9
10
|
import { loadProfiles } from "./profile/load.ts";
|
|
@@ -25,6 +26,7 @@ const profileProblems = (command: string, config: Config, text: CliText): string
|
|
|
25
26
|
export const settingProblems = (command: string, genreFlag: string | undefined, config: Config, text: CliText, ui: UiLanguage = "en"): string[] => [
|
|
26
27
|
...genreProblems(command, genreFlag, config, text),
|
|
27
28
|
...profileProblems(command, config, text),
|
|
28
|
-
...styleProblems(config, loadStyles(), ui),
|
|
29
|
+
...styleProblems(config, [...loadStyles(), ...(config.extensions?.styles ?? [])], ui),
|
|
29
30
|
...customRuleProblems(config, ui),
|
|
31
|
+
...extensionProblems(config, ui),
|
|
30
32
|
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { minorityStyle } from "./orthography.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 少ないほうがこの割合を超えると、書き損じではなく、書き方が二通りある文書と読む。1 箇所ずつ「違う」と指すと、
|
|
5
|
+
* 半々に近い文書でどちらかの側に立つことになる。そのときは 1 件にまとめて、両方の数を言う。
|
|
6
|
+
*/
|
|
7
|
+
const MIXED_SHARE = 0.2;
|
|
8
|
+
|
|
9
|
+
/** 割合が大きくても、これより少なければ 1 箇所ずつ言う。3 箇所のうち 1 箇所なら、その 1 箇所を見せるほうが早い。 */
|
|
10
|
+
const MIN_MIXED = 5;
|
|
11
|
+
|
|
12
|
+
/** each は少ないほうを 1 箇所ずつ、mixed は文書に書き方が二通りあることを 1 件で。first は少ないほうの最初の箇所。 */
|
|
13
|
+
export type MinorityReport<T> =
|
|
14
|
+
| { readonly mode: "each"; readonly odd: readonly T[] }
|
|
15
|
+
| { readonly mode: "mixed"; readonly first: T; readonly odd: number; readonly spaced: number; readonly touching: number };
|
|
16
|
+
|
|
17
|
+
/** 一つの種類の境目から、何をどう言うか。混ざっていない、または少ないほうが limit に届かなければ言わない。 */
|
|
18
|
+
export const minorityReport = <T extends { readonly spaced: boolean }>(ofKind: readonly T[], limit: number): MinorityReport<T> | undefined => {
|
|
19
|
+
const minority = minorityStyle(ofKind);
|
|
20
|
+
if (minority === undefined) return undefined;
|
|
21
|
+
const odd = ofKind.filter((entry) => entry.spaced === minority);
|
|
22
|
+
const first = odd[0];
|
|
23
|
+
if (first === undefined || odd.length < limit) return undefined;
|
|
24
|
+
if (odd.length < MIN_MIXED || odd.length <= ofKind.length * MIXED_SHARE) return { mode: "each", odd };
|
|
25
|
+
const spaced = ofKind.filter((entry) => entry.spaced).length;
|
|
26
|
+
return { mode: "mixed", first, odd: odd.length, spaced, touching: ofKind.length - spaced };
|
|
27
|
+
};
|