mirror of
https://github.com/thangisme/notes.git
synced 2024-11-01 00:27:24 -04:00
141 lines
4.7 KiB
JavaScript
141 lines
4.7 KiB
JavaScript
/* @flow */
|
|
"use strict"
|
|
const _ = require("lodash")
|
|
const assignDisabledRanges = require("./assignDisabledRanges")
|
|
const configurationError = require("./utils/configurationError")
|
|
const path = require("path")
|
|
const ruleDefinitions = require("./rules")
|
|
|
|
// Run stylelint on a PostCSS Result, either one that is provided
|
|
// or one that we create
|
|
module.exports = function (
|
|
stylelint/*: stylelint$internalApi*/,
|
|
options/*: {
|
|
code?: string,
|
|
codeFilename?: string, // Must be an absolute file path
|
|
filePath?: string, // Must be an absolute file path
|
|
existingPostcssResult?: Object,
|
|
}*/
|
|
)/*: Promise<Object>*/ {
|
|
options = options || {}
|
|
|
|
if (!options.filePath && options.code === undefined && !options.existingPostcssResult) {
|
|
return Promise.reject(new Error("You must provide filePath, code, or existingPostcssResult"))
|
|
}
|
|
|
|
const isCodeNotFile = options.code !== undefined
|
|
|
|
const inputFilePath = isCodeNotFile ? options.codeFilename : options.filePath
|
|
if (inputFilePath !== undefined && !path.isAbsolute(inputFilePath)) {
|
|
if (isCodeNotFile) {
|
|
return Promise.reject(new Error("codeFilename must be an absolute path"))
|
|
} else {
|
|
return Promise.reject(new Error("filePath must be an absolute path"))
|
|
}
|
|
}
|
|
|
|
const getIsIgnored = stylelint.isPathIgnored(inputFilePath).catch(err => {
|
|
if (isCodeNotFile && err.code === "ENOENT") return false
|
|
throw err
|
|
})
|
|
|
|
return getIsIgnored.then(isIgnored => {
|
|
if (isIgnored) {
|
|
const postcssResult = options.existingPostcssResult || createEmptyPostcssResult(inputFilePath)
|
|
postcssResult.stylelint = postcssResult.stylelint || {}
|
|
postcssResult.stylelint.ignored = true
|
|
postcssResult.standaloneIgnored = true // TODO: remove need for this
|
|
return postcssResult
|
|
}
|
|
|
|
const configSearchPath = stylelint._options.configFile || inputFilePath
|
|
|
|
const getConfig = stylelint.getConfigForFile(configSearchPath).catch(err => {
|
|
if (isCodeNotFile && err.code === "ENOENT") return stylelint.getConfigForFile(process.cwd())
|
|
throw err
|
|
})
|
|
|
|
return getConfig.then((result) => {
|
|
const config = result.config
|
|
const existingPostcssResult = options.existingPostcssResult
|
|
|
|
if (existingPostcssResult) {
|
|
return lintPostcssResult(stylelint, existingPostcssResult, config).then(() => existingPostcssResult)
|
|
}
|
|
|
|
return stylelint._getPostcssResult({
|
|
code: options.code,
|
|
codeFilename: options.codeFilename,
|
|
filePath: inputFilePath,
|
|
codeProcessors: config.codeProcessors,
|
|
}).then(postcssResult => {
|
|
return lintPostcssResult(stylelint, postcssResult, config).then(() => postcssResult)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function lintPostcssResult(
|
|
stylelint/*: stylelint$internalApi*/,
|
|
postcssResult/*: Object*/,
|
|
config/*: stylelint$config*/
|
|
)/*: Promise<>*/ {
|
|
postcssResult.stylelint = postcssResult.stylelint || {}
|
|
postcssResult.stylelint.ruleSeverities = {}
|
|
postcssResult.stylelint.customMessages = {}
|
|
postcssResult.stylelint.quiet = config.quiet
|
|
|
|
const postcssRoot = postcssResult.root
|
|
assignDisabledRanges(postcssRoot, postcssResult)
|
|
if (stylelint._options.reportNeedlessDisables || stylelint._options.ignoreDisables) {
|
|
postcssResult.stylelint.ignoreDisables = true
|
|
}
|
|
|
|
// 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.
|
|
const performRules = []
|
|
|
|
const rules = config.rules ? Object.keys(config.rules) : []
|
|
|
|
rules.forEach(ruleName => {
|
|
const ruleFunction = ruleDefinitions[ruleName] || _.get(config, [ "pluginFunctions", ruleName ])
|
|
|
|
if (ruleFunction === undefined) {
|
|
throw configurationError(`Undefined rule ${ruleName}`)
|
|
}
|
|
|
|
const ruleSettings = _.get(config, [ "rules", ruleName ])
|
|
if (ruleSettings === null || ruleSettings[0] === null) {
|
|
return
|
|
}
|
|
|
|
const primaryOption = ruleSettings[0]
|
|
const secondaryOptions = ruleSettings[1]
|
|
|
|
// Log the rule's severity in the PostCSS result
|
|
const defaultSeverity = config.defaultSeverity || "error"
|
|
postcssResult.stylelint.ruleSeverities[ruleName] = _.get(secondaryOptions, "severity", defaultSeverity)
|
|
postcssResult.stylelint.customMessages[ruleName] = _.get(secondaryOptions, "message")
|
|
|
|
const performRule = Promise.resolve().then(() => {
|
|
ruleFunction(primaryOption, secondaryOptions)(postcssRoot, postcssResult)
|
|
})
|
|
performRules.push(performRule)
|
|
})
|
|
|
|
return Promise.all(performRules)
|
|
}
|
|
|
|
function createEmptyPostcssResult(filePath/*:: ?: string*/)/*: Object*/ {
|
|
return {
|
|
root: {
|
|
source: {
|
|
input: { file: filePath },
|
|
},
|
|
},
|
|
messages: [],
|
|
stylelint: { stylelintError: null },
|
|
}
|
|
}
|