From 11b3c1e5b446f39c9d90b9da55bd2353fe6d3210 Mon Sep 17 00:00:00 2001 From: Aaron Casanova <32409546+aaronccasanova@users.noreply.github.com> Date: Fri, 11 Nov 2022 15:11:41 -0800 Subject: [PATCH] Add support autofix with `checkAgainstRule` (#6466) Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> --- .changeset/tricky-wolves-collect.md | 5 +++++ docs/developer-guide/plugins.md | 6 ++++-- lib/utils/__tests__/checkAgainstRule.test.js | 20 ++++++++++++++++++++ lib/utils/checkAgainstRule.js | 4 ++-- types/stylelint/index.d.ts | 18 ++++++++++++------ 5 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 .changeset/tricky-wolves-collect.md diff --git a/.changeset/tricky-wolves-collect.md b/.changeset/tricky-wolves-collect.md new file mode 100644 index 0000000000..dba4dd4321 --- /dev/null +++ b/.changeset/tricky-wolves-collect.md @@ -0,0 +1,5 @@ +--- +"stylelint": minor +--- + +Added: support autofix with `checkAgainstRule` diff --git a/docs/developer-guide/plugins.md b/docs/developer-guide/plugins.md index 11b11245c1..eea90b11e7 100644 --- a/docs/developer-guide/plugins.md +++ b/docs/developer-guide/plugins.md @@ -240,6 +240,7 @@ It accepts an options object and a callback that is invoked with warnings from t - `ruleSettings`: settings for the rule you are invoking - `root`: the root node to run this rule against - `result?`: the PostCSS result for resolving and invoking custom rules +- `context?`: the [context](rules.md#add-autofix) for the rule you are invoking Use the warning to create a _new_ warning _from your plugin rule_ that you report with `stylelint.utils.report`. @@ -250,7 +251,7 @@ const allowableAtRules = [ /* .. */ ]; -function myPluginRule(primaryOption, secondaryOptionObject) { +function myPluginRule(primaryOption, secondaryOptionObject, ruleContext) { return (postcssRoot, postcssResult) => { const defaultedOptions = Object.assign({}, secondaryOptionObject, { ignoreAtRules: allowableAtRules.concat(options.ignoreAtRules || []) @@ -261,7 +262,8 @@ function myPluginRule(primaryOption, secondaryOptionObject) { ruleName: "at-rule-no-unknown", ruleSettings: [primaryOption, defaultedOptions], root: postcssRoot, - result: postcssResult + result: postcssResult, + context: ruleContext }, (warning) => { stylelint.utils.report({ diff --git a/lib/utils/__tests__/checkAgainstRule.test.js b/lib/utils/__tests__/checkAgainstRule.test.js index fffaef6833..cd8a94fd91 100644 --- a/lib/utils/__tests__/checkAgainstRule.test.js +++ b/lib/utils/__tests__/checkAgainstRule.test.js @@ -87,6 +87,26 @@ describe('checkAgainstRule', () => { expect(warnings[0].column).toBe(1); }); + it('outputs fixed code when provided a context object', () => { + const root = postcss.parse(' a { color: red; }'); + const context = { fix: true }; + + const warnings = []; + + checkAgainstRule( + { + ruleName: 'indentation', + ruleSettings: 2, + root, + context, + }, + (warning) => warnings.push(warning), + ); + + expect(warnings).toHaveLength(0); + expect(root.toString()).toBe('a { color: red; }'); + }); + it('checks against custom rule (passing)', () => { const root = postcss.parse('.not-empty {}'); diff --git a/lib/utils/checkAgainstRule.js b/lib/utils/checkAgainstRule.js index 062a1ebdcb..8a138954fe 100644 --- a/lib/utils/checkAgainstRule.js +++ b/lib/utils/checkAgainstRule.js @@ -16,7 +16,7 @@ function checkAgainstRule(options, callback) { if (!callback) throw new Error('Expected a callback function'); - const { ruleName, ruleSettings, root, result } = options; + const { ruleName, ruleSettings, root, result, context = {} } = options; if (!ruleName) throw new Error('Expected a "ruleName" option'); @@ -37,7 +37,7 @@ function checkAgainstRule(options, callback) { // @ts-expect-error - this error should not occur with PostCSS 8 const tmpPostcssResult = new Result(); - rule(settings[0], /** @type {Object} */ (settings[1]), {})(root, tmpPostcssResult); + rule(settings[0], /** @type {Object} */ (settings[1]), context)(root, tmpPostcssResult); for (const warning of tmpPostcssResult.warnings()) callback(warning); } diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index d9344d822e..0e8b02ada8 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -148,11 +148,6 @@ declare module 'stylelint' { export type CustomSyntax = string | PostCSS.Syntax; - export type PluginContext = { - fix?: boolean | undefined; - newline?: string | undefined; - }; - // Note: With strict function types enabled, function signatures are checked contravariantly. // This means that it would not be possible for rule authors to narrow the message function // parameters to e.g. just `string`. Declaring the type for rule message functions through @@ -180,10 +175,20 @@ declare module 'stylelint' { optional?: boolean; }; + export type RuleContext = { + fix?: boolean | undefined; + newline?: string | undefined; + }; + + /** + * @deprecated Use `RuleContext` instead. + */ + export type PluginContext = RuleContext; + export type RuleBase

= ( primaryOption: P, secondaryOptions: Record, - context: PluginContext, + context: RuleContext, ) => (root: PostCSS.Root, result: PostcssResult) => Promise | void; export type RuleMeta = { @@ -518,6 +523,7 @@ declare module 'stylelint' { ruleSettings: ConfigRuleSettings; root: PostCSS.Root; result?: PostcssResult; + context?: RuleContext; }, callback: (warning: PostCSS.Warning) => void, ) => void;