UNPKG

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