From 0fa772b075e03b767fcbf7827fa511fe48a6055e Mon Sep 17 00:00:00 2001 From: Drew Powers Date: Tue, 30 Mar 2021 15:06:31 -0600 Subject: [PATCH] Extract Astro styles to external stylesheets --- .eslintrc.cjs | 2 + .github/workflows/nodejs.yml | 7 +++ snowpack-plugin.cjs | 8 ++- src/@types/astro.ts | 2 + src/compiler/codegen.ts | 34 ++++++++++--- src/compiler/index.ts | 15 +++--- src/compiler/optimize/styles.ts | 36 ++++--------- src/runtime.ts | 90 +++++++++++++++++++-------------- test/astro-styles-ssr.test.js | 25 ++++++--- 9 files changed, 130 insertions(+), 89 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8cdfdc2f383bc..b91860f0c54dc 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -7,8 +7,10 @@ module.exports = { '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/no-var-requires': 'off', + 'no-shadow': 'error', 'prettier/prettier': 'error', 'prefer-const': 'off', 'prefer-rest-params': 'off', + 'require-jsdoc': 'warn', }, }; diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 0808ce599db86..369d075631a51 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -27,3 +27,10 @@ jobs: npm test env: CI: true + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + - run: npm ci + - run: npm run lint diff --git a/snowpack-plugin.cjs b/snowpack-plugin.cjs index dcb714ea61117..4a4db8efdfd52 100644 --- a/snowpack-plugin.cjs +++ b/snowpack-plugin.cjs @@ -9,7 +9,7 @@ module.exports = function (snowpackConfig, { resolve, extensions, astroConfig } knownEntrypoints: ['deepmerge'], resolve: { input: ['.astro', '.md'], - output: ['.js'], + output: ['.js', '.css'], }, async load({ filePath }) { const { compileComponent } = await transformPromise; @@ -21,7 +21,11 @@ module.exports = function (snowpackConfig, { resolve, extensions, astroConfig } extensions, }; const result = await compileComponent(contents, { compileOptions, filename: filePath, projectRoot }); - return result.contents; + const output = { + '.js': result.contents, + }; + if (result.css) output['.css'] = result.css; + return output; }, }; }; diff --git a/src/@types/astro.ts b/src/@types/astro.ts index ee6a79eabac47..5790c4b788275 100644 --- a/src/@types/astro.ts +++ b/src/@types/astro.ts @@ -25,9 +25,11 @@ export interface TransformResult { script: string; imports: string[]; items: JsxItem[]; + css?: string; } export interface CompileResult { result: TransformResult; contents: string; + css?: string; } diff --git a/src/compiler/codegen.ts b/src/compiler/codegen.ts index 70620111d82fe..63fc44dfbcfd0 100644 --- a/src/compiler/codegen.ts +++ b/src/compiler/codegen.ts @@ -21,7 +21,7 @@ interface Attribute { end: number; type: 'Attribute'; name: string; - value: any; + value: TemplateNode[] | boolean; } interface CodeGenOptions { @@ -41,7 +41,8 @@ function getAttributes(attrs: Attribute[]): Record { result[attr.name] = JSON.stringify(attr.value); continue; } - if (attr.value === false) { + if (attr.value === false || attr.value === undefined) { + // note: attr.value shouldn’t be `undefined`, but a bad transform would cause a compile error here, so prevent that continue; } if (attr.value.length > 1) { @@ -59,7 +60,7 @@ function getAttributes(attrs: Attribute[]): Record { ')'; continue; } - const val: TemplateNode = attr.value[0]; + const val = attr.value[0]; if (!val) { result[attr.name] = '(' + val + ')'; continue; @@ -72,7 +73,7 @@ function getAttributes(attrs: Attribute[]): Record { result[attr.name] = JSON.stringify(getTextFromAttribute(val)); continue; default: - throw new Error('UNKNOWN V'); + throw new Error(`UNKNOWN: ${val.type}`); } } return result; @@ -253,7 +254,7 @@ async function acquireDynamicComponentImports(plugins: Set { +export async function codegen(ast: Ast, { compileOptions, filename, fileID }: CodeGenOptions): Promise { const { extensions = defaultExtensions, astroConfig } = compileOptions; await eslexer.init; @@ -334,6 +335,21 @@ export async function codegen(ast: Ast, { compileOptions, filename }: CodeGenOpt let collectionItem: JsxItem | undefined; let currentItemName: string | undefined; let currentDepth = 0; + let css: string[] = []; + + walk(ast.css, { + enter(node: TemplateNode) { + if (node.type === 'Style') { + css.push(node.content.styles); // if multiple