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