vite-plugin-taro 0.6.3 → 0.6.6

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.
Files changed (29) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +3 -3
  3. package/dist/node/plugins/wx/dev/dev-host.d.ts +5 -4
  4. package/dist/node/plugins/wx/dev/dev-host.js +19 -43
  5. package/dist/node/plugins/wx/dev/plugins.d.ts +4 -3
  6. package/dist/node/plugins/wx/dev/plugins.js +4 -4
  7. package/dist/node/plugins/wx/dev/wx-dev-options.d.ts +2 -3
  8. package/dist/node/plugins/wx/dev/wx-dev-options.js +4 -4
  9. package/dist/node/plugins/wx/plugins.js +5 -11
  10. package/dist/node/plugins/wx/styles/plugins.d.ts +141 -3
  11. package/dist/node/plugins/wx/styles/plugins.js +401 -89
  12. package/dist/node/utils/vite.d.ts +4 -14
  13. package/dist/node/utils/vite.js +7 -40
  14. package/package.json +4 -3
  15. package/src/node/plugins/wx/dev/dev-host.ts +22 -44
  16. package/src/node/plugins/wx/dev/plugins.ts +5 -4
  17. package/src/node/plugins/wx/dev/wx-dev-options.ts +5 -7
  18. package/src/node/plugins/wx/plugins.ts +5 -11
  19. package/src/node/plugins/wx/styles/plugins.ts +518 -93
  20. package/src/node/utils/vite.ts +13 -58
  21. package/dist/node/plugins/wx/dev/create-style-capture.d.ts +0 -54
  22. package/dist/node/plugins/wx/dev/create-style-capture.js +0 -173
  23. package/dist/node/plugins/wx/styles/transform-wx-style.d.ts +0 -8
  24. package/dist/node/plugins/wx/styles/transform-wx-style.js +0 -9
  25. package/dist/node/plugins/wx/styles/utils.d.ts +0 -39
  26. package/dist/node/plugins/wx/styles/utils.js +0 -95
  27. package/src/node/plugins/wx/dev/create-style-capture.ts +0 -248
  28. package/src/node/plugins/wx/styles/transform-wx-style.ts +0 -11
  29. package/src/node/plugins/wx/styles/utils.ts +0 -119
