@vistagenic/vista 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/dev-error-overlay-snippet.js +379 -153
- package/dist/dev-error.d.ts +14 -0
- package/dist/dev-error.js +1394 -336
- package/dist/server/engine.js +1 -7
- package/dist/server/rsc-engine.js +2 -12
- package/package.json +178 -178
package/dist/dev-error.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.VistaDevErrorBoundary = exports.DevErrorBoundary = void 0;
|
|
7
|
+
exports.fromCaughtError = fromCaughtError;
|
|
7
8
|
exports.renderErrorHTML = renderErrorHTML;
|
|
8
9
|
exports.ErrorOverlay = ErrorOverlay;
|
|
9
10
|
exports.VistaErrorOverlay = ErrorOverlay;
|
|
@@ -22,21 +23,21 @@ const OVERLAY_STYLES = `
|
|
|
22
23
|
* { box-sizing: border-box; }
|
|
23
24
|
html, body {
|
|
24
25
|
margin: 0;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
body {
|
|
31
|
-
line-height: 1.45;
|
|
26
|
+
height: 100%;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
background: #050505;
|
|
29
|
+
color: #ededed;
|
|
30
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
32
31
|
}
|
|
32
|
+
body { line-height: 1.5; }
|
|
33
33
|
.vista-error-page-root {
|
|
34
34
|
min-height: 100vh;
|
|
35
|
+
height: 100vh;
|
|
35
36
|
position: relative;
|
|
36
37
|
display: flex;
|
|
37
38
|
align-items: center;
|
|
38
39
|
justify-content: center;
|
|
39
|
-
padding:
|
|
40
|
+
padding: 20px;
|
|
40
41
|
overflow: hidden;
|
|
41
42
|
}
|
|
42
43
|
.vista-error-page-root[data-embedded='true'] {
|
|
@@ -47,203 +48,511 @@ body {
|
|
|
47
48
|
.vista-error-backdrop {
|
|
48
49
|
position: absolute;
|
|
49
50
|
inset: 0;
|
|
50
|
-
background:
|
|
51
|
-
backdrop-filter: blur(5px);
|
|
51
|
+
background: rgba(0, 0, 0, 0.72);
|
|
52
52
|
}
|
|
53
53
|
.vista-error-panel {
|
|
54
54
|
position: relative;
|
|
55
|
-
width: min(
|
|
56
|
-
|
|
55
|
+
width: min(1180px, calc(100vw - 32px));
|
|
56
|
+
height: min(820px, calc(100vh - 32px));
|
|
57
57
|
display: flex;
|
|
58
58
|
flex-direction: column;
|
|
59
|
-
border-radius:
|
|
59
|
+
border-radius: 8px;
|
|
60
60
|
overflow: hidden;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
box-shadow: 0
|
|
64
|
-
animation: vista-overlay-in
|
|
61
|
+
background: #1e1e1e;
|
|
62
|
+
border: 1px solid #2b2b2b;
|
|
63
|
+
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.62);
|
|
64
|
+
animation: vista-overlay-in 160ms ease;
|
|
65
65
|
}
|
|
66
|
-
.vista-
|
|
66
|
+
.vista-ide-workbench {
|
|
67
67
|
display: flex;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
gap: 14px;
|
|
71
|
-
padding: 15px 17px;
|
|
72
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
|
|
73
|
-
background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0));
|
|
68
|
+
flex: 1;
|
|
69
|
+
min-height: 0;
|
|
74
70
|
}
|
|
75
|
-
.vista-
|
|
76
|
-
|
|
71
|
+
.vista-ide-activity {
|
|
72
|
+
width: 48px;
|
|
73
|
+
flex-shrink: 0;
|
|
77
74
|
display: flex;
|
|
78
75
|
flex-direction: column;
|
|
79
|
-
gap: 8px;
|
|
80
|
-
}
|
|
81
|
-
.vista-error-top-row {
|
|
82
|
-
display: flex;
|
|
83
76
|
align-items: center;
|
|
84
|
-
|
|
77
|
+
padding-top: 8px;
|
|
78
|
+
background: #181818;
|
|
79
|
+
border-right: 1px solid #2b2b2b;
|
|
85
80
|
}
|
|
86
|
-
.vista-
|
|
81
|
+
.vista-ide-activity-item {
|
|
82
|
+
width: 48px;
|
|
83
|
+
height: 40px;
|
|
87
84
|
display: inline-flex;
|
|
88
85
|
align-items: center;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
padding: 0 10px;
|
|
92
|
-
border-radius: 999px;
|
|
93
|
-
border: 1px solid rgba(248, 113, 113, 0.48);
|
|
94
|
-
background: rgba(248, 113, 113, 0.14);
|
|
95
|
-
color: #fecaca;
|
|
96
|
-
font-size: 11px;
|
|
97
|
-
font-weight: 700;
|
|
98
|
-
letter-spacing: 0.07em;
|
|
99
|
-
text-transform: uppercase;
|
|
100
|
-
white-space: nowrap;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
color: #858585;
|
|
101
88
|
}
|
|
102
|
-
.vista-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
border-radius: 999px;
|
|
106
|
-
background: #f87171;
|
|
107
|
-
box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.24);
|
|
89
|
+
.vista-ide-activity-item.is-active {
|
|
90
|
+
color: #ffffff;
|
|
91
|
+
box-shadow: inset 2px 0 0 #0078d4;
|
|
108
92
|
}
|
|
109
|
-
.vista-
|
|
93
|
+
.vista-ide-activity-item svg {
|
|
94
|
+
width: 22px;
|
|
95
|
+
height: 22px;
|
|
96
|
+
display: block;
|
|
97
|
+
}
|
|
98
|
+
.vista-ide-main {
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-direction: column;
|
|
101
|
+
flex: 1;
|
|
102
|
+
min-width: 0;
|
|
103
|
+
min-height: 0;
|
|
104
|
+
}
|
|
105
|
+
.vista-ide-titlebar {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: space-between;
|
|
109
|
+
gap: 12px;
|
|
110
|
+
height: 38px;
|
|
111
|
+
padding: 0 10px;
|
|
112
|
+
background: #181818;
|
|
113
|
+
border-bottom: 1px solid #2b2b2b;
|
|
114
|
+
flex-shrink: 0;
|
|
115
|
+
}
|
|
116
|
+
.vista-ide-traffic {
|
|
110
117
|
display: inline-flex;
|
|
111
118
|
align-items: center;
|
|
112
119
|
gap: 6px;
|
|
113
|
-
|
|
120
|
+
width: 54px;
|
|
121
|
+
}
|
|
122
|
+
.vista-ide-traffic span {
|
|
123
|
+
width: 10px;
|
|
124
|
+
height: 10px;
|
|
114
125
|
border-radius: 999px;
|
|
115
|
-
border: 1px solid rgba(255, 255, 255, 0.18);
|
|
116
|
-
background: rgba(255, 255, 255, 0.04);
|
|
117
126
|
}
|
|
118
|
-
.vista-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
.vista-ide-traffic .is-close { background: #ff5f57; }
|
|
128
|
+
.vista-ide-traffic .is-min { background: #febc2e; }
|
|
129
|
+
.vista-ide-traffic .is-max { background: #28c840; }
|
|
130
|
+
.vista-ide-title {
|
|
131
|
+
min-width: 0;
|
|
132
|
+
flex: 1;
|
|
133
|
+
text-align: center;
|
|
134
|
+
color: #c6c6c6;
|
|
135
|
+
font-size: 12px;
|
|
136
|
+
font-weight: 500;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
text-overflow: ellipsis;
|
|
139
|
+
white-space: nowrap;
|
|
140
|
+
}
|
|
141
|
+
.vista-error-toolbar {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
flex-shrink: 0;
|
|
146
|
+
}
|
|
147
|
+
.vista-ide-tabbar {
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: stretch;
|
|
150
|
+
justify-content: space-between;
|
|
151
|
+
height: 35px;
|
|
152
|
+
background: #181818;
|
|
153
|
+
border-bottom: 1px solid #2b2b2b;
|
|
154
|
+
flex-shrink: 0;
|
|
155
|
+
}
|
|
156
|
+
.vista-ide-tabs {
|
|
157
|
+
display: flex;
|
|
158
|
+
min-width: 0;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
scrollbar-width: none;
|
|
161
|
+
}
|
|
162
|
+
.vista-ide-tabs::-webkit-scrollbar { display: none; }
|
|
163
|
+
.vista-ide-tab {
|
|
121
164
|
display: inline-flex;
|
|
122
165
|
align-items: center;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
166
|
+
gap: 8px;
|
|
167
|
+
height: 35px;
|
|
168
|
+
padding: 0 14px;
|
|
169
|
+
border: 0;
|
|
170
|
+
border-right: 1px solid #2b2b2b;
|
|
171
|
+
background: #1e1e1e;
|
|
172
|
+
color: #cccccc;
|
|
173
|
+
font-size: 12px;
|
|
130
174
|
cursor: pointer;
|
|
175
|
+
box-shadow: inset 0 -1px 0 #0078d4;
|
|
131
176
|
}
|
|
132
|
-
.vista-
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
.vista-ide-tab:hover { color: #fff; }
|
|
178
|
+
.vista-ide-tab.is-inactive {
|
|
179
|
+
background: #181818;
|
|
180
|
+
color: #8b8b8b;
|
|
181
|
+
box-shadow: none;
|
|
135
182
|
}
|
|
136
|
-
.vista-
|
|
137
|
-
|
|
183
|
+
.vista-ide-tab-icon {
|
|
184
|
+
width: 14px;
|
|
185
|
+
height: 14px;
|
|
186
|
+
flex-shrink: 0;
|
|
138
187
|
}
|
|
139
|
-
.vista-
|
|
140
|
-
|
|
141
|
-
|
|
188
|
+
.vista-ide-crumbs {
|
|
189
|
+
display: flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
gap: 6px;
|
|
192
|
+
height: 24px;
|
|
193
|
+
padding: 0 12px;
|
|
194
|
+
background: #1e1e1e;
|
|
195
|
+
border-bottom: 1px solid #2b2b2b;
|
|
196
|
+
color: #8b8b8b;
|
|
142
197
|
font-size: 11px;
|
|
143
|
-
font-
|
|
144
|
-
|
|
145
|
-
|
|
198
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
199
|
+
white-space: nowrap;
|
|
200
|
+
overflow: hidden;
|
|
201
|
+
text-overflow: ellipsis;
|
|
146
202
|
}
|
|
147
|
-
.vista-error-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
203
|
+
.vista-error-code {
|
|
204
|
+
display: flex;
|
|
205
|
+
flex-direction: column;
|
|
206
|
+
flex: 1;
|
|
207
|
+
min-height: 0;
|
|
208
|
+
background: #1e1e1e;
|
|
209
|
+
overflow: hidden;
|
|
210
|
+
}
|
|
211
|
+
.vista-error-editor-host {
|
|
212
|
+
flex: 1;
|
|
213
|
+
min-height: 0;
|
|
214
|
+
overflow: auto;
|
|
155
215
|
}
|
|
156
|
-
.vista-error-
|
|
216
|
+
.vista-error-editor {
|
|
157
217
|
margin: 0;
|
|
218
|
+
min-height: 100%;
|
|
219
|
+
padding: 8px 0 12px;
|
|
220
|
+
overflow: visible;
|
|
221
|
+
font-size: 13px;
|
|
222
|
+
line-height: 20px;
|
|
223
|
+
font-family: ui-monospace, SFMono-Regular, "Cascadia Code", Menlo, Consolas, monospace;
|
|
224
|
+
background: #1e1e1e;
|
|
225
|
+
}
|
|
226
|
+
.vista-error-editor-line {
|
|
227
|
+
display: grid;
|
|
228
|
+
grid-template-columns: 56px minmax(0, 1fr);
|
|
229
|
+
min-height: 20px;
|
|
230
|
+
}
|
|
231
|
+
.vista-error-editor-line.is-error {
|
|
232
|
+
background: rgba(248, 81, 73, 0.12);
|
|
233
|
+
}
|
|
234
|
+
.vista-error-editor-line.is-server {
|
|
235
|
+
background: rgba(248, 81, 73, 0.1);
|
|
236
|
+
}
|
|
237
|
+
.vista-error-editor-line.is-client {
|
|
238
|
+
background: rgba(63, 185, 80, 0.1);
|
|
239
|
+
}
|
|
240
|
+
.vista-ide-source-badge {
|
|
241
|
+
padding: 0 7px;
|
|
242
|
+
border-radius: 999px;
|
|
243
|
+
font-size: 10px;
|
|
244
|
+
font-weight: 600;
|
|
245
|
+
letter-spacing: 0.04em;
|
|
246
|
+
text-transform: uppercase;
|
|
247
|
+
background: rgba(255, 255, 255, 0.12);
|
|
248
|
+
}
|
|
249
|
+
.vista-ide-source-badge.is-server { background: #1f6feb; }
|
|
250
|
+
.vista-ide-source-badge.is-client { background: #238636; }
|
|
251
|
+
.vista-ide-source-badge.is-hydration { background: #9e6a03; }
|
|
252
|
+
.vista-error-hint {
|
|
253
|
+
margin: 8px 0 0;
|
|
254
|
+
color: #8b949e;
|
|
158
255
|
font-size: 12px;
|
|
159
|
-
|
|
256
|
+
line-height: 1.5;
|
|
160
257
|
}
|
|
161
|
-
.vista-error-
|
|
258
|
+
.vista-error-hint[hidden] { display: none; }
|
|
259
|
+
.vista-error-problem-icon.is-hydration { background: #d29922; }
|
|
260
|
+
.vista-error-problem-icon.is-server { background: #58a6ff; }
|
|
261
|
+
.vista-error-kind.is-hydration { color: #d29922; }
|
|
262
|
+
.vista-error-kind.is-server { color: #58a6ff; }
|
|
263
|
+
.vista-error-gutter {
|
|
264
|
+
padding: 0 12px 0 0;
|
|
265
|
+
border-right: 1px solid #2b2b2b;
|
|
266
|
+
color: #6e7681;
|
|
267
|
+
text-align: right;
|
|
268
|
+
user-select: none;
|
|
269
|
+
font-variant-numeric: tabular-nums;
|
|
270
|
+
}
|
|
271
|
+
.vista-error-editor-line.is-error .vista-error-gutter { color: #f85149; font-weight: 600; }
|
|
272
|
+
.vista-error-source {
|
|
273
|
+
position: relative;
|
|
274
|
+
padding: 0 16px 0 12px;
|
|
275
|
+
color: #d4d4d4;
|
|
276
|
+
white-space: pre;
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
}
|
|
279
|
+
.vista-error-squiggle {
|
|
280
|
+
position: absolute;
|
|
281
|
+
left: 12px;
|
|
282
|
+
bottom: 0;
|
|
283
|
+
height: 4px;
|
|
284
|
+
width: 3.2ch;
|
|
285
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='4' viewBox='0 0 6 4'%3E%3Cpath d='M0 3 Q1.5 0 3 3 T6 3' fill='none' stroke='%23f85149' stroke-width='1.4'/%3E%3C/svg%3E");
|
|
286
|
+
background-repeat: repeat-x;
|
|
287
|
+
background-size: 6px 4px;
|
|
288
|
+
pointer-events: none;
|
|
289
|
+
}
|
|
290
|
+
.vista-tok-kw { color: #c586c0; }
|
|
291
|
+
.vista-tok-str { color: #ce9178; }
|
|
292
|
+
.vista-tok-cmt { color: #6a9955; font-style: italic; }
|
|
293
|
+
.vista-tok-tag { color: #4ec9b0; }
|
|
294
|
+
.vista-tok-num { color: #b5cea8; }
|
|
295
|
+
.vista-ide-statusbar {
|
|
162
296
|
display: flex;
|
|
163
297
|
align-items: center;
|
|
164
|
-
|
|
298
|
+
justify-content: space-between;
|
|
299
|
+
gap: 12px;
|
|
300
|
+
height: 22px;
|
|
301
|
+
padding: 0 10px;
|
|
302
|
+
background: #007acc;
|
|
303
|
+
color: #ffffff;
|
|
304
|
+
font-size: 12px;
|
|
305
|
+
flex-shrink: 0;
|
|
165
306
|
}
|
|
166
|
-
.vista-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
border: 1px solid
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
307
|
+
.vista-ide-statusbar span { white-space: nowrap; }
|
|
308
|
+
.vista-ide-panel {
|
|
309
|
+
display: flex;
|
|
310
|
+
flex-direction: column;
|
|
311
|
+
background: #181818;
|
|
312
|
+
border-top: 1px solid #2b2b2b;
|
|
313
|
+
overflow: hidden;
|
|
314
|
+
flex: 0 0 auto;
|
|
315
|
+
max-height: 38%;
|
|
316
|
+
min-height: 148px;
|
|
317
|
+
}
|
|
318
|
+
.vista-ide-panel-tabs {
|
|
319
|
+
display: flex;
|
|
175
320
|
align-items: center;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
321
|
+
gap: 16px;
|
|
322
|
+
height: 32px;
|
|
323
|
+
padding: 0 8px 0 12px;
|
|
324
|
+
border-bottom: 1px solid #2b2b2b;
|
|
325
|
+
color: #bbbbbb;
|
|
326
|
+
font-size: 11px;
|
|
327
|
+
font-weight: 600;
|
|
328
|
+
letter-spacing: 0.06em;
|
|
329
|
+
flex-shrink: 0;
|
|
179
330
|
}
|
|
180
|
-
.vista-
|
|
181
|
-
|
|
182
|
-
|
|
331
|
+
.vista-ide-panel-tabs .is-active {
|
|
332
|
+
color: #ffffff;
|
|
333
|
+
box-shadow: inset 0 -1px 0 #ffffff;
|
|
334
|
+
padding-bottom: 8px;
|
|
183
335
|
}
|
|
184
|
-
.vista-
|
|
185
|
-
|
|
186
|
-
height: 14px;
|
|
187
|
-
display: block;
|
|
336
|
+
.vista-ide-panel-toggle {
|
|
337
|
+
margin-left: auto;
|
|
188
338
|
}
|
|
189
|
-
.vista-
|
|
190
|
-
.vista-
|
|
191
|
-
.vista-
|
|
192
|
-
|
|
193
|
-
|
|
339
|
+
.vista-ide-panel-toggle[hidden] { display: none; }
|
|
340
|
+
.vista-ide-panel-toggle .vista-ide-icon-restore { display: none; }
|
|
341
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-tabbar,
|
|
342
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-crumbs,
|
|
343
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-error-code,
|
|
344
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-statusbar {
|
|
345
|
+
display: none;
|
|
346
|
+
}
|
|
347
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-panel {
|
|
348
|
+
flex: 1;
|
|
349
|
+
max-height: none;
|
|
350
|
+
min-height: 0;
|
|
351
|
+
border-top: 0;
|
|
194
352
|
}
|
|
353
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-icon-expand { display: none; }
|
|
354
|
+
.vista-ide-main[data-panel-expanded='true'] .vista-ide-icon-restore { display: block; }
|
|
355
|
+
.vista-ide-main[data-terminal='true'] .vista-ide-tabbar,
|
|
356
|
+
.vista-ide-main[data-terminal='true'] .vista-ide-crumbs,
|
|
357
|
+
.vista-ide-main[data-terminal='true'] .vista-error-code,
|
|
358
|
+
.vista-ide-main[data-terminal='true'] .vista-ide-statusbar {
|
|
359
|
+
display: none;
|
|
360
|
+
}
|
|
361
|
+
.vista-ide-main[data-terminal='true'] .vista-ide-panel {
|
|
362
|
+
flex: 1;
|
|
363
|
+
max-height: none;
|
|
364
|
+
min-height: 0;
|
|
365
|
+
border-top: 0;
|
|
366
|
+
}
|
|
367
|
+
.vista-ide-main[data-terminal='true'] .vista-ide-panel-toggle { display: none; }
|
|
195
368
|
.vista-error-body {
|
|
196
|
-
|
|
369
|
+
flex: 1;
|
|
370
|
+
min-height: 0;
|
|
197
371
|
overflow: auto;
|
|
198
|
-
|
|
199
|
-
grid-template-columns: 1fr;
|
|
200
|
-
gap: 11px;
|
|
372
|
+
padding: 10px 14px 14px;
|
|
201
373
|
}
|
|
202
|
-
.vista-error-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
374
|
+
.vista-error-editor-host,
|
|
375
|
+
.vista-error-body,
|
|
376
|
+
.vista-ide-panel {
|
|
377
|
+
scrollbar-width: thin;
|
|
378
|
+
scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
|
|
207
379
|
}
|
|
208
|
-
.vista-error-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
380
|
+
.vista-error-editor-host::-webkit-scrollbar,
|
|
381
|
+
.vista-error-body::-webkit-scrollbar,
|
|
382
|
+
.vista-ide-panel::-webkit-scrollbar {
|
|
383
|
+
width: 6px;
|
|
384
|
+
height: 6px;
|
|
385
|
+
}
|
|
386
|
+
.vista-error-editor-host::-webkit-scrollbar-track,
|
|
387
|
+
.vista-error-body::-webkit-scrollbar-track,
|
|
388
|
+
.vista-ide-panel::-webkit-scrollbar-track,
|
|
389
|
+
.vista-error-editor-host::-webkit-scrollbar-corner,
|
|
390
|
+
.vista-error-body::-webkit-scrollbar-corner,
|
|
391
|
+
.vista-ide-panel::-webkit-scrollbar-corner {
|
|
392
|
+
background: transparent;
|
|
393
|
+
}
|
|
394
|
+
.vista-error-editor-host::-webkit-scrollbar-thumb,
|
|
395
|
+
.vista-error-body::-webkit-scrollbar-thumb,
|
|
396
|
+
.vista-ide-panel::-webkit-scrollbar-thumb {
|
|
397
|
+
background-color: rgba(255, 255, 255, 0.16);
|
|
398
|
+
border-radius: 999px;
|
|
399
|
+
}
|
|
400
|
+
.vista-error-editor-host::-webkit-scrollbar-thumb:hover,
|
|
401
|
+
.vista-error-body::-webkit-scrollbar-thumb:hover,
|
|
402
|
+
.vista-ide-panel::-webkit-scrollbar-thumb:hover {
|
|
403
|
+
background-color: rgba(255, 255, 255, 0.34);
|
|
215
404
|
}
|
|
216
|
-
.vista-error-
|
|
405
|
+
.vista-error-kind {
|
|
217
406
|
margin: 0;
|
|
407
|
+
color: #f85149;
|
|
408
|
+
font-size: 12px;
|
|
409
|
+
font-weight: 600;
|
|
410
|
+
}
|
|
411
|
+
.vista-error-headline {
|
|
412
|
+
margin: 6px 0 0;
|
|
413
|
+
color: #e6edf3;
|
|
414
|
+
font-size: 13px;
|
|
415
|
+
font-weight: 500;
|
|
416
|
+
line-height: 1.5;
|
|
417
|
+
word-break: break-word;
|
|
418
|
+
}
|
|
419
|
+
.vista-error-detail {
|
|
420
|
+
margin: 6px 0 0;
|
|
421
|
+
color: #8b949e;
|
|
422
|
+
font-size: 12px;
|
|
423
|
+
line-height: 1.5;
|
|
218
424
|
white-space: pre-wrap;
|
|
219
425
|
word-break: break-word;
|
|
220
|
-
font-size: 12.5px;
|
|
221
|
-
line-height: 1.58;
|
|
222
|
-
color: #f1f5f9;
|
|
223
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
224
426
|
}
|
|
225
|
-
.vista-error-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
.vista-error-
|
|
427
|
+
.vista-error-problem {
|
|
428
|
+
display: flex;
|
|
429
|
+
gap: 8px;
|
|
430
|
+
align-items: flex-start;
|
|
431
|
+
padding: 8px 2px 4px;
|
|
432
|
+
}
|
|
433
|
+
.vista-error-problem-icon {
|
|
434
|
+
width: 14px;
|
|
435
|
+
height: 14px;
|
|
436
|
+
margin-top: 2px;
|
|
437
|
+
border-radius: 999px;
|
|
438
|
+
background: #f85149;
|
|
439
|
+
flex-shrink: 0;
|
|
440
|
+
}
|
|
441
|
+
.vista-error-detail[hidden],
|
|
442
|
+
.vista-error-code[hidden],
|
|
443
|
+
.vista-error-stack[hidden] { display: none; }
|
|
444
|
+
.vista-error-stack { margin-top: 8px; }
|
|
445
|
+
.vista-error-stack-title {
|
|
446
|
+
margin: 0 0 6px;
|
|
447
|
+
color: #bbbbbb;
|
|
448
|
+
font-size: 11px;
|
|
449
|
+
font-weight: 600;
|
|
450
|
+
letter-spacing: 0.06em;
|
|
451
|
+
}
|
|
452
|
+
.vista-error-frames {
|
|
453
|
+
display: flex;
|
|
454
|
+
flex-direction: column;
|
|
455
|
+
}
|
|
456
|
+
.vista-error-frame {
|
|
457
|
+
display: flex;
|
|
458
|
+
flex-direction: column;
|
|
459
|
+
align-items: flex-start;
|
|
460
|
+
gap: 1px;
|
|
232
461
|
width: 100%;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
border:
|
|
237
|
-
background:
|
|
238
|
-
color:
|
|
239
|
-
|
|
240
|
-
|
|
462
|
+
margin: 0;
|
|
463
|
+
padding: 6px 8px;
|
|
464
|
+
border: 0;
|
|
465
|
+
border-radius: 0;
|
|
466
|
+
background: transparent;
|
|
467
|
+
color: inherit;
|
|
468
|
+
text-align: left;
|
|
469
|
+
cursor: pointer;
|
|
470
|
+
}
|
|
471
|
+
.vista-error-frame:hover { background: #2a2d2e; }
|
|
472
|
+
.vista-error-frame-name {
|
|
241
473
|
font-size: 12px;
|
|
474
|
+
font-weight: 500;
|
|
475
|
+
color: #e6edf3;
|
|
242
476
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
477
|
+
}
|
|
478
|
+
.vista-error-frame-loc {
|
|
479
|
+
font-size: 11px;
|
|
480
|
+
color: #8b949e;
|
|
481
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
482
|
+
}
|
|
483
|
+
.vista-error-pagination {
|
|
484
|
+
display: inline-flex;
|
|
485
|
+
align-items: center;
|
|
486
|
+
gap: 2px;
|
|
487
|
+
}
|
|
488
|
+
.vista-error-pagination[hidden] { display: none; }
|
|
489
|
+
.vista-error-page-btn {
|
|
490
|
+
width: 28px;
|
|
491
|
+
height: 28px;
|
|
492
|
+
display: inline-flex;
|
|
493
|
+
align-items: center;
|
|
494
|
+
justify-content: center;
|
|
495
|
+
border: 0;
|
|
496
|
+
border-radius: 6px;
|
|
497
|
+
background: transparent;
|
|
498
|
+
color: #a1a1a1;
|
|
499
|
+
font-size: 16px;
|
|
500
|
+
line-height: 1;
|
|
501
|
+
cursor: pointer;
|
|
502
|
+
}
|
|
503
|
+
.vista-error-page-btn:disabled { opacity: 0.28; cursor: default; }
|
|
504
|
+
.vista-error-page-btn:not(:disabled):hover { background: #2a2a2a; color: #ededed; }
|
|
505
|
+
.vista-error-page-count {
|
|
506
|
+
min-width: 36px;
|
|
507
|
+
padding: 0 4px;
|
|
508
|
+
text-align: center;
|
|
509
|
+
font-size: 13px;
|
|
510
|
+
font-weight: 500;
|
|
511
|
+
color: #a1a1a1;
|
|
512
|
+
font-variant-numeric: tabular-nums;
|
|
513
|
+
}
|
|
514
|
+
.vista-error-brand {
|
|
515
|
+
display: inline-flex;
|
|
516
|
+
align-items: center;
|
|
517
|
+
gap: 8px;
|
|
518
|
+
color: #a1a1a1;
|
|
519
|
+
font-size: 13px;
|
|
520
|
+
font-weight: 500;
|
|
521
|
+
white-space: nowrap;
|
|
522
|
+
}
|
|
523
|
+
.vista-error-brand-dot {
|
|
524
|
+
width: 8px;
|
|
525
|
+
height: 8px;
|
|
526
|
+
border-radius: 999px;
|
|
527
|
+
background: #22c55e;
|
|
528
|
+
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.16);
|
|
529
|
+
}
|
|
530
|
+
.vista-error-toolbar-actions {
|
|
531
|
+
display: inline-flex;
|
|
532
|
+
align-items: center;
|
|
533
|
+
gap: 2px;
|
|
534
|
+
}
|
|
535
|
+
.vista-error-icon-btn {
|
|
536
|
+
width: 28px;
|
|
537
|
+
height: 28px;
|
|
538
|
+
padding: 0;
|
|
539
|
+
border: 0;
|
|
540
|
+
border-radius: 6px;
|
|
541
|
+
background: transparent;
|
|
542
|
+
color: #a1a1a1;
|
|
543
|
+
display: inline-flex;
|
|
544
|
+
align-items: center;
|
|
545
|
+
justify-content: center;
|
|
243
546
|
cursor: pointer;
|
|
244
547
|
}
|
|
245
|
-
.vista-error-
|
|
246
|
-
|
|
548
|
+
.vista-error-icon-btn:hover { background: #2a2a2a; color: #ededed; }
|
|
549
|
+
.vista-ide-panel-tabs .vista-error-icon-btn:hover { background: #2a2a2a; }
|
|
550
|
+
.vista-error-icon-btn svg { width: 14px; height: 14px; display: block; }
|
|
551
|
+
.vista-error-icon-btn:focus-visible,
|
|
552
|
+
.vista-error-page-btn:focus-visible,
|
|
553
|
+
.vista-ide-tab:focus-visible {
|
|
554
|
+
outline: 2px solid #ededed;
|
|
555
|
+
outline-offset: 1px;
|
|
247
556
|
}
|
|
248
557
|
.vista-error-page-root[data-minimized='true'] .vista-error-backdrop,
|
|
249
558
|
.vista-error-page-root[data-minimized='true'] .vista-error-panel {
|
|
@@ -251,49 +560,38 @@ body {
|
|
|
251
560
|
}
|
|
252
561
|
.vista-error-minimized-trigger {
|
|
253
562
|
position: fixed;
|
|
254
|
-
left:
|
|
255
|
-
bottom:
|
|
563
|
+
left: 20px;
|
|
564
|
+
bottom: 20px;
|
|
256
565
|
z-index: 2147483647;
|
|
257
|
-
height:
|
|
566
|
+
height: 36px;
|
|
258
567
|
border-radius: 999px;
|
|
259
|
-
border: 1px solid
|
|
260
|
-
background:
|
|
261
|
-
color: #
|
|
262
|
-
box-shadow: 0 10px
|
|
568
|
+
border: 1px solid #262626;
|
|
569
|
+
background: #0a0a0a;
|
|
570
|
+
color: #ededed;
|
|
571
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
|
|
263
572
|
display: inline-flex;
|
|
264
573
|
align-items: center;
|
|
265
|
-
gap:
|
|
266
|
-
padding: 0 10px;
|
|
574
|
+
gap: 8px;
|
|
575
|
+
padding: 0 12px 0 10px;
|
|
267
576
|
cursor: pointer;
|
|
268
577
|
}
|
|
269
|
-
.vista-error-minimized-trigger[hidden] {
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
.vista-error-minimized-logo {
|
|
273
|
-
width: 14px;
|
|
274
|
-
height: 14px;
|
|
275
|
-
display: block;
|
|
276
|
-
}
|
|
277
|
-
.vista-error-minimized-close {
|
|
278
|
-
font-size: 12px;
|
|
279
|
-
line-height: 1;
|
|
280
|
-
color: #fca5a5;
|
|
281
|
-
}
|
|
578
|
+
.vista-error-minimized-trigger[hidden] { display: none; }
|
|
579
|
+
.vista-error-minimized-logo { width: 13px; height: 13px; display: block; }
|
|
580
|
+
.vista-error-minimized-close { font-size: 14px; line-height: 1; color: #a1a1a1; }
|
|
282
581
|
.vista-error-minimized-count {
|
|
283
|
-
font-size:
|
|
284
|
-
font-weight:
|
|
582
|
+
font-size: 12px;
|
|
583
|
+
font-weight: 600;
|
|
285
584
|
font-variant-numeric: tabular-nums;
|
|
585
|
+
color: #ff6369;
|
|
286
586
|
}
|
|
287
587
|
@keyframes vista-overlay-in {
|
|
288
|
-
from { opacity: 0; transform: translateY(
|
|
588
|
+
from { opacity: 0; transform: translateY(8px) scale(0.98); }
|
|
289
589
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
290
590
|
}
|
|
291
|
-
@media (max-width:
|
|
292
|
-
.vista-error-page-root { padding:
|
|
293
|
-
.vista-error-
|
|
294
|
-
.vista-error-
|
|
295
|
-
.vista-error-title { font-size: 16px; }
|
|
296
|
-
.vista-error-minimized-trigger { left: 16px; bottom: 14px; }
|
|
591
|
+
@media (max-width: 720px) {
|
|
592
|
+
.vista-error-page-root { padding: 16px 10px; }
|
|
593
|
+
.vista-error-headline { font-size: 14px; }
|
|
594
|
+
.vista-error-minimized-trigger { left: 12px; bottom: 12px; }
|
|
297
595
|
}
|
|
298
596
|
`;
|
|
299
597
|
const OVERLAY_SCRIPT = `
|
|
@@ -346,16 +644,20 @@ function escapeForInlineScript(text) {
|
|
|
346
644
|
}
|
|
347
645
|
function colorizeLineHtml(line) {
|
|
348
646
|
let escaped = escapeHtml(line);
|
|
647
|
+
const isActive = /^\s*>/.test(line);
|
|
349
648
|
if (/^\s*\^+/.test(line)) {
|
|
350
649
|
return `<span class="vista-error-tok-caret">${escaped}</span>`;
|
|
351
650
|
}
|
|
352
651
|
if (/^\s*at\s+/.test(line)) {
|
|
353
652
|
return `<span class="vista-error-tok-stack">${escaped}</span>`;
|
|
354
653
|
}
|
|
355
|
-
const numbered = escaped.match(/^(\s*\d+)(\s*\|)(.*)$/);
|
|
654
|
+
const numbered = escaped.match(/^(\s*>?\s*\d+)(\s*\|)(.*)$/);
|
|
356
655
|
if (numbered) {
|
|
357
656
|
escaped = `<span class="vista-error-tok-line">${numbered[1]}</span>${numbered[2]}${numbered[3]}`;
|
|
358
657
|
}
|
|
658
|
+
if (isActive) {
|
|
659
|
+
escaped = `<span class="vista-error-tok-active">${escaped}</span>`;
|
|
660
|
+
}
|
|
359
661
|
escaped = escaped.replace(/((?:[A-Za-z]:)?[\\/\w.@%:-]+\.(?:tsx?|jsx?|mjs|cjs|css|json|mdx?)(?::\d+(?::\d+)?)?)/g, '<span class="vista-error-tok-path">$1</span>');
|
|
360
662
|
escaped = escaped.replace(/("[^&]+"|'[^&]+'|`[^`]+`)/g, '<span class="vista-error-tok-string">$1</span>');
|
|
361
663
|
escaped = escaped.replace(/(TypeError:|ReferenceError:|SyntaxError:|Error:|Cannot find module|Module not found|Build Error|Runtime Error|Hydration Error)/g, '<span class="vista-error-tok-error">$1</span>');
|
|
@@ -367,6 +669,333 @@ function colorizeBlockHtml(value) {
|
|
|
367
669
|
.map((line) => colorizeLineHtml(line))
|
|
368
670
|
.join('\n');
|
|
369
671
|
}
|
|
672
|
+
const SOURCE_KEYWORDS = /^(import|from|function|return|const|let|var|export|default|class|extends|if|else|async|await|new|type|interface|true|false|null|undefined|typeof|void|as|of|in|for|while|switch|case|break|continue|try|catch|finally|this)\b/;
|
|
673
|
+
function highlightSource(text) {
|
|
674
|
+
let html = '';
|
|
675
|
+
let i = 0;
|
|
676
|
+
while (i < text.length) {
|
|
677
|
+
const ch = text[i];
|
|
678
|
+
if (ch === "'" || ch === '"' || ch === '`') {
|
|
679
|
+
let j = i + 1;
|
|
680
|
+
while (j < text.length && text[j] !== ch) {
|
|
681
|
+
j += text[j] === '\\' ? 2 : 1;
|
|
682
|
+
}
|
|
683
|
+
html += `<span class="vista-tok-str">${escapeHtml(text.slice(i, Math.min(j + 1, text.length)))}</span>`;
|
|
684
|
+
i = j + 1;
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
if (ch === '/' && text[i + 1] === '/') {
|
|
688
|
+
html += `<span class="vista-tok-cmt">${escapeHtml(text.slice(i))}</span>`;
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
if (ch === '<' && /[A-Za-z/]/.test(text[i + 1] || '')) {
|
|
692
|
+
const tag = text.slice(i).match(/^<\/?[A-Za-z][\w.-]*/);
|
|
693
|
+
if (tag) {
|
|
694
|
+
html += `<span class="vista-tok-tag">${escapeHtml(tag[0])}</span>`;
|
|
695
|
+
i += tag[0].length;
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (/[0-9]/.test(ch)) {
|
|
700
|
+
const num = text.slice(i).match(/^[0-9]+(?:\.[0-9]+)?/);
|
|
701
|
+
if (num) {
|
|
702
|
+
html += `<span class="vista-tok-num">${escapeHtml(num[0])}</span>`;
|
|
703
|
+
i += num[0].length;
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
if (/[A-Za-z_$]/.test(ch)) {
|
|
708
|
+
const ident = text.slice(i).match(/^[A-Za-z_$][\w$]*/);
|
|
709
|
+
if (ident) {
|
|
710
|
+
html += SOURCE_KEYWORDS.test(ident[0])
|
|
711
|
+
? `<span class="vista-tok-kw">${escapeHtml(ident[0])}</span>`
|
|
712
|
+
: escapeHtml(ident[0]);
|
|
713
|
+
i += ident[0].length;
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
html += escapeHtml(ch);
|
|
718
|
+
i += 1;
|
|
719
|
+
}
|
|
720
|
+
return html;
|
|
721
|
+
}
|
|
722
|
+
function parseCodeFrameLines(codeFrame) {
|
|
723
|
+
const rawLines = String(codeFrame || '').split(/\r?\n/);
|
|
724
|
+
const rows = [];
|
|
725
|
+
for (let i = 0; i < rawLines.length; i += 1) {
|
|
726
|
+
const line = rawLines[i];
|
|
727
|
+
const numbered = line.match(/^(\s*>)?\s*(\d+)\s+\|(.*)$/);
|
|
728
|
+
if (numbered) {
|
|
729
|
+
let text = numbered[3];
|
|
730
|
+
if (text.startsWith(' '))
|
|
731
|
+
text = text.slice(1);
|
|
732
|
+
const row = {
|
|
733
|
+
n: Number(numbered[2]),
|
|
734
|
+
text,
|
|
735
|
+
error: Boolean(numbered[1] && numbered[1].includes('>')),
|
|
736
|
+
squiggleAt: -1,
|
|
737
|
+
};
|
|
738
|
+
const next = rawLines[i + 1] || '';
|
|
739
|
+
const caret = next.match(/\|(.*)$/);
|
|
740
|
+
if (caret && caret[1].includes('^')) {
|
|
741
|
+
let mark = caret[1];
|
|
742
|
+
if (mark.startsWith(' '))
|
|
743
|
+
mark = mark.slice(1);
|
|
744
|
+
row.squiggleAt = Math.max(0, mark.indexOf('^'));
|
|
745
|
+
row.error = true;
|
|
746
|
+
i += 1;
|
|
747
|
+
}
|
|
748
|
+
rows.push(row);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
if (/^\s*\|?\s*\^/.test(line))
|
|
752
|
+
continue;
|
|
753
|
+
if (line.trim().length === 0)
|
|
754
|
+
continue;
|
|
755
|
+
rows.push({ n: null, text: line, error: false, squiggleAt: -1 });
|
|
756
|
+
}
|
|
757
|
+
return rows;
|
|
758
|
+
}
|
|
759
|
+
function fillEditorRows(rows, errorLine, errorColumn) {
|
|
760
|
+
const numbered = rows.filter((row) => typeof row.n === 'number');
|
|
761
|
+
if (numbered.length === 0)
|
|
762
|
+
return rows;
|
|
763
|
+
const min = Math.min(...numbered.map((row) => row.n));
|
|
764
|
+
const max = Math.max(...numbered.map((row) => row.n));
|
|
765
|
+
const byNumber = new Map(numbered.map((row) => [row.n, row]));
|
|
766
|
+
const filled = [];
|
|
767
|
+
for (let n = min; n <= max; n += 1) {
|
|
768
|
+
const existing = byNumber.get(n);
|
|
769
|
+
if (existing) {
|
|
770
|
+
if (existing.squiggleAt < 0 && errorLine === n && errorColumn) {
|
|
771
|
+
existing.squiggleAt = Math.max(0, errorColumn - 1);
|
|
772
|
+
existing.error = true;
|
|
773
|
+
}
|
|
774
|
+
filled.push(existing);
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
filled.push({
|
|
778
|
+
n,
|
|
779
|
+
text: '',
|
|
780
|
+
error: errorLine === n,
|
|
781
|
+
squiggleAt: errorLine === n && errorColumn ? Math.max(0, errorColumn - 1) : -1,
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return filled;
|
|
786
|
+
}
|
|
787
|
+
function renderIdeCodeHtml(codeFrame, errorLine, errorColumn) {
|
|
788
|
+
const rows = fillEditorRows(parseCodeFrameLines(codeFrame), errorLine, errorColumn);
|
|
789
|
+
const numbered = rows.filter((row) => typeof row.n === 'number');
|
|
790
|
+
if (numbered.length === 0) {
|
|
791
|
+
return renderLogHtml(codeFrame);
|
|
792
|
+
}
|
|
793
|
+
return `<div class="vista-error-editor">${rows
|
|
794
|
+
.map((row) => {
|
|
795
|
+
const squiggle = row.squiggleAt >= 0
|
|
796
|
+
? `<span class="vista-error-squiggle" style="width:3.2ch;margin-left:${row.squiggleAt}ch"></span>`
|
|
797
|
+
: '';
|
|
798
|
+
return `<div class="vista-error-editor-line${row.error ? ' is-error' : ''}"><span class="vista-error-gutter">${row.n ?? ''}</span><span class="vista-error-source">${highlightSource(row.text)}${squiggle}</span></div>`;
|
|
799
|
+
})
|
|
800
|
+
.join('')}</div>`;
|
|
801
|
+
}
|
|
802
|
+
function renderLogHtml(text, lineClass = '') {
|
|
803
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
804
|
+
if (lines.length === 1 && !lines[0]) {
|
|
805
|
+
return '<div class="vista-error-editor"><div class="vista-error-editor-line"><span class="vista-error-gutter"></span><span class="vista-error-source"></span></div></div>';
|
|
806
|
+
}
|
|
807
|
+
return `<div class="vista-error-editor">${lines
|
|
808
|
+
.map((line, index) => `<div class="vista-error-editor-line${lineClass}"><span class="vista-error-gutter">${index + 1}</span><span class="vista-error-source">${highlightSource(line)}</span></div>`)
|
|
809
|
+
.join('')}</div>`;
|
|
810
|
+
}
|
|
811
|
+
function renderLocationEditor(location) {
|
|
812
|
+
if (location.kind === 'server')
|
|
813
|
+
return renderLogHtml(location.codeFrame || '', ' is-server');
|
|
814
|
+
if (location.kind === 'client')
|
|
815
|
+
return renderLogHtml(location.codeFrame || '', ' is-client');
|
|
816
|
+
if (location.kind === 'log')
|
|
817
|
+
return renderLogHtml(location.codeFrame || location.file);
|
|
818
|
+
return renderIdeCodeHtml(location.codeFrame || '', location.line, location.column);
|
|
819
|
+
}
|
|
820
|
+
function tabLabel(location) {
|
|
821
|
+
if (location.kind === 'server')
|
|
822
|
+
return 'server';
|
|
823
|
+
if (location.kind === 'client')
|
|
824
|
+
return 'client';
|
|
825
|
+
return fileBasename(location.file);
|
|
826
|
+
}
|
|
827
|
+
function renderFileTabsHtml(related, activeIndex) {
|
|
828
|
+
return related
|
|
829
|
+
.map((location, index) => {
|
|
830
|
+
const name = tabLabel(location);
|
|
831
|
+
const inactive = index === activeIndex ? '' : ' is-inactive';
|
|
832
|
+
return `<button type="button" class="vista-ide-tab${inactive}" data-vista-file-tab="${index}"><svg class="vista-ide-tab-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><rect x="3" y="2" width="10" height="12" rx="1.5" stroke="#4fc1ff" stroke-width="1.4"/><path d="M6 6h4M6 9h4M6 12h2" stroke="#4fc1ff" stroke-width="1.2" stroke-linecap="round"/></svg><span>${escapeHtml(name)}</span></button>`;
|
|
833
|
+
})
|
|
834
|
+
.join('');
|
|
835
|
+
}
|
|
836
|
+
function isNoiseFile(file) {
|
|
837
|
+
const normalized = file.replace(/\\/g, '/');
|
|
838
|
+
return /node_modules\/|node:|webpack\/runtime|\/vista\/dist\//.test(normalized);
|
|
839
|
+
}
|
|
840
|
+
function parseLocationsFromText(text) {
|
|
841
|
+
const found = [];
|
|
842
|
+
const seen = new Set();
|
|
843
|
+
const pattern = /(?:ERROR in\s+)?((?:[A-Za-z]:)?[./\\]?[\w.@/-]+\.(?:tsx?|jsx?|mjs|cjs|css|json|mdx?))(?::(\d+)(?::(\d+))?)?/g;
|
|
844
|
+
let match;
|
|
845
|
+
while ((match = pattern.exec(text))) {
|
|
846
|
+
const file = match[1].replace(/\\/g, '/').replace(/^\.\//, '');
|
|
847
|
+
if (isNoiseFile(file))
|
|
848
|
+
continue;
|
|
849
|
+
const key = `${file}:${match[2] || ''}`;
|
|
850
|
+
if (seen.has(key) || seen.has(file))
|
|
851
|
+
continue;
|
|
852
|
+
seen.add(file);
|
|
853
|
+
seen.add(key);
|
|
854
|
+
found.push({
|
|
855
|
+
file,
|
|
856
|
+
line: match[2] ? Number(match[2]) : undefined,
|
|
857
|
+
column: match[3] ? Number(match[3]) : undefined,
|
|
858
|
+
kind: 'source',
|
|
859
|
+
});
|
|
860
|
+
if (found.length >= 8)
|
|
861
|
+
break;
|
|
862
|
+
}
|
|
863
|
+
return found;
|
|
864
|
+
}
|
|
865
|
+
function parseHydrationMismatch(message) {
|
|
866
|
+
const serverLines = [];
|
|
867
|
+
const clientLines = [];
|
|
868
|
+
for (const rawLine of String(message || '').split(/\r?\n/)) {
|
|
869
|
+
if (/^\s*-\s+(A |Variable |Date |External |Invalid |It can also|https?:)/i.test(rawLine))
|
|
870
|
+
continue;
|
|
871
|
+
if (/^\s*-\s+/.test(rawLine)) {
|
|
872
|
+
serverLines.push(rawLine.replace(/^\s*-\s?/, ''));
|
|
873
|
+
}
|
|
874
|
+
else if (/^\s*\+\s+/.test(rawLine)) {
|
|
875
|
+
clientLines.push(rawLine.replace(/^\s*\+\s?/, ''));
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (serverLines.length === 0 && clientLines.length === 0)
|
|
879
|
+
return null;
|
|
880
|
+
return { server: serverLines.join('\n'), client: clientLines.join('\n') };
|
|
881
|
+
}
|
|
882
|
+
function defaultHint(error) {
|
|
883
|
+
if (error.hint)
|
|
884
|
+
return error.hint;
|
|
885
|
+
if (error.type === 'hydration') {
|
|
886
|
+
return 'Server HTML did not match the client. Check Date.now(), Math.random(), invalid tag nesting, or a missing \'use client\'.';
|
|
887
|
+
}
|
|
888
|
+
if (error.source === 'server') {
|
|
889
|
+
return 'Thrown while rendering on the server. Open the first app frame in the call stack.';
|
|
890
|
+
}
|
|
891
|
+
if (error.type === 'build' && (error.related?.length || 0) > 1) {
|
|
892
|
+
return `${error.related.length} files are involved. Switch editor tabs to inspect each one.`;
|
|
893
|
+
}
|
|
894
|
+
return '';
|
|
895
|
+
}
|
|
896
|
+
function enrichError(error) {
|
|
897
|
+
const message = error.message || '';
|
|
898
|
+
const stack = error.stack || '';
|
|
899
|
+
let type = error.type;
|
|
900
|
+
let source = error.source;
|
|
901
|
+
if (type !== 'hydration' && /hydration|did not match|server rendered html|text content does not match/i.test(message)) {
|
|
902
|
+
type = 'hydration';
|
|
903
|
+
}
|
|
904
|
+
if (!source && /Flight SSR|Server Error|renderToString|rsc-engine|vista[\\/]server/i.test(`${message}\n${stack}`)) {
|
|
905
|
+
source = 'server';
|
|
906
|
+
}
|
|
907
|
+
const related = [];
|
|
908
|
+
const seen = new Set();
|
|
909
|
+
const add = (location) => {
|
|
910
|
+
const file = location.file.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
911
|
+
if (!file || isNoiseFile(file))
|
|
912
|
+
return;
|
|
913
|
+
const kind = location.kind || 'source';
|
|
914
|
+
const key = kind === 'source' || kind === 'log' ? `${kind}:${file}` : `${kind}:${file}:${location.line || ''}`;
|
|
915
|
+
if (seen.has(key))
|
|
916
|
+
return;
|
|
917
|
+
seen.add(key);
|
|
918
|
+
related.push({ ...location, file, kind });
|
|
919
|
+
};
|
|
920
|
+
if (error.file) {
|
|
921
|
+
add({
|
|
922
|
+
file: error.file,
|
|
923
|
+
line: error.line,
|
|
924
|
+
column: error.column,
|
|
925
|
+
codeFrame: error.codeFrame,
|
|
926
|
+
kind: 'source',
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
for (const frame of parseStackFrames(stack)) {
|
|
930
|
+
if (!frame.file)
|
|
931
|
+
continue;
|
|
932
|
+
add({ file: frame.file, line: frame.line || undefined, column: frame.column || undefined, kind: 'source' });
|
|
933
|
+
}
|
|
934
|
+
for (const location of parseLocationsFromText(`${message}\n${stack}`)) {
|
|
935
|
+
add(location);
|
|
936
|
+
}
|
|
937
|
+
const mismatch = type === 'hydration' ? parseHydrationMismatch(message) : null;
|
|
938
|
+
if (mismatch) {
|
|
939
|
+
if (mismatch.server)
|
|
940
|
+
add({ file: 'server.html', codeFrame: mismatch.server, kind: 'server' });
|
|
941
|
+
if (mismatch.client)
|
|
942
|
+
add({ file: 'client.html', codeFrame: mismatch.client, kind: 'client' });
|
|
943
|
+
}
|
|
944
|
+
if (related.length === 0) {
|
|
945
|
+
add({
|
|
946
|
+
file: error.file || (type === 'build' ? 'build.log' : 'error.log'),
|
|
947
|
+
line: error.line,
|
|
948
|
+
column: error.column,
|
|
949
|
+
codeFrame: error.codeFrame || (error.stack ? error.stack : error.message),
|
|
950
|
+
kind: error.codeFrame ? 'source' : 'log',
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
else if (error.codeFrame && !related[0].codeFrame) {
|
|
954
|
+
related[0] = { ...related[0], codeFrame: error.codeFrame };
|
|
955
|
+
}
|
|
956
|
+
const primary = related.find((item) => item.kind === 'source') || related[0];
|
|
957
|
+
const next = {
|
|
958
|
+
...error,
|
|
959
|
+
type,
|
|
960
|
+
source,
|
|
961
|
+
file: error.file || primary?.file,
|
|
962
|
+
line: error.line || primary?.line,
|
|
963
|
+
column: error.column || primary?.column,
|
|
964
|
+
related,
|
|
965
|
+
};
|
|
966
|
+
next.hint = defaultHint(next);
|
|
967
|
+
return next;
|
|
968
|
+
}
|
|
969
|
+
function parseStackFrames(stack) {
|
|
970
|
+
return parseStackTrace(stack).map((line) => {
|
|
971
|
+
const match = line.match(/^\s*at\s+(?:async\s+)?(?:(.+?)\s+\()?((?:[A-Za-z]:)?[^()\s]+):(\d+):(\d+)\)?\s*$/);
|
|
972
|
+
if (match) {
|
|
973
|
+
return {
|
|
974
|
+
name: (match[1] || '(anonymous)').replace(/^Object\./, ''),
|
|
975
|
+
file: match[2],
|
|
976
|
+
line: Number(match[3]),
|
|
977
|
+
column: Number(match[4]),
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
return { name: line.replace(/^\s*at\s+/, ''), file: '', line: 0, column: 0 };
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
function renderStackFramesHtml(stack) {
|
|
984
|
+
const frames = parseStackFrames(stack);
|
|
985
|
+
if (frames.length === 0)
|
|
986
|
+
return '';
|
|
987
|
+
return `<div class="vista-error-frames">${frames
|
|
988
|
+
.map((frame) => {
|
|
989
|
+
const loc = frame.file
|
|
990
|
+
? `${frame.file.replace(/\\/g, '/')}${frame.line ? `:${frame.line}` : ''}${frame.column ? `:${frame.column}` : ''}`
|
|
991
|
+
: '';
|
|
992
|
+
const open = frame.file
|
|
993
|
+
? ` data-vista-open-file="${escapeHtml(frame.file)}" data-vista-open-line="${frame.line || 1}" data-vista-open-col="${frame.column || 1}"`
|
|
994
|
+
: '';
|
|
995
|
+
return `<button type="button" class="vista-error-frame"${open}><span class="vista-error-frame-name">${escapeHtml(frame.name)}</span>${loc ? `<span class="vista-error-frame-loc">${escapeHtml(loc)}</span>` : ''}</button>`;
|
|
996
|
+
})
|
|
997
|
+
.join('')}</div>`;
|
|
998
|
+
}
|
|
370
999
|
function parseStackTrace(stack) {
|
|
371
1000
|
if (!stack)
|
|
372
1001
|
return [];
|
|
@@ -376,43 +1005,125 @@ function parseStackTrace(stack) {
|
|
|
376
1005
|
.filter((line) => line.trim().length > 0);
|
|
377
1006
|
}
|
|
378
1007
|
function normalizeError(error) {
|
|
379
|
-
return {
|
|
1008
|
+
return enrichError({
|
|
380
1009
|
type: error?.type === 'build' || error?.type === 'hydration' || error?.type === 'runtime'
|
|
381
1010
|
? error.type
|
|
382
1011
|
: 'runtime',
|
|
1012
|
+
source: error?.source === 'server' || error?.source === 'client' ? error.source : undefined,
|
|
383
1013
|
message: typeof error?.message === 'string' ? error.message : 'Unknown Error',
|
|
384
1014
|
stack: typeof error?.stack === 'string' ? error.stack : undefined,
|
|
385
1015
|
file: typeof error?.file === 'string' ? error.file : undefined,
|
|
386
1016
|
line: typeof error?.line === 'number' ? error.line : undefined,
|
|
387
1017
|
column: typeof error?.column === 'number' ? error.column : undefined,
|
|
388
1018
|
codeFrame: typeof error?.codeFrame === 'string' ? error.codeFrame : undefined,
|
|
389
|
-
|
|
1019
|
+
related: Array.isArray(error?.related) ? error.related : undefined,
|
|
1020
|
+
hint: typeof error?.hint === 'string' ? error.hint : undefined,
|
|
1021
|
+
});
|
|
390
1022
|
}
|
|
391
1023
|
function normalizeErrors(errors) {
|
|
392
1024
|
if (!Array.isArray(errors) || errors.length === 0) {
|
|
393
|
-
return [
|
|
394
|
-
{
|
|
395
|
-
type: 'runtime',
|
|
396
|
-
message: 'Unknown Error',
|
|
397
|
-
},
|
|
398
|
-
];
|
|
1025
|
+
return [normalizeError({ type: 'runtime', message: 'Unknown Error' })];
|
|
399
1026
|
}
|
|
400
1027
|
return errors.map((error) => normalizeError(error));
|
|
401
1028
|
}
|
|
402
|
-
function
|
|
403
|
-
if (
|
|
1029
|
+
function locationHasCode(location) {
|
|
1030
|
+
if (!location)
|
|
1031
|
+
return false;
|
|
1032
|
+
if ((location.kind || 'source') !== 'source')
|
|
1033
|
+
return false;
|
|
1034
|
+
return Boolean(location.codeFrame && String(location.codeFrame).trim());
|
|
1035
|
+
}
|
|
1036
|
+
function hasCodeView(error) {
|
|
1037
|
+
const related = error.related || [];
|
|
1038
|
+
if (related.some(locationHasCode))
|
|
1039
|
+
return true;
|
|
1040
|
+
return Boolean(error.codeFrame && String(error.codeFrame).trim());
|
|
1041
|
+
}
|
|
1042
|
+
function getErrorTypeLabel(error) {
|
|
1043
|
+
if (error.type === 'build')
|
|
404
1044
|
return 'Build Error';
|
|
405
|
-
if (type === 'hydration')
|
|
1045
|
+
if (error.type === 'hydration')
|
|
406
1046
|
return 'Hydration Error';
|
|
407
|
-
|
|
1047
|
+
if (error.source === 'server')
|
|
1048
|
+
return 'Server Error';
|
|
1049
|
+
return 'Unhandled Runtime Error';
|
|
1050
|
+
}
|
|
1051
|
+
function problemTone(error) {
|
|
1052
|
+
if (error.type === 'hydration')
|
|
1053
|
+
return 'hydration';
|
|
1054
|
+
if (error.source === 'server')
|
|
1055
|
+
return 'server';
|
|
1056
|
+
return '';
|
|
408
1057
|
}
|
|
409
|
-
function
|
|
410
|
-
|
|
1058
|
+
function sourceBadge(error) {
|
|
1059
|
+
if (error.type === 'hydration')
|
|
1060
|
+
return { label: 'Hydration', tone: 'hydration' };
|
|
1061
|
+
if (error.source === 'server')
|
|
1062
|
+
return { label: 'Server', tone: 'server' };
|
|
1063
|
+
if (error.source === 'client')
|
|
1064
|
+
return { label: 'Client', tone: 'client' };
|
|
1065
|
+
if (error.type === 'build')
|
|
1066
|
+
return { label: 'Build', tone: '' };
|
|
1067
|
+
return { label: 'Client', tone: 'client' };
|
|
1068
|
+
}
|
|
1069
|
+
function fromCaughtError(error, options) {
|
|
1070
|
+
const err = error instanceof Error ? error : new Error(String(error || 'Unknown Error'));
|
|
1071
|
+
return normalizeError({
|
|
1072
|
+
type: options?.type || 'runtime',
|
|
1073
|
+
source: options?.source,
|
|
1074
|
+
message: err.message || 'Unknown Error',
|
|
1075
|
+
stack: err.stack,
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
function splitMessage(message) {
|
|
1079
|
+
const lines = String(message || '')
|
|
411
1080
|
.split(/\r?\n/)
|
|
412
1081
|
.map((line) => line.trim())
|
|
413
1082
|
.filter(Boolean);
|
|
414
|
-
|
|
415
|
-
|
|
1083
|
+
return {
|
|
1084
|
+
headline: lines[0] || 'Unknown Error',
|
|
1085
|
+
detail: lines.slice(1).join('\n'),
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
function formatCodeHeader(error) {
|
|
1089
|
+
if (!error.file)
|
|
1090
|
+
return '';
|
|
1091
|
+
const file = error.file.replace(/\\/g, '/');
|
|
1092
|
+
if (!error.line)
|
|
1093
|
+
return file;
|
|
1094
|
+
return `${file} (${error.line}${error.column ? `:${error.column}` : ''})`;
|
|
1095
|
+
}
|
|
1096
|
+
function fileBasename(file) {
|
|
1097
|
+
if (!file)
|
|
1098
|
+
return 'untitled';
|
|
1099
|
+
const normalized = file.replace(/\\/g, '/');
|
|
1100
|
+
return normalized.split('/').filter(Boolean).pop() || normalized;
|
|
1101
|
+
}
|
|
1102
|
+
function fileBreadcrumb(file) {
|
|
1103
|
+
if (!file)
|
|
1104
|
+
return '';
|
|
1105
|
+
return file.replace(/\\/g, '/').split('/').filter(Boolean).join(' › ');
|
|
1106
|
+
}
|
|
1107
|
+
function languageFromFile(file) {
|
|
1108
|
+
const ext = (file || '').split('.').pop()?.toLowerCase();
|
|
1109
|
+
if (ext === 'tsx')
|
|
1110
|
+
return 'TypeScript React';
|
|
1111
|
+
if (ext === 'ts')
|
|
1112
|
+
return 'TypeScript';
|
|
1113
|
+
if (ext === 'jsx')
|
|
1114
|
+
return 'JavaScript React';
|
|
1115
|
+
if (ext === 'js' || ext === 'mjs' || ext === 'cjs')
|
|
1116
|
+
return 'JavaScript';
|
|
1117
|
+
if (ext === 'css')
|
|
1118
|
+
return 'CSS';
|
|
1119
|
+
if (ext === 'json')
|
|
1120
|
+
return 'JSON';
|
|
1121
|
+
return 'Plain Text';
|
|
1122
|
+
}
|
|
1123
|
+
function statusLine(error) {
|
|
1124
|
+
if (!error.line)
|
|
1125
|
+
return 'Ready';
|
|
1126
|
+
return `Ln ${error.line}, Col ${error.column || 1}`;
|
|
416
1127
|
}
|
|
417
1128
|
function formatLocation(error) {
|
|
418
1129
|
if (!error.file)
|
|
@@ -423,7 +1134,7 @@ function formatLocation(error) {
|
|
|
423
1134
|
return `${normalized}:${error.line}${error.column ? `:${error.column}` : ''}`;
|
|
424
1135
|
}
|
|
425
1136
|
function serializeErrorForCopy(error) {
|
|
426
|
-
const label = getErrorTypeLabel(error
|
|
1137
|
+
const label = getErrorTypeLabel(error);
|
|
427
1138
|
const parts = [label, '', error.message || 'Unknown Error'];
|
|
428
1139
|
if (error.file) {
|
|
429
1140
|
parts.push('');
|
|
@@ -485,14 +1196,40 @@ function copyTextInBrowser(value) {
|
|
|
485
1196
|
function renderErrorHTML(errors) {
|
|
486
1197
|
const normalizedErrors = normalizeErrors(errors);
|
|
487
1198
|
const firstError = normalizedErrors[0];
|
|
488
|
-
const firstLabel = getErrorTypeLabel(firstError
|
|
489
|
-
const
|
|
490
|
-
const
|
|
1199
|
+
const firstLabel = getErrorTypeLabel(firstError);
|
|
1200
|
+
const firstParts = splitMessage(firstError.message || 'Unknown Error');
|
|
1201
|
+
const firstRelated = firstError.related && firstError.related.length > 0
|
|
1202
|
+
? firstError.related
|
|
1203
|
+
: [
|
|
1204
|
+
{
|
|
1205
|
+
file: firstError.file || 'untitled',
|
|
1206
|
+
line: firstError.line,
|
|
1207
|
+
column: firstError.column,
|
|
1208
|
+
codeFrame: firstError.codeFrame,
|
|
1209
|
+
kind: 'source',
|
|
1210
|
+
},
|
|
1211
|
+
];
|
|
1212
|
+
const firstLocationEntry = firstRelated[0];
|
|
1213
|
+
const firstLocation = formatCodeHeader(firstError) || formatLocation(firstError);
|
|
491
1214
|
const firstStack = parseStackTrace(firstError.stack || '').join('\n');
|
|
492
|
-
const
|
|
493
|
-
const
|
|
494
|
-
const
|
|
495
|
-
|
|
1215
|
+
const firstCodeHtml = renderLocationEditor(firstLocationEntry);
|
|
1216
|
+
const firstCrumbs = fileBreadcrumb(firstLocationEntry.file) || firstLocation || 'Source';
|
|
1217
|
+
const firstStatus = firstLocationEntry.line
|
|
1218
|
+
? `Ln ${firstLocationEntry.line}, Col ${firstLocationEntry.column || 1}`
|
|
1219
|
+
: statusLine(firstError);
|
|
1220
|
+
const firstLang = firstLocationEntry.kind === 'server' || firstLocationEntry.kind === 'client'
|
|
1221
|
+
? 'HTML'
|
|
1222
|
+
: firstLocationEntry.kind === 'log'
|
|
1223
|
+
? 'Log'
|
|
1224
|
+
: languageFromFile(firstLocationEntry.file);
|
|
1225
|
+
const firstStackHtml = renderStackFramesHtml(firstStack);
|
|
1226
|
+
const firstTabsHtml = renderFileTabsHtml(firstRelated, 0);
|
|
1227
|
+
const firstTone = problemTone(firstError);
|
|
1228
|
+
const firstBadge = sourceBadge(firstError);
|
|
1229
|
+
const firstHint = firstError.hint || '';
|
|
1230
|
+
const firstTerminal = !hasCodeView(firstError);
|
|
1231
|
+
const firstTitleName = firstTerminal ? firstLabel : tabLabel(firstLocationEntry);
|
|
1232
|
+
const showPager = normalizedErrors.length > 1;
|
|
496
1233
|
const serializedErrors = escapeForInlineScript(JSON.stringify(normalizedErrors));
|
|
497
1234
|
return `<!DOCTYPE html>
|
|
498
1235
|
<html lang="en">
|
|
@@ -526,13 +1263,17 @@ function renderErrorHTML(errors) {
|
|
|
526
1263
|
errors = [{ type: 'runtime', message: 'Unknown Error' }];
|
|
527
1264
|
}
|
|
528
1265
|
|
|
529
|
-
var state = { index: 0, errors: errors };
|
|
1266
|
+
var state = { index: 0, fileTab: 0, errors: errors };
|
|
530
1267
|
var typeNode;
|
|
531
1268
|
var titleNode;
|
|
532
|
-
var
|
|
533
|
-
var
|
|
534
|
-
var
|
|
535
|
-
var
|
|
1269
|
+
var hintNode;
|
|
1270
|
+
var fileTabsNode;
|
|
1271
|
+
var sourceBadgeNode;
|
|
1272
|
+
var problemIconNode;
|
|
1273
|
+
var tabNameNodes;
|
|
1274
|
+
var crumbsNode;
|
|
1275
|
+
var statusLnNode;
|
|
1276
|
+
var statusLangNode;
|
|
536
1277
|
var locationButton;
|
|
537
1278
|
var codeWrap;
|
|
538
1279
|
var codeNode;
|
|
@@ -548,29 +1289,34 @@ function renderErrorHTML(errors) {
|
|
|
548
1289
|
var backdropNode;
|
|
549
1290
|
var minimizedTrigger;
|
|
550
1291
|
var minimizedCount;
|
|
1292
|
+
var mainNode;
|
|
1293
|
+
var panelExpandButton;
|
|
551
1294
|
|
|
552
|
-
function getLabel(
|
|
553
|
-
if (type === 'build') return 'Build Error';
|
|
554
|
-
if (type === 'hydration') return 'Hydration Error';
|
|
555
|
-
return '
|
|
1295
|
+
function getLabel(error) {
|
|
1296
|
+
if (error.type === 'build') return 'Build Error';
|
|
1297
|
+
if (error.type === 'hydration') return 'Hydration Error';
|
|
1298
|
+
if (error.source === 'server') return 'Server Error';
|
|
1299
|
+
return 'Unhandled Runtime Error';
|
|
556
1300
|
}
|
|
557
1301
|
|
|
558
|
-
function
|
|
1302
|
+
function splitMessage(message) {
|
|
559
1303
|
var lines = String(message || '')
|
|
560
1304
|
.split(/\\r?\\n/)
|
|
561
1305
|
.map(function(line) { return line.trim(); })
|
|
562
1306
|
.filter(function(line) { return line.length > 0; });
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
function pad2(value) {
|
|
568
|
-
return value < 10 ? '0' + value : String(value);
|
|
1307
|
+
return {
|
|
1308
|
+
headline: lines.length ? lines[0] : 'Unknown Error',
|
|
1309
|
+
detail: lines.slice(1).join('\\n')
|
|
1310
|
+
};
|
|
569
1311
|
}
|
|
570
1312
|
|
|
571
|
-
function
|
|
572
|
-
|
|
573
|
-
|
|
1313
|
+
function formatCodeHeader(error) {
|
|
1314
|
+
if (!error || !error.file) return '';
|
|
1315
|
+
var file = String(error.file).replace(/\\\\/g, '/');
|
|
1316
|
+
var line = Number(error.line || 0);
|
|
1317
|
+
var column = Number(error.column || 0);
|
|
1318
|
+
if (!line) return file;
|
|
1319
|
+
return file + ' (' + line + (column ? ':' + column : '') + ')';
|
|
574
1320
|
}
|
|
575
1321
|
|
|
576
1322
|
function currentError() {
|
|
@@ -599,44 +1345,200 @@ function renderErrorHTML(errors) {
|
|
|
599
1345
|
.replace(/'/g, ''');
|
|
600
1346
|
}
|
|
601
1347
|
|
|
602
|
-
function
|
|
603
|
-
var
|
|
1348
|
+
function highlightSource(text) {
|
|
1349
|
+
var html = '';
|
|
1350
|
+
var i = 0;
|
|
1351
|
+
var keywords = /^(import|from|function|return|const|let|var|export|default|class|extends|if|else|async|await|new|type|interface|true|false|null|undefined|typeof|void|as|of|in|for|while|switch|case|break|continue|try|catch|finally|this)\\b/;
|
|
1352
|
+
while (i < text.length) {
|
|
1353
|
+
var ch = text.charAt(i);
|
|
1354
|
+
if (ch === String.fromCharCode(39) || ch === String.fromCharCode(34) || ch === String.fromCharCode(96)) {
|
|
1355
|
+
var j = i + 1;
|
|
1356
|
+
while (j < text.length && text.charAt(j) !== ch) {
|
|
1357
|
+
j += text.charAt(j) === '\\\\' ? 2 : 1;
|
|
1358
|
+
}
|
|
1359
|
+
html += '<span class=\"vista-tok-str\">' + escapeHtml(text.slice(i, Math.min(j + 1, text.length))) + '</span>';
|
|
1360
|
+
i = j + 1;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
if (ch === '/' && text.charAt(i + 1) === '/') {
|
|
1364
|
+
html += '<span class=\"vista-tok-cmt\">' + escapeHtml(text.slice(i)) + '</span>';
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
if (ch === '<' && /[A-Za-z\\/]/.test(text.charAt(i + 1) || '')) {
|
|
1368
|
+
var tag = text.slice(i).match(/^<\\/?[A-Za-z][\\w.-]*/);
|
|
1369
|
+
if (tag) {
|
|
1370
|
+
html += '<span class=\"vista-tok-tag\">' + escapeHtml(tag[0]) + '</span>';
|
|
1371
|
+
i += tag[0].length;
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
if (/[0-9]/.test(ch)) {
|
|
1376
|
+
var num = text.slice(i).match(/^[0-9]+(?:\\.[0-9]+)?/);
|
|
1377
|
+
if (num) {
|
|
1378
|
+
html += '<span class=\"vista-tok-num\">' + escapeHtml(num[0]) + '</span>';
|
|
1379
|
+
i += num[0].length;
|
|
1380
|
+
continue;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
if (/[A-Za-z_$]/.test(ch)) {
|
|
1384
|
+
var ident = text.slice(i).match(/^[A-Za-z_$][\\w$]*/);
|
|
1385
|
+
if (ident) {
|
|
1386
|
+
html += keywords.test(ident[0])
|
|
1387
|
+
? '<span class=\"vista-tok-kw\">' + escapeHtml(ident[0]) + '</span>'
|
|
1388
|
+
: escapeHtml(ident[0]);
|
|
1389
|
+
i += ident[0].length;
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
html += escapeHtml(ch);
|
|
1394
|
+
i += 1;
|
|
1395
|
+
}
|
|
1396
|
+
return html;
|
|
1397
|
+
}
|
|
604
1398
|
|
|
605
|
-
|
|
606
|
-
|
|
1399
|
+
function renderIdeCode(codeFrame, errorLine, errorColumn) {
|
|
1400
|
+
var rawLines = String(codeFrame || '').split(/\\r?\\n/);
|
|
1401
|
+
var rows = [];
|
|
1402
|
+
for (var i = 0; i < rawLines.length; i += 1) {
|
|
1403
|
+
var line = rawLines[i];
|
|
1404
|
+
var numbered = line.match(/^(\\s*>)?\\s*(\\d+)\\s+\\|(.*)$/);
|
|
1405
|
+
if (!numbered) continue;
|
|
1406
|
+
var src = numbered[3];
|
|
1407
|
+
if (src.charAt(0) === ' ') src = src.slice(1);
|
|
1408
|
+
var isError = !!(numbered[1] && numbered[1].indexOf('>') !== -1);
|
|
1409
|
+
var squiggleAt = -1;
|
|
1410
|
+
var next = rawLines[i + 1] || '';
|
|
1411
|
+
var caret = next.match(/\\|(.*)$/);
|
|
1412
|
+
if (caret && caret[1].indexOf('^') !== -1) {
|
|
1413
|
+
var mark = caret[1];
|
|
1414
|
+
if (mark.charAt(0) === ' ') mark = mark.slice(1);
|
|
1415
|
+
squiggleAt = Math.max(0, mark.indexOf('^'));
|
|
1416
|
+
isError = true;
|
|
1417
|
+
i += 1;
|
|
1418
|
+
}
|
|
1419
|
+
rows.push({ n: Number(numbered[2]), text: src, error: isError, squiggleAt: squiggleAt });
|
|
607
1420
|
}
|
|
608
|
-
if (
|
|
609
|
-
|
|
1421
|
+
if (!rows.length) return '';
|
|
1422
|
+
var min = rows[0].n;
|
|
1423
|
+
var max = rows[0].n;
|
|
1424
|
+
var byN = {};
|
|
1425
|
+
for (var r = 0; r < rows.length; r += 1) {
|
|
1426
|
+
byN[rows[r].n] = rows[r];
|
|
1427
|
+
if (rows[r].n < min) min = rows[r].n;
|
|
1428
|
+
if (rows[r].n > max) max = rows[r].n;
|
|
610
1429
|
}
|
|
1430
|
+
var html = '';
|
|
1431
|
+
for (var n = min; n <= max; n += 1) {
|
|
1432
|
+
var row = byN[n] || { n: n, text: '', error: Number(errorLine) === n, squiggleAt: -1 };
|
|
1433
|
+
if (row.squiggleAt < 0 && Number(errorLine) === n && errorColumn) {
|
|
1434
|
+
row.squiggleAt = Math.max(0, Number(errorColumn) - 1);
|
|
1435
|
+
row.error = true;
|
|
1436
|
+
}
|
|
1437
|
+
html += '<div class=\"vista-error-editor-line' + (row.error ? ' is-error' : '') + '\">';
|
|
1438
|
+
html += '<span class=\"vista-error-gutter\">' + row.n + '</span>';
|
|
1439
|
+
html += '<span class=\"vista-error-source\">' + highlightSource(row.text);
|
|
1440
|
+
if (row.squiggleAt >= 0) {
|
|
1441
|
+
html += '<span class=\"vista-error-squiggle\" style=\"width:3.2ch;margin-left:' + row.squiggleAt + 'ch\"></span>';
|
|
1442
|
+
}
|
|
1443
|
+
html += '</span></div>';
|
|
1444
|
+
}
|
|
1445
|
+
return '<div class=\"vista-error-editor\">' + html + '</div>';
|
|
1446
|
+
}
|
|
611
1447
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
1448
|
+
function renderLog(text, extraClass) {
|
|
1449
|
+
var lines = String(text || '').split(/\\r?\\n/);
|
|
1450
|
+
var html = '';
|
|
1451
|
+
for (var i = 0; i < lines.length; i += 1) {
|
|
1452
|
+
html += '<div class=\"vista-error-editor-line' + (extraClass || '') + '\">';
|
|
1453
|
+
html += '<span class=\"vista-error-gutter\">' + (i + 1) + '</span>';
|
|
1454
|
+
html += '<span class=\"vista-error-source\">' + highlightSource(lines[i]) + '</span></div>';
|
|
616
1455
|
}
|
|
1456
|
+
return '<div class=\"vista-error-editor\">' + html + '</div>';
|
|
1457
|
+
}
|
|
617
1458
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
);
|
|
622
|
-
escaped = escaped.replace(
|
|
623
|
-
/("[^&]+"|'[^&]+')/g,
|
|
624
|
-
'<span class=\"vista-error-tok-string\">$1</span>'
|
|
625
|
-
);
|
|
626
|
-
escaped = escaped.replace(
|
|
627
|
-
/(TypeError:|ReferenceError:|SyntaxError:|Error:|Cannot find module|Module not found|Build Error|Runtime Error|Hydration Error)/g,
|
|
628
|
-
'<span class=\"vista-error-tok-error\">$1</span>'
|
|
629
|
-
);
|
|
630
|
-
return escaped;
|
|
1459
|
+
function relatedFor(error) {
|
|
1460
|
+
if (error.related && error.related.length) return error.related;
|
|
1461
|
+
return [{ file: error.file || 'untitled', line: error.line, column: error.column, codeFrame: error.codeFrame, kind: 'source' }];
|
|
631
1462
|
}
|
|
632
1463
|
|
|
633
|
-
function
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
1464
|
+
function locationHasCode(loc) {
|
|
1465
|
+
if (!loc) return false;
|
|
1466
|
+
if ((loc.kind || 'source') !== 'source') return false;
|
|
1467
|
+
return !!(loc.codeFrame && String(loc.codeFrame).trim());
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
function hasCodeView(error) {
|
|
1471
|
+
var related = relatedFor(error);
|
|
1472
|
+
for (var i = 0; i < related.length; i += 1) {
|
|
1473
|
+
if (locationHasCode(related[i])) return true;
|
|
1474
|
+
}
|
|
1475
|
+
return !!(error.codeFrame && String(error.codeFrame).trim());
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
function tabLabelFor(loc) {
|
|
1479
|
+
if (loc.kind === 'server') return 'server';
|
|
1480
|
+
if (loc.kind === 'client') return 'client';
|
|
1481
|
+
var file = String(loc.file || 'untitled').replace(/\\\\/g, '/');
|
|
1482
|
+
return file.split('/').filter(Boolean).pop() || file;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
function renderLocation(loc) {
|
|
1486
|
+
if (loc.kind === 'server') return renderLog(loc.codeFrame || '', ' is-server');
|
|
1487
|
+
if (loc.kind === 'client') return renderLog(loc.codeFrame || '', ' is-client');
|
|
1488
|
+
if (loc.kind === 'log') return renderLog(loc.codeFrame || loc.file || '');
|
|
1489
|
+
var frame = loc.codeFrame || '';
|
|
1490
|
+
var html = renderIdeCode(frame, loc.line, loc.column);
|
|
1491
|
+
return html || renderLog(frame);
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
function renderFileTabs(related, active) {
|
|
1495
|
+
var html = '';
|
|
1496
|
+
for (var i = 0; i < related.length; i += 1) {
|
|
1497
|
+
html += '<button type=\"button\" class=\"vista-ide-tab' + (i === active ? '' : ' is-inactive') + '\" data-vista-file-tab=\"' + i + '\">';
|
|
1498
|
+
html += '<svg class=\"vista-ide-tab-icon\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><rect x=\"3\" y=\"2\" width=\"10\" height=\"12\" rx=\"1.5\" stroke=\"#4fc1ff\" stroke-width=\"1.4\"/><path d=\"M6 6h4M6 9h4M6 12h2\" stroke=\"#4fc1ff\" stroke-width=\"1.2\" stroke-linecap=\"round\"/></svg>';
|
|
1499
|
+
html += '<span>' + escapeHtml(tabLabelFor(related[i])) + '</span></button>';
|
|
1500
|
+
}
|
|
1501
|
+
return html;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
function langFor(loc) {
|
|
1505
|
+
if (loc.kind === 'server' || loc.kind === 'client') return 'HTML';
|
|
1506
|
+
if (loc.kind === 'log') return 'Log';
|
|
1507
|
+
var ext = String(loc.file || '').split('.').pop().toLowerCase();
|
|
1508
|
+
if (ext === 'tsx') return 'TypeScript React';
|
|
1509
|
+
if (ext === 'ts') return 'TypeScript';
|
|
1510
|
+
if (ext === 'jsx') return 'JavaScript React';
|
|
1511
|
+
if (ext === 'js' || ext === 'mjs' || ext === 'cjs') return 'JavaScript';
|
|
1512
|
+
return 'Plain Text';
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
function renderStackFrames(stack) {
|
|
1516
|
+
var lines = String(stack || '').split(/\\r?\\n/).filter(function(line) { return line.trim().length > 0; });
|
|
1517
|
+
var html = '';
|
|
1518
|
+
for (var s = 0; s < lines.length; s += 1) {
|
|
1519
|
+
var line = lines[s];
|
|
1520
|
+
var match = line.match(/^\\s*at\\s+(?:async\\s+)?(?:(.+?)\\s+\\()?((?:[A-Za-z]:)?[^()\\s]+):(\\d+):(\\d+)\\)?\\s*$/);
|
|
1521
|
+
var name = line.replace(/^\\s*at\\s+/, '');
|
|
1522
|
+
var file = '';
|
|
1523
|
+
var ln = 1;
|
|
1524
|
+
var col = 1;
|
|
1525
|
+
var loc = '';
|
|
1526
|
+
if (match) {
|
|
1527
|
+
name = (match[1] || '(anonymous)').replace(/^Object\\./, '');
|
|
1528
|
+
file = match[2];
|
|
1529
|
+
ln = Number(match[3]);
|
|
1530
|
+
col = Number(match[4]);
|
|
1531
|
+
loc = file.replace(/\\\\/g, '/') + ':' + ln + ':' + col;
|
|
1532
|
+
}
|
|
1533
|
+
html += '<button type=\"button\" class=\"vista-error-frame\"';
|
|
1534
|
+
if (file) {
|
|
1535
|
+
html += ' data-vista-open-file=\"' + escapeHtml(file) + '\" data-vista-open-line=\"' + ln + '\" data-vista-open-col=\"' + col + '\"';
|
|
1536
|
+
}
|
|
1537
|
+
html += '><span class=\"vista-error-frame-name\">' + escapeHtml(name) + '</span>';
|
|
1538
|
+
if (loc) html += '<span class=\"vista-error-frame-loc\">' + escapeHtml(loc) + '</span>';
|
|
1539
|
+
html += '</button>';
|
|
1540
|
+
}
|
|
1541
|
+
return html ? '<div class=\"vista-error-frames\">' + html + '</div>' : '';
|
|
640
1542
|
}
|
|
641
1543
|
|
|
642
1544
|
function minimizeOverlay() {
|
|
@@ -663,41 +1565,84 @@ function renderErrorHTML(errors) {
|
|
|
663
1565
|
var error = currentError();
|
|
664
1566
|
if (!error) return;
|
|
665
1567
|
|
|
666
|
-
var label = getLabel(error
|
|
1568
|
+
var label = getLabel(error);
|
|
667
1569
|
var message = typeof error.message === 'string' ? error.message : String(error.message || 'Unknown Error');
|
|
668
|
-
var
|
|
669
|
-
var location = formatLocation(error);
|
|
670
|
-
var codeFrame = typeof error.codeFrame === 'string' ? error.codeFrame : '';
|
|
1570
|
+
var parts = splitMessage(message);
|
|
671
1571
|
var stack = typeof error.stack === 'string' ? error.stack.trim() : '';
|
|
1572
|
+
var related = relatedFor(error);
|
|
1573
|
+
if (state.fileTab > related.length - 1) state.fileTab = 0;
|
|
1574
|
+
var loc = related[state.fileTab] || related[0];
|
|
1575
|
+
var terminal = !hasCodeView(error);
|
|
1576
|
+
var file = String((loc && loc.file) || error.file || '').replace(/\\\\/g, '/');
|
|
1577
|
+
var tabName = terminal ? label : (loc ? tabLabelFor(loc) : 'untitled');
|
|
1578
|
+
var crumbs = file ? file.split('/').filter(Boolean).join(' › ') : 'Source';
|
|
1579
|
+
var lang = loc ? langFor(loc) : 'Plain Text';
|
|
1580
|
+
var tone = error.type === 'hydration' ? 'hydration' : error.source === 'server' ? 'server' : '';
|
|
1581
|
+
var badge = error.type === 'hydration' ? 'Hydration' : error.source === 'server' ? 'Server' : error.type === 'build' ? 'Build' : 'Client';
|
|
1582
|
+
var badgeTone = error.type === 'hydration' ? 'hydration' : error.source === 'server' ? 'server' : error.source === 'client' || error.type !== 'build' ? 'client' : '';
|
|
1583
|
+
var hint = error.hint || '';
|
|
672
1584
|
|
|
673
|
-
if (typeNode)
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
1585
|
+
if (typeNode) {
|
|
1586
|
+
typeNode.textContent = label;
|
|
1587
|
+
typeNode.className = 'vista-error-kind' + (tone ? ' is-' + tone : '');
|
|
1588
|
+
}
|
|
1589
|
+
if (problemIconNode) {
|
|
1590
|
+
problemIconNode.className = 'vista-error-problem-icon' + (tone ? ' is-' + tone : '');
|
|
1591
|
+
}
|
|
1592
|
+
if (titleNode) titleNode.textContent = parts.headline;
|
|
1593
|
+
if (detailNode) {
|
|
1594
|
+
detailNode.textContent = parts.detail;
|
|
1595
|
+
detailNode.hidden = parts.detail.length === 0;
|
|
1596
|
+
}
|
|
1597
|
+
if (hintNode) {
|
|
1598
|
+
hintNode.textContent = hint;
|
|
1599
|
+
hintNode.hidden = hint.length === 0;
|
|
678
1600
|
}
|
|
679
|
-
if (messageNode) messageNode.innerHTML = colorizeBlock(message);
|
|
680
1601
|
|
|
681
|
-
if (
|
|
682
|
-
|
|
1602
|
+
if (tabNameNodes) {
|
|
1603
|
+
for (var t = 0; t < tabNameNodes.length; t += 1) tabNameNodes[t].textContent = tabName;
|
|
1604
|
+
}
|
|
1605
|
+
if (fileTabsNode) fileTabsNode.innerHTML = renderFileTabs(related, state.fileTab);
|
|
1606
|
+
if (crumbsNode) crumbsNode.textContent = crumbs;
|
|
1607
|
+
if (statusLnNode) statusLnNode.textContent = loc && loc.line ? ('Ln ' + loc.line + ', Col ' + (loc.column || 1)) : (error.line ? ('Ln ' + error.line + ', Col ' + (error.column || 1)) : 'Ready');
|
|
1608
|
+
if (statusLangNode) statusLangNode.textContent = lang;
|
|
1609
|
+
if (sourceBadgeNode) {
|
|
1610
|
+
sourceBadgeNode.textContent = badge;
|
|
1611
|
+
sourceBadgeNode.className = 'vista-ide-source-badge' + (badgeTone ? ' is-' + badgeTone : '');
|
|
1612
|
+
}
|
|
683
1613
|
|
|
684
|
-
if (
|
|
685
|
-
if (codeNode) codeNode.innerHTML = colorizeBlock(codeFrame);
|
|
1614
|
+
if (codeNode) codeNode.innerHTML = renderLocation(loc || { file: file, codeFrame: error.codeFrame, line: error.line, column: error.column, kind: 'source' });
|
|
686
1615
|
|
|
687
1616
|
if (stackWrap) stackWrap.hidden = stack.length === 0;
|
|
688
|
-
if (stackNode) stackNode.innerHTML =
|
|
1617
|
+
if (stackNode) stackNode.innerHTML = renderStackFrames(stack);
|
|
689
1618
|
|
|
1619
|
+
if (countNode) countNode.textContent = (state.index + 1) + '/' + state.errors.length;
|
|
690
1620
|
if (paginationNode) paginationNode.hidden = state.errors.length <= 1;
|
|
691
|
-
if (countNode) countNode.textContent = (state.index + 1) + ' / ' + state.errors.length;
|
|
692
1621
|
if (prevButton) prevButton.disabled = state.index <= 0;
|
|
693
1622
|
if (nextButton) nextButton.disabled = state.index >= state.errors.length - 1;
|
|
694
1623
|
if (minimizedCount) minimizedCount.textContent = String(state.errors.length);
|
|
1624
|
+
if (mainNode) {
|
|
1625
|
+
if (terminal) {
|
|
1626
|
+
mainNode.setAttribute('data-terminal', 'true');
|
|
1627
|
+
mainNode.removeAttribute('data-panel-expanded');
|
|
1628
|
+
} else {
|
|
1629
|
+
mainNode.removeAttribute('data-terminal');
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
if (panelExpandButton) {
|
|
1633
|
+
panelExpandButton.hidden = terminal;
|
|
1634
|
+
if (terminal) {
|
|
1635
|
+
panelExpandButton.setAttribute('aria-pressed', 'false');
|
|
1636
|
+
panelExpandButton.setAttribute('aria-label', 'Expand problems panel');
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
695
1639
|
}
|
|
696
1640
|
|
|
697
1641
|
function changeIndex(offset) {
|
|
698
1642
|
var next = state.index + offset;
|
|
699
1643
|
if (next < 0 || next > state.errors.length - 1) return;
|
|
700
1644
|
state.index = next;
|
|
1645
|
+
state.fileTab = 0;
|
|
701
1646
|
render();
|
|
702
1647
|
}
|
|
703
1648
|
|
|
@@ -707,11 +1652,15 @@ function renderErrorHTML(errors) {
|
|
|
707
1652
|
backdropNode = document.querySelector('[data-vista-error-backdrop]');
|
|
708
1653
|
typeNode = document.querySelector('[data-vista-error-type]');
|
|
709
1654
|
titleNode = document.querySelector('[data-vista-error-title]');
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1655
|
+
detailNode = document.querySelector('[data-vista-error-detail]');
|
|
1656
|
+
hintNode = document.querySelector('[data-vista-error-hint]');
|
|
1657
|
+
problemIconNode = document.querySelector('.vista-error-problem-icon');
|
|
1658
|
+
tabNameNodes = document.querySelectorAll('[data-vista-tab-name]');
|
|
1659
|
+
crumbsNode = document.querySelector('[data-vista-crumbs]');
|
|
1660
|
+
statusLnNode = document.querySelector('[data-vista-status-ln]');
|
|
1661
|
+
statusLangNode = document.querySelector('[data-vista-status-lang]');
|
|
1662
|
+
sourceBadgeNode = document.querySelector('[data-vista-source-badge]');
|
|
1663
|
+
fileTabsNode = document.querySelector('[data-vista-file-tabs]');
|
|
715
1664
|
codeWrap = document.querySelector('[data-vista-code-wrap]');
|
|
716
1665
|
codeNode = document.querySelector('[data-vista-code]');
|
|
717
1666
|
stackWrap = document.querySelector('[data-vista-stack-wrap]');
|
|
@@ -723,6 +1672,8 @@ function renderErrorHTML(errors) {
|
|
|
723
1672
|
copyButton = document.querySelector('[data-vista-copy-btn]');
|
|
724
1673
|
minimizedTrigger = document.querySelector('[data-vista-minimized-trigger]');
|
|
725
1674
|
minimizedCount = document.querySelector('[data-vista-minimized-count]');
|
|
1675
|
+
mainNode = document.querySelector('[data-vista-ide-main]');
|
|
1676
|
+
panelExpandButton = document.querySelector('[data-vista-panel-expand]');
|
|
726
1677
|
|
|
727
1678
|
if (prevButton) {
|
|
728
1679
|
prevButton.addEventListener('click', function() { changeIndex(-1); });
|
|
@@ -736,7 +1687,7 @@ function renderErrorHTML(errors) {
|
|
|
736
1687
|
copyButton.addEventListener('click', function() {
|
|
737
1688
|
var error = currentError();
|
|
738
1689
|
if (!error) return;
|
|
739
|
-
var label = getLabel(error
|
|
1690
|
+
var label = getLabel(error);
|
|
740
1691
|
var message = typeof error.message === 'string' ? error.message : String(error.message || 'Unknown Error');
|
|
741
1692
|
var text = label + '\\n\\n' + message;
|
|
742
1693
|
var location = formatLocation(error);
|
|
@@ -747,11 +1698,48 @@ function renderErrorHTML(errors) {
|
|
|
747
1698
|
});
|
|
748
1699
|
}
|
|
749
1700
|
|
|
750
|
-
if (
|
|
751
|
-
|
|
1701
|
+
if (fileTabsNode) {
|
|
1702
|
+
fileTabsNode.addEventListener('click', function(event) {
|
|
1703
|
+
var target = event.target && event.target.closest ? event.target.closest('[data-vista-file-tab]') : null;
|
|
1704
|
+
if (!target) return;
|
|
1705
|
+
var nextTab = Number(target.getAttribute('data-vista-file-tab') || 0);
|
|
752
1706
|
var error = currentError();
|
|
753
|
-
|
|
754
|
-
|
|
1707
|
+
var related = error ? relatedFor(error) : [];
|
|
1708
|
+
var loc = related[nextTab];
|
|
1709
|
+
if (nextTab === state.fileTab && loc && loc.kind === 'source' && loc.file && loc.file.indexOf('.html') === -1) {
|
|
1710
|
+
vistaOpenInEditor(loc.file, Number(loc.line || 1), Number(loc.column || 1));
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
state.fileTab = nextTab;
|
|
1714
|
+
render();
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
if (panelExpandButton && mainNode) {
|
|
1719
|
+
panelExpandButton.addEventListener('click', function() {
|
|
1720
|
+
if (mainNode.getAttribute('data-terminal') === 'true') return;
|
|
1721
|
+
var expanded = mainNode.getAttribute('data-panel-expanded') === 'true';
|
|
1722
|
+
if (expanded) {
|
|
1723
|
+
mainNode.removeAttribute('data-panel-expanded');
|
|
1724
|
+
panelExpandButton.setAttribute('aria-pressed', 'false');
|
|
1725
|
+
panelExpandButton.setAttribute('aria-label', 'Expand problems panel');
|
|
1726
|
+
} else {
|
|
1727
|
+
mainNode.setAttribute('data-panel-expanded', 'true');
|
|
1728
|
+
panelExpandButton.setAttribute('aria-pressed', 'true');
|
|
1729
|
+
panelExpandButton.setAttribute('aria-label', 'Restore problems panel');
|
|
1730
|
+
}
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
if (stackWrap) {
|
|
1735
|
+
stackWrap.addEventListener('click', function(event) {
|
|
1736
|
+
var target = event.target && event.target.closest ? event.target.closest('[data-vista-open-file]') : null;
|
|
1737
|
+
if (!target) return;
|
|
1738
|
+
vistaOpenInEditor(
|
|
1739
|
+
target.getAttribute('data-vista-open-file'),
|
|
1740
|
+
Number(target.getAttribute('data-vista-open-line') || 1),
|
|
1741
|
+
Number(target.getAttribute('data-vista-open-col') || 1)
|
|
1742
|
+
);
|
|
755
1743
|
});
|
|
756
1744
|
}
|
|
757
1745
|
|
|
@@ -779,6 +1767,14 @@ function renderErrorHTML(errors) {
|
|
|
779
1767
|
} else if (event.key === 'ArrowRight') {
|
|
780
1768
|
changeIndex(1);
|
|
781
1769
|
} else if (event.key === 'Escape') {
|
|
1770
|
+
if (mainNode && mainNode.getAttribute('data-panel-expanded') === 'true' && mainNode.getAttribute('data-terminal') !== 'true') {
|
|
1771
|
+
mainNode.removeAttribute('data-panel-expanded');
|
|
1772
|
+
if (panelExpandButton) {
|
|
1773
|
+
panelExpandButton.setAttribute('aria-pressed', 'false');
|
|
1774
|
+
panelExpandButton.setAttribute('aria-label', 'Expand problems panel');
|
|
1775
|
+
}
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
782
1778
|
minimizeOverlay();
|
|
783
1779
|
}
|
|
784
1780
|
});
|
|
@@ -795,53 +1791,73 @@ function renderErrorHTML(errors) {
|
|
|
795
1791
|
<div class="vista-error-page-root" data-vista-error-root>
|
|
796
1792
|
<div class="vista-error-backdrop" data-vista-error-backdrop></div>
|
|
797
1793
|
<section class="vista-error-panel" data-vista-error-panel role="dialog" aria-label="Vista Error Overlay" aria-modal="true">
|
|
798
|
-
<
|
|
799
|
-
<div class="vista-
|
|
800
|
-
<
|
|
801
|
-
<span class="vista-error-badge" data-vista-error-type>
|
|
802
|
-
<span class="vista-error-badge-dot"></span>${escapeHtml(firstLabel)}
|
|
803
|
-
</span>
|
|
804
|
-
<div class="vista-error-pagination" data-vista-pagination${normalizedErrors.length <= 1 ? ' hidden' : ''}>
|
|
805
|
-
<button type="button" class="vista-error-page-btn" data-vista-prev-btn aria-label="Previous error"><</button>
|
|
806
|
-
<span class="vista-error-page-count" data-vista-count>1 / ${normalizedErrors.length}</span>
|
|
807
|
-
<button type="button" class="vista-error-page-btn" data-vista-next-btn aria-label="Next error">></button>
|
|
808
|
-
</div>
|
|
809
|
-
</div>
|
|
810
|
-
<h2 class="vista-error-title" data-vista-error-title>${escapeHtml(firstTitle)}</h2>
|
|
811
|
-
<p class="vista-error-meta" data-vista-error-meta>Vista Dev Overlay</p>
|
|
1794
|
+
<div class="vista-ide-titlebar">
|
|
1795
|
+
<div class="vista-ide-traffic" aria-hidden="true">
|
|
1796
|
+
<span class="is-close"></span><span class="is-min"></span><span class="is-max"></span>
|
|
812
1797
|
</div>
|
|
813
|
-
<div class="vista-
|
|
814
|
-
|
|
815
|
-
|
|
1798
|
+
<div class="vista-ide-title">Vista — <span data-vista-tab-name>${escapeHtml(firstTitleName)}</span></div>
|
|
1799
|
+
<div class="vista-error-toolbar">
|
|
1800
|
+
<button type="button" class="vista-error-icon-btn" data-vista-copy-btn aria-label="Copy error">
|
|
1801
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><rect x="9" y="9" width="10" height="10" rx="2" stroke="currentColor" stroke-width="1.6"/><rect x="5" y="5" width="10" height="10" rx="2" stroke="currentColor" stroke-width="1.6"/></svg>
|
|
816
1802
|
</button>
|
|
817
|
-
<button type="button" class="vista-error-btn" onclick="vistaReload()" aria-label="Reload page">
|
|
818
|
-
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M20 12a8 8 0 1 1-2.34-5.66" stroke="currentColor" stroke-width="
|
|
1803
|
+
<button type="button" class="vista-error-icon-btn" onclick="vistaReload()" aria-label="Reload page">
|
|
1804
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M20 12a8 8 0 1 1-2.34-5.66" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><path d="M20 4V10H14" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
819
1805
|
</button>
|
|
1806
|
+
<div class="vista-error-pagination" data-vista-pagination${showPager ? '' : ' hidden'}>
|
|
1807
|
+
<button type="button" class="vista-error-page-btn" data-vista-prev-btn aria-label="Previous error">‹</button>
|
|
1808
|
+
<span class="vista-error-page-count" data-vista-count>1/${normalizedErrors.length}</span>
|
|
1809
|
+
<button type="button" class="vista-error-page-btn" data-vista-next-btn aria-label="Next error">›</button>
|
|
1810
|
+
</div>
|
|
1811
|
+
</div>
|
|
1812
|
+
</div>
|
|
1813
|
+
<div class="vista-ide-workbench">
|
|
1814
|
+
<aside class="vista-ide-activity" aria-hidden="true">
|
|
1815
|
+
<span class="vista-ide-activity-item is-active">
|
|
1816
|
+
<svg viewBox="0 0 24 24" fill="none"><rect x="4" y="3" width="10" height="13" rx="1.2" stroke="currentColor" stroke-width="1.6"/><rect x="10" y="8" width="10" height="13" rx="1.2" stroke="currentColor" stroke-width="1.6"/></svg>
|
|
1817
|
+
</span>
|
|
1818
|
+
</aside>
|
|
1819
|
+
<div class="vista-ide-main" data-vista-ide-main${firstTerminal ? ' data-terminal="true"' : ''}>
|
|
1820
|
+
<div class="vista-ide-tabbar">
|
|
1821
|
+
<div class="vista-ide-tabs" data-vista-file-tabs>
|
|
1822
|
+
${firstTabsHtml}
|
|
1823
|
+
</div>
|
|
1824
|
+
</div>
|
|
1825
|
+
<div class="vista-ide-crumbs" data-vista-crumbs>${escapeHtml(firstCrumbs || firstLocation || 'Source')}</div>
|
|
1826
|
+
<div class="vista-error-code" data-vista-code-wrap>
|
|
1827
|
+
<div class="vista-error-editor-host" data-vista-code>${firstCodeHtml}</div>
|
|
1828
|
+
</div>
|
|
1829
|
+
<div class="vista-ide-statusbar">
|
|
1830
|
+
<span data-vista-status-ln>${escapeHtml(firstStatus)}</span>
|
|
1831
|
+
<span data-vista-status-lang>${escapeHtml(firstLang)}</span>
|
|
1832
|
+
<span class="vista-ide-source-badge${firstBadge ? ` is-${firstBadge.tone}` : ''}" data-vista-source-badge>${escapeHtml(firstBadge ? firstBadge.label : 'Client')}</span>
|
|
1833
|
+
<span>UTF-8</span>
|
|
1834
|
+
</div>
|
|
1835
|
+
<div class="vista-ide-panel">
|
|
1836
|
+
<div class="vista-ide-panel-tabs">
|
|
1837
|
+
<span class="is-active">PROBLEMS</span>
|
|
1838
|
+
<span>CALL STACK</span>
|
|
1839
|
+
<button type="button" class="vista-error-icon-btn vista-ide-panel-toggle" data-vista-panel-expand aria-label="Expand problems panel" aria-pressed="false"${firstTerminal ? ' hidden' : ''}>
|
|
1840
|
+
<svg class="vista-ide-icon-expand" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 6.5V3h3.5M13 6.5V3h-3.5M3 9.5V13h3.5M13 9.5V13h-3.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
1841
|
+
<svg class="vista-ide-icon-restore" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6.5 3v3.5H3M9.5 3v3.5H13M6.5 13V9.5H3M9.5 13V9.5H13" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
1842
|
+
</button>
|
|
1843
|
+
</div>
|
|
1844
|
+
<div class="vista-error-body">
|
|
1845
|
+
<div class="vista-error-problem">
|
|
1846
|
+
<span class="vista-error-problem-icon${firstTone ? ` is-${firstTone}` : ''}" aria-hidden="true"></span>
|
|
1847
|
+
<div>
|
|
1848
|
+
<p class="vista-error-kind${firstTone ? ` is-${firstTone}` : ''}" data-vista-error-type>${escapeHtml(firstLabel)}</p>
|
|
1849
|
+
<h1 class="vista-error-headline" data-vista-error-title>${escapeHtml(firstParts.headline)}</h1>
|
|
1850
|
+
<p class="vista-error-detail" data-vista-error-detail${firstParts.detail ? '' : ' hidden'}>${escapeHtml(firstParts.detail)}</p>
|
|
1851
|
+
<p class="vista-error-hint" data-vista-error-hint${firstHint ? '' : ' hidden'}>${escapeHtml(firstHint)}</p>
|
|
1852
|
+
</div>
|
|
1853
|
+
</div>
|
|
1854
|
+
<div class="vista-error-stack" data-vista-stack-wrap${firstStack ? '' : ' hidden'}>
|
|
1855
|
+
<h2 class="vista-error-stack-title">CALL STACK</h2>
|
|
1856
|
+
<div class="vista-error-frames-host" data-vista-stack>${firstStackHtml}</div>
|
|
1857
|
+
</div>
|
|
1858
|
+
</div>
|
|
1859
|
+
</div>
|
|
820
1860
|
</div>
|
|
821
|
-
</header>
|
|
822
|
-
|
|
823
|
-
<div class="vista-error-body">
|
|
824
|
-
<section class="vista-error-card" data-vista-location-wrap${firstLocation ? '' : ' hidden'}>
|
|
825
|
-
<h3 class="vista-error-card-title">Location</h3>
|
|
826
|
-
<button type="button" class="vista-error-location" data-vista-location-trigger>
|
|
827
|
-
<span data-vista-location-text>${escapeHtml(firstLocation)}</span>
|
|
828
|
-
</button>
|
|
829
|
-
</section>
|
|
830
|
-
|
|
831
|
-
<section class="vista-error-card">
|
|
832
|
-
<h3 class="vista-error-card-title">Message</h3>
|
|
833
|
-
<pre class="vista-error-pre" data-vista-error-message>${firstMessageHtml}</pre>
|
|
834
|
-
</section>
|
|
835
|
-
|
|
836
|
-
<section class="vista-error-card" data-vista-code-wrap${firstCode ? '' : ' hidden'}>
|
|
837
|
-
<h3 class="vista-error-card-title">Code Frame</h3>
|
|
838
|
-
<pre class="vista-error-pre" data-vista-code>${firstCodeHtml}</pre>
|
|
839
|
-
</section>
|
|
840
|
-
|
|
841
|
-
<section class="vista-error-card" data-vista-stack-wrap${firstStack ? '' : ' hidden'}>
|
|
842
|
-
<h3 class="vista-error-card-title">Stack Trace</h3>
|
|
843
|
-
<pre class="vista-error-pre" data-vista-stack>${firstStackHtml}</pre>
|
|
844
|
-
</section>
|
|
845
1861
|
</div>
|
|
846
1862
|
</section>
|
|
847
1863
|
<button type="button" class="vista-error-minimized-trigger" data-vista-minimized-trigger hidden aria-label="Reopen error overlay">
|
|
@@ -860,33 +1876,59 @@ function ErrorOverlay({ errors }) {
|
|
|
860
1876
|
const normalizedErrors = react_1.default.useMemo(() => normalizeErrors(errors), [errors]);
|
|
861
1877
|
const [activeIndex, setActiveIndex] = react_1.default.useState(0);
|
|
862
1878
|
const [isMinimized, setIsMinimized] = react_1.default.useState(false);
|
|
1879
|
+
const [panelExpanded, setPanelExpanded] = react_1.default.useState(false);
|
|
1880
|
+
const [fileTab, setFileTab] = react_1.default.useState(0);
|
|
863
1881
|
react_1.default.useEffect(() => {
|
|
864
1882
|
if (activeIndex > normalizedErrors.length - 1) {
|
|
865
1883
|
setActiveIndex(0);
|
|
866
1884
|
}
|
|
1885
|
+
setFileTab(0);
|
|
867
1886
|
}, [activeIndex, normalizedErrors.length]);
|
|
868
1887
|
const currentIndex = Math.max(0, Math.min(activeIndex, normalizedErrors.length - 1));
|
|
869
1888
|
const error = normalizedErrors[currentIndex];
|
|
870
1889
|
if (!error) {
|
|
871
1890
|
return (0, jsx_runtime_1.jsx)("div", {});
|
|
872
1891
|
}
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
|
|
1892
|
+
const related = error.related && error.related.length > 0
|
|
1893
|
+
? error.related
|
|
1894
|
+
: [
|
|
1895
|
+
{
|
|
1896
|
+
file: error.file || 'untitled',
|
|
1897
|
+
line: error.line,
|
|
1898
|
+
column: error.column,
|
|
1899
|
+
codeFrame: error.codeFrame,
|
|
1900
|
+
kind: 'source',
|
|
1901
|
+
},
|
|
1902
|
+
];
|
|
1903
|
+
const activeLocation = related[Math.max(0, Math.min(fileTab, related.length - 1))] || related[0];
|
|
1904
|
+
const isTerminal = !hasCodeView(error);
|
|
1905
|
+
const label = getErrorTypeLabel(error);
|
|
1906
|
+
const tone = problemTone(error);
|
|
1907
|
+
const badge = sourceBadge(error);
|
|
1908
|
+
const parts = splitMessage(error.message || 'Unknown Error');
|
|
1909
|
+
const location = formatCodeHeader(error) || formatLocation(error);
|
|
876
1910
|
const stackText = parseStackTrace(error.stack || '').join('\n');
|
|
877
|
-
const
|
|
878
|
-
const
|
|
879
|
-
const
|
|
880
|
-
const
|
|
1911
|
+
const codeHtml = renderLocationEditor(activeLocation);
|
|
1912
|
+
const stackHtml = renderStackFramesHtml(stackText);
|
|
1913
|
+
const tabName = tabLabel(activeLocation);
|
|
1914
|
+
const crumbs = fileBreadcrumb(activeLocation.file) || location || 'Source';
|
|
1915
|
+
const status = activeLocation.line
|
|
1916
|
+
? `Ln ${activeLocation.line}, Col ${activeLocation.column || 1}`
|
|
1917
|
+
: statusLine(error);
|
|
1918
|
+
const language = activeLocation.kind === 'server' || activeLocation.kind === 'client'
|
|
1919
|
+
? 'HTML'
|
|
1920
|
+
: activeLocation.kind === 'log'
|
|
1921
|
+
? 'Log'
|
|
1922
|
+
: languageFromFile(activeLocation.file);
|
|
881
1923
|
const minimizeOverlay = react_1.default.useCallback(() => {
|
|
882
1924
|
setIsMinimized(true);
|
|
883
1925
|
if (typeof window !== 'undefined') {
|
|
884
1926
|
const indicator = window.__VISTA_DEVTOOLS_INDICATOR__;
|
|
885
1927
|
if (indicator && typeof indicator.setError === 'function') {
|
|
886
|
-
indicator.setError(
|
|
1928
|
+
indicator.setError(parts.headline || 'Error', normalizedErrors.length);
|
|
887
1929
|
}
|
|
888
1930
|
}
|
|
889
|
-
}, [normalizedErrors.length,
|
|
1931
|
+
}, [normalizedErrors.length, parts.headline]);
|
|
890
1932
|
const restoreOverlay = react_1.default.useCallback(() => {
|
|
891
1933
|
setIsMinimized(false);
|
|
892
1934
|
if (typeof window !== 'undefined') {
|
|
@@ -899,7 +1941,12 @@ function ErrorOverlay({ errors }) {
|
|
|
899
1941
|
react_1.default.useEffect(() => {
|
|
900
1942
|
const onKeyDown = (event) => {
|
|
901
1943
|
if (event.key === 'Escape') {
|
|
902
|
-
|
|
1944
|
+
if (panelExpanded && !isTerminal) {
|
|
1945
|
+
setPanelExpanded(false);
|
|
1946
|
+
}
|
|
1947
|
+
else {
|
|
1948
|
+
minimizeOverlay();
|
|
1949
|
+
}
|
|
903
1950
|
}
|
|
904
1951
|
else if (event.key === 'ArrowLeft') {
|
|
905
1952
|
setActiveIndex((idx) => Math.max(0, idx - 1));
|
|
@@ -910,12 +1957,23 @@ function ErrorOverlay({ errors }) {
|
|
|
910
1957
|
};
|
|
911
1958
|
window.addEventListener('keydown', onKeyDown);
|
|
912
1959
|
return () => window.removeEventListener('keydown', onKeyDown);
|
|
913
|
-
}, [minimizeOverlay, normalizedErrors.length]);
|
|
914
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "vista-error-page-root", "data-embedded": "true", "data-minimized": isMinimized ? 'true' : undefined, children: [(0, jsx_runtime_1.jsx)("style", { children: OVERLAY_STYLES }), (0, jsx_runtime_1.jsx)("div", { className: "vista-error-backdrop", onClick: minimizeOverlay }), (0, jsx_runtime_1.jsxs)("section", { className: "vista-error-panel", role: "dialog", "aria-label": "Vista Error Overlay", "aria-modal": true, onClick: (event) => event.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("
|
|
1960
|
+
}, [minimizeOverlay, normalizedErrors.length, panelExpanded, isTerminal]);
|
|
1961
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "vista-error-page-root", "data-embedded": "true", "data-minimized": isMinimized ? 'true' : undefined, children: [(0, jsx_runtime_1.jsx)("style", { children: OVERLAY_STYLES }), (0, jsx_runtime_1.jsx)("div", { className: "vista-error-backdrop", onClick: minimizeOverlay }), (0, jsx_runtime_1.jsxs)("section", { className: "vista-error-panel", role: "dialog", "aria-label": "Vista Error Overlay", "aria-modal": true, onClick: (event) => event.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-titlebar", children: [(0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-traffic", "aria-hidden": "true", children: [(0, jsx_runtime_1.jsx)("span", { className: "is-close" }), (0, jsx_runtime_1.jsx)("span", { className: "is-min" }), (0, jsx_runtime_1.jsx)("span", { className: "is-max" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-title", children: ["Vista \u2014 ", (0, jsx_runtime_1.jsx)("span", { children: isTerminal ? label : tabName })] }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-error-toolbar", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "vista-error-icon-btn", onClick: () => copyTextInBrowser(serializeErrorForCopy(error)), "aria-label": "Copy error", children: (0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("rect", { x: "9", y: "9", width: "10", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.6" }), (0, jsx_runtime_1.jsx)("rect", { x: "5", y: "5", width: "10", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.6" })] }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "vista-error-icon-btn", onClick: () => {
|
|
915
1962
|
if (typeof window !== 'undefined') {
|
|
916
1963
|
window.location.reload();
|
|
917
1964
|
}
|
|
918
|
-
}, "aria-label": "Reload page", children: (0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 12a8 8 0 1 1-2.34-5.66", stroke: "currentColor", strokeWidth: "
|
|
1965
|
+
}, "aria-label": "Reload page", children: (0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 12a8 8 0 1 1-2.34-5.66", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }), (0, jsx_runtime_1.jsx)("path", { d: "M20 4V10H14", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" })] }) }), normalizedErrors.length > 1 ? ((0, jsx_runtime_1.jsxs)("div", { className: "vista-error-pagination", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "vista-error-page-btn", onClick: () => setActiveIndex((idx) => Math.max(0, idx - 1)), disabled: currentIndex === 0, "aria-label": "Previous error", children: "\u2039" }), (0, jsx_runtime_1.jsxs)("span", { className: "vista-error-page-count", children: [currentIndex + 1, "/", normalizedErrors.length] }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "vista-error-page-btn", onClick: () => setActiveIndex((idx) => Math.min(normalizedErrors.length - 1, idx + 1)), disabled: currentIndex >= normalizedErrors.length - 1, "aria-label": "Next error", children: "\u203A" })] })) : null] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-workbench", children: [(0, jsx_runtime_1.jsx)("aside", { className: "vista-ide-activity", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("span", { className: "vista-ide-activity-item is-active", children: (0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", children: [(0, jsx_runtime_1.jsx)("rect", { x: "4", y: "3", width: "10", height: "13", rx: "1.2", stroke: "currentColor", strokeWidth: "1.6" }), (0, jsx_runtime_1.jsx)("rect", { x: "10", y: "8", width: "10", height: "13", rx: "1.2", stroke: "currentColor", strokeWidth: "1.6" })] }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-main", "data-panel-expanded": !isTerminal && panelExpanded ? 'true' : undefined, "data-terminal": isTerminal ? 'true' : undefined, children: [(0, jsx_runtime_1.jsx)("div", { className: "vista-ide-tabbar", children: (0, jsx_runtime_1.jsx)("div", { className: "vista-ide-tabs", children: related.map((item, index) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: `vista-ide-tab${index === fileTab ? '' : ' is-inactive'}`, onClick: () => {
|
|
1966
|
+
if (index === fileTab && item.kind === 'source' && item.file && !item.file.endsWith('.html')) {
|
|
1967
|
+
openInEditorFromBrowser(item.file, item.line, item.column);
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
setFileTab(index);
|
|
1971
|
+
}, children: [(0, jsx_runtime_1.jsxs)("svg", { className: "vista-ide-tab-icon", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [(0, jsx_runtime_1.jsx)("rect", { x: "3", y: "2", width: "10", height: "12", rx: "1.5", stroke: "#4fc1ff", strokeWidth: "1.4" }), (0, jsx_runtime_1.jsx)("path", { d: "M6 6h4M6 9h4M6 12h2", stroke: "#4fc1ff", strokeWidth: "1.2", strokeLinecap: "round" })] }), (0, jsx_runtime_1.jsx)("span", { children: tabLabel(item) })] }, `${item.kind || 'source'}:${item.file}:${index}`))) }) }), (0, jsx_runtime_1.jsx)("div", { className: "vista-ide-crumbs", children: crumbs }), (0, jsx_runtime_1.jsx)("div", { className: "vista-error-code", children: (0, jsx_runtime_1.jsx)("div", { className: "vista-error-editor-host", dangerouslySetInnerHTML: { __html: codeHtml } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-statusbar", children: [(0, jsx_runtime_1.jsx)("span", { children: status }), (0, jsx_runtime_1.jsx)("span", { children: language }), badge ? ((0, jsx_runtime_1.jsx)("span", { className: `vista-ide-source-badge${badge.tone ? ` is-${badge.tone}` : ''}`, children: badge.label })) : null, (0, jsx_runtime_1.jsx)("span", { children: "UTF-8" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-panel", children: [(0, jsx_runtime_1.jsxs)("div", { className: "vista-ide-panel-tabs", children: [(0, jsx_runtime_1.jsx)("span", { className: "is-active", children: "PROBLEMS" }), (0, jsx_runtime_1.jsx)("span", { children: "CALL STACK" }), !isTerminal ? ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "vista-error-icon-btn vista-ide-panel-toggle", onClick: () => setPanelExpanded((open) => !open), "aria-label": panelExpanded ? 'Restore problems panel' : 'Expand problems panel', "aria-pressed": panelExpanded, children: [(0, jsx_runtime_1.jsx)("svg", { className: "vista-ide-icon-expand", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M3 6.5V3h3.5M13 6.5V3h-3.5M3 9.5V13h3.5M13 9.5V13h-3.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }) }), (0, jsx_runtime_1.jsx)("svg", { className: "vista-ide-icon-restore", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M6.5 3v3.5H3M9.5 3v3.5H13M6.5 13V9.5H3M9.5 13V9.5H13", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }) })] })) : null] }), (0, jsx_runtime_1.jsxs)("div", { className: "vista-error-body", children: [(0, jsx_runtime_1.jsxs)("div", { className: "vista-error-problem", children: [(0, jsx_runtime_1.jsx)("span", { className: `vista-error-problem-icon${tone ? ` is-${tone}` : ''}`, "aria-hidden": "true" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: `vista-error-kind${tone ? ` is-${tone}` : ''}`, children: label }), (0, jsx_runtime_1.jsx)("h1", { className: "vista-error-headline", children: parts.headline }), parts.detail ? (0, jsx_runtime_1.jsx)("p", { className: "vista-error-detail", children: parts.detail }) : null, error.hint ? (0, jsx_runtime_1.jsx)("p", { className: "vista-error-hint", children: error.hint }) : null] })] }), stackText ? ((0, jsx_runtime_1.jsxs)("div", { className: "vista-error-stack", children: [(0, jsx_runtime_1.jsx)("h2", { className: "vista-error-stack-title", children: "CALL STACK" }), (0, jsx_runtime_1.jsx)("div", { className: "vista-error-frames-host", dangerouslySetInnerHTML: { __html: stackHtml }, onClick: (event) => {
|
|
1972
|
+
const target = event.target.closest('[data-vista-open-file]');
|
|
1973
|
+
if (!target)
|
|
1974
|
+
return;
|
|
1975
|
+
openInEditorFromBrowser(target.getAttribute('data-vista-open-file') || undefined, Number(target.getAttribute('data-vista-open-line') || 1), Number(target.getAttribute('data-vista-open-col') || 1));
|
|
1976
|
+
} })] })) : null] })] })] })] })] }), isMinimized ? ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: "vista-error-minimized-trigger", onClick: restoreOverlay, "aria-label": "Reopen error overlay", children: [(0, jsx_runtime_1.jsx)("svg", { className: "vista-error-minimized-logo", viewBox: "0 0 168 177", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: (0, jsx_runtime_1.jsx)("path", { d: "M81.872 176.988L-2.01405e-06 -2.68173e-06H30.5816L83.5576 121.604L136.774 -2.68173e-06H167.115L85.484 176.988H81.872Z", fill: "white" }) }), (0, jsx_runtime_1.jsx)("span", { className: "vista-error-minimized-close", children: "\u00D7" }), (0, jsx_runtime_1.jsx)("span", { className: "vista-error-minimized-count", children: normalizedErrors.length })] })) : null] }));
|
|
919
1977
|
}
|
|
920
1978
|
// ============================================================================
|
|
921
1979
|
// Error Boundary (client-side)
|