├── .nvmrc
├── docs
├── introduction.md
├── public
│ └── logo.png
├── package.json
├── checkers
│ ├── overview.md
│ ├── vls.md
│ ├── oxlint.md
│ └── typescript.md
├── index.md
├── introduction
│ ├── getting-started.md
│ └── introduction.md
└── .vitepress
│ └── config.ts
├── playground
├── vls-vue2
│ ├── .npmrc
│ ├── .browserslistrc
│ ├── src
│ │ ├── shims-vue.d.ts
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── views
│ │ │ ├── About.vue
│ │ │ └── Home.vue
│ │ ├── store
│ │ │ └── index.ts
│ │ ├── main.ts
│ │ ├── shims-tsx.d.ts
│ │ ├── App.vue
│ │ └── router
│ │ │ └── index.ts
│ ├── public
│ │ └── favicon.ico
│ ├── .gitignore
│ ├── vetur.config.cjs
│ ├── .eslintrc.js
│ ├── index.html
│ ├── vite.config.js
│ ├── tsconfig.json
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── eslint-flat
│ ├── src
│ │ └── index.js
│ ├── eslint.config.js
│ ├── vite.config.js
│ ├── package.json
│ ├── index.html
│ ├── tsconfig.json
│ └── __tests__
│ │ ├── test.spec.ts
│ │ └── __snapshots__
│ │ └── test.spec.ts.snap
├── multiple-hmr
│ ├── src
│ │ ├── value.ts
│ │ ├── main.tsx
│ │ ├── index.css
│ │ ├── App.css
│ │ ├── App.tsx
│ │ └── favicon.svg
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── config-default
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ ├── test.spec.ts
│ │ └── __snapshots__
│ │ └── test.spec.ts.snap
├── eslint-default
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── config-overlay-false
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── multiple-reload
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ └── package.json
├── config-enableBuild-false
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── __tests__
│ │ └── test.spec.ts
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ └── package.json
├── config-overlay-changes
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ ├── __snapshots__
│ │ └── test.spec.ts.snap
│ │ └── test.spec.ts
├── config-terminal-false
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── __tests__
│ │ ├── test.spec.ts
│ │ └── __snapshots__
│ │ │ └── test.spec.ts.snap
│ ├── tsconfig.json
│ └── package.json
├── eslint-config-log-level
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── backend-integration
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── main.tsx
│ │ ├── App.css
│ │ ├── App.tsx
│ │ └── index.css
│ ├── tsconfig.node.json
│ ├── .gitignore
│ ├── index.html
│ ├── vite.config.js
│ ├── tsconfig.json
│ ├── package.json
│ ├── __test__
│ │ ├── test.spec.ts
│ │ ├── serve.js
│ │ └── __snapshots__
│ │ │ └── test.spec.ts.snap
│ ├── public
│ │ └── vite.svg
│ └── server.js
├── config-initialIsOpen-error
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ ├── __snapshots__
│ │ └── test.spec.ts.snap
│ │ └── test.spec.ts
├── config-initialIsOpen-false
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── config-no-runtime-in-build
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── config-overlay-position-style
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── index.html
│ ├── vite.config.js
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── config-initialIsOpen-error-warnings
│ ├── src
│ │ ├── text.ts
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── __tests__
│ │ ├── __snapshots__
│ │ │ └── test.spec.ts.snap
│ │ └── test.spec.ts
│ ├── tsconfig.json
│ └── package.json
├── stylelint-default
│ ├── .stylelintrc.json
│ ├── src
│ │ ├── style.css
│ │ └── main.ts
│ ├── .eslintrc.json
│ ├── vite.config.js
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ └── __tests__
│ │ └── test.spec.ts
├── oxlint-default
│ ├── .oxlintrc.json
│ ├── vite.config.js
│ ├── src
│ │ └── main.ts
│ ├── package.json
│ ├── index.html
│ ├── tsconfig.json
│ └── __tests__
│ │ └── test.spec.ts
├── vue-tsc-vue3
│ ├── src
│ │ ├── main.ts
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── shims-vue.d.ts
│ │ ├── App.vue
│ │ └── components
│ │ │ └── HelloWorld.vue
│ ├── public
│ │ └── favicon.ico
│ ├── vite.config.js
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── biome-default
│ ├── src
│ │ └── index.js
│ ├── vite.config.js
│ ├── biome.json
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ └── __tests__
│ │ └── test.spec.ts
├── vue-tsc-buildmode
│ ├── src
│ │ ├── main.ts
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── shims-vue.d.ts
│ │ ├── App.vue
│ │ └── components
│ │ │ └── HelloWorld.vue
│ ├── public
│ │ └── favicon.ico
│ ├── vite.config.js
│ ├── packages
│ │ ├── core
│ │ │ ├── src
│ │ │ │ └── index.ts
│ │ │ └── tsconfig.json
│ │ └── utils
│ │ │ ├── src
│ │ │ └── helpers.ts
│ │ │ └── tsconfig.json
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ └── __tests__
│ │ └── test.spec.ts
├── typescript-react
│ ├── vite.config.js
│ ├── src
│ │ ├── main.tsx
│ │ ├── index.css
│ │ ├── App.css
│ │ ├── App.tsx
│ │ └── favicon.svg
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── __tests__
│ │ └── test.spec.ts
├── tsconfig.json
├── serializers.ts
└── vitestGlobalSetup.ts
├── packages
├── vite-plugin-checker
│ ├── src
│ │ ├── checkers
│ │ │ ├── vls
│ │ │ │ └── typings.d.ts
│ │ │ ├── oxlint
│ │ │ │ ├── types.ts
│ │ │ │ ├── main.ts
│ │ │ │ ├── options.ts
│ │ │ │ └── server.ts
│ │ │ ├── stylelint
│ │ │ │ └── argv.ts
│ │ │ └── vueTsc
│ │ │ │ └── languagePlugins.cjs
│ │ ├── utils.ts
│ │ ├── FileDiagnosticManager.ts
│ │ ├── client
│ │ │ └── index.ts
│ │ └── glob.ts
│ ├── tsconfig.json
│ ├── tsup.config.ts
│ └── __tests__
│ │ ├── codeFrame.spec.ts
│ │ ├── logger.spec.ts
│ │ └── vlsConfig.spec.ts
└── runtime
│ ├── src
│ ├── vite-env.d.ts
│ ├── components
│ │ ├── List.ce.vue
│ │ └── Checker.ce.vue
│ ├── main.ts
│ ├── useChecker.ts
│ └── ws.ts
│ ├── .gitignore
│ ├── index.html
│ ├── tsconfig.node.json
│ ├── package.json
│ ├── README.md
│ ├── tsconfig.json
│ └── vite.config.ts
├── pnpm-workspace.yaml
├── .npmrc
├── .gitattributes
├── .vscode
├── extensions.json
└── settings.json
├── netlify.toml
├── CONTRIBUTING.md
├── scripts
├── docs-check.sh
└── vitestGlobalSetup.ts
├── vitest.config.ts
├── .github
├── renovate.json5
├── workflows
│ ├── provenance.yml
│ ├── release.yml
│ └── sync-volar.yml
└── ISSUE_TEMPLATE
│ └── feature_request.yaml
├── vitest.config.e2e.ts
├── knip.json
├── README.md
├── LICENSE
├── biome.json
├── package.json
└── .gitignore
/.nvmrc:
--------------------------------------------------------------------------------
1 | v24
2 |
--------------------------------------------------------------------------------
/docs/introduction.md:
--------------------------------------------------------------------------------
1 | # introduction
2 |
--------------------------------------------------------------------------------
/playground/vls-vue2/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
2 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/vls/typings.d.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/playground/eslint-flat/src/index.js:
--------------------------------------------------------------------------------
1 | const a = "hello"
2 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/value.ts:
--------------------------------------------------------------------------------
1 | export var value: string = 1
2 |
--------------------------------------------------------------------------------
/packages/runtime/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/playground/config-default/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/eslint-default/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/vls-vue2/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/multiple-reload/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Multiple Checkers'
2 |
--------------------------------------------------------------------------------
/packages/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /public/build/
3 |
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/backend-integration/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'playground/**'
3 | - 'packages/*'
4 | - 'docs'
5 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/src/text.ts:
--------------------------------------------------------------------------------
1 | export const text = 'Vanilla JS/TS'
2 |
--------------------------------------------------------------------------------
/playground/stylelint-default/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard"
3 | }
4 |
--------------------------------------------------------------------------------
/docs/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/docs/public/logo.png
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/oxlint/types.ts:
--------------------------------------------------------------------------------
1 | export type DisplayTarget = 'overlay' | 'terminal'
2 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | console.log(text)
4 |
--------------------------------------------------------------------------------
/playground/oxlint-default/.oxlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "categories": {
3 | "correctness": "error"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/playground/stylelint-default/src/style.css:
--------------------------------------------------------------------------------
1 | #root {
2 | }
3 |
4 | body {
5 | color: rgb(0, 0, 0);
6 | }
7 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
2 | auto-install-peers=false
3 | hoist=false
4 | shell-emulator=true
5 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # https://stackoverflow.com/questions/61958231/github-actions-prettier-finds-errors-only-on-windows-latest
2 | * text=auto eol=lf
--------------------------------------------------------------------------------
/playground/vls-vue2/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vls-vue2/public/favicon.ico
--------------------------------------------------------------------------------
/playground/vls-vue2/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vls-vue2/src/assets/logo.png
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/playground/biome-default/src/index.js:
--------------------------------------------------------------------------------
1 | const a = 'hello'
2 | var b = 'world'
3 | const c = '!'
4 | var d = a + b + c
5 |
6 | export default c
7 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vue-tsc-vue3/public/favicon.ico
--------------------------------------------------------------------------------
/playground/eslint-default/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vue-tsc-vue3/src/assets/logo.png
--------------------------------------------------------------------------------
/playground/multiple-reload/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/stylelint-default/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vue-tsc-buildmode/public/favicon.ico
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "vue.volar",
4 | "vue.vscode-typescript-vue-plugin",
5 | "biomejs.biome"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fi3ework/vite-plugin-checker/HEAD/playground/vue-tsc-buildmode/src/assets/logo.png
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/eslint-flat/eslint.config.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | files: ["src/**/*"],
4 | rules: {
5 | semi: 'error',
6 | },
7 | },
8 | ]
9 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"]
4 | }
5 |
--------------------------------------------------------------------------------
/playground/stylelint-default/src/main.ts:
--------------------------------------------------------------------------------
1 | import './style.css'
2 |
3 | const rootDom = document.querySelector('#root')!
4 | rootDom.innerHTML = 'Hello world.'
5 |
6 | export {}
7 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import { DefineComponent } from 'vue'
3 | const component: DefineComponent<{}, {}, any>
4 | export default component
5 | }
6 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | const rootDom = document.querySelector('#root')! as HTMLElement
4 | rootDom.innerHTML = text
5 |
6 | export {}
7 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import { DefineComponent } from 'vue'
3 | const component: DefineComponent<{}, {}, any>
4 | export default component
5 | }
6 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')!
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-default/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-default/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
4 | "parser": "@typescript-eslint/parser",
5 | "plugins": ["@typescript-eslint"]
6 | }
7 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var hello = 'Hello'
4 |
5 | const rootDom = document.querySelector('#root')! as HTMLElement
6 | rootDom.innerHTML = hello + text
7 |
8 | export {}
9 |
--------------------------------------------------------------------------------
/playground/eslint-default/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | let count: string = 0
4 | var hello = 'Hello'
5 |
6 | const rootDom = document.querySelector('#root')!
7 | rootDom.innerHTML = hello + text
8 |
9 | export {}
10 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | export default new Vuex.Store({
7 | state: {},
8 | mutations: {},
9 | actions: {},
10 | modules: {},
11 | })
12 |
--------------------------------------------------------------------------------
/playground/multiple-reload/src/main.ts:
--------------------------------------------------------------------------------
1 | import { text } from './text'
2 |
3 | var count: string = 0
4 | const hello = 'Hello'
5 |
6 | const rootDom = document.querySelector('#root')!
7 | rootDom.innerHTML = hello + text + count
8 |
9 | export {}
10 |
--------------------------------------------------------------------------------
/playground/oxlint-default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | oxlint: true,
8 | }),
9 | ],
10 | })
11 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "private": true,
4 | "type": "module",
5 | "scripts": {
6 | "build": "vitepress build",
7 | "dev": "vitepress dev"
8 | },
9 | "dependencies": {
10 | "vitepress": "^1.6.4"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/runtime/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/playground/backend-integration/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/playground/biome-default/vite.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { defineConfig } from 'vite'
3 | import checker from 'vite-plugin-checker'
4 |
5 | export default defineConfig({
6 | plugins: [
7 | checker({
8 | biome: true,
9 | }),
10 | ],
11 | })
12 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build.environment]
2 | NPM_FLAGS = "--version" # prevent Netlify npm install
3 | [build]
4 | publish = "docs/.vitepress/dist"
5 | command = "npx pnpm i --store=node_modules/.pnpm-store --frozen-lockfile && npm run docs:build"
6 | ignore = "./scripts/docs-check.sh"
7 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import checker from 'vite-plugin-checker'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue(), checker({ vueTsc: true })],
8 | })
9 |
--------------------------------------------------------------------------------
/packages/runtime/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import checker from 'vite-plugin-checker'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue(), checker({ vueTsc: { buildMode: true } })],
8 | })
9 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/packages/core/src/index.ts:
--------------------------------------------------------------------------------
1 | import { formatMessage, capitalize, processData as utilsProcessData } from '../../utils/src/helpers';
2 |
3 | export function processData(data: string): string {
4 | const processed = utilsProcessData(data);
5 | return formatMessage(capitalize(processed));
6 | }
--------------------------------------------------------------------------------
/playground/eslint-default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | eslint: {
8 | lintCommand: 'eslint ./src --ext .ts',
9 | },
10 | }),
11 | ],
12 | })
13 |
--------------------------------------------------------------------------------
/playground/stylelint-default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | stylelint: {
8 | lintCommand: 'stylelint "./**/*.css"',
9 | },
10 | }),
11 | ],
12 | })
13 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | eslint: {
8 | lintCommand: 'eslint ./src --ext .ts',
9 | },
10 | }),
11 | ],
12 | })
13 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # CONTRIBUTING
2 |
3 | ## Development
4 |
5 | ```bash
6 | # Make sure that corepack(https://github.com/nodejs/corepack) is enabled.
7 | corepack enable
8 | pnpm i
9 | pnpm build
10 | pnpm dev
11 | ```
12 |
13 | ## Publish
14 |
15 | Package is automated published in CI, see `.github/workflows/release.yml`.
16 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from '@/App.vue'
3 | import router from '@/router'
4 | import store from '@/store'
5 |
6 | Vue.config.productionTip = false
7 |
8 | new Vue({
9 | router,
10 | store,
11 | render: (h) => h(App),
12 | }).$mount('#app')
13 |
14 | export const str: string = 1
15 |
--------------------------------------------------------------------------------
/playground/eslint-flat/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | eslint: {
8 | lintCommand: 'eslint "./src/**/*.js"',
9 | useFlatConfig: true,
10 | },
11 | }),
12 | ],
13 | })
14 |
--------------------------------------------------------------------------------
/playground/multiple-reload/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | typescript: true,
8 | eslint: {
9 | lintCommand: 'eslint ./src --ext .ts',
10 | },
11 | }),
12 | ],
13 | })
14 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 |
5 | export default defineConfig({
6 | plugins: [
7 | checker({
8 | overlay: false,
9 | eslint: {
10 | lintCommand: 'eslint ./src --ext .ts',
11 | },
12 | }),
13 | ],
14 | })
15 |
--------------------------------------------------------------------------------
/playground/typescript-react/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import checker from 'vite-plugin-checker'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react(),
9 | checker({
10 | typescript: true,
11 | }),
12 | ],
13 | })
14 |
--------------------------------------------------------------------------------
/playground/biome-default/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
3 | "files": {
4 | "includes": ["./src/*.js"]
5 | },
6 | "linter": {
7 | "rules": {
8 | "recommended": true,
9 | "style": {
10 | "noDefaultExport": "error"
11 | }
12 | }
13 | },
14 | "formatter": {
15 | "enabled": false
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | eslint: {
8 | lintCommand: 'eslint ./src --ext .ts',
9 | dev: { logLevel: ['warning'] },
10 | },
11 | }),
12 | ],
13 | })
14 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/packages/utils/src/helpers.ts:
--------------------------------------------------------------------------------
1 | export function formatMessage(message: string): string {
2 | return `[Utils] ${message}`;
3 | }
4 |
5 | export function capitalize(str: string): string {
6 | return str.charAt(0).toUpperCase() + str.slice(1);
7 | }
8 |
9 | export function processData(input: number): string {
10 | return input.toString();
11 | }
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { createRoot } from 'react-dom/client'
3 |
4 | import App from './App'
5 | import './index.css'
6 |
7 | const container = document.getElementById('root') as HTMLElement
8 | const root = createRoot(container)
9 | root.render(
10 |
11 |
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/playground/backend-integration/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { createRoot } from 'react-dom/client'
3 |
4 | import App from './App'
5 | import './index.css'
6 |
7 | const container = document.getElementById('root') as HTMLElement
8 | const root = createRoot(container)
9 | root.render(
10 |
11 |
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import { buildSucceed, isBuild } from '../../testUtils'
4 |
5 | describe('config-enableBuild-false', () => {
6 | describe.runIf(isBuild)('build', () => {
7 | it('should pass', async () => {
8 | expect(buildSucceed).toBe(true)
9 | })
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/playground/typescript-react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { createRoot } from 'react-dom/client'
3 |
4 | import App from './App'
5 | import './index.css'
6 |
7 | const container = document.getElementById('root') as HTMLElement
8 | const root = createRoot(container)
9 | root.render(
10 |
11 |
12 |
13 | )
14 |
--------------------------------------------------------------------------------
/playground/vls-vue2/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
25 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/playground/oxlint-default/src/main.ts:
--------------------------------------------------------------------------------
1 | const unusedVariable1 = 42;
2 |
3 | console.log('This is a test');
4 |
5 | debugger;
6 |
7 | const unusedVariable2 = 100;
8 |
9 | function testFunction() {
10 | console.log('Inside test function');
11 | }
12 |
13 | console.log('yes'); debugger;
14 |
15 | console.log('no');
16 |
17 | console.log("complete line");
18 |
19 | testFunction();
20 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | overlay: {
8 | initialIsOpen: false,
9 | },
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | }),
14 | ],
15 | })
16 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue'
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | overlay: {
8 | initialIsOpen: 'error',
9 | },
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | }),
14 | ],
15 | })
16 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { isMainThread as _isMainThread, threadId } from 'node:worker_threads'
2 |
3 | // since vitest run all cases in worker thread, we should compatible with it to pass E2E tests
4 |
5 | // @ts-expect-error use Vitest
6 | export const isInVitestEntryThread = threadId === 0 && process.env.VITEST
7 | export const isMainThread = _isMainThread || isInVitestEntryThread
8 |
--------------------------------------------------------------------------------
/playground/backend-integration/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/playground/backend-integration/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Vite + React + TS
7 |
8 |
9 | Title on static server
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | overlay: {
8 | initialIsOpen: 'error',
9 | },
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | }),
14 | ],
15 | })
16 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | // config-edit-slot
7 | plugins: [
8 | checker({
9 | eslint: {
10 | lintCommand: 'eslint ./src --ext .ts',
11 | },
12 | // checker-edit-slot
13 | }),
14 | ],
15 | })
16 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | base: '/my-app/',
7 | // config-edit-slot
8 | plugins: [
9 | checker({
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | // checker-edit-slot
14 | }),
15 | ],
16 | })
17 |
--------------------------------------------------------------------------------
/scripts/docs-check.sh:
--------------------------------------------------------------------------------
1 | echo "prev commit: $CACHED_COMMIT_REF"
2 | echo "current commit: $COMMIT_REF"
3 | git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF docs package.json pnpm-lock.yaml netlify.toml scripts/docs-check.sh
4 | has_diff=$?
5 | git describe --exact-match --tags $(git log -n1 --pretty='%h')
6 | has_tag=$?
7 |
8 | echo "diff exit code: $has_diff"
9 | echo "tag exit code: $has_tag"
10 |
11 | exit $(($has_diff || $has_tag))
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | export default defineConfig({
4 | test: {
5 | exclude: [
6 | '**/node_modules/**',
7 | '**/dist/**',
8 | './playground/**/*.*',
9 | './playground-temp/**/*.*',
10 | ],
11 | testTimeout: 20000,
12 | globalSetup: ['./scripts/vitestGlobalSetup.ts'],
13 | },
14 | esbuild: {
15 | target: 'node14',
16 | },
17 | })
18 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | // config-edit-slot
7 | plugins: [
8 | checker({
9 | terminal: false,
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | // checker-edit-slot
14 | }),
15 | ],
16 | })
17 |
--------------------------------------------------------------------------------
/playground/eslint-flat/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/eslint-flat",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint .",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "eslint": "^9.39.1",
14 | "vite": "^7.1.11",
15 | "vite-plugin-checker": "workspace:*"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import checker from 'vite-plugin-checker'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 |
9 | react(),
10 | checker({
11 | typescript: true,
12 | eslint: {
13 | lintCommand: 'eslint ./src --ext .ts',
14 | },
15 | }),
16 | ],
17 | })
18 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | // config-edit-slot
7 | plugins: [
8 | checker({
9 | enableBuild: false,
10 | eslint: {
11 | lintCommand: 'eslint ./src --ext .ts',
12 | },
13 | // checker-edit-slot
14 | }),
15 | ],
16 | })
17 |
--------------------------------------------------------------------------------
/playground/eslint-flat/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/oxlint-default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/oxlint-default",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "oxlint",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "oxlint": "^1.18.0",
14 | "vite": "^7.1.11",
15 | "vite-plugin-checker": "workspace:*"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/playground/biome-default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/eslint-default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/multiple-reload/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/oxlint-default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/stylelint-default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/typescript-react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/biome-default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/biome-default",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "biome lint",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@biomejs/biome": "^2.1.2",
14 | "vite": "^7.1.11",
15 | "vite-plugin-checker": "workspace:*"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/playground/typescript-react/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/packages/utils/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "declaration": true,
8 | "outDir": "dist",
9 | "composite": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "skipLibCheck": true,
13 | "lib": ["esnext"]
14 | },
15 | "include": ["src/**/*.ts"]
16 | }
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/playground/backend-integration/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import checker from 'vite-plugin-checker'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | build: {
8 | // generate manifest.json in outDir
9 | manifest: true,
10 | rollupOptions: {
11 | input: './src/main.tsx',
12 | },
13 | },
14 | plugins: [react(), checker({ typescript: true })],
15 | })
16 |
--------------------------------------------------------------------------------
/.github/renovate.json5:
--------------------------------------------------------------------------------
1 | {
2 | $schema: 'https://docs.renovatebot.com/renovate-schema.json',
3 | extends: ['config:recommended', 'schedule:weekly'],
4 | ignorePaths: ['**/tests/**', '**/node_modules/**'],
5 | labels: ['dependencies'],
6 | rangeStrategy: 'bump',
7 | ignoreDeps: [
8 | // manually update some packages
9 | 'pnpm',
10 | 'typescript',
11 | // align Node.js version minimum requirements
12 | '@types/node',
13 | 'node',
14 | ],
15 | }
16 |
--------------------------------------------------------------------------------
/playground/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["./"],
3 | "exclude": ["**/dist/**"],
4 | "compilerOptions": {
5 | "lib": ["ESNext"],
6 | "target": "ES2020",
7 | "module": "ESNext",
8 | "outDir": "dist",
9 | "baseUrl": ".",
10 | "allowJs": true,
11 | "esModuleInterop": true,
12 | "resolveJsonModule": true,
13 | "moduleResolution": "Node",
14 | "skipLibCheck": true,
15 | "noUnusedLocals": true,
16 | "jsx": "preserve"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@tsconfig/strictest/tsconfig.json",
4 | "@tsconfig/node20/tsconfig.json"
5 | ],
6 | "compilerOptions": {
7 | "allowJs": true,
8 | "isolatedModules": true,
9 | "noUnusedParameters": false,
10 | "module": "preserve",
11 | "moduleResolution": "bundler",
12 | "exactOptionalPropertyTypes": false
13 | },
14 | "include": ["src", "__tests__"],
15 | "exclude": ["src/@runtime"]
16 | }
17 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import checker from 'vite-plugin-checker'
3 |
4 | export default defineConfig({
5 | plugins: [
6 | checker({
7 | overlay: {
8 | position: 'tr',
9 | badgeStyle: 'background-color: #E799B0',
10 | panelStyle: 'background-color: #A4C1FF;',
11 | },
12 | eslint: {
13 | lintCommand: 'eslint ./src --ext .ts',
14 | },
15 | }),
16 | ],
17 | })
18 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "jsx": "preserve",
8 | "sourceMap": true,
9 | "resolveJsonModule": true,
10 | "esModuleInterop": true,
11 | "skipLibCheck": true,
12 | "lib": ["esnext", "dom"],
13 | "types": ["vite/client"]
14 | },
15 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
16 | }
17 |
--------------------------------------------------------------------------------
/playground/vls-vue2/vetur.config.cjs:
--------------------------------------------------------------------------------
1 | // vetur.config.js
2 | /** @type {import('vls').VeturConfig} */
3 |
4 | module.exports = {
5 | // **optional** default: `{}`
6 | // override vscode settings
7 | // Notice: It only affects the settings used by Vetur.
8 | settings: {
9 | 'vetur.useWorkspaceDependencies': true,
10 | 'vetur.experimental.templateInterpolationService': true,
11 | },
12 | // **optional** default: `[{ root: './' }]`
13 | // support monorepos
14 | projects: ['./'],
15 | }
16 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/packages/core/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "declaration": true,
8 | "outDir": "dist",
9 | "composite": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "skipLibCheck": true,
13 | "lib": ["esnext"]
14 | },
15 | "include": ["src/**/*.ts"],
16 | "references": [
17 | { "path": "../utils" }
18 | ]
19 | }
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/vue-tsc-vue3",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "serve": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^3.5.24"
13 | },
14 | "devDependencies": {
15 | "@vitejs/plugin-vue": "^6.0.3",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*",
19 | "vue-tsc": "~3.0.4"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`config-initialIsOpen-error-warnings > serve > should not show overlay when only warning exists 1`] = `
4 | " 1 | import { text } from './text'
5 | 2 |
6 | > 3 | var rootDom = document.querySelector('#root')! as HTMLElement
7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | 4 | rootDom.innerHTML = text
9 | 5 |
10 | 6 | export {}"
11 | `;
12 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/vue-tsc-vue3",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "serve": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^3.5.24"
13 | },
14 | "devDependencies": {
15 | "@vitejs/plugin-vue": "^6.0.3",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*",
19 | "vue-tsc": "~3.0.4"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/playground/vls-vue2/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: [
7 | 'plugin:vue/essential',
8 | 'eslint:recommended',
9 | '@vue/typescript/recommended',
10 | '@vue/prettier',
11 | ],
12 | parserOptions: {
13 | ecmaVersion: 2020,
14 | parser: '@typescript-eslint/parser',
15 | },
16 | rules: {
17 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
18 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/provenance.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | permissions:
11 | contents: read
12 | jobs:
13 | check-provenance:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | with:
18 | fetch-depth: 0
19 | - name: Check provenance downgrades
20 | uses: danielroe/provenance-action@41bcc969e579d9e29af08ba44fcbfdf95cee6e6c # v0.1.1
21 | with:
22 | fail-on-provenance-change: true
23 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import { diagnostics, isServe, sleepForServerReady, stripedLog } from '../../testUtils'
5 |
6 | describe('config-terminal-false', () => {
7 | describe.runIf(isServe)('serve', () => {
8 | it('should not log into terminal', async () => {
9 | await sleepForServerReady()
10 | expect(stringify(diagnostics)).toMatchSnapshot()
11 | expect(stripedLog).toMatchSnapshot()
12 | })
13 | })
14 | })
15 |
--------------------------------------------------------------------------------
/playground/stylelint-default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/stylelint-default",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "stylelint \"./**/*.css\"",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "meow": "^13.2.0",
14 | "stylelint": "^16.22.0",
15 | "stylelint-config-standard": "^38.0.0",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/biome-default/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-default/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/eslint-default/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/eslint-flat/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/multiple-reload/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/oxlint-default/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/stylelint-default/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-default",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/eslint-default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/eslint-default",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/playground/multiple-reload/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/multiple-reload",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/runtime/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@vite-plugin-checker/runtime",
3 | "version": "0.0.0",
4 | "private": true,
5 | "description": "Runtime code for vite-plugin-checker",
6 | "sideEffects": [
7 | "*.ts"
8 | ],
9 | "type": "module",
10 | "main": "dist/main.js",
11 | "scripts": {
12 | "build": "vue-tsc --noEmit && vite build",
13 | "build:test": "pnpm run build",
14 | "dev": "vite build --watch"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^6.0.3",
18 | "vite": "^7.1.11",
19 | "vue": "^3.5.24",
20 | "vue-tsc": "~3.0.4"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { copyFile } from 'node:fs/promises'
2 | import { defineConfig } from 'tsup'
3 |
4 | export default defineConfig({
5 | format: ['esm'],
6 | outDir: 'dist',
7 | async onSuccess() {
8 | await copyFile(
9 | 'src/checkers/vueTsc/languagePlugins.cjs',
10 | 'dist/checkers/vueTsc/languagePlugins.cjs',
11 | )
12 | },
13 | entry: ['src', '!src/checkers/vueTsc/languagePlugins.cjs'],
14 | splitting: false,
15 | bundle: false,
16 | sourcemap: true,
17 | clean: true,
18 | target: 'node14',
19 | platform: 'node',
20 | dts: true,
21 | })
22 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-overlay-changes",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-overlay-false",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-terminal-false",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react"
18 | },
19 | "include": ["./src"]
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-enableBuild-false/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-enable-build-false",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/eslint-config-log-level",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/typescript-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "types": ["vite/client"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react"
18 | },
19 | "include": ["./src"]
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-initial-is-open-error",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-initial-is-open-false",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-no-runtime-in-build",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/multiple-hmr",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "serve": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^19.1.0",
13 | "react-dom": "^19.1.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^19.1.8",
17 | "@types/react-dom": "^19.1.6",
18 | "@vitejs/plugin-react": "^4.7.0",
19 | "typescript": "^5.8.3",
20 | "vite": "^7.1.11",
21 | "vite-plugin-checker": "workspace:*"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-overlay-position-style",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/typescript-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/typescript-react",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "serve": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^19.1.0",
13 | "react-dom": "^19.1.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^19.1.8",
17 | "@types/react-dom": "^19.1.6",
18 | "@vitejs/plugin-react": "^4.7.0",
19 | "typescript": "^5.8.3",
20 | "vite": "^7.1.11",
21 | "vite-plugin-checker": "workspace:*"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/config-initial-is-open-error-warnings",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "lint": "eslint --ext .js,.ts ./src/**",
10 | "serve": "vite preview"
11 | },
12 | "devDependencies": {
13 | "@typescript-eslint/eslint-plugin": "^5.62.0",
14 | "@typescript-eslint/parser": "^5.62.0",
15 | "eslint": "^8.57.1",
16 | "typescript": "^5.8.3",
17 | "vite": "^7.1.11",
18 | "vite-plugin-checker": "workspace:*"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "strict": true,
7 | "jsx": "preserve",
8 | "sourceMap": true,
9 | "resolveJsonModule": true,
10 | "esModuleInterop": true,
11 | "skipLibCheck": true,
12 | "lib": ["esnext", "dom"],
13 | "types": ["vite/client"],
14 | "outDir": "dist"
15 | },
16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
17 | "references": [
18 | { "path": "./packages/core" },
19 | { "path": "./packages/utils" }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/playground/vls-vue2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue2 + Vite
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/playground/config-overlay-false/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import { getHmrOverlayText, isServe, sleepForServerReady } from '../../testUtils'
4 |
5 | describe('config-overlay-false', () => {
6 | describe.runIf(isServe)('serve', async () => {
7 | it('should not find overlay', async () => {
8 | await sleepForServerReady()
9 | try {
10 | await getHmrOverlayText()
11 | } catch (e) {
12 | await expect((e as any).toString()).toContain(
13 | 'Error: Invariant failed: .message-body is expected in shadow root'
14 | )
15 | }
16 | })
17 | })
18 | })
19 |
--------------------------------------------------------------------------------
/packages/runtime/README.md:
--------------------------------------------------------------------------------
1 | # @vite-plugin-checker/runtime
2 |
3 | Runtime code for vite-plugin-checker, this package will be directly bundled into the vite-plugin-checker package in building process and hasn't be released to NPM for now.
4 |
5 | ## Development
6 |
7 | ### local
8 |
9 | Watch and compile code with mock diagnostics and html without vite-plugin-checker.
10 |
11 | ```bash
12 | pnpm dev-local
13 | pnpm preview
14 | ```
15 |
16 | ### with vite-plugin-checker
17 |
18 | Watch and compile bundled JS to `../vite-plugin-checker/dist/@runtime/main.js`. Run `pnpm dev` in monorepo root will invoke below scripts.
19 |
20 | ```bash
21 | pnpm dev
22 | ```
23 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
28 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
28 |
--------------------------------------------------------------------------------
/playground/backend-integration/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/playground/vls-vue2/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import { createVuePlugin } from 'vite-plugin-vue2'
3 | import ViteComponents from 'unplugin-vue-components/vite'
4 | import checker from 'vite-plugin-checker'
5 | import { resolve } from 'path'
6 |
7 | const config = defineConfig({
8 | resolve: {
9 | alias: {
10 | '@': `${resolve(__dirname, 'src')}`,
11 | },
12 | },
13 | base: '/vue-template/',
14 | build: {
15 | minify: true,
16 | },
17 | plugins: [
18 | createVuePlugin({}),
19 | (ViteComponents.default || ViteComponents)({ transformer: 'vue2' }),
20 | checker({ vls: true }),
21 | ],
22 | })
23 |
24 | export default config
25 |
--------------------------------------------------------------------------------
/packages/runtime/src/components/List.ce.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
22 |
23 |
24 |
35 |
--------------------------------------------------------------------------------
/packages/runtime/src/main.ts:
--------------------------------------------------------------------------------
1 | import { defineCustomElement } from 'vue'
2 | import App from './App.ce.vue'
3 |
4 | const ShadowElement = defineCustomElement(App)
5 | const overlayId = 'vite-plugin-checker-error-overlay'
6 |
7 | if (customElements && !customElements.get(overlayId)) {
8 | customElements.define(overlayId, ShadowElement)
9 | }
10 |
11 | export function inject({
12 | base,
13 | overlayConfig,
14 | }: {
15 | base: string
16 | overlayConfig: Record
17 | }) {
18 | if (document.querySelector('vite-plugin-checker-error-overlay')) return
19 |
20 | const overlayEle = new ShadowElement({
21 | base,
22 | overlayConfig,
23 | })
24 | document.body.appendChild(overlayEle)
25 | }
26 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Home |
5 | About
6 |
7 |
8 |
9 |
10 |
11 |
33 |
--------------------------------------------------------------------------------
/packages/runtime/src/components/Checker.ce.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
22 |
23 |
24 |
34 |
--------------------------------------------------------------------------------
/playground/vls-vue2/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "sourceMap": true,
14 | "baseUrl": ".",
15 | "types": ["vite/client"],
16 | "paths": {
17 | "@/*": ["src/*"]
18 | },
19 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
20 | },
21 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
22 | "exclude": ["node_modules"]
23 | }
24 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-false/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import { getHmrOverlayText, isServe, sleepForServerReady } from '../../testUtils'
4 |
5 | describe('config-initialIsOpen-false', () => {
6 | describe.runIf(isServe)('serve', () => {
7 | it('should not find overlay', async () => {
8 | if (isServe) {
9 | await sleepForServerReady()
10 | try {
11 | await getHmrOverlayText()
12 | } catch (e) {
13 | expect((e as any).toString()).toContain(
14 | 'Invariant failed: shadow dom is expected to be found, but got null'
15 | )
16 | }
17 | }
18 | })
19 | })
20 | })
21 |
--------------------------------------------------------------------------------
/playground/backend-integration/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/backend-integration",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "node server.js",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^19.1.0",
13 | "react-dom": "^19.1.0"
14 | },
15 | "devDependencies": {
16 | "@types/express": "^5.0.5",
17 | "@types/react": "^19.1.8",
18 | "@types/react-dom": "^19.1.6",
19 | "@vitejs/plugin-react": "^4.7.0",
20 | "express": "^5.2.0",
21 | "http-proxy-middleware": "^3.0.5",
22 | "typescript": "^5.8.3",
23 | "vite": "^7.1.11",
24 | "vite-plugin-checker": "workspace:*"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/packages/runtime/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "preserve",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/scripts/vitestGlobalSetup.ts:
--------------------------------------------------------------------------------
1 | import { rmSync } from 'node:fs'
2 | import fs from 'node:fs/promises'
3 | import path from 'node:path'
4 |
5 | const tempRuntimePath = path.resolve(
6 | __dirname,
7 | '../packages/vite-plugin-checker/src/@runtime',
8 | )
9 |
10 | export async function setup(): Promise {
11 | await fs.rm(tempRuntimePath, { force: true, recursive: true })
12 | await fs.mkdir(tempRuntimePath, { recursive: true })
13 | await fs.cp(
14 | path.resolve(__dirname, '../packages/vite-plugin-checker/dist/@runtime'),
15 | tempRuntimePath,
16 | {
17 | recursive: true,
18 | dereference: false,
19 | },
20 | )
21 | }
22 |
23 | export async function teardown(): Promise {
24 | rmSync(tempRuntimePath, { force: true, recursive: true })
25 | }
26 |
--------------------------------------------------------------------------------
/packages/runtime/vite.config.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import { fileURLToPath } from 'node:url'
3 |
4 | import vue from '@vitejs/plugin-vue'
5 | import { defineConfig } from 'vite'
6 |
7 | const __filename = fileURLToPath(import.meta.url)
8 | const __dirname = path.dirname(__filename)
9 |
10 | export default defineConfig({
11 | plugins: [vue()],
12 | define: {
13 | 'import.meta.hot': 'import.meta.hot',
14 | },
15 | build: {
16 | minify: false, // for easy to debug and the size is not that important
17 | emptyOutDir: true,
18 | outDir: path.resolve(__dirname, '../vite-plugin-checker/dist/@runtime'),
19 | lib: {
20 | entry: path.resolve(__dirname, 'src/main.ts'),
21 | formats: ['es'],
22 | fileName: () => 'main.js',
23 | },
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/playground/backend-integration/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | }
13 | .logo:hover {
14 | filter: drop-shadow(0 0 2em #646cffaa);
15 | }
16 | .logo.react:hover {
17 | filter: drop-shadow(0 0 2em #61dafbaa);
18 | }
19 |
20 | @keyframes logo-spin {
21 | from {
22 | transform: rotate(0deg);
23 | }
24 | to {
25 | transform: rotate(360deg);
26 | }
27 | }
28 |
29 | @media (prefers-reduced-motion: no-preference) {
30 | a:nth-of-type(2) .logo {
31 | animation: logo-spin infinite 20s linear;
32 | }
33 | }
34 |
35 | .card {
36 | padding: 2em;
37 | }
38 |
39 | .read-the-docs {
40 | color: #888;
41 | }
42 |
--------------------------------------------------------------------------------
/playground/vls-vue2/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter, { RouteConfig } from 'vue-router'
3 | import Home from '@/views/Home.vue'
4 |
5 | Vue.use(VueRouter)
6 |
7 | const routes: Array = [
8 | {
9 | path: '/',
10 | name: 'Home',
11 | component: Home,
12 | },
13 | {
14 | path: '/about',
15 | name: 'About',
16 | // route level code-splitting
17 | // this generates a separate chunk (about.[hash].js) for this route
18 | // which is lazy-loaded when the route is visited.
19 | component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
20 | },
21 | ]
22 |
23 | const router = new VueRouter({
24 | mode: 'history',
25 | base: import.meta.env.BASE_URL,
26 | routes,
27 | })
28 |
29 | export default router
30 |
--------------------------------------------------------------------------------
/vitest.config.e2e.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | const timeout = process.env.CI ? 80000 : 40000
4 |
5 | export default defineConfig({
6 | test: {
7 | cache: false,
8 | pool: 'forks',
9 | poolOptions: {
10 | forks: {
11 | // singleFork: true,
12 | },
13 | },
14 | include: ['./playground/**/*.spec.[tj]s'],
15 | setupFiles: ['./playground/vitestSetup.ts'],
16 | globalSetup: ['./playground/vitestGlobalSetup.ts'],
17 | testTimeout: timeout,
18 | hookTimeout: timeout,
19 | globals: true,
20 | reporters: 'dot',
21 | onConsoleLog(log) {
22 | if (log.match(/experimental|jit engine|emitted file|tailwind/i))
23 | return false
24 | },
25 | },
26 | esbuild: {
27 | target: 'node14',
28 | },
29 | })
30 |
--------------------------------------------------------------------------------
/docs/checkers/overview.md:
--------------------------------------------------------------------------------
1 | # Checkers overview
2 |
3 | vite-plugin-checkers provide built-in checkers. For now, it supports [TypeScript](/checkers/typescript), [ESLint](/checkers/eslint), [Biome](/checkers/biome), [vue-tsc](/checkers/vue-tsc), [VLS](/checkers/vls), [Stylelint](/checkers/stylelint), [oxlint](/checkers/oxlint).
4 |
5 | ## How to add a checker
6 |
7 | - Set the checker property to `true` to use a checker with its default value (except ESLint and Stylelint).
8 | - Leave the field blank or `false` will not use the checker.
9 | - Make sure to install the peer dependencies that checker relies on (documented on each checker's page if needed).
10 | - Checker can be enabled with an advanced object config.
11 | - Use [config](/configuration/config) to control the common behaviors settings of checkers.
12 |
--------------------------------------------------------------------------------
/playground/serializers.ts:
--------------------------------------------------------------------------------
1 | import type { SnapshotSerializer } from 'vitest'
2 |
3 | function normalizePaths(val: string) {
4 | return val
5 | .replace(/\\/gim, '/') // replace slashes
6 | .replace(/\/\//gim, '/') // replace slashes
7 | .replace(/[a-zA-Z]:\//gim, '/') // Remove win32 drive letters, C:\ -> \
8 | }
9 |
10 | function createResult(val: string) {
11 | const cwd = normalizePaths(process.cwd())
12 |
13 | return normalizePaths(val)
14 | .replaceAll(cwd, '')
15 | .replace(/\/r\/n/gim, '/n')
16 | }
17 |
18 | export const normalizeLogSerializer: SnapshotSerializer = {
19 | print(val: string, print) {
20 | return print(createResult(val))
21 | },
22 | test(val) {
23 | return typeof val === 'string' && val && createResult(val) !== val
24 | },
25 | }
26 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
40 | button {
41 | font-size: calc(10px + 2vmin);
42 | }
43 |
--------------------------------------------------------------------------------
/playground/typescript-react/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
40 | button {
41 | font-size: calc(10px + 2vmin);
42 | }
43 |
--------------------------------------------------------------------------------
/playground/config-no-runtime-in-build/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 | import { globSync } from 'tinyglobby'
3 | import path from 'path'
4 | import { describe, expect, it } from 'vitest'
5 |
6 | import { isBuild, sleepForServerReady, testDir } from '../../testUtils'
7 |
8 | describe('config-no-runtime-code-in-build', () => {
9 | describe.runIf(isBuild)('build', () => {
10 | it('should not contain plugin code in build artifacts', async () => {
11 | await sleepForServerReady()
12 | const files = globSync('**', { cwd: path.resolve(testDir, 'dist'), absolute: true, onlyFiles: true })
13 | expect(files.length).toBeGreaterThan(1)
14 | for await (const file of files) {
15 | const content = await fs.promises.readFile(file, 'utf-8')
16 | expect(content).not.toContain('vite-plugin-checker')
17 | }
18 | })
19 | })
20 | })
21 |
--------------------------------------------------------------------------------
/playground/config-default/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | sleepForServerReady,
11 | stripedLog,
12 | } from '../../testUtils'
13 |
14 | describe('config-default', () => {
15 | describe.runIf(isServe)('serve', () => {
16 | it('get initial error', async () => {
17 | await sleepForServerReady()
18 |
19 | expect(stringify(diagnostics)).toMatchSnapshot()
20 | expect(stripedLog).toMatchSnapshot()
21 | })
22 | })
23 |
24 | describe.runIf(isBuild)('build', () => {
25 | it('should fail', async () => {
26 | const expectedMsg = 'Unexpected var, use let or const instead no-var'
27 | expectStderrContains(log, expectedMsg)
28 | })
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/FileDiagnosticManager.ts:
--------------------------------------------------------------------------------
1 | import type { NormalizedDiagnostic } from './logger.js'
2 |
3 | class FileDiagnosticManager {
4 | public diagnostics: NormalizedDiagnostic[] = []
5 |
6 | /**
7 | * Initialize and reset the diagnostics array
8 | */
9 | public initWith(diagnostics: NormalizedDiagnostic[]) {
10 | this.diagnostics = [...diagnostics]
11 | }
12 |
13 | public getDiagnostics(fileName?: string) {
14 | if (fileName) {
15 | return this.diagnostics.filter((f) => f.id === fileName)
16 | }
17 |
18 | return this.diagnostics
19 | }
20 |
21 | public updateByFileId(fileId: string, next: NormalizedDiagnostic[] | null) {
22 | this.diagnostics = this.diagnostics.filter((d) => d.id !== fileId)
23 |
24 | if (next?.length) {
25 | this.diagnostics.push(...next)
26 | }
27 | }
28 | }
29 |
30 | export { FileDiagnosticManager }
31 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "vetur.experimental.templateInterpolationService": true,
3 | "typescript.tsdk": "node_modules/typescript/lib",
4 | "vitest.disableWorkspaceWarning": true,
5 | "cSpell.words": ["Stylelint"],
6 | "editor.codeActionsOnSave": {
7 | "source.organizeImports.biome": "always"
8 | },
9 | "[javascript]": {
10 | "editor.defaultFormatter": "biomejs.biome"
11 | },
12 | "[javascriptreact]": {
13 | "editor.defaultFormatter": "biomejs.biome"
14 | },
15 | "[json5]": {
16 | "editor.defaultFormatter": "biomejs.biome"
17 | },
18 | "[json]": {
19 | "editor.defaultFormatter": "biomejs.biome"
20 | },
21 | "[jsonc]": {
22 | "editor.defaultFormatter": "biomejs.biome"
23 | },
24 | "[typescript]": {
25 | "editor.defaultFormatter": "biomejs.biome"
26 | },
27 | "[typescriptreact]": {
28 | "editor.defaultFormatter": "biomejs.biome"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/__tests__/codeFrame.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import { lineColLocToBabelLoc, tsLikeLocToBabelLoc } from '../src/codeFrame'
4 |
5 | describe('code frame', () => {
6 | it('should add 1 offset to TS location', () => {
7 | const babelLoc = tsLikeLocToBabelLoc({
8 | start: { line: 1, character: 2 },
9 | end: { line: 3, character: 4 },
10 | })
11 |
12 | expect(babelLoc).toEqual({
13 | start: { line: 2, column: 3 },
14 | end: { line: 4, column: 5 },
15 | })
16 | })
17 |
18 | it('transform location without offset', () => {
19 | const babelLoc = lineColLocToBabelLoc({
20 | line: 1,
21 | column: 2,
22 | endLine: 3,
23 | endColumn: 4,
24 | })
25 |
26 | expect(babelLoc).toEqual({
27 | start: { line: 1, column: 2 },
28 | end: { line: 3, column: 4 },
29 | })
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`config-initialIsOpen-error > serve > -- should find overlay with error -- 1`] = `"Unexpected var, use let or const instead. (no-var)"`;
4 |
5 | exports[`config-initialIsOpen-error > serve > -- should find overlay with error -- 2`] = `"/playground-temp/config-initialIsOpen-error/src/main.ts:3:1"`;
6 |
7 | exports[`config-initialIsOpen-error > serve > -- should find overlay with error -- 3`] = `
8 | " 1 | import { text } from './text'
9 | 2 |
10 | > 3 | var hello = 'Hello'
11 | | ^^^^^^^^^^^^^^^^^^^
12 | 4 |
13 | 5 | const rootDom = document.querySelector('#root')! as HTMLElement
14 | 6 | rootDom.innerHTML = hello + text"
15 | `;
16 |
17 | exports[`config-initialIsOpen-error > serve > -- should find overlay with error -- 4`] = `""`;
18 |
--------------------------------------------------------------------------------
/playground/backend-integration/__test__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | sleepForServerReady,
11 | stripedLog,
12 | } from '../../testUtils'
13 |
14 | describe('backend-integration', () => {
15 | describe.runIf(isServe)('serve', () => {
16 | it('get initial error', async () => {
17 | await sleepForServerReady()
18 |
19 | expect(stringify(diagnostics)).toMatchSnapshot()
20 | expect(stripedLog).toMatchSnapshot()
21 | })
22 | })
23 |
24 | describe.runIf(isBuild)('build', () => {
25 | it('should fail', async () => {
26 | const expectedMsg = `TS2345: Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'`
27 | expectStderrContains(log, expectedMsg)
28 | })
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/playground/eslint-config-log-level/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | editFile,
7 | isServe,
8 | resetReceivedLog,
9 | sleepForEdit,
10 | sleepForServerReady,
11 | stripedLog,
12 | } from '../../testUtils'
13 |
14 | describe('eslint-config-log-level', () => {
15 | describe.runIf(isServe)('serve', () => {
16 | it('should only emit warning logs', async () => {
17 | await sleepForServerReady()
18 | expect(stringify(diagnostics)).toMatchSnapshot()
19 | expect(stripedLog).toMatchSnapshot()
20 |
21 | console.log('-- edit error file --')
22 | resetReceivedLog()
23 | editFile('src/main.ts', (code) => code.replace(`'Hello'`, `'Hello~'`))
24 | await sleepForEdit()
25 | expect(stringify(diagnostics)).toMatchSnapshot()
26 | expect(stripedLog).toMatchSnapshot()
27 | })
28 | })
29 | })
30 |
--------------------------------------------------------------------------------
/knip.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/knip@5/schema.json",
3 | "rules": {
4 | "duplicates": "off"
5 | },
6 | "workspaces": {
7 | ".": {
8 | "entry": ["scripts/*", "playground/*"],
9 | "ignoreDependencies": ["oxlint"]
10 | },
11 | "docs": {
12 | "entry": [".vitepress/config.ts"]
13 | },
14 | "packages/vite-plugin-checker": {
15 | "entry": [
16 | "src/**/*.ts",
17 | "src/checkers/vueTsc/languagePlugins.cjs",
18 | "__tests__/fixtures/tsDiagnostic.ts"
19 | ],
20 | "ignoreDependencies": ["eslint", "meow", "stylelint", "vls", "vue-tsc"]
21 | },
22 | "playground/backend-integration": {
23 | "entry": ["src/*.{js,ts,tsx}", "__test__/serve.js"]
24 | },
25 | "playground/vls-vue2": {
26 | "entry": ["vetur.config.cjs", "src/**/*"],
27 | "ignoreDependencies": [
28 | "tslib",
29 | "vue-class-component",
30 | "vue-property-decorator"
31 | ]
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/playground/backend-integration/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import reactLogo from './assets/react.svg'
3 | import './App.css'
4 |
5 | function App() {
6 | const [count, setCount] = useState(0)
7 |
8 | return (
9 |
10 |
18 |
Vite + React
19 |
20 |
21 |
22 | Edit src/App.tsx and save to test HMR
23 |
24 |
25 |
Click on the Vite and React logos to learn more
26 |
27 | )
28 | }
29 |
30 | export default App
31 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/oxlint/main.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath } from 'node:url'
2 | import { Checker } from '../../Checker.js'
3 | import parseArgsStringToArgv from '../stylelint/argv.js'
4 | import { createDiagnostic } from './diagnostics.js'
5 |
6 | const __filename = fileURLToPath(import.meta.url)
7 |
8 | export class OxlintChecker extends Checker<'oxlint'> {
9 | public constructor() {
10 | super({
11 | name: 'oxlint',
12 | absFilePath: __filename,
13 | build: {
14 | buildBin: ({ oxlint }) => {
15 | const commandStr =
16 | typeof oxlint === 'boolean'
17 | ? 'oxlint'
18 | : (oxlint?.lintCommand ?? 'oxlint')
19 | const command = parseArgsStringToArgv(commandStr)
20 | return [command[0]!, command.slice(1)]
21 | },
22 | },
23 | createDiagnostic,
24 | })
25 | }
26 | }
27 |
28 | const oxlint = new OxlintChecker()
29 | oxlint.prepare()
30 | oxlint.initWorkerThread()
31 |
32 | export const createServeAndBuild = oxlint.initMainThread()
33 |
--------------------------------------------------------------------------------
/packages/runtime/src/useChecker.ts:
--------------------------------------------------------------------------------
1 | import { ref } from 'vue'
2 | import {
3 | listenToCustomMessage,
4 | listenToReconnectMessage,
5 | prepareListen,
6 | } from './ws'
7 |
8 | const checkerResults = ref([])
9 |
10 | function updateErrorOverlay(payloads: any) {
11 | const payloadArray = Array.isArray(payloads) ? payloads : [payloads]
12 | const nextCheckerResults = [
13 | ...payloadArray,
14 | ...checkerResults.value.filter((existCheckerResult) => {
15 | return !payloadArray
16 | .map((p) => p.checkerId)
17 | .includes(existCheckerResult.checkerId)
18 | }),
19 | ]
20 |
21 | checkerResults.value = nextCheckerResults
22 | }
23 |
24 | function resumeErrorOverlay(data: any) {
25 | const payloadsToResume = data.map((d: any) => d.data)
26 | updateErrorOverlay(payloadsToResume)
27 | }
28 |
29 | export function useChecker() {
30 | const ws = prepareListen()
31 | listenToCustomMessage(updateErrorOverlay)
32 | listenToReconnectMessage(resumeErrorOverlay)
33 | ws.startListening()
34 |
35 | return {
36 | checkerResults,
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/__tests__/logger.spec.ts:
--------------------------------------------------------------------------------
1 | import { stripVTControlCharacters as strip } from 'node:util'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnosticToTerminalLog,
6 | normalizeEslintDiagnostic,
7 | } from '../src/logger'
8 | import {
9 | error1 as eslintError1,
10 | eslintResult1,
11 | warning1 as eslintWarning1,
12 | } from './fixtures/eslintDiagnostic'
13 |
14 | describe('logger', () => {
15 | describe('diagnosticToTerminalLog', () => {
16 | it('get error', () => {
17 | const received = strip(diagnosticToTerminalLog(eslintError1, 'ESLint'))
18 | expect(received).toMatchSnapshot()
19 | })
20 |
21 | it('get warning', () => {
22 | const received = strip(diagnosticToTerminalLog(eslintWarning1, 'ESLint'))
23 | expect(received).toMatchSnapshot()
24 | })
25 | })
26 |
27 | describe('normalizeEslintDiagnostic', () => {
28 | it('get multiple diagnostics', () => {
29 | const received = normalizeEslintDiagnostic(eslintResult1)
30 | expect(received).toMatchSnapshot()
31 | })
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: home
3 |
4 | title: vite-plugin-checker
5 | titleTemplate: Vite plugin that provide checks of TypeScript, ESLint, vue-tsc, and more.
6 |
7 | hero:
8 | name: vite-plugin-checker
9 | text: Add Checks to Your Vite Project
10 | tagline: Vite plugin that provide checks of TypeScript, ESLint, vue-tsc, and more.
11 | image:
12 | src: /logo.png
13 | alt: vite-plugin-checker
14 | actions:
15 | - theme: brand
16 | text: Get Started
17 | link: /introduction/introduction
18 | - theme: alt
19 | text: View on GitHub
20 | link: https://github.com/fi3ework/vite-plugin-checker
21 |
22 | features:
23 | - title: Mainstream checks provided
24 | details: Speeds up TypeScript, vue-tsc, ESLint, etc. checks by running in a worker thread in serve mode
25 | - title: Integration with frameworks
26 | details: Works good with vanilla JS / TS, React, Vue2, Vue3
27 | - title: Variety of ways to prompt
28 | details: Prompt errors in an overlay UI and terminal
29 | - title: In all modes
30 | details: Works both in Vite serve and build mode
31 | ---
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Visit [documentation](https://vite-plugin-checker.netlify.app) for usage
2 |
3 | A Vite plugin that can run TypeScript, VLS, vue-tsc, ESLint, Biome, Stylelint in worker thread.
4 |
5 |
6 |
7 |
8 |
9 | ## Online playground
10 |
11 | | Examples | StackBlitz |
12 | | ------------------ | ---------------------------------------------------------------- |
13 | | Vue3 + vue-tsc | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-e8pddl) |
14 | | React + TypeScript | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-b4zcev) |
15 | | ESLint | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-l1ritu) |
16 | | Vue2 + VLS | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-kpffk5) |
17 | | Multiple | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-mb4ea6) |
18 |
19 | ## License
20 |
21 | MIT License © 2022 [fi3ework](https://github.com/fi3ework)
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 fi3ework
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/playground/vls-vue2/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Martinus Suherman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/playground/vls-vue2/README.md:
--------------------------------------------------------------------------------
1 | # Vue2 + Typescript + Vite Starter Template
2 |
3 | [](https://www.codefactor.io/repository/github/martinussuherman/vue-template) [](https://github.com/martinussuherman/vue-template/actions/workflows/codeql-analysis.yml) [](https://github.com/martinussuherman/vue-template/actions/workflows/gh-pages.yml)
4 | ---
5 |
6 | Starter template example for Vue2 + Typescript + Vite.
7 |
8 | Note: Using pnpm for package manager.
9 |
10 | ## Project setup
11 | ```
12 | pnpm install
13 | ```
14 |
15 | ### Compiles and hot-reloads for development
16 | ```
17 | pnpm run serve
18 | ```
19 |
20 | ### Compiles and minifies for production
21 | ```
22 | pnpm run build
23 | ```
24 |
25 | ### Lints and fixes files
26 | ```
27 | pnpm run lint
28 | ```
29 |
30 | ### Customize configuration
31 | See [Configuration Reference](https://cli.vuejs.org/config/).
32 |
--------------------------------------------------------------------------------
/playground/vls-vue2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@playground/vls-vue2",
3 | "version": "0.0.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "build": "vite build",
8 | "dev": "vite",
9 | "serve": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^2.7.16",
13 | "vue-class-component": "7.2.6",
14 | "vue-property-decorator": "9.1.2",
15 | "vue-router": "3.6.5",
16 | "vuex": "3.6.2"
17 | },
18 | "devDependencies": {
19 | "@types/node": "^18.19.120",
20 | "@typescript-eslint/eslint-plugin": "^4.33.0",
21 | "@typescript-eslint/parser": "^4.33.0",
22 | "@vue/eslint-config-prettier": "6.0.0",
23 | "@vue/eslint-config-typescript": "^7.0.0",
24 | "eslint": "^7.32.0",
25 | "eslint-plugin-prettier": "^3.4.1",
26 | "eslint-plugin-vue": "^7.20.0",
27 | "prettier": "3.6.2",
28 | "sass": "^1.89.2",
29 | "typescript": "~4.9.5",
30 | "unplugin-vue-components": "^28.8.0",
31 | "vite": "^7.1.11",
32 | "vite-plugin-checker": "workspace:*",
33 | "vite-plugin-vue2": "^2.0.3",
34 | "vls": "^0.8.5",
35 | "vti": "^0.1.11",
36 | "vue-template-compiler": "^2.7.16"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/playground/typescript-react/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | editFile,
7 | expectStderrContains,
8 | isBuild,
9 | isServe,
10 | log,
11 | resetReceivedLog,
12 | sleepForEdit,
13 | sleepForServerReady,
14 | stripedLog,
15 | } from '../../testUtils'
16 |
17 | describe('typescript-react', () => {
18 | describe.runIf(isServe)('serve', () => {
19 | it('get initial error and subsequent error', async () => {
20 | await sleepForServerReady()
21 | expect(stringify(diagnostics)).toMatchSnapshot()
22 | expect(stripedLog).toMatchSnapshot()
23 |
24 | console.log('-- edit file --')
25 | resetReceivedLog()
26 | editFile('src/App.tsx', (code) => code.replace('useState(1)', 'useState(2)'))
27 | await sleepForEdit()
28 | expect(stringify(diagnostics)).toMatchSnapshot()
29 | expect(stripedLog).toMatchSnapshot()
30 | })
31 | })
32 |
33 | describe.runIf(isBuild)('build', () => {
34 | it('should fail', async () => {
35 | expectStderrContains(log, 'error TS2345')
36 | })
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/oxlint/options.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import { DiagnosticLevel, type OxlintConfig } from '../../types.js'
3 | import { getOxlintCommand, mapSeverity } from './cli.js'
4 |
5 | export interface ResolvedOptions {
6 | watchTarget: string | string[]
7 | logLevel?: DiagnosticLevel[]
8 | command: string
9 | }
10 |
11 | export function resolveOptions(
12 | root: string,
13 | config: Exclude,
14 | ): ResolvedOptions {
15 | const options = config === true ? { lintCommand: 'oxlint' } : config
16 | return {
17 | watchTarget: resolveWatchTarget(root, options.watchPath),
18 | logLevel: options.dev?.logLevel?.map((l) => mapSeverity(l)) ?? [
19 | DiagnosticLevel.Warning,
20 | DiagnosticLevel.Error,
21 | ],
22 | command: getOxlintCommand(options.lintCommand ?? 'oxlint').join(' '),
23 | }
24 | }
25 |
26 | function resolveWatchTarget(
27 | root: string,
28 | watchPath?: string | string[],
29 | ): string | string[] {
30 | return Array.isArray(watchPath)
31 | ? watchPath.map((p) => path.resolve(root, p))
32 | : typeof watchPath === 'string'
33 | ? path.resolve(root, watchPath)
34 | : root
35 | }
36 |
--------------------------------------------------------------------------------
/playground/eslint-flat/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 | import {
4 | diagnostics,
5 | editFile,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | resetReceivedLog,
11 | sleepForEdit,
12 | sleepForServerReady,
13 | stripedLog,
14 | } from '../../testUtils'
15 |
16 | describe('eslint', () => {
17 | describe.runIf(isServe)('serve', () => {
18 | it('get initial error and subsequent error', async () => {
19 | await sleepForServerReady()
20 | expect(stringify(diagnostics)).toMatchSnapshot()
21 | expect(stripedLog).toMatchSnapshot()
22 |
23 | console.log('-- edit error file --')
24 | resetReceivedLog()
25 | editFile('src/index.js', (code) => code.replace(`Hello`, `Hello~`))
26 | await sleepForEdit()
27 | expect(stringify(diagnostics)).toMatchSnapshot()
28 | expect(stripedLog).toMatchSnapshot()
29 | })
30 | })
31 |
32 | describe.runIf(isBuild)('build', () => {
33 | const expectedMsg = 'Missing semicolon'
34 |
35 | it('should fail', async () => {
36 | expectStderrContains(log, expectedMsg)
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error-warnings/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import {
4 | editFile,
5 | getHmrOverlay,
6 | getHmrOverlayText,
7 | isServe,
8 | pollingUntil,
9 | sleepForEdit,
10 | sleepForServerReady,
11 | } from '../../testUtils'
12 |
13 | describe('config-initialIsOpen-error-warnings', () => {
14 | describe.runIf(isServe)('serve', () => {
15 | it('should not show overlay when only warning exists', async () => {
16 | await sleepForServerReady()
17 | try {
18 | await getHmrOverlayText()
19 | } catch (e) {
20 | expect((e as any).toString()).toContain(
21 | 'Invariant failed: shadow dom is expected to be found, but got null'
22 | )
23 | }
24 |
25 | console.log('-- overlay appears after introduce an error --')
26 | editFile('src/main.ts', (code) => code.replace('const rootDom', 'var rootDom'))
27 | await sleepForEdit()
28 | await getHmrOverlayText()
29 | await pollingUntil(getHmrOverlay, (dom) => !!dom)
30 | const [, , frame] = await getHmrOverlayText()
31 | expect(frame).toMatchSnapshot()
32 | })
33 | })
34 | })
35 |
--------------------------------------------------------------------------------
/playground/typescript-react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import logo from './logo.svg'
3 | import './App.css'
4 |
5 | function App() {
6 | const [count, setCount] = useState(1)
7 | return (
8 |
9 |
10 |
11 | Hello Vite + React!
12 |
13 |
14 |
15 |
16 | Edit App.tsx and save to test HMR updates.
17 |
18 |
19 |
25 | Learn React
26 |
27 | {' | '}
28 |
34 | Vite Docs
35 |
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | export default App
43 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | editFile,
7 | expectStderrContains,
8 | isBuild,
9 | isServe,
10 | log,
11 | resetReceivedLog,
12 | sleepForEdit,
13 | sleepForServerReady,
14 | stripedLog,
15 | } from '../../testUtils'
16 |
17 | describe('vue-tsc-vue3', () => {
18 | describe.runIf(isServe)('serve', () => {
19 | it('get initial error and subsequent error', async () => {
20 | await sleepForServerReady(2)
21 | expect(stringify(diagnostics)).toMatchSnapshot()
22 | expect(stripedLog).toMatchSnapshot()
23 |
24 | console.log('-- edit file --')
25 | resetReceivedLog()
26 | editFile('src/App.vue', (code) =>
27 | code.replace('', '')
28 | )
29 | await sleepForEdit(2)
30 | expect(stringify(diagnostics)).toMatchSnapshot()
31 | expect(stripedLog).toMatchSnapshot()
32 | })
33 | })
34 |
35 | describe.runIf(isBuild)('build', () => {
36 | it('should fail', async () => {
37 | const expectedMsg = `error TS2345`
38 | expectStderrContains(log, expectedMsg)
39 | })
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/playground/stylelint-default/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 | import {
4 | diagnostics,
5 | editFile,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | resetReceivedLog,
11 | sleepForEdit,
12 | sleepForServerReady,
13 | stripedLog,
14 | } from '../../testUtils'
15 |
16 | describe('stylelint', () => {
17 | describe.runIf(isServe)('serve', () => {
18 | it('get initial error and subsequent error', async () => {
19 | await sleepForServerReady()
20 | expect(stringify(diagnostics)).toMatchSnapshot()
21 | expect(stripedLog).toMatchSnapshot()
22 |
23 | console.log('-- edit error file --')
24 | resetReceivedLog()
25 | editFile('src/style.css', (code) => code.replace(`color: rgb(0, 0, 0);`, `color: #fff;`))
26 | await sleepForEdit()
27 | expect(stringify(diagnostics)).toMatchSnapshot()
28 | expect(stripedLog).toMatchSnapshot()
29 | })
30 | })
31 |
32 | describe.runIf(isBuild)('build', () => {
33 | const expectedMsg = ['Unexpected empty block', 'Expected modern color-function notation']
34 |
35 | it('should fail', async () => {
36 | expectStderrContains(log, expectedMsg)
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import logo from './logo.svg'
3 | import { value } from './value'
4 | import './App.css'
5 |
6 | function App() {
7 | const [count, setCount] = useState(0)
8 | return (
9 |
10 |
11 |
12 | Hello Vite + React! ({value})
13 |
14 |
15 |
16 |
17 | Edit App.tsx and save to test HMR updates.
18 |
19 |
20 |
26 | Learn React
27 |
28 | {' | '}
29 |
35 | Vite Docs
36 |
37 |
38 |
39 |
40 | )
41 | }
42 |
43 | export default App
44 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | editFile,
7 | expectStderrContains,
8 | isBuild,
9 | isServe,
10 | log,
11 | resetReceivedLog,
12 | sleepForEdit,
13 | sleepForServerReady,
14 | stripedLog,
15 | } from '../../testUtils'
16 |
17 | describe('vue-tsc-build-mode', () => {
18 | describe.runIf(isServe)('serve', () => {
19 | it('get initial error and subsequent error', async () => {
20 | await sleepForServerReady(2)
21 | expect(stringify(diagnostics)).toMatchSnapshot()
22 | expect(stripedLog).toMatchSnapshot()
23 |
24 | console.log('-- edit file --')
25 | resetReceivedLog()
26 | editFile('packages/utils/src/helpers.ts', (code) =>
27 | code.replace('processData(input: number)', 'processData(input: boolean)')
28 | )
29 | await sleepForEdit(2)
30 | expect(stringify(diagnostics)).toMatchSnapshot()
31 | expect(stripedLog).toMatchSnapshot()
32 | })
33 | })
34 |
35 | describe.runIf(isBuild)('build', () => {
36 | it('should fail', async () => {
37 | const expectedMsg = `error TS2345`
38 | expectStderrContains(log, expectedMsg)
39 | })
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/client/index.ts:
--------------------------------------------------------------------------------
1 | import fs from 'node:fs'
2 | import { createRequire } from 'node:module'
3 | import type { SharedConfig } from '../types'
4 |
5 | const _require = createRequire(import.meta.url)
6 |
7 | export const RUNTIME_CLIENT_RUNTIME_PATH = '/@vite-plugin-checker-runtime'
8 | export const RUNTIME_CLIENT_ENTRY_PATH = '/@vite-plugin-checker-runtime-entry'
9 |
10 | export const wrapVirtualPrefix = (id: `/${string}`): `virtual:${string}` =>
11 | `virtual:${id.slice('/'.length)}`
12 | export const composePreambleCode = ({
13 | baseWithOrigin = '/',
14 | overlayConfig,
15 | }: {
16 | baseWithOrigin: string
17 | overlayConfig: SharedConfig['overlay']
18 | }) => `
19 | import { inject } from "${baseWithOrigin}${RUNTIME_CLIENT_RUNTIME_PATH.slice(1)}";
20 | inject({
21 | overlayConfig: ${JSON.stringify(overlayConfig)},
22 | base: "${baseWithOrigin}",
23 | });
24 | `
25 |
26 | // #region
27 | // NOTE: sync modification with packages/runtime/src/ws.js
28 | export const WS_CHECKER_ERROR_EVENT = 'vite-plugin-checker:error'
29 | export const WS_CHECKER_RECONNECT_EVENT = 'vite-plugin-checker:reconnect'
30 | // #endregion
31 |
32 | export const runtimeSourceFilePath = _require.resolve('../@runtime/main.js')
33 | export const runtimeCode = `${fs.readFileSync(runtimeSourceFilePath, 'utf-8')};`
34 |
--------------------------------------------------------------------------------
/playground/backend-integration/__test__/serve.js:
--------------------------------------------------------------------------------
1 | // this is automatically detected by playground/vitestSetup.ts and will replace
2 | // the default e2e test serve behavior
3 |
4 | import path from 'node:path'
5 | // import kill from 'kill-port'
6 | // import { hmrPorts, ports } from '~utils'
7 | import { fileURLToPath } from 'url'
8 |
9 | const isTest = process.env.VITEST
10 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
11 |
12 | export async function serve() {
13 | // await kill(port)
14 | const rootDir = path.resolve(__dirname, '../')
15 |
16 | const { createServer, port } = await import(path.resolve(rootDir, 'server.js'))
17 | const { app, viteDevServer } = await createServer(rootDir, port)
18 |
19 | return new Promise((resolve, reject) => {
20 | try {
21 | const server = app.listen(port, () => {
22 | resolve({
23 | // for test teardown
24 | async close() {
25 | await new Promise((resolve) => {
26 | server.close(resolve)
27 | })
28 | if (viteDevServer) {
29 | await viteDevServer.close()
30 | }
31 | },
32 | viteDevServer,
33 | port,
34 | })
35 | })
36 | } catch (e) {
37 | reject(e)
38 | }
39 | })
40 | }
41 |
42 | // serve()
43 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`config-overlay-changes > serve > get initial error from overlay and overlay error content changes on modifying 1`] = `"Unexpected var, use let or const instead. (no-var)"`;
4 |
5 | exports[`config-overlay-changes > serve > get initial error from overlay and overlay error content changes on modifying 2`] = `"/playground-temp/config-overlay-changes/src/main.ts:3:1"`;
6 |
7 | exports[`config-overlay-changes > serve > get initial error from overlay and overlay error content changes on modifying 3`] = `
8 | " 1 | import { text } from './text'
9 | 2 |
10 | > 3 | var hello = 'Hello'
11 | | ^^^^^^^^^^^^^^^^^^^
12 | 4 |
13 | 5 | const rootDom = document.querySelector('#root')! as HTMLElement
14 | 6 | rootDom.innerHTML = hello + text"
15 | `;
16 |
17 | exports[`config-overlay-changes > serve > get initial error from overlay and overlay error content changes on modifying 4`] = `
18 | " 1 | import { text } from './text'
19 | 2 |
20 | > 3 | var hello = 'Hello1'
21 | | ^^^^^^^^^^^^^^^^^^^^
22 | 4 |
23 | 5 | const rootDom = document.querySelector('#root')! as HTMLElement
24 | 6 | rootDom.innerHTML = hello + text"
25 | `;
26 |
--------------------------------------------------------------------------------
/playground/biome-default/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 | import {
4 | diagnostics,
5 | editFile,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | resetDiagnostics,
10 | resetReceivedLog,
11 | sleepForEdit,
12 | sleepForServerReady,
13 | stripedLog,
14 | } from '../../testUtils'
15 |
16 | describe('biome', () => {
17 | describe.runIf(isServe)('serve', () => {
18 | it('get initial error and subsequent error', async () => {
19 | await sleepForServerReady()
20 | expect(stringify(diagnostics)).toMatchSnapshot()
21 | expect(stripedLog).toMatchSnapshot()
22 |
23 | console.log('-- edit error file --')
24 | resetReceivedLog()
25 | resetDiagnostics()
26 | editFile('src/index.js', (code) =>
27 | code.replace(`var b = 'world'`, `const b = 'world'`),
28 | )
29 | await sleepForEdit()
30 | expect(stringify(diagnostics)).toMatchSnapshot()
31 | expect(stripedLog).toMatchSnapshot()
32 | })
33 | })
34 |
35 | describe.runIf(isBuild)('build', () => {
36 | it('should fail', async () => {
37 | const expectedMsg = ['Avoid default exports', 'Found 1 error']
38 | expectStderrContains(stripedLog, expectedMsg)
39 | })
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/playground/backend-integration/__test__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`backend-integration > serve > get initial error 1`] = `"[{"checkerId":"TypeScript","frame":" 4 |/n 5 | function App() {/n > 6 | const [count, setCount] = useState(0)/n | ^/n 7 |/n 8 | return (/n 9 | ","id":"
/playground-temp/backend-integration/src/App.tsx","level":1,"loc":{"column":46,"file":"/playground-temp/backend-integration/src/App.tsx","line":6},"message":"Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'.","stack":""}]"`;
4 |
5 | exports[`backend-integration > serve > get initial error 2`] = `
6 | [
7 | "
8 | ERROR(TypeScript) Argument of type 'number' is not assignable to parameter of type 'string | (() => string)'.
9 | FILE /playground-temp/backend-integration/src/App.tsx:6:46
10 |
11 | 4 |
12 | 5 | function App() {
13 | > 6 | const [count, setCount] = useState(0)
14 | | ^
15 | 7 |
16 | 8 | return (
17 | 9 |
18 |
19 | [TypeScript] Found 1 error. Watching for file changes.",
20 | ]
21 | `;
22 |
--------------------------------------------------------------------------------
/playground/config-terminal-false/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`config-terminal-false > serve > should not log into terminal 1`] = `"[{"checkerId":"ESLint","frame":" 1 | import { text } from './text'/n 2 |/n > 3 | var hello = 'Hello'/n | ^^^^^^^^^^^^^^^^^^^/n 4 |/n 5 | const rootDom = document.querySelector('#root')! as HTMLElement/n 6 | rootDom.innerHTML = hello + text","id":"
/playground-temp/config-terminal-false/src/main.ts","level":1,"loc":{"column":1,"file":"/playground-temp/config-terminal-false/src/main.ts","line":3},"message":"Unexpected var, use let or const instead. (no-var)","stack":""},{"checkerId":"ESLint","frame":" 3 | var hello = 'Hello'/n 4 |/n > 5 | const rootDom = document.querySelector('#root')! as HTMLElement/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 6 | rootDom.innerHTML = hello + text/n 7 |/n 8 | export {}","id":"/playground-temp/config-terminal-false/src/main.ts","level":0,"loc":{"column":17,"file":"/playground-temp/config-terminal-false/src/main.ts","line":5},"message":"Forbidden non-null assertion. (@typescript-eslint/no-non-null-assertion)","stack":""}]"`;
4 |
5 | exports[`config-terminal-false > serve > should not log into terminal 2`] = `[]`;
6 |
--------------------------------------------------------------------------------
/playground/vls-vue2/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import {
5 | diagnostics,
6 | editFile,
7 | expectStderrContains,
8 | isBuild,
9 | isServe,
10 | log,
11 | resetReceivedLog,
12 | sleepForEdit,
13 | sleepForServerReady,
14 | stripedLog,
15 | } from '../../testUtils'
16 |
17 | describe('vue2-vls', () => {
18 | describe.runIf(isServe)('serve', () => {
19 | it('get initial error and subsequent error', async () => {
20 | await sleepForServerReady()
21 | expect(stringify(diagnostics)).toMatchSnapshot()
22 | expect(stripedLog).toMatchSnapshot()
23 |
24 | console.log('-- edit file --')
25 | resetReceivedLog()
26 | editFile('src/components/HelloWorld.vue', (code) => code.replace('msg1', 'msg2'))
27 | await sleepForEdit()
28 |
29 | expect(stringify(diagnostics)).toMatchSnapshot()
30 | expect(stripedLog).toMatchSnapshot()
31 | })
32 | })
33 |
34 | // As per https://github.com/vuejs/vetur/issues/3686
35 | // We may remove VLS in the future to push the community to Vue 3 & Vue Language Tools.
36 | // describe.runIf(isBuild)('build', () => {
37 | // it('should fail', async () => {
38 | // expectStderrContains(log, `Property 'msg1' does not exist on type`)
39 | // })
40 | // })
41 | })
42 |
--------------------------------------------------------------------------------
/playground/config-initialIsOpen-error/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import {
4 | editFile,
5 | getHmrOverlay,
6 | getHmrOverlayText,
7 | isServe,
8 | pollingUntil,
9 | sleep,
10 | sleepForEdit,
11 | sleepForServerReady,
12 | } from '../../testUtils'
13 |
14 | describe('config-initialIsOpen-error', () => {
15 | describe.runIf(isServe)('serve', () => {
16 | it('-- should find overlay with error --', async () => {
17 | await sleepForServerReady()
18 | const [message1, file1, frame1] = await getHmrOverlayText()
19 | expect(message1).toMatchSnapshot()
20 | expect(file1).toMatchSnapshot()
21 | expect(frame1).toMatchSnapshot()
22 |
23 | console.log('-- overlay remains after fix error --')
24 | editFile('src/main.ts', (code) => code.replace('var hello', `const hello`))
25 | await sleepForEdit()
26 | await pollingUntil(getHmrOverlay, (dom) => !!dom)
27 | const [, , frame2] = await getHmrOverlayText()
28 | expect(frame2).toMatchSnapshot()
29 |
30 | console.log('-- overlay dismiss after fix warning --')
31 | editFile('src/main.ts', (code) => code.replace('! as', ` as`))
32 | await sleep(6000)
33 | await expect(getHmrOverlayText()).rejects.toThrow(
34 | 'Invariant failed: .message-body is expected in shadow root'
35 | )
36 | })
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/glob.ts:
--------------------------------------------------------------------------------
1 | import { type Stats, statSync } from 'node:fs'
2 | import { join, relative, resolve } from 'node:path'
3 | import picomatch from 'picomatch'
4 |
5 | export function createIgnore(_root: string, pattern: string | string[] = []) {
6 | const paths = Array.isArray(pattern) ? pattern : [pattern]
7 | const root = _root.replace(/\\/g, '/')
8 |
9 | const globs = paths
10 | .flatMap((f) => {
11 | const resolvedPath = resolve(root, f)
12 | const relativePath = relative(root, resolvedPath).replace(/\\/g, '/')
13 | try {
14 | const isDirectory =
15 | !relativePath.includes('*') && statSync(resolvedPath).isDirectory()
16 | if (isDirectory) {
17 | return [relativePath, join(relativePath, '**/*').replace(/\\/g, '/')]
18 | }
19 | } catch {}
20 | return [relativePath]
21 | })
22 | .filter(Boolean)
23 |
24 | const matcher = picomatch(globs, { cwd: root })
25 |
26 | return (path: string, _stats?: Stats) => {
27 | if (path.includes('node_modules')) {
28 | return true
29 | }
30 | const relativePath = relative(root, path).replace(/\\/g, '/')
31 | try {
32 | return (
33 | !!relativePath &&
34 | !matcher(relativePath) &&
35 | !(_stats ?? statSync(path)).isDirectory()
36 | )
37 | } catch {
38 | // do not ignore files that have been deleted as the watcher is iterating on them
39 | return false
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/playground/backend-integration/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/playground/config-overlay-changes/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import {
4 | editFile,
5 | getHmrOverlay,
6 | getHmrOverlayText,
7 | isServe,
8 | pollingUntil,
9 | sleep,
10 | sleepForEdit,
11 | sleepForServerReady,
12 | } from '../../testUtils'
13 |
14 | describe('config-overlay-changes', () => {
15 | describe.runIf(isServe)('serve', () => {
16 | it('get initial error from overlay and overlay error content changes on modifying', async () => {
17 | await sleepForServerReady()
18 | const [message1, file1, frame1] = await getHmrOverlayText()
19 | expect(message1).toMatchSnapshot()
20 | expect(file1).toMatchSnapshot()
21 | expect(frame1).toMatchSnapshot()
22 |
23 | console.log('-- overlay update after edit --')
24 | editFile('src/main.ts', (code) => code.replace('Hello', 'Hello1'))
25 | await sleepForEdit()
26 | await pollingUntil(getHmrOverlay, (dom) => !!dom)
27 | const [, , frame2] = await getHmrOverlayText()
28 | expect(frame2).toMatchSnapshot()
29 |
30 | console.log('-- overlay dismiss after fix error --')
31 | editFile('src/main.ts', (code) => code.replace('var hello', `const hello`))
32 | editFile('src/main.ts', (code) => code.replace('! as', ` as`))
33 | await sleep(6000)
34 | await expect(getHmrOverlayText()).rejects.toThrow(
35 | 'Invariant failed: .message-body is expected in shadow root'
36 | )
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/playground/backend-integration/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #242424;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | a {
19 | font-weight: 500;
20 | color: #646cff;
21 | text-decoration: inherit;
22 | }
23 | a:hover {
24 | color: #535bf2;
25 | }
26 |
27 | body {
28 | margin: 0;
29 | place-items: center;
30 | min-width: 320px;
31 | min-height: 100vh;
32 | }
33 |
34 | h1 {
35 | font-size: 3.2em;
36 | line-height: 1.1;
37 | }
38 |
39 | button {
40 | border-radius: 8px;
41 | border: 1px solid transparent;
42 | padding: 0.6em 1.2em;
43 | font-size: 1em;
44 | font-weight: 500;
45 | font-family: inherit;
46 | background-color: #1a1a1a;
47 | cursor: pointer;
48 | transition: border-color 0.25s;
49 | }
50 | button:hover {
51 | border-color: #646cff;
52 | }
53 | button:focus,
54 | button:focus-visible {
55 | outline: 4px auto -webkit-focus-ring-color;
56 | }
57 |
58 | @media (prefers-color-scheme: light) {
59 | :root {
60 | color: #213547;
61 | background-color: #ffffff;
62 | }
63 | a:hover {
64 | color: #747bff;
65 | }
66 | button {
67 | background-color: #f9f9f9;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/playground/config-overlay-position-style/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import { sleepForServerReady, getHmrOverlay, isServe } from '../../testUtils'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | describe('config-overlay-position-style', () => {
5 | describe.runIf(isServe)('serve', () => {
6 | it('find badge in right top corner and customized by badgeStyle', async () => {
7 | await sleepForServerReady()
8 | const shadowRoot = await getHmrOverlay()
9 | const badge = await shadowRoot!.$('.badge-base')
10 |
11 | const { bgColor, top, right } = await badge!.evaluate((el) => {
12 | const bgColor = window.getComputedStyle(el).getPropertyValue('background-color')
13 | const top = window.getComputedStyle(el).getPropertyValue('top')
14 | const right = window.getComputedStyle(el).getPropertyValue('right')
15 | return { bgColor, top, right }
16 | })
17 |
18 | expect(bgColor).toBe('rgb(231, 153, 176)')
19 | expect(top).toBe('0px')
20 | expect(right).toBe('0px')
21 | })
22 |
23 | it('panel be customized by panelStyle', async () => {
24 | await sleepForServerReady()
25 | const shadowRoot = await getHmrOverlay()
26 | const panel = await shadowRoot!.$('.window')
27 |
28 | const { bgColor } = await panel!.evaluate((el) => {
29 | const bgColor = window.getComputedStyle(el).getPropertyValue('background-color')
30 | return { bgColor }
31 | })
32 |
33 | expect(bgColor).toBe('rgb(164, 193, 255)')
34 | })
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/playground/eslint-default/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 | import {
4 | diagnostics,
5 | editFile,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | resetReceivedLog,
11 | sleepForEdit,
12 | sleepForServerReady,
13 | stripedLog,
14 | } from '../../testUtils'
15 |
16 | describe('eslint-default', () => {
17 | describe.runIf(isServe)('serve', () => {
18 | it('get initial error and subsequent error', async () => {
19 | await sleepForServerReady()
20 | expect(stringify(diagnostics)).toMatchSnapshot()
21 | expect(stripedLog).toMatchSnapshot()
22 |
23 | console.log('-- edit error file --')
24 | resetReceivedLog()
25 | editFile('src/main.ts', (code) => code.replace(`'Hello'`, `'Hello~'`))
26 | await sleepForEdit()
27 | expect(stringify(diagnostics)).toMatchSnapshot()
28 | expect(stripedLog).toMatchSnapshot()
29 |
30 | console.log('-- edit non error file --')
31 | resetReceivedLog()
32 | editFile('src/text.ts', (code) => code.replace(`Vanilla`, `vanilla`))
33 | await sleepForEdit()
34 | expect(stringify(diagnostics)).toMatchSnapshot()
35 | expect(stripedLog).toMatchSnapshot()
36 | })
37 | })
38 |
39 | describe.runIf(isBuild)('build', () => {
40 | const expectedMsg = 'Unexpected var, use let or const instead'
41 |
42 | it('should fail', async () => {
43 | expectStderrContains(log, expectedMsg)
44 | })
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/playground/typescript-react/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/playground/vue-tsc-vue3/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ msg }}
3 |
4 |
5 | Recommended IDE setup:
6 | VSCode
7 | +
8 | Vetur
12 | or
13 | Volar
14 | (if using
15 | <script setup>)
16 |
17 |
18 | See README.md for more information.
19 |
20 |
21 | Vite Docs |
22 | Vue 3 Docs
23 |
24 |
25 |
26 |
27 | Edit
28 | components/HelloWorld.vue to test hot module replacement.
29 |
30 |
31 |
32 |
48 |
49 |
66 |
--------------------------------------------------------------------------------
/docs/introduction/getting-started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | 1. Install plugin (pnpm recommended 🚀).
4 |
5 | ```bash
6 | pnpm add vite-plugin-checker -D
7 | ```
8 |
9 | If you are using Yarn or NPM
10 |
11 | ```bash
12 | yarn add vite-plugin-checker -D
13 | npm i vite-plugin-checker -D
14 | ```
15 |
16 | 2. Add plugin to Vite config file and config the checker you need. We add TypeScript here as an example. See all available checkers [here](/checkers/overview).
17 |
18 | ```ts
19 | // vite.config.js
20 | import checker from 'vite-plugin-checker'
21 | export default {
22 | plugins: [
23 | checker({
24 | // e.g. use TypeScript check
25 | typescript: true,
26 | }),
27 | ],
28 | }
29 | ```
30 |
31 | ::: tip
32 | If you'd prefer to not run the checkers during unit testing with Vitest, you can alter the config based on that. Example:
33 |
34 | ```ts
35 | // vite.config.js
36 | import checker from 'vite-plugin-checker'
37 | export default {
38 | plugins: [!process.env.VITEST ? checker({ typescript: true }) : undefined],
39 | }
40 | ```
41 |
42 | :::
43 |
44 | 3. You're all set. Open localhost page and start development 🚀.
45 |
46 | ::: tip
47 | It's recommended to open a browser for a better terminal flush, see [#27](https://github.com/fi3ework/vite-plugin-checker/pull/27).
48 | :::
49 |
50 | ::: warning
51 | `server.ws.on` is introduced to Vite in [2.6.8](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#268-2021-10-18). vite-plugin-checker relies on `server.ws.on` to make overlay visible after opening a new browser tab.
52 | :::
53 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/__tests__/vlsConfig.spec.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import { describe, expect, it } from 'vitest'
3 | import { ShutdownRequest } from 'vscode-languageserver/node'
4 | import { URI } from 'vscode-uri'
5 |
6 | import {
7 | logLevel2Severity,
8 | prepareClientConnection,
9 | } from '../src/checkers/vls/diagnostics'
10 |
11 | async function testVslConfig(overrideConfig?: any) {
12 | const workspaceUri = URI.file(path.join(__dirname, 'fixtures'))
13 | const { clientConnection, serverConnection, vls, up, down } =
14 | await prepareClientConnection(workspaceUri, logLevel2Severity.WARN, {
15 | watch: false,
16 | verbose: false,
17 | config: overrideConfig || null,
18 | })
19 |
20 | // @ts-expect-error
21 | expect(vls.workspaceConfig).toMatchSnapshot()
22 |
23 | // TODO: this test case will let Jest hang with out --forceExit option
24 | // current enable forceExit but we should find which resource is not released
25 | await clientConnection.sendRequest(ShutdownRequest.type)
26 | clientConnection.dispose()
27 | clientConnection.end()
28 | serverConnection.dispose()
29 | up.destroy()
30 | down.destroy()
31 | vls.dispose()
32 | }
33 |
34 | describe('VLS config', () => {
35 | it('default config', async () => {
36 | await testVslConfig()
37 | })
38 |
39 | it('customized config', async () => {
40 | await testVslConfig({
41 | vetur: {
42 | validation: {
43 | template: false,
44 | templateProps: false,
45 | interpolation: false,
46 | style: false,
47 | },
48 | },
49 | })
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/packages/runtime/src/ws.ts:
--------------------------------------------------------------------------------
1 | // #region
2 | // NOTE: sync modification with packages/vite-plugin-checker/client/index.ts
3 | const WS_CHECKER_ERROR_EVENT = 'vite-plugin-checker:error'
4 | const WS_CHECKER_RECONNECT_EVENT = 'vite-plugin-checker:reconnect'
5 | // #endregion
6 |
7 | const onCustomMessage: any[] = []
8 | const onReconnectMessage: any[] = []
9 |
10 | export function listenToCustomMessage(cb: (data: any) => any) {
11 | onCustomMessage.push(cb)
12 | }
13 |
14 | export function listenToReconnectMessage(cb: (data: any) => any) {
15 | onReconnectMessage.push(cb)
16 | }
17 |
18 | export function prepareListen() {
19 | const onMessage = async (data: any) => {
20 | switch (data.event) {
21 | case WS_CHECKER_ERROR_EVENT:
22 | for (const callbackfn of onCustomMessage) {
23 | callbackfn(data.data)
24 | }
25 |
26 | break
27 | case WS_CHECKER_RECONNECT_EVENT:
28 | for (const callbackfn of onReconnectMessage) {
29 | callbackfn(data.data)
30 | }
31 |
32 | break
33 | }
34 | }
35 |
36 | return {
37 | startListening: () => {
38 | if (import.meta.hot) {
39 | // listen server -> client messages
40 | import.meta.hot.on('vite-plugin-checker', (data: any) => {
41 | onMessage(data)
42 | })
43 |
44 | // told server that vite-plugin-checker runtime has loaded
45 | // then server should send stored diagnostics to display overlay
46 | // NOTE: sync modification with packages /packages/vite-plugin-checker/src/main.ts
47 | import.meta.hot.send('vite-plugin-checker', { event: 'runtime-loaded' })
48 | }
49 | },
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/playground/vue-tsc-buildmode/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ msg }}
3 |
4 |
5 | Recommended IDE setup:
6 | VSCode
7 | +
8 | Vetur
12 | or
13 | Volar
14 | (if using
15 | <script setup>)
16 |
17 |
18 | See README.md for more information.
19 |
20 |
21 | Vite Docs |
22 | Vue 3 Docs
23 |
24 |
25 |
26 |
27 | Edit
28 | components/HelloWorld.vue to test hot module replacement.
29 |
30 |
31 |
32 |
50 |
51 |
68 |
--------------------------------------------------------------------------------
/docs/checkers/vls.md:
--------------------------------------------------------------------------------
1 | # VLS
2 |
3 | You can use VLS checker for your Vue2 project. If you're using Vue3, choose [vue-tsc](/checkers/vue-tsc) checker.
4 |
5 | ## Installation
6 |
7 | 1. Make sure [vls](https://www.npmjs.com/package/vls) and [vti](https://www.npmjs.com/package/vti) are installed as peer dependencies, plugin will use vls on dev mode and vti on build mode.
8 |
9 | ```bash
10 | pnpm add vls vti -D
11 | ```
12 |
13 | 2. Add `vls` field to plugin config.
14 |
15 | ```js
16 | module.exports = {
17 | plugins: [checker({ vls: true })],
18 | }
19 | ```
20 |
21 | ## Configuration
22 |
23 | Advanced object configuration of `options.vls`
24 |
25 | VLS configuration accepts the same values that can be configured in VS code with keys that start with `vetur`.
26 | These are configured with nested objects rather than dotted string notation. TypeScript intellisense is available.
27 |
28 | See [`initParams.ts`](https://github.com/fi3ework/vite-plugin-checker/blob/8fc5d7f4a908a4c80d1cb978e0acf1d4e5700e6a/packages/vite-plugin-checker/src/checkers/vls/initParams.ts#L33) for a comprehensive list of the defaults that can be overridden. Unfortunately, Vetur does not provide a single comprehensive document of all its options.
29 |
30 | For example, to performing checking only the `
29 |
30 |
31 |
32 |
33 |
34 |
35 | `
36 | )
37 | res.status(200).set({ 'Content-Type': 'text/html' }).send(html)
38 | })
39 |
40 | app.use('/', createProxyMiddleware({ target: 'http://127.0.0.1:5173', changeOrigin: true }))
41 |
42 | return { app, viteDevServer }
43 | }
44 |
45 | const isTest = process.env.VITEST
46 |
47 | if (!isTest) {
48 | createServer().then(({ app, viteDevServer }) => {
49 | viteDevServer.listen()
50 | app.listen(port, () => {
51 | console.log('http://localhost:5173')
52 | })
53 | })
54 | }
55 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
1 | name: "\U0001F680 New feature proposal"
2 | description: Suggest an idea for this project
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | Thanks for your interest in the project and taking the time to fill out this feature report!
8 | - type: textarea
9 | id: feature-description
10 | attributes:
11 | label: Is your feature request related to a problem? Please describe.
12 | description: "A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]"
13 | validations:
14 | required: true
15 | - type: textarea
16 | id: suggested-solution
17 | attributes:
18 | label: Describe the solution you'd like
19 | description: A clear and concise description of what you want to happen.
20 | validations:
21 | required: true
22 | - type: textarea
23 | id: alternative
24 | attributes:
25 | label: Describe alternatives you've considered
26 | description: A clear and concise description of any alternative solutions or features you've considered.
27 | - type: textarea
28 | id: additional-context
29 | attributes:
30 | label: Additional context
31 | description: Add any other context or screenshots about the feature request here.
32 | - type: checkboxes
33 | id: checkboxes
34 | attributes:
35 | label: Validations
36 | description: Before submitting the issue, please make sure you do the following
37 | options:
38 | - label: Read the [docs](https://github.com/fi3ework/vite-plugin-checker#readme).
39 | required: true
40 | - label: Read the [Contributing Guidelines](https://github.com/fi3ework/vite-plugin-checker/blob/main/CONTRIBUTING.md).
41 | required: true
42 | - label: Check that there isn't already an issue that asks for the same feature to avoid creating a duplicate.
43 | required: true
44 |
--------------------------------------------------------------------------------
/playground/eslint-flat/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`eslint > serve > get initial error and subsequent error 1`] = `"[{"checkerId":"ESLint","frame":" > 1 | const a = /"hello/"/n | ^/n > 2 |/n | ^","id":"/playground-temp/eslint-flat/src/index.js","level":1,"loc":{"column":18,"file":"/playground-temp/eslint-flat/src/index.js","line":1},"message":"Missing semicolon. (semi)","stack":""}]"`;
4 |
5 | exports[`eslint > serve > get initial error and subsequent error 2`] = `
6 | [
7 | " ERROR(ESLint) Missing semicolon. (semi)
8 | FILE /playground-temp/eslint-flat/src/index.js:1:18
9 |
10 | > 1 | const a = "hello"
11 | | ^
12 | > 2 |
13 | | ^
14 | ",
15 | "[ESLint] Found 1 error and 0 warning",
16 | ]
17 | `;
18 |
19 | exports[`eslint > serve > get initial error and subsequent error 3`] = `"[{"checkerId":"ESLint","frame":" > 1 | const a = /"hello/"/n | ^/n > 2 |/n | ^","id":"/playground-temp/eslint-flat/src/index.js","level":1,"loc":{"column":18,"file":"/playground-temp/eslint-flat/src/index.js","line":1},"message":"Missing semicolon. (semi)","stack":""},{"checkerId":"ESLint","frame":" > 1 | const a = /"hello/"/n | ^/n > 2 |/n | ^","id":"/playground-temp/eslint-flat/src/index.js","level":1,"loc":{"column":18,"file":"/playground-temp/eslint-flat/src/index.js","line":1},"message":"Missing semicolon. (semi)","stack":""}]"`;
20 |
21 | exports[`eslint > serve > get initial error and subsequent error 4`] = `
22 | [
23 | " ERROR(ESLint) Missing semicolon. (semi)
24 | FILE /playground-temp/eslint-flat/src/index.js:1:18
25 |
26 | > 1 | const a = "hello"
27 | | ^
28 | > 2 |
29 | | ^
30 | ",
31 | "[ESLint] Found 1 error and 0 warning",
32 | ]
33 | `;
34 |
--------------------------------------------------------------------------------
/playground/vitestGlobalSetup.ts:
--------------------------------------------------------------------------------
1 | import { rmSync } from 'node:fs'
2 | import fs from 'node:fs/promises'
3 | import os from 'node:os'
4 | import path from 'node:path'
5 | import { chromium } from 'playwright-chromium'
6 |
7 | import type { BrowserServer } from 'playwright-chromium'
8 | const DIR = path.join(os.tmpdir(), 'vitest_playwright_global_setup')
9 |
10 | let browserServer: BrowserServer | undefined
11 |
12 | export async function setup(): Promise {
13 | browserServer = await chromium.launchServer({
14 | headless: !process.env.VITE_DEBUG_SERVE,
15 | args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : undefined,
16 | })
17 |
18 | await fs.mkdir(DIR, { recursive: true })
19 | await fs.writeFile(path.join(DIR, 'wsEndpoint'), browserServer.wsEndpoint())
20 |
21 | const tempDir = path.resolve(__dirname, '../playground-temp')
22 | await fs.rm(tempDir, { force: true, recursive: true })
23 | await fs.mkdir(tempDir, { recursive: true })
24 | await fs
25 | .cp(path.resolve(__dirname, '../playground'), tempDir, {
26 | dereference: false,
27 | recursive: true,
28 | filter(file) {
29 | const _file = file.replace(/\\/g, '/')
30 | return !_file.includes('__tests__') && !file.match(/dist(\/|$)/)
31 | },
32 | })
33 | .catch(async (error) => {
34 | if (error.code === 'EPERM' && error.syscall === 'symlink') {
35 | throw new Error(
36 | 'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.'
37 | )
38 | } else {
39 | throw error
40 | }
41 | })
42 | }
43 |
44 | export async function teardown(): Promise {
45 | browserServer?.close()
46 | if (!process.env.VITE_PRESERVE_BUILD_ARTIFACTS) {
47 | rmSync(path.resolve(__dirname, '../playground-temp'), { force: true, recursive: true })
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/docs/checkers/oxlint.md:
--------------------------------------------------------------------------------
1 | # oxlint
2 |
3 | ## Installation
4 |
5 | 1. Make sure [oxlint](https://www.npmjs.com/package/oxlint) is installed as a dependency.
6 |
7 | 2. Add `oxlint` field to plugin config. Valid options are either `true` or a configuration object.
8 |
9 | ```js
10 | // e.g.
11 | export default defineConfig({
12 | plugins: [
13 | checker({
14 | oxlint: true,
15 | // or
16 | oxlint: {
17 | lintCommand: "oxlint -D correctness",
18 | },
19 | }),
20 | ],
21 | });
22 | ```
23 |
24 | ## Configuration
25 |
26 | Advanced object configuration table of `options.oxlint`
27 |
28 | | field | Type | Default value | Description |
29 | | :----------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------- |------------------------------------------------------------------------------------------------------------------------|
30 | | lintCommand | `string` | `oxlint` | `lintCommand` will be executed at build mode. |
31 | | watchPath | `string \| string[]` | `undefined` | **(Only in dev mode)** Configure path to watch files for oxlint. If not specified, will watch the entire project root. |
32 | | dev.logLevel | `('error' \| 'warning')[]` | `['error', 'warning']` | **(Only in dev mode)** Which level of oxlint should be emitted to terminal and overlay in dev mode. |
33 |
34 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/stylelint/argv.ts:
--------------------------------------------------------------------------------
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(
6 | value: string,
7 | env?: string,
8 | file?: string,
9 | ): string[] {
10 | // ([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*) Matches nested quotes until the first space outside of quotes
11 |
12 | // [^\s'"]+ or Match if not a space ' or "
13 |
14 | // (['"])([^\5]*?)\5 or Match "quoted text" without quotes
15 | // `\3` and `\5` are a backreference to the quote style (' or ") captured
16 | const myRegexp =
17 | // @ts-expect-error Bypass typescript validation
18 | // biome-ignore lint/complexity/noUselessEscapeInRegex: Bypass validation
19 | /([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*)|[^\s'"]+|(['"])([^\5]*?)\5/gi
20 | const myString = value
21 | const myArray: string[] = []
22 | if (env) {
23 | myArray.push(env)
24 | }
25 | if (file) {
26 | myArray.push(file)
27 | }
28 | let match: RegExpExecArray | null
29 | do {
30 | // Each call to exec returns the next regex match as an array
31 | match = myRegexp.exec(myString)
32 | if (match !== null) {
33 | // Index 1 in the array is the captured group if it exists
34 | // Index 0 is the matched text, which we use if no captured group exists
35 | myArray.push(firstString(match[1], match[6], match[0])!)
36 | }
37 | } while (match !== null)
38 |
39 | return myArray
40 | }
41 |
42 | // Accepts any number of arguments, and returns the first one that is a string
43 | // (even an empty string)
44 | // @ts-ignore
45 | function firstString(...args: Array): string | undefined {
46 | // eslint-disable-next-line @typescript-eslint/prefer-for-of
47 | for (let i = 0; i < args.length; i++) {
48 | const arg = args[i]
49 | if (typeof arg === 'string') {
50 | return arg
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/vueTsc/languagePlugins.cjs:
--------------------------------------------------------------------------------
1 | const path = require('node:path')
2 |
3 | const vueTscDir = path.dirname(require.resolve('vue-tsc/package.json'))
4 | const vue =
5 | /** @type {typeof import('@vue/language-core') & { resolveVueCompilerOptions?: any }} */ (
6 | require(require.resolve('@vue/language-core', { paths: [vueTscDir] }))
7 | )
8 | const windowsPathReg = /\\/g
9 |
10 | const removeEmitGlobalTypesRegexp =
11 | /^[^\n]*__VLS_globalTypesStart[\w\W]*__VLS_globalTypesEnd[^\n]*\n?$/gm
12 |
13 | /**
14 | * @param dts {string}
15 | * @returns {string}
16 | */
17 | function removeEmitGlobalTypes(dts) {
18 | return dts.replace(removeEmitGlobalTypesRegexp, '')
19 | }
20 |
21 | const getDefaultCompilerOptions =
22 | vue.getDefaultCompilerOptions || (() => vue.resolveVueCompilerOptions({}))
23 |
24 | // #region copied from https://github.com/vuejs/language-tools/blob/0781998a29f176ad52c30d3139d5c78a5688bd5d/packages/tsc/index.ts
25 | /**
26 | * @param {typeof import('typescript')} ts
27 | * @param {import('typescript').CreateProgramOptions} options
28 | */
29 | exports.getLanguagePlugins = (ts, options) => {
30 | const { configFilePath } = options.options
31 | const vueOptions =
32 | typeof configFilePath === 'string'
33 | ? vue.createParsedCommandLine(
34 | ts,
35 | ts.sys,
36 | configFilePath.replace(windowsPathReg, '/'),
37 | ).vueOptions
38 | : getDefaultCompilerOptions()
39 |
40 | if (vue.writeGlobalTypes) {
41 | vue.writeGlobalTypes(vueOptions, ts.sys.writeFile)
42 | } else {
43 | const host = /** @type {import('typescript').CompilerHost} */ (options.host)
44 | const writeFile = host.writeFile.bind(host)
45 | host.writeFile = (fileName, contents, ...args) => {
46 | return writeFile(fileName, removeEmitGlobalTypes(contents), ...args)
47 | }
48 | }
49 | const vueLanguagePlugin = vue.createVueLanguagePlugin(
50 | ts,
51 | options.options,
52 | vueOptions,
53 | (id) => id,
54 | )
55 | return [vueLanguagePlugin]
56 | }
57 | // #endregion
58 |
--------------------------------------------------------------------------------
/docs/checkers/typescript.md:
--------------------------------------------------------------------------------
1 | # TypeScript
2 |
3 | You can use TypeScript checker for vanilla TypeScript project or React project.
4 |
5 | ## Installation
6 |
7 | 1. Make sure [typescript](https://www.npmjs.com/package/typescript) is installed as a peer dependency.
8 |
9 | 2. Add `typescript` field to plugin config.
10 |
11 | ```js
12 | export default {
13 | plugins: [checker({ typescript: true /** or an object config */ })],
14 | }
15 | ```
16 |
17 | ## Configuration
18 |
19 | Advanced object configuration table of `options.typescript`.
20 |
21 | | field | Type | Default value | Description |
22 | | :----------- | --------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23 | | root | `string` | [Vite config](https://vitejs.dev/config/#root) `root` | Root path to find tsconfig file |
24 | | tsconfigPath | `string` | `"tsconfig.json"` | Relative tsconfig path to `root` |
25 | | buildMode | `boolean` | `false` | Add [`--build`](https://www.typescriptlang.org/docs/handbook/project-references.html) to `tsc` flag, note that `noEmit` does NOT work if `buildMode` is `true` ([#36917](https://github.com/microsoft/TypeScript/issues/36917)) |
26 |
--------------------------------------------------------------------------------
/playground/oxlint-default/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import { describe, expect, it } from 'vitest'
3 | import {
4 | diagnostics,
5 | editFile,
6 | expectStderrContains,
7 | isBuild,
8 | isServe,
9 | log,
10 | resetDiagnostics,
11 | resetReceivedLog,
12 | sleepForEdit,
13 | sleepForServerReady,
14 | stripedLog,
15 | } from '../../testUtils'
16 |
17 | describe('oxlint-default', () => {
18 | describe.runIf(isServe)('serve', () => {
19 | it('should display initial errors', async () => {
20 | await sleepForServerReady()
21 |
22 | expect(stringify(diagnostics)).toMatchSnapshot()
23 | expect(stripedLog).toMatchSnapshot()
24 | })
25 |
26 | it('should react to project file change', async () => {
27 | await sleepForServerReady()
28 |
29 | expect(stringify(diagnostics)).toMatchSnapshot()
30 | expect(stripedLog).toMatchSnapshot()
31 |
32 | editFile('src/main.ts', (code) =>
33 | code.replace('const unusedVariable1 = 42;', ''),
34 | )
35 | await sleepForEdit()
36 |
37 | resetReceivedLog()
38 | resetDiagnostics()
39 |
40 | expect(stringify(diagnostics)).toMatchSnapshot()
41 | expect(stripedLog).toMatchSnapshot()
42 | })
43 |
44 | it('should react to oxlint config file change', async () => {
45 | await sleepForServerReady()
46 |
47 | expect(stringify(diagnostics)).toMatchSnapshot()
48 | expect(stripedLog).toMatchSnapshot()
49 |
50 | resetReceivedLog()
51 | resetDiagnostics()
52 |
53 | editFile('.oxlintrc.json', (code) =>
54 | code.replace('"correctness": "error"', '"correctness": "warn"'),
55 | )
56 | await sleepForEdit()
57 |
58 | expect(stringify(diagnostics)).toMatchSnapshot()
59 | expect(stripedLog).toMatchSnapshot()
60 | })
61 | })
62 |
63 | describe.runIf(isBuild)('build', () => {
64 | it('should fail', async () => {
65 | expectStderrContains(
66 | log,
67 | "Variable 'unusedVariable1' is declared but never used.",
68 | )
69 | })
70 | })
71 | })
72 |
--------------------------------------------------------------------------------
/biome.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
3 | "assist": { "actions": { "source": { "organizeImports": "on" } } },
4 | "vcs": {
5 | "enabled": true,
6 | "defaultBranch": "main",
7 | "clientKind": "git",
8 | "useIgnoreFile": true
9 | },
10 | "files": {
11 | "includes": [
12 | "**",
13 | "!**/*.vue",
14 | "!**/playground",
15 | "!**/packages/vite-plugin-checker/src/checkers/eslint/options.ts",
16 | "!**/packages/vite-plugin-checker/src/checkers/stylelint/options.ts",
17 | "!**/playground/**/*/src/**/*.*"
18 | ],
19 | "ignoreUnknown": true
20 | },
21 | "formatter": {
22 | "indentStyle": "space"
23 | },
24 | "javascript": {
25 | "formatter": {
26 | "semicolons": "asNeeded",
27 | "quoteStyle": "single"
28 | }
29 | },
30 | "linter": {
31 | "enabled": true,
32 | "rules": {
33 | "recommended": true,
34 | "style": {
35 | "noNonNullAssertion": "off",
36 | "useFilenamingConvention": {
37 | "level": "error",
38 | "options": {
39 | "filenameCases": ["camelCase", "PascalCase", "export"]
40 | }
41 | },
42 | "noParameterAssign": "error",
43 | "useAsConstAssertion": "error",
44 | "useDefaultParameterLast": "error",
45 | "useEnumInitializers": "error",
46 | "useSelfClosingElements": "error",
47 | "useSingleVarDeclarator": "error",
48 | "noUnusedTemplateLiteral": "error",
49 | "useNumberNamespace": "error",
50 | "noInferrableTypes": "error",
51 | "noUselessElse": "error"
52 | },
53 | "suspicious": {
54 | "noExplicitAny": "off",
55 | "noConfusingVoidType": "off"
56 | },
57 | "performance": {
58 | "noDelete": "off"
59 | }
60 | }
61 | },
62 | "overrides": [
63 | {
64 | "includes": ["packages/runtime/src/vite-env.d.ts"],
65 | "linter": {
66 | "rules": {
67 | "style": {
68 | "useFilenamingConvention": "off"
69 | }
70 | }
71 | }
72 | }
73 | ]
74 | }
75 |
--------------------------------------------------------------------------------
/playground/config-default/__tests__/__snapshots__/test.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`config-default > serve > get initial error 1`] = `"[{"checkerId":"ESLint","frame":" 1 | import { text } from './text'/n 2 |/n > 3 | var hello = 'Hello'/n | ^^^^^^^^^^^^^^^^^^^/n 4 |/n 5 | const rootDom = document.querySelector('#root')! as HTMLElement/n 6 | rootDom.innerHTML = hello + text","id":"/playground-temp/config-default/src/main.ts","level":1,"loc":{"column":1,"file":"/playground-temp/config-default/src/main.ts","line":3},"message":"Unexpected var, use let or const instead. (no-var)","stack":""},{"checkerId":"ESLint","frame":" 3 | var hello = 'Hello'/n 4 |/n > 5 | const rootDom = document.querySelector('#root')! as HTMLElement/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 6 | rootDom.innerHTML = hello + text/n 7 |/n 8 | export {}","id":"/playground-temp/config-default/src/main.ts","level":0,"loc":{"column":17,"file":"/playground-temp/config-default/src/main.ts","line":5},"message":"Forbidden non-null assertion. (@typescript-eslint/no-non-null-assertion)","stack":""}]"`;
4 |
5 | exports[`config-default > serve > get initial error 2`] = `
6 | [
7 | " ERROR(ESLint) Unexpected var, use let or const instead. (no-var)
8 | FILE /playground-temp/config-default/src/main.ts:3:1
9 |
10 | 1 | import { text } from './text'
11 | 2 |
12 | > 3 | var hello = 'Hello'
13 | | ^^^^^^^^^^^^^^^^^^^
14 | 4 |
15 | 5 | const rootDom = document.querySelector('#root')! as HTMLElement
16 | 6 | rootDom.innerHTML = hello + text
17 | ",
18 | " WARNING(ESLint) Forbidden non-null assertion. (@typescript-eslint/no-non-null-assertion)
19 | FILE /playground-temp/config-default/src/main.ts:5:17
20 |
21 | 3 | var hello = 'Hello'
22 | 4 |
23 | > 5 | const rootDom = document.querySelector('#root')! as HTMLElement
24 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 | 6 | rootDom.innerHTML = hello + text
26 | 7 |
27 | 8 | export {}
28 | ",
29 | "[ESLint] Found 1 error and 1 warning",
30 | ]
31 | `;
32 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitepress'
2 |
3 | export default defineConfig({
4 | lang: 'en-US',
5 | title: 'vite-plugin-checker',
6 | description:
7 | 'Vite plugin that provide checks of TypeScript, ESLint, Biome, vue-tsc, and more.',
8 | lastUpdated: true,
9 | themeConfig: {
10 | outline: 'deep',
11 | sidebar: {
12 | '/': sidebar(),
13 | },
14 | editLink: {
15 | pattern:
16 | 'https://github.com/fi3ework/vite-plugin-checker/edit/main/docs/:path',
17 | text: 'Edit this page on GitHub',
18 | },
19 | socialLinks: [
20 | {
21 | icon: 'github',
22 | link: 'https://github.com/fi3ework/vite-plugin-checker',
23 | },
24 | {
25 | icon: 'npm',
26 | link: 'https://www.npmjs.com/package/vite-plugin-checker',
27 | },
28 | ],
29 | footer: {
30 | message: 'Released under the MIT License.',
31 | copyright: 'Copyright fi3ework',
32 | },
33 | },
34 | })
35 |
36 | function sidebar() {
37 | return [
38 | {
39 | text: 'Introduction',
40 | collapsible: true,
41 | items: [
42 | { text: 'Introduction', link: '/introduction/introduction' },
43 | { text: 'Getting Started', link: '/introduction/getting-started' },
44 | ],
45 | },
46 | {
47 | text: 'Checkers',
48 | collapsible: true,
49 | items: [
50 | { text: 'Overview', link: '/checkers/overview' },
51 | { text: 'TypeScript', link: '/checkers/typescript' },
52 | { text: 'vue-tsc', link: '/checkers/vue-tsc' },
53 | { text: 'ESLint', link: '/checkers/eslint' },
54 | { text: 'Biome', link: '/checkers/biome' },
55 | { text: 'Stylelint', link: '/checkers/stylelint' },
56 | { text: 'VLS', link: '/checkers/vls' },
57 | { text: 'oxlint', link: '/checkers/oxlint' },
58 | ],
59 | },
60 | {
61 | text: 'Configuration',
62 | collapsible: true,
63 | items: [{ text: 'Shared ', link: '/configuration/config' }],
64 | },
65 | {
66 | text: 'FAQs',
67 | collapsible: true,
68 | items: [{ text: 'Integration', link: '/faq/integration' }],
69 | },
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.0.0",
3 | "private": true,
4 | "scripts": {
5 | "build": "pnpm -r --filter='./packages/**' run build",
6 | "build:test": "pnpm -r --filter='./packages/**' run build:test",
7 | "clean": "pnpm -r --filter='./packages/**' run clean",
8 | "dev": "pnpm -r --filter='./packages/**' --parallel run dev",
9 | "docs:build": "pnpm --filter docs run build",
10 | "docs:dev": "pnpm --filter docs run dev",
11 | "format": "biome format . --write",
12 | "postinstall": "simple-git-hooks install",
13 | "lint": "biome check . --diagnostic-level=warn",
14 | "publint": "pnpm build && pnpm -r --filter='vite-plugin-checker' exec publint",
15 | "sort-package-json": "npx sort-package-json \"packages/*/package.json\"",
16 | "test": "pnpm test-unit && pnpm test-serve && pnpm test-build",
17 | "test-build": "VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts",
18 | "test-knip": "knip",
19 | "test-serve": "vitest run -c vitest.config.e2e.ts",
20 | "test-unit": "vitest run",
21 | "test-unit:watch": "vitest",
22 | "type-check": "pnpm -r --parallel --filter \"vite-plugin-checker\" exec tsc --noEmit"
23 | },
24 | "simple-git-hooks": {
25 | "pre-commit": "npx lint-staged"
26 | },
27 | "lint-staged": {
28 | "package.json": "sort-package-json",
29 | "packages/**/*.{js,ts}": [
30 | "biome check --write"
31 | ]
32 | },
33 | "devDependencies": {
34 | "@biomejs/biome": "^2.1.2",
35 | "@tsconfig/node20": "^20.1.8",
36 | "@tsconfig/strictest": "^2.0.8",
37 | "@types/babel__code-frame": "^7.0.6",
38 | "@types/node": "^20.19.9",
39 | "execa": "^9.6.0",
40 | "fast-json-stable-stringify": "^2.1.0",
41 | "knip": "^5.66.3",
42 | "lint-staged": "^16.1.6",
43 | "oxlint": "^1.18.0",
44 | "pkg-pr-new": "^0.0.60",
45 | "playwright-chromium": "^1.54.2",
46 | "publint": "^0.3.15",
47 | "simple-git-hooks": "^2.13.1",
48 | "sort-deep-object-arrays": "^1.1.2",
49 | "sort-package-json": "^3.4.0",
50 | "tiny-invariant": "^1.3.3",
51 | "tinyglobby": "^0.2.15",
52 | "typescript": "^5.8.3",
53 | "vite": "^7.1.11",
54 | "vitest": "^3.2.4"
55 | },
56 | "packageManager": "pnpm@9.15.9"
57 | }
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # JetBrains IDEs
107 | .idea
108 |
109 | #
110 | lib/
111 | playground-temp/
112 | packages/runtime/public/build/bundle.js
113 | docs/.vitepress/cache
--------------------------------------------------------------------------------
/docs/introduction/introduction.md:
--------------------------------------------------------------------------------
1 | # About vite-plugin-checker
2 |
3 | A Vite plugin that can run TypeScript, VLS, vue-tsc, ESLint,
4 | Stylelint and oxlint in worker thread to **add type checking and linting support** for Vite.
5 |
6 |
12 |
13 |
14 |
15 |
16 |
17 | > History version documentations [0.1](https://github.com/fi3ework/vite-plugin-checker/tree/v0.1.x), [0.2](https://github.com/fi3ework/vite-plugin-checker/tree/v0.2), [0.3](https://github.com/fi3ework/vite-plugin-checker/tree/v0.3.x), [0.4](https://github.com/fi3ework/vite-plugin-checker/tree/v0.4.x/docs). It's highly recommended to use latest version before 1.0.0, although there's some breaking changes in each version bumping, the plugin configuration is quite simple.
18 |
19 | ## Online playground
20 |
21 | | Examples | StackBlitz |
22 | | ------------------ | ---------------------------------------------------------------- |
23 | | Vue3 + vue-tsc | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-e8pddl) |
24 | | React + TypeScript | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-b4zcev) |
25 | | ESLint | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-l1ritu) |
26 | | Vue2 + VLS | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-kpffk5) |
27 | | Multiple | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-mb4ea6) |
28 |
--------------------------------------------------------------------------------
/.github/workflows/sync-volar.yml:
--------------------------------------------------------------------------------
1 | name: Create issue when sync up Volar is required
2 |
3 | on:
4 | schedule:
5 | - cron: '0 0 * * *'
6 | workflow_dispatch:
7 |
8 | jobs:
9 | check_file_changes:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v4
15 | with:
16 | repository: 'volarjs/volar.js'
17 | fetch-depth: 0
18 |
19 | - name: Check if runTsc.ts changed in last 24 hours
20 | id: check_changes
21 | run: |
22 | CHANGED=$(git log --name-only --since="24 hours ago" --pretty=format: | sort | uniq | grep -q "packages/typescript/lib/quickstart/runTsc.ts" && echo "true" || echo "false")
23 | echo "file_changed=${CHANGED}"
24 | echo "file_changed=${CHANGED}" >> $GITHUB_OUTPUT
25 |
26 | - name: Create issue if runTsc.ts changed
27 | if: steps.check_changes.outputs.file_changed == 'true'
28 | uses: actions/github-script@v7
29 | with:
30 | github-token: ${{ secrets.GITHUB_TOKEN }}
31 | script: |
32 | const { owner, repo } = context.repo;
33 |
34 | const date = new Date();
35 | const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
36 | const formattedDate = date.toLocaleDateString('en-CA', options);
37 |
38 | const issueTitle = `Volar Change Detected in Last 24 Hours (${formattedDate})`;
39 | # write new line for each line in issueBody
40 | const issueBody = "## ✨ Sync up needed\n\nThe file [`packages/typescript/lib/quickstart/runTsc.ts`](https://github.com/volarjs/volar.js/blob/master/packages/typescript/lib/quickstart/runTsc.ts) in Volar has changed in the last 24 hours.\n\nFile [`packages/vite-plugin-checker/src/checkers/vueTsc/prepareVueTsc.ts`](https://github.com/fi3ework/vite-plugin-checker/blob/main/packages/vite-plugin-checker/src/checkers/vueTsc/prepareVueTsc.ts) contains some code copied from there, please help to sync up the modification from Volar.\n\nRemember to close this issue when is sync up is finished.";
41 |
42 | await github.rest.issues.create({
43 | owner,
44 | repo,
45 | title: issueTitle,
46 | body: issueBody,
47 | labels: ['vue-tsc']
48 | });
49 |
--------------------------------------------------------------------------------
/packages/vite-plugin-checker/src/checkers/oxlint/server.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import chokidar from 'chokidar'
3 | import type { FileDiagnosticManager } from '../../FileDiagnosticManager.js'
4 | import { filterLogLevel } from '../../logger.js'
5 | import { runOxlint } from './cli.js'
6 | import { dispatchDiagnostics } from './diagnostics.js'
7 | import type { ResolvedOptions } from './options.js'
8 | import type { DisplayTarget } from './types'
9 |
10 | export async function setupDevServer(
11 | root: string,
12 | options: ResolvedOptions,
13 | manager: FileDiagnosticManager,
14 | displayTargets: Set,
15 | ): Promise {
16 | const initial = await runOxlint(options.command, root)
17 | manager.initWith(initial)
18 | dispatchDiagnostics(
19 | filterLogLevel(manager.getDiagnostics(), options.logLevel),
20 | displayTargets,
21 | )
22 |
23 | const watcher = chokidar.watch(options.watchTarget, {
24 | cwd: root,
25 | ignored: (path: string) => path.includes('node_modules'),
26 | })
27 |
28 | watcher.on('change', async (filePath) => {
29 | await handleFileChange(root, options.command, filePath, manager)
30 | dispatchDiagnostics(
31 | filterLogLevel(manager.getDiagnostics(), options.logLevel),
32 | displayTargets,
33 | )
34 | })
35 |
36 | watcher.on('unlink', (filePath) => {
37 | handleFileUnlink(root, filePath, manager)
38 | dispatchDiagnostics(
39 | filterLogLevel(manager.getDiagnostics(), options.logLevel),
40 | displayTargets,
41 | )
42 | })
43 |
44 | watcher.add('.')
45 | }
46 |
47 | function handleFileUnlink(
48 | root: string,
49 | filePath: string,
50 | manager: FileDiagnosticManager,
51 | ) {
52 | const absPath = path.resolve(root, filePath)
53 | manager.updateByFileId(absPath, [])
54 | }
55 |
56 | async function handleFileChange(
57 | root: string,
58 | command: string,
59 | filePath: string,
60 | manager: FileDiagnosticManager,
61 | ) {
62 | const absPath = path.resolve(root, filePath)
63 |
64 | const isConfigFile = path.basename(absPath) === '.oxlintrc.json'
65 | if (isConfigFile) {
66 | const diagnostics = await runOxlint(`${command} ${root}`, root)
67 | manager.initWith(diagnostics)
68 | } else {
69 | const diagnostics = await runOxlint(`${command} ${absPath}`, root)
70 | manager.updateByFileId(absPath, diagnostics)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/playground/multiple-hmr/__tests__/test.spec.ts:
--------------------------------------------------------------------------------
1 | import stringify from 'fast-json-stable-stringify'
2 | import stable from 'sort-deep-object-arrays'
3 | import { describe, expect, it } from 'vitest'
4 |
5 | import {
6 | diagnostics,
7 | editFile,
8 | expectStderrContains,
9 | isBuild,
10 | isServe,
11 | resetDiagnostics,
12 | resetReceivedLog,
13 | log,
14 | sleepForEdit,
15 | sleepForServerReady,
16 | stripedLog,
17 | } from '../../testUtils'
18 |
19 | describe('multiple-hmr', () => {
20 | describe.runIf(isServe)('serve', () => {
21 | it('get initial error and subsequent error', async () => {
22 | await sleepForServerReady()
23 | expect(stringify(stable(diagnostics))).toMatchSnapshot()
24 | expect(stable(stripedLog)).toMatchSnapshot()
25 |
26 | console.log('-- edit with error --')
27 | resetDiagnostics()
28 | resetReceivedLog()
29 | editFile('src/value.ts', (code) =>
30 | code.replace('export var value: string = 1', 'export var value: string = 2')
31 | )
32 | await sleepForEdit()
33 | expect(stringify(stable(diagnostics))).toMatchSnapshot()
34 | // don't know why striped log in disorder on Linux, while correct on mac and Windows
35 | // comment out for now to pass test cases stably and striped log is duplicated with diagnostics somehow.
36 | // Need help to figure out what went wrong. 😅
37 | // expect(stripedLog).toMatchSnapshot()
38 |
39 | console.log('-- fix typescript error --')
40 | resetDiagnostics()
41 | resetReceivedLog()
42 | editFile('src/value.ts', (code) =>
43 | code.replace('export var value: string = 2', `export var value = 2`)
44 | )
45 | await sleepForEdit()
46 | expect(stringify(stable(diagnostics))).toMatchSnapshot()
47 |
48 | console.log('-- fix eslint error --')
49 | resetDiagnostics()
50 | resetReceivedLog()
51 | editFile('src/value.ts', (code) => code.replace('var', 'const'))
52 | await sleepForEdit()
53 | expect(stringify(stable(diagnostics))).toMatchSnapshot()
54 | })
55 | })
56 |
57 | describe.runIf(isBuild)('build', () => {
58 | const expectedMsg = [
59 | 'Unexpected var, use let or const instead',
60 | `error TS2322: Type 'number' is not assignable to type 'string'`,
61 | ]
62 |
63 | it('should fail', async () => {
64 | expectStderrContains(log, expectedMsg)
65 | })
66 | })
67 | })
68 |
--------------------------------------------------------------------------------