Skip to content

Commit 963fb65

Browse files
committed
feat: support show multiple errors
1 parent 132cd4e commit 963fb65

File tree

4 files changed

+69
-66
lines changed

4 files changed

+69
-66
lines changed

packages/vite-plugin-checker/src/@runtime/main.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
import type { ErrorPayload } from 'vite'
22
import { ErrorOverlay, overlayId } from './overlay'
3-
43
let enableOverlay = true
54

5+
const WS_CHECKER_ERROR_TYPE = 'vite-plugin-checker-error'
66
export function inject() {
77
const socketProtocol = null || (location.protocol === 'https:' ? 'wss' : 'ws')
88
const socketHost = `${null || location.hostname}:${'3000'}`
99
const socket = new WebSocket(`${socketProtocol}://${socketHost}`, 'vite-hmr')
10+
1011
socket.addEventListener('message', async ({ data: dataStr }) => {
1112
const data = JSON.parse(dataStr)
12-
if (data.type === 'checker-error') {
13-
createErrorOverlay(data.err)
13+
if (data.type === WS_CHECKER_ERROR_TYPE) {
14+
createErrorOverlay([data.err])
1415
}
1516
})
1617
}
1718

18-
function createErrorOverlay(err: ErrorPayload['err']) {
19+
function createErrorOverlay(err: ErrorPayload['err'][]) {
1920
if (!enableOverlay) return
2021
clearErrorOverlay()
21-
console.log('error! 标记!')
2222
document.body.appendChild(new ErrorOverlay(err))
2323
}
2424

packages/vite-plugin-checker/src/@runtime/overlay.ts

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { ErrorPayload } from 'vite'
22

3-
const template = `
3+
const template = (errors: string[]) => `
44
<style>
55
:host {
66
position: fixed;
7-
z-index: 99999;
7+
z-index: 9999;
88
top: 0;
99
left: 0;
1010
width: 100%;
@@ -26,21 +26,21 @@ const template = `
2626
line-height: 1.5;
2727
width: 800px;
2828
color: #d8d8d8;
29-
margin: 30px auto;
30-
padding: 25px 40px;
29+
margin: 40px auto;
30+
padding: 8px 16px;
3131
position: relative;
32-
background: #181818;
32+
background: #0D1117;
3333
border-radius: 6px 6px 8px 8px;
3434
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
35-
overflow: hidden;
36-
border-top: 8px solid var(--red);
35+
overflow: scroll;
3736
direction: ltr;
3837
text-align: left;
38+
max-height: 80vh;
3939
}
4040
4141
pre {
4242
font-family: var(--monospace);
43-
font-size: 16px;
43+
font-size: 14px;
4444
margin-top: 0;
4545
margin-bottom: 1em;
4646
overflow-x: scroll;
@@ -51,6 +51,15 @@ pre::-webkit-scrollbar {
5151
display: none;
5252
}
5353
54+
.message-item {
55+
border-top: 1px dotted #666;
56+
padding: 12px 0 0 0;
57+
}
58+
59+
.message-item:first-child {
60+
border-top: none;
61+
}
62+
5463
.message {
5564
line-height: 1.3;
5665
font-weight: 600;
@@ -100,10 +109,7 @@ code {
100109
}
101110
</style>
102111
<div class="window">
103-
<pre class="message"><span class="plugin"></span><span class="message-body"></span></pre>
104-
<pre class="file"></pre>
105-
<pre class="frame"></pre>
106-
<pre class="stack"></pre>
112+
${errors.join('\n')}
107113
<div class="tip">
108114
Click outside or fix the code to dismiss.<br>
109115
You can also disable this overlay by setting
@@ -112,36 +118,50 @@ code {
112118
</div>
113119
`
114120

121+
const errorTemplate = `
122+
<div class="message-item">
123+
<pre class="message"><span class="plugin"></span><span class="message-body"></span></pre>
124+
<pre class="file"></pre>
125+
<pre class="frame"></pre>
126+
<pre class="stack"></pre>
127+
128+
</div>
129+
`
130+
115131
const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g
116132
const codeframeRE = /^(?:>?\s+\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm
117133

118134
export class ErrorOverlay extends HTMLElement {
119135
public root: ShadowRoot
120136

121-
public constructor(err: ErrorPayload['err']) {
137+
public constructor(errs: ErrorPayload['err'][]) {
122138
super()
123139
this.root = this.attachShadow({ mode: 'open' })
124-
this.root.innerHTML = template
140+
this.root.innerHTML = template(new Array(errs.length).fill(errorTemplate))
125141

126-
codeframeRE.lastIndex = 0
127-
const hasFrame = err.frame && codeframeRE.test(err.frame)
128-
const message = hasFrame ? err.message.replace(codeframeRE, '') : err.message
129-
if (err.plugin) {
130-
this.text('.plugin', `[plugin:${err.plugin}] `)
131-
}
132-
this.text('.message-body', message.trim())
142+
errs.forEach((err, index) => {
143+
codeframeRE.lastIndex = 0
144+
const hasFrame = err.frame && codeframeRE.test(err.frame)
145+
const message = hasFrame ? err.message.replace(codeframeRE, '') : err.message
146+
const selectorPrefix = `.message-item:nth-child(${index + 1}) `
133147

134-
const [file] = (err.loc?.file || err.id || 'unknown file').split(`?`)
135-
if (err.loc) {
136-
this.text('.file', `${file}:${err.loc.line}:${err.loc.column}`, true)
137-
} else if (err.id) {
138-
this.text('.file', file)
139-
}
148+
if (err.plugin) {
149+
this.text(selectorPrefix + '.plugin', `[plugin:${err.plugin}] `)
150+
}
151+
this.text(selectorPrefix + '.message-body', message.trim())
140152

141-
if (hasFrame) {
142-
this.text('.frame', err.frame!.trim())
143-
}
144-
this.text('.stack', err.stack, true)
153+
const [file] = (err.loc?.file || err.id || 'unknown file').split(`?`)
154+
if (err.loc) {
155+
this.text(selectorPrefix + '.file', `${file}:${err.loc.line}:${err.loc.column}`, true)
156+
} else if (err.id) {
157+
this.text(selectorPrefix + '.file', file)
158+
}
159+
160+
if (hasFrame) {
161+
this.text(selectorPrefix + '.frame', err.frame!.trim())
162+
}
163+
this.text(selectorPrefix + '.stack', err.stack, true)
164+
})
145165

146166
this.root.querySelector('.window')!.addEventListener('click', (e) => {
147167
e.stopPropagation()
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
const RUNTIME_PUBLIC_PATH = '/@vite-plugin-checker/runtime'
21
import fs from 'fs'
32

4-
const runtimeFilePath = require.resolve('../@runtime/main.js')
3+
const RUNTIME_PUBLIC_PATH = '/@vite-plugin-checker-runtime'
4+
const RUNTIME_FILE_PATH = require.resolve('../@runtime/main.js')
5+
const WS_CHECKER_ERROR_TYPE = 'vite-plugin-checker-error'
56

6-
const runtimeCode = `
7-
${fs.readFileSync(runtimeFilePath, 'utf-8')};
8-
`
7+
const runtimeCode = `${fs.readFileSync(RUNTIME_FILE_PATH, 'utf-8')};`
98

10-
export { runtimeCode, RUNTIME_PUBLIC_PATH }
9+
export { runtimeCode, RUNTIME_PUBLIC_PATH, WS_CHECKER_ERROR_TYPE }

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

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import { spawn } from 'child_process'
22
import pick from 'lodash.pick'
33
import npmRunPath from 'npm-run-path'
44
import { ConfigEnv, Plugin } from 'vite'
5-
import { Checker } from './Checker'
6-
import { runtimeCode, RUNTIME_PUBLIC_PATH } from './client/index'
75

6+
import { Checker } from './Checker'
7+
import { RUNTIME_PUBLIC_PATH, runtimeCode, WS_CHECKER_ERROR_TYPE } from './client/index'
88
import {
9-
OverlayErrorAction,
9+
ACTION_TYPES,
10+
BuildCheckBinStr,
1011
BuildInCheckerNames,
12+
OverlayErrorAction,
13+
PluginConfig,
1114
ServeAndBuildChecker,
12-
UserPluginConfig,
1315
SharedConfig,
14-
BuildCheckBinStr,
15-
PluginConfig,
16-
ACTION_TYPES,
16+
UserPluginConfig,
1717
} from './types'
1818

1919
export * from './types'
@@ -83,27 +83,11 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin {
8383
},
8484
transformIndexHtml() {
8585
return [
86-
// {
87-
// tag: 'script',
88-
// attrs: { type: 'module' },
89-
// children: `
90-
// const socketProtocol = null || (location.protocol === 'https:' ? 'wss' : 'ws');
91-
// const socketHost = \`\${null || location.hostname}:\${'3000'}\`;
92-
// const socket = new WebSocket(\`\${socketProtocol}://\${socketHost}\`, 'vite-hmr');
93-
// socket.addEventListener('message', async ({ data }) => {
94-
// console.log(data)
95-
// });
96-
// `,
97-
// },
9886
{
9987
tag: 'script',
10088
attrs: { type: 'module' },
10189
children: `import { inject } from "${RUNTIME_PUBLIC_PATH}"; inject();`,
10290
},
103-
// {
104-
// tag: 'script',
105-
// attrs: { type: 'module', src: `/vue-template/vite-plugin-checker/lib/client/index.js` },
106-
// },
10791
]
10892
},
10993
buildStart: () => {
@@ -142,7 +126,7 @@ export default function Plugin(userConfig: UserPluginConfig): Plugin {
142126
latestOverlayErrors[index] = action.payload
143127
if (action.payload) {
144128
// @ts-ignore
145-
action.payload.type = 'checker-error'
129+
action.payload.type = WS_CHECKER_ERROR_TYPE
146130
server.ws.send(action.payload)
147131
}
148132
} else if (action.type === ACTION_TYPES.console) {

0 commit comments

Comments
 (0)