UNPKG

2.24 kBJavaScriptView Raw
1// @flow strict-local
2import type {Diagnostic} from '@parcel/diagnostic';
3import type {PluginOptions} from '@parcel/types';
4
5import formatCodeFrame from '@parcel/codeframe';
6import mdAnsi from '@parcel/markdown-ansi';
7import chalk from 'chalk';
8import path from 'path';
9import nullthrows from 'nullthrows';
10
11export type AnsiDiagnosticResult = {|
12 message: string,
13 stack: string,
14 codeframe: string,
15 hints: Array<string>,
16|};
17
18export default async function prettyDiagnostic(
19 diagnostic: Diagnostic,
20 options?: PluginOptions,
21 terminalWidth?: number,
22): Promise<AnsiDiagnosticResult> {
23 let {
24 origin,
25 message,
26 stack,
27 codeFrame,
28 hints,
29 filePath,
30 language,
31 skipFormatting,
32 } = diagnostic;
33
34 if (filePath != null && options && !path.isAbsolute(filePath)) {
35 filePath = path.join(options.projectRoot, filePath);
36 }
37
38 let result = {
39 message:
40 mdAnsi(`**${origin ?? 'unknown'}**: `) +
41 (skipFormatting ? message : mdAnsi(message)),
42 stack: '',
43 codeframe: '',
44 hints: [],
45 };
46
47 if (codeFrame !== undefined) {
48 let highlights = Array.isArray(codeFrame.codeHighlights)
49 ? codeFrame.codeHighlights
50 : [codeFrame.codeHighlights];
51
52 let code =
53 codeFrame.code ??
54 (options &&
55 (await options.inputFS.readFile(nullthrows(filePath), 'utf8')));
56
57 if (code != null) {
58 let formattedCodeFrame = formatCodeFrame(code, highlights, {
59 useColor: true,
60 syntaxHighlighting: true,
61 language:
62 // $FlowFixMe sketchy null checks do not matter here...
63 language || (filePath ? path.extname(filePath).substr(1) : undefined),
64 terminalWidth,
65 });
66
67 result.codeframe +=
68 typeof filePath !== 'string'
69 ? ''
70 : chalk.underline(
71 `${filePath}:${highlights[0].start.line}:${highlights[0].start.column}\n`,
72 );
73 result.codeframe += formattedCodeFrame;
74 }
75 }
76
77 if (stack != null) {
78 result.stack = stack;
79 } else if (filePath != null && result.codeframe == null) {
80 result.stack = filePath;
81 }
82
83 if (Array.isArray(hints) && hints.length) {
84 result.hints = hints.map(h => {
85 return mdAnsi(h);
86 });
87 }
88
89 return result;
90}