mirror of https://github.com/sveltejs/svelte
103 lines
3.1 KiB
103 lines
3.1 KiB
import deindent from '../utils/deindent.js';
|
|
import counter from '../utils/counter.js';
|
|
|
|
// collect all the conditions and blocks in the if/elseif/else chain
|
|
function generateBlock ( generator, node, name ) {
|
|
// walk the children here
|
|
generator.push({
|
|
useAnchor: true,
|
|
name,
|
|
target: 'target',
|
|
localElementDepth: 0,
|
|
|
|
initStatements: [],
|
|
mountStatements: [],
|
|
updateStatements: [],
|
|
teardownStatements: [],
|
|
|
|
counter: counter()
|
|
});
|
|
node.children.forEach( generator.visit );
|
|
generator.addRenderer( generator.current );
|
|
generator.pop();
|
|
// unset the children, to avoid them being visited again
|
|
node.children = [];
|
|
}
|
|
|
|
function getConditionsAndBlocks ( generator, node, _name, i = 0 ) {
|
|
generator.addSourcemapLocations( node.expression );
|
|
const name = `${_name}_${i}`;
|
|
|
|
const conditionsAndBlocks = [{
|
|
condition: generator.contextualise( node.expression ).snippet,
|
|
block: name
|
|
}];
|
|
generateBlock( generator, node, name );
|
|
|
|
if ( node.else && node.else.children.length === 1 &&
|
|
node.else.children[0].type === 'IfBlock' ) {
|
|
conditionsAndBlocks.push(
|
|
...getConditionsAndBlocks( generator, node.else.children[0], _name, i + 1 ) );
|
|
} else {
|
|
const name = `${_name}_${i + 1}`;
|
|
conditionsAndBlocks.push({
|
|
condition: null,
|
|
block: node.else ? name : null,
|
|
});
|
|
if (node.else) {
|
|
generateBlock( generator, node.else, name );
|
|
}
|
|
}
|
|
return conditionsAndBlocks;
|
|
}
|
|
|
|
export default {
|
|
enter ( generator, node ) {
|
|
const i = generator.counters.if++;
|
|
|
|
const { params } = generator.current;
|
|
const name = `ifBlock_${i}`;
|
|
const getBlock = `getBlock_${i}`;
|
|
const currentBlock = `currentBlock_${i}`;
|
|
|
|
const isToplevel = generator.current.localElementDepth === 0;
|
|
const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` );
|
|
|
|
const anchor = generator.createAnchor( name, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` );
|
|
|
|
generator.current.initStatements.push( deindent`
|
|
function ${getBlock} ( ${params} ) {
|
|
${conditionsAndBlocks.map( ({ condition, block }) => {
|
|
return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
|
|
} ).join( '\n' )}
|
|
}
|
|
|
|
var ${currentBlock} = ${getBlock}( ${params} );
|
|
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
|
|
` );
|
|
|
|
const mountStatement = `if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );`;
|
|
if ( isToplevel ) {
|
|
generator.current.mountStatements.push( mountStatement );
|
|
} else {
|
|
generator.current.initStatements.push( mountStatement );
|
|
}
|
|
|
|
generator.current.updateStatements.push( deindent`
|
|
var _${currentBlock} = ${currentBlock};
|
|
${currentBlock} = ${getBlock}( ${params} );
|
|
if ( _${currentBlock} === ${currentBlock} && ${name}) {
|
|
${name}.update( changed, ${params} );
|
|
} else {
|
|
if ( ${name} ) ${name}.teardown( true );
|
|
${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
|
|
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
|
|
}
|
|
` );
|
|
|
|
generator.current.teardownStatements.push( deindent`
|
|
if ( ${name} ) ${name}.teardown( ${isToplevel ? 'detach' : 'false'} );
|
|
` );
|
|
}
|
|
};
|