mirror of https://github.com/sveltejs/svelte
parent
7578af3a11
commit
9acdaea3ab
@ -0,0 +1,50 @@
|
||||
import Component from '../Component';
|
||||
import Expression from './shared/Expression';
|
||||
import TemplateScope from './shared/TemplateScope';
|
||||
import Node from './shared/Node';
|
||||
import Let from './Let';
|
||||
import Attribute from './Attribute';
|
||||
import { INode } from './interfaces';
|
||||
import compiler_errors from '../compiler_errors';
|
||||
import get_const_tags from './shared/get_const_tags';
|
||||
import ConstTag from './ConstTag';
|
||||
import AbstractBlock from './shared/AbstractBlock';
|
||||
import { regex_only_whitespaces } from '../../utils/patterns';
|
||||
|
||||
|
||||
export default class SlotTemplateElseBlock extends AbstractBlock {
|
||||
type: 'SlotTemplateElseBlock';
|
||||
expression: Expression;
|
||||
scope: TemplateScope;
|
||||
const_tags: ConstTag[];
|
||||
|
||||
constructor(
|
||||
component: Component,
|
||||
parent: INode,
|
||||
scope: TemplateScope,
|
||||
info: any
|
||||
) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
|
||||
const children = [];
|
||||
for (const child of info.children) {
|
||||
if (child.type === 'SlotTemplate' || child.type === 'ConstTag') {
|
||||
children.push(child);
|
||||
} else if (child.type === 'Comment') {
|
||||
// ignore
|
||||
} else if (child.type === 'Text' && regex_only_whitespaces.test(child.data)) {
|
||||
// ignore
|
||||
} else if (child.type === 'IfBlock') {
|
||||
children.push({
|
||||
...child,
|
||||
type: 'SlotTemplateIfBlock'
|
||||
});
|
||||
} else {
|
||||
this.component.error(child, compiler_errors.invalid_mix_element_and_conditional_slot);
|
||||
}
|
||||
}
|
||||
|
||||
([this.const_tags, this.children] = get_const_tags(children, component, this, this));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
import SlotTemplateElseBlock from './SlotTemplateElseBlock';
|
||||
import Component from '../Component';
|
||||
import AbstractBlock from './shared/AbstractBlock';
|
||||
import Expression from './shared/Expression';
|
||||
import TemplateScope from './shared/TemplateScope';
|
||||
import Node from './shared/Node';
|
||||
import compiler_errors from '../compiler_errors';
|
||||
import get_const_tags from './shared/get_const_tags';
|
||||
import { TemplateNode } from '../../interfaces';
|
||||
import ConstTag from './ConstTag';
|
||||
import { regex_only_whitespaces } from '../../utils/patterns';
|
||||
import SlotTemplate from './SlotTemplate';
|
||||
import { INode } from './interfaces';
|
||||
|
||||
|
||||
export default class SlotTemplateIfBlock extends AbstractBlock {
|
||||
type: 'SlotTemplateIfBlock';
|
||||
expression: Expression;
|
||||
else: SlotTemplateElseBlock;
|
||||
scope: TemplateScope;
|
||||
const_tags: ConstTag[];
|
||||
slot_names = new Set<string>();
|
||||
|
||||
constructor(
|
||||
component: Component,
|
||||
parent: Node,
|
||||
scope: TemplateScope,
|
||||
info: TemplateNode
|
||||
) {
|
||||
super(component, parent, scope, info);
|
||||
this.scope = scope.child();
|
||||
|
||||
const children = [];
|
||||
for (const child of info.children) {
|
||||
if (child.type === 'SlotTemplate' || child.type === 'ConstTag') {
|
||||
children.push(child);
|
||||
} else if (child.type === 'Comment') {
|
||||
// ignore
|
||||
} else if (child.type === 'Text' && regex_only_whitespaces.test(child.data)) {
|
||||
// ignore
|
||||
} else if (child.type === 'IfBlock') {
|
||||
children.push({
|
||||
...child,
|
||||
type: 'SlotTemplateIfBlock'
|
||||
});
|
||||
} else {
|
||||
this.component.error(child, compiler_errors.invalid_mix_element_and_conditional_slot);
|
||||
}
|
||||
}
|
||||
|
||||
this.expression = new Expression(component, this, this.scope, info.expression);
|
||||
([this.const_tags, this.children] = get_const_tags(children, component, this, this));
|
||||
|
||||
this.else = info.else
|
||||
? new SlotTemplateElseBlock(component, this, scope, { ...info.else, type: 'SlotTemplateElseBlock' })
|
||||
: null;
|
||||
}
|
||||
|
||||
validate_duplicate_slot_name(component_name: string): Map<string, SlotTemplate> {
|
||||
const if_slot_names = validate_get_slot_names(this.children, this.component, component_name);
|
||||
if (!this.else) {
|
||||
return if_slot_names;
|
||||
}
|
||||
|
||||
const else_slot_names = validate_get_slot_names(this.else.children, this.component, component_name);
|
||||
return new Map([...if_slot_names, ...else_slot_names]);
|
||||
}
|
||||
}
|
||||
|
||||
export function validate_get_slot_names(children: Array<INode>, component: Component, component_name: string) {
|
||||
const slot_names = new Map<string, SlotTemplate>();
|
||||
function add_slot_name(slot_name: string, child: SlotTemplate) {
|
||||
if (slot_names.has(slot_name)) {
|
||||
component.error(child, compiler_errors.duplicate_slot_name_in_component(slot_name, component_name));
|
||||
}
|
||||
slot_names.set(slot_name, child);
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
if (child.type === 'SlotTemplateIfBlock') {
|
||||
const child_slot_names = child.validate_duplicate_slot_name(component_name);
|
||||
for (const [slot_name, child] of child_slot_names) {
|
||||
add_slot_name(slot_name, child);
|
||||
}
|
||||
} else if (child.type === 'SlotTemplate') {
|
||||
add_slot_name(child.slot_template_name, child);
|
||||
}
|
||||
}
|
||||
return slot_names;
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
import Wrapper from './shared/Wrapper';
|
||||
import Renderer from '../Renderer';
|
||||
import Block from '../Block';
|
||||
import { Identifier } from 'estree';
|
||||
import SlotTemplateIfBlock from '../../nodes/SlotTemplateIfBlock';
|
||||
import SlotTemplateWrapper from './SlotTemplate';
|
||||
import SlotTemplate from '../../nodes/SlotTemplate';
|
||||
import { b } from 'code-red';
|
||||
import InlineComponentWrapper from './InlineComponent';
|
||||
import TemplateScope from '../../nodes/shared/TemplateScope';
|
||||
|
||||
export default class SlotTemplateIfBlockWrapper extends Wrapper {
|
||||
node: SlotTemplateIfBlock;
|
||||
needs_update = false;
|
||||
|
||||
var: Identifier = { type: 'Identifier', name: 'if_block' };
|
||||
children: Array<SlotTemplateWrapper | SlotTemplateIfBlockWrapper> = [];
|
||||
else: Array<SlotTemplateWrapper | SlotTemplateIfBlockWrapper> = [];
|
||||
parent: SlotTemplateIfBlockWrapper | InlineComponentWrapper;
|
||||
scope: TemplateScope
|
||||
|
||||
constructor(
|
||||
renderer: Renderer,
|
||||
block: Block,
|
||||
parent: Wrapper,
|
||||
node: SlotTemplateIfBlock,
|
||||
strip_whitespace: boolean,
|
||||
next_sibling: Wrapper
|
||||
) {
|
||||
super(renderer, block, parent, node);
|
||||
this.scope = node.scope;
|
||||
|
||||
for (const child of this.node.children) {
|
||||
if (child.type === 'SlotTemplate') {
|
||||
this.children.push(new SlotTemplateWrapper(renderer, block, this, child as SlotTemplate, strip_whitespace, next_sibling));
|
||||
} else if (child.type === 'SlotTemplateIfBlock') {
|
||||
this.children.push(new SlotTemplateIfBlockWrapper(renderer, block, this, child as SlotTemplateIfBlock, strip_whitespace, next_sibling));
|
||||
}
|
||||
}
|
||||
|
||||
if (node.else) {
|
||||
for (const child of node.else.children) {
|
||||
if (child.type === 'SlotTemplate') {
|
||||
this.else.push(new SlotTemplateWrapper(renderer, block, this, child as SlotTemplate, strip_whitespace, next_sibling));
|
||||
} else if (child.type === 'SlotTemplateIfBlock') {
|
||||
this.else.push(new SlotTemplateIfBlockWrapper(renderer, block, this, child as SlotTemplateIfBlock, strip_whitespace, next_sibling));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render_slot_template_content(should_cache: boolean) {
|
||||
this.children.forEach(slot => slot.render_slot_template_content(should_cache));
|
||||
this.else.forEach(slot => slot.render_slot_template_content(should_cache));
|
||||
}
|
||||
|
||||
render_slot_template_definition(block: Block) {
|
||||
if (this.else.length > 0) {
|
||||
return b`
|
||||
if (${this.node.expression.manipulate(block, '#ctx')}) {
|
||||
${this.children.map(slot => slot.render_slot_template_definition(block))}
|
||||
} else {
|
||||
${this.else.map(slot => slot.render_slot_template_definition(block))}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
return b`
|
||||
if (${this.node.expression.manipulate(block, '#ctx')}) {
|
||||
${this.children.map(slot => slot.render_slot_template_definition(block))}
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
import Renderer from "../../Renderer";
|
||||
import SlotTemplateWrapper from "../SlotTemplate";
|
||||
import SlotTemplateIfBlockWrapper from "../SlotTemplateIfBlock";
|
||||
import is_dynamic from "./is_dynamic";
|
||||
|
||||
export function collect_slot_fragment_dependencies(
|
||||
renderer: Renderer,
|
||||
children: Array<SlotTemplateIfBlockWrapper | SlotTemplateWrapper>,
|
||||
fragment_dependencies: Set<string>
|
||||
) {
|
||||
function collect(
|
||||
children: Array<SlotTemplateWrapper | SlotTemplateIfBlockWrapper>
|
||||
) {
|
||||
for (const child of children) {
|
||||
if (child instanceof SlotTemplateIfBlockWrapper) {
|
||||
collect(child.children);
|
||||
collect(child.else);
|
||||
for (const dep of child.node.expression.dependencies) {
|
||||
const is_let = child.scope.is_let(dep);
|
||||
const variable = renderer.component.var_lookup.get(dep);
|
||||
if (is_let || is_dynamic(variable)) fragment_dependencies.add(dep);
|
||||
}
|
||||
} else {
|
||||
for (const dep of child.block.dependencies) {
|
||||
const is_let = child.scope.is_let(dep);
|
||||
const variable = renderer.component.var_lookup.get(dep);
|
||||
if (is_let || is_dynamic(variable)) fragment_dependencies.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
collect(children);
|
||||
}
|
||||
|
||||
export function collect_slot_dynamic_dependencies(children: Array<SlotTemplateIfBlockWrapper | SlotTemplateWrapper>) {
|
||||
const result = new Set<string>();
|
||||
|
||||
function collect(children: Array<SlotTemplateIfBlockWrapper | SlotTemplateWrapper>) {
|
||||
for (const child of children) {
|
||||
if (child instanceof SlotTemplateIfBlockWrapper) {
|
||||
for (const dep of child.node.expression.dynamic_dependencies()) {
|
||||
result.add(dep);
|
||||
}
|
||||
collect(child.children);
|
||||
collect(child.else);
|
||||
}
|
||||
}
|
||||
}
|
||||
collect(children);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<p><slot>Fallback</slot></p>
|
||||
@ -0,0 +1,27 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: '<p>Fallback</p>',
|
||||
test({ assert, component, target }) {
|
||||
component.value = 1;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<p>One</p>
|
||||
`);
|
||||
|
||||
component.value = 2;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<p>Two</p>
|
||||
`);
|
||||
|
||||
component.value = 3;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<p>Fallback</p>
|
||||
`);
|
||||
|
||||
component.value = 4;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<p>Fallback</p>
|
||||
`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let value;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if value === 1}
|
||||
<svelte:fragment>One</svelte:fragment>
|
||||
{:else if value === 2}
|
||||
<svelte:fragment>Two</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,15 @@
|
||||
<div>Slot A</div>
|
||||
|
||||
<slot name="a" />
|
||||
|
||||
<div>Slot B</div>
|
||||
|
||||
<slot name="b"><div>Fallback B</div></slot>
|
||||
|
||||
<div>Slot C</div>
|
||||
|
||||
<slot name="c"><div>Fallback C</div></slot>
|
||||
|
||||
<div>Slot D</div>
|
||||
|
||||
<slot name="d" />
|
||||
@ -0,0 +1,81 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: `
|
||||
<div>Slot A</div>
|
||||
4A
|
||||
<div>Slot B</div>
|
||||
4B
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
`,
|
||||
test({ assert, component, target }) {
|
||||
component.value = 1;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
A
|
||||
<div>Slot B</div>
|
||||
<div>Fallback B</div>
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
`);
|
||||
|
||||
component.value = 2;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
2A
|
||||
<div>Slot B</div>
|
||||
2B
|
||||
<div>Slot C</div>
|
||||
2C
|
||||
<div>Slot D</div>
|
||||
`);
|
||||
|
||||
component.value = 3;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
3A
|
||||
<div>Slot B</div>
|
||||
3B
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
`);
|
||||
|
||||
component.condition = false;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
3A
|
||||
<div>Slot B</div>
|
||||
<div>Fallback B</div>
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
3D
|
||||
`);
|
||||
|
||||
component.value = 4;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
<div>Slot B</div>
|
||||
<div>Fallback B</div>
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
`);
|
||||
|
||||
component.value = 5;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div>Slot A</div>
|
||||
5A
|
||||
<div>Slot B</div>
|
||||
<div>Fallback B</div>
|
||||
<div>Slot C</div>
|
||||
<div>Fallback C</div>
|
||||
<div>Slot D</div>
|
||||
`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let value;
|
||||
export let condition = true;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if value === 1}
|
||||
<svelte:fragment slot="a">A</svelte:fragment>
|
||||
{:else if value === 2}
|
||||
<svelte:fragment slot="a">2A</svelte:fragment>
|
||||
<svelte:fragment slot="b">2B</svelte:fragment>
|
||||
<svelte:fragment slot="c">2C</svelte:fragment>
|
||||
{:else if value === 3}
|
||||
<svelte:fragment slot="a">3A</svelte:fragment>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="b">3B</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="d">3D</svelte:fragment>
|
||||
{/if}
|
||||
{:else}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">4A</svelte:fragment>
|
||||
<svelte:fragment slot="b">4B</svelte:fragment>
|
||||
{:else}
|
||||
{#if value === 5}
|
||||
<svelte:fragment slot="a">5A</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
export let value;
|
||||
</script>
|
||||
|
||||
<div id={value}>
|
||||
value: {value}
|
||||
<hr />
|
||||
<slot name="folder">
|
||||
<span>fallback folder</span>
|
||||
</slot>
|
||||
<hr />
|
||||
<slot name="file">
|
||||
<span>fallback file</span>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: `
|
||||
<div id="_">
|
||||
value: _
|
||||
<hr>
|
||||
<div id="a">
|
||||
value: a
|
||||
<hr>
|
||||
<div id="b">
|
||||
value: b
|
||||
<hr>
|
||||
<span>fallback folder</span>
|
||||
<hr>
|
||||
<div>#2 level</div>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
`,
|
||||
test({ assert, component, target }) {
|
||||
const lvl1 = target.querySelector('#a');
|
||||
const lvl2 = target.querySelector('#b');
|
||||
component.paths = ["x", "y", "z"];
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div id="_">
|
||||
value: _
|
||||
<hr>
|
||||
<div id="x">
|
||||
value: x
|
||||
<hr>
|
||||
<div id="y">
|
||||
value: y
|
||||
<hr>
|
||||
<div id="z">
|
||||
value: z
|
||||
<hr>
|
||||
<span>fallback folder</span>
|
||||
<hr>
|
||||
<div>#3 level</div>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
`);
|
||||
|
||||
assert.equal(lvl1, target.querySelector('#x'));
|
||||
assert.equal(lvl2, target.querySelector('#y'));
|
||||
const lvl3 = target.querySelector('#z');
|
||||
|
||||
component.paths = ["p"];
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
<div id="_">
|
||||
value: _
|
||||
<hr>
|
||||
<div id="p">
|
||||
value: p
|
||||
<hr>
|
||||
<span>fallback folder</span>
|
||||
<hr>
|
||||
<div>#1 level</div>
|
||||
</div>
|
||||
<hr>
|
||||
<span>fallback file</span>
|
||||
</div>
|
||||
`);
|
||||
|
||||
assert.equal(lvl1, target.querySelector('#p'));
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,46 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let paths = ["a", "b"];
|
||||
</script>
|
||||
|
||||
<Nested value="_">
|
||||
{#if paths[0]}
|
||||
<svelte:fragment slot="folder">
|
||||
<Nested value={paths[0]}>
|
||||
{#if paths[1]}
|
||||
<svelte:fragment slot="folder">
|
||||
<Nested value={paths[1]}>
|
||||
{#if paths[2]}
|
||||
<svelte:fragment slot="folder">
|
||||
<Nested value={paths[2]}>
|
||||
{#if paths[3]}
|
||||
<svelte:fragment slot="folder">
|
||||
<Nested value={paths[3]}/>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="file">
|
||||
<div>#3 level</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="file">
|
||||
<div>#2 level</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="file">
|
||||
<div>#1 level</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="file">
|
||||
<div>#0 level</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let value;
|
||||
export let a;
|
||||
export let b;
|
||||
</script>
|
||||
|
||||
<slot {a} {b}>{value}</slot>
|
||||
@ -0,0 +1,30 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: `a`,
|
||||
test({ assert, component, target }) {
|
||||
component.a = 'foo';
|
||||
assert.htmlEqual(target.innerHTML, 'foo');
|
||||
|
||||
component.condition = 2;
|
||||
assert.htmlEqual(target.innerHTML, 'foo + b = foob');
|
||||
|
||||
component.b = 'bar';
|
||||
assert.htmlEqual(target.innerHTML, 'foo + bar = foobar');
|
||||
|
||||
component.condition = 3;
|
||||
assert.htmlEqual(target.innerHTML, 'b: bar');
|
||||
|
||||
component.condition = 4;
|
||||
assert.htmlEqual(target.innerHTML, 'value');
|
||||
|
||||
component.value = 'xxx';
|
||||
assert.htmlEqual(target.innerHTML, 'xxx');
|
||||
|
||||
component.condition = 2;
|
||||
component.b = 'baz';
|
||||
component.a = 'qux';
|
||||
assert.htmlEqual(target.innerHTML, 'qux + baz = quxbaz');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition = 1;
|
||||
export let value = 'value';
|
||||
export let a = 'a';
|
||||
export let b = 'b';
|
||||
</script>
|
||||
|
||||
<Nested {value} {a} {b}>
|
||||
{#if condition === 1}
|
||||
<svelte:fragment let:a>
|
||||
{a}
|
||||
</svelte:fragment>
|
||||
{:else if condition === 2}
|
||||
<svelte:fragment let:a let:b>
|
||||
{a} + {b} = {a + b}
|
||||
</svelte:fragment>
|
||||
{:else if condition === 3}
|
||||
<svelte:fragment let:b>
|
||||
b: {b}
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,5 @@
|
||||
<slot name="top">top fallback</slot>
|
||||
<hr/>
|
||||
<slot name="middle">middle fallback</slot>
|
||||
<hr/>
|
||||
<slot name="bottom">bottom fallback</slot>
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
import Bar from './Bar.svelte'
|
||||
</script>
|
||||
|
||||
<Bar>
|
||||
{#if $$slots.top}
|
||||
<svelte:fragment slot="top"><slot name="top" /></svelte:fragment>
|
||||
{/if}
|
||||
<svelte:fragment slot="middle"><slot name="middle">Middle</slot></svelte:fragment>
|
||||
{#if $$slots.bottom}
|
||||
<svelte:fragment slot="bottom"><slot name="bottom" /></svelte:fragment>
|
||||
{/if}
|
||||
</Bar>
|
||||
@ -0,0 +1,28 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: `
|
||||
<div>
|
||||
Top content
|
||||
<hr>
|
||||
Middle
|
||||
<hr>
|
||||
bottom fallback
|
||||
</div>
|
||||
<div>
|
||||
Top content
|
||||
<hr>
|
||||
Middle
|
||||
<hr>
|
||||
Bottom content
|
||||
</div>
|
||||
<div>
|
||||
top fallback
|
||||
<hr>
|
||||
Middle Content
|
||||
<hr>
|
||||
bottom fallback
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
<script>
|
||||
import Foo from './Foo.svelte';
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Foo>
|
||||
<svelte:fragment slot="top">Top content</svelte:fragment>
|
||||
</Foo>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Foo>
|
||||
<svelte:fragment slot="top">Top content</svelte:fragment>
|
||||
<svelte:fragment slot="bottom">Bottom content</svelte:fragment>
|
||||
</Foo>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Foo>
|
||||
<svelte:fragment slot="middle">Middle Content</svelte:fragment>
|
||||
</Foo>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<slot name="top">top fallback</slot>
|
||||
<hr/>
|
||||
<slot name="middle">middle fallback</slot>
|
||||
<hr/>
|
||||
<slot name="bottom">bottom fallback</slot>
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
import Bar from './Bar.svelte'
|
||||
</script>
|
||||
|
||||
<Bar>
|
||||
{#if $$slots.top}
|
||||
<svelte:fragment slot="top"><slot name="top" /></svelte:fragment>
|
||||
{/if}
|
||||
<svelte:fragment slot="middle"><slot name="middle">Middle</slot></svelte:fragment>
|
||||
{#if $$slots.bottom}
|
||||
<svelte:fragment slot="bottom"><slot name="bottom" /></svelte:fragment>
|
||||
{/if}
|
||||
</Bar>
|
||||
@ -0,0 +1,33 @@
|
||||
export default {
|
||||
solo: true,
|
||||
skip_if_ssr: true,
|
||||
skip_if_hydrate: true,
|
||||
html: `
|
||||
top fallback
|
||||
<hr>
|
||||
Middle
|
||||
<hr>
|
||||
bottom fallback
|
||||
`,
|
||||
test({ assert, component, target }) {
|
||||
component.top = true;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
Top content
|
||||
<hr>
|
||||
Middle
|
||||
<hr>
|
||||
bottom fallback
|
||||
`);
|
||||
|
||||
component.top = false;
|
||||
component.middle = true;
|
||||
component.bottom = true;
|
||||
assert.htmlEqual(target.innerHTML, `
|
||||
top fallback
|
||||
<hr>
|
||||
Middle content
|
||||
<hr>
|
||||
Bottom content
|
||||
`);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
import Foo from './Foo.svelte';
|
||||
export let top = false;
|
||||
export let middle = false;
|
||||
export let bottom = false;
|
||||
</script>
|
||||
|
||||
<Foo>
|
||||
{#if top}
|
||||
<svelte:fragment slot="top">Top content</svelte:fragment>
|
||||
{/if}
|
||||
{#if middle}
|
||||
<svelte:fragment slot="middle">Middle content</svelte:fragment>
|
||||
{/if}
|
||||
{#if bottom}
|
||||
<svelte:fragment slot="bottom">Bottom content</svelte:fragment>
|
||||
{/if}
|
||||
</Foo>
|
||||
@ -1 +0,0 @@
|
||||
<slot value="Hi" />
|
||||
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
error: 'Duplicate slot name "foo" in <Nested>'
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
<slot value="Hi" />
|
||||
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
error: 'Duplicate slot name "foo" in <Nested>'
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
<slot />
|
||||
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
error: 'Found elements without slot attribute when using slot="default"'
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
<slot value="Hi" />
|
||||
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
error: 'Duplicate slot name "foo" in <Nested>'
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"foo\" in <Nested>",
|
||||
"start": { "line": 7, "column": 1, "character": 96 },
|
||||
"end": { "line": 7, "column": 26, "character": 121 },
|
||||
"pos": 96
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"a\" in <Nested>",
|
||||
"start": { "line": 11, "column": 2, "character": 179 },
|
||||
"end": { "line": 13, "column": 20, "character": 245 },
|
||||
"pos": 179
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"foo\" in <Nested>",
|
||||
"start": { "line": 7, "column": 1, "character": 124 },
|
||||
"end": { "line": 7, "column": 54, "character": 177 },
|
||||
"pos": 124
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"foo\" in <Nested>",
|
||||
"start": { "line": 7, "column": 1, "character": 124 },
|
||||
"end": { "line": 7, "column": 26, "character": 149 },
|
||||
"pos": 124
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Found elements without slot attribute when using slot=\"default\"",
|
||||
"start": { "line": 6, "column": 1, "character": 69 },
|
||||
"end": { "line": 6, "column": 56, "character": 124 },
|
||||
"pos": 69
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Found elements without slot attribute when using slot=\"default\"",
|
||||
"start": { "line": 11, "column": 2, "character": 154 },
|
||||
"end": { "line": 13, "column": 20, "character": 226 },
|
||||
"pos": 154
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<span>test</span>
|
||||
{/if}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="default">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,66 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
{#if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
{#if condition}
|
||||
<svelte:fragment slot="c">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="c">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
<svelte:fragment slot="c">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if condition}
|
||||
<svelte:fragment slot="d">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else}
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="d">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
{:else}
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="d">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"a\" in <Nested>",
|
||||
"start": { "line": 20, "column": 5, "character": 333 },
|
||||
"end": { "line": 22, "column": 23, "character": 405 },
|
||||
"pos": 333
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
{#if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{:else if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"a\" in <Nested>",
|
||||
"start": { "line": 24, "column": 5, "character": 424 },
|
||||
"end": { "line": 26, "column": 23, "character": 496 },
|
||||
"pos": 424
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
{#if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{:else if condition}
|
||||
<svelte:fragment slot="b">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="a">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "duplicate-slot-name-in-component",
|
||||
"message": "Duplicate slot name \"d\" in <Component>",
|
||||
"start": { "line": 13, "column": 1, "character": 195 },
|
||||
"end": { "line": 15, "column": 19, "character": 259 },
|
||||
"pos": 195
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import Component from './Component.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Component>
|
||||
{#if condition}
|
||||
<svelte:fragment slot="d">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
<svelte:fragment slot="d">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
</Component>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "invalid-mix-element-and-conditional-slot",
|
||||
"message": "Do not mix <svelte:fragment> and other elements under the same {#if}{:else} group. Default slot content should be wrapped with <svelte:fragment slot=\"default\">",
|
||||
"start": { "line": 10, "column": 2, "character": 139 },
|
||||
"end": { "line": 12, "column": 20, "character": 196 },
|
||||
"pos": 139
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<span>test</span>
|
||||
{:else}
|
||||
<svelte:fragment>
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<span>test</span>
|
||||
{/if}
|
||||
{#if condition}
|
||||
<svelte:fragment slot="bar">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="foo">
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
{/if}
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "invalid-mix-element-and-conditional-slot",
|
||||
"message": "Do not mix <svelte:fragment> and other elements under the same {#if}{:else} group. Default slot content should be wrapped with <svelte:fragment slot=\"default\">",
|
||||
"start": { "line": 9, "column": 6, "character": 124 },
|
||||
"end": { "line": 9, "column": 36, "character": 154 },
|
||||
"pos": 124
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import Nested from './Nested.svelte';
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
<div>
|
||||
{#if condition}
|
||||
<svelte:fragment slot='xxx' />
|
||||
{/if}
|
||||
</div>
|
||||
</Nested>
|
||||
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"code": "invalid-mix-element-and-conditional-slot",
|
||||
"message": "Do not mix <svelte:fragment> and other elements under the same {#if}{:else} group. Default slot content should be wrapped with <svelte:fragment slot=\"default\">",
|
||||
"start": { "line": 11, "column": 2, "character": 170 },
|
||||
"end": { "line": 11, "column": 19, "character": 187 },
|
||||
"pos": 170
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
import Nested from "./Nested.svelte";
|
||||
export let condition;
|
||||
</script>
|
||||
|
||||
<Nested>
|
||||
{#if condition}
|
||||
<svelte:fragment>
|
||||
<div>test</div>
|
||||
</svelte:fragment>
|
||||
<span>test</span>
|
||||
{/if}
|
||||
</Nested>
|
||||
Loading…
Reference in new issue