UNPKG

@ec0lint/plugin-css

Version:

ec0lint plugin that provides rules to verify CSS definition objects

147 lines (146 loc) 6.59 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 postcss_value_parser_1 = __importDefault(require("postcss-value-parser")); const regexp_1 = require("../utils/regexp"); const casing_1 = require("../utils/casing"); const resource_1 = require("../utils/resource"); exports.default = (0, utils_1.createRule)("no-length-zero-unit", { meta: { docs: { description: "disallow units for zero lengths", category: "Best Practices", recommended: false, standard: true, stylelint: "length-zero-no-unit", }, schema: [ { type: "object", properties: { ignoreProperties: { type: "array", items: { type: "string", }, uniqueItems: true, minItems: 1, }, ignoreFunctions: { type: "array", items: { type: "string", }, uniqueItems: true, minItems: 1, }, ignoreCustomProperties: { type: "boolean" }, }, additionalProperties: false, }, ], fixable: "code", messages: { unexpected: "Unexpected unit.", }, type: "suggestion", }, create(context) { var _a, _b, _c, _d, _e; const ignoreFunctions = [ ...((_b = (_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.ignoreFunctions) !== null && _b !== void 0 ? _b : []), ].map(regexp_1.toRegExp); const ignoreProperties = [ ...((_d = (_c = context.options[0]) === null || _c === void 0 ? void 0 : _c.ignoreProperties) !== null && _d !== void 0 ? _d : []), ].map(regexp_1.toRegExp); const ignoreCustomProperties = Boolean((_e = context.options[0]) === null || _e === void 0 ? void 0 : _e.ignoreCustomProperties); function createVisitor(cssContext) { function ignorePropName(name) { return (name === "line-height" || name === "flex" || ignoreProperties.some((r) => r.test(name)) || (ignoreCustomProperties && name.startsWith("--"))); } return { onProperty(property) { const prop = property.getName(); if (!prop || ignorePropName(prop.name) || ((0, casing_1.isCamelCase)(prop.name) && ignorePropName((0, casing_1.kebabCase)(prop.name)))) { return; } const value = property.getValue(); if (!value) { return; } const parsedValue = value.parsed; parsedValue.walk((valueNode, valueNodeIndex, valueNodes) => { if (prop.name === "font" && valueNodeIndex > 0 && valueNodes[valueNodeIndex - 1].type === "div" && valueNodes[valueNodeIndex - 1].value === "/") return undefined; const { value: textValue, sourceIndex } = valueNode; if (isMathFunction(valueNode)) return false; if (valueNode.type === "function" && ignoreFunctions.some((r) => r.test(valueNode.value))) return false; if (valueNode.type !== "word") return undefined; const numberUnit = postcss_value_parser_1.default.unit(textValue); if (numberUnit === false) return undefined; const { number, unit } = numberUnit; if (unit === "" || !isLengthUnit(unit) || unit.toLowerCase() === "fr" || Number(number) !== 0) return undefined; const sourceCode = context.getSourceCode(); const startIndex = value.expression.range[0] + sourceIndex + number.length + 1; const endIndex = startIndex + unit.length; const loc = value.directExpression ? { start: sourceCode.getLocFromIndex(startIndex), end: sourceCode.getLocFromIndex(endIndex), } : undefined; context.report({ node: value.expression, loc, messageId: "unexpected", fix(fixer) { if (cssContext.isFixable(value.directExpression) && sourceCode.text.slice(startIndex, endIndex) === unit) { return fixer.removeRange([ startIndex, endIndex, ]); } return null; }, }); return undefined; }); }, }; } return (0, utils_1.defineCSSVisitor)(context, { createVisitor, }); }, }); function isMathFunction(node) { return (node.type === "function" && resource_1.MATH_FUNCTIONS.has(node.value.toLowerCase())); } function isLengthUnit(unit) { return resource_1.LENGTH_UNITS.has(unit.toLowerCase()); }