Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return html when render markdown content #6097

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/purple-glasses-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'astro': minor
---

Return raw `html` when calling `render()` on a markdown content.
bluwy marked this conversation as resolved.
Show resolved Hide resolved

```astro
---
const entry = await getEntryBySlug('blog', 'my-first-post');
const { html } = await entry.render();
---

<div set:html={html}></div>
```
9 changes: 8 additions & 1 deletion packages/astro/src/content/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,16 @@ async function render({
propagation: 'self',
});

return {
// This should match the RenderResult type from template/types.d.ts
const renderResult: Record<string, any> = {
Content,
headings: mod.getHeadings(),
remarkPluginFrontmatter: mod.frontmatter,
};

if (!id.endsWith('mdx')) {
renderResult.html = mod.compiledContent();
}

return renderResult;
}
17 changes: 10 additions & 7 deletions packages/astro/src/content/template/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
declare module 'astro:content' {
export { z } from 'astro/zod';
export type CollectionEntry<C extends keyof typeof entryMap> =
(typeof entryMap)[C][keyof (typeof entryMap)[C]] & Render;
(typeof entryMap)[C][keyof (typeof entryMap)[C]];

type BaseSchemaWithoutEffects =
| import('astro/zod').AnyZodObject
Expand Down Expand Up @@ -57,13 +57,16 @@ declare module 'astro:content' {
Required<ContentConfig['collections'][C]>['schema']
>;

type Render = {
render(): Promise<{
Content: import('astro').MarkdownInstance<{}>['Content'];
headings: import('astro').MarkdownHeading[];
remarkPluginFrontmatter: Record<string, any>;
}>;
type RenderResult = {
Content: import('astro').MarkdownInstance<{}>['Content'];
headings: import('astro').MarkdownHeading[];
remarkPluginFrontmatter: Record<string, any>;
};
type RenderResultWithHtml = RenderResult & {
html: string;
};
type Render = () => Promise<RenderResult>;
type RenderWithHtml = () => Promise<RenderResultWithHtml>;

const entryMap: {
// @@ENTRY_MAP@@
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/content/types-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
}
Expand Down
27 changes: 27 additions & 0 deletions packages/astro/test/content-collections-render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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');
});
});
});
bluwy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
import { getEntryBySlug } from 'astro:content';

const entry = await getEntryBySlug('blog', 'one');
const { html } = await entry.render();
---
<html>
<head>
<title>Launch Week</title>
</head>
<body>
<main set:html={html} />
</body>
</html>