Skip to content

Commit

Permalink
Merge branch 'main' into single-file-build-3
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewp authored Mar 24, 2022
2 parents ccadcff + eb4ac82 commit bbdfc50
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .changeset/cyan-pigs-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fix a bug where tailwind integration wouldn't apply to markdown pages
8 changes: 7 additions & 1 deletion .github/ISSUE_TEMPLATE/---01-bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ body:
- type: input
attributes:
label: Link to Minimal Reproducible Example
description: 'Please use the following link to create a reproduction: https://astro.new'
description: 'Use [astro.new](https://astro.new) to create a minimal reproduction of the problem. **A minimal reproduction is required** so that others can help debug your issue. If a report is vague (e.g. just a generic error message) and has no reproduction, it may be auto-closed.'
placeholder: 'https://stackblitz.com/abcd1234'
validations:
required: true
- type: checkboxes
attributes:
label: Participation
options:
- label: I am willing to submit a pull request for this issue.
required: false
9 changes: 5 additions & 4 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

- What does this change?
- Be short and concise. Bullet points can help!
- Before/after screenshots can be helpful as well.
- Before/after screenshots can help as well.
- Don't forget a changeset! `pnpm exec changeset`

## Testing

Expand All @@ -11,6 +12,6 @@

## Docs

<!-- Did you make a user-facing change? You probably need to update docs! -->
<!-- Add a link to your docs PR here. If no docs added, explain why (e.g. "bug fix only") -->
<!-- Link: https://github.com/withastro/docs -->
<!-- Is this a visible change? You probably need to update docs! -->
<!-- DON'T DELETE THIS SECTION! If no docs added, explain why.-->
<!-- https://github.com/withastro/docs -->
5 changes: 3 additions & 2 deletions examples/with-tailwindcss/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import Button from '../components/Button.astro';
</head>

<body>
<div class="grid place-items-center h-screen">
<Button>Click Me!</Button>
<div class="grid place-items-center h-screen content-center">
<Button>Tailwind Button in Astro!</Button>
<a href="/markdown-page" class="p-4 underline">Markdown is also supported...</a>
</div>
</body>
</html>
10 changes: 10 additions & 0 deletions examples/with-tailwindcss/src/pages/markdown-page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: 'Markdown + Tailwind'
setup: |
import Button from '../components/Button.astro';
---

