UNPKG

@ec0lint/plugin-css

Version:

ec0lint plugin that provides rules to verify CSS definition objects

128 lines (127 loc) 5.18 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../utils"); const css_utils_1 = require("../utils/css-utils"); const postcss_value_parser_1 = __importDefault(require("postcss-value-parser")); const ast_utils_1 = require("../utils/ast-utils"); const SHORTHAND_PROPERTIES = new Set([ "margin", "padding", "border-color", "border-radius", "border-style", "border-width", "grid-gap", ]); const IGNORED_CHARS = ["+", "*", "/", "(", ")", "$", "@", "--", "var("]; function hasIgnoredCharacters(value) { if (typeof value !== "string") { return false; } return IGNORED_CHARS.some((char) => value.includes(char)); } function reducedValues(values) { var _a, _b; if (values.length <= 1 || values.length > 4) { return values; } const [top, right, bottom, left] = values; const lowerTop = top.toLowerCase(); const lowerRight = right.toLowerCase(); const lowerBottom = (_a = (bottom && bottom.toLowerCase())) !== null && _a !== void 0 ? _a : lowerTop; const lowerLeft = (_b = (left && left.toLowerCase())) !== null && _b !== void 0 ? _b : lowerRight; if ([lowerRight, lowerBottom, lowerLeft].every((val) => val === lowerTop)) { return [top]; } if (lowerRight === lowerLeft) { if (lowerTop === lowerBottom) { return [top, right]; } return [top, right, bottom]; } return [top, right, bottom, left]; } exports.default = (0, utils_1.createRule)("prefer-reduce-shorthand-property-box-values", { meta: { docs: { description: "require reduction in box values of shorthand property", category: "Best Practices", recommended: false, standard: true, stylelint: "shorthand-property-no-redundant-values", }, fixable: "code", schema: [], messages: { unexpected: "Unexpected longhand value '{{unexpected}}' instead of '{{expected}}'.", }, type: "suggestion", }, create(context) { function createVisitor(cssContext) { const sourceCode = context.getSourceCode(); return { onProperty(property) { const name = property.getName(); if (!name) { return; } const value = property.getValue(); if (!value) { return; } if (hasIgnoredCharacters(value.value) || !SHORTHAND_PROPERTIES.has((0, css_utils_1.normalizePropertyName)(name.name))) { return; } const boxValues = []; value.parsed.walk((node) => { if (node.type !== "word") { return; } boxValues.push(postcss_value_parser_1.default.stringify(node)); }); if (boxValues.length <= 1 || boxValues.length > 4) { return; } const shortestForm = reducedValues(boxValues); if (boxValues.length <= shortestForm.length) { return; } const startIndex = value.expression.range[0] + 1; const endIndex = value.expression.range[1] - 1; const loc = value.directExpression ? { start: sourceCode.getLocFromIndex(startIndex), end: sourceCode.getLocFromIndex(endIndex), } : undefined; const shortestFormString = shortestForm.join(" "); context.report({ node: value.expression, loc, messageId: "unexpected", data: { unexpected: String(value.value), expected: shortestFormString, }, fix(fixer) { if (cssContext.isFixable(value.directExpression) && ((0, ast_utils_1.isStaticTemplateLiteral)(value.expression) || (0, ast_utils_1.isStringLiteral)(value.expression))) { return fixer.replaceTextRange([startIndex, endIndex], shortestFormString); } return null; }, }); }, }; } return (0, utils_1.defineCSSVisitor)(context, { createVisitor, }); }, });