Skip to content

Commit 20b7399

Browse files
committed
fix(stylelint): parse lintCommand like argv
1 parent 8a99b8f commit 20b7399

File tree

5 files changed

+87
-15
lines changed

5 files changed

+87
-15
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// copied from https://github.com/jonschlinkert/is-plain-object/blob/master/is-plain-object.js
2+
// to make less breaking change, we'll make it a dependency before v1.0.0
3+
4+
export { parseArgsStringToArgv as default, parseArgsStringToArgv }
5+
function parseArgsStringToArgv(value: string, env?: string, file?: string): string[] {
6+
// ([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*) Matches nested quotes until the first space outside of quotes
7+
8+
// [^\s'"]+ or Match if not a space ' or "
9+
10+
// (['"])([^\5]*?)\5 or Match "quoted text" without quotes
11+
// `\3` and `\5` are a backreference to the quote style (' or ") captured
12+
const myRegexp = /([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*)|[^\s'"]+|(['"])([^\5]*?)\5/gi
13+
const myString = value
14+
const myArray: string[] = []
15+
if (env) {
16+
myArray.push(env)
17+
}
18+
if (file) {
19+
myArray.push(file)
20+
}
21+
let match: RegExpExecArray | null
22+
do {
23+
// Each call to exec returns the next regex match as an array
24+
match = myRegexp.exec(myString)
25+
if (match !== null) {
26+
// Index 1 in the array is the captured group if it exists
27+
// Index 0 is the matched text, which we use if no captured group exists
28+
myArray.push(firstString(match[1], match[6], match[0])!)
29+
}
30+
} while (match !== null)
31+
32+
return myArray
33+
}
34+
35+
// Accepts any number of arguments, and returns the first one that is a string
36+
// (even an empty string)
37+
// @ts-ignore
38+
function firstString(...args: Array<any>): string | undefined {
39+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
40+
for (let i = 0; i < args.length; i++) {
41+
const arg = args[i]
42+
if (typeof arg === 'string') {
43+
return arg
44+
}
45+
}
46+
}

packages/vite-plugin-checker/src/checkers/stylelint/main.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {
3737
async configureServer({ root }) {
3838
if (!pluginConfig.stylelint) return
3939

40-
const translatedOptions = translateOptions(pluginConfig.stylelint.lintCommand)
40+
const translatedOptions = await translateOptions(pluginConfig.stylelint.lintCommand)
41+
const baseConfig = {
42+
cwd: root,
43+
...translatedOptions,
44+
} as const
4145

4246
const logLevel = (() => {
4347
if (typeof pluginConfig.stylelint !== 'object') return undefined
@@ -80,7 +84,10 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {
8084
if (type === 'unlink') {
8185
manager.updateByFileId(absPath, [])
8286
} else if (type === 'change') {
83-
const { results: diagnosticsOfChangedFile } = await stylelint.lint({ files: filePath })
87+
const { results: diagnosticsOfChangedFile } = await stylelint.lint({
88+
...baseConfig,
89+
files: filePath,
90+
})
8491
const newDiagnostics = diagnosticsOfChangedFile
8592
.map((d) => normalizeStylelintDiagnostic(d))
8693
.flat(1)
@@ -92,8 +99,7 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {
9299

93100
// initial lint
94101
const { results: diagnostics } = await stylelint.lint({
95-
cwd: root,
96-
...translatedOptions,
102+
...baseConfig,
97103
...pluginConfig.stylelint.dev?.overrideConfig,
98104
})
99105

packages/vite-plugin-checker/src/checkers/stylelint/options.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import meow from 'meow'
1515
import type Stylelint from 'stylelint'
16+
import { parseArgsStringToArgv } from './argv.js'
1617

1718
//------------------------------------------------------------------------------
1819
// Typedefs
@@ -92,7 +93,7 @@ import type Stylelint from 'stylelint'
9293

9394
const EXIT_CODE_ERROR = 2
9495

95-
export const translateOptions = (command: string) => {
96+
export const translateOptions = async (command: string) => {
9697
const result = meow({
9798
autoHelp: false,
9899
autoVersion: false,
@@ -190,6 +191,9 @@ export const translateOptions = (command: string) => {
190191
cacheLocation: {
191192
type: 'string',
192193
},
194+
cacheStrategy: {
195+
type: 'string',
196+
},
193197
color: {
194198
type: 'boolean',
195199
},
@@ -214,7 +218,7 @@ export const translateOptions = (command: string) => {
214218
},
215219
formatter: {
216220
alias: 'f',
217-
default: 'json',
221+
default: 'string',
218222
type: 'string',
219223
},
220224
help: {
@@ -228,6 +232,7 @@ export const translateOptions = (command: string) => {
228232
ignorePath: {
229233
alias: 'i',
230234
type: 'string',
235+
isMultiple: true,
231236
},
232237
ignorePattern: {
233238
alias: 'ip',
@@ -267,18 +272,19 @@ export const translateOptions = (command: string) => {
267272
stdinFilename: {
268273
type: 'string',
269274
},
270-
syntax: {
271-
alias: 's',
272-
type: 'string',
273-
},
274275
version: {
275276
alias: 'v',
276277
type: 'boolean',
277278
},
279+
globbyOptions: {
280+
alias: 'go',
281+
type: 'string',
282+
},
278283
},
279-
argv: command.split(' ').filter((item) => !!item),
284+
argv: parseArgsStringToArgv(command),
280285
})
281-
return {
286+
287+
const optionsBase = {
282288
...Object.fromEntries(
283289
Object.entries(result.flags).filter(([key]) =>
284290
[
@@ -311,4 +317,6 @@ export const translateOptions = (command: string) => {
311317
formatter: result.flags.formatter === 'string' ? 'json' : result.flags.formatter,
312318
files: result.input[1],
313319
} as Stylelint.LinterOptions
320+
321+
return optionsBase
314322
}

playground/stylelint-default/__tests__/__snapshots__/test.spec.ts.snap

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ exports[`stylelint > serve > get initial error and subsequent error 2`] = `
2525
[Stylelint] Found 2 errors and 0 warning"
2626
`;
2727
28-
exports[`stylelint > serve > get initial error and subsequent error 3`] = `"[{\\"checkerId\\":\\"Stylelint\\",\\"frame\\":\\" > 1 | #root {/n | ^/n > 2 | }/n | ^^/n 3 |/n 4 | body {/n 5 | color: rgb(0, 0, 0);\\",\\"id\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"level\\":1,\\"loc\\":{\\"column\\":7,\\"file\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"line\\":1},\\"message\\":\\"Unexpected empty block (block-no-empty) (block-no-empty)\\",\\"stack\\":\\"\\"},{\\"checkerId\\":\\"Stylelint\\",\\"frame\\":\\" 3 |/n 4 | body {/n > 5 | color: rgb(0, 0, 0);/n | ^^^^^^^^^^^^/n 6 | }/n 7 |\\",\\"id\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"level\\":1,\\"loc\\":{\\"column\\":10,\\"file\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"line\\":5},\\"message\\":\\"Expected modern color-function notation (color-function-notation) (color-function-notation)\\",\\"stack\\":\\"\\"}]"`;
28+
exports[`stylelint > serve > get initial error and subsequent error 3`] = `"[{\\"checkerId\\":\\"Stylelint\\",\\"frame\\":\\" > 1 | #root {/n | ^/n > 2 | }/n | ^^/n 3 |/n 4 | body {/n 5 | color: #fff;\\",\\"id\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"level\\":1,\\"loc\\":{\\"column\\":7,\\"file\\":\\"<PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css\\",\\"line\\":1},\\"message\\":\\"Unexpected empty block (block-no-empty) (block-no-empty)\\",\\"stack\\":\\"\\"}]"`;
2929
30-
exports[`stylelint > serve > get initial error and subsequent error 4`] = `""`;
30+
exports[`stylelint > serve > get initial error and subsequent error 4`] = `
31+
" ERROR(Stylelint) Unexpected empty block (block-no-empty) (block-no-empty)
32+
FILE <PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css:1:7
33+
34+
> 1 | #root {
35+
| ^
36+
> 2 | }
37+
| ^^
38+
3 |
39+
4 | body {
40+
5 | color: #fff;
41+
[Stylelint] Found 1 error and 0 warning"
42+
`;

playground/stylelint-default/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default defineConfig({
55
plugins: [
66
checker({
77
stylelint: {
8-
lintCommand: 'stylelint ./**/*.css',
8+
lintCommand: 'stylelint "./**/*.css"',
99
},
1010
}),
1111
],

0 commit comments

Comments
 (0)