• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

antebudimir / eslint-plugin-vanilla-extract / 15882329539

25 Jun 2025 04:51PM UTC coverage: 91.396% (-7.9%) from 99.254%
15882329539

push

github

web-flow
feat 🥁: add wrapper function support with reference tracking

- add reference tracking for wrapper functions in vanilla-extract style objects
- implement ReferenceTracker class for detecting vanilla-extract imports
- add createReferenceBasedNodeVisitors for automatic function detection
- support wrapper functions with parameter mapping enable all lint rules to work with custom wrapper functions

This commit introduces robust reference tracking and wrapper function support, enabling all lint rules to work seamlessly with custom vanilla-extract style patterns while preserving compatibility with existing usage and improving rule extensibility.

503 of 534 branches covered (94.19%)

Branch coverage included in aggregate %.

416 of 604 new or added lines in 6 files covered. (68.87%)

18 existing lines in 4 files now uncovered.

2057 of 2267 relevant lines covered (90.74%)

545.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.98
/src/css-rules/shared-utils/reference-based-visitor-creator.ts
1
import type { Rule } from 'eslint';
1✔
NEW
2
import { TSESTree } from '@typescript-eslint/utils';
×
NEW
3
import { enforceAlphabeticalCSSOrderInRecipe } from '../alphabetical-order/recipe-order-enforcer.js';
×
NEW
4
import { enforceAlphabeticalCSSOrderInStyleObject } from '../alphabetical-order/style-object-processor.js';
×
NEW
5
import { enforceConcentricCSSOrderInRecipe } from '../concentric-order/recipe-order-enforcer.js';
×
NEW
6
import { enforceConcentricCSSOrderInStyleObject } from '../concentric-order/style-object-processor.js';
×
NEW
7
import { enforceUserDefinedGroupOrderInRecipe } from '../custom-order/recipe-order-enforcer.js';
×
NEW
8
import { enforceUserDefinedGroupOrderInStyleObject } from '../custom-order/style-object-processor.js';
×
NEW
9
import { enforceFontFaceOrder } from './font-face-property-order-enforcer.js';
×
NEW
10
import { ReferenceTracker, createReferenceTrackingVisitor } from './reference-tracker.js';
×
NEW
11
import { processStyleNode } from './style-node-processor.js';
×
12
import type { SortRemainingProperties } from '../concentric-order/types.js';
13
import type { OrderingStrategy } from '../types.js';
14

15
/**
16
 * Creates an ESLint rule listener with visitors for style-related function calls using reference tracking.
17
 * This automatically detects vanilla-extract functions based on their import statements.
18
 *
19
 * @param ruleContext The ESLint rule context.
20
 * @param orderingStrategy The strategy to use for ordering CSS properties.
21
 * @param userDefinedGroupOrder An optional array of property groups for the 'userDefinedGroupOrder' strategy.
22
 * @param sortRemainingProperties An optional strategy for sorting properties not in user-defined groups.
23
 * @returns An object with visitor functions for the ESLint rule.
24
 */
