@unocss/vite 0.16.3 → 0.18.0
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 +360 -1
- package/dist/index.cjs +95 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +95 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -2,5 +2,364 @@
|
|
|
2
2
|
|
|
3
3
|
The Vite plugin for UnoCSS. Ships with the `unocss` package.
|
|
4
4
|
|
|
5
|
-
> This plugin does not come with any default presets. You are
|
|
5
|
+
> This plugin does not come with any default presets. You are building a meta framework on top of UnoCSS, see [this file](https://github.com/antfu/unocss/blob/main/packages/unocss/src/vite.ts) for an example to bind the default presets.
|
|
6
6
|
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -D unocss
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// vite.config.ts
|
|
15
|
+
import Unocss from 'unocss/vite'
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
plugins: [
|
|
19
|
+
Unocss({ /* options */ })
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Add `uno.css` to your main entry:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// main.ts
|
|
28
|
+
import 'uno.css'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Modes
|
|
32
|
+
|
|
33
|
+
The Vite plugin comes with a set of modes that enable different behaviors.
|
|
34
|
+
|
|
35
|
+
### global (default)
|
|
36
|
+
|
|
37
|
+
This is the default mode for the plugin: in this mode you need to add the import of `uno.css` on your entry point.
|
|
38
|
+
|
|
39
|
+
This mode enables a set of Vite plugins for `build` and for `dev` with `HMR` support.
|
|
40
|
+
|
|
41
|
+
The generated `css` will be a global stylesheet injected on the `index.html`.
|
|
42
|
+
|
|
43
|
+
### vue-scoped (WIP)
|
|
44
|
+
|
|
45
|
+
This mode will inject generated CSS to Vue SFC's `<style scoped>` for isolation.
|
|
46
|
+
|
|
47
|
+
### per-module (WIP)
|
|
48
|
+
|
|
49
|
+
This mode will generate a CSS sheet for each module, can be scoped.
|
|
50
|
+
|
|
51
|
+
### dist-chunk (WIP)
|
|
52
|
+
|
|
53
|
+
This mode will generate a CSS sheet for each code chunk on build, great for MPA.
|
|
54
|
+
|
|
55
|
+
### shadow-dom
|
|
56
|
+
|
|
57
|
+
Since `Web Components` uses `Shadow DOM`, there is no way to style content directly from a global stylesheet (unless you use `custom css vars`, those will penetrate the `Shadow DOM`), you need to inline the generated css by the plugin into the `Shadow DOM` style.
|
|
58
|
+
|
|
59
|
+
To inline the generated css, you only need to configure the plugin mode to `shadow-dom` and include `@unocss-placeholder` magic placeholder on each web component style css block.
|
|
60
|
+
|
|
61
|
+
## Frameworks
|
|
62
|
+
|
|
63
|
+
Some UI/App frameworks have some caveats that must be fixed to make it work, if you're using one of the following frameworks, just apply the suggestions.
|
|
64
|
+
|
|
65
|
+
### React
|
|
66
|
+
|
|
67
|
+
If you're using `@vitejs/plugin-react`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// vite.config.js
|
|
71
|
+
import react from '@vitejs/plugin-react'
|
|
72
|
+
import Unocss from 'unocss/vite'
|
|
73
|
+
|
|
74
|
+
export default {
|
|
75
|
+
plugins: [
|
|
76
|
+
react(),
|
|
77
|
+
Unocss({
|
|
78
|
+
/* options */
|
|
79
|
+
}),
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
or if you're using `@vitejs/plugin-react-refresh`:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// vite.config.js
|
|
88
|
+
import reactRefresh from '@vitejs/plugin-react-refresh'
|
|
89
|
+
import Unocss from 'unocss/vite'
|
|
90
|
+
|
|
91
|
+
export default {
|
|
92
|
+
plugins: [
|
|
93
|
+
reactRefresh(),
|
|
94
|
+
Unocss({
|
|
95
|
+
/* options */
|
|
96
|
+
}),
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If you're using `@unocss/preset-attributify` you should remove `tsc` from the `build` script.
|
|
102
|
+
|
|
103
|
+
If you are using `@vitejs/plugin-react` with `@unocss/preset-attributify`, you must add the plugin before `@vitejs/plugin-react`.
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// vite.config.js
|
|
107
|
+
import react from '@vitejs/plugin-react'
|
|
108
|
+
import Unocss from 'unocss/vite'
|
|
109
|
+
|
|
110
|
+
export default {
|
|
111
|
+
plugins: [
|
|
112
|
+
Unocss({
|
|
113
|
+
/* options */
|
|
114
|
+
}),
|
|
115
|
+
react()
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
You have a `React` example project on [test/fixtures/vite-react](https://github.com/antfu/unocss/tree/main/test/fixtures/vite-react) directory using both plugins, check the scripts on `package.json` and its Vite configuration file.
|
|
121
|
+
|
|
122
|
+
### Preact
|
|
123
|
+
|
|
124
|
+
If you're using `@preact/preset-vite`:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
// vite.config.js
|
|
128
|
+
import preact from '@preact/preset-vite'
|
|
129
|
+
import Unocss from 'unocss/vite'
|
|
130
|
+
|
|
131
|
+
export default {
|
|
132
|
+
plugins: [
|
|
133
|
+
preact(),
|
|
134
|
+
Unocss({
|
|
135
|
+
/* options */
|
|
136
|
+
}),
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
or if you're using `@prefresh/vite`:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// vite.config.js
|
|
145
|
+
import prefresh from '@prefresh/vite'
|
|
146
|
+
import Unocss from 'unocss/vite'
|
|
147
|
+
|
|
148
|
+
export default {
|
|
149
|
+
plugins: [
|
|
150
|
+
prefresh(),
|
|
151
|
+
Unocss({
|
|
152
|
+
/* options */
|
|
153
|
+
}),
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If you're using `@unocss/preset-attributify` you should remove `tsc` from the `build` script.
|
|
159
|
+
|
|
160
|
+
If you are using `@preact/preset-vite` with `@unocss/preset-attributify`, you must add the plugin before `@preact/preset-vite`.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
// vite.config.js
|
|
164
|
+
import preact from '@preact/preset-vite'
|
|
165
|
+
import Unocss from 'unocss/vite'
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
plugins: [
|
|
169
|
+
Unocss({
|
|
170
|
+
/* options */
|
|
171
|
+
}),
|
|
172
|
+
preact()
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
You have a `Preact` example project on [test/fixtures/vite-preact](https://github.com/antfu/unocss/tree/main/test/fixtures/vite-preact) directory using both plugins, check the scripts on `package.json` and its Vite configuration file.
|
|
178
|
+
|
|
179
|
+
### Svelte
|
|
180
|
+
|
|
181
|
+
You must add the plugin before `@sveltejs/vite-plugin-svelte`.
|
|
182
|
+
|
|
183
|
+
To support `class:foo` and `class:foo={bar}` add the plugin and configure `extractorSvelte` on `extractors` option.
|
|
184
|
+
|
|
185
|
+
You can use simple rules with `class:`, for example `class:bg-red-500={foo}` or using `shorcuts` to include multiples rules, see `src/App.svelte` on linked example project bellow.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
// vite.config.js
|
|
189
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
190
|
+
import Unocss from 'unocss/vite'
|
|
191
|
+
import { extractorSvelte } from '@unocss/core'
|
|
192
|
+
|
|
193
|
+
export default {
|
|
194
|
+
plugins: [
|
|
195
|
+
Unocss({
|
|
196
|
+
extractors: [extractorSvelte],
|
|
197
|
+
/* more options */
|
|
198
|
+
}),
|
|
199
|
+
svelte()
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
You have a `Vite + Svelte` example project on [test/fixtures/vite-svelte](https://github.com/antfu/unocss/tree/main/test/fixtures/vite-svelte) directory.
|
|
205
|
+
|
|
206
|
+
### Sveltekit
|
|
207
|
+
|
|
208
|
+
To support `class:foo` and `class:foo={bar}` add the plugin and configure `extractorSvelte` on `extractors` option.
|
|
209
|
+
|
|
210
|
+
You can use simple rules with `class:`, for example `class:bg-red-500={foo}` or using `shorcuts` to include multiples rules, see `src/routes/__layout.svelte` on linked example project bellow.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
// svelte.config.js
|
|
214
|
+
import preprocess from 'svelte-preprocess'
|
|
215
|
+
import UnoCss from 'unocss/vite'
|
|
216
|
+
import { extractorSvelte } from '@unocss/core'
|
|
217
|
+
|
|
218
|
+
/** @type {import('@sveltejs/kit').Config} */
|
|
219
|
+
const config = {
|
|
220
|
+
// Consult https://github.com/sveltejs/svelte-preprocess
|
|
221
|
+
// for more information about preprocessors
|
|
222
|
+
preprocess: preprocess(),
|
|
223
|
+
|
|
224
|
+
kit: {
|
|
225
|
+
|
|
226
|
+
// hydrate the <div id="svelte"> element in src/app.html
|
|
227
|
+
target: '#svelte',
|
|
228
|
+
vite: {
|
|
229
|
+
plugins: [
|
|
230
|
+
UnoCss({
|
|
231
|
+
extractors: [extractorSvelte],
|
|
232
|
+
/* more options */
|
|
233
|
+
})
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
You have a `SvelteKit` example project on [test/fixtures/sveltekit](https://github.com/antfu/unocss/tree/main/test/fixtures/sveltekit) directory.
|
|
241
|
+
|
|
242
|
+
### Web Components
|
|
243
|
+
|
|
244
|
+
To work with web components you need to enable `shadow-dom` mode on the plugin.
|
|
245
|
+
|
|
246
|
+
Don't forget to remove the import for `uno.css` since the `shadow-dom` mode will not expose it and the application will not work.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
// vite.config.js
|
|
250
|
+
import Unocss from 'unocss/vite'
|
|
251
|
+
|
|
252
|
+
export default {
|
|
253
|
+
plugins: [
|
|
254
|
+
Unocss({
|
|
255
|
+
mode: 'shadow-dom',
|
|
256
|
+
/* more options */
|
|
257
|
+
}),
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
On each `web component` just add `@unocss-placeholder` to its style css block:
|
|
263
|
+
```ts
|
|
264
|
+
const template = document.createElement('template')
|
|
265
|
+
template.innerHTML = `
|
|
266
|
+
<style>
|
|
267
|
+
:host {...}
|
|
268
|
+
@unocss-placeholder
|
|
269
|
+
</style>
|
|
270
|
+
<div class="m-1em">
|
|
271
|
+
...
|
|
272
|
+
</div>
|
|
273
|
+
`
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
If you're using [Lit](https://lit.dev/):
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
@customElement('my-element')
|
|
280
|
+
export class MyElement extends LitElement {
|
|
281
|
+
static styles = css`
|
|
282
|
+
:host {...}
|
|
283
|
+
@unocss-placeholder
|
|
284
|
+
`
|
|
285
|
+
...
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
You have a `Web Components` example project on [test/fixtures/vite-lit](https://github.com/antfu/unocss/tree/main/test/fixtures/vite-lit) directory.
|
|
290
|
+
|
|
291
|
+
#### `::part` built-in support
|
|
292
|
+
|
|
293
|
+
You can use `::part` since the plugin supports it via `shortcuts` and using `part-[<part-name>]:<rule|shortcut>` rule from `preset-mini`, for example using it with simple rules like `part-[<part-name>]:bg-green-500` or using some `shortcut`: check `src/my-element.ts` on linked example project bellow.
|
|
294
|
+
|
|
295
|
+
The `part-[<part-name>]:<rule|shortcut>` will work only with this plugin using the `shadow-dom` mode.
|
|
296
|
+
|
|
297
|
+
The plugin uses `nth-of-type` to avoid collisions with multiple parts in the same web component and for the same parts on distinct web components, you don't need to worry about it, the plugin will take care for you.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// vite.config.js
|
|
301
|
+
import Unocss from 'unocss/vite'
|
|
302
|
+
|
|
303
|
+
export default {
|
|
304
|
+
plugins: [
|
|
305
|
+
Unocss({
|
|
306
|
+
mode: 'shadow-dom',
|
|
307
|
+
shortcuts: [
|
|
308
|
+
{ 'cool-blue': 'bg-blue-500 text-white' },
|
|
309
|
+
{ 'cool-green': 'bg-green-500 text-black' },
|
|
310
|
+
],
|
|
311
|
+
/* more options */
|
|
312
|
+
}),
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
then in your web components:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
// my-container-wc.ts
|
|
321
|
+
const template = document.createElement('template')
|
|
322
|
+
template.innerHTML = `
|
|
323
|
+
<style>
|
|
324
|
+
@unocss-placeholder
|
|
325
|
+
</style>
|
|
326
|
+
<my-wc-with-parts class="part-[cool-part]:cool-blue part-[another-cool-part]:cool-green">...</my-wc-with-parts>
|
|
327
|
+
`
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
// my-wc-with-parts.ts
|
|
332
|
+
const template = document.createElement('template')
|
|
333
|
+
template.innerHTML = `
|
|
334
|
+
<style>
|
|
335
|
+
@unocss-placeholder
|
|
336
|
+
</style>
|
|
337
|
+
<div>
|
|
338
|
+
<div part="cool-part">...</div>
|
|
339
|
+
<div part="another-cool-part">...</div>
|
|
340
|
+
</div>
|
|
341
|
+
`
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Solid
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
// vite.config.js
|
|
348
|
+
import solidPlugin from 'vite-plugin-solid'
|
|
349
|
+
import Unocss from 'unocss/vite'
|
|
350
|
+
|
|
351
|
+
export default {
|
|
352
|
+
plugins: [
|
|
353
|
+
solidPlugin(),
|
|
354
|
+
Unocss({
|
|
355
|
+
/* options */
|
|
356
|
+
}),
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
You have a `Vite + Solid` example project on [test/fixtures/vite-solid](https://github.com/antfu/unocss/tree/main/test/fixtures/vite-solid) directory.
|
|
362
|
+
|
|
363
|
+
## License
|
|
364
|
+
|
|
365
|
+
MIT License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)
|
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ function getHashPlaceholder(hash) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
const INCLUDE_COMMENT = "@unocss-include";
|
|
46
|
+
const CSS_PLACEHOLDER = "@unocss-placeholder";
|
|
46
47
|
|
|
47
48
|
function createContext(configOrPath, defaults = {}, extraConfigSources = []) {
|
|
48
49
|
const loadConfig = config.createConfigLoader(configOrPath, extraConfigSources);
|
|
@@ -76,7 +77,7 @@ function createContext(configOrPath, defaults = {}, extraConfigSources = []) {
|
|
|
76
77
|
invalidate();
|
|
77
78
|
}
|
|
78
79
|
const filter = (code, id) => {
|
|
79
|
-
return code.includes(INCLUDE_COMMENT) || rollupFilter(id);
|
|
80
|
+
return code.includes(INCLUDE_COMMENT) || code.includes(CSS_PLACEHOLDER) || rollupFilter(id);
|
|
80
81
|
};
|
|
81
82
|
async function getConfig() {
|
|
82
83
|
await ready;
|
|
@@ -461,6 +462,97 @@ function VueScopedPlugin({ uno, ready }) {
|
|
|
461
462
|
};
|
|
462
463
|
}
|
|
463
464
|
|
|
465
|
+
function ShadowDomModuleModePlugin({ uno }) {
|
|
466
|
+
const partExtractorRegex = /^part-\[(.+)]:/;
|
|
467
|
+
const nameRegexp = /<([^\s^!>]+)\s*([^>]*)>/;
|
|
468
|
+
const checkElement = (useParts, idxResolver, element) => {
|
|
469
|
+
if (!element)
|
|
470
|
+
return null;
|
|
471
|
+
const applyParts = useParts.filter((p) => element[2].includes(p.rule));
|
|
472
|
+
if (applyParts.length === 0)
|
|
473
|
+
return null;
|
|
474
|
+
const name = element[1];
|
|
475
|
+
const idx = idxResolver(name);
|
|
476
|
+
return {
|
|
477
|
+
name,
|
|
478
|
+
entries: applyParts.map(({ rule, part }) => [
|
|
479
|
+
`.${rule.replace(/[:[\]]/g, "\\$&")}::part(${part})`,
|
|
480
|
+
`${name}:nth-of-type(${idx})::part(${part})`
|
|
481
|
+
])
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
const idxMapFactory = () => {
|
|
485
|
+
const elementIdxMap = /* @__PURE__ */ new Map();
|
|
486
|
+
return {
|
|
487
|
+
idxResolver: (name) => {
|
|
488
|
+
let idx = elementIdxMap.get(name);
|
|
489
|
+
if (!idx) {
|
|
490
|
+
idx = 1;
|
|
491
|
+
elementIdxMap.set(name, idx);
|
|
492
|
+
}
|
|
493
|
+
return idx;
|
|
494
|
+
},
|
|
495
|
+
incrementIdx: (name) => {
|
|
496
|
+
elementIdxMap.set(name, elementIdxMap.get(name) + 1);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
const transformWebComponent = async (code) => {
|
|
501
|
+
if (!code.match(CSS_PLACEHOLDER))
|
|
502
|
+
return code;
|
|
503
|
+
let { css, matched } = await uno.generate(code, { preflights: false });
|
|
504
|
+
if (css && matched) {
|
|
505
|
+
const useParts = Array.from(matched).reduce((acc, rule) => {
|
|
506
|
+
const matcher = rule.match(partExtractorRegex);
|
|
507
|
+
if (matcher)
|
|
508
|
+
acc.push({ part: matcher[1], rule });
|
|
509
|
+
return acc;
|
|
510
|
+
}, new Array());
|
|
511
|
+
if (useParts.length > 0) {
|
|
512
|
+
let useCode = code;
|
|
513
|
+
let element;
|
|
514
|
+
const partsToApply = /* @__PURE__ */ new Map();
|
|
515
|
+
const { idxResolver, incrementIdx } = idxMapFactory();
|
|
516
|
+
while (element = nameRegexp.exec(useCode)) {
|
|
517
|
+
const result = checkElement(useParts, idxResolver, element);
|
|
518
|
+
if (result) {
|
|
519
|
+
result.entries.forEach(([name, replacement]) => {
|
|
520
|
+
let list = partsToApply.get(name);
|
|
521
|
+
if (!list) {
|
|
522
|
+
list = [];
|
|
523
|
+
partsToApply.set(name, list);
|
|
524
|
+
}
|
|
525
|
+
list.push(replacement);
|
|
526
|
+
});
|
|
527
|
+
incrementIdx(result.name);
|
|
528
|
+
}
|
|
529
|
+
useCode = useCode.slice(element[0].length + 1);
|
|
530
|
+
}
|
|
531
|
+
if (partsToApply.size > 0) {
|
|
532
|
+
css = Array.from(partsToApply.entries()).reduce((k, [r, name]) => {
|
|
533
|
+
return k.replace(r, name.join(",\n"));
|
|
534
|
+
}, css);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return code.replace(CSS_PLACEHOLDER, css || "");
|
|
539
|
+
};
|
|
540
|
+
return {
|
|
541
|
+
name: "unocss:shadow-dom",
|
|
542
|
+
enforce: "pre",
|
|
543
|
+
async transform(code) {
|
|
544
|
+
return transformWebComponent(code);
|
|
545
|
+
},
|
|
546
|
+
handleHotUpdate(ctx) {
|
|
547
|
+
const read = ctx.read;
|
|
548
|
+
ctx.read = async () => {
|
|
549
|
+
const code = await read();
|
|
550
|
+
return await transformWebComponent(code);
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
464
556
|
function ConfigHMRPlugin(ctx) {
|
|
465
557
|
const { ready, uno } = ctx;
|
|
466
558
|
return {
|
|
@@ -503,6 +595,8 @@ function UnocssPlugin(configOrPath, defaults = {}) {
|
|
|
503
595
|
plugins.push(PerModuleModePlugin(ctx));
|
|
504
596
|
} else if (mode === "vue-scoped") {
|
|
505
597
|
plugins.push(VueScopedPlugin(ctx));
|
|
598
|
+
} else if (mode === "shadow-dom") {
|
|
599
|
+
plugins.push(ShadowDomModuleModePlugin(ctx));
|
|
506
600
|
} else if (mode === "global") {
|
|
507
601
|
plugins.push(...GlobalModePlugin(ctx));
|
|
508
602
|
} else if (mode === "dist-chunk") {
|
package/dist/index.d.ts
CHANGED
|
@@ -17,10 +17,11 @@ interface VitePluginConfig<Theme extends {} = {}> extends UserConfig<Theme> {
|
|
|
17
17
|
* - `dist-chunk` - generate a CSS sheet for each code chunk on build, great for MPA
|
|
18
18
|
* - `per-module` - generate a CSS sheet for each module, can be scoped
|
|
19
19
|
* - `vue-scoped` - inject generated CSS to Vue SFC's `<style scoped>` for isolation
|
|
20
|
+
* - `shadow-dom` - inject generated CSS to `Shadow DOM` css style block for each web component
|
|
20
21
|
*
|
|
21
22
|
* @default 'global'
|
|
22
23
|
*/
|
|
23
|
-
mode?: 'global' | 'per-module' | 'vue-scoped' | 'dist-chunk';
|
|
24
|
+
mode?: 'global' | 'per-module' | 'vue-scoped' | 'dist-chunk' | 'shadow-dom';
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
interface UnocssPluginContext<Config extends UserConfig = UserConfig> {
|
package/dist/index.mjs
CHANGED
|
@@ -35,6 +35,7 @@ function getHashPlaceholder(hash) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const INCLUDE_COMMENT = "@unocss-include";
|
|
38
|
+
const CSS_PLACEHOLDER = "@unocss-placeholder";
|
|
38
39
|
|
|
39
40
|
function createContext(configOrPath, defaults = {}, extraConfigSources = []) {
|
|
40
41
|
const loadConfig = createConfigLoader(configOrPath, extraConfigSources);
|
|
@@ -68,7 +69,7 @@ function createContext(configOrPath, defaults = {}, extraConfigSources = []) {
|
|
|
68
69
|
invalidate();
|
|
69
70
|
}
|
|
70
71
|
const filter = (code, id) => {
|
|
71
|
-
return code.includes(INCLUDE_COMMENT) || rollupFilter(id);
|
|
72
|
+
return code.includes(INCLUDE_COMMENT) || code.includes(CSS_PLACEHOLDER) || rollupFilter(id);
|
|
72
73
|
};
|
|
73
74
|
async function getConfig() {
|
|
74
75
|
await ready;
|
|
@@ -453,6 +454,97 @@ function VueScopedPlugin({ uno, ready }) {
|
|
|
453
454
|
};
|
|
454
455
|
}
|
|
455
456
|
|
|
457
|
+
function ShadowDomModuleModePlugin({ uno }) {
|
|
458
|
+
const partExtractorRegex = /^part-\[(.+)]:/;
|
|
459
|
+
const nameRegexp = /<([^\s^!>]+)\s*([^>]*)>/;
|
|
460
|
+
const checkElement = (useParts, idxResolver, element) => {
|
|
461
|
+
if (!element)
|
|
462
|
+
return null;
|
|
463
|
+
const applyParts = useParts.filter((p) => element[2].includes(p.rule));
|
|
464
|
+
if (applyParts.length === 0)
|
|
465
|
+
return null;
|
|
466
|
+
const name = element[1];
|
|
467
|
+
const idx = idxResolver(name);
|
|
468
|
+
return {
|
|
469
|
+
name,
|
|
470
|
+
entries: applyParts.map(({ rule, part }) => [
|
|
471
|
+
`.${rule.replace(/[:[\]]/g, "\\$&")}::part(${part})`,
|
|
472
|
+
`${name}:nth-of-type(${idx})::part(${part})`
|
|
473
|
+
])
|
|
474
|
+
};
|
|
475
|
+
};
|
|
476
|
+
const idxMapFactory = () => {
|
|
477
|
+
const elementIdxMap = /* @__PURE__ */ new Map();
|
|
478
|
+
return {
|
|
479
|
+
idxResolver: (name) => {
|
|
480
|
+
let idx = elementIdxMap.get(name);
|
|
481
|
+
if (!idx) {
|
|
482
|
+
idx = 1;
|
|
483
|
+
elementIdxMap.set(name, idx);
|
|
484
|
+
}
|
|
485
|
+
return idx;
|
|
486
|
+
},
|
|
487
|
+
incrementIdx: (name) => {
|
|
488
|
+
elementIdxMap.set(name, elementIdxMap.get(name) + 1);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
const transformWebComponent = async (code) => {
|
|
493
|
+
if (!code.match(CSS_PLACEHOLDER))
|
|
494
|
+
return code;
|
|
495
|
+
let { css, matched } = await uno.generate(code, { preflights: false });
|
|
496
|
+
if (css && matched) {
|
|
497
|
+
const useParts = Array.from(matched).reduce((acc, rule) => {
|
|
498
|
+
const matcher = rule.match(partExtractorRegex);
|
|
499
|
+
if (matcher)
|
|
500
|
+
acc.push({ part: matcher[1], rule });
|
|
501
|
+
return acc;
|
|
502
|
+
}, new Array());
|
|
503
|
+
if (useParts.length > 0) {
|
|
504
|
+
let useCode = code;
|
|
505
|
+
let element;
|
|
506
|
+
const partsToApply = /* @__PURE__ */ new Map();
|
|
507
|
+
const { idxResolver, incrementIdx } = idxMapFactory();
|
|
508
|
+
while (element = nameRegexp.exec(useCode)) {
|
|
509
|
+
const result = checkElement(useParts, idxResolver, element);
|
|
510
|
+
if (result) {
|
|
511
|
+
result.entries.forEach(([name, replacement]) => {
|
|
512
|
+
let list = partsToApply.get(name);
|
|
513
|
+
if (!list) {
|
|
514
|
+
list = [];
|
|
515
|
+
partsToApply.set(name, list);
|
|
516
|
+
}
|
|
517
|
+
list.push(replacement);
|
|
518
|
+
});
|
|
519
|
+
incrementIdx(result.name);
|
|
520
|
+
}
|
|
521
|
+
useCode = useCode.slice(element[0].length + 1);
|
|
522
|
+
}
|
|
523
|
+
if (partsToApply.size > 0) {
|
|
524
|
+
css = Array.from(partsToApply.entries()).reduce((k, [r, name]) => {
|
|
525
|
+
return k.replace(r, name.join(",\n"));
|
|
526
|
+
}, css);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return code.replace(CSS_PLACEHOLDER, css || "");
|
|
531
|
+
};
|
|
532
|
+
return {
|
|
533
|
+
name: "unocss:shadow-dom",
|
|
534
|
+
enforce: "pre",
|
|
535
|
+
async transform(code) {
|
|
536
|
+
return transformWebComponent(code);
|
|
537
|
+
},
|
|
538
|
+
handleHotUpdate(ctx) {
|
|
539
|
+
const read = ctx.read;
|
|
540
|
+
ctx.read = async () => {
|
|
541
|
+
const code = await read();
|
|
542
|
+
return await transformWebComponent(code);
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
456
548
|
function ConfigHMRPlugin(ctx) {
|
|
457
549
|
const { ready, uno } = ctx;
|
|
458
550
|
return {
|
|
@@ -495,6 +587,8 @@ function UnocssPlugin(configOrPath, defaults = {}) {
|
|
|
495
587
|
plugins.push(PerModuleModePlugin(ctx));
|
|
496
588
|
} else if (mode === "vue-scoped") {
|
|
497
589
|
plugins.push(VueScopedPlugin(ctx));
|
|
590
|
+
} else if (mode === "shadow-dom") {
|
|
591
|
+
plugins.push(ShadowDomModuleModePlugin(ctx));
|
|
498
592
|
} else if (mode === "global") {
|
|
499
593
|
plugins.push(...GlobalModePlugin(ctx));
|
|
500
594
|
} else if (mode === "dist-chunk") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unocss/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "The Vite plugin for UnoCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unocss",
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@rollup/pluginutils": "^4.1.
|
|
38
|
-
"@unocss/config": "0.
|
|
39
|
-
"@unocss/core": "0.
|
|
40
|
-
"@unocss/inspector": "0.
|
|
41
|
-
"@unocss/scope": "0.
|
|
37
|
+
"@rollup/pluginutils": "^4.1.2",
|
|
38
|
+
"@unocss/config": "0.18.0",
|
|
39
|
+
"@unocss/core": "0.18.0",
|
|
40
|
+
"@unocss/inspector": "0.18.0",
|
|
41
|
+
"@unocss/scope": "0.18.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"vite": "^2.7.
|
|
44
|
+
"vite": "^2.7.4"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "unbuild",
|