@salesforce-ux/eslint-plugin-slds
Version:
ESLint plugin provides custom linting rules specifically built for Salesforce Lightning Design System 2 (SLDS 2 beta)
91 lines (90 loc) • 4.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const node_1 = require("./utils/node");
const sds_metadata_1 = __importDefault(require("@salesforce-ux/sds-metadata"));
const bemMapping = sds_metadata_1.default.bemNaming;
const deprecatedClasses = sds_metadata_1.default.deprecatedClasses;
/**
* Checks if a given className or its BEM mapped equivalent is deprecated.
*
* This function checks whether the provided className is included in the
* `deprecatedClasses` list or if the BEM mapped class is deprecated.
*
* @param className - The class name to check for deprecation.
* @returns A boolean indicating whether the className or its mapped version is deprecated.
*/
const isDeprecatedClass = (className) => {
return (deprecatedClasses.includes(className) || deprecatedClasses.includes(bemMapping[className]));
};
module.exports = {
meta: {
type: "problem", // The rule type
docs: {
category: "Stylistic Issues",
recommended: true,
description: "Replace BEM double-dash syntax in class names with single underscore syntax.",
url: "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-bem-usage"
},
fixable: "code", // This rule can be fixed automatically
schema: [
{
type: "object",
properties: {
pattern: { type: "string" }, // Regex pattern for BEM
flags: { type: "string" }, // Regex flags
},
additionalProperties: false,
},
],
},
create(context) {
function check(node) {
if ((0, node_1.isAttributesEmpty)(node)) {
return;
}
const classAttr = (0, node_1.findAttr)(node, "class");
if (classAttr && classAttr.value) {
const classNames = classAttr.value.value.split(/\s+/);
classNames.forEach((className) => {
if (className && className in bemMapping && !isDeprecatedClass(className)) {
// Find the exact location of the problematic class name
const classNameStart = classAttr.value.value.indexOf(className) + 7; // 7 here is for `class= "`
const classNameEnd = classNameStart + className.length;
// Use the loc property to get line and column from the class attribute
const startLoc = {
line: classAttr.loc.start.line,
column: classAttr.loc.start.column + classNameStart,
};
const endLoc = {
line: classAttr.loc.start.line,
column: classAttr.loc.start.column + classNameEnd,
};
// Check whether a fixed class is available
const newValue = bemMapping[className];
context.report({
node,
loc: { start: startLoc, end: endLoc },
data: {
actual: className,
newValue
},
message: "{{actual}} has been retired. Update it to the new name {{newValue}}.",
fix(fixer) {
if (newValue) {
const newClassValue = classAttr.value.value.replace(className, newValue);
return fixer.replaceTextRange([classAttr.value.range[0], classAttr.value.range[1]], `${newClassValue}`);
}
return null; // Ensure a return value even if no fix is applied
},
});
}
});
}
}
return {
Tag: check,
};
},
};