@@ -192,8 +191,12 @@ export class ErrorOverlay extends HTMLElement {
}
public appendErrors({ errors, checkerId }: OverlayData) {
+ if (!errors.length) {
+ return
+ }
+
const toAppend: string[] = new Array(errors.length).fill(errorItemTemplate(checkerId))
- this.root.querySelector('.message-list')!.innerHTML += toAppend
+ this.root.querySelector('.message-list')!.innerHTML += toAppend.join('')
errors.forEach((err, index) => {
codeframeRE.lastIndex = 0
const hasFrame = err.frame && codeframeRE.test(err.frame)
diff --git a/packages/vite-plugin-checker/src/FileDiagnosticManager.ts b/packages/vite-plugin-checker/src/FileDiagnosticManager.ts
new file mode 100644
index 00000000..9b3c33e8
--- /dev/null
+++ b/packages/vite-plugin-checker/src/FileDiagnosticManager.ts
@@ -0,0 +1,51 @@
+import type { NormalizedDiagnostic } from './logger'
+
+class FileDiagnosticManager {
+ public diagnostics: NormalizedDiagnostic[] = []
+
+ public initWith(diagnostics: NormalizedDiagnostic[]) {
+ diagnostics.forEach((d) => {
+ this.diagnostics.push(d)
+ })
+ }
+
+ public getDiagnostics(fileName?: string) {
+ if (fileName) {
+ return this.diagnostics.filter((f) => f.id === fileName)
+ }
+
+ return this.diagnostics
+ }
+
+ // public get lastDiagnostic() {
+ // return this.diagnostics[this.diagnostics.length - 1]
+ // }
+
+ public setFile(fileName: string, next: NormalizedDiagnostic[] | null) {
+ for (let i = 0; i < this.diagnostics.length; i++) {
+ if (this.diagnostics[i].id === fileName) {
+ this.diagnostics.splice(i, 1)
+ i--
+ }
+ }
+
+ if (next?.length) {
+ this.diagnostics.push(...next)
+ }
+ }
+
+ // public updateFile(next: NormalizedDiagnostic[] | null) {
+ // for (let i = 0; i < this.diagnostics.length; i++) {
+ // if (this.diagnostics[i].loc?.start.line === fileName) {
+ // this.diagnostics.splice(i, 1)
+ // i--
+ // }
+ // }
+
+ // if (next?.length) {
+ // this.diagnostics.push(...next)
+ // }
+ // }
+}
+
+export { FileDiagnosticManager }
diff --git a/packages/vite-plugin-checker/src/checkers/eslint/main.ts b/packages/vite-plugin-checker/src/checkers/eslint/main.ts
index 72995750..aa75fd91 100644
--- a/packages/vite-plugin-checker/src/checkers/eslint/main.ts
+++ b/packages/vite-plugin-checker/src/checkers/eslint/main.ts
@@ -17,6 +17,9 @@ import {
} from '../../logger'
import { ACTION_TYPES } from '../../types'
import { translateOptions } from './cli'
+import { FileDiagnosticManager } from '../../FileDiagnosticManager'
+
+const manager = new FileDiagnosticManager()
import type { CreateDiagnostic } from '../../types'
const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
@@ -56,19 +59,23 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
// : pluginConfig.eslint.files
// const paths = config.
- let diagnosticsCache: NormalizedDiagnostic[] = []
+ // let diagnosticsCache: NormalizedDiagnostic[] = []
const dispatchDiagnostics = () => {
- diagnosticsCache.forEach((n) => {
- consoleLog(diagnosticToTerminalLog(n, 'ESLint'))
+ const diagnostics = manager.getDiagnostics()
+ diagnostics.forEach((d) => {
+ consoleLog(diagnosticToTerminalLog(d, 'ESLint'))
})
- const lastErr = diagnosticsCache[0]
+ // const lastErr = diagnosticsCache[0]
if (overlay) {
parentPort?.postMessage({
type: ACTION_TYPES.overlayError,
- payload: toViteCustomPayload('eslint', lastErr ? [diagnosticToViteError(lastErr)] : []),
+ payload: toViteCustomPayload(
+ 'eslint',
+ diagnostics.map((d) => diagnosticToViteError(d))
+ ),
// payload: lastErr
// ? {
@@ -82,18 +89,19 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
const handleFileChange = async (filePath: string, type: 'change' | 'unlink') => {
// if (!extensions.includes(path.extname(filePath))) return
+ const absPath = path.resolve(root, filePath)
if (type === 'unlink') {
- const absPath = path.resolve(root, filePath)
- diagnosticsCache = diagnosticsCache.filter((d) => d.id !== absPath)
+ manager.setFile(absPath, [])
+ // diagnosticsCache = diagnosticsCache.filter((d) => d.id !== absPath)
} else if (type === 'change') {
- console.log(filePath)
const diagnosticsOfChangedFile = await eslint.lintFiles(filePath)
const newDiagnostics = diagnosticsOfChangedFile
.map((d) => normalizeEslintDiagnostic(d))
.flat(1)
- const absPath = diagnosticsOfChangedFile[0].filePath
- diagnosticsCache = diagnosticsCache.filter((d) => d.id !== absPath).concat(newDiagnostics)
+ // const absPath = diagnosticsOfChangedFile[0].filePath
+ // diagnosticsCache = diagnosticsCache.filter((d) => d.id !== absPath).concat(newDiagnostics)
+ manager.setFile(absPath, newDiagnostics)
}
dispatchDiagnostics()
@@ -102,7 +110,8 @@ const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
// initial lint
const files = options._.slice(1)
const diagnostics = await eslint.lintFiles(files)
- diagnosticsCache = diagnostics.map((p) => normalizeEslintDiagnostic(p)).flat(1)
+ manager.initWith(diagnostics.map((p) => normalizeEslintDiagnostic(p)).flat(1))
+ // diagnosticsCache = diagnostics.map((p) => normalizeEslintDiagnostic(p)).flat(1)
dispatchDiagnostics()
// watch lint
diff --git a/playground/multiple/__tests__/__snapshots__/test.spec.ts.snap b/playground/multiple/__tests__/__snapshots__/test.spec.ts.snap
new file mode 100644
index 00000000..66f9f591
--- /dev/null
+++ b/playground/multiple/__tests__/__snapshots__/test.spec.ts.snap
@@ -0,0 +1,148 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`multiple serve get initial error and subsequent error 1`] = `"[{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"
/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1'/n | ^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Type 'string' is not assignable to type 'number'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Type 'string' is not assignable to type 'boolean'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"}]"`;
+
+exports[`multiple serve get initial error and subsequent error 2`] = `
+" ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:3:1
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:4:1
+
+ 2 |
+ 3 | var hello1: number = 'Hello1'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'number'.
+ FILE /temp/multiple/src/main.ts:3:5
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1'
+ | ^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'boolean'.
+ FILE /temp/multiple/src/main.ts:4:5
+
+ 2 |
+ 3 | var hello1: number = 'Hello1'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+Found 2 errors. Watching for file changes."
+`;
+
+exports[`multiple serve get initial error and subsequent error 3`] = `"[{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1~'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1~'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1~'/n | ^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Type 'string' is not assignable to type 'number'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1~'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Type 'string' is not assignable to type 'boolean'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"}]"`;
+
+exports[`multiple serve get initial error and subsequent error 4`] = `
+" ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:3:1
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1~'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:4:1
+
+ 2 |
+ 3 | var hello1: number = 'Hello1~'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'number'.
+ FILE /temp/multiple/src/main.ts:3:5
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1~'
+ | ^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'boolean'.
+ FILE /temp/multiple/src/main.ts:4:5
+
+ 2 |
+ 3 | var hello1: number = 'Hello1~'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+Found 2 errors. Watching for file changes."
+`;
+
+exports[`multiple serve get initial error and subsequent error 5`] = `"[{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1~'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1~'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":1,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Unexpected var, use let or const instead.\\",\\"plugin\\":\\"ESLint\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 1 | import { text } from './text'/n 2 |/n > 3 | var hello1: number = 'Hello1~'/n | ^^^^^^/n 4 | var hello2: boolean = 'Hello2'/n 5 |/n 6 | const rootDom = document.querySelector('#root')!\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":3},\\"message\\":\\"Type 'string' is not assignable to type 'number'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"},{\\"frame\\":\\" 2 |/n 3 | var hello1: number = 'Hello1~'/n > 4 | var hello2: boolean = 'Hello2'/n | ^^^^^^/n 5 |/n 6 | const rootDom = document.querySelector('#root')!/n 7 | rootDom.innerHTML = hello1 + text\\",\\"id\\":\\"/temp/multiple/src/main.ts\\",\\"loc\\":{\\"column\\":5,\\"file\\":\\"/temp/multiple/src/main.ts\\",\\"line\\":4},\\"message\\":\\"Type 'string' is not assignable to type 'boolean'.\\",\\"plugin\\":\\"TypeScript\\",\\"stack\\":\\"\\"}]"`;
+
+exports[`multiple serve get initial error and subsequent error 6`] = `
+" ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:3:1
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1~'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ ERROR(ESLint) Unexpected var, use let or const instead.
+ FILE /temp/multiple/src/main.ts:4:1
+
+ 2 |
+ 3 | var hello1: number = 'Hello1~'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'number'.
+ FILE /temp/multiple/src/main.ts:3:5
+
+ 1 | import { text } from './text'
+ 2 |
+ > 3 | var hello1: number = 'Hello1~'
+ | ^^^^^^
+ 4 | var hello2: boolean = 'Hello2'
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+
+ ERROR(TypeScript) Type 'string' is not assignable to type 'boolean'.
+ FILE /temp/multiple/src/main.ts:4:5
+
+ 2 |
+ 3 | var hello1: number = 'Hello1~'
+ > 4 | var hello2: boolean = 'Hello2'
+ | ^^^^^^
+ 5 |
+ 6 | const rootDom = document.querySelector('#root')!
+ 7 | rootDom.innerHTML = hello1 + text
+
+Found 2 errors. Watching for file changes."
+`;
diff --git a/playground/multiple/__tests__/test.spec.ts b/playground/multiple/__tests__/test.spec.ts
new file mode 100644
index 00000000..18b63f50
--- /dev/null
+++ b/playground/multiple/__tests__/test.spec.ts
@@ -0,0 +1,99 @@
+import stringify from 'fast-json-stable-stringify'
+
+import {
+ killServer,
+ preTest,
+ proxyConsoleInTest,
+ resetReceivedLog,
+ sleepForEdit,
+ sleepForServerReady,
+ stripedLog,
+ viteBuild,
+ viteServe,
+} from '../../../packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox'
+import {
+ editFile,
+ sleep,
+ testDir,
+ WORKER_CLEAN_TIMEOUT,
+} from '../../../packages/vite-plugin-checker/__tests__/e2e/testUtils'
+import { WS_CHECKER_ERROR_EVENT } from '../../../packages/vite-plugin-checker/src/client'
+import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv'
+import { serializers } from '../../../scripts/serializers'
+
+beforeAll(async () => {
+ await preTest()
+})
+
+expect.addSnapshotSerializer(serializers)
+
+afterAll(async () => {
+ await sleep(WORKER_CLEAN_TIMEOUT)
+})
+
+describe('multiple', () => {
+ beforeEach(async () => {
+ await copyCode()
+ })
+
+ describe('serve', () => {
+ afterEach(async () => {
+ await killServer()
+ })
+
+ it('get initial error and subsequent error', async () => {
+ let errors: any[] = []
+ await viteServe({
+ cwd: testDir,
+ wsSend: (_payload) => {
+ if (_payload.type === 'custom' && _payload.event === WS_CHECKER_ERROR_EVENT) {
+ errors = errors.concat(_payload.data.errors)
+ }
+ },
+ proxyConsole: () => proxyConsoleInTest(true),
+ })
+ await sleepForServerReady()
+ expect(stringify(errors.sort())).toMatchSnapshot()
+ expect(stripedLog).toMatchSnapshot()
+
+ console.log('-- edit error file --')
+ errors = []
+ resetReceivedLog()
+ editFile('src/main.ts', (code) => code.replace(`'Hello1'`, `'Hello1~'`))
+ await sleepForEdit()
+ expect(stringify(errors.sort())).toMatchSnapshot()
+ expect(stripedLog).toMatchSnapshot()
+
+ console.log('-- edit non error file --')
+ errors = []
+ resetReceivedLog()
+ editFile('src/text.ts', (code) => code.replace(`Multiple`, `multiple`))
+ await sleepForEdit()
+ expect(stringify(errors.sort())).toMatchSnapshot()
+ expect(stripedLog).toMatchSnapshot()
+ })
+ })
+
+ describe('build', () => {
+ const expectedMsg = [
+ '3:1 error Unexpected var, use let or const instead no-var',
+ '4:1 error Unexpected var, use let or const instead no-var',
+ `src/main.ts(3,5): error TS2322: Type 'string' is not assignable to type 'number'.`,
+ `src/main.ts(4,5): error TS2322: Type 'string' is not assignable to type 'boolean'.`,
+ ]
+
+ it('enableBuild: true', async () => {
+ await viteBuild({ expectedErrorMsg: expectedMsg, cwd: testDir })
+ })
+
+ it('enableBuild: false', async () => {
+ editFile('vite.config.ts', (code) =>
+ code.replace('eslint: {', 'enableBuild: false, eslint: {')
+ )
+ await viteBuild({
+ unexpectedErrorMsg: 'error',
+ cwd: testDir,
+ })
+ })
+ })
+})
diff --git a/playground/multiple/index.html b/playground/multiple/index.html
new file mode 100644
index 00000000..5f4067d6
--- /dev/null
+++ b/playground/multiple/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite App
+
+
+
+
+
+
diff --git a/playground/multiple/package.json b/playground/multiple/package.json
new file mode 100644
index 00000000..6c951a38
--- /dev/null
+++ b/playground/multiple/package.json
@@ -0,0 +1,23 @@
+{
+ "private": true,
+ "name": "vite-react-typescript-starter",
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "serve": "vite preview",
+ "lint": "eslint --ext .js,.ts ./src/**"
+ },
+ "dependencies": {
+ "react": "^17.0.0",
+ "react-dom": "^17.0.0"
+ },
+ "devDependencies": {
+ "@types/react": "^17.0.0",
+ "@types/react-dom": "^17.0.0",
+ "@vitejs/plugin-react-refresh": "^1.3.1",
+ "typescript": "^4.1.2",
+ "vite": "^2.7.13",
+ "vite-plugin-checker": "workspace:*"
+ }
+}
diff --git a/playground/multiple/src/main.ts b/playground/multiple/src/main.ts
new file mode 100644
index 00000000..0a8e5eb5
--- /dev/null
+++ b/playground/multiple/src/main.ts
@@ -0,0 +1,9 @@
+import { text } from './text'
+
+var hello1: number = 'Hello1'
+var hello2: boolean = 'Hello2'
+
+const rootDom = document.querySelector('#root')!
+rootDom.innerHTML = hello1 + text
+
+export {}
diff --git a/playground/multiple/src/text.ts b/playground/multiple/src/text.ts
new file mode 100644
index 00000000..050791ca
--- /dev/null
+++ b/playground/multiple/src/text.ts
@@ -0,0 +1 @@
+export const text = 'Multiple Checkers'
diff --git a/playground/multiple/tsconfig.json b/playground/multiple/tsconfig.json
new file mode 100644
index 00000000..36f84d9e
--- /dev/null
+++ b/playground/multiple/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ "types": ["vite/client"],
+ "allowJs": false,
+ "skipLibCheck": false,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "include": ["./src"]
+}
diff --git a/playground/multiple/vite.config.ts b/playground/multiple/vite.config.ts
new file mode 100644
index 00000000..5d951b21
--- /dev/null
+++ b/playground/multiple/vite.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vite'
+import reactRefresh from '@vitejs/plugin-react-refresh'
+import checker from 'vite-plugin-checker'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [
+ reactRefresh(),
+ checker({
+ typescript: true,
+ eslint: {
+ lintCommand: 'eslint ./src --ext .ts',
+ },
+ }),
+ ],
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e2ac3d85..ff63ebc8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -127,6 +127,27 @@ importers:
optionator: 0.9.1
vls: 0.7.4
+ playground/multiple:
+ specifiers:
+ '@types/react': ^17.0.0
+ '@types/react-dom': ^17.0.0
+ '@vitejs/plugin-react-refresh': ^1.3.1
+ react: ^17.0.0
+ react-dom: ^17.0.0
+ typescript: ^4.1.2
+ vite: ^2.7.13
+ vite-plugin-checker: workspace:*
+ dependencies:
+ react: 17.0.2
+ react-dom: 17.0.2_react@17.0.2
+ devDependencies:
+ '@types/react': 17.0.11
+ '@types/react-dom': 17.0.7
+ '@vitejs/plugin-react-refresh': 1.3.3
+ typescript: 4.3.2
+ vite: 2.7.13
+ vite-plugin-checker: link:../../packages/vite-plugin-checker
+
playground/react-ts:
specifiers:
'@types/react': ^17.0.0