@ec0lint/plugin-css
Version:
ec0lint plugin that provides rules to verify CSS definition objects
128 lines (127 loc) • 5.18 kB
JavaScript
;
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,
});
},
});