mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Vite: Add support for <style> tags in Astro files (#14340)
This works similar to the Vue setup. The styles that Astro will receive might still contain Tailwind CSS APIs but since it's not picky, we can pass that through to the regular Vite `transform` handlers for now. This, however, will have issues like https://github.com/tailwindlabs/tailwindcss/issues/14205. We have to fix this together with Vue and other similar extensions later. For now, it will break when syntax is used that lightningcss rewrites (like `@apply text-3xl/tight;`) --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
parent
805c8a0201
commit
2dd52f5a0f
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Support TypeScript for `@plugin` and `@config` files ([#14317](https://github.com/tailwindlabs/tailwindcss/pull/14317))
|
||||
- Add `default` option to `@theme` to support overriding default theme values from plugins/JS config files ([#14327](https://github.com/tailwindlabs/tailwindcss/pull/14327))
|
||||
- Add support for `<style>` tags in Astro files to the Vite plugin ([#14340](https://github.com/tailwindlabs/tailwindcss/pull/14340))
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@ -536,32 +536,40 @@ export async function fetchStyles(port: number, path = '/'): Promise<string> {
|
||||
let index = await fetch(`http://localhost:${port}${path}`)
|
||||
let html = await index.text()
|
||||
|
||||
let regex = /<link rel="stylesheet" href="([a-zA-Z0-9\/_\.\?=%-]+)"/g
|
||||
let linkRegex = /<link rel="stylesheet" href="([a-zA-Z0-9\/_\.\?=%-]+)"/gi
|
||||
let styleRegex = /<style\b[^>]*>([\s\S]*?)<\/style>/gi
|
||||
|
||||
let stylesheets: string[] = []
|
||||
|
||||
let paths: string[] = []
|
||||
let match
|
||||
while ((match = regex.exec(html)) !== null) {
|
||||
for (let match of html.matchAll(linkRegex)) {
|
||||
let path: string = match[1]
|
||||
if (path.startsWith('./')) {
|
||||
path = path.slice(1)
|
||||
}
|
||||
paths.push(path)
|
||||
}
|
||||
|
||||
let stylesheets = await Promise.all(
|
||||
paths.map(async (path) => {
|
||||
let css = await fetch(`http://localhost:${port}${path}`, {
|
||||
headers: {
|
||||
Accept: 'text/css',
|
||||
},
|
||||
})
|
||||
return await css.text()
|
||||
}),
|
||||
stylesheets.push(
|
||||
...(await Promise.all(
|
||||
paths.map(async (path) => {
|
||||
let css = await fetch(`http://localhost:${port}${path}`, {
|
||||
headers: {
|
||||
Accept: 'text/css',
|
||||
},
|
||||
})
|
||||
return await css.text()
|
||||
}),
|
||||
)),
|
||||
)
|
||||
|
||||
for (let match of html.matchAll(styleRegex)) {
|
||||
stylesheets.push(match[1])
|
||||
}
|
||||
|
||||
return stylesheets.reduce((acc, css) => {
|
||||
return acc + '\n' + css
|
||||
})
|
||||
}, '')
|
||||
}
|
||||
|
||||
async function gracefullyRemove(dir: string) {
|
||||
|
||||
63
integrations/vite/astro.test.ts
Normal file
63
integrations/vite/astro.test.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { expect } from 'vitest'
|
||||
import { candidate, fetchStyles, html, json, retryAssertion, test, ts } from '../utils'
|
||||
|
||||
test.debug(
|
||||
'dev mode',
|
||||
{
|
||||
fs: {
|
||||
'package.json': json`
|
||||
{
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"astro": "^4.15.2",
|
||||
"@tailwindcss/vite": "workspace:^",
|
||||
"tailwindcss": "workspace:^"
|
||||
}
|
||||
}
|
||||
`,
|
||||
'astro.config.mjs': ts`
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'astro/config'
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
})
|
||||
`,
|
||||
'src/pages/index.astro': html`
|
||||
<div class="underline">Hello, world!</div>
|
||||
|
||||
<style is:global>
|
||||
@import 'tailwindcss';
|
||||
</style>
|
||||
`,
|
||||
},
|
||||
},
|
||||
async ({ fs, spawn, getFreePort }) => {
|
||||
let port = await getFreePort()
|
||||
await spawn(`pnpm astro dev --port ${port}`)
|
||||
|
||||
await retryAssertion(async () => {
|
||||
let css = await fetchStyles(port)
|
||||
expect(css).toContain(candidate`underline`)
|
||||
})
|
||||
|
||||
await fs.write(
|
||||
'src/pages/index.astro',
|
||||
html`
|
||||
<div class="underline font-bold">Hello, world!</div>
|
||||
|
||||
<style is:global>
|
||||
@import 'tailwindcss';
|
||||
</style>
|
||||
`,
|
||||
)
|
||||
await retryAssertion(async () => {
|
||||
let css = await fetchStyles(port)
|
||||
expect(css).toContain(candidate`underline`)
|
||||
expect(css).toContain(candidate`font-bold`)
|
||||
})
|
||||
},
|
||||
)
|
||||
@ -262,7 +262,10 @@ function getExtension(id: string) {
|
||||
|
||||
function isPotentialCssRootFile(id: string) {
|
||||
let extension = getExtension(id)
|
||||
let isCssFile = extension === 'css' || (extension === 'vue' && id.includes('&lang.css'))
|
||||
let isCssFile =
|
||||
extension === 'css' ||
|
||||
(extension === 'vue' && id.includes('&lang.css')) ||
|
||||
(extension === 'astro' && id.includes('&lang.css'))
|
||||
return isCssFile
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user