// NOTICE: This file is generated by Rollup. To modify it, // please instead edit the ESM counterpart and rebuild with Rollup (npm run build). 'use strict'; const valueParser = require('postcss-value-parser'); const validateTypes = require('../../utils/validateTypes.cjs'); const properties = require('../../reference/properties.cjs'); const colordUtils = require('./colordUtils.cjs'); const nodeFieldIndices = require('../../utils/nodeFieldIndices.cjs'); const hasColorFunction = require('../../utils/hasColorFunction.cjs'); const hasNamedColor = require('../../utils/hasNamedColor.cjs'); const hasValidHex = require('../../utils/hasValidHex.cjs'); const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction.cjs'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue.cjs'); const keywords = require('../../reference/keywords.cjs'); const optionsMatches = require('../../utils/optionsMatches.cjs'); const report = require('../../utils/report.cjs'); const ruleMessages = require('../../utils/ruleMessages.cjs'); const validateOptions = require('../../utils/validateOptions.cjs'); const ruleName = 'color-named'; const messages = ruleMessages(ruleName, { expected: (expected, actual) => `Expected "${actual}" to be "${expected}"`, rejected: (keyword) => `Unexpected named color "${keyword}"`, }); const meta = { url: 'https://stylelint.io/user-guide/rules/color-named', }; // Todo tested on case insensitivity const NODE_TYPES = new Set(['word', 'function']); const HAS_GRAY_FUNCTION = /\bgray\(/i; /** @type {import('stylelint').CoreRules[ruleName]} */ const rule = (primary, secondaryOptions) => { return (root, result) => { const validOptions = validateOptions( result, ruleName, { actual: primary, possible: ['never', 'always-where-possible'], }, { actual: secondaryOptions, possible: { ignoreProperties: [validateTypes.isString, validateTypes.isRegExp], ignore: ['inside-function'], }, optional: true, }, ); if (!validOptions) { return; } root.walkDecls((decl) => { if (properties.acceptCustomIdentsProperties.has(decl.prop)) { return; } // Return early if the property is to be ignored if (optionsMatches(secondaryOptions, 'ignoreProperties', decl.prop)) { return; } const { value: declValue } = decl; if (primary === 'never' && !hasNamedColor(declValue)) { return; } if ( primary === 'always-where-possible' && !hasValidHex(declValue) && !hasColorFunction(declValue) && !HAS_GRAY_FUNCTION.test(declValue) ) { return; } valueParser(declValue).walk((node) => { const value = node.value; const type = node.type; const sourceIndex = node.sourceIndex; if (optionsMatches(secondaryOptions, '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.has(type)) { return; } // Check for named colors for "never" option if ( primary === 'never' && type === 'word' && keywords.namedColorsKeywords.has(value.toLowerCase()) ) { complain( messages.rejected(value), decl, nodeFieldIndices.declarationValueIndex(decl) + sourceIndex, value.length, ); return; } // Check "always-where-possible" option ... if (primary !== 'always-where-possible') { return; } let rawColorString = null; let colorString = null; if (type === 'function') { rawColorString = valueParser.stringify(node); // First by checking for alternative color function representations ... // Remove all spaces to match what's in `representations` colorString = rawColorString.replace(/\s*([,/()])\s*/g, '$1').replace(/\s{2,}/g, ' '); } else if (type === 'word' && value.startsWith('#')) { // Then by checking for alternative hex representations rawColorString = colorString = value; } else { return; } const color = colordUtils.colord(colorString); if (!color.isValid()) { return; } const namedColor = color.toName(); if (namedColor && namedColor.toLowerCase() !== 'transparent') { complain( messages.expected(namedColor, colorString), decl, nodeFieldIndices.declarationValueIndex(decl) + sourceIndex, rawColorString.length, ); } }); }); /** * @param {string} message * @param {import('postcss').Node} node * @param {number} index * @param {number} length */ function complain(message, node, index, length) { report({ result, ruleName, message, node, index, endIndex: index + length, }); } }; }; rule.ruleName = ruleName; rule.messages = messages; rule.meta = meta; module.exports = rule;