1 |
|
2 | "use strict";
|
3 |
|
4 | const autoSyntax = require("postcss-syntax");
|
5 | const dynamicRequire = require("./dynamicRequire");
|
6 | const fs = require("fs");
|
7 | const LazyResult = require("postcss/lib/lazy-result");
|
8 | const postcss = require("postcss");
|
9 |
|
10 | const postcssProcessor = postcss();
|
11 |
|
12 | module.exports = function(
|
13 | stylelint /*: stylelint$internalApi*/
|
14 | ) /*: Promise<?Object>*/ {
|
15 | const options |
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | =
|
23 | arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
24 |
|
25 | const cached = stylelint._postcssResultCache.get(
|
26 | options.filePath
|
27 | );
|
28 |
|
29 | if (cached) return Promise.resolve(cached);
|
30 |
|
31 | let getCode;
|
32 |
|
33 | if (options.code !== undefined) {
|
34 | getCode = Promise.resolve(options.code);
|
35 | } else if (options.filePath) {
|
36 | getCode = readFile(options.filePath);
|
37 | }
|
38 |
|
39 | if (!getCode) {
|
40 | throw new Error("code or filePath required");
|
41 | }
|
42 |
|
43 | return getCode
|
44 | .then(code => {
|
45 | const customSyntax = stylelint._options.customSyntax;
|
46 | let syntax = stylelint._options.syntax;
|
47 |
|
48 | if (customSyntax) {
|
49 | try {
|
50 | syntax = dynamicRequire(customSyntax);
|
51 | } catch (e) {
|
52 | throw new Error(
|
53 | `Cannot resolve custom syntax module ${customSyntax}`
|
54 | );
|
55 | }
|
56 |
|
57 | |
58 |
|
59 |
|
60 |
|
61 | if (!syntax.parse) {
|
62 | syntax = {
|
63 | parse: syntax,
|
64 | stringify: postcss.stringify
|
65 | };
|
66 | }
|
67 | } else if (syntax) {
|
68 | switch (syntax) {
|
69 | case "css-in-js": {
|
70 | syntax = "postcss-jsx";
|
71 | break;
|
72 | }
|
73 | case "html":
|
74 | case "less":
|
75 | case "markdown":
|
76 | case "sass":
|
77 | case "scss": {
|
78 | syntax = "postcss-" + syntax;
|
79 | break;
|
80 | }
|
81 | case "sugarss": {
|
82 | break;
|
83 | }
|
84 | default: {
|
85 | throw new Error(
|
86 | "You must use a valid syntax option, either: css-in-js, html, less, markdown, sass, scss or sugarss"
|
87 | );
|
88 | }
|
89 | }
|
90 |
|
91 | syntax = dynamicRequire(syntax);
|
92 | } else if (
|
93 | !(options.codeProcessors && options.codeProcessors.length) ||
|
94 | (options.filePath && /\.(scss|sass|less)$/.test(options.filePath))
|
95 | ) {
|
96 | syntax = autoSyntax({
|
97 | css: {
|
98 | parse: stylelint._options.fix
|
99 | ? dynamicRequire("postcss-safe-parser")
|
100 | : postcss.parse,
|
101 | stringify: postcss.stringify
|
102 | }
|
103 | });
|
104 | }
|
105 |
|
106 | const postcssOptions = {
|
107 | from: options.filePath,
|
108 | syntax
|
109 | };
|
110 |
|
111 | const source = options.code ? options.codeFilename : options.filePath;
|
112 | let preProcessedCode = code;
|
113 |
|
114 | if (options.codeProcessors && options.codeProcessors.length) {
|
115 | if (stylelint._options.fix) {
|
116 |
|
117 | console.warn(
|
118 | "Autofix is incompatible with processors and will be disabled. Are you sure you need a processor?"
|
119 | );
|
120 | stylelint._options.fix = false;
|
121 | }
|
122 |
|
123 | options.codeProcessors.forEach(codeProcessor => {
|
124 | preProcessedCode = codeProcessor(preProcessedCode, source);
|
125 | });
|
126 | }
|
127 |
|
128 | const result = new LazyResult(
|
129 | postcssProcessor,
|
130 | preProcessedCode,
|
131 | postcssOptions
|
132 | );
|
133 |
|
134 | return result;
|
135 | })
|
136 | .then(postcssResult => {
|
137 | stylelint._postcssResultCache.set(options.filePath, postcssResult);
|
138 |
|
139 | return postcssResult;
|
140 | });
|
141 | };
|
142 |
|
143 | function readFile(filePath /*: string*/) /*: Promise<string>*/ {
|
144 | return new Promise((resolve, reject) => {
|
145 | fs.readFile(filePath, "utf8", (err, content) => {
|
146 | if (err) {
|
147 | return reject(err);
|
148 | }
|
149 |
|
150 | resolve(content);
|
151 | });
|
152 | });
|
153 | }
|