Files
barker/bookie/sort-component-imports.js
Amritanshu 68ab90ec48 Chore: Cleaned up imports to use Modules.
Feature: Added an eslint rule to sort component imports
2024-12-19 08:29:05 +05:30

115 lines
4.1 KiB
JavaScript

/**
* @fileoverview ESLint rule to enforce sorted imports arrays in Angular @Component decorators.
*/
"use strict";
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Enforce sorted imports array in Angular @Component decorators",
category: "Stylistic Issues",
recommended: false,
},
fixable: "code",
schema: [] // no options
},
create(context) {
return {
Decorator(node) {
// Look for @Component decorator
if (
node.expression &&
node.expression.callee &&
node.expression.callee.name === "Component" &&
node.expression.arguments &&
node.expression.arguments.length > 0
) {
const arg = node.expression.arguments[0];
if (arg && arg.type === "ObjectExpression") {
// Find the 'imports' property
const importsProperty = arg.properties.find(
(prop) =>
prop.type === "Property" &&
((prop.key.type === "Identifier" && prop.key.name === "imports") ||
(prop.key.type === "Literal" && prop.key.value === "imports"))
);
if (importsProperty && importsProperty.value.type === "ArrayExpression") {
const elements = importsProperty.value.elements;
// Extract the names from the elements
// Assuming elements are simple Identifiers or Literals
const elementNames = elements.map((el) => {
if (!el) return "";
if (el.type === "Identifier") {
return el.name;
} else if (el.type === "Literal" && typeof el.value === "string") {
return el.value;
} else {
return ""; // Non-standard entry, skip sorting
}
});
// Check if sorted
const sorted = [...elementNames].sort((a, b) =>
a.localeCompare(b, undefined, { sensitivity: "base" })
);
// Compare elementNames and sorted
let isSorted = true;
for (let i = 0; i < elementNames.length; i++) {
if (elementNames[i] !== sorted[i]) {
isSorted = false;
break;
}
}
if (!isSorted) {
// Report and fix
context.report({
node: importsProperty,
message: "The imports array in @Component should be sorted alphabetically.",
fix: (fixer) => {
// Build a sorted array expression text
const sourceCode = context.getSourceCode();
const sortedElements = [];
for (const name of sorted) {
// Attempt to find original element to preserve formatting if possible
const originalElement = elements.find((el) => {
if (!el) return false;
if (el.type === "Identifier" && el.name === name) return true;
if (el.type === "Literal" && el.value === name) return true;
return false;
});
if (originalElement) {
sortedElements.push(sourceCode.getText(originalElement));
} else {
// fallback: write identifier as is
// If it's a string, wrap in quotes
const isIdentifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
sortedElements.push(isIdentifier ? name : `'${name}'`);
}
}
const arrayText = `[${sortedElements.join(", ")}]`;
const importsValue = importsProperty.value;
return fixer.replaceTextRange(
[importsValue.range[0], importsValue.range[1]],
arrayText
);
},
});
}
}
}
}
},
};
},
};