UNPKG

4.08 kBJavaScriptView Raw
1'use strict';
2
3const assignDisabledRanges = require('./assignDisabledRanges');
4const getOsEol = require('./utils/getOsEol');
5const reportUnknownRuleNames = require('./reportUnknownRuleNames');
6const rulesOrder = require('./rules');
7
8/** @typedef {import('stylelint').LinterOptions} LinterOptions */
9/** @typedef {import('stylelint').PostcssResult} PostcssResult */
10/** @typedef {import('stylelint').Config} StylelintConfig */
11
12/**
13 * @param {LinterOptions} stylelintOptions
14 * @param {PostcssResult} postcssResult
15 * @param {StylelintConfig} config
16 * @returns {Promise<any>}
17 */
18function lintPostcssResult(stylelintOptions, postcssResult, config) {
19 postcssResult.stylelint.ruleSeverities = {};
20 postcssResult.stylelint.customMessages = {};
21 postcssResult.stylelint.stylelintError = false;
22 postcssResult.stylelint.quiet = config.quiet;
23 postcssResult.stylelint.config = config;
24
25 /** @type {string | undefined} */
26 let newline;
27 const postcssDoc = postcssResult.root;
28
29 if (postcssDoc) {
30 if (!('type' in postcssDoc)) {
31 throw new Error('Unexpected Postcss root object!');
32 }
33
34 const newlineMatch = postcssDoc.source && postcssDoc.source.input.css.match(/\r?\n/);
35
36 newline = newlineMatch ? newlineMatch[0] : getOsEol();
37
38 assignDisabledRanges(postcssDoc, postcssResult);
39 }
40
41 const isFileFixCompatible = isFixCompatible(postcssResult);
42
43 if (!isFileFixCompatible) {
44 postcssResult.stylelint.disableWritingFix = true;
45 }
46
47 const postcssRoots = /** @type {import('postcss').Root[]} */ (
48 postcssDoc && postcssDoc.constructor.name === 'Document' ? postcssDoc.nodes : [postcssDoc]
49 );
50
51 // Promises for the rules. Although the rule code runs synchronously now,
52 // the use of Promises makes it compatible with the possibility of async
53 // rules down the line.
54 /** @type {Array<Promise<any>>} */
55 const performRules = [];
56
57 const rules = config.rules
58 ? Object.keys(config.rules).sort(
59 (a, b) => Object.keys(rulesOrder).indexOf(a) - Object.keys(rulesOrder).indexOf(b),
60 )
61 : [];
62
63 rules.forEach((ruleName) => {
64 const ruleFunction =
65 rulesOrder[ruleName] || (config.pluginFunctions && config.pluginFunctions[ruleName]);
66
67 if (ruleFunction === undefined) {
68 performRules.push(
69 Promise.all(
70 postcssRoots.map((postcssRoot) =>
71 reportUnknownRuleNames(ruleName, postcssRoot, postcssResult),
72 ),
73 ),
74 );
75
76 return;
77 }
78
79 const ruleSettings = config.rules && config.rules[ruleName];
80
81 if (ruleSettings === null || ruleSettings[0] === null) {
82 return;
83 }
84
85 const primaryOption = ruleSettings[0];
86 const secondaryOptions = ruleSettings[1];
87
88 // Log the rule's severity in the PostCSS result
89 const defaultSeverity = config.defaultSeverity || 'error';
90 // disableFix in secondary option
91 const disableFix = (secondaryOptions && secondaryOptions.disableFix === true) || false;
92
93 if (disableFix) {
94 postcssResult.stylelint.ruleDisableFix = true;
95 }
96
97 postcssResult.stylelint.ruleSeverities[ruleName] =
98 (secondaryOptions && secondaryOptions.severity) || defaultSeverity;
99 postcssResult.stylelint.customMessages[ruleName] = secondaryOptions && secondaryOptions.message;
100
101 performRules.push(
102 Promise.all(
103 postcssRoots.map((postcssRoot) =>
104 ruleFunction(primaryOption, secondaryOptions, {
105 fix:
106 !disableFix &&
107 stylelintOptions.fix &&
108 // Next two conditionals are temporary measures until #2643 is resolved
109 isFileFixCompatible &&
110 !postcssResult.stylelint.disabledRanges[ruleName],
111 newline,
112 })(postcssRoot, postcssResult),
113 ),
114 ),
115 );
116 });
117
118 return Promise.all(performRules);
119}
120
121/**
122 * There are currently some bugs in the autofixer of Stylelint.
123 * The autofixer does not yet adhere to stylelint-disable comments, so if there are disabled
124 * ranges we can not autofix this document. More info in issue #2643.
125 *
126 * @param {PostcssResult} postcssResult
127 * @returns {boolean}
128 */
129function isFixCompatible({ stylelint }) {
130 // Check for issue #2643
131 if (stylelint.disabledRanges.all.length) return false;
132
133 return true;
134}
135
136module.exports = lintPostcssResult;