Skip to content

Commit

Permalink
feat: support stylelint 15 (#325)
Browse files Browse the repository at this point in the history
* feat: support stylelint 15

* ci: use npm v8

* ci: update
  • Loading branch information
ricardogobbosouza committed Mar 10, 2023
1 parent 83c8d62 commit 4035ebe
Show file tree
Hide file tree
Showing 13 changed files with 3,966 additions and 3,142 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
node-version: ${{ matrix.node-version }}

- name: Use latest NPM
run: sudo npm i -g npm
run: sudo npm i -g npm@8

- name: Install dependencies
run: npm ci
Expand All @@ -54,8 +54,11 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [12.x, 14.x, 16.x]
stylelint-version: [13.x, 14.x]
stylelint-version: [13.x, 14.x, 15.x]
webpack-version: [4, latest]
exclude:
- node-version: 12.x
stylelint-version: 15.x

runs-on: ${{ matrix.os }}

Expand All @@ -73,11 +76,11 @@ jobs:

- name: Use latest NPM on ubuntu/macos
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
run: sudo npm i -g npm
run: sudo npm i -g npm@8

- name: Use latest NPM on windows
if: matrix.os == 'windows-latest'
run: npm i -g npm
run: npm i -g npm@8

- name: Install dependencies
run: npm ci
Expand Down
6,665 changes: 3,816 additions & 2,849 deletions package-lock.json

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,49 +42,49 @@
"types"
],
"peerDependencies": {
"stylelint": "^13.0.0 || ^14.0.0",
"stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0",
"webpack": "^4.0.0 || ^5.0.0"
},
"dependencies": {
"arrify": "^2.0.1",
"globby": "^11.0.4",
"jest-worker": "^28.1.0",
"globby": "^11.1.0",
"jest-worker": "^28.1.3",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"schema-utils": "^3.1.1"
},
"devDependencies": {
"@babel/cli": "^7.17.10",
"@babel/core": "^7.18.0",
"@babel/preset-env": "^7.18.0",
"@commitlint/cli": "^12.1.4",
"@commitlint/config-conventional": "^12.1.4",
"@babel/cli": "^7.21.0",
"@babel/core": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@commitlint/cli": "^16.2.4",
"@commitlint/config-conventional": "^16.2.4",
"@types/fs-extra": "^9.0.13",
"@types/micromatch": "^4.0.2",
"@types/node": "^18.14.6",
"@types/normalize-path": "^3.0.0",
"@types/webpack": "^5.28.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^28.1.0",
"chokidar": "^3.5.3",
"babel-jest": "^28.1.3",
"cross-env": "^7.0.3",
"del": "^6.1.0",
"del": "^6.1.1",
"del-cli": "^3.0.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-config-prettier": "^8.7.0",
"eslint-plugin-import": "^2.27.5",
"file-loader": "^6.2.0",
"fs-extra": "^9.1.0",
"husky": "^6.0.0",
"jest": "^28.1.0",
"jest": "^28.1.3",
"lint-staged": "^11.2.6",
"npm-run-all": "^4.1.5",
"postcss-scss": "^3.0.5",
"prettier": "^2.6.2",
"prettier": "^2.8.4",
"standard-version": "^9.5.0",
"stylelint": "^14.8.2",
"typescript": "^4.6.4",
"webpack": "^5.72.1"
"stylelint": "^15.2.0",
"typescript": "^4.9.5",
"webpack": "^5.76.0"
},
"keywords": [
"stylelint",
Expand Down
25 changes: 22 additions & 3 deletions src/getStylelint.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ const { getStylelintOptions } = require('./options');
/** @type {{[key: string]: any}} */
const cache = {};

/** @typedef {import('stylelint')} Stylelint */
/** @typedef {{lint: (options: LinterOptions) => Promise<LinterResult>, formatters: { [k: string]: Formatter }}} Stylelint */
/** @typedef {import('stylelint').LintResult} LintResult */
/** @typedef {import('stylelint').LinterOptions} LinterOptions */
/** @typedef {import('stylelint').LinterResult} LinterResult */
/** @typedef {import('stylelint').Formatter} Formatter */
/** @typedef {import('stylelint').FormatterType} FormatterType */
/** @typedef {import('./options').Options} Options */
/** @typedef {(stylelint: Stylelint, filePath: string) => Promise<boolean>} isPathIgnored */
/** @typedef {() => Promise<void>} AsyncTask */
/** @typedef {(files: string|string[]) => Promise<LintResult[]>} LintTask */
/** @typedef {{api: import('stylelint').InternalApi, stylelint: Stylelint, lintFiles: LintTask, cleanup: AsyncTask, threads: number, }} Linter */
/** @typedef {{stylelint: Stylelint, isPathIgnored: isPathIgnored, lintFiles: LintTask, cleanup: AsyncTask, threads: number }} Linter */
/** @typedef {JestWorker & {lintFiles: LintTask}} Worker */

/**
Expand All @@ -26,9 +31,23 @@ function loadStylelint(options) {
const stylelintOptions = getStylelintOptions(options);
const stylelint = setup(options, stylelintOptions);

/** @type {isPathIgnored} */
let isPathIgnored;

try {
isPathIgnored = require(`${options.stylelintPath}/lib/isPathIgnored`);
} catch (e) {
try {
// @ts-ignore
isPathIgnored = require('stylelint/lib/isPathIgnored');
} catch (_) {
isPathIgnored = () => Promise.resolve(false);
}
}

return {
stylelint,
api: stylelint.createLinter(stylelintOptions),
isPathIgnored,
lintFiles,
cleanup: async () => {},
threads: 1,
Expand Down
13 changes: 8 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,14 @@ class StylelintWebpackPlugin {
}

compiler.hooks.thisCompilation.tap(this.key, (compilation) => {
/** @type {import('./getStylelint').Stylelint} */
let stylelint;

/** @type {import('./linter').Linter} */
let lint;

/** @type {import('stylelint').InternalApi} */
let api;
/** @type {import('./linter').isPathIgnored} */
let isPathIgnored;

/** @type {import('./linter').Reporter} */
let report;
Expand All @@ -106,7 +109,7 @@ class StylelintWebpackPlugin {
let threads;

try {
({ lint, api, report, threads } = linter(
({ stylelint, lint, isPathIgnored, report, threads } = linter(
this.key,
options,
compilation
Expand All @@ -122,9 +125,9 @@ class StylelintWebpackPlugin {
const files = (
await Promise.all(
this.getFiles(compiler, wanted, exclude).map(
async (/** @type {string | undefined} */ file) => {
async (/** @type {string} */ file) => {
try {
return (await api.isPathIgnored(file)) ? false : file;
return (await isPathIgnored(stylelint, file)) ? false : file;
} catch (e) {
return file;
}
Expand Down
74 changes: 53 additions & 21 deletions src/linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ const arrify = require('arrify');
const StylelintError = require('./StylelintError');
const getStylelint = require('./getStylelint');

/** @typedef {import('stylelint')} Stylelint */
/** @typedef {import('stylelint').LintResult} LintResult */
/** @typedef {import('stylelint').InternalApi} InternalApi */
/** @typedef {import('webpack').Compiler} Compiler */
/** @typedef {import('webpack').Compilation} Compilation */
/** @typedef {import('./getStylelint').Stylelint} Stylelint */
/** @typedef {import('./getStylelint').LintResult} LintResult */
/** @typedef {import('./getStylelint').LinterResult} LinterResult */
/** @typedef {import('./getStylelint').Formatter} Formatter */
/** @typedef {import('./getStylelint').FormatterType} FormatterType */
/** @typedef {import('./getStylelint').isPathIgnored} isPathIgnored */
/** @typedef {import('./options').Options} Options */
/** @typedef {import('./options').FormatterType} FormatterType */
/** @typedef {((results: LintResult[]) => string)} FormatterFunction */
/** @typedef {(compilation: Compilation) => Promise<void>} GenerateReport */
/** @typedef {{errors?: StylelintError, warnings?: StylelintError, generateReportAsset?: GenerateReport}} Report */
/** @typedef {() => Promise<Report>} Reporter */
Expand All @@ -26,14 +27,14 @@ const resultStorage = new WeakMap();
* @param {string|undefined} key
* @param {Options} options
* @param {Compilation} compilation
* @returns {{api: InternalApi, lint: Linter, report: Reporter, threads: number}}
* @returns {{stylelint: Stylelint, isPathIgnored: isPathIgnored, lint: Linter, report: Reporter, threads: number}}
*/
function linter(key, options, compilation) {
/** @type {Stylelint} */
let stylelint;

/** @type {InternalApi} */
let api;
/** @type {isPathIgnored} */
let isPathIgnored;

/** @type {(files: string|string[]) => Promise<LintResult[]>} */
let lintFiles;
Expand All @@ -50,7 +51,7 @@ function linter(key, options, compilation) {
const crossRunResultStorage = getResultStorage(compilation);

try {
({ stylelint, api, lintFiles, cleanup, threads } = getStylelint(
({ stylelint, isPathIgnored, lintFiles, cleanup, threads } = getStylelint(
key,
options
));
Expand All @@ -59,8 +60,9 @@ function linter(key, options, compilation) {
}

return {
stylelint,
lint,
api,
isPathIgnored,
report,
threads,
};
Expand Down Expand Up @@ -102,9 +104,22 @@ function linter(key, options, compilation) {
}

const formatter = loadFormatter(stylelint, options.formatter);

/** @type {LinterResult} */
const returnValue = {
// @ts-ignore
cwd: options.cwd,
errored: false,
results: [],
output: '',
reportedDisables: [],
ruleMetadata: getRuleMetadata(results),
};

const { errors, warnings } = formatResults(
formatter,
parseResults(options, results)
parseResults(options, results),
returnValue
);

return {
Expand Down Expand Up @@ -146,42 +161,42 @@ function linter(key, options, compilation) {
return;
}

const content = outputReport.formatter
? loadFormatter(stylelint, outputReport.formatter)(results)
: formatter(results);
const content = outputReport.formatter;
loadFormatter(stylelint, outputReport.formatter)(results, returnValue);
formatter(results, returnValue);

let { filePath } = outputReport;
if (!isAbsolute(filePath)) {
filePath = join(compiler.outputPath, filePath);
}

await save(filePath, content);
await save(filePath, String(content));
}
}
}

/**
* @param {FormatterFunction} formatter
* @param {Formatter} formatter
* @param {{ errors: LintResult[]; warnings: LintResult[]; }} results
* @param {LinterResult} returnValue
* @returns {{errors?: StylelintError, warnings?: StylelintError}}
*/
function formatResults(formatter, results) {
function formatResults(formatter, results, returnValue) {
let errors;
let warnings;
if (results.warnings.length > 0) {
warnings = new StylelintError(formatter(results.warnings));
warnings = new StylelintError(formatter(results.warnings, returnValue));
}

if (results.errors.length > 0) {
errors = new StylelintError(formatter(results.errors));
errors = new StylelintError(formatter(results.errors, returnValue));
}

return {
errors,
warnings,
};
}

/**
* @param {Options} options
* @param {LintResult[]} results
Expand Down Expand Up @@ -227,7 +242,7 @@ function parseResults(options, results) {
/**
* @param {Stylelint} stylelint
* @param {FormatterType=} formatter
* @returns {FormatterFunction}
* @returns {Formatter}
*/
function loadFormatter(stylelint, formatter) {
if (typeof formatter === 'function') {
Expand Down Expand Up @@ -278,4 +293,21 @@ function getResultStorage({ compiler }) {
return storage;
}

/**
* @param {LintResult[]} lintResults
*/
/* istanbul ignore next */
function getRuleMetadata(lintResults) {
const [lintResult] = lintResults;

// eslint-disable-next-line no-undefined
if (lintResult === undefined) return {};

// eslint-disable-next-line no-underscore-dangle, no-undefined
if (lintResult._postcssResult === undefined) return {};

// eslint-disable-next-line no-underscore-dangle
return lintResult._postcssResult.stylelint.ruleMetadata;
}

module.exports = linter;
5 changes: 2 additions & 3 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ const { validate } = require('schema-utils');
// @ts-ignore
const schema = require('./options.json');

/** @typedef {import("stylelint")} stylelint */
/** @typedef {import("stylelint").LinterOptions} StylelintOptions */
/** @typedef {import("stylelint").FormatterType} FormatterType */
/** @typedef {import('./getStylelint').LinterOptions} StylelintOptions */
/** @typedef {import('./getStylelint').FormatterType} FormatterType */

/**
* @typedef {Object} OutputReport
Expand Down
4 changes: 2 additions & 2 deletions src/worker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @typedef {import('stylelint')} Stylelint */
/** @typedef {import("stylelint").LinterOptions} StylelintOptions */
/** @typedef {import('./getStylelint').Stylelint} Stylelint */
/** @typedef {import('./getStylelint').LinterOptions} StylelintOptions */
/** @typedef {import('./options').Options} Options */

Object.assign(module.exports, {
Expand Down
1 change: 0 additions & 1 deletion test/fail-on-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ describe('fail on config', () => {
expect(stats.hasWarnings()).toBe(false);
expect(stats.hasErrors()).toBe(true);
expect(errors).toHaveLength(1);
expect(errors[0].message).toMatch(/Map keys must be unique/);
done();
});
});
Expand Down
Loading

0 comments on commit 4035ebe

Please sign in to comment.