diff --git a/README.md b/README.md
index 6f5a27e3..60b7d0ae 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# Visit [documentation](https://vite-plugin-checker.netlify.app) for usage.
+# Visit [documentation](https://vite-plugin-checker.netlify.app) for usage
-A Vite plugin that can run TypeScript, VLS, vue-tsc, ESLint in worker thread.
+A Vite plugin that can run TypeScript, VLS, vue-tsc, ESLint, Stylelint in worker thread.
diff --git a/package.json b/package.json
index 25600fde..26874244 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"pre-commit": "pnpm exec lint-staged"
},
"lint-staged": {
- "{packages}/**/*.{js,ts}": [
+ "packages/**/*.{js,ts}": [
"eslint --fix",
"prettier --write",
"git add"
diff --git a/packages/runtime/src/components/Diagnostic.svelte b/packages/runtime/src/components/Diagnostic.svelte
index f718bf87..2c284bfb 100644
--- a/packages/runtime/src/components/Diagnostic.svelte
+++ b/packages/runtime/src/components/Diagnostic.svelte
@@ -7,6 +7,7 @@
ESLint: '#7b7fe3',
VLS: '#64b587',
'vue-tsc': '#64b587',
+ Stylelint: '#ffffff',
}
const fileRE = /(?:[a-zA-Z]:\\|\/).*(:\d+:\d+)?/g
diff --git a/packages/vite-plugin-checker/package.json b/packages/vite-plugin-checker/package.json
index 4d47fbb2..9c9aaf4c 100644
--- a/packages/vite-plugin-checker/package.json
+++ b/packages/vite-plugin-checker/package.json
@@ -59,6 +59,8 @@
},
"peerDependencies": {
"eslint": ">=7",
+ "meow": "^9.0.0",
+ "stylelint": ">=13",
"typescript": "*",
"vite": "^2.0.0 || ^3.0.0-0",
"vls": "*",
@@ -69,6 +71,12 @@
"eslint": {
"optional": true
},
+ "meow": {
+ "optional": true
+ },
+ "stylelint": {
+ "optional": true
+ },
"typescript": {
"optional": true
},
@@ -88,8 +96,10 @@
"@types/lodash.pick": "^4.4.6",
"@volar/vue-typescript": "^0.33.0",
"esbuild": "^0.14.27",
+ "meow": "^9.0.0",
"npm-run-all": "^4.1.5",
"optionator": "^0.9.1",
+ "stylelint": "^14.0.0",
"tsup": "^6.2.2",
"typescript": "~4.5.5",
"vls": "^0.7.6",
diff --git a/packages/vite-plugin-checker/src/Checker.ts b/packages/vite-plugin-checker/src/Checker.ts
index e21a7df2..17e2369e 100644
--- a/packages/vite-plugin-checker/src/Checker.ts
+++ b/packages/vite-plugin-checker/src/Checker.ts
@@ -1,12 +1,16 @@
import invariant from 'tiny-invariant'
import { isInVitestEntryThread, isMainThread } from './utils.js'
-import type { ServeAndBuildChecker, BuildInCheckerNames } from './types.js'
import { createScript, Script } from './worker.js'
// still an only issue https://github.com/microsoft/TypeScript/issues/29808#issuecomment-829750974
import type {} from 'vite'
-import type { CreateDiagnostic, BuildInCheckers } from './types.js'
+import type {
+ CreateDiagnostic,
+ BuildInCheckers,
+ ServeAndBuildChecker,
+ BuildInCheckerNames,
+} from './types.js'
if (!(isMainThread || isInVitestEntryThread)) {
process.stdout.isTTY = true
diff --git a/packages/vite-plugin-checker/src/checkers/stylelint/main.ts b/packages/vite-plugin-checker/src/checkers/stylelint/main.ts
new file mode 100644
index 00000000..efbb54c7
--- /dev/null
+++ b/packages/vite-plugin-checker/src/checkers/stylelint/main.ts
@@ -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()
diff --git a/packages/vite-plugin-checker/src/checkers/stylelint/options.ts b/packages/vite-plugin-checker/src/checkers/stylelint/options.ts
new file mode 100644
index 00000000..2ad3307e
--- /dev/null
+++ b/packages/vite-plugin-checker/src/checkers/stylelint/options.ts
@@ -0,0 +1,314 @@
+/* eslint-disable */
+
+/**
+ * This file is copied and modified from https://github.com/stylelint/stylelint/blob/97ea6f7446b861fd8940f69e90b41fa9ab1fffb5/lib/cli.js
+ *
+ */
+
+'use strict'
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+import meow from 'meow'
+import type Stylelint from 'stylelint'
+
+//------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/**
+ * @typedef {object} CLIFlags
+ * @property {boolean} [cache]
+ * @property {string} [cacheLocation]
+ * @property {string | false} config
+ * @property {string} [configBasedir]
+ * @property {string} [customSyntax]
+ * @property {string} [printConfig]
+ * @property {string} [color]
+ * @property {string} [customFormatter]
+ * @property {boolean} [disableDefaultIgnores]
+ * @property {boolean} [fix]
+ * @property {string} [formatter="json"]
+ * @property {string} [help]
+ * @property {boolean} [ignoreDisables]
+ * @property {string} [ignorePath]
+ * @property {string[]} [ignorePattern]
+ * @property {string} [noColor]
+ * @property {string} [outputFile]
+ * @property {boolean} [stdin]
+ * @property {string} [stdinFilename]
+ * @property {boolean} [reportNeedlessDisables]
+ * @property {boolean} [reportInvalidScopeDisables]
+ * @property {boolean} [reportDescriptionlessDisables]
+ * @property {number} [maxWarnings]
+ * @property {boolean} quiet
+ * @property {string} [syntax]
+ * @property {string} [version]
+ * @property {boolean} [allowEmptyInput]
+ */
+
+/**
+ * @typedef {object} CLIOptions
+ * @property {any} input
+ * @property {any} help
+ * @property {any} pkg
+ * @property {Function} showHelp
+ * @property {Function} showVersion
+ * @property {CLIFlags} flags
+ */
+
+/**
+ * @typedef {object} OptionBaseType
+ * @property {any} formatter
+ * @property {boolean} [cache]
+ * @property {string} [configFile]
+ * @property {string} [cacheLocation]
+ * @property {string} [customSyntax]
+ * @property {string} [codeFilename]
+ * @property {string} [configBasedir]
+ * @property {boolean} [quiet]
+ * @property {any} [printConfig]
+ * @property {boolean} [fix]
+ * @property {boolean} [ignoreDisables]
+ * @property {any} [ignorePath]
+ * @property {string} [outputFile]
+ * @property {boolean} [reportNeedlessDisables]
+ * @property {boolean} [reportInvalidScopeDisables]
+ * @property {boolean} [reportDescriptionlessDisables]
+ * @property {boolean} [disableDefaultIgnores]
+ * @property {number} [maxWarnings]
+ * @property {string} [syntax]
+ * @property {string[]} [ignorePattern]
+ * @property {boolean} [allowEmptyInput]
+ * @property {string} [files]
+ * @property {string} [code]
+ */
+
+//------------------------------------------------------------------------------
+// Initialization and Public Interface
+//------------------------------------------------------------------------------
+
+const EXIT_CODE_ERROR = 2
+
+export default (command: string) => {
+ const result = meow({
+ autoHelp: false,
+ autoVersion: false,
+ help: `
+ Usage: stylelint [input] [options]
+ Input: Files(s), glob(s), or nothing to use stdin.
+ If an input argument is wrapped in quotation marks, it will be passed to
+ globby for cross-platform glob support. node_modules are always ignored.
+ You can also pass no input and use stdin, instead.
+ Options:
+ --config
+ Path to a specific configuration file (JSON, YAML, or CommonJS), or the
+ name of a module in node_modules that points to one. If no --config
+ argument is provided, stylelint will search for configuration files in
+ the following places, in this order:
+ - a stylelint property in package.json
+ - a .stylelintrc file (with or without filename extension:
+ .json, .yaml, .yml, and .js are available)
+ - a stylelint.config.js file exporting a JS object
+ The search will begin in the working directory and move up the directory
+ tree until a configuration file is found.
+ --config-basedir
+ An absolute path to the directory that relative paths defining "extends"
+ and "plugins" are *relative to*. Only necessary if these values are
+ relative paths.
+ --print-config
+ Print the configuration for the given path.
+ --ignore-path, -i
+ Path to a file containing patterns that describe files to ignore. The
+ path can be absolute or relative to process.cwd(). By default, stylelint
+ looks for .stylelintignore in process.cwd().
+ --ignore-pattern, --ip
+ Pattern of files to ignore (in addition to those in .stylelintignore)
+ --fix
+ Automatically fix problems of certain rules.
+ --custom-syntax
+ Module name or path to a JS file exporting a PostCSS-compatible syntax.
+ --stdin
+ Accept stdin input even if it is empty.
+ --stdin-filename
+ A filename to assign stdin input.
+ --ignore-disables, --id
+ Ignore stylelint-disable comments.
+ --disable-default-ignores, --di
+ Allow linting of node_modules.
+ --cache [default: false]
+ Store the info about processed files in order to only operate on the
+ changed ones the next time you run stylelint. By default, the cache
+ is stored in "./.stylelintcache". To adjust this, use --cache-location.
+ --cache-location [default: '.stylelintcache']
+ Path to a file or directory to be used for the cache location.
+ Default is "./.stylelintcache". If a directory is specified, a cache
+ file will be created inside the specified folder, with a name derived
+ from a hash of the current working directory.
+ If the directory for the cache does not exist, make sure you add a trailing "/"
+ on *nix systems or "\\" on Windows. Otherwise the path will be assumed to be a file.
+ --formatter, -f [default: "string"]
+ The output formatter: "compact", "json", "tap", "unix" or "verbose"
+ --custom-formatter
+ Path to a JS file exporting a custom formatting function.
+ --quiet, -q
+ Only register problems for rules with an "error"-level severity (ignore
+ "warning"-level).
+ --color
+ --no-color
+ Force enabling/disabling of color.
+ --report-needless-disables, --rd
+ Also report errors for stylelint-disable comments that are not blocking a lint warning.
+ The process will exit with code ${EXIT_CODE_ERROR} if needless disables are found.
+ --report-invalid-scope-disables, --risd
+ Report stylelint-disable comments that used for rules that don't exist within the configuration object.
+ The process will exit with code ${EXIT_CODE_ERROR} if invalid scope disables are found.
+ --report-descriptionless-disables, --rdd
+ Report stylelint-disable comments without a description.
+ The process will exit with code ${EXIT_CODE_ERROR} if descriptionless disables are found.
+ --max-warnings, --mw
+ Number of warnings above which the process will exit with code ${EXIT_CODE_ERROR}.
+ Useful when setting "defaultSeverity" to "warning" and expecting the
+ process to fail on warnings (e.g. CI build).
+ --output-file, -o
+ Path of file to write report.
+ --version, -v
+ Show the currently installed version of stylelint.
+ --allow-empty-input, --aei
+ When glob pattern matches no files, the process will exit without throwing an error.
+ `,
+ flags: {
+ allowEmptyInput: {
+ alias: 'aei',
+ type: 'boolean',
+ },
+ cache: {
+ type: 'boolean',
+ },
+ cacheLocation: {
+ type: 'string',
+ },
+ color: {
+ type: 'boolean',
+ },
+ config: {
+ type: 'string',
+ },
+ configBasedir: {
+ type: 'string',
+ },
+ customFormatter: {
+ type: 'string',
+ },
+ customSyntax: {
+ type: 'string',
+ },
+ disableDefaultIgnores: {
+ alias: 'di',
+ type: 'boolean',
+ },
+ fix: {
+ type: 'boolean',
+ },
+ formatter: {
+ alias: 'f',
+ default: 'json',
+ type: 'string',
+ },
+ help: {
+ alias: 'h',
+ type: 'boolean',
+ },
+ ignoreDisables: {
+ alias: 'id',
+ type: 'boolean',
+ },
+ ignorePath: {
+ alias: 'i',
+ type: 'string',
+ },
+ ignorePattern: {
+ alias: 'ip',
+ type: 'string',
+ isMultiple: true,
+ },
+ maxWarnings: {
+ alias: 'mw',
+ type: 'number',
+ },
+ outputFile: {
+ alias: 'o',
+ type: 'string',
+ },
+ printConfig: {
+ type: 'boolean',
+ },
+ quiet: {
+ alias: 'q',
+ type: 'boolean',
+ },
+ reportDescriptionlessDisables: {
+ alias: 'rdd',
+ type: 'boolean',
+ },
+ reportInvalidScopeDisables: {
+ alias: 'risd',
+ type: 'boolean',
+ },
+ reportNeedlessDisables: {
+ alias: 'rd',
+ type: 'boolean',
+ },
+ stdin: {
+ type: 'boolean',
+ },
+ stdinFilename: {
+ type: 'string',
+ },
+ syntax: {
+ alias: 's',
+ type: 'string',
+ },
+ version: {
+ alias: 'v',
+ type: 'boolean',
+ },
+ },
+ argv: command.split(' ').filter((item) => !!item),
+ })
+ return {
+ ...Object.fromEntries(
+ Object.entries(result.flags).filter(([key]) =>
+ [
+ 'files',
+ 'globbyOptions',
+ 'cache',
+ 'cacheLocation',
+ 'code',
+ 'codeFilename',
+ 'config',
+ 'configFile',
+ 'configBasedir',
+ 'cwd',
+ 'ignoreDisables',
+ 'ignorePath',
+ 'ignorePattern',
+ 'reportDescriptionlessDisables',
+ 'reportNeedlessDisables',
+ 'reportInvalidScopeDisables',
+ 'maxWarnings',
+ 'customSyntax',
+ 'formatter',
+ 'disableDefaultIgnores',
+ 'fix',
+ 'allowEmptyInput',
+ 'quiet',
+ ].includes(key)
+ )
+ ),
+ formatter: result.flags.formatter === 'string' ? 'json' : result.flags.formatter,
+ files: result.input[1],
+ } as Stylelint.LinterOptions
+}
diff --git a/packages/vite-plugin-checker/src/logger.ts b/packages/vite-plugin-checker/src/logger.ts
index 329c3ae5..8e2496be 100644
--- a/packages/vite-plugin-checker/src/logger.ts
+++ b/packages/vite-plugin-checker/src/logger.ts
@@ -16,6 +16,7 @@ import type { CustomPayload } from 'vite'
const _require = createRequire(import.meta.url)
import type { Range } from 'vscode-languageclient'
import type { ESLint } from 'eslint'
+import type Stylelint from 'stylelint'
import type {
Diagnostic as LspDiagnostic,
PublishDiagnosticsParams,
@@ -81,7 +82,7 @@ export function filterLogLevel(
export function diagnosticToTerminalLog(
d: NormalizedDiagnostic,
- name?: 'TypeScript' | 'vue-tsc' | 'VLS' | 'ESLint'
+ name?: 'TypeScript' | 'vue-tsc' | 'VLS' | 'ESLint' | 'Stylelint'
): string {
const nameInLabel = name ? `(${name})` : ''
const boldBlack = chalk.bold.rgb(0, 0, 0)
@@ -380,6 +381,56 @@ export function normalizeEslintDiagnostic(diagnostic: ESLint.LintResult): Normal
.filter(isNormalizedDiagnostic)
}
+/* --------------------------------- Stylelint --------------------------------- */
+
+export function normalizeStylelintDiagnostic(
+ diagnostic: Stylelint.LintResult
+): NormalizedDiagnostic[] {
+ return diagnostic.warnings
+ .map((d) => {
+ let level = DiagnosticLevel.Error
+ switch (d.severity) {
+ case 'warning': // warn
+ level = DiagnosticLevel.Warning
+ break
+ case 'error': // error
+ level = DiagnosticLevel.Error
+ break
+ default:
+ level = DiagnosticLevel.Error
+ return null
+ }
+
+ const loc: SourceLocation = {
+ start: {
+ line: d.line,
+ column: d.column,
+ },
+ end: {
+ line: d.endLine || 0,
+ column: d.endColumn,
+ },
+ }
+
+ const codeFrame = createFrame({
+ source: diagnostic.source ?? '',
+ location: loc,
+ })
+
+ return {
+ message: `${d.text} (${d.rule})`,
+ conclusion: '',
+ codeFrame,
+ stripedCodeFrame: codeFrame && strip(codeFrame),
+ id: diagnostic.source,
+ checker: 'Stylelint',
+ loc,
+ level,
+ } as any as NormalizedDiagnostic
+ })
+ .filter(isNormalizedDiagnostic)
+}
+
/* ------------------------------ miscellaneous ----------------------------- */
export function ensureCall(callback: CallableFunction) {
setTimeout(() => {
diff --git a/packages/vite-plugin-checker/src/main.ts b/packages/vite-plugin-checker/src/main.ts
index bb59fd24..9d3dfc6b 100644
--- a/packages/vite-plugin-checker/src/main.ts
+++ b/packages/vite-plugin-checker/src/main.ts
@@ -18,7 +18,13 @@ import {
} from './types.js'
const sharedConfigKeys: (keyof SharedConfig)[] = ['enableBuild', 'overlay']
-const buildInCheckerKeys: BuildInCheckerNames[] = ['typescript', 'vueTsc', 'vls', 'eslint']
+const buildInCheckerKeys: BuildInCheckerNames[] = [
+ 'typescript',
+ 'vueTsc',
+ 'vls',
+ 'eslint',
+ 'stylelint',
+]
async function createCheckers(
userConfig: UserPluginConfig,
diff --git a/packages/vite-plugin-checker/src/types.ts b/packages/vite-plugin-checker/src/types.ts
index 0178df17..a3a3fb03 100644
--- a/packages/vite-plugin-checker/src/types.ts
+++ b/packages/vite-plugin-checker/src/types.ts
@@ -1,6 +1,7 @@
import type { ErrorPayload, ConfigEnv, CustomPayload } from 'vite'
import type { Worker } from 'worker_threads'
import type { ESLint } from 'eslint'
+import type * as Stylelint from 'stylelint'
import type { VlsOptions } from './checkers/vls/initParams.js'
/* ----------------------------- userland plugin options ----------------------------- */
@@ -59,6 +60,23 @@ export type EslintConfig =
}>
}
+/** Stylelint checker configuration */
+export type StylelintConfig =
+ | false
+ | {
+ /**
+ * lintCommand will be executed at build mode, and will also be used as
+ * default config for dev mode when options.stylelint.dev.stylelint is nullable.
+ */
+ lintCommand: string
+ dev?: Partial<{
+ /** You can override the options of translated from lintCommand. */
+ overrideConfig: Stylelint.LinterOptions
+ /** which level of the diagnostic will be emitted from plugin */
+ logLevel: ('error' | 'warning')[]
+ }>
+ }
+
export enum DiagnosticLevel {
Warning = 0,
Error = 1,
@@ -134,6 +152,7 @@ export interface BuildInCheckers {
vueTsc: VueTscConfig
vls: VlsConfig
eslint: EslintConfig
+ stylelint: StylelintConfig
}
export type BuildInCheckerNames = keyof BuildInCheckers
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1898471e..4fa7bb2a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -133,10 +133,12 @@ importers:
fast-glob: ^3.2.7
lodash.debounce: ^4.0.8
lodash.pick: ^4.4.0
+ meow: ^9.0.0
npm-run-all: ^4.1.5
npm-run-path: ^4.0.1
optionator: ^0.9.1
strip-ansi: ^6.0.0
+ stylelint: ^14.0.0
tiny-invariant: ^1.1.0
tsup: ^6.2.2
typescript: ~4.5.5
@@ -169,8 +171,10 @@ importers:
'@types/lodash.pick': 4.4.7
'@volar/vue-typescript': 0.33.9
esbuild: 0.14.54
+ meow: 9.0.0
npm-run-all: 4.1.5
optionator: 0.9.1
+ stylelint: 14.13.0
tsup: 6.2.2_typescript@4.5.5
typescript: 4.5.5
vls: 0.7.6
@@ -519,7 +523,7 @@ importers:
vue: 2.7.8
vue-class-component: 7.2.6_vue@2.7.8
vue-property-decorator: 9.1.2_chk7q7rgeabwy64hfqmb36krqe
- vue-router: 3.5.4
+ vue-router: 3.5.4_vue@2.7.8
vuex: 3.6.2_vue@2.7.8
devDependencies:
'@types/node': 15.14.9
@@ -1045,6 +1049,17 @@ packages:
'@babel/helper-validator-identifier': 7.18.6
to-fast-properties: 2.0.0
+ /@csstools/selector-specificity/2.0.2_pnx64jze6bptzcedy5bidi3zdi:
+ resolution: {integrity: sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==}
+ engines: {node: ^12 || ^14 || >=16}
+ peerDependencies:
+ postcss: ^8.2
+ postcss-selector-parser: ^6.0.10
+ dependencies:
+ postcss: 8.4.16
+ postcss-selector-parser: 6.0.10
+ dev: true
+
/@docsearch/css/3.2.1:
resolution: {integrity: sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==}
dev: false
@@ -2299,6 +2314,10 @@ packages:
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ /balanced-match/2.0.0:
+ resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
+ dev: true
+
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
@@ -2481,6 +2500,10 @@ packages:
/color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ /colord/2.9.3:
+ resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
+ dev: true
+
/colorette/1.4.0:
resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
dev: true
@@ -3010,8 +3033,8 @@ packages:
engines: {node: '>=10'}
hasBin: true
dependencies:
- is-text-path: 1.0.1
JSONStream: 1.3.5
+ is-text-path: 1.0.1
lodash: 4.17.21
meow: 8.1.2
split2: 3.2.2
@@ -3067,6 +3090,11 @@ packages:
which: 2.0.2
dev: true
+ /css-functions-list/3.1.0:
+ resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==}
+ engines: {node: '>=12.22'}
+ dev: true
+
/cssesc/3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@@ -4001,6 +4029,17 @@ packages:
merge2: 1.4.1
micromatch: 4.0.5
+ /fast-glob/3.2.12:
+ resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
/fast-json-stable-stringify/2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
dev: true
@@ -4009,6 +4048,11 @@ packages:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
dev: true
+ /fastest-levenshtein/1.0.16:
+ resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==}
+ engines: {node: '>= 4.9.1'}
+ dev: true
+
/fastq/1.13.0:
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
dependencies:
@@ -4252,6 +4296,22 @@ packages:
path-is-absolute: 1.0.1
dev: true
+ /global-modules/2.0.0:
+ resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==}
+ engines: {node: '>=6'}
+ dependencies:
+ global-prefix: 3.0.0
+ dev: true
+
+ /global-prefix/3.0.0:
+ resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==}
+ engines: {node: '>=6'}
+ dependencies:
+ ini: 1.3.8
+ kind-of: 6.0.3
+ which: 1.3.1
+ dev: true
+
/globals/11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
@@ -4276,6 +4336,10 @@ packages:
slash: 3.0.0
dev: true
+ /globjoin/0.1.4:
+ resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==}
+ dev: true
+
/graceful-fs/4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
dev: true
@@ -4372,6 +4436,11 @@ packages:
engines: {node: '>=4'}
dev: true
+ /html-tags/3.2.0:
+ resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==}
+ engines: {node: '>=8'}
+ dev: true
+
/human-signals/2.1.0:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
@@ -4399,6 +4468,11 @@ packages:
resolve-from: 4.0.0
dev: true
+ /import-lazy/4.0.0:
+ resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
+ engines: {node: '>=8'}
+ dev: true
+
/imurmurhash/0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -4527,6 +4601,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /is-plain-object/5.0.0:
+ resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
/is-regex/1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}
@@ -4691,6 +4770,10 @@ packages:
engines: {node: '>=6'}
dev: true
+ /known-css-properties/0.25.0:
+ resolution: {integrity: sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==}
+ dev: true
+
/levn/0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -4893,6 +4976,10 @@ packages:
engines: {node: '>=8'}
dev: true
+ /mathml-tag-names/2.1.3:
+ resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
+ dev: true
+
/memorystream/0.3.1:
resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
engines: {node: '>= 0.10.0'}
@@ -4915,6 +5002,24 @@ packages:
yargs-parser: 20.2.9
dev: true
+ /meow/9.0.0:
+ resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ '@types/minimist': 1.2.2
+ camelcase-keys: 6.2.2
+ decamelize: 1.2.0
+ decamelize-keys: 1.1.0
+ hard-rejection: 2.1.0
+ minimist-options: 4.1.0
+ normalize-package-data: 3.0.3
+ read-pkg-up: 7.0.1
+ redent: 3.0.0
+ trim-newlines: 3.0.1
+ type-fest: 0.18.1
+ yargs-parser: 20.2.9
+ dev: true
+
/merge-source-map/1.1.0:
resolution: {integrity: sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==}
dependencies:
@@ -5332,6 +5437,23 @@ packages:
yaml: 1.10.2
dev: true
+ /postcss-media-query-parser/0.2.3:
+ resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
+ dev: true
+
+ /postcss-resolve-nested-selector/0.1.1:
+ resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==}
+ dev: true
+
+ /postcss-safe-parser/6.0.0_postcss@8.4.16:
+ resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.3.3
+ dependencies:
+ postcss: 8.4.16
+ dev: true
+
/postcss-selector-parser/6.0.10:
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
engines: {node: '>=4'}
@@ -5340,6 +5462,10 @@ packages:
util-deprecate: 1.0.2
dev: true
+ /postcss-value-parser/4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ dev: true
+
/postcss/7.0.39:
resolution: {integrity: sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==}
engines: {node: '>=6.0.0'}
@@ -5979,6 +6105,57 @@ packages:
acorn: 8.8.0
dev: true
+ /style-search/0.1.0:
+ resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
+ dev: true
+
+ /stylelint/14.13.0:
+ resolution: {integrity: sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@csstools/selector-specificity': 2.0.2_pnx64jze6bptzcedy5bidi3zdi
+ balanced-match: 2.0.0
+ colord: 2.9.3
+ cosmiconfig: 7.0.1
+ css-functions-list: 3.1.0
+ debug: 4.3.4
+ fast-glob: 3.2.12
+ fastest-levenshtein: 1.0.16
+ file-entry-cache: 6.0.1
+ global-modules: 2.0.0
+ globby: 11.1.0
+ globjoin: 0.1.4
+ html-tags: 3.2.0
+ ignore: 5.2.0
+ import-lazy: 4.0.0
+ imurmurhash: 0.1.4
+ is-plain-object: 5.0.0
+ known-css-properties: 0.25.0
+ mathml-tag-names: 2.1.3
+ meow: 9.0.0
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.16
+ postcss-media-query-parser: 0.2.3
+ postcss-resolve-nested-selector: 0.1.1
+ postcss-safe-parser: 6.0.0_postcss@8.4.16
+ postcss-selector-parser: 6.0.10
+ postcss-value-parser: 4.2.0
+ resolve-from: 5.0.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ style-search: 0.1.0
+ supports-hyperlinks: 2.3.0
+ svg-tags: 1.0.0
+ table: 6.8.0
+ v8-compile-cache: 2.3.0
+ write-file-atomic: 4.0.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/sucrase/3.25.0:
resolution: {integrity: sha512-WxTtwEYXSmZArPGStGBicyRsg5TBEFhT5b7N+tF+zauImP0Acy+CoUK0/byJ8JNPK/5lbpWIVuFagI4+0l85QQ==}
engines: {node: '>=8'}
@@ -6011,6 +6188,14 @@ packages:
has-flag: 4.0.0
dev: true
+ /supports-hyperlinks/2.3.0:
+ resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ supports-color: 7.2.0
+ dev: true
+
/supports-preserve-symlinks-flag/1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -6793,8 +6978,12 @@ packages:
vue-class-component: 7.2.6_vue@2.7.8
dev: false
- /vue-router/3.5.4:
+ /vue-router/3.5.4_vue@2.7.8:
resolution: {integrity: sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ==}
+ peerDependencies:
+ vue: ^2
+ dependencies:
+ vue: 2.7.8
dev: false
/vue-template-compiler/2.7.8:
@@ -6931,6 +7120,14 @@ packages:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
+ /write-file-atomic/4.0.2:
+ resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
+ engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 3.0.7
+ dev: true
+
/ws/8.8.1:
resolution: {integrity: sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==}
engines: {node: '>=10.0.0'}