visitors can just be functions now

pull/453/head
Rich-Harris 9 years ago
parent 2d4f9eac00
commit e7d324f305

@ -168,13 +168,13 @@ export default {
key: null key: null
}); });
this.elementDepth += 1; generator.elementDepth += 1;
node.children.forEach( child => { node.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
this.elementDepth -= 1; generator.elementDepth -= 1;
generator.pop(); generator.pop();
} }

@ -110,13 +110,13 @@ export default {
key: null key: null
}); });
this.elementDepth += 1; generator.elementDepth += 1;
node.children.forEach( child => { node.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
this.elementDepth -= 1; generator.elementDepth -= 1;
if ( node.name in meta ) { if ( node.name in meta ) {
if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node ); if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node );

@ -2,7 +2,5 @@ import visitors from './visitors/index.js';
export default function visit ( node, generator ) { export default function visit ( node, generator ) {
const visitor = visitors[ node.type ]; const visitor = visitors[ node.type ];
visitor( generator, node );
if ( visitor.enter ) visitor.enter( generator, node );
if ( visitor.leave ) visitor.leave( generator, node );
} }

@ -1,3 +1,3 @@
export default { export default function visitComment () {
// do nothing // do nothing
}; }

@ -1,79 +1,77 @@
import flattenReference from '../../../utils/flattenReference.js'; import flattenReference from '../../../utils/flattenReference.js';
import visit from '../visit.js'; import visit from '../visit.js';
export default { export default function visitComponent ( generator, node ) {
enter ( generator, node ) { function stringify ( chunk ) {
function stringify ( chunk ) { if ( chunk.type === 'Text' ) return chunk.data;
if ( chunk.type === 'Text' ) return chunk.data; if ( chunk.type === 'MustacheTag' ) {
if ( chunk.type === 'MustacheTag' ) { const { snippet } = generator.contextualise( chunk.expression );
const { snippet } = generator.contextualise( chunk.expression ); return '${__escape( ' + snippet + ')}';
return '${__escape( ' + snippet + ')}';
}
} }
}
const attributes = []; const attributes = [];
const bindings = []; const bindings = [];
node.attributes.forEach( attribute => { node.attributes.forEach( attribute => {
if ( attribute.type === 'Attribute' ) { if ( attribute.type === 'Attribute' ) {
attributes.push( attribute ); attributes.push( attribute );
} else if ( attribute.type === 'Binding' ) { } else if ( attribute.type === 'Binding' ) {
bindings.push( attribute ); bindings.push( attribute );
} }
}); });
const props = attributes const props = attributes
.map( attribute => { .map( attribute => {
let value; let value;
if ( attribute.value === true ) { if ( attribute.value === true ) {
value = `true`; value = `true`;
} else if ( attribute.value.length === 0 ) { } else if ( attribute.value.length === 0 ) {
value = `''`; value = `''`;
} else if ( attribute.value.length === 1 ) { } else if ( attribute.value.length === 1 ) {
const chunk = attribute.value[0]; const chunk = attribute.value[0];
if ( chunk.type === 'Text' ) { if ( chunk.type === 'Text' ) {
value = isNaN( chunk.data ) ? JSON.stringify( chunk.data ) : chunk.data; value = isNaN( chunk.data ) ? JSON.stringify( chunk.data ) : chunk.data;
} else {
const { snippet } = generator.contextualise( chunk.expression );
value = snippet;
}
} else { } else {
value = '`' + attribute.value.map( stringify ).join( '' ) + '`'; const { snippet } = generator.contextualise( chunk.expression );
value = snippet;
} }
} else {
value = '`' + attribute.value.map( stringify ).join( '' ) + '`';
}
return `${attribute.name}: ${value}`; return `${attribute.name}: ${value}`;
}) })
.concat( bindings.map( binding => { .concat( bindings.map( binding => {
const { name, keypath } = flattenReference( binding.value ); const { name, keypath } = flattenReference( binding.value );
const value = generator.current.contexts.has( name ) ? keypath : `root.${keypath}`; const value = generator.current.contexts.has( name ) ? keypath : `root.${keypath}`;
return `${binding.name}: ${value}`; return `${binding.name}: ${value}`;
})) }))
.join( ', ' ); .join( ', ' );
const expression = node.name === ':Self' ? generator.name : generator.importedComponents.get( node.name ) || `${generator.alias( 'template' )}.components.${node.name}`; const expression = node.name === ':Self' ? generator.name : generator.importedComponents.get( node.name ) || `${generator.alias( 'template' )}.components.${node.name}`;
bindings.forEach( binding => { bindings.forEach( binding => {
generator.addBinding( binding, expression ); generator.addBinding( binding, expression );
}); });
let open = `\${${expression}.render({${props}}`; let open = `\${${expression}.render({${props}}`;
if ( node.children.length ) { if ( node.children.length ) {
open += `, { yield: () => \``; open += `, { yield: () => \``;
} }
generator.append( open ); generator.append( open );
this.elementDepth += 1; generator.elementDepth += 1;
node.children.forEach( child => { node.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
this.elementDepth -= 1; generator.elementDepth -= 1;
const close = node.children.length ? `\` })}` : ')}'; const close = node.children.length ? `\` })}` : ')}';
generator.append( close ); generator.append( close );
} }
};

@ -1,36 +1,34 @@
import visit from '../visit.js'; import visit from '../visit.js';
export default { export default function visitEachBlock ( generator, node ) {
enter ( generator, node ) { const { dependencies, snippet } = generator.contextualise( node.expression );
const { dependencies, snippet } = generator.contextualise( node.expression );
const open = `\${ ${snippet}.map( ${ node.index ? `( ${node.context}, ${node.index} )` : node.context} => \``; const open = `\${ ${snippet}.map( ${ node.index ? `( ${node.context}, ${node.index} )` : node.context} => \``;
generator.append( open ); generator.append( open );
// TODO should this be the generator's job? It's duplicated between // TODO should this be the generator's job? It's duplicated between
// here and the equivalent DOM compiler visitor // here and the equivalent DOM compiler visitor
const contexts = new Map( generator.current.contexts ); const contexts = new Map( generator.current.contexts );
contexts.set( node.context, node.context ); contexts.set( node.context, node.context );
const indexes = new Map( generator.current.indexes ); const indexes = new Map( generator.current.indexes );
if ( node.index ) indexes.set( node.index, node.context ); if ( node.index ) indexes.set( node.index, node.context );
const contextDependencies = new Map( generator.current.contextDependencies ); const contextDependencies = new Map( generator.current.contextDependencies );
contextDependencies.set( node.context, dependencies ); contextDependencies.set( node.context, dependencies );
generator.push({ generator.push({
contexts, contexts,
indexes, indexes,
contextDependencies contextDependencies
}); });
node.children.forEach( child => { node.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
const close = `\` ).join( '' )}`; const close = `\` ).join( '' )}`;
generator.append( close ); generator.append( close );
generator.pop(); generator.pop();
} }
};

@ -1,72 +1,60 @@
import Component from './Component.js'; import visitComponent from './Component.js';
import isVoidElementName from '../../../utils/isVoidElementName.js'; import isVoidElementName from '../../../utils/isVoidElementName.js';
import visit from '../visit.js'; import visit from '../visit.js';
import Window from './meta/Window.js'; import visitWindow from './meta/Window.js';
const meta = { const meta = {
':Window': Window ':Window': visitWindow
}; };
export default { export default function visitElement ( generator, node ) {
enter ( generator, node ) { if ( node.name in meta ) {
if ( node.name in meta ) { return meta[ node.name ]( generator, node );
return meta[ node.name ].enter( generator, node ); }
}
if ( generator.components.has( node.name ) || node.name === ':Self' ) {
Component.enter( generator, node );
return;
}
let openingTag = `<${node.name}`;
node.attributes.forEach( attribute => { if ( generator.components.has( node.name ) || node.name === ':Self' ) {
if ( attribute.type !== 'Attribute' ) return; visitComponent( generator, node );
return;
}
let str = ` ${attribute.name}`; let openingTag = `<${node.name}`;
if ( attribute.value !== true ) { node.attributes.forEach( attribute => {
str += `="` + attribute.value.map( chunk => { if ( attribute.type !== 'Attribute' ) return;
if ( chunk.type === 'Text' ) {
return chunk.data;
}
const { snippet } = generator.contextualise( chunk.expression ); let str = ` ${attribute.name}`;
return '${' + snippet + '}';
}).join( '' ) + `"`;
}
openingTag += str; if ( attribute.value !== true ) {
}); str += `="` + attribute.value.map( chunk => {
if ( chunk.type === 'Text' ) {
return chunk.data;
}
if ( generator.cssId && !generator.elementDepth ) { const { snippet } = generator.contextualise( chunk.expression );
openingTag += ` ${generator.cssId}`; return '${' + snippet + '}';
}).join( '' ) + `"`;
} }
openingTag += '>'; openingTag += str;
});
generator.append( openingTag ); if ( generator.cssId && !generator.elementDepth ) {
openingTag += ` ${generator.cssId}`;
}
this.elementDepth += 1; openingTag += '>';
node.children.forEach( child => { generator.append( openingTag );
visit( child, generator );
});
this.elementDepth -= 1; generator.elementDepth += 1;
if ( node.name in meta ) { node.children.forEach( child => {
if ( meta[ node.name ].leave ) meta[ node.name ].leave( generator, node ); visit( child, generator );
return; });
}
if ( generator.components.has( node.name ) || node.name === ':Self' ) { generator.elementDepth -= 1;
Component.leave( generator, node );
return;
}
if ( !isVoidElementName( node.name ) ) { if ( !isVoidElementName( node.name ) ) {
generator.append( `</${node.name}>` ); generator.append( `</${node.name}>` );
}
} }
}; }

@ -1,29 +1,27 @@
import visit from '../visit.js'; import visit from '../visit.js';
export default { export default function visitIfBlock ( generator, node ) {
enter ( generator, node ) { const { snippet } = generator.contextualise( node.expression );
const { snippet } = generator.contextualise( node.expression );
generator.append( '${ ' + snippet + ' ? `' ); generator.append( '${ ' + snippet + ' ? `' );
generator.push({ generator.push({
conditions: generator.current.conditions.concat( snippet ) conditions: generator.current.conditions.concat( snippet )
}); });
node.children.forEach( child => { node.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
generator.append( '` : `' ); generator.append( '` : `' );
if ( node.else ) { if ( node.else ) {
node.else.children.forEach( child => { node.else.children.forEach( child => {
visit( child, generator ); visit( child, generator );
}); });
} }
generator.append( '` }' ); generator.append( '` }' );
generator.pop(); generator.pop();
} }
};

@ -1,6 +1,4 @@
export default { export default function visitMustacheTag ( generator, node ) {
enter ( generator, node ) { const { snippet } = generator.contextualise( node.expression );
const { snippet } = generator.contextualise( node.expression ); generator.append( '${__escape( ' + snippet + ' )}' );
generator.append( '${__escape( ' + snippet + ' )}' ); }
}
};

@ -1,6 +1,4 @@
export default { export default function visitRawMustacheTag ( generator, node ) {
enter ( generator, node ) { const { snippet } = generator.contextualise( node.expression );
const { snippet } = generator.contextualise( node.expression ); generator.append( '${' + snippet + '}' );
generator.append( '${' + snippet + '}' ); }
}
};

@ -1,5 +1,3 @@
export default { export default function visitText ( generator, node ) {
enter ( generator, node ) { generator.append( node.data.replace( /\${/g, '\\${' ) );
generator.append( node.data.replace( /\${/g, '\\${' ) ); }
}
};

@ -1,5 +1,3 @@
export default { export default function visitYieldTag ( generator ) {
enter ( generator ) { generator.append( `\${options && options.yield ? options.yield() : ''}` );
generator.append( `\${options && options.yield ? options.yield() : ''}` ); }
}
};

@ -1,9 +1,3 @@
export default { export default function visitWindow () {
enter () { // noop
// noop }
},
leave () {
// noop
}
};
Loading…
Cancel
Save