diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index 58cb848a5b..6c4e40dbd9 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -6,16 +6,34 @@ import processCss from '../shared/css/process.js'; import visitors from './visitors/index.js'; import Generator from '../Generator.js'; -export default function dom ( parsed, source, options, names ) { - const format = options.format || 'es'; - const name = options.name || 'SvelteComponent'; +class DomGenerator extends Generator { + constructor ( parsed, source, names, visitors ) { + super( parsed, source, names, visitors ); + this.renderers = []; + } - const generator = new Generator( parsed, source, names, visitors ); + addElement ( name, renderStatement, needsIdentifier = false ) { + const isToplevel = this.current.localElementDepth === 0; + if ( needsIdentifier || isToplevel ) { + this.current.builders.init.addLine( + `var ${name} = ${renderStatement};` + ); - const { computations, templateProperties } = generator.parseJs(); + this.createMountStatement( name ); + } else { + this.current.builders.init.addLine( + `${this.current.target}.appendChild( ${renderStatement} );` + ); + } - const renderers = []; - function addRenderer ( fragment ) { + if ( isToplevel ) { + this.current.builders.detach.addLine( + `${name}.parentNode.removeChild( ${name} );` + ); + } + } + + addRenderer ( fragment ) { if ( fragment.autofocus ) { fragment.builders.init.addLine( `${fragment.autofocus}.focus();` ); } @@ -32,7 +50,7 @@ export default function dom ( parsed, source, options, names ) { ` ); } - renderers.push( deindent` + this.renderers.push( deindent` function ${fragment.name} ( ${fragment.params}, component ) { ${fragment.builders.init} @@ -53,67 +71,48 @@ export default function dom ( parsed, source, options, names ) { ` ); } - generator.on( 'addRenderer', addRenderer ); - - generator.on( 'addElement', ({ name, renderStatement, needsIdentifier }) => { - const isToplevel = generator.current.localElementDepth === 0; - if ( needsIdentifier || isToplevel ) { - generator.current.builders.init.addLine( - `var ${name} = ${renderStatement};` - ); - - generator.fire( 'createMountStatement', name ); - } else { - generator.current.builders.init.addLine( - `${generator.current.target}.appendChild( ${renderStatement} );` - ); - } - - if ( isToplevel ) { - generator.current.builders.detach.addLine( - `${name}.parentNode.removeChild( ${name} );` - ); - } - }); - - generator.on( 'createAnchor', ({ name, description = '' }) => { + createAnchor ( name, description = '' ) { const renderStatement = `document.createComment( ${JSON.stringify( description )} )`; + this.addElement( name, renderStatement, true ); + } - generator.fire( 'addElement', { - name, - renderStatement, - needsIdentifier: true - }); - }); - - generator.on( 'createMountStatement', name => { - if ( generator.current.target === 'target' ) { - generator.current.builders.mount.addLine( + createMountStatement ( name ) { + if ( this.current.target === 'target' ) { + this.current.builders.mount.addLine( `target.insertBefore( ${name}, anchor );` ); } else { - generator.current.builders.init.addLine( - `${generator.current.target}.appendChild( ${name} );` ); + this.current.builders.init.addLine( + `${this.current.target}.appendChild( ${name} );` ); } - }); + } - generator.on( 'generateBlock', ({ node, name }) => { - generator.push({ + generateBlock ( node, name ) { + this.push({ name, target: 'target', localElementDepth: 0, builders: getBuilders(), - getUniqueName: generator.getUniqueNameMaker() + getUniqueName: this.getUniqueNameMaker() }); // walk the children here - node.children.forEach( node => generator.visit( node ) ); - generator.fire( 'addRenderer', generator.current ); - generator.pop(); + node.children.forEach( node => this.visit( node ) ); + this.addRenderer( this.current ); + this.pop(); // unset the children, to avoid them being visited again node.children = []; - }); + } +} + +export default function dom ( parsed, source, options, names ) { + const format = options.format || 'es'; + const name = options.name || 'SvelteComponent'; + + const generator = new DomGenerator( parsed, source, names, visitors ); + + const { computations, templateProperties } = generator.parseJs(); let namespace = null; if ( templateProperties.namespace ) { @@ -142,7 +141,7 @@ export default function dom ( parsed, source, options, names ) { parsed.html.children.forEach( node => generator.visit( node ) ); - addRenderer( generator.pop() ); + generator.addRenderer( generator.pop() ); const builders = { main: new CodeBuilder(), @@ -196,8 +195,8 @@ export default function dom ( parsed, source, options, names ) { ` ); } - let i = renderers.length; - while ( i-- ) builders.main.addBlock( renderers[i] ); + let i = generator.renderers.length; + while ( i-- ) builders.main.addBlock( generator.renderers[i] ); if ( parsed.css && options.css !== false ) { builders.init.addLine( `if ( !addedCss ) addCss();` ); diff --git a/src/generators/dom/visitors/Component.js b/src/generators/dom/visitors/Component.js index 81e682a233..113417c2fe 100644 --- a/src/generators/dom/visitors/Component.js +++ b/src/generators/dom/visitors/Component.js @@ -33,10 +33,7 @@ export default { if ( hasChildren ) { const yieldName = generator.current.getUniqueName( `render${name}YieldFragment` ); - generator.fire( 'generateBlock', { - node, - name: yieldName - }); + generator.generateBlock( node, yieldName ); generator.current.builders.init.addLine( `var ${name}_yieldFragment = ${yieldName}( root, component );` diff --git a/src/generators/dom/visitors/EachBlock.js b/src/generators/dom/visitors/EachBlock.js index 372f3bc10a..b0ec2113e0 100644 --- a/src/generators/dom/visitors/EachBlock.js +++ b/src/generators/dom/visitors/EachBlock.js @@ -20,10 +20,7 @@ export default { const { dependencies, snippet } = generator.contextualise( node.expression ); const anchor = `${name}_anchor`; - generator.fire( 'createAnchor', { - name: anchor, - description: `#each ${generator.source.slice( node.expression.start, node.expression.end )}` - }); + generator.createAnchor( anchor, `#each ${generator.source.slice( node.expression.start, node.expression.end )}` ); generator.current.builders.init.addBlock( deindent` var ${name}_value = ${snippet}; @@ -106,10 +103,7 @@ export default { } if ( node.else ) { - generator.fire( 'generateBlock', { - node: node.else, - name: renderElse - }); + generator.generateBlock( node.else, renderElse ); } const indexNames = Object.assign( {}, generator.current.indexNames ); @@ -159,7 +153,7 @@ export default { }, leave ( generator ) { - generator.fire( 'addRenderer', generator.current ); + generator.addRenderer( generator.current ); generator.pop(); } }; diff --git a/src/generators/dom/visitors/Element.js b/src/generators/dom/visitors/Element.js index 50fa0e3f32..67759ad60a 100644 --- a/src/generators/dom/visitors/Element.js +++ b/src/generators/dom/visitors/Element.js @@ -82,7 +82,7 @@ export default { generator.current.builders.init.addBlock( local.init ); if ( !local.update.isEmpty() ) generator.current.builders.update.addBlock( local.update ); - generator.fire( 'createMountStatement', name ); + generator.createMountStatement( name ); generator.push({ namespace: local.namespace, diff --git a/src/generators/dom/visitors/IfBlock.js b/src/generators/dom/visitors/IfBlock.js index 9920548463..02133e539d 100644 --- a/src/generators/dom/visitors/IfBlock.js +++ b/src/generators/dom/visitors/IfBlock.js @@ -9,26 +9,22 @@ function getConditionsAndBlocks ( generator, node, _name, i = 0 ) { block: name }]; - generator.fire( 'generateBlock', { - node, - name - }); + generator.generateBlock( 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 ) ); + ...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) { - generator.fire( 'generateBlock', { - node: node.else, - name - }); + + if ( node.else ) { + generator.generateBlock( node.else, name ); } } return conditionsAndBlocks; @@ -45,10 +41,7 @@ export default { const conditionsAndBlocks = getConditionsAndBlocks( generator, node, generator.getUniqueName( `renderIfBlock` ) ); const anchor = `${name}_anchor`; - generator.fire( 'createAnchor', { - name: anchor, - description: `#if ${generator.source.slice( node.expression.start, node.expression.end )}` - }); + generator.createAnchor( anchor, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` ); generator.current.builders.init.addBlock( deindent` function ${getBlock} ( ${params} ) { diff --git a/src/generators/dom/visitors/MustacheTag.js b/src/generators/dom/visitors/MustacheTag.js index 231ba26557..f956a7be08 100644 --- a/src/generators/dom/visitors/MustacheTag.js +++ b/src/generators/dom/visitors/MustacheTag.js @@ -7,11 +7,7 @@ export default { generator.addSourcemapLocations( node.expression ); const { snippet } = generator.contextualise( node.expression ); - generator.fire( 'addElement', { - name, - renderStatement: `document.createTextNode( ${snippet} )`, - needsIdentifier: true - }); + generator.addElement( name, `document.createTextNode( ${snippet} )`, true ); generator.current.builders.update.addBlock( deindent` ${name}.data = ${snippet}; diff --git a/src/generators/dom/visitors/RawMustacheTag.js b/src/generators/dom/visitors/RawMustacheTag.js index 3a2e4429bc..191b3c8a9d 100644 --- a/src/generators/dom/visitors/RawMustacheTag.js +++ b/src/generators/dom/visitors/RawMustacheTag.js @@ -10,18 +10,10 @@ export default { // we would have used comments here, but the `insertAdjacentHTML` api only // exists for `Element`s. const before = `${name}_before`; - generator.fire( 'addElement', { - name: before, - renderStatement: `document.createElement( 'noscript' )`, - needsIdentifier: true - }); - + generator.addElement( before, `document.createElement( 'noscript' )`, true ); + const after = `${name}_after`; - generator.fire( 'addElement', { - name: after, - renderStatement: `document.createElement( 'noscript' )`, - needsIdentifier: true - }); + generator.addElement( after, `document.createElement( 'noscript' )`, true ); const isToplevel = generator.current.localElementDepth === 0; diff --git a/src/generators/dom/visitors/Text.js b/src/generators/dom/visitors/Text.js index 58090872bd..fcc9f9b447 100644 --- a/src/generators/dom/visitors/Text.js +++ b/src/generators/dom/visitors/Text.js @@ -5,10 +5,6 @@ export default { } const name = generator.current.getUniqueName( `text` ); - generator.fire( 'addElement', { - name, - renderStatement: `document.createTextNode( ${JSON.stringify( node.data )} )`, - needsIdentifier: false - }); + generator.addElement( name, `document.createTextNode( ${JSON.stringify( node.data )} )`, false ); } }; diff --git a/src/generators/dom/visitors/YieldTag.js b/src/generators/dom/visitors/YieldTag.js index 583964d129..a2ac7f57d7 100644 --- a/src/generators/dom/visitors/YieldTag.js +++ b/src/generators/dom/visitors/YieldTag.js @@ -1,10 +1,7 @@ export default { enter ( generator ) { const anchor = `yield_anchor`; - generator.fire( 'createAnchor', { - name: anchor, - description: 'yield' - }); + generator.createAnchor( anchor, 'yield' ); generator.current.builders.mount.addLine( `component.yield && component.yield.mount( ${generator.current.target}, ${anchor} );`