UNPKG

stylelint

Version:

A mighty, modern CSS linter.

121 lines (90 loc) 3.01 kB
// @ts-nocheck 'use strict'; const valueParser = require('postcss-value-parser'); const declarationValueIndex = require('../../utils/declarationValueIndex'); const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); const ruleName = 'color-function-notation'; const messages = ruleMessages(ruleName, { expected: (primary) => `Expected ${primary} color-function notation`, }); const LEGACY_FUNCS = ['rgba', 'hsla']; const LEGACY_NOTATION_FUNCS = ['rgb', 'rgba', 'hsl', 'hsla']; function rule(primary, secondary, context) { return (root, result) => { const validOptions = validateOptions(result, ruleName, { actual: primary, possible: ['modern', 'legacy'], }); if (!validOptions) return; root.walkDecls((decl) => { if (!isStandardSyntaxDeclaration(decl)) return; let needsFix = false; const parsedValue = valueParser(getValue(decl)); parsedValue.walk((node) => { const { value, type, sourceIndex, nodes } = node; if (type !== 'function') return; if (!LEGACY_NOTATION_FUNCS.includes(value.toLowerCase())) return; if (primary === 'modern' && !hasCommas(node)) return; if (primary === 'legacy' && hasCommas(node)) return; if (context.fix && primary === 'modern') { let commaCount = 0; // Convert punctuation node.nodes = nodes.map((childNode) => { if (isComma(childNode)) { // Non-alpha commas to space and alpha commas to slashes if (commaCount < 2) { childNode.type = 'space'; childNode.value = atLeastOneSpace(childNode.after); commaCount++; } else { childNode.value = '/'; childNode.before = atLeastOneSpace(childNode.before); childNode.after = atLeastOneSpace(childNode.after); } } return childNode; }); // Remove trailing 'a' from legacy function name if (LEGACY_FUNCS.includes(node.value.toLowerCase())) { node.value = node.value.slice(0, -1); } needsFix = true; return; } report({ message: messages.expected(primary), node: decl, index: declarationValueIndex(decl) + sourceIndex, result, ruleName, }); }); if (needsFix) { setValue(decl, parsedValue.toString()); } }); }; } function atLeastOneSpace(whitespace) { return whitespace !== '' ? whitespace : ' '; } function isComma(node) { return node.type === 'div' && node.value === ','; } function hasCommas(node) { return node.nodes && node.nodes.some((childNode) => isComma(childNode)); } function getValue(decl) { return decl.raws.value ? decl.raws.value.raw : decl.value; } function setValue(decl, value) { if (decl.raws.value) decl.raws.value.raw = value; else decl.value = value; return decl; } rule.ruleName = ruleName; rule.messages = messages; module.exports = rule;