mirror of
https://github.com/sveltejs/svelte.git
synced 2024-12-01 17:30:59 +01:00
Merge pull request #1978 from evs-chris/gh-1977-evschris
Render default slot content event handlers conditionally (with bonus) - #1977
This commit is contained in:
commit
f3701794be
@ -234,29 +234,7 @@ export default class Block {
|
|||||||
this.builders.mount.addLine(`${this.autofocus}.focus();`);
|
this.builders.mount.addLine(`${this.autofocus}.focus();`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.event_listeners.length > 0) {
|
this.renderListeners();
|
||||||
this.addVariable('#dispose');
|
|
||||||
|
|
||||||
if (this.event_listeners.length === 1) {
|
|
||||||
this.builders.hydrate.addLine(
|
|
||||||
`#dispose = ${this.event_listeners[0]};`
|
|
||||||
);
|
|
||||||
|
|
||||||
this.builders.destroy.addLine(
|
|
||||||
`#dispose();`
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
this.builders.hydrate.addBlock(deindent`
|
|
||||||
#dispose = [
|
|
||||||
${this.event_listeners.join(',\n')}
|
|
||||||
];
|
|
||||||
`);
|
|
||||||
|
|
||||||
this.builders.destroy.addLine(
|
|
||||||
`@run_all(#dispose);`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const properties = new CodeBuilder();
|
const properties = new CodeBuilder();
|
||||||
|
|
||||||
@ -398,6 +376,32 @@ export default class Block {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderListeners(chunk: string = '') {
|
||||||
|
if (this.event_listeners.length > 0) {
|
||||||
|
this.addVariable(`#dispose${chunk}`);
|
||||||
|
|
||||||
|
if (this.event_listeners.length === 1) {
|
||||||
|
this.builders.hydrate.addLine(
|
||||||
|
`#dispose${chunk} = ${this.event_listeners[0]};`
|
||||||
|
);
|
||||||
|
|
||||||
|
this.builders.destroy.addLine(
|
||||||
|
`#dispose${chunk}();`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.builders.hydrate.addBlock(deindent`
|
||||||
|
#dispose${chunk} = [
|
||||||
|
${this.event_listeners.join(',\n')}
|
||||||
|
];
|
||||||
|
`);
|
||||||
|
|
||||||
|
this.builders.destroy.addLine(
|
||||||
|
`@run_all(#dispose${chunk});`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
const localKey = this.key && this.getUniqueName('key');
|
const localKey = this.key && this.getUniqueName('key');
|
||||||
|
|
||||||
|
@ -72,7 +72,11 @@ export default class SlotWrapper extends Wrapper {
|
|||||||
block.builders.update.pushCondition(`!${content_name}`);
|
block.builders.update.pushCondition(`!${content_name}`);
|
||||||
block.builders.destroy.pushCondition(`!${content_name}`);
|
block.builders.destroy.pushCondition(`!${content_name}`);
|
||||||
|
|
||||||
|
const listeners = block.event_listeners;
|
||||||
|
block.event_listeners = [];
|
||||||
this.fragment.render(block, parentNode, parentNodes);
|
this.fragment.render(block, parentNode, parentNodes);
|
||||||
|
block.renderListeners(`_${content_name}`);
|
||||||
|
block.event_listeners = listeners;
|
||||||
|
|
||||||
block.builders.create.popCondition();
|
block.builders.create.popCondition();
|
||||||
block.builders.hydrate.popCondition();
|
block.builders.hydrate.popCondition();
|
||||||
|
@ -1,168 +1,111 @@
|
|||||||
import repeat from './repeat';
|
import repeat from './repeat';
|
||||||
|
|
||||||
enum ChunkType {
|
const whitespace = /^\s+$/;
|
||||||
Line,
|
|
||||||
Block
|
interface Chunk {
|
||||||
|
parent?: BlockChunk;
|
||||||
|
type: 'root'|'line'|'condition';
|
||||||
|
children?: Chunk[];
|
||||||
|
line?: string;
|
||||||
|
block?: boolean;
|
||||||
|
condition?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Condition {
|
interface BlockChunk extends Chunk {
|
||||||
condition: string;
|
type: 'root'|'condition';
|
||||||
used: boolean;
|
children: Chunk[];
|
||||||
|
parent: BlockChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class CodeBuilder {
|
export default class CodeBuilder {
|
||||||
result: string;
|
root: BlockChunk = { type: 'root', children: [], parent: null };
|
||||||
first: ChunkType;
|
last: Chunk;
|
||||||
last: ChunkType;
|
current: BlockChunk;
|
||||||
lastCondition: string;
|
|
||||||
conditionStack: Condition[];
|
|
||||||
indent: string;
|
|
||||||
|
|
||||||
constructor(str = '') {
|
constructor(str = '') {
|
||||||
this.result = str;
|
this.current = this.last = this.root;
|
||||||
|
this.addLine(str);
|
||||||
const initial = str
|
|
||||||
? /\n/.test(str) ? ChunkType.Block : ChunkType.Line
|
|
||||||
: null;
|
|
||||||
this.first = initial;
|
|
||||||
this.last = initial;
|
|
||||||
|
|
||||||
this.lastCondition = null;
|
|
||||||
this.conditionStack = [];
|
|
||||||
this.indent = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addConditional(condition: string, body: string) {
|
addConditional(condition: string, body: string) {
|
||||||
this.reifyConditions();
|
if (this.last.type === 'condition' && this.last.condition === condition) {
|
||||||
|
if (body && !whitespace.test(body)) this.last.children.push({ type: 'line', line: body });
|
||||||
const indent = this.indent + (condition ? '\t' : '');
|
|
||||||
body = body.replace(/^/gm, indent);
|
|
||||||
|
|
||||||
if (condition === this.lastCondition) {
|
|
||||||
this.result += `\n${body}`;
|
|
||||||
} else {
|
} else {
|
||||||
if (this.lastCondition) {
|
const next = this.last = { type: 'condition', condition, parent: this.current, children: [] };
|
||||||
this.result += `\n${this.indent}}`;
|
this.current.children.push(next);
|
||||||
}
|
if (body && !whitespace.test(body)) next.children.push({ type: 'line', line: body });
|
||||||
|
|
||||||
const block = condition
|
|
||||||
? `if (${condition}) {\n${body}`
|
|
||||||
: body;
|
|
||||||
|
|
||||||
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}${block}`;
|
|
||||||
this.lastCondition = condition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.last = ChunkType.Block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addLine(line: string) {
|
addLine(line: string) {
|
||||||
this.reifyConditions();
|
if (line && !whitespace.test(line)) this.current.children.push(this.last = { type: 'line', line });
|
||||||
|
|
||||||
if (this.lastCondition) {
|
|
||||||
this.result += `\n${this.indent}}`;
|
|
||||||
this.lastCondition = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.last === ChunkType.Block) {
|
|
||||||
this.result += `\n\n${this.indent}${line}`;
|
|
||||||
} else if (this.last === ChunkType.Line) {
|
|
||||||
this.result += `\n${this.indent}${line}`;
|
|
||||||
} else {
|
|
||||||
this.result += line;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.last = ChunkType.Line;
|
|
||||||
if (!this.first) this.first = ChunkType.Line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addLineAtStart(line: string) {
|
addLineAtStart(line: string) {
|
||||||
this.reifyConditions();
|
if (line && !whitespace.test(line)) this.root.children.unshift({ type: 'line', line });
|
||||||
|
|
||||||
if (this.first === ChunkType.Block) {
|
|
||||||
this.result = `${line}\n\n${this.indent}${this.result}`;
|
|
||||||
} else if (this.first === ChunkType.Line) {
|
|
||||||
this.result = `${line}\n${this.indent}${this.result}`;
|
|
||||||
} else {
|
|
||||||
this.result += line;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.first = ChunkType.Line;
|
|
||||||
if (!this.last) this.last = ChunkType.Line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlock(block: string) {
|
addBlock(block: string) {
|
||||||
this.reifyConditions();
|
if (block && !whitespace.test(block)) this.current.children.push(this.last = { type: 'line', line: block, block: true });
|
||||||
|
|
||||||
if (this.indent) block = block.replace(/^/gm, `${this.indent}`);
|
|
||||||
|
|
||||||
if (this.lastCondition) {
|
|
||||||
this.result += `\n${this.indent}}`;
|
|
||||||
this.lastCondition = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.result) {
|
|
||||||
this.result += `\n\n${this.indent}${block}`;
|
|
||||||
} else {
|
|
||||||
this.result += block;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.last = ChunkType.Block;
|
|
||||||
if (!this.first) this.first = ChunkType.Block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlockAtStart(block: string) {
|
addBlockAtStart(block: string) {
|
||||||
this.reifyConditions();
|
if (block && !whitespace.test(block)) this.root.children.unshift({ type: 'line', line: block, block: true });
|
||||||
|
|
||||||
if (this.result) {
|
|
||||||
this.result = `${block}\n\n${this.indent}${this.result}`;
|
|
||||||
} else {
|
|
||||||
this.result += block;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.first = ChunkType.Block;
|
|
||||||
if (!this.last) this.last = ChunkType.Block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isEmpty() {
|
isEmpty() { return !findLine(this.root); }
|
||||||
return this.result === '';
|
|
||||||
}
|
|
||||||
|
|
||||||
pushCondition(condition: string) {
|
pushCondition(condition: string) {
|
||||||
this.conditionStack.push({ condition, used: false });
|
if (this.last.type === 'condition' && this.last.condition === condition) {
|
||||||
|
this.current = this.last as BlockChunk;
|
||||||
|
} else {
|
||||||
|
const next = this.last = { type: 'condition', condition, parent: this.current, children: [] };
|
||||||
|
this.current.children.push(next);
|
||||||
|
this.current = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popCondition() {
|
popCondition() {
|
||||||
const { used } = this.conditionStack.pop();
|
if (!this.current.parent) throw new Error(`Popping a condition that maybe wasn't pushed.`);
|
||||||
|
this.current = this.current.parent;
|
||||||
this.indent = repeat('\t', this.conditionStack.length);
|
|
||||||
if (used) this.addLine('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
reifyConditions() {
|
|
||||||
for (let i = 0; i < this.conditionStack.length; i += 1) {
|
|
||||||
const condition = this.conditionStack[i];
|
|
||||||
if (!condition.used) {
|
|
||||||
const line = `if (${condition.condition}) {`;
|
|
||||||
|
|
||||||
if (this.last === ChunkType.Block) {
|
|
||||||
this.result += `\n\n${this.indent}${line}`;
|
|
||||||
} else if (this.last === ChunkType.Line) {
|
|
||||||
this.result += `\n${this.indent}${line}`;
|
|
||||||
} else {
|
|
||||||
this.result += line;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.last = ChunkType.Line;
|
|
||||||
if (!this.first) this.first = ChunkType.Line;
|
|
||||||
|
|
||||||
this.indent = repeat('\t', this.conditionStack.length);
|
|
||||||
condition.used = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return this.result.trim() + (this.lastCondition ? `\n}` : ``);
|
return chunkToString(this.root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findLine(chunk: BlockChunk) {
|
||||||
|
for (const c of chunk.children) {
|
||||||
|
if (c.type === 'line' || findLine(c as BlockChunk)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function chunkToString(chunk: Chunk, level: number = 0, lastBlock?: boolean, first?: boolean): string {
|
||||||
|
if (chunk.type === 'line') {
|
||||||
|
return `${lastBlock || (!first && chunk.block) ? '\n' : ''}${chunk.line.replace(/^/gm, repeat('\t', level))}`;
|
||||||
|
} else if (chunk.type === 'condition') {
|
||||||
|
let t = false;
|
||||||
|
const lines = chunk.children.map((c, i) => {
|
||||||
|
const str = chunkToString(c, level + 1, t, i === 0);
|
||||||
|
t = c.type !== 'line' || c.block;
|
||||||
|
return str;
|
||||||
|
}).filter(l => !!l);
|
||||||
|
|
||||||
|
if (!lines.length) return '';
|
||||||
|
|
||||||
|
return `${lastBlock || (!first) ? '\n' : ''}${repeat('\t', level)}if (${chunk.condition}) {\n${lines.join('\n')}\n${repeat('\t', level)}}`;
|
||||||
|
} else if (chunk.type === 'root') {
|
||||||
|
let t = false;
|
||||||
|
const lines = chunk.children.map((c, i) => {
|
||||||
|
const str = chunkToString(c, 0, t, i === 0);
|
||||||
|
t = c.type !== 'line' || c.block;
|
||||||
|
return str;
|
||||||
|
}).filter(l => !!l);
|
||||||
|
|
||||||
|
if (!lines.length) return '';
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ function create_fragment($$, ctx) {
|
|||||||
|
|
||||||
d(detach) {
|
d(detach) {
|
||||||
if_block.d(detach);
|
if_block.d(detach);
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
detachNode(if_block_anchor);
|
detachNode(if_block_anchor);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ function create_fragment($$, ctx) {
|
|||||||
|
|
||||||
d(detach) {
|
d(detach) {
|
||||||
if (if_block) if_block.d(detach);
|
if (if_block) if_block.d(detach);
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
detachNode(if_block_anchor);
|
detachNode(if_block_anchor);
|
||||||
}
|
}
|
||||||
|
@ -232,11 +232,13 @@ function create_fragment($$, ctx) {
|
|||||||
if (if_block1) if_block1.d();
|
if (if_block1) if_block1.d();
|
||||||
if (if_block2) if_block2.d();
|
if (if_block2) if_block2.d();
|
||||||
if (if_block3) if_block3.d();
|
if (if_block3) if_block3.d();
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
detachNode(text7);
|
detachNode(text7);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (if_block4) if_block4.d(detach);
|
if (if_block4) if_block4.d(detach);
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
detachNode(if_block4_anchor);
|
detachNode(if_block4_anchor);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
function click() {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<slot><button on:click>Should not appear</button></slot>
|
||||||
|
</p>
|
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
html: '<p>Hello</p>', show: true
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.html';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Nested>
|
||||||
|
Hello
|
||||||
|
</Nested>
|
Loading…
Reference in New Issue
Block a user