1
0
mirror of https://github.com/thangisme/notes.git synced 2024-06-28 11:15:26 +00:00
notes/node_modules/stylelint/lib/rules/color-named/index.js
Patrick Marsceill b7b0d0d7bf
Initial commit
2017-03-09 13:16:08 -05:00

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