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