diff --git a/packages/astro/package.json b/packages/astro/package.json
index 474faa1f410d..5d227208d346 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -239,4 +239,4 @@
"publishConfig": {
"provenance": true
}
-}
+}
\ No newline at end of file
diff --git a/packages/astro/src/content/loaders/glob.ts b/packages/astro/src/content/loaders/glob.ts
index 578f13057baf..4a4ecbcac8d3 100644
--- a/packages/astro/src/content/loaders/glob.ts
+++ b/packages/astro/src/content/loaders/glob.ts
@@ -128,17 +128,7 @@ export function glob(globOptions: GlobOptions): Loader {
data,
filePath,
});
-
- if (entryType.extensions.includes('.mdx')) {
- store.set({
- id,
- data: parsedData,
- body,
- filePath: relativePath,
- digest,
- deferredRender: true,
- });
- } else if (entryType.getRenderFunction) {
+ if (entryType.getRenderFunction) {
let render = renderFunctionByContentType.get(entryType);
if (!render) {
render = await entryType.getRenderFunction(settings);
@@ -170,6 +160,16 @@ export function glob(globOptions: GlobOptions): Loader {
if (rendered?.metadata?.imagePaths?.length) {
store.addAssetImports(rendered.metadata.imagePaths, relativePath);
}
+ // todo: add an explicit way to opt in to deferred rendering
+ } else if ('contentModuleTypes' in entryType) {
+ store.set({
+ id,
+ data: parsedData,
+ body,
+ filePath: relativePath,
+ digest,
+ deferredRender: true,
+ });
} else {
store.set({ id, data: parsedData, body, filePath: relativePath, digest });
}
diff --git a/packages/astro/test/content-layer-markdoc.test.js b/packages/astro/test/content-layer-markdoc.test.js
new file mode 100644
index 000000000000..c5279b9e7522
--- /dev/null
+++ b/packages/astro/test/content-layer-markdoc.test.js
@@ -0,0 +1,88 @@
+import assert from 'node:assert/strict';
+import { after, before, describe, it } from 'node:test';
+import * as cheerio from 'cheerio';
+import { loadFixture } from './test-utils.js';
+
+describe('Content layer markdoc', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/content-layer-markdoc/',
+ });
+ });
+
+ describe('dev', () => {
+ let devServer;
+
+ before(async () => {
+ devServer = await fixture.startDevServer();
+ });
+
+ after(async () => {
+ await devServer.stop();
+ });
+
+ it('renders content - with components', async () => {
+ const res = await fixture.fetch('/');
+ const html = await res.text();
+
+ renderComponentsChecks(html);
+ });
+
+ it('renders content - with components inside partials', async () => {
+ const res = await fixture.fetch('/');
+ const html = await res.text();
+
+ renderComponentsInsidePartialsChecks(html);
+ });
+ });
+
+ describe('build', () => {
+ before(async () => {
+ await fixture.build();
+ });
+
+ it('renders content - with components', async () => {
+ const html = await fixture.readFile('/index.html');
+
+ renderComponentsChecks(html);
+ });
+
+ it('renders content - with components inside partials', async () => {
+ const html = await fixture.readFile('/index.html');
+
+ renderComponentsInsidePartialsChecks(html);
+ });
+ });
+});
+
+/** @param {string} html */
+function renderComponentsChecks(html) {
+ const $ = cheerio.load(html);
+ const h2 = $('h2');
+ assert.equal(h2.text(), 'Post with components');
+
+ // Renders custom shortcode component
+ const marquee = $('marquee');
+ assert.notEqual(marquee, null);
+ assert.equal(marquee.attr('data-custom-marquee'), '');
+
+ // Renders Astro Code component
+ const pre = $('pre');
+ assert.notEqual(pre, null);
+ assert.ok(pre.hasClass('github-dark'));
+ assert.ok(pre.hasClass('astro-code'));
+}
+
+/** @param {string} html */
+function renderComponentsInsidePartialsChecks(html) {
+ const $ = cheerio.load(html);
+ // renders Counter.tsx
+ const button = $('#counter');
+ assert.equal(button.text(), '1');
+
+ // renders DeeplyNested.astro
+ const deeplyNested = $('#deeply-nested');
+ assert.equal(deeplyNested.text(), 'Deeply nested partial');
+}
diff --git a/packages/astro/test/content-layer-render.test.js b/packages/astro/test/content-layer-render.test.js
index ab38bb1da2b4..fa743e719ca4 100644
--- a/packages/astro/test/content-layer-render.test.js
+++ b/packages/astro/test/content-layer-render.test.js
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { loadFixture } from './test-utils.js';
-describe('Content Layer dev', () => {
+describe('Content Layer MDX rendering dev', () => {
/** @type {import("./test-utils.js").Fixture} */
let fixture;
@@ -10,7 +10,6 @@ describe('Content Layer dev', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/content-layer-rendering/',
- cacheDir: './fixtures/content-layer-rendering/.cache',
});
devServer = await fixture.startDevServer();
});
@@ -27,13 +26,12 @@ describe('Content Layer dev', () => {
});
});
-describe('Content Layer build', () => {
+describe('Content Layer MDX rendering build', () => {
/** @type {import("./test-utils.js").Fixture} */
let fixture;
before(async () => {
fixture = await loadFixture({
root: './fixtures/content-layer-rendering/',
- cacheDir: './fixtures/content-layer-rendering/.cache',
});
await fixture.build();
});
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/astro.config.mjs b/packages/astro/test/fixtures/content-layer-markdoc/astro.config.mjs
new file mode 100644
index 000000000000..bbb19ad302db
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/astro.config.mjs
@@ -0,0 +1,9 @@
+import markdoc from '@astrojs/markdoc';
+import preact from '@astrojs/preact';
+import { defineConfig } from 'astro/config';
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [markdoc(), preact()],
+ experimental: { contentLayer: true }
+});
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/content/_nested.mdoc b/packages/astro/test/fixtures/content-layer-markdoc/content/_nested.mdoc
new file mode 100644
index 000000000000..68f529280124
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/content/_nested.mdoc
@@ -0,0 +1,3 @@
+Render components from a deeply nested partial:
+
+{% deeply-nested /%}
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/content/blog/_counter.mdoc b/packages/astro/test/fixtures/content-layer-markdoc/content/blog/_counter.mdoc
new file mode 100644
index 000000000000..4a015695c68e
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/content/blog/_counter.mdoc
@@ -0,0 +1,7 @@
+# Hello from a partial!
+
+Render a component from a partial:
+
+{% counter /%}
+
+{% partial file="../_nested.mdoc" /%}
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/content/blog/with-components.mdoc b/packages/astro/test/fixtures/content-layer-markdoc/content/blog/with-components.mdoc
new file mode 100644
index 000000000000..eb7d20426e59
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/content/blog/with-components.mdoc
@@ -0,0 +1,19 @@
+---
+title: Post with components
+---
+
+## Post with components
+
+This uses a custom marquee component with a shortcode:
+
+{% marquee-element direction="right" %}
+I'm a marquee too!
+{% /marquee-element %}
+
+{% partial file="_counter.mdoc" /%}
+
+And a code component for code blocks:
+
+```js
+const isRenderedWithShiki = true;
+```
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/markdoc.config.ts b/packages/astro/test/fixtures/content-layer-markdoc/markdoc.config.ts
new file mode 100644
index 000000000000..6093ec5938a5
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/markdoc.config.ts
@@ -0,0 +1,32 @@
+import { Markdoc, component, defineMarkdocConfig } from '@astrojs/markdoc/config';
+
+export default defineMarkdocConfig({
+ nodes: {
+ fence: {
+ render: component('./src/components/Code.astro'),
+ attributes: {
+ language: { type: String },
+ content: { type: String },
+ },
+ },
+ },
+ tags: {
+ 'marquee-element': {
+ render: component('./src/components/CustomMarquee.astro'),
+ attributes: {
+ direction: {
+ type: String,
+ default: 'left',
+ matches: ['left', 'right', 'up', 'down'],
+ errorLevel: 'critical',
+ },
+ },
+ },
+ counter: {
+ render: component('./src/components/CounterWrapper.astro'),
+ },
+ 'deeply-nested': {
+ render: component('./src/components/DeeplyNested.astro'),
+ },
+ },
+});
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/package.json b/packages/astro/test/fixtures/content-layer-markdoc/package.json
new file mode 100644
index 000000000000..91ca2f8c9c00
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "@test/content-layer-markdoc",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/markdoc": "workspace:*",
+ "@astrojs/preact": "workspace:*",
+ "astro": "workspace:*",
+ "preact": "^10.23.1"
+ }
+}
\ No newline at end of file
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/src/components/Code.astro b/packages/astro/test/fixtures/content-layer-markdoc/src/components/Code.astro
new file mode 100644
index 000000000000..18bf1399f22e
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/src/components/Code.astro
@@ -0,0 +1,12 @@
+---
+import { Code } from 'astro/components';
+
+type Props = {
+ content: string;
+ language: string;
+}
+
+const { content, language } = Astro.props as Props;
+---
+
+
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/src/components/Counter.tsx b/packages/astro/test/fixtures/content-layer-markdoc/src/components/Counter.tsx
new file mode 100644
index 000000000000..f1e239718cf8
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/src/components/Counter.tsx
@@ -0,0 +1,10 @@
+import { useState } from 'preact/hooks';
+
+export default function Counter() {
+ const [count, setCount] = useState(1);
+ return (
+
+ );
+}
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/src/components/CounterWrapper.astro b/packages/astro/test/fixtures/content-layer-markdoc/src/components/CounterWrapper.astro
new file mode 100644
index 000000000000..e45ac6438152
--- /dev/null
+++ b/packages/astro/test/fixtures/content-layer-markdoc/src/components/CounterWrapper.astro
@@ -0,0 +1,5 @@
+---
+import Counter from './Counter';
+---
+
+
Deeply nested partial
diff --git a/packages/astro/test/fixtures/content-layer-markdoc/src/content/config.ts b/packages/astro/test/fixtures/content-layer-markdoc/src/content/config.ts new file mode 100644 index 000000000000..18ead9aa161f --- /dev/null +++ b/packages/astro/test/fixtures/content-layer-markdoc/src/content/config.ts @@ -0,0 +1,11 @@ +import { defineCollection } from 'astro:content'; +import { glob } from 'astro/loaders'; + +const blog = defineCollection({ + loader: glob({ + pattern: '*.mdoc', + base: 'content/blog', + }), +}); + +export const collections = { blog }; diff --git a/packages/astro/test/fixtures/content-layer-markdoc/src/pages/index.astro b/packages/astro/test/fixtures/content-layer-markdoc/src/pages/index.astro new file mode 100644 index 000000000000..5c7747eef923 --- /dev/null +++ b/packages/astro/test/fixtures/content-layer-markdoc/src/pages/index.astro @@ -0,0 +1,19 @@ +--- +import { getEntry, render } from "astro:content"; + +const post = await getEntry('blog', 'with-components'); +const { Content } = await render(post); +--- + + + + + + + +