UNPKG

4.38 kBJavaScriptView Raw
1export function loadDiagnostic(context, postcssError, filePath) {
2 if (!postcssError || !context) {
3 return;
4 }
5 const level = postcssError.level === 'warning' ? 'warn' : postcssError.level || 'error';
6 const diagnostic = {
7 level,
8 type: 'css',
9 language: 'postcss',
10 header: `postcss ${level}`,
11 code: postcssError.status && postcssError.status.toString(),
12 relFilePath: null,
13 absFilePath: null,
14 messageText: postcssError.reason || postcssError.message || JSON.stringify(postcssError),
15 lines: [],
16 };
17 if (filePath) {
18 diagnostic.absFilePath = filePath;
19 diagnostic.relFilePath = formatFileName(context.config.rootDir, diagnostic.absFilePath);
20 diagnostic.header = formatHeader('postcss', diagnostic.absFilePath, context.config.rootDir, postcssError.line);
21 if (postcssError.line > -1) {
22 try {
23 const sourceText = context.fs.readFileSync(diagnostic.absFilePath);
24 const srcLines = sourceText.split(/(\r?\n)/);
25 const errorLine = {
26 lineIndex: postcssError.line - 1,
27 lineNumber: postcssError.line,
28 text: srcLines[postcssError.line - 1],
29 errorCharStart: postcssError.column,
30 errorLength: 0,
31 };
32 for (let i = errorLine.errorCharStart; i >= 0; i--) {
33 if (STOP_CHARS.indexOf(errorLine.text.charAt(i)) > -1) {
34 break;
35 }
36 errorLine.errorCharStart = i;
37 }
38 for (let j = errorLine.errorCharStart; j <= errorLine.text.length; j++) {
39 if (STOP_CHARS.indexOf(errorLine.text.charAt(j)) > -1) {
40 break;
41 }
42 errorLine.errorLength++;
43 }
44 if (errorLine.errorLength === 0 && errorLine.errorCharStart > 0) {
45 errorLine.errorLength = 1;
46 errorLine.errorCharStart--;
47 }
48 diagnostic.lines.push(errorLine);
49 if (errorLine.lineIndex > 0) {
50 const previousLine = {
51 lineIndex: errorLine.lineIndex - 1,
52 lineNumber: errorLine.lineNumber - 1,
53 text: srcLines[errorLine.lineIndex - 1],
54 errorCharStart: -1,
55 errorLength: -1,
56 };
57 diagnostic.lines.unshift(previousLine);
58 }
59 if (errorLine.lineIndex + 1 < srcLines.length) {
60 const nextLine = {
61 lineIndex: errorLine.lineIndex + 1,
62 lineNumber: errorLine.lineNumber + 1,
63 text: srcLines[errorLine.lineIndex + 1],
64 errorCharStart: -1,
65 errorLength: -1,
66 };
67 diagnostic.lines.push(nextLine);
68 }
69 }
70 catch (e) {
71 console.error(`StylePostcssPlugin loadDiagnostic, ${e}`);
72 }
73 }
74 }
75 context.diagnostics.push(diagnostic);
76}
77function formatFileName(rootDir, fileName) {
78 if (!rootDir || !fileName)
79 return '';
80 fileName = fileName.replace(rootDir, '');
81 if (/\/|\\/.test(fileName.charAt(0))) {
82 fileName = fileName.substr(1);
83 }
84 if (fileName.length > 80) {
85 fileName = '...' + fileName.substr(fileName.length - 80);
86 }
87 return fileName;
88}
89function formatHeader(type, fileName, rootDir, startLineNumber = null, endLineNumber = null) {
90 let header = `${type}: ${formatFileName(rootDir, fileName)}`;
91 if (startLineNumber !== null && startLineNumber > 0) {
92 if (endLineNumber !== null && endLineNumber > startLineNumber) {
93 header += `, lines: ${startLineNumber} - ${endLineNumber}`;
94 }
95 else {
96 header += `, line: ${startLineNumber}`;
97 }
98 }
99 return header;
100}
101const STOP_CHARS = [
102 '',
103 '\n',
104 '\r',
105 '\t',
106 ' ',
107 ':',
108 ';',
109 ',',
110 '{',
111 '}',
112 '.',
113 '#',
114 '@',
115 '!',
116 '[',
117 ']',
118 '(',
119 ')',
120 '&',
121 '+',
122 '~',
123 '^',
124 '*',
125 '$',
126];