package/README.en.md CHANGED
@@ -1,4 +1,4 @@
1
- # vite-plugin-taro
1
+ # VPT
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/vite-plugin-taro.svg)](https://www.npmjs.com/package/vite-plugin-taro)
4
4
  ![Vite](https://img.shields.io/npm/dependency-version/vite-plugin-taro/peer/vite?label=Vite)
@@ -20,7 +20,7 @@ Continue with the [Quick Start guide](https://vpt.js.org/guides/quick-start/).
20
20
 
21
21
  ### React Hot Reload in WeChat DevTools
22
22
 
23
- <video src="https://github.com/user-attachments/assets/cb93daf5-1827-496a-bb74-8397975accf6" controls autoplay muted loop playsinline width="100%"></video>
23
+ <video src="https://github.com/user-attachments/assets/c8289e1e-d8ad-429f-a0d9-a40656b4962a" controls autoplay muted loop playsinline width="100%"></video>
24
24
 
25
25
  - **Vite 8 + React 19** Build one codebase for WeChat Mini Program and Web with the Vite ecosystem.
26
26
  - **Hot reload** Preserve App data, the active page, React component state, and input state while editing.
@@ -39,7 +39,7 @@ Continue with the [Quick Start guide](https://vpt.js.org/guides/quick-start/).
39
39
  - [Configuration options](https://vpt.js.org/guides/configuration/)
40
40
  - [Conditional compilation](https://vpt.js.org/guides/conditional-directives/)
41
41
  - [Skyline mode](https://vpt.js.org/guides/skyline-mode/)
42
- - [Migrate from Taro CLI](https://vpt.js.org/guides/migrate-from-taro/)
42
+ - [Migrate from Taro](https://vpt.js.org/guides/migrate-from-taro/)
43
43
  - [Module system](https://vpt.js.org/references/module-system/)
44
44
  - [Hot module replacement internals](https://vpt.js.org/references/hmr-implementation/)
45
45
  - [Repository management](https://vpt.js.org/references/repository-management/)
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # vite-plugin-taro
1
+ # VPT
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/vite-plugin-taro.svg)](https://www.npmjs.com/package/vite-plugin-taro)
4
4
  ![Vite](https://img.shields.io/npm/dependency-version/vite-plugin-taro/peer/vite?label=Vite)
@@ -21,7 +21,7 @@ npm create vite-taro@latest my-app
21
21
 
22
22
  ### 已支持微信开发者工具的 React 热更新
23
23
 
24
- <video src="https://github.com/user-attachments/assets/cb93daf5-1827-496a-bb74-8397975accf6" controls autoplay muted loop playsinline width="100%"></video>
24
+ <video src="https://github.com/user-attachments/assets/c8289e1e-d8ad-429f-a0d9-a40656b4962a" controls autoplay muted loop playsinline width="100%"></video>
25
25
 
26
26
  - **Vite 8 + React 19** 基于 Vite 生态,一份代码覆盖微信小程序与 Web。
27
27
  - **热更新** 编辑代码时保留 App 数据、当前页面、React 组件状态与输入状态。
@@ -40,7 +40,7 @@ npm create vite-taro@latest my-app
40
40
  - [配置选项](https://vpt.js.org/guides/configuration/)
41
41
  - [条件编译](https://vpt.js.org/guides/conditional-directives/)
42
42
  - [Skyline 模式](https://vpt.js.org/guides/skyline-mode/)
43
- - [从 Taro CLI 迁移](https://vpt.js.org/guides/migrate-from-taro/)
43
+ - [从 Taro 迁移](https://vpt.js.org/guides/migrate-from-taro/)
44
44
  - [模块系统](https://vpt.js.org/references/module-system/)
45
45
  - [热更新原理](https://vpt.js.org/references/hmr-implementation/)
46
46
  - [仓库维护](https://vpt.js.org/references/repository-management/)
@@ -1,5 +1,6 @@
1
1
  import type { ViteDevServer } from 'vite';
2
2
  import type { VptOptions } from '../../../../options.ts';
3
+ import type { WxStylePlugin } from '../styles/plugins.ts';
3
4
  export type WxDevHost = Readonly<{
4
5
  close: () => Promise<void>;
5
6
  }>;
@@ -9,11 +10,11 @@ export type WxDevHost = Readonly<{
9
10
  * engine writes directly to the Mini Program output directory instead of serving browser
10
11
  * HMR over HTTP.
11
12
  *
12
- * `applicationEntryIds` is the resolver's immutable cascade policy, not a second graph: it selects the App capsule followed
13
- * by configured Page capsules from Rolldown's larger entry set. Rolldown remains the authority for every live import edge.
13
+ * The shared style plugin carries the resolver's immutable App/Page cascade policy while Rolldown remains authoritative for
14
+ * every live import edge.
14
15
  */
15
- export declare function createWxDevHost({ server, options, applicationEntryIds }: {
16
+ export declare function createWxDevHost({ server, options, styles }: {
16
17
  server: ViteDevServer;
17
18
  options: VptOptions;
18
- applicationEntryIds: readonly string[];
19
+ styles: WxStylePlugin;
19
20
  }): Promise<WxDevHost>;
@@ -1,11 +1,9 @@
1
- import { readFile } from 'node:fs/promises';
2
1
  import path from 'node:path';
3
2
  import colors from 'picocolors';
4
3
  import { dev } from 'rolldown/experimental';
5
4
  import { asyncScheduler } from 'rxjs';
6
5
  import { createHmrResultsStream } from './create-hmr-results-stream.js';
7
- import { createStyleCapture } from './create-style-capture.js';
8
- import { developmentAppWxssFileName, hmrControlPath, hmrInfoFileName, hmrPatchesFileName, renderDevelopmentAppWxss, renderHmrInfo, renderInitialHmrPatches, writeHmrFile } from './hmr-files.js';
6
+ import { developmentAppWxssFileName, globalWxssFileName, hmrControlPath, hmrInfoFileName, hmrPatchesFileName, renderDevelopmentAppWxss, renderHmrInfo, renderInitialHmrPatches, writeHmrFile } from './hmr-files.js';
9
7
  import { createHostActions } from './host-actions.js';
10
8
  import { PatchPublisher } from './patch-publisher.js';
11
9
  import { createRuntimeReportsStream } from './runtime-reports.js';
@@ -18,27 +16,16 @@ const hmrSettleMilliseconds = 16;
18
16
  * engine writes directly to the Mini Program output directory instead of serving browser
19
17
  * HMR over HTTP.
20
18
  *
21
- * `applicationEntryIds` is the resolver's immutable cascade policy, not a second graph: it selects the App capsule followed
22
- * by configured Page capsules from Rolldown's larger entry set. Rolldown remains the authority for every live import edge.
19
+ * The shared style plugin carries the resolver's immutable App/Page cascade policy while Rolldown remains authoritative for
20
+ * every live import edge.
23
21
  */
24
- export async function createWxDevHost({ server, options, applicationEntryIds }) {
22
+ export async function createWxDevHost({ server, options, styles }) {
25
23
  const bundledDev = getBundledDev(server);
26
24
  // All callbacks admit typed actions through this edge; concatMap is the sole owner of effect ordering and mutable host state.
27
25
  const hostActions = createHostActions(applyHostAction, (action, error) => logWxError(server.config.logger, `wx HMR ${action.kind} failed`, error));
28
- const styleCapture = createStyleCapture({
29
- applicationEntryIds: applicationEntryIds,
30
- outDir: server.config.build.outDir,
31
- // Capture hooks run only after engine.run, when the host action subscription and all reducer dependencies are ready.
32
- emit: (action) => hostActions.next(action),
33
- transformTailwindRoot: async (rootId, requestId) => {
34
- // The capture contains generated CSS, while the sidecar must re-run from raw Tailwind directives. Vite exposes no
35
- // raw source in its live module graph, so this read is the authoritative source generation rather than a read-back.
36
- return server.environments.client.pluginContainer.transform(await readFile(rootId, 'utf8'), requestId);
37
- }
38
- });
39
26
  const publisher = new PatchPublisher((content) => writeHmrFile(server.config.build.outDir, hmrPatchesFileName, content));
40
27
  // Option installation now configures only Rolldown. Build lifecycle results enter through the engine's output action below.
41
- installWxDevOptions({ bundledDev, server, options, hostPlugins: [styleCapture.plugin] });
28
+ installWxDevOptions({ bundledDev, server, options });
42
29
  const engine = await createEngine();
43
30
  const hmrResults = createHmrResultsStream(hmrSettleMilliseconds, asyncScheduler, (result) => {
44
31
  // One reduced window becomes one existing host transaction: style preparation, one cumulative patch write, then
@@ -98,11 +85,15 @@ export async function createWxDevHost({ server, options, applicationEntryIds })
98
85
  hmrResults.complete();
99
86
  runtimeReports.complete();
100
87
  await hostActions.waitForIdle();
101
- // Keep the action edge open until the final generation has admitted all capture and output callbacks.
88
+ // Keep the action edge open until the final generation has admitted every output callback.
102
89
  await engine.ensureCurrentBuildFinish();
103
90
  await hostActions.complete();
104
91
  }
105
92
  };
93
+ /** Atomically materializes the style plugin's prepared global artifact. */
94
+ async function writeGlobalStyle(wxss) {
95
+ await writeHmrFile(server.config.build.outDir, globalWxssFileName, wxss);
96
+ }
106
97
  /** Rotates the build identity and materializes the App metadata for it. */
107
98
  async function rotateBuildSession() {
108
99
  const port = boundPort(server);
@@ -142,14 +133,6 @@ export async function createWxDevHost({ server, options, applicationEntryIds })
142
133
  /** Reduces one merged source action through the existing authoritative host state. */
143
134
  function applyHostAction(action) {
144
135
  switch (action.kind) {
145
- case 'capture-graph':
146
- // The buildStart reader is a live capability; replacing it only here makes the reducer own build rebinding.
147
- styleCapture.captureGraph(action.getModuleInfo);
148
- return;
149
- case 'capture-style':
150
- // A failed upstream transform emits no action, intentionally retaining the last valid processed CSS generation.
151
- styleCapture.captureStyle(action.id, action.style);
152
- return;
153
136
  case 'publish':
154
137
  return publishUpdates(action.result);
155
138
  case 'error':
@@ -163,20 +146,14 @@ export async function createWxDevHost({ server, options, applicationEntryIds })
163
146
  logWxError(server.config.logger, 'wx dev build failed', action.result);
164
147
  return;
165
148
  }
166
- return reconcileCompleteOutput(action.result.output);
149
+ return publishCompleteStyles();
167
150
  case 'listening':
168
151
  return rotateBuildSession();
169
152
  }
170
153
  }
171
- /**
172
- * Reconciles graph-complete styles before rotating the App-visible build identity.
173
- *
174
- * DevEngine has already written its compiler asset when onOutput fires, but bundled development may have omitted CSS Modules
175
- * from that asset. Awaiting reconciliation inside the serialized reducer guarantees the subsequent app.wxss rotation—the
176
- * event that refreshes DevTools—can only expose a generation whose global WXSS already represents the complete App/Page graph.
177
- */
178
- async function reconcileCompleteOutput(output) {
179
- await styleCapture.reconcileComplete(output);
154
+ /** Publishes graph-complete styles before rotating the App-visible build identity. */
155
+ async function publishCompleteStyles() {
156
+ await styles.finalizeUpdate([], writeGlobalStyle);
180
157
  await rotateBuildSession();
181
158
  }
182
159
  /** Applies one runtime receipt to the active physical patch history. */
@@ -252,16 +229,15 @@ export async function createWxDevHost({ server, options, applicationEntryIds })
252
229
  if (patches.length === 0) {
253
230
  return;
254
231
  }
255
- // `onHmrUpdates` is the transaction boundary after every affected transform has updated graph and candidate state.
256
- // Every non-CSS edit may alter imports or Tailwind classes; rendering broadly and comparing finalized bytes avoids
257
- // source scanning while preventing unrelated JavaScript edits from notifying DevTools through an identical rename.
258
- await styleCapture.publishChanged(patches.flatMap((patch) => patch.changedIds));
232
+ // `onHmrUpdates` runs after every affected transform has updated captured CSS and the live import graph. The style
233
+ // boundary finalizes every factory before atomically publishing their matching WXSS.
234
+ const finalizedPatches = await styles.finalizeUpdate(patches, writeGlobalStyle);
259
235
  // Publish global.wxss before the matching JavaScript patch so DevTools observes a coherent HMR transaction.
260
236
  // The physical file must exist before Rolldown advances: once committed, later patches may be generated relative to
261
237
  // this batch even if DevTools has not observed its file event yet. PatchPublisher keeps the unapplied range cumulative,
262
238
  // so any later file generation still carries every factory needed to bridge the runtime's older application frontier.
263
- await publisher.produce(patches);
264
- await commitPublishedBatch(patches);
239
+ await publisher.produce(finalizedPatches);
240
+ await commitPublishedBatch(finalizedPatches);
265
241
  }
266
242
  /**
267
243
  * Advances Rolldown's published frontier in the same sequence order materialized in the cumulative physical file.
@@ -1,5 +1,6 @@
1
1
  import { type PluginOption } from 'vite';
2
2
  import type { VptOptions } from '../../../../options.ts';
3
+ import type { WxStylePlugin } from '../styles/plugins.ts';
3
4
  /** Selects the sole Vite environment that owns the physical Mini Program development project. */
4
5
  export declare function isWxClientEnvironment(environment: Readonly<{
5
6
  name: string;
@@ -8,10 +9,10 @@ export declare function isWxClientEnvironment(environment: Readonly<{
8
9
  * Adds the serve-only bundled-development plugin set for the wx target: the dev adapter,
9
10
  * Page HMR activation, and React Refresh adaptation transforms.
10
11
  *
11
- * The ordered application entries cross this configuration boundary unchanged so the host can compose global CSS without
12
- * reconstructing the resolver's App/Page ownership policy from unrelated Rolldown shell and transport entries.
12
+ * The shared style pipeline already owns the resolver's ordered App/Page cascade policy, so the host does not reconstruct it
13
+ * from unrelated Rolldown shell and transport entries.
13
14
  */
14
- export declare function createWxDevelopmentPlugin(options: VptOptions, applicationEntryIds: readonly string[]): PluginOption[];
15
+ export declare function createWxDevelopmentPlugin(options: VptOptions, styles: WxStylePlugin): PluginOption[];
15
16
  /**
16
17
  * Transfers development ownership of `app.wxss` from complete output to the dev host.
17
18
  *
@@ -14,10 +14,10 @@ export function isWxClientEnvironment(environment) {
14
14
  * Adds the serve-only bundled-development plugin set for the wx target: the dev adapter,
15
15
  * Page HMR activation, and React Refresh adaptation transforms.
16
16
  *
17
- * The ordered application entries cross this configuration boundary unchanged so the host can compose global CSS without
18
- * reconstructing the resolver's App/Page ownership policy from unrelated Rolldown shell and transport entries.
17
+ * The shared style pipeline already owns the resolver's ordered App/Page cascade policy, so the host does not reconstruct it
18
+ * from unrelated Rolldown shell and transport entries.
19
19
  */
20
- export function createWxDevelopmentPlugin(options, applicationEntryIds) {
20
+ export function createWxDevelopmentPlugin(options, styles) {
21
21
  /*
22
22
  * Vite creates this plugin descriptor before a server or DevEngine exists, then invokes configureServer and closeBundle on
23
23
  * different lifecycle stacks. This mutable handle transfers the one client-owned host between those hooks: configureServer
@@ -65,7 +65,7 @@ export function createWxDevelopmentPlugin(options, applicationEntryIds) {
65
65
  host = await createWxDevHost({
66
66
  server: server,
67
67
  options: options,
68
- applicationEntryIds: applicationEntryIds
68
+ styles: styles
69
69
  });
70
70
  }
71
71
  },
@@ -1,4 +1,4 @@
1
- import type { InputOptions, OutputOptions, Plugin } from 'rolldown';
1
+ import type { InputOptions, OutputOptions } from 'rolldown';
2
2
  import { type DevEngine } from 'rolldown/experimental';
3
3
  import type { ViteDevServer } from 'vite';
4
4
  import type { VptOptions } from '../../../../options.ts';
@@ -19,11 +19,10 @@ export type BundledDev = {
19
19
  * Installs physical WX output and runtime conventions over Vite's browser-oriented bundled-development options.
20
20
  * Build completion deliberately remains outside this options adapter: DevEngine onOutput is the single lifecycle authority.
21
21
  */
22
- export declare function installWxDevOptions({ bundledDev, server, options, hostPlugins }: {
22
+ export declare function installWxDevOptions({ bundledDev, server, options }: {
23
23
  bundledDev: BundledDev;
24
24
  server: ViteDevServer;
25
25
  options: VptOptions;
26
- hostPlugins: Plugin[];
27
26
  }): void;
28
27
  /** Returns the configured output after rejecting states unsupported by the physical WX engine. */
29
28
  export declare function requireSingleOutput(rolldownOptions: BundledDevRolldownOptions): OutputOptions;
@@ -8,7 +8,7 @@ import { appShellFileName } from '../module/module.js';
8
8
  * Installs physical WX output and runtime conventions over Vite's browser-oriented bundled-development options.
9
9
  * Build completion deliberately remains outside this options adapter: DevEngine onOutput is the single lifecycle authority.
10
10
  */
11
- export function installWxDevOptions({ bundledDev, server, options, hostPlugins }) {
11
+ export function installWxDevOptions({ bundledDev, server, options }) {
12
12
  /*
13
13
  * Vite owns this mutable adapter method and calls it later when constructing DevEngine. Replacing that one seam preserves
14
14
  * Vite's resolved graph while applying WX physical-output conventions to every options generation. Capturing and mutating one
@@ -78,10 +78,10 @@ export function installWxDevOptions({ bundledDev, server, options, hostPlugins }
78
78
  };
79
79
  /*
80
80
  * The plugin list is mutable configuration consumed once by this engine generation. Replace the top-level reference with
81
- * an ordered composite rather than pushing into Vite's potentially shared nested array: existing transforms run first,
82
- * host capture observes their final values, and the reporter observes final output without mutating either input list.
81
+ * an ordered composite rather than pushing into Vite's potentially shared nested array; the reporter observes final output
82
+ * without mutating Vite's retained input list.
83
83
  */
84
- rolldownOptions.plugins = [rolldownOptions.plugins, hostPlugins, createViteReporter(server)];
84
+ rolldownOptions.plugins = [rolldownOptions.plugins, createViteReporter(server)];
85
85
  disableViteOxcSourcemap(rolldownOptions.plugins);
86
86
  return rolldownOptions;
87
87
  };
@@ -10,19 +10,15 @@ import { renderCapsule } from './render/capsule.js';
10
10
  import { renderNative } from './render/native.js';
11
11
  import { materializeTransport } from './render/transport.js';
12
12
  import { createResolver } from './resolve/resolver.js';
13
- import { createWxStylePlugins } from './styles/plugins.js';
13
+ import { createWxStylePlugin } from './styles/plugins.js';
14
14
  /** Creates the complete plugin set for the wx target. */
15
15
  export function createWxTargetPlugins(options) {
16
16
  const resolver = createResolver(options);
17
17
  // Reuse the resolver instance's ordered application subset. Rolldown's complete input also contains bootstrap, transport,
18
18
  // shell, and component entries; entry membership alone cannot recover which roots define the App/Page CSS cascade.
19
19
  const placement = createWxPlacementPlugin();
20
- return [
21
- placement,
22
- createWxStylePlugins(),
23
- createWxPlugin(options, resolver, placement),
24
- createWxDevelopmentPlugin(options, resolver.applicationEntryIds)
25
- ];
20
+ const styles = createWxStylePlugin(resolver.applicationEntryIds);
21
+ return [placement, styles, createWxPlugin(options, resolver, placement), createWxDevelopmentPlugin(options, styles)];
26
22
  }
27
23
  /** Configures the complete wx target build pipeline. */
28
24
  function createWxPlugin(options, resolver, placement) {
@@ -106,10 +102,8 @@ function createWxPlugin(options, resolver, placement) {
106
102
  },
107
103
  generateBundle: {
108
104
  /*
109
- * This hook is registered after createWxStylePlugins() and shares hook-level `order: 'post'` with the adapted
110
- * upstream hooks and VPT style finalizer. Registration order therefore guarantees that the imported global
111
- * stylesheet is complete before native Page/component companions are emitted. Without this order, the finalizer
112
- * could consume incomplete Tailwind output or mistake native WXSS companions for additional compiler styles.
105
+ * Registration after the style pipeline makes the compiler stylesheet final before native Page and component
106
+ * companions are emitted. The style finalizer therefore cannot mistake native WXSS for application CSS.
113
107
  */
114
108
  order: 'post',
115
109
  async handler(_, bundle) {
@@ -1,3 +1,141 @@
1
- import type { PluginOption } from 'vite';
2
- /** Creates the complete WX Tailwind and global-style pipeline. */
3
- export declare function createWxStylePlugins(): PluginOption[];
1
+ import { type Plugin } from 'vite';
2
+ import { createContext } from 'weapp-tailwindcss/core';
3
+ /** JavaScript code plus the physical filename required by the Weapp JavaScript transformer. */
4
+ type JavaScriptArtifact = Readonly<{
5
+ code: string;
6
+ filename: string;
7
+ }>;
8
+ /** Vite plugin with the development-host operation that finalizes one coherent WX style/JavaScript transaction. */
9
+ export type WxStylePlugin = Plugin & Readonly<{
10
+ /** Converts patch factories and publishes their matching global WXSS through the host's atomic writer. */
11
+ finalizeUpdate: <Artifact extends JavaScriptArtifact>(artifacts: readonly Artifact[], writeWxss: (wxss: string) => Promise<void>) => Promise<readonly Artifact[]>;
12
+ }>;
13
+ /**
14
+ * Creates the single owner of global WX style compilation, graph projection, JavaScript class rewriting, and publication.
15
+ *
16
+ * ## Architectural invariant
17
+ *
18
+ * A WX transaction must expose JavaScript and WXSS produced from one class-identity snapshot. Tailwind utility names can be
19
+ * rewritten for WeChat—for example, `py-5.5` becomes `py-5_d5`—so publishing either side independently can leave running code
20
+ * referring to selectors that do not yet exist. This plugin therefore treats reachable CSS, Tailwind candidates, converted
21
+ * WXSS, and converted JavaScript as one output. Complete builds and HMR updates both call `finalizeOutput()`; they differ only
22
+ * in how the returned bytes are materialized.
23
+ *
24
+ * ## Ownership boundaries
25
+ *
26
+ * The pipeline deliberately gives each subsystem one responsibility:
27
+ *
28
+ * 1. Rolldown owns module reachability and invalidation. VPT reads `getModuleInfo()` and registers watch files, but does not
29
+ * maintain a second import graph or decide independently which root should rerun.
30
+ * 2. The persistent Tailwind generator owns candidate discovery and incremental candidate removal. VPT invokes it only from
31
+ * the owning CSS root's Rolldown transform and never rescans the project during output publication.
32
+ * 3. Vite owns preprocessors, PostCSS, CSS Modules, and final module CSS semantics. VPT observes the input to the resolved
33
+ * `vite:css-post` hook only after the original hook succeeds; it never rereads source files or repeats CSS preprocessing.
34
+ * 4. The Weapp transformation context owns WX selector conversion and JavaScript class-string conversion. One retained context
35
+ * and one projected candidate set drive both operations.
36
+ * 5. VPT owns physical global WXSS and patch publication. Vite's browser CSS asset is only an intermediate carrier and is
37
+ * removed before VPT emits `assets/global.wxss`.
38
+ *
39
+ * Native Page and component WXSS are outside this global pipeline. The WX output plugin is registered after this style plugin
40
+ * and emits those opaque companions later. The WX configuration also enforces `cssCodeSplit: false`, so Vite contributes at
41
+ * most one browser compiler stylesheet for this plugin to replace.
42
+ *
43
+ * ## Compilation phases
44
+ *
45
+ * ### 1. Tailwind pre-transform
46
+ *
47
+ * The pre-transform checks physical application CSS for Tailwind imports or directives. Ordinary styles pass through. A
48
+ * Tailwind root compiles to browser CSS before Vite's normal CSS pipeline runs. Successful generation records the generator,
49
+ * scanner, current class set, compiler dependencies, and exact root source under the normalized physical module ID.
50
+ *
51
+ * Candidate files and compiler dependencies intentionally have different invalidation behavior:
52
+ *
53
+ * - Candidate-file changes rerun the root with the existing generator and scanner. `incrementalCache: true` updates additions
54
+ * and removals without discarding the generator's authoritative cache.
55
+ * - Compiler-dependency changes mark the root invalid. Its next Rolldown transform resolves a new Tailwind source and creates a
56
+ * new generator and scanner. Replacement is delayed until that transform has current source and plugin context.
57
+ * - If a stylesheet stops being a Tailwind root, its generator is disposed and its Tailwind state is removed. The later Vite
58
+ * CSS hook replaces the retained CSS after normal processing succeeds.
59
+ *
60
+ * ### 2. Vite-final CSS capture
61
+ *
62
+ * `configResolved` wraps the concrete `vite:css-post` transform while preserving its hook metadata, filter, ordering, and
63
+ * plugin context. The original Vite hook executes first, which preserves CSS Module exports and Vite's internal extraction
64
+ * state. Only a successful transform updates `styleByModuleId`; syntax errors therefore leave the last successful CSS available
65
+ * to the currently running application. Query modes such as `?raw`, `?url`, and `?inline` are excluded because they represent
66
+ * values rather than graph-owned stylesheets.
67
+ *
68
+ * ### 3. Live-graph projection
69
+ *
70
+ * Output finalization starts from resolved App/Page entry IDs and traverses Rolldown's current static and dynamic import edges
71
+ * in dependency-first post-order. Transaction-local visited sets terminate cycles and deduplicate shared modules and physical
72
+ * stylesheets. A retained stylesheet contributes only when its module is still reachable, so removing an import prunes its CSS
73
+ * and Tailwind candidates without a separate prune protocol or persistent topology cache. Candidate sets are unioned only from
74
+ * the Tailwind roots whose captured CSS survives that exact traversal, preserving the CSS/class identity invariant.
75
+ *
76
+ * ### 4. Shared WX finalization
77
+ *
78
+ * `finalizeOutput()` first converts the concatenated reachable CSS to WXSS, then transforms every supplied JavaScript artifact
79
+ * with the same projected class set. It returns data and performs no bundle mutation or filesystem publication. If either
80
+ * transformation fails, the promise rejects before callers expose partial output. JavaScript conversion is skipped when the
81
+ * projection contains no Tailwind candidates, preserving ordinary bundle bytes.
82
+ *
83
+ * ### 5a. Complete-build commit
84
+ *
85
+ * The post-order `generateBundle` hook gathers all JavaScript chunks, finalizes them as one operation, and only then mutates the
86
+ * bundle. It assigns converted code, clears invalid source maps, removes Vite's intermediate browser stylesheet, and always
87
+ * emits `assets/global.wxss`. Emitting an empty global file is required because `app.wxss` imports it even when the application
88
+ * currently has no styles. Native output hooks run afterward and emit Page/component companion files independently.
89
+ *
90
+ * ### 5b. Development commit
91
+ *
92
+ * The development host calls `finalizeUpdate()` after Rolldown produces patch factories or a complete-output notification.
93
+ * Finalization uses the `PluginContext` captured by `buildStart`, so it observes the same current graph as the compiler. After
94
+ * all conversion succeeds, the host's atomic writer publishes changed WXSS before `finalizeUpdate()` returns converted patch
95
+ * factories. The patch publisher therefore cannot expose newer JavaScript class identities before matching selectors exist.
96
+ * `publishedWxss` advances only after a successful write and suppresses byte-identical writes that would otherwise trigger
97
+ * unnecessary WeChat DevTools reload events.
98
+ *
99
+ * ## Retained state and lifecycle
100
+ *
101
+ * The factory retains four explicit mutable state owners plus one library-owned transformation context:
102
+ *
103
+ * - `entryIds`: graph-exact App/Page entry identities resolved at the start of each build;
104
+ * - `graphContext`: the active Rolldown graph reader needed by host calls made outside plugin hooks;
105
+ * - `styleByModuleId`: the latest successful Vite CSS plus optional Tailwind state at one normalized module identity;
106
+ * - `publishedWxss`: the last durably published development stylesheet used for unchanged-write suppression;
107
+ * - `weappContext`: Weapp's internal conversion state, retained so selector and JavaScript rewriting share one context.
108
+ *
109
+ * The state owners remain scoped to one plugin instance; `entryIds` is atomically replaced after each complete resolution.
110
+ * Build-command bundles dispose Tailwind generators after bundle generation. A development watcher otherwise keeps them alive
111
+ * across updates and disposes them when it closes. Captured CSS survives compiler cleanup because output notifications can
112
+ * arrive after that cleanup, and is cleared only when the watcher terminates.
113
+ *
114
+ * ## Cost model
115
+ *
116
+ * Projection is `O(V + E + B + C)` for reachable modules, import edges, concatenated CSS bytes, and candidate insertions.
117
+ * JavaScript conversion is linear in the total supplied chunk or patch-factory bytes, subject to the Weapp parser's own cost.
118
+ * Retained memory is `O(B + C + D + F)` for latest CSS, candidate sets, compiler dependencies, and scanner file identities; no
119
+ * second application graph is retained. Tailwind's generator and Oxide scanner caches are intentionally persistent because
120
+ * recreating them on every candidate edit would repeat source normalization and scanning work.
121
+ */
122
+ export declare function createWxStylePlugin(applicationEntryIds: readonly string[]): WxStylePlugin;
123
+ /**
124
+ * Produces WXSS and JavaScript from one live-graph projection.
125
+ *
126
+ * The function receives every stateful dependency explicitly so tests and both output modes execute the same algorithm. It
127
+ * completes WXSS conversion before JavaScript conversion and returns bytes without publishing or mutating caller artifacts.
128
+ */
129
+ export declare function finalizeOutput(entryIds: readonly string[], styleByModuleId: ReadonlyMap<string, Readonly<{
130
+ css: string | undefined;
131
+ tailwind: Readonly<{
132
+ classSet: ReadonlySet<string>;
133
+ }> | undefined;
134
+ }>>, getModuleInfo: (moduleId: string) => Readonly<{
135
+ importedIds: readonly string[];
136
+ dynamicallyImportedIds: readonly string[];
137
+ }> | null | undefined, weappContext: Pick<ReturnType<typeof createContext>, 'transformJs' | 'transformWxss'>, javaScript: readonly JavaScriptArtifact[]): Promise<{
138
+ javaScript: string[];
139
+ wxss: string;
140
+ }>;
141
+ export {};