UNPKG

2.83 kBJavaScriptView Raw
1'use strict';
2
3const execall = require('execall');
4const splitLines = require('split-lines');
5const reindent = require('./lib/reindent');
6
7const sourceToLineMap = new Map();
8
9module.exports = function (options) {
10 options = options || {};
11 options.startTag = options.startTag || '[^`\'"]<style[\\s\\S]*?>';
12 options.endTag = options.endTag || '</\\s*?style>';
13 options.body = options.body || '[\\s\\S]*?';
14 options.fileFilterRegex = options.fileFilterRegex || [];
15
16 const snippetRegexp = new RegExp(`(${options.startTag})(${options.body})\\s*${options.endTag}`, 'g');
17
18 /**
19 * Checks whether the given file is allowed by the filter
20 */
21 function isFileProcessable(filepath) {
22 if (options.fileFilterRegex.length === 0) {
23 return true;
24 }
25
26 return options.fileFilterRegex.some((regex) => filepath.match(regex) !== null);
27 }
28
29 function transformCode(sourceCode, filepath) {
30 if (!isFileProcessable(filepath)) {
31 return sourceCode;
32 }
33
34 const extractedToSourceLineMap = new Map();
35 let extractedCode = '';
36 let currentExtractedCodeLine = 0;
37
38 execall(snippetRegexp, sourceCode).forEach((match) => {
39 const reindentData = reindent(match.sub[1]);
40 const chunkCode = reindentData.text;
41 if (!chunkCode) return;
42
43 const openingTag = match.sub[0];
44 const startIndex = match.index + openingTag.length;
45 const startLine = splitLines(sourceCode.slice(0, startIndex)).length;
46 const linesWithin = splitLines(chunkCode).length;
47
48 for (let i = 0; i < linesWithin; i++) {
49 currentExtractedCodeLine += 1;
50 extractedToSourceLineMap.set(currentExtractedCodeLine, {
51 line: startLine + i,
52 indentColumns: reindentData.indentColumns,
53 });
54 }
55
56 extractedCode += chunkCode + '\n';
57 });
58
59 sourceToLineMap.set(filepath, extractedToSourceLineMap);
60 return extractedCode;
61 }
62
63 function transformResult(result, filepath) {
64 if (!isFileProcessable(filepath)) {
65 return;
66 }
67
68 const extractedToSourceLineMap = sourceToLineMap.get(filepath);
69 const newWarnings = result.warnings.reduce((memo, warning) => {
70 // This might end up rendering to null when there's no content on the
71 // file being parsed. It's likely that it has been flagged due a
72 // `no-empty-source` rule.
73 const warningSourceMap = extractedToSourceLineMap.get(warning.line);
74
75 if (warning.line && warningSourceMap) {
76 warning.line = warningSourceMap.line;
77 }
78
79 if (warning.column && warningSourceMap) {
80 warning.column = warning.column + warningSourceMap.indentColumns;
81 }
82
83 memo.push(warning);
84 return memo;
85 }, []);
86
87 return Object.assign(result, { warnings: newWarnings });
88 }
89
90 return {
91 code: transformCode,
92 result: transformResult,
93 };
94};