diff --git a/.gitignore b/.gitignore index 83786476b8..8136f5eb09 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ lib/ dist/ *.tsbuildinfo .DS_Store +test/fixtures/*/_site/ diff --git a/src/build/bundle.ts b/src/build/bundle.ts index e447097a2c..a0f61289e6 100644 --- a/src/build/bundle.ts +++ b/src/build/bundle.ts @@ -8,6 +8,7 @@ import esbuild from 'esbuild'; import { promises as fsPromises } from 'fs'; import { parse } from '../parser/index.js'; import { transform } from '../compiler/transform/index.js'; +import { convertMdToAstroSource } from '../compiler/index.js'; import { getAttrValue } from '../ast.js'; import { walk } from 'estree-walker'; import babelParser from '@babel/parser'; @@ -72,12 +73,17 @@ export async function collectDynamicImports(filename: URL, { astroConfig, loggin const imports = new Set(); // Only astro files - if (!filename.pathname.endsWith('astro')) { + if (!filename.pathname.endsWith('.astro') && !filename.pathname.endsWith('.md')) { return imports; } const extensions = astroConfig.extensions || defaultExtensions; - const source = await readFile(filename, 'utf-8'); + + let source = await readFile(filename, 'utf-8'); + if (filename.pathname.endsWith('.md')) { + source = await convertMdToAstroSource(source); + } + const ast = parse(source, { filename, }); diff --git a/src/compiler/index.ts b/src/compiler/index.ts index c20596f65f..d2d7bff084 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -48,13 +48,9 @@ async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): P } /** - * .md -> .jsx - * Core function processing Markdown, but along the way also calls convertAstroToJsx(). + * .md -> .astro source */ -async function convertMdToJsx( - contents: string, - { compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string } -): Promise { +export async function convertMdToAstroSource(contents: string): Promise { const { data: frontmatterData, content } = matter(contents); const { headers, headersExtension } = createMarkdownHeadersCollector(); const { htmlAstro, mdAstro } = encodeAstroMdx(); @@ -80,15 +76,24 @@ async function convertMdToJsx( // Break it up here so that the HTML parser won't detect it. const stringifiedSetupContext = JSON.stringify(contentData).replace(/\<\/script\>/g, ``); - const raw = `--- + return `--- ${imports} ${frontmatterData.layout ? `import {__renderPage as __layout} from '${frontmatterData.layout}';` : 'const __layout = undefined;'} export const __content = ${stringifiedSetupContext}; ---
${mdHtml}
`; +} +/** + * .md -> .jsx + * Core function processing Markdown, but along the way also calls convertAstroToJsx(). + */ +async function convertMdToJsx( + contents: string, + { compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string } +): Promise { + const raw = await convertMdToAstroSource(contents); const convertOptions = { compileOptions, filename, fileID }; - return await convertAstroToJsx(raw, convertOptions); } diff --git a/test/astro-markdown.test.js b/test/astro-markdown.test.js index 572569466a..1651a0a6f8 100644 --- a/test/astro-markdown.test.js +++ b/test/astro-markdown.test.js @@ -1,15 +1,22 @@ +import { existsSync, promises as fsPromises } from 'fs'; +import { join } from 'path'; import { suite } from 'uvu'; import * as assert from 'uvu/assert'; import { createRuntime } from '../lib/runtime.js'; +import { build } from '../lib/build.js'; import { loadConfig } from '../lib/config.js'; import { doc } from './test-utils.js'; +const { rmdir, readFile } = fsPromises; + const Markdown = suite('Astro Markdown'); -let runtime, setupError; +let runtime, setupError, fixturePath, astroConfig; Markdown.before(async () => { - const astroConfig = await loadConfig(new URL('./fixtures/astro-markdown', import.meta.url).pathname); + fixturePath = new URL('./fixtures/astro-markdown', import.meta.url).pathname; + + astroConfig = await loadConfig(fixturePath); const logging = { level: 'error', @@ -26,6 +33,7 @@ Markdown.before(async () => { Markdown.after(async () => { (await runtime) && runtime.shutdown(); + rmdir(join(fixturePath, '_site'), { recursive: true }); }); Markdown('No errors creating a runtime', () => { @@ -50,4 +58,13 @@ Markdown('Can load more complex jsxy stuff', async () => { assert.equal($el.text(), 'Hello world'); }); +Markdown('Bundles client-side JS for prod', async () => { + await build(astroConfig); + + const complexHtml = await readFile(join(fixturePath, './_site/complex/index.html'), 'utf-8'); + + assert.match(complexHtml, `import("/_astro/components/Counter.js"`); + assert.ok(existsSync(join(fixturePath, `./_site/_astro/components/Counter.js`)), 'Counter.jsx is bundled for prod'); +}); + Markdown.run(); diff --git a/test/fixtures/astro-markdown/astro/components/Counter.jsx b/test/fixtures/astro-markdown/astro/components/Counter.jsx new file mode 100644 index 0000000000..a75f858b51 --- /dev/null +++ b/test/fixtures/astro-markdown/astro/components/Counter.jsx @@ -0,0 +1,7 @@ +import { h } from 'preact'; +import { useState } from 'preact/hooks'; + +export default function () { + const [count, setCount] = useState(0); + return ; +} diff --git a/test/fixtures/astro-markdown/astro/pages/complex.md b/test/fixtures/astro-markdown/astro/pages/complex.md index ff7582c843..6367948b97 100644 --- a/test/fixtures/astro-markdown/astro/pages/complex.md +++ b/test/fixtures/astro-markdown/astro/pages/complex.md @@ -4,8 +4,10 @@ title: My Blog Post description: This is a post about some stuff. import: Hello: '../components/Hello.jsx' + Counter: '../components/Counter.jsx' --- ## Interesting Topic + \ No newline at end of file diff --git a/test/fixtures/astro-markdown/astro/pages/index.astro b/test/fixtures/astro-markdown/astro/pages/index.astro deleted file mode 100644 index e6b8a1235f..0000000000 --- a/test/fixtures/astro-markdown/astro/pages/index.astro +++ /dev/null @@ -1,14 +0,0 @@ ---- - export function setup() { - return {props: {}} - } ---- - - - - - - -

Hello world!

- -