chaffjs 0.20.0 → 0.22.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 +7 -5
- package/dist/api.d.ts +16 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js.map +1 -1
- package/dist/cli-text.d.ts +2 -0
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +18 -5
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -11
- package/dist/cli.js.map +1 -1
- package/dist/command-help.d.ts +7 -0
- package/dist/command-help.d.ts.map +1 -0
- package/dist/command-help.js +18 -0
- package/dist/command-help.js.map +1 -0
- package/dist/commands/eval.js +2 -2
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/fix-plan.d.ts.map +1 -1
- package/dist/commands/fix-plan.js +11 -1
- package/dist/commands/fix-plan.js.map +1 -1
- package/dist/commands/help.d.ts +4 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +7 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/init-command.d.ts +4 -0
- package/dist/commands/init-command.d.ts.map +1 -0
- package/dist/commands/init-command.js +15 -0
- package/dist/commands/init-command.js.map +1 -0
- package/dist/commands/plugin-init.d.ts +20 -0
- package/dist/commands/plugin-init.d.ts.map +1 -0
- package/dist/commands/plugin-init.js +129 -0
- package/dist/commands/plugin-init.js.map +1 -0
- package/dist/commands/plugin-test.d.ts +11 -0
- package/dist/commands/plugin-test.d.ts.map +1 -0
- package/dist/commands/plugin-test.js +81 -0
- package/dist/commands/plugin-test.js.map +1 -0
- package/dist/config/load.d.ts +2 -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.js +2 -2
- package/dist/config/option-problems.js.map +1 -1
- package/dist/config/rule-problems.js +2 -2
- package/dist/config/rule-problems.js.map +1 -1
- package/dist/custom/checked.d.ts +9 -0
- package/dist/custom/checked.d.ts.map +1 -0
- package/dist/custom/checked.js +3 -0
- package/dist/custom/checked.js.map +1 -0
- package/dist/custom/dsl-fields.d.ts +27 -0
- package/dist/custom/dsl-fields.d.ts.map +1 -0
- package/dist/custom/dsl-fields.js +86 -0
- package/dist/custom/dsl-fields.js.map +1 -0
- package/dist/custom/load.d.ts.map +1 -1
- package/dist/custom/load.js +2 -0
- package/dist/custom/load.js.map +1 -1
- package/dist/custom/parse.d.ts +14 -3
- package/dist/custom/parse.d.ts.map +1 -1
- package/dist/custom/parse.js +44 -40
- package/dist/custom/parse.js.map +1 -1
- package/dist/custom/problems.d.ts.map +1 -1
- package/dist/custom/problems.js +10 -1
- package/dist/custom/problems.js.map +1 -1
- package/dist/detectors/amount-for-count.d.ts +21 -0
- package/dist/detectors/amount-for-count.d.ts.map +1 -0
- package/dist/detectors/amount-for-count.js +55 -0
- package/dist/detectors/amount-for-count.js.map +1 -0
- package/dist/detectors/blank-structure.d.ts.map +1 -1
- package/dist/detectors/blank-structure.js +6 -4
- package/dist/detectors/blank-structure.js.map +1 -1
- package/dist/detectors/clause-shape.d.ts +22 -0
- package/dist/detectors/clause-shape.d.ts.map +1 -0
- package/dist/detectors/clause-shape.js +149 -0
- package/dist/detectors/clause-shape.js.map +1 -0
- package/dist/detectors/code-fences.d.ts +34 -0
- package/dist/detectors/code-fences.d.ts.map +1 -0
- package/dist/detectors/code-fences.js +100 -0
- package/dist/detectors/code-fences.js.map +1 -0
- package/dist/detectors/cross-definitions.d.ts +4 -0
- package/dist/detectors/cross-definitions.d.ts.map +1 -0
- package/dist/detectors/cross-definitions.js +43 -0
- package/dist/detectors/cross-definitions.js.map +1 -0
- package/dist/detectors/cross-facts.d.ts +4 -0
- package/dist/detectors/cross-facts.d.ts.map +1 -0
- package/dist/detectors/cross-facts.js +53 -0
- package/dist/detectors/cross-facts.js.map +1 -0
- package/dist/detectors/cross-registry/cross-doc-duplicate-definition.d.ts +3 -0
- package/dist/detectors/cross-registry/cross-doc-duplicate-definition.d.ts.map +1 -0
- package/dist/detectors/cross-registry/cross-doc-duplicate-definition.js +3 -0
- package/dist/detectors/cross-registry/cross-doc-duplicate-definition.js.map +1 -0
- package/dist/detectors/cross-registry/cross-doc-fact-conflict.d.ts +3 -0
- package/dist/detectors/cross-registry/cross-doc-fact-conflict.d.ts.map +1 -0
- package/dist/detectors/cross-registry/cross-doc-fact-conflict.js +3 -0
- package/dist/detectors/cross-registry/cross-doc-fact-conflict.js.map +1 -0
- package/dist/detectors/currency-notation.d.ts +29 -0
- package/dist/detectors/currency-notation.d.ts.map +1 -0
- package/dist/detectors/currency-notation.js +58 -0
- package/dist/detectors/currency-notation.js.map +1 -0
- package/dist/detectors/custom.d.ts.map +1 -1
- package/dist/detectors/custom.js +4 -1
- package/dist/detectors/custom.js.map +1 -1
- package/dist/detectors/dangling-opener.d.ts +14 -0
- package/dist/detectors/dangling-opener.d.ts.map +1 -0
- package/dist/detectors/dangling-opener.js +55 -0
- package/dist/detectors/dangling-opener.js.map +1 -0
- package/dist/detectors/defined-term-form.d.ts +25 -0
- package/dist/detectors/defined-term-form.d.ts.map +1 -0
- package/dist/detectors/defined-term-form.js +170 -0
- package/dist/detectors/defined-term-form.js.map +1 -0
- package/dist/detectors/email-letter.d.ts +46 -0
- package/dist/detectors/email-letter.d.ts.map +1 -0
- package/dist/detectors/email-letter.js +234 -0
- package/dist/detectors/email-letter.js.map +1 -0
- package/dist/detectors/footnote-mismatch.d.ts +11 -0
- package/dist/detectors/footnote-mismatch.d.ts.map +1 -0
- package/dist/detectors/footnote-mismatch.js +55 -0
- package/dist/detectors/footnote-mismatch.js.map +1 -0
- package/dist/detectors/form-minority.d.ts +13 -0
- package/dist/detectors/form-minority.d.ts.map +1 -0
- package/dist/detectors/form-minority.js +19 -0
- package/dist/detectors/form-minority.js.map +1 -0
- package/dist/detectors/heading-end-mark.d.ts +10 -0
- package/dist/detectors/heading-end-mark.d.ts.map +1 -0
- package/dist/detectors/heading-end-mark.js +59 -0
- package/dist/detectors/heading-end-mark.js.map +1 -0
- package/dist/detectors/impossible-date.d.ts +20 -0
- package/dist/detectors/impossible-date.d.ts.map +1 -0
- package/dist/detectors/impossible-date.js +105 -0
- package/dist/detectors/impossible-date.js.map +1 -0
- package/dist/detectors/impossible-time.d.ts +18 -0
- package/dist/detectors/impossible-time.d.ts.map +1 -0
- package/dist/detectors/impossible-time.js +116 -0
- package/dist/detectors/impossible-time.js.map +1 -0
- package/dist/detectors/link-shape.d.ts +11 -0
- package/dist/detectors/link-shape.d.ts.map +1 -0
- package/dist/detectors/link-shape.js +56 -0
- package/dist/detectors/link-shape.js.map +1 -0
- package/dist/detectors/list-marker.d.ts +7 -0
- package/dist/detectors/list-marker.d.ts.map +1 -0
- package/dist/detectors/list-marker.js +50 -0
- package/dist/detectors/list-marker.js.map +1 -0
- package/dist/detectors/mark-shape.d.ts +53 -0
- package/dist/detectors/mark-shape.d.ts.map +1 -0
- package/dist/detectors/mark-shape.js +160 -0
- package/dist/detectors/mark-shape.js.map +1 -0
- package/dist/detectors/markdown-slip.d.ts +19 -0
- package/dist/detectors/markdown-slip.d.ts.map +1 -0
- package/dist/detectors/markdown-slip.js +122 -0
- package/dist/detectors/markdown-slip.js.map +1 -0
- package/dist/detectors/numeral-opener.d.ts +10 -0
- package/dist/detectors/numeral-opener.d.ts.map +1 -0
- package/dist/detectors/numeral-opener.js +65 -0
- package/dist/detectors/numeral-opener.js.map +1 -0
- package/dist/detectors/ordinal-suffix.d.ts +12 -0
- package/dist/detectors/ordinal-suffix.d.ts.map +1 -0
- package/dist/detectors/ordinal-suffix.js +33 -0
- package/dist/detectors/ordinal-suffix.js.map +1 -0
- package/dist/detectors/range-notation.d.ts +15 -0
- package/dist/detectors/range-notation.d.ts.map +1 -0
- package/dist/detectors/range-notation.js +58 -0
- package/dist/detectors/range-notation.js.map +1 -0
- package/dist/detectors/registry/adverb-polarity.d.ts +3 -0
- package/dist/detectors/registry/adverb-polarity.d.ts.map +1 -0
- package/dist/detectors/registry/adverb-polarity.js +3 -0
- package/dist/detectors/registry/adverb-polarity.js.map +1 -0
- package/dist/detectors/registry/amount-for-count.d.ts +3 -0
- package/dist/detectors/registry/amount-for-count.d.ts.map +1 -0
- package/dist/detectors/registry/amount-for-count.js +3 -0
- package/dist/detectors/registry/amount-for-count.js.map +1 -0
- package/dist/detectors/registry/attachment-missing.d.ts +3 -0
- package/dist/detectors/registry/attachment-missing.d.ts.map +1 -0
- package/dist/detectors/registry/attachment-missing.js +3 -0
- package/dist/detectors/registry/attachment-missing.js.map +1 -0
- package/dist/detectors/registry/bare-url-mix.d.ts +3 -0
- package/dist/detectors/registry/bare-url-mix.d.ts.map +1 -0
- package/dist/detectors/registry/bare-url-mix.js +3 -0
- package/dist/detectors/registry/bare-url-mix.js.map +1 -0
- package/dist/detectors/registry/caps-shouting.d.ts +3 -0
- package/dist/detectors/registry/caps-shouting.d.ts.map +1 -0
- package/dist/detectors/registry/caps-shouting.js +3 -0
- package/dist/detectors/registry/caps-shouting.js.map +1 -0
- package/dist/detectors/registry/code-fence-language.d.ts +3 -0
- package/dist/detectors/registry/code-fence-language.d.ts.map +1 -0
- package/dist/detectors/registry/code-fence-language.js +3 -0
- package/dist/detectors/registry/code-fence-language.js.map +1 -0
- package/dist/detectors/registry/currency-notation.d.ts +3 -0
- package/dist/detectors/registry/currency-notation.d.ts.map +1 -0
- package/dist/detectors/registry/currency-notation.js +3 -0
- package/dist/detectors/registry/currency-notation.js.map +1 -0
- package/dist/detectors/registry/dangling-opener.d.ts +3 -0
- package/dist/detectors/registry/dangling-opener.d.ts.map +1 -0
- package/dist/detectors/registry/dangling-opener.js +3 -0
- package/dist/detectors/registry/dangling-opener.js.map +1 -0
- package/dist/detectors/registry/defined-name-repeated.d.ts +3 -0
- package/dist/detectors/registry/defined-name-repeated.d.ts.map +1 -0
- package/dist/detectors/registry/defined-name-repeated.js +3 -0
- package/dist/detectors/registry/defined-name-repeated.js.map +1 -0
- package/dist/detectors/registry/defined-term-form.d.ts +3 -0
- package/dist/detectors/registry/defined-term-form.d.ts.map +1 -0
- package/dist/detectors/registry/defined-term-form.js +3 -0
- package/dist/detectors/registry/defined-term-form.js.map +1 -0
- package/dist/detectors/registry/email-frame.d.ts +3 -0
- package/dist/detectors/registry/email-frame.d.ts.map +1 -0
- package/dist/detectors/registry/email-frame.js +3 -0
- package/dist/detectors/registry/email-frame.js.map +1 -0
- package/dist/detectors/registry/email-subject.d.ts +3 -0
- package/dist/detectors/registry/email-subject.d.ts.map +1 -0
- package/dist/detectors/registry/email-subject.js +3 -0
- package/dist/detectors/registry/email-subject.js.map +1 -0
- package/dist/detectors/registry/ending-run.d.ts +3 -0
- package/dist/detectors/registry/ending-run.d.ts.map +1 -0
- package/dist/detectors/registry/ending-run.js +3 -0
- package/dist/detectors/registry/ending-run.js.map +1 -0
- package/dist/detectors/registry/footnote-mismatch.d.ts +3 -0
- package/dist/detectors/registry/footnote-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/footnote-mismatch.js +3 -0
- package/dist/detectors/registry/footnote-mismatch.js.map +1 -0
- package/dist/detectors/registry/heading-command.d.ts +3 -0
- package/dist/detectors/registry/heading-command.d.ts.map +1 -0
- package/dist/detectors/registry/heading-command.js +3 -0
- package/dist/detectors/registry/heading-command.js.map +1 -0
- package/dist/detectors/registry/heading-end-punctuation.d.ts +3 -0
- package/dist/detectors/registry/heading-end-punctuation.d.ts.map +1 -0
- package/dist/detectors/registry/heading-end-punctuation.js +3 -0
- package/dist/detectors/registry/heading-end-punctuation.js.map +1 -0
- package/dist/detectors/registry/hyphen-dash.d.ts +3 -0
- package/dist/detectors/registry/hyphen-dash.d.ts.map +1 -0
- package/dist/detectors/registry/hyphen-dash.js +3 -0
- package/dist/detectors/registry/hyphen-dash.js.map +1 -0
- package/dist/detectors/registry/image-file-name-alt.d.ts +3 -0
- package/dist/detectors/registry/image-file-name-alt.d.ts.map +1 -0
- package/dist/detectors/registry/image-file-name-alt.js +3 -0
- package/dist/detectors/registry/image-file-name-alt.js.map +1 -0
- package/dist/detectors/registry/impossible-date.d.ts +3 -0
- package/dist/detectors/registry/impossible-date.d.ts.map +1 -0
- package/dist/detectors/registry/impossible-date.js +3 -0
- package/dist/detectors/registry/impossible-date.js.map +1 -0
- package/dist/detectors/registry/impossible-time.d.ts +3 -0
- package/dist/detectors/registry/impossible-time.d.ts.map +1 -0
- package/dist/detectors/registry/impossible-time.js +3 -0
- package/dist/detectors/registry/impossible-time.js.map +1 -0
- package/dist/detectors/registry/latin-abbreviation.d.ts +3 -0
- package/dist/detectors/registry/latin-abbreviation.d.ts.map +1 -0
- package/dist/detectors/registry/latin-abbreviation.js +3 -0
- package/dist/detectors/registry/latin-abbreviation.js.map +1 -0
- package/dist/detectors/registry/link-text-url-mismatch.d.ts +3 -0
- package/dist/detectors/registry/link-text-url-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/link-text-url-mismatch.js +3 -0
- package/dist/detectors/registry/link-text-url-mismatch.js.map +1 -0
- package/dist/detectors/registry/list-marker.d.ts +3 -0
- package/dist/detectors/registry/list-marker.d.ts.map +1 -0
- package/dist/detectors/registry/list-marker.js +3 -0
- package/dist/detectors/registry/list-marker.js.map +1 -0
- package/dist/detectors/registry/mark-consistency.d.ts +3 -0
- package/dist/detectors/registry/mark-consistency.d.ts.map +1 -0
- package/dist/detectors/registry/mark-consistency.js +3 -0
- package/dist/detectors/registry/mark-consistency.js.map +1 -0
- package/dist/detectors/registry/numeral-opener.d.ts +3 -0
- package/dist/detectors/registry/numeral-opener.d.ts.map +1 -0
- package/dist/detectors/registry/numeral-opener.js +3 -0
- package/dist/detectors/registry/numeral-opener.js.map +1 -0
- package/dist/detectors/registry/ordinal-suffix.d.ts +3 -0
- package/dist/detectors/registry/ordinal-suffix.d.ts.map +1 -0
- package/dist/detectors/registry/ordinal-suffix.js +3 -0
- package/dist/detectors/registry/ordinal-suffix.js.map +1 -0
- package/dist/detectors/registry/origin-particle.d.ts +3 -0
- package/dist/detectors/registry/origin-particle.d.ts.map +1 -0
- package/dist/detectors/registry/origin-particle.js +3 -0
- package/dist/detectors/registry/origin-particle.js.map +1 -0
- package/dist/detectors/registry/range-notation.d.ts +3 -0
- package/dist/detectors/registry/range-notation.d.ts.map +1 -0
- package/dist/detectors/registry/range-notation.js +3 -0
- package/dist/detectors/registry/range-notation.js.map +1 -0
- package/dist/detectors/registry/relative-pronoun-mix.d.ts +3 -0
- package/dist/detectors/registry/relative-pronoun-mix.d.ts.map +1 -0
- package/dist/detectors/registry/relative-pronoun-mix.js +3 -0
- package/dist/detectors/registry/relative-pronoun-mix.js.map +1 -0
- package/dist/detectors/registry/request-without-deadline.d.ts +3 -0
- package/dist/detectors/registry/request-without-deadline.d.ts.map +1 -0
- package/dist/detectors/registry/request-without-deadline.js +3 -0
- package/dist/detectors/registry/request-without-deadline.js.map +1 -0
- package/dist/detectors/registry/sentence-spacing.d.ts +3 -0
- package/dist/detectors/registry/sentence-spacing.d.ts.map +1 -0
- package/dist/detectors/registry/sentence-spacing.js +3 -0
- package/dist/detectors/registry/sentence-spacing.js.map +1 -0
- package/dist/detectors/registry/share-over-hundred.d.ts +3 -0
- package/dist/detectors/registry/share-over-hundred.d.ts.map +1 -0
- package/dist/detectors/registry/share-over-hundred.js +3 -0
- package/dist/detectors/registry/share-over-hundred.js.map +1 -0
- package/dist/detectors/registry/shell-prompt.d.ts +3 -0
- package/dist/detectors/registry/shell-prompt.d.ts.map +1 -0
- package/dist/detectors/registry/shell-prompt.js +3 -0
- package/dist/detectors/registry/shell-prompt.js.map +1 -0
- package/dist/detectors/registry/step-reference.d.ts +3 -0
- package/dist/detectors/registry/step-reference.d.ts.map +1 -0
- package/dist/detectors/registry/step-reference.js +3 -0
- package/dist/detectors/registry/step-reference.js.map +1 -0
- package/dist/detectors/registry/step-statement.d.ts +3 -0
- package/dist/detectors/registry/step-statement.d.ts.map +1 -0
- package/dist/detectors/registry/step-statement.js +3 -0
- package/dist/detectors/registry/step-statement.js.map +1 -0
- package/dist/detectors/registry/table-row-overflow.d.ts +3 -0
- package/dist/detectors/registry/table-row-overflow.d.ts.map +1 -0
- package/dist/detectors/registry/table-row-overflow.js +3 -0
- package/dist/detectors/registry/table-row-overflow.js.map +1 -0
- package/dist/detectors/registry/toc-heading.d.ts +3 -0
- package/dist/detectors/registry/toc-heading.d.ts.map +1 -0
- package/dist/detectors/registry/toc-heading.js +3 -0
- package/dist/detectors/registry/toc-heading.js.map +1 -0
- package/dist/detectors/registry/unclosed-code-fence.d.ts +3 -0
- package/dist/detectors/registry/unclosed-code-fence.d.ts.map +1 -0
- package/dist/detectors/registry/unclosed-code-fence.js +3 -0
- package/dist/detectors/registry/unclosed-code-fence.js.map +1 -0
- package/dist/detectors/registry/unpaired-parallel.d.ts +3 -0
- package/dist/detectors/registry/unpaired-parallel.d.ts.map +1 -0
- package/dist/detectors/registry/unpaired-parallel.js +3 -0
- package/dist/detectors/registry/unpaired-parallel.js.map +1 -0
- package/dist/detectors/registry/unrendered-emphasis.d.ts +3 -0
- package/dist/detectors/registry/unrendered-emphasis.d.ts.map +1 -0
- package/dist/detectors/registry/unrendered-emphasis.js +3 -0
- package/dist/detectors/registry/unrendered-emphasis.js.map +1 -0
- package/dist/detectors/relative-pronoun-mix.d.ts +19 -0
- package/dist/detectors/relative-pronoun-mix.d.ts.map +1 -0
- package/dist/detectors/relative-pronoun-mix.js +60 -0
- package/dist/detectors/relative-pronoun-mix.js.map +1 -0
- package/dist/detectors/request-owner.d.ts +23 -0
- package/dist/detectors/request-owner.d.ts.map +1 -0
- package/dist/detectors/request-owner.js +110 -0
- package/dist/detectors/request-owner.js.map +1 -0
- package/dist/detectors/share-over-hundred.d.ts +20 -0
- package/dist/detectors/share-over-hundred.d.ts.map +1 -0
- package/dist/detectors/share-over-hundred.js +55 -0
- package/dist/detectors/share-over-hundred.js.map +1 -0
- package/dist/detectors/step-reference.d.ts +20 -0
- package/dist/detectors/step-reference.d.ts.map +1 -0
- package/dist/detectors/step-reference.js +57 -0
- package/dist/detectors/step-reference.js.map +1 -0
- package/dist/detectors/technical-docs.d.ts +32 -0
- package/dist/detectors/technical-docs.d.ts.map +1 -0
- package/dist/detectors/technical-docs.js +199 -0
- package/dist/detectors/technical-docs.js.map +1 -0
- package/dist/detectors/toc-heading.d.ts +10 -0
- package/dist/detectors/toc-heading.d.ts.map +1 -0
- package/dist/detectors/toc-heading.js +99 -0
- package/dist/detectors/toc-heading.js.map +1 -0
- package/dist/extension/pack-read.d.ts +21 -0
- package/dist/extension/pack-read.d.ts.map +1 -0
- package/dist/extension/pack-read.js +117 -0
- package/dist/extension/pack-read.js.map +1 -0
- package/dist/extension/plugin-load.d.ts.map +1 -1
- package/dist/extension/plugin-load.js +44 -10
- package/dist/extension/plugin-load.js.map +1 -1
- package/dist/extension/plugin-parse.d.ts.map +1 -1
- package/dist/extension/plugin-parse.js +10 -3
- package/dist/extension/plugin-parse.js.map +1 -1
- package/dist/facts/address-values.d.ts +5 -0
- package/dist/facts/address-values.d.ts.map +1 -0
- package/dist/facts/address-values.js +64 -0
- package/dist/facts/address-values.js.map +1 -0
- package/dist/facts/cross-facts.d.ts +20 -0
- package/dist/facts/cross-facts.d.ts.map +1 -0
- package/dist/facts/cross-facts.js +41 -0
- package/dist/facts/cross-facts.js.map +1 -0
- package/dist/fix-plan/chosen-depth.d.ts +10 -0
- package/dist/fix-plan/chosen-depth.d.ts.map +1 -0
- package/dist/fix-plan/chosen-depth.js +24 -0
- package/dist/fix-plan/chosen-depth.js.map +1 -0
- package/dist/fix-plan/mode.d.ts +13 -4
- package/dist/fix-plan/mode.d.ts.map +1 -1
- package/dist/fix-plan/mode.js +38 -7
- package/dist/fix-plan/mode.js.map +1 -1
- package/dist/fix-plan/plan.d.ts +20 -0
- package/dist/fix-plan/plan.d.ts.map +1 -1
- package/dist/fix-plan/plan.js +23 -5
- package/dist/fix-plan/plan.js.map +1 -1
- package/dist/fix-plan/render.d.ts.map +1 -1
- package/dist/fix-plan/render.js +24 -0
- package/dist/fix-plan/render.js.map +1 -1
- package/dist/fix-plan/text.d.ts +8 -0
- package/dist/fix-plan/text.d.ts.map +1 -1
- package/dist/fix-plan/text.js +36 -10
- package/dist/fix-plan/text.js.map +1 -1
- package/dist/genre-load.d.ts +1 -1
- package/dist/genre-load.d.ts.map +1 -1
- package/dist/genre-load.js +7 -4
- package/dist/genre-load.js.map +1 -1
- package/dist/genre-parse.d.ts +6 -0
- package/dist/genre-parse.d.ts.map +1 -1
- package/dist/genre-parse.js +18 -0
- package/dist/genre-parse.js.map +1 -1
- package/dist/init.js +10 -10
- package/dist/init.js.map +1 -1
- package/dist/known-genres.d.ts +8 -0
- package/dist/known-genres.d.ts.map +1 -0
- package/dist/known-genres.js +17 -0
- package/dist/known-genres.js.map +1 -0
- package/dist/link-shape.d.ts +20 -0
- package/dist/link-shape.d.ts.map +1 -0
- package/dist/link-shape.js +58 -0
- package/dist/link-shape.js.map +1 -0
- package/dist/list-marks.d.ts +21 -0
- package/dist/list-marks.d.ts.map +1 -0
- package/dist/list-marks.js +82 -0
- package/dist/list-marks.js.map +1 -0
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +15 -4
- package/dist/reasons.js.map +1 -1
- package/dist/render/explain.d.ts.map +1 -1
- package/dist/render/explain.js +11 -2
- package/dist/render/explain.js.map +1 -1
- package/dist/render/friendly.js +1 -1
- package/dist/render/friendly.js.map +1 -1
- package/dist/render/rules-json.d.ts.map +1 -1
- package/dist/render/rules-json.js +12 -3
- package/dist/render/rules-json.js.map +1 -1
- package/dist/render/rules-table.js +6 -6
- package/dist/render/rules-table.js.map +1 -1
- package/dist/render/semantic.js +2 -2
- package/dist/render/semantic.js.map +1 -1
- package/dist/render/suppressions.js +2 -2
- package/dist/render/suppressions.js.map +1 -1
- package/dist/rewrite-depth.d.ts +22 -0
- package/dist/rewrite-depth.d.ts.map +1 -0
- package/dist/rewrite-depth.js +42 -0
- package/dist/rewrite-depth.js.map +1 -0
- package/dist/rule-fields.d.ts +28 -0
- package/dist/rule-fields.d.ts.map +1 -0
- package/dist/rule-fields.js +85 -0
- package/dist/rule-fields.js.map +1 -0
- package/dist/rule-guide.d.ts +3 -0
- package/dist/rule-guide.d.ts.map +1 -1
- package/dist/rule-guide.js +6 -0
- package/dist/rule-guide.js.map +1 -1
- package/dist/rule-load.d.ts.map +1 -1
- package/dist/rule-load.js +13 -5
- package/dist/rule-load.js.map +1 -1
- package/dist/rule-offs.d.ts +14 -0
- package/dist/rule-offs.d.ts.map +1 -0
- package/dist/rule-offs.js +45 -0
- package/dist/rule-offs.js.map +1 -0
- package/dist/structure/build.d.ts.map +1 -1
- package/dist/structure/build.js +14 -1
- package/dist/structure/build.js.map +1 -1
- package/dist/structure/cross-definitions.d.ts +23 -0
- package/dist/structure/cross-definitions.d.ts.map +1 -0
- package/dist/structure/cross-definitions.js +34 -0
- package/dist/structure/cross-definitions.js.map +1 -0
- package/genres.yaml +14 -313
- package/package.json +3 -3
- package/rules/absolute-exception.yaml +3 -1
- package/rules/abstract-length.yaml +7 -1
- package/rules/acronym-expansion-conflict.yaml +2 -1
- package/rules/adverb-overuse.yaml +7 -1
- package/rules/adverb-without-negation.yaml +60 -0
- package/rules/adversative-ga-repeat.yaml +2 -1
- package/rules/agentless-passive.yaml +10 -1
- package/rules/agreement-slip.yaml +4 -1
- package/rules/ai-generated-composite.yaml +6 -1
- package/rules/ai-structure.yaml +8 -2
- package/rules/ai-tell.yaml +7 -1
- package/rules/all-caps-shouting.yaml +61 -0
- package/rules/announced-count-mismatch.yaml +3 -1
- package/rules/announcing-opener.yaml +7 -1
- package/rules/article-sound.yaml +6 -2
- package/rules/assistant-residue.yaml +4 -1
- package/rules/attachment-not-attached.yaml +112 -0
- package/rules/baito-keigo.yaml +64 -0
- package/rules/bare-url-mix.yaml +86 -0
- package/rules/bold-density.yaml +1 -0
- package/rules/bold-label-list.yaml +9 -1
- package/rules/bracket-nesting.yaml +2 -1
- package/rules/bracket-width-consistency.yaml +64 -0
- package/rules/broken-link.yaml +1 -1
- package/rules/chat-citation-residue.yaml +2 -1
- package/rules/citation-reference-mismatch.yaml +7 -1
- package/rules/citation-style-mix.yaml +7 -1
- package/rules/clause-chain.yaml +6 -1
- package/rules/cliche.yaml +67 -0
- package/rules/closing-cliche.yaml +7 -0
- package/rules/code-fence-language-mix.yaml +176 -0
- package/rules/colloquial-opener.yaml +62 -0
- package/rules/colon-lead-in.yaml +7 -1
- package/rules/concrete-evidence-density.yaml +6 -0
- package/rules/contraction-consistency.yaml +4 -1
- package/rules/contrast-framing.yaml +7 -1
- package/rules/cross-doc-duplicate-definition.yaml +70 -0
- package/rules/cross-doc-fact-conflict.yaml +64 -0
- package/rules/currency-notation-consistency.yaml +77 -0
- package/rules/cushion-phrase-density.yaml +8 -1
- package/rules/dangling-figure-reference.yaml +3 -1
- package/rules/dangling-participle.yaml +58 -0
- package/rules/dangling-reference.yaml +3 -1
- package/rules/date-format-consistency.yaml +3 -2
- package/rules/date-order.yaml +3 -1
- package/rules/date-range-reversed.yaml +3 -1
- package/rules/date-weekday-mismatch.yaml +3 -1
- package/rules/date-without-year.yaml +4 -3
- package/rules/defined-name-repeated.yaml +97 -0
- package/rules/defined-term-form.yaml +113 -0
- package/rules/demonstrative-opener-run.yaml +2 -1
- package/rules/double-keigo.yaml +6 -1
- package/rules/double-negative.yaml +5 -1
- package/rules/doubled-nado.yaml +2 -1
- package/rules/doubled-punctuation.yaml +1 -1
- package/rules/doubled-word.yaml +4 -1
- package/rules/duplicate-definition.yaml +3 -1
- package/rules/duplicate-heading.yaml +1 -1
- package/rules/duration-mismatch.yaml +2 -1
- package/rules/elapsed-years-mismatch.yaml +4 -1
- package/rules/email-greeting-closing.yaml +122 -0
- package/rules/email-subject-length.yaml +112 -0
- package/rules/emoji-density.yaml +3 -1
- package/rules/emoji-heading.yaml +7 -1
- package/rules/empty-intensifier.yaml +4 -0
- package/rules/empty-list-item.yaml +2 -1
- package/rules/empty-section.yaml +1 -1
- package/rules/empty-table-cell.yaml +2 -1
- package/rules/excessive-hedging.yaml +7 -1
- package/rules/exclamation-width-consistency.yaml +64 -0
- package/rules/expletive-construction.yaml +7 -1
- package/rules/fact-conflict.yaml +4 -1
- package/rules/figure-reference-order.yaml +7 -1
- package/rules/footnote-mismatch.yaml +91 -0
- package/rules/fullwidth-alnum-consistency.yaml +2 -2
- package/rules/hankaku-kana.yaml +1 -1
- package/rules/heading-command-missing.yaml +109 -0
- package/rules/heading-echo.yaml +6 -1
- package/rules/heading-end-punctuation-mix.yaml +158 -0
- package/rules/heading-level-skip.yaml +3 -3
- package/rules/heading-numbering-mix.yaml +4 -3
- package/rules/hiragana-fukushi.yaml +4 -1
- package/rules/homophone-slip.yaml +5 -1
- package/rules/humble-for-others.yaml +63 -0
- package/rules/hyphen-as-dash.yaml +59 -0
- package/rules/idiom-misuse.yaml +4 -1
- package/rules/image-file-name-alt.yaml +83 -0
- package/rules/impossible-date.yaml +79 -0
- package/rules/impossible-time.yaml +76 -0
- package/rules/internal-jargon.yaml +1 -1
- package/rules/invisible-character.yaml +1 -1
- package/rules/katakana-density.yaml +2 -1
- package/rules/katakana-long-vowel.yaml +1 -1
- package/rules/known-misspelling.yaml +2 -1
- package/rules/kutoten-consistency.yaml +1 -1
- package/rules/latin-abbreviation-form.yaml +58 -0
- package/rules/latin-spacing.yaml +6 -2
- package/rules/less-for-fewer.yaml +59 -0
- package/rules/link-text-url-mismatch.yaml +72 -0
- package/rules/list-item-form-mix.yaml +7 -1
- package/rules/list-marker-mix.yaml +111 -0
- package/rules/max-kanji-continuous.yaml +10 -2
- package/rules/max-paragraph-length.yaml +4 -1
- package/rules/max-sentence-length.yaml +29 -21
- package/rules/max-ten.yaml +4 -1
- package/rules/misconversion.yaml +2 -1
- package/rules/modal-conflict.yaml +2 -1
- package/rules/name-variant.yaml +4 -3
- package/rules/ngram-repetition.yaml +5 -0
- package/rules/no-doubled-joshi.yaml +5 -1
- package/rules/no-em-dash.yaml +4 -1
- package/rules/no-lead.yaml +6 -1
- package/rules/no-mixed-desumasu.yaml +5 -2
- package/rules/no-nakaguro-parallel.yaml +3 -0
- package/rules/nominalization.yaml +5 -1
- package/rules/nonstandard-word.yaml +80 -0
- package/rules/number-style-consistency.yaml +6 -1
- package/rules/number-without-unit.yaml +2 -1
- package/rules/numbering-gap.yaml +1 -1
- package/rules/numeral-sentence-start.yaml +56 -0
- package/rules/one-sentence-paragraph-run.yaml +5 -1
- package/rules/ordinal-suffix-mismatch.yaml +65 -0
- package/rules/orthographic-variant.yaml +4 -1
- package/rules/outside-announced-list.yaml +2 -1
- package/rules/oxford-comma-consistency.yaml +3 -1
- package/rules/padded-intro.yaml +7 -0
- package/rules/paragraph-length-variance.yaml +7 -1
- package/rules/paragraph-restatement.yaml +6 -1
- package/rules/percent-sum-mismatch.yaml +3 -1
- package/rules/person-consistency.yaml +4 -1
- package/rules/preamble-length.yaml +6 -0
- package/rules/preferred-term.yaml +1 -1
- package/rules/proper-noun-density.yaml +8 -1
- package/rules/quote-style-consistency.yaml +66 -0
- package/rules/ra-nuki.yaml +4 -1
- package/rules/range-notation-consistency.yaml +73 -0
- package/rules/redundant-expression.yaml +4 -1
- package/rules/reference-title-mismatch.yaml +4 -3
- package/rules/reference-topic-missing.yaml +2 -1
- package/rules/relative-date-mismatch.yaml +2 -1
- package/rules/repeated-conjunction.yaml +4 -1
- package/rules/repeated-sentence-ending.yaml +62 -0
- package/rules/repeated-sentence-head.yaml +4 -0
- package/rules/request-without-deadline.yaml +92 -0
- package/rules/required-sections.yaml +1 -1
- package/rules/requirement-modal.yaml +1 -1
- package/rules/requirement-smell.yaml +12 -4
- package/rules/rule-of-three.yaml +8 -1
- package/rules/sasete-itadaku.yaml +7 -1
- package/rules/section-length-uniformity.yaml +7 -1
- package/rules/sentence-initial-conjunction-run.yaml +5 -1
- package/rules/sentence-initial-so.yaml +6 -1
- package/rules/sentence-rhythm.yaml +8 -1
- package/rules/sentence-spacing-consistency.yaml +63 -0
- package/rules/share-over-hundred.yaml +65 -0
- package/rules/shell-prompt-mix.yaml +128 -0
- package/rules/space-before-punctuation.yaml +1 -1
- package/rules/spelling-consistency.yaml +3 -1
- package/rules/step-reference-missing.yaml +85 -0
- package/rules/step-statement-mix.yaml +76 -0
- package/rules/stock-transition.yaml +8 -1
- package/rules/stray-space.yaml +2 -2
- package/rules/summary-fact-mismatch.yaml +4 -1
- package/rules/table-header-variant.yaml +2 -1
- package/rules/table-row-overflow.yaml +90 -0
- package/rules/taigen-dome-in-prose.yaml +6 -0
- package/rules/tari-unpaired.yaml +58 -0
- package/rules/teki-overuse.yaml +2 -1
- package/rules/title-case-consistency.yaml +1 -1
- package/rules/title-length.yaml +7 -1
- package/rules/toc-heading-mismatch.yaml +136 -0
- package/rules/topic-predicate-distance.yaml +6 -1
- package/rules/total-mismatch.yaml +3 -1
- package/rules/translationese-density.yaml +4 -1
- package/rules/unbalanced-bracket.yaml +3 -3
- package/rules/unclosed-code-fence.yaml +107 -0
- package/rules/uncomparable-graded.yaml +65 -0
- package/rules/undefined-acronym.yaml +8 -1
- package/rules/unfilled-placeholder.yaml +1 -1
- package/rules/unit-mismatch.yaml +2 -1
- package/rules/unknown-word.yaml +4 -1
- package/rules/unqualified-superlative.yaml +6 -1
- package/rules/unrendered-emphasis.yaml +73 -0
- package/rules/unused-definition.yaml +4 -3
- package/rules/url-run-on.yaml +1 -1
- package/rules/use-before-definition.yaml +4 -3
- package/rules/vague-figure-reference.yaml +3 -1
- package/rules/vague-link-text.yaml +2 -1
- package/rules/vague-word-density.yaml +2 -1
- package/rules/very-adjective.yaml +5 -1
- package/rules/weasel-word.yaml +6 -1
- package/rules/which-that-consistency.yaml +64 -0
- package/rules/wordy-phrase.yaml +6 -1
- package/rules/yori-as-from.yaml +61 -0
- package/skills/chaff/SKILL.md +7 -7
- package/src/api.ts +13 -1
- package/src/cli-text.ts +22 -7
- package/src/cli.ts +8 -9
- package/src/command-help.ts +26 -0
- package/src/commands/eval.ts +2 -2
- package/src/commands/fix-plan.ts +13 -1
- package/src/commands/help.ts +8 -0
- package/src/commands/init-command.ts +13 -0
- package/src/commands/plugin-init.ts +150 -0
- package/src/commands/plugin-test.ts +111 -0
- package/src/config/load.ts +3 -0
- package/src/config/option-problems.ts +2 -2
- package/src/config/rule-problems.ts +2 -2
- package/src/custom/checked.ts +8 -0
- package/src/custom/dsl-fields.ts +102 -0
- package/src/custom/load.ts +2 -0
- package/src/custom/parse.ts +72 -50
- package/src/custom/problems.ts +16 -2
- package/src/detectors/amount-for-count.ts +90 -0
- package/src/detectors/blank-structure.ts +12 -4
- package/src/detectors/clause-shape.ts +199 -0
- package/src/detectors/code-fences.ts +113 -0
- package/src/detectors/cross-definitions.ts +49 -0
- package/src/detectors/cross-facts.ts +60 -0
- package/src/detectors/cross-registry/cross-doc-duplicate-definition.ts +4 -0
- package/src/detectors/cross-registry/cross-doc-fact-conflict.ts +4 -0
- package/src/detectors/currency-notation.ts +90 -0
- package/src/detectors/custom.ts +10 -2
- package/src/detectors/dangling-opener.ts +74 -0
- package/src/detectors/defined-term-form.ts +200 -0
- package/src/detectors/email-letter.ts +262 -0
- package/src/detectors/footnote-mismatch.ts +72 -0
- package/src/detectors/form-minority.ts +21 -0
- package/src/detectors/heading-end-mark.ts +82 -0
- package/src/detectors/impossible-date.ts +141 -0
- package/src/detectors/impossible-time.ts +151 -0
- package/src/detectors/link-shape.ts +70 -0
- package/src/detectors/list-marker.ts +60 -0
- package/src/detectors/mark-shape.ts +202 -0
- package/src/detectors/markdown-slip.ts +140 -0
- package/src/detectors/numeral-opener.ts +72 -0
- package/src/detectors/ordinal-suffix.ts +40 -0
- package/src/detectors/range-notation.ts +76 -0
- package/src/detectors/registry/adverb-polarity.ts +4 -0
- package/src/detectors/registry/amount-for-count.ts +4 -0
- package/src/detectors/registry/attachment-missing.ts +4 -0
- package/src/detectors/registry/bare-url-mix.ts +4 -0
- package/src/detectors/registry/caps-shouting.ts +4 -0
- package/src/detectors/registry/code-fence-language.ts +4 -0
- package/src/detectors/registry/currency-notation.ts +4 -0
- package/src/detectors/registry/dangling-opener.ts +4 -0
- package/src/detectors/registry/defined-name-repeated.ts +4 -0
- package/src/detectors/registry/defined-term-form.ts +4 -0
- package/src/detectors/registry/email-frame.ts +4 -0
- package/src/detectors/registry/email-subject.ts +4 -0
- package/src/detectors/registry/ending-run.ts +4 -0
- package/src/detectors/registry/footnote-mismatch.ts +4 -0
- package/src/detectors/registry/heading-command.ts +4 -0
- package/src/detectors/registry/heading-end-punctuation.ts +4 -0
- package/src/detectors/registry/hyphen-dash.ts +4 -0
- package/src/detectors/registry/image-file-name-alt.ts +4 -0
- package/src/detectors/registry/impossible-date.ts +4 -0
- package/src/detectors/registry/impossible-time.ts +4 -0
- package/src/detectors/registry/latin-abbreviation.ts +4 -0
- package/src/detectors/registry/link-text-url-mismatch.ts +4 -0
- package/src/detectors/registry/list-marker.ts +4 -0
- package/src/detectors/registry/mark-consistency.ts +4 -0
- package/src/detectors/registry/numeral-opener.ts +4 -0
- package/src/detectors/registry/ordinal-suffix.ts +4 -0
- package/src/detectors/registry/origin-particle.ts +4 -0
- package/src/detectors/registry/range-notation.ts +4 -0
- package/src/detectors/registry/relative-pronoun-mix.ts +4 -0
- package/src/detectors/registry/request-without-deadline.ts +4 -0
- package/src/detectors/registry/sentence-spacing.ts +4 -0
- package/src/detectors/registry/share-over-hundred.ts +4 -0
- package/src/detectors/registry/shell-prompt.ts +4 -0
- package/src/detectors/registry/step-reference.ts +4 -0
- package/src/detectors/registry/step-statement.ts +4 -0
- package/src/detectors/registry/table-row-overflow.ts +4 -0
- package/src/detectors/registry/toc-heading.ts +4 -0
- package/src/detectors/registry/unclosed-code-fence.ts +4 -0
- package/src/detectors/registry/unpaired-parallel.ts +4 -0
- package/src/detectors/registry/unrendered-emphasis.ts +4 -0
- package/src/detectors/relative-pronoun-mix.ts +79 -0
- package/src/detectors/request-owner.ts +141 -0
- package/src/detectors/share-over-hundred.ts +75 -0
- package/src/detectors/step-reference.ts +83 -0
- package/src/detectors/technical-docs.ts +230 -0
- package/src/detectors/toc-heading.ts +125 -0
- package/src/extension/pack-read.ts +128 -0
- package/src/extension/plugin-load.ts +49 -9
- package/src/extension/plugin-parse.ts +10 -3
- package/src/facts/address-values.ts +74 -0
- package/src/facts/cross-facts.ts +54 -0
- package/src/fix-plan/chosen-depth.ts +28 -0
- package/src/fix-plan/mode.ts +57 -11
- package/src/fix-plan/plan.ts +37 -5
- package/src/fix-plan/render.ts +24 -0
- package/src/fix-plan/text.ts +47 -10
- package/src/genre-load.ts +7 -4
- package/src/genre-parse.ts +19 -0
- package/src/init.ts +10 -10
- package/src/known-genres.ts +19 -0
- package/src/link-shape.ts +62 -0
- package/src/list-marks.ts +106 -0
- package/src/reasons.ts +16 -4
- package/src/render/explain.ts +14 -2
- package/src/render/friendly.ts +1 -1
- package/src/render/rules-json.ts +14 -3
- package/src/render/rules-table.ts +6 -6
- package/src/render/semantic.ts +2 -2
- package/src/render/suppressions.ts +2 -2
- package/src/rewrite-depth.ts +60 -0
- package/src/rule-fields.ts +123 -0
- package/src/rule-guide.ts +9 -0
- package/src/rule-load.ts +10 -4
- package/src/rule-offs.ts +50 -0
- package/src/structure/build.ts +21 -1
- package/src/structure/cross-definitions.ts +60 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { API_VERSION } from "../api.ts";
|
|
4
|
+
import { VERSION } from "../version.ts";
|
|
5
|
+
import type { Texts, UiLanguage } from "../ui.ts";
|
|
6
|
+
|
|
7
|
+
// chaff init --plugin <name>: a rule pack to start from, written in YAML alone. One rule, its word list in Japanese and
|
|
8
|
+
// English, and a test command (chaff plugin-test) that checks each rule's example against the rule.
|
|
9
|
+
|
|
10
|
+
/** A pack's own name: lowercase letters, digits and hyphens, optionally under a scope (@team/house). */
|
|
11
|
+
const PACK_NAME = /^(?:(@[a-z0-9][a-z0-9._-]*)\/)?([a-z][a-z0-9-]*)$/u;
|
|
12
|
+
|
|
13
|
+
export type PackName = { readonly scope: string | undefined; readonly name: string };
|
|
14
|
+
|
|
15
|
+
/** The name as written after --plugin, or undefined when it cannot be a plugin's name. "chaff-plugin-" in front is allowed and dropped. */
|
|
16
|
+
export const packNameOf = (written: string | undefined): PackName | undefined => {
|
|
17
|
+
const match = PACK_NAME.exec((written ?? "").replace(/(^|\/)chaff-plugin-/u, "$1"));
|
|
18
|
+
if (match === null) return undefined;
|
|
19
|
+
const [, scope, name] = match;
|
|
20
|
+
return name === undefined ? undefined : { scope, name };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** The package's name and the folder it is made in: chaff-plugin-house, or @team/chaff-plugin-house in chaff-plugin-house. */
|
|
24
|
+
export const packageOf = (pack: PackName): { readonly packageName: string; readonly folder: string } => ({
|
|
25
|
+
packageName: pack.scope === undefined ? `chaff-plugin-${pack.name}` : `${pack.scope}/chaff-plugin-${pack.name}`,
|
|
26
|
+
folder: `chaff-plugin-${pack.name}`,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const RULE = `# One rule of the pack. It is written as a rule under custom_rules in chaff.yaml is; see
|
|
30
|
+
# https://isamu.github.io/lab/en/guide/adding-rules for every field.
|
|
31
|
+
id: avoid-words
|
|
32
|
+
type: words
|
|
33
|
+
# The words come from lexicons/<language>/avoid-words.yaml, in the document's language.
|
|
34
|
+
word_list: avoid-words
|
|
35
|
+
name: { ja: チームで使わない言葉, en: A word the team does not use }
|
|
36
|
+
why:
|
|
37
|
+
ja: このチームでは、同じものを決まった言葉で呼びます。別の言葉が混ざると、読む人は別のものかと迷います。
|
|
38
|
+
en: The team calls each thing by one word. Another word makes a reader wonder whether it is another thing.
|
|
39
|
+
how_to_fix: { ja: チームの言葉に置き換えます。, en: Use the team's word. }
|
|
40
|
+
message:
|
|
41
|
+
ja: 「{matched}」ではなく「{preferred}」と書きます
|
|
42
|
+
en: 'Write "{preferred}", not "{matched}"'
|
|
43
|
+
level: warning
|
|
44
|
+
example:
|
|
45
|
+
ja: { before: 弊社の新しい窓口をご案内します。, after: 当社の新しい窓口をご案内します。 }
|
|
46
|
+
en: { before: We utilize the new form for every request., after: We use the new form for every request. }
|
|
47
|
+
rewrite:
|
|
48
|
+
depth: light
|
|
49
|
+
ja:
|
|
50
|
+
direction: 指された言葉だけを、チームの言葉に置き換えます。
|
|
51
|
+
pairs:
|
|
52
|
+
- { before: 弊社の新しい窓口をご案内します。, after: 当社の新しい窓口をご案内します。 }
|
|
53
|
+
- { before: 弊社では毎月点検しています。, after: 当社では毎月点検しています。 }
|
|
54
|
+
keep: [文のほかの部分]
|
|
55
|
+
avoid: [言葉と一緒に文の意味を変える]
|
|
56
|
+
en:
|
|
57
|
+
direction: Replace only the flagged word with the team's word.
|
|
58
|
+
pairs:
|
|
59
|
+
- { before: We utilize the new form for every request., after: We use the new form for every request. }
|
|
60
|
+
- { before: Utilize the search box first., after: Use the search box first. }
|
|
61
|
+
keep: [the rest of the sentence]
|
|
62
|
+
avoid: [changing what the sentence says along with the word]
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
const LEXICON_JA = `# 使わない言葉(pattern)と、使う言葉(rewrite)。
|
|
66
|
+
- { pattern: 弊社, rewrite: 当社 }
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const LEXICON_EN = `# The word not to use (pattern) and the word to use (rewrite).
|
|
70
|
+
- { pattern: utilize, rewrite: use }
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
const packageJson = (packageName: string): string =>
|
|
74
|
+
`${JSON.stringify(
|
|
75
|
+
{
|
|
76
|
+
name: packageName,
|
|
77
|
+
version: "0.1.0",
|
|
78
|
+
description: "Rules for chaff, written in YAML.",
|
|
79
|
+
files: ["rules", "lexicons", "styles"],
|
|
80
|
+
chaff: { apiVersion: API_VERSION },
|
|
81
|
+
scripts: { test: "chaffjs plugin-test ." },
|
|
82
|
+
peerDependencies: { chaffjs: `>=${VERSION}` },
|
|
83
|
+
},
|
|
84
|
+
null,
|
|
85
|
+
2,
|
|
86
|
+
)}\n`;
|
|
87
|
+
|
|
88
|
+
const FILES = (packageName: string): Readonly<Record<string, string>> => ({
|
|
89
|
+
"package.json": packageJson(packageName),
|
|
90
|
+
"rules/avoid-words.yaml": RULE,
|
|
91
|
+
"lexicons/ja/avoid-words.yaml": LEXICON_JA,
|
|
92
|
+
"lexicons/en/avoid-words.yaml": LEXICON_EN,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const TEXT: Texts<{
|
|
96
|
+
readonly badName: (written: string) => string;
|
|
97
|
+
readonly exists: (folder: string) => string;
|
|
98
|
+
readonly made: (folder: string, packageName: string) => string;
|
|
99
|
+
readonly next: (folder: string, name: string) => readonly string[];
|
|
100
|
+
}> = {
|
|
101
|
+
ja: {
|
|
102
|
+
badName: (written) => `--plugin ${written}: プラグインの名前は英小文字・数字・ハイフンで書きます(house、@team/house)`,
|
|
103
|
+
exists: (folder) => `${folder} はもうあります。上書きしないので、別の名前にするか消してから実行してください`,
|
|
104
|
+
made: (folder, packageName) => `${folder}/ に YAML だけのルールの束 ${packageName} を作りました。`,
|
|
105
|
+
next: (folder, name) => [
|
|
106
|
+
"",
|
|
107
|
+
"次に:",
|
|
108
|
+
` cd ${folder} && npx chaffjs plugin-test . ルールの例をルールにかけて確かめる`,
|
|
109
|
+
` chaff.yaml に plugins: [./${folder}] と書くと、${name}/avoid-words として動きます`,
|
|
110
|
+
"",
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
en: {
|
|
114
|
+
badName: (written) => `--plugin ${written}: a plugin's name is lowercase letters, digits and hyphens (house, @team/house)`,
|
|
115
|
+
exists: (folder) => `${folder} already exists. Nothing is overwritten; choose another name or remove it first`,
|
|
116
|
+
made: (folder, packageName) => `Made the YAML rule pack ${packageName} in ${folder}/.`,
|
|
117
|
+
next: (folder, name) => [
|
|
118
|
+
"",
|
|
119
|
+
"Next:",
|
|
120
|
+
` cd ${folder} && npx chaffjs plugin-test . check each rule against its own example`,
|
|
121
|
+
` add plugins: [./${folder}] to chaff.yaml and it runs as ${name}/avoid-words`,
|
|
122
|
+
"",
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** Makes the pack in dir. Lines to print, and whether it was made; nothing is written when the folder is already there. */
|
|
128
|
+
export const initPlugin = (dir: string, written: string | undefined, ui: UiLanguage): { readonly ok: boolean; readonly lines: readonly string[] } => {
|
|
129
|
+
const text = TEXT[ui];
|
|
130
|
+
const pack = packNameOf(written);
|
|
131
|
+
if (pack === undefined) return { ok: false, lines: [text.badName(written ?? "")] };
|
|
132
|
+
const { packageName, folder } = packageOf(pack);
|
|
133
|
+
if (existsSync(join(dir, folder))) return { ok: false, lines: [text.exists(folder)] };
|
|
134
|
+
Object.entries(FILES(packageName)).forEach(([path, body]) => {
|
|
135
|
+
mkdirSync(dirname(join(dir, folder, path)), { recursive: true });
|
|
136
|
+
writeFileSync(join(dir, folder, path), body, "utf8");
|
|
137
|
+
});
|
|
138
|
+
const name = pack.scope === undefined ? pack.name : `${pack.scope}/${pack.name}`;
|
|
139
|
+
return {
|
|
140
|
+
ok: true,
|
|
141
|
+
lines: [text.made(folder, packageName), ...Object.keys(FILES(packageName)).map((path) => ` ${folder}/${path}`), ...text.next(folder, name)],
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/** chaff init --plugin <name>: makes the pack in dir and says what it made, or why it did not. */
|
|
146
|
+
export const runInitPlugin = (dir: string, written: string | undefined, ui: UiLanguage): number => {
|
|
147
|
+
const made = initPlugin(dir, written, ui);
|
|
148
|
+
made.lines.forEach((line) => (made.ok ? console.log(line) : console.error(line)));
|
|
149
|
+
return made.ok ? 0 : 1;
|
|
150
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { EMPTY, type Config } from "../config/load.ts";
|
|
5
|
+
import { withExtensions } from "../extension/load.ts";
|
|
6
|
+
import { extensionProblems } from "../extension/problem-text.ts";
|
|
7
|
+
import { loadGenres } from "../genre-load.ts";
|
|
8
|
+
import type { RuleDefinition } from "../plugin.ts";
|
|
9
|
+
import type { Skipped } from "../run.ts";
|
|
10
|
+
import type { Texts, UiLanguage } from "../ui.ts";
|
|
11
|
+
import type { Checked } from "./feedback.ts";
|
|
12
|
+
|
|
13
|
+
// chaff plugin-test [folder]: loads a plugin as chaff.yaml would, then runs each of its rules on the rule's own example,
|
|
14
|
+
// in every language the example is written in. The before must give the rule a finding and the after must give it
|
|
15
|
+
// none. A rule that does not run there (no word list for the language) fails, with the reason.
|
|
16
|
+
|
|
17
|
+
export type PluginTestContext = {
|
|
18
|
+
readonly ui: UiLanguage;
|
|
19
|
+
/** Lints one file with these settings, as chaff on the command line does. */
|
|
20
|
+
readonly check: (path: string, config: Config, argv: readonly string[]) => Promise<Pick<Checked, "findings" | "skipped">>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Outcome = { readonly rule: string; readonly language: string; readonly failure: string | undefined };
|
|
24
|
+
|
|
25
|
+
const TEXT: Texts<{
|
|
26
|
+
readonly noRules: (dir: string) => string;
|
|
27
|
+
readonly beforeQuiet: string;
|
|
28
|
+
readonly afterFlagged: (count: number) => string;
|
|
29
|
+
readonly notRun: (why: string) => string;
|
|
30
|
+
readonly noExample: string;
|
|
31
|
+
readonly summary: (passed: number, total: number) => string;
|
|
32
|
+
}> = {
|
|
33
|
+
ja: {
|
|
34
|
+
noRules: (dir) => `${dir} にルールがありません。`,
|
|
35
|
+
beforeQuiet: "例の before で指摘が出ません",
|
|
36
|
+
afterFlagged: (count) => `例の after で指摘が ${String(count)} 件出ます`,
|
|
37
|
+
notRun: (why) => `動きません(${why})`,
|
|
38
|
+
noExample: "例がありません",
|
|
39
|
+
summary: (passed, total) => `${String(total)} 件のうち ${String(passed)} 件が通りました。`,
|
|
40
|
+
},
|
|
41
|
+
en: {
|
|
42
|
+
noRules: (dir) => `${dir} has no rules.`,
|
|
43
|
+
beforeQuiet: "the example's before gets no finding",
|
|
44
|
+
afterFlagged: (count) => `the example's after gets ${String(count)} ${count === 1 ? "finding" : "findings"}`,
|
|
45
|
+
notRun: (why) => `it does not run (${why})`,
|
|
46
|
+
noExample: "it has no example",
|
|
47
|
+
summary: (passed, total) => `${String(passed)} of ${String(total)} passed.`,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** The first genre the rule is for: the example runs where the rule does. */
|
|
52
|
+
const genreFor = (rule: RuleDefinition): string => {
|
|
53
|
+
const genres = loadGenres().genres.map((genre) => genre.id);
|
|
54
|
+
return genres.find((genre) => rule.use_for.some((target) => genre === target || genre.startsWith(`${target}/`))) ?? genres[0] ?? "business/report";
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const skippedWhy = (skipped: readonly Skipped[], rule: string): string | undefined => skipped.find((entry) => entry.rule === rule)?.why;
|
|
58
|
+
|
|
59
|
+
/** One rule in one language: before flagged, after clean. */
|
|
60
|
+
const testExample = async (rule: RuleDefinition, language: string, config: Config, context: PluginTestContext): Promise<Outcome> => {
|
|
61
|
+
const text = TEXT[context.ui];
|
|
62
|
+
const example = rule.guide?.examples[language];
|
|
63
|
+
if (example === undefined) return { rule: rule.id, language, failure: text.noExample };
|
|
64
|
+
const dir = mkdtempSync(join(tmpdir(), "chaff-plugin-test-"));
|
|
65
|
+
const argv = ["--language", language, "--genre", genreFor(rule)];
|
|
66
|
+
const run = async (name: string, body: string): Promise<Pick<Checked, "findings" | "skipped">> => {
|
|
67
|
+
writeFileSync(join(dir, name), `${body.trimEnd()}\n`, "utf8");
|
|
68
|
+
return context.check(join(dir, name), config, argv);
|
|
69
|
+
};
|
|
70
|
+
const before = await run("before.md", example.before);
|
|
71
|
+
const why = skippedWhy(before.skipped, rule.id);
|
|
72
|
+
if (why !== undefined) return { rule: rule.id, language, failure: text.notRun(why) };
|
|
73
|
+
if (!before.findings.some((finding) => finding.rule === rule.id)) return { rule: rule.id, language, failure: text.beforeQuiet };
|
|
74
|
+
const after = (await run("after.md", example.after)).findings.filter((finding) => finding.rule === rule.id).length;
|
|
75
|
+
return { rule: rule.id, language, failure: after === 0 ? undefined : text.afterFlagged(after) };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const lineOf = (outcome: Outcome): string =>
|
|
79
|
+
outcome.failure === undefined ? ` ✓ ${outcome.rule} (${outcome.language})` : ` ✗ ${outcome.rule} (${outcome.language}): ${outcome.failure}`;
|
|
80
|
+
|
|
81
|
+
/** The languages a rule's example is written in, or the rule's languages when it has none, so a missing example is said. */
|
|
82
|
+
const languagesOf = (rule: RuleDefinition): readonly string[] => {
|
|
83
|
+
const written = Object.keys(rule.guide?.examples ?? {});
|
|
84
|
+
return written.length > 0 ? written : (rule.languages ?? ["ja", "en"]);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** Exit 0 when every rule passes on every example; 1 when the plugin cannot be loaded or a rule fails. */
|
|
88
|
+
export const runPluginTest = async (folder: string | undefined, context: PluginTestContext): Promise<number> => {
|
|
89
|
+
const text = TEXT[context.ui];
|
|
90
|
+
const dir = resolve(folder ?? ".");
|
|
91
|
+
const config = await withExtensions({ ...EMPTY, plugins: [dir], baseDir: dir, path: dir });
|
|
92
|
+
const problems = extensionProblems(config, context.ui);
|
|
93
|
+
if (problems.length > 0) {
|
|
94
|
+
problems.forEach((problem) => console.error(problem));
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
const rules = config.extensions?.rules ?? [];
|
|
98
|
+
if (rules.length === 0) {
|
|
99
|
+
console.error(text.noRules(dir));
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
const cases = rules.flatMap((rule) => languagesOf(rule).map((language) => ({ rule, language })));
|
|
103
|
+
const outcomes = await cases.reduce<Promise<Outcome[]>>(
|
|
104
|
+
async (done, entry) => [...(await done), await testExample(entry.rule, entry.language, config, context)],
|
|
105
|
+
Promise.resolve([]),
|
|
106
|
+
);
|
|
107
|
+
outcomes.map(lineOf).forEach((line) => console.log(line));
|
|
108
|
+
const passed = outcomes.filter((outcome) => outcome.failure === undefined).length;
|
|
109
|
+
console.log(`\n${text.summary(passed, outcomes.length)}`);
|
|
110
|
+
return passed === outcomes.length ? 0 : 1;
|
|
111
|
+
};
|
package/src/config/load.ts
CHANGED
|
@@ -52,6 +52,8 @@ export type Config = {
|
|
|
52
52
|
readonly customRules?: unknown;
|
|
53
53
|
/** grade as written: the rubric `chaff grade` reads (grade/rubric.ts). */
|
|
54
54
|
readonly grade?: unknown;
|
|
55
|
+
/** fix_plan as written: the depth chaff fix-plan rewrites to (fix-plan/chosen-depth.ts reads and checks it). */
|
|
56
|
+
readonly fixPlan?: unknown;
|
|
55
57
|
/** plugins as written: package names and paths. extension/plugin-load.ts reads and checks them. */
|
|
56
58
|
readonly plugins?: unknown;
|
|
57
59
|
/** The code chaff.yaml names, once loaded (extension/load.ts). Reading chaff.yaml does not load it. */
|
|
@@ -197,6 +199,7 @@ export const loadConfig = (path: string): Config => {
|
|
|
197
199
|
style: raw["style"] === undefined || raw["style"] === null ? undefined : (str(raw["style"]) ?? printed(raw["style"])),
|
|
198
200
|
customRules: raw["custom_rules"],
|
|
199
201
|
grade: raw["grade"],
|
|
202
|
+
fixPlan: raw["fix_plan"],
|
|
200
203
|
plugins: raw["plugins"],
|
|
201
204
|
};
|
|
202
205
|
};
|
|
@@ -36,7 +36,7 @@ const TEXT: Texts<ProblemText> = {
|
|
|
36
36
|
ja: {
|
|
37
37
|
notAMap: (where, value) => `${where}: options の ${value} は読めません。ルールの名前の下に、オプションの名前と値を並べてください`,
|
|
38
38
|
problem: (where, problem) => {
|
|
39
|
-
if (problem.kind === "unknown-rule") return `${where}: options の ${problem.rule} というルールはありません(npx
|
|
39
|
+
if (problem.kind === "unknown-rule") return `${where}: options の ${problem.rule} というルールはありません(npx chaffjs rules --json で一覧が出ます)`;
|
|
40
40
|
if (problem.kind === "no-options") return `${where}: ${problem.rule} にはオプションがありません。options に書いても何も変わりません`;
|
|
41
41
|
if (problem.kind === "not-a-map") return `${where}: options の ${problem.rule} の下には、オプションの名前と値を並べてください`;
|
|
42
42
|
if (problem.kind === "unknown-option")
|
|
@@ -47,7 +47,7 @@ const TEXT: Texts<ProblemText> = {
|
|
|
47
47
|
en: {
|
|
48
48
|
notAMap: (where, value) => `${where}: cannot read ${value} under options. Under each rule's name, list option names and values`,
|
|
49
49
|
problem: (where, problem) => {
|
|
50
|
-
if (problem.kind === "unknown-rule") return `${where}: there is no rule named ${problem.rule} under options (npx
|
|
50
|
+
if (problem.kind === "unknown-rule") return `${where}: there is no rule named ${problem.rule} under options (npx chaffjs rules --json lists them)`;
|
|
51
51
|
if (problem.kind === "no-options") return `${where}: ${problem.rule} takes no options, so writing some changes nothing`;
|
|
52
52
|
if (problem.kind === "not-a-map") return `${where}: under options, ${problem.rule} needs option names and values`;
|
|
53
53
|
if (problem.kind === "unknown-option") return `${where}: ${problem.rule} has no option ${problem.option} (it takes ${problem.known.join(" / ")})`;
|
|
@@ -9,7 +9,7 @@ const TEXT: Texts<{
|
|
|
9
9
|
readonly numberOnSeverity: (where: string, id: string) => string;
|
|
10
10
|
}> = {
|
|
11
11
|
ja: {
|
|
12
|
-
unknown: (where, id) => `${where}: ${id} というルールはありません(npx
|
|
12
|
+
unknown: (where, id) => `${where}: ${id} というルールはありません(npx chaffjs rules --json で一覧が出ます)`,
|
|
13
13
|
unreadable: (where, id, value) => `${where}: ${id} の値 ${value} は読めません(strict / normal / relaxed / off か、正の数)`,
|
|
14
14
|
numberOnSemantic: (where, id) =>
|
|
15
15
|
`${where}: ${id} は意味を読む検査なので数値の上限はありません。normal として動きます(strict / normal / relaxed / off で書いてください)`,
|
|
@@ -17,7 +17,7 @@ const TEXT: Texts<{
|
|
|
17
17
|
`${where}: ${id} には数の上限がありません。normal として動きます(段階は指摘の重さを変えます。relaxed で一段軽く、off で止まります)`,
|
|
18
18
|
},
|
|
19
19
|
en: {
|
|
20
|
-
unknown: (where, id) => `${where}: there is no rule named ${id} (npx
|
|
20
|
+
unknown: (where, id) => `${where}: there is no rule named ${id} (npx chaffjs rules --json lists them)`,
|
|
21
21
|
unreadable: (where, id, value) => `${where}: cannot read ${value} as the level of ${id} (strict / normal / relaxed / off, or a positive number)`,
|
|
22
22
|
numberOnSemantic: (where, id) => `${where}: ${id} reads meaning and has no numeric limit; it runs as normal (write strict / normal / relaxed / off)`,
|
|
23
23
|
numberOnSeverity: (where, id) =>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CustomProblem } from "./parse.ts";
|
|
2
|
+
|
|
3
|
+
/** One field of one rule, read: its value when it can be used, and what is wrong with it otherwise. */
|
|
4
|
+
export type Checked<T> = { readonly value: T | undefined; readonly problems: readonly CustomProblem[] };
|
|
5
|
+
|
|
6
|
+
export const ok = <T>(value: T): Checked<T> => ({ value, problems: [] });
|
|
7
|
+
|
|
8
|
+
export const failed = <T>(...problems: CustomProblem[]): Checked<T> => ({ value: undefined, problems });
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { LevelTable, Localized, Severity } from "../plugin.ts";
|
|
2
|
+
import { RULE_GROUPS, ruleGuideOf, type RuleGroup, type RuleGuide } from "../rule-guide.ts";
|
|
3
|
+
import { fieldProblems } from "../rule-fields.ts";
|
|
4
|
+
import { failed, ok, type Checked } from "./checked.ts";
|
|
5
|
+
|
|
6
|
+
// The fields a team's rule (custom_rules, or a plugin's rules) writes the way chaff's own rules/*.yaml do: levels,
|
|
7
|
+
// use_for, group, summary, the example by language and rewrite. Each is optional; without it the rule reads as a team
|
|
8
|
+
// rule always has. The shared fields are checked by rule-fields.ts, the one place chaff's own rules are checked too. Pure.
|
|
9
|
+
|
|
10
|
+
const SEVERITIES: readonly Severity[] = ["info", "warning", "error"];
|
|
11
|
+
const LEVEL_NAMES = ["strict", "normal", "relaxed"] as const;
|
|
12
|
+
|
|
13
|
+
const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
+
|
|
15
|
+
const printed = (value: unknown): string => (typeof value === "string" ? value : (JSON.stringify(value) ?? typeof value));
|
|
16
|
+
|
|
17
|
+
const rankOf = (severity: Severity): number => SEVERITIES.indexOf(severity) + 1;
|
|
18
|
+
|
|
19
|
+
/** level: one severity; normal is the rule's own, relaxed one lower, strict one higher, where there is one. */
|
|
20
|
+
const tableFor = (severity: Severity): LevelTable => {
|
|
21
|
+
const rank = rankOf(severity);
|
|
22
|
+
return { ...(rank < SEVERITIES.length ? { strict: rank + 1 } : {}), normal: rank, ...(rank > 1 ? { relaxed: rank - 1 } : {}) };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const severityAt = (value: unknown): Severity | undefined => SEVERITIES.find((entry) => entry === value);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* levels: a severity for each of strict, normal and relaxed, as chaff's rules with nothing to count write them. A
|
|
29
|
+
* team's detector reports places, not counts, so a number has nothing to be compared with and is refused.
|
|
30
|
+
*/
|
|
31
|
+
const tableOf = (written: unknown): { table: LevelTable; severity: Severity } | undefined => {
|
|
32
|
+
if (!isRecord(written) || Object.keys(written).some((key) => !LEVEL_NAMES.some((name) => name === key))) return undefined;
|
|
33
|
+
const ranks = LEVEL_NAMES.flatMap((name) => {
|
|
34
|
+
const severity = severityAt(written[name]);
|
|
35
|
+
return severity === undefined ? [] : [[name, rankOf(severity)] as const];
|
|
36
|
+
});
|
|
37
|
+
const normal = severityAt(written["normal"]);
|
|
38
|
+
if (normal === undefined || ranks.length !== Object.keys(written).length) return undefined;
|
|
39
|
+
return { table: Object.fromEntries(ranks), severity: normal };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type RuleLevels = { readonly table: LevelTable; readonly severity: Severity };
|
|
43
|
+
|
|
44
|
+
/** level (one severity, as before) or levels (a severity per level). Not both: they would disagree on normal. */
|
|
45
|
+
export const levelsOf = (raw: Readonly<Record<string, unknown>>, at: string): Checked<RuleLevels> => {
|
|
46
|
+
const [level, levels] = [raw["level"], raw["levels"]];
|
|
47
|
+
if (level !== undefined && levels !== undefined) return failed({ kind: "level-and-levels", at });
|
|
48
|
+
if (levels !== undefined) {
|
|
49
|
+
const read = tableOf(levels);
|
|
50
|
+
return read === undefined ? failed({ kind: "bad-levels", at, written: printed(levels) }) : ok(read);
|
|
51
|
+
}
|
|
52
|
+
if (level === undefined) return ok({ table: tableFor("warning"), severity: "warning" });
|
|
53
|
+
const severity = severityAt(level);
|
|
54
|
+
return severity === undefined ? failed({ kind: "bad-level", at, written: printed(level) }) : ok({ table: tableFor(severity), severity });
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** An example written by language ({ ja: { before, after } }) rather than as { before, after }. */
|
|
58
|
+
const isExampleByLanguage = (example: unknown): example is Record<string, unknown> =>
|
|
59
|
+
isRecord(example) && Object.keys(example).length > 0 && !("before" in example) && !("after" in example);
|
|
60
|
+
|
|
61
|
+
/** example's before and after, each by language, whichever form it is written in. */
|
|
62
|
+
export const exampleSides = (example: unknown): { readonly before: unknown; readonly after: unknown } => {
|
|
63
|
+
if (!isRecord(example)) return { before: undefined, after: undefined };
|
|
64
|
+
if (!isExampleByLanguage(example)) return { before: example["before"], after: example["after"] };
|
|
65
|
+
const pairs = Object.entries(example).flatMap(([language, pair]) => (isRecord(pair) ? [[language, pair] as const] : []));
|
|
66
|
+
return {
|
|
67
|
+
before: Object.fromEntries(pairs.map(([language, pair]) => [language, pair["before"]])),
|
|
68
|
+
after: Object.fromEntries(pairs.map(([language, pair]) => [language, pair["after"]])),
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type Described = Pick<RuleGuide, "rewrite" | "rewriteDepth"> & {
|
|
73
|
+
readonly group: RuleGroup;
|
|
74
|
+
/** undefined: the rule's name stands for its summary. */
|
|
75
|
+
readonly summary: Localized | undefined;
|
|
76
|
+
/** undefined: every genre, as a team's rule always has. */
|
|
77
|
+
readonly useFor: readonly string[] | undefined;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const textOf = (value: unknown): Localized | undefined => {
|
|
81
|
+
if (typeof value === "string") return value.trim() === "" ? undefined : { ja: value.trim(), en: value.trim() };
|
|
82
|
+
return isRecord(value) ? ruleGuideOf({ summary: value }).summary : undefined;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The fields a team's rule shares with chaff's own, checked in rule-fields.ts. An example written as { before, after }
|
|
87
|
+
* is left to the caller, which has always read and reported it.
|
|
88
|
+
*/
|
|
89
|
+
export const describedOf = (raw: Readonly<Record<string, unknown>>, at: string, genres: readonly string[]): Checked<Described> => {
|
|
90
|
+
const shared = { ...raw, example: isExampleByLanguage(raw["example"]) ? raw["example"] : undefined };
|
|
91
|
+
const problems = fieldProblems(shared, genres).map((problem) => ({ kind: problem.kind, at, written: problem.written }));
|
|
92
|
+
if (problems.length > 0) return failed(...problems);
|
|
93
|
+
const { rewrite, rewriteDepth } = ruleGuideOf({ rewrite: raw["rewrite"] });
|
|
94
|
+
const useFor = raw["use_for"];
|
|
95
|
+
return ok({
|
|
96
|
+
group: RULE_GROUPS.find((group) => group === raw["group"]) ?? "team",
|
|
97
|
+
summary: textOf(raw["summary"]),
|
|
98
|
+
useFor: Array.isArray(useFor) ? useFor.map((entry) => String(entry)) : undefined,
|
|
99
|
+
rewrite,
|
|
100
|
+
rewriteDepth,
|
|
101
|
+
});
|
|
102
|
+
};
|
package/src/custom/load.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Config } from "../config/load.ts";
|
|
|
2
2
|
import type { RuleDefinition } from "../plugin.ts";
|
|
3
3
|
import { loadRules } from "../rule-load.ts";
|
|
4
4
|
import { loadGenres } from "../genre-load.ts";
|
|
5
|
+
import { knownGenres } from "../known-genres.ts";
|
|
5
6
|
import { parseCustomRules, type CustomRules } from "./parse.ts";
|
|
6
7
|
|
|
7
8
|
/** The team's custom_rules as rules, with what could not be read. A team's rule applies to every genre, like the team's words. */
|
|
@@ -9,6 +10,7 @@ export const customRulesOf = (config: Pick<Config, "customRules" | "baseDir">):
|
|
|
9
10
|
parseCustomRules(config.customRules, {
|
|
10
11
|
builtIn: new Set(loadRules("en").map((rule) => rule.id)),
|
|
11
12
|
useFor: loadGenres().groups.map((group) => group.id),
|
|
13
|
+
genres: knownGenres(),
|
|
12
14
|
baseDir: config.baseDir,
|
|
13
15
|
});
|
|
14
16
|
|