@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 +31 -2
- package/README.md +61 -1
- package/constants.d.mts +2 -0
- package/evaluation/astEvaluator.d.mts +11 -3
- package/evaluation/batchEvaluator.d.mts +3 -2
- package/evaluation/evalCache.d.mts +9 -0
- package/evaluation/fluentTokensPlugin.d.mts +2 -0
- package/evaluation/hybridEvaluator.d.mts +2 -0
- package/evaluation/module.d.mts +29 -0
- package/evaluation/process.d.mts +24 -0
- package/evaluation/types.d.mts +29 -0
- package/evaluation/vmEvaluator.d.mts +1 -2
- package/index.d.mts +7 -2
- package/package.json +5 -5
- package/transform.js +567 -176
- package/transformSync.d.mts +3 -1
- package/types.d.mts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
# Change Log - @griffel/transform
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
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:
|
|
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
|
package/constants.d.mts
ADDED
|
@@ -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 {
|
|
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,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;
|
package/evaluation/types.d.mts
CHANGED
|
@@ -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 '
|
|
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 {
|
|
3
|
-
export
|
|
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
|
|
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.
|
|
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.
|
|
24
|
-
"oxc-walker": "^0.
|
|
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
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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,
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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
|
|
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 === "
|
|
270
|
-
const
|
|
271
|
-
if (
|
|
272
|
-
|
|
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
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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 (
|
|
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,
|
|
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,
|
|
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
|
|
401
|
-
|
|
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
|
-
|
|
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
|
-
|
|
425
|
-
|
|
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
|
};
|
package/transformSync.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StrictOptions } from '
|
|
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;
|