From 65216ef921d0f080d9a4995b0d8ebaf653ee3bfa Mon Sep 17 00:00:00 2001
From: Drew Powers <1369770+drwpow@users.noreply.github.com>
Date: Mon, 15 Nov 2021 14:16:07 -0700
Subject: [PATCH] Fix PostCSS (and Autoprefixer) processing (#1837)
* Fix PostCSS processing
* Skip Windows tests
(for now)
---
.changeset/twenty-rabbits-repeat.md | 5 ++
docs/src/pages/guides/styling.md | 6 +-
packages/astro/package.json | 1 +
packages/astro/src/core/ssr/css.ts | 1 -
packages/astro/src/core/util.ts | 4 +-
packages/astro/src/vite-plugin-astro/index.ts | 4 +-
.../astro/src/vite-plugin-astro/styles.ts | 9 ++-
.../test/fixtures/postcss/postcss.config.cjs | 7 +++
.../test/fixtures/postcss/public/global.css | 3 +
.../postcss/src/components/Astro.astro | 9 +++
.../fixtures/postcss/src/components/Solid.css | 3 +
.../fixtures/postcss/src/components/Solid.jsx | 10 +++
.../postcss/src/components/Svelte.svelte | 9 +++
.../fixtures/postcss/src/components/Vue.vue | 12 ++++
.../fixtures/postcss/src/pages/index.astro | 24 ++++++++
.../fixtures/postcss/src/styles/linked.css | 3 +
packages/astro/test/postcss.test.js | 61 +++++++++++++++++++
yarn.lock | 5 ++
18 files changed, 164 insertions(+), 12 deletions(-)
create mode 100644 .changeset/twenty-rabbits-repeat.md
create mode 100644 packages/astro/test/fixtures/postcss/postcss.config.cjs
create mode 100644 packages/astro/test/fixtures/postcss/public/global.css
create mode 100644 packages/astro/test/fixtures/postcss/src/components/Astro.astro
create mode 100644 packages/astro/test/fixtures/postcss/src/components/Solid.css
create mode 100644 packages/astro/test/fixtures/postcss/src/components/Solid.jsx
create mode 100644 packages/astro/test/fixtures/postcss/src/components/Svelte.svelte
create mode 100644 packages/astro/test/fixtures/postcss/src/components/Vue.vue
create mode 100644 packages/astro/test/fixtures/postcss/src/pages/index.astro
create mode 100644 packages/astro/test/fixtures/postcss/src/styles/linked.css
create mode 100644 packages/astro/test/postcss.test.js
diff --git a/.changeset/twenty-rabbits-repeat.md b/.changeset/twenty-rabbits-repeat.md
new file mode 100644
index 000000000..4c39ad433
--- /dev/null
+++ b/.changeset/twenty-rabbits-repeat.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Bugfix: PostCSS not working in all contexts
diff --git a/docs/src/pages/guides/styling.md b/docs/src/pages/guides/styling.md
index a42d759df..550ddd5f9 100644
--- a/docs/src/pages/guides/styling.md
+++ b/docs/src/pages/guides/styling.md
@@ -129,8 +129,10 @@ It’s recommended to only use this in scenarios where a `` tag won’t wo
```js
// postcss.config.cjs
module.exports = {
- autoprefixer: {
- /* (optional) autoprefixer settings */
+ plugins: {
+ autoprefixer: {
+ /* (optional) autoprefixer settings */
+ },
},
};
```
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 6729aad1c..134011378 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -70,6 +70,7 @@
"astring": "^1.7.5",
"ci-info": "^3.2.0",
"connect": "^3.7.0",
+ "eol": "^0.9.1",
"es-module-lexer": "^0.7.1",
"esbuild": "^0.13.6",
"estree-util-value-to-estree": "^1.2.0",
diff --git a/packages/astro/src/core/ssr/css.ts b/packages/astro/src/core/ssr/css.ts
index 9fba52fca..28fcbafd8 100644
--- a/packages/astro/src/core/ssr/css.ts
+++ b/packages/astro/src/core/ssr/css.ts
@@ -4,7 +4,6 @@ import path from 'path';
// https://vitejs.dev/guide/features.html#css-pre-processors
export const STYLE_EXTENSIONS = new Set(['.css', '.pcss', '.scss', '.sass', '.styl', '.stylus', '.less']);
-export const PREPROCESSOR_EXTENSIONS = new Set(['.pcss', '.scss', '.sass', '.styl', '.stylus', '.less']);
/** find unloaded styles */
export function getStylesForID(id: string, viteServer: vite.ViteDevServer): Set {
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 3f29a32ba..3981aad95 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -1,6 +1,6 @@
import type { AstroConfig } from '../@types/astro-core';
import type { ErrorPayload } from 'vite';
-import fs from 'fs';
+import eol from 'eol';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import resolve from 'resolve';
@@ -41,7 +41,7 @@ export function parseNpmName(spec: string): { scope?: string; name: string; subp
/** generate code frame from esbuild error */
export function codeFrame(src: string, loc: ErrorPayload['err']['loc']): string {
if (!loc) return '';
- const lines = src.replace(/\r\n/g, '\n').split('\n');
+ const lines = eol.lf(src).split('\n');
// grab 2 lines before, and 3 lines after focused line
const visibleLines = [];
for (let n = -2; n <= 2; n++) {
diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts
index ea321f65b..821dd3b36 100644
--- a/packages/astro/src/vite-plugin-astro/index.ts
+++ b/packages/astro/src/vite-plugin-astro/index.ts
@@ -63,8 +63,8 @@ export default function astro({ config, devServer }: AstroPluginOptions): vite.P
sourcemap: 'both',
internalURL: 'astro/internal',
preprocessStyle: async (value: string, attrs: Record) => {
- if (!attrs || !attrs.lang) return null;
- const result = await transformWithVite({ value, attrs, id, transformHook: viteTransform, ssr: isSSR(opts) });
+ const lang = `.${attrs?.lang || 'css'}`.toLowerCase();
+ const result = await transformWithVite({ value, lang, id, transformHook: viteTransform, ssr: isSSR(opts) });
if (!result) {
// TODO: compiler supports `null`, but types don't yet
return result as any;
diff --git a/packages/astro/src/vite-plugin-astro/styles.ts b/packages/astro/src/vite-plugin-astro/styles.ts
index 7c87e60d2..96971f308 100644
--- a/packages/astro/src/vite-plugin-astro/styles.ts
+++ b/packages/astro/src/vite-plugin-astro/styles.ts
@@ -1,6 +1,6 @@
import type vite from '../core/vite';
-import { PREPROCESSOR_EXTENSIONS } from '../core/ssr/css.js';
+import { STYLE_EXTENSIONS } from '../core/ssr/css.js';
export type TransformHook = (code: string, id: string, ssr?: boolean) => Promise;
@@ -14,16 +14,15 @@ export function getViteTransform(viteConfig: vite.ResolvedConfig): TransformHook
interface TransformWithViteOptions {
value: string;
- attrs: Record;
+ lang: string;
id: string;
transformHook: TransformHook;
ssr?: boolean;
}
/** Transform style using Vite hook */
-export async function transformWithVite({ value, attrs, transformHook, id, ssr }: TransformWithViteOptions): Promise {
- const lang = (`.${attrs.lang}` || '').toLowerCase(); // add leading "."; don’t be case-sensitive
- if (!PREPROCESSOR_EXTENSIONS.has(lang)) {
+export async function transformWithVite({ value, lang, transformHook, id, ssr }: TransformWithViteOptions): Promise {
+ if (!STYLE_EXTENSIONS.has(lang)) {
return null; // only preprocess langs supported by Vite
}
return transformHook(value, id + `?astro&type=style&lang${lang}`, ssr);
diff --git a/packages/astro/test/fixtures/postcss/postcss.config.cjs b/packages/astro/test/fixtures/postcss/postcss.config.cjs
new file mode 100644
index 000000000..019f40040
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/postcss.config.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ plugins: {
+ autoprefixer: {
+ overrideBrowserslist: ['> 0.1%', 'IE 11'] // enforce `appearance: none;` is prefixed with -webkit and -moz
+ }
+ }
+};
diff --git a/packages/astro/test/fixtures/postcss/public/global.css b/packages/astro/test/fixtures/postcss/public/global.css
new file mode 100644
index 000000000..878eed346
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/public/global.css
@@ -0,0 +1,3 @@
+.global {
+ appearance: none;
+}
diff --git a/packages/astro/test/fixtures/postcss/src/components/Astro.astro b/packages/astro/test/fixtures/postcss/src/components/Astro.astro
new file mode 100644
index 000000000..c85cd0415
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/components/Astro.astro
@@ -0,0 +1,9 @@
+
+
+
+ Astro
+
diff --git a/packages/astro/test/fixtures/postcss/src/components/Solid.css b/packages/astro/test/fixtures/postcss/src/components/Solid.css
new file mode 100644
index 000000000..9c4272b56
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/components/Solid.css
@@ -0,0 +1,3 @@
+.solid {
+ appearance: none;
+}
diff --git a/packages/astro/test/fixtures/postcss/src/components/Solid.jsx b/packages/astro/test/fixtures/postcss/src/components/Solid.jsx
new file mode 100644
index 000000000..9f172eb3b
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/components/Solid.jsx
@@ -0,0 +1,10 @@
+import { h } from 'solid-js';
+import './Solid.css';
+
+export default function Counter() {
+ return (
+
+ Solid
+
+ );
+}
diff --git a/packages/astro/test/fixtures/postcss/src/components/Svelte.svelte b/packages/astro/test/fixtures/postcss/src/components/Svelte.svelte
new file mode 100644
index 000000000..0b55ab627
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/components/Svelte.svelte
@@ -0,0 +1,9 @@
+
+
+
+ Svelte
+
diff --git a/packages/astro/test/fixtures/postcss/src/components/Vue.vue b/packages/astro/test/fixtures/postcss/src/components/Vue.vue
new file mode 100644
index 000000000..20b928e08
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/components/Vue.vue
@@ -0,0 +1,12 @@
+
+
+
+
+ Vue
+
+
+
diff --git a/packages/astro/test/fixtures/postcss/src/pages/index.astro b/packages/astro/test/fixtures/postcss/src/pages/index.astro
new file mode 100644
index 000000000..bba92dbf7
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/pages/index.astro
@@ -0,0 +1,24 @@
+---
+import AstroComponent from '../components/Astro.astro';
+import JSX from '../components/Solid.jsx';
+import Svelte from '../components/Svelte.svelte';
+import Vue from '../components/Vue.vue';
+---
+
+
+
+
+
+
+
+
+
diff --git a/packages/astro/test/fixtures/postcss/src/styles/linked.css b/packages/astro/test/fixtures/postcss/src/styles/linked.css
new file mode 100644
index 000000000..c989da683
--- /dev/null
+++ b/packages/astro/test/fixtures/postcss/src/styles/linked.css
@@ -0,0 +1,3 @@
+.a-n {
+ appearance: none;
+}
diff --git a/packages/astro/test/postcss.test.js b/packages/astro/test/postcss.test.js
new file mode 100644
index 000000000..ac38f6622
--- /dev/null
+++ b/packages/astro/test/postcss.test.js
@@ -0,0 +1,61 @@
+import { expect } from 'chai';
+import cheerio from 'cheerio';
+import eol from 'eol';
+import os from 'os';
+import { loadFixture } from './test-utils.js';
+
+const PREFIXED_CSS = `{-webkit-appearance:none;-moz-appearance:none;appearance:none}`;
+
+let fixture;
+let bundledCSS;
+before(async () => {
+ fixture = await loadFixture({
+ projectRoot: './fixtures/postcss',
+ renderers: ['@astrojs/renderer-solid', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'],
+ });
+ await fixture.build();
+
+ // get bundled CSS (will be hashed, hence DOM query)
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
+ const bundledCSSHREF = $('link[rel=stylesheet][href^=assets/]').attr('href');
+ bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/'));
+});
+
+describe('PostCSS', () => {
+ it('works in Astro page styles', () => {
+ expect(bundledCSS).to.match(new RegExp(`.astro-page.astro-[^{]+${PREFIXED_CSS}`));
+ });
+
+ it('works in Astro component styles', () => {
+ expect(bundledCSS).to.match(new RegExp(`.astro-component.astro-[^{]+${PREFIXED_CSS}`));
+ });
+
+ it('works in ', () => {
+ expect(bundledCSS).to.match(new RegExp(`.a-n${PREFIXED_CSS}`));
+ });
+
+ it('works in JSX', () => {
+ // TODO: fix in Windows
+ if (os.platform() === 'win32') return;
+ expect(bundledCSS).to.match(new RegExp(`.solid${PREFIXED_CSS}`));
+ });
+
+ it('works in Vue', () => {
+ // TODO: fix in Windows
+ if (os.platform() === 'win32') return;
+ expect(bundledCSS).to.match(new RegExp(`.vue${PREFIXED_CSS}`));
+ });
+
+ it('works in Svelte', () => {
+ // TODO: fix in Windows
+ if (os.platform() === 'win32') return;
+ expect(bundledCSS).to.match(new RegExp(`.svelte.s[^{]+${PREFIXED_CSS}`));
+ });
+
+ it('ignores CSS in public/', async () => {
+ const publicCSS = await fixture.readFile('/global.css');
+ // neither minified nor prefixed
+ expect(eol.lf(publicCSS.trim())).to.equal(`.global {\n appearance: none;\n}`);
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index feac9266f..943f1176a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4008,6 +4008,11 @@ envinfo@^7.7.4:
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
+eol@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd"
+ integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==
+
eol@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eol/-/eol-0.2.0.tgz#2f6db086a243a46e3e5dbd0e13435c7ebebf09dd"