make abstract removeNode function

pull/447/head
Rich-Harris 9 years ago
parent 3881f5f84b
commit caec96f9da

@ -4,6 +4,7 @@ import isReference from '../utils/isReference.js';
import flattenReference from '../utils/flattenReference.js';
import globalWhitelist from '../utils/globalWhitelist.js';
import reservedNames from '../utils/reservedNames.js';
import { removeNode } from '../utils/removeNode.js';
import getIntro from './shared/utils/getIntro.js';
import getOutro from './shared/utils/getOutro.js';
import processCss from './shared/processCss.js';
@ -268,28 +269,25 @@ export default class Generator {
if ( js ) {
this.addSourcemapLocations( js.content );
const body = js.content.body.slice(); // slice, because we're going to be mutating the original
// imports need to be hoisted out of the IIFE
for ( let i = 0; i < js.content.body.length; i += 1 ) {
const node = js.content.body[i];
for ( let i = 0; i < body.length; i += 1 ) {
const node = body[i];
if ( node.type === 'ImportDeclaration' ) {
let a = node.start;
let b = node.end;
while ( /[ \t]/.test( source[ a - 1 ] ) ) a -= 1;
while ( source[b] === '\n' ) b += 1;
removeNode( this.code, js.content, node );
imports.push( node );
this.code.remove( a, b );
node.specifiers.forEach( specifier => {
this.importedNames.add( specifier.local.name );
});
}
}
defaultExport = js.content.body.find( node => node.type === 'ExportDefaultDeclaration' );
defaultExport = body.find( node => node.type === 'ExportDefaultDeclaration' );
if ( defaultExport ) {
const finalNode = js.content.body[ js.content.body.length - 1 ];
const finalNode = body[ body.length - 1 ];
if ( defaultExport === finalNode ) {
// export is last property, we can just return it
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `return ` );

@ -2,7 +2,7 @@ import deindent from '../../utils/deindent.js';
import getBuilders from './utils/getBuilders.js';
import CodeBuilder from '../../utils/CodeBuilder.js';
import namespaces from '../../utils/namespaces.js';
import removeObjectKey from '../../utils/removeObjectKey.js';
import { removeObjectKey } from '../../utils/removeNode.js';
import visitors from './visitors/index.js';
import Generator from '../Generator.js';
import * as shared from '../../shared/index.js';
@ -175,7 +175,7 @@ export default function dom ( parsed, source, options ) {
const ns = templateProperties.namespace.value.value;
namespace = namespaces[ ns ] || ns;
removeObjectKey( generator, defaultExport.declaration, 'namespace' );
removeObjectKey( generator.code, defaultExport.declaration, 'namespace' );
}
if ( templateProperties.components ) {
@ -192,11 +192,11 @@ export default function dom ( parsed, source, options ) {
if ( hasNonImportedComponent ) {
// remove the specific components that were imported, as we'll refer to them directly
Array.from( generator.importedComponents.keys() ).forEach( key => {
removeObjectKey( generator, templateProperties.components.value, key );
removeObjectKey( generator.code, templateProperties.components.value, key );
});
} else {
// remove the entire components portion of the export
removeObjectKey( generator, defaultExport.declaration, 'components' );
removeObjectKey( generator.code, defaultExport.declaration, 'components' );
}
}

@ -0,0 +1,55 @@
const keys = {
ObjectExpression: 'properties',
Program: 'body'
};
const offsets = {
ObjectExpression: [ 1, -1 ],
Program: [ 0, 0 ]
};
export function removeNode ( code, parent, node ) {
const key = keys[ parent.type ];
const offset = offsets[ parent.type ];
if ( !key || !offset ) throw new Error( `not implemented: ${parent.type}` );
const list = parent[ key ];
const i = list.indexOf( node );
if ( i === -1 ) throw new Error( 'node not in list' );
let a;
let b;
if ( list.length === 1 ) {
// remove everything, leave {}
a = parent.start + offset[0];
b = parent.end + offset[1];
} else if ( i === 0 ) {
// remove everything before second node, including comments
a = parent.start + offset[0];
while ( /\s/.test( code.original[a] ) ) a += 1;
b = list[i].end;
while ( /[\s,]/.test( code.original[b] ) ) b += 1;
} else {
// remove the end of the previous node to the end of this one
a = list[ i - 1 ].end;
b = node.end;
}
code.remove( a, b );
list.splice( i, 1 );
return;
}
export function removeObjectKey ( code, node, key ) {
if ( node.type !== 'ObjectExpression' ) return;
let i = node.properties.length;
while ( i-- ) {
const property = node.properties[i];
if ( property.key.type === 'Identifier' && property.key.name === key ) {
removeNode( code, node, property );
}
}
}

@ -1,33 +0,0 @@
export default function removeObjectKey ( generator, node, key ) {
if ( node.type !== 'ObjectExpression' ) return;
let i = node.properties.length;
while ( i-- ) {
const property = node.properties[i];
if ( property.key.type === 'Identifier' && property.key.name === key ) {
let a;
let b;
if ( node.properties.length === 1 ) {
// remove everything, leave {}
a = node.start + 1;
b = node.end - 1;
} else if ( i === 0 ) {
// remove everything before second property, including comments
a = node.start + 1;
while ( /\s/.test( generator.code.original[a] ) ) a += 1;
b = node.properties[i].end;
while ( /[\s,]/.test( generator.code.original[b] ) ) b += 1;
} else {
// remove the end of the previous property to the end of this one
a = node.properties[ i - 1 ].end;
b = property.end;
}
generator.code.remove( a, b );
node.properties.splice( i, 1 );
return;
}
}
}
Loading…
Cancel
Save