diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index 8088fbc912..000ec6d75f 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -5,11 +5,13 @@ import namespaces from '../../utils/namespaces.js'; import processCss from '../shared/css/process.js'; import visitors from './visitors/index.js'; import Generator from '../Generator.js'; +import * as shared from '../../shared/index.js'; class DomGenerator extends Generator { constructor ( parsed, source, names, visitors ) { super( parsed, source, names, visitors ); this.renderers = []; + this.uses = {}; } addElement ( name, renderStatement, needsIdentifier = false ) { @@ -21,15 +23,13 @@ class DomGenerator extends Generator { this.createMountStatement( name ); } else { - this.current.builders.init.addLine( - `${this.current.target}.appendChild( ${renderStatement} );` - ); + this.uses.appendNode = true; + this.current.builders.init.addLine( `appendNode( ${renderStatement}, ${this.current.target} );` ); } if ( isToplevel ) { - this.current.builders.detach.addLine( - `${name}.parentNode.removeChild( ${name} );` - ); + this.uses.detachNode = true; + this.current.builders.detach.addLine( `detachNode( ${name} );` ); } } @@ -54,19 +54,38 @@ class DomGenerator extends Generator { if ( fragment.key ) properties.addBlock( `key: key,` ); - properties.addBlock( deindent` - mount: function ( target, anchor ) { - ${fragment.builders.mount} - }, + if ( fragment.builders.mount.isEmpty() ) { + this.uses.noop = true; + properties.addBlock( `mount: noop,` ); + } else { + properties.addBlock( deindent` + mount: function ( target, anchor ) { + ${fragment.builders.mount} + }, + ` ); + } - update: function ( changed, ${fragment.params} ) { - ${fragment.builders.update} - }, + if ( fragment.builders.update.isEmpty() ) { + this.uses.noop = true; + properties.addBlock( `update: noop,` ); + } else { + properties.addBlock( deindent` + update: function ( changed, ${fragment.params} ) { + ${fragment.builders.update} + }, + ` ); + } - teardown: function ( detach ) { - ${fragment.builders.teardown} - } - ` ); + if ( fragment.builders.teardown.isEmpty() ) { + this.uses.noop = true; + properties.addBlock( `teardown: noop,` ); + } else { + properties.addBlock( deindent` + teardown: function ( detach ) { + ${fragment.builders.teardown} + }, + ` ); + } this.renderers.push( deindent` function ${fragment.name} ( ${fragment.params}, component${fragment.key ? `, key` : ''} ) { @@ -80,18 +99,18 @@ class DomGenerator extends Generator { } createAnchor ( name, description = '' ) { - const renderStatement = `document.createComment( ${JSON.stringify( description )} )`; + this.uses.createComment = true; + const renderStatement = `createComment( ${JSON.stringify( description )} )`; this.addElement( name, renderStatement, true ); } createMountStatement ( name ) { if ( this.current.target === 'target' ) { - this.current.builders.mount.addLine( - `target.insertBefore( ${name}, anchor );` - ); + this.uses.insertNode = true; + this.current.builders.mount.addLine( `insertNode( ${name}, target, anchor );` ); } else { - this.current.builders.init.addLine( - `${this.current.target}.appendChild( ${name} );` ); + this.uses.appendNode = true; + this.current.builders.init.addLine( `appendNode( ${name}, ${this.current.target} );` ); } } @@ -192,12 +211,15 @@ export default function dom ( parsed, source, options, names ) { } if ( parsed.css && options.css !== false ) { + generator.uses.appendNode = true; + generator.uses.createElement = true; + builders.main.addBlock( deindent` let addedCss = false; function addCss () { - var style = document.createElement( 'style' ); + var style = createElement( 'style' ); style.textContent = ${JSON.stringify( processCss( parsed ) )}; - document.head.appendChild( style ); + appendNode( style, document.head ); addedCss = true; } @@ -364,5 +386,10 @@ export default function dom ( parsed, source, options, names ) { builders.main.addBlock( `${name}.prototype = template.methods;` ); } + Object.keys( generator.uses ).forEach( key => { + const fn = shared[ key ]; // eslint-disable-line import/namespace + builders.main.addBlock( fn.toString() ); + }); + return generator.generate( builders.main.toString(), options, { name, format } ); } diff --git a/src/generators/dom/visitors/Element.js b/src/generators/dom/visitors/Element.js index 9409ff9710..92bfec0500 100644 --- a/src/generators/dom/visitors/Element.js +++ b/src/generators/dom/visitors/Element.js @@ -57,9 +57,19 @@ export default { local.update.addBlock( updates ); } - let render = local.namespace ? - `var ${name} = document.createElementNS( '${local.namespace}', '${node.name}' );` : - `var ${name} = document.createElement( '${node.name}' );`; + let render; + + if ( local.namespace ) { + if ( local.namespace === 'http://www.w3.org/2000/svg' ) { + generator.uses.createSvgElement = true; + render = `var ${name} = createSvgElement( '${node.name}' )`; + } else { + render = `var ${name} = document.createElementNS( '${local.namespace}', '${node.name}' );`; + } + } else { + generator.uses.createElement = true; + render = `var ${name} = createElement( '${node.name}' );`; + } if ( generator.cssId && !generator.elementDepth ) { render += `\n${name}.setAttribute( '${generator.cssId}', '' );`; @@ -67,7 +77,8 @@ export default { local.init.addLineAtStart( render ); if ( isToplevel ) { - generator.current.builders.detach.addLine( `${name}.parentNode.removeChild( ${name} );` ); + generator.uses.detachNode = true; + generator.current.builders.detach.addLine( `detachNode( ${name} );` ); } // special case – bound