@griffel/transform 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,12 +1,41 @@
1
1
  # Change Log - @griffel/transform
2
2
 
3
- This log was last generated on Mon, 03 Nov 2025 15:42:47 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 06 Mar 2026 15:54:55 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.2.1
8
+
9
+ Fri, 06 Mar 2026 15:54:55 GMT
10
+
11
+ ### Patches
12
+
13
+ - refactor: remove cookModuleId from module evaluation (olfedias@microsoft.com)
14
+ - Bump @griffel/core to v1.20.1
15
+
16
+ ## 1.2.0
17
+
18
+ Fri, 06 Mar 2026 08:17:05 GMT
19
+
20
+ ### Minor changes
21
+
22
+ - feat: add AST evaluator plugin system with evaluationPlugins option (olfedias@microsoft.com)
23
+ - feat: wrap imported asset paths in <griffel-asset> tags for reliable CSS extraction (olfedias@microsoft.com)
24
+ - feat: add makeStaticStyles AOT/CSS extraction support (olfedias@microsoft.com)
25
+ - feat: hybrid evaluator that shakes ESM node_modules instead of ignoring them (olfedias@microsoft.com)
26
+ - feat: throw on non-ESM input in transformSync (olfedias@microsoft.com)
27
+ - Bump @griffel/core to v1.20.0
28
+
29
+ ### Patches
30
+
31
+ - refactor: use ScopeTracker from oxc-walker for scope-aware import resolution (olfedias@microsoft.com)
32
+ - refactor: extract dedupeCSSRules result to a variable in transformSync (olfedias@microsoft.com)
33
+ - refactor: internalize Linaria Module/EvalCache to remove @linaria/babel-preset dependency (olfedias@microsoft.com)
34
+ - perf: replace DeoptError with DEOPT sentinel symbol, optimize CSS rule dedup and lookups (olfedias@microsoft.com)
35
+
7
36
  ## 1.1.0
8
37
 
9
- Mon, 03 Nov 2025 15:42:47 GMT
38
+ Mon, 03 Nov 2025 15:43:56 GMT
10
39
 
11
40
  ### Minor changes
12
41
 
package/README.md CHANGED
@@ -6,12 +6,15 @@ A high-performance transformation package for Griffel that unifies CSS-in-JS tra
6
6
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
7
7
 
