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 allowEmptyInput, cache, fix options to configuration object #6778

Merged
merged 6 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/seven-coats-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"stylelint": minor
---

Added: `allowEmptyInput`, `cache`, `fix` options to configuration object
42 changes: 42 additions & 0 deletions docs/user-guide/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,45 @@ If the globs are absolute paths, they are used as is. If they are relative, they
- or `process.cwd()`.

_Note that this is not an efficient method for ignoring lots of files._ If you want to ignore a lot of files efficiently, use [`.stylelintignore`](ignore-code.md) or adjust your files globs.

## `allowEmptyInput`

Stylelint does not throw an error when the glob pattern matches no files.

For example:

```json
{
"allowEmptyInput": true
}
```

[More info](options.md#allowemptyinput).

## `cache`

Store the results of processed files so that Stylelint only operates on the changed ones.

For example:

```json
{
"cache": true
}
```

[More info](options.md#cache).

## `fix`

Automatically fix, where possible, problems reported by rules.

For example:

```json
{
"fix": true
}
```

[More info](options.md#fix).
85 changes: 85 additions & 0 deletions lib/__tests__/standalone-cache.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,91 @@ describe('standalone cache uses cacheLocation', () => {
});
});

describe('standalone cache (enabled in config)', () => {
const cwd = path.join(__dirname, 'tmp', 'standalone-cache');

safeChdir(cwd);

const expectedCacheFilePath = path.join(cwd, '.stylelintcache');

function getConfigWithCache(additional = {}) {
return {
files: replaceBackslashes(path.join(fixturesPath, 'cache', '*.css')),
config: {
cache: true,
rules: { 'block-no-empty': true, 'color-no-invalid-hex': true },
},
...additional,
};
}

beforeEach(async () => {
// Initial run to warm up the cache
await standalone(getConfigWithCache());
});

afterEach(async () => {
// Clean up after each test case
await removeFile(expectedCacheFilePath);
await removeFile(newFileDest);
});

it('uses cache when no CLI argument is provided', async () => {
mattxwang marked this conversation as resolved.
Show resolved Hide resolved
// Add "changed" file
await fs.copyFile(validFile, newFileDest);

// Next run should lint only changed files
const { results } = await standalone(getConfigWithCache());

// Ensure only changed files are linted
expect(results.some((file) => isChanged(file, validFile))).toBe(false);
expect(results.some((file) => isChanged(file, newFileDest))).toBe(true);

const { cache } = fCache.createFromFile(expectedCacheFilePath);

expect(typeof cache.getKey(validFile)).toBe('object');
expect(cache.getKey(validFile)).toBeTruthy();
expect(typeof cache.getKey(newFileDest)).toBe('object');
expect(cache.getKey(newFileDest)).toBeTruthy();
});

it('uses cache when --cache is provided', async () => {
// Add "changed" file
await fs.copyFile(validFile, newFileDest);

// Next run should lint only changed files
const { results } = await standalone(getConfigWithCache({ cache: true }));

// Ensure only changed files are linted
expect(results.some((file) => isChanged(file, validFile))).toBe(false);
expect(results.some((file) => isChanged(file, newFileDest))).toBe(true);

const { cache } = fCache.createFromFile(expectedCacheFilePath);

expect(typeof cache.getKey(validFile)).toBe('object');
expect(cache.getKey(validFile)).toBeTruthy();
expect(typeof cache.getKey(newFileDest)).toBe('object');
expect(cache.getKey(newFileDest)).toBeTruthy();
});

it('does not use cache when --no-cache is explicitly provided', async () => {
// Add "changed" file
await fs.copyFile(validFile, newFileDest);

// Next run should lint all files (regardless of changed)
const { results } = await standalone(getConfigWithCache({ cache: false }));

// Ensure all files are linted
expect(results.some((file) => isChanged(file, validFile))).toBe(true);
expect(results.some((file) => isChanged(file, newFileDest))).toBe(true);

const { cache } = fCache.createFromFile(expectedCacheFilePath);

expect(cache.getKey(validFile)).toBeUndefined();
expect(cache.getKey(newFileDest)).toBeUndefined();
});
});

describe('standalone cache uses a config file', () => {
const cwd = path.join(__dirname, 'tmp', 'standalone-cache-use-config-file');

Expand Down
13 changes: 13 additions & 0 deletions lib/__tests__/standalone-fix.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ it('outputs fixed code when input is code string', async () => {
expect(result.output).toBe('a { color: red; }');
});

it('fixes when enabled in config', async () => {
const config = {
fix: true,
rules: {
'color-hex-length': 'short',
},
};

const { output } = await standalone({ code: 'a { color: #ffffff; }', config });

expect(output).toBe('a { color: #fff; }');
});

it('apply indentation autofix at last', async () => {
const result = await standalone({
code: 'a {\nbox-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.2), inset 0 1px 2px 0 rgba(0, 0, 0, 0.1);\n}',
Expand Down
11 changes: 11 additions & 0 deletions lib/__tests__/standalone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ it('standalone with nonexistent-file and allowEmptyInput enabled quietly exits',
expect(output).toBe('[]');
});

it('standalone with nonexistent-file and allowEmptyInput enabled (in config) quitely exits', async () => {
const { results, errored, output } = await standalone({
files: `${fixturesPath}/nonexistent-file.css`,
config: { ...configBlockNoEmpty, allowEmptyInput: true },
});

expect(results).toHaveLength(0);
expect(errored).toBe(false);
expect(output).toBe('[]');
});

describe('standalone passing code with syntax error', () => {
let results;

Expand Down
4 changes: 4 additions & 0 deletions lib/augmentConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,10 @@ function addOptions(stylelint, config) {
augmentedConfig.customSyntax = stylelint._options.customSyntax;
}

if (stylelint._options.fix) {
augmentedConfig.fix = stylelint._options.fix;
}

return augmentedConfig;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/lintPostcssResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ module.exports = function lintPostcssResult(stylelintOptions, postcssResult, con
configurationComment: config.configurationComment || DEFAULT_CONFIGURATION_COMMENT,
fix:
!disableFix &&
stylelintOptions.fix &&
config.fix &&
// Next two conditionals are temporary measures until #2643 is resolved
isFileFixCompatible &&
!postcssResult.stylelint.disabledRanges[ruleName],
Expand Down
9 changes: 6 additions & 3 deletions lib/standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const writeFileAtomic = require('write-file-atomic');
*/
async function standalone({
allowEmptyInput = false,
mattxwang marked this conversation as resolved.
Show resolved Hide resolved
cache: useCache = false,
cache,
cacheLocation,
cacheStrategy,
code,
Expand Down Expand Up @@ -134,7 +134,7 @@ async function standalone({
const postcssResult = stylelintResult._postcssResult;
const returnValue = prepareReturnValue([stylelintResult], maxWarnings, formatterFunction, cwd);

if (fix && postcssResult && !postcssResult.stylelint.ignored) {
if ((fix || config?.fix) && postcssResult && !postcssResult.stylelint.ignored) {
mattxwang marked this conversation as resolved.
Show resolved Hide resolved
returnValue.output =
!postcssResult.stylelint.disableWritingFix && postcssResult.opts
? // If we're fixing, the output should be the fixed code
Expand Down Expand Up @@ -164,6 +164,9 @@ async function standalone({
fileList = fileList.concat(ALWAYS_IGNORED_GLOBS.map((glob) => `!${glob}`));
}

// do not cache if config is explicitly overrided by option
const useCache = cache || (config?.cache && cache !== false);
mattxwang marked this conversation as resolved.
Show resolved Hide resolved

if (!useCache) {
stylelint._fileCache.destroy();
}
Expand Down Expand Up @@ -246,7 +249,7 @@ async function standalone({
});

stylelintResults = await Promise.all(getStylelintResults);
} else if (allowEmptyInput) {
} else if (allowEmptyInput || config?.allowEmptyInput) {
mattxwang marked this conversation as resolved.
Show resolved Hide resolved
stylelintResults = await Promise.all([]);
} else if (filePathsLengthBeforeIgnore) {
// All input files ignored
Expand Down
3 changes: 3 additions & 0 deletions types/stylelint/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ declare namespace stylelint {
configurationComment?: string;
overrides?: ConfigOverride[];
customSyntax?: CustomSyntax;
allowEmptyInput?: boolean;
cache?: boolean;
fix?: boolean;
};

/** @internal */
Expand Down