UNPKG

4.23 kBJavaScriptView Raw
1'use strict';
2
3const assignDisabledRanges = require('./assignDisabledRanges');
4const getOsEol = require('./utils/getOsEol');
5const reportUnknownRuleNames = require('./reportUnknownRuleNames');
6const rules = 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.ruleMetadata = {};
22 postcssResult.stylelint.stylelintError = false;
23 postcssResult.stylelint.quiet = config.quiet;
24 postcssResult.stylelint.config = config;
25
26 /** @type {string | undefined} */
27 let newline;
28 const postcssDoc = postcssResult.root;
29
30 if (postcssDoc) {
31 if (!('type' in postcssDoc)) {
32 throw new Error('Unexpected Postcss root object!');
33 }
34
35 const newlineMatch = postcssDoc.source && postcssDoc.source.input.css.match(/\r?\n/);
36
37 newline = newlineMatch ? newlineMatch[0] : getOsEol();
38
39 assignDisabledRanges(postcssDoc, postcssResult);
40 }
41
42 const isFileFixCompatible = isFixCompatible(postcssResult);
43
44 if (!isFileFixCompatible) {
45 postcssResult.stylelint.disableWritingFix = true;
46 }
47
48 const postcssRoots = /** @type {import('postcss').Root[]} */ (
49 postcssDoc && postcssDoc.constructor.name === 'Document' ? postcssDoc.nodes : [postcssDoc]
50 );
51
52 // Promises for the rules. Although the rule code runs synchronously now,
53 // the use of Promises makes it compatible with the possibility of async
54 // rules down the line.
55 /** @type {Array<Promise<any>>} */
56 const performRules = [];
57
58 const rulesOrder = Object.keys(rules);
59 const ruleNames = config.rules
60 ? Object.keys(config.rules).sort((a, b) => rulesOrder.indexOf(a) - rulesOrder.indexOf(b))
61 : [];
62
63 for (const ruleName of ruleNames) {
64 const ruleFunction =
65 rules[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 continue;
77 }
78
79 const ruleSettings = config.rules && config.rules[ruleName];
80
81 if (ruleSettings === null || ruleSettings[0] === null) {
82 continue;
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 postcssResult.stylelint.ruleMetadata[ruleName] = ruleFunction.meta || {};
101
102 performRules.push(
103 Promise.all(
104 postcssRoots.map((postcssRoot) =>
105 ruleFunction(primaryOption, secondaryOptions, {
106 fix:
107 !disableFix &&
108 stylelintOptions.fix &&
109 // Next two conditionals are temporary measures until #2643 is resolved
110 isFileFixCompatible &&
111 !postcssResult.stylelint.disabledRanges[ruleName],
112 newline,
113 })(postcssRoot, postcssResult),
114 ),
115 ),
116 );
117 }
118
119 return Promise.all(performRules);
120}
121
122/**
123 * There are currently some bugs in the autofixer of Stylelint.
124 * The autofixer does not yet adhere to stylelint-disable comments, so if there are disabled
125 * ranges we can not autofix this document. More info in issue #2643.
126 *
127 * @param {PostcssResult} postcssResult
128 * @returns {boolean}
129 */
130function isFixCompatible({ stylelint }) {
131 // Check for issue #2643
132 if (stylelint.disabledRanges.all && stylelint.disabledRanges.all.length) return false;
133
134 return true;
135}
136
137module.exports = lintPostcssResult;