diff --git a/.changeset/purple-glasses-pretend.md b/.changeset/purple-glasses-pretend.md
new file mode 100644
index 000000000000..bfba17393b76
--- /dev/null
+++ b/.changeset/purple-glasses-pretend.md
@@ -0,0 +1,14 @@
+---
+'astro': minor
+---
+
+Return raw `html` when calling `render()` on a markdown content.
+
+```astro
+---
+const entry = await getEntryBySlug('blog', 'my-first-post');
+const { html } = await entry.render();
+---
+
+
+```
diff --git a/packages/astro/src/content/internal.ts b/packages/astro/src/content/internal.ts
index 04280166feb3..be21885b0816 100644
--- a/packages/astro/src/content/internal.ts
+++ b/packages/astro/src/content/internal.ts
@@ -175,9 +175,16 @@ async function render({
propagation: 'self',
});
- return {
+ // This should match the RenderResult type from template/types.d.ts
+ const renderResult: Record = {
Content,
headings: mod.getHeadings(),
remarkPluginFrontmatter: mod.frontmatter,
};
+
+ if (!id.endsWith('mdx')) {
+ renderResult.html = mod.compiledContent();
+ }
+
+ return renderResult;
}
diff --git a/packages/astro/src/content/template/types.d.ts b/packages/astro/src/content/template/types.d.ts
index f14a541f1e8a..7eaa5c6300fa 100644
--- a/packages/astro/src/content/template/types.d.ts
+++ b/packages/astro/src/content/template/types.d.ts
@@ -1,7 +1,7 @@
declare module 'astro:content' {
export { z } from 'astro/zod';
export type CollectionEntry =
- (typeof entryMap)[C][keyof (typeof entryMap)[C]] & Render;
+ (typeof entryMap)[C][keyof (typeof entryMap)[C]];
type BaseSchemaWithoutEffects =
| import('astro/zod').AnyZodObject
@@ -57,13 +57,17 @@ declare module 'astro:content' {
Required['schema']
>;
- type Render = {
- render(): Promise<{
- Content: import('astro').MarkdownInstance<{}>['Content'];
- headings: import('astro').MarkdownHeading[];
- remarkPluginFrontmatter: Record;
- }>;
- };
+ interface RenderResult {
+ Content: import('astro').MarkdownInstance<{}>['Content'];
+ headings: import('astro').MarkdownHeading[];
+ remarkPluginFrontmatter: Record;
+ html: undefined;
+ }
+ interface RenderResultWithHtml extends RenderResult {
+ html: string;
+ }
+ type Render = () => Promise;
+ type RenderWithHtml = () => Promise;
const entryMap: {
// @@ENTRY_MAP@@
diff --git a/packages/astro/src/content/types-generator.ts b/packages/astro/src/content/types-generator.ts
index b6f359b2cd85..de0d6bce2d9f 100644
--- a/packages/astro/src/content/types-generator.ts
+++ b/packages/astro/src/content/types-generator.ts
@@ -326,7 +326,8 @@ async function writeContentFiles({
const entryMetadata = contentTypes[collectionKey][entryKey];
const dataType = collectionConfig?.schema ? `InferEntrySchema<${collectionKey}>` : 'any';
const slugType = JSON.stringify(entryMetadata.slug);
- contentTypesStr += `${entryKey}: {\n id: ${entryKey},\n slug: ${slugType},\n body: string,\n collection: ${collectionKey},\n data: ${dataType}\n},\n`;
+ const renderType = JSON.parse(entryKey).endsWith('.mdx') ? 'Render' : 'RenderWithHtml';
+ contentTypesStr += `${entryKey}: {\n id: ${entryKey},\n slug: ${slugType},\n body: string,\n collection: ${collectionKey},\n data: ${dataType},\n render: ${renderType}\n},\n`;
}
contentTypesStr += `},\n`;
}
diff --git a/packages/astro/test/content-collections-render.test.js b/packages/astro/test/content-collections-render.test.js
index da14a4765f05..b47c191b7720 100644
--- a/packages/astro/test/content-collections-render.test.js
+++ b/packages/astro/test/content-collections-render.test.js
@@ -80,6 +80,13 @@ describe('Content Collections - render()', () => {
expect(h2).to.have.a.lengthOf(1);
expect(h2.attr('data-components-export-applied')).to.equal('true');
});
+
+ it('Renders with raw html for markdown content', async () => {
+ const html = await fixture.readFile('/render-with-html/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('p').text()).to.equal('This is a post');
+ });
});
describe('Build - SSR', () => {
@@ -131,6 +138,16 @@ describe('Content Collections - render()', () => {
expect(h2).to.have.a.lengthOf(1);
expect(h2.attr('data-components-export-applied')).to.equal('true');
});
+
+ it('Renders with raw html for markdown content', async () => {
+ const app = await fixture.loadTestAdapterApp();
+ const request = new Request('http://example.com/render-with-html');
+ const response = await app.render(request);
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ expect($('p').text()).to.equal('This is a post');
+ });
});
describe('Dev - SSG', () => {
@@ -195,5 +212,15 @@ describe('Content Collections - render()', () => {
expect(h2).to.have.a.lengthOf(1);
expect(h2.attr('data-components-export-applied')).to.equal('true');
});
+
+ it('Renders with raw html for markdown content', async () => {
+ const response = await fixture.fetch('/render-with-html', { method: 'GET' });
+ expect(response.status).to.equal(200);
+
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ expect($('p').text()).to.equal('This is a post');
+ });
});
});
diff --git a/packages/astro/test/content-collections.test.js b/packages/astro/test/content-collections.test.js
index c8105184e83b..96779c9cbde8 100644
--- a/packages/astro/test/content-collections.test.js
+++ b/packages/astro/test/content-collections.test.js
@@ -129,6 +129,22 @@ describe('Content Collections', () => {
});
});
});
+
+ describe('Render HTML', () => {
+ let json;
+ before(async () => {
+ const rawJson = await fixture.readFile('/render-html.json');
+ json = JSON.parse(rawJson);
+ });
+
+ it('Renders HTML correctly', async () => {
+ expect(json).to.deep.equal({
+ one: 'one
',
+ three: 'three
',
+ two: 'two
',
+ });
+ });
+ });
});
const blogSlugToContents = {
diff --git a/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/one.md b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/one.md
new file mode 100644
index 000000000000..b8aad57f977a
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/one.md
@@ -0,0 +1 @@
+# one
diff --git a/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/three.md b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/three.md
new file mode 100644
index 000000000000..f49407daa8a3
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/three.md
@@ -0,0 +1 @@
+# three
diff --git a/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/two.md b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/two.md
new file mode 100644
index 000000000000..02f0d6c20b83
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/content/rss-markdown/two.md
@@ -0,0 +1 @@
+# two
diff --git a/packages/astro/test/fixtures/content-collections/src/pages/render-html.json.ts b/packages/astro/test/fixtures/content-collections/src/pages/render-html.json.ts
new file mode 100644
index 000000000000..39280ff2761c
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections/src/pages/render-html.json.ts
@@ -0,0 +1,12 @@
+import { getCollection } from 'astro:content';
+
+export async function get() {
+ const collection = await getCollection('rss-markdown')
+ const result = {}
+ await Promise.all(collection.map(async (item) => {
+ result[item.slug] = (await item.render()).html
+ }))
+ return {
+ body: JSON.stringify(result)
+ }
+}
diff --git a/packages/astro/test/fixtures/content/src/pages/render-with-html.astro b/packages/astro/test/fixtures/content/src/pages/render-with-html.astro
new file mode 100644
index 000000000000..887040f08774
--- /dev/null
+++ b/packages/astro/test/fixtures/content/src/pages/render-with-html.astro
@@ -0,0 +1,14 @@
+---
+import { getEntryBySlug } from 'astro:content';
+
+const entry = await getEntryBySlug('blog', 'one');
+const { html } = await entry.render();
+---
+
+
+ Launch Week
+
+
+
+
+