<div class="grid place-items-center h-screen content-center">
<Button>Tailwind Button in Markdown!</Button>
<a href="/" class="p-4 underline">Go home...</a>
</div>
2 changes: 1 addition & 1 deletion packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ export interface AstroUserConfig {
* - "page": Injected into the JavaScript bundle of every page. Processed & resolved by Vite.
* - "page-ssr": Injected into the frontmatter of every Astro page. Processed & resolved by Vite.
*/
type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' | 'page-ssr';
export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' | 'page-ssr';

/**
* Resolved Astro Config
Expand Down
12 changes: 9 additions & 3 deletions packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import type { OutputAsset, OutputChunk, RollupOutput } from 'rollup';
import type { PageBuildData } from './types';
import type { AstroConfig, AstroRenderer, ComponentInstance, EndpointHandler, SSRLoadedRenderer } from '../../@types/astro';
import type { StaticBuildOptions, SingleFileBuiltModule } from './types';
import type { PageBuildData, StaticBuildOptions, SingleFileBuiltModule } from './types';
import type { BuildInternals } from '../../core/build/internal.js';
import type { RenderOptions } from '../../core/render/core';

import fs from 'fs';
import { bgMagenta, black, cyan, dim, magenta } from 'kleur/colors';
import npath from 'path';
import type { OutputAsset, OutputChunk, RollupOutput } from 'rollup';
import { fileURLToPath } from 'url';
import type { AstroConfig, AstroRenderer, ComponentInstance, EndpointHandler, SSRLoadedRenderer } from '../../@types/astro';
import type { BuildInternals } from '../../core/build/internal.js';
import { debug, error, info } from '../../core/logger.js';
import { prependForwardSlash } from '../../core/path.js';
import type { RenderOptions } from '../../core/render/core';
import { resolveDependency } from '../../core/util.js';
import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { call as callEndpoint } from '../endpoint/index.js';
import { render } from '../render/core.js';
import { createLinkStylesheetElementSet, createModuleScriptElementWithSrcSet } from '../render/ssr-element.js';
import { getOutRoot, getOutFolder, getOutFile, getServerRoot } from './common.js';
import { getOutFile, getOutRoot, getOutFolder, getOutFile, getServerRoot } from './common.js';
import { getPageDataByComponent, eachPageData } from './internal.js';
import { bgMagenta, black, cyan, dim, magenta } from 'kleur/colors';
import { getTimeStat } from './util.js';
Expand Down Expand Up @@ -194,7 +200,7 @@ async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: G
// Return this as placeholder, which will be ignored by the browser.
// TODO: In the future, we hope to run this entire script through Vite,
// removing the need to maintain our own custom Vite-mimic resolve logic.
if (specifier === 'astro:scripts/before-hydration.js') {
if (specifier === BEFORE_HYDRATION_SCRIPT_ID) {
return 'data:text/javascript;charset=utf-8,//[no before-hydration script]';
}
throw new Error(`Cannot find the built path for ${specifier}`);
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/core/build/vite-plugin-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { serializeRouteData } from '../routing/index.js';
import { eachPageData } from './internal.js';
import { addRollupInput } from './add-rollup-input.js';
import { virtualModuleId as pagesVirtualModuleId } from './vite-plugin-pages.js';
import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';

export const virtualModuleId = '@astrojs-ssr-virtual-entry';
const resolvedVirtualModuleId = '\0' + virtualModuleId;
Expand Down Expand Up @@ -88,7 +89,7 @@ function buildManifest(opts: StaticBuildOptions, internals: BuildInternals): Ser

// HACK! Patch this special one.
const entryModules = Object.fromEntries(internals.entrySpecifierToBundleMap.entries());
entryModules['astro:scripts/before-hydration.js'] = 'data:text/javascript;charset=utf-8,//[no before-hydration script]';
entryModules[BEFORE_HYDRATION_SCRIPT_ID] = 'data:text/javascript;charset=utf-8,//[no before-hydration script]';

const ssrManifest: SerializedSSRManifest = {
routes,
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/runtime/server/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ export async function generateHydrateScript(scriptOptions: HydrateScriptOptions,
: `await import("${await result.resolve(componentUrl)}");
return () => {};
`;

// TODO: If we can figure out tree-shaking in the final SSR build, we could safely
// use BEFORE_HYDRATION_SCRIPT_ID instead of 'astro:scripts/before-hydration.js'.
const hydrationScript = {
props: { type: 'module', 'data-astro-component-hydration': true },
children: `import setup from '${await result.resolve(hydrationSpecifier(hydrate))}';
Expand Down
7 changes: 4 additions & 3 deletions packages/astro/src/vite-plugin-astro/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { cachedCompilation } from './compile.js';
import ancestor from 'common-ancestor-path';
import { trackCSSDependencies, handleHotUpdate } from './hmr.js';
import { isRelativePath, startsWithForwardSlash } from '../core/path.js';
import { PAGE_SCRIPT_ID, PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';

const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms;
interface AstroPluginOptions {
Expand Down Expand Up @@ -93,9 +94,9 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
const filename = normalizeFilename(parsedId.filename);
const fileUrl = new URL(`file://${filename}`);
let source = await fs.promises.readFile(fileUrl, 'utf-8');
const isPage = filename.startsWith(config.pages.pathname);
const isPage = fileUrl.pathname.startsWith(config.pages.pathname);
if (isPage && config._ctx.scripts.some((s) => s.stage === 'page')) {
source += `\n<script hoist src="astro:scripts/page.js" />`;
source += `\n<script hoist src="${PAGE_SCRIPT_ID}" />`;
}
if (query.astro) {
if (query.type === 'style') {
Expand Down Expand Up @@ -152,7 +153,7 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
}
// Add handling to inject scripts into each page JS bundle, if needed.
if (isPage) {
SUFFIX += `\nimport "astro:scripts/page-ssr.js";`;
SUFFIX += `\nimport "${PAGE_SSR_SCRIPT_ID}";`;
}
return {
code: `${code}${SUFFIX}`,
Expand Down
17 changes: 9 additions & 8 deletions packages/astro/src/vite-plugin-markdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import esbuild from 'esbuild';
import fs from 'fs';
import type { Plugin } from 'vite';
import type { AstroConfig } from '../@types/astro';
import { PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';

interface AstroPluginOptions {
config: AstroConfig;
Expand All @@ -27,7 +28,7 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
enforce: 'pre', // run transforms before other plugins can
async load(id) {
if (id.endsWith('.md')) {
let source = await fs.promises.readFile(id, 'utf8');
const source = await fs.promises.readFile(id, 'utf8');

// Transform from `.md` to valid `.astro`
let render = config.markdownOptions.render;
Expand All @@ -42,13 +43,20 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
let renderResult = await render(source, renderOpts);
let { frontmatter, metadata, code: astroResult } = renderResult;

const filename = normalizeFilename(id);
const fileUrl = new URL(`file://${filename}`);
const isPage = fileUrl.pathname.startsWith(config.pages.pathname);
const hasInjectedScript = isPage && config._ctx.scripts.some((s) => s.stage === 'page-ssr');

// Extract special frontmatter keys
const { layout = '', components = '', setup = '', ...content } = frontmatter;
content.astro = metadata;
const prelude = `---
${layout ? `import Layout from '${layout}';` : ''}
${components ? `import * from '${components}';` : ''}
${hasInjectedScript ? `import '${PAGE_SSR_SCRIPT_ID}';` : ''}
${setup}
const $$content = ${JSON.stringify(content)}
---`;
const imports = `${layout ? `import Layout from '${layout}';` : ''}
Expand All @@ -60,13 +68,6 @@ ${setup}`.trim();
astroResult = `${prelude}\n${astroResult}`;
}

const filename = normalizeFilename(id);
const fileUrl = new URL(`file://${filename}`);
const isPage = filename.startsWith(config.pages.pathname);
if (isPage && config._ctx.scripts.some((s) => s.stage === 'page')) {
source += `\n<script hoist src="astro:scripts/page.js" />`;
}

// Transform from `.astro` to valid `.ts`
let { code: tsResult } = await transform(astroResult, {
pathname: fileUrl.pathname.substr(config.projectRoot.pathname.length - 1),
Expand Down
8 changes: 4 additions & 4 deletions packages/astro/src/vite-plugin-scripts/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Plugin as VitePlugin } from 'vite';
import { AstroConfig } from '../@types/astro.js';
import { AstroConfig, InjectedScriptStage } from '../@types/astro.js';

// NOTE: We can't use the virtual "\0" ID convention because we need to
// inject these as ESM imports into actual code, where they would not
// resolve correctly.
const SCRIPT_ID_PREFIX = `astro:scripts/`;
const BEFORE_HYDRATION_SCRIPT_ID = `${SCRIPT_ID_PREFIX}before-hydration.js`;
const PAGE_SCRIPT_ID = `${SCRIPT_ID_PREFIX}page.js`;
const PAGE_SSR_SCRIPT_ID = `${SCRIPT_ID_PREFIX}page-ssr.js`;
export const BEFORE_HYDRATION_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${'before-hydration' as InjectedScriptStage}.js`;
export const PAGE_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${'page' as InjectedScriptStage}.js`;
export const PAGE_SSR_SCRIPT_ID = `${SCRIPT_ID_PREFIX}${'page-ssr' as InjectedScriptStage}.js`;

export default function astroScriptsPlugin({ config }: { config: AstroConfig }): VitePlugin {
return {
Expand Down
13 changes: 10 additions & 3 deletions packages/astro/test/errors.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isWindows, loadFixture } from './test-utils.js';
import { expect } from 'chai';

describe('Error display', () => {
if (isWindows) return;
Expand All @@ -12,15 +13,21 @@ describe('Error display', () => {
});
});

describe('Astro', () => {
it('properly detect syntax errors in template', async () => {
describe('Astro', async () => {
// This test is skipped because it will hang on vite@2.8.x
// TODO: unskip test once vite@2.9.x lands
// See pre-integration system test: https://github.com/withastro/astro/blob/0f376a7c52d3a22ff32b33e0afc34dd306ed70c4/packages/astro/test/errors.test.js
it.skip('properly detect syntax errors in template', async () => {
try {
devServer = await fixture.startDevServer();
} catch (err) {
return;
}

// This is new behavior in vite@2.9.x, previously the server would throw on startup
const res = await fixture.fetch('/astro-syntax-error');
await devServer.stop();
throw new Error('Expected to throw on startup');
expect(res.status).to.equal(500, `Successfully responded with 500 Error for invalid file`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
// Component Imports
import Button from '../components/Button.astro';
import Complex from '../components/Complex.astro';
import "../styles/global.css";
// Full Astro Component Syntax:
// https://docs.astro.build/core-concepts/astro-components/
---

<html lang="en">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: "Markdown + Tailwind"
setup: |
import Button from '../components/Button.astro';
import Complex from '../components/Complex.astro';
---

<div class="grid place-items-center h-screen content-center">
<Button>Tailwind Button in Markdown!</Button>
<Complex />
</div>

This file was deleted.

12 changes: 10 additions & 2 deletions packages/astro/test/tailwindcss.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ describe('Tailwind', () => {
expect(button.hasClass('w-10/12'), 'solidus').to.be.true;
expect(button.hasClass('2xl:w-[80%]'), 'complex class').to.be.true;
});

it('handles Markdown pages', async () => {
const html = await fixture.readFile('/markdown-page/index.html');
const $ = cheerio.load(html);
const bundledCSSHREF = $('link[rel=stylesheet][href^=/assets/]').attr('href');
const bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/'));
expect(bundledCSS, 'includes used component classes').to.match(/\.bg-purple-600{/);
});
});

// with "build" handling CSS checking, the dev tests are mostly testing the paths resolve in dev
Expand All @@ -73,8 +81,8 @@ describe('Tailwind', () => {
});

it('resolves CSS in src/styles', async () => {
const href = $(`link[href$="/src/styles/global.css"]`).attr('href');
const res = await fixture.fetch(href);
const bundledCSSHREF = $('link[rel=stylesheet]').attr('href');
const res = await fixture.fetch(bundledCSSHREF);
expect(res.status).to.equal(200);

const text = await res.text();
Expand Down

0 comments on commit bbdfc50

Please sign in to comment.