@stylexswc/unplugin 0.13.0 → 0.13.1-rc.2

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 CHANGED
@@ -75,6 +75,23 @@ module.exports = {
75
75
 
76
76
  <br></details>
77
77
 
78
+ <details>
79
+ <summary>Rspack</summary><br>
80
+
81
+ ```ts
82
+ // rspack.config.js
83
+ module.exports = {
84
+ /* ... */
85
+ plugins: [
86
+ require('@stylexswc/unplugin/rspack')({
87
+ /* options */
88
+ }),
89
+ ],
90
+ };
91
+ ```
92
+
93
+ <br></details>
94
+
78
95
  <details>
79
96
  <summary>Nuxt</summary><br>
80
97
 
@@ -184,71 +201,101 @@ build({
184
201
  - Default: `['js', 'jsx', 'ts', 'tsx', 'mjs', 'mts']`
185
202
  - Description: File extensions to process for StyleX transformations.
186
203
 
187
- #### `useViteCssPipeline`
204
+ #### `useCssPlaceholder`
188
205
 
189
- - Type: `boolean`
206
+ - Type: `boolean | string`
190
207
  - Default: `false`
191
- - Description: **(Vite only)** Integrates StyleX-generated CSS into Vite's CSS processing pipeline as a virtual module. When enabled, StyleX CSS will be processed through Vite's CSS transformers (including PostCSS, LightningCSS, etc.) and benefit from proper HMR support.
208
+ - Description: Enable CSS injection into CSS files via placeholder marker.
209
+ - When set to `true`, the plugin will look for the default `@stylex;` marker
210
+ - When set to a string, the plugin will use that string as the custom marker
192
211
 
193
212
  ##### Benefits
194
213
 
195
- - **CSS Processing**: Generated StyleX CSS goes through Vite's CSS pipeline (PostCSS, LightningCSS, etc.)
196
- - **Better HMR**: CSS updates are handled through Vite's native CSS HMR with proper source maps
214
+ - **CSS Processing**: Generated StyleX CSS goes through the bundler's CSS pipeline (PostCSS, LightningCSS, css-loader, etc.)
215
+ - **Deterministic Builds**: No race conditions or hash instability from virtual modules
197
216
  - **Consistent Output**: All CSS follows the same processing rules and bundling strategy
198
217
  - **Build Optimization**: CSS can be code-split and optimized alongside other stylesheets
218
+ - **Works Everywhere**: Same approach works for Vite, Webpack, Rspack, esbuild, Rollup, and Farm
199
219
 
200
220
  ##### How to Use
201
221
 
222
+ 1. Create a CSS file with a marker (e.g., `global.css`):
223
+
224
+ ```css
225
+ /* global.css */
226
+ :root {
227
+ --brand-color: #663399;
228
+ }
229
+
230
+ body {
231
+ margin: 0;
232
+ font-family: system-ui, sans-serif;
233
+ }
234
+
235
+ @stylex;
236
+ ```
237
+
238
+ 2. Import the CSS file in your entry point:
239
+
202
240
  ```typescript
203
- // vite.config.ts
241
+ // src/main.ts
242
+ import './global.css';
243
+ import { App } from './App';
244
+ ```
245
+
246
+ 3. Configure the plugin with `useCssPlaceholder`:
247
+
248
+ ```typescript
249
+ // vite.config.ts (or webpack.config.js, rspack.config.js, etc.)
204
250
  import StylexRsPlugin from '@stylexswc/unplugin/vite';
205
251
  import { defineConfig } from 'vite';
206
252
 
207
253
  export default defineConfig({
208
254
  plugins: [
209
255
  StylexRsPlugin({
210
- useViteCssPipeline: true,
256
+ useCssPlaceholder: true, // Uses default '@stylex;' marker
257
+ useCSSLayers: true,
211
258
  }),
212
259
  ],
213
260
  });
214
261
  ```
215
262
 
216
- Then import the virtual CSS module in your entry file:
263
+ ##### Using a Custom Marker
217
264
 
218
- ```typescript
219
- // src/main.ts
220
- import 'virtual:stylex.css';
221
- import { App } from './App';
222
- ```
265
+ You can specify a custom marker string:
223
266
 
224
- **TypeScript Support:**
267
+ ```css
268
+ /* global.css */
269
+ :root {
270
+ --brand-color: #663399;
271
+ }
225
272
 
226
- For TypeScript projects, add the type definition to your `tsconfig.json`:
273
+ /* INJECT_STYLEX_HERE */
274
+ ```
227
275
 
228
- ```json
229
- {
230
- "compilerOptions": {
231
- "types": ["@stylexswc/unplugin/virtual-css"]
232
- }
233
- }
276
+ ```typescript
277
+ StylexRsPlugin({
278
+ useCssPlaceholder: '/* INJECT_STYLEX_HERE */',
279
+ useCSSLayers: true,
280
+ })
234
281
  ```
235
282
 
283
+ The plugin will replace the marker with the generated StyleX CSS during the build process.
284
+
236
285
  > [!NOTE]
237
- > When `useViteCssPipeline` is enabled, you need to explicitly import `virtual:stylex.css` in your application. The plugin will no longer inject CSS automatically into the HTML.
286
+ > When `useCssPlaceholder` is enabled, the plugin will no longer inject CSS automatically into HTML or emit a separate `stylex.css` file. The CSS is injected into your specified CSS file.
238
287
 
239
288
  > [!IMPORTANT]
240
- > **Reset CSS and Other Global Styles**
289
+ > **Migration from `useViteCssPipeline`**
241
290
  >
242
- > The `virtual:stylex.css` module should only contain StyleX-generated CSS. If you need to include reset CSS, global styles, or other non-StyleX CSS, import them from separate CSS files:
291
+ > The `useViteCssPipeline` option (which used virtual CSS modules) has been replaced with the `useCssPlaceholder` approach.
292
+ > The new approach uses real CSS files instead of virtual modules, which provides:
243
293
  >
244
- > ```typescript
245
- > // src/main.ts
246
- > import './reset.css'; // Your reset CSS
247
- > import './global.css'; // Other global styles
248
- > import 'virtual:stylex.css'; // StyleX-generated CSS
249
- > ```
294
+ > - Better compatibility across all bundlers
295
+ > - No race conditions or timing issues
296
+ > - Deterministic builds with stable hashes
250
297
  >
251
- > **Do not** put reset CSS or other styles inside the virtual module, as they should be managed separately from the StyleX-generated styles. See the examples in [`apps/vite-unplugin-virtual-css-example`](../../apps/vite-unplugin-virtual-css-example) and [`apps/vue-unplugin-virtual-css-example`](../../apps/vue-unplugin-virtual-css-example) for reference.
298
+ > To migrate, simply create a CSS file with a marker and set `useCssPlaceholder: true` (or use a custom marker string).
252
299
 
253
300
  ### Example Configuration
254
301
 
@@ -268,7 +315,7 @@ export default defineConfig({
268
315
  exclude: ['**/*.test.*', '**/*.stories.*', '**/__tests__/**'],
269
316
  },
270
317
  useCSSLayers: true,
271
- fileName: 'stylex.[hash].css',
318
+ useCssPlaceholder: true,
272
319
  }),
273
320
  ],
274
321
  });
@@ -343,29 +390,3 @@ StylexRsPlugin({
343
390
  },
344
391
  })
345
392
  ```
346
-
347
- **Exclude node_modules except specific packages:**
348
-
349
- ```typescript
350
- StylexRsPlugin({
351
- rsOptions: {
352
- // Exclude all node_modules except @stylexjs/open-props
353
- exclude: [/node_modules(?!\/@stylexjs\/open-props)/],
354
- },
355
- })
356
- ```
357
-
358
- **Transform only specific packages from node_modules:**
359
-
360
- ```typescript
361
- StylexRsPlugin({
362
- rsOptions: {
363
- include: [
364
- 'src/**/*.{ts,tsx}',
365
- 'node_modules/@stylexjs/open-props/**/*.js',
366
- 'node_modules/@my-org/design-system/**/*.js',
367
- ],
368
- exclude: ['**/*.test.*'],
369
- },
370
- })
371
- ```
package/dist/astro.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkUW5Q43ZTcjs = require('./chunk-UW5Q43ZT.cjs');
3
+ var _chunk3JYHFOPBcjs = require('./chunk-3JYHFOPB.cjs');
4
4
  require('./chunk-ZBPRDZS4.cjs');
5
5
 
6
6
  // src/astro.ts
@@ -10,7 +10,7 @@ var astro_default = (options) => ({
10
10
  "astro:config:setup": async (astro) => {
11
11
  var _a;
12
12
  (_a = astro.config.vite).plugins || (_a.plugins = []);
13
- astro.config.vite.plugins.push(_chunkUW5Q43ZTcjs.index_default.vite(options));
13
+ astro.config.vite.plugins.push(_chunk3JYHFOPBcjs.index_default.vite(options));
14
14
  }
15
15
  }
16
16
  });
package/dist/astro.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  index_default
3
- } from "./chunk-SKFER6F5.js";
3
+ } from "./chunk-UUQN4CTB.js";
4
4
  import "./chunk-6F4PWJZI.js";
