parse event handler directives

pull/31/head
Rich-Harris 8 years ago
parent 1936414800
commit b59b33bf06

@ -13,7 +13,7 @@ export default function parse ( template ) {
return this.stack[ this.stack.length - 1 ];
},
error ( message ) {
error ( message, index = this.index ) {
const { line, column } = locate( this.template, this.index );
throw new Error( `${message} (${line}:${column})` );
},

@ -0,0 +1,41 @@
import { tokenizer, tokTypes, parseExpressionAt } from 'acorn';
export function readEventHandlerDirective ( parser, name ) {
const quoteMark = (
parser.eat( `'` ) ? `'` :
parser.eat( `"` ) ? `"` :
null
);
const start = parser.index;
let end = null;
let depth = 0;
for ( const token of tokenizer( parser.remaining() ) ) {
if ( token.type === tokTypes.parenL ) depth += 1;
if ( token.type === tokTypes.parenR ) {
depth -= 1;
if ( depth === 0 ) {
end = start + token.end;
break;
}
}
}
const expression = parseExpressionAt( parser.template.slice( 0, end ), start );
parser.index = expression.end;
if ( expression.type !== 'CallExpression' ) {
parser.error( `Expected call expression`, start );
}
if ( quoteMark ) {
parser.eat( quoteMark, true );
}
return {
type: 'EventHandler',
name,
expression
};
}

@ -1,6 +1,7 @@
import readExpression from '../read/expression.js';
import readScript from '../read/script.js';
import readStyle from '../read/style.js';
import { readEventHandlerDirective } from '../read/directives.js';
const validTagName = /^[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
const voidElementNames = /^(?:area|base|br|col|command|doctype|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i;
@ -26,6 +27,8 @@ export default function tag ( parser ) {
const name = readTagName( parser );
parser.allowWhitespace();
if ( isClosingTag ) {
if ( !parser.eat( '>' ) ) parser.error( `Expected '>'` );
@ -100,9 +103,18 @@ function readAttribute ( parser ) {
parser.allowWhitespace();
if ( /^on:/.test( name ) ) {
parser.eat( '=', true );
return readEventHandlerDirective( parser, name.slice( 3 ) );
}
const value = parser.eat( '=' ) ? readAttributeValue( parser ) : true;
return { name, value };
return {
type: 'Attribute',
name,
value
};
}
function readAttributeValue ( parser ) {

@ -32,6 +32,7 @@
},
"dependencies": {
"acorn": "^4.0.3",
"locate-character": "^2.0.0"
"locate-character": "^2.0.0",
"magic-string": "^0.16.0"
}
}

@ -0,0 +1,36 @@
export default {
description: 'nested {{#each}} blocks where inner iterates over property of outer',
data: {
categories: [
{
name: 'animals',
things: [
{ name: 'aardvark' },
{ name: 'buffalo' },
{ name: 'chinchilla' }
]
},
{
name: 'countries',
things: [
{ name: 'albania' },
{ name: 'brazil' },
{ name: 'china' }
]
},
{
name: 'people',
things: [
{ name: 'alice' },
{ name: 'bob' },
{ name: 'carol' },
{ name: 'dave' }
]
}
]
},
html: `<p>animals: aardvark</p><p>animals: buffalo</p><p>animals: chinchilla</p><!--#each category.things--><p>countries: albania</p><p>countries: brazil</p><p>countries: china</p><!--#each category.things--><p>people: alice</p><p>people: bob</p><p>people: carol</p><p>people: dave</p><!--#each category.things--><!--#each categories-->`,
test ( component, target ) {
// TODO
}
};

@ -0,0 +1,5 @@
{{#each categories as category}}
{{#each category.things as thing}}
<p>{{category.name}}: {{thing.name}}</p>
{{/each}}
{{/each}}

@ -0,0 +1,5 @@
<button on:click='set({ visible: !visible })'>toggle</button>
{{#if visible}}
<p>hello!</p>
{{/if}}

@ -0,0 +1,107 @@
{
"html": {
"start": 0,
"end": 101,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 61,
"type": "Element",
"name": "button",
"attributes": [
{
"type": "EventHandler",
"name": "click",
"expression": {
"start": 18,
"end": 44,
"type": "CallExpression",
"callee": {
"start": 18,
"end": 21,
"type": "Identifier",
"name": "set"
},
"arguments": [
{
"start": 22,
"end": 43,
"type": "ObjectExpression",
"properties": [
{
"start": 24,
"end": 41,
"type": "Property",
"kind": "init",
"computed": false,
"method": false,
"shorthand": false,
"key": {
"start": 24,
"end": 31,
"type": "Identifier",
"name": "visible"
},
"value": {
"start": 33,
"end": 41,
"type": "UnaryExpression",
"operator": "!",
"prefix": true,
"argument": {
"start": 34,
"end": 41,
"type": "Identifier",
"name": "visible"
}
}
}
]
}
]
}
}
],
"children": [
{
"data": "toggle",
"start": 46,
"end": 52,
"type": "Text"
}
]
},
{
"start": 63,
"end": 101,
"type": "IfBlock",
"expression": {
"end": 76,
"name": "visible",
"start": 69,
"type": "Identifier"
},
"children": [
{
"start": 80,
"end": 93,
"type": "Element",
"name": "p",
"attributes": [],
"children": [
{
"data": "hello!",
"end": 89,
"start": 83,
"type": "Text"
}
]
}
]
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save