-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Stylelint basic support (#158)
* feat: add stylelint basic support * fix: rename variables * chore: {packages} -> packages * feat: match upstream changes
- Loading branch information
Showing
15 changed files
with
796 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
# Checkers overview | ||
|
||
vite-plugin-checkers provide built-in checkers. For now, it provides [TypeScript](/checkers/typescript), [ESLint](/checkers/eslint), [vue-tsc](/checkers/vue-tsc), [VLS](/checkers/vls). | ||
vite-plugin-checkers provide built-in checkers. For now, it provides [TypeScript](/checkers/typescript), [ESLint](/checkers/eslint), [vue-tsc](/checkers/vue-tsc), [VLS](/checkers/vls), [Stylelint](/checkers/stylelint). | ||
|
||
## How to add a checker | ||
|
||
- Set to `true` to use a checker with its default value (except ESLint). | ||
- Set to `true` to use a checker with its default value (except ESLint and Stylelint). | ||
- Leave the field blank or `false` to disable the checker. | ||
- Make sure to install the peer dependencies indicated of each checker. | ||
- Checker can be enabled with an advanced object config. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Stylelint | ||
|
||
## Installation | ||
|
||
1. Make sure [stylelint](https://www.npmjs.com/package/stylelint) and related plugins for your `stylelintrc` are installed as peer dependencies. | ||
|
||
::: warning | ||
**(Optional but highly recommended)** Install `meow@^9.0.0` with your package manager. It's needed because of Stylelint dependents on it. It's probably working fine even it's not installed as it's accessed as a phantom dependency. But when you set `hoist=false` of pnpm. It won't be accessible anymore without explicit installation. | ||
|
||
::: | ||
|
||
2. Add `stylelint` field to plugin config and `options.stylelint.lintCommand` is required. The `lintCommand` is the same as the lint command of your project. The default root of the command uses Vite's [root](https://vitejs.dev/config/#root). | ||
|
||
```js | ||
// e.g. | ||
export default { | ||
plugins: [ | ||
checker({ | ||
stylelint: { | ||
lintCommand: 'stylelint ./src/**/*.{css,vue}', // for example, lint .css & .vue | ||
}, | ||
}), | ||
], | ||
} | ||
``` | ||
|
||
## Configuration | ||
|
||
Advanced object configuration table of `options.stylelint` | ||
|
||
| field | Type | Default value | Description | | ||
| :----------------- | -------------------------------------------------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| lintCommand | `string` | This value is required | `lintCommand` will be executed at build mode, and will also be used as default config for dev mode when `stylelint.dev.stylelint` is nullable. | | ||
| dev.overrideConfig | [`Stylelint.LinterOptions`](https://github.com/stylelint/stylelint/blob/main/types/stylelint/index.d.ts) | `undefined` | **(Only in dev mode)** You can override the options of the translated from `lintCommand`. Config priority: `stylelint.lint({ cwd: root, ...translatedOptions, ...pluginConfig.stylelint.dev?.overrideConfig, })`. | | ||
| dev.logLevel | `('error' \| 'warning')[]` | `['error', 'warning']` | **(Only in dev mode)** Which level of Stylelint should be emitted to terminal and overlay in dev mode | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
packages/vite-plugin-checker/src/checkers/stylelint/main.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import chokidar from 'chokidar' | ||
import stylelint from 'stylelint' | ||
import translateOptions from './options' | ||
import path from 'path' | ||
import { fileURLToPath } from 'url' | ||
import { parentPort } from 'worker_threads' | ||
|
||
import { Checker } from '../../Checker.js' | ||
import { FileDiagnosticManager } from '../../FileDiagnosticManager.js' | ||
import { | ||
composeCheckerSummary, | ||
consoleLog, | ||
diagnosticToRuntimeError, | ||
diagnosticToTerminalLog, | ||
filterLogLevel, | ||
normalizeStylelintDiagnostic, | ||
toViteCustomPayload, | ||
} from '../../logger.js' | ||
import { ACTION_TYPES, DiagnosticLevel } from '../../types.js' | ||
|
||
const manager = new FileDiagnosticManager() | ||
|
||
import type { CreateDiagnostic } from '../../types.js' | ||
|
||
const __filename = fileURLToPath(import.meta.url) | ||
|
||
const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => { | ||
let overlay = true | ||
let terminal = true | ||
|
||
return { | ||
config: async ({ enableOverlay, enableTerminal }) => { | ||
overlay = enableOverlay | ||
terminal = enableTerminal | ||
}, | ||
async configureServer({ root }) { | ||
if (!pluginConfig.stylelint) return | ||
|
||
const translatedOptions = translateOptions(pluginConfig.stylelint.lintCommand) | ||
|
||
const logLevel = (() => { | ||
if (typeof pluginConfig.stylelint !== 'object') return undefined | ||
const userLogLevel = pluginConfig.stylelint.dev?.logLevel | ||
if (!userLogLevel) return undefined | ||
const map = { | ||
error: DiagnosticLevel.Error, | ||
warning: DiagnosticLevel.Warning, | ||
} as const | ||
|
||
return userLogLevel.map((l) => map[l]) | ||
})() | ||
|
||
const dispatchDiagnostics = () => { | ||
const diagnostics = filterLogLevel(manager.getDiagnostics(), logLevel) | ||
|
||
if (terminal) { | ||
diagnostics.forEach((d) => { | ||
consoleLog(diagnosticToTerminalLog(d, 'Stylelint')) | ||
}) | ||
const errorCount = diagnostics.filter((d) => d.level === DiagnosticLevel.Error).length | ||
const warningCount = diagnostics.filter((d) => d.level === DiagnosticLevel.Warning).length | ||
consoleLog(composeCheckerSummary('Stylelint', errorCount, warningCount)) | ||
} | ||
|
||
if (overlay) { | ||
parentPort?.postMessage({ | ||
type: ACTION_TYPES.overlayError, | ||
payload: toViteCustomPayload( | ||
'stylelint', | ||
diagnostics.map((d) => diagnosticToRuntimeError(d)) | ||
), | ||
}) | ||
} | ||
} | ||
|
||
const handleFileChange = async (filePath: string, type: 'change' | 'unlink') => { | ||
const absPath = path.resolve(root, filePath) | ||
|
||
if (type === 'unlink') { | ||
manager.updateByFileId(absPath, []) | ||
} else if (type === 'change') { | ||
const { results: diagnosticsOfChangedFile } = await stylelint.lint({ files: filePath }) | ||
const newDiagnostics = diagnosticsOfChangedFile | ||
.map((d) => normalizeStylelintDiagnostic(d)) | ||
.flat(1) | ||
manager.updateByFileId(absPath, newDiagnostics) | ||
} | ||
|
||
dispatchDiagnostics() | ||
} | ||
|
||
// initial lint | ||
const { results: diagnostics } = await stylelint.lint({ | ||
cwd: root, | ||
...translatedOptions, | ||
...pluginConfig.stylelint.dev?.overrideConfig, | ||
}) | ||
|
||
manager.initWith(diagnostics.map((p) => normalizeStylelintDiagnostic(p)).flat(1)) | ||
dispatchDiagnostics() | ||
|
||
// watch lint | ||
const watcher = chokidar.watch([], { | ||
cwd: root, | ||
ignored: (path: string) => path.includes('node_modules'), | ||
}) | ||
watcher.add(translatedOptions.files as string) | ||
watcher.on('change', async (filePath) => { | ||
handleFileChange(filePath, 'change') | ||
}) | ||
watcher.on('unlink', async (filePath) => { | ||
handleFileChange(filePath, 'unlink') | ||
}) | ||
}, | ||
} | ||
} | ||
|
||
export class StylelintChecker extends Checker<'stylelint'> { | ||
public constructor() { | ||
super({ | ||
name: 'stylelint', | ||
absFilePath: __filename, | ||
build: { | ||
buildBin: (pluginConfig) => { | ||
if (pluginConfig.stylelint) { | ||
const { lintCommand } = pluginConfig.stylelint | ||
return ['stylelint', lintCommand.split(' ').slice(1)] | ||
} | ||
return ['stylelint', ['']] | ||
}, | ||
}, | ||
createDiagnostic, | ||
}) | ||
} | ||
|
||
public init() { | ||
const createServeAndBuild = super.initMainThread() | ||
module.exports.createServeAndBuild = createServeAndBuild | ||
super.initWorkerThread() | ||
} | ||
} | ||
|
||
const stylelintChecker = new StylelintChecker() | ||
stylelintChecker.prepare() | ||
stylelintChecker.init() |
Oops, something went wrong.