mirror of
https://github.com/thangisme/notes.git
synced 2024-12-23 00:26:28 -05:00
182 lines
5.7 KiB
JavaScript
182 lines
5.7 KiB
JavaScript
|
/* @flow */
|
||
|
"use strict"
|
||
|
const _ = require("lodash")
|
||
|
|
||
|
const COMMAND_PREFIX = "stylelint-"
|
||
|
const disableCommand = COMMAND_PREFIX + "disable"
|
||
|
const enableCommand = COMMAND_PREFIX + "enable"
|
||
|
const disableLineCommand = COMMAND_PREFIX + "disable-line"
|
||
|
const disableNextLineCommand = COMMAND_PREFIX + "disable-next-line"
|
||
|
const ALL_RULES = "all"
|
||
|
|
||
|
/*:: type disabledRangeObject = {
|
||
|
[ruleName: string]: Array<{
|
||
|
start: number,
|
||
|
end?: number,
|
||
|
}>
|
||
|
}*/
|
||
|
|
||
|
// Run it like a plugin ...
|
||
|
module.exports = function (
|
||
|
root/*: Object*/,
|
||
|
result/*: Object*/
|
||
|
) {
|
||
|
result.stylelint = result.stylelint || {}
|
||
|
|
||
|
// Most of the functions below work via side effects mutating
|
||
|
// this object
|
||
|
const disabledRanges/*: disabledRangeObject*/ = {
|
||
|
all: [],
|
||
|
}
|
||
|
result.stylelint.disabledRanges = disabledRanges
|
||
|
root.walkComments(checkComment)
|
||
|
|
||
|
return result
|
||
|
|
||
|
function processDisableLineCommand(comment/*: postcss$comment*/) {
|
||
|
getCommandRules(disableLineCommand, comment.text).forEach(ruleName => {
|
||
|
disableLine(comment.source.start.line, ruleName, comment)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function processDisableNextLineCommand(comment/*: postcss$comment*/) {
|
||
|
getCommandRules(disableNextLineCommand, comment.text).forEach(ruleName => {
|
||
|
disableLine(comment.source.start.line + 1, ruleName, comment)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function disableLine(
|
||
|
line/*: number*/,
|
||
|
ruleName/*: string*/,
|
||
|
comment/*: postcss$comment*/
|
||
|
) {
|
||
|
if (ruleIsDisabled(ALL_RULES)) {
|
||
|
throw comment.error("All rules have already been disabled", { plugin: "stylelint" })
|
||
|
}
|
||
|
if (ruleIsDisabled(ruleName)) {
|
||
|
throw comment.error(`"${ruleName}" has already been disabled`, { plugin: "stylelint" })
|
||
|
}
|
||
|
if (ruleName === ALL_RULES) {
|
||
|
Object.keys(disabledRanges).forEach(disabledRuleName => {
|
||
|
startDisabledRange(line, disabledRuleName)
|
||
|
endDisabledRange(line, disabledRuleName)
|
||
|
})
|
||
|
} else {
|
||
|
startDisabledRange(line, ruleName)
|
||
|
endDisabledRange(line, ruleName)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function processDisableCommand(comment/*: postcss$comment*/) {
|
||
|
getCommandRules(disableCommand, comment.text).forEach(ruleToDisable => {
|
||
|
if (ruleToDisable === ALL_RULES) {
|
||
|
if (ruleIsDisabled(ALL_RULES)) {
|
||
|
throw comment.error("All rules have already been disabled", { plugin: "stylelint" })
|
||
|
}
|
||
|
Object.keys(disabledRanges).forEach(ruleName => {
|
||
|
startDisabledRange(comment.source.start.line, ruleName)
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (ruleIsDisabled(ruleToDisable)) {
|
||
|
throw comment.error(`"${ruleToDisable}" has already been disabled`, { plugin: "stylelint" })
|
||
|
}
|
||
|
startDisabledRange(comment.source.start.line, ruleToDisable)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function processEnableCommand(comment/*: postcss$comment*/) {
|
||
|
getCommandRules(enableCommand, comment.text).forEach(ruleToEnable => {
|
||
|
if (ruleToEnable === ALL_RULES) {
|
||
|
if (_.values(disabledRanges).every(ranges => _.isEmpty(ranges) || !!_.last(ranges.end))) {
|
||
|
throw comment.error("No rules have been disabled", { plugin: "stylelint" })
|
||
|
}
|
||
|
Object.keys(disabledRanges).forEach(ruleName => {
|
||
|
if (!_.get(_.last(disabledRanges[ruleName]), "end")) {
|
||
|
endDisabledRange(comment.source.end.line, ruleName)
|
||
|
}
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (ruleIsDisabled(ALL_RULES) && disabledRanges[ruleToEnable] === undefined) {
|
||
|
// Get a starting point from the where all rules were disabled
|
||
|
if (!disabledRanges[ruleToEnable]) {
|
||
|
disabledRanges[ruleToEnable] = _.cloneDeep(disabledRanges.all)
|
||
|
} else {
|
||
|
disabledRanges[ruleToEnable].push(_.clone(_.last(disabledRanges[ALL_RULES])))
|
||
|
}
|
||
|
endDisabledRange(comment.source.end.line, ruleToEnable)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (ruleIsDisabled(ruleToEnable)) {
|
||
|
endDisabledRange(comment.source.end.line, ruleToEnable)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
throw comment.error(`"${ruleToEnable}" has not been disabled`, { plugin: "stylelint" })
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function checkComment(comment/*: postcss$comment*/) {
|
||
|
const text = comment.text
|
||
|
|
||
|
// Ignore comments that are not relevant commands
|
||
|
|
||
|
if (text.indexOf(COMMAND_PREFIX) !== 0) {
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
if (text.indexOf(disableLineCommand) === 0) {
|
||
|
processDisableLineCommand(comment)
|
||
|
} else if (text.indexOf(disableNextLineCommand) === 0) {
|
||
|
processDisableNextLineCommand(comment)
|
||
|
} else if (text.indexOf(disableCommand) === 0) {
|
||
|
processDisableCommand(comment)
|
||
|
} else if (text.indexOf(enableCommand) === 0) {
|
||
|
processEnableCommand(comment)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function getCommandRules(
|
||
|
command/*: string*/,
|
||
|
fullText/*: string*/
|
||
|
)/*: Array<string>*/ {
|
||
|
const rules = _.compact(fullText.slice(command.length).split(",")).map(r => r.trim())
|
||
|
if (_.isEmpty(rules)) {
|
||
|
return [ALL_RULES]
|
||
|
}
|
||
|
return rules
|
||
|
}
|
||
|
|
||
|
function startDisabledRange(line/*: number*/, ruleName/*: string*/) {
|
||
|
const rangeObj = { start: line }
|
||
|
ensureRuleRanges(ruleName)
|
||
|
disabledRanges[ruleName].push(rangeObj)
|
||
|
}
|
||
|
|
||
|
function endDisabledRange(line/*: number*/, ruleName/*: string*/) {
|
||
|
const lastRangeForRule = _.last(disabledRanges[ruleName])
|
||
|
if (!lastRangeForRule) {
|
||
|
return
|
||
|
}
|
||
|
// Add an `end` prop to the last range of that rule
|
||
|
lastRangeForRule.end = line
|
||
|
}
|
||
|
|
||
|
function ensureRuleRanges(ruleName/*: string*/) {
|
||
|
if (!disabledRanges[ruleName]) {
|
||
|
disabledRanges[ruleName] = _.cloneDeep(disabledRanges.all)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function ruleIsDisabled(ruleName/*: string*/)/*: boolean*/ {
|
||
|
if (disabledRanges[ruleName] === undefined) return false
|
||
|
if (_.last(disabledRanges[ruleName]) === undefined) return false
|
||
|
if (_.get(_.last(disabledRanges[ruleName]), "end") === undefined) return true
|
||
|
return false
|
||
|
}
|
||
|
}
|