UNPKG

3.45 kBJavaScriptView Raw
1'use strict';
2
3const isPathNotFoundError = require('./utils/isPathNotFoundError');
4const lintPostcssResult = require('./lintPostcssResult');
5const path = require('path');
6
7/** @typedef {import('stylelint').InternalApi} StylelintInternalApi */
8/** @typedef {import('stylelint').GetLintSourceOptions} Options */
9/** @typedef {import('postcss').Result} Result */
10/** @typedef {import('stylelint').PostcssResult} PostcssResult */
11/** @typedef {import('stylelint').StylelintPostcssResult} StylelintPostcssResult */
12
13/**
14 * Run stylelint on a PostCSS Result, either one that is provided
15 * or one that we create
16 * @param {StylelintInternalApi} stylelint
17 * @param {Options} options
18 * @returns {Promise<PostcssResult>}
19 */
20module.exports = async function lintSource(stylelint, options = {}) {
21 if (!options.filePath && options.code === undefined && !options.existingPostcssResult) {
22 return Promise.reject(new Error('You must provide filePath, code, or existingPostcssResult'));
23 }
24
25 const isCodeNotFile = options.code !== undefined;
26
27 const inputFilePath = isCodeNotFile ? options.codeFilename : options.filePath;
28
29 if (inputFilePath !== undefined && !path.isAbsolute(inputFilePath)) {
30 if (isCodeNotFile) {
31 return Promise.reject(new Error('codeFilename must be an absolute path'));
32 }
33
34 return Promise.reject(new Error('filePath must be an absolute path'));
35 }
36
37 const isIgnored = await stylelint.isPathIgnored(inputFilePath).catch((err) => {
38 if (isCodeNotFile && isPathNotFoundError(err)) return false;
39
40 throw err;
41 });
42
43 if (isIgnored) {
44 return options.existingPostcssResult
45 ? Object.assign(options.existingPostcssResult, {
46 stylelint: createEmptyStylelintPostcssResult(),
47 })
48 : createEmptyPostcssResult(inputFilePath);
49 }
50
51 const configSearchPath = stylelint._options.configFile || inputFilePath;
52 const cwd = stylelint._options.cwd;
53
54 const configForFile = await stylelint
55 .getConfigForFile(configSearchPath, inputFilePath)
56 .catch((err) => {
57 if (isCodeNotFile && isPathNotFoundError(err)) return stylelint.getConfigForFile(cwd);
58
59 throw err;
60 });
61
62 if (!configForFile) {
63 return Promise.reject(new Error('Config file not found'));
64 }
65
66 const config = configForFile.config;
67 const existingPostcssResult = options.existingPostcssResult;
68
69 /** @type {StylelintPostcssResult} */
70 const stylelintResult = {
71 ruleSeverities: {},
72 customMessages: {},
73 ruleMetadata: {},
74 disabledRanges: {},
75 };
76
77 const postcssResult =
78 existingPostcssResult ||
79 (await stylelint._getPostcssResult({
80 code: options.code,
81 codeFilename: options.codeFilename,
82 filePath: inputFilePath,
83 codeProcessors: config.codeProcessors,
84 customSyntax: config.customSyntax,
85 }));
86
87 const stylelintPostcssResult = Object.assign(postcssResult, {
88 stylelint: stylelintResult,
89 });
90
91 await lintPostcssResult(stylelint._options, stylelintPostcssResult, config);
92
93 return stylelintPostcssResult;
94};
95
96/**
97 * @returns {StylelintPostcssResult}
98 */
99function createEmptyStylelintPostcssResult() {
100 return {
101 ruleSeverities: {},
102 customMessages: {},
103 ruleMetadata: {},
104 disabledRanges: {},
105 ignored: true,
106 stylelintError: false,
107 };
108}
109
110/**
111 * @param {string} [filePath]
112 * @returns {PostcssResult}
113 */
114function createEmptyPostcssResult(filePath) {
115 return {
116 root: {
117 source: {
118 input: { file: filePath },
119 },
120 },
121 messages: [],
122 opts: undefined,
123 stylelint: createEmptyStylelintPostcssResult(),
124 warn: () => {},
125 };
126}