diff --git a/examples/vite-vue3/public/uno.svg b/examples/vite-vue3/public/uno.svg new file mode 100644 index 0000000000..60bc8837c7 --- /dev/null +++ b/examples/vite-vue3/public/uno.svg @@ -0,0 +1,11 @@ + + + + + diff --git a/examples/vite-vue3/src/App.vue b/examples/vite-vue3/src/App.vue index e2382ef5cc..45d3e32c62 100644 --- a/examples/vite-vue3/src/App.vue +++ b/examples/vite-vue3/src/App.vue @@ -6,5 +6,6 @@
+ diff --git a/examples/vite-vue3/src/uno.svg b/examples/vite-vue3/src/uno.svg new file mode 100644 index 0000000000..60bc8837c7 --- /dev/null +++ b/examples/vite-vue3/src/uno.svg @@ -0,0 +1,11 @@ + + + + + diff --git a/packages/vite/src/modes/global/build.ts b/packages/vite/src/modes/global/build.ts index 1ab58328d7..33405ff418 100644 --- a/packages/vite/src/modes/global/build.ts +++ b/packages/vite/src/modes/global/build.ts @@ -1,6 +1,7 @@ import { resolve } from 'path' import type { Plugin, ResolvedConfig } from 'vite' import type { GenerateResult, UnocssPluginContext } from '@unocss/core' +import type { PluginContext } from 'rollup' import { HASH_PLACEHOLDER_RE, LAYER_MARK_ALL, LAYER_PLACEHOLDER_RE, RESOLVED_ID_RE, @@ -24,14 +25,14 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get const cssPostPlugins = new Map() const cssPlugins = new Map() - async function applyCssTransform(css: string, id: string, dir: string | undefined) { + async function applyCssTransform(css: string, id: string, dir: string | undefined, ctx: PluginContext) { const { postcss = true, } = await getConfig() if (!cssPlugins.get(dir) || !postcss) return css - // @ts-expect-error no this context - const result = await cssPlugins.get(dir).transform(css, id) + // @ts-expect-error without this context absolute assets will throw an error + const result = await cssPlugins.get(dir).transform.call(ctx, css, id) if (!result) return css if (typeof result === 'string') @@ -122,7 +123,7 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get let { css } = await generateAll() const fakeCssId = `${chunk.fileName}-unocss-hash.css` - css = await applyCssTransform(css, fakeCssId, options.dir) + css = await applyCssTransform(css, fakeCssId, options.dir, this) const hash = getHash(css) const transformHandler = 'handler' in cssPost.transform! @@ -145,6 +146,32 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get { name: 'unocss:global:build:generate', apply: 'build', + async renderChunk(code, chunk, options) { + const cssPost = cssPostPlugins.get(options.dir) + if (!cssPost) { + this.warn('[unocss] failed to find vite:css-post plugin. It might be an internal bug of UnoCSS') + return null + } + const result = await generateAll() + const cssWithLayers = Array.from(vfsLayers).map(layer => + `#--unocss-layer-start--${layer}--{start:${layer}} ${ + layer === LAYER_MARK_ALL + ? result.getLayers(undefined, Array.from(vfsLayers)) + : result.getLayer(layer) || '' + } #--unocss-layer-end--${layer}--{end:${layer}}`, + ).join('') + + const fakeCssId = `${chunk.fileName}-unocss-hash.css` + const css = await applyCssTransform(cssWithLayers, fakeCssId, options.dir, this) + const transformHandler = 'handler' in cssPost.transform! + ? cssPost.transform.handler + : cssPost.transform! + await transformHandler.call({} as unknown as any, css, fakeCssId) + }, + }, + { + name: 'unocss:global:build:bundle', + apply: 'build', configResolved(config) { viteConfig = config }, @@ -164,20 +191,29 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get return } - const result = await generateAll() let replaced = false + const getLayer = (layer: string, input: string, replace = false) => { + const re = new RegExp(`#--unocss-layer-start--${layer}--\\{start:${layer}\\}([\\s\\S]*?)#--unocss-layer-end--${layer}--\\{end:${layer}\\}`, 'g') + if (replace) + return input.replace(re, '') + + const match = re.exec(input) + if (match) + return match[1] + return '' + } for (const file of files) { const chunk = bundle[file] - if (chunk.type === 'asset' && typeof chunk.source === 'string') { const css = chunk.source .replace(HASH_PLACEHOLDER_RE, '') chunk.source = await replaceAsync(css, LAYER_PLACEHOLDER_RE, async (_, __, layer) => { replaced = true - return layer === LAYER_MARK_ALL - ? result.getLayers(undefined, Array.from(vfsLayers)) - : result.getLayer(layer) || '' + return getLayer(layer, css) + }) + Array.from(vfsLayers).forEach((layer) => { + chunk.source = getLayer(layer, chunk.source as string, true) }) } else if (chunk.type === 'chunk' && typeof chunk.code === 'string') { @@ -185,13 +221,14 @@ export function GlobalModeBuildPlugin({ uno, ready, extract, tokens, filter, get .replace(HASH_PLACEHOLDER_RE, '') chunk.code = await replaceAsync(js, LAYER_PLACEHOLDER_RE, async (_, __, layer) => { replaced = true - const css = layer === LAYER_MARK_ALL - ? result.getLayers(undefined, Array.from(vfsLayers)) - : result.getLayer(layer) || '' + const css = getLayer(layer, js) return css .replace(/\n/g, '') .replace(/(? { + chunk.code = getLayer(layer, chunk.code, true) + }) } }