feat 🥁: initialize project with complete codebase

This commit is contained in:
Ante Budimir 2025-03-04 20:16:50 +02:00
commit d569dea1fb
35 changed files with 4413 additions and 0 deletions

View file

@ -0,0 +1,3 @@
import alphabeticalOrderRule from './rule-definition.js';
export default alphabeticalOrderRule;

View file

@ -0,0 +1,84 @@
import type { Rule } from 'eslint';
import { TSESTree } from '@typescript-eslint/utils';
import { generateFixesForCSSOrder } from '../shared-utils/css-order-fixer.js';
import { getPropertyName } from '../shared-utils/property-separator.js';
/**
* Compares two CSS properties alphabetically.
* @param firstProperty The first property to compare.
* @param secondProperty The second property to compare.
* @returns A number indicating the relative order of the properties (-1, 0, or 1).
*/
const comparePropertiesAlphabetically = (
firstProperty: TSESTree.Property,
secondProperty: TSESTree.Property,
): number => {
const firstName = getPropertyName(firstProperty);
const secondName = getPropertyName(secondProperty);
return firstName.localeCompare(secondName);
};
/**
* Reports an ordering issue to ESLint and generates fixes.
* @param ruleContext The ESLint rule context.
* @param currentProperty The current property in the order.
* @param nextProperty The next property that is out of order.
* @param regularProperties The full list of regular properties to be reordered.
*/
const reportOrderingIssue = (
ruleContext: Rule.RuleContext,
currentProperty: TSESTree.Property,
nextProperty: TSESTree.Property,
regularProperties: TSESTree.Property[],
): void => {
ruleContext.report({
node: nextProperty as Rule.Node,
messageId: 'alphabeticalOrder',
data: {
nextProperty: getPropertyName(nextProperty),
currentProperty: getPropertyName(currentProperty),
},
fix: (fixer) =>
generateFixesForCSSOrder(
fixer,
ruleContext,
regularProperties,
comparePropertiesAlphabetically,
(property) => property as Rule.Node,
),
});
};
/**
* Enforces alphabetical ordering of CSS properties.
* @param ruleContext The ESLint rule context.
* @param regularProperties An array of regular CSS properties to be checked.
*
* This function does the following:
* 1. Checks if there are enough properties to compare (more than 1).
* 2. Creates pairs of consecutive properties for comparison.
* 3. Finds the first pair that violates alphabetical order.
* 4. If a violation is found, reports the issue and generates fixes.
*/
export const enforceAlphabeticalCSSOrder = (
ruleContext: Rule.RuleContext,
regularProperties: TSESTree.Property[],
): void => {
if (regularProperties.length <= 1) {
return;
}
// Create pairs of consecutive properties
const propertyPairs = regularProperties.slice(0, -1).map((currentProperty, index) => ({
currentProperty,
nextProperty: regularProperties[index + 1] as TSESTree.Property,
}));
const violatingPair = propertyPairs.find(
({ currentProperty, nextProperty }) => comparePropertiesAlphabetically(currentProperty, nextProperty) > 0,
);
if (violatingPair) {
reportOrderingIssue(ruleContext, violatingPair.currentProperty, violatingPair.nextProperty, regularProperties);
}
};

View file

@ -0,0 +1,28 @@
import type { Rule } from 'eslint';
import { TSESTree } from '@typescript-eslint/utils';
import { processRecipeProperties } from '../shared-utils/recipe-property-processor.js';
import { processStyleNode } from '../shared-utils/style-node-processor.js';
import { enforceAlphabeticalCSSOrderInStyleObject } from './style-object-processor.js';
/**
* Enforces alphabetical ordering of CSS properties within a recipe function call.
*
* @param node The CallExpression node representing the recipe function call.
* @param context The ESLint rule context.
*
* This function does the following:
* 1. Checks if the first argument of the recipe function is an ObjectExpression.
* 2. If valid, processes the recipe object's properties.
* 3. For each relevant property (e.g., 'base', 'variants'), it applies alphabetical ordering to the CSS properties.
*/
export const enforceAlphabeticalCSSOrderInRecipe = (node: TSESTree.CallExpression, context: Rule.RuleContext): void => {
if (!node.arguments[0] || node.arguments[0].type !== 'ObjectExpression') {
return;
}
const recipeObject = node.arguments[0];
processRecipeProperties(context, recipeObject, (context, object) =>
processStyleNode(context, object, enforceAlphabeticalCSSOrderInStyleObject),
);
};

View file

@ -0,0 +1,23 @@
import type { Rule } from 'eslint';
import { createNodeVisitors } from '../shared-utils/order-strategy-visitor-creator.js';
const alphabeticalOrderRule: Rule.RuleModule = {
meta: {
type: 'suggestion',
docs: {
description: 'enforce alphabetical CSS property ordering in vanilla-extract styles',
category: 'Stylistic Issues',
recommended: true,
},
fixable: 'code',
schema: [],
messages: {
alphabeticalOrder: "Property '{{next}}' should come before '{{current}}' in alphabetical order.",
},
},
create(context) {
return createNodeVisitors(context, 'alphabetical');
},
};
export default alphabeticalOrderRule;

View file

@ -0,0 +1,37 @@
import type { Rule } from 'eslint';
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
import { isSelectorsObject, processNestedSelectors } from '../shared-utils/nested-selectors-processor.js';
import { separateProperties } from '../shared-utils/property-separator.js';
import { enforceAlphabeticalCSSOrder } from './property-order-enforcer.js';
/**
* Processes a style object to enforce alphabetical ordering of CSS properties.
*
* This function handles different types of style objects:
* 1. If the object is invalid or not an ObjectExpression, it returns immediately.
* 2. For 'selectors' objects, it processes nested selectors recursively.
* 3. For regular style objects, it separates and enforces alphabetical order on properties.
* 4. It always processes nested objects recursively, regardless of type.
*
* @param ruleContext - The ESLint rule context for reporting and fixing issues.
* @param styleObject - The object expression representing the style object to be processed.
*/
export const enforceAlphabeticalCSSOrderInStyleObject = (
ruleContext: Rule.RuleContext,
styleObject: TSESTree.ObjectExpression,
): void => {
if (!styleObject || styleObject.type !== AST_NODE_TYPES.ObjectExpression) {
return;
}
if (isSelectorsObject(styleObject)) {
processNestedSelectors(ruleContext, styleObject, enforceAlphabeticalCSSOrderInStyleObject);
return;
}
const { regularProperties } = separateProperties(styleObject.properties);
enforceAlphabeticalCSSOrder(ruleContext, regularProperties);
processNestedSelectors(ruleContext, styleObject, enforceAlphabeticalCSSOrderInStyleObject);
};