server-side named slots

pull/787/head
Rich Harris 7 years ago
parent efe25555cf
commit 1ae3ab7bf9

@ -12,6 +12,8 @@ export class SsrGenerator extends Generator {
bindings: string[]; bindings: string[];
renderCode: string; renderCode: string;
elementDepth: number; // TODO is this necessary? appears to be unused elementDepth: number; // TODO is this necessary? appears to be unused
appendTargets: Record<string, string> | null;
appendTarget: string | null;
constructor( constructor(
parsed: Parsed, parsed: Parsed,
@ -24,6 +26,7 @@ export class SsrGenerator extends Generator {
this.bindings = []; this.bindings = [];
this.renderCode = ''; this.renderCode = '';
this.elementDepth = 0; this.elementDepth = 0;
this.appendTargets = null;
// in an SSR context, we don't need to include events, methods, oncreate or ondestroy // in an SSR context, we don't need to include events, methods, oncreate or ondestroy
const { templateProperties, defaultExport } = this; const { templateProperties, defaultExport } = this;
@ -59,7 +62,23 @@ export class SsrGenerator extends Generator {
} }
append(code: string) { append(code: string) {
this.renderCode += code; if (this.appendTarget) {
this.appendTargets[this.appendTarget] += code;
} else {
this.renderCode += code;
}
}
removeAppendTarget() {
this.appendTarget = this.appendTargets = null;
}
setAppendTarget(name: string) {
if (!this.appendTargets[name]) {
this.appendTargets[name] = '';
}
this.appendTarget = name;
} }
} }

@ -80,19 +80,25 @@ export default function visitComponent(
let open = `\${${expression}.render({${props}}`; let open = `\${${expression}.render({${props}}`;
if (node.children.length) { if (node.children.length) {
open += `, { slotted: { default: () => \``; generator.appendTargets = {};
} generator.setAppendTarget('default');
generator.append(open); generator.elementDepth += 1;
generator.elementDepth += 1; node.children.forEach((child: Node) => {
visit(generator, block, child);
});
node.children.forEach((child: Node) => { generator.elementDepth -= 1;
visit(generator, block, child);
});
generator.elementDepth -= 1; const slotted = Object.keys(generator.appendTargets)
.map(name => `${name}: () => \`${generator.appendTargets[name]}\``)
.join(', ');
const close = node.children.length ? `\` } })}` : ')}'; open += `, { slotted: { ${slotted} } }`;
generator.append(close); generator.setAppendTarget(null);
}
generator.append(open);
generator.append(')}');
} }

@ -47,6 +47,11 @@ export default function visitElement(
let openingTag = `<${node.name}`; let openingTag = `<${node.name}`;
let textareaContents; // awkward special case let textareaContents; // awkward special case
const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot');
if (slot) {
generator.setAppendTarget(slot.value[0].data);
}
node.attributes.forEach((attribute: Node) => { node.attributes.forEach((attribute: Node) => {
if (attribute.type !== 'Attribute') return; if (attribute.type !== 'Attribute') return;

@ -9,7 +9,11 @@ export default function visitSlot(
node: Node node: Node
) { ) {
// TODO named slots // TODO named slots
generator.append(`<slot>\${options && options.slotted && options.slotted.default ? options.slotted.default() : '`); const name = node.attributes.find((attribute: Node) => attribute.name);
const slotName = name && name.value[0].data || 'default';
generator.append(`<slot${slotName !== 'default' ? ` name='${slotName}'` : ''}>`);
generator.append(`\${options && options.slotted && options.slotted.${slotName} ? options.slotted.${slotName}() : '`);
generator.elementDepth += 1; generator.elementDepth += 1;

@ -1,5 +1,4 @@
export default { export default {
solo: true,
html: ` html: `
<div> <div>
<slot>Hello</slot> <slot>Hello</slot>

Loading…
Cancel
Save