diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index ccc31d8aec..fc87740e5a 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -176,7 +176,7 @@ export default class Generator { }; } - findDependencies ( contextDependencies, indexes, expression ) { + findDependencies ( contextDependencies: Map, indexes: Map, expression: Node ) { if ( expression._dependencies ) return expression._dependencies; let scope = annotateWithScopes( expression ); @@ -340,23 +340,23 @@ export default class Generator { removeNode( this.code, js.content, node ); imports.push( node ); - node.specifiers.forEach( specifier => { + node.specifiers.forEach( ( specifier: Node ) => { this.importedNames.add( specifier.local.name ); }); } } - const defaultExport = body.find( node => node.type === 'ExportDefaultDeclaration' ); + const defaultExport = body.find( ( node: Node ) => node.type === 'ExportDefaultDeclaration' ); if ( defaultExport ) { - defaultExport.declaration.properties.forEach( prop => { + 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 => { + templateProperties[ key ].value.properties.forEach( ( prop: node ) => { this[ key ].add( prop.key.name ); }); } @@ -365,11 +365,11 @@ export default class Generator { if ( templateProperties.computed ) { const dependencies = new Map(); - templateProperties.computed.value.properties.forEach( prop => { + templateProperties.computed.value.properties.forEach( ( prop: Node ) => { const key = prop.key.name; const value = prop.value; - const deps = value.params.map( param => param.type === 'AssignmentPattern' ? param.left.name : param.name ); + const deps = value.params.map( ( param: Node ) => param.type === 'AssignmentPattern' ? param.left.name : param.name ); dependencies.set( key, deps ); }); @@ -387,7 +387,7 @@ export default class Generator { computations.push({ key, deps }); } - templateProperties.computed.value.properties.forEach( prop => visit( prop.key.name ) ); + templateProperties.computed.value.properties.forEach( ( prop: Node ) => visit( prop.key.name ) ); } if ( templateProperties.namespace ) { @@ -399,7 +399,7 @@ export default class Generator { if ( templateProperties.components ) { let hasNonImportedComponent = false; - templateProperties.components.value.properties.forEach( property => { + 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 ) ) { diff --git a/src/generators/dom/Block.ts b/src/generators/dom/Block.ts index 9683cf6556..9523d42e7c 100644 --- a/src/generators/dom/Block.ts +++ b/src/generators/dom/Block.ts @@ -4,11 +4,20 @@ import { DomGenerator } from './index'; import { Node } from '../../interfaces'; export interface BlockOptions { - generator: DomGenerator; name: string; - expression: Node; - context: string; - key: string; + generator?: DomGenerator; + expression?: Node; + context?: string; + key?: string; + contexts?: Map; + indexes?: Map; + contextDependencies?: Map; + params?: string[]; + indexNames?: Map; + listNames?: Map; + indexName?: string; + listName?: string; + dependencies?: Set; } export default class Block { @@ -16,7 +25,19 @@ export default class Block { name: string; expression: Node; context: string; + key: string; + first: string; + + contexts: Map; + indexes: Map; + contextDependencies: Map; + dependencies: Set; + params: string[]; + indexNames: Map; + listNames: Map; + indexName: string; + listName: string; builders: { create: CodeBuilder; @@ -41,6 +62,7 @@ export default class Block { target: string; hasUpdateMethod: boolean; + autofocus: string; constructor ( options: BlockOptions ) { this.generator = options.generator; @@ -95,7 +117,7 @@ export default class Block { }); } - addElement ( name: string, renderStatement: string, parentNode, needsIdentifier = false ) { + addElement ( name: string, renderStatement: string, parentNode: string, needsIdentifier = false ) { const isToplevel = !parentNode; if ( needsIdentifier || isToplevel ) { this.builders.create.addLine( diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index d2d02ff14d..dc112bb4ca 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -18,6 +18,10 @@ export class DomGenerator extends Generator { readonly: Set; metaBindings: string[]; + hasIntroTransitions: boolean; + hasOutroTransitions: boolean; + hasComplexBindings: boolean; + constructor ( parsed: Parsed, source: string, name: string, options: CompileOptions ) { super( parsed, source, name, options ); this.blocks = []; @@ -48,13 +52,7 @@ export default function dom ( parsed: Parsed, source: string, options: CompileOp const { computations, hasJs, templateProperties, namespace } = generator.parseJs(); - const state = { - namespace, - parentNode: null, - isTopLevel: true - }; - - const block = preprocess( generator, state, parsed.html ); + const { block, state } = preprocess( generator, namespace, parsed.html ); parsed.html.children.forEach( ( node: Node ) => { visit( generator, block, state, node ); diff --git a/src/generators/dom/interfaces.ts b/src/generators/dom/interfaces.ts new file mode 100644 index 0000000000..6385d93566 --- /dev/null +++ b/src/generators/dom/interfaces.ts @@ -0,0 +1,10 @@ +export interface State { + namespace: string; + parentNode: string; + isTopLevel: boolean + parentNodeName?: string; + basename?: string; + inEachBlock?: boolean; + allUsedContexts?: string[]; + usesComponent?: boolean; +} \ No newline at end of file diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index 1ea44a6855..3a96aca3f2 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -3,12 +3,13 @@ import { trimStart, trimEnd } from '../../utils/trim'; import { assign } from '../../shared/index.js'; 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 getChildState ( parent, child = {} ) { +function getChildState ( parent: State, child = {} ) { return assign( {}, parent, { name: null, parentNode: null }, child || {} ); } @@ -27,7 +28,7 @@ const elementsWithoutText = new Set([ ]); const preprocessors = { - MustacheTag: ( generator: DomGenerator, block, state, node: Node ) => { + MustacheTag: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { const dependencies = block.findDependencies( node.expression ); block.addDependencies( dependencies ); @@ -36,7 +37,7 @@ const preprocessors = { }); }, - RawMustacheTag: ( generator: DomGenerator, block, state, node: Node ) => { + RawMustacheTag: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { const dependencies = block.findDependencies( node.expression ); block.addDependencies( dependencies ); @@ -46,7 +47,7 @@ const preprocessors = { node._state = getChildState( state, { basename, name }); }, - Text: ( generator: DomGenerator, block, state, node: Node ) => { + Text: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { node._state = getChildState( state ); if ( !/\S/.test( node.data ) ) { @@ -58,8 +59,8 @@ const preprocessors = { node._state.name = block.getUniqueName( `text` ); }, - IfBlock: ( generator: DomGenerator, block, state, node: Node ) => { - const blocks = []; + IfBlock: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { + const blocks: Block[] = []; let dynamic = false; let hasIntros = false; let hasOutros = false; @@ -115,7 +116,7 @@ const preprocessors = { generator.blocks.push( ...blocks ); }, - EachBlock: ( generator: DomGenerator, block, state, node: Node ) => { + EachBlock: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { const dependencies = block.findDependencies( node.expression ); block.addDependencies( dependencies ); @@ -177,7 +178,7 @@ const preprocessors = { } }, - Element: ( generator: DomGenerator, block, state, node: Node ) => { + Element: ( generator: DomGenerator, block: Block, state: State, node: Node ) => { const isComponent = generator.components.has( node.name ) || node.name === ':Self'; if ( isComponent ) { @@ -240,7 +241,7 @@ const preprocessors = { } }; -function preprocessChildren ( generator: DomGenerator, block, state, node: Node, isTopLevel: boolean ) { +function preprocessChildren ( generator: DomGenerator, block: Block, state: State, node: Node, isTopLevel: boolean = false ) { // glue text nodes together const cleaned: Node[] = []; let lastChild: Node; @@ -294,7 +295,7 @@ function preprocessChildren ( generator: DomGenerator, block, state, node: Node, node.children = cleaned; } -export default function preprocess ( generator: DomGenerator, state, node ) { +export default function preprocess ( generator: DomGenerator, namespace: string, node: Node ) { const block = new Block({ generator, name: generator.alias( 'create_main_fragment' ), @@ -311,9 +312,15 @@ export default function preprocess ( generator: DomGenerator, state, node ) { dependencies: new Set() }); + const state: State = { + namespace, + parentNode: null, + isTopLevel: true + }; + generator.blocks.push( block ); preprocessChildren( generator, block, state, node, true ); block.hasUpdateMethod = block.dependencies.size > 0; - return block; + return { block, state }; } \ No newline at end of file diff --git a/src/generators/dom/visitors/Component/Attribute.ts b/src/generators/dom/visitors/Component/Attribute.ts index 0055c75e0a..690cb88639 100644 --- a/src/generators/dom/visitors/Component/Attribute.ts +++ b/src/generators/dom/visitors/Component/Attribute.ts @@ -1,8 +1,9 @@ import { DomGenerator } from '../../index'; import Block from '../../Block'; import { Node } from '../../../../interfaces'; +import { State } from '../../interfaces'; -export default function visitAttribute ( generator: DomGenerator, block: Block, state, node: Node, attribute, local ) { +export default function visitAttribute ( generator: DomGenerator, block: Block, state: State, node: Node, attribute, local ) { if ( attribute.value === true ) { // attributes without values, e.g.