mirror of
https://github.com/thangisme/notes.git
synced 2024-06-28 11:15:26 +00:00
146 lines
4.3 KiB
JavaScript
146 lines
4.3 KiB
JavaScript
"use strict"
|
|
|
|
const _ = require("lodash")
|
|
const declarationValueIndex = require("../../utils/declarationValueIndex")
|
|
const isStandardSyntaxFunction = require("../../utils/isStandardSyntaxFunction")
|
|
const isStandardSyntaxValue = require("../../utils/isStandardSyntaxValue")
|
|
const keywordSets = require("../../reference/keywordSets")
|
|
const namedColorData = require("../../reference/namedColorData")
|
|
const optionsMatches = require("../../utils/optionsMatches")
|
|
const propertySets = require("../../reference/propertySets")
|
|
const report = require("../../utils/report")
|
|
const ruleMessages = require("../../utils/ruleMessages")
|
|
const validateOptions = require("../../utils/validateOptions")
|
|
const valueParser = require("postcss-value-parser")
|
|
|
|
const ruleName = "color-named"
|
|
|
|
const messages = ruleMessages(ruleName, {
|
|
expected: (named, original) => `Expected "${original}" to be "${named}"`,
|
|
rejected: named => `Unexpected named color "${named}"`,
|
|
})
|
|
|
|
// Todo tested on case insensivity
|
|
const NODE_TYPES = [
|
|
"word",
|
|
"function",
|
|
]
|
|
|
|
const rule = function (expectation, options) {
|
|
return (root, result) => {
|
|
const validOptions = validateOptions(result, ruleName, {
|
|
actual: expectation,
|
|
possible: [
|
|
"never",
|
|
"always-where-possible",
|
|
],
|
|
}, {
|
|
actual: options,
|
|
possible: {
|
|
ignoreProperties: [_.isString],
|
|
ignore: ["inside-function"],
|
|
},
|
|
optional: true,
|
|
})
|
|
|
|
if (!validOptions) {
|
|
return
|
|
}
|
|
|
|
const namedColors = Object.keys(namedColorData)
|
|
|
|
root.walkDecls(decl => {
|
|
if (propertySets.acceptCustomIdents.has(decl.prop)) {
|
|
return
|
|
}
|
|
|
|
// Return early if the property is to be ignored
|
|
if (optionsMatches(options, "ignoreProperties", decl.prop)) {
|
|
return
|
|
}
|
|
|
|
valueParser(decl.value).walk(node => {
|
|
const value = node.value,
|
|
type = node.type,
|
|
sourceIndex = node.sourceIndex
|
|
|
|
if (
|
|
optionsMatches(options, "ignore", "inside-function")
|
|
&& type === "function"
|
|
) {
|
|
return false
|
|
}
|
|
|
|
if (!isStandardSyntaxFunction(node)) {
|
|
return false
|
|
}
|
|
|
|
if (!isStandardSyntaxValue(value)) {
|
|
return
|
|
}
|
|
// Return early if neither a word nor a function
|
|
if (NODE_TYPES.indexOf(type) === -1) {
|
|
return
|
|
}
|
|
|
|
// Check for named colors for "never" option
|
|
if (
|
|
expectation === "never"
|
|
&& type === "word"
|
|
&& namedColors.indexOf(value.toLowerCase()) !== -1
|
|
) {
|
|
complain(messages.rejected(value), decl, declarationValueIndex(decl) + sourceIndex)
|
|
return
|
|
}
|
|
|
|
// Check "always-where-possible" option ...
|
|
if (expectation !== "always-where-possible") {
|
|
return
|
|
}
|
|
|
|
// First by checking for alternative color function representations ...
|
|
if (
|
|
type === "function"
|
|
&& keywordSets.colorFunctionNames.has(value.toLowerCase())
|
|
) {
|
|
// Remove all spaces to match what's in `representations`
|
|
const normalizedFunctionString = valueParser.stringify(node).replace(/\s+/g, "")
|
|
let namedColor
|
|
for (let i = 0, l = namedColors.length; i < l; i++) {
|
|
namedColor = namedColors[i]
|
|
if (namedColorData[namedColor].func.indexOf(normalizedFunctionString.toLowerCase()) !== -1) {
|
|
complain(messages.expected(namedColor, normalizedFunctionString), decl, declarationValueIndex(decl) + sourceIndex)
|
|
return // Exit as soon as a problem is found
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// Then by checking for alternative hex representations
|
|
let namedColor
|
|
for (let i = 0, l = namedColors.length; i < l; i++) {
|
|
namedColor = namedColors[i]
|
|
if (namedColorData[namedColor].hex.indexOf(value.toLowerCase()) !== -1) {
|
|
complain(messages.expected(namedColor, value), decl, declarationValueIndex(decl) + sourceIndex)
|
|
return // Exit as soon as a problem is found
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
function complain(message, node, index) {
|
|
report({
|
|
result,
|
|
ruleName,
|
|
message,
|
|
node,
|
|
index,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
rule.ruleName = ruleName
|
|
rule.messages = messages
|
|
module.exports = rule
|