8
8
  - [Overview](#overview)
9
- - [Features](#features)
10
9
  - [Install](#install)
11
10
  - [Usage](#usage)
12
11
  - [Basic Transformation](#basic-transformation)
13
12
  - [API Reference](#api-reference)
14
13
  - [transformSync(sourceCode, options)](#transformsyncsourcecode-options)
14
+ - [Evaluation Plugins](#evaluation-plugins)
15
+ - [Built-in Plugins](#built-in-plugins)
16
+ - [`fluentTokensPlugin`](#fluenttokensplugin)
17
+ - [Custom Plugins](#custom-plugins)
15
18
 
16
19
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
17
20
 
@@ -76,3 +79,60 @@ Transforms source code containing `makeStyles` or `makeResetStyles` calls.
76
79
  - `modules?` (string[]): Module sources to process
77
80
  - `babelOptions?` (object): Babel configuration for complex evaluations
78
81
  - `evaluationRules?` (array): Rules for determining evaluation strategy
82
+ - `astEvaluationPlugins?` (AstEvaluatorPlugin[]): Plugins for extending AST evaluation with custom node handling (default: `[fluentTokensPlugin]`)
83
+
84
+ ## Evaluation Plugins
85
+
86
+ The AST evaluator supports a plugin system that allows extending static evaluation to handle additional AST node types. Plugins are tried in order when the base evaluator encounters a node type it doesn't handle (i.e., anything beyond `Literal`, `ObjectExpression`, and simple `TemplateLiteral` without expressions).
87
+
88
+ ### Built-in Plugins
89
+
90
+ #### `fluentTokensPlugin`
91
+
92
+ Handles Fluent UI design token expressions, transforming `tokens.propertyName` into `var(--propertyName)`. Enabled by default — no configuration needed.
93
+
94
+ To disable it, pass an empty array:
95
+
96
+ ```typescript
97
+ const result = transformSync(sourceCode, {
98
+ filename: 'styles.ts',
99
+ astEvaluationPlugins: [],
100
+ });
101
+ ```
102
+
103
+ This plugin handles:
104
+
105
+ - `MemberExpression`: `tokens.colorBrandBackground` → `var(--colorBrandBackground)`
106
+ - `TemplateLiteral`: `` `${tokens.spacingVerticalS} 0` `` → `var(--spacingVerticalS) 0`
107
+
108
+ ### Custom Plugins
109
+
110
+ You can create custom plugins by implementing the `AstEvaluatorPlugin` interface:
111
+
112
+ ```typescript
113
+ import { type AstEvaluatorPlugin, DEOPT } from '@griffel/transform';
114
+
115
+ const myPlugin: AstEvaluatorPlugin = {
116
+ name: 'myPlugin',
117
+ evaluateNode(node, context) {
118
+ // Handle specific node types
119
+ if (node.type === 'MemberExpression') {
120
+ // Custom evaluation logic...
121
+ return 'some-value';
122
+ }
123
+
124
+ // Return DEOPT to signal "can't handle this node" and let the next plugin try
125
+ return DEOPT;
126
+ },
127
+ };
128
+
129
+ const result = transformSync(sourceCode, {
130
+ filename: 'styles.ts',
131
+ astEvaluationPlugins: [myPlugin],
132
+ });
133
+ ```
134
+
135
+ The `context` parameter provides:
136
+
137
+ - `programAst`: The full program AST for cross-referencing
138
+ - `evaluateNode(node)`: Recursive evaluator callback that goes through base evaluation + all plugins
@@ -0,0 +1,2 @@
1
+ export declare const ASSET_TAG_OPEN = "<griffel-asset>";
2
+ export declare const ASSET_TAG_CLOSE = "</griffel-asset>";
@@ -1,5 +1,11 @@
1
- import { Node } from 'oxc-parser';
2
- import { EvaluationResult } from './types.mjs';
1
+ import { Node, Program } from 'oxc-parser';
2
+ import { EvaluationResult, AstEvaluatorPlugin } from './types.mjs';
3
+ /**
4
+ * Sentinel value returned by plugins and evaluateNode to signal "can't handle this node".
5
+ * Using a symbol avoids the cost of Error construction and stack trace capture.
6
+ */
7
+ export declare const DEOPT: unique symbol;
8
+ export type Deopt = typeof DEOPT;
3
9
  /**
4
10
  * Simple static evaluator for object expressions with nested objects.
5
11
  * Based on Babel's evaluation approach but simplified for our specific use case.
@@ -8,5 +14,7 @@ import { EvaluationResult } from './types.mjs';
8
14
  * - Objects with nested objects: { root: { color: 'red', padding: 0 } }
9
15
  * - String literals, numeric literals, boolean literals, null
10
16
  * - Simple property access
17
+ *
18
+ * Plugins can extend evaluation to handle additional node types.
11
19
  */
12
- export declare function astEvaluator(node: Node): EvaluationResult;
20
+ export declare function astEvaluator(node: Node, programAst: Program, plugins?: AstEvaluatorPlugin[]): EvaluationResult;
@@ -1,11 +1,12 @@
1
- import { StrictOptions } from '@linaria/babel-preset';
1
+ import { Program } from 'oxc-parser';
2
+ import { StrictOptions, AstEvaluatorPlugin } from './types.mjs';
2
3
  import { StyleCall } from '../types.mjs';
3
4
  /**
4
5
  * Batch evaluates all style calls in a file for better performance.
5
6
  * Uses static evaluation first, then falls back to VM evaluation for complex expressions.
6
7
  * Optimizes VM evaluation by sharing module loading and parsing overhead.
7
8
  */
8
- export declare function batchEvaluator(sourceCode: string, filename: string, styleCalls: StyleCall[], babelOptions: NonNullable<StrictOptions['babelOptions']>, evaluationRules: NonNullable<StrictOptions['rules']>): {
9
+ export declare function batchEvaluator(sourceCode: string, filename: string, styleCalls: StyleCall[], babelOptions: NonNullable<StrictOptions['babelOptions']>, evaluationRules: NonNullable<StrictOptions['rules']>, programAst: Program, astEvaluationPlugins?: AstEvaluatorPlugin[]): {
9
10
  usedVMForEvaluation: boolean;
10
11
  evaluationResults: unknown[];
11
12
  };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Evaluation cache for module results.
3
+ * Copied from @linaria/babel-preset v3.0.0-beta.19, adapted to use `debug` package.
4
+ */
5
+ export declare const clear: () => void;
6
+ export declare const clearForFile: (filename: string) => void;
7
+ export declare const has: ([filename, ...exports]: string[], text: string) => boolean;
8
+ export declare const get: ([filename, ...exports]: string[], text: string) => unknown;
9
+ export declare const set: ([filename, ...exports]: string[], text: string, value: unknown) => void;
@@ -0,0 +1,2 @@
1
+ import { AstEvaluatorPlugin } from './types.mjs';
2
+ export declare const fluentTokensPlugin: AstEvaluatorPlugin;
@@ -0,0 +1,2 @@
1
+ import { Evaluator } from './types.mjs';
2
+ export declare function createHybridEvaluator(shakerEvaluator: Evaluator): Evaluator;
@@ -0,0 +1,29 @@
1
+ import { StrictOptions } from './types.mjs';
2
+ export declare class Module {
3
+ readonly id: string;
4
+ readonly filename: string;
5
+ readonly paths: readonly string[];
6
+ options: StrictOptions;
7
+ imports: Map<string, string[]> | null;
8
+ dependencies: string[] | null;
9
+ transform: ((code: string, filename: string) => string) | null;
10
+ exports: unknown;
11
+ extensions: string[];
12
+ private debug;
13
+ private debuggerDepth;
14
+ constructor(filename: string, options: StrictOptions, debuggerDepth?: number);
15
+ resolve: (id: string) => string;
16
+ require: ((id: string) => unknown) & {
17
+ ensure: () => void;
18
+ cache: Record<string, Module>;
19
+ resolve: (id: string) => string;
20
+ };
21
+ evaluate(text: string, only?: string[] | null): void;
22
+ static invalidate: () => void;
23
+ static invalidateEvalCache: () => void;
24
+ static _resolveFilename: (id: string, options: {
25
+ filename: string;
26
+ paths: readonly string[];
27
+ }) => string;
28
+ static _nodeModulePaths: (filename: string) => string[];
29
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Mocked `process` variable for the VM sandbox used in module evaluation.
3
+ * Copied from @linaria/babel-preset v3.0.0-beta.19.
4
+ */
5
+ export declare const nextTick: (fn: (...args: unknown[]) => void) => ReturnType<typeof setTimeout>;
6
+ export declare const platform = "browser";
7
+ export declare const arch = "browser";
8
+ export declare const execPath = "browser";
9
+ export declare const title = "browser";
10
+ export declare const pid = 1;
11
+ export declare const browser = true;
12
+ export declare const argv: string[];
13
+ export declare const binding: () => never;
14
+ export declare const cwd: () => string;
15
+ export declare const exit: () => void;
16
+ export declare const kill: () => void;
17
+ export declare const chdir: () => void;
18
+ export declare const umask: () => void;
19
+ export declare const dlopen: () => void;
20
+ export declare const uptime: () => void;
21
+ export declare const memoryUsage: () => void;
22
+ export declare const uvCounters: () => void;
23
+ export declare const features: {};
24
+ export declare const env: NodeJS.ProcessEnv;
@@ -1,5 +1,34 @@
1
+ import { Node, Program } from 'oxc-parser';
2
+ export type Evaluator = (filename: string, options: StrictOptions, text: string, only: string[] | null) => [string, Map<string, string[]> | null];
3
+ export type EvalRule = {
4
+ test?: RegExp | ((path: string) => boolean);
5
+ action: Evaluator | 'ignore' | string;
6
+ };
7
+ export type StrictOptions = {
8
+ displayName: boolean;
9
+ evaluate: boolean;
10
+ babelOptions: {
11
+ plugins?: unknown[];
12
+ presets?: unknown[];
13
+ [key: string]: unknown;
14
+ };
15
+ rules: EvalRule[];
16
+ };
1
17
  export interface EvaluationResult {
2
18
  confident: boolean;
3
19
  value?: unknown;
4
20
  error?: Error;
5
21
  }
22
+ export interface AstEvaluatorContext {
23
+ /** Full program AST */
24
+ programAst: Program;
25
+ /** Recursive evaluator callback (goes through base + all plugins) */
26
+ evaluateNode: (node: Node) => unknown;
27
+ }
28
+ export interface AstEvaluatorPlugin {
29
+ name: string;
30
+ /**
31
+ * Evaluate an AST node. Return DEOPT symbol to signal "can't handle this".
32
+ */
33
+ evaluateNode: (node: Node, context: AstEvaluatorContext) => unknown;
34
+ }
@@ -1,3 +1,2 @@
1
- import { StrictOptions } from '@linaria/babel-preset';
2
- import { EvaluationResult } from './types.mjs';
1
+ import { EvaluationResult, StrictOptions } from './types.mjs';
3
2
  export declare function vmEvaluator(sourceCode: string, filename: string, expressionCode: string, babelOptions: NonNullable<StrictOptions['babelOptions']>, evaluationRules: NonNullable<StrictOptions['rules']>): EvaluationResult;
package/index.d.mts CHANGED
@@ -1,4 +1,9 @@
1
1
  export { default as shakerEvaluator } from '@linaria/shaker';
2
- export { EvalCache, Module } from '@linaria/babel-preset';
3
- export type { Evaluator, EvalRule } from '@linaria/babel-preset';
2
+ export { Module } from './evaluation/module.mjs';
3
+ export * as EvalCache from './evaluation/evalCache.mjs';
4
+ export { ASSET_TAG_OPEN, ASSET_TAG_CLOSE } from './constants.mjs';
5
+ export type { Evaluator, EvalRule } from './evaluation/types.mjs';
4
6
  export { transformSync, type TransformOptions, type TransformResult } from './transformSync.mjs';
7
+ export { DEOPT, type Deopt } from './evaluation/astEvaluator.mjs';
8
+ export type { AstEvaluatorPlugin, AstEvaluatorContext } from './evaluation/types.mjs';
9
+ export { fluentTokensPlugin } from './evaluation/fluentTokensPlugin.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@griffel/transform",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "A package that performs build time transforms for Griffel",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,11 +16,11 @@
16
16
  "./package.json": "./package.json"
17
17
  },
18
18
  "dependencies": {
19
- "@griffel/core": "^1.19.2",
20
- "@linaria/babel-preset": "^3.0.0-beta.24",
19
+ "@griffel/core": "^1.20.1",
21
20
  "@linaria/shaker": "^3.0.0-beta.22",
21
+ "debug": "^4.3.0",
22
22
  "magic-string": "^0.30.19",
23
- "oxc-parser": "^0.90.0",
24
- "oxc-walker": "^0.5.2"
23
+ "oxc-parser": "^0.116.0",
24
+ "oxc-walker": "^0.7.0"
25
25
  }
26
26
  }
package/transform.js CHANGED
@@ -1,86 +1,412 @@
1
1
  import _shaker from "@linaria/shaker";
2
2
  import { default as default2 } from "@linaria/shaker";
3
- import { Module } from "@linaria/babel-preset";
4
- import { EvalCache, Module as Module2 } from "@linaria/babel-preset";
5
- import { parseSync } from "oxc-parser";
6
- import { walk } from "oxc-walker";
3
+ import fs from "node:fs";
4
+ import NativeModule from "node:module";
5
+ import path, { dirname, extname } from "node:path";
6
+ import vm from "node:vm";
7
+ import createDebug from "debug";
8
+ import { createHash } from "node:crypto";
9
+ import { rawTransferSupported, parseSync } from "oxc-parser";
10
+ import { ScopeTracker, walk } from "oxc-walker";
7
11
  import MagicString from "magic-string";
8
- import { resolveResetStyleRules, resolveStyleRulesForSlots, normalizeCSSBucketEntry } from "@griffel/core";
9
- class DeoptError extends Error {
10
- }
11
- function evaluateNode(node) {
12
- switch (node.type) {
13
- case "Literal":
14
- return node.value;
15
- case "ObjectExpression":
16
- return evaluateObjectExpression(node);
17
- case "TemplateLiteral":
18
- return evaluateTemplateLiteral(node);
19
- case "MemberExpression":
20
- return evaluateMemberExpression(node);
21
- default:
22
- throw new DeoptError(`Unsupported node type: ${node.type}`);
12
+ import { resolveStaticStyleRules, resolveResetStyleRules, resolveStyleRulesForSlots, normalizeCSSBucketEntry } from "@griffel/core";
13
+ const ASSET_TAG_OPEN = "<griffel-asset>";
14
+ const ASSET_TAG_CLOSE = "</griffel-asset>";
15
+ const debug$1 = createDebug("griffel:eval-cache");
16
+ const fileHashes = /* @__PURE__ */ new Map();
17
+ const evalCache = /* @__PURE__ */ new Map();
18
+ const fileKeys = /* @__PURE__ */ new Map();
19
+ const hash = (text) => createHash("sha1").update(text).digest("base64");
20
+ let lastText = "";
21
+ let lastHash = hash(lastText);
22
+ const memoizedHash = (text) => {
23
+ if (lastText !== text) {
24
+ lastHash = hash(text);
25
+ lastText = text;
23
26
  }
24
- }
25
- function evaluateObjectExpression(node) {
26
- const obj = {};
27
- for (const prop of node.properties) {
28
- if (prop.type !== "Property" || prop.kind !== "init") {
29
- throw new DeoptError("Only standard properties are supported");
27
+ return lastHash;
28
+ };
29
+ const toKey = (filename, exports$1) => exports$1.length > 0 ? `${filename}:${exports$1.join(",")}` : filename;
30
+ const clear = () => {
31
+ fileHashes.clear();
32
+ evalCache.clear();
33
+ fileKeys.clear();
34
+ };
35
+ const clearForFile = (filename) => {
36
+ const keys = fileKeys.get(filename) ?? [];
37
+ if (keys.length === 0) {
38
+ return;
39
+ }
40
+ debug$1("clear-for-file", filename);
41
+ keys.forEach((key) => {
42
+ fileHashes.delete(key);
43
+ evalCache.delete(key);
44
+ });
45
+ fileKeys.set(filename, []);
46
+ };
47
+ const has = ([filename, ...exports$1], text) => {
48
+ const key = toKey(filename, exports$1);
49
+ const textHash = memoizedHash(text);
50
+ debug$1("has", `${key} ${textHash}`);
51
+ return fileHashes.get(key) === textHash;
52
+ };
53
+ const get = ([filename, ...exports$1], text) => {
54
+ const key = toKey(filename, exports$1);
55
+ const textHash = memoizedHash(text);
56
+ debug$1("get", `${key} ${textHash}`);
57
+ if (fileHashes.get(key) !== textHash) {
58
+ return void 0;
59
+ }
60
+ return evalCache.get(key);
61
+ };
62
+ const set = ([filename, ...exports$1], text, value) => {
63
+ const key = toKey(filename, exports$1);
64
+ const textHash = memoizedHash(text);
65
+ debug$1("set", `${key} ${textHash}`);
66
+ fileHashes.set(key, textHash);
67
+ evalCache.set(key, value);
68
+ if (!fileKeys.has(filename)) {
69
+ fileKeys.set(filename, []);
70
+ }
71
+ fileKeys.get(filename).push(key);
72
+ };
73
+ const evalCache$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
74
+ __proto__: null,
75
+ clear,
76
+ clearForFile,
77
+ get,
78
+ has,
79
+ set
80
+ }, Symbol.toStringTag, { value: "Module" }));
81
+ const nextTick = (fn) => setTimeout(fn, 0);
82
+ const platform = "browser";
83
+ const arch = "browser";
84
+ const execPath = "browser";
85
+ const title = "browser";
86
+ const pid = 1;
87
+ const browser = true;
88
+ const argv = [];
89
+ const binding = function binding2() {
90
+ throw new Error("No such module. (Possibly not yet loaded)");
91
+ };
92
+ const cwd = () => "/";
93
+ const noop = () => {
94
+ };
95
+ const exit = noop;
96
+ const kill = noop;
97
+ const chdir = noop;
98
+ const umask = noop;
99
+ const dlopen = noop;
100
+ const uptime = noop;
101
+ const memoryUsage = noop;
102
+ const uvCounters = noop;
103
+ const features = {};
104
+ const env = process.env;
105
+ const mockProcess = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
106
+ __proto__: null,
107
+ arch,
108
+ argv,
109
+ binding,
110
+ browser,
111
+ chdir,
112
+ cwd,
113
+ dlopen,
114
+ env,
115
+ execPath,
116
+ exit,
117
+ features,
118
+ kill,
119
+ memoryUsage,
120
+ nextTick,
121
+ pid,
122
+ platform,
123
+ title,
124
+ umask,
125
+ uptime,
126
+ uvCounters
127
+ }, Symbol.toStringTag, { value: "Module" }));
128
+ const debug = createDebug("griffel:module");
129
+ const builtins = {
130
+ assert: true,
131
+ buffer: true,
132
+ child_process: false,
133
+ cluster: false,
134
+ console: true,
135
+ constants: true,
136
+ crypto: true,
137
+ dgram: false,
138
+ dns: false,
139
+ domain: true,
140
+ events: true,
141
+ fs: false,
142
+ http: true,
143
+ https: true,
144
+ module: false,
145
+ net: false,
146
+ os: true,
147
+ path: true,
148
+ punycode: true,
149
+ process: true,
150
+ querystring: true,
151
+ readline: false,
152
+ repl: false,
153
+ stream: true,
154
+ string_decoder: true,
155
+ sys: true,
156
+ timers: true,
157
+ tls: false,
158
+ tty: true,
159
+ url: true,
160
+ util: true,
161
+ vm: true,
162
+ zlib: true
163
+ };
164
+ let cache = {};
165
+ const NOOP = () => {
166
+ };
167
+ const createCustomDebug = (depth) => (namespaces, arg1, ...args) => {
168
+ const modulePrefix = depth === 0 ? "module" : `sub-module-${depth}`;
169
+ debug(`${modulePrefix}:${namespaces}`, arg1, ...args);
170
+ };
171
+ class Module {
172
+ id;
173
+ filename;
174
+ options;
175
+ imports = null;
176
+ dependencies = null;
177
+ transform = null;
178
+ exports = {};
179
+ extensions;
180
+ debug;
181
+ debuggerDepth;
182
+ constructor(filename, options, debuggerDepth = 0) {
183
+ this.id = filename;
184
+ this.filename = filename;
185
+ this.options = options;
186
+ this.debuggerDepth = debuggerDepth;
187
+ this.debug = createCustomDebug(debuggerDepth);
188
+ Object.defineProperties(this, {
189
+ id: {
190
+ value: filename,
191
+ writable: false
192
+ },
193
+ filename: {
194
+ value: filename,
195
+ writable: false
196
+ },
197
+ paths: {
198
+ value: Object.freeze(
199
+ NativeModule._nodeModulePaths(
200
+ path.dirname(filename)
201
+ )
202
+ ),
203
+ writable: false
204
+ }
205
+ });
206
+ this.exports = {};
207
+ this.extensions = [".json", ".js", ".jsx", ".ts", ".tsx", ".cjs"];
208
+ this.debug("prepare", filename);
209
+ }
210
+ resolve = (id) => {
211
+ const extensions = NativeModule._extensions;
212
+ const added = [];
213
+ try {
214
+ this.extensions.forEach((ext) => {
215
+ if (ext in extensions) {
216
+ return;
217
+ }
218
+ extensions[ext] = NOOP;
219
+ added.push(ext);
220
+ });
221
+ return Module._resolveFilename(id, this);
222
+ } finally {
223
+ added.forEach((ext) => delete extensions[ext]);
30
224
  }
31
- let key;
32
- if (prop.computed) {
33
- throw new DeoptError("Computed properties are not supported");
34
- } else if (prop.key.type === "Identifier") {
35
- key = prop.key.name;
36
- } else if (prop.key.type === "Literal") {
37
- const keyLiteral = prop.key;
38
- if (typeof keyLiteral.value === "string" || typeof keyLiteral.value === "number") {
39
- key = String(keyLiteral.value);
225
+ };
226
+ require = Object.assign(
227
+ (id) => {
228
+ this.debug("require", id);
229
+ if (id in builtins) {
230
+ if (builtins[id]) {
231
+ return require(id);
232
+ }
233
+ return null;
234
+ }
235
+ const filename = this.resolve(id);
236
+ if (filename === id && !path.isAbsolute(id)) {
237
+ throw new Error(`Unable to import "${id}". Importing Node builtins is not supported in the sandbox.`);
238
+ }
239
+ this.dependencies?.push(id);
240
+ let cacheKey = filename;
241
+ let only = [];
242
+ if (this.imports?.has(id)) {
243
+ only = this.imports.get(id).sort();
244
+ if (only.length === 0) {
245
+ only = ["default"];
246
+ }
247
+ cacheKey += `:${only.join(",")}`;
248
+ }
249
+ let m = cache[cacheKey];
250
+ if (!m) {
251
+ this.debug("cached:not-exist", id);
252
+ m = new Module(filename, this.options, this.debuggerDepth + 1);
253
+ m.transform = this.transform;
254
+ cache[cacheKey] = m;
255
+ if (this.extensions.includes(path.extname(filename))) {
256
+ const code = fs.readFileSync(filename, "utf-8");
257
+ if (/\.json$/.test(filename)) {
258
+ m.exports = JSON.parse(code);
259
+ } else {
260
+ m.evaluate(code, only.includes("*") ? ["*"] : only);
261
+ }
262
+ } else {
263
+ m.exports = ASSET_TAG_OPEN + filename + ASSET_TAG_CLOSE;
264
+ }
40
265
  } else {
41
- throw new DeoptError("Unsupported literal key type");
266
+ this.debug("cached:exist", id);
267
+ }
268
+ return m.exports;
269
+ },
270
+ {
271
+ ensure: NOOP,
272
+ cache,
273
+ resolve: this.resolve
274
+ }
275
+ );
276
+ evaluate(text, only = null) {
277
+ const { filename } = this;
278
+ let action = "ignore";
279
+ for (let i = this.options.rules.length - 1; i >= 0; i--) {
280
+ const { test } = this.options.rules[i];
281
+ if (!test || (typeof test === "function" ? test(filename) : test instanceof RegExp && test.test(filename))) {
282
+ action = this.options.rules[i].action;
283
+ break;
42
284
  }
285
+ }
286
+ const cacheKey = [this.filename, ...only ?? []];
287
+ if (has(cacheKey, text)) {
288
+ this.exports = get(cacheKey, text);
289
+ return;
290
+ }
291
+ let code;
292
+ if (action === "ignore") {
293
+ this.debug("ignore", `${filename}`);
294
+ code = text;
43
295
  } else {
44
- throw new DeoptError("Unsupported key type");
296
+ const evaluator = typeof action === "function" ? action : require(require.resolve(action, {
297
+ paths: [dirname(this.filename)]
298
+ })).default;
299
+ let imports;
300
+ this.debug("prepare-evaluation", this.filename, "using", evaluator.name);
301
+ [code, imports] = evaluator(this.filename, this.options, text, only);
302
+ this.imports = imports;
303
+ this.debug("evaluate", `${this.filename} (only ${(only || []).join(", ")}):
304
+ ${code}`);
45
305
  }
46
- obj[key] = evaluateNode(prop.value);
306
+ const script = new vm.Script(`(function (exports) { ${code}
307
+ })(exports);`, {
308
+ filename: this.filename
309
+ });
310
+ script.runInContext(
311
+ vm.createContext({
312
+ clearImmediate: NOOP,
313
+ clearInterval: NOOP,
314
+ clearTimeout: NOOP,
315
+ setImmediate: NOOP,
316
+ setInterval: NOOP,
317
+ setTimeout: NOOP,
318
+ global,
319
+ process: mockProcess,
320
+ module: this,
321
+ exports: this.exports,
322
+ require: this.require,
323
+ __filename: this.filename,
324
+ __dirname: path.dirname(this.filename)
325
+ })
326
+ );
327
+ set(cacheKey, text, this.exports);
47
328
  }
48
- return obj;
329
+ static invalidate = () => {
330
+ cache = {};
331
+ };
332
+ static invalidateEvalCache = () => {
333
+ clear();
334
+ };
335
+ // Alias to resolve the module using node's resolve algorithm
336
+ // This static property can be overridden by the webpack loader
337
+ // This allows us to use webpack's module resolution algorithm
338
+ static _resolveFilename = (id, options) => NativeModule._resolveFilename(
339
+ id,
340
+ options
341
+ );
342
+ static _nodeModulePaths = (filename) => NativeModule._nodeModulePaths(filename);
49
343
  }
50
- function evaluateTemplateLiteral(node) {
51
- let result = "";
52
- for (let i = 0; i < node.quasis.length; i++) {
53
- result += node.quasis[i].value.cooked;
54
- if (i < node.expressions.length) {
55
- const expression = node.expressions[i];
56
- if (expression.type === "MemberExpression" && expression.object.type === "Identifier" && expression.object.name === "tokens" && expression.property.type === "Identifier" && !expression.computed) {
57
- result += `var(--${expression.property.name})`;
58
- } else {
59
- throw new DeoptError("Only tokens.propertyName expressions are supported in template literals");
344
+ const DEOPT = /* @__PURE__ */ Symbol("deopt");
345
+ function astEvaluator(node, programAst, plugins = []) {
346
+ const context = {
347
+ programAst,
348
+ evaluateNode
349
+ };
350
+ function evaluateNode(node2) {
351
+ switch (node2.type) {
352
+ case "Literal":
353
+ return node2.value;
354
+ case "ObjectExpression":
355
+ return evaluateObjectExpression(node2);
356
+ case "TemplateLiteral":
357
+ if (node2.expressions.length === 0) {
358
+ return node2.quasis[0].value.cooked;
359
+ }
360
+ break;
361
+ }
362
+ for (const plugin of plugins) {
363
+ const result2 = plugin.evaluateNode(node2, context);
364
+ if (result2 !== DEOPT) {
365
+ return result2;
60
366
  }
61
367
  }
368
+ return DEOPT;
62
369
  }
63
- return result;
64
- }
65
- function evaluateMemberExpression(node) {
66
- if (node.object.type === "Identifier" && node.object.name === "tokens" && node.property.type === "Identifier" && !node.computed) {
67
- return `var(--${node.property.name})`;
68
- } else {
69
- throw new DeoptError("Only tokens.propertyName member expressions are supported");
370
+ function evaluateObjectExpression(node2) {
371
+ const obj = {};
372
+ for (const prop of node2.properties) {
373
+ if (prop.type !== "Property" || prop.kind !== "init") {
374
+ return DEOPT;
375
+ }
376
+ let key;
377
+ if (prop.computed) {
378
+ return DEOPT;
379
+ } else if (prop.key.type === "Identifier") {
380
+ key = prop.key.name;
381
+ } else if (prop.key.type === "Literal") {
382
+ const keyLiteral = prop.key;
383
+ if (typeof keyLiteral.value === "string" || typeof keyLiteral.value === "number") {
384
+ key = String(keyLiteral.value);
385
+ } else {
386
+ return DEOPT;
387
+ }
388
+ } else {
389
+ return DEOPT;
390
+ }
391
+ const value = evaluateNode(prop.value);
392
+ if (value === DEOPT) {
393
+ return DEOPT;
394
+ }
395
+ obj[key] = value;
396
+ }
397
+ return obj;
70
398
  }
71
- }
72
- function astEvaluator(node) {
73
- try {
74
- return {
75
- confident: true,
76
- value: evaluateNode(node)
77
- };
78
- } catch {
399
+ const result = evaluateNode(node);
400
+ if (result === DEOPT) {
79
401
  return {
80
402
  confident: false,
81
403
  value: void 0
82
404
  };
83
405
  }
406
+ return {
407
+ confident: true,
408
+ value: result
409
+ };
84
410
  }
85
411
  function isError(e) {
86
412
  return Object.prototype.toString.call(e) === "[object Error]";
@@ -123,13 +449,13 @@ if (typeof module !== 'undefined' && module.exports) {
123
449
  return { confident: false, error: err };
124
450
  }
125
451
  }
126
- function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluationRules) {
452
+ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluationRules, programAst, astEvaluationPlugins = []) {
127
453
  const evaluationResults = new Array(styleCalls.length);
128
454
  const argumentsCode = new Array(styleCalls.length).fill(null);
129
455
  let vmEvaluationNeeded = false;
130
456
  for (let i = 0; i < styleCalls.length; i++) {
131
457
  const styleCall = styleCalls[i];
132
- const staticResult = astEvaluator(styleCall.argumentNode);
458
+ const staticResult = astEvaluator(styleCall.argumentNode, programAst, astEvaluationPlugins);
133
459
  if (staticResult.confident) {
134
460
  evaluationResults[i] = staticResult.value;
135
461
  continue;
@@ -163,22 +489,91 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
163
489
  evaluationResults
164
490
  };
165
491
  }
492
+ const CJS_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".json"]);
493
+ const ESM_EXTENSIONS = /* @__PURE__ */ new Set([".mjs", ".mts"]);
494
+ const useRawTransfer = rawTransferSupported();
495
+ const NODE_MODULES_RE = /[/\\]node_modules[/\\]/;
496
+ function createHybridEvaluator(shakerEvaluator2) {
497
+ return (filename, options, text, only) => {
498
+ if (!NODE_MODULES_RE.test(filename)) {
499
+ return shakerEvaluator2(filename, options, text, only);
500
+ }
501
+ const ext = extname(filename);
502
+ if (CJS_EXTENSIONS.has(ext)) {
503
+ return [text, null];
504
+ }
505
+ if (ESM_EXTENSIONS.has(ext)) {
506
+ return shakerEvaluator2(filename, options, text, only);
507
+ }
508
+ const parseResult = parseSync(filename, text, {
509
+ sourceType: "unambiguous",
510
+ ...useRawTransfer && { experimentalLazy: true }
511
+ });
512
+ const isESM = parseResult.module.hasModuleSyntax;
513
+ parseResult.dispose?.();
514
+ if (!isESM) {
515
+ return [text, null];
516
+ }
517
+ return shakerEvaluator2(filename, options, text, only);
518
+ };
519
+ }
520
+ function evaluateTemplateLiteralWithTokens(node) {
521
+ let result = "";
522
+ for (let i = 0; i < node.quasis.length; i++) {
523
+ result += node.quasis[i].value.cooked;
524
+ if (i < node.expressions.length) {
525
+ const expression = node.expressions[i];
526
+ if (expression.type === "MemberExpression" && expression.object.type === "Identifier" && expression.object.name === "tokens" && expression.property.type === "Identifier" && !expression.computed) {
527
+ result += `var(--${expression.property.name})`;
528
+ } else {
529
+ return DEOPT;
530
+ }
531
+ }
532
+ }
533
+ return result;
534
+ }
535
+ function evaluateTokensMemberExpression(node) {
536
+ if (node.object.type === "Identifier" && node.object.name === "tokens" && node.property.type === "Identifier" && !node.computed) {
537
+ return `var(--${node.property.name})`;
538
+ } else {
539
+ return DEOPT;
540
+ }
541
+ }
542
+ const fluentTokensPlugin = {
543
+ name: "fluentTokensPlugin",
544
+ evaluateNode(node) {
545
+ switch (node.type) {
546
+ case "TemplateLiteral":
547
+ return evaluateTemplateLiteralWithTokens(node);
548
+ case "MemberExpression":
549
+ return evaluateTokensMemberExpression(node);
550
+ default:
551
+ return DEOPT;
552
+ }
553
+ }
554
+ };
166
555
  function dedupeCSSRules(cssRulesByBucket) {
167
556
  return Object.fromEntries(
168
557
  Object.entries(cssRulesByBucket).map(([styleBucketName, cssBucketEntries]) => {
169
558
  if (styleBucketName === "m") {
170
- return [
171
- styleBucketName,
172
- cssBucketEntries.filter(
173
- (entryA, index, entries) => entries.findIndex((entryB) => entryA[0] === entryB[0]) === index
174
- )
175
- ];
559
+ const seen = /* @__PURE__ */ new Map();
560
+ for (const entry of cssBucketEntries) {
561
+ if (!seen.has(entry[0])) {
562
+ seen.set(entry[0], entry);
563
+ }
564
+ }
565
+ return [styleBucketName, Array.from(seen.values())];
176
566
  }
177
- return [styleBucketName, [...new Set(cssBucketEntries)]];
567
+ return [styleBucketName, Array.from(new Set(cssBucketEntries))];
178
568
  })
179
569
  );
180
570
  }
181
571
  const shakerEvaluator = _shaker.default || _shaker;
572
+ const RUNTIME_IDENTIFIERS = /* @__PURE__ */ new Map([
573
+ ["makeStyles", "__css"],
574
+ ["makeResetStyles", "__resetCSS"],
575
+ ["makeStaticStyles", "__staticCSS"]
576
+ ]);
182
577
  function buildCSSResetEntriesMetadata(cssResetEntries, cssRules, declaratorId) {
183
578
  const cssRulesByBucket = Array.isArray(cssRules) ? { d: cssRules } : cssRules;
184
579
  cssResetEntries[declaratorId] ??= [];
@@ -227,11 +622,15 @@ function buildCSSEntriesMetadata(cssEntries, classnamesMapping, cssRulesByBucket
227
622
  );
228
623
  }
229
624
  function concatCSSRulesByBucket(bucketA = {}, bucketB) {
230
- Object.entries(bucketB).forEach(([cssBucketName, cssBucketEntries]) => {
231
- bucketA[cssBucketName] = cssBucketEntries.concat(
232
- bucketA[cssBucketName] || []
233
- );
234
- });
625
+ for (const cssBucketName in bucketB) {
626
+ const bucketName = cssBucketName;
627
+ const bucketBEntries = bucketB[bucketName] ?? [];
628
+ if (bucketA[bucketName]) {
629
+ bucketA[bucketName].push(...bucketBEntries);
630
+ } else {
631
+ bucketA[bucketName] = bucketBEntries;
632
+ }
633
+ }
235
634
  return bucketA;
236
635
  }
237
636
  function transformSync(sourceCode, options) {
@@ -241,109 +640,96 @@ function transformSync(sourceCode, options) {
241
640
  classNameHashSalt = "",
242
641
  generateMetadata = false,
243
642
  modules = ["@griffel/core", "@griffel/react", "@fluentui/react-components"],
244
- evaluationRules = [
245
- { action: shakerEvaluator },
246
- {
247
- test: /[/\\]node_modules[/\\]/,
248
- action: "ignore"
249
- }
250
- ]
643
+ evaluationRules = [{ action: createHybridEvaluator(shakerEvaluator) }],
644
+ astEvaluationPlugins = [fluentTokensPlugin]
251
645
  } = options;
252
646
  if (!filename) {
253
647
  throw new Error('Transform error: "filename" option is required');
254
648
  }
255
649
  const parseResult = parseSync(filename, sourceCode);
256
- parseResult.module.staticImports;
257
650
  if (parseResult.errors.length > 0) {
258
651
  throw new Error(`Failed to parse "${filename}": ${parseResult.errors.map((e) => e.message).join(", ")}`);
259
652
  }
653
+ if (parseResult.program.body.length > 0 && !parseResult.module.hasModuleSyntax) {
654
+ throw new Error(
655
+ `Transform error: "${filename}" is not an ES module. @griffel/transform only supports ES modules (files using import/export syntax).`
656
+ );
657
+ }
260
658
  const magicString = new MagicString(sourceCode);
261
659
  const programAst = parseResult.program;
262
- const imports = [];
660
+ const hasGriffelImports = parseResult.module.staticImports.some(
661
+ (si) => modules.includes(si.moduleRequest.value) && si.entries.some((e) => e.importName.kind === "Name" && RUNTIME_IDENTIFIERS.has(e.importName.name))
662
+ );
663
+ if (!hasGriffelImports) {
664
+ return { code: sourceCode, usedProcessing: false, usedVMForEvaluation: false };
665
+ }
263
666
  const styleCalls = [];
264
667
  const cssEntries = {};
265
668
  const cssResetEntries = {};
266
669
  let cssRulesByBucket = {};
670
+ const scopeTracker = new ScopeTracker();
671
+ const matchedSpecifiers = /* @__PURE__ */ new Map();
267
672
  walk(programAst, {
673
+ scopeTracker,
268
674
  enter(node, parent) {
269
- if (node.type === "ImportDeclaration") {
270
- const moduleSource = node.source.value;
271
- if (modules.includes(moduleSource)) {
272
- const specifiers = node.specifiers.reduce((acc, spec) => {
273
- if (spec.type === "ImportSpecifier") {
274
- const importedName = spec.imported;
275
- if (importedName.type === "Identifier" && (importedName.name === "makeStyles" || importedName.name === "makeResetStyles")) {
276
- acc.push({
277
- imported: importedName.name,
278
- local: spec.local.name,
279
- start: spec.start,
280
- end: spec.end
281
- });
282
- }
283
- }
284
- return acc;
285
- }, []);
286
- if (specifiers.length > 0) {
287
- imports.push({
288
- source: moduleSource,
289
- specifiers,
290
- start: node.start,
291
- end: node.end
292
- });
293
- }
675
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
676
+ const declaration = scopeTracker.getDeclaration(node.callee.name);
677
+ if (declaration?.type !== "Import" || declaration.node.type !== "ImportSpecifier") {
678
+ return;
294
679
  }
295
- }
296
- if (node.type === "CallExpression") {
297
- let functionKind = null;
298
- let importId;
299
- if (node.callee.type === "Identifier") {
300
- const calleeName = node.callee.name;
301
- for (const importInfo of imports) {
302
- const specifier = importInfo.specifiers.find((s) => s.local === calleeName);
303
- if (specifier) {
304
- if (node.arguments.length !== 1) {
305
- throw new Error(`${functionKind}() function accepts only a single param`);
306
- }
307
- functionKind = specifier.imported;
308
- importId = specifier.local;
309
- break;
310
- }
311
- }
680
+ const importSource = declaration.importNode.source.value;
681
+ if (!modules.includes(importSource)) {
682
+ return;
683
+ }
684
+ const imported = declaration.node.imported;
685
+ if (imported.type !== "Identifier") {
686
+ return;
312
687
  }
313
- if (functionKind && importId) {
314
- let declaratorId = "unknownHook";
315
- let current = parent;
316
- while (current) {
317
- if (!current) {
318
- break;
319
- }
320
- if (current.type === "VariableDeclarator" && current.id.type === "Identifier") {
321
- declaratorId = current.id.name;
322
- break;
323
- }
324
- if ("parent" in current) {
325
- current = current.parent;
326
- continue;
327
- }
688
+ const importedName = imported.name;
689
+ if (!RUNTIME_IDENTIFIERS.has(importedName)) {
690
+ return;
691
+ }
692
+ const functionKind = importedName;
693
+ if (node.arguments.length !== 1) {
694
+ throw new Error(`${functionKind}() function accepts only a single param`);
695
+ }
696
+ matchedSpecifiers.set(declaration.node.start, {
697
+ start: declaration.node.start,
698
+ end: declaration.node.end,
699
+ functionKind
700
+ });
701
+ let declaratorId = "unknownHook";
702
+ let current = parent;
703
+ while (current) {
704
+ if (!current) {
705
+ break;
706
+ }
707
+ if (current.type === "VariableDeclarator" && current.id.type === "Identifier") {
708
+ declaratorId = current.id.name;
328
709
  break;
329
710
  }
330
- const argument = node.arguments[0];
331
- styleCalls.push({
332
- declaratorId,
333
- functionKind,
334
- argumentStart: argument.start,
335
- argumentEnd: argument.end,
336
- argumentCode: sourceCode.slice(argument.start, argument.end),
337
- argumentNode: argument,
338
- callStart: node.start,
339
- callEnd: node.end,
340
- importId
341
- });
711
+ if ("parent" in current) {
712
+ current = current.parent;
713
+ continue;
714
+ }
715
+ break;
342
716
  }
717
+ const argument = node.arguments[0];
718
+ styleCalls.push({
719
+ declaratorId,
720
+ functionKind,
721
+ argumentStart: argument.start,
722
+ argumentEnd: argument.end,
723
+ argumentCode: sourceCode.slice(argument.start, argument.end),
724
+ argumentNode: argument,
725
+ callStart: node.start,
726
+ callEnd: node.end,
727
+ importId: node.callee.name
728
+ });
343
729
  }
344
730
  }
345
731
  });
346
- if (imports.length === 0 || styleCalls.length === 0) {
732
+ if (styleCalls.length === 0) {
347
733
  return {
348
734
  code: sourceCode,
349
735
  usedProcessing: false,
@@ -355,7 +741,9 @@ function transformSync(sourceCode, options) {
355
741
  filename,
356
742
  styleCalls,
357
743
  babelOptions,
358
- evaluationRules
744
+ evaluationRules,
745
+ programAst,
746
+ astEvaluationPlugins
359
747
  );
360
748
  for (let i = 0; i < styleCalls.length; i++) {
361
749
  const styleCall = styleCalls[i];
@@ -364,17 +752,13 @@ function transformSync(sourceCode, options) {
364
752
  case "makeStyles":
365
753
  {
366
754
  const stylesBySlots = evaluationResult;
367
- const [classnamesMapping, cssRulesByBucketA] = resolveStyleRulesForSlots(stylesBySlots, classNameHashSalt);
755
+ const [classnamesMapping, resolvedCSSRules] = resolveStyleRulesForSlots(stylesBySlots, classNameHashSalt);
756
+ const uniqueCSSRules = dedupeCSSRules(cssRulesByBucket);
368
757
  if (generateMetadata) {
369
- buildCSSEntriesMetadata(
370
- cssEntries,
371
- classnamesMapping,
372
- dedupeCSSRules(cssRulesByBucket),
373
- styleCall.declaratorId
374
- );
758
+ buildCSSEntriesMetadata(cssEntries, classnamesMapping, uniqueCSSRules, styleCall.declaratorId);
375
759
  }
376
760
  magicString.overwrite(styleCall.argumentStart, styleCall.argumentEnd, `${JSON.stringify(classnamesMapping)}`);
377
- cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket, cssRulesByBucketA);
761
+ cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket, resolvedCSSRules);
378
762
  }
379
763
  break;
380
764
  case "makeResetStyles":
@@ -395,22 +779,25 @@ function transformSync(sourceCode, options) {
395
779
  );
396
780
  }
397
781
  break;
782
+ case "makeStaticStyles":
783
+ {
784
+ const styles = evaluationResult;
785
+ const stylesSet = Array.isArray(styles) ? styles : [styles];
786
+ const cssRules = resolveStaticStyleRules(stylesSet);
787
+ magicString.overwrite(styleCall.argumentStart, styleCall.argumentEnd, JSON.stringify({ d: cssRules }));
788
+ cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket, { d: cssRules });
789
+ }
790
+ break;
398
791
  }
399
792
  }
400
- for (const importInfo of imports) {
401
- for (const specifier of importInfo.specifiers) {
402
- if (specifier.imported === "makeStyles") {
403
- magicString.overwrite(specifier.start, specifier.end, "__css");
404
- } else if (specifier.imported === "makeResetStyles") {
405
- magicString.overwrite(specifier.start, specifier.end, "__resetCSS");
406
- }
407
- }
793
+ for (const specifier of matchedSpecifiers.values()) {
794
+ magicString.overwrite(specifier.start, specifier.end, RUNTIME_IDENTIFIERS.get(specifier.functionKind));
408
795
  }
409
796
  for (const styleCall of styleCalls) {
410
797
  magicString.overwrite(
411
798
  styleCall.callStart,
412
799
  styleCall.callStart + styleCall.importId.length,
413
- "__" + (styleCall.functionKind === "makeStyles" ? "css" : "resetCSS")
800
+ RUNTIME_IDENTIFIERS.get(styleCall.functionKind)
414
801
  );
415
802
  }
416
803
  return {
@@ -421,8 +808,12 @@ function transformSync(sourceCode, options) {
421
808
  };
422
809
  }
423
810
  export {
424
- EvalCache,
425
- Module2 as Module,
811
+ ASSET_TAG_CLOSE,
812
+ ASSET_TAG_OPEN,
813
+ DEOPT,
814
+ evalCache$1 as EvalCache,
815
+ Module,
816
+ fluentTokensPlugin,
426
817
  default2 as shakerEvaluator,
427
818
  transformSync
428
819
  };
@@ -1,4 +1,4 @@
1
- import { StrictOptions } from '@linaria/babel-preset';
1
+ import { StrictOptions, AstEvaluatorPlugin } from './evaluation/types.mjs';
2
2
  import { CSSRulesByBucket } from '@griffel/core';
3
3
  export type TransformOptions = {
4
4
  filename: string;
@@ -17,6 +17,8 @@ export type TransformOptions = {
17
17
  babelOptions?: Pick<StrictOptions['babelOptions'], 'plugins' | 'presets'>;
18
18
  /** The set of rules that defines how the matched files will be transformed during the evaluation. */
19
19
  evaluationRules?: StrictOptions['rules'];
20
+ /** Plugins for extending AST evaluation with custom node handling. */
21
+ astEvaluationPlugins?: AstEvaluatorPlugin[];
20
22
  };
21
23
  export type TransformResult = {
22
24
  code: string;
package/types.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Node } from 'oxc-parser';
2
2
  export interface StyleCall {
3
3
  declaratorId: string;
4
- functionKind: 'makeStyles' | 'makeResetStyles';
4
+ functionKind: 'makeStyles' | 'makeResetStyles' | 'makeStaticStyles';
5
5
  argumentStart: number;
6
6
  argumentEnd: number;
7
7
  argumentCode: string;