Merge pull request #847 from sveltejs/gh-827

Don't slot elements inside custom elements
pull/851/head
Rich Harris 8 years ago committed by GitHub
commit 049fe59082

@ -2,6 +2,7 @@ import Block from './Block';
import { trimStart, trimEnd } from '../../utils/trim';
import { assign } from '../../shared/index.js';
import getStaticAttributeValue from '../../utils/getStaticAttributeValue';
import isChildOfComponent from '../shared/utils/isChildOfComponent';
import { DomGenerator } from './index';
import { Node } from '../../interfaces';
import { State } from './interfaces';
@ -340,7 +341,8 @@ const preprocessors = {
});
} else {
const slot = getStaticAttributeValue(node, 'slot');
if (slot) {
if (slot && isChildOfComponent(node, generator)) {
node.slotted = true;
// TODO validate slots — no nesting, no dynamic names...
const component = componentStack[componentStack.length - 1];
component._slots.add(slot);

@ -63,7 +63,7 @@ export default function visitElement(
const name = childState.parentNode;
const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot');
const parentNode = slot ?
const parentNode = node.slotted ?
`${componentStack[componentStack.length - 1].var}._slotted.${slot.value[0].data}` : // TODO this looks bonkers
state.parentNode;

@ -1,3 +1,5 @@
import getStaticAttributeValue from '../../utils/getStaticAttributeValue';
import isChildOfComponent from '../shared/utils/isChildOfComponent';
import { SsrGenerator } from './index';
import { Node } from '../../interfaces';
@ -62,6 +64,11 @@ const preprocessors = {
if (!isComponent) {
generator.stylesheet.apply(node, elementStack);
const slot = getStaticAttributeValue(node, 'slot');
if (slot && isChildOfComponent(node, generator)) {
node.slotted = true;
}
}
if (node.children.length) {
@ -80,6 +87,8 @@ function preprocessChildren(
elementStack: Node[]
) {
node.children.forEach((child: Node, i: number) => {
child.parent = node;
const preprocessor = preprocessors[child.type];
if (preprocessor) preprocessor(generator, child, elementStack);
});

@ -47,8 +47,8 @@ export default function visitElement(
let openingTag = `<${node.name}`;
let textareaContents; // awkward special case
const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot');
if (slot) {
if (node.slotted) {
const slot = node.attributes.find((attribute: Node) => attribute.name === 'slot');
const slotName = slot.value[0].data;
const appendTarget = generator.appendTargets[generator.appendTargets.length - 1];
appendTarget.slotStack.push(slotName);

@ -0,0 +1,13 @@
import { Node } from '../../../interfaces';
import Generator from '../../Generator';
export default function isChildOfComponent(node: Node, generator: Generator) {
while (node = node.parent) {
if (node.type !== 'Element') continue;
if (generator.components.has(node.name)) return true;
if (/-/.test(node.name)) return false;
}
// TODO do this in validation
throw new Error(`Element with a slot='...' attribute must be a descendant of a component or custom element`);
}

@ -0,0 +1,7 @@
export default {
html: `
<custom-element>
<header slot='header'>header header header</header>
</custom-element>
`
};

@ -0,0 +1,3 @@
<custom-element>
<header slot='header'>header header header</header>
</custom-element>
Loading…
Cancel
Save