vite-plugin-taro 0.0.2 → 0.0.4

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 (42) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +205 -54
  3. package/dist/public/components.js +1 -1
  4. package/dist/public/taro.js +8 -10
  5. package/dist/shim/h5.js +5 -6
  6. package/dist/shim/wx.js +5 -5
  7. package/dist/vite/constants.js +3 -0
  8. package/dist/vite/plugins.js +186 -0
  9. package/dist/vite/tailwindcss.js +35 -0
  10. package/dist/vite/targets/h5.js +202 -0
  11. package/dist/vite/targets/wx.js +364 -0
  12. package/dist/vite/types.js +1 -0
  13. package/dist/vite/{utils.d.ts → utils.js} +13 -4
  14. package/dist/vite/vite-plugin-taro.js +80 -0
  15. package/dist/vite.js +1 -851
  16. package/package.json +23 -24
  17. package/src/public/components.ts +1 -0
  18. package/src/public/taro.ts +10 -0
  19. package/src/shim/h5.ts +6 -0
  20. package/src/shim/wx.ts +6 -0
  21. package/src/vite/constants.ts +5 -0
  22. package/src/vite/plugins.ts +218 -0
  23. package/src/vite/tailwindcss.ts +41 -0
  24. package/src/vite/targets/h5.ts +230 -0
  25. package/src/vite/targets/wx.ts +438 -0
  26. package/{dist/vite/types.d.ts → src/vite/types.ts} +31 -21
  27. package/src/vite/utils.ts +35 -0
  28. package/src/vite/vite-plugin-taro.ts +105 -0
  29. package/src/vite.ts +2 -0
  30. package/dist/public/components.d.ts +0 -1
  31. package/dist/public/taro.js.map +0 -1
  32. package/dist/shim/h5.d.ts +0 -3
  33. package/dist/shim/wx.d.ts +0 -3
  34. package/dist/vite/constants.d.ts +0 -2
  35. package/dist/vite/plugins.d.ts +0 -8
  36. package/dist/vite/tailwindcss.d.ts +0 -3
  37. package/dist/vite/targets/h5.d.ts +0 -31
  38. package/dist/vite/targets/wx.d.ts +0 -74
  39. package/dist/vite/taro.d.ts +0 -7
  40. package/dist/vite.d.ts +0 -2
  41. package/dist/vite.js.map +0 -1
  42. /package/{dist → src}/public/taro.d.ts +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 felix
3
+ Copyright (c) 2026 sep2
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,60 +1,196 @@
1
1
  # vite-plugin-taro
2
2
 