NEW
25
export const createReferenceBasedNodeVisitors = (
×
NEW
26
  ruleContext: Rule.RuleContext,
×
NEW
27
  orderingStrategy: OrderingStrategy,
×
NEW
28
  userDefinedGroupOrder?: string[],
×
NEW
29
  sortRemainingProperties?: SortRemainingProperties,
×
NEW
30
): Rule.RuleListener => {
×
NEW
31
  const tracker = new ReferenceTracker();
×
NEW
32
  const trackingVisitor = createReferenceTrackingVisitor(tracker);
×
33

34
  // Select the appropriate property processing function based on the ordering strategy
NEW
35
  const processProperty = (() => {
×
NEW
36
    switch (orderingStrategy) {
×
NEW
37
      case 'alphabetical':
×
NEW
38
        return enforceAlphabeticalCSSOrderInStyleObject;
×
NEW
39
      case 'concentric':
×
NEW
40
        return enforceConcentricCSSOrderInStyleObject;
×
NEW
41
      case 'userDefinedGroupOrder':
×
NEW
42
        if (!userDefinedGroupOrder || userDefinedGroupOrder.length === 0) {
×
NEW
43
          return enforceAlphabeticalCSSOrderInStyleObject;
×
NEW
44
        }
×
NEW
45
        return (ruleContext: Rule.RuleContext, node: TSESTree.ObjectExpression) =>
×
NEW
46
          enforceUserDefinedGroupOrderInStyleObject(ruleContext, node, userDefinedGroupOrder, sortRemainingProperties);
×
NEW
47
      default:
×
NEW
48
        return enforceAlphabeticalCSSOrderInStyleObject;
×
NEW
49
    }
×
NEW
50
  })();
×
51

NEW
52
  return {
×
53
    // Include the reference tracking visitors
NEW
54
    ...trackingVisitor,
×
55

NEW
56
    CallExpression(callExpression) {
×
NEW
57
      if (callExpression.callee.type !== 'Identifier') {
×
NEW
58
        return;
×
NEW
59
      }
×
60

NEW
61
      const functionName = callExpression.callee.name;
×
62

63
      // Check if this function is tracked as a vanilla-extract function
NEW
64
      if (!tracker.isTrackedFunction(functionName)) {
×
NEW
65
        return;
×
NEW
66
      }
×
67

NEW
68
      const originalName = tracker.getOriginalName(functionName);
×
NEW
69
      if (!originalName) {
×
NEW
70
        return;
×
NEW
71
      }
×
72

73
      // Handle different function types based on their original imported name
NEW
74
      switch (originalName) {
×
NEW
75
        case 'fontFace':
×
NEW
76
          if (callExpression.arguments.length > 0) {
×
NEW
77
            const styleArguments = callExpression.arguments[0];
×
NEW
78
            enforceFontFaceOrder(ruleContext, styleArguments as TSESTree.ObjectExpression);
×
NEW
79
          }
×
NEW
80
          break;
×
81

NEW
82
        case 'globalFontFace':
×
NEW
83
          if (callExpression.arguments.length > 1) {
×
NEW
84
            const styleArguments = callExpression.arguments[1];
×
NEW
85
            enforceFontFaceOrder(ruleContext, styleArguments as TSESTree.ObjectExpression);
×
NEW
86
          }
×
NEW
87
          break;
×
88

NEW
89
        case 'style':
×
NEW
90
        case 'styleVariants':
×
NEW
91
        case 'keyframes':
×
NEW
92
          if (callExpression.arguments.length > 0) {
×
NEW
93
            const styleArguments = callExpression.arguments[0];
×
NEW
94
            processStyleNode(ruleContext, styleArguments as TSESTree.Node, processProperty);
×
NEW
95
          }
×
NEW
96
          break;
×
97

NEW
98
        case 'globalStyle':
×
NEW
99
        case 'globalKeyframes':
×
NEW
100
          if (callExpression.arguments.length > 1) {
×
NEW
101
            const styleArguments = callExpression.arguments[1];
×
NEW
102
            processStyleNode(ruleContext, styleArguments as TSESTree.Node, processProperty);
×
NEW
103
          }
×
NEW
104
          break;
×
105

NEW
106
        case 'recipe':
×
NEW
107
          switch (orderingStrategy) {
×
NEW
108
            case 'alphabetical':
×
NEW
109
              enforceAlphabeticalCSSOrderInRecipe(callExpression as TSESTree.CallExpression, ruleContext);
×
NEW
110
              break;
×
NEW
111
            case 'concentric':
×
NEW
112
              enforceConcentricCSSOrderInRecipe(ruleContext, callExpression as TSESTree.CallExpression);
×
NEW
113
              break;
×
NEW
114
            case 'userDefinedGroupOrder':
×
NEW
115
              if (userDefinedGroupOrder) {
×
NEW
116
                enforceUserDefinedGroupOrderInRecipe(
×
NEW
117
                  ruleContext,
×
NEW
118
                  callExpression as TSESTree.CallExpression,
×
NEW
119
                  userDefinedGroupOrder,
×
NEW
120
                  sortRemainingProperties,
×
NEW
121
                );
×
NEW
122
              }
×
NEW
123
              break;
×
NEW
124
          }
×
NEW
125
          break;
×
NEW
126
      }
×
NEW
127
    },
×
NEW
128
  };
×
NEW
129
};
×
130

131
/**
132
 * Backwards-compatible alias that maintains the original API.
133
 * Uses reference tracking internally for automatic detection of vanilla-extract functions.
134
 */
NEW
135
export const createNodeVisitors = createReferenceBasedNodeVisitors;
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc