chaffjs 0.17.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 +2 -0
- package/dist/calendar-number.d.ts.map +1 -1
- package/dist/calendar-number.js +9 -2
- 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/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 +2 -4
- 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 +2 -0
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +12 -4
- package/dist/detectors/acronym-context.js.map +1 -1
- 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/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/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 +7 -4
- 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/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 +34 -1
- 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/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/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 +14 -10
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts +7 -1
- package/dist/detectors/oxford-comma.d.ts.map +1 -1
- package/dist/detectors/oxford-comma.js +135 -229
- package/dist/detectors/oxford-comma.js.map +1 -1
- 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 +67 -46
- package/dist/detectors/signals.js.map +1 -1
- 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 +1 -3
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +3 -4
- 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 +90 -98
- 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/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 +33 -10
- 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.js +8 -5
- 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 +119 -17
- package/dist/number-name.js.map +1 -1
- package/dist/orthography.d.ts +2 -0
- package/dist/orthography.d.ts.map +1 -1
- package/dist/orthography.js +9 -4
- 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/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 +115 -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.map +1 -1
- package/dist/quoted-span.js +8 -3
- 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 +87 -33
- 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.d.ts +13 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +54 -10
- package/dist/run.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/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 +76 -30
- 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/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 +26 -0
- 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 +14 -1
- 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 +28 -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 +31 -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 +33 -0
- package/rules/max-sentence-length.yaml +32 -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 +18 -0
- 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 +18 -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 +22 -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 +18 -4
- package/src/cli-args.ts +6 -0
- package/src/cli-text.ts +8 -4
- package/src/cli.ts +37 -37
- 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 +2 -4
- 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 +16 -4
- 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/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/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 +8 -4
- package/src/detectors/heading-level-skip.ts +19 -0
- package/src/detectors/image-alt-text.ts +11 -0
- package/src/detectors/index.ts +43 -1
- package/src/detectors/kutoten-consistency.ts +96 -0
- package/src/detectors/lead-in.ts +3 -1
- package/src/detectors/lexicon-match.ts +9 -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 +23 -17
- package/src/detectors/oxford-comma.ts +178 -283
- 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 +80 -46
- package/src/detectors/structure-tree.ts +45 -1
- package/src/detectors/structure.ts +3 -4
- 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 +106 -138
- 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/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 +52 -9
- 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 +8 -8
- package/src/number-name.ts +151 -24
- package/src/orthography.ts +10 -3
- package/src/page-furniture.ts +11 -2
- package/src/plain-source.ts +2 -1
- package/src/plugin.ts +101 -1
- package/src/profile/for-file.ts +3 -1
- package/src/quoted-span.ts +9 -3
- 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 +91 -34
- package/src/rule-options.ts +131 -0
- package/src/run.ts +74 -11
- package/src/sentence-shape.ts +4 -5
- package/src/setting-problems.ts +7 -1
- package/src/span-cut.ts +28 -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 +77 -30
- 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/template-syntax.ts +164 -0
- package/src/text-above.ts +49 -0
- package/src/text-figures.ts +147 -0
- package/src/trailing-aside.ts +50 -0
- package/src/tree-walk.ts +48 -0
- package/styles/bunkacho.yaml +25 -0
- package/styles/ieice.yaml +29 -0
- package/styles/jis-z8301-2011.yaml +25 -0
package/src/render/rules-json.ts
CHANGED
|
@@ -1,58 +1,104 @@
|
|
|
1
|
-
import { definedLevels, resolve } from "../levels.ts";
|
|
1
|
+
import { definedLevels, resolve, severityAt } from "../levels.ts";
|
|
2
2
|
import type { Config } from "../config/load.ts";
|
|
3
|
-
import type { RuleDefinition } from "../plugin.ts";
|
|
3
|
+
import type { Level, Localized, RuleDefinition } from "../plugin.ts";
|
|
4
|
+
import { readableText } from "./text.ts";
|
|
4
5
|
import { uiLanguageOf, type Texts } from "../ui.ts";
|
|
5
|
-
import { presetLevels } from "../genre-load.ts";
|
|
6
|
-
import type
|
|
6
|
+
import { loadGenres, presetLevels } from "../genre-load.ts";
|
|
7
|
+
import { presetLevelsOf, type PresetLevels } from "../genre-parse.ts";
|
|
8
|
+
import { RULE_GROUPS, groupTextOf } from "../rule-guide.ts";
|
|
9
|
+
import { standingIn } from "../rule-genres.ts";
|
|
10
|
+
import { optionsJson } from "./options.ts";
|
|
11
|
+
import { styleLevelSource } from "../config/style.ts";
|
|
12
|
+
import { loadStyles } from "../style-load.ts";
|
|
13
|
+
import type { OptionLayer } from "../rule-options.ts";
|
|
7
14
|
|
|
8
15
|
const TEXT: Texts<{
|
|
9
16
|
readonly offBySetting: string;
|
|
10
17
|
readonly offByGenre: (genre: string) => string;
|
|
18
|
+
readonly offUnsuited: (genre: string) => string;
|
|
11
19
|
readonly offExperimental: string;
|
|
12
20
|
readonly valuesNote: string;
|
|
13
21
|
readonly reason: string;
|
|
14
22
|
readonly byFile: string;
|
|
23
|
+
readonly optionsByFile: string;
|
|
24
|
+
readonly fromStyleNote: readonly string[];
|
|
15
25
|
}> = {
|
|
16
26
|
ja: {
|
|
17
27
|
offBySetting: "設定で止めている",
|
|
18
28
|
offByGenre: (genre) => `ジャンル ${genre} では見ない`,
|
|
29
|
+
offUnsuited: (genre) => `ジャンル ${genre} の文書には向かない rule(use_for)`,
|
|
19
30
|
offExperimental: "experimental な rule は既定で動かさない",
|
|
20
31
|
valuesNote: "この 4 語のかわりに数字を直接書いてもよい。4 語のほうを勧める。",
|
|
21
32
|
reason: "<理由>",
|
|
22
33
|
byFile: "chaff.yaml の rules に <rule-id>: <level> を足す。既定のままのものは書かない。",
|
|
34
|
+
optionsByFile: "options を持つ rule は、chaff.yaml の options に <rule-id>: { <option>: <value> } を足す。",
|
|
35
|
+
fromStyleNote: [
|
|
36
|
+
"チームの書き方の決まり(例: です・ます、1 文 80 字まで)を一つずつ読む。",
|
|
37
|
+
"決まりごとに、summary と level_meaning が合う rule を選ぶ。数の決まりは levels の数と比べ、合う段階を選ぶか数を直接書く。",
|
|
38
|
+
"文書の種類が分かれば genre を決める。rules[].genres で、そのジャンルで動くか・止まるかを確かめる。",
|
|
39
|
+
"表記の決まりは prefer、社内用語は jargon、必須の見出しは required_sections に書く。",
|
|
40
|
+
"既定と同じものは書かない。書いたら npx chaff explain <rule-id> と、決まりに沿った短い見本で確かめる。",
|
|
41
|
+
],
|
|
23
42
|
},
|
|
24
43
|
en: {
|
|
25
44
|
offBySetting: "turned off in the settings",
|
|
26
45
|
offByGenre: (genre) => `the ${genre} genre does not check it`,
|
|
46
|
+
offUnsuited: (genre) => `not a rule for ${genre} documents (use_for)`,
|
|
27
47
|
offExperimental: "experimental rules do not run by default",
|
|
28
48
|
valuesNote: "A number may be written instead of these four words. The words are recommended.",
|
|
29
49
|
reason: "<reason>",
|
|
30
50
|
byFile: "Add <rule-id>: <level> under rules in chaff.yaml. Leave out anything at its default.",
|
|
51
|
+
optionsByFile: "For a rule with options, add <rule-id>: { <option>: <value> } under options in chaff.yaml.",
|
|
52
|
+
fromStyleNote: [
|
|
53
|
+
"Read the team's style note one requirement at a time (for example: polite endings, sentences of at most 80 characters).",
|
|
54
|
+
"For each requirement, pick the rule whose summary and level_meaning match. For a number, compare it with the rule's levels and pick a level, or write the number itself.",
|
|
55
|
+
"If the kind of document is known, set genre, and check rules[].genres for whether each rule runs or is off in it.",
|
|
56
|
+
"Put spellings under prefer, in-house words under jargon, and required headings under required_sections.",
|
|
57
|
+
"Leave out anything at its default. Then check each rule with npx chaff explain <rule-id> and a short sample that follows the note.",
|
|
58
|
+
],
|
|
31
59
|
},
|
|
32
60
|
};
|
|
33
61
|
|
|
34
62
|
const now = (rule: RuleDefinition, config: Config, genre: string, text: (typeof TEXT)["ja"], preset: PresetLevels): Record<string, unknown> => {
|
|
63
|
+
// A run leaves out a rule whose use_for does not cover the genre before it reads any level.
|
|
64
|
+
if (standingIn(rule, genre, {}).kind === "unsuited") return { level: "off", why_off: text.offUnsuited(genre) };
|
|
35
65
|
const explicit = config.rules[rule.id] ?? preset[rule.id];
|
|
36
66
|
if (explicit === "off" && config.rules[rule.id] === undefined) return { level: "off", why_off: text.offByGenre(genre) };
|
|
37
67
|
if (explicit === "off") return { level: "off", why_off: text.offBySetting };
|
|
38
|
-
const limit = rule.
|
|
68
|
+
const limit = rule.level_sets === "severity" ? undefined : config.limits[rule.id];
|
|
39
69
|
if (limit !== undefined) return { level: "normal", limit, set_as: "number" };
|
|
40
|
-
if (explicit !== undefined) return { level: explicit,
|
|
70
|
+
if (explicit !== undefined) return { level: explicit, ...effectAt(rule, explicit, genre) };
|
|
41
71
|
if (rule.status === "experimental" && !config.experimental) {
|
|
42
72
|
return { level: "off", why_off: text.offExperimental, turn_on_with: `npx chaff lint --experimental` };
|
|
43
73
|
}
|
|
44
|
-
return { level: "normal",
|
|
74
|
+
return { level: "normal", ...effectAt(rule, "normal", genre) };
|
|
45
75
|
};
|
|
46
76
|
|
|
77
|
+
/** The level a rule runs at now, and why it is off when it is: what `chaff rules` shows in its table. */
|
|
78
|
+
export const nowFor = (rule: RuleDefinition, config: Config, language: string, genre: string): Record<string, unknown> =>
|
|
79
|
+
now(rule, config, genre, TEXT[uiLanguageOf(language)], presetLevels(genre));
|
|
80
|
+
|
|
81
|
+
/** What a level does to a rule: the limit it counts to, or, with nothing to count, the severity of its findings. */
|
|
82
|
+
const effectAt = (rule: RuleDefinition, level: Exclude<Level, "off">, genre: string): Record<string, unknown> =>
|
|
83
|
+
rule.level_sets === "severity" ? { severity: severityAt(rule, level, genre) } : { limit: resolve(rule, level, genre).limit };
|
|
84
|
+
|
|
47
85
|
const yourSetting = (rule: RuleDefinition, config: Config): Record<string, unknown> | null => {
|
|
48
86
|
const level = config.rules[rule.id];
|
|
49
87
|
if (level === undefined) return null;
|
|
50
|
-
const
|
|
51
|
-
|
|
88
|
+
const from = styleLevelSource(config, rule.id) ?? config.path;
|
|
89
|
+
const limit = rule.level_sets === "severity" ? undefined : config.limits[rule.id];
|
|
90
|
+
return limit === undefined ? { level, from } : { level, limit, from };
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/** 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
|
+
const styleOf = (config: Config): Record<string, unknown> | null => {
|
|
95
|
+
const style = loadStyles().find((entry) => entry.id === config.applied?.style);
|
|
96
|
+
return style === undefined ? null : { id: style.id, name: style.name, summary: style.summary, source: style.source };
|
|
52
97
|
};
|
|
53
98
|
|
|
54
99
|
/** ジャンルで数字が変わる rule があるので、いま効いている表と既定の表の両方を出す。 */
|
|
55
100
|
const levelsOf = (rule: RuleDefinition, genre: string): Record<string, unknown> => {
|
|
101
|
+
if (rule.level_sets === "severity") return { levels: severitiesOf(rule, genre) };
|
|
56
102
|
const effective = Object.fromEntries(
|
|
57
103
|
definedLevels(rule)
|
|
58
104
|
.filter((level) => level !== "off")
|
|
@@ -62,33 +108,103 @@ const levelsOf = (rule: RuleDefinition, genre: string): Record<string, unknown>
|
|
|
62
108
|
return overridden ? { levels: effective, levels_default: rule.levels, levels_from: "by_genre" } : { levels: rule.levels };
|
|
63
109
|
};
|
|
64
110
|
|
|
111
|
+
const severitiesOf = (rule: RuleDefinition, genre: string): Record<string, string> =>
|
|
112
|
+
Object.fromEntries(
|
|
113
|
+
definedLevels(rule)
|
|
114
|
+
.filter((level) => level !== "off")
|
|
115
|
+
.map((level) => [level, severityAt(rule, level, genre)]),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/** 指摘が無いので、置き場所は rule の言葉で読ませる。言語はどれも出す。 */
|
|
119
|
+
const readableInEvery = (rule: RuleDefinition, field: Localized): Localized =>
|
|
120
|
+
Object.fromEntries(Object.keys(field).map((language) => [language, readableText(rule, field, language)]));
|
|
121
|
+
|
|
122
|
+
const READER_LANGUAGES = ["ja", "en"];
|
|
123
|
+
|
|
124
|
+
/** How the rule stands in every genre with no chaff.yaml, so an AI can pick a genre before it picks levels. */
|
|
125
|
+
const genresOf = (rule: RuleDefinition): Record<string, Record<string, string>> => {
|
|
126
|
+
const data = loadGenres();
|
|
127
|
+
return Object.fromEntries(
|
|
128
|
+
data.genres.map((genre) => {
|
|
129
|
+
const standing = standingIn(rule, genre.id, presetLevelsOf(data, genre.id));
|
|
130
|
+
return [genre.id, standing.kind === "on" ? { runs: "on", level: standing.level } : { runs: standing.kind }];
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/** The plain-language part of the rule file: what it finds, an example, what it leaves alone, what a level means. */
|
|
136
|
+
const guideOf = (rule: RuleDefinition): Record<string, unknown> => ({
|
|
137
|
+
group: rule.guide?.group ?? null,
|
|
138
|
+
summary: rule.guide?.summary ?? {},
|
|
139
|
+
example: rule.guide?.examples ?? {},
|
|
140
|
+
not_flagged: rule.guide?.notFlagged ?? {},
|
|
141
|
+
level_meaning: rule.guide?.levelMeaning ?? {},
|
|
142
|
+
languages: rule.languages ?? READER_LANGUAGES,
|
|
143
|
+
requires: rule.requires,
|
|
144
|
+
genres: genresOf(rule),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const groupsOf = (): Record<string, unknown>[] =>
|
|
148
|
+
RULE_GROUPS.map((group) => ({
|
|
149
|
+
id: group,
|
|
150
|
+
name: Object.fromEntries(READER_LANGUAGES.map((language) => [language, groupTextOf(language, group).name])),
|
|
151
|
+
note: Object.fromEntries(READER_LANGUAGES.map((language) => [language, groupTextOf(language, group).note])),
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 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 when they ship: the style presets under style:, the custom_rules types, and each rule's options.
|
|
157
|
+
*/
|
|
158
|
+
const COMING = {
|
|
159
|
+
style_presets: { status: "coming", presets: [] },
|
|
160
|
+
custom_rule_types: { status: "coming", planned: ["words", "pattern", "tokens", "module"] },
|
|
161
|
+
rule_options: { status: "coming", note: "Each rule's options (with their types and allowed values) will be listed under options." },
|
|
162
|
+
};
|
|
163
|
+
|
|
65
164
|
/** AI に設定を書かせるときの入口。推測せずに書けるだけの情報を 1 つに入れる。spec §19.3。 */
|
|
66
|
-
export const rulesJson = (
|
|
165
|
+
export const rulesJson = (
|
|
166
|
+
rules: readonly RuleDefinition[],
|
|
167
|
+
config: Config,
|
|
168
|
+
language: string,
|
|
169
|
+
genre: string,
|
|
170
|
+
optionLayers: readonly OptionLayer[] = [],
|
|
171
|
+
): string => {
|
|
67
172
|
const text = TEXT[uiLanguageOf(language)];
|
|
68
173
|
const preset = presetLevels(genre);
|
|
69
174
|
return JSON.stringify(
|
|
70
175
|
{
|
|
71
|
-
|
|
176
|
+
// 2: rules gained group, summary, example, not_flagged, level_meaning, languages, requires and genres,
|
|
177
|
+
// and groups and the coming local-rules fields were added. Nothing from 1 was removed or renamed.
|
|
178
|
+
schema_version: 2,
|
|
72
179
|
config_file: "chaff.yaml",
|
|
73
180
|
detected: { genre, language },
|
|
181
|
+
...(config.applied === undefined ? {} : { style: styleOf(config) }),
|
|
74
182
|
values_you_can_use: ["strict", "normal", "relaxed", "off"],
|
|
75
183
|
values_note: text.valuesNote,
|
|
184
|
+
groups: groupsOf(),
|
|
185
|
+
...COMING,
|
|
76
186
|
rules: rules.map((rule) => ({
|
|
77
187
|
id: rule.id,
|
|
78
188
|
layer: rule.layer,
|
|
79
189
|
status: rule.status,
|
|
80
|
-
name: rule.name,
|
|
81
|
-
why: rule.why,
|
|
82
|
-
how_to_fix: rule.how_to_fix,
|
|
190
|
+
name: readableInEvery(rule, rule.name),
|
|
191
|
+
why: readableInEvery(rule, rule.why),
|
|
192
|
+
how_to_fix: readableInEvery(rule, rule.how_to_fix),
|
|
83
193
|
use_for: rule.use_for,
|
|
194
|
+
level_sets: rule.level_sets,
|
|
84
195
|
...levelsOf(rule, genre),
|
|
85
196
|
levels_you_can_set: definedLevels(rule),
|
|
86
197
|
your_setting: yourSetting(rule, config),
|
|
87
198
|
now: now(rule, config, genre, text, preset),
|
|
199
|
+
...(rule.options === undefined ? {} : { options: optionsJson(rule, optionLayers) }),
|
|
200
|
+
...(rule.custom === undefined ? {} : { defined_in: "chaff.yaml custom_rules", custom: rule.custom }),
|
|
201
|
+
...guideOf(rule),
|
|
88
202
|
})),
|
|
203
|
+
how_to_write_settings_from_a_style_note: text.fromStyleNote,
|
|
89
204
|
how_to_change: {
|
|
90
205
|
by_command: ["relax", "strict", "off"].map((command) => `npx chaff ${command} <rule-id> --why "${text.reason}"`),
|
|
91
206
|
by_file: text.byFile,
|
|
207
|
+
options_by_file: text.optionsByFile,
|
|
92
208
|
},
|
|
93
209
|
},
|
|
94
210
|
null,
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Config } from "../config/load.ts";
|
|
2
|
+
import type { RuleDefinition } from "../plugin.ts";
|
|
3
|
+
import { groupTextOf, rulesByGroup } from "../rule-guide.ts";
|
|
4
|
+
import { uiLanguageOf, type Texts } from "../ui.ts";
|
|
5
|
+
import { nowFor } from "./rules-json.ts";
|
|
6
|
+
|
|
7
|
+
// `chaff rules`: every rule, grouped the way the reference groups them, with the level it runs at now.
|
|
8
|
+
// `chaff rules --json` carries the same and more, for an AI to read.
|
|
9
|
+
|
|
10
|
+
type RunsWhen = "default" | "experimental" | "team" | "test";
|
|
11
|
+
|
|
12
|
+
const TEXT: Texts<{
|
|
13
|
+
readonly heading: (genre: string, count: number) => string;
|
|
14
|
+
readonly runsWhen: Readonly<Record<RunsWhen, string>>;
|
|
15
|
+
readonly ungrouped: string;
|
|
16
|
+
readonly footer: readonly string[];
|
|
17
|
+
}> = {
|
|
18
|
+
ja: {
|
|
19
|
+
heading: (genre, count) => `chaff のルール ${count} 本(ジャンル ${genre})`,
|
|
20
|
+
runsWhen: { default: "既定", experimental: "試験中", team: "要設定", test: "AI" },
|
|
21
|
+
ungrouped: "(グループ未設定)",
|
|
22
|
+
footer: [
|
|
23
|
+
"既定: 何も書かなくても動く 試験中: --experimental か chaff.yaml で動く",
|
|
24
|
+
"要設定: chaff.yaml に語や見出しを書いたときだけ AI: npx chaff test で動く",
|
|
25
|
+
"",
|
|
26
|
+
"詳しく: npx chaff explain <rule>",
|
|
27
|
+
"AI に渡す: npx chaff rules --json",
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
en: {
|
|
31
|
+
heading: (genre, count) => `chaff's ${count} rules (genre ${genre})`,
|
|
32
|
+
runsWhen: { default: "default", experimental: "experimental", team: "needs list", test: "AI" },
|
|
33
|
+
ungrouped: "(no group yet)",
|
|
34
|
+
footer: [
|
|
35
|
+
"default: runs with no settings experimental: runs with --experimental or a level in chaff.yaml",
|
|
36
|
+
"needs list: runs only on words or headings listed in chaff.yaml AI: runs with npx chaff test",
|
|
37
|
+
"",
|
|
38
|
+
"More on one rule: npx chaff explain <rule>",
|
|
39
|
+
"For an AI: npx chaff rules --json",
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const runsWhenOf = (rule: RuleDefinition): RunsWhen => {
|
|
45
|
+
if (rule.layer === "L4") return "test";
|
|
46
|
+
if (rule.guide?.group === "team") return "team";
|
|
47
|
+
return rule.status === "experimental" ? "experimental" : "default";
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Columns line up in a terminal only if a wide (CJK) character counts as two. */
|
|
51
|
+
const widthOf = (text: string): number => Array.from(text).reduce((sum, char) => sum + ((char.codePointAt(0) ?? 0) >= 0x2e80 ? 2 : 1), 0);
|
|
52
|
+
|
|
53
|
+
const pad = (text: string, width: number): string => `${text}${" ".repeat(Math.max(0, width - widthOf(text)))}`;
|
|
54
|
+
|
|
55
|
+
/** "normal (100)", "strict (error)", or "off". */
|
|
56
|
+
const levelNow = (now: Record<string, unknown>): string => {
|
|
57
|
+
const level = typeof now["level"] === "string" ? now["level"] : "";
|
|
58
|
+
const detail = now["limit"] ?? now["severity"];
|
|
59
|
+
return level !== "off" && (typeof detail === "number" || typeof detail === "string") ? `${level} (${String(detail)})` : level;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
type Row = { readonly id: string; readonly level: string; readonly runs: string; readonly summary: string };
|
|
63
|
+
|
|
64
|
+
/** A rule for one language only does not run on the others' documents, whatever its level says. */
|
|
65
|
+
const forLanguage = (rule: RuleDefinition, language: string): boolean => rule.languages === undefined || rule.languages.includes(language);
|
|
66
|
+
|
|
67
|
+
const rowOf = (rule: RuleDefinition, config: Config, language: string, genre: string): Row => ({
|
|
68
|
+
id: rule.id,
|
|
69
|
+
level: forLanguage(rule, language) ? levelNow(nowFor(rule, config, language, genre)) : `off (${(rule.languages ?? []).join("/")})`,
|
|
70
|
+
runs: TEXT[uiLanguageOf(language)].runsWhen[runsWhenOf(rule)],
|
|
71
|
+
summary: rule.guide?.summary[uiLanguageOf(language)] ?? "",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const lineOf = (row: Row, widths: { id: number; level: number; runs: number }): string =>
|
|
75
|
+
` ${pad(row.id, widths.id)} ${pad(row.level, widths.level)} ${pad(row.runs, widths.runs)} ${row.summary}`.trimEnd();
|
|
76
|
+
|
|
77
|
+
export const rulesTable = (rules: readonly RuleDefinition[], config: Config, language: string, genre: string): string => {
|
|
78
|
+
const text = TEXT[uiLanguageOf(language)];
|
|
79
|
+
const grouped = rulesByGroup(rules, (rule) => rule.guide?.group).map(({ group, rules: members }) => ({ name: groupTextOf(language, group).name, members }));
|
|
80
|
+
// A rule added without its plain-language fields still shows, so the table never hides a rule that runs.
|
|
81
|
+
const ungrouped = { name: text.ungrouped, members: rules.filter((rule) => rule.guide?.group === undefined) };
|
|
82
|
+
const groups = [...grouped, ungrouped].map(({ name, members }) => ({ name, rows: members.map((rule) => rowOf(rule, config, language, genre)) }));
|
|
83
|
+
const rows = groups.flatMap((group) => group.rows);
|
|
84
|
+
const widths = {
|
|
85
|
+
id: Math.max(...rows.map((row) => widthOf(row.id))),
|
|
86
|
+
level: Math.max(...rows.map((row) => widthOf(row.level))),
|
|
87
|
+
runs: Math.max(...rows.map((row) => widthOf(row.runs))),
|
|
88
|
+
};
|
|
89
|
+
const body = groups.filter((group) => group.rows.length > 0).flatMap((group) => ["", group.name, ...group.rows.map((row) => lineOf(row, widths))]);
|
|
90
|
+
return [text.heading(genre, rows.length), ...body, "", ...text.footer].join("\n");
|
|
91
|
+
};
|
package/src/render/sarif.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { messageOf, readableText } from "./text.ts";
|
|
2
2
|
import type { Finding, RuleDefinition, Severity } from "../plugin.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -48,10 +48,10 @@ const ruleFor = (located: Located): RuleDefinition | undefined => located.rules.
|
|
|
48
48
|
const sarifRule = (rule: RuleDefinition, language: string): SarifRule => ({
|
|
49
49
|
id: ruleIdOf(rule.id),
|
|
50
50
|
name: rule.id,
|
|
51
|
-
shortDescription: { text:
|
|
51
|
+
shortDescription: { text: readableText(rule, rule.name, language) },
|
|
52
52
|
// なぜ直すのかと、どう直すのかを一緒に上げる。指摘だけでは書いた人が動けない。
|
|
53
|
-
fullDescription: { text:
|
|
54
|
-
help: { text:
|
|
53
|
+
fullDescription: { text: readableText(rule, rule.why, language) },
|
|
54
|
+
help: { text: readableText(rule, rule.how_to_fix, language) },
|
|
55
55
|
properties: { tags: [rule.layer, ...rule.use_for] },
|
|
56
56
|
});
|
|
57
57
|
|
package/src/render/semantic.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { UserCheck } from "../checks.ts";
|
|
|
3
3
|
import type { Narrowing } from "../look-at.ts";
|
|
4
4
|
import type { Job as Plan, SemanticResult } from "../run-semantic.ts";
|
|
5
5
|
import { uiLanguageOf, type Texts, type UiLanguage } from "../ui.ts";
|
|
6
|
-
import { MARK, localized } from "./text.ts";
|
|
6
|
+
import { MARK, fill, localized } from "./text.ts";
|
|
7
7
|
import { counted, formFor } from "./plural.ts";
|
|
8
8
|
|
|
9
9
|
const RULE = 60;
|
|
@@ -129,13 +129,13 @@ const block = (finding: Finding, named: Named, language: UiLanguage): string[] =
|
|
|
129
129
|
const confidence = finding.values["confidence"];
|
|
130
130
|
const reason = String(finding.values["reason"] ?? "");
|
|
131
131
|
const sure = confidence === undefined ? "" : ` ${text.confidence(String(confidence))}`;
|
|
132
|
-
const fix = named.howToFix.length > 0 ? ["", ...indent(`→ ${named.howToFix}`, " ")] : [];
|
|
132
|
+
const fix = named.howToFix.length > 0 ? ["", ...indent(`→ ${fill(named.howToFix, finding.values)}`, " ")] : [];
|
|
133
133
|
return [
|
|
134
134
|
"",
|
|
135
135
|
// "12 行目" and "line 12" take the same width on a terminal, so the rule ends in the same column in both.
|
|
136
136
|
`─── ${text.line(finding.line)} ${"─".repeat(Math.max(0, RULE - String(finding.line).length - 8))}`,
|
|
137
137
|
"",
|
|
138
|
-
` ${MARK[finding.severity] ?? "·"} ${named.name}${sure}`,
|
|
138
|
+
` ${MARK[finding.severity] ?? "·"} ${fill(named.name, finding.values)}${sure}`,
|
|
139
139
|
"",
|
|
140
140
|
...indent(reason, " "),
|
|
141
141
|
...fix,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Severity } from "../plugin.ts";
|
|
2
|
+
import type { Texts } from "../ui.ts";
|
|
3
|
+
|
|
4
|
+
/** A severity as the summary line names it (エラー / 注意 / 参考, error / warning / note). */
|
|
5
|
+
export const SEVERITY_NAME: Texts<Readonly<Record<Severity, string>>> = {
|
|
6
|
+
ja: { error: "エラー", warning: "注意", info: "参考" },
|
|
7
|
+
en: { error: "error", warning: "warning", info: "note" },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const withArticle = (word: string): string => (/^[aeiou]/u.test(word) ? `an ${word}` : `a ${word}`);
|
package/src/render/text.ts
CHANGED
|
@@ -6,23 +6,37 @@ export const localized = (field: Localized, language: string): string => field[l
|
|
|
6
6
|
/** `{count}` is the value; `{count|word|words}` is the form that agrees with it (English only; Japanese has no plural). */
|
|
7
7
|
const PLACEHOLDER = /\{(\w+)(?:\|([^|{}]*)\|([^|{}]*))?\}/gu;
|
|
8
8
|
|
|
9
|
-
const fill = (template: string, values: Readonly<Record<string, string | number>>): string =>
|
|
9
|
+
export const fill = (template: string, values: Readonly<Record<string, string | number>>): string =>
|
|
10
10
|
template.replace(PLACEHOLDER, (whole, key: string, singular: string | undefined, plural: string | undefined) => {
|
|
11
11
|
const value = values[key];
|
|
12
12
|
if (value === undefined) return whole;
|
|
13
13
|
return singular === undefined || plural === undefined ? String(value) : formFor(value, singular, plural);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
/** A template as the rule reference shows it: each agreeing form as its plural ("{count} such words"). */
|
|
17
|
-
export const templateForReading = (template: string): string =>
|
|
18
|
-
template.replace(PLACEHOLDER, (whole,
|
|
19
|
-
singular === undefined || plural === undefined ? whole : plural,
|
|
16
|
+
/** A template as the rule reference shows it: each agreeing form as its plural ("{count} such words"), each value as its reading when given. */
|
|
17
|
+
export const templateForReading = (template: string, readings: Readonly<Record<string, string>> = {}): string =>
|
|
18
|
+
template.replace(PLACEHOLDER, (whole, key: string, singular: string | undefined, plural: string | undefined) =>
|
|
19
|
+
singular === undefined || plural === undefined ? (readings[key] ?? whole) : plural,
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
+
/** A rule's text for one finding, with the finding's values in it. */
|
|
23
|
+
export const filledText = (field: Localized, finding: Finding, language: string): string => fill(localized(field, language), finding.values);
|
|
24
|
+
|
|
25
|
+
/** A rule's text where no finding fills it (explain, rules --json, the rule reference): each value as the rule's words for it. */
|
|
26
|
+
export const readableText = (rule: Pick<RuleDefinition, "placeholders">, field: Localized, language: string): string => {
|
|
27
|
+
// The same fallback as the text itself: an English-only rule read in Japanese still gets its English words.
|
|
28
|
+
const readings = Object.fromEntries(
|
|
29
|
+
Object.entries(rule.placeholders ?? {}).flatMap(([key, reading]) => {
|
|
30
|
+
const words = localized(reading, language);
|
|
31
|
+
return words === "" ? [] : [[key, words]];
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
34
|
+
return templateForReading(localized(field, language), readings);
|
|
35
|
+
};
|
|
36
|
+
|
|
22
37
|
const templateOf = (rule: RuleDefinition, finding: Finding): Localized =>
|
|
23
38
|
(finding.variant === undefined ? undefined : rule.messages[finding.variant]) ?? rule.message;
|
|
24
39
|
|
|
25
|
-
export const messageOf = (rule: RuleDefinition, finding: Finding, language: string): string =>
|
|
26
|
-
fill(localized(templateOf(rule, finding), language), finding.values);
|
|
40
|
+
export const messageOf = (rule: RuleDefinition, finding: Finding, language: string): string => filledText(templateOf(rule, finding), finding, language);
|
|
27
41
|
|
|
28
42
|
export const MARK: Readonly<Record<string, string>> = { error: "✖", warning: "⚠", info: "·" };
|
package/src/resolve-genre.ts
CHANGED
|
@@ -3,17 +3,20 @@ import type { Config } from "./config/load.ts";
|
|
|
3
3
|
import type { GenreSource } from "./cli-text.ts";
|
|
4
4
|
import { frontMatterGenre, GENRES, guessGenre } from "./genre.ts";
|
|
5
5
|
import { unknownFrontMatterGenre } from "./genre-check.ts";
|
|
6
|
+
import { plainSource } from "./plain-source.ts";
|
|
6
7
|
|
|
7
8
|
/** unread: a genre the front matter wrote that chaff does not know, when the front matter was looked at. */
|
|
8
9
|
type ResolvedGenre = { readonly genre: string; readonly from: GenreSource; readonly unread?: string | undefined };
|
|
9
10
|
|
|
10
|
-
export const resolveGenre = (path: string,
|
|
11
|
+
export const resolveGenre = (path: string, text: string, config: Config, cliGenre?: string): ResolvedGenre => {
|
|
11
12
|
// コマンドで指定したものが最優先。その実行だけの指定だから、設定より強い。
|
|
12
13
|
if (cliGenre !== undefined) return { genre: cliGenre, from: "--genre" };
|
|
13
14
|
// パスごとの上書きが次。「全体はこう、ここだけは違う」を書けるようにする。
|
|
14
15
|
const override = applyByPath(config.byPath, config.baseDir, path);
|
|
15
16
|
if (override.genre !== undefined) return { genre: override.genre, from: "by_path" };
|
|
16
17
|
if (config.genre !== undefined) return { genre: config.genre, from: "config" };
|
|
18
|
+
// front matter と行頭の手がかりは、buildDocument と同じく BOM と CRLF / CR をそろえた本文で読む。
|
|
19
|
+
const source = plainSource(text);
|
|
17
20
|
const guess = guessGenre(path, source, frontMatterGenre(source));
|
|
18
21
|
const unread = unknownFrontMatterGenre(source, GENRES);
|
|
19
22
|
return guess === undefined ? { genre: "blog/tech", from: "default", unread } : { genre: guess.genre, from: guess.from, unread };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Level, RuleDefinition } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How a rule stands in one genre, with no chaff.yaml: the same order of precedence as a run (use_for, then the genre's
|
|
5
|
+
* preset, then the rule's status).
|
|
6
|
+
* unsuited: the rule is not for this kind of document (use_for), and does not run
|
|
7
|
+
* genre-off: the genre's preset turns it off
|
|
8
|
+
* experimental: it runs only with --experimental or a level in chaff.yaml
|
|
9
|
+
* on: it runs, at this level
|
|
10
|
+
*/
|
|
11
|
+
export type GenreStanding =
|
|
12
|
+
| { readonly kind: "unsuited" }
|
|
13
|
+
| { readonly kind: "genre-off" }
|
|
14
|
+
| { readonly kind: "experimental" }
|
|
15
|
+
| { readonly kind: "on"; readonly level: Exclude<Level, "off">; readonly byPreset: boolean };
|
|
16
|
+
|
|
17
|
+
type RuleFacts = Pick<RuleDefinition, "id" | "status" | "use_for">;
|
|
18
|
+
|
|
19
|
+
export const standingIn = (rule: RuleFacts, genre: string, preset: Readonly<Record<string, Level>>): GenreStanding => {
|
|
20
|
+
if (!rule.use_for.some((target) => genre.startsWith(target))) return { kind: "unsuited" };
|
|
21
|
+
const fromPreset = preset[rule.id];
|
|
22
|
+
if (fromPreset === "off") return { kind: "genre-off" };
|
|
23
|
+
if (fromPreset !== undefined) return { kind: "on", level: fromPreset, byPreset: true };
|
|
24
|
+
return rule.status === "experimental" ? { kind: "experimental" } : { kind: "on", level: "normal", byPreset: false };
|
|
25
|
+
};
|
|
@@ -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) }));
|