pull/31/head
Rich-Harris 8 years ago
parent 49a6aeb190
commit f136f951b3

@ -2,7 +2,6 @@ import MagicString from 'magic-string';
import { walk } from 'estree-walker';
import deindent from './utils/deindent.js';
import walkHtml from './utils/walkHtml.js';
import flattenReference from './utils/flattenReference.js';
import isReference from './utils/isReference.js';
import contextualise from './utils/contextualise.js';
import counter from './utils/counter.js';
@ -54,6 +53,13 @@ export default function generate ( parsed, template ) {
}
}
const helpers = {};
if ( templateProperties.helpers ) {
templateProperties.helpers.properties.forEach( prop => {
helpers[ prop.key.name ] = prop.value;
});
}
const renderers = [];
const expressionFunctions = [];
@ -86,6 +92,10 @@ export default function generate ( parsed, template ) {
parsed.html.children.forEach( child => {
walkHtml( child, {
Comment: {
// do nothing
},
Element: {
enter ( node ) {
const name = current.counter( node.name );
@ -105,7 +115,7 @@ export default function generate ( parsed, template ) {
node.attributes.forEach( attribute => {
if ( attribute.type === 'Attribute' ) {
let metadata = attributeLookup[ attribute.name ];
if ( metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) metadata = null;
if ( metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) metadata = null;
if ( attribute.value === true ) {
// attributes without values, e.g. <textarea readonly>
@ -142,7 +152,7 @@ export default function generate ( parsed, template ) {
else {
// dynamic but potentially non-string attributes
contextualise( code, value.expression, current.contexts );
contextualise( code, value.expression, current.contexts, helpers );
result = `[✂${value.expression.start}-${value.expression.end}✂]`;
if ( metadata ) {
@ -163,7 +173,7 @@ export default function generate ( parsed, template ) {
if ( chunk.type === 'Text' ) {
return JSON.stringify( chunk.data );
} else {
contextualise( code, chunk.expression, current.contexts );
contextualise( code, chunk.expression, current.contexts, helpers );
return `[✂${chunk.expression.start}-${chunk.expression.end}✂]`;
}
}).join( ' + ' )
@ -190,7 +200,7 @@ export default function generate ( parsed, template ) {
const usedContexts = new Set();
attribute.expression.arguments.forEach( arg => {
const contexts = contextualise( code, arg, current.contexts );
const contexts = contextualise( code, arg, current.contexts, helpers );
contexts.forEach( context => {
usedContexts.add( context );
@ -285,7 +295,7 @@ export default function generate ( parsed, template ) {
${current.target}.appendChild( ${name} );
` );
const usedContexts = contextualise( code, node.expression, current.contexts );
const usedContexts = contextualise( code, node.expression, current.contexts, helpers );
const snippet = `[✂${node.expression.start}-${node.expression.end}✂]`;
if ( isReference( node.expression ) ) {
@ -299,17 +309,17 @@ export default function generate ( parsed, template ) {
}
` );
} else {
const expressionFunction = getName( 'expression' );
expressionFunctions.push( deindent`
function ${expressionFunction} ( ${usedContexts.join( ', ' )} ) {
return ${snippet};
}
` );
// const expressionFunction = getName( 'expression' );
// expressionFunctions.push( deindent`
// function ${expressionFunction} ( ${usedContexts.join( ', ' )} ) {
// return ${snippet};
// }
// ` );
const temp = getName( 'temp' );
current.updateStatements.push( deindent`
var ${temp} = ${expressionFunction}( ${usedContexts.join( ', ' )} );
var ${temp} = ${snippet};
if ( ${temp} !== ${name}_value ) {
${name}_value = ${temp};
${name}.data = ${name}_value;
@ -331,7 +341,7 @@ export default function generate ( parsed, template ) {
var ${name} = null;
` );
const usedContexts = contextualise( code, node.expression, current.contexts );
const usedContexts = contextualise( code, node.expression, current.contexts, helpers );
const snippet = `[✂${node.expression.start}-${node.expression.end}✂]`;
let expression;
@ -371,7 +381,7 @@ export default function generate ( parsed, template ) {
}
if ( ${name} ) {
${name}.update( ${current.contextChain.join( '\n' )} );
${name}.update( ${current.contextChain.join( ', ' )} );
}
` );
@ -417,7 +427,7 @@ export default function generate ( parsed, template ) {
const ${name}_fragment = document.createDocumentFragment();
` );
const usedContexts = contextualise( code, node.expression, current.contexts );
const usedContexts = contextualise( code, node.expression, current.contexts, helpers );
const snippet = `[✂${node.expression.start}-${node.expression.end}✂]`;
let expression;

@ -2,13 +2,19 @@ import { walk } from 'estree-walker';
import isReference from './isReference.js';
import flattenReference from './flattenReference.js';
export default function contextualise ( code, expression, contexts ) {
export default function contextualise ( code, expression, contexts, helpers ) {
const usedContexts = [];
walk( expression, {
enter ( node, parent ) {
if ( isReference( node, parent ) ) {
const { name } = flattenReference( node );
if ( parent && parent.type === 'CallExpression' && node === parent.callee ) {
if ( helpers[ name ] ) code.insertRight( node.start, `template.helpers.` );
return;
}
if ( contexts[ name ] ) {
if ( !~usedContexts.indexOf( name ) ) usedContexts.push( name );
} else {

@ -17,10 +17,16 @@ export default function readScript ( parser, start, attributes ) {
const source = spaces( scriptStart ) + parser.template.slice( scriptStart, scriptEnd );
const ast = parse( source, {
ecmaVersion: 8,
sourceType: 'module'
});
let ast;
try {
ast = parse( source, {
ecmaVersion: 8,
sourceType: 'module'
});
} catch ( err ) {
parser.acornError( err );
}
ast.start = scriptStart;

@ -0,0 +1,3 @@
export default {
html: '<p>sdrawkcab</p>'
};

@ -0,0 +1,14 @@
<p>{{reverse('backwards')}}</p>
<script>
export default {
helpers: {
reverse ( str ) {
let reversed = '';
let i = str.length;
while ( i-- ) reversed += str[i];
return reversed;
}
}
};
</script>
Loading…
Cancel
Save