3
- Vite 8 + React 19 plugin for building one React/Taro codebase for both:
3
+ [![npm version](https://img.shields.io/npm/v/vite-plugin-taro.svg)](https://www.npmjs.com/package/vite-plugin-taro)
4
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
5
 
5
- - `wx`: WeChat Mini Program output.
6
- - `h5`: Web output powered by Taro H5 runtime and router.
6
+ Vite 8 plugin for building one React 19 + Taro 4 app as either Web (`h5`) or WeChat Mini Program (`wx`).
7
7
 
8
- It wraps React 19-compatible Taro runtime packages, emits the generated app/page entries that Taro normally creates, and configures Vite/Rolldown, Tailwind CSS, and target-specific aliases for the selected target.
8
+ ## Highlights
9
+
10
+ - Builds the same React/Taro pages for `h5` and `wx` targets.
11
+ - Uses React 19-compatible Taro React packages published by this monorepo.
12
+ - Generates Taro-style app/page entries instead of requiring generated files in your app source.
13
+ - Emits WeChat Mini Program assets: `app.json`, page JSON, WXML, WXS, WXSS, and CommonJS chunks.
14
+ - Boots H5 with Taro's official router/runtime and component CSS.
15
+ - Handles Tailwind CSS v4 for H5 and transforms Tailwind output for WeChat Mini Programs.
16
+ - Strips inactive Taro-style conditional compilation blocks before Vite parses code.
17
+ - Provides app-facing facades for Taro APIs and components.
18
+
19
+ ## Compatibility
20
+
21
+ | Dependency | Supported version |
22
+ | --- | --- |
23
+ | Node.js | `^20.19.0` or `>=22.12.0` |
24
+ | Vite | `^8.0.0` |
25
+ | React / React DOM | `^19.0.0` |
26
+ | Taro runtime packages | `4.2.0` |
27
+ | Tailwind CSS | `4.x` |
9
28
 
10
29
  ## Install
11
30
 
12
31
  ```sh
13
- pnpm add -D vite-plugin-taro vite
32
+ pnpm add -D vite vite-plugin-taro
14
33
  pnpm add react react-dom
15
34
  ```
16
35
 
17
- ## Vite usage
36
+ ## Package exports
37
+
38
+ | Import | Use |
39
+ | --- | --- |
40
+ | `vite-plugin-taro/vite` | Recommended Vite plugin entry. Exports the default plugin plus option/target types. |
41
+ | `vite-plugin-taro` | Same plugin entry as `vite-plugin-taro/vite`. |
42
+ | `vite-plugin-taro/components` | Re-export of Taro React components. Use this in application code. |
43
+ | `vite-plugin-taro/taro` | Taro API facade. Use this instead of importing `@tarojs/taro` directly. |
44
+ | `vite-plugin-taro/shim/h5` | Internal H5 runtime shim used by generated entries. |
45
+ | `vite-plugin-taro/shim/wx` | Internal WeChat runtime shim used by generated entries. |
46
+
47
+ Application code should normally use only `vite-plugin-taro/components` and `vite-plugin-taro/taro`.
48
+
49
+ ## Minimal setup
50
+
51
+ ### Vite config
18
52
 
19
53
  ```ts
20
- import taro, { type TaroTarget } from 'vite-plugin-taro/vite'
21
54
  import { defineConfig, loadEnv } from 'vite'
55
+ import vitePluginTaro, { type VitePluginTaroTarget } from 'vite-plugin-taro/vite'
56
+
57
+ function getTarget(value: string | undefined): VitePluginTaroTarget {
58
+ if (value === 'h5' || value === 'wx') return value
59
+ throw new Error('VITE_PLUGIN_TARO_TARGET must be "h5" or "wx".')
60
+ }
22
61
 
23
62
  export default defineConfig(({ mode }) => {
24
63
  const env = loadEnv(mode, process.cwd(), 'VITE_PLUGIN_TARO_')
25
- const target = env.VITE_PLUGIN_TARO_TARGET as TaroTarget
64
+ const target = getTarget(env.VITE_PLUGIN_TARO_TARGET)
26
65
 
27
66
  return {
67
+ base: target === 'h5' ? './' : undefined,
68
+ build: {
69
+ outDir: `dist/${target}`
70
+ },
28
71
  plugins: [
29
- taro({
72
+ vitePluginTaro({
30
73
  target,
31
74
  app: 'src/app.ts',
32
- pages: [{ path: 'pages/index/index', config: {} }],
75
+ pages: [
76
+ {
77
+ path: 'pages/index/index',
78
+ config: {
79
+ navigationBarTitleText: 'Home'
80
+ }
81
+ }
82
+ ],
33
83
  appJson: {},
34
- projectConfigJson: { appid: 'touristappid' },
35
- sitemapJson: { rules: [{ action: 'allow', page: '*' }] }
84
+ projectConfigJson: {
85
+ appid: env.VITE_PLUGIN_TARO_WECHAT_APP_ID || 'touristappid'
86
+ },
87
+ sitemapJson: {
88
+ rules: [{ action: 'allow', page: '*' }]
89
+ }
36
90
  })
37
91
  ]
38
92
  }
39
93
  })
40
94
  ```
41
95
 
42
- Application code should usually import only `vite-plugin-taro/components` and `vite-plugin-taro/taro`.
96
+ ### App component
43
97
 
44
- ## Package exports
98
+ `app` points to a module that default-exports the root React app component.
99
+
100
+ ```tsx
101
+ // src/app.ts
102
+ import type { PropsWithChildren } from 'react'
103
+ import Taro from 'vite-plugin-taro/taro'
104
+ import './app.css'
105
+
106
+ export default function App({ children }: PropsWithChildren) {
107
+ Taro.useLaunch(() => {
108
+ console.log('App launch')
109
+ })
110
+
111
+ return children
112
+ }
113
+ ```
114
+
115
+ ### Page component
116
+
117
+ Each `pages[].path` maps to `src/${path}.tsx`.
118
+
119
+ ```tsx
120
+ // src/pages/index/index.tsx
121
+ import { Text, View } from 'vite-plugin-taro/components'
122
+ import Taro from 'vite-plugin-taro/taro'
123
+
124
+ export default function IndexPage() {
125
+ const windowInfo = Taro.getWindowInfo()
126
+
127
+ return (
128
+ <View>
129
+ <Text>Viewport width: {windowInfo.windowWidth}</Text>
130
+ </View>
131
+ )
132
+ }
133
+ ```
134
+
135
+ ### HTML shell for H5
136
+
137
+ For H5 builds, keep a normal Vite `index.html`. The plugin injects the generated Taro H5 entry automatically.
138
+
139
+ ```html
140
+ <div id="app"></div>
141
+ ```
45
142
 
46
- | Import | Purpose |
143
+ ## Plugin options
144
+
145
+ ```ts
146
+ type VitePluginTaroTarget = 'wx' | 'h5'
147
+
148
+ type VitePluginTaroPageOption = {
149
+ path: string
150
+ config: Record<string, unknown>
151
+ }
152
+
153
+ type VitePluginTaroOptions = {
154
+ target: VitePluginTaroTarget
155
+ app: string
156
+ pages: VitePluginTaroPageOption[]
157
+ appJson: Record<string, unknown>
158
+ projectConfigJson: Record<string, unknown>
159
+ sitemapJson: Record<string, unknown>
160
+ }
161
+ ```
162
+
163
+ | Option | Description |
47
164
  | --- | --- |
48
- | `vite-plugin-taro` | Default Vite plugin and public plugin types. |
49
- | `vite-plugin-taro/vite` | Default Vite plugin and `TaroTarget`, `TaroPluginOptions`, `TaroPageOption` types. |
50
- | `vite-plugin-taro/components` | Re-export of `@tarojs/components`. Use this in app code. |
51
- | `vite-plugin-taro/taro` | Taro API facade. Use this instead of importing `@tarojs/taro` directly. |
52
- | `vite-plugin-taro/shim/h5` | H5 runtime shim used by generated entries. |
53
- | `vite-plugin-taro/shim/wx` | WeChat runtime shim used by generated entries. |
165
+ | `target` | Active target for this Vite invocation: `h5` or `wx`. |
166
+ | `app` | Source file that default-exports the root React app component. |
167
+ | `pages` | Ordered page list. The order becomes `app.json.pages` and the H5 route order. |
168
+ | `pages[].path` | Taro-style route and output path without extension, for example `pages/index/index`. The page component must exist at `src/${path}.tsx`. |
169
+ | `pages[].config` | Page JSON config merged into WeChat page JSON and H5 route config. |
170
+ | `appJson` | Base app config. The plugin overwrites `pages` from `options.pages`. |
171
+ | `projectConfigJson` | WeChat `project.config.json` content emitted for `wx` builds. |
172
+ | `sitemapJson` | WeChat `sitemap.json` content emitted for `wx` builds. |
173
+
174
+ ## Scripts in your app
175
+
176
+ Use separate scripts or environment files to build each target.
177
+
178
+ ```json
179
+ {
180
+ "scripts": {
181
+ "dev:h5": "VITE_PLUGIN_TARO_TARGET=h5 vite",
182
+ "build:h5": "VITE_PLUGIN_TARO_TARGET=h5 vite build",
183
+ "dev:wx": "VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
184
+ "build:wx": "VITE_PLUGIN_TARO_TARGET=wx vite build"
185
+ }
186
+ }
187
+ ```
188
+
189
+ On Windows shells, use `cross-env` or your package manager's environment-file support.
54
190
 
55
191
  ## Conditional compilation
56
192
 
57
- vite-plugin-taro strips inactive Taro-style conditional comment blocks before Vite parses source files. Supported files include TypeScript, JavaScript, JSX/TSX, CSS, Sass, Less, and Stylus.
193
+ The plugin strips inactive Taro-style conditional comment blocks before Vite parses source files. Supported source types include TypeScript, JavaScript, JSX/TSX, CSS, Sass, Less, and Stylus.
58
194
 
59
195
  ```ts
60
196
  // #ifdef wx
@@ -74,52 +210,67 @@ console.log('fallback')
74
210
  // #endif
75
211
  ```
76
212
 
77
- Supported directives are `#ifdef`, `#ifndef`, `#if`, `#elif`, `#else`, and `#endif`. Expressions support simple target tokens with `!`, `&&`, and `||`.
78
-
79
- ## Target output
213
+ Supported directives are `#ifdef`, `#ifndef`, `#if`, `#elif`, `#else`, and `#endif`. Expressions support target tokens with `!`, `&&`, and `||`.
80
214
 
81
- ### `wx`
215
+ ## Styling
82
216
 
83
- vite-plugin-taro configures Rolldown for WeChat-compatible CommonJS chunks and emits Mini Program assets including:
217
+ - H5 builds use `@tailwindcss/vite`.
218
+ - WeChat builds use `weapp-tailwindcss` with Tailwind CSS v4 support, `px`/`rem` to `rpx` conversion, and WeChat-compatible selector output.
219
+ - CSS emitted by Vite for `wx` is collected into `app.wxss`; page-level `.wxss` files are emitted as companions.
220
+ - Import global styles from the app component, for example `import './app.css'`.
84
221
 
85
- - `app.js`, `app.json`, `app.wxss`.
86
- - Page `*.js`, `*.json`, `*.wxml`, and `*.wxss` files.
87
- - Shared Taro recursive template assets: `base.wxml`, `comp.js`, `comp.json`, `comp.wxml`, `utils.wxs`.
88
- - `project.config.json` and `sitemap.json`.
222
+ ## Target outputs
89
223
 
90
224
  ### `h5`
91
225
 
92
- vite-plugin-taro injects a virtual module into `index.html`, creates Taro H5 route records from `pages`, and mounts the app with Taro's hash-history router.
93
-
94
- ## React 19 compatibility
226
+ The plugin injects a virtual module into `index.html`, imports Taro's component styles, creates H5 route records from `pages`, mounts the root app, and uses Taro's hash-history router.
95
227
 
96
- Taro 4.2's official React runtime targets React 18. vite-plugin-taro depends on two small React 19-compatible runtime packages generated from the official Taro npm tarballs plus vite-plugin-taro's local patch files:
228
+ Typical output directory:
97
229
 
98
- - `vite-plugin-taro-react`
99
- - `vite-plugin-taro-plugin-framework-react`
230
+ ```text
231
+ dist/h5/
232
+ ```
100
233
 
101
- In the workspace these are referenced with pnpm workspace aliases:
234
+ ### `wx`
102
235
 
103
- ```json
104
- {
105
- "@tarojs/react": "workspace:vite-plugin-taro-react@*",
106
- "@tarojs/plugin-framework-react": "workspace:vite-plugin-taro-plugin-framework-react@*"
107
- }
236
+ The plugin configures Rolldown for WeChat-compatible CommonJS chunks and emits Mini Program companion files.
237
+
238
+ Typical output directory:
239
+
240
+ ```text
241
+ dist/wx/
242
+ ├── app.js
243
+ ├── app.json
244
+ ├── app.wxss
245
+ ├── base.wxml
246
+ ├── comp.js
247
+ ├── comp.json
248
+ ├── comp.wxml
249
+ ├── project.config.json
250
+ ├── sitemap.json
251
+ ├── utils.wxs
252
+ └── pages/**
108
253
  ```
109
254
 
110
- When packed/published by pnpm, those become npm aliases to the published patched packages. vite-plugin-taro source can keep importing the upstream Taro specifiers while users receive the patched React 19-compatible packages automatically.
255
+ Open the `wx` output directory with WeChat DevTools.
111
256
 
112
- Run `pnpm prepare:taro` to regenerate the patched packages from upstream tarballs. Publish those runtime packages before publishing `vite-plugin-taro`.
257
+ ## Limitations
113
258
 
114
- ## Publishing
259
+ - Supported targets are currently `h5` and WeChat Mini Program (`wx`). Other Taro platforms are not generated by this plugin.
260
+ - Page modules follow the fixed convention `src/${page.path}.tsx`.
261
+ - `projectConfigJson` and `sitemapJson` are required by the option type even though they are only emitted for `wx` builds.
262
+ - Import Taro APIs/components through `vite-plugin-taro/taro` and `vite-plugin-taro/components`; direct `@tarojs/*` imports can bypass target aliases.
115
263
 
116
- ```sh
117
- pnpm install
118
- pnpm publish:dry
119
- pnpm publish:all
264
+ ## Troubleshooting
120
265
 
121
- # If npm 2FA is enabled:
122
- pnpm publish:all -- --otp 123456
123
- ```
266
+ | Problem | Check |
267
+ | --- | --- |
268
+ | `VITE_PLUGIN_TARO_TARGET must be "h5" or "wx"` | Set the target environment variable before running Vite. |
269
+ | A page cannot be resolved | Confirm that `pages[].path` has a matching `src/${path}.tsx` file. |
270
+ | H5 component styles load in the wrong order | Make sure the plugin is registered and `vite-plugin-taro/components` is used for components. |
271
+ | WeChat DevTools cannot open the project | Check `projectConfigJson.appid` and open the generated `dist/wx` directory, not the source package. |
272
+ | Taro APIs behave differently per target | Import from `vite-plugin-taro/taro` so the plugin can apply target-specific runtime aliases and H5 API transforms. |
273
+
274
+ ## License
124
275
 
125
- The package publishes built ESM JavaScript and `.d.ts` files from `dist`.
276
+ MIT. See [`LICENSE`](LICENSE).
@@ -1 +1 @@
1
- export * from "@tarojs/components";
1
+ export * from '@tarojs/components';
@@ -1,10 +1,8 @@
1
- import { hooks } from "@tarojs/runtime";
2
- import Taro from "@tarojs/taro";
3
- export * from "@tarojs/taro";
4
- //#region src/public/taro.ts
5
- if (hooks.isExist("initNativeApi")) hooks.call("initNativeApi", Taro);
6
- var taro_default = Taro;
7
- //#endregion
8
- export { taro_default as default };
9
-
10
- //# sourceMappingURL=taro.js.map
1
+ import { hooks } from '@tarojs/runtime';
2
+ import Taro from '@tarojs/taro';
3
+ if (hooks.isExist('initNativeApi')) {
4
+ hooks.call('initNativeApi', Taro);
5
+ }
6
+ // @ts-expect-error @tarojs/taro declares export= types, but vite-plugin-taro target aliases expose runtime named exports.
7
+ export * from '@tarojs/taro';
8
+ export default Taro;
package/dist/shim/h5.js CHANGED
@@ -1,6 +1,5 @@
1
- import { window } from "@tarojs/runtime";
2
- import "@tarojs/plugin-platform-h5/dist/runtime";
3
- import "@tarojs/components/global.css";
4
- import { createReactApp } from "@tarojs/plugin-framework-react/dist/runtime";
5
- import { createBrowserHistory, createHashHistory, createRouter, handleAppMount } from "@tarojs/router";
6
- export { createBrowserHistory, createHashHistory, createReactApp, createRouter, handleAppMount, window };
1
+ import '@tarojs/plugin-platform-h5/dist/runtime';
2
+ // @ts-expect-error Taro exposes createReactApp from this runtime-only deep entry without types.
3
+ export { createReactApp } from '@tarojs/plugin-framework-react/dist/runtime';
4
+ export { createBrowserHistory, createHashHistory, createRouter, handleAppMount } from '@tarojs/router';
5
+ export { window } from '@tarojs/runtime';
package/dist/shim/wx.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createPageConfig, createRecursiveComponentConfig } from "@tarojs/runtime";
2
- import { createReactApp } from "@tarojs/plugin-framework-react/dist/runtime";
3
- import "@tarojs/plugin-platform-weapp/dist/runtime.js";
4
- import ReactDOM from "@tarojs/react";
5
- export { ReactDOM, createPageConfig, createReactApp, createRecursiveComponentConfig };
1
+ import '@tarojs/plugin-platform-weapp/dist/runtime.js';
2
+ // @ts-expect-error Taro exposes createReactApp from this runtime-only deep entry without types.
3
+ export { createReactApp } from '@tarojs/plugin-framework-react/dist/runtime';
4
+ export { default as ReactDOM } from '@tarojs/react';
5
+ export { createPageConfig, createRecursiveComponentConfig } from '@tarojs/runtime';
@@ -0,0 +1,3 @@
1
+ import { createRequire } from 'node:module';
2
+ export const isProd = process.env.NODE_ENV === 'production';
3
+ export const nodeRequire = createRequire(import.meta.url);
@@ -0,0 +1,186 @@
1
+ import { normalizeModuleId } from './utils.js';
2
+ /**
3
+ * Applies Taro-style conditional compilation comments before Vite parses source files.
4
+ *
5
+ * Mirrors Taro's CSS #ifdef/#ifndef handling, generalized before Vite parses code.
6
+ */
7
+ export function createVitePluginTaroConditionalDirectivePlugin(context) {
8
+ const target = context.target;
9
+ return {
10
+ name: 'vite-plugin-taro-conditional-directives',
11
+ enforce: 'pre',
12
+ transform(code, id) {
13
+ if (!isConditionalDirectiveSource(id) || !code.includes('#if'))
14
+ return;
15
+ return { code: transformConditionalDirectives(code, target), map: null };
16
+ }
17
+ };
18
+ }
19
+ /**
20
+ * Filters files where Taro's conditional comments are meaningful.
21
+ *
22
+ * Plugin-only: source filter for generalized conditional-directive transform.
23
+ */
24
+ function isConditionalDirectiveSource(id) {
25
+ const normalizedId = normalizeModuleId(id);
26
+ if (normalizedId.includes('/node_modules/'))
27
+ return false;
28
+ return /\.(?:[cm]?[jt]sx?|css|s[ac]ss|less|styl)(?:\?|$)/.test(normalizedId);
29
+ }
30
+ /**
31
+ * Removes inactive blocks guarded by Taro conditional comments.
32
+ *
33
+ * Mirrors Taro's CSS #ifdef/#ifndef handling.
34
+ */
35
+ function transformConditionalDirectives(code, target) {
36
+ const lines = code.match(/[^\n]*(?:\n|$)/g) ?? [];
37
+ const frames = [];
38
+ let transformed = '';
39
+ for (const line of lines) {
40
+ if (!line)
41
+ continue;
42
+ const directive = parseConditionalDirective(line);
43
+ const lineEnding = getLineEnding(line);
44
+ if (directive) {
45
+ updateConditionalDirectiveFrames(frames, directive, target);
46
+ transformed += lineEnding;
47
+ continue;
48
+ }
49
+ transformed += isDirectiveStackActive(frames) ? line : lineEnding;
50
+ }
51
+ return transformed;
52
+ }
53
+ /**
54
+ * Parses one Taro conditional compilation directive from a comment-only line.
55
+ *
56
+ * Mirrors Taro's CSS comment-token handling.
57
+ */
58
+ function parseConditionalDirective(line) {
59
+ const match = line.match(/^\s*(?:(?:\/\/)|(?:\/\*))\s*#(ifdef|ifndef|if|elif|else|endif)\b([^*\r\n]*)/);
60
+ if (!match)
61
+ return;
62
+ const name = toConditionalDirectiveName(match[1]);
63
+ if (!name)
64
+ return;
65
+ return {
66
+ name,
67
+ expression: match[2]?.replace(/\*\/$/, '').trim() ?? ''
68
+ };
69
+ }
70
+ /**
71
+ * Converts a regex capture into a supported directive name.
72
+ *
73
+ * Mirrors Taro's CSS #ifdef/#ifndef/#endif token handling.
74
+ */
75
+ function toConditionalDirectiveName(value) {
76
+ if (value === 'ifdef' ||
77
+ value === 'ifndef' ||
78
+ value === 'if' ||
79
+ value === 'elif' ||
80
+ value === 'else' ||
81
+ value === 'endif') {
82
+ return value;
83
+ }
84
+ }
85
+ /**
86
+ * Updates the active conditional stack using Taro-style #ifdef/#ifndef/#else/#endif semantics.
87
+ *
88
+ * Plugin-only: stack-based #if/#elif/#else support has no Taro webpack counterpart.
89
+ */
90
+ function updateConditionalDirectiveFrames(frames, directive, target) {
91
+ if (directive.name === 'ifdef' || directive.name === 'ifndef' || directive.name === 'if') {
92
+ const conditionMatched = evaluateConditionalDirective(directive, target);
93
+ const parentActive = isDirectiveStackActive(frames);
94
+ frames.push({ parentActive, active: parentActive && conditionMatched, matched: conditionMatched });
95
+ return;
96
+ }
97
+ const currentFrame = frames.at(-1);
98
+ if (!currentFrame)
99
+ return;
100
+ if (directive.name === 'elif') {
101
+ if (currentFrame.matched) {
102
+ currentFrame.active = false;
103
+ return;
104
+ }
105
+ const conditionMatched = evaluateConditionalDirective(directive, target);
106
+ currentFrame.active = currentFrame.parentActive && conditionMatched;
107
+ currentFrame.matched = conditionMatched;
108
+ return;
109
+ }
110
+ if (directive.name === 'else') {
111
+ currentFrame.active = currentFrame.parentActive && !currentFrame.matched;
112
+ currentFrame.matched = true;
113
+ return;
114
+ }
115
+ if (directive.name === 'endif')
116
+ frames.pop();
117
+ }
118
+ /**
119
+ * Evaluates the small expression subset used by Taro conditional comments.
120
+ *
121
+ * Mirrors Taro's simple CSS platform membership checks.
122
+ */
123
+ function evaluateConditionalDirective(directive, target) {
124
+ if (directive.name === 'ifndef')
125
+ return !matchesDirectiveTarget(directive.expression, target);
126
+ if (directive.name === 'ifdef')
127
+ return matchesDirectiveTarget(directive.expression, target);
128
+ return evaluateConditionalExpression(directive.expression, target);
129
+ }
130
+ /**
131
+ * Supports simple #if expressions with !, &&, and || over the configured target token.
132
+ *
133
+ * Plugin-only: #if expressions with && and || have no Taro webpack counterpart.
134
+ */
135
+ function evaluateConditionalExpression(expression, target) {
136
+ const orTerms = expression.split('||');
137
+ return orTerms.some((term) => term
138
+ .split('&&')
139
+ .map((factor) => factor.trim())
140
+ .filter(Boolean)
141
+ .every((factor) => evaluateConditionalFactor(factor, target)));
142
+ }
143
+ /**
144
+ * Evaluates one target token, optionally negated.
145
+ *
146
+ * Plugin-only: negated #if factors have no Taro webpack counterpart.
147
+ */
148
+ function evaluateConditionalFactor(factor, target) {
149
+ let token = factor.replace(/[()]/g, '').trim();
150
+ let negated = false;
151
+ while (token.startsWith('!')) {
152
+ negated = !negated;
153
+ token = token.slice(1).trim();
154
+ }
155
+ const matched = matchesDirectiveTarget(token, target);
156
+ return negated ? !matched : matched;
157
+ }
158
+ /**
159
+ * Checks whether a directive target list includes the current target.
160
+ *
161
+ * Mirrors Taro's simple CSS platform membership checks.
162
+ */
163
+ function matchesDirectiveTarget(expression, target) {
164
+ const tokens = expression
165
+ .split(/[\s,|&()!]+/)
166
+ .map((token) => token.trim().toLowerCase())
167
+ .filter(Boolean);
168
+ return tokens.includes(target);
169
+ }
170
+ /**
171
+ * Preserves source line counts when conditional blocks are stripped.
172
+ *
173
+ * Plugin-only: preserves Vite source-map line counts while stripping conditional blocks.
174
+ */
175
+ function getLineEnding(line) {
176
+ const match = line.match(/\r?\n$/);
177
+ return match?.[0] ?? '';
178
+ }
179
+ /**
180
+ * Returns whether all active nested conditional frames include the current line.
181
+ *
182
+ * Plugin-only: stack activity helper for generalized conditional directives.
183
+ */
184
+ function isDirectiveStackActive(frames) {
185
+ return frames.every((frame) => frame.active);
186
+ }
@@ -0,0 +1,35 @@
1
+ import tailwindcss from '@tailwindcss/vite';
2
+ import { WeappTailwindcss } from 'weapp-tailwindcss/vite';
3
+ export function createTailwindcssPlugins(context) {
4
+ if (context.target === 'h5')
5
+ return [tailwindcss()];
6
+ const plugins = WeappTailwindcss({
7
+ appType: 'taro',
8
+ generator: {
9
+ target: 'weapp'
10
+ },
11
+ tailwindcss: {
12
+ version: 4,
13
+ packageName: 'tailwindcss'
14
+ },
15
+ cssCalc: false,
16
+ // skyline does not support -webkit prefix.
17
+ autoprefixer: false,
18
+ postcssOptions: {
19
+ // Tailwind v4 prod mode emits legacy :before/:after selectors; skyline requires ::before/::after.
20
+ plugins: [createWechatPseudoElementPlugin()]
21
+ },
22
+ rem2rpx: true,
23
+ px2rpx: true
24
+ });
25
+ return plugins ?? [];
26
+ }
27
+ function createWechatPseudoElementPlugin() {
28
+ const legacyPseudoElementPattern = /(?<!:):(before|after)\b/g;
29
+ return {
30
+ postcssPlugin: 'vite-plugin-taro-wechat-pseudo-elements',
31
+ Rule(rule) {
32
+ rule.selector = rule.selector.replace(legacyPseudoElementPattern, '::$1');
33
+ }
34
+ };
35
+ }