@gracile-labs/better-errors 0.1.0-next.0

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.
@@ -0,0 +1,549 @@
1
+ /* eslint-disable max-lines */
2
+ import { css } from 'lit';
3
+ export const style = css `
4
+ :host {
5
+ --sl-color-emerald-50: rgb(236, 253, 245);
6
+ --sl-color-emerald-100: rgb(209, 250, 229);
7
+ --sl-color-emerald-200: rgb(167, 243, 208);
8
+ --sl-color-emerald-300: rgb(110, 231, 183);
9
+ --sl-color-emerald-400: rgb(52, 211, 153);
10
+ --sl-color-emerald-500: rgb(16, 185, 129);
11
+ --sl-color-emerald-600: rgb(5, 150, 105);
12
+ --sl-color-emerald-700: rgb(4, 120, 87);
13
+ --sl-color-emerald-800: rgb(6, 95, 70);
14
+ --sl-color-emerald-900: rgb(6, 78, 59);
15
+ --sl-color-emerald-950: rgb(3, 45, 34);
16
+
17
+ --sl-color-neutral-50: var(--sl-color-gray-50);
18
+ --sl-color-neutral-100: var(--sl-color-gray-100);
19
+ --sl-color-neutral-200: var(--sl-color-gray-200);
20
+ --sl-color-neutral-300: var(--sl-color-gray-300);
21
+ --sl-color-neutral-400: var(--sl-color-gray-400);
22
+ --sl-color-neutral-500: var(--sl-color-gray-500);
23
+ --sl-color-neutral-600: var(--sl-color-gray-600);
24
+ --sl-color-neutral-700: var(--sl-color-gray-700);
25
+ --sl-color-neutral-800: var(--sl-color-gray-800);
26
+ --sl-color-neutral-900: var(--sl-color-gray-900);
27
+ --sl-color-neutral-950: var(--sl-color-gray-950);
28
+
29
+ --sl-color-sky-50: hsl(203 63.8% 20.9%);
30
+ --sl-color-sky-100: hsl(203.4 70.4% 28%);
31
+ --sl-color-sky-200: hsl(202.7 75.8% 30.8%);
32
+ --sl-color-sky-300: hsl(203.1 80.4% 36.1%);
33
+ --sl-color-sky-400: hsl(202.1 80.5% 44.3%);
34
+ --sl-color-sky-500: hsl(199.7 85.9% 47.7%);
35
+ --sl-color-sky-600: hsl(198.7 97.9% 57.2%);
36
+ --sl-color-sky-700: hsl(198.7 100% 70.5%);
37
+ --sl-color-sky-800: hsl(198.8 100% 82.5%);
38
+ --sl-color-sky-900: hsl(198.5 100% 89.9%);
39
+ --sl-color-sky-950: hsl(186 100% 95.5%);
40
+ }
41
+
42
+ /* */
43
+
44
+ * {
45
+ box-sizing: border-box;
46
+ }
47
+
48
+ :host {
49
+ /** Needed so Playwright can find the element */
50
+ position: fixed;
51
+ top: 0;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 100%;
55
+ z-index: 99999;
56
+
57
+ /* Fonts */
58
+ --font-normal: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
59
+ 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
60
+ 'Helvetica Neue', Arial, sans-serif;
61
+ --font-monospace: ui-monospace, Menlo, Monaco, 'Cascadia Mono',
62
+ 'Segoe UI Mono', 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace',
63
+ 'Source Code Pro', 'Fira Mono', 'Droid Sans Mono', 'Courier New',
64
+ monospace;
65
+
66
+ /* Borders */
67
+ --roundiness: 4px;
68
+
69
+ /* Colors */
70
+ --background: #ffffff;
71
+ --error-text: #ba1212;
72
+ --error-text-hover: #a10000;
73
+ --title-text: #090b11;
74
+ --box-background: #f3f4f7;
75
+ --box-background-hover: #dadbde;
76
+ --hint-text: #505d84;
77
+ --hint-text-hover: #37446b;
78
+ --border: #c3cadb;
79
+ --accent: var(--sl-color-emerald-700);
80
+ --accent-hover: var(--sl-color-emerald-800);
81
+ /* --accent: #5f11a6;
82
+ --accent-hover: #792bc0; */
83
+ --stack-text: #3d4663;
84
+ --misc-text: #6474a2;
85
+
86
+ --betterr-logo-overlay: linear-gradient(
87
+ 180deg,
88
+ rgba(255, 255, 255, 0) 3.95%,
89
+ rgba(255, 255, 255, 0.0086472) 9.68%,
90
+ rgba(255, 255, 255, 0.03551) 15.4%,
91
+ rgba(255, 255, 255, 0.0816599) 21.13%,
92
+ rgba(255, 255, 255, 0.147411) 26.86%,
93
+ rgba(255, 255, 255, 0.231775) 32.58%,
94
+ rgba(255, 255, 255, 0.331884) 38.31%,
95
+ rgba(255, 255, 255, 0.442691) 44.03%,
96
+ rgba(255, 255, 255, 0.557309) 49.76%,
97
+ rgba(255, 255, 255, 0.668116) 55.48%,
98
+ rgba(255, 255, 255, 0.768225) 61.21%,
99
+ rgba(255, 255, 255, 0.852589) 66.93%,
100
+ rgba(255, 255, 255, 0.91834) 72.66%,
101
+ rgba(255, 255, 255, 0.96449) 78.38%,
102
+ rgba(255, 255, 255, 0.991353) 84.11%,
103
+ #ffffff 89.84%
104
+ );
105
+
106
+ /* Theme toggle */
107
+ --toggle-ball-color: var(--accent);
108
+ --toggle-table-background: var(--background);
109
+ --sun-icon-color: #ffffff;
110
+ --moon-icon-color: #a3acc8;
111
+ --toggle-border-color: #c3cadb;
112
+
113
+ /* Syntax Highlighting */
114
+ --betterr-code-foreground: #000000;
115
+ --betterr-code-token-constant: #4ca48f;
116
+ --betterr-code-token-string: #9f722a;
117
+ --betterr-code-token-comment: #8490b5;
118
+ --betterr-code-token-keyword: var(--accent);
119
+ --betterr-code-token-parameter: #aa0000;
120
+ --betterr-code-token-function: #4ca48f;
121
+ --betterr-code-token-string-expression: #9f722a;
122
+ --betterr-code-token-punctuation: #000000;
123
+ --betterr-code-token-link: #9f722a;
124
+ }
125
+
126
+ :host(.betterr-dark) {
127
+ --background: #090b11;
128
+ --error-text: #f49090;
129
+ --error-text-hover: #ffaaaa;
130
+ --title-text: #ffffff;
131
+ --box-background: #141925;
132
+ --box-background-hover: #2e333f;
133
+ --hint-text: #a3acc8;
134
+ --hint-text-hover: #bdc6e2;
135
+ --border: #283044;
136
+ --accent: var(--sl-color-emerald-300);
137
+ --accent-hover: var(--sl-color-emerald-200);
138
+ /* --accent: #c490f4;
139
+ --accent-hover: #deaaff; */
140
+ --stack-text: #c3cadb;
141
+ --misc-text: #8490b5;
142
+
143
+ --betterr-logo-overlay: linear-gradient(
144
+ 180deg,
145
+ rgba(9, 11, 17, 0) 3.95%,
146
+ rgba(9, 11, 17, 0.0086472) 9.68%,
147
+ rgba(9, 11, 17, 0.03551) 15.4%,
148
+ rgba(9, 11, 17, 0.0816599) 21.13%,
149
+ rgba(9, 11, 17, 0.147411) 26.86%,
150
+ rgba(9, 11, 17, 0.231775) 32.58%,
151
+ rgba(9, 11, 17, 0.331884) 38.31%,
152
+ rgba(9, 11, 17, 0.442691) 44.03%,
153
+ rgba(9, 11, 17, 0.557309) 49.76%,
154
+ rgba(9, 11, 17, 0.668116) 55.48%,
155
+ rgba(9, 11, 17, 0.768225) 61.21%,
156
+ rgba(9, 11, 17, 0.852589) 66.93%,
157
+ rgba(9, 11, 17, 0.91834) 72.66%,
158
+ rgba(9, 11, 17, 0.96449) 78.38%,
159
+ rgba(9, 11, 17, 0.991353) 84.11%,
160
+ #090b11 89.84%
161
+ );
162
+
163
+ /* Theme toggle */
164
+ --sun-icon-color: #505d84;
165
+ --moon-icon-color: #090b11;
166
+ --toggle-border-color: #3d4663;
167
+
168
+ /* Syntax Highlighting */
169
+ --betterr-code-foreground: #ffffff;
170
+ --betterr-code-token-constant: #90f4e3;
171
+ --betterr-code-token-string: #f4cf90;
172
+ --betterr-code-token-comment: #8490b5;
173
+ --betterr-code-token-keyword: var(--accent);
174
+ --betterr-code-token-parameter: #aa0000;
175
+ --betterr-code-token-function: #90f4e3;
176
+ --betterr-code-token-string-expression: #f4cf90;
177
+ --betterr-code-token-punctuation: #ffffff;
178
+ --betterr-code-token-link: #f4cf90;
179
+ }
180
+
181
+ #theme-toggle-wrapper {
182
+ position: relative;
183
+ display: inline-block;
184
+ }
185
+
186
+ #theme-toggle-wrapper > div {
187
+ position: absolute;
188
+ right: 3px;
189
+ margin-top: 3px;
190
+ }
191
+
192
+ .theme-toggle-checkbox {
193
+ opacity: 0;
194
+ position: absolute;
195
+ }
196
+
197
+ #theme-toggle-label {
198
+ background-color: var(--toggle-table-background);
199
+ border-radius: 50px;
200
+ cursor: pointer;
201
+ display: flex;
202
+ align-items: center;
203
+ justify-content: space-between;
204
+ padding: 7.5px;
205
+ position: relative;
206
+ width: 66px;
207
+ height: 30px;
208
+ transform: scale(1.2);
209
+ box-shadow: 0 0 0 1px var(--toggle-border-color);
210
+ outline: 1px solid transparent;
211
+ }
212
+
213
+ .theme-toggle-checkbox:focus ~ #theme-toggle-label {
214
+ outline: 2px solid var(--toggle-border-color);
215
+ outline-offset: 4px;
216
+ }
217
+
218
+ #theme-toggle-label #theme-toggle-ball {
219
+ background-color: var(--accent);
220
+ border-radius: 50%;
221
+ position: absolute;
222
+ height: 30px;
223
+ width: 30px;
224
+ transform: translateX(-7.5px);
225
+ transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
226
+ }
227
+
228
+ @media (forced-colors: active) {
229
+ #theme-toggle-label {
230
+ --moon-icon-color: CanvasText;
231
+ --sun-icon-color: CanvasText;
232
+ }
233
+ #theme-toggle-label #theme-toggle-ball {
234
+ background-color: SelectedItem;
235
+ }
236
+ }
237
+
238
+ .theme-toggle-checkbox:checked + #theme-toggle-label #theme-toggle-ball {
239
+ transform: translateX(28.5px);
240
+ }
241
+
242
+ .sr-only {
243
+ border: 0 !important;
244
+ clip: rect(1px, 1px, 1px, 1px) !important;
245
+ -webkit-clip-path: inset(50%) !important;
246
+ clip-path: inset(50%) !important;
247
+ height: 1px !important;
248
+ margin: -1px !important;
249
+ overflow: hidden !important;
250
+ padding: 0 !important;
251
+ position: absolute !important;
252
+ width: 1px !important;
253
+ white-space: nowrap !important;
254
+ }
255
+
256
+ .icon-tabler {
257
+ transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
258
+ z-index: 10;
259
+ }
260
+
261
+ .icon-tabler-moon {
262
+ color: var(--moon-icon-color);
263
+ }
264
+
265
+ .icon-tabler-sun {
266
+ color: var(--sun-icon-color);
267
+ }
268
+
269
+ #backdrop {
270
+ font-family: var(--font-monospace);
271
+ position: fixed;
272
+ z-index: 99999;
273
+ top: 0;
274
+ left: 0;
275
+ width: 100%;
276
+ height: 100%;
277
+ background: var(--background);
278
+ overflow-y: auto;
279
+ }
280
+
281
+ #layout {
282
+ max-width: min(100%, 1280px);
283
+ position: relative;
284
+ width: 1280px;
285
+ margin: 0 auto;
286
+ padding: 40px;
287
+ display: flex;
288
+ flex-direction: column;
289
+ gap: 24px;
290
+ }
291
+
292
+ @media (max-width: 768px) {
293
+ #header {
294
+ padding: 12px;
295
+ margin-top: 12px;
296
+ }
297
+
298
+ #theme-toggle-wrapper > div {
299
+ position: absolute;
300
+ right: 22px;
301
+ margin-top: 47px;
302
+ }
303
+
304
+ #layout {
305
+ padding: 0;
306
+ }
307
+ }
308
+
309
+ @media (max-width: 1024px) {
310
+ #betterr-logo,
311
+ #betterr-logo-overlay {
312
+ display: none;
313
+ }
314
+ }
315
+
316
+ #header {
317
+ position: relative;
318
+ margin-top: 48px;
319
+ }
320
+
321
+ #header-left {
322
+ min-height: 63px;
323
+ display: flex;
324
+ align-items: flex-start;
325
+ flex-direction: column;
326
+ justify-content: end;
327
+ }
328
+
329
+ #name {
330
+ font-size: 18px;
331
+ font-weight: normal;
332
+ line-height: 22px;
333
+ color: var(--error-text);
334
+ margin: 0;
335
+ padding: 0;
336
+ }
337
+
338
+ #title {
339
+ font-size: 34px;
340
+ line-height: 41px;
341
+ font-weight: 600;
342
+ margin: 0;
343
+ padding: 0;
344
+ color: var(--title-text);
345
+ font-family: var(--font-normal);
346
+ }
347
+
348
+ #betterr-logo {
349
+ position: absolute;
350
+ bottom: -50px;
351
+ right: 72px;
352
+ top: -20px;
353
+
354
+ z-index: -50;
355
+ color: var(--error-text);
356
+ }
357
+
358
+ #betterr-logo-overlay {
359
+ width: 175px;
360
+ height: 250px;
361
+ position: absolute;
362
+ bottom: -100px;
363
+ right: 32px;
364
+ z-index: -25;
365
+ background: var(--betterr-logo-overlay);
366
+ }
367
+
368
+ #message-hints,
369
+ #stack,
370
+ #code,
371
+ #cause {
372
+ border-radius: var(--roundiness);
373
+ background-color: var(--box-background);
374
+ }
375
+
376
+ #message,
377
+ #hint {
378
+ display: flex;
379
+ padding: 16px;
380
+ gap: 16px;
381
+ }
382
+
383
+ #message-content,
384
+ #hint-content {
385
+ white-space: pre-wrap;
386
+ line-height: 26px;
387
+ flex-grow: 1;
388
+ }
389
+
390
+ #message {
391
+ color: var(--error-text);
392
+ }
393
+
394
+ #message-content a {
395
+ color: var(--error-text);
396
+ }
397
+
398
+ #message-content a:hover {
399
+ color: var(--error-text-hover);
400
+ }
401
+
402
+ #hint {
403
+ color: var(--hint-text);
404
+ border-top: 1px solid var(--border);
405
+ display: none;
406
+ }
407
+
408
+ #hint a {
409
+ color: var(--hint-text);
410
+ }
411
+
412
+ #hint a:hover {
413
+ color: var(--hint-text-hover);
414
+ }
415
+
416
+ #message-hints code {
417
+ font-family: var(--font-monospace);
418
+ background-color: var(--border);
419
+ padding: 2px 4px;
420
+ border-radius: var(--roundiness);
421
+ white-space: nowrap;
422
+ }
423
+
424
+ .link {
425
+ min-width: fit-content;
426
+ padding-right: 8px;
427
+ padding-top: 8px;
428
+ }
429
+
430
+ .link button {
431
+ background: none;
432
+ border: none;
433
+ font-size: inherit;
434
+ font-family: inherit;
435
+ }
436
+
437
+ .link a,
438
+ .link button {
439
+ color: var(--accent);
440
+ text-decoration: none;
441
+ display: flex;
442
+ gap: 8px;
443
+ }
444
+
445
+ .link a:hover,
446
+ .link button:hover {
447
+ color: var(--accent-hover);
448
+ text-decoration: underline;
449
+ cursor: pointer;
450
+ }
451
+
452
+ .link svg {
453
+ vertical-align: text-top;
454
+ }
455
+
456
+ #code {
457
+ display: none;
458
+ }
459
+
460
+ #code header {
461
+ padding: 24px;
462
+ display: flex;
463
+ justify-content: space-between;
464
+ gap: 1rem;
465
+ }
466
+
467
+ #code h2 {
468
+ font-family: var(--font-monospace);
469
+ color: var(--title-text);
470
+ font-size: 18px;
471
+ margin: 0;
472
+ overflow-wrap: anywhere;
473
+ }
474
+
475
+ #code .link {
476
+ padding: 0;
477
+ }
478
+
479
+ .shiki {
480
+ margin: 0;
481
+ border-top: 1px solid var(--border);
482
+ max-height: 17rem;
483
+ overflow: auto;
484
+ }
485
+
486
+ .shiki code {
487
+ font-family: var(--font-monospace);
488
+ counter-reset: step;
489
+ counter-increment: step 0;
490
+ font-size: 14px;
491
+ line-height: 21px;
492
+ tab-size: 1;
493
+ }
494
+
495
+ .shiki code .line:not(.error-caret)::before {
496
+ content: counter(step);
497
+ counter-increment: step;
498
+ width: 1rem;
499
+ margin-right: 16px;
500
+ display: inline-block;
501
+ text-align: right;
502
+ padding: 0 8px;
503
+ color: var(--misc-text);
504
+ border-right: solid 1px var(--border);
505
+ }
506
+
507
+ .shiki code .line:first-child::before {
508
+ padding-top: 8px;
509
+ }
510
+
511
+ .shiki code .line:last-child::before {
512
+ padding-bottom: 8px;
513
+ }
514
+
515
+ .error-line {
516
+ background-color: #f4909026;
517
+ display: inline-block;
518
+ width: 100%;
519
+ }
520
+
521
+ .error-caret {
522
+ margin-left: calc(33px + 1rem);
523
+ color: var(--error-text);
524
+ }
525
+
526
+ #stack h2,
527
+ #cause h2 {
528
+ color: var(--title-text);
529
+ font-family: var(--font-normal);
530
+ font-size: 22px;
531
+ margin: 0;
532
+ padding: 24px;
533
+ border-bottom: 1px solid var(--border);
534
+ }
535
+
536
+ #stack-content,
537
+ #cause-content {
538
+ font-size: 14px;
539
+ white-space: pre;
540
+ line-height: 21px;
541
+ overflow: auto;
542
+ padding: 24px;
543
+ color: var(--stack-text);
544
+ }
545
+
546
+ #cause {
547
+ /* display: none; */
548
+ }
549
+ `;
@@ -0,0 +1,5 @@
1
+ import { type ErrorWithMetadata } from '../errors.js';
2
+ import type { BetterErrorData } from '../errors-data.js';
3
+ export declare function padMultilineString(source: string, n?: number): string;
4
+ export declare function formatErrorMessage(err: ErrorWithMetadata, showFullStacktrace: boolean, errorsData: Record<string, BetterErrorData>, docsBaseUrl?: string): string;
5
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/dev/logger.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA+CzD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,SAAI,UAGvD;AAED,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,iBAAiB,EACtB,kBAAkB,EAAE,OAAO,EAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EAC3C,WAAW,CAAC,EAAE,MAAM,GAClB,MAAM,CAiDR"}
@@ -0,0 +1,82 @@
1
+ import { getDocsForError, renderErrorMarkdown } from './utils.js';
2
+ import picocolors from 'picocolors';
3
+ import { BetterError } from '../errors.js';
4
+ const { yellow, bold, cyan, dim, underline, red } = picocolors;
5
+ // a regex to match the first line of a stack trace
6
+ const STACK_LINE_REGEXP = /^\s+at /g;
7
+ const IRRELEVANT_STACK_REGEXP = /node_modules|astro[/\\]dist/g;
8
+ function formatErrorStackTrace(err, showFullStacktrace) {
9
+ const stackLines = (err.stack || '')
10
+ .split('\n')
11
+ .filter((line) => STACK_LINE_REGEXP.test(line));
12
+ // If full details are required, just return the entire stack trace.
13
+ if (showFullStacktrace) {
14
+ return stackLines.join('\n');
15
+ }
16
+ // Grab every string from the user's codebase, exit when you hit node_modules or astro/dist
17
+ const irrelevantStackIndex = stackLines.findIndex((line) => IRRELEVANT_STACK_REGEXP.test(line));
18
+ if (irrelevantStackIndex <= 0) {
19
+ const errorId = err.id;
20
+ const errorLoc = err.loc;
21
+ if (errorId || errorLoc?.file) {
22
+ const prettyLocation = ` at ${errorId ?? errorLoc?.file}${errorLoc?.line && errorLoc.column
23
+ ? `:${errorLoc.line}:${errorLoc.column}`
24
+ : ''}`;
25
+ return (prettyLocation +
26
+ '\n [...] See full stack trace in the browser, or rerun with --verbose.');
27
+ }
28
+ else {
29
+ return stackLines.join('\n');
30
+ }
31
+ }
32
+ // If the error occurred inside of a dependency, grab the entire stack.
33
+ // Otherwise, only grab the part of the stack that is relevant to the user's codebase.
34
+ return (stackLines.splice(0, irrelevantStackIndex).join('\n') +
35
+ '\n [...] See full stack trace in the browser, or rerun with --verbose.');
36
+ }
37
+ export function padMultilineString(source, n = 2) {
38
+ const lines = source.split(/\r?\n/);
39
+ return lines.map((l) => ` `.repeat(n) + l).join(`\n`);
40
+ }
41
+ export function formatErrorMessage(err, showFullStacktrace, errorsData, docsBaseUrl) {
42
+ const isOurError = BetterError.is(err); /* || CompilerError.is(err) || AstroUserError.is(err) */
43
+ let message = '';
44
+ if (isOurError) {
45
+ message +=
46
+ red(`[${err.name}]`) + ' ' + renderErrorMarkdown(err.message, 'cli');
47
+ }
48
+ else {
49
+ message += err.message;
50
+ }
51
+ const output = [message];
52
+ if (err.hint) {
53
+ output.push(` ${bold('Hint:')}`);
54
+ output.push(yellow(padMultilineString(renderErrorMarkdown(err.hint, 'cli'), 4)));
55
+ }
56
+ if (docsBaseUrl) {
57
+ const docsLink = getDocsForError(err, errorsData, docsBaseUrl);
58
+ if (docsLink) {
59
+ output.push(` ${bold('Error reference:')}`);
60
+ output.push(` ${cyan(underline(docsLink))}`);
61
+ }
62
+ }
63
+ if (err.stack) {
64
+ output.push(` ${bold('Stack trace:')}`);
65
+ output.push(dim(formatErrorStackTrace(err, showFullStacktrace)));
66
+ }
67
+ if (err.cause) {
68
+ output.push(` ${bold('Caused by:')}`);
69
+ let causeMessage = ' ';
70
+ if (err.cause instanceof Error) {
71
+ causeMessage +=
72
+ err.cause.message +
73
+ '\n' +
74
+ formatErrorStackTrace(err.cause, showFullStacktrace);
75
+ }
76
+ else {
77
+ causeMessage += JSON.stringify(err.cause);
78
+ }
79
+ output.push(dim(causeMessage));
80
+ }
81
+ return output.join('\n');
82
+ }
@@ -0,0 +1,5 @@
1
+ import type { ErrorLocation } from '../errors.js';
2
+ export declare function normalizeLF(code: string): string;
3
+ /** Generate a code frame from string and an error location */
4
+ export declare function codeFrame(src: string, loc: ErrorLocation): string;
5
+ //# sourceMappingURL=printer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../../src/dev/printer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,UAEvC;AAED,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAgCjE"}
@@ -0,0 +1,38 @@
1
+ /* eslint-disable no-restricted-syntax */
2
+ export function normalizeLF(code) {
3
+ return code.replace(/\r\n|\r(?!\n)|\n/g, '\n');
4
+ }
5
+ /** Generate a code frame from string and an error location */
6
+ export function codeFrame(src, loc) {
7
+ if (!loc || loc.line === undefined || loc.column === undefined) {
8
+ return '';
9
+ }
10
+ const lines = normalizeLF(src)
11
+ .split('\n')
12
+ .map((ln) => ln.replace(/\t/g, ' '));
13
+ // grab 2 lines before, and 3 lines after focused line
14
+ const visibleLines = [];
15
+ for (let n = -2; n <= 2; n += 1) {
16
+ if (lines[loc.line + n])
17
+ visibleLines.push(loc.line + n);
18
+ }
19
+ // figure out gutter width
20
+ let gutterWidth = 0;
21
+ for (const lineNo of visibleLines) {
22
+ const w = `> ${lineNo}`;
23
+ if (w.length > gutterWidth)
24
+ gutterWidth = w.length;
25
+ }
26
+ // print lines
27
+ let output = '';
28
+ for (const lineNo of visibleLines) {
29
+ const isFocusedLine = lineNo === loc.line - 1;
30
+ output += isFocusedLine ? '> ' : ' ';
31
+ output += `${lineNo + 1} | ${lines[lineNo]}\n`;
32
+ if (isFocusedLine)
33
+ output += `${Array.from({ length: gutterWidth }).join(' ')} | ${Array.from({
34
+ length: loc.column,
35
+ }).join(' ')}^\n`;
36
+ }
37
+ return output;
38
+ }
@@ -0,0 +1,16 @@
1
+ import { type ErrorWithMetadata } from '../errors.js';
2
+ import type { BetterErrorData } from '../errors-data.js';
3
+ /** Coalesce any throw variable to an Error instance. */
4
+ export declare function createSafeError(err: any): Error;
5
+ export declare function normalizeLF(code: string): string;
6
+ /**
7
+ * Takes any error-like object and returns a standardized Error + metadata object.
8
+ * Useful for consistent reporting regardless of where the error surfaced from.
9
+ */
10
+ export declare function collectErrorMetadata(e: any, rootFolder?: URL | undefined): ErrorWithMetadata;
11
+ export declare function getDocsForError(err: ErrorWithMetadata, errorsData: Record<string, BetterErrorData>, docsBaseUrl: string): string | undefined;
12
+ /**
13
+ * Render a subset of Markdown to HTML or a CLI output
14
+ */
15
+ export declare function renderErrorMarkdown(markdown: string, target: 'html' | 'cli'): string;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/dev/utils.ts"],"names":[],"mappings":"AAeA,OAAO,EAEN,KAAK,iBAAiB,EAEtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAezD,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK,CAW/C;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,UAEvC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,CAAC,EAAE,GAAG,EACN,UAAU,CAAC,EAAE,GAAG,GAAG,SAAS,GAC1B,iBAAiB,CAuInB;AAqGD,wBAAgB,eAAe,CAC9B,GAAG,EAAE,iBAAiB,EACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EAC3C,WAAW,EAAE,MAAM,GACjB,MAAM,GAAG,SAAS,CAcpB;AAQD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,UAc3E"}