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.
- package/LICENSE +1 -1
- package/README.md +205 -54
- package/dist/public/components.js +1 -1
- package/dist/public/taro.js +8 -10
- package/dist/shim/h5.js +5 -6
- package/dist/shim/wx.js +5 -5
- package/dist/vite/constants.js +3 -0
- package/dist/vite/plugins.js +186 -0
- package/dist/vite/tailwindcss.js +35 -0
- package/dist/vite/targets/h5.js +202 -0
- package/dist/vite/targets/wx.js +364 -0
- package/dist/vite/types.js +1 -0
- package/dist/vite/{utils.d.ts → utils.js} +13 -4
- package/dist/vite/vite-plugin-taro.js +80 -0
- package/dist/vite.js +1 -851
- package/package.json +23 -24
- package/src/public/components.ts +1 -0
- package/src/public/taro.ts +10 -0
- package/src/shim/h5.ts +6 -0
- package/src/shim/wx.ts +6 -0
- package/src/vite/constants.ts +5 -0
- package/src/vite/plugins.ts +218 -0
- package/src/vite/tailwindcss.ts +41 -0
- package/src/vite/targets/h5.ts +230 -0
- package/src/vite/targets/wx.ts +438 -0
- package/{dist/vite/types.d.ts → src/vite/types.ts} +31 -21
- package/src/vite/utils.ts +35 -0
- package/src/vite/vite-plugin-taro.ts +105 -0
- package/src/vite.ts +2 -0
- package/dist/public/components.d.ts +0 -1
- package/dist/public/taro.js.map +0 -1
- package/dist/shim/h5.d.ts +0 -3
- package/dist/shim/wx.d.ts +0 -3
- package/dist/vite/constants.d.ts +0 -2
- package/dist/vite/plugins.d.ts +0 -8
- package/dist/vite/tailwindcss.d.ts +0 -3
- package/dist/vite/targets/h5.d.ts +0 -31
- package/dist/vite/targets/wx.d.ts +0 -74
- package/dist/vite/taro.d.ts +0 -7
- package/dist/vite.d.ts +0 -2
- package/dist/vite.js.map +0 -1
- /package/{dist → src}/public/taro.d.ts +0 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,60 +1,196 @@
|
|
|
1
1
|
# vite-plugin-taro
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/vite-plugin-taro)
|
|
4
|
+
[](LICENSE)
|
|
4
5
|
|
|
5
|
-
|
|
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
|
-
|
|
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
|
|
32
|
+
pnpm add -D vite vite-plugin-taro
|
|
14
33
|
pnpm add react react-dom
|
|
15
34
|
```
|
|
16
35
|
|
|
17
|
-
##
|
|
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
|
|
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
|
-
|
|
72
|
+
vitePluginTaro({
|
|
30
73
|
target,
|
|
31
74
|
app: 'src/app.ts',
|
|
32
|
-
pages: [
|
|
75
|
+
pages: [
|
|
76
|
+
{
|
|
77
|
+
path: 'pages/index/index',
|
|
78
|
+
config: {
|
|
79
|
+
navigationBarTitleText: 'Home'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
],
|
|
33
83
|
appJson: {},
|
|
34
|
-
projectConfigJson: {
|
|
35
|
-
|
|
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
|
-
|
|
96
|
+
### App component
|
|
43
97
|
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
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
|
-
|
|
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
|
|
78
|
-
|
|
79
|
-
## Target output
|
|
213
|
+
Supported directives are `#ifdef`, `#ifndef`, `#if`, `#elif`, `#else`, and `#endif`. Expressions support target tokens with `!`, `&&`, and `||`.
|
|
80
214
|
|
|
81
|
-
|
|
215
|
+
## Styling
|
|
82
216
|
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
228
|
+
Typical output directory:
|
|
97
229
|
|
|
98
|
-
|
|
99
|
-
|
|
230
|
+
```text
|
|
231
|
+
dist/h5/
|
|
232
|
+
```
|
|
100
233
|
|
|
101
|
-
|
|
234
|
+
### `wx`
|
|
102
235
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
255
|
+
Open the `wx` output directory with WeChat DevTools.
|
|
111
256
|
|
|
112
|
-
|
|
257
|
+
## Limitations
|
|
113
258
|
|
|
114
|
-
|
|
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
|
-
|
|
117
|
-
pnpm install
|
|
118
|
-
pnpm publish:dry
|
|
119
|
-
pnpm publish:all
|
|
264
|
+
## Troubleshooting
|
|
120
265
|
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
276
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from '@tarojs/components';
|
package/dist/public/taro.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { hooks } from
|
|
2
|
-
import Taro from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export {
|
|
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,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
|
+
}
|