5
5
 
6
6
  // src/astro.ts
@@ -1,6 +1,4 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -16,7 +14,6 @@ var __spreadValues = (a, b) => {
16
14
  }
17
15
  return a;
18
16
  };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
17
 
21
18
  // src/index.ts
22
19
  var _path = require('path'); var path = _interopRequireWildcard(_path);
@@ -36,16 +33,26 @@ function getStyleXRules(stylexRules, useCSSLayers) {
36
33
 
37
34
  // src/utils/normalizeOptions.ts
38
35
  var _rscompiler = require('@stylexswc/rs-compiler'); var _rscompiler2 = _interopRequireDefault(_rscompiler);
36
+ var DEFAULT_CSS_PLACEHOLDER = "@stylex;";
39
37
  function normalizeOptions(options) {
40
- var _a, _b, _c, _d, _e;
41
- return __spreadProps(__spreadValues({}, options), {
38
+ var _a, _b, _c, _d;
39
+ let useCssPlaceholder = false;
40
+ if (options.useCssPlaceholder === true) {
41
+ useCssPlaceholder = DEFAULT_CSS_PLACEHOLDER;
42
+ } else if (typeof options.useCssPlaceholder === "string") {
43
+ const useCssPlaceholderTrimmed = options.useCssPlaceholder.trim();
44
+ if (useCssPlaceholderTrimmed) {
45
+ useCssPlaceholder = useCssPlaceholderTrimmed;
46
+ }
47
+ }
48
+ return {
42
49
  fileName: (_a = options.fileName) != null ? _a : "stylex.css",
43
50
  useCSSLayers: (_b = options.useCSSLayers) != null ? _b : false,
44
51
  pageExtensions: (_c = options.pageExtensions) != null ? _c : ["tsx", "jsx", "js", "ts"],
45
52
  rsOptions: _rscompiler.normalizeRsOptions.call(void 0, options.rsOptions || {}),
46
53
  extractCSS: (_d = options.extractCSS) != null ? _d : true,
47
- useViteCssPipeline: (_e = options.useViteCssPipeline) != null ? _e : false
48
- });
54
+ useCssPlaceholder
55
+ };
49
56
  }
50
57
 
51
58
  // src/index.ts
@@ -60,12 +67,7 @@ function generateHash(content) {
60
67
  // src/index.ts
61
68
 
62
69
  var { writeFile, mkdir } = _fs.promises;
63
- var VIRTUAL_CSS_MODULE_ID = "virtual:stylex.css";
64
- var RESOLVED_VIRTUAL_CSS_MODULE_ID = "\0" + VIRTUAL_CSS_MODULE_ID;
65
- var VIRTUAL_CSS_MARKER_VAR = "--stylex-placeholder";
66
- var VIRTUAL_CSS_MARKER = `:root{${VIRTUAL_CSS_MARKER_VAR}:1}`;
67
- var viteDevServer = null;
68
- var hasInvalidatedInitialCSS = false;
70
+ var PLUGIN_NAME = "unplugin-stylex-rs";
69
71
  function replaceFileName(original, css) {
70
72
  if (!original.includes("[hash]")) {
71
73
  return original;
@@ -73,6 +75,45 @@ function replaceFileName(original, css) {
73
75
  const hash = _crypto2.default.createHash("sha256").update(css).digest("hex").slice(0, 8);
74
76
  return original.replace(/\[hash\]/g, hash);
75
77
  }
78
+ function pickCssAsset(cssAssets, chooseFn) {
79
+ if (cssAssets.length === 0) return null;
80
+ if (typeof chooseFn === "function") {
81
+ const chosen = cssAssets.find(chooseFn);
82
+ if (chosen) return chosen;
83
+ }
84
+ const preferred = cssAssets.find((f) => /(^|\/)index\.css$/.test(f)) || cssAssets.find((f) => /(^|\/)style\.css$/.test(f)) || cssAssets.find((f) => /(^|\/)main\.css$/.test(f));
85
+ return preferred || cssAssets[0] || null;
86
+ }
87
+ function injectStyleXCss(assets, injectMarker, collectedCSS, fallbackFileName, updateAsset, emitAsset, createRawSource) {
88
+ const cssAssets = Object.keys(assets).filter((f) => f.endsWith(".css"));
89
+ let injected = false;
90
+ for (const fileName of cssAssets) {
91
+ const asset = assets[fileName];
92
+ if (!asset) continue;
93
+ const source = asset.source().toString();
94
+ if (source.includes(injectMarker)) {
95
+ const newSource = source.replace(injectMarker, collectedCSS);
96
+ updateAsset(fileName, createRawSource(newSource));
97
+ injected = true;
98
+ break;
99
+ }
100
+ }
101
+ if (!injected && cssAssets.length > 0) {
102
+ const targetAsset = pickCssAsset(cssAssets);
103
+ if (targetAsset) {
104
+ const asset = assets[targetAsset];
105
+ if (asset) {
106
+ const existing = asset.source().toString();
107
+ const newSource = existing ? existing + "\n" + collectedCSS : collectedCSS;
108
+ updateAsset(targetAsset, createRawSource(newSource));
109
+ injected = true;
110
+ }
111
+ }
112
+ }
113
+ if (!injected) {
114
+ emitAsset(fallbackFileName, createRawSource(collectedCSS));
115
+ }
116
+ }
76
117
  var unpluginFactory = (options = {}) => {
77
118
  const normalizedOptions = normalizeOptions(options);
78
119
  const stylexRules = {};
@@ -81,7 +122,10 @@ var unpluginFactory = (options = {}) => {
81
122
  let cssFileName = null;
82
123
  let wsSend = void 0;
83
124
  return {
84
- name: "unplugin-stylex-rs",
125
+ name: PLUGIN_NAME,
126
+ buildStart() {
127
+ hasCssToExtract = false;
128
+ },
85
129
  transformInclude(id) {
86
130
  var _a, _b;
87
131
  const pageExtensions = normalizedOptions.pageExtensions;
@@ -130,36 +174,13 @@ var unpluginFactory = (options = {}) => {
130
174
  ]
131
175
  });
132
176
  }
133
- if (normalizedOptions.useViteCssPipeline && viteDevServer && !hasInvalidatedInitialCSS) {
134
- const hasStyleXCode2 = code !== inputCode;
135
- if (hasStyleXCode2) {
136
- hasInvalidatedInitialCSS = true;
137
- setTimeout(() => {
138
- const mod = viteDevServer == null ? void 0 : viteDevServer.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CSS_MODULE_ID);
139
- if (mod) {
140
- viteDevServer == null ? void 0 : viteDevServer.moduleGraph.invalidateModule(mod);
141
- viteDevServer == null ? void 0 : viteDevServer.ws.send({
142
- type: "update",
143
- updates: [
144
- {
145
- type: "js-update",
146
- acceptedPath: RESOLVED_VIRTUAL_CSS_MODULE_ID,
147
- path: RESOLVED_VIRTUAL_CSS_MODULE_ID,
148
- timestamp: Date.now()
149
- }
150
- ]
151
- });
152
- }
153
- }, 50);
154
- }
155
- }
156
177
  return {
157
178
  code,
158
179
  map,
159
180
  stylexRules
160
181
  };
161
182
  } catch (error) {
162
- console.error("Tansformation error:", error);
183
+ console.error("Transformation error:", error);
163
184
  this.error(error);
164
185
  }
165
186
  },
@@ -169,6 +190,9 @@ var unpluginFactory = (options = {}) => {
169
190
  if (framework === "esbuild") {
170
191
  return;
171
192
  }
193
+ if (normalizedOptions.useCssPlaceholder) {
194
+ return;
195
+ }
172
196
  const { processedFileName, collectedCSS } = generateCSSAssets(stylexRules, normalizedOptions);
173
197
  if (!collectedCSS) return;
174
198
  hasCssToExtract = true;
@@ -191,51 +215,46 @@ var unpluginFactory = (options = {}) => {
191
215
  config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
192
216
  config.optimizeDeps.exclude.push("@stylexjs/open-props");
193
217
  },
194
- resolveId(id) {
195
- if (id === VIRTUAL_CSS_MODULE_ID) {
196
- return RESOLVED_VIRTUAL_CSS_MODULE_ID;
197
- }
198
- },
199
- async load(id) {
200
- var _a;
201
- if (id === RESOLVED_VIRTUAL_CSS_MODULE_ID) {
202
- const isDev = (_a = this.meta) == null ? void 0 : _a.watchMode;
203
- if (isDev) {
204
- const collectedCSS = getStyleXRules(stylexRules, normalizedOptions.useCSSLayers);
205
- if (!collectedCSS || collectedCSS.trim().length === 0) {
206
- return {
207
- code: "/* StyleX styles will load after transformation */",
208
- map: null
209
- };
210
- }
211
- return {
212
- code: collectedCSS,
213
- map: null
214
- };
215
- }
216
- return {
217
- code: VIRTUAL_CSS_MARKER,
218
- map: null
219
- };
220
- }
221
- },
222
218
  generateBundle(_options, bundle) {
223
- if (!normalizedOptions.useViteCssPipeline) return;
219
+ if (!normalizedOptions.useCssPlaceholder) return;
224
220
  const collectedCSS = getStyleXRules(stylexRules, normalizedOptions.useCSSLayers);
225
221
  if (!collectedCSS) return;
222
+ const cssAssets = [];
226
223
  for (const [fileName, output] of Object.entries(bundle)) {
227
224
  if (output.type === "asset" && fileName.endsWith(".css")) {
228
- const source = output.source.toString();
229
- if (source.includes(VIRTUAL_CSS_MARKER)) {
230
- output.source = source.replace(VIRTUAL_CSS_MARKER, collectedCSS);
231
- break;
232
- }
225
+ cssAssets.push({ fileName, output });
233
226
  }
234
227
  }
228
+ let injected = false;
229
+ for (const { output } of cssAssets) {
230
+ if (output.type !== "asset") continue;
231
+ const source = output.source.toString();
232
+ if (normalizedOptions.useCssPlaceholder && source.includes(normalizedOptions.useCssPlaceholder)) {
233
+ output.source = source.replace(normalizedOptions.useCssPlaceholder, collectedCSS);
234
+ injected = true;
235
+ break;
236
+ }
237
+ }
238
+ if (!injected && cssAssets.length > 0) {
239
+ const targetName = pickCssAsset(cssAssets.map((a) => a.fileName));
240
+ const target = cssAssets.find((a) => a.fileName === targetName);
241
+ if (target && target.output.type === "asset") {
242
+ const existing = target.output.source.toString();
243
+ target.output.source = existing ? existing + "\n" + collectedCSS : collectedCSS;
244
+ injected = true;
245
+ }
246
+ }
247
+ if (!injected) {
248
+ this.emitFile({
249
+ type: "asset",
250
+ fileName: normalizedOptions.fileName,
251
+ source: collectedCSS
252
+ });
253
+ }
235
254
  },
236
255
  buildEnd() {
237
256
  var _a, _b;
238
- if (normalizedOptions.useViteCssPipeline) {
257
+ if (normalizedOptions.useCssPlaceholder) {
239
258
  return;
240
259
  }
241
260
  const isDev = (_a = this.meta) == null ? void 0 : _a.watchMode;
@@ -257,8 +276,6 @@ var unpluginFactory = (options = {}) => {
257
276
  }
258
277
  },
259
278
  configureServer(server) {
260
- viteDevServer = server;
261
- hasInvalidatedInitialCSS = false;
262
279
  server.middlewares.use((req, res, next) => {
263
280
  var _a;
264
281
  if (cssFileName && ((_a = req.url) == null ? void 0 : _a.includes(cssFileName))) {
@@ -270,16 +287,9 @@ var unpluginFactory = (options = {}) => {
270
287
  next();
271
288
  });
272
289
  },
273
- async handleHotUpdate({ file: id, file, server, read, modules }) {
290
+ async handleHotUpdate({ file: id, file, server, read }) {
274
291
  var _a;
275
292
  if (file.includes(".vue")) {
276
- if (normalizedOptions.useViteCssPipeline) {
277
- const virtualMod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CSS_MODULE_ID);
278
- if (virtualMod) {
279
- server.moduleGraph.invalidateModule(virtualMod);
280
- return [...modules, virtualMod];
281
- }
282
- }
283
293
  return;
284
294
  }
285
295
  const inputCode = await read();
@@ -293,32 +303,24 @@ var unpluginFactory = (options = {}) => {
293
303
  (_a = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _a.assetsDir
294
304
  );
295
305
  if (!collectedCSS) return;
296
- if (normalizedOptions.useViteCssPipeline) {
297
- const virtualMod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CSS_MODULE_ID);
298
- if (virtualMod) {
299
- server.moduleGraph.invalidateModule(virtualMod);
300
- return [...modules, virtualMod];
301
- }
302
- } else {
303
- if (processedFileName) {
304
- const normalizedFileName = ensureLeadingSlash(processedFileName);
305
- server.ws.send({
306
- type: "update",
307
- updates: [
308
- {
309
- acceptedPath: normalizedFileName,
310
- path: normalizedFileName,
311
- timestamp: Date.now(),
312
- type: "css-update"
313
- }
314
- ]
315
- });
316
- }
306
+ if (processedFileName) {
307
+ const normalizedFileName = ensureLeadingSlash(processedFileName);
308
+ server.ws.send({
309
+ type: "update",
310
+ updates: [
311
+ {
312
+ acceptedPath: normalizedFileName,
313
+ path: normalizedFileName,
314
+ timestamp: Date.now(),
315
+ type: "css-update"
316
+ }
317
+ ]
318
+ });
317
319
  }
318
320
  },
319
321
  transformIndexHtml: (html, ctx) => {
320
322
  var _a, _b;
321
- if (normalizedOptions.useViteCssPipeline) {
323
+ if (normalizedOptions.useCssPlaceholder) {
322
324
  return html;
323
325
  }
324
326
  const isDev = !!ctx.server;
@@ -349,11 +351,63 @@ var unpluginFactory = (options = {}) => {
349
351
  },
350
352
  esbuild: {
351
353
  setup(build) {
352
- build.onEnd(async ({ outputFiles }) => {
354
+ build.onEnd(async ({ outputFiles, metafile }) => {
353
355
  const fileName = normalizedOptions.fileName;
354
356
  const collectedCSS = getStyleXRules(stylexRules, normalizedOptions.useCSSLayers);
355
357
  if (!collectedCSS) return;
356
358
  const shouldWriteToDisk = build.initialOptions.write === void 0 || build.initialOptions.write;
359
+ const outDir = build.initialOptions.outdir || (build.initialOptions.outfile ? path.dirname(build.initialOptions.outfile) : null);
360
+ if (normalizedOptions.useCssPlaceholder && outDir && shouldWriteToDisk) {
361
+ const injectMarker = normalizedOptions.useCssPlaceholder;
362
+ let cssFiles = [];
363
+ if (metafile == null ? void 0 : metafile.outputs) {
364
+ cssFiles = Object.keys(metafile.outputs).filter((f) => f.endsWith(".css")).map((f) => path.isAbsolute(f) ? f : path.join(process.cwd(), f));
365
+ }
366
+ if (cssFiles.length === 0) {
367
+ try {
368
+ const { readdir } = await Promise.resolve().then(() => _interopRequireWildcard(require("fs/promises")));
369
+ const files = await readdir(outDir);
370
+ cssFiles = files.filter((f) => f.endsWith(".css")).map((f) => path.join(outDir, f));
371
+ } catch (e) {
372
+ }
373
+ }
374
+ let injected = false;
375
+ for (const cssFile of cssFiles) {
376
+ try {
377
+ const { readFile } = await Promise.resolve().then(() => _interopRequireWildcard(require("fs/promises")));
378
+ const content = await readFile(cssFile, "utf8");
379
+ if (content.includes(injectMarker)) {
380
+ const newContent = content.replace(injectMarker, collectedCSS);
381
+ await writeFile(cssFile, newContent, "utf8");
382
+ injected = true;
383
+ break;
384
+ }
385
+ } catch (e) {
386
+ }
387
+ }
388
+ if (!injected && cssFiles.length > 0) {
389
+ const targetFile = pickCssAsset(cssFiles.map((f) => path.basename(f)));
390
+ if (targetFile) {
391
+ const fullPath = cssFiles.find((f) => f.endsWith(targetFile));
392
+ if (fullPath) {
393
+ try {
394
+ const { readFile } = await Promise.resolve().then(() => _interopRequireWildcard(require("fs/promises")));
395
+ const existing = await readFile(fullPath, "utf8");
396
+ const newContent = existing ? existing + "\n" + collectedCSS : collectedCSS;
397
+ await writeFile(fullPath, newContent, "utf8");
398
+ injected = true;
399
+ } catch (e) {
400
+ }
401
+ }
402
+ }
403
+ }
404
+ if (!injected) {
405
+ const generatedCSSFileName = path.join(outDir, fileName);
406
+ await mkdir(path.dirname(generatedCSSFileName), { recursive: true });
407
+ await writeFile(generatedCSSFileName, collectedCSS, "utf8");
408
+ }
409
+ return;
410
+ }
357
411
  if (shouldWriteToDisk) {
358
412
  const generatedCSSFileName = path.join(process.cwd(), fileName);
359
413
  await mkdir(path.dirname(generatedCSSFileName), {
@@ -378,6 +432,9 @@ var unpluginFactory = (options = {}) => {
378
432
  farm: {
379
433
  transformHtml: {
380
434
  executor(resource) {
435
+ if (normalizedOptions.useCssPlaceholder) {
436
+ return Promise.resolve(resource.htmlResource);
437
+ }
381
438
  if (!hasCssToExtract) return Promise.resolve(resource.htmlResource);
382
439
  const htmlResource = resource.htmlResource;
383
440
  let htmlContent = Buffer.from(htmlResource.bytes).toString("utf-8");
@@ -386,6 +443,58 @@ var unpluginFactory = (options = {}) => {
386
443
  return Promise.resolve(resource.htmlResource);
387
444
  }
388
445
  }
446
+ // Farm uses Rollup-like bundle hooks, so generateBundle handles CSS injection
447
+ // The useCssPlaceholder logic is handled in the shared generateBundle (via Vite hooks)
448
+ },
449
+ rspack(compiler) {
450
+ if (!normalizedOptions.useCssPlaceholder) return;
451
+ const injectMarker = normalizedOptions.useCssPlaceholder;
452
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
453
+ compilation.hooks.processAssets.tap(
454
+ {
455
+ name: PLUGIN_NAME,
456
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
457
+ },
458
+ (assets) => {
459
+ const collectedCSS = getStyleXRules(stylexRules, normalizedOptions.useCSSLayers);
460
+ if (!collectedCSS) return;
461
+ injectStyleXCss(
462
+ assets,
463
+ injectMarker,
464
+ collectedCSS,
465
+ normalizedOptions.fileName,
466
+ (fileName, source) => compilation.updateAsset(fileName, source),
467
+ (fileName, source) => compilation.emitAsset(fileName, source),
468
+ (content) => new compiler.webpack.sources.RawSource(content)
469
+ );
470
+ }
471
+ );
472
+ });
473
+ },
474
+ webpack(compiler) {
475
+ if (!normalizedOptions.useCssPlaceholder) return;
476
+ const injectMarker = normalizedOptions.useCssPlaceholder;
477
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
478
+ compilation.hooks.processAssets.tap(
479
+ {
480
+ name: PLUGIN_NAME,
481
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
482
+ },
483
+ (assets) => {
484
+ const collectedCSS = getStyleXRules(stylexRules, normalizedOptions.useCSSLayers);
485
+ if (!collectedCSS) return;
486
+ injectStyleXCss(
487
+ assets,
488
+ injectMarker,
489
+ collectedCSS,
490
+ normalizedOptions.fileName,
491
+ (fileName, source) => compilation.updateAsset(fileName, source),
492
+ (fileName, source) => compilation.emitAsset(fileName, source),
493
+ (content) => new compiler.webpack.sources.RawSource(content)
494
+ );
495
+ }
496
+ );
497
+ });
389
498
  }
390
499
  };
391
500
  };
@@ -1,10 +1,10 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkUW5Q43ZTcjs = require('./chunk-UW5Q43ZT.cjs');
3
+ var _chunk3JYHFOPBcjs = require('./chunk-3JYHFOPB.cjs');
4
4
 
5
5
  // src/vite.ts
6
6
  var _unplugin = require('unplugin');
7
- var vite_default = _unplugin.createVitePlugin.call(void 0, _chunkUW5Q43ZTcjs.unpluginFactory);
7
+ var vite_default = _unplugin.createVitePlugin.call(void 0, _chunk3JYHFOPBcjs.unpluginFactory);
8
8
 
9
9
 
10
10