Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support autofix with checkAgainstRule #6466

Merged
merged 8 commits into from Nov 11, 2022
5 changes: 5 additions & 0 deletions .changeset/tricky-wolves-collect.md
@@ -0,0 +1,5 @@
---
"stylelint": minor
---

Added: support autofix with `checkAgainstRule`
6 changes: 4 additions & 2 deletions docs/developer-guide/plugins.md
Expand Up @@ -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`.

Expand All @@ -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 || [])
Expand All @@ -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({
Expand Down
20 changes: 20 additions & 0 deletions lib/utils/__tests__/checkAgainstRule.test.js
Expand Up @@ -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 {}');

Expand Down
4 changes: 2 additions & 2 deletions lib/utils/checkAgainstRule.js
Expand Up @@ -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');

Expand All @@ -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);
}
Expand Down
18 changes: 12 additions & 6 deletions types/stylelint/index.d.ts
Expand Up @@ -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
Expand Down Expand Up @@ -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<P = any, S = any> = (
primaryOption: P,
secondaryOptions: Record<string, S>,
context: PluginContext,
context: RuleContext,
) => (root: PostCSS.Root, result: PostcssResult) => Promise<void> | void;

export type RuleMeta = {
Expand Down Expand Up @@ -518,6 +523,7 @@ declare module 'stylelint' {
ruleSettings: ConfigRuleSettings<T, O>;
root: PostCSS.Root;
result?: PostcssResult;
context?: RuleContext;
},
callback: (warning: PostCSS.Warning) => void,
) => void;
Expand Down