Skip to content

Commit

Permalink
fix(stylelint): parse lintCommand like argv
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Mar 4, 2023
1 parent 8a99b8f commit 20b7399
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 15 deletions.
46 changes: 46 additions & 0 deletions packages/vite-plugin-checker/src/checkers/stylelint/argv.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// copied from https://github.com/jonschlinkert/is-plain-object/blob/master/is-plain-object.js
// to make less breaking change, we'll make it a dependency before v1.0.0

export { parseArgsStringToArgv as default, parseArgsStringToArgv }
function parseArgsStringToArgv(value: string, env?: string, file?: string): string[] {
// ([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*) Matches nested quotes until the first space outside of quotes

// [^\s'"]+ or Match if not a space ' or "

// (['"])([^\5]*?)\5 or Match "quoted text" without quotes
// `\3` and `\5` are a backreference to the quote style (' or ") captured
const myRegexp = /([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*)|[^\s'"]+|(['"])([^\5]*?)\5/gi
const myString = value
const myArray: string[] = []
if (env) {
myArray.push(env)
}
if (file) {
myArray.push(file)
}
let match: RegExpExecArray | null
do {
// Each call to exec returns the next regex match as an array
match = myRegexp.exec(myString)
if (match !== null) {
// Index 1 in the array is the captured group if it exists
// Index 0 is the matched text, which we use if no captured group exists
myArray.push(firstString(match[1], match[6], match[0])!)
}
} while (match !== null)

return myArray
}

// Accepts any number of arguments, and returns the first one that is a string
// (even an empty string)
// @ts-ignore
function firstString(...args: Array<any>): string | undefined {
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < args.length; i++) {
const arg = args[i]
if (typeof arg === 'string') {
return arg
}
}
}
14 changes: 10 additions & 4 deletions packages/vite-plugin-checker/src/checkers/stylelint/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {
async configureServer({ root }) {
if (!pluginConfig.stylelint) return

const translatedOptions = translateOptions(pluginConfig.stylelint.lintCommand)
const translatedOptions = await translateOptions(pluginConfig.stylelint.lintCommand)
const baseConfig = {
cwd: root,
...translatedOptions,
} as const

const logLevel = (() => {
if (typeof pluginConfig.stylelint !== 'object') return undefined
Expand Down Expand Up @@ -80,7 +84,10 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {
if (type === 'unlink') {
manager.updateByFileId(absPath, [])
} else if (type === 'change') {
const { results: diagnosticsOfChangedFile } = await stylelint.lint({ files: filePath })
const { results: diagnosticsOfChangedFile } = await stylelint.lint({
...baseConfig,
files: filePath,
})
const newDiagnostics = diagnosticsOfChangedFile
.map((d) => normalizeStylelintDiagnostic(d))
.flat(1)
Expand All @@ -92,8 +99,7 @@ const createDiagnostic: CreateDiagnostic<'stylelint'> = (pluginConfig) => {

// initial lint
const { results: diagnostics } = await stylelint.lint({
cwd: root,
...translatedOptions,
...baseConfig,
...pluginConfig.stylelint.dev?.overrideConfig,
})

Expand Down
24 changes: 16 additions & 8 deletions packages/vite-plugin-checker/src/checkers/stylelint/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import meow from 'meow'
import type Stylelint from 'stylelint'
import { parseArgsStringToArgv } from './argv.js'

//------------------------------------------------------------------------------
// Typedefs
Expand Down Expand Up @@ -92,7 +93,7 @@ import type Stylelint from 'stylelint'

const EXIT_CODE_ERROR = 2

export const translateOptions = (command: string) => {
export const translateOptions = async (command: string) => {
const result = meow({
autoHelp: false,
autoVersion: false,
Expand Down Expand Up @@ -190,6 +191,9 @@ export const translateOptions = (command: string) => {
cacheLocation: {
type: 'string',
},
cacheStrategy: {
type: 'string',
},
color: {
type: 'boolean',
},
Expand All @@ -214,7 +218,7 @@ export const translateOptions = (command: string) => {
},
formatter: {
alias: 'f',
default: 'json',
default: 'string',
type: 'string',
},
help: {
Expand All @@ -228,6 +232,7 @@ export const translateOptions = (command: string) => {
ignorePath: {
alias: 'i',
type: 'string',
isMultiple: true,
},
ignorePattern: {
alias: 'ip',
Expand Down Expand Up @@ -267,18 +272,19 @@ export const translateOptions = (command: string) => {
stdinFilename: {
type: 'string',
},
syntax: {
alias: 's',
type: 'string',
},
version: {
alias: 'v',
type: 'boolean',
},
globbyOptions: {
alias: 'go',
type: 'string',
},
},
argv: command.split(' ').filter((item) => !!item),
argv: parseArgsStringToArgv(command),
})
return {

const optionsBase = {
...Object.fromEntries(
Object.entries(result.flags).filter(([key]) =>
[
Expand Down Expand Up @@ -311,4 +317,6 @@ export const translateOptions = (command: string) => {
formatter: result.flags.formatter === 'string' ? 'json' : result.flags.formatter,
files: result.input[1],
} as Stylelint.LinterOptions

return optionsBase
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ exports[`stylelint > serve > get initial error and subsequent error 2`] = `
[Stylelint] Found 2 errors and 0 warning"
`;
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\\":\\"\\"}]"`;
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\\":\\"\\"}]"`;
exports[`stylelint > serve > get initial error and subsequent error 4`] = `""`;
exports[`stylelint > serve > get initial error and subsequent error 4`] = `
" ERROR(Stylelint) Unexpected empty block (block-no-empty) (block-no-empty)
FILE <PROJECT_ROOT>/playground-temp/stylelint-default/src/style.css:1:7
> 1 | #root {
| ^
> 2 | }
| ^^
3 |
4 | body {
5 | color: #fff;
[Stylelint] Found 1 error and 0 warning"
`;
2 changes: 1 addition & 1 deletion playground/stylelint-default/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default defineConfig({
plugins: [
checker({
stylelint: {
lintCommand: 'stylelint ./**/*.css',
lintCommand: 'stylelint "./**/*.css"',
},
}),
],
Expand Down

0 comments on commit 20b7399

Please sign in to comment.