mirror of
https://github.com/antebudimir/eslint-plugin-vanilla-extract.git
synced 2026-01-01 17:23:31 +00:00
91 lines
3.5 KiB
TypeScript
91 lines
3.5 KiB
TypeScript
import type { Rule } from 'eslint';
|
|
import { generateFixesForCSSOrder } from '../shared-utils/css-order-fixer.js';
|
|
import { createCSSPropertyPriorityMap } from '../shared-utils/css-property-priority-map.js';
|
|
import type { CSSPropertyInfo } from '../concentric-order/types.js';
|
|
|
|
/**
|
|
* Enforces a custom ordering of CSS properties based on user-defined groups.
|
|
*
|
|
* @param ruleContext The ESLint rule context used for reporting and fixing.
|
|
* @param cssPropertyInfoList An array of CSS property information objects to be ordered.
|
|
* @param userDefinedGroups Array of user-defined property groups for custom ordering.
|
|
* @param sortRemainingProperties Strategy for sorting properties not in user-defined groups
|
|
* ('alphabetical' or 'concentric'). Defaults to 'concentric'.
|
|
*
|
|
* This function compares CSS properties based on their group priority and position within
|
|
* those groups. Properties not part of user-defined groups are sorted according to the
|
|
* specified strategy. If an ordering violation is detected, an ESLint report is generated
|
|
* with a suggested fix.
|
|
*/
|
|
export const enforceCustomGroupOrder = (
|
|
ruleContext: Rule.RuleContext,
|
|
cssPropertyInfoList: CSSPropertyInfo[],
|
|
userDefinedGroups: string[] = [],
|
|
sortRemainingProperties?: 'alphabetical' | 'concentric',
|
|
): void => {
|
|
if (cssPropertyInfoList.length <= 1) {
|
|
return;
|
|
}
|
|
|
|
const cssPropertyPriorityMap = createCSSPropertyPriorityMap(userDefinedGroups);
|
|
|
|
const compareProperties = (firstProperty: CSSPropertyInfo, secondProperty: CSSPropertyInfo) => {
|
|
const firstPropertyInfo = cssPropertyPriorityMap.get(firstProperty.name) || {
|
|
groupIndex: Infinity,
|
|
positionInGroup: Infinity,
|
|
inUserGroup: false,
|
|
};
|
|
const secondPropertyInfo = cssPropertyPriorityMap.get(secondProperty.name) || {
|
|
groupIndex: Infinity,
|
|
positionInGroup: Infinity,
|
|
inUserGroup: false,
|
|
};
|
|
|
|
if (firstPropertyInfo.inUserGroup !== secondPropertyInfo.inUserGroup) {
|
|
return firstPropertyInfo.inUserGroup ? -1 : 1;
|
|
}
|
|
|
|
if (firstPropertyInfo.inUserGroup) {
|
|
if (firstPropertyInfo.groupIndex !== secondPropertyInfo.groupIndex) {
|
|
return firstPropertyInfo.groupIndex - secondPropertyInfo.groupIndex;
|
|
}
|
|
return firstPropertyInfo.positionInGroup - secondPropertyInfo.positionInGroup;
|
|
}
|
|
|
|
// For properties not in user-defined groups
|
|
if (sortRemainingProperties === 'alphabetical') {
|
|
return firstProperty.name.localeCompare(secondProperty.name);
|
|
} else {
|
|
return (
|
|
firstPropertyInfo.groupIndex - secondPropertyInfo.groupIndex ||
|
|
firstPropertyInfo.positionInGroup - secondPropertyInfo.positionInGroup
|
|
);
|
|
}
|
|
};
|
|
|
|
const sortedPropertyList = [...cssPropertyInfoList].sort(compareProperties);
|
|
|
|
// Find the first pair that violates the new ordering
|
|
const violatingProperty = cssPropertyInfoList
|
|
.slice(0, -1)
|
|
.find((currentProperty, index) => currentProperty.name !== sortedPropertyList[index]?.name);
|
|
|
|
if (violatingProperty) {
|
|
ruleContext.report({
|
|
node: violatingProperty.node as Rule.Node,
|
|
messageId: 'incorrectOrder',
|
|
data: {
|
|
currentProperty: violatingProperty.name,
|
|
nextProperty: sortedPropertyList[cssPropertyInfoList.indexOf(violatingProperty)]?.name || '',
|
|
},
|
|
fix: (fixer) =>
|
|
generateFixesForCSSOrder(
|
|
fixer,
|
|
ruleContext,
|
|
cssPropertyInfoList,
|
|
compareProperties,
|
|
(propertyInfo) => propertyInfo.node as Rule.Node,
|
|
),
|
|
});
|
|
}
|
|
};
|