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

Fix prettier and other rules working at the same time #360

Merged
merged 2 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ module.exports = {
'plugin:n/recommended',
'plugin:prettier/recommended',
],
env: {
node: true,
},
};
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const ruleFunction = (expectation, options, context) => {
// Default to '<input>' if a filepath was not provided.
// This mimics eslint's behaviour
const filepath = root.source.input.file || '<input>';
const source = root.source.input.css;

const prettierRcOptions = await prettier.resolveConfig(filepath, {
editorconfig: true,
Expand Down Expand Up @@ -107,6 +106,7 @@ const ruleFunction = (expectation, options, context) => {

let prettierSource;

const source = root.toString();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where asynchrony comes into play. Previously, this code was executed before some asynchronous operations, and it turned out that first this plugin gets the code, after that other rules made changes to the code, and after that the prettier was launched on the old version of the code. Now this code works synchronously because it runs after all asynchronous operations.

try {
prettierSource = await prettier.format(source, prettierOptions);
} catch (err) {
Expand Down Expand Up @@ -182,7 +182,7 @@ const ruleFunction = (expectation, options, context) => {
insertText +
rawData.substring(difference.offset + deleteText.length)
);
}, root.source.input.css);
}, source);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like the prettier always runs on the raw input data, and not on the current version of the code (some rules may have done their job before the prettier).


// If root.source.syntax exists then it means stylelint had to use
// postcss-syntax to guess the postcss parser that it should use based
Expand Down
30 changes: 27 additions & 3 deletions test/stylelint-prettier-e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import {spawnSync} from 'node:child_process';
import {resolve, sep, dirname} from 'node:path';
import {fileURLToPath} from 'node:url';

import stylelint from 'stylelint';

import baseConfig from './fixtures/stylelint.config.js';

const __dirname = dirname(fileURLToPath(import.meta.url));

const stylelintCwd = `${__dirname}/fixtures`;

/**
* Tests that report errors in multiple files may change the order of the files
* across multiple runs.
Expand Down Expand Up @@ -65,15 +71,33 @@ describe('E2E Tests', () => {
assert.strictEqual(result.error, expectedResult);
assert.strictEqual(result.status, 0);
});

/** @see https://github.com/prettier/stylelint-prettier/issues/354 */
test('the --fix option works correctly with other rules', async () => {
const inputCode = `.a {\n color: #ffffff;\n font-size: 16px\n}\n`;
const fixConfig = structuredClone(baseConfig);
fixConfig.rules['color-hex-length'] = 'short';

const {code: outputCode} = await stylelint.lint({
code: inputCode,
configBasedir: stylelintCwd,
fix: true,
config: fixConfig,
});

assert.strictEqual(
outputCode,
'.a {\n color: #fff;\n font-size: 16px;\n}\n'
);
});
});

function runStylelint(pattern) {
const stylelintCmd = resolve(`${__dirname}/../node_modules/.bin/stylelint`);
const cwd = `${__dirname}/fixtures`;

// Use github formatter as it is less likely to change across releases
const result = spawnSync(stylelintCmd, ['--formatter=github', pattern], {
cwd,
cwd: stylelintCwd,
});

return {
Expand All @@ -82,6 +106,6 @@ function runStylelint(pattern) {
error: result.stderr
.toString()
.trim()
.replaceAll(`file=${cwd}${sep}`, 'file='),
.replaceAll(`file=${stylelintCwd}${sep}`, 'file='),
};
}