@stylexswc/rs-compiler 0.17.0 → 0.17.1-rc.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/README.md +248 -470
- package/dist/index.d.ts +1 -0
- package/dist/index.js +14 -6
- package/dist/transform.d.ts +7 -0
- package/dist/transform.js +52 -52
- package/package.json +54 -27
package/README.md
CHANGED
|
@@ -1,260 +1,138 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @stylexswc/rs-compiler
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> High-performance StyleX compiler for Node.js, written in Rust on NAPI-RS and
|
|
4
|
+
> SWC. Part of the
|
|
4
5
|
> [StyleX SWC Plugin](https://github.com/Dwlad90/stylex-swc-plugin#readme)
|
|
5
|
-
> workspace
|
|
6
|
+
> workspace.
|
|
6
7
|
|
|
7
8
|
<!-- stylex-compatibility:start -->
|
|
9
|
+
|
|
8
10
|
> [!NOTE]
|
|
9
11
|
> Compatibility target: this package has been updated through official
|
|
10
12
|
> StyleX v0.19.0. This is not an official Meta support guarantee.
|
|
11
|
-
<!-- stylex-compatibility:end -->
|
|
12
|
-
|
|
13
|
-
StyleX is a JavaScript library developed by Meta for defining styles optimized
|
|
14
|
-
for user interfaces. You can find the
|
|
15
|
-
[official StyleX repository](https://www.github.com/facebook/stylex) here.
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
> This is an unofficial style compiler for StyleX.
|
|
19
|
-
|
|
20
|
-
## Overview
|
|
21
|
-
|
|
22
|
-
This package provides an unofficial, high-performance NAPI-RS compiler for
|
|
23
|
-
StyleX, a popular library from Meta for building optimized user interfaces. It
|
|
24
|
-
is the top-level consumer crate that exposes the full StyleX pipeline to
|
|
25
|
-
Node.js, leveraging SWC for parsing and transformation.
|
|
26
|
-
|
|
27
|
-
> [!IMPORTANT]
|
|
28
|
-
> The usage of StyleX does not change. All changes are internal.
|
|
29
|
-
|
|
30
|
-
- Faster Build Times: By utilizing SWC instead of Babel, you can potentially
|
|
31
|
-
experience significant speed improvements during StyleX processing.
|
|
32
|
-
- Seamless Integration: This compiler seamlessly integrates with Next.js's
|
|
33
|
-
default SWC Compiler, ensuring a smooth workflow.
|
|
34
|
-
- Drop-in Replacement: Designed to be a drop-in replacement for the official
|
|
35
|
-
StyleX Babel plugin, minimizing disruption to existing codebases.
|
|
36
|
-
- Advanced Tooling Capabilities: NAPI-RS compiler unlocks access to StyleX
|
|
37
|
-
metadata and source maps, enabling the creation of advanced plugins and tools
|
|
38
|
-
for StyleX, ex. for creating a plugin for Webpack, Rollup, or other tools.
|
|
39
|
-
|
|
40
|
-
## Advantages of a `NAPI-RS` compiler versus a `SWC plugin`
|
|
41
|
-
|
|
42
|
-
- Compability with SWC: under the hood, the NAPI-RS compiler uses SWC for
|
|
43
|
-
parsing and transforming JavaScript code, ensuring compatibility with the
|
|
44
|
-
latest ECMAScript features.
|
|
45
|
-
- Direct Access to Node.js APIs: NAPI-RS allows you to directly access Node.js
|
|
46
|
-
APIs from your Rust code, providing greater flexibility and control.
|
|
47
|
-
- Improved Performance: NAPI-RS can often offer better performance than
|
|
48
|
-
traditional Node.js addons, especially for computationally intensive tasks.
|
|
49
|
-
- Simplified Development: NAPI-RS simplifies the process of developing Node.js
|
|
50
|
-
addons in Rust, making it easier to create high-performance and efficient
|
|
51
|
-
tools.
|
|
52
|
-
|
|
53
|
-
## Architecture
|
|
54
|
-
|
|
55
|
-
- **Layer**: 9 — Compilers (top-level consumer)
|
|
56
|
-
- **Depends on**: `stylex-ast`, `stylex-enums`, `stylex-logs`, `stylex-macros`,
|
|
57
|
-
`stylex-regex`, `stylex-structures`, `stylex-transform`, `stylex-types`,
|
|
58
|
-
`stylex-utils`
|
|
59
|
-
- **Depended on by**: None (top-level entry point)
|
|
60
|
-
|
|
61
|
-
### Public API
|
|
62
|
-
|
|
63
|
-
- `transform()` — Main entry point: takes source code + options, returns
|
|
64
|
-
transformed output
|
|
65
|
-
- `should_transform_file()` — File filtering based on path patterns
|
|
66
|
-
- `normalize_rs_options()` — Options normalization and validation
|
|
67
|
-
|
|
68
|
-
### Modules
|
|
69
|
-
|
|
70
|
-
- `enums` — Compiler-specific enum types
|
|
71
|
-
- `structs` — Compiler-specific struct types
|
|
72
|
-
- `utils::fn_parser` — Function argument parsing
|
|
73
|
-
- `utils::metadata` — Build metadata handling
|
|
74
|
-
- `utils::path_filter` — File path filtering logic
|
|
75
|
-
|
|
76
|
-
## Dependency Graph
|
|
77
|
-
|
|
78
|
-
<details>
|
|
79
|
-
<summary><h3>Dependency Graph</h3></summary>
|
|
80
|
-
|
|
81
|
-
```mermaid
|
|
82
|
-
graph TD
|
|
83
|
-
subgraph L0["Primitives"]
|
|
84
|
-
stylex_constants["constants"]
|
|
85
|
-
stylex_regex["regex"]
|
|
86
|
-
stylex_styleq["styleq"]
|
|
87
|
-
stylex_utils["utils"]
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
subgraph L1["Proc Macros"]
|
|
91
|
-
stylex_macros["macros"]
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
subgraph L2["Domain Leaves"]
|
|
95
|
-
stylex_enums["enums"]
|
|
96
|
-
stylex_js["js"]
|
|
97
|
-
stylex_logs["logs"]
|
|
98
|
-
stylex_css_parser["css-parser"]
|
|
99
|
-
stylex_path_resolver["path-resolver"]
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
subgraph L3["Core Data Structures"]
|
|
103
|
-
stylex_structures["structures"]
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
subgraph L4["Type System"]
|
|
107
|
-
stylex_types["types"]
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
subgraph L5["AST Foundations"]
|
|
111
|
-
stylex_ast["ast"]
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
subgraph L6["Evaluation"]
|
|
115
|
-
stylex_evaluator["evaluator"]
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
subgraph L7["CSS Processing"]
|
|
119
|
-
stylex_css["css"]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
subgraph L8["StyleX Transform"]
|
|
123
|
-
stylex_transform["transform"]
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
subgraph L9["Compilers"]
|
|
127
|
-
stylex_compiler_rs["rs-compiler"]
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
stylex_utils --> stylex_regex
|
|
131
|
-
|
|
132
|
-
stylex_macros --> stylex_constants
|
|
133
|
-
|
|
134
|
-
stylex_enums --> stylex_macros
|
|
135
|
-
stylex_js --> stylex_constants
|
|
136
|
-
stylex_js --> stylex_macros
|
|
137
|
-
stylex_logs --> stylex_macros
|
|
138
|
-
stylex_css_parser --> stylex_macros
|
|
139
|
-
stylex_path_resolver --> stylex_macros
|
|
140
|
-
|
|
141
|
-
stylex_structures --> stylex_constants
|
|
142
|
-
stylex_structures --> stylex_enums
|
|
143
|
-
stylex_structures --> stylex_macros
|
|
144
|
-
|
|
145
|
-
stylex_types --> stylex_constants
|
|
146
|
-
stylex_types --> stylex_enums
|
|
147
|
-
stylex_types --> stylex_macros
|
|
148
|
-
stylex_types --> stylex_structures
|
|
149
|
-
stylex_types --> stylex_utils
|
|
150
|
-
|
|
151
|
-
stylex_ast --> stylex_constants
|
|
152
|
-
stylex_ast --> stylex_macros
|
|
153
|
-
stylex_ast --> stylex_types
|
|
154
|
-
stylex_ast --> stylex_utils
|
|
155
|
-
|
|
156
|
-
stylex_evaluator --> stylex_ast
|
|
157
|
-
stylex_evaluator --> stylex_constants
|
|
158
|
-
stylex_evaluator --> stylex_js
|
|
159
|
-
stylex_evaluator --> stylex_macros
|
|
160
|
-
stylex_evaluator --> stylex_path_resolver
|
|
161
|
-
stylex_evaluator --> stylex_types
|
|
162
|
-
|
|
163
|
-
stylex_css --> stylex_ast
|
|
164
|
-
stylex_css --> stylex_constants
|
|
165
|
-
stylex_css --> stylex_css_parser
|
|
166
|
-
stylex_css --> stylex_enums
|
|
167
|
-
stylex_css --> stylex_evaluator
|
|
168
|
-
stylex_css --> stylex_macros
|
|
169
|
-
stylex_css --> stylex_regex
|
|
170
|
-
stylex_css --> stylex_structures
|
|
171
|
-
stylex_css --> stylex_types
|
|
172
|
-
stylex_css --> stylex_utils
|
|
173
|
-
|
|
174
|
-
stylex_transform --> stylex_ast
|
|
175
|
-
stylex_transform --> stylex_constants
|
|
176
|
-
stylex_transform --> stylex_css
|
|
177
|
-
stylex_transform --> stylex_css_parser
|
|
178
|
-
stylex_transform --> stylex_enums
|
|
179
|
-
stylex_transform --> stylex_evaluator
|
|
180
|
-
stylex_transform --> stylex_logs
|
|
181
|
-
stylex_transform --> stylex_macros
|
|
182
|
-
stylex_transform --> stylex_path_resolver
|
|
183
|
-
stylex_transform --> stylex_regex
|
|
184
|
-
stylex_transform --> stylex_structures
|
|
185
|
-
stylex_transform --> stylex_styleq
|
|
186
|
-
stylex_transform --> stylex_types
|
|
187
|
-
stylex_transform --> stylex_utils
|
|
188
|
-
|
|
189
|
-
stylex_compiler_rs --> stylex_ast
|
|
190
|
-
stylex_compiler_rs --> stylex_enums
|
|
191
|
-
stylex_compiler_rs --> stylex_logs
|
|
192
|
-
stylex_compiler_rs --> stylex_macros
|
|
193
|
-
stylex_compiler_rs --> stylex_regex
|
|
194
|
-
stylex_compiler_rs --> stylex_structures
|
|
195
|
-
stylex_compiler_rs --> stylex_transform
|
|
196
|
-
stylex_compiler_rs --> stylex_types
|
|
197
|
-
stylex_compiler_rs --> stylex_utils
|
|
198
|
-
|
|
199
|
-
classDef l0 fill:#e8e8e8,stroke:#999,color:#333
|
|
200
|
-
classDef l1 fill:#dce8ff,stroke:#6699cc,color:#333
|
|
201
|
-
classDef l2 fill:#dcf5dc,stroke:#66aa66,color:#333
|
|
202
|
-
classDef l3 fill:#fff3dc,stroke:#cc9933,color:#333
|
|
203
|
-
classDef l4 fill:#ffe8dc,stroke:#cc6633,color:#333
|
|
204
|
-
classDef l5 fill:#f5dcff,stroke:#9933cc,color:#333
|
|
205
|
-
classDef l6 fill:#dcfff5,stroke:#33aaaa,color:#333
|
|
206
|
-
classDef l7 fill:#ffdcdc,stroke:#cc3333,color:#333
|
|
207
|
-
classDef l8 fill:#fffdc0,stroke:#aaaa33,color:#333
|
|
208
|
-
classDef l9 fill:#ffc0c0,stroke:#cc0000,color:#333
|
|
209
|
-
|
|
210
|
-
class stylex_constants,stylex_regex,stylex_styleq,stylex_utils l0
|
|
211
|
-
class stylex_macros l1
|
|
212
|
-
class stylex_enums,stylex_js,stylex_logs,stylex_css_parser,stylex_path_resolver l2
|
|
213
|
-
class stylex_structures l3
|
|
214
|
-
class stylex_types l4
|
|
215
|
-
class stylex_ast l5
|
|
216
|
-
class stylex_evaluator l6
|
|
217
|
-
class stylex_css l7
|
|
218
|
-
class stylex_transform l8
|
|
219
|
-
class stylex_compiler_rs l9
|
|
220
|
-
```
|
|
14
|
+
<!-- stylex-compatibility:end -->
|
|
221
15
|
|
|
222
|
-
|
|
16
|
+
[StyleX](https://stylexjs.com) is Meta's CSS-in-JS library with compile-time
|
|
17
|
+
style extraction. The official toolchain compiles it with a Babel plugin; this
|
|
18
|
+
package is a from-scratch Rust implementation of that same transform, exposed to
|
|
19
|
+
Node.js as a native addon through [NAPI-RS](https://napi.rs) and parsed with
|
|
20
|
+
[SWC](https://swc.rs). It is designed as a drop-in replacement: your StyleX code
|
|
21
|
+
and its output do not change, but transforms run 2x to 5x faster than
|
|
22
|
+
Babel — see
|
|
23
|
+
[performance](https://github.com/Dwlad90/stylex-swc-plugin#performance).
|
|
24
|
+
|
|
25
|
+
This is a community project and is not affiliated with or supported by Meta. It
|
|
26
|
+
requires Node.js 20 or newer; prebuilt binaries ship for macOS, Linux (glibc and
|
|
27
|
+
musl), and Windows on x64 and arm64.
|
|
28
|
+
|
|
29
|
+
Most projects should not call this package directly — use the integration for
|
|
30
|
+
your build tool, all of which drive this compiler under the hood:
|
|
31
|
+
|
|
32
|
+
| Build tool | Package |
|
|
33
|
+
| --------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
34
|
+
| Next.js (Webpack, Rspack, Turbopack) | [`@stylexswc/nextjs-plugin`](https://www.npmjs.com/package/@stylexswc/nextjs-plugin) |
|
|
35
|
+
| Vite, esbuild, Farm, Rsbuild, Nuxt, ... | [`@stylexswc/unplugin`](https://www.npmjs.com/package/@stylexswc/unplugin) |
|
|
36
|
+
| webpack | [`@stylexswc/webpack-plugin`](https://www.npmjs.com/package/@stylexswc/webpack-plugin) |
|
|
37
|
+
| Rspack | [`@stylexswc/rspack-plugin`](https://www.npmjs.com/package/@stylexswc/rspack-plugin) |
|
|
38
|
+
| Rollup | [`@stylexswc/rollup-plugin`](https://www.npmjs.com/package/@stylexswc/rollup-plugin) |
|
|
39
|
+
| PostCSS pipelines | [`@stylexswc/postcss-plugin`](https://www.npmjs.com/package/@stylexswc/postcss-plugin) |
|
|
40
|
+
| Jest | [`@stylexswc/jest`](https://www.npmjs.com/package/@stylexswc/jest) |
|
|
41
|
+
|
|
42
|
+
Use this package directly when building your own tooling: custom bundler
|
|
43
|
+
plugins, codemods, or anything that needs the transformed code plus StyleX
|
|
44
|
+
metadata and source maps.
|
|
223
45
|
|
|
224
46
|
## Installation
|
|
225
47
|
|
|
226
|
-
To install the package, run the following command:
|
|
227
|
-
|
|
228
48
|
```bash
|
|
229
49
|
npm install --save-dev @stylexswc/rs-compiler
|
|
230
50
|
```
|
|
231
51
|
|
|
232
|
-
|
|
52
|
+
## Usage
|
|
233
53
|
|
|
234
|
-
|
|
235
|
-
|
|
54
|
+
The main entry point is `transform`. It takes a filename, the source code, and
|
|
55
|
+
options, and returns the transformed code, metadata about the generated styles,
|
|
56
|
+
and an optional source map:
|
|
236
57
|
|
|
237
58
|
```ts
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
/// ...other logic
|
|
59
|
+
const { transform } = require('@stylexswc/rs-compiler');
|
|
241
60
|
|
|
242
|
-
const { code, metadata,
|
|
61
|
+
const { code, metadata, map } = transform(
|
|
243
62
|
filename,
|
|
244
63
|
inputSourceCode,
|
|
245
64
|
transformOptions
|
|
246
65
|
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Example
|
|
69
|
+
|
|
70
|
+
Input StyleX code:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import * as stylex from '@stylexjs/stylex';
|
|
74
|
+
|
|
75
|
+
const styles = stylex.create({
|
|
76
|
+
root: {
|
|
77
|
+
padding: 10,
|
|
78
|
+
},
|
|
79
|
+
element: {
|
|
80
|
+
backgroundColor: 'red',
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const styleProps = stylex.props(styles.root, styles.element);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Output code:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import * as stylex from '@stylexjs/stylex';
|
|
91
|
+
export const styleProps = {
|
|
92
|
+
className: 'x7z7khe xrkmrrc',
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Output shape
|
|
97
|
+
|
|
98
|
+
Transforming the example above with source maps enabled
|
|
99
|
+
(`sourceMap: SourceMaps.True`) returns:
|
|
247
100
|
|
|
248
|
-
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"code": "import * as stylex from '@stylexjs/stylex';\nexport const styleProps = {\n className: \"x7z7khe xrkmrrc\"\n};\n",
|
|
104
|
+
"metadata": {
|
|
105
|
+
"stylex": [
|
|
106
|
+
[
|
|
107
|
+
"x7z7khe",
|
|
108
|
+
{
|
|
109
|
+
"ltr": ".x7z7khe{padding:10px}",
|
|
110
|
+
"rtl": null
|
|
111
|
+
},
|
|
112
|
+
1000
|
|
113
|
+
],
|
|
114
|
+
[
|
|
115
|
+
"xrkmrrc",
|
|
116
|
+
{
|
|
117
|
+
"ltr": ".xrkmrrc{background-color:red}",
|
|
118
|
+
"rtl": null
|
|
119
|
+
},
|
|
120
|
+
3000
|
|
121
|
+
]
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
"map": "{\"version\":3,\"sources\":[\"app/components/Button.tsx\"],\"names\":[],\"mappings\":\"AAAA;AAWA;;EAAoE\"}"
|
|
125
|
+
}
|
|
249
126
|
```
|
|
250
127
|
|
|
251
|
-
|
|
128
|
+
The `metadata.stylex` rules are what bundler plugins collect to build the final
|
|
129
|
+
CSS file.
|
|
130
|
+
|
|
131
|
+
## Path Filtering
|
|
252
132
|
|
|
253
133
|
> [!NOTE]
|
|
254
|
-
> The `include` and `exclude` options are exclusive to
|
|
255
|
-
>
|
|
256
|
-
> StyleX Babel plugin. They provide powerful file filtering capabilities to
|
|
257
|
-
> control which files are transformed.
|
|
134
|
+
> The `include` and `exclude` options are exclusive to this compiler and
|
|
135
|
+
> are not available in the official StyleX Babel plugin.
|
|
258
136
|
|
|
259
137
|
The compiler exports a `shouldTransformFile` function to determine whether a
|
|
260
138
|
file should be transformed based on include/exclude patterns:
|
|
@@ -273,36 +151,29 @@ if (shouldTransform) {
|
|
|
273
151
|
}
|
|
274
152
|
```
|
|
275
153
|
|
|
276
|
-
|
|
154
|
+
### Pattern Types
|
|
277
155
|
|
|
278
|
-
- **Glob patterns** (strings):
|
|
279
|
-
- `src/**/*.tsx`
|
|
280
|
-
- `**/*.test.*`
|
|
281
|
-
- `**/node_modules/**`
|
|
156
|
+
- **Glob patterns** (strings): standard glob syntax matched against file paths
|
|
157
|
+
- `src/**/*.tsx` — all `.tsx` files in `src` and subdirectories
|
|
158
|
+
- `**/*.test.*` — all test files
|
|
159
|
+
- `**/node_modules/**` — all files in `node_modules`
|
|
282
160
|
|
|
283
|
-
- **Regular expressions**:
|
|
284
|
-
- `/\.test\./`
|
|
285
|
-
- `/^src\/.*\.tsx$/`
|
|
286
|
-
|
|
287
|
-
**Advanced: Lookahead/Lookbehind Support**
|
|
161
|
+
- **Regular expressions**: RegExp objects for complex matching
|
|
162
|
+
- `/\.test\./` — files containing `.test.`
|
|
163
|
+
- `/^src\/.*\.tsx$/` — `.tsx` files directly in the `src` directory
|
|
288
164
|
|
|
289
165
|
The Rust regex engine fully supports lookahead and lookbehind assertions,
|
|
290
|
-
|
|
291
|
-
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
- **Positive Lookbehind** `(?<=...)`: Match if preceded by pattern
|
|
303
|
-
- `/(?<=components\/).*\.tsx$/` - Match only .tsx files in components/
|
|
304
|
-
|
|
305
|
-
#### Filtering Rules
|
|
166
|
+
which the JavaScript-side patterns can rely on:
|
|
167
|
+
- Negative lookahead `(?!...)`: `/node_modules(?!\/@stylexjs)/` excludes all
|
|
168
|
+
of `node_modules` except `@stylexjs` packages
|
|
169
|
+
- Positive lookahead `(?=...)`: `/.*\.test(?=\.tsx$)/` matches only
|
|
170
|
+
`.test.tsx` files
|
|
171
|
+
- Negative lookbehind `(?<!...)`: `/(?<!src\/).*\.tsx$/` excludes `.tsx` files
|
|
172
|
+
outside `src/`
|
|
173
|
+
- Positive lookbehind `(?<=...)`: `/(?<=components\/).*\.tsx$/` matches only
|
|
174
|
+
`.tsx` files in `components/`
|
|
175
|
+
|
|
176
|
+
### Filtering Rules
|
|
306
177
|
|
|
307
178
|
1. If `include` patterns are specified and not empty, files must match at least
|
|
308
179
|
one pattern
|
|
@@ -310,18 +181,17 @@ if (shouldTransform) {
|
|
|
310
181
|
3. Exclude patterns take precedence over include patterns
|
|
311
182
|
4. All paths are matched relative to the current working directory
|
|
312
183
|
|
|
313
|
-
|
|
184
|
+
### Common Use Cases
|
|
314
185
|
|
|
315
|
-
|
|
186
|
+
Exclude all of `node_modules` except one package:
|
|
316
187
|
|
|
317
188
|
```ts
|
|
318
|
-
// Exclude all node_modules except @stylexjs/open-props
|
|
319
189
|
shouldTransformFile(filePath, undefined, [
|
|
320
190
|
/node_modules(?!\/@stylexjs\/open-props)/,
|
|
321
191
|
]);
|
|
322
192
|
```
|
|
323
193
|
|
|
324
|
-
|
|
194
|
+
Transform only specific packages from `node_modules`:
|
|
325
195
|
|
|
326
196
|
```ts
|
|
327
197
|
shouldTransformFile(
|
|
@@ -335,22 +205,10 @@ shouldTransformFile(
|
|
|
335
205
|
);
|
|
336
206
|
```
|
|
337
207
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
```ts
|
|
341
|
-
// Exclude all node_modules except @stylexjs packages
|
|
342
|
-
shouldTransformFile(filePath, undefined, [/node_modules(?!\/@stylexjs)/]);
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### SWC Plugin Support
|
|
208
|
+
## SWC Plugin Support
|
|
346
209
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
> before StyleX transformation. This allows you to chain transformations and
|
|
350
|
-
> integrate custom SWC plugins seamlessly.
|
|
351
|
-
|
|
352
|
-
The `transform` function accepts an optional `swcPlugins` array in the options
|
|
353
|
-
object, allowing you to run SWC WASM plugins before the StyleX transformation:
|
|
210
|
+
The `transform` function accepts an optional `swcPlugins` array, allowing you to
|
|
211
|
+
run SWC WASM plugins before the StyleX transformation:
|
|
354
212
|
|
|
355
213
|
```ts
|
|
356
214
|
const { transform } = require('@stylexswc/rs-compiler');
|
|
@@ -380,124 +238,27 @@ const { code, metadata, map } = transform('Button.tsx', sourceCode, {
|
|
|
380
238
|
});
|
|
381
239
|
```
|
|
382
240
|
|
|
383
|
-
|
|
241
|
+
How it works:
|
|
384
242
|
|
|
385
|
-
1. **Plugin
|
|
243
|
+
1. **Plugin execution phase**: if `swcPlugins` are provided, the source code is
|
|
386
244
|
first transformed using `@swc/core`'s `transformSync` with the specified WASM
|
|
387
245
|
plugins
|
|
388
|
-
2. **StyleX
|
|
246
|
+
2. **StyleX transformation phase**: the plugin-transformed code is then passed
|
|
389
247
|
to the StyleX compiler
|
|
390
248
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
Each plugin in the `swcPlugins` array is a tuple of:
|
|
394
|
-
|
|
395
|
-
- **Plugin Path** (string): Can be:
|
|
396
|
-
- An absolute path to a `.wasm` file: `/path/to/plugin.wasm`
|
|
397
|
-
- An npm package name: `@swc/plugin-emotion`
|
|
398
|
-
- **Plugin Config** (object): Plugin-specific configuration options
|
|
399
|
-
|
|
400
|
-
#### Example: Custom Theme Plugin
|
|
401
|
-
|
|
402
|
-
```ts
|
|
403
|
-
transform(filename, code, {
|
|
404
|
-
dev: true,
|
|
405
|
-
swcPlugins: [
|
|
406
|
-
[
|
|
407
|
-
'/Users/me/plugins/swc_plugin_theme.wasm',
|
|
408
|
-
{
|
|
409
|
-
themeName: 'theme-name',
|
|
410
|
-
themeConfig: {
|
|
411
|
-
primaryColor: 'blue',
|
|
412
|
-
spacing: 8,
|
|
413
|
-
},
|
|
414
|
-
},
|
|
415
|
-
],
|
|
416
|
-
],
|
|
417
|
-
});
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
#### Benefits
|
|
249
|
+
Each entry in `swcPlugins` is a tuple of:
|
|
421
250
|
|
|
422
|
-
-
|
|
423
|
-
|
|
424
|
-
-
|
|
425
|
-
- ✅ Full compatibility with SWC WASM plugins
|
|
426
|
-
- ✅ No additional build configuration needed
|
|
427
|
-
|
|
428
|
-
### Output
|
|
429
|
-
|
|
430
|
-
The output from the compiler includes the transformed code, metadata about the
|
|
431
|
-
generated styles, and an optional source map.
|
|
432
|
-
|
|
433
|
-
```json
|
|
434
|
-
{
|
|
435
|
-
"code": "import * as stylex from '@stylexjs/stylex';\nexport const styles = {\n default: {\n backgroundColor: \"xrkmrrc\",\n color: \"xju2f9n\",\n $$css: true\n }\n};\n",
|
|
436
|
-
"metadata": {
|
|
437
|
-
"stylex": {
|
|
438
|
-
"styles": [
|
|
439
|
-
[
|
|
440
|
-
"xrkmrrc",
|
|
441
|
-
{
|
|
442
|
-
"ltr": ".xrkmrrc{background-color:red}",
|
|
443
|
-
"rtl": null
|
|
444
|
-
},
|
|
445
|
-
3000
|
|
446
|
-
],
|
|
447
|
-
[
|
|
448
|
-
"xju2f9n",
|
|
449
|
-
{
|
|
450
|
-
"ltr": ".xju2f9n{color:blue}",
|
|
451
|
-
"rtl": null
|
|
452
|
-
},
|
|
453
|
-
3000
|
|
454
|
-
]
|
|
455
|
-
]
|
|
456
|
-
}
|
|
457
|
-
},
|
|
458
|
-
"map": "{\"version\":3,\"sources\":[\"<anon>\"],\"names\":[],\"mappings\":\"AACE;AACA;;;;;;EAKG\"}"
|
|
459
|
-
}
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
## Example
|
|
463
|
-
|
|
464
|
-
Below is a simple example of input StyleX code:
|
|
465
|
-
|
|
466
|
-
```ts
|
|
467
|
-
import * as stylex from '@stylexjs/stylex';
|
|
468
|
-
|
|
469
|
-
const styles = stylex.create({
|
|
470
|
-
root: {
|
|
471
|
-
padding: 10,
|
|
472
|
-
},
|
|
473
|
-
element: {
|
|
474
|
-
backgroundColor: 'red',
|
|
475
|
-
},
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
const styleProps = stylex.props(styles.root, styles.element);
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
Output code:
|
|
482
|
-
|
|
483
|
-
```ts
|
|
484
|
-
import * as stylex from '@stylexjs/stylex';
|
|
485
|
-
const styleProps = {
|
|
486
|
-
className: 'x7z7khe xrkmrrc',
|
|
487
|
-
};
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
## Compatibility
|
|
491
|
-
|
|
492
|
-
> [!IMPORTANT]
|
|
493
|
-
> The current resolution of the `exports` field from
|
|
494
|
-
> `package. json` is only partially supported, so if you encounter problems,
|
|
495
|
-
> please open an
|
|
496
|
-
> [issue](https://github.com/Dwlad90/stylex-swc-plugin/issues/new) with an
|
|
497
|
-
> attached link to reproduce the problem.
|
|
251
|
+
- **Plugin path** (string): an absolute path to a `.wasm` file
|
|
252
|
+
(`/path/to/plugin.wasm`) or an npm package name (`@swc/plugin-emotion`)
|
|
253
|
+
- **Plugin config** (object): plugin-specific configuration options
|
|
498
254
|
|
|
499
255
|
## Configuration Options
|
|
500
256
|
|
|
257
|
+
The compiler accepts the standard StyleX options (`dev`, `debug`,
|
|
258
|
+
`importSources`, `unstable_moduleResolution`, and so on — see the
|
|
259
|
+
[StyleX configuration docs](https://stylexjs.com/docs/api/configuration/babel-plugin/))
|
|
260
|
+
plus the compiler-specific options below.
|
|
261
|
+
|
|
501
262
|
### `injectStylexSideEffects`
|
|
502
263
|
|
|
503
264
|
**Type:** `boolean` **Default:** `false`
|
|
@@ -505,10 +266,8 @@ const styleProps = {
|
|
|
505
266
|
Automatically injects side-effect imports for `.stylex` and `.consts` files to
|
|
506
267
|
prevent tree-shaking from removing them during bundling.
|
|
507
268
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
When using build tools that perform tree-shaking (like webpack, rollup, vite),
|
|
511
|
-
imports from `.stylex` or `.consts` files may appear unused after StyleX
|
|
269
|
+
The problem: when build tools perform tree-shaking (webpack, Rollup, Vite),
|
|
270
|
+
imports from `.stylex` or `.consts` files may appear unused after the StyleX
|
|
512
271
|
transformation and get removed:
|
|
513
272
|
|
|
514
273
|
```ts
|
|
@@ -536,13 +295,11 @@ const styles = {
|
|
|
536
295
|
};
|
|
537
296
|
```
|
|
538
297
|
|
|
539
|
-
The bundler may remove these "unused" imports, but they
|
|
298
|
+
The bundler may remove these "unused" imports, but they are needed for other
|
|
540
299
|
files to resolve the same StyleX/const references correctly.
|
|
541
300
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
When `injectStylexSideEffects: true`, the compiler automatically adds
|
|
545
|
-
side-effect imports to preserve these modules:
|
|
301
|
+
With `injectStylexSideEffects: true`, the compiler adds side-effect imports to
|
|
302
|
+
preserve these modules:
|
|
546
303
|
|
|
547
304
|
```ts
|
|
548
305
|
// After transformation with injectStylexSideEffects: true
|
|
@@ -550,116 +307,106 @@ import { colors } from './theme.stylex';
|
|
|
550
307
|
import { spacing } from './tokens.consts';
|
|
551
308
|
import './theme.stylex'; // Side-effect import (prevents tree-shaking)
|
|
552
309
|
import './tokens.consts'; // Side-effect import (prevents tree-shaking)
|
|
553
|
-
|
|
554
|
-
const styles = {
|
|
555
|
-
root: {
|
|
556
|
-
backgroundColor: 'x1a2b3c',
|
|
557
|
-
padding: 'x4d5e6f',
|
|
558
|
-
$$css: true,
|
|
559
|
-
},
|
|
560
|
-
};
|
|
561
310
|
```
|
|
562
311
|
|
|
563
|
-
|
|
312
|
+
When to use:
|
|
564
313
|
|
|
565
|
-
-
|
|
566
|
-
|
|
567
|
-
-
|
|
568
|
-
- ❌ **Use `false`** when StyleX runs **after** tree-shaking (e.g., webpack's
|
|
314
|
+
- Use `true` when your bundler runs the StyleX transformation **before** other
|
|
315
|
+
optimizations (recommended), for example with webpack's `loaderOrder: 'first'`
|
|
316
|
+
- Use `false` when StyleX runs **after** tree-shaking (e.g. webpack's
|
|
569
317
|
`loaderOrder: 'last'`)
|
|
570
318
|
|
|
571
319
|
> [!TIP]
|
|
572
320
|
> This option is automatically enabled when using
|
|
573
321
|
> `@stylexswc/webpack-plugin` with `loaderOrder: 'first'` (the default).
|
|
574
322
|
|
|
575
|
-
### `
|
|
323
|
+
### `inputSourceMap`
|
|
576
324
|
|
|
577
|
-
**Type:** `
|
|
325
|
+
**Type:** `string` (JSON source map) **Default:** `undefined`
|
|
578
326
|
|
|
579
|
-
|
|
580
|
-
|
|
327
|
+
Source map for the incoming `code`, produced by earlier tooling — for example a
|
|
328
|
+
loader chain that expands compile-time macros before the StyleX transformation
|
|
329
|
+
runs.
|
|
581
330
|
|
|
582
|
-
|
|
331
|
+
The problem: when the compiler receives code already rewritten by previous
|
|
332
|
+
tools, positions in that code no longer match the original authored file. Two
|
|
333
|
+
things degrade as a result:
|
|
583
334
|
|
|
584
|
-
-
|
|
585
|
-
|
|
586
|
-
|
|
335
|
+
- Debug source-map annotations (`$$css: "file.tsx:LINE"`, emitted with
|
|
336
|
+
`debug: true`) point at lines of the intermediate code
|
|
337
|
+
- The emitted source map resolves to the intermediate code instead of the
|
|
338
|
+
original file
|
|
587
339
|
|
|
588
|
-
|
|
589
|
-
reporting. This is useful when:
|
|
590
|
-
- Working with in-memory transformations
|
|
591
|
-
- Source files are not available on disk
|
|
592
|
-
- You want faster compilation (skips file I/O)
|
|
340
|
+
When `inputSourceMap` is provided, the compiler:
|
|
593
341
|
|
|
594
|
-
|
|
342
|
+
1. Resolves each style namespace to its position using the namespace key's own
|
|
343
|
+
span — exact, with no re-parsing — and maps it through the input map back to
|
|
344
|
+
the original authored file
|
|
345
|
+
2. Chains the emitted source map onto the input map, so downstream tooling (e.g.
|
|
346
|
+
devtools) resolves positions all the way back to the original file
|
|
595
347
|
|
|
596
348
|
```ts
|
|
597
|
-
transform(filename,
|
|
598
|
-
use_real_file_for_source: true, // Use actual source files (default)
|
|
349
|
+
const { code, metadata, map } = transform(filename, inputCode, {
|
|
599
350
|
dev: true,
|
|
600
|
-
|
|
351
|
+
debug: true,
|
|
352
|
+
// Source map produced by the previous transformation step
|
|
353
|
+
inputSourceMap: JSON.stringify(previousStepSourceMap),
|
|
601
354
|
});
|
|
602
355
|
```
|
|
603
356
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
**Use `true` (recommended for development):**
|
|
607
|
-
|
|
608
|
-
- Local development with files on disk
|
|
609
|
-
- Accurate error messages with real line numbers
|
|
610
|
-
- Better debugging experience
|
|
611
|
-
- Source maps match your actual files
|
|
612
|
-
|
|
613
|
-
**Use `false` (for special cases):**
|
|
614
|
-
|
|
615
|
-
- In-memory transformations without disk access
|
|
616
|
-
- Virtual file systems
|
|
617
|
-
- Performance optimization when error accuracy is less critical
|
|
618
|
-
- Build pipelines where source files are not available
|
|
357
|
+
This is also the fastest position-resolution path: two binary searches per
|
|
358
|
+
namespace instead of re-reading and re-parsing the source.
|
|
619
359
|
|
|
620
360
|
> [!TIP]
|
|
621
|
-
>
|
|
622
|
-
>
|
|
623
|
-
>
|
|
361
|
+
> The bundler plugins (`@stylexswc/rspack-plugin`,
|
|
362
|
+
> `@stylexswc/webpack-plugin`, `@stylexswc/turbopack-plugin`,
|
|
363
|
+
> `@stylexswc/rollup-plugin`, and `@stylexswc/unplugin` on Rollup-compatible
|
|
364
|
+
> hosts) forward the previous loader's / plugin's source map automatically — no
|
|
365
|
+
> configuration needed as long as source maps are enabled in the bundler.
|
|
624
366
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
> representation instead of the original source code, which can lead to line
|
|
629
|
-
> number mismatches. This happens because:
|
|
630
|
-
>
|
|
631
|
-
> - The AST may have been modified by previous transformations
|
|
632
|
-
> - Comments and whitespace are normalized in the AST
|
|
633
|
-
> - The structure may differ from what's in your actual source file
|
|
634
|
-
>
|
|
635
|
-
> For accurate error reporting and debugging, always use
|
|
636
|
-
> `useRealFileForSource: true` (the default) during development.
|
|
367
|
+
An invalid map is ignored with a warning, and the compiler falls back to
|
|
368
|
+
locating positions in the source text as described under
|
|
369
|
+
[`useRealFileForSource`](#userealfileforsource).
|
|
637
370
|
|
|
638
|
-
|
|
371
|
+
### `useRealFileForSource`
|
|
639
372
|
|
|
640
|
-
|
|
641
|
-
environment variable. This is useful for troubleshooting and understanding the
|
|
642
|
-
internal processing of StyleX code.
|
|
373
|
+
**Type:** `boolean` **Default:** `true`
|
|
643
374
|
|
|
644
|
-
|
|
375
|
+
Controls whether the compiler reads source files from disk for error reporting
|
|
376
|
+
and source map generation. Only relevant when no
|
|
377
|
+
[`inputSourceMap`](#inputsourcemap) is available — with an input map, debug
|
|
378
|
+
source-map annotations are resolved from the compiler's own parse and do not
|
|
379
|
+
depend on this option.
|
|
645
380
|
|
|
646
|
-
|
|
381
|
+
- **`true` (default)**: the compiler reads the actual source file from disk when
|
|
382
|
+
generating error messages and source maps. This provides accurate line numbers
|
|
383
|
+
and source context that match what you see in your editor. Style namespaces
|
|
384
|
+
are located **by their key**, so positions resolve correctly even when the
|
|
385
|
+
incoming code was already rewritten by earlier tooling (keys survive
|
|
386
|
+
value-level transforms such as macro expansion).
|
|
647
387
|
|
|
648
|
-
-
|
|
649
|
-
-
|
|
650
|
-
|
|
651
|
-
- `debug`: Shows debug information and all above levels
|
|
652
|
-
- `trace`: Shows very detailed execution information
|
|
388
|
+
- **`false`**: the compiler uses the transformed AST representation for error
|
|
389
|
+
reporting. Useful for in-memory transformations, virtual file systems, or when
|
|
390
|
+
skipping file I/O matters more than exact positions.
|
|
653
391
|
|
|
654
|
-
|
|
392
|
+
> [!WARNING]
|
|
393
|
+
> With `useRealFileForSource: false`, error messages may report
|
|
394
|
+
> incorrect line numbers: the AST may have been modified by previous
|
|
395
|
+
> transformations, comments and whitespace are normalized, and the structure may
|
|
396
|
+
> differ from the file on disk. Keep the default `true` during development, and
|
|
397
|
+
> provide an [`inputSourceMap`](#inputsourcemap) when the incoming code was
|
|
398
|
+
> already transformed by earlier tooling.
|
|
655
399
|
|
|
656
|
-
|
|
400
|
+
## Debug Logging
|
|
401
|
+
|
|
402
|
+
Enable debug logging with the `STYLEX_DEBUG` environment variable. Available
|
|
403
|
+
levels: `error`, `warn` (default), `info`, `debug`, `trace`.
|
|
657
404
|
|
|
658
405
|
```bash
|
|
659
406
|
# Set to debug level
|
|
660
407
|
STYLEX_DEBUG=debug npm run build
|
|
661
408
|
|
|
662
|
-
# Set to trace for most verbose output
|
|
409
|
+
# Set to trace for the most verbose output
|
|
663
410
|
STYLEX_DEBUG=trace npm run dev
|
|
664
411
|
```
|
|
665
412
|
|
|
@@ -677,11 +424,9 @@ $env:STYLEX_DEBUG="debug"; npm run build
|
|
|
677
424
|
|
|
678
425
|
## Error Handling
|
|
679
426
|
|
|
680
|
-
The compiler produces
|
|
681
|
-
prefix, replacing Rust's default panic boilerplate with
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
### Error Format
|
|
427
|
+
The compiler produces structured error messages with a branded `[StyleX]`
|
|
428
|
+
prefix, replacing Rust's default panic boilerplate with readable diagnostics in
|
|
429
|
+
both the terminal and at the NAPI boundary.
|
|
685
430
|
|
|
686
431
|
All StyleX errors follow this format in the terminal:
|
|
687
432
|
|
|
@@ -699,6 +444,39 @@ Errors are color-coded for readability:
|
|
|
699
444
|
| Unimplemented feature | `[UNIMPLEMENTED]` | Magenta label |
|
|
700
445
|
| Internal unreachable state | `[UNREACHABLE]` | Blue label |
|
|
701
446
|
|
|
447
|
+
## FAQ
|
|
448
|
+
|
|
449
|
+
### Is this a drop-in replacement for `@stylexjs/babel-plugin`?
|
|
450
|
+
|
|
451
|
+
Yes, by design. It implements the same transform, is validated against the
|
|
452
|
+
official StyleX test suite, and produces compatible output. It also adds
|
|
453
|
+
compiler-only capabilities: `include`/`exclude` filtering, SWC WASM plugin
|
|
454
|
+
chaining, `inputSourceMap` chaining, and structured metadata output.
|
|
455
|
+
|
|
456
|
+
### Do I need Rust installed to use it?
|
|
457
|
+
|
|
458
|
+
No. Prebuilt native binaries are published for each supported platform and
|
|
459
|
+
installed automatically as optional dependencies.
|
|
460
|
+
|
|
461
|
+
### Which package should I install for my app?
|
|
462
|
+
|
|
463
|
+
One of the bundler integrations listed at the top of this page. Install
|
|
464
|
+
`@stylexswc/rs-compiler` directly only when building custom tooling on top of
|
|
465
|
+
the `transform` API.
|
|
466
|
+
|
|
467
|
+
### Known limitations?
|
|
468
|
+
|
|
469
|
+
Resolution of the `exports` field in `package.json` is only partially supported.
|
|
470
|
+
If you hit a problem, please open an
|
|
471
|
+
[issue](https://github.com/Dwlad90/stylex-swc-plugin/issues/new) with a
|
|
472
|
+
reproduction link.
|
|
473
|
+
|
|
474
|
+
## Documentation
|
|
475
|
+
|
|
476
|
+
- [StyleX documentation](https://stylexjs.com)
|
|
477
|
+
- [NAPI-RS documentation](https://napi.rs)
|
|
478
|
+
- [SWC documentation](https://swc.rs)
|
|
479
|
+
|
|
702
480
|
## License
|
|
703
481
|
|
|
704
482
|
MIT — see
|