fix: bundle client-side code for components used in .md pages (#78)
This commit is contained in:
parent
b588581396
commit
ac22d94e11
7 changed files with 50 additions and 26 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ lib/
|
|||
dist/
|
||||
*.tsbuildinfo
|
||||
.DS_Store
|
||||
test/fixtures/*/_site/
|
||||
|
|
|
@ -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<string>();
|
||||
|
||||
// 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,
|
||||
});
|
||||
|
|
|
@ -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<TransformResult> {
|
||||
export async function convertMdToAstroSource(contents: string): Promise<string> {
|
||||
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, `</scrip" + "t>`);
|
||||
|
||||
const raw = `---
|
||||
return `---
|
||||
${imports}
|
||||
${frontmatterData.layout ? `import {__renderPage as __layout} from '${frontmatterData.layout}';` : 'const __layout = undefined;'}
|
||||
export const __content = ${stringifiedSetupContext};
|
||||
---
|
||||
<section>${mdHtml}</section>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* .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<TransformResult> {
|
||||
const raw = await convertMdToAstroSource(contents);
|
||||
const convertOptions = { compileOptions, filename, fileID };
|
||||
|
||||
return await convertAstroToJsx(raw, convertOptions);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
7
test/fixtures/astro-markdown/astro/components/Counter.jsx
vendored
Normal file
7
test/fixtures/astro-markdown/astro/components/Counter.jsx
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { h } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
|
||||
export default function () {
|
||||
const [count, setCount] = useState(0);
|
||||
return <button onClick={() => setCount(count + 1)}>{count}</button>;
|
||||
}
|
|
@ -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
|
||||
|
||||
<Hello name={`world`} />
|
||||
<Counter:load />
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
export function setup() {
|
||||
return {props: {}}
|
||||
}
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Head Stuff -->
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello world!</h1>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue