0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

Add tailwindcss nesting support (#9529)

* Add tailwindcss nesting support

* Update lockfile
This commit is contained in:
Bjorn Lu 2023-12-28 00:34:01 +07:00 committed by GitHub
parent cf993bc263
commit d252fc61b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 121 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/tailwind': minor
---
Adds `nesting` option to enable `tailwindcss/nesting` support

View file

@ -29,7 +29,8 @@
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"dev": "astro-scripts dev \"src/**/*.ts\""
"dev": "astro-scripts dev \"src/**/*.ts\"",
"test": "mocha --exit --timeout 20000 test/"
},
"dependencies": {
"autoprefixer": "^10.4.15",
@ -39,6 +40,8 @@
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"chai": "^4.3.7",
"mocha": "^10.2.0",
"tailwindcss": "^3.3.5",
"vite": "^5.0.10"
},

View file

@ -1,3 +1,4 @@
import { fileURLToPath } from 'node:url';
import type { AstroIntegration } from 'astro';
import autoprefixerPlugin from 'autoprefixer';
import tailwindPlugin from 'tailwindcss';
@ -23,15 +24,22 @@ async function getPostCssConfig(
async function getViteConfiguration(
tailwindConfigPath: string | undefined,
viteConfig: UserConfig
nesting: boolean,
root: string,
postcssInlineOptions: CSSOptions['postcss']
): Promise<Partial<UserConfig>> {
// We need to manually load postcss config files because when inlining the tailwind and autoprefixer plugins,
// that causes vite to ignore postcss config files
const postcssConfigResult = await getPostCssConfig(viteConfig.root, viteConfig.css?.postcss);
const postcssConfigResult = await getPostCssConfig(root, postcssInlineOptions);
const postcssOptions = postcssConfigResult?.options ?? {};
const postcssPlugins = postcssConfigResult?.plugins?.slice() ?? [];
if (nesting) {
const tailwindcssNestingPlugin = (await import('tailwindcss/nesting/index.js')).default;
postcssPlugins.push(tailwindcssNestingPlugin());
}
postcssPlugins.push(tailwindPlugin(tailwindConfigPath));
postcssPlugins.push(autoprefixerPlugin());
@ -59,18 +67,30 @@ type TailwindOptions = {
* @default true
*/
applyBaseStyles?: boolean;
/**
* Add CSS nesting support using `tailwindcss/nesting`. See {@link https://tailwindcss.com/docs/using-with-preprocessors#nesting Tailwind's docs}
* for how this works with `postcss-nesting` and `postcss-nested`.
*/
nesting?: boolean;
};
export default function tailwindIntegration(options?: TailwindOptions): AstroIntegration {
const applyBaseStyles = options?.applyBaseStyles ?? true;
const customConfigPath = options?.configFile;
const nesting = options?.nesting ?? false;
return {
name: '@astrojs/tailwind',
hooks: {
'astro:config:setup': async ({ config, updateConfig, injectScript }) => {
// Inject the Tailwind postcss plugin
updateConfig({
vite: await getViteConfiguration(customConfigPath, config.vite),
vite: await getViteConfiguration(
customConfigPath,
nesting,
fileURLToPath(config.root),
config.vite.css?.postcss
),
});
if (applyBaseStyles) {

View file

@ -0,0 +1,33 @@
import { expect } from 'chai';
import { loadFixture } from '../../../astro/test/test-utils.js';
describe('Basic', () => {
let fixture;
before(async () => {
fixture = await loadFixture({
root: new URL('./fixtures/basic/', import.meta.url),
});
});
describe('build', () => {
before(async () => {
await fixture.build();
});
it('works', async () => {
const astroChunkDir = await fixture.readdir('/_astro');
let css = '';
for (const file of astroChunkDir) {
if (file.endsWith('.css')) {
css += await fixture.readFile(`/_astro/${file}`);
}
}
expect(css).to.include('box-sizing:border-box;'); // base css
expect(css).to.include('text-red-500'); // class css
expect(css).to.match(/\.a\[data-astro-cid-.*?\] \.b\[data-astro-cid-.*?\]/); // nesting
});
});
});

View file

@ -0,0 +1,12 @@
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [
tailwind({
configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
nesting: true
}),
]
});

View file

@ -0,0 +1,10 @@
{
"name": "@test/tailwind-basic",
"version": "0.0.0",
"private": true,
"type": "module",
"dependencies": {
"astro": "workspace:*",
"@astrojs/tailwind": "workspace:*"
}
}

View file

@ -0,0 +1,13 @@
<div class="text-red-500">red</div>
<div class="a">
<div class="b">nested blue</div>
</div>
<style>
.a {
.b {
color: blue;
}
}
</style>

View file

@ -0,0 +1,6 @@
import path from 'node:path';
/** @type {import('tailwindcss').Config} */
export default {
content: [path.join(__dirname, 'src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}')],
};

15
pnpm-lock.yaml generated
View file

@ -4566,6 +4566,12 @@ importers:
astro-scripts:
specifier: workspace:*
version: link:../../../scripts
chai:
specifier: ^4.3.7
version: 4.3.10
mocha:
specifier: ^10.2.0
version: 10.2.0
tailwindcss:
specifier: ^3.3.5
version: 3.3.5
@ -4573,6 +4579,15 @@ importers:
specifier: ^5.0.10
version: 5.0.10(@types/node@18.18.6)(sass@1.69.5)
packages/integrations/tailwind/test/fixtures/basic:
dependencies:
'@astrojs/tailwind':
specifier: workspace:*
version: link:../../..
astro:
specifier: workspace:*
version: link:../../../../../astro
packages/integrations/vercel:
dependencies:
'@astrojs/internal-helpers':