From 84595fb38192ef00dcad44676e64155ba85f26af Mon Sep 17 00:00:00 2001
From: Rich Harris <richard.a.harris@gmail.com>
Date: Fri, 2 Jun 2017 21:57:25 -0400
Subject: [PATCH] run prettier on src, update tests

---
 src/generators/Generator.ts                   | 490 +++++++++++-------
 src/generators/dom/Block.ts                   | 208 ++++----
 src/generators/dom/index.ts                   | 298 +++++++----
 src/generators/dom/interfaces.ts              |   2 +-
 src/generators/dom/preprocess.ts              | 314 ++++++-----
 src/generators/dom/visit.ts                   |  13 +-
 .../dom/visitors/Component/Attribute.ts       |  68 +--
 .../dom/visitors/Component/Binding.ts         |  70 ++-
 .../dom/visitors/Component/Component.ts       | 164 +++---
 .../dom/visitors/Component/EventHandler.ts    |  45 +-
 src/generators/dom/visitors/Component/Ref.ts  |  15 +-
 src/generators/dom/visitors/EachBlock.ts      | 281 ++++++----
 .../dom/visitors/Element/Attribute.ts         | 154 +++---
 .../dom/visitors/Element/Binding.ts           | 231 ++++++---
 .../dom/visitors/Element/Element.ts           | 133 +++--
 .../dom/visitors/Element/EventHandler.ts      |  96 ++--
 src/generators/dom/visitors/Element/Ref.ts    |  14 +-
 .../dom/visitors/Element/addTransitions.ts    |  79 +--
 .../Element/getStaticAttributeValue.ts        |  14 +-
 src/generators/dom/visitors/Element/lookup.ts | 313 +++++++----
 .../dom/visitors/Element/meta/Window.ts       | 131 +++--
 src/generators/dom/visitors/IfBlock.ts        | 308 ++++++-----
 src/generators/dom/visitors/MustacheTag.ts    |  26 +-
 src/generators/dom/visitors/RawMustacheTag.ts |  47 +-
 src/generators/dom/visitors/Text.ts           |  18 +-
 src/generators/dom/visitors/YieldTag.ts       |  10 +-
 .../dom/visitors/shared/binding/getSetter.ts  |  40 +-
 src/generators/server-side-rendering/Block.ts |  34 +-
 src/generators/server-side-rendering/index.ts |  75 ++-
 src/generators/server-side-rendering/visit.ts |  12 +-
 .../server-side-rendering/visitors/Comment.ts |   2 +-
 .../visitors/Component.ts                     |  73 +--
 .../visitors/EachBlock.ts                     |  36 +-
 .../server-side-rendering/visitors/Element.ts |  62 ++-
 .../server-side-rendering/visitors/IfBlock.ts |  28 +-
 .../visitors/MustacheTag.ts                   |  12 +-
 .../visitors/RawMustacheTag.ts                |  12 +-
 .../server-side-rendering/visitors/Text.ts    |  10 +-
 .../visitors/YieldTag.ts                      |   6 +-
 .../visitors/meta/Window.ts                   |   4 +-
 src/generators/shared/processCss.ts           | 113 ++--
 src/generators/shared/utils/getGlobals.ts     |  48 +-
 src/generators/shared/utils/getIntro.ts       | 101 ++--
 src/generators/shared/utils/getOutro.ts       |  29 +-
 src/generators/shared/utils/walkHtml.ts       |  20 +-
 src/index.ts                                  |  67 +--
 src/interfaces.ts                             |  14 +-
 src/parse/index.ts                            | 124 +++--
 src/parse/read/directives.ts                  | 109 ++--
 src/parse/read/expression.ts                  |  24 +-
 src/parse/read/script.ts                      |  19 +-
 src/parse/read/style.ts                       |  20 +-
 src/parse/state/fragment.ts                   |   6 +-
 src/parse/state/mustache.ts                   | 152 +++---
 src/parse/state/tag.ts                        | 334 ++++++------
 src/parse/state/text.ts                       |  12 +-
 src/parse/utils/entities.ts                   |   2 +-
 src/parse/utils/hash.ts                       |   4 +-
 src/parse/utils/html.ts                       |  78 ++-
 src/server-side-rendering/register.js         |  12 +-
 src/shared/_build.js                          |  41 +-
 src/shared/dom.js                             |  66 +--
 src/shared/index.js                           | 111 ++--
 src/shared/transitions.js                     | 133 +++--
 src/shared/utils.js                           |  13 +-
 src/utils/CodeBuilder.ts                      |  58 ++-
 src/utils/CompileError.ts                     |  28 +-
 src/utils/__test__.ts                         | 132 +++--
 src/utils/annotateWithScopes.ts               | 106 ++--
 src/utils/deindent.js                         |  45 +-
 src/utils/flattenReference.ts                 |  16 +-
 src/utils/getCodeFrame.ts                     |  37 +-
 src/utils/globalWhitelist.ts                  |  27 +-
 src/utils/isReference.ts                      |  22 +-
 src/utils/isVoidElementName.ts                |   4 +-
 src/utils/namespaces.ts                       |  24 +-
 src/utils/removeNode.ts                       |  42 +-
 src/utils/reservedNames.ts                    |  55 +-
 src/utils/spaces.js                           |   4 +-
 src/utils/trim.ts                             |  12 +-
 src/validate/html/index.ts                    |  52 +-
 src/validate/html/validateElement.ts          | 166 +++---
 src/validate/html/validateEventHandler.ts     |  43 +-
 src/validate/html/validateWindow.ts           |  46 +-
 src/validate/index.ts                         |  53 +-
 src/validate/js/index.ts                      |  86 +--
 src/validate/js/propValidators/components.ts  |  26 +-
 src/validate/js/propValidators/computed.ts    |  52 +-
 src/validate/js/propValidators/data.ts        |  10 +-
 src/validate/js/propValidators/events.ts      |  13 +-
 src/validate/js/propValidators/helpers.ts     |  62 ++-
 src/validate/js/propValidators/methods.ts     |  36 +-
 src/validate/js/propValidators/namespace.ts   |  24 +-
 src/validate/js/propValidators/oncreate.ts    |  11 +-
 src/validate/js/propValidators/ondestroy.ts   |  11 +-
 src/validate/js/propValidators/onrender.ts    |   9 +-
 src/validate/js/propValidators/onteardown.ts  |   9 +-
 src/validate/js/propValidators/transitions.ts |  15 +-
 src/validate/js/utils/checkForAccessors.ts    |  12 +-
 src/validate/js/utils/checkForComputedKeys.ts |  11 +-
 src/validate/js/utils/checkForDupes.ts        |  13 +-
 src/validate/js/utils/usesThisOrArguments.ts  |  20 +-
 src/validate/utils/FuzzySet.ts                |  72 ++-
 src/validate/utils/fuzzymatch.ts              |  12 +-
 src/validate/utils/list.ts                    |  10 +-
 .../expected-bundle.js                        | 122 ++---
 .../computed-collapsed-if/expected-bundle.js  |  98 ++--
 .../expected-bundle.js                        | 130 ++---
 .../each-block-changed-check/expected.js      |   2 +-
 .../event-handlers-custom/expected-bundle.js  | 114 ++--
 .../if-block-no-update/expected-bundle.js     | 122 ++---
 .../if-block-simple/expected-bundle.js        | 122 ++---
 .../non-imported-component/expected-bundle.js | 106 ++--
 .../expected-bundle.js                        |  98 ++--
 .../expected-bundle.js                        | 122 ++---
 test/js/update.js                             |  10 +
 116 files changed, 4787 insertions(+), 3345 deletions(-)
 create mode 100644 test/js/update.js

diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts
index 6ee4171cf1..09b7e3409a 100644
--- a/src/generators/Generator.ts
+++ b/src/generators/Generator.ts
@@ -42,7 +42,12 @@ export default class Generator {
 	aliases: Map<string, string>;
 	usedNames: Set<string>;
 
-	constructor ( parsed: Parsed, source: string, name: string, options: CompileOptions ) {
+	constructor(
+		parsed: Parsed,
+		source: string,
+		name: string,
+		options: CompileOptions
+	) {
 		this.parsed = parsed;
 		this.source = source;
 		this.name = name;
@@ -61,9 +66,9 @@ export default class Generator {
 		// in dev mode
 		this.expectedProperties = new Set();
 
-		this.code = new MagicString( source );
+		this.code = new MagicString(source);
 		this.cascade = options.cascade !== false; // TODO remove this option in v2
-		this.css = parsed.css ? processCss( parsed, this.code, this.cascade ) : null;
+		this.css = parsed.css ? processCss(parsed, this.code, this.cascade) : null;
 		this.cssId = parsed.css ? `svelte-${parsed.hash}` : '';
 		this.usesRefs = false;
 
@@ -71,105 +76,112 @@ export default class Generator {
 		// Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`;
 		this.importedNames = new Set();
 		this.aliases = new Map();
-		this.usedNames = new Set( [ name ] );
+		this.usedNames = new Set([name]);
 	}
 
-	addSourcemapLocations ( node: Node ) {
-		walk( node, {
-			enter: ( node: Node ) => {
-				this.code.addSourcemapLocation( node.start );
-				this.code.addSourcemapLocation( node.end );
+	addSourcemapLocations(node: Node) {
+		walk(node, {
+			enter: (node: Node) => {
+				this.code.addSourcemapLocation(node.start);
+				this.code.addSourcemapLocation(node.end);
 			}
 		});
 	}
 
-	alias ( name: string ) {
-		if ( !this.aliases.has( name ) ) {
-			this.aliases.set( name, this.getUniqueName( name ) );
+	alias(name: string) {
+		if (!this.aliases.has(name)) {
+			this.aliases.set(name, this.getUniqueName(name));
 		}
 
-		return this.aliases.get( name );
+		return this.aliases.get(name);
 	}
 
-	contextualise ( block: DomBlock | SsrBlock, expression: Node, context: string, isEventHandler: boolean ) {
-		this.addSourcemapLocations( expression );
+	contextualise(
+		block: DomBlock | SsrBlock,
+		expression: Node,
+		context: string,
+		isEventHandler: boolean
+	) {
+		this.addSourcemapLocations(expression);
 
 		const usedContexts: string[] = [];
 
 		const { code, helpers } = this;
 		const { contexts, indexes } = block;
 
-		let scope = annotateWithScopes( expression ); // TODO this already happens in findDependencies
+		let scope = annotateWithScopes(expression); // TODO this already happens in findDependencies
 		let lexicalDepth = 0;
 
 		const self = this;
 
-		walk( expression, {
-			enter ( node: Node, parent: Node, key: string ) {
-				if ( /^Function/.test( node.type ) ) lexicalDepth += 1;
+		walk(expression, {
+			enter(node: Node, parent: Node, key: string) {
+				if (/^Function/.test(node.type)) lexicalDepth += 1;
 
-				if ( node._scope ) {
+				if (node._scope) {
 					scope = node._scope;
 					return;
 				}
 
-				if ( node.type === 'ThisExpression' ) {
-					if ( lexicalDepth === 0 && context ) code.overwrite( node.start, node.end, context, { storeName: true, contentOnly: false } );
-				}
-
-				else if ( isReference( node, parent ) ) {
-					const { name } = flattenReference( node );
-					if ( scope.has( name ) ) return;
-
-					if ( name === 'event' && isEventHandler ) {
+				if (node.type === 'ThisExpression') {
+					if (lexicalDepth === 0 && context)
+						code.overwrite(node.start, node.end, context, {
+							storeName: true,
+							contentOnly: false
+						});
+				} else if (isReference(node, parent)) {
+					const { name } = flattenReference(node);
+					if (scope.has(name)) return;
+
+					if (name === 'event' && isEventHandler) {
 						// noop
-					}
-
-					else if ( contexts.has( name ) ) {
-						const contextName = contexts.get( name );
-						if ( contextName !== name ) {
+					} else if (contexts.has(name)) {
+						const contextName = contexts.get(name);
+						if (contextName !== name) {
 							// this is true for 'reserved' names like `state` and `component`
-							code.overwrite( node.start, node.start + name.length, contextName, { storeName: true, contentOnly: false } );
+							code.overwrite(
+								node.start,
+								node.start + name.length,
+								contextName,
+								{ storeName: true, contentOnly: false }
+							);
 						}
 
-						if ( !~usedContexts.indexOf( name ) ) usedContexts.push( name );
-					}
-
-					else if ( helpers.has( name ) ) {
-						code.prependRight( node.start, `${self.alias( 'template' )}.helpers.` );
-					}
-
-					else if ( indexes.has( name ) ) {
-						const context = indexes.get( name );
-						if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
-					}
-
-					else {
+						if (!~usedContexts.indexOf(name)) usedContexts.push(name);
+					} else if (helpers.has(name)) {
+						code.prependRight(node.start, `${self.alias('template')}.helpers.`);
+					} else if (indexes.has(name)) {
+						const context = indexes.get(name);
+						if (!~usedContexts.indexOf(context)) usedContexts.push(context);
+					} else {
 						// handle shorthand properties
-						if ( parent && parent.type === 'Property' && parent.shorthand ) {
-							if ( key === 'key' ) {
-								code.appendLeft( node.start, `${name}: ` );
+						if (parent && parent.type === 'Property' && parent.shorthand) {
+							if (key === 'key') {
+								code.appendLeft(node.start, `${name}: `);
 								return;
 							}
 						}
 
-						if ( globalWhitelist.has( name ) ) {
-							code.prependRight( node.start, `( '${name}' in state ? state.` );
-							code.appendLeft( node.object ? node.object.end : node.end, ` : ${name} )` );
+						if (globalWhitelist.has(name)) {
+							code.prependRight(node.start, `( '${name}' in state ? state.`);
+							code.appendLeft(
+								node.object ? node.object.end : node.end,
+								` : ${name} )`
+							);
 						} else {
-							code.prependRight( node.start, `state.` );
+							code.prependRight(node.start, `state.`);
 						}
 
-						if ( !~usedContexts.indexOf( 'state' ) ) usedContexts.push( 'state' );
+						if (!~usedContexts.indexOf('state')) usedContexts.push('state');
 					}
 
 					this.skip();
 				}
 			},
 
-			leave ( node: Node ) {
-				if ( /^Function/.test( node.type ) ) lexicalDepth -= 1;
-				if ( node._scope ) scope = scope.parent;
+			leave(node: Node) {
+				if (/^Function/.test(node.type)) lexicalDepth -= 1;
+				if (node._scope) scope = scope.parent;
 			}
 		});
 
@@ -180,112 +192,133 @@ export default class Generator {
 		};
 	}
 
-	findDependencies ( contextDependencies: Map<string, string[]>, indexes: Map<string, string>, expression: Node ) {
-		if ( expression._dependencies ) return expression._dependencies;
+	findDependencies(
+		contextDependencies: Map<string, string[]>,
+		indexes: Map<string, string>,
+		expression: Node
+	) {
+		if (expression._dependencies) return expression._dependencies;
 
-		let scope = annotateWithScopes( expression );
+		let scope = annotateWithScopes(expression);
 		const dependencies: string[] = [];
 
 		const generator = this; // can't use arrow functions, because of this.skip()
 
-		walk( expression, {
-			enter ( node: Node, parent: Node ) {
-				if ( node._scope ) {
+		walk(expression, {
+			enter(node: Node, parent: Node) {
+				if (node._scope) {
 					scope = node._scope;
 					return;
 				}
 
-				if ( isReference( node, parent ) ) {
-					const { name } = flattenReference( node );
-					if ( scope.has( name ) || generator.helpers.has( name ) ) return;
+				if (isReference(node, parent)) {
+					const { name } = flattenReference(node);
+					if (scope.has(name) || generator.helpers.has(name)) return;
 
-					if ( contextDependencies.has( name ) ) {
-						dependencies.push( ...contextDependencies.get( name ) );
-					} else if ( !indexes.has( name ) ) {
-						dependencies.push( name );
+					if (contextDependencies.has(name)) {
+						dependencies.push(...contextDependencies.get(name));
+					} else if (!indexes.has(name)) {
+						dependencies.push(name);
 					}
 
 					this.skip();
 				}
 			},
 
-			leave ( node: Node ) {
-				if ( node._scope ) scope = scope.parent;
+			leave(node: Node) {
+				if (node._scope) scope = scope.parent;
 			}
 		});
 
-		dependencies.forEach( name => {
-			if ( !globalWhitelist.has( name ) ) {
-				this.expectedProperties.add( name );
+		dependencies.forEach(name => {
+			if (!globalWhitelist.has(name)) {
+				this.expectedProperties.add(name);
 			}
 		});
 
-		return ( expression._dependencies = dependencies );
+		return (expression._dependencies = dependencies);
 	}
 
-	generate ( result, options, { name, format } ) {
-		if ( this.imports.length ) {
+	generate(result, options, { name, format }) {
+		if (this.imports.length) {
 			const statements: string[] = [];
 
-			this.imports.forEach( ( declaration, i ) => {
-				if ( format === 'es' ) {
-					statements.push( this.source.slice( declaration.start, declaration.end ) );
+			this.imports.forEach((declaration, i) => {
+				if (format === 'es') {
+					statements.push(
+						this.source.slice(declaration.start, declaration.end)
+					);
 					return;
 				}
 
-				const defaultImport = declaration.specifiers.find( ( x: Node ) => x.type === 'ImportDefaultSpecifier' || x.type === 'ImportSpecifier' && x.imported.name === 'default' );
-				const namespaceImport = declaration.specifiers.find( ( x: Node ) => x.type === 'ImportNamespaceSpecifier' );
-				const namedImports = declaration.specifiers.filter( ( x: Node ) => x.type === 'ImportSpecifier' && x.imported.name !== 'default' );
-
-				const name = ( defaultImport || namespaceImport ) ? ( defaultImport || namespaceImport ).local.name : `__import${i}`;
+				const defaultImport = declaration.specifiers.find(
+					(x: Node) =>
+						x.type === 'ImportDefaultSpecifier' ||
+						(x.type === 'ImportSpecifier' && x.imported.name === 'default')
+				);
+				const namespaceImport = declaration.specifiers.find(
+					(x: Node) => x.type === 'ImportNamespaceSpecifier'
+				);
+				const namedImports = declaration.specifiers.filter(
+					(x: Node) =>
+						x.type === 'ImportSpecifier' && x.imported.name !== 'default'
+				);
+
+				const name = defaultImport || namespaceImport
+					? (defaultImport || namespaceImport).local.name
+					: `__import${i}`;
 				declaration.name = name; // hacky but makes life a bit easier later
 
-				namedImports.forEach( ( specifier: Node ) => {
-					statements.push( `var ${specifier.local.name} = ${name}.${specifier.imported.name}` );
+				namedImports.forEach((specifier: Node) => {
+					statements.push(
+						`var ${specifier.local.name} = ${name}.${specifier.imported.name}`
+					);
 				});
 
-				if ( defaultImport ) {
-					statements.push( `${name} = ( ${name} && ${name}.__esModule ) ? ${name}['default'] : ${name};` );
+				if (defaultImport) {
+					statements.push(
+						`${name} = ( ${name} && ${name}.__esModule ) ? ${name}['default'] : ${name};`
+					);
 				}
 			});
 
-			result = `${statements.join( '\n' )}\n\n${result}`;
+			result = `${statements.join('\n')}\n\n${result}`;
 		}
 
 		const pattern = /\[✂(\d+)-(\d+)$/;
 
-		const parts = result.split( '✂]' );
+		const parts = result.split('✂]');
 		const finalChunk = parts.pop();
 
 		const compiled = new Bundle({ separator: '' });
 
-		function addString ( str: string ) {
+		function addString(str: string) {
 			compiled.addSource({
-				content: new MagicString( str )
+				content: new MagicString(str)
 			});
 		}
 
-		const intro = getIntro( format, options, this.imports );
-		if ( intro ) addString( intro );
+		const intro = getIntro(format, options, this.imports);
+		if (intro) addString(intro);
 
 		const { filename } = options;
 
 		// special case — the source file doesn't actually get used anywhere. we need
 		// to add an empty file to populate map.sources and map.sourcesContent
-		if ( !parts.length ) {
+		if (!parts.length) {
 			compiled.addSource({
 				filename,
-				content: new MagicString( this.source ).remove( 0, this.source.length )
+				content: new MagicString(this.source).remove(0, this.source.length)
 			});
 		}
 
-		parts.forEach( ( str: string ) => {
-			const chunk = str.replace( pattern, '' );
-			if ( chunk ) addString( chunk );
+		parts.forEach((str: string) => {
+			const chunk = str.replace(pattern, '');
+			if (chunk) addString(chunk);
 
-			const match = pattern.exec( str );
+			const match = pattern.exec(str);
 
-			const snippet = this.code.snip( +match[1], +match[2] );
+			const snippet = this.code.snip(+match[1], +match[2]);
 
 			compiled.addSource({
 				filename,
@@ -293,36 +326,52 @@ export default class Generator {
 			});
 		});
 
-		addString( finalChunk );
-		addString( '\n\n' + getOutro( format, name, options, this.imports ) );
+		addString(finalChunk);
+		addString('\n\n' + getOutro(format, name, options, this.imports));
 
 		return {
 			code: compiled.toString(),
-			map: compiled.generateMap({ includeContent: true, file: options.outputFilename }),
+			map: compiled.generateMap({
+				includeContent: true,
+				file: options.outputFilename
+			}),
 			css: this.css
 		};
 	}
 
-	getUniqueName ( name: string ) {
-		if ( test ) name = `${name}$`;
+	getUniqueName(name: string) {
+		if (test) name = `${name}$`;
 		let alias = name;
-		for ( let i = 1; reservedNames.has( alias ) || this.importedNames.has( alias ) || this.usedNames.has( alias ); alias = `${name}_${i++}` );
-		this.usedNames.add( alias );
+		for (
+			let i = 1;
+			reservedNames.has(alias) ||
+			this.importedNames.has(alias) ||
+			this.usedNames.has(alias);
+			alias = `${name}_${i++}`
+		);
+		this.usedNames.add(alias);
 		return alias;
 	}
 
-	getUniqueNameMaker ( params ) {
-		const localUsedNames = new Set( params );
+	getUniqueNameMaker(params) {
+		const localUsedNames = new Set(params);
 		return name => {
-			if ( test ) name = `${name}$`;
+			if (test) name = `${name}$`;
 			let alias = name;
-			for ( let i = 1; reservedNames.has( alias ) || this.importedNames.has( alias ) || this.usedNames.has( alias ) || localUsedNames.has( alias ); alias = `${name}_${i++}` );
-			localUsedNames.add( alias );
+			for (
+				let i = 1;
+				reservedNames.has(alias) ||
+				this.importedNames.has(alias) ||
+				this.usedNames.has(alias) ||
+				localUsedNames.has(alias);
+				alias = `${name}_${i++}`
+			);
+			localUsedNames.add(alias);
 			return alias;
 		};
 	}
 
-	parseJs ( ssr: boolean = false ) {
+	parseJs(ssr: boolean = false) {
 		const { source } = this;
 		const { js } = this.parsed;
 
@@ -333,154 +382,213 @@ export default class Generator {
 		let namespace = null;
 		let hasJs = !!js;
 
-		if ( js ) {
-			this.addSourcemapLocations( js.content );
+		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 < body.length; i += 1 ) {
+			for (let i = 0; i < body.length; i += 1) {
 				const node = body[i];
-				if ( node.type === 'ImportDeclaration' ) {
-					removeNode( this.code, js.content, node );
-					imports.push( node );
+				if (node.type === 'ImportDeclaration') {
+					removeNode(this.code, js.content, node);
+					imports.push(node);
 
-					node.specifiers.forEach( ( specifier: Node ) => {
-						this.importedNames.add( specifier.local.name );
+					node.specifiers.forEach((specifier: Node) => {
+						this.importedNames.add(specifier.local.name);
 					});
 				}
 			}
 
-			const defaultExport = body.find( ( node: Node ) => node.type === 'ExportDefaultDeclaration' );
+			const defaultExport = body.find(
+				(node: Node) => node.type === 'ExportDefaultDeclaration'
+			);
 
-			if ( defaultExport ) {
-				defaultExport.declaration.properties.forEach( ( prop: Node ) => {
-					templateProperties[ prop.key.name ] = prop;
+			if (defaultExport) {
+				defaultExport.declaration.properties.forEach((prop: Node) => {
+					templateProperties[prop.key.name] = prop;
 				});
 			}
 
-			[ 'helpers', 'events', 'components', 'transitions' ].forEach( key => {
-				if ( templateProperties[ key ] ) {
-					templateProperties[ key ].value.properties.forEach( ( prop: node ) => {
-						this[ key ].add( prop.key.name );
+			['helpers', 'events', 'components', 'transitions'].forEach(key => {
+				if (templateProperties[key]) {
+					templateProperties[key].value.properties.forEach((prop: node) => {
+						this[key].add(prop.key.name);
 					});
 				}
 			});
 
-			if ( templateProperties.computed ) {
+			if (templateProperties.computed) {
 				const dependencies = new Map();
 
-				templateProperties.computed.value.properties.forEach( ( prop: Node ) => {
+				templateProperties.computed.value.properties.forEach((prop: Node) => {
 					const key = prop.key.name;
 					const value = prop.value;
 
-					const deps = value.params.map( ( param: Node ) => param.type === 'AssignmentPattern' ? param.left.name : param.name );
-					dependencies.set( key, deps );
+					const deps = value.params.map(
+						(param: Node) =>
+							param.type === 'AssignmentPattern' ? param.left.name : param.name
+					);
+					dependencies.set(key, deps);
 				});
 
 				const visited = new Set();
 
-				function visit ( key ) {
-					if ( !dependencies.has( key ) ) return; // not a computation
+				function visit(key) {
+					if (!dependencies.has(key)) return; // not a computation
 
-					if ( visited.has( key ) ) return;
-					visited.add( key );
+					if (visited.has(key)) return;
+					visited.add(key);
 
-					const deps = dependencies.get( key );
-					deps.forEach( visit );
+					const deps = dependencies.get(key);
+					deps.forEach(visit);
 
 					computations.push({ key, deps });
 				}
 
-				templateProperties.computed.value.properties.forEach( ( prop: Node ) => visit( prop.key.name ) );
+				templateProperties.computed.value.properties.forEach((prop: Node) =>
+					visit(prop.key.name)
+				);
 			}
 
-			if ( templateProperties.namespace ) {
+			if (templateProperties.namespace) {
 				const ns = templateProperties.namespace.value.value;
-				namespace = namespaces[ ns ] || ns;
+				namespace = namespaces[ns] || ns;
 
-				removeObjectKey( this.code, defaultExport.declaration, 'namespace' );
+				removeObjectKey(this.code, defaultExport.declaration, 'namespace');
 			}
 
-			if ( templateProperties.components ) {
+			if (templateProperties.components) {
 				let hasNonImportedComponent = false;
-				templateProperties.components.value.properties.forEach( ( property: Node ) => {
-					const key = property.key.name;
-					const value = source.slice( property.value.start, property.value.end );
-					if ( this.importedNames.has( value ) ) {
-						this.importedComponents.set( key, value );
-					} else {
-						hasNonImportedComponent = true;
+				templateProperties.components.value.properties.forEach(
+					(property: Node) => {
+						const key = property.key.name;
+						const value = source.slice(
+							property.value.start,
+							property.value.end
+						);
+						if (this.importedNames.has(value)) {
+							this.importedComponents.set(key, value);
+						} else {
+							hasNonImportedComponent = true;
+						}
 					}
-				});
-				if ( hasNonImportedComponent ) {
+				);
+				if (hasNonImportedComponent) {
 					// remove the specific components that were imported, as we'll refer to them directly
-					Array.from( this.importedComponents.keys() ).forEach( key => {
-						removeObjectKey( this.code, templateProperties.components.value, key );
+					Array.from(this.importedComponents.keys()).forEach(key => {
+						removeObjectKey(
+							this.code,
+							templateProperties.components.value,
+							key
+						);
 					});
 				} else {
 					// remove the entire components portion of the export
-					removeObjectKey( this.code, defaultExport.declaration, 'components' );
+					removeObjectKey(this.code, defaultExport.declaration, 'components');
 				}
 			}
 
 			// Remove these after version 2
-			if ( templateProperties.onrender ) {
+			if (templateProperties.onrender) {
 				const { key } = templateProperties.onrender;
-				this.code.overwrite( key.start, key.end, 'oncreate', { storeName: true, contentOnly: false } );
+				this.code.overwrite(key.start, key.end, 'oncreate', {
+					storeName: true,
+					contentOnly: false
+				});
 				templateProperties.oncreate = templateProperties.onrender;
 			}
 
-			if ( templateProperties.onteardown ) {
+			if (templateProperties.onteardown) {
 				const { key } = templateProperties.onteardown;
-				this.code.overwrite( key.start, key.end, 'ondestroy', { storeName: true, contentOnly: false } );
+				this.code.overwrite(key.start, key.end, 'ondestroy', {
+					storeName: true,
+					contentOnly: false
+				});
 				templateProperties.ondestroy = templateProperties.onteardown;
 			}
 
 			// in an SSR context, we don't need to include events, methods, oncreate or ondestroy
-			if ( ssr ) {
-				if ( templateProperties.oncreate ) removeNode( this.code, defaultExport.declaration, templateProperties.oncreate );
-				if ( templateProperties.ondestroy ) removeNode( this.code, defaultExport.declaration, templateProperties.ondestroy );
-				if ( templateProperties.methods ) removeNode( this.code, defaultExport.declaration, templateProperties.methods );
-				if ( templateProperties.events ) removeNode( this.code, defaultExport.declaration, templateProperties.events );
+			if (ssr) {
+				if (templateProperties.oncreate)
+					removeNode(
+						this.code,
+						defaultExport.declaration,
+						templateProperties.oncreate
+					);
+				if (templateProperties.ondestroy)
+					removeNode(
+						this.code,
+						defaultExport.declaration,
+						templateProperties.ondestroy
+					);
+				if (templateProperties.methods)
+					removeNode(
+						this.code,
+						defaultExport.declaration,
+						templateProperties.methods
+					);
+				if (templateProperties.events)
+					removeNode(
+						this.code,
+						defaultExport.declaration,
+						templateProperties.events
+					);
 			}
 
 			// now that we've analysed the default export, we can determine whether or not we need to keep it
 			let hasDefaultExport = !!defaultExport;
-			if ( defaultExport && defaultExport.declaration.properties.length === 0 ) {
+			if (defaultExport && defaultExport.declaration.properties.length === 0) {
 				hasDefaultExport = false;
-				removeNode( this.code, js.content, defaultExport );
+				removeNode(this.code, js.content, defaultExport);
 			}
 
 			// if we do need to keep it, then we need to generate a return statement
-			if ( hasDefaultExport ) {
-				const finalNode = body[ body.length - 1 ];
-				if ( defaultExport === finalNode ) {
+			if (hasDefaultExport) {
+				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 ` );
+					this.code.overwrite(
+						defaultExport.start,
+						defaultExport.declaration.start,
+						`return `
+					);
 				} else {
-					const { declarations } = annotateWithScopes( js );
+					const { declarations } = annotateWithScopes(js);
 					let template = 'template';
-					for ( let i = 1; declarations.has( template ); template = `template_${i++}` );
-
-					this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `var ${template} = ` );
+					for (
+						let i = 1;
+						declarations.has(template);
+						template = `template_${i++}`
+					);
+
+					this.code.overwrite(
+						defaultExport.start,
+						defaultExport.declaration.start,
+						`var ${template} = `
+					);
 
 					let i = defaultExport.start;
-					while ( /\s/.test( source[ i - 1 ] ) ) i--;
+					while (/\s/.test(source[i - 1])) i--;
 
-					const indentation = source.slice( i, defaultExport.start );
-					this.code.appendLeft( finalNode.end, `\n\n${indentation}return ${template};` );
+					const indentation = source.slice(i, defaultExport.start);
+					this.code.appendLeft(
+						finalNode.end,
+						`\n\n${indentation}return ${template};`
+					);
 				}
 			}
 
 			// user code gets wrapped in an IIFE
-			if ( js.content.body.length ) {
-				const prefix = hasDefaultExport ? `var ${this.alias( 'template' )} = (function () {` : `(function () {`;
-				this.code.prependRight( js.content.start, prefix ).appendLeft( js.content.end, '}());' );
-			}
-
-			// if there's no need to include user code, remove it altogether
-			else {
-				this.code.remove( js.content.start, js.content.end );
+			if (js.content.body.length) {
+				const prefix = hasDefaultExport
+					? `var ${this.alias('template')} = (function () {`
+					: `(function () {`;
+				this.code
+					.prependRight(js.content.start, prefix)
+					.appendLeft(js.content.end, '}());');
+			} else {
+				// if there's no need to include user code, remove it altogether
+				this.code.remove(js.content.start, js.content.end);
 				hasJs = false;
 			}
 		}
diff --git a/src/generators/dom/Block.ts b/src/generators/dom/Block.ts
index 0131ca1e12..f99c1d52c9 100644
--- a/src/generators/dom/Block.ts
+++ b/src/generators/dom/Block.ts
@@ -48,7 +48,7 @@ export default class Block {
 		unmount: CodeBuilder;
 		detachRaw: CodeBuilder;
 		destroy: CodeBuilder;
-	}
+	};
 
 	hasIntroMethod: boolean;
 	hasOutroMethod: boolean;
@@ -64,7 +64,7 @@ export default class Block {
 	hasUpdateMethod: boolean;
 	autofocus: string;
 
-	constructor ( options: BlockOptions ) {
+	constructor(options: BlockOptions) {
 		this.generator = options.generator;
 		this.name = options.name;
 		this.expression = options.expression;
@@ -102,144 +102,169 @@ export default class Block {
 
 		this.aliases = new Map();
 		this.variables = new Map();
-		this.getUniqueName = this.generator.getUniqueNameMaker( options.params );
+		this.getUniqueName = this.generator.getUniqueNameMaker(options.params);
 
 		// unique names
-		this.component = this.getUniqueName( 'component' );
-		this.target = this.getUniqueName( 'target' );
+		this.component = this.getUniqueName('component');
+		this.target = this.getUniqueName('target');
 
 		this.hasUpdateMethod = false; // determined later
 	}
 
-	addDependencies ( dependencies ) {
-		dependencies.forEach( dependency => {
-			this.dependencies.add( dependency );
+	addDependencies(dependencies) {
+		dependencies.forEach(dependency => {
+			this.dependencies.add(dependency);
 		});
 	}
 
-	addElement ( name: string, renderStatement: string, parentNode: string, needsIdentifier = false ) {
+	addElement(
+		name: string,
+		renderStatement: string,
+		parentNode: string,
+		needsIdentifier = false
+	) {
 		const isToplevel = !parentNode;
-		if ( needsIdentifier || isToplevel ) {
-			this.builders.create.addLine(
-				`var ${name} = ${renderStatement};`
-			);
+		if (needsIdentifier || isToplevel) {
+			this.builders.create.addLine(`var ${name} = ${renderStatement};`);
 
-			this.mount( name, parentNode );
+			this.mount(name, parentNode);
 		} else {
-			this.builders.create.addLine( `${this.generator.helper( 'appendNode' )}( ${renderStatement}, ${parentNode} );` );
+			this.builders.create.addLine(
+				`${this.generator.helper(
+					'appendNode'
+				)}( ${renderStatement}, ${parentNode} );`
+			);
 		}
 
-		if ( isToplevel ) {
-			this.builders.unmount.addLine( `${this.generator.helper( 'detachNode' )}( ${name} );` );
+		if (isToplevel) {
+			this.builders.unmount.addLine(
+				`${this.generator.helper('detachNode')}( ${name} );`
+			);
 		}
 	}
 
-	addVariable ( name: string, init?: string ) {
-		if ( this.variables.has( name ) && this.variables.get( name ) !== init ) {
-			throw new Error( `Variable '${name}' already initialised with a different value` );
+	addVariable(name: string, init?: string) {
+		if (this.variables.has(name) && this.variables.get(name) !== init) {
+			throw new Error(
+				`Variable '${name}' already initialised with a different value`
+			);
 		}
 
-		this.variables.set( name, init );
+		this.variables.set(name, init);
 	}
 
-	alias ( name: string ) {
-		if ( !this.aliases.has( name ) ) {
-			this.aliases.set( name, this.getUniqueName( name ) );
+	alias(name: string) {
+		if (!this.aliases.has(name)) {
+			this.aliases.set(name, this.getUniqueName(name));
 		}
 
-		return this.aliases.get( name );
+		return this.aliases.get(name);
 	}
 
-	child ( options: BlockOptions ) {
-		return new Block( Object.assign( {}, this, options, { parent: this } ) );
+	child(options: BlockOptions) {
+		return new Block(Object.assign({}, this, options, { parent: this }));
 	}
 
-	contextualise ( expression: Node, context?: string, isEventHandler?: boolean ) {
-		return this.generator.contextualise( this, expression, context, isEventHandler );
+	contextualise(expression: Node, context?: string, isEventHandler?: boolean) {
+		return this.generator.contextualise(
+			this,
+			expression,
+			context,
+			isEventHandler
+		);
 	}
 
-	findDependencies ( expression ) {
-		return this.generator.findDependencies( this.contextDependencies, this.indexes, expression );
+	findDependencies(expression) {
+		return this.generator.findDependencies(
+			this.contextDependencies,
+			this.indexes,
+			expression
+		);
 	}
 
-	mount ( name: string, parentNode: string ) {
-		if ( parentNode ) {
-			this.builders.create.addLine( `${this.generator.helper( 'appendNode' )}( ${name}, ${parentNode} );` );
+	mount(name: string, parentNode: string) {
+		if (parentNode) {
+			this.builders.create.addLine(
+				`${this.generator.helper('appendNode')}( ${name}, ${parentNode} );`
+			);
 		} else {
-			this.builders.mount.addLine( `${this.generator.helper( 'insertNode' )}( ${name}, ${this.target}, anchor );` );
+			this.builders.mount.addLine(
+				`${this.generator.helper('insertNode')}( ${name}, ${this
+					.target}, anchor );`
+			);
 		}
 	}
 
-	render () {
+	render() {
 		let introing;
 		const hasIntros = !this.builders.intro.isEmpty();
-		if ( hasIntros ) {
-			introing = this.getUniqueName( 'introing' );
-			this.addVariable( introing );
+		if (hasIntros) {
+			introing = this.getUniqueName('introing');
+			this.addVariable(introing);
 		}
 
 		let outroing;
 		const hasOutros = !this.builders.outro.isEmpty();
-		if ( hasOutros ) {
-			outroing = this.getUniqueName( 'outroing' );
-			this.addVariable( outroing );
+		if (hasOutros) {
+			outroing = this.getUniqueName('outroing');
+			this.addVariable(outroing);
 		}
 
-		if ( this.variables.size ) {
-			const variables = Array.from( this.variables.keys() )
-				.map( key => {
-					const init = this.variables.get( key );
+		if (this.variables.size) {
+			const variables = Array.from(this.variables.keys())
+				.map(key => {
+					const init = this.variables.get(key);
 					return init !== undefined ? `${key} = ${init}` : key;
 				})
-				.join( ', ' );
+				.join(', ');
 
-			this.builders.create.addBlockAtStart( `var ${variables};` );
+			this.builders.create.addBlockAtStart(`var ${variables};`);
 		}
 
-		if ( this.autofocus ) {
-			this.builders.create.addLine( `${this.autofocus}.focus();` );
+		if (this.autofocus) {
+			this.builders.create.addLine(`${this.autofocus}.focus();`);
 		}
 
 		// minor hack – we need to ensure that any {{{triples}}} are detached first
-		this.builders.unmount.addBlockAtStart( this.builders.detachRaw );
+		this.builders.unmount.addBlockAtStart(this.builders.detachRaw);
 
 		const properties = new CodeBuilder();
 
 		let localKey;
-		if ( this.key ) {
-			localKey = this.getUniqueName( 'key' );
-			properties.addBlock( `key: ${localKey},` );
+		if (this.key) {
+			localKey = this.getUniqueName('key');
+			properties.addBlock(`key: ${localKey},`);
 		}
 
-		if ( this.first ) {
-			properties.addBlock( `first: ${this.first},` );
+		if (this.first) {
+			properties.addBlock(`first: ${this.first},`);
 		}
 
-		if ( this.builders.mount.isEmpty() ) {
-			properties.addBlock( `mount: ${this.generator.helper( 'noop' )},` );
+		if (this.builders.mount.isEmpty()) {
+			properties.addBlock(`mount: ${this.generator.helper('noop')},`);
 		} else {
-			properties.addBlock( deindent`
+			properties.addBlock(deindent`
 				mount: function ( ${this.target}, anchor ) {
 					${this.builders.mount}
 				},
-			` );
+			`);
 		}
 
-		if ( this.hasUpdateMethod ) {
-			if ( this.builders.update.isEmpty() ) {
-				properties.addBlock( `update: ${this.generator.helper( 'noop' )},` );
+		if (this.hasUpdateMethod) {
+			if (this.builders.update.isEmpty()) {
+				properties.addBlock(`update: ${this.generator.helper('noop')},`);
 			} else {
-				properties.addBlock( deindent`
-					update: function ( changed, ${this.params.join( ', ' )} ) {
+				properties.addBlock(deindent`
+					update: function ( changed, ${this.params.join(', ')} ) {
 						${this.builders.update}
 					},
-				` );
+				`);
 			}
 		}
 
-		if ( this.hasIntroMethod ) {
-			if ( hasIntros ) {
-				properties.addBlock( deindent`
+		if (this.hasIntroMethod) {
+			if (hasIntros) {
+				properties.addBlock(deindent`
 					intro: function ( ${this.target}, anchor ) {
 						if ( ${introing} ) return;
 						${introing} = true;
@@ -249,60 +274,63 @@ export default class Block {
 
 						this.mount( ${this.target}, anchor );
 					},
-				` );
+				`);
 			} else {
-				properties.addBlock( deindent`
+				properties.addBlock(deindent`
 					intro: function ( ${this.target}, anchor ) {
 						this.mount( ${this.target}, anchor );
 					},
-				` );
+				`);
 			}
 		}
 
-		if ( this.hasOutroMethod ) {
-			if ( hasOutros ) {
-				properties.addBlock( deindent`
-					outro: function ( ${this.alias( 'outrocallback' )} ) {
+		if (this.hasOutroMethod) {
+			if (hasOutros) {
+				properties.addBlock(deindent`
+					outro: function ( ${this.alias('outrocallback')} ) {
 						if ( ${outroing} ) return;
 						${outroing} = true;
 						${hasIntros && `${introing} = false;`}
 
-						var ${this.alias( 'outros' )} = ${this.outros};
+						var ${this.alias('outros')} = ${this.outros};
 
 						${this.builders.outro}
 					},
-				` );
+				`);
 			} else {
-				properties.addBlock( deindent`
+				properties.addBlock(deindent`
 					outro: function ( outrocallback ) {
 						outrocallback();
 					},
-				` );
+				`);
 			}
 		}
 
-		if ( this.builders.unmount.isEmpty() ) {
-			properties.addBlock( `unmount: ${this.generator.helper('noop')},`);
+		if (this.builders.unmount.isEmpty()) {
+			properties.addBlock(`unmount: ${this.generator.helper('noop')},`);
 		} else {
-			properties.addBlock( deindent`
+			properties.addBlock(deindent`
 				unmount: function () {
 					${this.builders.unmount}
 				},
-			` );
+			`);
 		}
 
-		if ( this.builders.destroy.isEmpty() ) {
-			properties.addBlock( `destroy: ${this.generator.helper( 'noop' )}` );
+		if (this.builders.destroy.isEmpty()) {
+			properties.addBlock(`destroy: ${this.generator.helper('noop')}`);
 		} else {
-			properties.addBlock( deindent`
+			properties.addBlock(deindent`
 				destroy: function () {
 					${this.builders.destroy}
 				}
-			` );
+			`);
 		}
 
 		return deindent`
-			function ${this.name} ( ${this.params.join( ', ' )}, ${this.component}${this.key ? `, ${localKey}` : ''} ) {
+			function ${this.name} ( ${this.params.join(', ')}, ${this.component}${this
+			.key
+			? `, ${localKey}`
+			: ''} ) {
 				${this.builders.create}
 
 				return {
@@ -311,4 +339,4 @@ export default class Block {
 			}
 		`;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts
index 341608d428..cfb3bacdca 100644
--- a/src/generators/dom/index.ts
+++ b/src/generators/dom/index.ts
@@ -13,7 +13,7 @@ import Block from './Block';
 import { Parsed, CompileOptions, Node } from '../../interfaces';
 
 export class DomGenerator extends Generator {
-	blocks: Block[]
+	blocks: Block[];
 	uses: Set<string>;
 	readonly: Set<string>;
 	metaBindings: string[];
@@ -22,8 +22,13 @@ export class DomGenerator extends Generator {
 	hasOutroTransitions: boolean;
 	hasComplexBindings: boolean;
 
-	constructor ( parsed: Parsed, source: string, name: string, options: CompileOptions ) {
-		super( parsed, source, name, options );
+	constructor(
+		parsed: Parsed,
+		source: string,
+		name: string,
+		options: CompileOptions
+	) {
+		super(parsed, source, name, options);
 		this.blocks = [];
 		this.uses = new Set();
 
@@ -33,29 +38,38 @@ export class DomGenerator extends Generator {
 		this.metaBindings = [];
 	}
 
-	helper ( name: string ) {
-		if ( this.options.dev && `${name}Dev` in shared ) {
+	helper(name: string) {
+		if (this.options.dev && `${name}Dev` in shared) {
 			name = `${name}Dev`;
 		}
 
-		this.uses.add( name );
+		this.uses.add(name);
 
-		return this.alias( name );
+		return this.alias(name);
 	}
 }
 
-export default function dom ( parsed: Parsed, source: string, options: CompileOptions ) {
+export default function dom(
+	parsed: Parsed,
+	source: string,
+	options: CompileOptions
+) {
 	const format = options.format || 'es';
 	const name = options.name || 'SvelteComponent';
 
-	const generator = new DomGenerator( parsed, source, name, options );
+	const generator = new DomGenerator(parsed, source, name, options);
 
-	const { computations, hasJs, templateProperties, namespace } = generator.parseJs();
+	const {
+		computations,
+		hasJs,
+		templateProperties,
+		namespace
+	} = generator.parseJs();
 
-	const { block, state } = preprocess( generator, namespace, parsed.html );
+	const { block, state } = preprocess(generator, namespace, parsed.html);
 
-	parsed.html.children.forEach( ( node: Node ) => {
-		visit( generator, block, state, node );
+	parsed.html.children.forEach((node: Node) => {
+		visit(generator, block, state, node);
 	});
 
 	const builders = {
@@ -63,94 +77,139 @@ export default function dom ( parsed: Parsed, source: string, options: CompileOp
 		_set: new CodeBuilder()
 	};
 
-	if ( computations.length ) {
+	if (computations.length) {
 		const builder = new CodeBuilder();
-		const differs = generator.helper( 'differs' );
+		const differs = generator.helper('differs');
 
-		computations.forEach( ({ key, deps }) => {
-			if ( generator.readonly.has( key ) ) {
+		computations.forEach(({ key, deps }) => {
+			if (generator.readonly.has(key)) {
 				// <:Window> bindings
-				throw new Error( `Cannot have a computed value '${key}' that clashes with a read-only property` );
+				throw new Error(
+					`Cannot have a computed value '${key}' that clashes with a read-only property`
+				);
 			}
 
-			generator.readonly.add( key );
+			generator.readonly.add(key);
 
-			const condition = `isInitial || ${deps.map( dep => `( '${dep}' in newState && ${differs}( state.${dep}, oldState.${dep} ) )` ).join( ' || ' )}`;
-			const statement = `state.${key} = newState.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} );`;
+			const condition = `isInitial || ${deps
+				.map(
+					dep =>
+						`( '${dep}' in newState && ${differs}( state.${dep}, oldState.${dep} ) )`
+				)
+				.join(' || ')}`;
+			const statement = `state.${key} = newState.${key} = ${generator.alias(
+				'template'
+			)}.computed.${key}( ${deps.map(dep => `state.${dep}`).join(', ')} );`;
 
-			builder.addConditionalLine( condition, statement );
+			builder.addConditionalLine(condition, statement);
 		});
 
-		builders.main.addBlock( deindent`
-			function ${generator.alias( 'recompute' )} ( state, newState, oldState, isInitial ) {
+		builders.main.addBlock(deindent`
+			function ${generator.alias(
+				'recompute'
+			)} ( state, newState, oldState, isInitial ) {
 				${builder}
 			}
-		` );
+		`);
 	}
 
-	builders._set.addBlock( deindent`
-		${options.dev && deindent`
+	builders._set.addBlock(deindent`
+		${options.dev &&
+			deindent`
 			if ( typeof newState !== 'object' ) {
 				throw new Error( 'Component .set was called without an object of data key-values to update.' );
 			}
 
-			${Array.from( generator.readonly ).map( prop =>
-				`if ( '${prop}' in newState && !this._updatingReadonlyProperty ) throw new Error( "Cannot set read-only property '${prop}'" );`
+			${Array.from(generator.readonly).map(
+				prop =>
+					`if ( '${prop}' in newState && !this._updatingReadonlyProperty ) throw new Error( "Cannot set read-only property '${prop}'" );`
 			)}
 		`}
 
 		var oldState = this._state;
-		this._state = ${generator.helper( 'assign' )}( {}, oldState, newState );
-		${computations.length && `${generator.alias( 'recompute' )}( this._state, newState, oldState, false )`}
-		${generator.helper( 'dispatchObservers' )}( this, this._observers.pre, newState, oldState );
+		this._state = ${generator.helper('assign')}( {}, oldState, newState );
+		${computations.length &&
+			`${generator.alias(
+				'recompute'
+			)}( this._state, newState, oldState, false )`}
+		${generator.helper(
+			'dispatchObservers'
+		)}( this, this._observers.pre, newState, oldState );
 		${block.hasUpdateMethod && `this._fragment.update( newState, this._state );`}
-		${generator.helper( 'dispatchObservers' )}( this, this._observers.post, newState, oldState );
-		${generator.hasComplexBindings && `while ( this._bindings.length ) this._bindings.pop()();`}
-		${( generator.hasComponents || generator.hasIntroTransitions ) && `this._flush();`}
-	` );
-
-	if ( hasJs ) {
-		builders.main.addBlock( `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` );
+		${generator.helper(
+			'dispatchObservers'
+		)}( this, this._observers.post, newState, oldState );
+		${generator.hasComplexBindings &&
+			`while ( this._bindings.length ) this._bindings.pop()();`}
+		${(generator.hasComponents || generator.hasIntroTransitions) &&
+			`this._flush();`}
+	`);
+
+	if (hasJs) {
+		builders.main.addBlock(
+			`[✂${parsed.js.content.start}-${parsed.js.content.end}✂]`
+		);
 	}
 
-	if ( generator.css && options.css !== false ) {
-		builders.main.addBlock( deindent`
-			function ${generator.alias( 'add_css' )} () {
-				var style = ${generator.helper( 'createElement' )}( 'style' );
-				style.id = ${JSON.stringify( generator.cssId + '-style' )};
-				style.textContent = ${JSON.stringify( generator.css )};
-				${generator.helper( 'appendNode' )}( style, document.head );
+	if (generator.css && options.css !== false) {
+		builders.main.addBlock(deindent`
+			function ${generator.alias('add_css')} () {
+				var style = ${generator.helper('createElement')}( 'style' );
+				style.id = ${JSON.stringify(generator.cssId + '-style')};
+				style.textContent = ${JSON.stringify(generator.css)};
+				${generator.helper('appendNode')}( style, document.head );
 			}
-		` );
+		`);
 	}
 
-	generator.blocks.forEach( block => {
-		builders.main.addBlock( block.render() );
+	generator.blocks.forEach(block => {
+		builders.main.addBlock(block.render());
 	});
 
-	const sharedPath = options.shared === true ? 'svelte/shared.js' : options.shared;
-
-	const prototypeBase = `${name}.prototype` + ( templateProperties.methods ? `, ${generator.alias( 'template' )}.methods` : '' );
-	const proto = sharedPath ? `${generator.helper( 'proto' )} ` : deindent`
+	const sharedPath = options.shared === true
+		? 'svelte/shared.js'
+		: options.shared;
+
+	const prototypeBase =
+		`${name}.prototype` +
+		(templateProperties.methods
+			? `, ${generator.alias('template')}.methods`
+			: '');
+	const proto = sharedPath
+		? `${generator.helper('proto')} `
+		: deindent`
 		{
-			${
-				[ 'get', 'fire', 'observe', 'on', 'set', '_flush' ]
-					.map( n => `${n}: ${generator.helper( n )}` )
-					.join( ',\n' )
-			}
+			${['get', 'fire', 'observe', 'on', 'set', '_flush']
+				.map(n => `${n}: ${generator.helper(n)}`)
+				.join(',\n')}
 		}`;
 
 	// TODO deprecate component.teardown()
-	builders.main.addBlock( deindent`
+	builders.main.addBlock(deindent`
 		function ${name} ( options ) {
 			options = options || {};
-			${options.dev && `if ( !options.target && !options._root ) throw new Error( "'target' is a required option" );`}
+			${options.dev &&
+				`if ( !options.target && !options._root ) throw new Error( "'target' is a required option" );`}
 			${generator.usesRefs && `this.refs = {};`}
-			this._state = ${templateProperties.data ? `${generator.helper( 'assign' )}( ${generator.alias( 'template' )}.data(), options.data )` : `options.data || {}`};
+			this._state = ${templateProperties.data
+				? `${generator.helper('assign')}( ${generator.alias(
+						'template'
+					)}.data(), options.data )`
+				: `options.data || {}`};
 			${generator.metaBindings}
-			${computations.length && `${generator.alias( 'recompute' )}( this._state, this._state, {}, true );`}
-			${options.dev && Array.from( generator.expectedProperties ).map( prop => `if ( !( '${prop}' in this._state ) ) console.warn( "Component was created without expected data property '${prop}'" );`)}
-			${generator.bindingGroups.length && `this._bindingGroups = [ ${Array( generator.bindingGroups.length ).fill( '[]' ).join( ', ' )} ];`}
+			${computations.length &&
+				`${generator.alias(
+					'recompute'
+				)}( this._state, this._state, {}, true );`}
+			${options.dev &&
+				Array.from(generator.expectedProperties).map(
+					prop =>
+						`if ( !( '${prop}' in this._state ) ) console.warn( "Component was created without expected data property '${prop}'" );`
+				)}
+			${generator.bindingGroups.length &&
+				`this._bindingGroups = [ ${Array(generator.bindingGroups.length)
+					.fill('[]')
+					.join(', ')} ];`}
 
 			this._observers = {
 				pre: Object.create( null ),
@@ -163,25 +222,37 @@ export default function dom ( parsed: Parsed, source: string, options: CompileOp
 			this._yield = options._yield;
 
 			this._torndown = false;
-			${parsed.css && options.css !== false && `if ( !document.getElementById( ${JSON.stringify( generator.cssId + '-style' )} ) ) ${generator.alias( 'add_css' )}();`}
-			${( generator.hasComponents || generator.hasIntroTransitions ) && `this._renderHooks = [];`}
+			${parsed.css &&
+				options.css !== false &&
+				`if ( !document.getElementById( ${JSON.stringify(
+					generator.cssId + '-style'
+				)} ) ) ${generator.alias('add_css')}();`}
+			${(generator.hasComponents || generator.hasIntroTransitions) &&
+				`this._renderHooks = [];`}
 			${generator.hasComplexBindings && `this._bindings = [];`}
 
-			this._fragment = ${generator.alias( 'create_main_fragment' )}( this._state, this );
+			this._fragment = ${generator.alias(
+				'create_main_fragment'
+			)}( this._state, this );
 			if ( options.target ) this._fragment.mount( options.target, null );
-			${generator.hasComplexBindings && `while ( this._bindings.length ) this._bindings.pop()();`}
-			${( generator.hasComponents || generator.hasIntroTransitions ) && `this._flush();`}
+			${generator.hasComplexBindings &&
+				`while ( this._bindings.length ) this._bindings.pop()();`}
+			${(generator.hasComponents || generator.hasIntroTransitions) &&
+				`this._flush();`}
 
-			${templateProperties.oncreate && deindent`
+			${templateProperties.oncreate &&
+				deindent`
 				if ( options._root ) {
-					options._root._renderHooks.push( ${generator.alias( 'template' )}.oncreate.bind( this ) );
+					options._root._renderHooks.push( ${generator.alias(
+						'template'
+					)}.oncreate.bind( this ) );
 				} else {
-					${generator.alias( 'template' )}.oncreate.call( this );
+					${generator.alias('template')}.oncreate.call( this );
 				}
 			`}
 		}
 
-		${generator.helper( 'assign' )}( ${prototypeBase}, ${proto});
+		${generator.helper('assign')}( ${prototypeBase}, ${proto});
 
 		${name}.prototype._set = function _set ( newState ) {
 			${builders._set}
@@ -189,7 +260,8 @@ export default function dom ( parsed: Parsed, source: string, options: CompileOp
 
 		${name}.prototype.teardown = ${name}.prototype.destroy = function destroy ( detach ) {
 			this.fire( 'destroy' );
-			${templateProperties.ondestroy && `${generator.alias( 'template' )}.ondestroy.call( this );`}
+			${templateProperties.ondestroy &&
+				`${generator.alias('template')}.ondestroy.call( this );`}
 
 			if ( detach !== false ) this._fragment.unmount();
 			this._fragment.destroy();
@@ -198,63 +270,79 @@ export default function dom ( parsed: Parsed, source: string, options: CompileOp
 			this._state = {};
 			this._torndown = true;
 		};
-	` );
+	`);
 
-	if ( sharedPath ) {
-		if ( format !== 'es' ) {
-			throw new Error( `Components with shared helpers must be compiled to ES2015 modules (format: 'es')` );
+	if (sharedPath) {
+		if (format !== 'es') {
+			throw new Error(
+				`Components with shared helpers must be compiled to ES2015 modules (format: 'es')`
+			);
 		}
 
-		const names = Array.from( generator.uses ).sort().map( name => {
-			return name !== generator.alias( name ) ? `${name} as ${generator.alias( name )}` : name;
+		const names = Array.from(generator.uses).sort().map(name => {
+			return name !== generator.alias(name)
+				? `${name} as ${generator.alias(name)}`
+				: name;
 		});
 
 		builders.main.addLineAtStart(
-			`import { ${names.join( ', ' )} } from ${JSON.stringify( sharedPath )};`
+			`import { ${names.join(', ')} } from ${JSON.stringify(sharedPath)};`
 		);
 	} else {
-		generator.uses.forEach( key => {
-			const str = shared[ key ];
-			const code = new MagicString( str );
-			const expression = parseExpressionAt( str, 0 );
-
-			let scope = annotateWithScopes( expression );
-
-			walk( expression, {
-				enter ( node, parent ) {
-					if ( node._scope ) scope = node._scope;
-
-					if ( node.type === 'Identifier' && isReference( node, parent ) && !scope.has( node.name ) ) {
-						if ( node.name in shared ) {
+		generator.uses.forEach(key => {
+			const str = shared[key];
+			const code = new MagicString(str);
+			const expression = parseExpressionAt(str, 0);
+
+			let scope = annotateWithScopes(expression);
+
+			walk(expression, {
+				enter(node, parent) {
+					if (node._scope) scope = node._scope;
+
+					if (
+						node.type === 'Identifier' &&
+						isReference(node, parent) &&
+						!scope.has(node.name)
+					) {
+						if (node.name in shared) {
 							// this helper function depends on another one
 							const dependency = node.name;
-							generator.uses.add( dependency );
+							generator.uses.add(dependency);
 
-							const alias = generator.alias( dependency );
-							if ( alias !== node.name ) code.overwrite( node.start, node.end, alias );
+							const alias = generator.alias(dependency);
+							if (alias !== node.name)
+								code.overwrite(node.start, node.end, alias);
 						}
 					}
 				},
 
-				leave ( node ) {
-					if ( node._scope ) scope = scope.parent;
+				leave(node) {
+					if (node._scope) scope = scope.parent;
 				}
 			});
 
-			if ( key === 'transitionManager' ) { // special case
+			if (key === 'transitionManager') {
+				// special case
 				const global = `_svelteTransitionManager`;
 
 				builders.main.addBlock(
-					`var ${generator.alias( 'transitionManager' )} = window.${global} || ( window.${global} = ${code});`
+					`var ${generator.alias(
+						'transitionManager'
+					)} = window.${global} || ( window.${global} = ${code});`
 				);
 			} else {
-				const alias = generator.alias( expression.id.name );
-				if ( alias !== expression.id.name ) code.overwrite( expression.id.start, expression.id.end, alias );
+				const alias = generator.alias(expression.id.name);
+				if (alias !== expression.id.name)
+					code.overwrite(expression.id.start, expression.id.end, alias);
 
-				builders.main.addBlock( code.toString() );
+				builders.main.addBlock(code.toString());
 			}
 		});
 	}
 
-	return generator.generate( builders.main.toString(), options, { name, format } );
+	return generator.generate(builders.main.toString(), options, {
+		name,
+		format
+	});
 }
diff --git a/src/generators/dom/interfaces.ts b/src/generators/dom/interfaces.ts
index a58069da90..8c460a4733 100644
--- a/src/generators/dom/interfaces.ts
+++ b/src/generators/dom/interfaces.ts
@@ -2,7 +2,7 @@ export interface State {
 	name: string;
 	namespace: string;
 	parentNode: string;
-	isTopLevel: boolean
+	isTopLevel: boolean;
 	parentNodeName?: string;
 	basename?: string;
 	inEachBlock?: boolean;
diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts
index 3a96aca3f2..595b753d57 100644
--- a/src/generators/dom/preprocess.ts
+++ b/src/generators/dom/preprocess.ts
@@ -5,12 +5,14 @@ import { DomGenerator } from './index';
 import { Node } from '../../interfaces';
 import { State } from './interfaces';
 
-function isElseIf ( node: Node ) {
-	return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
+function isElseIf(node: Node) {
+	return (
+		node && node.children.length === 1 && node.children[0].type === 'IfBlock'
+	);
 }
 
-function getChildState ( parent: State, child = {} ) {
-	return assign( {}, parent, { name: null, parentNode: null }, child || {} );
+function getChildState(parent: State, child = {}) {
+	return assign({}, parent, { name: null, parentNode: null }, child || {});
 }
 
 // Whitespace inside one of these elements will not result in
@@ -28,118 +30,144 @@ const elementsWithoutText = new Set([
 ]);
 
 const preprocessors = {
-	MustacheTag: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
-		const dependencies = block.findDependencies( node.expression );
-		block.addDependencies( dependencies );
-
-		node._state = getChildState( state, {
-			name: block.getUniqueName( 'text' )
+	MustacheTag: (
+		generator: DomGenerator,
+		block: Block,
+		state: State,
+		node: Node
+	) => {
+		const dependencies = block.findDependencies(node.expression);
+		block.addDependencies(dependencies);
+
+		node._state = getChildState(state, {
+			name: block.getUniqueName('text')
 		});
 	},
 
-	RawMustacheTag: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
-		const dependencies = block.findDependencies( node.expression );
-		block.addDependencies( dependencies );
+	RawMustacheTag: (
+		generator: DomGenerator,
+		block: Block,
+		state: State,
+		node: Node
+	) => {
+		const dependencies = block.findDependencies(node.expression);
+		block.addDependencies(dependencies);
 
-		const basename = block.getUniqueName( 'raw' );
-		const name = block.getUniqueName( `${basename}_before` );
+		const basename = block.getUniqueName('raw');
+		const name = block.getUniqueName(`${basename}_before`);
 
-		node._state = getChildState( state, { basename, name });
+		node._state = getChildState(state, { basename, name });
 	},
 
-	Text: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
-		node._state = getChildState( state );
+	Text: (generator: DomGenerator, block: Block, state: State, node: Node) => {
+		node._state = getChildState(state);
 
-		if ( !/\S/.test( node.data ) ) {
-			if ( state.namespace ) return;
-			if ( elementsWithoutText.has( state.parentNodeName ) ) return;
+		if (!/\S/.test(node.data)) {
+			if (state.namespace) return;
+			if (elementsWithoutText.has(state.parentNodeName)) return;
 		}
 
 		node._state.shouldCreate = true;
-		node._state.name = block.getUniqueName( `text` );
+		node._state.name = block.getUniqueName(`text`);
 	},
 
-	IfBlock: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
+	IfBlock: (
+		generator: DomGenerator,
+		block: Block,
+		state: State,
+		node: Node
+	) => {
 		const blocks: Block[] = [];
 		let dynamic = false;
 		let hasIntros = false;
 		let hasOutros = false;
 
-		function attachBlocks ( node: Node ) {
-			const dependencies = block.findDependencies( node.expression );
-			block.addDependencies( dependencies );
+		function attachBlocks(node: Node) {
+			const dependencies = block.findDependencies(node.expression);
+			block.addDependencies(dependencies);
 
 			node._block = block.child({
-				name: generator.getUniqueName( `create_if_block` )
+				name: generator.getUniqueName(`create_if_block`)
 			});
 
-			node._state = getChildState( state );
+			node._state = getChildState(state);
 
-			blocks.push( node._block );
-			preprocessChildren( generator, node._block, node._state, node );
+			blocks.push(node._block);
+			preprocessChildren(generator, node._block, node._state, node);
 
-			if ( node._block.dependencies.size > 0 ) {
+			if (node._block.dependencies.size > 0) {
 				dynamic = true;
-				block.addDependencies( node._block.dependencies );
+				block.addDependencies(node._block.dependencies);
 			}
 
-			if ( node._block.hasIntroMethod ) hasIntros = true;
-			if ( node._block.hasOutroMethod ) hasOutros = true;
+			if (node._block.hasIntroMethod) hasIntros = true;
+			if (node._block.hasOutroMethod) hasOutros = true;
 
-			if ( isElseIf( node.else ) ) {
-				attachBlocks( node.else.children[0] );
-			} else if ( node.else ) {
+			if (isElseIf(node.else)) {
+				attachBlocks(node.else.children[0]);
+			} else if (node.else) {
 				node.else._block = block.child({
-					name: generator.getUniqueName( `create_if_block` )
+					name: generator.getUniqueName(`create_if_block`)
 				});
 
-				node.else._state = getChildState( state );
+				node.else._state = getChildState(state);
 
-				blocks.push( node.else._block );
-				preprocessChildren( generator, node.else._block, node.else._state, node.else );
+				blocks.push(node.else._block);
+				preprocessChildren(
+					generator,
+					node.else._block,
+					node.else._state,
+					node.else
+				);
 
-				if ( node.else._block.dependencies.size > 0 ) {
+				if (node.else._block.dependencies.size > 0) {
 					dynamic = true;
-					block.addDependencies( node.else._block.dependencies );
+					block.addDependencies(node.else._block.dependencies);
 				}
 			}
 		}
 
-		attachBlocks( node );
+		attachBlocks(node);
 
-		blocks.forEach( block => {
+		blocks.forEach(block => {
 			block.hasUpdateMethod = dynamic;
 			block.hasIntroMethod = hasIntros;
 			block.hasOutroMethod = hasOutros;
 		});
 
-		generator.blocks.push( ...blocks );
+		generator.blocks.push(...blocks);
 	},
 
-	EachBlock: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
-		const dependencies = block.findDependencies( node.expression );
-		block.addDependencies( dependencies );
+	EachBlock: (
+		generator: DomGenerator,
+		block: Block,
+		state: State,
+		node: Node
+	) => {
+		const dependencies = block.findDependencies(node.expression);
+		block.addDependencies(dependencies);
 
-		const indexNames = new Map( block.indexNames );
-		const indexName = node.index || block.getUniqueName( `${node.context}_index` );
-		indexNames.set( node.context, indexName );
+		const indexNames = new Map(block.indexNames);
+		const indexName =
+			node.index || block.getUniqueName(`${node.context}_index`);
+		indexNames.set(node.context, indexName);
 
-		const listNames = new Map( block.listNames );
-		const listName = block.getUniqueName( `each_block_value` );
-		listNames.set( node.context, listName );
+		const listNames = new Map(block.listNames);
+		const listName = block.getUniqueName(`each_block_value`);
+		listNames.set(node.context, listName);
 
-		const context = generator.getUniqueName( node.context );
-		const contexts = new Map( block.contexts );
-		contexts.set( node.context, context );
+		const context = generator.getUniqueName(node.context);
+		const contexts = new Map(block.contexts);
+		contexts.set(node.context, context);
 
-		const indexes = new Map( block.indexes );
-		if ( node.index ) indexes.set( indexName, node.context );
+		const indexes = new Map(block.indexes);
+		if (node.index) indexes.set(indexName, node.context);
 
-		const contextDependencies = new Map( block.contextDependencies );
-		contextDependencies.set( node.context, dependencies );
+		const contextDependencies = new Map(block.contextDependencies);
+		contextDependencies.set(node.context, dependencies);
 
 		node._block = block.child({
-			name: generator.getUniqueName( 'create_each_block' ),
+			name: generator.getUniqueName('create_each_block'),
 			expression: node.expression,
 			context: node.context,
 			key: node.key,
@@ -153,134 +181,152 @@ const preprocessors = {
 
 			indexNames,
 			listNames,
-			params: block.params.concat( listName, context, indexName )
+			params: block.params.concat(listName, context, indexName)
 		});
 
-		node._state = getChildState( state, {
+		node._state = getChildState(state, {
 			inEachBlock: true
 		});
 
-		generator.blocks.push( node._block );
-		preprocessChildren( generator, node._block, node._state, node );
-		block.addDependencies( node._block.dependencies );
+		generator.blocks.push(node._block);
+		preprocessChildren(generator, node._block, node._state, node);
+		block.addDependencies(node._block.dependencies);
 		node._block.hasUpdateMethod = node._block.dependencies.size > 0;
 
-		if ( node.else ) {
+		if (node.else) {
 			node.else._block = block.child({
-				name: generator.getUniqueName( `${node._block.name}_else` )
+				name: generator.getUniqueName(`${node._block.name}_else`)
 			});
 
-			node.else._state = getChildState( state );
+			node.else._state = getChildState(state);
 
-			generator.blocks.push( node.else._block );
-			preprocessChildren( generator, node.else._block, node.else._state, node.else );
+			generator.blocks.push(node.else._block);
+			preprocessChildren(
+				generator,
+				node.else._block,
+				node.else._state,
+				node.else
+			);
 			node.else._block.hasUpdateMethod = node.else._block.dependencies.size > 0;
 		}
 	},
 
-	Element: ( generator: DomGenerator, block: Block, state: State, node: Node ) => {
-		const isComponent = generator.components.has( node.name ) || node.name === ':Self';
-
-		if ( isComponent ) {
-			node._state = getChildState( state );
+	Element: (
+		generator: DomGenerator,
+		block: Block,
+		state: State,
+		node: Node
+	) => {
+		const isComponent =
+			generator.components.has(node.name) || node.name === ':Self';
+
+		if (isComponent) {
+			node._state = getChildState(state);
 		} else {
-			const name = block.getUniqueName( node.name.replace( /[^a-zA-Z0-9_$]/g, '_' ) );
+			const name = block.getUniqueName(
+				node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
+			);
 
-			node._state = getChildState( state, {
+			node._state = getChildState(state, {
 				isTopLevel: false,
 				name,
 				parentNode: name,
 				parentNodeName: node.name,
-				namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : state.namespace,
+				namespace: node.name === 'svg'
+					? 'http://www.w3.org/2000/svg'
+					: state.namespace,
 				allUsedContexts: []
 			});
 		}
 
-		node.attributes.forEach( ( attribute: Node ) => {
-			if ( attribute.type === 'Attribute' && attribute.value !== true ) {
-				attribute.value.forEach( ( chunk: Node ) => {
-					if ( chunk.type !== 'Text' ) {
-						const dependencies = block.findDependencies( chunk.expression );
-						block.addDependencies( dependencies );
+		node.attributes.forEach((attribute: Node) => {
+			if (attribute.type === 'Attribute' && attribute.value !== true) {
+				attribute.value.forEach((chunk: Node) => {
+					if (chunk.type !== 'Text') {
+						const dependencies = block.findDependencies(chunk.expression);
+						block.addDependencies(dependencies);
 					}
 				});
-			}
-
-			else if ( attribute.type === 'Binding' ) {
-				const dependencies = block.findDependencies( attribute.value );
-				block.addDependencies( dependencies );
-			}
-
-			else if ( attribute.type === 'Transition' ) {
-				if ( attribute.intro ) generator.hasIntroTransitions = block.hasIntroMethod = true;
-				if ( attribute.outro ) {
+			} else if (attribute.type === 'Binding') {
+				const dependencies = block.findDependencies(attribute.value);
+				block.addDependencies(dependencies);
+			} else if (attribute.type === 'Transition') {
+				if (attribute.intro)
+					generator.hasIntroTransitions = block.hasIntroMethod = true;
+				if (attribute.outro) {
 					generator.hasOutroTransitions = block.hasOutroMethod = true;
 					block.outros += 1;
 				}
 			}
 		});
 
-		if ( node.children.length ) {
-			if ( isComponent ) {
-				const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );
+		if (node.children.length) {
+			if (isComponent) {
+				const name = block.getUniqueName(
+					(node.name === ':Self' ? generator.name : node.name).toLowerCase()
+				);
 
 				node._block = block.child({
-					name: generator.getUniqueName( `create_${name}_yield_fragment` )
+					name: generator.getUniqueName(`create_${name}_yield_fragment`)
 				});
 
-				generator.blocks.push( node._block );
-				preprocessChildren( generator, node._block, node._state, node );
-				block.addDependencies( node._block.dependencies );
+				generator.blocks.push(node._block);
+				preprocessChildren(generator, node._block, node._state, node);
+				block.addDependencies(node._block.dependencies);
 				node._block.hasUpdateMethod = node._block.dependencies.size > 0;
-			}
-
-			else {
-				preprocessChildren( generator, block, node._state, node );
+			} else {
+				preprocessChildren(generator, block, node._state, node);
 			}
 		}
 	}
 };
 
-function preprocessChildren ( generator: DomGenerator, block: Block, state: State, node: Node, isTopLevel: boolean = false ) {
+function preprocessChildren(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	isTopLevel: boolean = false
+) {
 	// glue text nodes together
 	const cleaned: Node[] = [];
 	let lastChild: Node;
 
-	node.children.forEach( ( child: Node ) => {
-		if ( child.type === 'Comment' ) return;
+	node.children.forEach((child: Node) => {
+		if (child.type === 'Comment') return;
 
-		if ( child.type === 'Text' && lastChild && lastChild.type === 'Text' ) {
+		if (child.type === 'Text' && lastChild && lastChild.type === 'Text') {
 			lastChild.data += child.data;
 			lastChild.end = child.end;
 		} else {
-			cleaned.push( child );
+			cleaned.push(child);
 		}
 
 		lastChild = child;
 	});
 
-	if ( isTopLevel ) {
+	if (isTopLevel) {
 		// trim leading and trailing whitespace from the top level
 		const firstChild = cleaned[0];
-		if ( firstChild && firstChild.type === 'Text' ) {
-			firstChild.data = trimStart( firstChild.data );
-			if ( !firstChild.data ) cleaned.shift();
+		if (firstChild && firstChild.type === 'Text') {
+			firstChild.data = trimStart(firstChild.data);
+			if (!firstChild.data) cleaned.shift();
 		}
 
-		const lastChild = cleaned[ cleaned.length - 1 ];
-		if ( lastChild && lastChild.type === 'Text' ) {
-			lastChild.data = trimEnd( lastChild.data );
-			if ( !lastChild.data ) cleaned.pop();
+		const lastChild = cleaned[cleaned.length - 1];
+		if (lastChild && lastChild.type === 'Text') {
+			lastChild.data = trimEnd(lastChild.data);
+			if (!lastChild.data) cleaned.pop();
 		}
 	}
 
 	lastChild = null;
 
-	cleaned.forEach( ( child: Node ) => {
-		const preprocess = preprocessors[ child.type ];
-		if ( preprocess ) preprocess( generator, block, state, child );
+	cleaned.forEach((child: Node) => {
+		const preprocess = preprocessors[child.type];
+		if (preprocess) preprocess(generator, block, state, child);
 
-		if ( lastChild ) {
+		if (lastChild) {
 			lastChild.next = child;
 			lastChild.needsAnchor = !child._state || !child._state.name;
 		}
@@ -288,24 +334,28 @@ function preprocessChildren ( generator: DomGenerator, block: Block, state: Stat
 		lastChild = child;
 	});
 
-	if ( lastChild ) {
+	if (lastChild) {
 		lastChild.needsAnchor = !state.parentNode;
 	}
 
 	node.children = cleaned;
 }
 
-export default function preprocess ( generator: DomGenerator, namespace: string, node: Node ) {
+export default function preprocess(
+	generator: DomGenerator,
+	namespace: string,
+	node: Node
+) {
 	const block = new Block({
 		generator,
-		name: generator.alias( 'create_main_fragment' ),
+		name: generator.alias('create_main_fragment'),
 		key: null,
 
 		contexts: new Map(),
 		indexes: new Map(),
 		contextDependencies: new Map(),
 
-		params: [ 'state' ],
+		params: ['state'],
 		indexNames: new Map(),
 		listNames: new Map(),
 
@@ -318,9 +368,9 @@ export default function preprocess ( generator: DomGenerator, namespace: string,
 		isTopLevel: true
 	};
 
-	generator.blocks.push( block );
-	preprocessChildren( generator, block, state, node, true );
+	generator.blocks.push(block);
+	preprocessChildren(generator, block, state, node, true);
 	block.hasUpdateMethod = block.dependencies.size > 0;
 
 	return { block, state };
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visit.ts b/src/generators/dom/visit.ts
index 1443a32049..91601fa8fd 100644
--- a/src/generators/dom/visit.ts
+++ b/src/generators/dom/visit.ts
@@ -3,7 +3,12 @@ import { DomGenerator } from './index';
 import Block from './Block';
 import { Node } from '../../interfaces';
 
-export default function visit ( generator: DomGenerator, block: Block, state, node: Node ) {
-	const visitor = visitors[ node.type ];
-	visitor( generator, block, state, node );
-}
\ No newline at end of file
+export default function visit(
+	generator: DomGenerator,
+	block: Block,
+	state,
+	node: Node
+) {
+	const visitor = visitors[node.type];
+	visitor(generator, block, state, node);
+}
diff --git a/src/generators/dom/visitors/Component/Attribute.ts b/src/generators/dom/visitors/Component/Attribute.ts
index 690cb88639..1bd477a396 100644
--- a/src/generators/dom/visitors/Component/Attribute.ts
+++ b/src/generators/dom/visitors/Component/Attribute.ts
@@ -3,37 +3,40 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitAttribute ( generator: DomGenerator, block: Block, state: State, node: Node, attribute, local ) {
-	if ( attribute.value === true ) {
+export default function visitAttribute(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute,
+	local
+) {
+	if (attribute.value === true) {
 		// attributes without values, e.g. <textarea readonly>
 		local.staticAttributes.push({
 			name: attribute.name,
 			value: true
 		});
-	}
-
-	else if ( attribute.value.length === 0 ) {
+	} else if (attribute.value.length === 0) {
 		local.staticAttributes.push({
 			name: attribute.name,
 			value: `''`
 		});
-	}
-
-	else if ( attribute.value.length === 1 ) {
+	} else if (attribute.value.length === 1) {
 		const value = attribute.value[0];
 
-		if ( value.type === 'Text' ) {
+		if (value.type === 'Text') {
 			// static attributes
-			const result = isNaN( value.data ) ? JSON.stringify( value.data ) : value.data;
+			const result = isNaN(value.data)
+				? JSON.stringify(value.data)
+				: value.data;
 			local.staticAttributes.push({
 				name: attribute.name,
 				value: result
 			});
-		}
-
-		else {
+		} else {
 			// simple dynamic attributes
-			const { dependencies, snippet } = block.contextualise( value.expression );
+			const { dependencies, snippet } = block.contextualise(value.expression);
 
 			// TODO only update attributes that have changed
 			local.dynamicAttributes.push({
@@ -42,26 +45,29 @@ export default function visitAttribute ( generator: DomGenerator, block: Block,
 				dependencies
 			});
 		}
-	}
-
-	else {
+	} else {
 		// complex dynamic attributes
 		const allDependencies = [];
 
-		const value = ( attribute.value[0].type === 'Text' ? '' : `"" + ` ) + (
-			attribute.value.map( chunk => {
-				if ( chunk.type === 'Text' ) {
-					return JSON.stringify( chunk.data );
-				} else {
-					const { dependencies, snippet } = block.contextualise( chunk.expression );
-					dependencies.forEach( dependency => {
-						if ( !~allDependencies.indexOf( dependency ) ) allDependencies.push( dependency );
-					});
+		const value =
+			(attribute.value[0].type === 'Text' ? '' : `"" + `) +
+			attribute.value
+				.map(chunk => {
+					if (chunk.type === 'Text') {
+						return JSON.stringify(chunk.data);
+					} else {
+						const { dependencies, snippet } = block.contextualise(
+							chunk.expression
+						);
+						dependencies.forEach(dependency => {
+							if (!~allDependencies.indexOf(dependency))
+								allDependencies.push(dependency);
+						});
 
-					return `( ${snippet} )`;
-				}
-			}).join( ' + ' )
-		);
+						return `( ${snippet} )`;
+					}
+				})
+				.join(' + ');
 
 		local.dynamicAttributes.push({
 			name: attribute.name,
@@ -69,4 +75,4 @@ export default function visitAttribute ( generator: DomGenerator, block: Block,
 			dependencies: allDependencies
 		});
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Component/Binding.ts b/src/generators/dom/visitors/Component/Binding.ts
index 9c30f24dc7..d84c2bcfb9 100644
--- a/src/generators/dom/visitors/Component/Binding.ts
+++ b/src/generators/dom/visitors/Component/Binding.ts
@@ -6,26 +6,40 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitBinding ( generator: DomGenerator, block: Block, state: State, node: Node, attribute, local ) {
-	const { name } = flattenReference( attribute.value );
-	const { snippet, contexts, dependencies } = block.contextualise( attribute.value );
+export default function visitBinding(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute,
+	local
+) {
+	const { name } = flattenReference(attribute.value);
+	const { snippet, contexts, dependencies } = block.contextualise(
+		attribute.value
+	);
 
-	if ( dependencies.length > 1 ) throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' );
+	if (dependencies.length > 1)
+		throw new Error(
+			'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!'
+		);
 
-	contexts.forEach( context => {
-		if ( !~local.allUsedContexts.indexOf( context ) ) local.allUsedContexts.push( context );
+	contexts.forEach(context => {
+		if (!~local.allUsedContexts.indexOf(context))
+			local.allUsedContexts.push(context);
 	});
 
-	const contextual = block.contexts.has( name );
+	const contextual = block.contexts.has(name);
 
 	let obj;
 	let prop;
 
-	if ( contextual ) {
-		obj = block.listNames.get( name );
-		prop = block.indexNames.get( name );
-	} else if ( attribute.value.type === 'MemberExpression' ) {
-		prop = `'[✂${attribute.value.property.start}-${attribute.value.property.end}✂]'`;
+	if (contextual) {
+		obj = block.listNames.get(name);
+		prop = block.indexNames.get(name);
+	} else if (attribute.value.type === 'MemberExpression') {
+		prop = `'[✂${attribute.value.property.start}-${attribute.value.property
+			.end}✂]'`;
 		obj = `[✂${attribute.value.object.start}-${attribute.value.object.end}✂]`;
 	} else {
 		obj = 'state';
@@ -39,14 +53,22 @@ export default function visitBinding ( generator: DomGenerator, block: Block, st
 		prop
 	});
 
-	const setter = getSetter({ block, name, snippet, context: '_context', attribute, dependencies, value: 'value' });
+	const setter = getSetter({
+		block,
+		name,
+		snippet,
+		context: '_context',
+		attribute,
+		dependencies,
+		value: 'value'
+	});
 
 	generator.hasComplexBindings = true;
 
-	const updating = block.getUniqueName( `${local.name}_updating` );
-	block.addVariable( updating, 'false' );
+	const updating = block.getUniqueName(`${local.name}_updating`);
+	block.addVariable(updating, 'false');
 
-	local.create.addBlock( deindent`
+	local.create.addBlock(deindent`
 		${block.component}._bindings.push( function () {
 			if ( ${local.name}._torndown ) return;
 			${local.name}.observe( '${attribute.name}', function ( value ) {
@@ -54,15 +76,19 @@ export default function visitBinding ( generator: DomGenerator, block: Block, st
 				${updating} = true;
 				${setter}
 				${updating} = false;
-			}, { init: ${generator.helper( 'differs' )}( ${local.name}.get( '${attribute.name}' ), ${snippet} ) });
+			}, { init: ${generator.helper(
+				'differs'
+			)}( ${local.name}.get( '${attribute.name}' ), ${snippet} ) });
 		});
-	` );
+	`);
 
-	local.update.addBlock( deindent`
-		if ( !${updating} && ${dependencies.map( dependency => `'${dependency}' in changed` ).join( '||' )} ) {
+	local.update.addBlock(deindent`
+		if ( !${updating} && ${dependencies
+		.map(dependency => `'${dependency}' in changed`)
+		.join('||')} ) {
 			${updating} = true;
 			${local.name}._set({ ${attribute.name}: ${snippet} });
 			${updating} = false;
 		}
-	` );
-}
\ No newline at end of file
+	`);
+}
diff --git a/src/generators/dom/visitors/Component/Component.ts b/src/generators/dom/visitors/Component/Component.ts
index 106a08a92c..e25088cc2e 100644
--- a/src/generators/dom/visitors/Component/Component.ts
+++ b/src/generators/dom/visitors/Component/Component.ts
@@ -10,13 +10,13 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-function stringifyProps ( props: string[] ) {
-	if ( !props.length ) return '{}';
+function stringifyProps(props: string[]) {
+	if (!props.length) return '{}';
 
-	const joined = props.join( ', ' );
-	if ( joined.length > 40 ) {
+	const joined = props.join(', ');
+	if (joined.length > 40) {
 		// make larger data objects readable
-		return `{\n\t${props.join( ',\n\t' )}\n}`;
+		return `{\n\t${props.join(',\n\t')}\n}`;
 	}
 
 	return `{ ${joined} }`;
@@ -36,9 +36,16 @@ const visitors = {
 	Ref: visitRef
 };
 
-export default function visitComponent ( generator: DomGenerator, block: Block, state: State, node: Node ) {
+export default function visitComponent(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
 	const hasChildren = node.children.length > 0;
-	const name = block.getUniqueName( ( node.name === ':Self' ? generator.name : node.name ).toLowerCase() );
+	const name = block.getUniqueName(
+		(node.name === ':Self' ? generator.name : node.name).toLowerCase()
+	);
 
 	const childState = node._state;
 
@@ -61,115 +68,139 @@ export default function visitComponent ( generator: DomGenerator, block: Block,
 	generator.hasComponents = true;
 
 	node.attributes
-		.sort( ( a, b ) => order[ a.type ] - order[ b.type ] )
-		.forEach( attribute => {
-			visitors[ attribute.type ]( generator, block, childState, node, attribute, local );
+		.sort((a, b) => order[a.type] - order[b.type])
+		.forEach(attribute => {
+			visitors[attribute.type](
+				generator,
+				block,
+				childState,
+				node,
+				attribute,
+				local
+			);
 		});
 
-	if ( local.allUsedContexts.length ) {
-		const initialProps = local.allUsedContexts.map( contextName => {
-			if ( contextName === 'state' ) return `state: state`;
+	if (local.allUsedContexts.length) {
+		const initialProps = local.allUsedContexts
+			.map(contextName => {
+				if (contextName === 'state') return `state: state`;
 
-			const listName = block.listNames.get( contextName );
-			const indexName = block.indexNames.get( contextName );
+				const listName = block.listNames.get(contextName);
+				const indexName = block.indexNames.get(contextName);
 
-			return `${listName}: ${listName},\n${indexName}: ${indexName}`;
-		}).join( ',\n' );
+				return `${listName}: ${listName},\n${indexName}: ${indexName}`;
+			})
+			.join(',\n');
 
-		const updates = local.allUsedContexts.map( contextName => {
-			if ( contextName === 'state' ) return `${name}._context.state = state;`;
+		const updates = local.allUsedContexts
+			.map(contextName => {
+				if (contextName === 'state') return `${name}._context.state = state;`;
 
-			const listName = block.listNames.get( contextName );
-			const indexName = block.indexNames.get( contextName );
+				const listName = block.listNames.get(contextName);
+				const indexName = block.indexNames.get(contextName);
 
-			return `${name}._context.${listName} = ${listName};\n${name}._context.${indexName} = ${indexName};`;
-		}).join( '\n' );
+				return `${name}._context.${listName} = ${listName};\n${name}._context.${indexName} = ${indexName};`;
+			})
+			.join('\n');
 
-		local.create.addBlock( deindent`
+		local.create.addBlock(deindent`
 			${name}._context = {
 				${initialProps}
 			};
-		` );
+		`);
 
-		local.update.addBlock( updates );
+		local.update.addBlock(updates);
 	}
 
 	const componentInitProperties = [
-		`target: ${!isTopLevel ? state.parentNode: 'null'}`,
+		`target: ${!isTopLevel ? state.parentNode : 'null'}`,
 		`_root: ${block.component}._root`
 	];
 
 	// Component has children, put them in a separate {{yield}} block
-	if ( hasChildren ) {
-		const params = block.params.join( ', ' );
+	if (hasChildren) {
+		const params = block.params.join(', ');
 
 		const childBlock = node._block;
 
-		node.children.forEach( child => {
-			visit( generator, childBlock, childState, child );
+		node.children.forEach(child => {
+			visit(generator, childBlock, childState, child);
 		});
 
-		const yieldFragment = block.getUniqueName( `${name}_yield_fragment` );
+		const yieldFragment = block.getUniqueName(`${name}_yield_fragment`);
 
 		block.builders.create.addLine(
 			`var ${yieldFragment} = ${childBlock.name}( ${params}, ${block.component} );`
 		);
 
-		if ( childBlock.hasUpdateMethod ) {
+		if (childBlock.hasUpdateMethod) {
 			block.builders.update.addLine(
 				`${yieldFragment}.update( changed, ${params} );`
 			);
 		}
 
-		block.builders.destroy.addLine(
-			`${yieldFragment}.destroy();`
-		);
+		block.builders.destroy.addLine(`${yieldFragment}.destroy();`);
 
-		componentInitProperties.push( `_yield: ${yieldFragment}`);
+		componentInitProperties.push(`_yield: ${yieldFragment}`);
 	}
 
 	const statements: string[] = [];
 
-	if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) {
+	if (
+		local.staticAttributes.length ||
+		local.dynamicAttributes.length ||
+		local.bindings.length
+	) {
 		const initialProps = local.staticAttributes
-			.concat( local.dynamicAttributes )
-			.map( attribute => `${attribute.name}: ${attribute.value}` );
+			.concat(local.dynamicAttributes)
+			.map(attribute => `${attribute.name}: ${attribute.value}`);
 
-		const initialPropString = stringifyProps( initialProps );
+		const initialPropString = stringifyProps(initialProps);
 
-		if ( local.bindings.length ) {
-			const initialData = block.getUniqueName( `${name}_initial_data` );
+		if (local.bindings.length) {
+			const initialData = block.getUniqueName(`${name}_initial_data`);
 
-			statements.push( `var ${initialData} = ${initialPropString};` );
+			statements.push(`var ${initialData} = ${initialPropString};`);
 
-			local.bindings.forEach( binding => {
-				statements.push( `if ( ${binding.prop} in ${binding.obj} ) ${initialData}.${binding.name} = ${binding.value};` );
+			local.bindings.forEach(binding => {
+				statements.push(
+					`if ( ${binding.prop} in ${binding.obj} ) ${initialData}.${binding.name} = ${binding.value};`
+				);
 			});
 
-			componentInitProperties.push( `data: ${initialData}` );
-		} else if ( initialProps.length ) {
-			componentInitProperties.push( `data: ${initialPropString}` );
+			componentInitProperties.push(`data: ${initialData}`);
+		} else if (initialProps.length) {
+			componentInitProperties.push(`data: ${initialPropString}`);
 		}
 	}
 
-	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}`;
 
-	local.create.addBlockAtStart( deindent`
-		${statements.join( '\n' )}
+	local.create.addBlockAtStart(deindent`
+		${statements.join('\n')}
 		var ${name} = new ${expression}({
 			${componentInitProperties.join(',\n')}
 		});
-	` );
+	`);
 
-	if ( isTopLevel ) {
-		block.builders.mount.addLine( `${name}._fragment.mount( ${block.target}, anchor );` );
+	if (isTopLevel) {
+		block.builders.mount.addLine(
+			`${name}._fragment.mount( ${block.target}, anchor );`
+		);
 	}
 
-	if ( local.dynamicAttributes.length ) {
-		const updates = local.dynamicAttributes.map( attribute => {
-			if ( attribute.dependencies.length ) {
+	if (local.dynamicAttributes.length) {
+		const updates = local.dynamicAttributes.map(attribute => {
+			if (attribute.dependencies.length) {
 				return deindent`
-					if ( ${attribute.dependencies.map( dependency => `'${dependency}' in changed` ).join( '||' )} ) ${name}_changes.${attribute.name} = ${attribute.value};
+					if ( ${attribute.dependencies
+						.map(dependency => `'${dependency}' in changed`)
+						.join(
+							'||'
+						)} ) ${name}_changes.${attribute.name} = ${attribute.value};
 				`;
 			}
 
@@ -178,18 +209,19 @@ export default function visitComponent ( generator: DomGenerator, block: Block,
 			return `${name}_changes.${attribute.name} = ${attribute.value};`;
 		});
 
-		local.update.addBlock( deindent`
+		local.update.addBlock(deindent`
 			var ${name}_changes = {};
 
-			${updates.join( '\n' )}
+			${updates.join('\n')}
 
 			if ( Object.keys( ${name}_changes ).length ) ${name}.set( ${name}_changes );
-		` );
+		`);
 	}
 
-	if ( isTopLevel ) block.builders.unmount.addLine( `${name}._fragment.unmount();` );
-	block.builders.destroy.addLine( `${name}.destroy( false );` );
+	if (isTopLevel)
+		block.builders.unmount.addLine(`${name}._fragment.unmount();`);
+	block.builders.destroy.addLine(`${name}.destroy( false );`);
 
-	block.builders.create.addBlock( local.create );
-	if ( !local.update.isEmpty() ) block.builders.update.addBlock( local.update );
+	block.builders.create.addBlock(local.create);
+	if (!local.update.isEmpty()) block.builders.update.addBlock(local.update);
 }
diff --git a/src/generators/dom/visitors/Component/EventHandler.ts b/src/generators/dom/visitors/Component/EventHandler.ts
index 41f2b42b5a..ddc37da085 100644
--- a/src/generators/dom/visitors/Component/EventHandler.ts
+++ b/src/generators/dom/visitors/Component/EventHandler.ts
@@ -4,36 +4,49 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitEventHandler ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, local ) {
+export default function visitEventHandler(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node,
+	local
+) {
 	// TODO verify that it's a valid callee (i.e. built-in or declared method)
-	generator.addSourcemapLocations( attribute.expression );
-	generator.code.prependRight( attribute.expression.start, `${block.component}.` );
+	generator.addSourcemapLocations(attribute.expression);
+	generator.code.prependRight(
+		attribute.expression.start,
+		`${block.component}.`
+	);
 
 	const usedContexts: string[] = [];
-	attribute.expression.arguments.forEach( ( arg: Node ) => {
-		const { contexts } = block.contextualise( arg, null, true );
+	attribute.expression.arguments.forEach((arg: Node) => {
+		const { contexts } = block.contextualise(arg, null, true);
 
-		contexts.forEach( context => {
-			if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
-			if ( !~local.allUsedContexts.indexOf( context ) ) local.allUsedContexts.push( context );
+		contexts.forEach(context => {
+			if (!~usedContexts.indexOf(context)) usedContexts.push(context);
+			if (!~local.allUsedContexts.indexOf(context))
+				local.allUsedContexts.push(context);
 		});
 	});
 
 	// TODO hoist event handlers? can do `this.__component.method(...)`
-	const declarations = usedContexts.map( name => {
-		if ( name === 'state' ) return 'var state = this._context.state;';
+	const declarations = usedContexts.map(name => {
+		if (name === 'state') return 'var state = this._context.state;';
 
-		const listName = block.listNames.get( name );
-		const indexName = block.indexNames.get( name );
+		const listName = block.listNames.get(name);
+		const indexName = block.indexNames.get(name);
 
 		return `var ${listName} = this._context.${listName}, ${indexName} = this._context.${indexName}, ${name} = ${listName}[${indexName}]`;
 	});
 
-	const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
+	const handlerBody =
+		(declarations.length ? declarations.join('\n') + '\n\n' : '') +
+		`[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
 
-	local.create.addBlock( deindent`
+	local.create.addBlock(deindent`
 		${local.name}.on( '${attribute.name}', function ( event ) {
 			${handlerBody}
 		});
-	` );
-}
\ No newline at end of file
+	`);
+}
diff --git a/src/generators/dom/visitors/Component/Ref.ts b/src/generators/dom/visitors/Component/Ref.ts
index 480af0d11c..b966e81c71 100644
--- a/src/generators/dom/visitors/Component/Ref.ts
+++ b/src/generators/dom/visitors/Component/Ref.ts
@@ -4,14 +4,21 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, local ) {
+export default function visitRef(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node,
+	local
+) {
 	generator.usesRefs = true;
 
 	local.create.addLine(
 		`${block.component}.refs.${attribute.name} = ${local.name};`
 	);
 
-	block.builders.destroy.addLine( deindent`
+	block.builders.destroy.addLine(deindent`
 		if ( ${block.component}.refs.${attribute.name} === ${local.name} ) ${block.component}.refs.${attribute.name} = null;
-	` );
-}
\ No newline at end of file
+	`);
+}
diff --git a/src/generators/dom/visitors/EachBlock.ts b/src/generators/dom/visitors/EachBlock.ts
index 4f5eeee27e..4e0358b85a 100644
--- a/src/generators/dom/visitors/EachBlock.ts
+++ b/src/generators/dom/visitors/EachBlock.ts
@@ -5,72 +5,98 @@ import Block from '../Block';
 import { Node } from '../../../interfaces';
 import { State } from '../interfaces';
 
-export default function visitEachBlock ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	const each_block = generator.getUniqueName( `each_block` );
+export default function visitEachBlock(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	const each_block = generator.getUniqueName(`each_block`);
 	const create_each_block = node._block.name;
 	const each_block_value = node._block.listName;
-	const iterations = block.getUniqueName( `${each_block}_iterations` );
-	const i = block.alias( `i` );
-	const params = block.params.join( ', ' );
-	const anchor = node.needsAnchor ? block.getUniqueName( `${each_block}_anchor` ) : ( node.next && node.next._state.name ) || 'null';
+	const iterations = block.getUniqueName(`${each_block}_iterations`);
+	const i = block.alias(`i`);
+	const params = block.params.join(', ');
+	const anchor = node.needsAnchor
+		? block.getUniqueName(`${each_block}_anchor`)
+		: (node.next && node.next._state.name) || 'null';
 
 	const mountOrIntro = node._block.hasIntroMethod ? 'intro' : 'mount';
-	const vars = { each_block, create_each_block, each_block_value, iterations, i, params, anchor, mountOrIntro };
-
-	const { snippet } = block.contextualise( node.expression );
-
-	block.builders.create.addLine( `var ${each_block_value} = ${snippet};` );
-
-	if ( node.key ) {
-		keyed( generator, block, state, node, snippet, vars );
+	const vars = {
+		each_block,
+		create_each_block,
+		each_block_value,
+		iterations,
+		i,
+		params,
+		anchor,
+		mountOrIntro
+	};
+
+	const { snippet } = block.contextualise(node.expression);
+
+	block.builders.create.addLine(`var ${each_block_value} = ${snippet};`);
+
+	if (node.key) {
+		keyed(generator, block, state, node, snippet, vars);
 	} else {
-		unkeyed( generator, block, state, node, snippet, vars );
+		unkeyed(generator, block, state, node, snippet, vars);
 	}
 
 	const isToplevel = !state.parentNode;
 
-	if ( node.needsAnchor ) {
-		block.addElement( anchor, `${generator.helper( 'createComment' )}()`, state.parentNode, true );
-	} else if ( node.next ) {
+	if (node.needsAnchor) {
+		block.addElement(
+			anchor,
+			`${generator.helper('createComment')}()`,
+			state.parentNode,
+			true
+		);
+	} else if (node.next) {
 		node.next.usedAsAnchor = true;
 	}
 
-	if ( node.else ) {
-		const each_block_else = generator.getUniqueName( `${each_block}_else` );
+	if (node.else) {
+		const each_block_else = generator.getUniqueName(`${each_block}_else`);
 
-		block.builders.create.addLine( `var ${each_block_else} = null;` );
+		block.builders.create.addLine(`var ${each_block_else} = null;`);
 
 		// TODO neaten this up... will end up with an empty line in the block
-		block.builders.create.addBlock( deindent`
+		block.builders.create.addBlock(deindent`
 			if ( !${each_block_value}.length ) {
-				${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} );
-				${!isToplevel ? `${each_block_else}.${mountOrIntro}( ${state.parentNode}, null );` : ''}
+				${each_block_else} = ${node.else._block
+			.name}( ${params}, ${block.component} );
+				${!isToplevel
+					? `${each_block_else}.${mountOrIntro}( ${state.parentNode}, null );`
+					: ''}
 			}
-		` );
+		`);
 
-		block.builders.mount.addBlock( deindent`
+		block.builders.mount.addBlock(deindent`
 			if ( ${each_block_else} ) {
-				${each_block_else}.${mountOrIntro}( ${state.parentNode || block.target}, null );
+				${each_block_else}.${mountOrIntro}( ${state.parentNode ||
+			block.target}, null );
 			}
-		` );
+		`);
 
 		const parentNode = state.parentNode || `${anchor}.parentNode`;
 
-		if ( node.else._block.hasUpdateMethod ) {
-			block.builders.update.addBlock( deindent`
+		if (node.else._block.hasUpdateMethod) {
+			block.builders.update.addBlock(deindent`
 				if ( !${each_block_value}.length && ${each_block_else} ) {
 					${each_block_else}.update( changed, ${params} );
 				} else if ( !${each_block_value}.length ) {
-					${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} );
+					${each_block_else} = ${node.else._block
+				.name}( ${params}, ${block.component} );
 					${each_block_else}.${mountOrIntro}( ${parentNode}, ${anchor} );
 				} else if ( ${each_block_else} ) {
 					${each_block_else}.unmount();
 					${each_block_else}.destroy();
 					${each_block_else} = null;
 				}
-			` );
+			`);
 		} else {
-			block.builders.update.addBlock( deindent`
+			block.builders.update.addBlock(deindent`
 				if ( ${each_block_value}.length ) {
 					if ( ${each_block_else} ) {
 						${each_block_else}.unmount();
@@ -78,48 +104,70 @@ export default function visitEachBlock ( generator: DomGenerator, block: Block,
 						${each_block_else} = null;
 					}
 				} else if ( !${each_block_else} ) {
-					${each_block_else} = ${node.else._block.name}( ${params}, ${block.component} );
+					${each_block_else} = ${node.else._block
+				.name}( ${params}, ${block.component} );
 					${each_block_else}.${mountOrIntro}( ${parentNode}, ${anchor} );
 				}
-			` );
+			`);
 		}
 
 		block.builders.unmount.addLine(
 			`if ( ${each_block_else} ) ${each_block_else}.unmount()`
 		);
 
-		block.builders.destroy.addBlock( deindent`
+		block.builders.destroy.addBlock(deindent`
 			if ( ${each_block_else} ) ${each_block_else}.destroy( false );
-		` );
+		`);
 	}
 
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, node._block, node._state, child );
+	node.children.forEach((child: Node) => {
+		visit(generator, node._block, node._state, child);
 	});
 
-	if ( node.else ) {
-		node.else.children.forEach( ( child: Node ) => {
-			visit( generator, node.else._block, node.else._state, child );
+	if (node.else) {
+		node.else.children.forEach((child: Node) => {
+			visit(generator, node.else._block, node.else._state, child);
 		});
 	}
 }
 
-function keyed ( generator: DomGenerator, block: Block, state: State, node: Node, snippet, { each_block, create_each_block, each_block_value, i, params, anchor, mountOrIntro } ) {
-	const key = block.getUniqueName( 'key' );
-	const lookup = block.getUniqueName( `${each_block}_lookup` );
-	const iteration = block.getUniqueName( `${each_block}_iteration` );
-	const head = block.getUniqueName( `${each_block}_head` );
-	const last = block.getUniqueName( `${each_block}_last` );
-	const expected = block.getUniqueName( `${each_block}_expected` );
-
-	if ( node.children[0] && node.children[0].type === 'Element' ) { // TODO or text/tag/raw
+function keyed(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	snippet,
+	{
+		each_block,
+		create_each_block,
+		each_block_value,
+		i,
+		params,
+		anchor,
+		mountOrIntro
+	}
+) {
+	const key = block.getUniqueName('key');
+	const lookup = block.getUniqueName(`${each_block}_lookup`);
+	const iteration = block.getUniqueName(`${each_block}_iteration`);
+	const head = block.getUniqueName(`${each_block}_head`);
+	const last = block.getUniqueName(`${each_block}_last`);
+	const expected = block.getUniqueName(`${each_block}_expected`);
+
+	if (node.children[0] && node.children[0].type === 'Element') {
+		// TODO or text/tag/raw
 		node._block.first = node.children[0]._state.parentNode; // TODO this is highly confusing
 	} else {
-		node._block.first = node._block.getUniqueName( 'first' );
-		node._block.addElement( node._block.first, `${generator.helper( 'createComment' )}()`, null, true );
+		node._block.first = node._block.getUniqueName('first');
+		node._block.addElement(
+			node._block.first,
+			`${generator.helper('createComment')}()`,
+			null,
+			true
+		);
 	}
 
-	block.builders.create.addBlock( deindent`
+	block.builders.create.addBlock(deindent`
 		var ${lookup} = Object.create( null );
 
 		var ${head};
@@ -128,7 +176,8 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 		for ( var ${i} = 0; ${i} < ${each_block_value}.length; ${i} += 1 ) {
 			var ${key} = ${each_block_value}[${i}].${node.key};
 			var ${iteration} = ${lookup}[${key}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component}, ${key} );
-			${state.parentNode && `${iteration}.${mountOrIntro}( ${state.parentNode}, null );`}
+			${state.parentNode &&
+				`${iteration}.${mountOrIntro}( ${state.parentNode}, null );`}
 
 			if ( ${last} ) ${last}.next = ${iteration};
 			${iteration}.last = ${last};
@@ -136,25 +185,25 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 
 			if ( ${i} === 0 ) ${head} = ${iteration};
 		}
-	` );
+	`);
 
-	if ( !state.parentNode ) {
-		block.builders.mount.addBlock( deindent`
+	if (!state.parentNode) {
+		block.builders.mount.addBlock(deindent`
 			var ${iteration} = ${head};
 			while ( ${iteration} ) {
 				${iteration}.${mountOrIntro}( ${block.target}, anchor );
 				${iteration} = ${iteration}.next;
 			}
-		` );
+		`);
 	}
 
 	const dynamic = node._block.hasUpdateMethod;
 	const parentNode = state.parentNode || `${anchor}.parentNode`;
 
 	let destroy;
-	if ( node._block.hasOutroMethod ) {
-		const fn = block.getUniqueName( `${each_block}_outro` );
-		block.builders.create.addBlock( deindent`
+	if (node._block.hasOutroMethod) {
+		const fn = block.getUniqueName(`${each_block}_outro`);
+		block.builders.create.addBlock(deindent`
 			function ${fn} ( iteration ) {
 				iteration.outro( function () {
 					iteration.unmount();
@@ -162,7 +211,7 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 					${lookup}[iteration.key] = null;
 				});
 			}
-		` );
+		`);
 
 		destroy = deindent`
 			while ( ${expected} ) {
@@ -177,14 +226,14 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 			}
 		`;
 	} else {
-		const fn = block.getUniqueName( `${each_block}_destroy` );
-		block.builders.create.addBlock( deindent`
+		const fn = block.getUniqueName(`${each_block}_destroy`);
+		block.builders.create.addBlock(deindent`
 			function ${fn} ( iteration ) {
 				iteration.unmount();
 				iteration.destroy();
 				${lookup}[iteration.key] = null;
 			}
-		` );
+		`);
 
 		destroy = deindent`
 			while ( ${expected} ) {
@@ -201,7 +250,7 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 		`;
 	}
 
-	block.builders.update.addBlock( deindent`
+	block.builders.update.addBlock(deindent`
 		var ${each_block_value} = ${snippet};
 
 		var ${expected} = ${head};
@@ -213,7 +262,8 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 			var ${key} = ${each_block_value}[${i}].${node.key};
 			var ${iteration} = ${lookup}[${key}];
 
-			${dynamic && `if ( ${iteration} ) ${iteration}.update( changed, ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i} );`}
+			${dynamic &&
+				`if ( ${iteration} ) ${iteration}.update( changed, ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i} );`}
 
 			if ( ${expected} ) {
 				if ( ${key} === ${expected}.key ) {
@@ -256,7 +306,8 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 
 			if ( ${last} ) ${last}.next = ${iteration};
 			${iteration}.last = ${last};
-			${node._block.hasIntroMethod && `${iteration}.intro( ${parentNode}, ${anchor} );`}
+			${node._block.hasIntroMethod &&
+				`${iteration}.intro( ${parentNode}, ${anchor} );`}
 			${last} = ${iteration};
 		}
 
@@ -265,87 +316,103 @@ function keyed ( generator: DomGenerator, block: Block, state: State, node: Node
 		${destroy}
 
 		${head} = ${lookup}[${each_block_value}[0] && ${each_block_value}[0].${node.key}];
-	` );
+	`);
 
-	if ( !state.parentNode ) {
-		block.builders.unmount.addBlock( deindent`
+	if (!state.parentNode) {
+		block.builders.unmount.addBlock(deindent`
 			var ${iteration} = ${head};
 			while ( ${iteration} ) {
 				${iteration}.unmount();
 				${iteration} = ${iteration}.next;
 			}
-		` );
+		`);
 	}
 
-	block.builders.destroy.addBlock( deindent`
+	block.builders.destroy.addBlock(deindent`
 		var ${iteration} = ${head};
 		while ( ${iteration} ) {
 			${iteration}.destroy( false );
 			${iteration} = ${iteration}.next;
 		}
-	` );
+	`);
 }
 
-function unkeyed ( generator: DomGenerator, block: Block, state: State, node: Node, snippet, { create_each_block, each_block_value, iterations, i, params, anchor, mountOrIntro } ) {
-	block.builders.create.addBlock( deindent`
+function unkeyed(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	snippet,
+	{
+		create_each_block,
+		each_block_value,
+		iterations,
+		i,
+		params,
+		anchor,
+		mountOrIntro
+	}
+) {
+	block.builders.create.addBlock(deindent`
 		var ${iterations} = [];
 
 		for ( var ${i} = 0; ${i} < ${each_block_value}.length; ${i} += 1 ) {
 			${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} );
-			${state.parentNode && `${iterations}[${i}].${mountOrIntro}( ${state.parentNode}, null );`}
+			${state.parentNode &&
+				`${iterations}[${i}].${mountOrIntro}( ${state.parentNode}, null );`}
 		}
-	` );
+	`);
 
-	if ( !state.parentNode ) {
-		block.builders.mount.addBlock( deindent`
+	if (!state.parentNode) {
+		block.builders.mount.addBlock(deindent`
 			for ( var ${i} = 0; ${i} < ${iterations}.length; ${i} += 1 ) {
 				${iterations}[${i}].${mountOrIntro}( ${block.target}, anchor );
 			}
-		` );
+		`);
 	}
 
-	const dependencies = block.findDependencies( node.expression );
-	const allDependencies = new Set( node._block.dependencies );
-	dependencies.forEach( dependency => {
-		allDependencies.add( dependency );
+	const dependencies = block.findDependencies(node.expression);
+	const allDependencies = new Set(node._block.dependencies);
+	dependencies.forEach(dependency => {
+		allDependencies.add(dependency);
 	});
 
 	// TODO do this for keyed blocks as well
-	const condition = Array.from( allDependencies )
-		.map( dependency => `'${dependency}' in changed` )
-		.join( ' || ' );
+	const condition = Array.from(allDependencies)
+		.map(dependency => `'${dependency}' in changed`)
+		.join(' || ');
 
 	const parentNode = state.parentNode || `${anchor}.parentNode`;
 
-	if ( condition !== '' ) {
-		const forLoopBody = node._block.hasUpdateMethod ?
-			node._block.hasIntroMethod ?
-				deindent`
+	if (condition !== '') {
+		const forLoopBody = node._block.hasUpdateMethod
+			? node._block.hasIntroMethod
+				? deindent`
 					if ( ${iterations}[${i}] ) {
 						${iterations}[${i}].update( changed, ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i} );
 					} else {
 						${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} );
 					}
 					${iterations}[${i}].intro( ${parentNode}, ${anchor} );
-				` :
-				deindent`
+				`
+				: deindent`
 					if ( ${iterations}[${i}] ) {
 						${iterations}[${i}].update( changed, ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i} );
 					} else {
 						${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} );
 						${iterations}[${i}].mount( ${parentNode}, ${anchor} );
 					}
-				` :
-			deindent`
+				`
+			: deindent`
 				${iterations}[${i}] = ${create_each_block}( ${params}, ${each_block_value}, ${each_block_value}[${i}], ${i}, ${block.component} );
 				${iterations}[${i}].${mountOrIntro}( ${parentNode}, ${anchor} );
 			`;
 
 		const start = node._block.hasUpdateMethod ? '0' : `${iterations}.length`;
 
-		const outro = block.getUniqueName( 'outro' );
-		const destroy = node._block.hasOutroMethod ?
-			deindent`
+		const outro = block.getUniqueName('outro');
+		const destroy = node._block.hasOutroMethod
+			? deindent`
 				function ${outro} ( i ) {
 					if ( ${iterations}[i] ) {
 						${iterations}[i].outro( function () {
@@ -357,8 +424,8 @@ function unkeyed ( generator: DomGenerator, block: Block, state: State, node: No
 				}
 
 				for ( ; ${i} < ${iterations}.length; ${i} += 1 ) ${outro}( ${i} );
-			` :
-			deindent`
+			`
+			: deindent`
 				for ( ; ${i} < ${iterations}.length; ${i} += 1 ) {
 					${iterations}[${i}].unmount();
 					${iterations}[${i}].destroy();
@@ -366,7 +433,7 @@ function unkeyed ( generator: DomGenerator, block: Block, state: State, node: No
 				${iterations}.length = ${each_block_value}.length;
 			`;
 
-		block.builders.update.addBlock( deindent`
+		block.builders.update.addBlock(deindent`
 			var ${each_block_value} = ${snippet};
 
 			if ( ${condition} ) {
@@ -376,16 +443,16 @@ function unkeyed ( generator: DomGenerator, block: Block, state: State, node: No
 
 				${destroy}
 			}
-		` );
+		`);
 	}
 
-	block.builders.unmount.addBlock( deindent`
+	block.builders.unmount.addBlock(deindent`
 		for ( var ${i} = 0; ${i} < ${iterations}.length; ${i} += 1 ) {
 			${iterations}[${i}].unmount();
 		}
-	` );
+	`);
 
 	block.builders.destroy.addBlock(
-		`${generator.helper( 'destroyEach' )}( ${iterations}, false, 0 );`
+		`${generator.helper('destroyEach')}( ${iterations}, false, 0 );`
 	);
 }
diff --git a/src/generators/dom/visitors/Element/Attribute.ts b/src/generators/dom/visitors/Element/Attribute.ts
index 7252eb6886..8270852e11 100644
--- a/src/generators/dom/visitors/Element/Attribute.ts
+++ b/src/generators/dom/visitors/Element/Attribute.ts
@@ -6,64 +6,85 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitAttribute ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
+export default function visitAttribute(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node
+) {
 	const name = attribute.name;
 
-	let metadata = state.namespace ? null : attributeLookup[ name ];
-	if ( metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) metadata = null;
+	let metadata = state.namespace ? null : attributeLookup[name];
+	if (metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf(node.name))
+		metadata = null;
 
-	const isIndirectlyBoundValue = name === 'value' && (
-		node.name === 'option' || // TODO check it's actually bound
-		node.name === 'input' && /^(checkbox|radio)$/.test( getStaticAttributeValue( node, 'type' ) )
-	);
+	const isIndirectlyBoundValue =
+		name === 'value' &&
+		(node.name === 'option' || // TODO check it's actually bound
+			(node.name === 'input' &&
+				/^(checkbox|radio)$/.test(getStaticAttributeValue(node, 'type'))));
 
-	const propertyName = isIndirectlyBoundValue ? '__value' : metadata && metadata.propertyName;
+	const propertyName = isIndirectlyBoundValue
+		? '__value'
+		: metadata && metadata.propertyName;
 
 	// xlink is a special case... we could maybe extend this to generic
 	// namespaced attributes but I'm not sure that's applicable in
 	// HTML5?
-	const method = name.slice( 0, 6 ) === 'xlink:' ? 'setXlinkAttribute' : 'setAttribute';
+	const method = name.slice(0, 6) === 'xlink:'
+		? 'setXlinkAttribute'
+		: 'setAttribute';
 
-	const isDynamic = attribute.value !== true && attribute.value.length > 1 || ( attribute.value.length === 1 && attribute.value[0].type !== 'Text' );
+	const isDynamic =
+		(attribute.value !== true && attribute.value.length > 1) ||
+		(attribute.value.length === 1 && attribute.value[0].type !== 'Text');
 
-	if ( isDynamic ) {
+	if (isDynamic) {
 		let value;
 
-		if ( attribute.value.length === 1 ) {
+		if (attribute.value.length === 1) {
 			// single {{tag}} — may be a non-string
-			const { snippet } = block.contextualise( attribute.value[0].expression );
+			const { snippet } = block.contextualise(attribute.value[0].expression);
 			value = snippet;
 		} else {
 			// '{{foo}} {{bar}}' — treat as string concatenation
-			value = ( attribute.value[0].type === 'Text' ? '' : `"" + ` ) + (
-				attribute.value.map( ( chunk: Node ) => {
-					if ( chunk.type === 'Text' ) {
-						return JSON.stringify( chunk.data );
-					} else {
-						const { snippet } = block.contextualise( chunk.expression );
-						return `( ${snippet} )`;
-					}
-				}).join( ' + ' )
-			);
+			value =
+				(attribute.value[0].type === 'Text' ? '' : `"" + `) +
+				attribute.value
+					.map((chunk: Node) => {
+						if (chunk.type === 'Text') {
+							return JSON.stringify(chunk.data);
+						} else {
+							const { snippet } = block.contextualise(chunk.expression);
+							return `( ${snippet} )`;
+						}
+					})
+					.join(' + ');
 		}
 
-		const last = block.getUniqueName( `${state.parentNode}_${name.replace( /[^a-zA-Z_$]/g, '_')}_value` );
-		block.addVariable( last );
+		const last = block.getUniqueName(
+			`${state.parentNode}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value`
+		);
+		block.addVariable(last);
 
-		const isSelectValueAttribute = name === 'value' && state.parentNodeName === 'select';
+		const isSelectValueAttribute =
+			name === 'value' && state.parentNodeName === 'select';
 
 		let updater;
 
-		if ( isSelectValueAttribute ) {
+		if (isSelectValueAttribute) {
 			// annoying special case
-			const isMultipleSelect = node.name === 'select' && node.attributes.find( attr => attr.name.toLowerCase() === 'multiple' ); // TODO use getStaticAttributeValue
-			const i = block.getUniqueName( 'i' );
-			const option = block.getUniqueName( 'option' );
-
-			const ifStatement = isMultipleSelect ?
-				deindent`
-					${option}.selected = ~${last}.indexOf( ${option}.__value );` :
-				deindent`
+			const isMultipleSelect =
+				node.name === 'select' &&
+				node.attributes.find(attr => attr.name.toLowerCase() === 'multiple'); // TODO use getStaticAttributeValue
+			const i = block.getUniqueName('i');
+			const option = block.getUniqueName('option');
+
+			const ifStatement = isMultipleSelect
+				? deindent`
+					${option}.selected = ~${last}.indexOf( ${option}.__value );`
+				: deindent`
 					if ( ${option}.__value === ${last} ) {
 						${option}.selected = true;
 						break;
@@ -77,53 +98,62 @@ export default function visitAttribute ( generator: DomGenerator, block: Block,
 				}
 			`;
 
-			block.builders.create.addLine( deindent`
+			block.builders.create.addLine(deindent`
 				${last} = ${value}
 				${updater}
-			` );
-		} else if ( propertyName ) {
-			block.builders.create.addLine( `${state.parentNode}.${propertyName} = ${last} = ${value};` );
+			`);
+		} else if (propertyName) {
+			block.builders.create.addLine(
+				`${state.parentNode}.${propertyName} = ${last} = ${value};`
+			);
 			updater = `${state.parentNode}.${propertyName} = ${last};`;
 		} else {
-			block.builders.create.addLine( `${generator.helper( method )}( ${state.parentNode}, '${name}', ${last} = ${value} );` );
-			updater = `${generator.helper( method )}( ${state.parentNode}, '${name}', ${last} );`;
+			block.builders.create.addLine(
+				`${generator.helper(
+					method
+				)}( ${state.parentNode}, '${name}', ${last} = ${value} );`
+			);
+			updater = `${generator.helper(
+				method
+			)}( ${state.parentNode}, '${name}', ${last} );`;
 		}
 
-		block.builders.update.addBlock( deindent`
+		block.builders.update.addBlock(deindent`
 			if ( ${last} !== ( ${last} = ${value} ) ) {
 				${updater}
 			}
-		` );
-	}
-
-	else {
-		const value = attribute.value === true ? 'true' :
-		              attribute.value.length === 0 ? `''` :
-		              JSON.stringify( attribute.value[0].data );
-
-		const statement = propertyName ?
-			`${state.parentNode}.${propertyName} = ${value};` :
-			`${generator.helper( method )}( ${state.parentNode}, '${name}', ${value} );`;
-
-
-		block.builders.create.addLine( statement );
+		`);
+	} else {
+		const value = attribute.value === true
+			? 'true'
+			: attribute.value.length === 0
+				? `''`
+				: JSON.stringify(attribute.value[0].data);
+
+		const statement = propertyName
+			? `${state.parentNode}.${propertyName} = ${value};`
+			: `${generator.helper(
+					method
+				)}( ${state.parentNode}, '${name}', ${value} );`;
+
+		block.builders.create.addLine(statement);
 
 		// special case – autofocus. has to be handled in a bit of a weird way
-		if ( attribute.value === true && name === 'autofocus' ) {
+		if (attribute.value === true && name === 'autofocus') {
 			block.autofocus = state.parentNode;
 		}
 
 		// special case — xmlns
-		if ( name === 'xmlns' ) {
+		if (name === 'xmlns') {
 			// TODO this attribute must be static – enforce at compile time
 			state.namespace = attribute.value[0].data;
 		}
 	}
 
-	if ( isIndirectlyBoundValue ) {
+	if (isIndirectlyBoundValue) {
 		const updateValue = `${state.parentNode}.value = ${state.parentNode}.__value;`;
 
-		block.builders.create.addLine( updateValue );
-		if ( isDynamic ) block.builders.update.addLine( updateValue );
+		block.builders.create.addLine(updateValue);
+		if (isDynamic) block.builders.update.addLine(updateValue);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Element/Binding.ts b/src/generators/dom/visitors/Element/Binding.ts
index 04173a3cd7..e32c8cbf0b 100644
--- a/src/generators/dom/visitors/Element/Binding.ts
+++ b/src/generators/dom/visitors/Element/Binding.ts
@@ -7,51 +7,88 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-function getObject ( node ) {
+function getObject(node) {
 	// TODO validation should ensure this is an Identifier or a MemberExpression
-	while ( node.type === 'MemberExpression' ) node = node.object;
+	while (node.type === 'MemberExpression') node = node.object;
 	return node;
 }
 
-export default function visitBinding ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
-	const { name } = getObject( attribute.value );
-	const { snippet, contexts } = block.contextualise( attribute.value );
-	const dependencies = block.contextDependencies.has( name ) ? block.contextDependencies.get( name ) : [ name ];
-
-	if ( dependencies.length > 1 ) throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' );
+export default function visitBinding(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node
+) {
+	const { name } = getObject(attribute.value);
+	const { snippet, contexts } = block.contextualise(attribute.value);
+	const dependencies = block.contextDependencies.has(name)
+		? block.contextDependencies.get(name)
+		: [name];
+
+	if (dependencies.length > 1)
+		throw new Error(
+			'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!'
+		);
 
-	contexts.forEach( context => {
-		if ( !~state.allUsedContexts.indexOf( context ) ) state.allUsedContexts.push( context );
+	contexts.forEach(context => {
+		if (!~state.allUsedContexts.indexOf(context))
+			state.allUsedContexts.push(context);
 	});
 
-	const eventName = getBindingEventName( node, attribute );
-	const handler = block.getUniqueName( `${state.parentNode}_${eventName}_handler` );
-	const isMultipleSelect = node.name === 'select' && node.attributes.find( ( attr: Node ) => attr.name.toLowerCase() === 'multiple' ); // TODO use getStaticAttributeValue
-	const type = getStaticAttributeValue( node, 'type' );
-	const bindingGroup = attribute.name === 'group' ? getBindingGroup( generator, attribute.value ) : null;
-	const value = getBindingValue( generator, block, state, node, attribute, isMultipleSelect, bindingGroup, type );
-
-	let setter = getSetter({ block, name, snippet, context: '_svelte', attribute, dependencies, value });
+	const eventName = getBindingEventName(node, attribute);
+	const handler = block.getUniqueName(
+		`${state.parentNode}_${eventName}_handler`
+	);
+	const isMultipleSelect =
+		node.name === 'select' &&
+		node.attributes.find(
+			(attr: Node) => attr.name.toLowerCase() === 'multiple'
+		); // TODO use getStaticAttributeValue
+	const type = getStaticAttributeValue(node, 'type');
+	const bindingGroup = attribute.name === 'group'
+		? getBindingGroup(generator, attribute.value)
+		: null;
+	const value = getBindingValue(
+		generator,
+		block,
+		state,
+		node,
+		attribute,
+		isMultipleSelect,
+		bindingGroup,
+		type
+	);
+
+	let setter = getSetter({
+		block,
+		name,
+		snippet,
+		context: '_svelte',
+		attribute,
+		dependencies,
+		value
+	});
 	let updateElement = `${state.parentNode}.${attribute.name} = ${snippet};`;
-	const lock = block.alias( `${state.parentNode}_updating` );
+	const lock = block.alias(`${state.parentNode}_updating`);
 	let updateCondition = `!${lock}`;
 
-	block.addVariable( lock, 'false' );
+	block.addVariable(lock, 'false');
 
 	// <select> special case
-	if ( node.name === 'select' ) {
-		if ( !isMultipleSelect ) {
+	if (node.name === 'select') {
+		if (!isMultipleSelect) {
 			setter = `var selectedOption = ${state.parentNode}.querySelector(':checked') || ${state.parentNode}.options[0];\n${setter}`;
 		}
 
-		const value = block.getUniqueName( 'value' );
-		const i = block.alias( 'i' );
-		const option = block.getUniqueName( 'option' );
+		const value = block.getUniqueName('value');
+		const i = block.alias('i');
+		const option = block.getUniqueName('option');
 
-		const ifStatement = isMultipleSelect ?
-			deindent`
-				${option}.selected = ~${value}.indexOf( ${option}.__value );` :
-			deindent`
+		const ifStatement = isMultipleSelect
+			? deindent`
+				${option}.selected = ~${value}.indexOf( ${option}.__value );`
+			: deindent`
 				if ( ${option}.__value === ${value} ) {
 					${option}.selected = true;
 					break;
@@ -65,20 +102,18 @@ export default function visitBinding ( generator: DomGenerator, block: Block, st
 				${ifStatement}
 			}
 		`;
-	}
-
-	// <input type='checkbox|radio' bind:group='selected'> special case
-	else if ( attribute.name === 'group' ) {
-		if ( type === 'radio' ) {
+	} else if (attribute.name === 'group') {
+		// <input type='checkbox|radio' bind:group='selected'> special case
+		if (type === 'radio') {
 			setter = deindent`
 				if ( !${state.parentNode}.checked ) return;
 				${setter}
 			`;
 		}
 
-		const condition = type === 'checkbox' ?
-			`~${snippet}.indexOf( ${state.parentNode}.__value )` :
-			`${state.parentNode}.__value === ${snippet}`;
+		const condition = type === 'checkbox'
+			? `~${snippet}.indexOf( ${state.parentNode}.__value )`
+			: `${state.parentNode}.__value === ${snippet}`;
 
 		block.builders.create.addLine(
 			`${block.component}._bindingGroups[${bindingGroup}].push( ${state.parentNode} );`
@@ -89,15 +124,15 @@ export default function visitBinding ( generator: DomGenerator, block: Block, st
 		);
 
 		updateElement = `${state.parentNode}.checked = ${condition};`;
-	}
-
-	else if ( node.name === 'audio' || node.name === 'video' ) {
+	} else if (node.name === 'audio' || node.name === 'video') {
 		generator.hasComplexBindings = true;
-		block.builders.create.addBlock( `${block.component}._bindings.push( ${handler} );` );
+		block.builders.create.addBlock(
+			`${block.component}._bindings.push( ${handler} );`
+		);
 
-		if ( attribute.name === 'currentTime' ) {
-			const frame = block.getUniqueName( `${state.parentNode}_animationframe` );
-			block.addVariable( frame );
+		if (attribute.name === 'currentTime') {
+			const frame = block.getUniqueName(`${state.parentNode}_animationframe`);
+			block.addVariable(frame);
 			setter = deindent`
 				cancelAnimationFrame( ${frame} );
 				if ( !${state.parentNode}.paused ) ${frame} = requestAnimationFrame( ${handler} );
@@ -105,108 +140,132 @@ export default function visitBinding ( generator: DomGenerator, block: Block, st
 			`;
 
 			updateCondition += ` && !isNaN( ${snippet} )`;
-		}
-
-		else if ( attribute.name === 'duration' ) {
+		} else if (attribute.name === 'duration') {
 			updateCondition = null;
-		}
-
-		else if ( attribute.name === 'paused' ) {
+		} else if (attribute.name === 'paused') {
 			// this is necessary to prevent the audio restarting by itself
-			const last = block.getUniqueName( `${state.parentNode}_paused_value` );
-			block.addVariable( last, 'true' );
+			const last = block.getUniqueName(`${state.parentNode}_paused_value`);
+			block.addVariable(last, 'true');
 
 			updateCondition = `${last} !== ( ${last} = ${snippet} )`;
 			updateElement = `${state.parentNode}[ ${last} ? 'pause' : 'play' ]();`;
 		}
 	}
 
-	block.builders.create.addBlock( deindent`
+	block.builders.create.addBlock(deindent`
 		function ${handler} () {
 			${lock} = true;
 			${setter}
 			${lock} = false;
 		}
 
-		${generator.helper( 'addEventListener' )}( ${state.parentNode}, '${eventName}', ${handler} );
-	` );
+		${generator.helper(
+			'addEventListener'
+		)}( ${state.parentNode}, '${eventName}', ${handler} );
+	`);
 
-	if ( node.name !== 'audio' && node.name !== 'video' ) node.initialUpdate = updateElement;
+	if (node.name !== 'audio' && node.name !== 'video')
+		node.initialUpdate = updateElement;
 
-	if ( updateCondition !== null ) {
+	if (updateCondition !== null) {
 		// audio/video duration is read-only, it never updates
-		block.builders.update.addBlock( deindent`
+		block.builders.update.addBlock(deindent`
 			if ( ${updateCondition} ) {
 				${updateElement}
 			}
-		` );
+		`);
 	}
 
-	block.builders.destroy.addLine( deindent`
-		${generator.helper( 'removeEventListener' )}( ${state.parentNode}, '${eventName}', ${handler} );
-	` );
+	block.builders.destroy.addLine(deindent`
+		${generator.helper(
+			'removeEventListener'
+		)}( ${state.parentNode}, '${eventName}', ${handler} );
+	`);
 
-	if ( attribute.name === 'paused' ) {
-		block.builders.create.addLine( `${generator.helper( 'addEventListener' )}( ${state.parentNode}, 'play', ${handler} );` );
-		block.builders.destroy.addLine( `${generator.helper( 'removeEventListener' )}( ${state.parentNode}, 'play', ${handler} );` );
+	if (attribute.name === 'paused') {
+		block.builders.create.addLine(
+			`${generator.helper(
+				'addEventListener'
+			)}( ${state.parentNode}, 'play', ${handler} );`
+		);
+		block.builders.destroy.addLine(
+			`${generator.helper(
+				'removeEventListener'
+			)}( ${state.parentNode}, 'play', ${handler} );`
+		);
 	}
 }
 
-function getBindingEventName ( node: Node, attribute: Node ) {
-	if ( node.name === 'input' ) {
-		const typeAttribute = node.attributes.find( ( attr: Node ) => attr.type === 'Attribute' && attr.name === 'type' );
+function getBindingEventName(node: Node, attribute: Node) {
+	if (node.name === 'input') {
+		const typeAttribute = node.attributes.find(
+			(attr: Node) => attr.type === 'Attribute' && attr.name === 'type'
+		);
 		const type = typeAttribute ? typeAttribute.value[0].data : 'text'; // TODO in validation, should throw if type attribute is not static
 
 		return type === 'checkbox' || type === 'radio' ? 'change' : 'input';
 	}
 
-	if ( node.name === 'textarea' ) return 'input';
-	if ( attribute.name === 'currentTime' ) return 'timeupdate';
-	if ( attribute.name === 'duration' ) return 'durationchange';
-	if ( attribute.name === 'paused' ) return 'pause';
+	if (node.name === 'textarea') return 'input';
+	if (attribute.name === 'currentTime') return 'timeupdate';
+	if (attribute.name === 'duration') return 'durationchange';
+	if (attribute.name === 'paused') return 'pause';
 
 	return 'change';
 }
 
-function getBindingValue ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, isMultipleSelect: boolean, bindingGroup: number, type: string ) {
+function getBindingValue(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node,
+	isMultipleSelect: boolean,
+	bindingGroup: number,
+	type: string
+) {
 	// <select multiple bind:value='selected>
-	if ( isMultipleSelect ) {
+	if (isMultipleSelect) {
 		return `[].map.call( ${state.parentNode}.querySelectorAll(':checked'), function ( option ) { return option.__value; })`;
 	}
 
 	// <select bind:value='selected>
-	if ( node.name === 'select' ) {
+	if (node.name === 'select') {
 		return 'selectedOption && selectedOption.__value';
 	}
 
 	// <input type='checkbox' bind:group='foo'>
-	if ( attribute.name === 'group' ) {
-		if ( type === 'checkbox' ) {
-			return `${generator.helper( 'getBindingGroupValue' )}( ${block.component}._bindingGroups[${bindingGroup}] )`;
+	if (attribute.name === 'group') {
+		if (type === 'checkbox') {
+			return `${generator.helper(
+				'getBindingGroupValue'
+			)}( ${block.component}._bindingGroups[${bindingGroup}] )`;
 		}
 
 		return `${state.parentNode}.__value`;
 	}
 
 	// <input type='range|number' bind:value>
-	if ( type === 'range' || type === 'number' ) {
-		return `${generator.helper( 'toNumber' )}( ${state.parentNode}.${attribute.name} )`;
+	if (type === 'range' || type === 'number') {
+		return `${generator.helper(
+			'toNumber'
+		)}( ${state.parentNode}.${attribute.name} )`;
 	}
 
 	// everything else
 	return `${state.parentNode}.${attribute.name}`;
 }
 
-function getBindingGroup ( generator: DomGenerator, value: Node ) {
-	const { parts } = flattenReference( value ); // TODO handle cases involving computed member expressions
-	const keypath = parts.join( '.' );
+function getBindingGroup(generator: DomGenerator, value: Node) {
+	const { parts } = flattenReference(value); // TODO handle cases involving computed member expressions
+	const keypath = parts.join('.');
 
 	// TODO handle contextual bindings — `keypath` should include unique ID of
 	// each block that provides context
-	let index = generator.bindingGroups.indexOf( keypath );
-	if ( index === -1 ) {
+	let index = generator.bindingGroups.indexOf(keypath);
+	if (index === -1) {
 		index = generator.bindingGroups.length;
-		generator.bindingGroups.push( keypath );
+		generator.bindingGroups.push(keypath);
 	}
 
 	return index;
diff --git a/src/generators/dom/visitors/Element/Element.ts b/src/generators/dom/visitors/Element/Element.ts
index b122634845..12ad94448a 100644
--- a/src/generators/dom/visitors/Element/Element.ts
+++ b/src/generators/dom/visitors/Element/Element.ts
@@ -30,87 +30,109 @@ const visitors = {
 	Ref: visitRef
 };
 
-export default function visitElement ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	if ( node.name in meta ) {
-		return meta[ node.name ]( generator, block, node );
+export default function visitElement(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	if (node.name in meta) {
+		return meta[node.name](generator, block, node);
 	}
 
-	if ( generator.components.has( node.name ) || node.name === ':Self' ) {
-		return visitComponent( generator, block, state, node );
+	if (generator.components.has(node.name) || node.name === ':Self') {
+		return visitComponent(generator, block, state, node);
 	}
 
 	const childState = node._state;
 	const name = childState.parentNode;
 
-	block.builders.create.addLine( `var ${name} = ${getRenderStatement( generator, childState.namespace, node.name )};` );
-	block.mount( name, state.parentNode );
+	block.builders.create.addLine(
+		`var ${name} = ${getRenderStatement(
+			generator,
+			childState.namespace,
+			node.name
+		)};`
+	);
+	block.mount(name, state.parentNode);
 
 	// add CSS encapsulation attribute
-	if ( generator.cssId && ( !generator.cascade || state.isTopLevel ) ) {
-		block.builders.create.addLine( `${generator.helper( 'setAttribute' )}( ${name}, '${generator.cssId}', '' );` );
+	if (generator.cssId && (!generator.cascade || state.isTopLevel)) {
+		block.builders.create.addLine(
+			`${generator.helper(
+				'setAttribute'
+			)}( ${name}, '${generator.cssId}', '' );`
+		);
 	}
 
-	function visitAttributesAndAddProps () {
+	function visitAttributesAndAddProps() {
 		let intro;
 		let outro;
 
 		node.attributes
-			.sort( ( a: Node, b: Node ) => order[ a.type ] - order[ b.type ] )
-			.forEach( ( attribute: Node ) => {
-				if ( attribute.type === 'Transition' ) {
-					if ( attribute.intro ) intro = attribute;
-					if ( attribute.outro ) outro = attribute;
+			.sort((a: Node, b: Node) => order[a.type] - order[b.type])
+			.forEach((attribute: Node) => {
+				if (attribute.type === 'Transition') {
+					if (attribute.intro) intro = attribute;
+					if (attribute.outro) outro = attribute;
 					return;
 				}
 
-				visitors[ attribute.type ]( generator, block, childState, node, attribute );
+				visitors[attribute.type](generator, block, childState, node, attribute);
 			});
 
-		if ( intro || outro ) addTransitions( generator, block, childState, node, intro, outro );
+		if (intro || outro)
+			addTransitions(generator, block, childState, node, intro, outro);
 
-		if ( childState.allUsedContexts.length || childState.usesComponent ) {
+		if (childState.allUsedContexts.length || childState.usesComponent) {
 			const initialProps: string[] = [];
 			const updates: string[] = [];
 
-			if ( childState.usesComponent ) {
-				initialProps.push( `component: ${block.component}` );
+			if (childState.usesComponent) {
+				initialProps.push(`component: ${block.component}`);
 			}
 
-			childState.allUsedContexts.forEach( ( contextName: string ) => {
-				if ( contextName === 'state' ) return;
+			childState.allUsedContexts.forEach((contextName: string) => {
+				if (contextName === 'state') return;
 
-				const listName = block.listNames.get( contextName );
-				const indexName = block.indexNames.get( contextName );
+				const listName = block.listNames.get(contextName);
+				const indexName = block.indexNames.get(contextName);
 
-				initialProps.push( `${listName}: ${listName},\n${indexName}: ${indexName}` );
-				updates.push( `${name}._svelte.${listName} = ${listName};\n${name}._svelte.${indexName} = ${indexName};` );
+				initialProps.push(
+					`${listName}: ${listName},\n${indexName}: ${indexName}`
+				);
+				updates.push(
+					`${name}._svelte.${listName} = ${listName};\n${name}._svelte.${indexName} = ${indexName};`
+				);
 			});
 
-			if ( initialProps.length ) {
-				block.builders.create.addBlock( deindent`
+			if (initialProps.length) {
+				block.builders.create.addBlock(deindent`
 					${name}._svelte = {
-						${initialProps.join( ',\n' )}
+						${initialProps.join(',\n')}
 					};
-				` );
+				`);
 			}
 
-			if ( updates.length ) {
-				block.builders.update.addBlock( updates.join( '\n' ) );
+			if (updates.length) {
+				block.builders.update.addBlock(updates.join('\n'));
 			}
 		}
 	}
 
-	if ( !state.parentNode ) {
+	if (!state.parentNode) {
 		// TODO we eventually need to consider what happens to elements
 		// that belong to the same outgroup as an outroing element...
-		block.builders.unmount.addLine( `${generator.helper( 'detachNode' )}( ${name} );` );
+		block.builders.unmount.addLine(
+			`${generator.helper('detachNode')}( ${name} );`
+		);
 	}
 
-	if ( node.name !== 'select' ) {
-		if ( node.name === 'textarea' ) {
+	if (node.name !== 'select') {
+		if (node.name === 'textarea') {
 			// this is an egregious hack, but it's the easiest way to get <textarea>
 			// children treated the same way as a value attribute
-			if ( node.children.length > 0 ) {
+			if (node.children.length > 0) {
 				node.attributes.push({
 					type: 'Attribute',
 					name: 'value',
@@ -127,36 +149,47 @@ export default function visitElement ( generator: DomGenerator, block: Block, st
 	}
 
 	// special case – bound <option> without a value attribute
-	if ( node.name === 'option' && !node.attributes.find( ( attribute: Node ) => attribute.type === 'Attribute' && attribute.name === 'value' ) ) { 	// TODO check it's bound
+	if (
+		node.name === 'option' &&
+		!node.attributes.find(
+			(attribute: Node) =>
+				attribute.type === 'Attribute' && attribute.name === 'value'
+		)
+	) {
+		// TODO check it's bound
 		const statement = `${name}.__value = ${name}.textContent;`;
 		node.initialUpdate = node.lateUpdate = statement;
 	}
 
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, block, childState, child );
+	node.children.forEach((child: Node) => {
+		visit(generator, block, childState, child);
 	});
 
-	if ( node.lateUpdate ) {
-		block.builders.update.addLine( node.lateUpdate );
+	if (node.lateUpdate) {
+		block.builders.update.addLine(node.lateUpdate);
 	}
 
-	if ( node.name === 'select' ) {
+	if (node.name === 'select') {
 		visitAttributesAndAddProps();
 	}
 
-	if ( node.initialUpdate ) {
-		block.builders.create.addBlock( node.initialUpdate );
+	if (node.initialUpdate) {
+		block.builders.create.addBlock(node.initialUpdate);
 	}
 }
 
-function getRenderStatement ( generator: DomGenerator, namespace: string, name: string ) {
-	if ( namespace === 'http://www.w3.org/2000/svg' ) {
-		return `${generator.helper( 'createSvgElement' )}( '${name}' )`;
+function getRenderStatement(
+	generator: DomGenerator,
+	namespace: string,
+	name: string
+) {
+	if (namespace === 'http://www.w3.org/2000/svg') {
+		return `${generator.helper('createSvgElement')}( '${name}' )`;
 	}
 
-	if ( namespace ) {
+	if (namespace) {
 		return `document.createElementNS( '${namespace}', '${name}' )`;
 	}
 
-	return `${generator.helper( 'createElement' )}( '${name}' )`;
+	return `${generator.helper('createElement')}( '${name}' )`;
 }
diff --git a/src/generators/dom/visitors/Element/EventHandler.ts b/src/generators/dom/visitors/Element/EventHandler.ts
index b244bdcae4..1227925bf7 100644
--- a/src/generators/dom/visitors/Element/EventHandler.ts
+++ b/src/generators/dom/visitors/Element/EventHandler.ts
@@ -5,49 +5,61 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitEventHandler ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
+export default function visitEventHandler(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node
+) {
 	const name = attribute.name;
-	const isCustomEvent = generator.events.has( name );
+	const isCustomEvent = generator.events.has(name);
 	const shouldHoist = !isCustomEvent && state.inEachBlock;
 
-	generator.addSourcemapLocations( attribute.expression );
+	generator.addSourcemapLocations(attribute.expression);
 
-	const flattened = flattenReference( attribute.expression.callee );
-	if ( flattened.name !== 'event' && flattened.name !== 'this' ) {
+	const flattened = flattenReference(attribute.expression.callee);
+	if (flattened.name !== 'event' && flattened.name !== 'this') {
 		// allow event.stopPropagation(), this.select() etc
 		// TODO verify that it's a valid callee (i.e. built-in or declared method)
-		generator.code.prependRight( attribute.expression.start, `${block.component}.` );
-		if ( shouldHoist ) state.usesComponent = true; // this feels a bit hacky but it works!
+		generator.code.prependRight(
+			attribute.expression.start,
+			`${block.component}.`
+		);
+		if (shouldHoist) state.usesComponent = true; // this feels a bit hacky but it works!
 	}
 
 	const context = shouldHoist ? null : state.parentNode;
 	const usedContexts: string[] = [];
-	attribute.expression.arguments.forEach( ( arg: Node ) => {
-		const { contexts } = block.contextualise( arg, context, true );
+	attribute.expression.arguments.forEach((arg: Node) => {
+		const { contexts } = block.contextualise(arg, context, true);
 
-		contexts.forEach( context => {
-			if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
-			if ( !~state.allUsedContexts.indexOf( context ) ) state.allUsedContexts.push( context );
+		contexts.forEach(context => {
+			if (!~usedContexts.indexOf(context)) usedContexts.push(context);
+			if (!~state.allUsedContexts.indexOf(context))
+				state.allUsedContexts.push(context);
 		});
 	});
 
 	const _this = context || 'this';
-	const declarations = usedContexts.map( name => {
-		if ( name === 'state' ) {
-			if ( shouldHoist ) state.usesComponent = true;
+	const declarations = usedContexts.map(name => {
+		if (name === 'state') {
+			if (shouldHoist) state.usesComponent = true;
 			return `var state = ${block.component}.get();`;
 		}
 
-		const listName = block.listNames.get( name );
-		const indexName = block.indexNames.get( name );
-		const contextName = block.contexts.get( name );
+		const listName = block.listNames.get(name);
+		const indexName = block.indexNames.get(name);
+		const contextName = block.contexts.get(name);
 
 		return `var ${listName} = ${_this}._svelte.${listName}, ${indexName} = ${_this}._svelte.${indexName}, ${contextName} = ${listName}[${indexName}];`;
 	});
 
 	// get a name for the event handler that is globally unique
 	// if hoisted, locally unique otherwise
-	const handlerName = ( shouldHoist ? generator : block ).getUniqueName( `${name.replace( /[^a-zA-Z0-9_$]/g, '_' )}_handler` );
+	const handlerName = (shouldHoist ? generator : block).getUniqueName(
+		`${name.replace(/[^a-zA-Z0-9_$]/g, '_')}_handler`
+	);
 
 	// create the handler body
 	const handlerBody = deindent`
@@ -56,37 +68,45 @@ export default function visitEventHandler ( generator: DomGenerator, block: Bloc
 		[✂${attribute.expression.start}-${attribute.expression.end}✂];
 	`;
 
-	const handler = isCustomEvent ?
-		deindent`
-			var ${handlerName} = ${generator.alias( 'template' )}.events.${name}.call( ${block.component}, ${state.parentNode}, function ( event ) {
+	const handler = isCustomEvent
+		? deindent`
+			var ${handlerName} = ${generator.alias(
+				'template'
+			)}.events.${name}.call( ${block.component}, ${state.parentNode}, function ( event ) {
 				${handlerBody}
 			});
-		` :
-		deindent`
+		`
+		: deindent`
 			function ${handlerName} ( event ) {
 				${handlerBody}
 			}
 		`;
 
-	if ( shouldHoist ) {
-		generator.blocks.push(<Block>{
-			render: () => handler
-		});
+	if (shouldHoist) {
+		generator.blocks.push(
+			<Block>{
+				render: () => handler
+			}
+		);
 	} else {
-		block.builders.create.addBlock( handler );
+		block.builders.create.addBlock(handler);
 	}
 
-	if ( isCustomEvent ) {
-		block.builders.destroy.addLine( deindent`
+	if (isCustomEvent) {
+		block.builders.destroy.addLine(deindent`
 			${handlerName}.teardown();
-		` );
+		`);
 	} else {
-		block.builders.create.addLine( deindent`
-			${generator.helper( 'addEventListener' )}( ${state.parentNode}, '${name}', ${handlerName} );
-		` );
+		block.builders.create.addLine(deindent`
+			${generator.helper(
+				'addEventListener'
+			)}( ${state.parentNode}, '${name}', ${handlerName} );
+		`);
 
-		block.builders.destroy.addLine( deindent`
-			${generator.helper( 'removeEventListener' )}( ${state.parentNode}, '${name}', ${handlerName} );
-		` );
+		block.builders.destroy.addLine(deindent`
+			${generator.helper(
+				'removeEventListener'
+			)}( ${state.parentNode}, '${name}', ${handlerName} );
+		`);
 	}
 }
diff --git a/src/generators/dom/visitors/Element/Ref.ts b/src/generators/dom/visitors/Element/Ref.ts
index 10db528edf..6577114e6e 100644
--- a/src/generators/dom/visitors/Element/Ref.ts
+++ b/src/generators/dom/visitors/Element/Ref.ts
@@ -4,16 +4,22 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
+export default function visitRef(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	attribute: Node
+) {
 	const name = attribute.name;
 
 	block.builders.create.addLine(
 		`${block.component}.refs.${name} = ${state.parentNode};`
 	);
 
-	block.builders.destroy.addLine( deindent`
+	block.builders.destroy.addLine(deindent`
 		if ( ${block.component}.refs.${name} === ${state.parentNode} ) ${block.component}.refs.${name} = null;
-	` );
+	`);
 
 	generator.usesRefs = true; // so this component.refs object is created
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Element/addTransitions.ts b/src/generators/dom/visitors/Element/addTransitions.ts
index 80e02ad402..66d4a83cb9 100644
--- a/src/generators/dom/visitors/Element/addTransitions.ts
+++ b/src/generators/dom/visitors/Element/addTransitions.ts
@@ -4,77 +4,88 @@ import Block from '../../Block';
 import { Node } from '../../../../interfaces';
 import { State } from '../../interfaces';
 
-export default function addTransitions ( generator: DomGenerator, block: Block, state: State, node: Node, intro, outro ) {
-	const wrapTransition = generator.helper( 'wrapTransition' );
+export default function addTransitions(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	intro,
+	outro
+) {
+	const wrapTransition = generator.helper('wrapTransition');
 
-	if ( intro === outro ) {
-		const name = block.getUniqueName( `${state.name}_transition` );
-		const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
+	if (intro === outro) {
+		const name = block.getUniqueName(`${state.name}_transition`);
+		const snippet = intro.expression
+			? block.contextualise(intro.expression).snippet
+			: '{}';
 
-		block.addVariable( name );
+		block.addVariable(name);
 
-		const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`;
+		const fn = `${generator.alias('template')}.transitions.${intro.name}`;
 
-		block.builders.intro.addBlock( deindent`
+		block.builders.intro.addBlock(deindent`
 			${block.component}._renderHooks.push( function () {
 				if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
 				${name}.run( true, function () {
 					${block.component}.fire( 'intro.end', { node: ${state.name} });
 				});
 			});
-		` );
+		`);
 
-		block.builders.outro.addBlock( deindent`
+		block.builders.outro.addBlock(deindent`
 			${name}.run( false, function () {
 				${block.component}.fire( 'outro.end', { node: ${state.name} });
-				if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
+				if ( --${block.alias('outros')} === 0 ) ${block.alias('outrocallback')}();
 				${name} = null;
 			});
-		` );
-	}
-
-	else {
-		const introName = intro && block.getUniqueName( `${state.name}_intro` );
-		const outroName = outro && block.getUniqueName( `${state.name}_outro` );
+		`);
+	} else {
+		const introName = intro && block.getUniqueName(`${state.name}_intro`);
+		const outroName = outro && block.getUniqueName(`${state.name}_outro`);
 
-		if ( intro ) {
-			block.addVariable( introName );
-			const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
+		if (intro) {
+			block.addVariable(introName);
+			const snippet = intro.expression
+				? block.contextualise(intro.expression).snippet
+				: '{}';
 
-			const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`; // TODO add built-in transitions?
+			const fn = `${generator.alias('template')}.transitions.${intro.name}`; // TODO add built-in transitions?
 
-			if ( outro ) {
-				block.builders.intro.addBlock( deindent`
+			if (outro) {
+				block.builders.intro.addBlock(deindent`
 					if ( ${introName} ) ${introName}.abort();
 					if ( ${outroName} ) ${outroName}.abort();
-				` );
+				`);
 			}
 
-			block.builders.intro.addBlock( deindent`
+			block.builders.intro.addBlock(deindent`
 				${block.component}._renderHooks.push( function () {
 					${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
 					${introName}.run( true, function () {
 						${block.component}.fire( 'intro.end', { node: ${state.name} });
 					});
 				});
-			` );
+			`);
 		}
 
-		if ( outro ) {
-			block.addVariable( outroName );
-			const snippet = outro.expression ? block.contextualise( outro.expression ).snippet : '{}';
+		if (outro) {
+			block.addVariable(outroName);
+			const snippet = outro.expression
+				? block.contextualise(outro.expression).snippet
+				: '{}';
 
-			const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
+			const fn = `${generator.alias('template')}.transitions.${outro.name}`;
 
 			// TODO hide elements that have outro'd (unless they belong to a still-outroing
 			// group) prior to their removal from the DOM
-			block.builders.outro.addBlock( deindent`
+			block.builders.outro.addBlock(deindent`
 				${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
 				${outroName}.run( false, function () {
 					${block.component}.fire( 'outro.end', { node: ${state.name} });
-					if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
+					if ( --${block.alias('outros')} === 0 ) ${block.alias('outrocallback')}();
 				});
-			` );
+			`);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Element/getStaticAttributeValue.ts b/src/generators/dom/visitors/Element/getStaticAttributeValue.ts
index bc24de7d2f..42b5ea6ce9 100644
--- a/src/generators/dom/visitors/Element/getStaticAttributeValue.ts
+++ b/src/generators/dom/visitors/Element/getStaticAttributeValue.ts
@@ -1,13 +1,15 @@
 import { Node } from '../../../../interfaces';
 
-export default function getStaticAttributeValue ( node: Node, name: string ) {
-	const attribute = node.attributes.find( ( attr: Node ) => attr.name.toLowerCase() === name );
-	if ( !attribute ) return null;
+export default function getStaticAttributeValue(node: Node, name: string) {
+	const attribute = node.attributes.find(
+		(attr: Node) => attr.name.toLowerCase() === name
+	);
+	if (!attribute) return null;
 
-	if ( attribute.value.length !== 1 || attribute.value[0].type !== 'Text' ) {
+	if (attribute.value.length !== 1 || attribute.value[0].type !== 'Text') {
 		// TODO catch this in validation phase, give a more useful error (with location etc)
-		throw new Error( `'${name} must be a static attribute` );
+		throw new Error(`'${name} must be a static attribute`);
 	}
 
 	return attribute.value[0].data;
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Element/lookup.ts b/src/generators/dom/visitors/Element/lookup.ts
index de48507fea..5b9a42e0f1 100644
--- a/src/generators/dom/visitors/Element/lookup.ts
+++ b/src/generators/dom/visitors/Element/lookup.ts
@@ -1,122 +1,235 @@
 // source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
 const lookup = {
-	accept: { appliesTo: [ 'form', 'input' ] },
-	'accept-charset': { propertyName: 'acceptCharset', appliesTo: [ 'form' ] },
+	accept: { appliesTo: ['form', 'input'] },
+	'accept-charset': { propertyName: 'acceptCharset', appliesTo: ['form'] },
 	accesskey: { propertyName: 'accessKey' },
-	action: { appliesTo: [ 'form' ] },
-	align: { appliesTo: [ 'applet', 'caption', 'col', 'colgroup', 'hr', 'iframe', 'img', 'table', 'tbody', 'td', 'tfoot' , 'th', 'thead', 'tr' ] },
-	allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: [ 'iframe' ] },
-	alt: { appliesTo: [ 'applet', 'area', 'img', 'input' ] },
-	async: { appliesTo: [ 'script' ] },
-	autocomplete: { appliesTo: [ 'form', 'input' ] },
-	autofocus: { appliesTo: [ 'button', 'input', 'keygen', 'select', 'textarea' ] },
-	autoplay: { appliesTo: [ 'audio', 'video' ] },
-	autosave: { appliesTo: [ 'input' ] },
-	bgcolor: { propertyName: 'bgColor', appliesTo: [ 'body', 'col', 'colgroup', 'marquee', 'table', 'tbody', 'tfoot', 'td', 'th', 'tr' ] },
-	border: { appliesTo: [ 'img', 'object', 'table' ] },
-	buffered: { appliesTo: [ 'audio', 'video' ] },
-	challenge: { appliesTo: [ 'keygen' ] },
-	charset: { appliesTo: [ 'meta', 'script' ] },
-	checked: { appliesTo: [ 'command', 'input' ] },
-	cite: { appliesTo: [ 'blockquote', 'del', 'ins', 'q' ] },
+	action: { appliesTo: ['form'] },
+	align: {
+		appliesTo: [
+			'applet',
+			'caption',
+			'col',
+			'colgroup',
+			'hr',
+			'iframe',
+			'img',
+			'table',
+			'tbody',
+			'td',
+			'tfoot',
+			'th',
+			'thead',
+			'tr'
+		]
+	},
+	allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: ['iframe'] },
+	alt: { appliesTo: ['applet', 'area', 'img', 'input'] },
+	async: { appliesTo: ['script'] },
+	autocomplete: { appliesTo: ['form', 'input'] },
+	autofocus: { appliesTo: ['button', 'input', 'keygen', 'select', 'textarea'] },
+	autoplay: { appliesTo: ['audio', 'video'] },
+	autosave: { appliesTo: ['input'] },
+	bgcolor: {
+		propertyName: 'bgColor',
+		appliesTo: [
+			'body',
+			'col',
+			'colgroup',
+			'marquee',
+			'table',
+			'tbody',
+			'tfoot',
+			'td',
+			'th',
+			'tr'
+		]
+	},
+	border: { appliesTo: ['img', 'object', 'table'] },
+	buffered: { appliesTo: ['audio', 'video'] },
+	challenge: { appliesTo: ['keygen'] },
+	charset: { appliesTo: ['meta', 'script'] },
+	checked: { appliesTo: ['command', 'input'] },
+	cite: { appliesTo: ['blockquote', 'del', 'ins', 'q'] },
 	class: { propertyName: 'className' },
-	code: { appliesTo: [ 'applet' ] },
-	codebase: { propertyName: 'codeBase', appliesTo: [ 'applet' ] },
-	color: { appliesTo: [ 'basefont', 'font', 'hr' ] },
-	cols: { appliesTo: [ 'textarea' ] },
-	colspan: { propertyName: 'colSpan', appliesTo: [ 'td', 'th' ] },
-	content: { appliesTo: [ 'meta' ] },
+	code: { appliesTo: ['applet'] },
+	codebase: { propertyName: 'codeBase', appliesTo: ['applet'] },
+	color: { appliesTo: ['basefont', 'font', 'hr'] },
+	cols: { appliesTo: ['textarea'] },
+	colspan: { propertyName: 'colSpan', appliesTo: ['td', 'th'] },
+	content: { appliesTo: ['meta'] },
 	contenteditable: { propertyName: 'contentEditable' },
 	contextmenu: {},
-	controls: { appliesTo: [ 'audio', 'video' ] },
-	coords: { appliesTo: [ 'area' ] },
-	data: { appliesTo: [ 'object' ] },
-	datetime: { propertyName: 'dateTime', appliesTo: [ 'del', 'ins', 'time' ] },
-	default: { appliesTo: [ 'track' ] },
-	defer: { appliesTo: [ 'script' ] },
+	controls: { appliesTo: ['audio', 'video'] },
+	coords: { appliesTo: ['area'] },
+	data: { appliesTo: ['object'] },
+	datetime: { propertyName: 'dateTime', appliesTo: ['del', 'ins', 'time'] },
+	default: { appliesTo: ['track'] },
+	defer: { appliesTo: ['script'] },
 	dir: {},
-	dirname: { propertyName: 'dirName', appliesTo: [ 'input', 'textarea' ] },
-	disabled: { appliesTo: [ 'button', 'command', 'fieldset', 'input', 'keygen', 'optgroup', 'option', 'select', 'textarea' ] },
-	download: { appliesTo: [ 'a', 'area' ] },
+	dirname: { propertyName: 'dirName', appliesTo: ['input', 'textarea'] },
+	disabled: {
+		appliesTo: [
+			'button',
+			'command',
+			'fieldset',
+			'input',
+			'keygen',
+			'optgroup',
+			'option',
+			'select',
+			'textarea'
+		]
+	},
+	download: { appliesTo: ['a', 'area'] },
 	draggable: {},
 	dropzone: {},
-	enctype: { appliesTo: [ 'form' ] },
-	for: { propertyName: 'htmlFor', appliesTo: [ 'label', 'output' ] },
-	form: { appliesTo: [ 'button', 'fieldset', 'input', 'keygen', 'label', 'meter', 'object', 'output', 'progress', 'select', 'textarea' ] },
-	formaction: { appliesTo: [ 'input', 'button' ] },
-	headers: { appliesTo: [ 'td', 'th' ] },
-	height: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
+	enctype: { appliesTo: ['form'] },
+	for: { propertyName: 'htmlFor', appliesTo: ['label', 'output'] },
+	form: {
+		appliesTo: [
+			'button',
+			'fieldset',
+			'input',
+			'keygen',
+			'label',
+			'meter',
+			'object',
+			'output',
+			'progress',
+			'select',
+			'textarea'
+		]
+	},
+	formaction: { appliesTo: ['input', 'button'] },
+	headers: { appliesTo: ['td', 'th'] },
+	height: {
+		appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video']
+	},
 	hidden: {},
-	high: { appliesTo: [ 'meter' ] },
-	href: { appliesTo: [ 'a', 'area', 'base', 'link' ] },
-	hreflang: { appliesTo: [ 'a', 'area', 'link' ] },
-	'http-equiv': { propertyName: 'httpEquiv', appliesTo: [ 'meta' ] },
-	icon: { appliesTo: [ 'command' ] },
+	high: { appliesTo: ['meter'] },
+	href: { appliesTo: ['a', 'area', 'base', 'link'] },
+	hreflang: { appliesTo: ['a', 'area', 'link'] },
+	'http-equiv': { propertyName: 'httpEquiv', appliesTo: ['meta'] },
+	icon: { appliesTo: ['command'] },
 	id: {},
-	ismap: { propertyName: 'isMap', appliesTo: [ 'img' ] },
+	ismap: { propertyName: 'isMap', appliesTo: ['img'] },
 	itemprop: {},
-	keytype: { appliesTo: [ 'keygen' ] },
-	kind: { appliesTo: [ 'track' ] },
-	label: { appliesTo: [ 'track' ] },
+	keytype: { appliesTo: ['keygen'] },
+	kind: { appliesTo: ['track'] },
+	label: { appliesTo: ['track'] },
 	lang: {},
-	language: { appliesTo: [ 'script' ] },
-	loop: { appliesTo: [ 'audio', 'bgsound', 'marquee', 'video' ] },
-	low: { appliesTo: [ 'meter' ] },
-	manifest: { appliesTo: [ 'html' ] },
-	max: { appliesTo: [ 'input', 'meter', 'progress' ] },
-	maxlength: { propertyName: 'maxLength', appliesTo: [ 'input', 'textarea' ] },
-	media: { appliesTo: [ 'a', 'area', 'link', 'source', 'style' ] },
-	method: { appliesTo: [ 'form' ] },
-	min: { appliesTo: [ 'input', 'meter' ] },
-	multiple: { appliesTo: [ 'input', 'select' ] },
-	muted: { appliesTo: [ 'video' ] },
-	name: { appliesTo: [ 'button', 'form', 'fieldset', 'iframe', 'input', 'keygen', 'object', 'output', 'select', 'textarea', 'map', 'meta', 'param' ] },
-	novalidate: { propertyName: 'noValidate', appliesTo: [ 'form' ] },
-	open: { appliesTo: [ 'details' ] },
-	optimum: { appliesTo: [ 'meter' ] },
-	pattern: { appliesTo: [ 'input' ] },
-	ping: { appliesTo: [ 'a', 'area' ] },
-	placeholder: { appliesTo: [ 'input', 'textarea' ] },
-	poster: { appliesTo: [ 'video' ] },
-	preload: { appliesTo: [ 'audio', 'video' ] },
-	radiogroup: { appliesTo: [ 'command' ] },
-	readonly: { propertyName: 'readOnly', appliesTo: [ 'input', 'textarea' ] },
-	rel: { appliesTo: [ 'a', 'area', 'link' ] },
-	required: { appliesTo: [ 'input', 'select', 'textarea' ] },
-	reversed: { appliesTo: [ 'ol' ] },
-	rows: { appliesTo: [ 'textarea' ] },
-	rowspan: { propertyName: 'rowSpan', appliesTo: [ 'td', 'th' ] },
-	sandbox: { appliesTo: [ 'iframe' ] },
-	scope: { appliesTo: [ 'th' ] },
-	scoped: { appliesTo: [ 'style' ] },
-	seamless: { appliesTo: [ 'iframe' ] },
-	selected: { appliesTo: [ 'option' ] },
-	shape: { appliesTo: [ 'a', 'area' ] },
-	size: { appliesTo: [ 'input', 'select' ] },
-	sizes: { appliesTo: [ 'link', 'img', 'source' ] },
-	span: { appliesTo: [ 'col', 'colgroup' ] },
+	language: { appliesTo: ['script'] },
+	loop: { appliesTo: ['audio', 'bgsound', 'marquee', 'video'] },
+	low: { appliesTo: ['meter'] },
+	manifest: { appliesTo: ['html'] },
+	max: { appliesTo: ['input', 'meter', 'progress'] },
+	maxlength: { propertyName: 'maxLength', appliesTo: ['input', 'textarea'] },
+	media: { appliesTo: ['a', 'area', 'link', 'source', 'style'] },
+	method: { appliesTo: ['form'] },
+	min: { appliesTo: ['input', 'meter'] },
+	multiple: { appliesTo: ['input', 'select'] },
+	muted: { appliesTo: ['video'] },
+	name: {
+		appliesTo: [
+			'button',
+			'form',
+			'fieldset',
+			'iframe',
+			'input',
+			'keygen',
+			'object',
+			'output',
+			'select',
+			'textarea',
+			'map',
+			'meta',
+			'param'
+		]
+	},
+	novalidate: { propertyName: 'noValidate', appliesTo: ['form'] },
+	open: { appliesTo: ['details'] },
+	optimum: { appliesTo: ['meter'] },
+	pattern: { appliesTo: ['input'] },
+	ping: { appliesTo: ['a', 'area'] },
+	placeholder: { appliesTo: ['input', 'textarea'] },
+	poster: { appliesTo: ['video'] },
+	preload: { appliesTo: ['audio', 'video'] },
+	radiogroup: { appliesTo: ['command'] },
+	readonly: { propertyName: 'readOnly', appliesTo: ['input', 'textarea'] },
+	rel: { appliesTo: ['a', 'area', 'link'] },
+	required: { appliesTo: ['input', 'select', 'textarea'] },
+	reversed: { appliesTo: ['ol'] },
+	rows: { appliesTo: ['textarea'] },
+	rowspan: { propertyName: 'rowSpan', appliesTo: ['td', 'th'] },
+	sandbox: { appliesTo: ['iframe'] },
+	scope: { appliesTo: ['th'] },
+	scoped: { appliesTo: ['style'] },
+	seamless: { appliesTo: ['iframe'] },
+	selected: { appliesTo: ['option'] },
+	shape: { appliesTo: ['a', 'area'] },
+	size: { appliesTo: ['input', 'select'] },
+	sizes: { appliesTo: ['link', 'img', 'source'] },
+	span: { appliesTo: ['col', 'colgroup'] },
 	spellcheck: {},
-	src: { appliesTo: [ 'audio', 'embed', 'iframe', 'img', 'input', 'script', 'source', 'track', 'video' ] },
-	srcdoc: { appliesTo: [ 'iframe' ] },
-	srclang: { appliesTo: [ 'track' ] },
-	srcset: { appliesTo: [ 'img' ] },
-	start: { appliesTo: [ 'ol' ] },
-	step: { appliesTo: [ 'input' ] },
+	src: {
+		appliesTo: [
+			'audio',
+			'embed',
+			'iframe',
+			'img',
+			'input',
+			'script',
+			'source',
+			'track',
+			'video'
+		]
+	},
+	srcdoc: { appliesTo: ['iframe'] },
+	srclang: { appliesTo: ['track'] },
+	srcset: { appliesTo: ['img'] },
+	start: { appliesTo: ['ol'] },
+	step: { appliesTo: ['input'] },
 	style: { propertyName: 'style.cssText' },
-	summary: { appliesTo: [ 'table' ] },
+	summary: { appliesTo: ['table'] },
 	tabindex: { propertyName: 'tabIndex' },
-	target: { appliesTo: [ 'a', 'area', 'base', 'form' ] },
+	target: { appliesTo: ['a', 'area', 'base', 'form'] },
 	title: {},
-	type: { appliesTo: [ 'button', 'input', 'command', 'embed', 'object', 'script', 'source', 'style', 'menu' ] },
-	usemap: { propertyName: 'useMap', appliesTo: [ 'img', 'input', 'object' ] },
-	value: { appliesTo: [ 'button', 'option', 'input', 'li', 'meter', 'progress', 'param', 'select', 'textarea' ] },
-	width: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
-	wrap: { appliesTo: [ 'textarea' ] }
+	type: {
+		appliesTo: [
+			'button',
+			'input',
+			'command',
+			'embed',
+			'object',
+			'script',
+			'source',
+			'style',
+			'menu'
+		]
+	},
+	usemap: { propertyName: 'useMap', appliesTo: ['img', 'input', 'object'] },
+	value: {
+		appliesTo: [
+			'button',
+			'option',
+			'input',
+			'li',
+			'meter',
+			'progress',
+			'param',
+			'select',
+			'textarea'
+		]
+	},
+	width: {
+		appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video']
+	},
+	wrap: { appliesTo: ['textarea'] }
 };
 
-Object.keys( lookup ).forEach( name => {
-	const metadata = lookup[ name ];
-	if ( !metadata.propertyName ) metadata.propertyName = name;
+Object.keys(lookup).forEach(name => {
+	const metadata = lookup[name];
+	if (!metadata.propertyName) metadata.propertyName = name;
 });
 
 export default lookup;
diff --git a/src/generators/dom/visitors/Element/meta/Window.ts b/src/generators/dom/visitors/Element/meta/Window.ts
index bdf2231bff..68df181635 100644
--- a/src/generators/dom/visitors/Element/meta/Window.ts
+++ b/src/generators/dom/visitors/Element/meta/Window.ts
@@ -22,65 +22,74 @@ const readonly = new Set([
 	'online'
 ]);
 
-export default function visitWindow ( generator: DomGenerator, block: Block, node: Node ) {
+export default function visitWindow(
+	generator: DomGenerator,
+	block: Block,
+	node: Node
+) {
 	const events = {};
 	const bindings = {};
 
-	node.attributes.forEach( ( attribute: Node ) => {
-		if ( attribute.type === 'EventHandler' ) {
+	node.attributes.forEach((attribute: Node) => {
+		if (attribute.type === 'EventHandler') {
 			// TODO verify that it's a valid callee (i.e. built-in or declared method)
-			generator.addSourcemapLocations( attribute.expression );
+			generator.addSourcemapLocations(attribute.expression);
 
 			let usesState = false;
 
-			attribute.expression.arguments.forEach( ( arg: Node ) => {
-				const { contexts } = block.contextualise( arg, null, true );
-				if ( contexts.length ) usesState = true;
+			attribute.expression.arguments.forEach((arg: Node) => {
+				const { contexts } = block.contextualise(arg, null, true);
+				if (contexts.length) usesState = true;
 			});
 
-			const flattened = flattenReference( attribute.expression.callee );
-			if ( flattened.name !== 'event' && flattened.name !== 'this' ) {
+			const flattened = flattenReference(attribute.expression.callee);
+			if (flattened.name !== 'event' && flattened.name !== 'this') {
 				// allow event.stopPropagation(), this.select() etc
-				generator.code.prependRight( attribute.expression.start, `${block.component}.` );
+				generator.code.prependRight(
+					attribute.expression.start,
+					`${block.component}.`
+				);
 			}
 
-			const handlerName = block.getUniqueName( `onwindow${attribute.name}` );
+			const handlerName = block.getUniqueName(`onwindow${attribute.name}`);
 			const handlerBody = deindent`
 				${usesState && `var state = ${block.component}.get();`}
 				[✂${attribute.expression.start}-${attribute.expression.end}✂];
 			`;
 
-			block.builders.create.addBlock( deindent`
+			block.builders.create.addBlock(deindent`
 				function ${handlerName} ( event ) {
 					${handlerBody}
 				};
 				window.addEventListener( '${attribute.name}', ${handlerName} );
-			` );
+			`);
 
-			block.builders.destroy.addBlock( deindent`
+			block.builders.destroy.addBlock(deindent`
 				window.removeEventListener( '${attribute.name}', ${handlerName} );
-			` );
+			`);
 		}
 
-		if ( attribute.type === 'Binding' ) {
+		if (attribute.type === 'Binding') {
 			// in dev mode, throw if read-only values are written to
-			if ( readonly.has( attribute.name ) ) {
-				generator.readonly.add( attribute.value.name );
+			if (readonly.has(attribute.name)) {
+				generator.readonly.add(attribute.value.name);
 			}
 
-			bindings[ attribute.name ] = attribute.value.name;
+			bindings[attribute.name] = attribute.value.name;
 
 			// bind:online is a special case, we need to listen for two separate events
-			if ( attribute.name === 'online' ) return;
+			if (attribute.name === 'online') return;
 
-			const associatedEvent = associatedEvents[ attribute.name ];
+			const associatedEvent = associatedEvents[attribute.name];
 
-			if ( !associatedEvent ) {
-				throw new Error( `Cannot bind to ${attribute.name} on <:Window>` );
+			if (!associatedEvent) {
+				throw new Error(`Cannot bind to ${attribute.name} on <:Window>`);
 			}
 
-			if ( !events[ associatedEvent ] ) events[ associatedEvent ] = [];
-			events[ associatedEvent ].push( `${attribute.value.name}: this.${attribute.name}` );
+			if (!events[associatedEvent]) events[associatedEvent] = [];
+			events[associatedEvent].push(
+				`${attribute.value.name}: this.${attribute.name}`
+			);
 
 			// add initial value
 			generator.metaBindings.push(
@@ -89,14 +98,15 @@ export default function visitWindow ( generator: DomGenerator, block: Block, nod
 		}
 	});
 
-	const lock = block.getUniqueName( `window_updating` );
+	const lock = block.getUniqueName(`window_updating`);
 
-	Object.keys( events ).forEach( event => {
-		const handlerName = block.getUniqueName( `onwindow${event}` );
-		const props = events[ event ].join( ',\n' );
+	Object.keys(events).forEach(event => {
+		const handlerName = block.getUniqueName(`onwindow${event}`);
+		const props = events[event].join(',\n');
 
-		if ( event === 'scroll' ) { // TODO other bidirectional bindings...
-			block.addVariable( lock, 'false' );
+		if (event === 'scroll') {
+			// TODO other bidirectional bindings...
+			block.addVariable(lock, 'false');
 		}
 
 		const handlerBody = deindent`
@@ -111,63 +121,74 @@ export default function visitWindow ( generator: DomGenerator, block: Block, nod
 			${event === 'scroll' && `${lock} = false;`}
 		`;
 
-		block.builders.create.addBlock( deindent`
+		block.builders.create.addBlock(deindent`
 			function ${handlerName} ( event ) {
 				${handlerBody}
 			};
 			window.addEventListener( '${event}', ${handlerName} );
-		` );
+		`);
 
-		block.builders.destroy.addBlock( deindent`
+		block.builders.destroy.addBlock(deindent`
 			window.removeEventListener( '${event}', ${handlerName} );
-		` );
+		`);
 	});
 
 	// special case... might need to abstract this out if we add more special cases
-	if ( bindings.scrollX && bindings.scrollY ) {
-		const observerCallback = block.getUniqueName( `scrollobserver` );
+	if (bindings.scrollX && bindings.scrollY) {
+		const observerCallback = block.getUniqueName(`scrollobserver`);
 
-		block.builders.create.addBlock( deindent`
+		block.builders.create.addBlock(deindent`
 			function ${observerCallback} () {
 				if ( ${lock} ) return;
-				var x = ${bindings.scrollX ? `${block.component}.get( '${bindings.scrollX}' )` : `window.scrollX`};
-				var y = ${bindings.scrollY ? `${block.component}.get( '${bindings.scrollY}' )` : `window.scrollY`};
+				var x = ${bindings.scrollX
+					? `${block.component}.get( '${bindings.scrollX}' )`
+					: `window.scrollX`};
+				var y = ${bindings.scrollY
+					? `${block.component}.get( '${bindings.scrollY}' )`
+					: `window.scrollY`};
 				window.scrollTo( x, y );
 			};
-		` );
+		`);
 
-		if ( bindings.scrollX ) block.builders.create.addLine( `${block.component}.observe( '${bindings.scrollX}', ${observerCallback} );` );
-		if ( bindings.scrollY ) block.builders.create.addLine( `${block.component}.observe( '${bindings.scrollY}', ${observerCallback} );` );
-	} else if ( bindings.scrollX || bindings.scrollY ) {
+		if (bindings.scrollX)
+			block.builders.create.addLine(
+				`${block.component}.observe( '${bindings.scrollX}', ${observerCallback} );`
+			);
+		if (bindings.scrollY)
+			block.builders.create.addLine(
+				`${block.component}.observe( '${bindings.scrollY}', ${observerCallback} );`
+			);
+	} else if (bindings.scrollX || bindings.scrollY) {
 		const isX = !!bindings.scrollX;
 
-		block.builders.create.addBlock( deindent`
-			${block.component}.observe( '${bindings.scrollX || bindings.scrollY}', function ( ${isX ? 'x' : 'y'} ) {
+		block.builders.create.addBlock(deindent`
+			${block.component}.observe( '${bindings.scrollX ||
+			bindings.scrollY}', function ( ${isX ? 'x' : 'y'} ) {
 				if ( ${lock} ) return;
-				window.scrollTo( ${isX ? 'x, window.scrollY' : 'window.scrollX, y' } );
+				window.scrollTo( ${isX ? 'x, window.scrollY' : 'window.scrollX, y'} );
 			});
-		` );
+		`);
 	}
 
 	// another special case. (I'm starting to think these are all special cases.)
-	if ( bindings.online ) {
-		const handlerName = block.getUniqueName( `onlinestatuschanged` );
-		block.builders.create.addBlock( deindent`
+	if (bindings.online) {
+		const handlerName = block.getUniqueName(`onlinestatuschanged`);
+		block.builders.create.addBlock(deindent`
 			function ${handlerName} ( event ) {
 				${block.component}.set({ ${bindings.online}: navigator.onLine });
 			};
 			window.addEventListener( 'online', ${handlerName} );
 			window.addEventListener( 'offline', ${handlerName} );
-		` );
+		`);
 
 		// add initial value
 		generator.metaBindings.push(
 			`this._state.${bindings.online} = navigator.onLine;`
 		);
 
-		block.builders.destroy.addBlock( deindent`
+		block.builders.destroy.addBlock(deindent`
 			window.removeEventListener( 'online', ${handlerName} );
 			window.removeEventListener( 'offline', ${handlerName} );
-		` );
+		`);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/IfBlock.ts b/src/generators/dom/visitors/IfBlock.ts
index 48e7b3b145..dbb40b67f4 100644
--- a/src/generators/dom/visitors/IfBlock.ts
+++ b/src/generators/dom/visitors/IfBlock.ts
@@ -5,28 +5,37 @@ import Block from '../Block';
 import { Node } from '../../../interfaces';
 import { State } from '../interfaces';
 
-function isElseIf ( node: Node ) {
-	return node && node.children.length === 1 && node.children[0].type === 'IfBlock';
+function isElseIf(node: Node) {
+	return (
+		node && node.children.length === 1 && node.children[0].type === 'IfBlock'
+	);
 }
 
-function isElseBranch ( branch ) {
+function isElseBranch(branch) {
 	return branch.block && !branch.condition;
 }
 
-function getBranches ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	const branches = [{
-		condition: block.contextualise( node.expression ).snippet,
-		block: node._block.name,
-		hasUpdateMethod: node._block.hasUpdateMethod,
-		hasIntroMethod: node._block.hasIntroMethod,
-		hasOutroMethod: node._block.hasOutroMethod
-	}];
+function getBranches(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	const branches = [
+		{
+			condition: block.contextualise(node.expression).snippet,
+			block: node._block.name,
+			hasUpdateMethod: node._block.hasUpdateMethod,
+			hasIntroMethod: node._block.hasIntroMethod,
+			hasOutroMethod: node._block.hasOutroMethod
+		}
+	];
 
-	visitChildren( generator, block, state, node );
+	visitChildren(generator, block, state, node);
 
-	if ( isElseIf( node.else ) ) {
+	if (isElseIf(node.else)) {
 		branches.push(
-			...getBranches( generator, block, state, node.else.children[0] )
+			...getBranches(generator, block, state, node.else.children[0])
 		);
 	} else {
 		branches.push({
@@ -37,28 +46,40 @@ function getBranches ( generator: DomGenerator, block: Block, state: State, node
 			hasOutroMethod: node.else ? node.else._block.hasOutroMethod : false
 		});
 
-		if ( node.else ) {
-			visitChildren( generator, block, state, node.else );
+		if (node.else) {
+			visitChildren(generator, block, state, node.else);
 		}
 	}
 
 	return branches;
 }
 
-function visitChildren ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, node._block, node._state, child );
+function visitChildren(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	node.children.forEach((child: Node) => {
+		visit(generator, node._block, node._state, child);
 	});
 }
 
-export default function visitIfBlock ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	const name = generator.getUniqueName( `if_block` );
-	const anchor = node.needsAnchor ? block.getUniqueName( `${name}_anchor` ) : ( node.next && node.next._state.name ) || 'null';
-	const params = block.params.join( ', ' );
-
-	const branches = getBranches( generator, block, state, node );
-
-	const hasElse = isElseBranch( branches[ branches.length - 1 ] );
+export default function visitIfBlock(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	const name = generator.getUniqueName(`if_block`);
+	const anchor = node.needsAnchor
+		? block.getUniqueName(`${name}_anchor`)
+		: (node.next && node.next._state.name) || 'null';
+	const params = block.params.join(', ');
+
+	const branches = getBranches(generator, block, state, node);
+
+	const hasElse = isElseBranch(branches[branches.length - 1]);
 	const if_name = hasElse ? '' : `if ( ${name} ) `;
 
 	const dynamic = branches[0].hasUpdateMethod; // can use [0] as proxy for all, since they necessarily have the same value
@@ -66,42 +87,67 @@ export default function visitIfBlock ( generator: DomGenerator, block: Block, st
 
 	const vars = { name, anchor, params, if_name, hasElse };
 
-	if ( node.else ) {
-		if ( hasOutros ) {
-			compoundWithOutros( generator, block, state, node, branches, dynamic, vars );
+	if (node.else) {
+		if (hasOutros) {
+			compoundWithOutros(
+				generator,
+				block,
+				state,
+				node,
+				branches,
+				dynamic,
+				vars
+			);
 		} else {
-			compound( generator, block, state, node, branches, dynamic, vars );
+			compound(generator, block, state, node, branches, dynamic, vars);
 		}
 	} else {
-		simple( generator, block, state, node, branches[0], dynamic, vars );
+		simple(generator, block, state, node, branches[0], dynamic, vars);
 	}
 
-	if ( node.needsAnchor ) {
-		block.addElement( anchor, `${generator.helper( 'createComment' )}()`, state.parentNode, true );
-	} else if ( node.next ) {
+	if (node.needsAnchor) {
+		block.addElement(
+			anchor,
+			`${generator.helper('createComment')}()`,
+			state.parentNode,
+			true
+		);
+	} else if (node.next) {
 		node.next.usedAsAnchor = true;
 	}
 }
 
-function simple ( generator: DomGenerator, block: Block, state: State, node: Node, branch, dynamic, { name, anchor, params, if_name } ) {
-	block.builders.create.addBlock( deindent`
+function simple(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	branch,
+	dynamic,
+	{ name, anchor, params, if_name }
+) {
+	block.builders.create.addBlock(deindent`
 		var ${name} = (${branch.condition}) && ${branch.block}( ${params}, ${block.component} );
-	` );
+	`);
 
 	const isTopLevel = !state.parentNode;
 	const mountOrIntro = branch.hasIntroMethod ? 'intro' : 'mount';
 
-	if ( isTopLevel ) {
-		block.builders.mount.addLine( `if ( ${name} ) ${name}.${mountOrIntro}( ${block.target}, anchor );` );
+	if (isTopLevel) {
+		block.builders.mount.addLine(
+			`if ( ${name} ) ${name}.${mountOrIntro}( ${block.target}, anchor );`
+		);
 	} else {
-		block.builders.create.addLine( `if ( ${name} ) ${name}.${mountOrIntro}( ${state.parentNode}, null );` );
+		block.builders.create.addLine(
+			`if ( ${name} ) ${name}.${mountOrIntro}( ${state.parentNode}, null );`
+		);
 	}
 
 	const parentNode = state.parentNode || `${anchor}.parentNode`;
 
-	const enter = dynamic ?
-		( branch.hasIntroMethod ?
-			deindent`
+	const enter = dynamic
+		? branch.hasIntroMethod
+			? deindent`
 				if ( ${name} ) {
 					${name}.update( changed, ${params} );
 				} else {
@@ -109,83 +155,93 @@ function simple ( generator: DomGenerator, block: Block, state: State, node: Nod
 				}
 
 				${name}.intro( ${parentNode}, ${anchor} );
-			` :
-			deindent`
+			`
+			: deindent`
 				if ( ${name} ) {
 					${name}.update( changed, ${params} );
 				} else {
 					${name} = ${branch.block}( ${params}, ${block.component} );
 					${name}.mount( ${parentNode}, ${anchor} );
 				}
-			` ) :
-		( branch.hasIntroMethod ?
-			deindent`
+			`
+		: branch.hasIntroMethod
+			? deindent`
 				if ( !${name} ) ${name} = ${branch.block}( ${params}, ${block.component} );
 				${name}.intro( ${parentNode}, ${anchor} );
-			` :
-			deindent`
+			`
+			: deindent`
 				if ( !${name} ) {
 					${name} = ${branch.block}( ${params}, ${block.component} );
 					${name}.mount( ${parentNode}, ${anchor} );
 				}
-			` );
+			`;
 
 	// no `update()` here — we don't want to update outroing nodes,
 	// as that will typically result in glitching
-	const exit = branch.hasOutroMethod ?
-		deindent`
+	const exit = branch.hasOutroMethod
+		? deindent`
 			${name}.outro( function () {
 				${name}.unmount();
 				${name}.destroy();
 				${name} = null;
 			});
-		` :
-		deindent`
+		`
+		: deindent`
 			${name}.unmount();
 			${name}.destroy();
 			${name} = null;
 		`;
 
-	block.builders.update.addBlock( deindent`
+	block.builders.update.addBlock(deindent`
 		if ( ${branch.condition} ) {
 			${enter}
 		} else if ( ${name} ) {
 			${exit}
 		}
-	` );
+	`);
 
-	block.builders.unmount.addLine(
-		`${if_name}${name}.unmount();`
-	);
+	block.builders.unmount.addLine(`${if_name}${name}.unmount();`);
 
-	block.builders.destroy.addLine(
-		`${if_name}${name}.destroy();`
-	);
+	block.builders.destroy.addLine(`${if_name}${name}.destroy();`);
 }
 
-function compound ( generator: DomGenerator, block: Block, state: State, node: Node, branches, dynamic, { name, anchor, params, hasElse, if_name } ) {
-	const get_block = block.getUniqueName( `get_block` );
-	const current_block = block.getUniqueName( `current_block` );
+function compound(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	branches,
+	dynamic,
+	{ name, anchor, params, hasElse, if_name }
+) {
+	const get_block = block.getUniqueName(`get_block`);
+	const current_block = block.getUniqueName(`current_block`);
 	const current_block_and = hasElse ? '' : `${current_block} && `;
 
-	block.builders.create.addBlock( deindent`
+	block.builders.create.addBlock(deindent`
 		function ${get_block} ( ${params} ) {
-			${branches.map( ({ condition, block }) => {
-				return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
-			} ).join( '\n' )}
+			${branches
+				.map(({ condition, block }) => {
+					return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
+				})
+				.join('\n')}
 		}
 
 		var ${current_block} = ${get_block}( ${params} );
 		var ${name} = ${current_block_and}${current_block}( ${params}, ${block.component} );
-	` );
+	`);
 
 	const isTopLevel = !state.parentNode;
 	const mountOrIntro = branches[0].hasIntroMethod ? 'intro' : 'mount';
 
-	if ( isTopLevel ) {
-		block.builders.mount.addLine( `${if_name}${name}.${mountOrIntro}( ${block.target}, anchor );` );
+	if (isTopLevel) {
+		block.builders.mount.addLine(
+			`${if_name}${name}.${mountOrIntro}( ${block.target}, anchor );`
+		);
 	} else {
-		block.builders.create.addLine( `${if_name}${name}.${mountOrIntro}( ${state.parentNode}, null );` );
+		block.builders.create.addLine(
+			`${if_name}${name}.${mountOrIntro}( ${state.parentNode}, null );`
+		);
 	}
 
 	const parentNode = state.parentNode || `${anchor}.parentNode`;
@@ -199,20 +255,20 @@ function compound ( generator: DomGenerator, block: Block, state: State, node: N
 		${if_name}${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
 	`;
 
-	if ( dynamic ) {
-		block.builders.update.addBlock( deindent`
+	if (dynamic) {
+		block.builders.update.addBlock(deindent`
 			if ( ${current_block} === ( ${current_block} = ${get_block}( ${params} ) ) && ${name} ) {
 				${name}.update( changed, ${params} );
 			} else {
 				${changeBlock}
 			}
-		` );
+		`);
 	} else {
-		block.builders.update.addBlock( deindent`
+		block.builders.update.addBlock(deindent`
 			if ( ${current_block} !== ( ${current_block} = ${get_block}( ${params} ) ) ) {
 				${changeBlock}
 			}
-		` );
+		`);
 	}
 
 	block.builders.destroy.addLine(
@@ -225,52 +281,70 @@ function compound ( generator: DomGenerator, block: Block, state: State, node: N
 
 // if any of the siblings have outros, we need to keep references to the blocks
 // (TODO does this only apply to bidi transitions?)
-function compoundWithOutros ( generator: DomGenerator, block: Block, state: State, node: Node, branches, dynamic, { name, anchor, params, hasElse } ) {
-	const get_block = block.getUniqueName( `get_block` );
-	const current_block_index = block.getUniqueName( `current_block_index` );
-	const previous_block_index = block.getUniqueName( `previous_block_index` );
-	const if_block_creators = block.getUniqueName( `if_block_creators` );
-	const if_blocks = block.getUniqueName( `if_blocks` );
-
-	const if_current_block_index = hasElse ? '' : `if ( ~${current_block_index} ) `;
-
-	block.addVariable( current_block_index );
-	block.addVariable( name );
-
-	block.builders.create.addBlock( deindent`
+function compoundWithOutros(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node,
+	branches,
+	dynamic,
+	{ name, anchor, params, hasElse }
+) {
+	const get_block = block.getUniqueName(`get_block`);
+	const current_block_index = block.getUniqueName(`current_block_index`);
+	const previous_block_index = block.getUniqueName(`previous_block_index`);
+	const if_block_creators = block.getUniqueName(`if_block_creators`);
+	const if_blocks = block.getUniqueName(`if_blocks`);
+
+	const if_current_block_index = hasElse
+		? ''
+		: `if ( ~${current_block_index} ) `;
+
+	block.addVariable(current_block_index);
+	block.addVariable(name);
+
+	block.builders.create.addBlock(deindent`
 		var ${if_block_creators} = [
-			${branches.map( branch => branch.block ).join( ',\n' )}
+			${branches.map(branch => branch.block).join(',\n')}
 		];
 
 		var ${if_blocks} = [];
 
 		function ${get_block} ( ${params} ) {
-			${branches.map( ({ condition, block }, i ) => {
-				return `${condition ? `if ( ${condition} ) ` : ''}return ${block ? i : -1};`;
-			} ).join( '\n' )}
+			${branches
+				.map(({ condition, block }, i) => {
+					return `${condition ? `if ( ${condition} ) ` : ''}return ${block
+						? i
+						: -1};`;
+				})
+				.join('\n')}
 		}
-	` );
+	`);
 
-	if ( hasElse ) {
-		block.builders.create.addBlock( deindent`
+	if (hasElse) {
+		block.builders.create.addBlock(deindent`
 			${current_block_index} = ${get_block}( ${params} );
 			${name} = ${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
-		` );
+		`);
 	} else {
-		block.builders.create.addBlock( deindent`
+		block.builders.create.addBlock(deindent`
 			if ( ~( ${current_block_index} = ${get_block}( ${params} ) ) ) {
 				${name} = ${if_blocks}[ ${current_block_index} ] = ${if_block_creators}[ ${current_block_index} ]( ${params}, ${block.component} );
 			}
-		` );
+		`);
 	}
 
 	const isTopLevel = !state.parentNode;
 	const mountOrIntro = branches[0].hasIntroMethod ? 'intro' : 'mount';
 
-	if ( isTopLevel ) {
-		block.builders.mount.addLine( `${if_current_block_index}${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${block.target}, anchor );` );
+	if (isTopLevel) {
+		block.builders.mount.addLine(
+			`${if_current_block_index}${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${block.target}, anchor );`
+		);
 	} else {
-		block.builders.create.addLine( `${if_current_block_index}${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${state.parentNode}, null );` );
+		block.builders.create.addLine(
+			`${if_current_block_index}${if_blocks}[ ${current_block_index} ].${mountOrIntro}( ${state.parentNode}, null );`
+		);
 	}
 
 	const parentNode = state.parentNode || `${anchor}.parentNode`;
@@ -288,13 +362,13 @@ function compoundWithOutros ( generator: DomGenerator, block: Block, state: Stat
 		${name}.${mountOrIntro}( ${parentNode}, ${anchor} );
 	`;
 
-	const changeBlock = hasElse ?
-		deindent`
+	const changeBlock = hasElse
+		? deindent`
 			${destroyOldBlock}
 
 			${createNewBlock}
-		` :
-		deindent`
+		`
+		: deindent`
 			if ( ${name} ) {
 				${destroyOldBlock}
 			}
@@ -306,8 +380,8 @@ function compoundWithOutros ( generator: DomGenerator, block: Block, state: Stat
 			}
 		`;
 
-	if ( dynamic ) {
-		block.builders.update.addBlock( deindent`
+	if (dynamic) {
+		block.builders.update.addBlock(deindent`
 			var ${previous_block_index} = ${current_block_index};
 			${current_block_index} = ${get_block}( state );
 			if ( ${current_block_index} === ${previous_block_index} ) {
@@ -315,21 +389,21 @@ function compoundWithOutros ( generator: DomGenerator, block: Block, state: Stat
 			} else {
 				${changeBlock}
 			}
-		` );
+		`);
 	} else {
-		block.builders.update.addBlock( deindent`
+		block.builders.update.addBlock(deindent`
 			var ${previous_block_index} = ${current_block_index};
 			${current_block_index} = ${get_block}( state );
 			if ( ${current_block_index} !== ${previous_block_index} ) {
 				${changeBlock}
 			}
-		` );
+		`);
 	}
 
-	block.builders.destroy.addLine( deindent`
+	block.builders.destroy.addLine(deindent`
 		${if_current_block_index}{
 			${if_blocks}[ ${current_block_index} ].unmount();
 			${if_blocks}[ ${current_block_index} ].destroy();
 		}
-	` );
+	`);
 }
diff --git a/src/generators/dom/visitors/MustacheTag.ts b/src/generators/dom/visitors/MustacheTag.ts
index ed0f4c656b..21604778f5 100644
--- a/src/generators/dom/visitors/MustacheTag.ts
+++ b/src/generators/dom/visitors/MustacheTag.ts
@@ -4,18 +4,28 @@ import Block from '../Block';
 import { Node } from '../../../interfaces';
 import { State } from '../interfaces';
 
-export default function visitMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
+export default function visitMustacheTag(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
 	const name = node._state.name;
-	const value = block.getUniqueName( `${name}_value` );
+	const value = block.getUniqueName(`${name}_value`);
 
-	const { snippet } = block.contextualise( node.expression );
+	const { snippet } = block.contextualise(node.expression);
 
-	block.addVariable( value );
-	block.addElement( name, `${generator.helper( 'createText' )}( ${value} = ${snippet} )`, state.parentNode, true );
+	block.addVariable(value);
+	block.addElement(
+		name,
+		`${generator.helper('createText')}( ${value} = ${snippet} )`,
+		state.parentNode,
+		true
+	);
 
-	block.builders.update.addBlock( deindent`
+	block.builders.update.addBlock(deindent`
 		if ( ${value} !== ( ${value} = ${snippet} ) ) {
 			${name}.data = ${value};
 		}
-	` );
-}
\ No newline at end of file
+	`);
+}
diff --git a/src/generators/dom/visitors/RawMustacheTag.ts b/src/generators/dom/visitors/RawMustacheTag.ts
index a66c71f938..04c3c835d2 100644
--- a/src/generators/dom/visitors/RawMustacheTag.ts
+++ b/src/generators/dom/visitors/RawMustacheTag.ts
@@ -4,37 +4,54 @@ import Block from '../Block';
 import { Node } from '../../../interfaces';
 import { State } from '../interfaces';
 
-export default function visitRawMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
+export default function visitRawMustacheTag(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
 	const name = node._state.basename;
 	const before = node._state.name;
-	const value = block.getUniqueName( `${name}_value` );
-	const after = block.getUniqueName( `${name}_after` );
+	const value = block.getUniqueName(`${name}_value`);
+	const after = block.getUniqueName(`${name}_after`);
 
-	const { snippet } = block.contextualise( node.expression );
+	const { snippet } = block.contextualise(node.expression);
 
 	// we would have used comments here, but the `insertAdjacentHTML` api only
 	// exists for `Element`s.
-	block.addElement( before, `${generator.helper( 'createElement' )}( 'noscript' )`, state.parentNode, true );
-	block.addElement( after, `${generator.helper( 'createElement' )}( 'noscript' )`, state.parentNode, true );
+	block.addElement(
+		before,
+		`${generator.helper('createElement')}( 'noscript' )`,
+		state.parentNode,
+		true
+	);
+	block.addElement(
+		after,
+		`${generator.helper('createElement')}( 'noscript' )`,
+		state.parentNode,
+		true
+	);
 
 	const isToplevel = !state.parentNode;
 
-	block.builders.create.addLine( `var ${value} = ${snippet};` );
+	block.builders.create.addLine(`var ${value} = ${snippet};`);
 	const mountStatement = `${before}.insertAdjacentHTML( 'afterend', ${value} );`;
-	const detachStatement = `${generator.helper( 'detachBetween' )}( ${before}, ${after} );`;
+	const detachStatement = `${generator.helper(
+		'detachBetween'
+	)}( ${before}, ${after} );`;
 
-	if ( isToplevel ) {
-		block.builders.mount.addLine( mountStatement );
+	if (isToplevel) {
+		block.builders.mount.addLine(mountStatement);
 	} else {
-		block.builders.create.addLine( mountStatement );
+		block.builders.create.addLine(mountStatement);
 	}
 
-	block.builders.update.addBlock( deindent`
+	block.builders.update.addBlock(deindent`
 		if ( ${value} !== ( ${value} = ${snippet} ) ) {
 			${detachStatement}
 			${mountStatement}
 		}
-	` );
+	`);
 
-	block.builders.detachRaw.addBlock( detachStatement );
-}
\ No newline at end of file
+	block.builders.detachRaw.addBlock(detachStatement);
+}
diff --git a/src/generators/dom/visitors/Text.ts b/src/generators/dom/visitors/Text.ts
index d84ffefd68..b8a3850142 100644
--- a/src/generators/dom/visitors/Text.ts
+++ b/src/generators/dom/visitors/Text.ts
@@ -3,7 +3,17 @@ import Block from '../Block';
 import { Node } from '../../../interfaces';
 import { State } from '../interfaces';
 
-export default function visitText ( generator: DomGenerator, block: Block, state: State, node: Node ) {
-	if ( !node._state.shouldCreate ) return;
-	block.addElement( node._state.name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, state.parentNode, node.usedAsAnchor );
-}
\ No newline at end of file
+export default function visitText(
+	generator: DomGenerator,
+	block: Block,
+	state: State,
+	node: Node
+) {
+	if (!node._state.shouldCreate) return;
+	block.addElement(
+		node._state.name,
+		`${generator.helper('createText')}( ${JSON.stringify(node.data)} )`,
+		state.parentNode,
+		node.usedAsAnchor
+	);
+}
diff --git a/src/generators/dom/visitors/YieldTag.ts b/src/generators/dom/visitors/YieldTag.ts
index 5a665b041f..f3d7111941 100644
--- a/src/generators/dom/visitors/YieldTag.ts
+++ b/src/generators/dom/visitors/YieldTag.ts
@@ -2,14 +2,18 @@ import { DomGenerator } from '../index';
 import Block from '../Block';
 import { State } from '../interfaces';
 
-export default function visitYieldTag ( generator: DomGenerator, block: Block, state: State ) {
+export default function visitYieldTag(
+	generator: DomGenerator,
+	block: Block,
+	state: State
+) {
 	const parentNode = state.parentNode || block.target;
 
-	( state.parentNode ? block.builders.create : block.builders.mount ).addLine(
+	(state.parentNode ? block.builders.create : block.builders.mount).addLine(
 		`if ( ${block.component}._yield ) ${block.component}._yield.mount( ${parentNode}, null );`
 	);
 
 	block.builders.destroy.addLine(
 		`if ( ${block.component}._yield ) ${block.component}._yield.unmount();`
 	);
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/shared/binding/getSetter.ts b/src/generators/dom/visitors/shared/binding/getSetter.ts
index 11028915e4..2216311b87 100644
--- a/src/generators/dom/visitors/shared/binding/getSetter.ts
+++ b/src/generators/dom/visitors/shared/binding/getSetter.ts
@@ -1,15 +1,25 @@
 import deindent from '../../../../../utils/deindent.js';
 
-export default function getSetter ({ block, name, snippet, context, attribute, dependencies, value }) {
-	const tail = attribute.value.type === 'MemberExpression' ? getTailSnippet( attribute.value ) : '';
-
-	if ( block.contexts.has( name ) ) {
+export default function getSetter({
+	block,
+	name,
+	snippet,
+	context,
+	attribute,
+	dependencies,
+	value
+}) {
+	const tail = attribute.value.type === 'MemberExpression'
+		? getTailSnippet(attribute.value)
+		: '';
+
+	if (block.contexts.has(name)) {
 		const prop = dependencies[0];
-		const computed = isComputed( attribute.value );
+		const computed = isComputed(attribute.value);
 
 		return deindent`
-			var list = this.${context}.${block.listNames.get( name )};
-			var index = this.${context}.${block.indexNames.get( name )};
+			var list = this.${context}.${block.listNames.get(name)};
+			var index = this.${context}.${block.indexNames.get(name)};
 			${computed && `var state = ${block.component}.get();`}
 			list[index]${tail} = ${value};
 
@@ -17,8 +27,8 @@ export default function getSetter ({ block, name, snippet, context, attribute, d
 		`;
 	}
 
-	if ( attribute.value.type === 'MemberExpression' ) {
-		const alias = block.alias( name );
+	if (attribute.value.type === 'MemberExpression') {
+		const alias = block.alias(name);
 
 		return deindent`
 			var state = ${block.component}.get();
@@ -30,19 +40,19 @@ export default function getSetter ({ block, name, snippet, context, attribute, d
 	return `${block.component}._set({ ${name}: ${value} });`;
 }
 
-function getTailSnippet ( node ) {
+function getTailSnippet(node) {
 	const end = node.end;
-	while ( node.type === 'MemberExpression' ) node = node.object;
+	while (node.type === 'MemberExpression') node = node.object;
 	const start = node.end;
 
 	return `[✂${start}-${end}✂]`;
 }
 
-function isComputed ( node ) {
-	while ( node.type === 'MemberExpression' ) {
-		if ( node.computed ) return true;
+function isComputed(node) {
+	while (node.type === 'MemberExpression') {
+		if (node.computed) return true;
 		node = node.object;
 	}
 
 	return false;
-}
\ No newline at end of file
+}
diff --git a/src/generators/server-side-rendering/Block.ts b/src/generators/server-side-rendering/Block.ts
index d73fde6c6e..a8ebc029f5 100644
--- a/src/generators/server-side-rendering/Block.ts
+++ b/src/generators/server-side-rendering/Block.ts
@@ -15,33 +15,39 @@ export default class Block {
 	indexes: Map<string, string>;
 	contextDependencies: Map<string, string[]>;
 
-	constructor ( options: BlockOptions ) {
-		Object.assign( this, options );
+	constructor(options: BlockOptions) {
+		Object.assign(this, options);
 	}
 
-	addBinding ( binding: Node, name: string ) {
-		const conditions = [ `!( '${binding.name}' in state )`].concat( // TODO handle contextual bindings...
-			this.conditions.map( c => `(${c})` )
+	addBinding(binding: Node, name: string) {
+		const conditions = [`!( '${binding.name}' in state )`].concat(
+			// TODO handle contextual bindings...
+			this.conditions.map(c => `(${c})`)
 		);
 
-		const { keypath } = flattenReference( binding.value );
+		const { keypath } = flattenReference(binding.value);
 
-		this.generator.bindings.push( deindent`
-			if ( ${conditions.join( '&&' )} ) {
+		this.generator.bindings.push(deindent`
+			if ( ${conditions.join('&&')} ) {
 				tmp = ${name}.data();
 				if ( '${keypath}' in tmp ) {
 					state.${binding.name} = tmp.${keypath};
 					settled = false;
 				}
 			}
-		` );
+		`);
 	}
 
-	child ( options: BlockOptions ) {
-		return new Block( Object.assign( {}, this, options, { parent: this } ) );
+	child(options: BlockOptions) {
+		return new Block(Object.assign({}, this, options, { parent: this }));
 	}
 
-	contextualise ( expression: Node, context?: string, isEventHandler?: boolean ) {
-		return this.generator.contextualise( this, expression, context, isEventHandler );
+	contextualise(expression: Node, context?: string, isEventHandler?: boolean) {
+		return this.generator.contextualise(
+			this,
+			expression,
+			context,
+			isEventHandler
+		);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/server-side-rendering/index.ts b/src/generators/server-side-rendering/index.ts
index 90c4e6cdf3..74e3d4b9dd 100644
--- a/src/generators/server-side-rendering/index.ts
+++ b/src/generators/server-side-rendering/index.ts
@@ -9,25 +9,34 @@ export class SsrGenerator extends Generator {
 	renderCode: string;
 	elementDepth: number;
 
-	constructor ( parsed: Parsed, source: string, name: string, options: CompileOptions ) {
-		super( parsed, source, name, options );
+	constructor(
+		parsed: Parsed,
+		source: string,
+		name: string,
+		options: CompileOptions
+	) {
+		super(parsed, source, name, options);
 		this.bindings = [];
 		this.renderCode = '';
 		this.elementDepth = 0;
 	}
 
-	append ( code: string ) {
+	append(code: string) {
 		this.renderCode += code;
 	}
 }
 
-export default function ssr ( parsed: Parsed, source: string, options: CompileOptions ) {
+export default function ssr(
+	parsed: Parsed,
+	source: string,
+	options: CompileOptions
+) {
 	const format = options.format || 'cjs';
 	const name = options.name || 'SvelteComponent';
 
-	const generator = new SsrGenerator( parsed, source, name, options );
+	const generator = new SsrGenerator(parsed, source, name, options);
 
-	const { computations, hasJs, templateProperties } = generator.parseJs( true );
+	const { computations, hasJs, templateProperties } = generator.parseJs(true);
 
 	// create main render() function
 	const mainBlock = new Block({
@@ -37,8 +46,8 @@ export default function ssr ( parsed: Parsed, source: string, options: CompileOp
 		conditions: []
 	});
 
-	parsed.html.children.forEach( ( node: Node ) => {
-		visit( generator, mainBlock, node );
+	parsed.html.children.forEach((node: Node) => {
+		visit(generator, mainBlock, node);
 	});
 
 	const result = deindent`
@@ -46,27 +55,37 @@ export default function ssr ( parsed: Parsed, source: string, options: CompileOp
 
 		var ${name} = {};
 
-		${name}.filename = ${JSON.stringify( options.filename )};
+		${name}.filename = ${JSON.stringify(options.filename)};
 
 		${name}.data = function () {
-			return ${templateProperties.data ? `${generator.alias( 'template' )}.data()` : `{}`};
+			return ${templateProperties.data
+				? `${generator.alias('template')}.data()`
+				: `{}`};
 		};
 
 		${name}.render = function ( state, options ) {
-			${templateProperties.data ? `state = Object.assign( ${generator.alias( 'template' )}.data(), state || {} );` : `state = state || {};`}
-
-			${computations.map( ({ key, deps }) =>
-				`state.${key} = ${generator.alias( 'template' )}.computed.${key}( ${deps.map( dep => `state.${dep}` ).join( ', ' )} );`
+			${templateProperties.data
+				? `state = Object.assign( ${generator.alias(
+						'template'
+					)}.data(), state || {} );`
+				: `state = state || {};`}
+
+			${computations.map(
+				({ key, deps }) =>
+					`state.${key} = ${generator.alias(
+						'template'
+					)}.computed.${key}( ${deps.map(dep => `state.${dep}`).join(', ')} );`
 			)}
 
-			${generator.bindings.length && deindent`
+			${generator.bindings.length &&
+				deindent`
 				var settled = false;
 				var tmp;
 
 				while ( !settled ) {
 					settled = true;
 
-					${generator.bindings.join( '\n\n' )}
+					${generator.bindings.join('\n\n')}
 				}
 			`}
 
@@ -76,15 +95,17 @@ export default function ssr ( parsed: Parsed, source: string, options: CompileOp
 		${name}.renderCss = function () {
 			var components = [];
 
-			${generator.css && deindent`
+			${generator.css &&
+				deindent`
 				components.push({
 					filename: ${name}.filename,
-					css: ${JSON.stringify( generator.css )},
+					css: ${JSON.stringify(generator.css)},
 					map: null // TODO
 				});
 			`}
 
-			${templateProperties.components && deindent`
+			${templateProperties.components &&
+				deindent`
 				var seen = {};
 
 				function addComponent ( component ) {
@@ -96,13 +117,13 @@ export default function ssr ( parsed: Parsed, source: string, options: CompileOp
 					});
 				}
 
-				${
-					templateProperties.components.value.properties.map( prop => {
-						const { name } = prop.key;
-						const expression = generator.importedComponents.get( name ) || `${generator.alias( 'template' )}.components.${name}`;
-						return `addComponent( ${expression} );`;
-					})
-				}
+				${templateProperties.components.value.properties.map(prop => {
+					const { name } = prop.key;
+					const expression =
+						generator.importedComponents.get(name) ||
+						`${generator.alias('template')}.components.${name}`;
+					return `addComponent( ${expression} );`;
+				})}
 			`}
 
 			return {
@@ -125,5 +146,5 @@ export default function ssr ( parsed: Parsed, source: string, options: CompileOp
 		}
 	`;
 
-	return generator.generate( result, options, { name, format } );
+	return generator.generate(result, options, { name, format });
 }
diff --git a/src/generators/server-side-rendering/visit.ts b/src/generators/server-side-rendering/visit.ts
index 8668a8a922..0c2bba8d69 100644
--- a/src/generators/server-side-rendering/visit.ts
+++ b/src/generators/server-side-rendering/visit.ts
@@ -3,7 +3,11 @@ import { SsrGenerator } from './index';
 import Block from './Block';
 import { Node } from '../../interfaces';
 
-export default function visit ( generator: SsrGenerator, block: Block, node: Node ) {
-	const visitor = visitors[ node.type ];
-	visitor( generator, block, node );
-}
\ No newline at end of file
+export default function visit(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	const visitor = visitors[node.type];
+	visitor(generator, block, node);
+}
diff --git a/src/generators/server-side-rendering/visitors/Comment.ts b/src/generators/server-side-rendering/visitors/Comment.ts
index 4d3477d7ef..ad10d20aa5 100644
--- a/src/generators/server-side-rendering/visitors/Comment.ts
+++ b/src/generators/server-side-rendering/visitors/Comment.ts
@@ -1,3 +1,3 @@
-export default function visitComment () {
+export default function visitComment() {
 	// do nothing
 }
diff --git a/src/generators/server-side-rendering/visitors/Component.ts b/src/generators/server-side-rendering/visitors/Component.ts
index 557b6553c1..05523a29a8 100644
--- a/src/generators/server-side-rendering/visitors/Component.ts
+++ b/src/generators/server-side-rendering/visitors/Component.ts
@@ -4,11 +4,15 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitComponent ( generator: SsrGenerator, block: Block, node: Node ) {
-	function stringify ( chunk: Node ) {
-		if ( chunk.type === 'Text' ) return chunk.data;
-		if ( chunk.type === 'MustacheTag' ) {
-			const { snippet } = block.contextualise( chunk.expression );
+export default function visitComponent(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	function stringify(chunk: Node) {
+		if (chunk.type === 'Text') return chunk.data;
+		if (chunk.type === 'MustacheTag') {
+			const { snippet } = block.contextualise(chunk.expression);
 			return '${__escape( ' + snippet + ')}';
 		}
 	}
@@ -16,65 +20,70 @@ export default function visitComponent ( generator: SsrGenerator, block: Block,
 	const attributes: Node[] = [];
 	const bindings: Node[] = [];
 
-	node.attributes.forEach( ( attribute: Node ) => {
-		if ( attribute.type === 'Attribute' ) {
-			attributes.push( attribute );
-		} else if ( attribute.type === 'Binding' ) {
-			bindings.push( attribute );
+	node.attributes.forEach((attribute: Node) => {
+		if (attribute.type === 'Attribute') {
+			attributes.push(attribute);
+		} else if (attribute.type === 'Binding') {
+			bindings.push(attribute);
 		}
 	});
 
 	const props = attributes
-		.map( attribute => {
+		.map(attribute => {
 			let value;
 
-			if ( attribute.value === true ) {
+			if (attribute.value === true) {
 				value = `true`;
-			} else if ( attribute.value.length === 0 ) {
+			} else if (attribute.value.length === 0) {
 				value = `''`;
-			} else if ( attribute.value.length === 1 ) {
+			} else if (attribute.value.length === 1) {
 				const chunk = attribute.value[0];
-				if ( chunk.type === 'Text' ) {
-					value = isNaN( chunk.data ) ? JSON.stringify( chunk.data ) : chunk.data;
+				if (chunk.type === 'Text') {
+					value = isNaN(chunk.data) ? JSON.stringify(chunk.data) : chunk.data;
 				} else {
-					const { snippet } = block.contextualise( chunk.expression );
+					const { snippet } = block.contextualise(chunk.expression);
 					value = snippet;
 				}
 			} else {
-				value = '`' + attribute.value.map( stringify ).join( '' ) + '`';
+				value = '`' + attribute.value.map(stringify).join('') + '`';
 			}
 
 			return `${attribute.name}: ${value}`;
 		})
-		.concat( bindings.map( binding => {
-			const { name, keypath } = flattenReference( binding.value );
-			const value = block.contexts.has( name ) ? keypath : `state.${keypath}`;
-			return `${binding.name}: ${value}`;
-		}))
-		.join( ', ' );
+		.concat(
+			bindings.map(binding => {
+				const { name, keypath } = flattenReference(binding.value);
+				const value = block.contexts.has(name) ? keypath : `state.${keypath}`;
+				return `${binding.name}: ${value}`;
+			})
+		)
+		.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 => {
-		block.addBinding( binding, expression );
+	bindings.forEach(binding => {
+		block.addBinding(binding, expression);
 	});
 
 	let open = `\${${expression}.render({${props}}`;
 
-	if ( node.children.length ) {
+	if (node.children.length) {
 		open += `, { yield: () => \``;
 	}
 
-	generator.append( open );
+	generator.append(open);
 
 	generator.elementDepth += 1;
 
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, block, child );
+	node.children.forEach((child: Node) => {
+		visit(generator, block, child);
 	});
 
 	generator.elementDepth -= 1;
 
 	const close = node.children.length ? `\` })}` : ')}';
-	generator.append( close );
+	generator.append(close);
 }
diff --git a/src/generators/server-side-rendering/visitors/EachBlock.ts b/src/generators/server-side-rendering/visitors/EachBlock.ts
index a08ffd2668..5da589f185 100644
--- a/src/generators/server-side-rendering/visitors/EachBlock.ts
+++ b/src/generators/server-side-rendering/visitors/EachBlock.ts
@@ -3,22 +3,28 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitEachBlock ( generator: SsrGenerator, block: Block, node: Node ) {
-	const { dependencies, snippet } = block.contextualise( node.expression );
-
-	const open = `\${ ${snippet}.map( ${ node.index ? `( ${node.context}, ${node.index} )` : node.context} => \``;
-	generator.append( open );
+export default function visitEachBlock(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	const { dependencies, snippet } = block.contextualise(node.expression);
+
+	const open = `\${ ${snippet}.map( ${node.index
+		? `( ${node.context}, ${node.index} )`
+		: node.context} => \``;
+	generator.append(open);
 
 	// TODO should this be the generator's job? It's duplicated between
 	// here and the equivalent DOM compiler visitor
-	const contexts = new Map( block.contexts );
-	contexts.set( node.context, node.context );
+	const contexts = new Map(block.contexts);
+	contexts.set(node.context, node.context);
 
-	const indexes = new Map( block.indexes );
-	if ( node.index ) indexes.set( node.index, node.context );
+	const indexes = new Map(block.indexes);
+	if (node.index) indexes.set(node.index, node.context);
 
-	const contextDependencies = new Map( block.contextDependencies );
-	contextDependencies.set( node.context, dependencies );
+	const contextDependencies = new Map(block.contextDependencies);
+	contextDependencies.set(node.context, dependencies);
 
 	const childBlock = block.child({
 		contexts,
@@ -26,10 +32,10 @@ export default function visitEachBlock ( generator: SsrGenerator, block: Block,
 		contextDependencies
 	});
 
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, childBlock, child );
+	node.children.forEach((child: Node) => {
+		visit(generator, childBlock, child);
 	});
 
 	const close = `\` ).join( '' )}`;
-	generator.append( close );
-}
\ No newline at end of file
+	generator.append(close);
+}
diff --git a/src/generators/server-side-rendering/visitors/Element.ts b/src/generators/server-side-rendering/visitors/Element.ts
index 2c351ed680..a01f8eabd4 100644
--- a/src/generators/server-side-rendering/visitors/Element.ts
+++ b/src/generators/server-side-rendering/visitors/Element.ts
@@ -10,67 +10,73 @@ const meta = {
 	':Window': visitWindow
 };
 
-function stringifyAttributeValue ( block: Block, chunks: Node[] ) {
-	return chunks.map( ( chunk: Node ) => {
-		if ( chunk.type === 'Text' ) {
-			return chunk.data;
-		}
+function stringifyAttributeValue(block: Block, chunks: Node[]) {
+	return chunks
+		.map((chunk: Node) => {
+			if (chunk.type === 'Text') {
+				return chunk.data;
+			}
 
-		const { snippet } = block.contextualise( chunk.expression );
-		return '${' + snippet + '}';
-	}).join( '' )
+			const { snippet } = block.contextualise(chunk.expression);
+			return '${' + snippet + '}';
+		})
+		.join('');
 }
 
-export default function visitElement ( generator: SsrGenerator, block: Block, node: Node ) {
-	if ( node.name in meta ) {
-		return meta[ node.name ]( generator, block, node );
+export default function visitElement(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	if (node.name in meta) {
+		return meta[node.name](generator, block, node);
 	}
 
-	if ( generator.components.has( node.name ) || node.name === ':Self' ) {
-		visitComponent( generator, block, node );
+	if (generator.components.has(node.name) || node.name === ':Self') {
+		visitComponent(generator, block, node);
 		return;
 	}
 
 	let openingTag = `<${node.name}`;
 	let textareaContents; // awkward special case
 
-	node.attributes.forEach( ( attribute: Node ) => {
-		if ( attribute.type !== 'Attribute' ) return;
+	node.attributes.forEach((attribute: Node) => {
+		if (attribute.type !== 'Attribute') return;
 
-		if ( attribute.name === 'value' && node.name === 'textarea' ) {
-			textareaContents = stringifyAttributeValue( block, attribute.value );
+		if (attribute.name === 'value' && node.name === 'textarea') {
+			textareaContents = stringifyAttributeValue(block, attribute.value);
 		} else {
 			let str = ` ${attribute.name}`;
 
-			if ( attribute.value !== true ) {
-				str += `="${stringifyAttributeValue( block, attribute.value )}"`;
+			if (attribute.value !== true) {
+				str += `="${stringifyAttributeValue(block, attribute.value)}"`;
 			}
 
 			openingTag += str;
 		}
 	});
 
-	if ( generator.cssId && ( !generator.cascade || generator.elementDepth === 0 ) ) {
+	if (generator.cssId && (!generator.cascade || generator.elementDepth === 0)) {
 		openingTag += ` ${generator.cssId}`;
 	}
 
 	openingTag += '>';
 
-	generator.append( openingTag );
+	generator.append(openingTag);
 
-	if ( node.name === 'textarea' && textareaContents !== undefined ) {
-		generator.append( textareaContents );
+	if (node.name === 'textarea' && textareaContents !== undefined) {
+		generator.append(textareaContents);
 	} else {
 		generator.elementDepth += 1;
 
-		node.children.forEach( ( child: Node ) => {
-			visit( generator, block, child );
+		node.children.forEach((child: Node) => {
+			visit(generator, block, child);
 		});
 
 		generator.elementDepth -= 1;
 	}
 
-	if ( !isVoidElementName( node.name ) ) {
-		generator.append( `</${node.name}>` );
+	if (!isVoidElementName(node.name)) {
+		generator.append(`</${node.name}>`);
 	}
-}
\ No newline at end of file
+}
diff --git a/src/generators/server-side-rendering/visitors/IfBlock.ts b/src/generators/server-side-rendering/visitors/IfBlock.ts
index 42cd2f861b..a110b08bba 100644
--- a/src/generators/server-side-rendering/visitors/IfBlock.ts
+++ b/src/generators/server-side-rendering/visitors/IfBlock.ts
@@ -3,26 +3,30 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitIfBlock ( generator: SsrGenerator, block: Block, node: Node ) {
-	const { snippet } = block.contextualise( node.expression );
+export default function visitIfBlock(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	const { snippet } = block.contextualise(node.expression);
 
-	generator.append( '${ ' + snippet + ' ? `' );
+	generator.append('${ ' + snippet + ' ? `');
 
 	const childBlock = block.child({
-		conditions: block.conditions.concat( snippet )
+		conditions: block.conditions.concat(snippet)
 	});
 
-	node.children.forEach( ( child: Node ) => {
-		visit( generator, childBlock, child );
+	node.children.forEach((child: Node) => {
+		visit(generator, childBlock, child);
 	});
 
-	generator.append( '` : `' );
+	generator.append('` : `');
 
-	if ( node.else ) {
-		node.else.children.forEach( ( child: Node ) => {
-			visit( generator, childBlock, child );
+	if (node.else) {
+		node.else.children.forEach((child: Node) => {
+			visit(generator, childBlock, child);
 		});
 	}
 
-	generator.append( '` }' );
-}
\ No newline at end of file
+	generator.append('` }');
+}
diff --git a/src/generators/server-side-rendering/visitors/MustacheTag.ts b/src/generators/server-side-rendering/visitors/MustacheTag.ts
index 78c4646588..db6c496692 100644
--- a/src/generators/server-side-rendering/visitors/MustacheTag.ts
+++ b/src/generators/server-side-rendering/visitors/MustacheTag.ts
@@ -2,7 +2,11 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitMustacheTag ( generator: SsrGenerator, block: Block, node: Node ) {
-	const { snippet } = block.contextualise( node.expression );
-	generator.append( '${__escape( ' + snippet + ' )}' );
-}
\ No newline at end of file
+export default function visitMustacheTag(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	const { snippet } = block.contextualise(node.expression);
+	generator.append('${__escape( ' + snippet + ' )}');
+}
diff --git a/src/generators/server-side-rendering/visitors/RawMustacheTag.ts b/src/generators/server-side-rendering/visitors/RawMustacheTag.ts
index 9dfaf171e6..8112349d04 100644
--- a/src/generators/server-side-rendering/visitors/RawMustacheTag.ts
+++ b/src/generators/server-side-rendering/visitors/RawMustacheTag.ts
@@ -2,7 +2,11 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitRawMustacheTag ( generator: SsrGenerator, block: Block, node: Node ) {
-	const { snippet } = block.contextualise( node.expression );
-	generator.append( '${' + snippet + '}' );
-}
\ No newline at end of file
+export default function visitRawMustacheTag(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	const { snippet } = block.contextualise(node.expression);
+	generator.append('${' + snippet + '}');
+}
diff --git a/src/generators/server-side-rendering/visitors/Text.ts b/src/generators/server-side-rendering/visitors/Text.ts
index 3d119ff6be..c35bd9ced9 100644
--- a/src/generators/server-side-rendering/visitors/Text.ts
+++ b/src/generators/server-side-rendering/visitors/Text.ts
@@ -2,6 +2,10 @@ import { SsrGenerator } from '../index';
 import Block from '../Block';
 import { Node } from '../../../interfaces';
 
-export default function visitText ( generator: SsrGenerator, block: Block, node: Node ) {
-	generator.append( node.data.replace( /\${/g, '\\${' ) );
-}
\ No newline at end of file
+export default function visitText(
+	generator: SsrGenerator,
+	block: Block,
+	node: Node
+) {
+	generator.append(node.data.replace(/\${/g, '\\${'));
+}
diff --git a/src/generators/server-side-rendering/visitors/YieldTag.ts b/src/generators/server-side-rendering/visitors/YieldTag.ts
index 16dd83ddbc..03c83655ab 100644
--- a/src/generators/server-side-rendering/visitors/YieldTag.ts
+++ b/src/generators/server-side-rendering/visitors/YieldTag.ts
@@ -1,5 +1,5 @@
 import { SsrGenerator } from '../index';
 
-export default function visitYieldTag ( generator: SsrGenerator ) {
-	generator.append( `\${options && options.yield ? options.yield() : ''}` );
-}
\ No newline at end of file
+export default function visitYieldTag(generator: SsrGenerator) {
+	generator.append(`\${options && options.yield ? options.yield() : ''}`);
+}
diff --git a/src/generators/server-side-rendering/visitors/meta/Window.ts b/src/generators/server-side-rendering/visitors/meta/Window.ts
index 4b4bf67ccc..733bf2b5c0 100644
--- a/src/generators/server-side-rendering/visitors/meta/Window.ts
+++ b/src/generators/server-side-rendering/visitors/meta/Window.ts
@@ -1,3 +1,3 @@
-export default function visitWindow () {
+export default function visitWindow() {
 	// noop
-}
\ No newline at end of file
+}
diff --git a/src/generators/shared/processCss.ts b/src/generators/shared/processCss.ts
index 4eff632244..468a866649 100644
--- a/src/generators/shared/processCss.ts
+++ b/src/generators/shared/processCss.ts
@@ -3,7 +3,11 @@ import { Parsed, Node } from '../../interfaces';
 
 const commentsPattern = /\/\*[\s\S]*?\*\//g;
 
-export default function processCss ( parsed: Parsed, code: MagicString, cascade: boolean ) {
+export default function processCss(
+	parsed: Parsed,
+	code: MagicString,
+	cascade: boolean
+) {
 	const css = parsed.css.content.styles;
 	const offset = parsed.css.content.start;
 
@@ -11,75 +15,73 @@ export default function processCss ( parsed: Parsed, code: MagicString, cascade:
 
 	const keyframes = new Map();
 
-	function walkKeyframes ( node: Node ) {
-		if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
-			node.expression.children.forEach( ( expression: Node ) => {
-				if ( expression.type === 'Identifier' ) {
-					if ( expression.name.startsWith( '-global-' ) ) {
-						code.remove( expression.start, expression.start + 8 );
+	function walkKeyframes(node: Node) {
+		if (node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes') {
+			node.expression.children.forEach((expression: Node) => {
+				if (expression.type === 'Identifier') {
+					if (expression.name.startsWith('-global-')) {
+						code.remove(expression.start, expression.start + 8);
 					} else {
 						const newName = `svelte-${parsed.hash}-${expression.name}`;
-						code.overwrite( expression.start, expression.end, newName );
-						keyframes.set( expression.name, newName );
+						code.overwrite(expression.start, expression.end, newName);
+						keyframes.set(expression.name, newName);
 					}
 				}
 			});
-		} else if ( node.children ) {
-			node.children.forEach( walkKeyframes );
-		} else if ( node.block ) {
-			walkKeyframes( node.block );
+		} else if (node.children) {
+			node.children.forEach(walkKeyframes);
+		} else if (node.block) {
+			walkKeyframes(node.block);
 		}
 	}
 
-	parsed.css.children.forEach( walkKeyframes );
+	parsed.css.children.forEach(walkKeyframes);
 
-	function transform ( rule: Node ) {
-		rule.selector.children.forEach( ( selector: Node ) => {
-			if ( cascade ) {
+	function transform(rule: Node) {
+		rule.selector.children.forEach((selector: Node) => {
+			if (cascade) {
 				// TODO disable cascading (without :global(...)) in v2
 				const start = selector.start - offset;
 				const end = selector.end - offset;
 
-				const selectorString = css.slice( start, end );
+				const selectorString = css.slice(start, end);
 
 				const firstToken = selector.children[0];
 
 				let transformed;
 
-				if ( firstToken.type === 'TypeSelector' ) {
+				if (firstToken.type === 'TypeSelector') {
 					const insert = firstToken.end - offset;
-					const head = css.slice( start, insert );
-					const tail = css.slice( insert, end );
+					const head = css.slice(start, insert);
+					const tail = css.slice(insert, end);
 
 					transformed = `${head}${attr}${tail}, ${attr} ${selectorString}`;
 				} else {
 					transformed = `${attr}${selectorString}, ${attr} ${selectorString}`;
 				}
 
-				code.overwrite( selector.start, selector.end, transformed );
-			}
-
-			else {
+				code.overwrite(selector.start, selector.end, transformed);
+			} else {
 				let shouldTransform = true;
 				let c = selector.start;
 
-				selector.children.forEach( ( child: Node ) => {
-					if ( child.type === 'WhiteSpace' || child.type === 'Combinator' ) {
-						code.appendLeft( c, attr );
+				selector.children.forEach((child: Node) => {
+					if (child.type === 'WhiteSpace' || child.type === 'Combinator') {
+						code.appendLeft(c, attr);
 						shouldTransform = true;
 						return;
 					}
 
-					if ( !shouldTransform ) return;
+					if (!shouldTransform) return;
 
-					if ( child.type === 'PseudoClassSelector' ) {
+					if (child.type === 'PseudoClassSelector') {
 						// `:global(xyz)` > xyz
-						if ( child.name === 'global' ) {
+						if (child.name === 'global') {
 							const first = child.children[0];
 							const last = child.children[child.children.length - 1];
-							code.remove( child.start, first.start ).remove( last.end, child.end );
+							code.remove(child.start, first.start).remove(last.end, child.end);
 						} else {
-							code.prependRight( c, attr );
+							code.prependRight(c, attr);
 						}
 
 						shouldTransform = false;
@@ -88,21 +90,21 @@ export default function processCss ( parsed: Parsed, code: MagicString, cascade:
 					c = child.end;
 				});
 
-				if ( shouldTransform ) {
-					code.appendLeft( c, attr );
+				if (shouldTransform) {
+					code.appendLeft(c, attr);
 				}
 			}
 		});
 
-		rule.block.children.forEach( ( block: Node ) => {
-			if ( block.type === 'Declaration' ) {
+		rule.block.children.forEach((block: Node) => {
+			if (block.type === 'Declaration') {
 				const property = block.property.toLowerCase();
-				if ( property === 'animation' || property === 'animation-name' ) {
-					block.value.children.forEach( ( block: Node ) => {
-						if ( block.type === 'Identifier' ) {
+				if (property === 'animation' || property === 'animation-name') {
+					block.value.children.forEach((block: Node) => {
+						if (block.type === 'Identifier') {
 							const name = block.name;
-							if ( keyframes.has( name ) ) {
-								code.overwrite( block.start, block.end, keyframes.get( name ) );
+							if (keyframes.has(name)) {
+								code.overwrite(block.start, block.end, keyframes.get(name));
 							}
 						}
 					});
@@ -111,28 +113,31 @@ export default function processCss ( parsed: Parsed, code: MagicString, cascade:
 		});
 	}
 
-	function walk ( node: Node ) {
-		if ( node.type === 'Rule' ) {
-			transform( node );
-		} else if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
+	function walk(node: Node) {
+		if (node.type === 'Rule') {
+			transform(node);
+		} else if (
+			node.type === 'Atrule' &&
+			node.name.toLowerCase() === 'keyframes'
+		) {
 			// these have already been processed
-		} else if ( node.children ) {
-			node.children.forEach( walk );
-		} else if ( node.block ) {
-			walk( node.block );
+		} else if (node.children) {
+			node.children.forEach(walk);
+		} else if (node.block) {
+			walk(node.block);
 		}
 	}
 
-	parsed.css.children.forEach( walk );
+	parsed.css.children.forEach(walk);
 
 	// remove comments. TODO would be nice if this was exposed in css-tree
 	let match;
-	while ( match = commentsPattern.exec( css ) ) {
+	while ((match = commentsPattern.exec(css))) {
 		const start = match.index + offset;
 		const end = start + match[0].length;
 
-		code.remove( start, end );
+		code.remove(start, end);
 	}
 
-	return code.slice( parsed.css.content.start, parsed.css.content.end );
+	return code.slice(parsed.css.content.start, parsed.css.content.end);
 }
diff --git a/src/generators/shared/utils/getGlobals.ts b/src/generators/shared/utils/getGlobals.ts
index 3ba58cf29a..f79e002471 100644
--- a/src/generators/shared/utils/getGlobals.ts
+++ b/src/generators/shared/utils/getGlobals.ts
@@ -1,33 +1,35 @@
-import { Declaration, Options } from './getIntro';
+import { Declaration, Options } from './getIntro';
 
 export type Globals = (id: string) => any;
 
-export default function getGlobals ( imports: Declaration[], options: Options ) {
+export default function getGlobals(imports: Declaration[], options: Options) {
 	const { globals, onerror, onwarn } = options;
-	const globalFn = getGlobalFn( globals );
-
-	return imports.map( x => {
-		let name = globalFn( x.source.value );
-
-		if ( !name ) {
-			if ( x.name.startsWith( '__import' ) ) {
-				const error = new Error( `Could not determine name for imported module '${x.source.value}' – use options.globals` );
-				if ( onerror ) {
-					onerror( error );
+	const globalFn = getGlobalFn(globals);
+
+	return imports.map(x => {
+		let name = globalFn(x.source.value);
+
+		if (!name) {
+			if (x.name.startsWith('__import')) {
+				const error = new Error(
+					`Could not determine name for imported module '${x.source
+						.value}' – use options.globals`
+				);
+				if (onerror) {
+					onerror(error);
 				} else {
 					throw error;
 				}
-			}
-
-			else {
+			} else {
 				const warning = {
-					message: `No name was supplied for imported module '${x.source.value}'. Guessing '${x.name}', but you should use options.globals`
+					message: `No name was supplied for imported module '${x.source
+						.value}'. Guessing '${x.name}', but you should use options.globals`
 				};
 
-				if ( onwarn ) {
-					onwarn( warning );
+				if (onwarn) {
+					onwarn(warning);
 				} else {
-					console.warn( warning ); // eslint-disable-line no-console
+					console.warn(warning); // eslint-disable-line no-console
 				}
 			}
 
@@ -38,10 +40,10 @@ export default function getGlobals ( imports: Declaration[], options: Options )
 	});
 }
 
-function getGlobalFn ( globals: any ): Globals {
-	if ( typeof globals === 'function' ) return globals;
-	if ( typeof globals === 'object' ) {
-		return id => globals[ id ];
+function getGlobalFn(globals: any): Globals {
+	if (typeof globals === 'function') return globals;
+	if (typeof globals === 'object') {
+		return id => globals[id];
 	}
 
 	return () => undefined;
diff --git a/src/generators/shared/utils/getIntro.ts b/src/generators/shared/utils/getIntro.ts
index dab45cec20..aea5f47062 100644
--- a/src/generators/shared/utils/getIntro.ts
+++ b/src/generators/shared/utils/getIntro.ts
@@ -1,7 +1,7 @@
 import deindent from '../../../utils/deindent.js';
-import getGlobals, { Globals } from './getGlobals';
+import getGlobals, { Globals } from './getGlobals';
 
-export type ModuleFormat = "es" | "amd" | "cjs" | "iife" | "umd" | "eval";
+export type ModuleFormat = 'es' | 'amd' | 'cjs' | 'iife' | 'umd' | 'eval';
 
 export interface Options {
 	name: string;
@@ -20,75 +20,96 @@ export interface Declaration {
 	};
 }
 
-export default function getIntro ( format: ModuleFormat, options: Options, imports: Declaration[] ) {
-	if ( format === 'es' ) return '';
-	if ( format === 'amd' ) return getAmdIntro( options, imports );
-	if ( format === 'cjs' ) return getCjsIntro( options, imports );
-	if ( format === 'iife' ) return getIifeIntro( options, imports );
-	if ( format === 'umd' ) return getUmdIntro( options, imports );
-	if ( format === 'eval' ) return getEvalIntro( options, imports );
-
-	throw new Error( `Not implemented: ${format}` );
+export default function getIntro(
+	format: ModuleFormat,
+	options: Options,
+	imports: Declaration[]
+) {
+	if (format === 'es') return '';
+	if (format === 'amd') return getAmdIntro(options, imports);
+	if (format === 'cjs') return getCjsIntro(options, imports);
+	if (format === 'iife') return getIifeIntro(options, imports);
+	if (format === 'umd') return getUmdIntro(options, imports);
+	if (format === 'eval') return getEvalIntro(options, imports);
+
+	throw new Error(`Not implemented: ${format}`);
 }
 
-function getAmdIntro ( options: Options, imports: Declaration[] ) {
-	const sourceString = imports.length ?
-		`[ ${imports.map( declaration => `'${removeExtension( declaration.source.value )}'` ).join( ', ' )} ], ` :
-		'';
+function getAmdIntro(options: Options, imports: Declaration[]) {
+	const sourceString = imports.length
+		? `[ ${imports
+				.map(declaration => `'${removeExtension(declaration.source.value)}'`)
+				.join(', ')} ], `
+		: '';
 
 	const id = options.amd && options.amd.id;
 
-	return `define(${id ? ` '${id}', ` : ''}${sourceString}function (${paramString( imports )}) { 'use strict';\n\n`;
+	return `define(${id
+		? ` '${id}', `
+		: ''}${sourceString}function (${paramString(imports)}) { 'use strict';\n\n`;
 }
 
-function getCjsIntro ( options: Options, imports: Declaration[] ) {
+function getCjsIntro(options: Options, imports: Declaration[]) {
 	const requireBlock = imports
-		.map( declaration => `var ${declaration.name} = require( '${declaration.source.value}' );` )
-		.join( '\n\n' );
+		.map(
+			declaration =>
+				`var ${declaration.name} = require( '${declaration.source.value}' );`
+		)
+		.join('\n\n');
 
-	if ( requireBlock ) {
+	if (requireBlock) {
 		return `'use strict';\n\n${requireBlock}\n\n`;
 	}
 
 	return `'use strict';\n\n`;
 }
 
-function getIifeIntro ( options: Options, imports: Declaration[] ) {
-	if ( !options.name ) {
-		throw new Error( `Missing required 'name' option for IIFE export` );
+function getIifeIntro(options: Options, imports: Declaration[]) {
+	if (!options.name) {
+		throw new Error(`Missing required 'name' option for IIFE export`);
 	}
 
-	return `var ${options.name} = (function (${paramString( imports )}) { 'use strict';\n\n`;
+	return `var ${options.name} = (function (${paramString(
+		imports
+	)}) { 'use strict';\n\n`;
 }
 
-function getUmdIntro ( options: Options, imports: Declaration[] ) {
-	if ( !options.name ) {
-		throw new Error( `Missing required 'name' option for UMD export` );
+function getUmdIntro(options: Options, imports: Declaration[]) {
+	if (!options.name) {
+		throw new Error(`Missing required 'name' option for UMD export`);
 	}
 
 	const amdId = options.amd && options.amd.id ? `'${options.amd.id}', ` : '';
 
-	const amdDeps = imports.length ? `[${imports.map( declaration => `'${removeExtension( declaration.source.value )}'` ).join( ', ')}], ` : '';
-	const cjsDeps = imports.map( declaration => `require('${declaration.source.value}')` ).join( ', ' );
-	const globalDeps = getGlobals( imports, options );
-
-	return deindent`
+	const amdDeps = imports.length
+		? `[${imports
+				.map(declaration => `'${removeExtension(declaration.source.value)}'`)
+				.join(', ')}], `
+		: '';
+	const cjsDeps = imports
+		.map(declaration => `require('${declaration.source.value}')`)
+		.join(', ');
+	const globalDeps = getGlobals(imports, options);
+
+	return (
+		deindent`
 		(function ( global, factory ) {
 			typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(${cjsDeps}) :
 			typeof define === 'function' && define.amd ? define(${amdId}${amdDeps}factory) :
 			(global.${options.name} = factory(${globalDeps}));
-		}(this, (function (${paramString( imports )}) { 'use strict';` + '\n\n';
+		}(this, (function (${paramString(imports)}) { 'use strict';` + '\n\n'
+	);
 }
 
-function getEvalIntro ( options: Options, imports: Declaration[] ) {
-	return `(function (${paramString( imports )}) { 'use strict';\n\n`;
+function getEvalIntro(options: Options, imports: Declaration[]) {
+	return `(function (${paramString(imports)}) { 'use strict';\n\n`;
 }
 
-function paramString ( imports: Declaration[] ) {
-	return imports.length ? ` ${imports.map( dep => dep.name ).join( ', ' )} ` : '';
+function paramString(imports: Declaration[]) {
+	return imports.length ? ` ${imports.map(dep => dep.name).join(', ')} ` : '';
 }
 
-function removeExtension ( file: string ) {
-	const index = file.lastIndexOf( '.' );
-	return ~index ? file.slice( 0, index ) : file;
+function removeExtension(file: string) {
+	const index = file.lastIndexOf('.');
+	return ~index ? file.slice(0, index) : file;
 }
diff --git a/src/generators/shared/utils/getOutro.ts b/src/generators/shared/utils/getOutro.ts
index b1cac890a3..f9d8f186bc 100644
--- a/src/generators/shared/utils/getOutro.ts
+++ b/src/generators/shared/utils/getOutro.ts
@@ -1,31 +1,36 @@
 import getGlobals from './getGlobals';
 
-export default function getOutro ( format: string, name: string, options, imports ) {
-	if ( format === 'es' ) {
+export default function getOutro(
+	format: string,
+	name: string,
+	options,
+	imports
+) {
+	if (format === 'es') {
 		return `export default ${name};`;
 	}
 
-	if ( format === 'amd' ) {
+	if (format === 'amd') {
 		return `return ${name};\n\n});`;
 	}
 
-	if ( format === 'cjs' ) {
+	if (format === 'cjs') {
 		return `module.exports = ${name};`;
 	}
 
-	if ( format === 'iife' ) {
-		const globals = getGlobals( imports, options );
-		return `return ${name};\n\n}(${globals.join( ', ' )}));`;
+	if (format === 'iife') {
+		const globals = getGlobals(imports, options);
+		return `return ${name};\n\n}(${globals.join(', ')}));`;
 	}
 
-	if ( format === 'eval' ) {
-		const globals = getGlobals( imports, options );
-		return `return ${name};\n\n}(${globals.join( ', ' )}));`;
+	if (format === 'eval') {
+		const globals = getGlobals(imports, options);
+		return `return ${name};\n\n}(${globals.join(', ')}));`;
 	}
 
-	if ( format === 'umd' ) {
+	if (format === 'umd') {
 		return `return ${name};\n\n})));`;
 	}
 
-	throw new Error( `Not implemented: ${format}` );
+	throw new Error(`Not implemented: ${format}`);
 }
diff --git a/src/generators/shared/utils/walkHtml.ts b/src/generators/shared/utils/walkHtml.ts
index ad5d826e1a..e12b36bbf2 100644
--- a/src/generators/shared/utils/walkHtml.ts
+++ b/src/generators/shared/utils/walkHtml.ts
@@ -1,20 +1,20 @@
 import { Node } from '../../../interfaces';
 
-export default function walkHtml ( html: Node, visitors ) {
-	function visit ( node: Node ) {
-		const visitor = visitors[ node.type ];
-		if ( !visitor ) throw new Error( `Not implemented: ${node.type}` );
+export default function walkHtml(html: Node, visitors) {
+	function visit(node: Node) {
+		const visitor = visitors[node.type];
+		if (!visitor) throw new Error(`Not implemented: ${node.type}`);
 
-		if ( visitor.enter ) visitor.enter( node );
+		if (visitor.enter) visitor.enter(node);
 
-		if ( node.children ) {
-			node.children.forEach( ( child: Node ) => {
-				visit( child );
+		if (node.children) {
+			node.children.forEach((child: Node) => {
+				visit(child);
 			});
 		}
 
-		if ( visitor.leave ) visitor.leave( node );
+		if (visitor.leave) visitor.leave(node);
 	}
 
-	visit( html );
+	visit(html);
 }
diff --git a/src/index.ts b/src/index.ts
index 3d3b02a937..c392f5217d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,62 +6,65 @@ import { assign } from './shared/index.js';
 import { version } from '../package.json';
 import { Parsed, CompileOptions, Warning } from './interfaces';
 
-function normalizeOptions ( options: CompileOptions ) :CompileOptions {
-	return assign({
-		generate: 'dom',
+function normalizeOptions(options: CompileOptions): CompileOptions {
+	return assign(
+		{
+			generate: 'dom',
 
-		// a filename is necessary for sourcemap generation
-		filename: 'SvelteComponent.html',
+			// a filename is necessary for sourcemap generation
+			filename: 'SvelteComponent.html',
 
-		onwarn: ( warning: Warning ) => {
-			if ( warning.loc ) {
-				console.warn( `(${warning.loc.line}:${warning.loc.column}) – ${warning.message}` ); // eslint-disable-line no-console
-			} else {
-				console.warn( warning.message ); // eslint-disable-line no-console
+			onwarn: (warning: Warning) => {
+				if (warning.loc) {
+					console.warn(
+						`(${warning.loc.line}:${warning.loc.column}) – ${warning.message}`
+					); // eslint-disable-line no-console
+				} else {
+					console.warn(warning.message); // eslint-disable-line no-console
+				}
+			},
+
+			onerror: (error: Error) => {
+				throw error;
 			}
 		},
-
-		onerror: ( error: Error ) => {
-			throw error;
-		}
-	}, options );
+		options
+	);
 }
 
-export function compile ( source: string, _options: CompileOptions ) {
-	const options = normalizeOptions( _options );
+export function compile(source: string, _options: CompileOptions) {
+	const options = normalizeOptions(_options);
 
 	let parsed: Parsed;
 
 	try {
-		parsed = parse( source, options );
-	} catch ( err ) {
-		options.onerror( err );
+		parsed = parse(source, options);
+	} catch (err) {
+		options.onerror(err);
 		return;
 	}
 
-	validate( parsed, source, options );
+	validate(parsed, source, options);
 
-	const compiler = options.generate === 'ssr'
-		? generateSSR
-		: generate;
+	const compiler = options.generate === 'ssr' ? generateSSR : generate;
 
-	return compiler( parsed, source, options );
+	return compiler(parsed, source, options);
 }
 
-export function create ( source: string, _options: CompileOptions = {} ) {
+export function create(source: string, _options: CompileOptions = {}) {
 	_options.format = 'eval';
 
-	const compiled = compile( source, _options );
+	const compiled = compile(source, _options);
 
-	if ( !compiled || !compiled.code ) {
+	if (!compiled || !compiled.code) {
 		return;
 	}
 
 	try {
-		return (new Function( 'return ' + compiled.code ))();
-	} catch ( err ) {
-		if ( _options.onerror ) {
-			_options.onerror( err );
+		return new Function('return ' + compiled.code)();
+	} catch (err) {
+		if (_options.onerror) {
+			_options.onerror(err);
 			return;
 		} else {
 			throw err;
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 0caa4d6ed1..fd12939860 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -26,10 +26,10 @@ export interface Parsed {
 }
 
 export interface Warning {
-	loc?: {line: number, column: number, pos: number};
-	message: string
-	filename?: string
-	toString: () => string
+	loc?: { line: number; column: number; pos: number };
+	message: string;
+	filename?: string;
+	toString: () => string;
 }
 
 export interface CompileOptions {
@@ -42,6 +42,6 @@ export interface CompileOptions {
 	shared?: boolean | string;
 	cascade?: boolean;
 
-	onerror?: (error: Error) => void
-	onwarn?: (warning: Warning) => void
-}
\ No newline at end of file
+	onerror?: (error: Error) => void;
+	onwarn?: (warning: Warning) => void;
+}
diff --git a/src/parse/index.ts b/src/parse/index.ts
index 262dc764d5..c3ae27c3e4 100644
--- a/src/parse/index.ts
+++ b/src/parse/index.ts
@@ -5,17 +5,22 @@ import { trimStart, trimEnd } from '../utils/trim';
 import getCodeFrame from '../utils/getCodeFrame';
 import hash from './utils/hash';
 import { Node, Parsed } from '../interfaces';
-import CompileError from '../utils/CompileError'
+import CompileError from '../utils/CompileError';
 
 class ParseError extends CompileError {
-	constructor ( message: string, template: string, index: number, filename: string ) {
-		super( message, template, index, filename );
+	constructor(
+		message: string,
+		template: string,
+		index: number,
+		filename: string
+	) {
+		super(message, template, index, filename);
 		this.name = 'ParseError';
 	}
 }
 
 interface ParserOptions {
-	filename?: string
+	filename?: string;
 }
 
 export class Parser {
@@ -28,14 +33,14 @@ export class Parser {
 	html: Node;
 	css: Node;
 	js: Node;
-	metaTags: {}
+	metaTags: {};
 
-	constructor ( template: string, options: ParserOptions ) {
-		if ( typeof template !== 'string' ) {
-			throw new TypeError( 'Template must be a string' );
+	constructor(template: string, options: ParserOptions) {
+		if (typeof template !== 'string') {
+			throw new TypeError('Template must be a string');
 		}
 
-		this.template = template.replace( /\s+$/, '' );
+		this.template = template.replace(/\s+$/, '');
 		this.filename = options.filename;
 
 		this.index = 0;
@@ -52,36 +57,36 @@ export class Parser {
 		this.css = null;
 		this.js = null;
 
-		this.stack.push( this.html );
+		this.stack.push(this.html);
 
 		let state = fragment;
 
-		while ( this.index < this.template.length ) {
-			state = state( this ) || fragment;
+		while (this.index < this.template.length) {
+			state = state(this) || fragment;
 		}
 
-		if ( this.stack.length > 1 ) {
+		if (this.stack.length > 1) {
 			const current = this.current();
 
 			const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
-			this.error( `${type} was left open`, current.start );
+			this.error(`${type} was left open`, current.start);
 		}
 
-		if ( state !== fragment ) {
-			this.error( 'Unexpected end of input' );
+		if (state !== fragment) {
+			this.error('Unexpected end of input');
 		}
 
 		// trim unnecessary whitespace
-		while ( this.html.children.length ) {
+		while (this.html.children.length) {
 			const firstChild = this.html.children[0];
 			this.html.start = firstChild.start;
 
-			if ( firstChild.type !== 'Text' ) break;
+			if (firstChild.type !== 'Text') break;
 
 			const length = firstChild.data.length;
-			firstChild.data = trimStart( firstChild.data );
+			firstChild.data = trimStart(firstChild.data);
 
-			if ( firstChild.data === '' ) {
+			if (firstChild.data === '') {
 				this.html.children.shift();
 			} else {
 				this.html.start += length - firstChild.data.length;
@@ -89,16 +94,16 @@ export class Parser {
 			}
 		}
 
-		while ( this.html.children.length ) {
-			const lastChild = this.html.children[ this.html.children.length - 1 ];
+		while (this.html.children.length) {
+			const lastChild = this.html.children[this.html.children.length - 1];
 			this.html.end = lastChild.end;
 
-			if ( lastChild.type !== 'Text' ) break;
+			if (lastChild.type !== 'Text') break;
 
 			const length = lastChild.data.length;
-			lastChild.data = trimEnd( lastChild.data );
+			lastChild.data = trimEnd(lastChild.data);
 
-			if ( lastChild.data === '' ) {
+			if (lastChild.data === '') {
 				this.html.children.pop();
 			} else {
 				this.html.end -= length - lastChild.data.length;
@@ -107,82 +112,89 @@ export class Parser {
 		}
 	}
 
-	current () {
-		return this.stack[ this.stack.length - 1 ];
+	current() {
+		return this.stack[this.stack.length - 1];
 	}
 
-	acornError ( err: Error ) {
-		this.error( err.message.replace( / \(\d+:\d+\)$/, '' ), err.pos );
+	acornError(err: Error) {
+		this.error(err.message.replace(/ \(\d+:\d+\)$/, ''), err.pos);
 	}
 
-	error ( message: string, index = this.index ) {
-		throw new ParseError( message, this.template, index, this.filename );
+	error(message: string, index = this.index) {
+		throw new ParseError(message, this.template, index, this.filename);
 	}
 
-	eat ( str: string, required?: boolean ) {
-		if ( this.match( str ) ) {
+	eat(str: string, required?: boolean) {
+		if (this.match(str)) {
 			this.index += str.length;
 			return true;
 		}
 
-		if ( required ) {
-			this.error( `Expected ${str}` );
+		if (required) {
+			this.error(`Expected ${str}`);
 		}
 	}
 
-	match ( str: string ) {
-		return this.template.slice( this.index, this.index + str.length ) === str;
+	match(str: string) {
+		return this.template.slice(this.index, this.index + str.length) === str;
 	}
 
-	allowWhitespace () {
-		while ( this.index < this.template.length && whitespace.test( this.template[ this.index ] ) ) {
+	allowWhitespace() {
+		while (
+			this.index < this.template.length &&
+			whitespace.test(this.template[this.index])
+		) {
 			this.index++;
 		}
 	}
 
-	read ( pattern: RegExp ) {
-		const match = pattern.exec( this.template.slice( this.index ) );
-		if ( !match || match.index !== 0 ) return null;
+	read(pattern: RegExp) {
+		const match = pattern.exec(this.template.slice(this.index));
+		if (!match || match.index !== 0) return null;
 
 		this.index += match[0].length;
 
 		return match[0];
 	}
 
-	readUntil ( pattern: RegExp ) {
-		if ( this.index >= this.template.length ) this.error( 'Unexpected end of input' );
+	readUntil(pattern: RegExp) {
+		if (this.index >= this.template.length)
+			this.error('Unexpected end of input');
 
 		const start = this.index;
-		const match = pattern.exec( this.template.slice( start ) );
+		const match = pattern.exec(this.template.slice(start));
 
-		if ( match ) {
+		if (match) {
 			const start = this.index;
 			this.index = start + match.index;
-			return this.template.slice( start, this.index );
+			return this.template.slice(start, this.index);
 		}
 
 		this.index = this.template.length;
-		return this.template.slice( start );
+		return this.template.slice(start);
 	}
 
-	remaining () {
-		return this.template.slice( this.index );
+	remaining() {
+		return this.template.slice(this.index);
 	}
 
-	requireWhitespace () {
-		if ( !whitespace.test( this.template[ this.index ] ) ) {
-			this.error( `Expected whitespace` );
+	requireWhitespace() {
+		if (!whitespace.test(this.template[this.index])) {
+			this.error(`Expected whitespace`);
 		}
 
 		this.allowWhitespace();
 	}
 }
 
-export default function parse ( template: string, options: ParserOptions = {} ) :Parsed {
-	const parser = new Parser( template, options );
+export default function parse(
+	template: string,
+	options: ParserOptions = {}
+): Parsed {
+	const parser = new Parser(template, options);
 
 	return {
-		hash: hash( parser.template ),
+		hash: hash(parser.template),
 		html: parser.html,
 		css: parser.css,
 		js: parser.js
diff --git a/src/parse/read/directives.ts b/src/parse/read/directives.ts
index f4bc5d4f60..b318e5ac2e 100644
--- a/src/parse/read/directives.ts
+++ b/src/parse/read/directives.ts
@@ -2,61 +2,57 @@ import { parseExpressionAt } from 'acorn';
 import spaces from '../../utils/spaces.js';
 import { Parser } from '../index';
 
-function readExpression ( parser: Parser, start: number, quoteMark ) {
+function readExpression(parser: Parser, start: number, quoteMark) {
 	let str = '';
 	let escaped = false;
 
-	for ( let i = start; i < parser.template.length; i += 1 ) {
+	for (let i = start; i < parser.template.length; i += 1) {
 		const char = parser.template[i];
 
-		if ( quoteMark ) {
-			if ( char === quoteMark ) {
-				if ( escaped ) {
+		if (quoteMark) {
+			if (char === quoteMark) {
+				if (escaped) {
 					str += quoteMark;
 				} else {
 					break;
 				}
-			} else if ( escaped ) {
+			} else if (escaped) {
 				str += '\\' + char;
 				escaped = false;
-			} else if ( char === '\\' ) {
+			} else if (char === '\\') {
 				escaped = true;
 			} else {
 				str += char;
 			}
-		}
-
-		else if ( /\s/.test( char ) ) {
+		} else if (/\s/.test(char)) {
 			break;
-		}
-
-		else {
+		} else {
 			str += char;
 		}
 	}
 
-	const expression = parseExpressionAt( spaces( start ) + str, start );
+	const expression = parseExpressionAt(spaces(start) + str, start);
 	parser.index = expression.end;
 
 	parser.allowWhitespace();
-	if ( quoteMark ) parser.eat( quoteMark, true );
+	if (quoteMark) parser.eat(quoteMark, true);
 
 	return expression;
 }
 
-export function readEventHandlerDirective ( parser: Parser, start: number, name: string ) {
-	const quoteMark = (
-		parser.eat( `'` ) ? `'` :
-		parser.eat( `"` ) ? `"` :
-		null
-	);
+export function readEventHandlerDirective(
+	parser: Parser,
+	start: number,
+	name: string
+) {
+	const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
 
 	const expressionStart = parser.index;
 
-	const expression = readExpression( parser, expressionStart, quoteMark );
+	const expression = readExpression(parser, expressionStart, quoteMark);
 
-	if ( expression.type !== 'CallExpression' ) {
-		parser.error( `Expected call expression`, expressionStart );
+	if (expression.type !== 'CallExpression') {
+		parser.error(`Expected call expression`, expressionStart);
 	}
 
 	return {
@@ -68,49 +64,49 @@ export function readEventHandlerDirective ( parser: Parser, start: number, name:
 	};
 }
 
-export function readBindingDirective ( parser: Parser, start: number, name: string ) {
+export function readBindingDirective(
+	parser: Parser,
+	start: number,
+	name: string
+) {
 	let value;
 
-	if ( parser.eat( '=' ) ) {
-		const quoteMark = (
-			parser.eat( `'` ) ? `'` :
-			parser.eat( `"` ) ? `"` :
-			null
-		);
+	if (parser.eat('=')) {
+		const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
 
 		const a = parser.index;
 
-		if ( parser.eat( '{{' ) ) {
+		if (parser.eat('{{')) {
 			let message = 'bound values should not be wrapped';
-			const b = parser.template.indexOf( '}}', a );
-			if ( b !== -1 ) {
-				const value = parser.template.slice( parser.index, b );
+			const b = parser.template.indexOf('}}', a);
+			if (b !== -1) {
+				const value = parser.template.slice(parser.index, b);
 				message += ` — use '${value}', not '{{${value}}}'`;
 			}
 
-			parser.error( message, a );
+			parser.error(message, a);
 		}
 
 		// this is a bit of a hack so that we can give Acorn something parseable
 		let b;
-		if ( quoteMark ) {
-			b = parser.index = parser.template.indexOf( quoteMark, parser.index );
+		if (quoteMark) {
+			b = parser.index = parser.template.indexOf(quoteMark, parser.index);
 		} else {
-			parser.readUntil( /[\s\r\n\/>]/ );
+			parser.readUntil(/[\s\r\n\/>]/);
 			b = parser.index;
 		}
 
-		const source = spaces( a ) + parser.template.slice( a, b );
-		value = parseExpressionAt( source, a );
+		const source = spaces(a) + parser.template.slice(a, b);
+		value = parseExpressionAt(source, a);
 
-		if ( value.type !== 'Identifier' && value.type !== 'MemberExpression' ) {
-			parser.error( `Cannot bind to rvalue`, value.start );
+		if (value.type !== 'Identifier' && value.type !== 'MemberExpression') {
+			parser.error(`Cannot bind to rvalue`, value.start);
 		}
 
 		parser.allowWhitespace();
 
-		if ( quoteMark ) {
-			parser.eat( quoteMark, true );
+		if (quoteMark) {
+			parser.eat(quoteMark, true);
 		}
 	} else {
 		// shorthand – bind:foo equivalent to bind:foo='foo'
@@ -131,22 +127,23 @@ export function readBindingDirective ( parser: Parser, start: number, name: stri
 	};
 }
 
-export function readTransitionDirective ( parser: Parser, start: number, name: string, type: string ) {
+export function readTransitionDirective(
+	parser: Parser,
+	start: number,
+	name: string,
+	type: string
+) {
 	let expression = null;
 
-	if ( parser.eat( '=' ) ) {
-		const quoteMark = (
-			parser.eat( `'` ) ? `'` :
-			parser.eat( `"` ) ? `"` :
-			null
-		);
+	if (parser.eat('=')) {
+		const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
 
 		const expressionStart = parser.index;
 
-		expression = readExpression( parser, expressionStart, quoteMark );
+		expression = readExpression(parser, expressionStart, quoteMark);
 
-		if ( expression.type !== 'ObjectExpression' ) {
-			parser.error( `Expected object expression`, expressionStart );
+		if (expression.type !== 'ObjectExpression') {
+			parser.error(`Expected object expression`, expressionStart);
 		}
 	}
 
@@ -159,4 +156,4 @@ export function readTransitionDirective ( parser: Parser, start: number, name: s
 		outro: type === 'out' || type === 'transition',
 		expression
 	};
-}
\ No newline at end of file
+}
diff --git a/src/parse/read/expression.ts b/src/parse/read/expression.ts
index 75529e3ce2..6e40f004f9 100644
--- a/src/parse/read/expression.ts
+++ b/src/parse/read/expression.ts
@@ -1,25 +1,21 @@
 import { parseExpressionAt } from 'acorn';
 import { Parser } from '../index';
 
-const literals = new Map([
-	[ 'true', true ],
-	[ 'false', false ],
-	[ 'null', null ]
-]);
+const literals = new Map([['true', true], ['false', false], ['null', null]]);
 
-export default function readExpression ( parser: Parser ) {
+export default function readExpression(parser: Parser) {
 	const start = parser.index;
 
-	const name = parser.readUntil( /\s*}}/ );
-	if ( name && /^[a-z]+$/.test( name ) ) {
+	const name = parser.readUntil(/\s*}}/);
+	if (name && /^[a-z]+$/.test(name)) {
 		const end = start + name.length;
 
-		if ( literals.has( name ) ) {
+		if (literals.has(name)) {
 			return {
 				type: 'Literal',
 				start,
 				end,
-				value: literals.get( name ),
+				value: literals.get(name),
 				raw: name
 			};
 		}
@@ -35,11 +31,13 @@ export default function readExpression ( parser: Parser ) {
 	parser.index = start;
 
 	try {
-		const node = parseExpressionAt( parser.template, parser.index, { preserveParens: true } );
+		const node = parseExpressionAt(parser.template, parser.index, {
+			preserveParens: true
+		});
 		parser.index = node.end;
 
 		return node;
-	} catch ( err ) {
-		parser.acornError( err );
+	} catch (err) {
+		parser.acornError(err);
 	}
 }
diff --git a/src/parse/read/script.ts b/src/parse/read/script.ts
index 3d2e3d3d4b..3f56229c2b 100644
--- a/src/parse/read/script.ts
+++ b/src/parse/read/script.ts
@@ -2,29 +2,30 @@ import { parse } from 'acorn';
 import spaces from '../../utils/spaces.js';
 import { Parser } from '../index';
 
-const scriptClosingTag = '<\/script>';
+const scriptClosingTag = '</script>';
 
-export default function readScript ( parser: Parser, start: number, attributes ) {
+export default function readScript(parser: Parser, start: number, attributes) {
 	const scriptStart = parser.index;
-	const scriptEnd = parser.template.indexOf( scriptClosingTag, scriptStart );
+	const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart);
 
-	if ( scriptEnd === -1 ) parser.error( `<script> must have a closing tag` );
+	if (scriptEnd === -1) parser.error(`<script> must have a closing tag`);
 
-	const source = spaces( scriptStart ) + parser.template.slice( scriptStart, scriptEnd );
+	const source =
+		spaces(scriptStart) + parser.template.slice(scriptStart, scriptEnd);
 	parser.index = scriptEnd + scriptClosingTag.length;
 
 	let ast;
 
 	try {
-		ast = parse( source, {
+		ast = parse(source, {
 			ecmaVersion: 8,
 			sourceType: 'module'
 		});
-	} catch ( err ) {
-		parser.acornError( err );
+	} catch (err) {
+		parser.acornError(err);
 	}
 
-	if ( !ast.body.length ) return null;
+	if (!ast.body.length) return null;
 
 	ast.start = scriptStart;
 	return {
diff --git a/src/parse/read/style.ts b/src/parse/read/style.ts
index 0259905ea3..13696642a9 100644
--- a/src/parse/read/style.ts
+++ b/src/parse/read/style.ts
@@ -2,43 +2,43 @@ import parse from 'css-tree/lib/parser/index.js';
 import walk from 'css-tree/lib/utils/walk.js';
 import { Parser } from '../index';
 
-export default function readStyle ( parser: Parser, start: number, attributes ) {
+export default function readStyle(parser: Parser, start: number, attributes) {
 	const contentStart = parser.index;
-	const styles = parser.readUntil( /<\/style>/ );
+	const styles = parser.readUntil(/<\/style>/);
 	const contentEnd = parser.index;
 
 	let ast;
 
 	try {
-		ast = parse( styles, {
+		ast = parse(styles, {
 			positions: true,
 			offset: contentStart
 		});
-	} catch ( err ) {
-		if ( err.name === 'CssSyntaxError' ) {
-			parser.error( err.message, err.offset );
+	} catch (err) {
+		if (err.name === 'CssSyntaxError') {
+			parser.error(err.message, err.offset);
 		} else {
 			throw err;
 		}
 	}
 
 	// tidy up AST
-	walk.all( ast, node => {
-		if ( node.loc ) {
+	walk.all(ast, node => {
+		if (node.loc) {
 			node.start = node.loc.start.offset;
 			node.end = node.loc.end.offset;
 			delete node.loc;
 		}
 	});
 
-	parser.eat( '</style>', true );
+	parser.eat('</style>', true);
 	const end = parser.index;
 
 	return {
 		start,
 		end,
 		attributes,
-		children: JSON.parse( JSON.stringify( ast.children ) ),
+		children: JSON.parse(JSON.stringify(ast.children)),
 		content: {
 			start: contentStart,
 			end: contentEnd,
diff --git a/src/parse/state/fragment.ts b/src/parse/state/fragment.ts
index 7cd2702a5a..c82b3e2f8a 100644
--- a/src/parse/state/fragment.ts
+++ b/src/parse/state/fragment.ts
@@ -3,12 +3,12 @@ import mustache from './mustache';
 import text from './text';
 import { Parser } from '../index';
 
-export default function fragment ( parser: Parser ) {
-	if ( parser.match( '<' ) ) {
+export default function fragment(parser: Parser) {
+	if (parser.match('<')) {
 		return tag;
 	}
 
-	if ( parser.match( '{{' ) ) {
+	if (parser.match('{{')) {
 		return mustache;
 	}
 
diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts
index afa439a45c..88bfc401f7 100644
--- a/src/parse/state/mustache.ts
+++ b/src/parse/state/mustache.ts
@@ -6,92 +6,93 @@ import { Node } from '../../interfaces';
 
 const validIdentifier = /[a-zA-Z_$][a-zA-Z0-9_$]*/;
 
-function trimWhitespace ( block, trimBefore, trimAfter ) {
+function trimWhitespace(block, trimBefore, trimAfter) {
 	const firstChild = block.children[0];
-	const lastChild = block.children[ block.children.length - 1 ];
+	const lastChild = block.children[block.children.length - 1];
 
-	if ( firstChild.type === 'Text' && trimBefore ) {
-		firstChild.data = trimStart( firstChild.data );
-		if ( !firstChild.data ) block.children.shift();
+	if (firstChild.type === 'Text' && trimBefore) {
+		firstChild.data = trimStart(firstChild.data);
+		if (!firstChild.data) block.children.shift();
 	}
 
-	if ( lastChild.type === 'Text' && trimAfter ) {
-		lastChild.data = trimEnd( lastChild.data );
-		if ( !lastChild.data ) block.children.pop();
+	if (lastChild.type === 'Text' && trimAfter) {
+		lastChild.data = trimEnd(lastChild.data);
+		if (!lastChild.data) block.children.pop();
 	}
 
-	if ( block.else ) {
-		trimWhitespace( block.else, trimBefore, trimAfter );
+	if (block.else) {
+		trimWhitespace(block.else, trimBefore, trimAfter);
 	}
 
-	if ( firstChild.elseif ) {
-		trimWhitespace( firstChild, trimBefore, trimAfter );
+	if (firstChild.elseif) {
+		trimWhitespace(firstChild, trimBefore, trimAfter);
 	}
 }
 
-export default function mustache ( parser: Parser ) {
+export default function mustache(parser: Parser) {
 	const start = parser.index;
 	parser.index += 2;
 
 	parser.allowWhitespace();
 
 	// {{/if}} or {{/each}}
-	if ( parser.eat( '/' ) ) {
+	if (parser.eat('/')) {
 		let block = parser.current();
 		let expected;
 
-		if ( block.type === 'ElseBlock' ) {
+		if (block.type === 'ElseBlock') {
 			block.end = start;
 			parser.stack.pop();
 			block = parser.current();
 		}
 
-		if ( block.type === 'IfBlock' ) {
+		if (block.type === 'IfBlock') {
 			expected = 'if';
-		} else if ( block.type === 'EachBlock' ) {
+		} else if (block.type === 'EachBlock') {
 			expected = 'each';
 		} else {
-			parser.error( `Unexpected block closing tag` );
+			parser.error(`Unexpected block closing tag`);
 		}
 
-		parser.eat( expected, true );
+		parser.eat(expected, true);
 		parser.allowWhitespace();
-		parser.eat( '}}', true );
+		parser.eat('}}', true);
 
-		while ( block.elseif ) {
+		while (block.elseif) {
 			block.end = parser.index;
 			parser.stack.pop();
 			block = parser.current();
 
-			if ( block.else ) {
+			if (block.else) {
 				block.else.end = start;
 			}
 		}
 
 		// strip leading/trailing whitespace as necessary
-		if ( !block.children.length ) parser.error( `Empty block`, block.start );
+		if (!block.children.length) parser.error(`Empty block`, block.start);
 
-		const charBefore = parser.template[ block.start - 1 ];
-		const charAfter = parser.template[ parser.index ];
-		const trimBefore = !charBefore || whitespace.test( charBefore );
-		const trimAfter = !charAfter || whitespace.test( charAfter );
+		const charBefore = parser.template[block.start - 1];
+		const charAfter = parser.template[parser.index];
+		const trimBefore = !charBefore || whitespace.test(charBefore);
+		const trimAfter = !charAfter || whitespace.test(charAfter);
 
-		trimWhitespace( block, trimBefore, trimAfter );
+		trimWhitespace(block, trimBefore, trimAfter);
 
 		block.end = parser.index;
 		parser.stack.pop();
-	}
-
-	else if ( parser.eat( 'elseif' ) ) {
+	} else if (parser.eat('elseif')) {
 		const block = parser.current();
-		if ( block.type !== 'IfBlock' ) parser.error( 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block' );
+		if (block.type !== 'IfBlock')
+			parser.error(
+				'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
+			);
 
 		parser.requireWhitespace();
 
-		const expression = readExpression( parser );
+		const expression = readExpression(parser);
 
 		parser.allowWhitespace();
-		parser.eat( '}}', true );
+		parser.eat('}}', true);
 
 		block.else = {
 			start: parser.index,
@@ -109,17 +110,17 @@ export default function mustache ( parser: Parser ) {
 			]
 		};
 
-		parser.stack.push( block.else.children[0] );
-	}
-
-	else if ( parser.eat( 'else' ) ) {
+		parser.stack.push(block.else.children[0]);
+	} else if (parser.eat('else')) {
 		const block = parser.current();
-		if ( block.type !== 'IfBlock' && block.type !== 'EachBlock' ) {
-			parser.error( 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block' );
+		if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
+			parser.error(
+				'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
+			);
 		}
 
 		parser.allowWhitespace();
-		parser.eat( '}}', true );
+		parser.eat('}}', true);
 
 		block.else = {
 			start: parser.index,
@@ -128,24 +129,22 @@ export default function mustache ( parser: Parser ) {
 			children: []
 		};
 
-		parser.stack.push( block.else );
-	}
-
-	// {{#if foo}} or {{#each foo}}
-	else if ( parser.eat( '#' ) ) {
+		parser.stack.push(block.else);
+	} else if (parser.eat('#')) {
+		// {{#if foo}} or {{#each foo}}
 		let type;
 
-		if ( parser.eat( 'if' ) ) {
+		if (parser.eat('if')) {
 			type = 'IfBlock';
-		} else if ( parser.eat( 'each' ) ) {
+		} else if (parser.eat('each')) {
 			type = 'EachBlock';
 		} else {
-			parser.error( `Expected if or each` );
+			parser.error(`Expected if or each`);
 		}
 
 		parser.requireWhitespace();
 
-		const expression = readExpression( parser );
+		const expression = readExpression(parser);
 
 		const block: Node = {
 			start,
@@ -158,54 +157,49 @@ export default function mustache ( parser: Parser ) {
 		parser.allowWhitespace();
 
 		// {{#each}} blocks must declare a context – {{#each list as item}}
-		if ( type === 'EachBlock' ) {
-			parser.eat( 'as', true );
+		if (type === 'EachBlock') {
+			parser.eat('as', true);
 			parser.requireWhitespace();
 
-			block.context = parser.read( validIdentifier ); // TODO check it's not a keyword
-			if ( !block.context ) parser.error( `Expected name` );
+			block.context = parser.read(validIdentifier); // TODO check it's not a keyword
+			if (!block.context) parser.error(`Expected name`);
 
 			parser.allowWhitespace();
 
-			if ( parser.eat( ',' ) ) {
+			if (parser.eat(',')) {
 				parser.allowWhitespace();
-				block.index = parser.read( validIdentifier );
-				if ( !block.index ) parser.error( `Expected name` );
+				block.index = parser.read(validIdentifier);
+				if (!block.index) parser.error(`Expected name`);
 				parser.allowWhitespace();
 			}
 
-			if ( parser.eat( '@' ) ) {
-				block.key = parser.read( validIdentifier );
-				if ( !block.key ) parser.error( `Expected name` );
+			if (parser.eat('@')) {
+				block.key = parser.read(validIdentifier);
+				if (!block.key) parser.error(`Expected name`);
 				parser.allowWhitespace();
 			}
 		}
 
-		parser.eat( '}}', true );
-
-		parser.current().children.push( block );
-		parser.stack.push( block );
-	}
-
-	// {{yield}}
-	else if ( parser.eat( 'yield' ) ) {
+		parser.eat('}}', true);
 
+		parser.current().children.push(block);
+		parser.stack.push(block);
+	} else if (parser.eat('yield')) {
+		// {{yield}}
 		parser.allowWhitespace();
-		parser.eat( '}}', true );
+		parser.eat('}}', true);
 
 		parser.current().children.push({
 			start,
 			end: parser.index,
 			type: 'YieldTag'
 		});
-	}
-
-	// {{{raw}}} mustache
-	else if ( parser.eat( '{' ) ) {
-		const expression = readExpression( parser );
+	} else if (parser.eat('{')) {
+		// {{{raw}}} mustache
+		const expression = readExpression(parser);
 
 		parser.allowWhitespace();
-		parser.eat( '}}}', true );
+		parser.eat('}}}', true);
 
 		parser.current().children.push({
 			start,
@@ -213,13 +207,11 @@ export default function mustache ( parser: Parser ) {
 			type: 'RawMustacheTag',
 			expression
 		});
-	}
-
-	else {
-		const expression = readExpression( parser );
+	} else {
+		const expression = readExpression(parser);
 
 		parser.allowWhitespace();
-		parser.eat( '}}', true );
+		parser.eat('}}', true);
 
 		parser.current().children.push({
 			start,
diff --git a/src/parse/state/tag.ts b/src/parse/state/tag.ts
index 47b8b1c7d6..ec5aaca638 100644
--- a/src/parse/state/tag.ts
+++ b/src/parse/state/tag.ts
@@ -1,7 +1,11 @@
 import readExpression from '../read/expression';
 import readScript from '../read/script';
 import readStyle from '../read/style';
-import { readEventHandlerDirective, readBindingDirective, readTransitionDirective } from '../read/directives';
+import {
+	readEventHandlerDirective,
+	readBindingDirective,
+	readTransitionDirective
+} from '../read/directives';
 import { trimStart, trimEnd } from '../../utils/trim';
 import { decodeCharacterReferences } from '../utils/html';
 import isVoidElementName from '../../utils/isVoidElementName';
@@ -16,60 +20,73 @@ const metaTags = {
 	':Window': true
 };
 
-const specials = new Map( [
-	[ 'script', {
-		read: readScript,
-		property: 'js'
-	} ],
-	[ 'style', {
-		read: readStyle,
-		property: 'css'
-	} ]
-] );
+const specials = new Map([
+	[
+		'script',
+		{
+			read: readScript,
+			property: 'js'
+		}
+	],
+	[
+		'style',
+		{
+			read: readStyle,
+			property: 'css'
+		}
+	]
+]);
 
 // based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
-const disallowedContents = new Map( [
-	[ 'li', new Set( [ 'li' ] ) ],
-	[ 'dt', new Set( [ 'dt', 'dd' ] ) ],
-	[ 'dd', new Set( [ 'dt', 'dd' ] ) ],
-	[ 'p', new Set( 'address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split( ' ' ) ) ],
-	[ 'rt', new Set( [ 'rt', 'rp' ] ) ],
-	[ 'rp', new Set( [ 'rt', 'rp' ] ) ],
-	[ 'optgroup', new Set( [ 'optgroup' ] ) ],
-	[ 'option', new Set( [ 'option', 'optgroup' ] ) ],
-	[ 'thead', new Set( [ 'tbody', 'tfoot' ] ) ],
-	[ 'tbody', new Set( [ 'tbody', 'tfoot' ] ) ],
-	[ 'tfoot', new Set( [ 'tbody' ] ) ],
-	[ 'tr', new Set( [ 'tr', 'tbody' ] ) ],
-	[ 'td', new Set( [ 'td', 'th', 'tr' ] ) ],
-	[ 'th', new Set( [ 'td', 'th', 'tr' ] ) ],
-] );
-
-function stripWhitespace ( element ) {
-	if ( element.children.length ) {
+const disallowedContents = new Map([
+	['li', new Set(['li'])],
+	['dt', new Set(['dt', 'dd'])],
+	['dd', new Set(['dt', 'dd'])],
+	[
+		'p',
+		new Set(
+			'address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split(
+				' '
+			)
+		)
+	],
+	['rt', new Set(['rt', 'rp'])],
+	['rp', new Set(['rt', 'rp'])],
+	['optgroup', new Set(['optgroup'])],
+	['option', new Set(['option', 'optgroup'])],
+	['thead', new Set(['tbody', 'tfoot'])],
+	['tbody', new Set(['tbody', 'tfoot'])],
+	['tfoot', new Set(['tbody'])],
+	['tr', new Set(['tr', 'tbody'])],
+	['td', new Set(['td', 'th', 'tr'])],
+	['th', new Set(['td', 'th', 'tr'])]
+]);
+
+function stripWhitespace(element) {
+	if (element.children.length) {
 		const firstChild = element.children[0];
-		const lastChild = element.children[ element.children.length - 1 ];
+		const lastChild = element.children[element.children.length - 1];
 
-		if ( firstChild.type === 'Text' ) {
-			firstChild.data = trimStart( firstChild.data );
-			if ( !firstChild.data ) element.children.shift();
+		if (firstChild.type === 'Text') {
+			firstChild.data = trimStart(firstChild.data);
+			if (!firstChild.data) element.children.shift();
 		}
 
-		if ( lastChild.type === 'Text' ) {
-			lastChild.data = trimEnd( lastChild.data );
-			if ( !lastChild.data ) element.children.pop();
+		if (lastChild.type === 'Text') {
+			lastChild.data = trimEnd(lastChild.data);
+			if (!lastChild.data) element.children.pop();
 		}
 	}
 }
 
-export default function tag ( parser: Parser ) {
+export default function tag(parser: Parser) {
 	const start = parser.index++;
 
 	let parent = parser.current();
 
-	if ( parser.eat( '!--' ) ) {
-		const data = parser.readUntil( /-->/ );
-		parser.eat( '-->' );
+	if (parser.eat('!--')) {
+		const data = parser.readUntil(/-->/);
+		parser.eat('-->');
 
 		parser.current().children.push({
 			start,
@@ -81,38 +98,48 @@ export default function tag ( parser: Parser ) {
 		return null;
 	}
 
-	const isClosingTag = parser.eat( '/' );
+	const isClosingTag = parser.eat('/');
 
-	const name = readTagName( parser );
+	const name = readTagName(parser);
 
-	if ( name in metaTags ) {
-		if ( name in parser.metaTags ) {
-			if ( isClosingTag && parser.current().children.length ) {
-				parser.error( `<${name}> cannot have children`, parser.current().children[0].start );
+	if (name in metaTags) {
+		if (name in parser.metaTags) {
+			if (isClosingTag && parser.current().children.length) {
+				parser.error(
+					`<${name}> cannot have children`,
+					parser.current().children[0].start
+				);
 			}
 
-			parser.error( `A component can only have one <${name}> tag`, start );
+			parser.error(`A component can only have one <${name}> tag`, start);
 		}
 
-		parser.metaTags[ name ] = true;
+		parser.metaTags[name] = true;
 
-		if ( parser.stack.length > 1 ) {
-			parser.error( `<${name}> tags cannot be inside elements or blocks`, start );
+		if (parser.stack.length > 1) {
+			parser.error(`<${name}> tags cannot be inside elements or blocks`, start);
 		}
 	}
 
 	parser.allowWhitespace();
 
-	if ( isClosingTag ) {
-		if ( isVoidElementName( name ) ) {
-			parser.error( `<${name}> is a void element and cannot have children, or a closing tag`, start );
+	if (isClosingTag) {
+		if (isVoidElementName(name)) {
+			parser.error(
+				`<${name}> is a void element and cannot have children, or a closing tag`,
+				start
+			);
 		}
 
-		if ( !parser.eat( '>' ) ) parser.error( `Expected '>'` );
+		if (!parser.eat('>')) parser.error(`Expected '>'`);
 
 		// close any elements that don't have their own closing tags, e.g. <div><p></div>
-		while ( parent.name !== name ) {
-			if ( parent.type !== 'Element' ) parser.error( `</${name}> attempted to close an element that was not open`, start );
+		while (parent.name !== name) {
+			if (parent.type !== 'Element')
+				parser.error(
+					`</${name}> attempted to close an element that was not open`,
+					start
+				);
 
 			parent.end = start;
 			parser.stack.pop();
@@ -121,17 +148,17 @@ export default function tag ( parser: Parser ) {
 		}
 
 		// strip leading/trailing whitespace as necessary
-		stripWhitespace( parent );
+		stripWhitespace(parent);
 
 		parent.end = parser.index;
 		parser.stack.pop();
 
 		return null;
-	} else if ( disallowedContents.has( parent.name ) ) {
+	} else if (disallowedContents.has(parent.name)) {
 		// can this be a child of the parent element, or does it implicitly
 		// close it, like `<li>one<li>two`?
-		if ( disallowedContents.get( parent.name ).has( name ) ) {
-			stripWhitespace( parent );
+		if (disallowedContents.get(parent.name).has(name)) {
+			stripWhitespace(parent);
 
 			parent.end = start;
 			parser.stack.pop();
@@ -142,24 +169,26 @@ export default function tag ( parser: Parser ) {
 	const uniqueNames = new Set();
 
 	let attribute;
-	while ( attribute = readAttribute( parser, uniqueNames ) ) {
-		attributes.push( attribute );
+	while ((attribute = readAttribute(parser, uniqueNames))) {
+		attributes.push(attribute);
 		parser.allowWhitespace();
 	}
 
 	parser.allowWhitespace();
 
 	// special cases – top-level <script> and <style>
-	if ( specials.has( name ) && parser.stack.length === 1 ) {
-		const special = specials.get( name );
+	if (specials.has(name) && parser.stack.length === 1) {
+		const special = specials.get(name);
 
-		if ( parser[ special.property ] ) {
+		if (parser[special.property]) {
 			parser.index = start;
-			parser.error( `You can only have one top-level <${name}> tag per component` );
+			parser.error(
+				`You can only have one top-level <${name}> tag per component`
+			);
 		}
 
-		parser.eat( '>', true );
-		parser[ special.property ] = special.read( parser, start, attributes );
+		parser.eat('>', true);
+		parser[special.property] = special.read(parser, start, attributes);
 		return;
 	}
 
@@ -172,106 +201,118 @@ export default function tag ( parser: Parser ) {
 		children: []
 	};
 
-	parser.current().children.push( element );
+	parser.current().children.push(element);
 
-	const selfClosing = parser.eat( '/' ) || isVoidElementName( name );
+	const selfClosing = parser.eat('/') || isVoidElementName(name);
 
-	parser.eat( '>', true );
+	parser.eat('>', true);
 
-	if ( selfClosing ) {
+	if (selfClosing) {
 		element.end = parser.index;
-	} else if ( name === 'textarea' ) {
+	} else if (name === 'textarea') {
 		// special case
-		element.children = readSequence( parser, () => parser.template.slice( parser.index, parser.index + 11 ) === '</textarea>' );
-		parser.read( /<\/textarea>/ );
+		element.children = readSequence(
+			parser,
+			() =>
+				parser.template.slice(parser.index, parser.index + 11) === '</textarea>'
+		);
+		parser.read(/<\/textarea>/);
 		element.end = parser.index;
 	} else {
 		// don't push self-closing elements onto the stack
-		parser.stack.push( element );
+		parser.stack.push(element);
 	}
 
 	return null;
 }
 
-function readTagName ( parser: Parser ) {
+function readTagName(parser: Parser) {
 	const start = parser.index;
 
-	if ( parser.eat( SELF ) ) {
+	if (parser.eat(SELF)) {
 		// check we're inside a block, otherwise this
 		// will cause infinite recursion
 		let i = parser.stack.length;
 		let legal = false;
 
-		while ( i-- ) {
+		while (i--) {
 			const fragment = parser.stack[i];
-			if ( fragment.type === 'IfBlock' || fragment.type === 'EachBlock' ) {
+			if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock') {
 				legal = true;
 				break;
 			}
 		}
 
-		if ( !legal ) {
-			parser.error( `<${SELF}> components can only exist inside if-blocks or each-blocks`, start );
+		if (!legal) {
+			parser.error(
+				`<${SELF}> components can only exist inside if-blocks or each-blocks`,
+				start
+			);
 		}
 
 		return SELF;
 	}
 
-	const name = parser.readUntil( /(\s|\/|>)/ );
+	const name = parser.readUntil(/(\s|\/|>)/);
 
-	if ( name in metaTags ) return name;
+	if (name in metaTags) return name;
 
-	if ( !validTagName.test( name ) ) {
-		parser.error( `Expected valid tag name`, start );
+	if (!validTagName.test(name)) {
+		parser.error(`Expected valid tag name`, start);
 	}
 
 	return name;
 }
 
-function readAttribute ( parser: Parser, uniqueNames ) {
+function readAttribute(parser: Parser, uniqueNames) {
 	const start = parser.index;
 
-	let name = parser.readUntil( /(\s|=|\/|>)/ );
-	if ( !name ) return null;
-	if ( uniqueNames.has( name ) ) {
-		parser.error( 'Attributes need to be unique', start );
+	let name = parser.readUntil(/(\s|=|\/|>)/);
+	if (!name) return null;
+	if (uniqueNames.has(name)) {
+		parser.error('Attributes need to be unique', start);
 	}
 
-	uniqueNames.add( name );
+	uniqueNames.add(name);
 
 	parser.allowWhitespace();
 
-	if ( /^on:/.test( name ) ) {
-		parser.eat( '=', true );
-		return readEventHandlerDirective( parser, start, name.slice( 3 ) );
+	if (/^on:/.test(name)) {
+		parser.eat('=', true);
+		return readEventHandlerDirective(parser, start, name.slice(3));
 	}
 
-	if ( /^bind:/.test( name ) ) {
-		return readBindingDirective( parser, start, name.slice( 5 ) );
+	if (/^bind:/.test(name)) {
+		return readBindingDirective(parser, start, name.slice(5));
 	}
 
-	if ( /^ref:/.test( name ) ) {
+	if (/^ref:/.test(name)) {
 		return {
 			start,
 			end: parser.index,
 			type: 'Ref',
-			name: name.slice( 4 )
+			name: name.slice(4)
 		};
 	}
 
-	const match = /^(in|out|transition):/.exec( name );
-	if ( match ) {
-		return readTransitionDirective( parser, start, name.slice( match[0].length ), match[1] );
+	const match = /^(in|out|transition):/.exec(name);
+	if (match) {
+		return readTransitionDirective(
+			parser,
+			start,
+			name.slice(match[0].length),
+			match[1]
+		);
 	}
 
 	let value;
 
 	// :foo is shorthand for foo='{{foo}}'
-	if ( /^:\w+$/.test( name ) ) {
-		name = name.slice( 1 );
-		value = getShorthandValue( start + 1, name );
+	if (/^:\w+$/.test(name)) {
+		name = name.slice(1);
+		value = getShorthandValue(start + 1, name);
 	} else {
-		value = parser.eat( '=' ) ? readAttributeValue( parser ) : true;
+		value = parser.eat('=') ? readAttributeValue(parser) : true;
 	}
 
 	return {
@@ -283,42 +324,40 @@ function readAttribute ( parser: Parser, uniqueNames ) {
 	};
 }
 
-function readAttributeValue ( parser: Parser ) {
-	const quoteMark = (
-		parser.eat( `'` ) ? `'` :
-		parser.eat( `"` ) ? `"` :
-		null
-	);
+function readAttributeValue(parser: Parser) {
+	const quoteMark = parser.eat(`'`) ? `'` : parser.eat(`"`) ? `"` : null;
 
-	const regex = (
-		quoteMark === `'` ? /'/ :
-		quoteMark === `"` ? /"/ :
-		/[\s"'=<>\/`]/
-	);
+	const regex = quoteMark === `'`
+		? /'/
+		: quoteMark === `"` ? /"/ : /[\s"'=<>\/`]/;
 
-	const value = readSequence( parser, () => regex.test( parser.template[ parser.index ] ) );
+	const value = readSequence(parser, () =>
+		regex.test(parser.template[parser.index])
+	);
 
-	if ( quoteMark ) parser.index += 1;
+	if (quoteMark) parser.index += 1;
 	return value;
 }
 
-function getShorthandValue ( start: number, name: string ) {
+function getShorthandValue(start: number, name: string) {
 	const end = start + name.length;
 
-	return [{
-		type: 'AttributeShorthand',
-		start,
-		end,
-		expression: {
-			type: 'Identifier',
+	return [
+		{
+			type: 'AttributeShorthand',
 			start,
 			end,
-			name
+			expression: {
+				type: 'Identifier',
+				start,
+				end,
+				name
+			}
 		}
-	}];
+	];
 }
 
-function readSequence ( parser: Parser, done: () => boolean ) {
+function readSequence(parser: Parser, done: () => boolean) {
 	let currentChunk: Node = {
 		start: parser.index,
 		end: null,
@@ -328,31 +367,30 @@ function readSequence ( parser: Parser, done: () => boolean ) {
 
 	const chunks = [];
 
-	while ( parser.index < parser.template.length ) {
+	while (parser.index < parser.template.length) {
 		const index = parser.index;
 
-		if ( done() ) {
+		if (done()) {
 			currentChunk.end = parser.index;
 
-			if ( currentChunk.data ) chunks.push( currentChunk );
+			if (currentChunk.data) chunks.push(currentChunk);
 
-			chunks.forEach( chunk => {
-				if ( chunk.type === 'Text' ) chunk.data = decodeCharacterReferences( chunk.data );
+			chunks.forEach(chunk => {
+				if (chunk.type === 'Text')
+					chunk.data = decodeCharacterReferences(chunk.data);
 			});
 
 			return chunks;
-		}
-
-		else if ( parser.eat( '{{' ) ) {
-			if ( currentChunk.data ) {
+		} else if (parser.eat('{{')) {
+			if (currentChunk.data) {
 				currentChunk.end = index;
-				chunks.push( currentChunk );
+				chunks.push(currentChunk);
 			}
 
-			const expression = readExpression( parser );
+			const expression = readExpression(parser);
 			parser.allowWhitespace();
-			if ( !parser.eat( '}}' ) ) {
-				parser.error( `Expected }}` );
+			if (!parser.eat('}}')) {
+				parser.error(`Expected }}`);
 			}
 
 			chunks.push({
@@ -368,12 +406,10 @@ function readSequence ( parser: Parser, done: () => boolean ) {
 				type: 'Text',
 				data: ''
 			};
-		}
-
-		else {
-			currentChunk.data += parser.template[ parser.index++ ];
+		} else {
+			currentChunk.data += parser.template[parser.index++];
 		}
 	}
 
-	parser.error( `Unexpected end of input` );
-}
\ No newline at end of file
+	parser.error(`Unexpected end of input`);
+}
diff --git a/src/parse/state/text.ts b/src/parse/state/text.ts
index cc46772556..a59e00e15f 100644
--- a/src/parse/state/text.ts
+++ b/src/parse/state/text.ts
@@ -1,20 +1,24 @@
 import { decodeCharacterReferences } from '../utils/html';
 import { Parser } from '../index';
 
-export default function text ( parser: Parser ) {
+export default function text(parser: Parser) {
 	const start = parser.index;
 
 	let data = '';
 
-	while ( parser.index < parser.template.length && !parser.match( '<' ) && !parser.match( '{{' ) ) {
-		data += parser.template[ parser.index++ ];
+	while (
+		parser.index < parser.template.length &&
+		!parser.match('<') &&
+		!parser.match('{{')
+	) {
+		data += parser.template[parser.index++];
 	}
 
 	parser.current().children.push({
 		start,
 		end: parser.index,
 		type: 'Text',
-		data: decodeCharacterReferences( data )
+		data: decodeCharacterReferences(data)
 	});
 
 	return null;
diff --git a/src/parse/utils/entities.ts b/src/parse/utils/entities.ts
index 4b3c924aff..7b43ced2c1 100644
--- a/src/parse/utils/entities.ts
+++ b/src/parse/utils/entities.ts
@@ -2031,4 +2031,4 @@ export default {
 	wp: 8472,
 	wr: 8768,
 	xi: 958
-};
\ No newline at end of file
+};
diff --git a/src/parse/utils/hash.ts b/src/parse/utils/hash.ts
index 02f98dd20a..8f2221ee49 100644
--- a/src/parse/utils/hash.ts
+++ b/src/parse/utils/hash.ts
@@ -1,8 +1,8 @@
 // https://github.com/darkskyapp/string-hash/blob/master/index.js
-export default function hash ( str: string ) :number {
+export default function hash(str: string): number {
 	let hash = 5381;
 	let i = str.length;
 
-	while ( i-- ) hash = ( hash * 33 ) ^ str.charCodeAt( i );
+	while (i--) hash = (hash * 33) ^ str.charCodeAt(i);
 	return hash >>> 0;
 }
diff --git a/src/parse/utils/html.ts b/src/parse/utils/html.ts
index 4b06db0723..3b26f3bc73 100644
--- a/src/parse/utils/html.ts
+++ b/src/parse/utils/html.ts
@@ -1,26 +1,62 @@
 import htmlEntities from './entities';
 
-const windows1252 = [ 8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376 ];
-const entityPattern = new RegExp( `&(#?(?:x[\\w\\d]+|\\d+|${Object.keys( htmlEntities ).join( '|' )}));?`, 'g' );
+const windows1252 = [
+	8364,
+	129,
+	8218,
+	402,
+	8222,
+	8230,
+	8224,
+	8225,
+	710,
+	8240,
+	352,
+	8249,
+	338,
+	141,
+	381,
+	143,
+	144,
+	8216,
+	8217,
+	8220,
+	8221,
+	8226,
+	8211,
+	8212,
+	732,
+	8482,
+	353,
+	8250,
+	339,
+	157,
+	382,
+	376
+];
+const entityPattern = new RegExp(
+	`&(#?(?:x[\\w\\d]+|\\d+|${Object.keys(htmlEntities).join('|')}));?`,
+	'g'
+);
 
-export function decodeCharacterReferences ( html: string ) {
-	return html.replace( entityPattern, ( match, entity ) => {
+export function decodeCharacterReferences(html: string) {
+	return html.replace(entityPattern, (match, entity) => {
 		let code;
 
 		// Handle named entities
-		if ( entity[0] !== '#' ) {
-			code = htmlEntities[ entity ];
-		} else if ( entity[1] === 'x' ) {
-			code = parseInt( entity.substring( 2 ), 16 );
+		if (entity[0] !== '#') {
+			code = htmlEntities[entity];
+		} else if (entity[1] === 'x') {
+			code = parseInt(entity.substring(2), 16);
 		} else {
-			code = parseInt( entity.substring( 1 ), 10 );
+			code = parseInt(entity.substring(1), 10);
 		}
 
-		if ( !code ) {
+		if (!code) {
 			return match;
 		}
 
-		return String.fromCodePoint( validateCode( code ) );
+		return String.fromCodePoint(validateCode(code));
 	});
 }
 
@@ -31,45 +67,45 @@ const NUL = 0;
 // to replace them ourselves
 //
 // Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
-function validateCode ( code: number ) {
+function validateCode(code: number) {
 	// line feed becomes generic whitespace
-	if ( code === 10 ) {
+	if (code === 10) {
 		return 32;
 	}
 
 	// ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
-	if ( code < 128 ) {
+	if (code < 128) {
 		return code;
 	}
 
 	// code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
 	// to correct the mistake or we'll end up with missing € signs and so on
-	if ( code <= 159 ) {
-		return windows1252[ code - 128 ];
+	if (code <= 159) {
+		return windows1252[code - 128];
 	}
 
 	// basic multilingual plane
-	if ( code < 55296 ) {
+	if (code < 55296) {
 		return code;
 	}
 
 	// UTF-16 surrogate halves
-	if ( code <= 57343 ) {
+	if (code <= 57343) {
 		return NUL;
 	}
 
 	// rest of the basic multilingual plane
-	if ( code <= 65535 ) {
+	if (code <= 65535) {
 		return code;
 	}
 
 	// supplementary multilingual plane 0x10000 - 0x1ffff
-	if ( code >= 65536 && code <= 131071 ) {
+	if (code >= 65536 && code <= 131071) {
 		return code;
 	}
 
 	// supplementary ideographic plane 0x20000 - 0x2ffff
-	if ( code >= 131072 && code <= 196607 ) {
+	if (code >= 131072 && code <= 196607) {
 		return code;
 	}
 
diff --git a/src/server-side-rendering/register.js b/src/server-side-rendering/register.js
index 3a1ca58030..442888e99e 100644
--- a/src/server-side-rendering/register.js
+++ b/src/server-side-rendering/register.js
@@ -2,16 +2,16 @@ import * as fs from 'fs';
 import * as path from 'path';
 import { compile } from '../index.ts';
 
-function capitalise ( name ) {
-	return name[0].toUpperCase() + name.slice( 1 );
+function capitalise(name) {
+	return name[0].toUpperCase() + name.slice(1);
 }
 
-require.extensions[ '.html' ] = function ( module, filename ) {
-	const { code } = compile( fs.readFileSync( filename, 'utf-8' ), {
+require.extensions['.html'] = function(module, filename) {
+	const { code } = compile(fs.readFileSync(filename, 'utf-8'), {
 		filename,
-		name: capitalise( path.basename( filename ).replace( /\.html$/, '' ) ),
+		name: capitalise(path.basename(filename).replace(/\.html$/, '')),
 		generate: 'ssr'
 	});
 
-	return module._compile( code, filename );
+	return module._compile(code, filename);
 };
diff --git a/src/shared/_build.js b/src/shared/_build.js
index 3d8f1f3ae6..3bbf0298ff 100644
--- a/src/shared/_build.js
+++ b/src/shared/_build.js
@@ -1,35 +1,38 @@
-const fs = require( 'fs' );
-const path = require( 'path' );
-const acorn = require( 'acorn' );
+const fs = require('fs');
+const path = require('path');
+const acorn = require('acorn');
 
 const declarations = {};
 
-fs.readdirSync( __dirname ).forEach( file => {
-	if ( !/^[a-z]+\.js$/.test( file ) ) return;
+fs.readdirSync(__dirname).forEach(file => {
+	if (!/^[a-z]+\.js$/.test(file)) return;
 
-	const source = fs.readFileSync( path.join( __dirname, file ), 'utf-8' );
-	const ast = acorn.parse( source, {
+	const source = fs.readFileSync(path.join(__dirname, file), 'utf-8');
+	const ast = acorn.parse(source, {
 		ecmaVersion: 6,
 		sourceType: 'module'
 	});
 
-	ast.body.forEach( node => {
-		if ( node.type !== 'ExportNamedDeclaration' ) return;
+	ast.body.forEach(node => {
+		if (node.type !== 'ExportNamedDeclaration') return;
 
 		const declaration = node.declaration;
-		if ( !declaration ) return;
+		if (!declaration) return;
 
-		const name = declaration.type === 'VariableDeclaration' ?
-			declaration.declarations[0].id.name :
-			declaration.id.name;
+		const name = declaration.type === 'VariableDeclaration'
+			? declaration.declarations[0].id.name
+			: declaration.id.name;
 
-		const value = declaration.type === 'VariableDeclaration' ?
-			declaration.declarations[0].init :
-			declaration;
+		const value = declaration.type === 'VariableDeclaration'
+			? declaration.declarations[0].init
+			: declaration;
 
-		declarations[ name ] = source.slice( value.start, value.end );
+		declarations[name] = source.slice(value.start, value.end);
 	});
 });
 
-fs.writeFileSync( 'src/generators/dom/shared.ts', `// this file is auto-generated, do not edit it
-export default ${JSON.stringify( declarations, null, '\t' )};` );
\ No newline at end of file
+fs.writeFileSync(
+	'src/generators/dom/shared.ts',
+	`// this file is auto-generated, do not edit it
+export default ${JSON.stringify(declarations, null, '\t')};`
+);
diff --git a/src/shared/dom.js b/src/shared/dom.js
index 97c227e7f7..11f178317b 100644
--- a/src/shared/dom.js
+++ b/src/shared/dom.js
@@ -1,68 +1,68 @@
-export function appendNode ( node, target ) {
-	target.appendChild( node );
+export function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-export function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+export function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-export function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+export function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-export function detachBetween ( before, after ) {
-	while ( before.nextSibling && before.nextSibling !== after ) {
-		before.parentNode.removeChild( before.nextSibling );
+export function detachBetween(before, after) {
+	while (before.nextSibling && before.nextSibling !== after) {
+		before.parentNode.removeChild(before.nextSibling);
 	}
 }
 
 // TODO this is out of date
-export function destroyEach ( iterations, detach, start ) {
-	for ( var i = start; i < iterations.length; i += 1 ) {
-		if ( iterations[i] ) iterations[i].destroy( detach );
+export function destroyEach(iterations, detach, start) {
+	for (var i = start; i < iterations.length; i += 1) {
+		if (iterations[i]) iterations[i].destroy(detach);
 	}
 }
 
-export function createElement ( name ) {
-	return document.createElement( name );
+export function createElement(name) {
+	return document.createElement(name);
 }
 
-export function createSvgElement ( name ) {
-	return document.createElementNS( 'http://www.w3.org/2000/svg', name );
+export function createSvgElement(name) {
+	return document.createElementNS('http://www.w3.org/2000/svg', name);
 }
 
-export function createText ( data ) {
-	return document.createTextNode( data );
+export function createText(data) {
+	return document.createTextNode(data);
 }
 
-export function createComment () {
-	return document.createComment( '' );
+export function createComment() {
+	return document.createComment('');
 }
 
-export function addEventListener ( node, event, handler ) {
-	node.addEventListener( event, handler, false );
+export function addEventListener(node, event, handler) {
+	node.addEventListener(event, handler, false);
 }
 
-export function removeEventListener ( node, event, handler ) {
-	node.removeEventListener( event, handler, false );
+export function removeEventListener(node, event, handler) {
+	node.removeEventListener(event, handler, false);
 }
 
-export function setAttribute ( node, attribute, value ) {
-	node.setAttribute( attribute, value );
+export function setAttribute(node, attribute, value) {
+	node.setAttribute(attribute, value);
 }
 
-export function setXlinkAttribute ( node, attribute, value ) {
-	node.setAttributeNS( 'http://www.w3.org/1999/xlink', attribute, value );
+export function setXlinkAttribute(node, attribute, value) {
+	node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
 }
 
-export function getBindingGroupValue ( group ) {
+export function getBindingGroupValue(group) {
 	var value = [];
-	for ( var i = 0; i < group.length; i += 1 ) {
-		if ( group[i].checked ) value.push( group[i].__value );
+	for (var i = 0; i < group.length; i += 1) {
+		if (group[i].checked) value.push(group[i].__value);
 	}
 	return value;
 }
 
-export function toNumber ( value ) {
+export function toNumber(value) {
 	return value === '' ? undefined : +value;
-}
\ No newline at end of file
+}
diff --git a/src/shared/index.js b/src/shared/index.js
index d31bbffc17..b7b5ff7b64 100644
--- a/src/shared/index.js
+++ b/src/shared/index.js
@@ -3,109 +3,116 @@ export * from './dom.js';
 export * from './transitions.js';
 export * from './utils.js';
 
-export function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+export function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-export function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+export function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-export function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+export function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-export function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+export function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-export function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+export function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-export function observeDev ( key, callback, options ) {
-	var c = ( key = '' + key ).search( /[^\w]/ );
-	if ( c > -1 ) {
-		var message = "The first argument to component.observe(...) must be the name of a top-level property";
-		if ( c > 0 ) message += ", i.e. '" + key.slice( 0, c ) + "' rather than '" + key + "'";
+export function observeDev(key, callback, options) {
+	var c = (key = '' + key).search(/[^\w]/);
+	if (c > -1) {
+		var message =
+			'The first argument to component.observe(...) must be the name of a top-level property';
+		if (c > 0)
+			message += ", i.e. '" + key.slice(0, c) + "' rather than '" + key + "'";
 
-		throw new Error( message );
+		throw new Error(message);
 	}
 
-	return observe.call( this, key, callback, options );
+	return observe.call(this, key, callback, options);
 }
 
-export function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+export function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-export function onDev ( eventName, handler ) {
-	if ( eventName === 'teardown' ) {
-		console.warn( "Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2" );
-		return this.on( 'destroy', handler );
+export function onDev(eventName, handler) {
+	if (eventName === 'teardown') {
+		console.warn(
+			"Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2"
+		);
+		return this.on('destroy', handler);
 	}
 
-	return on.call( this, eventName, handler );
+	return on.call(this, eventName, handler);
 }
 
-export function set ( newState ) {
-	this._set( assign( {}, newState ) );
+export function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-export function _flush () {
-	if ( !this._renderHooks ) return;
+export function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/src/shared/transitions.js b/src/shared/transitions.js
index 1fe7aa28e6..ded3a35b4d 100644
--- a/src/shared/transitions.js
+++ b/src/shared/transitions.js
@@ -1,50 +1,60 @@
 import { assign, noop } from './utils.js';
 
-export function linear ( t ) {
+export function linear(t) {
 	return t;
 }
 
-export function generateKeyframes ( a, b, delta, duration, ease, fn, node, style ) {
-	var id = '__svelte' + ~~( Math.random() * 1e9 ); // TODO make this more robust
+export function generateKeyframes(
+	a,
+	b,
+	delta,
+	duration,
+	ease,
+	fn,
+	node,
+	style
+) {
+	var id = '__svelte' + ~~(Math.random() * 1e9); // TODO make this more robust
 	var keyframes = '@keyframes ' + id + '{\n';
 
-	for ( var p = 0; p <= 1; p += 16.666 / duration ) {
-		var t = a + delta * ease( p );
-		keyframes += ( p * 100 ) + '%{' + fn( t ) + '}\n';
+	for (var p = 0; p <= 1; p += 16.666 / duration) {
+		var t = a + delta * ease(p);
+		keyframes += p * 100 + '%{' + fn(t) + '}\n';
 	}
 
-	keyframes += '100% {' + fn( b ) + '}\n}';
+	keyframes += '100% {' + fn(b) + '}\n}';
 	style.textContent += keyframes;
 
-	document.head.appendChild( style );
+	document.head.appendChild(style);
 
-	node.style.animation = ( node.style.animation || '' ).split( ',' )
-		.filter( function ( anim ) {
+	node.style.animation = (node.style.animation || '')
+		.split(',')
+		.filter(function(anim) {
 			// when introing, discard old animations if there are any
-			return anim && ( delta < 0 || !/__svelte/.test( anim ) );
+			return anim && (delta < 0 || !/__svelte/.test(anim));
 		})
-		.concat( id + ' ' + duration + 'ms linear 1 forwards' )
-		.join( ', ' );
+		.concat(id + ' ' + duration + 'ms linear 1 forwards')
+		.join(', ');
 }
 
-export function wrapTransition ( node, fn, params, intro, outgroup ) {
-	var obj = fn( node, params );
+export function wrapTransition(node, fn, params, intro, outgroup) {
+	var obj = fn(node, params);
 	var duration = obj.duration || 300;
 	var ease = obj.easing || linear;
 	var cssText;
 
 	// TODO share <style> tag between all transitions?
-	if ( obj.css ) {
-		var style = document.createElement( 'style' );
+	if (obj.css) {
+		var style = document.createElement('style');
 	}
 
-	if ( intro ) {
-		if ( obj.css && obj.delay ) {
+	if (intro) {
+		if (obj.css && obj.delay) {
 			cssText = node.style.cssText;
-			node.style.cssText += obj.css( 0 );
+			node.style.cssText += obj.css(0);
 		}
 
-		if ( obj.tick ) obj.tick( 0 );
+		if (obj.tick) obj.tick(0);
 	}
 
 	return {
@@ -52,58 +62,67 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) {
 		running: false,
 		program: null,
 		pending: null,
-		run: function ( intro, callback ) {
+		run: function(intro, callback) {
 			var program = {
-				start: window.performance.now() + ( obj.delay || 0 ),
+				start: window.performance.now() + (obj.delay || 0),
 				intro: intro,
 				callback: callback
 			};
 
-			if ( obj.delay ) {
+			if (obj.delay) {
 				this.pending = program;
 			} else {
-				this.start( program );
+				this.start(program);
 			}
 
-			if ( !this.running ) {
+			if (!this.running) {
 				this.running = true;
-				transitionManager.add( this );
+				transitionManager.add(this);
 			}
 		},
-		start: function ( program ) {
+		start: function(program) {
 			program.a = this.t;
 			program.b = program.intro ? 1 : 0;
 			program.delta = program.b - program.a;
-			program.duration = duration * Math.abs( program.b - program.a );
+			program.duration = duration * Math.abs(program.b - program.a);
 			program.end = program.start + program.duration;
 
-			if ( obj.css ) {
-				if ( obj.delay ) node.style.cssText = cssText;
-				generateKeyframes( program.a, program.b, program.delta, program.duration, ease, obj.css, node, style );
+			if (obj.css) {
+				if (obj.delay) node.style.cssText = cssText;
+				generateKeyframes(
+					program.a,
+					program.b,
+					program.delta,
+					program.duration,
+					ease,
+					obj.css,
+					node,
+					style
+				);
 			}
 
 			this.program = program;
 			this.pending = null;
 		},
-		update: function ( now ) {
+		update: function(now) {
 			var program = this.program;
-			if ( !program ) return;
+			if (!program) return;
 
 			var p = now - program.start;
-			this.t = program.a + program.delta * ease( p / program.duration );
-			if ( obj.tick ) obj.tick( this.t );
+			this.t = program.a + program.delta * ease(p / program.duration);
+			if (obj.tick) obj.tick(this.t);
 		},
-		done: function () {
+		done: function() {
 			this.t = this.program.b;
-			if ( obj.tick ) obj.tick( this.t );
-			if ( obj.css ) document.head.removeChild( style );
+			if (obj.tick) obj.tick(this.t);
+			if (obj.css) document.head.removeChild(style);
 			this.program.callback();
 			this.program = null;
 			this.running = !!this.pending;
 		},
-		abort: function () {
-			if ( obj.tick ) obj.tick( 1 );
-			if ( obj.css ) document.head.removeChild( style );
+		abort: function() {
+			if (obj.tick) obj.tick(1);
+			if (obj.css) document.head.removeChild(style);
 			this.program = this.pending = null;
 			this.running = false;
 		}
@@ -115,42 +134,42 @@ export var transitionManager = {
 	transitions: [],
 	bound: null,
 
-	add: function ( transition ) {
-		this.transitions.push( transition );
+	add: function(transition) {
+		this.transitions.push(transition);
 
-		if ( !this.running ) {
+		if (!this.running) {
 			this.running = true;
 			this.next();
 		}
 	},
 
-	next: function () {
+	next: function() {
 		this.running = false;
 
 		var now = window.performance.now();
 		var i = this.transitions.length;
 
-		while ( i-- ) {
+		while (i--) {
 			var transition = this.transitions[i];
 
-			if ( transition.program && now >= transition.program.end ) {
+			if (transition.program && now >= transition.program.end) {
 				transition.done();
 			}
 
-			if ( transition.pending && now >= transition.pending.start ) {
-				transition.start( transition.pending );
+			if (transition.pending && now >= transition.pending.start) {
+				transition.start(transition.pending);
 			}
 
-			if ( transition.running ) {
-				transition.update( now );
+			if (transition.running) {
+				transition.update(now);
 				this.running = true;
-			} else if ( !transition.pending ) {
-				this.transitions.splice( i, 1 );
+			} else if (!transition.pending) {
+				this.transitions.splice(i, 1);
 			}
 		}
 
-		if ( this.running ) {
-			requestAnimationFrame( this.bound || ( this.bound = this.next.bind( this ) ) );
+		if (this.running) {
+			requestAnimationFrame(this.bound || (this.bound = this.next.bind(this)));
 		}
 	}
-};
\ No newline at end of file
+};
diff --git a/src/shared/utils.js b/src/shared/utils.js
index 9eb3ed2cee..4cf2f32a1d 100644
--- a/src/shared/utils.js
+++ b/src/shared/utils.js
@@ -1,10 +1,13 @@
-export function noop () {}
+export function noop() {}
 
-export function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+export function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
diff --git a/src/utils/CodeBuilder.ts b/src/utils/CodeBuilder.ts
index 79c36a96c6..92c88ea483 100644
--- a/src/utils/CodeBuilder.ts
+++ b/src/utils/CodeBuilder.ts
@@ -4,26 +4,28 @@ enum ChunkType {
 }
 
 export default class CodeBuilder {
-	result: string
-	first: ChunkType
-	last: ChunkType
-	lastCondition: string
+	result: string;
+	first: ChunkType;
+	last: ChunkType;
+	lastCondition: string;
 
-	constructor ( str = '' ) {
+	constructor(str = '') {
 		this.result = str;
 
-		const initial = str ? ( /\n/.test( str ) ? ChunkType.Block : ChunkType.Line ) : null;
+		const initial = str
+			? /\n/.test(str) ? ChunkType.Block : ChunkType.Line
+			: null;
 		this.first = initial;
 		this.last = initial;
 
 		this.lastCondition = null;
 	}
 
-	addConditionalLine ( condition: string, line: string ) {
-		if ( condition === this.lastCondition ) {
+	addConditionalLine(condition: string, line: string) {
+		if (condition === this.lastCondition) {
 			this.result += `\n\t${line}`;
 		} else {
-			if ( this.lastCondition ) {
+			if (this.lastCondition) {
 				this.result += `\n}\n\n`;
 			}
 
@@ -34,69 +36,69 @@ export default class CodeBuilder {
 		this.last = ChunkType.Block;
 	}
 
-	addLine ( line: string ) {
-		if ( this.lastCondition ) {
+	addLine(line: string) {
+		if (this.lastCondition) {
 			this.result += `\n}`;
 			this.lastCondition = null;
 		}
 
-		if ( this.last === ChunkType.Block ) {
+		if (this.last === ChunkType.Block) {
 			this.result += `\n\n${line}`;
-		} else if ( this.last === ChunkType.Line ) {
+		} else if (this.last === ChunkType.Line) {
 			this.result += `\n${line}`;
 		} else {
 			this.result += line;
 		}
 
 		this.last = ChunkType.Line;
-		if ( !this.first ) this.first = ChunkType.Line;
+		if (!this.first) this.first = ChunkType.Line;
 	}
 
-	addLineAtStart ( line: string ) {
-		if ( this.first === ChunkType.Block ) {
+	addLineAtStart(line: string) {
+		if (this.first === ChunkType.Block) {
 			this.result = `${line}\n\n${this.result}`;
-		} else if ( this.first === ChunkType.Line ) {
+		} else if (this.first === ChunkType.Line) {
 			this.result = `${line}\n${this.result}`;
 		} else {
 			this.result += line;
 		}
 
 		this.first = ChunkType.Line;
-		if ( !this.last ) this.last = ChunkType.Line;
+		if (!this.last) this.last = ChunkType.Line;
 	}
 
-	addBlock ( block: string ) {
-		if ( this.lastCondition ) {
+	addBlock(block: string) {
+		if (this.lastCondition) {
 			this.result += `\n}`;
 			this.lastCondition = null;
 		}
 
-		if ( this.result ) {
+		if (this.result) {
 			this.result += `\n\n${block}`;
 		} else {
 			this.result += block;
 		}
 
 		this.last = ChunkType.Block;
-		if ( !this.first ) this.first = ChunkType.Block;
+		if (!this.first) this.first = ChunkType.Block;
 	}
 
-	addBlockAtStart ( block: string ) {
-		if ( this.result ) {
+	addBlockAtStart(block: string) {
+		if (this.result) {
 			this.result = `${block}\n\n${this.result}`;
 		} else {
 			this.result += block;
 		}
 
 		this.first = ChunkType.Block;
-		if ( !this.last ) this.last = ChunkType.Block;
+		if (!this.last) this.last = ChunkType.Block;
 	}
 
-	isEmpty () {
+	isEmpty() {
 		return this.result === '';
 	}
 
-	toString () {
-		return this.result.trim() + ( this.lastCondition ? `\n}` : `` );
+	toString() {
+		return this.result.trim() + (this.lastCondition ? `\n}` : ``);
 	}
 }
diff --git a/src/utils/CompileError.ts b/src/utils/CompileError.ts
index 85d713dc79..1af9b39c2f 100644
--- a/src/utils/CompileError.ts
+++ b/src/utils/CompileError.ts
@@ -2,24 +2,30 @@ import { locate } from 'locate-character';
 import getCodeFrame from '../utils/getCodeFrame';
 
 export default class CompileError extends Error {
-	frame: string
-	loc: { line: number, column: number }
-	pos: number
-	filename: string
+	frame: string;
+	loc: { line: number; column: number };
+	pos: number;
+	filename: string;
 
-	constructor ( message: string, template: string, index: number, filename: string ) {
-		super( message );
+	constructor(
+		message: string,
+		template: string,
+		index: number,
+		filename: string
+	) {
+		super(message);
 
-		const { line, column } = locate( template, index );
+		const { line, column } = locate(template, index);
 
 		this.loc = { line: line + 1, column };
 		this.pos = index;
 		this.filename = filename;
 
-		this.frame = getCodeFrame( template, line, column );
+		this.frame = getCodeFrame(template, line, column);
 	}
 
-	toString () {
-		return `${this.message} (${this.loc.line}:${this.loc.column})\n${this.frame}`;
+	toString() {
+		return `${this.message} (${this.loc.line}:${this.loc.column})\n${this
+			.frame}`;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/utils/__test__.ts b/src/utils/__test__.ts
index 99e90bb76a..9f1cc87768 100644
--- a/src/utils/__test__.ts
+++ b/src/utils/__test__.ts
@@ -2,25 +2,25 @@ import * as assert from 'assert';
 import deindent from './deindent.js';
 import CodeBuilder from './CodeBuilder';
 
-describe( 'deindent', () => {
-	it( 'deindents a simple string', () => {
+describe('deindent', () => {
+	it('deindents a simple string', () => {
 		const deindented = deindent`
 			deindent me please
 		`;
 
-		assert.equal( deindented, `deindent me please` );
+		assert.equal(deindented, `deindent me please`);
 	});
 
-	it( 'deindents a multiline string', () => {
+	it('deindents a multiline string', () => {
 		const deindented = deindent`
 			deindent me please
 			and me as well
 		`;
 
-		assert.equal( deindented, `deindent me please\nand me as well` );
+		assert.equal(deindented, `deindent me please\nand me as well`);
 	});
 
-	it( 'preserves indentation of inserted values', () => {
+	it('preserves indentation of inserted values', () => {
 		const insert = deindent`
 			line one
 			line two
@@ -32,45 +32,47 @@ describe( 'deindent', () => {
 			after
 		`;
 
-		assert.equal( deindented, `before\n\tline one\n\tline two\nafter` );
+		assert.equal(deindented, `before\n\tline one\n\tline two\nafter`);
 	});
 });
 
-describe( 'CodeBuilder', () => {
-	it( 'creates an empty block', () => {
+describe('CodeBuilder', () => {
+	it('creates an empty block', () => {
 		const builder = new CodeBuilder();
-		assert.equal( builder.toString(), '' );
+		assert.equal(builder.toString(), '');
 	});
 
-	it( 'creates a block with a line', () => {
+	it('creates a block with a line', () => {
 		const builder = new CodeBuilder();
 
-		builder.addLine( 'var answer = 42;' );
-		assert.equal( builder.toString(), 'var answer = 42;' );
+		builder.addLine('var answer = 42;');
+		assert.equal(builder.toString(), 'var answer = 42;');
 	});
 
-	it( 'creates a block with two lines', () => {
+	it('creates a block with two lines', () => {
 		const builder = new CodeBuilder();
 
-		builder.addLine( 'var problems = 99;' );
-		builder.addLine( 'var answer = 42;' );
-		assert.equal( builder.toString(), 'var problems = 99;\nvar answer = 42;' );
+		builder.addLine('var problems = 99;');
+		builder.addLine('var answer = 42;');
+		assert.equal(builder.toString(), 'var problems = 99;\nvar answer = 42;');
 	});
 
-	it( 'adds newlines around blocks', () => {
+	it('adds newlines around blocks', () => {
 		const builder = new CodeBuilder();
 
-		builder.addLine( '// line 1' );
-		builder.addLine( '// line 2' );
-		builder.addBlock( deindent`
+		builder.addLine('// line 1');
+		builder.addLine('// line 2');
+		builder.addBlock(deindent`
 			if ( foo ) {
 				bar();
 			}
-		` );
-		builder.addLine( '// line 3' );
-		builder.addLine( '// line 4' );
+		`);
+		builder.addLine('// line 3');
+		builder.addLine('// line 4');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// line 1
 			// line 2
 
@@ -80,31 +82,34 @@ describe( 'CodeBuilder', () => {
 
 			// line 3
 			// line 4
-		` );
+		`
+		);
 	});
 
-	it( 'nests codebuilders with correct indentation', () => {
+	it('nests codebuilders with correct indentation', () => {
 		const child = new CodeBuilder();
 
-		child.addBlock( deindent`
+		child.addBlock(deindent`
 			var obj = {
 				answer: 42
 			};
-		` );
+		`);
 
 		const builder = new CodeBuilder();
 
-		builder.addLine( '// line 1' );
-		builder.addLine( '// line 2' );
-		builder.addBlock( deindent`
+		builder.addLine('// line 1');
+		builder.addLine('// line 2');
+		builder.addBlock(deindent`
 			if ( foo ) {
 				${child}
 			}
-		` );
-		builder.addLine( '// line 3' );
-		builder.addLine( '// line 4' );
+		`);
+		builder.addLine('// line 3');
+		builder.addLine('// line 4');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// line 1
 			// line 2
 
@@ -116,57 +121,70 @@ describe( 'CodeBuilder', () => {
 
 			// line 3
 			// line 4
-		` );
+		`
+		);
 	});
 
-	it( 'adds a line at start', () => {
+	it('adds a line at start', () => {
 		const builder = new CodeBuilder();
 
-		builder.addLine( '// second' );
-		builder.addLineAtStart( '// first' );
+		builder.addLine('// second');
+		builder.addLineAtStart('// first');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// first
 			// second
-		` );
+		`
+		);
 	});
 
-	it( 'adds a line at start before a block', () => {
+	it('adds a line at start before a block', () => {
 		const builder = new CodeBuilder();
 
-		builder.addBlock( '// second' );
-		builder.addLineAtStart( '// first' );
+		builder.addBlock('// second');
+		builder.addLineAtStart('// first');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// first
 
 			// second
-		` );
+		`
+		);
 	});
 
-	it( 'adds a block at start', () => {
+	it('adds a block at start', () => {
 		const builder = new CodeBuilder();
 
-		builder.addLine( '// second' );
-		builder.addBlockAtStart( '// first' );
+		builder.addLine('// second');
+		builder.addBlockAtStart('// first');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// first
 
 			// second
-		` );
+		`
+		);
 	});
 
-	it( 'adds a block at start before a block', () => {
+	it('adds a block at start before a block', () => {
 		const builder = new CodeBuilder();
 
-		builder.addBlock( '// second' );
-		builder.addBlockAtStart( '// first' );
+		builder.addBlock('// second');
+		builder.addBlockAtStart('// first');
 
-		assert.equal( builder.toString(), deindent`
+		assert.equal(
+			builder.toString(),
+			deindent`
 			// first
 
 			// second
-		` );
+		`
+		);
 	});
 });
diff --git a/src/utils/annotateWithScopes.ts b/src/utils/annotateWithScopes.ts
index 7989065f38..323523188e 100644
--- a/src/utils/annotateWithScopes.ts
+++ b/src/utils/annotateWithScopes.ts
@@ -1,41 +1,35 @@
 import { walk } from 'estree-walker';
 import { Node } from '../interfaces';
 
-export default function annotateWithScopes ( expression: Node ) {
-	let scope = new Scope( null, false );
-
-	walk( expression, {
-		enter ( node: Node ) {
-			if ( /Function/.test( node.type ) ) {
-				if ( node.type === 'FunctionDeclaration' ) {
-					scope.declarations.add( node.id.name );
+export default function annotateWithScopes(expression: Node) {
+	let scope = new Scope(null, false);
+
+	walk(expression, {
+		enter(node: Node) {
+			if (/Function/.test(node.type)) {
+				if (node.type === 'FunctionDeclaration') {
+					scope.declarations.add(node.id.name);
 				} else {
-					node._scope = scope = new Scope( scope, false );
-					if ( node.id ) scope.declarations.add( node.id.name );
+					node._scope = scope = new Scope(scope, false);
+					if (node.id) scope.declarations.add(node.id.name);
 				}
 
-				node.params.forEach( ( param: Node ) => {
-					extractNames( param ).forEach( name => {
-						scope.declarations.add( name );
+				node.params.forEach((param: Node) => {
+					extractNames(param).forEach(name => {
+						scope.declarations.add(name);
 					});
 				});
-			}
-
-			else if ( /For(?:In|Of)Statement/.test( node.type ) ) {
-				node._scope = scope = new Scope( scope, true );
-			}
-
-			else if ( node.type === 'BlockStatement' ) {
-				node._scope = scope = new Scope( scope, true );
-			}
-
-			else if ( /(Function|Class|Variable)Declaration/.test( node.type ) ) {
-				scope.addDeclaration( node );
+			} else if (/For(?:In|Of)Statement/.test(node.type)) {
+				node._scope = scope = new Scope(scope, true);
+			} else if (node.type === 'BlockStatement') {
+				node._scope = scope = new Scope(scope, true);
+			} else if (/(Function|Class|Variable)Declaration/.test(node.type)) {
+				scope.addDeclaration(node);
 			}
 		},
 
-		leave ( node: Node ) {
-			if ( node._scope ) {
+		leave(node: Node) {
+			if (node._scope) {
 				scope = scope.parent;
 			}
 		}
@@ -45,63 +39,65 @@ export default function annotateWithScopes ( expression: Node ) {
 }
 
 class Scope {
-	parent: Scope
-	block: boolean
-	declarations: Set<string>
+	parent: Scope;
+	block: boolean;
+	declarations: Set<string>;
 
-	constructor ( parent: Scope, block: boolean ) {
+	constructor(parent: Scope, block: boolean) {
 		this.parent = parent;
 		this.block = block;
 		this.declarations = new Set();
 	}
 
-	addDeclaration ( node: Node ) {
-		if ( node.kind === 'var' && !this.block && this.parent ) {
-			this.parent.addDeclaration( node );
-		} else if ( node.type === 'VariableDeclaration' ) {
-			node.declarations.forEach( ( declarator: Node ) => {
-				extractNames( declarator.id ).forEach( name => {
-					this.declarations.add( name );
+	addDeclaration(node: Node) {
+		if (node.kind === 'var' && !this.block && this.parent) {
+			this.parent.addDeclaration(node);
+		} else if (node.type === 'VariableDeclaration') {
+			node.declarations.forEach((declarator: Node) => {
+				extractNames(declarator.id).forEach(name => {
+					this.declarations.add(name);
 				});
 			});
 		} else {
-			this.declarations.add( node.id.name );
+			this.declarations.add(node.id.name);
 		}
 	}
 
-	has ( name: string ) :boolean {
-		return this.declarations.has( name ) || this.parent && this.parent.has( name );
+	has(name: string): boolean {
+		return (
+			this.declarations.has(name) || (this.parent && this.parent.has(name))
+		);
 	}
 }
 
-function extractNames ( param: Node ) {
+function extractNames(param: Node) {
 	const names: string[] = [];
-	extractors[ param.type ]( names, param );
+	extractors[param.type](names, param);
 	return names;
 }
 
 const extractors = {
-	Identifier ( names: string[], param: Node ) {
-		names.push( param.name );
+	Identifier(names: string[], param: Node) {
+		names.push(param.name);
 	},
 
-	ObjectPattern ( names: string[], param: Node ) {
-		param.properties.forEach( ( prop: Node ) => {
-			extractors[ prop.value.type ]( names, prop.value );
+	ObjectPattern(names: string[], param: Node) {
+		param.properties.forEach((prop: Node) => {
+			extractors[prop.value.type](names, prop.value);
 		});
 	},
 
-	ArrayPattern ( names: string[], param: Node ) {
-		param.elements.forEach( ( element: Node ) => {
-			if ( element ) extractors[ element.type ]( names, element );
+	ArrayPattern(names: string[], param: Node) {
+		param.elements.forEach((element: Node) => {
+			if (element) extractors[element.type](names, element);
 		});
 	},
 
-	RestElement ( names: string[], param: Node ) {
-		extractors[ param.argument.type ]( names, param.argument );
+	RestElement(names: string[], param: Node) {
+		extractors[param.argument.type](names, param.argument);
 	},
 
-	AssignmentPattern ( names: string[], param: Node ) {
-		extractors[ param.left.type ]( names, param.left );
+	AssignmentPattern(names: string[], param: Node) {
+		extractors[param.left.type](names, param.left);
 	}
 };
diff --git a/src/utils/deindent.js b/src/utils/deindent.js
index be20e42ef4..6c335ca6f0 100644
--- a/src/utils/deindent.js
+++ b/src/utils/deindent.js
@@ -1,40 +1,41 @@
 const start = /\n(\t+)/;
 
-export default function deindent ( strings, ...values ) {
-	const indentation = start.exec( strings[0] )[1];
-	const pattern = new RegExp( `^${indentation}`, 'gm' );
+export default function deindent(strings, ...values) {
+	const indentation = start.exec(strings[0])[1];
+	const pattern = new RegExp(`^${indentation}`, 'gm');
 
-	let result = strings[0].replace( start, '' ).replace( pattern, '' );
+	let result = strings[0].replace(start, '').replace(pattern, '');
 
-	let trailingIndentation = getTrailingIndentation( result );
+	let trailingIndentation = getTrailingIndentation(result);
 
-	for ( let i = 1; i < strings.length; i += 1 ) {
-		let expression = values[ i - 1 ];
-		const string = strings[i].replace( pattern, '' );
+	for (let i = 1; i < strings.length; i += 1) {
+		let expression = values[i - 1];
+		const string = strings[i].replace(pattern, '');
 
-		if ( Array.isArray( expression ) ) {
-			expression = expression.length ? expression.join( '\n' ) : null;
+		if (Array.isArray(expression)) {
+			expression = expression.length ? expression.join('\n') : null;
 		}
 
-		if ( expression || expression === '' ) {
-			const value = String( expression ).replace( /\n/g, `\n${trailingIndentation}` );
+		if (expression || expression === '') {
+			const value = String(expression).replace(
+				/\n/g,
+				`\n${trailingIndentation}`
+			);
 			result += value + string;
-		}
-
-		else {
+		} else {
 			let c = result.length;
-			while ( /\s/.test( result[ c - 1 ] ) ) c -= 1;
-			result = result.slice( 0, c ) + string;
+			while (/\s/.test(result[c - 1])) c -= 1;
+			result = result.slice(0, c) + string;
 		}
 
-		trailingIndentation = getTrailingIndentation( result );
+		trailingIndentation = getTrailingIndentation(result);
 	}
 
-	return result.trim().replace( /\t+$/gm, '' );
+	return result.trim().replace(/\t+$/gm, '');
 }
 
-function getTrailingIndentation ( str ) {
+function getTrailingIndentation(str) {
 	let i = str.length;
-	while ( str[ i - 1 ] === ' ' || str[ i - 1 ] === '\t' ) i -= 1;
-	return str.slice( i, str.length );
+	while (str[i - 1] === ' ' || str[i - 1] === '\t') i -= 1;
+	return str.slice(i, str.length);
 }
diff --git a/src/utils/flattenReference.ts b/src/utils/flattenReference.ts
index 90946f3a8b..b44fb6e27f 100644
--- a/src/utils/flattenReference.ts
+++ b/src/utils/flattenReference.ts
@@ -1,21 +1,23 @@
 import { Node } from '../interfaces';
 
-export default function flatten ( node: Node ) {
+export default function flatten(node: Node) {
 	const parts = [];
 	const propEnd = node.end;
 
-	while ( node.type === 'MemberExpression' ) {
-		if ( node.computed ) return null;
-		parts.unshift( node.property.name );
+	while (node.type === 'MemberExpression') {
+		if (node.computed) return null;
+		parts.unshift(node.property.name);
 
 		node = node.object;
 	}
 
 	const propStart = node.end;
-	const name = node.type === 'Identifier' ? node.name : node.type === 'ThisExpression' ? 'this' : null;
+	const name = node.type === 'Identifier'
+		? node.name
+		: node.type === 'ThisExpression' ? 'this' : null;
 
-	if ( !name ) return null;
+	if (!name) return null;
 
-	parts.unshift( name );
+	parts.unshift(name);
 	return { name, parts, keypath: `${name}[✂${propStart}-${propEnd}✂]` };
 }
diff --git a/src/utils/getCodeFrame.ts b/src/utils/getCodeFrame.ts
index b87e267ff2..eb237841ae 100644
--- a/src/utils/getCodeFrame.ts
+++ b/src/utils/getCodeFrame.ts
@@ -1,31 +1,36 @@
 import spaces from './spaces.js';
 
-function tabsToSpaces ( str: string ) {
-	return str.replace( /^\t+/, match => match.split( '\t' ).join( '  ' ) );
+function tabsToSpaces(str: string) {
+	return str.replace(/^\t+/, match => match.split('\t').join('  '));
 }
 
-export default function getCodeFrame ( source: string, line: number, column: number ) {
-	const lines = source.split( '\n' );
+export default function getCodeFrame(
+	source: string,
+	line: number,
+	column: number
+) {
+	const lines = source.split('\n');
 
-	const frameStart = Math.max( 0, line - 2 );
-	const frameEnd = Math.min( line + 3, lines.length );
+	const frameStart = Math.max(0, line - 2);
+	const frameEnd = Math.min(line + 3, lines.length);
 
-	const digits = String( frameEnd + 1 ).length;
+	const digits = String(frameEnd + 1).length;
 
 	return lines
-		.slice( frameStart, frameEnd )
-		.map( ( str, i ) => {
+		.slice(frameStart, frameEnd)
+		.map((str, i) => {
 			const isErrorLine = frameStart + i === line;
 
-			let lineNum = String( i + frameStart + 1 );
-			while ( lineNum.length < digits ) lineNum = ` ${lineNum}`;
+			let lineNum = String(i + frameStart + 1);
+			while (lineNum.length < digits) lineNum = ` ${lineNum}`;
 
-			if ( isErrorLine ) {
-				const indicator = spaces( digits + 2 + tabsToSpaces( str.slice( 0, column ) ).length ) + '^';
-				return `${lineNum}: ${tabsToSpaces( str )}\n${indicator}`;
+			if (isErrorLine) {
+				const indicator =
+					spaces(digits + 2 + tabsToSpaces(str.slice(0, column)).length) + '^';
+				return `${lineNum}: ${tabsToSpaces(str)}\n${indicator}`;
 			}
 
-			return `${lineNum}: ${tabsToSpaces( str )}`;
+			return `${lineNum}: ${tabsToSpaces(str)}`;
 		})
-		.join( '\n' );
+		.join('\n');
 }
diff --git a/src/utils/globalWhitelist.ts b/src/utils/globalWhitelist.ts
index 8472308174..9a684a4552 100644
--- a/src/utils/globalWhitelist.ts
+++ b/src/utils/globalWhitelist.ts
@@ -1 +1,26 @@
-export default new Set( [ 'Array', 'Boolean', 'console', 'Date', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Infinity', 'Intl', 'isFinite', 'isNaN', 'JSON', 'Map', 'Math', 'NaN', 'Number', 'Object', 'parseFloat', 'parseInt', 'RegExp', 'Set', 'String', 'undefined' ] );
+export default new Set([
+	'Array',
+	'Boolean',
+	'console',
+	'Date',
+	'decodeURI',
+	'decodeURIComponent',
+	'encodeURI',
+	'encodeURIComponent',
+	'Infinity',
+	'Intl',
+	'isFinite',
+	'isNaN',
+	'JSON',
+	'Map',
+	'Math',
+	'NaN',
+	'Number',
+	'Object',
+	'parseFloat',
+	'parseInt',
+	'RegExp',
+	'Set',
+	'String',
+	'undefined'
+]);
diff --git a/src/utils/isReference.ts b/src/utils/isReference.ts
index d486cf5c26..9a5f3688fb 100644
--- a/src/utils/isReference.ts
+++ b/src/utils/isReference.ts
@@ -1,29 +1,33 @@
 import { Node } from '../interfaces';
 
-export default function isReference ( node: Node, parent: Node ): boolean {
-	if ( node.type === 'MemberExpression' ) {
-		return !node.computed && isReference( node.object, node );
+export default function isReference(node: Node, parent: Node): boolean {
+	if (node.type === 'MemberExpression') {
+		return !node.computed && isReference(node.object, node);
 	}
 
-	if ( node.type === 'Identifier' ) {
+	if (node.type === 'Identifier') {
 		// the only time we could have an identifier node without a parent is
 		// if it's the entire body of a function without a block statement –
 		// i.e. an arrow function expression like `a => a`
-		if ( !parent ) return true;
+		if (!parent) return true;
 
 		// TODO is this right?
-		if ( parent.type === 'MemberExpression' || parent.type === 'MethodDefinition' ) {
+		if (
+			parent.type === 'MemberExpression' ||
+			parent.type === 'MethodDefinition'
+		) {
 			return parent.computed || node === parent.object;
 		}
 
 		// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
-		if ( parent.type === 'Property' ) return parent.computed || node === parent.value;
+		if (parent.type === 'Property')
+			return parent.computed || node === parent.value;
 
 		// disregard the `bar` in `class Foo { bar () {...} }`
-		if ( parent.type === 'MethodDefinition' ) return false;
+		if (parent.type === 'MethodDefinition') return false;
 
 		// disregard the `bar` in `export { foo as bar }`
-		if ( parent.type === 'ExportSpecifier' && node !== parent.local ) return;
+		if (parent.type === 'ExportSpecifier' && node !== parent.local) return;
 
 		return true;
 	}
diff --git a/src/utils/isVoidElementName.ts b/src/utils/isVoidElementName.ts
index b640cafbe8..2396a0cde2 100644
--- a/src/utils/isVoidElementName.ts
+++ b/src/utils/isVoidElementName.ts
@@ -1,5 +1,5 @@
 const voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
 
-export default function isVoidElementName ( name: string ) {
-	return voidElementNames.test( name ) || name.toLowerCase() === '!doctype';
+export default function isVoidElementName(name: string) {
+	return voidElementNames.test(name) || name.toLowerCase() === '!doctype';
 }
diff --git a/src/utils/namespaces.ts b/src/utils/namespaces.ts
index 595d0f0def..975f01a4d1 100644
--- a/src/utils/namespaces.ts
+++ b/src/utils/namespaces.ts
@@ -1,13 +1,23 @@
-export const html   = 'http://www.w3.org/1999/xhtml';
+export const html = 'http://www.w3.org/1999/xhtml';
 export const mathml = 'http://www.w3.org/1998/Math/MathML';
-export const svg    = 'http://www.w3.org/2000/svg';
-export const xlink  = 'http://www.w3.org/1999/xlink';
-export const xml    = 'http://www.w3.org/XML/1998/namespace';
-export const xmlns  = 'http://www.w3.org/2000/xmlns';
+export const svg = 'http://www.w3.org/2000/svg';
+export const xlink = 'http://www.w3.org/1999/xlink';
+export const xml = 'http://www.w3.org/XML/1998/namespace';
+export const xmlns = 'http://www.w3.org/2000/xmlns';
 
 export const validNamespaces = [
-	'html', 'mathml', 'svg', 'xlink', 'xml', 'xmlns',
-	html, mathml, svg, xlink, xml, xmlns
+	'html',
+	'mathml',
+	'svg',
+	'xlink',
+	'xml',
+	'xmlns',
+	html,
+	mathml,
+	svg,
+	xlink,
+	xml,
+	xmlns
 ];
 
 export default { html, mathml, svg, xlink, xml, xmlns };
diff --git a/src/utils/removeNode.ts b/src/utils/removeNode.ts
index ec3a7152fa..3d237399a6 100644
--- a/src/utils/removeNode.ts
+++ b/src/utils/removeNode.ts
@@ -6,52 +6,52 @@ const keys = {
 };
 
 const offsets = {
-	ObjectExpression: [ 1, -1 ],
-	Program: [ 0, 0 ]
+	ObjectExpression: [1, -1],
+	Program: [0, 0]
 };
 
-export function removeNode ( code, parent: Node, node: Node ) {
-	const key = keys[ parent.type ];
-	const offset = offsets[ parent.type ];
-	if ( !key || !offset ) throw new Error( `not implemented: ${parent.type}` );
+export function removeNode(code, parent: Node, node: 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' );
+	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 ) {
+	if (list.length === 1) {
 		// remove everything, leave {}
 		a = parent.start + offset[0];
 		b = parent.end + offset[1];
-	} else if ( i === 0 ) {
+	} else if (i === 0) {
 		// remove everything before second node, including comments
 		a = parent.start + offset[0];
-		while ( /\s/.test( code.original[a] ) ) a += 1;
+		while (/\s/.test(code.original[a])) a += 1;
 
 		b = list[i].end;
-		while ( /[\s,]/.test( code.original[b] ) ) b += 1;
+		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;
+		a = list[i - 1].end;
 		b = node.end;
 	}
 
-	code.remove( a, b );
-	list.splice( i, 1 );
+	code.remove(a, b);
+	list.splice(i, 1);
 	return;
 }
 
-export function removeObjectKey ( code, node, key ) {
-	if ( node.type !== 'ObjectExpression' ) return;
+export function removeObjectKey(code, node, key) {
+	if (node.type !== 'ObjectExpression') return;
 
 	let i = node.properties.length;
-	while ( i-- ) {
+	while (i--) {
 		const property = node.properties[i];
-		if ( property.key.type === 'Identifier' && property.key.name === key ) {
-			removeNode( code, node, property );
+		if (property.key.type === 'Identifier' && property.key.name === key) {
+			removeNode(code, node, property);
 		}
 	}
 }
diff --git a/src/utils/reservedNames.ts b/src/utils/reservedNames.ts
index cc44bbd873..a5ecd09fbd 100644
--- a/src/utils/reservedNames.ts
+++ b/src/utils/reservedNames.ts
@@ -1,6 +1,55 @@
-const reservedNames = new Set( [ 'arguments', 'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield' ] );
+const reservedNames = new Set([
+	'arguments',
+	'await',
+	'break',
+	'case',
+	'catch',
+	'class',
+	'const',
+	'continue',
+	'debugger',
+	'default',
+	'delete',
+	'do',
+	'else',
+	'enum',
+	'eval',
+	'export',
+	'extends',
+	'false',
+	'finally',
+	'for',
+	'function',
+	'if',
+	'implements',
+	'import',
+	'in',
+	'instanceof',
+	'interface',
+	'let',
+	'new',
+	'null',
+	'package',
+	'private',
+	'protected',
+	'public',
+	'return',
+	'static',
+	'super',
+	'switch',
+	'this',
+	'throw',
+	'true',
+	'try',
+	'typeof',
+	'var',
+	'void',
+	'while',
+	'with',
+	'yield'
+]);
 
 // prevent e.g. `{{#each states as state}}` breaking
-reservedNames.add( 'state' );
+reservedNames.add('state');
 
-export default reservedNames;
\ No newline at end of file
+export default reservedNames;
diff --git a/src/utils/spaces.js b/src/utils/spaces.js
index 26c818fd8d..b1c7a47498 100644
--- a/src/utils/spaces.js
+++ b/src/utils/spaces.js
@@ -1,5 +1,5 @@
-export default function spaces ( i ) {
+export default function spaces(i) {
 	let result = '';
-	while ( i-- ) result += ' ';
+	while (i--) result += ' ';
 	return result;
 }
diff --git a/src/utils/trim.ts b/src/utils/trim.ts
index 3c339a159b..387b368826 100644
--- a/src/utils/trim.ts
+++ b/src/utils/trim.ts
@@ -1,15 +1,15 @@
 import { whitespace } from './patterns';
 
-export function trimStart ( str: string ) {
+export function trimStart(str: string) {
 	let i = 0;
-	while ( whitespace.test( str[i] ) ) i += 1;
+	while (whitespace.test(str[i])) i += 1;
 
-	return str.slice( i );
+	return str.slice(i);
 }
 
-export function trimEnd ( str: string ) {
+export function trimEnd(str: string) {
 	let i = str.length;
-	while ( whitespace.test( str[ i - 1 ] ) ) i -= 1;
+	while (whitespace.test(str[i - 1])) i -= 1;
 
-	return str.slice( 0, i );
+	return str.slice(0, i);
 }
diff --git a/src/validate/html/index.ts b/src/validate/html/index.ts
index b091a90db3..b09cece0e4 100644
--- a/src/validate/html/index.ts
+++ b/src/validate/html/index.ts
@@ -6,51 +6,59 @@ import { Node } from '../../interfaces';
 
 const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|title|tref|tspan|unknown|use|view|vkern)$/;
 
-const meta = new Map([
-	[ ':Window', validateWindow ]
-]);
+const meta = new Map([[':Window', validateWindow]]);
 
-export default function validateHtml ( validator: Validator, html: Node ) {
+export default function validateHtml(validator: Validator, html: Node) {
 	let elementDepth = 0;
 
-	function visit ( node: Node ) {
-		if ( node.type === 'Element' ) {
-			if ( elementDepth === 0 && validator.namespace !== namespaces.svg && svg.test( node.name ) ) {
-				validator.warn( `<${node.name}> is an SVG element – did you forget to add { namespace: 'svg' } ?`, node.start );
+	function visit(node: Node) {
+		if (node.type === 'Element') {
+			if (
+				elementDepth === 0 &&
+				validator.namespace !== namespaces.svg &&
+				svg.test(node.name)
+			) {
+				validator.warn(
+					`<${node.name}> is an SVG element – did you forget to add { namespace: 'svg' } ?`,
+					node.start
+				);
 			}
 
-			if ( meta.has( node.name ) ) {
-				return meta.get( node.name )( validator, node );
+			if (meta.has(node.name)) {
+				return meta.get(node.name)(validator, node);
 			}
 
 			elementDepth += 1;
 
-			validateElement( validator, node );
-		} else if ( node.type === 'EachBlock' ) {
-			if ( validator.helpers.has( node.context ) ) {
+			validateElement(validator, node);
+		} else if (node.type === 'EachBlock') {
+			if (validator.helpers.has(node.context)) {
 				let c = node.expression.end;
 
 				// find start of context
-				while ( /\s/.test( validator.source[c] ) ) c += 1;
+				while (/\s/.test(validator.source[c])) c += 1;
 				c += 2;
-				while ( /\s/.test( validator.source[c] ) ) c += 1;
+				while (/\s/.test(validator.source[c])) c += 1;
 
-				validator.warn( `Context clashes with a helper. Rename one or the other to eliminate any ambiguity`, c );
+				validator.warn(
+					`Context clashes with a helper. Rename one or the other to eliminate any ambiguity`,
+					c
+				);
 			}
 		}
 
-		if ( node.children ) {
-			node.children.forEach( visit );
+		if (node.children) {
+			node.children.forEach(visit);
 		}
 
-		if ( node.else ) {
-			visit( node.else );
+		if (node.else) {
+			visit(node.else);
 		}
 
-		if ( node.type === 'Element' ) {
+		if (node.type === 'Element') {
 			elementDepth -= 1;
 		}
 	}
 
-	html.children.forEach( visit );
+	html.children.forEach(visit);
 }
diff --git a/src/validate/html/validateElement.ts b/src/validate/html/validateElement.ts
index 18c906b298..081fea6028 100644
--- a/src/validate/html/validateElement.ts
+++ b/src/validate/html/validateElement.ts
@@ -2,102 +2,144 @@ import validateEventHandler from './validateEventHandler';
 import { Validator } from '../index';
 import { Node } from '../../interfaces';
 
-export default function validateElement ( validator: Validator, node: Node ) {
-	const isComponent = node.name === ':Self' || validator.components.has( node.name );
+export default function validateElement(validator: Validator, node: Node) {
+	const isComponent =
+		node.name === ':Self' || validator.components.has(node.name);
 
 	let hasIntro: boolean;
 	let hasOutro: boolean;
 	let hasTransition: boolean;
 
-	node.attributes.forEach( ( attribute: Node ) => {
-		if ( !isComponent && attribute.type === 'Binding' ) {
+	node.attributes.forEach((attribute: Node) => {
+		if (!isComponent && attribute.type === 'Binding') {
 			const { name } = attribute;
 
-			if ( name === 'value' ) {
-				if ( node.name !== 'input' && node.name !== 'textarea' && node.name !== 'select' ) {
-					validator.error( `'value' is not a valid binding on <${node.name}> elements`, attribute.start );
+			if (name === 'value') {
+				if (
+					node.name !== 'input' &&
+					node.name !== 'textarea' &&
+					node.name !== 'select'
+				) {
+					validator.error(
+						`'value' is not a valid binding on <${node.name}> elements`,
+						attribute.start
+					);
 				}
-			}
-
-			else if ( name === 'checked' ) {
-				if ( node.name !== 'input' ) {
-					validator.error( `'checked' is not a valid binding on <${node.name}> elements`, attribute.start );
+			} else if (name === 'checked') {
+				if (node.name !== 'input') {
+					validator.error(
+						`'checked' is not a valid binding on <${node.name}> elements`,
+						attribute.start
+					);
 				}
 
-				if ( getType( validator, node ) !== 'checkbox' ) {
-					validator.error( `'checked' binding can only be used with <input type="checkbox">`, attribute.start );
+				if (getType(validator, node) !== 'checkbox') {
+					validator.error(
+						`'checked' binding can only be used with <input type="checkbox">`,
+						attribute.start
+					);
 				}
-			}
-
-			else if ( name === 'group' ) {
-				if ( node.name !== 'input' ) {
-					validator.error( `'group' is not a valid binding on <${node.name}> elements`, attribute.start );
+			} else if (name === 'group') {
+				if (node.name !== 'input') {
+					validator.error(
+						`'group' is not a valid binding on <${node.name}> elements`,
+						attribute.start
+					);
 				}
 
-				const type = getType( validator, node );
+				const type = getType(validator, node);
 
-				if ( type !== 'checkbox' && type !== 'radio' ) {
-					validator.error( `'checked' binding can only be used with <input type="checkbox"> or <input type="radio">`, attribute.start );
+				if (type !== 'checkbox' && type !== 'radio') {
+					validator.error(
+						`'checked' binding can only be used with <input type="checkbox"> or <input type="radio">`,
+						attribute.start
+					);
 				}
-			}
-
-			else if ( name === 'currentTime' || name === 'duration' || name === 'paused' ) {
-				if ( node.name !== 'audio' && node.name !== 'video' ) {
-					validator.error( `'${name}' binding can only be used with <audio> or <video>`, attribute.start );
+			} else if (
+				name === 'currentTime' ||
+				name === 'duration' ||
+				name === 'paused'
+			) {
+				if (node.name !== 'audio' && node.name !== 'video') {
+					validator.error(
+						`'${name}' binding can only be used with <audio> or <video>`,
+						attribute.start
+					);
 				}
+			} else {
+				validator.error(
+					`'${attribute.name}' is not a valid binding`,
+					attribute.start
+				);
 			}
-
-			else {
-				validator.error( `'${attribute.name}' is not a valid binding`, attribute.start );
-			}
-		}
-
-		else if ( attribute.type === 'EventHandler' ) {
-			validateEventHandler( validator, attribute );
-		}
-
-		else if ( attribute.type === 'Transition' ) {
+		} else if (attribute.type === 'EventHandler') {
+			validateEventHandler(validator, attribute);
+		} else if (attribute.type === 'Transition') {
 			const bidi = attribute.intro && attribute.outro;
 
-			if ( hasTransition ) {
-				if ( bidi ) validator.error( `An element can only have one 'transition' directive`, attribute.start );
-				validator.error( `An element cannot have both a 'transition' directive and an '${attribute.intro ? 'in' : 'out'}' directive`, attribute.start );
+			if (hasTransition) {
+				if (bidi)
+					validator.error(
+						`An element can only have one 'transition' directive`,
+						attribute.start
+					);
+				validator.error(
+					`An element cannot have both a 'transition' directive and an '${attribute.intro
+						? 'in'
+						: 'out'}' directive`,
+					attribute.start
+				);
 			}
 
-			if ( ( hasIntro && attribute.intro ) || ( hasOutro && attribute.outro ) ) {
-				if ( bidi ) validator.error( `An element cannot have both an '${hasIntro ? 'in' : 'out'}' directive and a 'transition' directive`, attribute.start );
-				validator.error( `An element can only have one '${hasIntro ? 'in' : 'out'}' directive`, attribute.start );
+			if ((hasIntro && attribute.intro) || (hasOutro && attribute.outro)) {
+				if (bidi)
+					validator.error(
+						`An element cannot have both an '${hasIntro
+							? 'in'
+							: 'out'}' directive and a 'transition' directive`,
+						attribute.start
+					);
+				validator.error(
+					`An element can only have one '${hasIntro ? 'in' : 'out'}' directive`,
+					attribute.start
+				);
 			}
 
-			if ( attribute.intro ) hasIntro = true;
-			if ( attribute.outro ) hasOutro = true;
-			if ( bidi ) hasTransition = true;
+			if (attribute.intro) hasIntro = true;
+			if (attribute.outro) hasOutro = true;
+			if (bidi) hasTransition = true;
 
-			if ( !validator.transitions.has( attribute.name ) ) {
-				validator.error( `Missing transition '${attribute.name}'`, attribute.start );
+			if (!validator.transitions.has(attribute.name)) {
+				validator.error(
+					`Missing transition '${attribute.name}'`,
+					attribute.start
+				);
 			}
-		}
-
-		else if ( attribute.type === 'Attribute' ) {
-			if ( attribute.name === 'value' && node.name === 'textarea' ) {
-				if ( node.children.length ) {
-					validator.error( `A <textarea> can have either a value attribute or (equivalently) child content, but not both`, attribute.start );
+		} else if (attribute.type === 'Attribute') {
+			if (attribute.name === 'value' && node.name === 'textarea') {
+				if (node.children.length) {
+					validator.error(
+						`A <textarea> can have either a value attribute or (equivalently) child content, but not both`,
+						attribute.start
+					);
 				}
 			}
 		}
 	});
 }
 
-function getType ( validator: Validator, node: Node ) {
-	const attribute = node.attributes.find( ( attribute: Node ) => attribute.name === 'type' );
-	if ( !attribute ) return null;
+function getType(validator: Validator, node: Node) {
+	const attribute = node.attributes.find(
+		(attribute: Node) => attribute.name === 'type'
+	);
+	if (!attribute) return null;
 
-	if ( attribute.value === true ) {
-		validator.error( `'type' attribute must be specified`, attribute.start );
+	if (attribute.value === true) {
+		validator.error(`'type' attribute must be specified`, attribute.start);
 	}
 
-	if ( attribute.value.length > 1 || attribute.value[0].type !== 'Text' ) {
-		validator.error( `'type attribute cannot be dynamic`, attribute.start );
+	if (attribute.value.length > 1 || attribute.value[0].type !== 'Text') {
+		validator.error(`'type attribute cannot be dynamic`, attribute.start);
 	}
 
 	return attribute.value[0].data;
diff --git a/src/validate/html/validateEventHandler.ts b/src/validate/html/validateEventHandler.ts
index 81ece1c148..85fdad08e6 100644
--- a/src/validate/html/validateEventHandler.ts
+++ b/src/validate/html/validateEventHandler.ts
@@ -3,35 +3,40 @@ import list from '../utils/list';
 import { Validator } from '../index';
 import { Node } from '../../interfaces';
 
-const validBuiltins = new Set([
-	'set',
-	'fire',
-	'destroy'
-]);
+const validBuiltins = new Set(['set', 'fire', 'destroy']);
 
-export default function validateEventHandlerCallee ( validator: Validator, attribute: Node ) {
+export default function validateEventHandlerCallee(
+	validator: Validator,
+	attribute: Node
+) {
 	const { callee, start, type } = attribute.expression;
 
-	if ( type !== 'CallExpression' ) {
-		validator.error( `Expected a call expression`, start );
+	if (type !== 'CallExpression') {
+		validator.error(`Expected a call expression`, start);
 	}
 
-	const { name } = flattenReference( callee );
+	const { name } = flattenReference(callee);
 
-	if ( name === 'this' || name === 'event' ) return;
-	if ( callee.type === 'Identifier' && validBuiltins.has( callee.name ) || validator.methods.has( callee.name ) ) return;
+	if (name === 'this' || name === 'event') return;
+	if (
+		(callee.type === 'Identifier' && validBuiltins.has(callee.name)) ||
+		validator.methods.has(callee.name)
+	)
+		return;
 
-	const validCallees = [ 'this.*', 'event.*' ]
-		.concat(
-			Array.from( validBuiltins ),
-			Array.from( validator.methods.keys() )
-		);
+	const validCallees = ['this.*', 'event.*'].concat(
+		Array.from(validBuiltins),
+		Array.from(validator.methods.keys())
+	);
 
-	let message = `'${validator.source.slice( callee.start, callee.end )}' is an invalid callee (should be one of ${list( validCallees )})`;
+	let message = `'${validator.source.slice(
+		callee.start,
+		callee.end
+	)}' is an invalid callee (should be one of ${list(validCallees)})`;
 
-	if ( callee.type === 'Identifier' && validator.helpers.has( callee.name ) ) {
+	if (callee.type === 'Identifier' && validator.helpers.has(callee.name)) {
 		message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`;
 	}
 
-	validator.warn( message, start );
+	validator.warn(message, start);
 }
diff --git a/src/validate/html/validateWindow.ts b/src/validate/html/validateWindow.ts
index fadcac10a7..8889b849ff 100644
--- a/src/validate/html/validateWindow.ts
+++ b/src/validate/html/validateWindow.ts
@@ -14,37 +14,43 @@ const validBindings = [
 	'scrollY'
 ];
 
-export default function validateWindow ( validator: Validator, node: Node ) {
-	node.attributes.forEach( ( attribute: Node ) => {
-		if ( attribute.type === 'Binding' ) {
-			if ( attribute.value.type !== 'Identifier' ) {
-				const { parts } = flattenReference( attribute.value );
+export default function validateWindow(validator: Validator, node: Node) {
+	node.attributes.forEach((attribute: Node) => {
+		if (attribute.type === 'Binding') {
+			if (attribute.value.type !== 'Identifier') {
+				const { parts } = flattenReference(attribute.value);
 
 				validator.error(
-					`Bindings on <:Window/> must be to top-level properties, e.g. '${parts[ parts.length - 1 ]}' rather than '${parts.join( '.' )}'`,
+					`Bindings on <:Window/> must be to top-level properties, e.g. '${parts[
+						parts.length - 1
+					]}' rather than '${parts.join('.')}'`,
 					attribute.value.start
 				);
 			}
 
-			if ( !~validBindings.indexOf( attribute.name ) ) {
-				const match = (
-					attribute.name === 'width' ? 'innerWidth' :
-					attribute.name === 'height' ? 'innerHeight' :
-					fuzzymatch( attribute.name, validBindings )
-				);
+			if (!~validBindings.indexOf(attribute.name)) {
+				const match = attribute.name === 'width'
+					? 'innerWidth'
+					: attribute.name === 'height'
+						? 'innerHeight'
+						: fuzzymatch(attribute.name, validBindings);
 
 				const message = `'${attribute.name}' is not a valid binding on <:Window>`;
 
-				if ( match ) {
-					validator.error( `${message} (did you mean '${match}'?)`, attribute.start );
+				if (match) {
+					validator.error(
+						`${message} (did you mean '${match}'?)`,
+						attribute.start
+					);
 				} else {
-					validator.error( `${message} — valid bindings are ${list( validBindings )}`, attribute.start );
+					validator.error(
+						`${message} — valid bindings are ${list(validBindings)}`,
+						attribute.start
+					);
 				}
 			}
-		}
-
-		else if ( attribute.type === 'EventHandler' ) {
-			validateEventHandler( validator, attribute );
+		} else if (attribute.type === 'EventHandler') {
+			validateEventHandler(validator, attribute);
 		}
 	});
-}
\ No newline at end of file
+}
diff --git a/src/validate/index.ts b/src/validate/index.ts
index 891132d23b..07338c9327 100644
--- a/src/validate/index.ts
+++ b/src/validate/index.ts
@@ -2,12 +2,17 @@ import validateJs from './js/index';
 import validateHtml from './html/index';
 import { getLocator, Location } from 'locate-character';
 import getCodeFrame from '../utils/getCodeFrame';
-import CompileError from '../utils/CompileError'
+import CompileError from '../utils/CompileError';
 import { Node, Parsed, CompileOptions, Warning } from '../interfaces';
 
 class ValidationError extends CompileError {
-	constructor ( message: string, template: string, index: number, filename: string ) {
-		super( message, template, index, filename );
+	constructor(
+		message: string,
+		template: string,
+		index: number,
+		filename: string
+	) {
+		super(message, template, index, filename);
 		this.name = 'ValidationError';
 	}
 }
@@ -27,7 +32,7 @@ export class Validator {
 	helpers: Map<string, Node>;
 	transitions: Map<string, Node>;
 
-	constructor ( parsed: Parsed, source: string, options: CompileOptions ) {
+	constructor(parsed: Parsed, source: string, options: CompileOptions) {
 		this.source = source;
 		this.filename = options !== undefined ? options.filename : undefined;
 
@@ -43,15 +48,15 @@ export class Validator {
 		this.transitions = new Map();
 	}
 
-	error ( message: string, pos: number ) {
-		throw new ValidationError( message, this.source, pos, this.filename );
+	error(message: string, pos: number) {
+		throw new ValidationError(message, this.source, pos, this.filename);
 	}
 
-	warn ( message: string, pos: number ) {
-		if ( !this.locator ) this.locator = getLocator( this.source );
-		const { line, column } = this.locator( pos );
+	warn(message: string, pos: number) {
+		if (!this.locator) this.locator = getLocator(this.source);
+		const { line, column } = this.locator(pos);
 
-		const frame = getCodeFrame( this.source, line, column );
+		const frame = getCodeFrame(this.source, line, column);
 
 		this.onwarn({
 			message,
@@ -64,16 +69,20 @@ export class Validator {
 	}
 }
 
-export default function validate ( parsed: Parsed, source: string, options: CompileOptions ) {
+export default function validate(
+	parsed: Parsed,
+	source: string,
+	options: CompileOptions
+) {
 	const { onwarn, onerror, name, filename } = options;
 
 	try {
-		if ( name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( name ) ) {
-			const error = new Error( `options.name must be a valid identifier` );
+		if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) {
+			const error = new Error(`options.name must be a valid identifier`);
 			throw error;
 		}
 
-		if ( name && !/^[A-Z]/.test( name ) ) {
+		if (name && !/^[A-Z]/.test(name)) {
 			const message = `options.name should be capitalised`;
 			onwarn({
 				message,
@@ -82,22 +91,22 @@ export default function validate ( parsed: Parsed, source: string, options: Comp
 			});
 		}
 
-		const validator = new Validator( parsed, source, {
+		const validator = new Validator(parsed, source, {
 			onwarn,
 			name,
 			filename
 		});
 
-		if ( parsed.js ) {
-			validateJs( validator, parsed.js );
+		if (parsed.js) {
+			validateJs(validator, parsed.js);
 		}
 
-		if ( parsed.html ) {
-			validateHtml( validator, parsed.html );
+		if (parsed.html) {
+			validateHtml(validator, parsed.html);
 		}
-	} catch ( err ) {
-		if ( onerror ) {
-			onerror( err );
+	} catch (err) {
+		if (onerror) {
+			onerror(err);
 		} else {
 			throw err;
 		}
diff --git a/src/validate/js/index.ts b/src/validate/js/index.ts
index f43922f81c..0b7547f64c 100644
--- a/src/validate/js/index.ts
+++ b/src/validate/js/index.ts
@@ -6,69 +6,89 @@ import namespaces from '../../utils/namespaces';
 import { Validator } from '../';
 import { Node } from '../../interfaces';
 
-const validPropList = Object.keys( propValidators );
+const validPropList = Object.keys(propValidators);
 
-export default function validateJs ( validator: Validator, js: Node ) {
-	js.content.body.forEach( ( node: Node ) => {
+export default function validateJs(validator: Validator, js: Node) {
+	js.content.body.forEach((node: Node) => {
 		// check there are no named exports
-		if ( node.type === 'ExportNamedDeclaration' ) {
-			validator.error( `A component can only have a default export`, node.start );
+		if (node.type === 'ExportNamedDeclaration') {
+			validator.error(`A component can only have a default export`, node.start);
 		}
 
-		if ( node.type === 'ExportDefaultDeclaration' ) {
-			if ( node.declaration.type !== 'ObjectExpression' ) {
-				return validator.error( `Default export must be an object literal`, node.declaration.start );
+		if (node.type === 'ExportDefaultDeclaration') {
+			if (node.declaration.type !== 'ObjectExpression') {
+				return validator.error(
+					`Default export must be an object literal`,
+					node.declaration.start
+				);
 			}
 
-			checkForComputedKeys( validator, node.declaration.properties );
-			checkForDupes( validator, node.declaration.properties );
+			checkForComputedKeys(validator, node.declaration.properties);
+			checkForDupes(validator, node.declaration.properties);
 
 			const props = validator.properties;
 
-			node.declaration.properties.forEach( ( prop: Node ) => {
-				props.set( prop.key.name, prop );
+			node.declaration.properties.forEach((prop: Node) => {
+				props.set(prop.key.name, prop);
 			});
 
 			// Remove these checks in version 2
-			if ( props.has( 'oncreate' ) && props.has( 'onrender' ) ) {
-				validator.error( 'Cannot have both oncreate and onrender', props.get( 'onrender' ).start );
+			if (props.has('oncreate') && props.has('onrender')) {
+				validator.error(
+					'Cannot have both oncreate and onrender',
+					props.get('onrender').start
+				);
 			}
 
-			if ( props.has( 'ondestroy' ) && props.has( 'onteardown' ) ) {
-				validator.error( 'Cannot have both ondestroy and onteardown', props.get( 'onteardown' ).start );
+			if (props.has('ondestroy') && props.has('onteardown')) {
+				validator.error(
+					'Cannot have both ondestroy and onteardown',
+					props.get('onteardown').start
+				);
 			}
 
 			// ensure all exported props are valid
-			node.declaration.properties.forEach( ( prop: Node ) => {
-				const propValidator = propValidators[ prop.key.name ];
+			node.declaration.properties.forEach((prop: Node) => {
+				const propValidator = propValidators[prop.key.name];
 
-				if ( propValidator ) {
-					propValidator( validator, prop );
+				if (propValidator) {
+					propValidator(validator, prop);
 				} else {
-					const match = fuzzymatch( prop.key.name, validPropList );
-					if ( match ) {
-						validator.error( `Unexpected property '${prop.key.name}' (did you mean '${match}'?)`, prop.start );
-					} else if ( /FunctionExpression/.test( prop.value.type ) ) {
-						validator.error( `Unexpected property '${prop.key.name}' (did you mean to include it in 'methods'?)`, prop.start );
+					const match = fuzzymatch(prop.key.name, validPropList);
+					if (match) {
+						validator.error(
+							`Unexpected property '${prop.key
+								.name}' (did you mean '${match}'?)`,
+							prop.start
+						);
+					} else if (/FunctionExpression/.test(prop.value.type)) {
+						validator.error(
+							`Unexpected property '${prop.key
+								.name}' (did you mean to include it in 'methods'?)`,
+							prop.start
+						);
 					} else {
-						validator.error( `Unexpected property '${prop.key.name}'`, prop.start );
+						validator.error(
+							`Unexpected property '${prop.key.name}'`,
+							prop.start
+						);
 					}
 				}
 			});
 
-			if ( props.has( 'namespace' ) ) {
-				const ns = props.get( 'namespace' ).value.value;
-				validator.namespace = namespaces[ ns ] || ns;
+			if (props.has('namespace')) {
+				const ns = props.get('namespace').value.value;
+				validator.namespace = namespaces[ns] || ns;
 			}
 
 			validator.defaultExport = node;
 		}
 	});
 
-	[ 'components', 'methods', 'helpers', 'transitions' ].forEach( key => {
-		if ( validator.properties.has( key ) ) {
-			validator.properties.get( key ).value.properties.forEach( ( prop: Node ) => {
-				validator[ key ].set( prop.key.name, prop.value );
+	['components', 'methods', 'helpers', 'transitions'].forEach(key => {
+		if (validator.properties.has(key)) {
+			validator.properties.get(key).value.properties.forEach((prop: Node) => {
+				validator[key].set(prop.key.name, prop.value);
 			});
 		}
 	});
diff --git a/src/validate/js/propValidators/components.ts b/src/validate/js/propValidators/components.ts
index 36077c52ed..a7ca5eb990 100644
--- a/src/validate/js/propValidators/components.ts
+++ b/src/validate/js/propValidators/components.ts
@@ -3,22 +3,28 @@ import checkForComputedKeys from '../utils/checkForComputedKeys';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function components ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'components' property must be an object literal`, prop.start );
+export default function components(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'components' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 
-	prop.value.properties.forEach( ( component: Node ) => {
-		if ( component.key.name === 'state' ) {
-			validator.error( `Component constructors cannot be called 'state' due to technical limitations`, component.start );
+	prop.value.properties.forEach((component: Node) => {
+		if (component.key.name === 'state') {
+			validator.error(
+				`Component constructors cannot be called 'state' due to technical limitations`,
+				component.start
+			);
 		}
 
-		if ( !/^[A-Z]/.test( component.key.name ) ) {
-			validator.warn( `Component names should be capitalised`, component.start );
+		if (!/^[A-Z]/.test(component.key.name)) {
+			validator.warn(`Component names should be capitalised`, component.start);
 		}
 	});
 }
diff --git a/src/validate/js/propValidators/computed.ts b/src/validate/js/propValidators/computed.ts
index c72ef26e73..ec0156bd99 100644
--- a/src/validate/js/propValidators/computed.ts
+++ b/src/validate/js/propValidators/computed.ts
@@ -3,35 +3,53 @@ import checkForComputedKeys from '../utils/checkForComputedKeys';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-const isFunctionExpression = new Set( [ 'FunctionExpression', 'ArrowFunctionExpression' ] );
-
-export default function computed ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'computed' property must be an object literal`, prop.start );
+const isFunctionExpression = new Set([
+	'FunctionExpression',
+	'ArrowFunctionExpression'
+]);
+
+export default function computed(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'computed' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 
-	prop.value.properties.forEach( ( computation: Node ) => {
-		if ( !isFunctionExpression.has( computation.value.type ) ) {
-			validator.error( `Computed properties can be function expressions or arrow function expressions`, computation.value.start );
+	prop.value.properties.forEach((computation: Node) => {
+		if (!isFunctionExpression.has(computation.value.type)) {
+			validator.error(
+				`Computed properties can be function expressions or arrow function expressions`,
+				computation.value.start
+			);
 			return;
 		}
 
 		const params = computation.value.params;
 
-		if ( params.length === 0 ) {
-			validator.error( `A computed value must depend on at least one property`, computation.value.start );
+		if (params.length === 0) {
+			validator.error(
+				`A computed value must depend on at least one property`,
+				computation.value.start
+			);
 			return;
 		}
 
-		params.forEach( ( param: Node ) => {
-			const valid = param.type === 'Identifier' || param.type === 'AssignmentPattern' && param.left.type === 'Identifier';
-
-			if ( !valid ) {
-				validator.error( `Computed properties cannot use destructuring in function parameters`, param.start );
+		params.forEach((param: Node) => {
+			const valid =
+				param.type === 'Identifier' ||
+				(param.type === 'AssignmentPattern' &&
+					param.left.type === 'Identifier');
+
+			if (!valid) {
+				validator.error(
+					`Computed properties cannot use destructuring in function parameters`,
+					param.start
+				);
 			}
 		});
 	});
diff --git a/src/validate/js/propValidators/data.ts b/src/validate/js/propValidators/data.ts
index 9727385a78..b49931cf21 100644
--- a/src/validate/js/propValidators/data.ts
+++ b/src/validate/js/propValidators/data.ts
@@ -1,14 +1,14 @@
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-const disallowed = new Set([ 'Literal', 'ObjectExpression', 'ArrayExpression' ]);
+const disallowed = new Set(['Literal', 'ObjectExpression', 'ArrayExpression']);
 
-export default function data ( validator: Validator, prop: Node ) {
-	while ( prop.type === 'ParenthesizedExpression' ) prop = prop.expression;
+export default function data(validator: Validator, prop: Node) {
+	while (prop.type === 'ParenthesizedExpression') prop = prop.expression;
 
 	// TODO should we disallow references and expressions as well?
 
-	if ( disallowed.has( prop.value.type ) ) {
-		validator.error( `'data' must be a function`, prop.value.start );
+	if (disallowed.has(prop.value.type)) {
+		validator.error(`'data' must be a function`, prop.value.start);
 	}
 }
diff --git a/src/validate/js/propValidators/events.ts b/src/validate/js/propValidators/events.ts
index b1c7ecb842..1bbf75d1e6 100644
--- a/src/validate/js/propValidators/events.ts
+++ b/src/validate/js/propValidators/events.ts
@@ -3,12 +3,15 @@ import checkForComputedKeys from '../utils/checkForComputedKeys';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function events ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'events' property must be an object literal`, prop.start );
+export default function events(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'events' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 }
diff --git a/src/validate/js/propValidators/helpers.ts b/src/validate/js/propValidators/helpers.ts
index 6505eb9b5e..6dfc02013f 100644
--- a/src/validate/js/propValidators/helpers.ts
+++ b/src/validate/js/propValidators/helpers.ts
@@ -4,53 +4,67 @@ import { walk } from 'estree-walker';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function helpers ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'helpers' property must be an object literal`, prop.start );
+export default function helpers(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'helpers' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 
-	prop.value.properties.forEach( ( prop: Node ) => {
-		if ( !/FunctionExpression/.test( prop.value.type ) ) return;
+	prop.value.properties.forEach((prop: Node) => {
+		if (!/FunctionExpression/.test(prop.value.type)) return;
 
 		let lexicalDepth = 0;
 		let usesArguments = false;
 
-		walk( prop.value.body, {
-			enter ( node: Node ) {
-				if ( /^Function/.test( node.type ) ) {
+		walk(prop.value.body, {
+			enter(node: Node) {
+				if (/^Function/.test(node.type)) {
 					lexicalDepth += 1;
-				}
-
-				else if ( lexicalDepth === 0 ) {
+				} else if (lexicalDepth === 0) {
 					// handle special case that's caused some people confusion — using `this.get(...)` instead of passing argument
 					// TODO do the same thing for computed values?
-					if ( node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && node.callee.object.type === 'ThisExpression' && node.callee.property.name === 'get' && !node.callee.property.computed ) {
-						validator.error( `Cannot use this.get(...) — it must be passed into the helper function as an argument`, node.start );
-					}
-
-					if ( node.type === 'ThisExpression' ) {
-						validator.error( `Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`, node.start );
+					if (
+						node.type === 'CallExpression' &&
+						node.callee.type === 'MemberExpression' &&
+						node.callee.object.type === 'ThisExpression' &&
+						node.callee.property.name === 'get' &&
+						!node.callee.property.computed
+					) {
+						validator.error(
+							`Cannot use this.get(...) — it must be passed into the helper function as an argument`,
+							node.start
+						);
 					}
 
-					else if ( node.type === 'Identifier' && node.name === 'arguments' ) {
+					if (node.type === 'ThisExpression') {
+						validator.error(
+							`Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`,
+							node.start
+						);
+					} else if (node.type === 'Identifier' && node.name === 'arguments') {
 						usesArguments = true;
 					}
 				}
 			},
 
-			leave ( node: Node ) {
-				if ( /^Function/.test( node.type ) ) {
+			leave(node: Node) {
+				if (/^Function/.test(node.type)) {
 					lexicalDepth -= 1;
 				}
 			}
 		});
 
-		if ( prop.value.params.length === 0 && !usesArguments ) {
-			validator.warn( `Helpers should be pure functions, with at least one argument`, prop.start );
+		if (prop.value.params.length === 0 && !usesArguments) {
+			validator.warn(
+				`Helpers should be pure functions, with at least one argument`,
+				prop.start
+			);
 		}
 	});
 }
diff --git a/src/validate/js/propValidators/methods.ts b/src/validate/js/propValidators/methods.ts
index 144a2257ee..7d8547ef39 100644
--- a/src/validate/js/propValidators/methods.ts
+++ b/src/validate/js/propValidators/methods.ts
@@ -5,26 +5,36 @@ import usesThisOrArguments from '../utils/usesThisOrArguments';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-const builtin = new Set( [ 'set', 'get', 'on', 'fire', 'observe', 'destroy' ] );
+const builtin = new Set(['set', 'get', 'on', 'fire', 'observe', 'destroy']);
 
-export default function methods ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'methods' property must be an object literal`, prop.start );
+export default function methods(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'methods' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForAccessors( validator, prop.value.properties, 'Methods' );
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForAccessors(validator, prop.value.properties, 'Methods');
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 
-	prop.value.properties.forEach( ( prop: Node ) => {
-		if ( builtin.has( prop.key.name ) ) {
-			validator.error( `Cannot overwrite built-in method '${prop.key.name}'`, prop.start );
+	prop.value.properties.forEach((prop: Node) => {
+		if (builtin.has(prop.key.name)) {
+			validator.error(
+				`Cannot overwrite built-in method '${prop.key.name}'`,
+				prop.start
+			);
 		}
 
-		if ( prop.value.type === 'ArrowFunctionExpression' ) {
-			if ( usesThisOrArguments( prop.value.body ) ) {
-				validator.error( `Method '${prop.key.name}' should be a function expression, not an arrow function expression`, prop.start );
+		if (prop.value.type === 'ArrowFunctionExpression') {
+			if (usesThisOrArguments(prop.value.body)) {
+				validator.error(
+					`Method '${prop.key
+						.name}' should be a function expression, not an arrow function expression`,
+					prop.start
+				);
 			}
 		}
 	});
diff --git a/src/validate/js/propValidators/namespace.ts b/src/validate/js/propValidators/namespace.ts
index 5b43bf72ea..30e3ead77f 100644
--- a/src/validate/js/propValidators/namespace.ts
+++ b/src/validate/js/propValidators/namespace.ts
@@ -3,21 +3,27 @@ import fuzzymatch from '../../utils/fuzzymatch';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-const valid = new Set( namespaces.validNamespaces );
+const valid = new Set(namespaces.validNamespaces);
 
-export default function namespace ( validator: Validator, prop: Node ) {
+export default function namespace(validator: Validator, prop: Node) {
 	const ns = prop.value.value;
 
-	if ( prop.value.type !== 'Literal' || typeof ns !== 'string' ) {
-		validator.error( `The 'namespace' property must be a string literal representing a valid namespace`, prop.start );
+	if (prop.value.type !== 'Literal' || typeof ns !== 'string') {
+		validator.error(
+			`The 'namespace' property must be a string literal representing a valid namespace`,
+			prop.start
+		);
 	}
 
-	if ( !valid.has( ns ) ) {
-		const match = fuzzymatch( ns, namespaces.validNamespaces );
-		if ( match ) {
-			validator.error( `Invalid namespace '${ns}' (did you mean '${match}'?)`, prop.start );
+	if (!valid.has(ns)) {
+		const match = fuzzymatch(ns, namespaces.validNamespaces);
+		if (match) {
+			validator.error(
+				`Invalid namespace '${ns}' (did you mean '${match}'?)`,
+				prop.start
+			);
 		} else {
-			validator.error( `Invalid namespace '${ns}'`, prop.start );
+			validator.error(`Invalid namespace '${ns}'`, prop.start);
 		}
 	}
 }
diff --git a/src/validate/js/propValidators/oncreate.ts b/src/validate/js/propValidators/oncreate.ts
index 9ebf44a782..587a8b3679 100644
--- a/src/validate/js/propValidators/oncreate.ts
+++ b/src/validate/js/propValidators/oncreate.ts
@@ -2,10 +2,13 @@ import usesThisOrArguments from '../utils/usesThisOrArguments';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function oncreate ( validator: Validator, prop: Node ) {
-	if ( prop.value.type === 'ArrowFunctionExpression' ) {
-		if ( usesThisOrArguments( prop.value.body ) ) {
-			validator.error( `'oncreate' should be a function expression, not an arrow function expression`, prop.start );
+export default function oncreate(validator: Validator, prop: Node) {
+	if (prop.value.type === 'ArrowFunctionExpression') {
+		if (usesThisOrArguments(prop.value.body)) {
+			validator.error(
+				`'oncreate' should be a function expression, not an arrow function expression`,
+				prop.start
+			);
 		}
 	}
 }
diff --git a/src/validate/js/propValidators/ondestroy.ts b/src/validate/js/propValidators/ondestroy.ts
index 62155e563f..e12525e73f 100644
--- a/src/validate/js/propValidators/ondestroy.ts
+++ b/src/validate/js/propValidators/ondestroy.ts
@@ -2,10 +2,13 @@ import usesThisOrArguments from '../utils/usesThisOrArguments';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function ondestroy ( validator: Validator, prop: Node ) {
-	if ( prop.value.type === 'ArrowFunctionExpression' ) {
-		if ( usesThisOrArguments( prop.value.body ) ) {
-			validator.error( `'ondestroy' should be a function expression, not an arrow function expression`, prop.start );
+export default function ondestroy(validator: Validator, prop: Node) {
+	if (prop.value.type === 'ArrowFunctionExpression') {
+		if (usesThisOrArguments(prop.value.body)) {
+			validator.error(
+				`'ondestroy' should be a function expression, not an arrow function expression`,
+				prop.start
+			);
 		}
 	}
 }
diff --git a/src/validate/js/propValidators/onrender.ts b/src/validate/js/propValidators/onrender.ts
index 0cc58c8af4..fd6751a373 100644
--- a/src/validate/js/propValidators/onrender.ts
+++ b/src/validate/js/propValidators/onrender.ts
@@ -2,7 +2,10 @@ import oncreate from './oncreate';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function onrender ( validator: Validator, prop: Node ) {
-	validator.warn( `'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x`, prop.start );
-	oncreate( validator, prop );
+export default function onrender(validator: Validator, prop: Node) {
+	validator.warn(
+		`'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x`,
+		prop.start
+	);
+	oncreate(validator, prop);
 }
diff --git a/src/validate/js/propValidators/onteardown.ts b/src/validate/js/propValidators/onteardown.ts
index 6c6afef7a0..cca770909c 100644
--- a/src/validate/js/propValidators/onteardown.ts
+++ b/src/validate/js/propValidators/onteardown.ts
@@ -2,7 +2,10 @@ import ondestroy from './ondestroy';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function onteardown ( validator: Validator, prop: Node ) {
-	validator.warn( `'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x`, prop.start );
-	ondestroy( validator, prop );
+export default function onteardown(validator: Validator, prop: Node) {
+	validator.warn(
+		`'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x`,
+		prop.start
+	);
+	ondestroy(validator, prop);
 }
diff --git a/src/validate/js/propValidators/transitions.ts b/src/validate/js/propValidators/transitions.ts
index b50302d93e..6470beee6f 100644
--- a/src/validate/js/propValidators/transitions.ts
+++ b/src/validate/js/propValidators/transitions.ts
@@ -3,16 +3,19 @@ import checkForComputedKeys from '../utils/checkForComputedKeys';
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function transitions ( validator: Validator, prop: Node ) {
-	if ( prop.value.type !== 'ObjectExpression' ) {
-		validator.error( `The 'transitions' property must be an object literal`, prop.start );
+export default function transitions(validator: Validator, prop: Node) {
+	if (prop.value.type !== 'ObjectExpression') {
+		validator.error(
+			`The 'transitions' property must be an object literal`,
+			prop.start
+		);
 		return;
 	}
 
-	checkForDupes( validator, prop.value.properties );
-	checkForComputedKeys( validator, prop.value.properties );
+	checkForDupes(validator, prop.value.properties);
+	checkForComputedKeys(validator, prop.value.properties);
 
-	prop.value.properties.forEach( () => {
+	prop.value.properties.forEach(() => {
 		// TODO probably some validation that can happen here...
 		// checking for use of `this` etc?
 	});
diff --git a/src/validate/js/utils/checkForAccessors.ts b/src/validate/js/utils/checkForAccessors.ts
index 45ee1eb30d..6c00d3a23a 100644
--- a/src/validate/js/utils/checkForAccessors.ts
+++ b/src/validate/js/utils/checkForAccessors.ts
@@ -1,10 +1,14 @@
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function checkForAccessors ( validator: Validator, properties: Node[], label: string ) {
-	properties.forEach( prop => {
-		if ( prop.kind !== 'init' ) {
-			validator.error( `${label} cannot use getters and setters`, prop.start );
+export default function checkForAccessors(
+	validator: Validator,
+	properties: Node[],
+	label: string
+) {
+	properties.forEach(prop => {
+		if (prop.kind !== 'init') {
+			validator.error(`${label} cannot use getters and setters`, prop.start);
 		}
 	});
 }
diff --git a/src/validate/js/utils/checkForComputedKeys.ts b/src/validate/js/utils/checkForComputedKeys.ts
index ca0291e2a9..cf3892d02c 100644
--- a/src/validate/js/utils/checkForComputedKeys.ts
+++ b/src/validate/js/utils/checkForComputedKeys.ts
@@ -1,10 +1,13 @@
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function checkForComputedKeys ( validator: Validator, properties: Node[] ) {
-	properties.forEach( prop => {
-		if ( prop.key.computed ) {
-			validator.error( `Cannot use computed keys`, prop.start );
+export default function checkForComputedKeys(
+	validator: Validator,
+	properties: Node[]
+) {
+	properties.forEach(prop => {
+		if (prop.key.computed) {
+			validator.error(`Cannot use computed keys`, prop.start);
 		}
 	});
 }
diff --git a/src/validate/js/utils/checkForDupes.ts b/src/validate/js/utils/checkForDupes.ts
index db16a1133f..8565ab5388 100644
--- a/src/validate/js/utils/checkForDupes.ts
+++ b/src/validate/js/utils/checkForDupes.ts
@@ -1,14 +1,17 @@
 import { Validator } from '../../';
 import { Node } from '../../../interfaces';
 
-export default function checkForDupes ( validator: Validator, properties: Node[] ) {
+export default function checkForDupes(
+	validator: Validator,
+	properties: Node[]
+) {
 	const seen = new Set();
 
-	properties.forEach( prop => {
-		if ( seen.has( prop.key.name ) ) {
-			validator.error( `Duplicate property '${prop.key.name}'`, prop.start );
+	properties.forEach(prop => {
+		if (seen.has(prop.key.name)) {
+			validator.error(`Duplicate property '${prop.key.name}'`, prop.start);
 		}
 
-		seen.add( prop.key.name );
+		seen.add(prop.key.name);
 	});
 }
diff --git a/src/validate/js/utils/usesThisOrArguments.ts b/src/validate/js/utils/usesThisOrArguments.ts
index 2c56a57f6c..a9c181a67d 100644
--- a/src/validate/js/utils/usesThisOrArguments.ts
+++ b/src/validate/js/utils/usesThisOrArguments.ts
@@ -2,20 +2,28 @@ import { walk } from 'estree-walker';
 import isReference from '../../../utils/isReference';
 import { Node } from '../../../interfaces';
 
-export default function usesThisOrArguments ( node: Node ) {
+export default function usesThisOrArguments(node: Node) {
 	let result = false;
 
-	walk( node, {
-		enter ( node: Node, parent: Node ) {
-			if ( result || node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' ) {
+	walk(node, {
+		enter(node: Node, parent: Node) {
+			if (
+				result ||
+				node.type === 'FunctionExpression' ||
+				node.type === 'FunctionDeclaration'
+			) {
 				return this.skip();
 			}
 
-			if ( node.type === 'ThisExpression' ) {
+			if (node.type === 'ThisExpression') {
 				result = true;
 			}
 
-			if ( node.type === 'Identifier' && isReference( node, parent ) && node.name === 'arguments' ) {
+			if (
+				node.type === 'Identifier' &&
+				isReference(node, parent) &&
+				node.name === 'arguments'
+			) {
 				result = true;
 			}
 		}
diff --git a/src/validate/utils/FuzzySet.ts b/src/validate/utils/FuzzySet.ts
index bed3ee1c13..2d7ae95d23 100644
--- a/src/validate/utils/FuzzySet.ts
+++ b/src/validate/utils/FuzzySet.ts
@@ -1,12 +1,19 @@
 // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js
 // BSD Licensed
 
-export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUpper) {
+export default function FuzzySet(
+	arr,
+	useLevenshtein,
+	gramSizeLower,
+	gramSizeUpper
+) {
 	// default options
 	arr = arr || [];
 	this.gramSizeLower = gramSizeLower || 2;
 	this.gramSizeUpper = gramSizeUpper || 3;
-	this.useLevenshtein = (typeof useLevenshtein !== 'boolean') ? true : useLevenshtein;
+	this.useLevenshtein = typeof useLevenshtein !== 'boolean'
+		? true
+		: useLevenshtein;
 
 	// define all the object functions and attributes
 	this.exactSet = {};
@@ -14,7 +21,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 	this.items = {};
 
 	// helper functions
-	function levenshtein ( str1, str2 ) {
+	function levenshtein(str1, str2) {
 		const current = [];
 		let prev;
 		let value;
@@ -40,10 +47,12 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 	}
 
 	// return an edit distance from 0 to 1
-	function _distance (str1, str2) {
-		if (str1 === null && str2 === null) throw 'Trying to compare two null values';
+	function _distance(str1, str2) {
+		if (str1 === null && str2 === null)
+			throw 'Trying to compare two null values';
 		if (str1 === null || str2 === null) return 0;
-		str1 = String(str1); str2 = String(str2);
+		str1 = String(str1);
+		str2 = String(str2);
 
 		const distance = levenshtein(str1, str2);
 		if (str1.length > str2.length) {
@@ -55,7 +64,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 
 	const _nonWordRe = /[^\w, ]+/;
 
-	function _iterateGrams (value, gramSize) {
+	function _iterateGrams(value, gramSize) {
 		gramSize = gramSize || 2;
 		const simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-';
 		const lenDiff = gramSize - simplified.length;
@@ -72,7 +81,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		return results;
 	}
 
-	function _gramCounter (value, gramSize) {
+	function _gramCounter(value, gramSize) {
 		// return an object where key=gram, value=number of occurrences
 		gramSize = gramSize || 2;
 		const result = {};
@@ -90,7 +99,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 	}
 
 	// the main functions
-	this.get = function (value, defaultValue) {
+	this.get = function(value, defaultValue) {
 		// check for value in set, returning defaultValue or null if none found
 		const result = this._get(value);
 		if (!result && typeof defaultValue !== 'undefined') {
@@ -99,7 +108,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		return result;
 	};
 
-	this._get = function (value) {
+	this._get = function(value) {
 		const normalizedValue = this._normalizeStr(value);
 		const result = this.exactSet[normalizedValue];
 
@@ -109,7 +118,11 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 
 		let results = [];
 		// start with high gram size and if there are no results, go to lower gram sizes
-		for (let gramSize = this.gramSizeUpper; gramSize >= this.gramSizeLower; --gramSize) {
+		for (
+			let gramSize = this.gramSizeUpper;
+			gramSize >= this.gramSizeLower;
+			--gramSize
+		) {
 			results = this.__get(value, gramSize);
 			if (results) {
 				return results;
@@ -118,7 +131,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		return null;
 	};
 
-	this.__get = function (value, gramSize) {
+	this.__get = function(value, gramSize) {
 		const normalizedValue = this._normalizeStr(value);
 		const matches = {};
 		const gramCounts = _gramCounter(normalizedValue, gramSize);
@@ -146,10 +159,9 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 			}
 		}
 
-		function isEmptyObject ( obj ) {
-			for ( const prop in obj ) {
-				if ( obj.hasOwnProperty( prop ) )
-					return false;
+		function isEmptyObject(obj) {
+			for (const prop in obj) {
+				if (obj.hasOwnProperty(prop)) return false;
 			}
 			return true;
 		}
@@ -165,9 +177,12 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		// build a results list of [score, str]
 		for (const matchIndex in matches) {
 			matchScore = matches[matchIndex];
-			results.push([matchScore / (vectorNormal * items[matchIndex][0]), items[matchIndex][1]]);
+			results.push([
+				matchScore / (vectorNormal * items[matchIndex][0]),
+				items[matchIndex][1]
+			]);
 		}
-		function sortDescending (a, b) {
+		function sortDescending(a, b) {
 			if (a[0] < b[0]) {
 				return 1;
 			} else if (a[0] > b[0]) {
@@ -183,7 +198,10 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 			const endIndex = Math.min(50, results.length);
 			// truncate somewhat arbitrarily to 50
 			for (let i = 0; i < endIndex; ++i) {
-				newResults.push([_distance(results[i][1], normalizedValue), results[i][1]]);
+				newResults.push([
+					_distance(results[i][1], normalizedValue),
+					results[i][1]
+				]);
 			}
 			results = newResults;
 			results.sort(sortDescending);
@@ -197,7 +215,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		return newResults;
 	};
 
-	this.add = function (value) {
+	this.add = function(value) {
 		const normalizedValue = this._normalizeStr(value);
 		if (normalizedValue in this.exactSet) {
 			return false;
@@ -209,7 +227,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		}
 	};
 
-	this._add = function (value, gramSize) {
+	this._add = function(value, gramSize) {
 		const normalizedValue = this._normalizeStr(value);
 		const items = this.items[gramSize] || [];
 		const index = items.length;
@@ -235,13 +253,14 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		this.exactSet[normalizedValue] = value;
 	};
 
-	this._normalizeStr = function (str) {
-		if (Object.prototype.toString.call(str) !== '[object String]') throw 'Must use a string as argument to FuzzySet functions';
+	this._normalizeStr = function(str) {
+		if (Object.prototype.toString.call(str) !== '[object String]')
+			throw 'Must use a string as argument to FuzzySet functions';
 		return str.toLowerCase();
 	};
 
 	// return length of items in set
-	this.length = function () {
+	this.length = function() {
 		let count = 0;
 		let prop;
 
@@ -254,7 +273,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 	};
 
 	// return is set is empty
-	this.isEmpty = function () {
+	this.isEmpty = function() {
 		for (const prop in this.exactSet) {
 			if (this.exactSet.hasOwnProperty(prop)) {
 				return false;
@@ -264,7 +283,7 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 	};
 
 	// return list of values loaded into set
-	this.values = function () {
+	this.values = function() {
 		const values = [];
 
 		for (const prop in this.exactSet) {
@@ -275,7 +294,6 @@ export default function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUp
 		return values;
 	};
 
-
 	// initialization
 	let i = this.gramSizeLower;
 	for (i; i < this.gramSizeUpper + 1; ++i) {
diff --git a/src/validate/utils/fuzzymatch.ts b/src/validate/utils/fuzzymatch.ts
index 1769871df9..5d70372191 100644
--- a/src/validate/utils/fuzzymatch.ts
+++ b/src/validate/utils/fuzzymatch.ts
@@ -1,10 +1,8 @@
 import FuzzySet from './FuzzySet';
 
-export default function fuzzymatch ( name: string, names: string[] ) {
-	const set = new FuzzySet( names );
-	const matches = set.get( name );
+export default function fuzzymatch(name: string, names: string[]) {
+	const set = new FuzzySet(names);
+	const matches = set.get(name);
 
-	return matches && matches[0] && matches[0][0] > 0.7 ?
-		matches[0][1] :
-		null;
-}
\ No newline at end of file
+	return matches && matches[0] && matches[0][0] > 0.7 ? matches[0][1] : null;
+}
diff --git a/src/validate/utils/list.ts b/src/validate/utils/list.ts
index c37b6dd541..785f006d19 100644
--- a/src/validate/utils/list.ts
+++ b/src/validate/utils/list.ts
@@ -1,4 +1,6 @@
-export default function list ( items: string[], conjunction = 'or' ) {
-	if ( items.length === 1 ) return items[0];
-	return `${items.slice( 0, -1 ).join( ', ' )} ${conjunction} ${items[ items.length - 1 ]}`;
-}
\ No newline at end of file
+export default function list(items: string[], conjunction = 'or') {
+	if (items.length === 1) return items[0];
+	return `${items.slice(0, -1).join(', ')} ${conjunction} ${items[
+		items.length - 1
+	]}`;
+}
diff --git a/test/js/samples/collapses-text-around-comments/expected-bundle.js b/test/js/samples/collapses-text-around-comments/expected-bundle.js
index b3197f189d..e8ad287400 100644
--- a/test/js/samples/collapses-text-around-comments/expected-bundle.js
+++ b/test/js/samples/collapses-text-around-comments/expected-bundle.js
@@ -1,121 +1,127 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function setAttribute ( node, attribute, value ) {
-	node.setAttribute( attribute, value );
+function setAttribute(node, attribute, value) {
+	node.setAttribute(attribute, value);
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/computed-collapsed-if/expected-bundle.js b/test/js/samples/computed-collapsed-if/expected-bundle.js
index fce7cbda6f..f491d92da1 100644
--- a/test/js/samples/computed-collapsed-if/expected-bundle.js
+++ b/test/js/samples/computed-collapsed-if/expected-bundle.js
@@ -1,97 +1,103 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/each-block-changed-check/expected-bundle.js b/test/js/samples/each-block-changed-check/expected-bundle.js
index 9a1b10e93f..4bfdc1e50b 100644
--- a/test/js/samples/each-block-changed-check/expected-bundle.js
+++ b/test/js/samples/each-block-changed-check/expected-bundle.js
@@ -1,130 +1,136 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function detachBetween ( before, after ) {
-	while ( before.nextSibling && before.nextSibling !== after ) {
-		before.parentNode.removeChild( before.nextSibling );
+function detachBetween(before, after) {
+	while (before.nextSibling && before.nextSibling !== after) {
+		before.parentNode.removeChild(before.nextSibling);
 	}
 }
 
 // TODO this is out of date
-function destroyEach ( iterations, detach, start ) {
-	for ( var i = start; i < iterations.length; i += 1 ) {
-		if ( iterations[i] ) iterations[i].destroy( detach );
+function destroyEach(iterations, detach, start) {
+	for (var i = start; i < iterations.length; i += 1) {
+		if (iterations[i]) iterations[i].destroy(detach);
 	}
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js
index 3859406832..e79b8f0659 100644
--- a/test/js/samples/each-block-changed-check/expected.js
+++ b/test/js/samples/each-block-changed-check/expected.js
@@ -168,4 +168,4 @@ SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = functio
 	this._torndown = true;
 };
 
-export default SvelteComponent;
+export default SvelteComponent;
\ No newline at end of file
diff --git a/test/js/samples/event-handlers-custom/expected-bundle.js b/test/js/samples/event-handlers-custom/expected-bundle.js
index 804c128f60..128cc96c43 100644
--- a/test/js/samples/event-handlers-custom/expected-bundle.js
+++ b/test/js/samples/event-handlers-custom/expected-bundle.js
@@ -1,115 +1,121 @@
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/if-block-no-update/expected-bundle.js b/test/js/samples/if-block-no-update/expected-bundle.js
index d03f5b63fd..bf5690896d 100644
--- a/test/js/samples/if-block-no-update/expected-bundle.js
+++ b/test/js/samples/if-block-no-update/expected-bundle.js
@@ -1,121 +1,127 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function createComment () {
-	return document.createComment( '' );
+function createComment() {
+	return document.createComment('');
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/if-block-simple/expected-bundle.js b/test/js/samples/if-block-simple/expected-bundle.js
index 730f56c546..03b2450bfc 100644
--- a/test/js/samples/if-block-simple/expected-bundle.js
+++ b/test/js/samples/if-block-simple/expected-bundle.js
@@ -1,121 +1,127 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function createComment () {
-	return document.createComment( '' );
+function createComment() {
+	return document.createComment('');
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/non-imported-component/expected-bundle.js b/test/js/samples/non-imported-component/expected-bundle.js
index f66a1e1421..3a03995a16 100644
--- a/test/js/samples/non-imported-component/expected-bundle.js
+++ b/test/js/samples/non-imported-component/expected-bundle.js
@@ -1,109 +1,115 @@
 import Imported from 'Imported.html';
 
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/onrender-onteardown-rewritten/expected-bundle.js b/test/js/samples/onrender-onteardown-rewritten/expected-bundle.js
index 88472296ad..8a9044c8ca 100644
--- a/test/js/samples/onrender-onteardown-rewritten/expected-bundle.js
+++ b/test/js/samples/onrender-onteardown-rewritten/expected-bundle.js
@@ -1,97 +1,103 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/samples/use-elements-as-anchors/expected-bundle.js b/test/js/samples/use-elements-as-anchors/expected-bundle.js
index d39c029eed..30bf07a1e4 100644
--- a/test/js/samples/use-elements-as-anchors/expected-bundle.js
+++ b/test/js/samples/use-elements-as-anchors/expected-bundle.js
@@ -1,121 +1,127 @@
-function noop () {}
-
-function assign ( target ) {
-	var k, source, i = 1, len = arguments.length;
-	for ( ; i < len; i++ ) {
+function noop() {}
+
+function assign(target) {
+	var k,
+		source,
+		i = 1,
+		len = arguments.length;
+	for (; i < len; i++) {
 		source = arguments[i];
-		for ( k in source ) target[k] = source[k];
+		for (k in source) target[k] = source[k];
 	}
 
 	return target;
 }
 
-function appendNode ( node, target ) {
-	target.appendChild( node );
+function appendNode(node, target) {
+	target.appendChild(node);
 }
 
-function insertNode ( node, target, anchor ) {
-	target.insertBefore( node, anchor );
+function insertNode(node, target, anchor) {
+	target.insertBefore(node, anchor);
 }
 
-function detachNode ( node ) {
-	node.parentNode.removeChild( node );
+function detachNode(node) {
+	node.parentNode.removeChild(node);
 }
 
-function createElement ( name ) {
-	return document.createElement( name );
+function createElement(name) {
+	return document.createElement(name);
 }
 
-function createText ( data ) {
-	return document.createTextNode( data );
+function createText(data) {
+	return document.createTextNode(data);
 }
 
-function createComment () {
-	return document.createComment( '' );
+function createComment() {
+	return document.createComment('');
 }
 
-function differs ( a, b ) {
-	return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );
+function differs(a, b) {
+	return a !== b || ((a && typeof a === 'object') || typeof a === 'function');
 }
 
-function dispatchObservers ( component, group, newState, oldState ) {
-	for ( var key in group ) {
-		if ( !( key in newState ) ) continue;
+function dispatchObservers(component, group, newState, oldState) {
+	for (var key in group) {
+		if (!(key in newState)) continue;
 
-		var newValue = newState[ key ];
-		var oldValue = oldState[ key ];
+		var newValue = newState[key];
+		var oldValue = oldState[key];
 
-		if ( differs( newValue, oldValue ) ) {
-			var callbacks = group[ key ];
-			if ( !callbacks ) continue;
+		if (differs(newValue, oldValue)) {
+			var callbacks = group[key];
+			if (!callbacks) continue;
 
-			for ( var i = 0; i < callbacks.length; i += 1 ) {
+			for (var i = 0; i < callbacks.length; i += 1) {
 				var callback = callbacks[i];
-				if ( callback.__calling ) continue;
+				if (callback.__calling) continue;
 
 				callback.__calling = true;
-				callback.call( component, newValue, oldValue );
+				callback.call(component, newValue, oldValue);
 				callback.__calling = false;
 			}
 		}
 	}
 }
 
-function get ( key ) {
-	return key ? this._state[ key ] : this._state;
+function get(key) {
+	return key ? this._state[key] : this._state;
 }
 
-function fire ( eventName, data ) {
-	var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
-	if ( !handlers ) return;
+function fire(eventName, data) {
+	var handlers =
+		eventName in this._handlers && this._handlers[eventName].slice();
+	if (!handlers) return;
 
-	for ( var i = 0; i < handlers.length; i += 1 ) {
-		handlers[i].call( this, data );
+	for (var i = 0; i < handlers.length; i += 1) {
+		handlers[i].call(this, data);
 	}
 }
 
-function observe ( key, callback, options ) {
-	var group = ( options && options.defer ) ? this._observers.post : this._observers.pre;
+function observe(key, callback, options) {
+	var group = options && options.defer
+		? this._observers.post
+		: this._observers.pre;
 
-	( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+	(group[key] || (group[key] = [])).push(callback);
 
-	if ( !options || options.init !== false ) {
+	if (!options || options.init !== false) {
 		callback.__calling = true;
-		callback.call( this, this._state[ key ] );
+		callback.call(this, this._state[key]);
 		callback.__calling = false;
 	}
 
 	return {
-		cancel: function () {
-			var index = group[ key ].indexOf( callback );
-			if ( ~index ) group[ key ].splice( index, 1 );
+		cancel: function() {
+			var index = group[key].indexOf(callback);
+			if (~index) group[key].splice(index, 1);
 		}
 	};
 }
 
-function on ( eventName, handler ) {
-	if ( eventName === 'teardown' ) return this.on( 'destroy', handler );
+function on(eventName, handler) {
+	if (eventName === 'teardown') return this.on('destroy', handler);
 
-	var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
-	handlers.push( handler );
+	var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
+	handlers.push(handler);
 
 	return {
-		cancel: function () {
-			var index = handlers.indexOf( handler );
-			if ( ~index ) handlers.splice( index, 1 );
+		cancel: function() {
+			var index = handlers.indexOf(handler);
+			if (~index) handlers.splice(index, 1);
 		}
 	};
 }
 
-function set ( newState ) {
-	this._set( assign( {}, newState ) );
+function set(newState) {
+	this._set(assign({}, newState));
 	this._root._flush();
 }
 
-function _flush () {
-	if ( !this._renderHooks ) return;
+function _flush() {
+	if (!this._renderHooks) return;
 
-	while ( this._renderHooks.length ) {
+	while (this._renderHooks.length) {
 		this._renderHooks.pop()();
 	}
 }
diff --git a/test/js/update.js b/test/js/update.js
new file mode 100644
index 0000000000..4b51bf039d
--- /dev/null
+++ b/test/js/update.js
@@ -0,0 +1,10 @@
+// this file will replace all the expected.js and expected-bundle.js files with
+// their _actual equivalents. Only use it when you're sure that you haven't
+// broken anything!
+const fs = require('fs');
+const glob = require('glob');
+
+glob.sync('samples/*/_actual*', {cwd: __dirname}).forEach(file => {
+	const actual = fs.readFileSync(`${__dirname}/${file}`, 'utf-8');
+	fs.writeFileSync(`${__dirname}/${file.replace('_actual', 'expected')}`, actual);
+});
\ No newline at end of file