Skip to content

Commit

Permalink
Support Astro.slots.render for mdx (#4973)
Browse files Browse the repository at this point in the history
* Support Astro.slots.render for mdx

* Remove extra imports
  • Loading branch information
bluwy authored Oct 4, 2022
1 parent 5d58787 commit c733d4f
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/friendly-wolves-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Support Astro.slots.render for mdx
11 changes: 9 additions & 2 deletions packages/astro/src/core/render/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
SSRResult,
} from '../../@types/astro';
import { renderSlot } from '../../runtime/server/index.js';
import { renderJSX } from '../../runtime/server/jsx.js';
import { AstroCookies } from '../cookies/index.js';
import { LogOptions, warn } from '../logger/core.js';
import { isScriptRequest } from './script.js';
Expand Down Expand Up @@ -94,21 +95,27 @@ class Slots {
if (!this.has(name)) return undefined;
if (!cacheable) {
const component = await this.#slots[name]();
const expression = getFunctionExpression(component);

if (!Array.isArray(args)) {
warn(
this.#loggingOpts,
'Astro.slots.render',
`Expected second parameter to be an array, received a ${typeof args}. If you're trying to pass an array as a single argument and getting unexpected results, make sure you're passing your array as a item of an array. Ex: Astro.slots.render('default', [["Hello", "World"]])`
);
} else {
// Astro
const expression = getFunctionExpression(component);
if (expression) {
const slot = expression(...args);
return await renderSlot(this.#result, slot).then((res) =>
res != null ? String(res) : res
);
}
// JSX
if (typeof component === 'function') {
return await renderJSX(this.#result, component(...args)).then((res) =>
res != null ? String(res) : res
);
}
}
}
const content = await renderSlot(this.#result, this.#slots[name]).then((res) =>
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/runtime/server/jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export async function renderJSX(result: SSRResult, vnode: any): Promise<any> {
return vnode;
case typeof vnode === 'string':
return markHTMLString(escapeHTML(vnode));
case typeof vnode === 'function':
return vnode;
case !vnode && vnode !== 0:
return '';
case Array.isArray(vnode):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
const { id } = Astro.props;
const content = await Astro.slots.render('default');
---

<div id={id} set:html={content} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
const { id, text } = Astro.props;
---

<div id={id} set:html={Astro.slots.render('default', [text])} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
const { id } = Astro.props;
const content = await Astro.slots.render('default');
---

<div id={id} set:html={content} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Render from '../components/Render.astro';
import RenderFn from '../components/RenderFn.astro';
import RenderArgs from '../components/RenderArgs.astro';

# Slots: MDX

<Render id="render">render</Render>
<RenderFn id="render-fn">{() => "render-fn"}</RenderFn>
<RenderArgs id="render-args" text="render-args">{(text) => <span>{text}</span>}</RenderArgs>
27 changes: 27 additions & 0 deletions packages/astro/test/slots-react.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,31 @@ describe('Slots: React', () => {
expect($('#dash-case').text().trim()).to.equal('Fallback / Dash Case');
});
});

describe('Slots.render() API', async () => {
it('Simple imperative slot render', async () => {
const html = await fixture.readFile('/slottedapi-render/index.html');
const $ = cheerio.load(html);

expect($('#render')).to.have.lengthOf(1);
expect($('#render').text()).to.equal('render');
});

it('Child function render without args', async () => {
const html = await fixture.readFile('/slottedapi-render/index.html');
const $ = cheerio.load(html);

expect($('#render-fn')).to.have.lengthOf(1);
expect($('#render-fn').text()).to.equal('render-fn');
});

it('Child function render with args', async () => {
const html = await fixture.readFile('/slottedapi-render/index.html');
const $ = cheerio.load(html);

expect($('#render-args')).to.have.lengthOf(1);
expect($('#render-args span')).to.have.lengthOf(1);
expect($('#render-args').text()).to.equal('render-args');
});
});
});

0 comments on commit c733d4f

Please sign in to comment.