@griffel/transform 1.1.0 → 1.2.0
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 +22 -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 +583 -176
- package/transformSync.d.mts +3 -1
- package/types.d.mts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
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 08:15:28 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 1.2.0
|
|
8
|
+
|
|
9
|
+
Fri, 06 Mar 2026 08:15:28 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- feat: add AST evaluator plugin system with evaluationPlugins option (olfedias@microsoft.com)
|
|
14
|
+
- feat: wrap imported asset paths in <griffel-asset> tags for reliable CSS extraction (olfedias@microsoft.com)
|
|
15
|
+
- feat: add makeStaticStyles AOT/CSS extraction support (olfedias@microsoft.com)
|
|
16
|
+
- feat: hybrid evaluator that shakes ESM node_modules instead of ignoring them (olfedias@microsoft.com)
|
|
17
|
+
- feat: throw on non-ESM input in transformSync (olfedias@microsoft.com)
|
|
18
|
+
- Bump @griffel/core to v1.20.0
|
|
19
|
+
|
|
20
|
+
### Patches
|
|
21
|
+
|
|
22
|
+
- refactor: use ScopeTracker from oxc-walker for scope-aware import resolution (olfedias@microsoft.com)
|
|
23
|
+
- refactor: extract dedupeCSSRules result to a variable in transformSync (olfedias@microsoft.com)
|
|
24
|
+
- refactor: internalize Linaria Module/EvalCache to remove @linaria/babel-preset dependency (olfedias@microsoft.com)
|
|
25
|
+
- perf: replace DeoptError with DEOPT sentinel symbol, optimize CSS rule dedup and lookups (olfedias@microsoft.com)
|
|
26
|
+
|
|
7
27
|
## 1.1.0
|
|
8
28
|
|
|
9
|
-
Mon, 03 Nov 2025 15:
|
|
29
|
+
Mon, 03 Nov 2025 15:43:56 GMT
|
|
10
30
|
|
|
11
31
|
### Minor changes
|
|
12
32
|
|
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: (rawId: 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.
|
|
3
|
+
"version": "1.2.0",
|
|
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.0",
|
|
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,428 @@
|
|
|
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
|
+
const BABEL_ESM = "/@babel/runtime/helpers/esm/";
|
|
172
|
+
const BABEL_CJS = "/@babel/runtime/helpers/";
|
|
173
|
+
const SWC_HELPERS_RE = /(@swc\/helpers\/)src(\/.+)\.mjs/;
|
|
174
|
+
const cookModuleId = (rawId) => {
|
|
175
|
+
const babelESMIndex = rawId.indexOf(BABEL_ESM);
|
|
176
|
+
if (babelESMIndex !== -1) {
|
|
177
|
+
return rawId.slice(0, babelESMIndex) + BABEL_CJS + rawId.slice(babelESMIndex + BABEL_ESM.length);
|
|
178
|
+
}
|
|
179
|
+
const swcHelpersIndex = rawId.indexOf("@swc/helpers/src/");
|
|
180
|
+
if (swcHelpersIndex === -1) {
|
|
181
|
+
return rawId.replace(SWC_HELPERS_RE, "$1lib$2.js");
|
|
182
|
+
}
|
|
183
|
+
return rawId;
|
|
184
|
+
};
|
|
185
|
+
class Module {
|
|
186
|
+
id;
|
|
187
|
+
filename;
|
|
188
|
+
options;
|
|
189
|
+
imports = null;
|
|
190
|
+
dependencies = null;
|
|
191
|
+
transform = null;
|
|
192
|
+
exports = {};
|
|
193
|
+
extensions;
|
|
194
|
+
debug;
|
|
195
|
+
debuggerDepth;
|
|
196
|
+
constructor(filename, options, debuggerDepth = 0) {
|
|
197
|
+
this.id = filename;
|
|
198
|
+
this.filename = filename;
|
|
199
|
+
this.options = options;
|
|
200
|
+
this.debuggerDepth = debuggerDepth;
|
|
201
|
+
this.debug = createCustomDebug(debuggerDepth);
|
|
202
|
+
Object.defineProperties(this, {
|
|
203
|
+
id: {
|
|
204
|
+
value: filename,
|
|
205
|
+
writable: false
|
|
206
|
+
},
|
|
207
|
+
filename: {
|
|
208
|
+
value: filename,
|
|
209
|
+
writable: false
|
|
210
|
+
},
|
|
211
|
+
paths: {
|
|
212
|
+
value: Object.freeze(
|
|
213
|
+
NativeModule._nodeModulePaths(
|
|
214
|
+
path.dirname(filename)
|
|
215
|
+
)
|
|
216
|
+
),
|
|
217
|
+
writable: false
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
this.exports = {};
|
|
221
|
+
this.extensions = [".json", ".js", ".jsx", ".ts", ".tsx", ".cjs"];
|
|
222
|
+
this.debug("prepare", filename);
|
|
223
|
+
}
|
|
224
|
+
resolve = (rawId) => {
|
|
225
|
+
const id = cookModuleId(rawId);
|
|
226
|
+
const extensions = NativeModule._extensions;
|
|
227
|
+
const added = [];
|
|
228
|
+
try {
|
|
229
|
+
this.extensions.forEach((ext) => {
|
|
230
|
+
if (ext in extensions) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
extensions[ext] = NOOP;
|
|
234
|
+
added.push(ext);
|
|
235
|
+
});
|
|
236
|
+
return Module._resolveFilename(id, this);
|
|
237
|
+
} finally {
|
|
238
|
+
added.forEach((ext) => delete extensions[ext]);
|
|
30
239
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
240
|
+
};
|
|
241
|
+
require = Object.assign(
|
|
242
|
+
(rawId) => {
|
|
243
|
+
const id = cookModuleId(rawId);
|
|
244
|
+
this.debug("require", id);
|
|
245
|
+
if (id in builtins) {
|
|
246
|
+
if (builtins[id]) {
|
|
247
|
+
return require(id);
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const filename = this.resolve(id);
|
|
252
|
+
if (filename === id && !path.isAbsolute(id)) {
|
|
253
|
+
throw new Error(`Unable to import "${id}". Importing Node builtins is not supported in the sandbox.`);
|
|
254
|
+
}
|
|
255
|
+
this.dependencies?.push(id);
|
|
256
|
+
let cacheKey = filename;
|
|
257
|
+
let only = [];
|
|
258
|
+
if (this.imports?.has(id)) {
|
|
259
|
+
only = this.imports.get(id).sort();
|
|
260
|
+
if (only.length === 0) {
|
|
261
|
+
only = ["default"];
|
|
262
|
+
}
|
|
263
|
+
cacheKey += `:${only.join(",")}`;
|
|
264
|
+
}
|
|
265
|
+
let m = cache[cacheKey];
|
|
266
|
+
if (!m) {
|
|
267
|
+
this.debug("cached:not-exist", id);
|
|
268
|
+
m = new Module(filename, this.options, this.debuggerDepth + 1);
|
|
269
|
+
m.transform = this.transform;
|
|
270
|
+
cache[cacheKey] = m;
|
|
271
|
+
if (this.extensions.includes(path.extname(filename))) {
|
|
272
|
+
const code = fs.readFileSync(filename, "utf-8");
|
|
273
|
+
if (/\.json$/.test(filename)) {
|
|
274
|
+
m.exports = JSON.parse(code);
|
|
275
|
+
} else {
|
|
276
|
+
m.evaluate(code, only.includes("*") ? ["*"] : only);
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
m.exports = ASSET_TAG_OPEN + filename + ASSET_TAG_CLOSE;
|
|
280
|
+
}
|
|
40
281
|
} else {
|
|
41
|
-
|
|
282
|
+
this.debug("cached:exist", id);
|
|
283
|
+
}
|
|
284
|
+
return m.exports;
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
ensure: NOOP,
|
|
288
|
+
cache,
|
|
289
|
+
resolve: this.resolve
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
evaluate(text, only = null) {
|
|
293
|
+
const { filename } = this;
|
|
294
|
+
let action = "ignore";
|
|
295
|
+
for (let i = this.options.rules.length - 1; i >= 0; i--) {
|
|
296
|
+
const { test } = this.options.rules[i];
|
|
297
|
+
if (!test || (typeof test === "function" ? test(filename) : test instanceof RegExp && test.test(filename))) {
|
|
298
|
+
action = this.options.rules[i].action;
|
|
299
|
+
break;
|
|
42
300
|
}
|
|
301
|
+
}
|
|
302
|
+
const cacheKey = [this.filename, ...only ?? []];
|
|
303
|
+
if (has(cacheKey, text)) {
|
|
304
|
+
this.exports = get(cacheKey, text);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
let code;
|
|
308
|
+
if (action === "ignore") {
|
|
309
|
+
this.debug("ignore", `${filename}`);
|
|
310
|
+
code = text;
|
|
43
311
|
} else {
|
|
44
|
-
|
|
312
|
+
const evaluator = typeof action === "function" ? action : require(require.resolve(action, {
|
|
313
|
+
paths: [dirname(this.filename)]
|
|
314
|
+
})).default;
|
|
315
|
+
let imports;
|
|
316
|
+
this.debug("prepare-evaluation", this.filename, "using", evaluator.name);
|
|
317
|
+
[code, imports] = evaluator(this.filename, this.options, text, only);
|
|
318
|
+
this.imports = imports;
|
|
319
|
+
this.debug("evaluate", `${this.filename} (only ${(only || []).join(", ")}):
|
|
320
|
+
${code}`);
|
|
45
321
|
}
|
|
46
|
-
|
|
322
|
+
const script = new vm.Script(`(function (exports) { ${code}
|
|
323
|
+
})(exports);`, {
|
|
324
|
+
filename: this.filename
|
|
325
|
+
});
|
|
326
|
+
script.runInContext(
|
|
327
|
+
vm.createContext({
|
|
328
|
+
clearImmediate: NOOP,
|
|
329
|
+
clearInterval: NOOP,
|
|
330
|
+
clearTimeout: NOOP,
|
|
331
|
+
setImmediate: NOOP,
|
|
332
|
+
setInterval: NOOP,
|
|
333
|
+
setTimeout: NOOP,
|
|
334
|
+
global,
|
|
335
|
+
process: mockProcess,
|
|
336
|
+
module: this,
|
|
337
|
+
exports: this.exports,
|
|
338
|
+
require: this.require,
|
|
339
|
+
__filename: this.filename,
|
|
340
|
+
__dirname: path.dirname(this.filename)
|
|
341
|
+
})
|
|
342
|
+
);
|
|
343
|
+
set(cacheKey, text, this.exports);
|
|
47
344
|
}
|
|
48
|
-
|
|
345
|
+
static invalidate = () => {
|
|
346
|
+
cache = {};
|
|
347
|
+
};
|
|
348
|
+
static invalidateEvalCache = () => {
|
|
349
|
+
clear();
|
|
350
|
+
};
|
|
351
|
+
// Alias to resolve the module using node's resolve algorithm
|
|
352
|
+
// This static property can be overridden by the webpack loader
|
|
353
|
+
// This allows us to use webpack's module resolution algorithm
|
|
354
|
+
static _resolveFilename = (id, options) => NativeModule._resolveFilename(
|
|
355
|
+
id,
|
|
356
|
+
options
|
|
357
|
+
);
|
|
358
|
+
static _nodeModulePaths = (filename) => NativeModule._nodeModulePaths(filename);
|
|
49
359
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
360
|
+
const DEOPT = /* @__PURE__ */ Symbol("deopt");
|
|
361
|
+
function astEvaluator(node, programAst, plugins = []) {
|
|
362
|
+
const context = {
|
|
363
|
+
programAst,
|
|
364
|
+
evaluateNode
|
|
365
|
+
};
|
|
366
|
+
function evaluateNode(node2) {
|
|
367
|
+
switch (node2.type) {
|
|
368
|
+
case "Literal":
|
|
369
|
+
return node2.value;
|
|
370
|
+
case "ObjectExpression":
|
|
371
|
+
return evaluateObjectExpression(node2);
|
|
372
|
+
case "TemplateLiteral":
|
|
373
|
+
if (node2.expressions.length === 0) {
|
|
374
|
+
return node2.quasis[0].value.cooked;
|
|
375
|
+
}
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
for (const plugin of plugins) {
|
|
379
|
+
const result2 = plugin.evaluateNode(node2, context);
|
|
380
|
+
if (result2 !== DEOPT) {
|
|
381
|
+
return result2;
|
|
60
382
|
}
|
|
61
383
|
}
|
|
384
|
+
return DEOPT;
|
|
62
385
|
}
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
386
|
+
function evaluateObjectExpression(node2) {
|
|
387
|
+
const obj = {};
|
|
388
|
+
for (const prop of node2.properties) {
|
|
389
|
+
if (prop.type !== "Property" || prop.kind !== "init") {
|
|
390
|
+
return DEOPT;
|
|
391
|
+
}
|
|
392
|
+
let key;
|
|
393
|
+
if (prop.computed) {
|
|
394
|
+
return DEOPT;
|
|
395
|
+
} else if (prop.key.type === "Identifier") {
|
|
396
|
+
key = prop.key.name;
|
|
397
|
+
} else if (prop.key.type === "Literal") {
|
|
398
|
+
const keyLiteral = prop.key;
|
|
399
|
+
if (typeof keyLiteral.value === "string" || typeof keyLiteral.value === "number") {
|
|
400
|
+
key = String(keyLiteral.value);
|
|
401
|
+
} else {
|
|
402
|
+
return DEOPT;
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
return DEOPT;
|
|
406
|
+
}
|
|
407
|
+
const value = evaluateNode(prop.value);
|
|
408
|
+
if (value === DEOPT) {
|
|
409
|
+
return DEOPT;
|
|
410
|
+
}
|
|
411
|
+
obj[key] = value;
|
|
412
|
+
}
|
|
413
|
+
return obj;
|
|
70
414
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
return {
|
|
75
|
-
confident: true,
|
|
76
|
-
value: evaluateNode(node)
|
|
77
|
-
};
|
|
78
|
-
} catch {
|
|
415
|
+
const result = evaluateNode(node);
|
|
416
|
+
if (result === DEOPT) {
|
|
79
417
|
return {
|
|
80
418
|
confident: false,
|
|
81
419
|
value: void 0
|
|
82
420
|
};
|
|
83
421
|
}
|
|
422
|
+
return {
|
|
423
|
+
confident: true,
|
|
424
|
+
value: result
|
|
425
|
+
};
|
|
84
426
|
}
|
|
85
427
|
function isError(e) {
|
|
86
428
|
return Object.prototype.toString.call(e) === "[object Error]";
|
|
@@ -123,13 +465,13 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
123
465
|
return { confident: false, error: err };
|
|
124
466
|
}
|
|
125
467
|
}
|
|
126
|
-
function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluationRules) {
|
|
468
|
+
function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluationRules, programAst, astEvaluationPlugins = []) {
|
|
127
469
|
const evaluationResults = new Array(styleCalls.length);
|
|
128
470
|
const argumentsCode = new Array(styleCalls.length).fill(null);
|
|
129
471
|
let vmEvaluationNeeded = false;
|
|
130
472
|
for (let i = 0; i < styleCalls.length; i++) {
|
|
131
473
|
const styleCall = styleCalls[i];
|
|
132
|
-
const staticResult = astEvaluator(styleCall.argumentNode);
|
|
474
|
+
const staticResult = astEvaluator(styleCall.argumentNode, programAst, astEvaluationPlugins);
|
|
133
475
|
if (staticResult.confident) {
|
|
134
476
|
evaluationResults[i] = staticResult.value;
|
|
135
477
|
continue;
|
|
@@ -163,22 +505,91 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
|
|
|
163
505
|
evaluationResults
|
|
164
506
|
};
|
|
165
507
|
}
|
|
508
|
+
const CJS_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".json"]);
|
|
509
|
+
const ESM_EXTENSIONS = /* @__PURE__ */ new Set([".mjs", ".mts"]);
|
|
510
|
+
const useRawTransfer = rawTransferSupported();
|
|
511
|
+
const NODE_MODULES_RE = /[/\\]node_modules[/\\]/;
|
|
512
|
+
function createHybridEvaluator(shakerEvaluator2) {
|
|
513
|
+
return (filename, options, text, only) => {
|
|
514
|
+
if (!NODE_MODULES_RE.test(filename)) {
|
|
515
|
+
return shakerEvaluator2(filename, options, text, only);
|
|
516
|
+
}
|
|
517
|
+
const ext = extname(filename);
|
|
518
|
+
if (CJS_EXTENSIONS.has(ext)) {
|
|
519
|
+
return [text, null];
|
|
520
|
+
}
|
|
521
|
+
if (ESM_EXTENSIONS.has(ext)) {
|
|
522
|
+
return shakerEvaluator2(filename, options, text, only);
|
|
523
|
+
}
|
|
524
|
+
const parseResult = parseSync(filename, text, {
|
|
525
|
+
sourceType: "unambiguous",
|
|
526
|
+
...useRawTransfer && { experimentalLazy: true }
|
|
527
|
+
});
|
|
528
|
+
const isESM = parseResult.module.hasModuleSyntax;
|
|
529
|
+
parseResult.dispose?.();
|
|
530
|
+
if (!isESM) {
|
|
531
|
+
return [text, null];
|
|
532
|
+
}
|
|
533
|
+
return shakerEvaluator2(filename, options, text, only);
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
function evaluateTemplateLiteralWithTokens(node) {
|
|
537
|
+
let result = "";
|
|
538
|
+
for (let i = 0; i < node.quasis.length; i++) {
|
|
539
|
+
result += node.quasis[i].value.cooked;
|
|
540
|
+
if (i < node.expressions.length) {
|
|
541
|
+
const expression = node.expressions[i];
|
|
542
|
+
if (expression.type === "MemberExpression" && expression.object.type === "Identifier" && expression.object.name === "tokens" && expression.property.type === "Identifier" && !expression.computed) {
|
|
543
|
+
result += `var(--${expression.property.name})`;
|
|
544
|
+
} else {
|
|
545
|
+
return DEOPT;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return result;
|
|
550
|
+
}
|
|
551
|
+
function evaluateTokensMemberExpression(node) {
|
|
552
|
+
if (node.object.type === "Identifier" && node.object.name === "tokens" && node.property.type === "Identifier" && !node.computed) {
|
|
553
|
+
return `var(--${node.property.name})`;
|
|
554
|
+
} else {
|
|
555
|
+
return DEOPT;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
const fluentTokensPlugin = {
|
|
559
|
+
name: "fluentTokensPlugin",
|
|
560
|
+
evaluateNode(node) {
|
|
561
|
+
switch (node.type) {
|
|
562
|
+
case "TemplateLiteral":
|
|
563
|
+
return evaluateTemplateLiteralWithTokens(node);
|
|
564
|
+
case "MemberExpression":
|
|
565
|
+
return evaluateTokensMemberExpression(node);
|
|
566
|
+
default:
|
|
567
|
+
return DEOPT;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
};
|
|
166
571
|
function dedupeCSSRules(cssRulesByBucket) {
|
|
167
572
|
return Object.fromEntries(
|
|
168
573
|
Object.entries(cssRulesByBucket).map(([styleBucketName, cssBucketEntries]) => {
|
|
169
574
|
if (styleBucketName === "m") {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
575
|
+
const seen = /* @__PURE__ */ new Map();
|
|
576
|
+
for (const entry of cssBucketEntries) {
|
|
577
|
+
if (!seen.has(entry[0])) {
|
|
578
|
+
seen.set(entry[0], entry);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return [styleBucketName, Array.from(seen.values())];
|
|
176
582
|
}
|
|
177
|
-
return [styleBucketName,
|
|
583
|
+
return [styleBucketName, Array.from(new Set(cssBucketEntries))];
|
|
178
584
|
})
|
|
179
585
|
);
|
|
180
586
|
}
|
|
181
587
|
const shakerEvaluator = _shaker.default || _shaker;
|
|
588
|
+
const RUNTIME_IDENTIFIERS = /* @__PURE__ */ new Map([
|
|
589
|
+
["makeStyles", "__css"],
|
|
590
|
+
["makeResetStyles", "__resetCSS"],
|
|
591
|
+
["makeStaticStyles", "__staticCSS"]
|
|
592
|
+
]);
|
|
182
593
|
function buildCSSResetEntriesMetadata(cssResetEntries, cssRules, declaratorId) {
|
|
183
594
|
const cssRulesByBucket = Array.isArray(cssRules) ? { d: cssRules } : cssRules;
|
|
184
595
|
cssResetEntries[declaratorId] ??= [];
|
|
@@ -227,11 +638,15 @@ function buildCSSEntriesMetadata(cssEntries, classnamesMapping, cssRulesByBucket
|
|
|
227
638
|
);
|
|
228
639
|
}
|
|
229
640
|
function concatCSSRulesByBucket(bucketA = {}, bucketB) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)
|
|
234
|
-
|
|
641
|
+
for (const cssBucketName in bucketB) {
|
|
642
|
+
const bucketName = cssBucketName;
|
|
643
|
+
const bucketBEntries = bucketB[bucketName] ?? [];
|
|
644
|
+
if (bucketA[bucketName]) {
|
|
645
|
+
bucketA[bucketName].push(...bucketBEntries);
|
|
646
|
+
} else {
|
|
647
|
+
bucketA[bucketName] = bucketBEntries;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
235
650
|
return bucketA;
|
|
236
651
|
}
|
|
237
652
|
function transformSync(sourceCode, options) {
|
|
@@ -241,109 +656,96 @@ function transformSync(sourceCode, options) {
|
|
|
241
656
|
classNameHashSalt = "",
|
|
242
657
|
generateMetadata = false,
|
|
243
658
|
modules = ["@griffel/core", "@griffel/react", "@fluentui/react-components"],
|
|
244
|
-
evaluationRules = [
|
|
245
|
-
|
|
246
|
-
{
|
|
247
|
-
test: /[/\\]node_modules[/\\]/,
|
|
248
|
-
action: "ignore"
|
|
249
|
-
}
|
|
250
|
-
]
|
|
659
|
+
evaluationRules = [{ action: createHybridEvaluator(shakerEvaluator) }],
|
|
660
|
+
astEvaluationPlugins = [fluentTokensPlugin]
|
|
251
661
|
} = options;
|
|
252
662
|
if (!filename) {
|
|
253
663
|
throw new Error('Transform error: "filename" option is required');
|
|
254
664
|
}
|
|
255
665
|
const parseResult = parseSync(filename, sourceCode);
|
|
256
|
-
parseResult.module.staticImports;
|
|
257
666
|
if (parseResult.errors.length > 0) {
|
|
258
667
|
throw new Error(`Failed to parse "${filename}": ${parseResult.errors.map((e) => e.message).join(", ")}`);
|
|
259
668
|
}
|
|
669
|
+
if (parseResult.program.body.length > 0 && !parseResult.module.hasModuleSyntax) {
|
|
670
|
+
throw new Error(
|
|
671
|
+
`Transform error: "${filename}" is not an ES module. @griffel/transform only supports ES modules (files using import/export syntax).`
|
|
672
|
+
);
|
|
673
|
+
}
|
|
260
674
|
const magicString = new MagicString(sourceCode);
|
|
261
675
|
const programAst = parseResult.program;
|
|
262
|
-
const
|
|
676
|
+
const hasGriffelImports = parseResult.module.staticImports.some(
|
|
677
|
+
(si) => modules.includes(si.moduleRequest.value) && si.entries.some((e) => e.importName.kind === "Name" && RUNTIME_IDENTIFIERS.has(e.importName.name))
|
|
678
|
+
);
|
|
679
|
+
if (!hasGriffelImports) {
|
|
680
|
+
return { code: sourceCode, usedProcessing: false, usedVMForEvaluation: false };
|
|
681
|
+
}
|
|
263
682
|
const styleCalls = [];
|
|
264
683
|
const cssEntries = {};
|
|
265
684
|
const cssResetEntries = {};
|
|
266
685
|
let cssRulesByBucket = {};
|
|
686
|
+
const scopeTracker = new ScopeTracker();
|
|
687
|
+
const matchedSpecifiers = /* @__PURE__ */ new Map();
|
|
267
688
|
walk(programAst, {
|
|
689
|
+
scopeTracker,
|
|
268
690
|
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
|
-
}
|
|
691
|
+
if (node.type === "CallExpression" && node.callee.type === "Identifier") {
|
|
692
|
+
const declaration = scopeTracker.getDeclaration(node.callee.name);
|
|
693
|
+
if (declaration?.type !== "Import" || declaration.node.type !== "ImportSpecifier") {
|
|
694
|
+
return;
|
|
294
695
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
}
|
|
696
|
+
const importSource = declaration.importNode.source.value;
|
|
697
|
+
if (!modules.includes(importSource)) {
|
|
698
|
+
return;
|
|
312
699
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
700
|
+
const imported = declaration.node.imported;
|
|
701
|
+
if (imported.type !== "Identifier") {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
const importedName = imported.name;
|
|
705
|
+
if (!RUNTIME_IDENTIFIERS.has(importedName)) {
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
const functionKind = importedName;
|
|
709
|
+
if (node.arguments.length !== 1) {
|
|
710
|
+
throw new Error(`${functionKind}() function accepts only a single param`);
|
|
711
|
+
}
|
|
712
|
+
matchedSpecifiers.set(declaration.node.start, {
|
|
713
|
+
start: declaration.node.start,
|
|
714
|
+
end: declaration.node.end,
|
|
715
|
+
functionKind
|
|
716
|
+
});
|
|
717
|
+
let declaratorId = "unknownHook";
|
|
718
|
+
let current = parent;
|
|
719
|
+
while (current) {
|
|
720
|
+
if (!current) {
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
if (current.type === "VariableDeclarator" && current.id.type === "Identifier") {
|
|
724
|
+
declaratorId = current.id.name;
|
|
328
725
|
break;
|
|
329
726
|
}
|
|
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
|
-
});
|
|
727
|
+
if ("parent" in current) {
|
|
728
|
+
current = current.parent;
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
break;
|
|
342
732
|
}
|
|
733
|
+
const argument = node.arguments[0];
|
|
734
|
+
styleCalls.push({
|
|
735
|
+
declaratorId,
|
|
736
|
+
functionKind,
|
|
737
|
+
argumentStart: argument.start,
|
|
738
|
+
argumentEnd: argument.end,
|
|
739
|
+
argumentCode: sourceCode.slice(argument.start, argument.end),
|
|
740
|
+
argumentNode: argument,
|
|
741
|
+
callStart: node.start,
|
|
742
|
+
callEnd: node.end,
|
|
743
|
+
importId: node.callee.name
|
|
744
|
+
});
|
|
343
745
|
}
|
|
344
746
|
}
|
|
345
747
|
});
|
|
346
|
-
if (
|
|
748
|
+
if (styleCalls.length === 0) {
|
|
347
749
|
return {
|
|
348
750
|
code: sourceCode,
|
|
349
751
|
usedProcessing: false,
|
|
@@ -355,7 +757,9 @@ function transformSync(sourceCode, options) {
|
|
|
355
757
|
filename,
|
|
356
758
|
styleCalls,
|
|
357
759
|
babelOptions,
|
|
358
|
-
evaluationRules
|
|
760
|
+
evaluationRules,
|
|
761
|
+
programAst,
|
|
762
|
+
astEvaluationPlugins
|
|
359
763
|
);
|
|
360
764
|
for (let i = 0; i < styleCalls.length; i++) {
|
|
361
765
|
const styleCall = styleCalls[i];
|
|
@@ -364,17 +768,13 @@ function transformSync(sourceCode, options) {
|
|
|
364
768
|
case "makeStyles":
|
|
365
769
|
{
|
|
366
770
|
const stylesBySlots = evaluationResult;
|
|
367
|
-
const [classnamesMapping,
|
|
771
|
+
const [classnamesMapping, resolvedCSSRules] = resolveStyleRulesForSlots(stylesBySlots, classNameHashSalt);
|
|
772
|
+
const uniqueCSSRules = dedupeCSSRules(cssRulesByBucket);
|
|
368
773
|
if (generateMetadata) {
|
|
369
|
-
buildCSSEntriesMetadata(
|
|
370
|
-
cssEntries,
|
|
371
|
-
classnamesMapping,
|
|
372
|
-
dedupeCSSRules(cssRulesByBucket),
|
|
373
|
-
styleCall.declaratorId
|
|
374
|
-
);
|
|
774
|
+
buildCSSEntriesMetadata(cssEntries, classnamesMapping, uniqueCSSRules, styleCall.declaratorId);
|
|
375
775
|
}
|
|
376
776
|
magicString.overwrite(styleCall.argumentStart, styleCall.argumentEnd, `${JSON.stringify(classnamesMapping)}`);
|
|
377
|
-
cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket,
|
|
777
|
+
cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket, resolvedCSSRules);
|
|
378
778
|
}
|
|
379
779
|
break;
|
|
380
780
|
case "makeResetStyles":
|
|
@@ -395,22 +795,25 @@ function transformSync(sourceCode, options) {
|
|
|
395
795
|
);
|
|
396
796
|
}
|
|
397
797
|
break;
|
|
798
|
+
case "makeStaticStyles":
|
|
799
|
+
{
|
|
800
|
+
const styles = evaluationResult;
|
|
801
|
+
const stylesSet = Array.isArray(styles) ? styles : [styles];
|
|
802
|
+
const cssRules = resolveStaticStyleRules(stylesSet);
|
|
803
|
+
magicString.overwrite(styleCall.argumentStart, styleCall.argumentEnd, JSON.stringify({ d: cssRules }));
|
|
804
|
+
cssRulesByBucket = concatCSSRulesByBucket(cssRulesByBucket, { d: cssRules });
|
|
805
|
+
}
|
|
806
|
+
break;
|
|
398
807
|
}
|
|
399
808
|
}
|
|
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
|
-
}
|
|
809
|
+
for (const specifier of matchedSpecifiers.values()) {
|
|
810
|
+
magicString.overwrite(specifier.start, specifier.end, RUNTIME_IDENTIFIERS.get(specifier.functionKind));
|
|
408
811
|
}
|
|
409
812
|
for (const styleCall of styleCalls) {
|
|
410
813
|
magicString.overwrite(
|
|
411
814
|
styleCall.callStart,
|
|
412
815
|
styleCall.callStart + styleCall.importId.length,
|
|
413
|
-
|
|
816
|
+
RUNTIME_IDENTIFIERS.get(styleCall.functionKind)
|
|
414
817
|
);
|
|
415
818
|
}
|
|
416
819
|
return {
|
|
@@ -421,8 +824,12 @@ function transformSync(sourceCode, options) {
|
|
|
421
824
|
};
|
|
422
825
|
}
|
|
423
826
|
export {
|
|
424
|
-
|
|
425
|
-
|
|
827
|
+
ASSET_TAG_CLOSE,
|
|
828
|
+
ASSET_TAG_OPEN,
|
|
829
|
+
DEOPT,
|
|
830
|
+
evalCache$1 as EvalCache,
|
|
831
|
+
Module,
|
|
832
|
+
fluentTokensPlugin,
|
|
426
833
|
default2 as shakerEvaluator,
|
|
427
834
|
transformSync
|
|
428
835
|
};
|
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;
|