From a690ba0b8fa528b66b9bb4fbff21e331565720d0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 28 Apr 2018 19:59:19 -0400 Subject: [PATCH] remove files that mysteriously reappeared --- src/generators/nodes/Binding.ts | 296 ---------- src/generators/nodes/Fragment.ts | 45 -- src/generators/nodes/IfBlock.ts | 504 ------------------ src/generators/nodes/shared/Node.ts | 172 ------ src/generators/server-side-rendering/index.ts | 175 ------ src/validate/index.ts | 1 - 6 files changed, 1193 deletions(-) delete mode 100644 src/generators/nodes/Binding.ts delete mode 100644 src/generators/nodes/Fragment.ts delete mode 100644 src/generators/nodes/IfBlock.ts delete mode 100644 src/generators/nodes/shared/Node.ts delete mode 100644 src/generators/server-side-rendering/index.ts diff --git a/src/generators/nodes/Binding.ts b/src/generators/nodes/Binding.ts deleted file mode 100644 index 1ed2a8fc7b..0000000000 --- a/src/generators/nodes/Binding.ts +++ /dev/null @@ -1,296 +0,0 @@ -import Node from './shared/Node'; -import Element from './Element'; -import getObject from '../../utils/getObject'; -import getTailSnippet from '../../utils/getTailSnippet'; -import flattenReference from '../../utils/flattenReference'; -import Block from '../dom/Block'; -import Expression from './shared/Expression'; -import Compiler from '../../compile/Compiler'; - -const readOnlyMediaAttributes = new Set([ - 'duration', - 'buffered', - 'seekable', - 'played' -]); - -export default class Binding extends Node { - name: string; - value: Expression; - isContextual: boolean; - usesContext: boolean; - obj: string; - prop: string; - - constructor(compiler, parent, scope, info) { - super(compiler, parent, scope, info); - - this.name = info.name; - this.value = new Expression(compiler, this, scope, info.value); - - let obj; - let prop; - - const { name } = getObject(this.value.node); - this.isContextual = scope.names.has(name); - - if (this.value.node.type === 'MemberExpression') { - prop = `[✂${this.value.node.property.start}-${this.value.node.property.end}✂]`; - if (!this.value.node.computed) prop = `'${prop}'`; - obj = `[✂${this.value.node.object.start}-${this.value.node.object.end}✂]`; - - this.usesContext = true; - } else { - obj = 'ctx'; - prop = `'${name}'`; - - this.usesContext = scope.names.has(name); - } - - this.obj = obj; - this.prop = prop; - } - - munge( - block: Block - ) { - const node: Element = this.parent; - - const needsLock = node.name !== 'input' || !/radio|checkbox|range|color/.test(node.getStaticAttributeValue('type')); - const isReadOnly = node.isMediaNode() && readOnlyMediaAttributes.has(this.name); - - let updateCondition: string; - - const { name } = getObject(this.value.node); - const { snippet } = this.value; - - // special case: if you have e.g. `` - // and `selected` is an object chosen with a - if (binding.name === 'group') { - const bindingGroup = getBindingGroup(compiler, binding.value.node); - if (type === 'checkbox') { - return `@getBindingGroupValue(#component._bindingGroups[${bindingGroup}])`; - } - - return `${node.var}.__value`; - } - - // - if (type === 'range' || type === 'number') { - return `@toNumber(${node.var}.${binding.name})`; - } - - if ((binding.name === 'buffered' || binding.name === 'seekable' || binding.name === 'played')) { - return `@timeRangesToArray(${node.var}.${binding.name})` - } - - // everything else - return `${node.var}.${binding.name}`; -} - -function isComputed(node: Node) { - while (node.type === 'MemberExpression') { - if (node.computed) return true; - node = node.object; - } - - return false; -} diff --git a/src/generators/nodes/Fragment.ts b/src/generators/nodes/Fragment.ts deleted file mode 100644 index f0de86fa97..0000000000 --- a/src/generators/nodes/Fragment.ts +++ /dev/null @@ -1,45 +0,0 @@ -import Node from './shared/Node'; -import Compiler from '../Compiler'; -import mapChildren from './shared/mapChildren'; -import Block from '../dom/Block'; -import TemplateScope from './shared/TemplateScope'; - -export default class Fragment extends Node { - block: Block; - children: Node[]; - scope: TemplateScope; - - constructor(compiler: Compiler, info: any) { - const scope = new TemplateScope(); - super(compiler, null, scope, info); - - this.scope = scope; - this.children = mapChildren(compiler, this, scope, info.children); - } - - init() { - this.block = new Block({ - compiler: this.compiler, - name: '@create_main_fragment', - key: null, - - indexNames: new Map(), - listNames: new Map(), - - dependencies: new Set(), - }); - - this.compiler.target.blocks.push(this.block); - this.initChildren(this.block, true, null); - - this.block.hasUpdateMethod = true; - } - - build() { - this.init(); - - this.children.forEach(child => { - child.build(this.block, null, 'nodes'); - }); - } -} \ No newline at end of file diff --git a/src/generators/nodes/IfBlock.ts b/src/generators/nodes/IfBlock.ts deleted file mode 100644 index c075949e77..0000000000 --- a/src/generators/nodes/IfBlock.ts +++ /dev/null @@ -1,504 +0,0 @@ -import deindent from '../../utils/deindent'; -import Node from './shared/Node'; -import ElseBlock from './ElseBlock'; -import Block from '../dom/Block'; -import createDebuggingComment from '../../utils/createDebuggingComment'; -import Expression from './shared/Expression'; -import mapChildren from './shared/mapChildren'; - -function isElseIf(node: ElseBlock) { - return ( - node && node.children.length === 1 && node.children[0].type === 'IfBlock' - ); -} - -function isElseBranch(branch) { - return branch.block && !branch.condition; -} - -export default class IfBlock extends Node { - type: 'IfBlock'; - expression: Expression; - children: any[]; - else: ElseBlock; - - block: Block; - - constructor(compiler, parent, scope, info) { - super(compiler, parent, scope, info); - - this.expression = new Expression(compiler, this, scope, info.expression); - this.children = mapChildren(compiler, this, scope, info.children); - - this.else = info.else - ? new ElseBlock(compiler, this, scope, info.else) - : null; - } - - init( - block: Block, - stripWhitespace: boolean, - nextSibling: Node - ) { - const { compiler } = this; - - this.cannotUseInnerHTML(); - - const blocks: Block[] = []; - let dynamic = false; - let hasIntros = false; - let hasOutros = false; - - function attachBlocks(node: IfBlock) { - node.var = block.getUniqueName(`if_block`); - - block.addDependencies(node.expression.dependencies); - - node.block = block.child({ - comment: createDebuggingComment(node, compiler), - name: compiler.getUniqueName(`create_if_block`), - }); - - blocks.push(node.block); - node.initChildren(node.block, stripWhitespace, nextSibling); - - if (node.block.dependencies.size > 0) { - dynamic = true; - block.addDependencies(node.block.dependencies); - } - - 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) { - node.else.block = block.child({ - comment: createDebuggingComment(node.else, compiler), - name: compiler.getUniqueName(`create_if_block`), - }); - - blocks.push(node.else.block); - node.else.initChildren( - node.else.block, - stripWhitespace, - nextSibling - ); - - if (node.else.block.dependencies.size > 0) { - dynamic = true; - block.addDependencies(node.else.block.dependencies); - } - } - } - - attachBlocks(this); - - blocks.forEach(block => { - block.hasUpdateMethod = dynamic; - block.hasIntroMethod = hasIntros; - block.hasOutroMethod = hasOutros; - }); - - compiler.target.blocks.push(...blocks); - } - - build( - block: Block, - parentNode: string, - parentNodes: string - ) { - const name = this.var; - - const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode(); - const anchor = needsAnchor - ? block.getUniqueName(`${name}_anchor`) - : (this.next && this.next.var) || 'null'; - - const branches = this.getBranches(block, parentNode, parentNodes, this); - - 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 - const hasOutros = branches[0].hasOutroMethod; - - const vars = { name, anchor, if_name, hasElse }; - - if (this.else) { - if (hasOutros) { - this.buildCompoundWithOutros(block, parentNode, parentNodes, branches, dynamic, vars); - } else { - this.buildCompound(block, parentNode, parentNodes, branches, dynamic, vars); - } - } else { - this.buildSimple(block, parentNode, parentNodes, branches[0], dynamic, vars); - } - - block.builders.create.addLine(`${if_name}${name}.c();`); - - if (parentNodes) { - block.builders.claim.addLine( - `${if_name}${name}.l(${parentNodes});` - ); - } - - if (needsAnchor) { - block.addElement( - anchor, - `@createComment()`, - parentNodes && `@createComment()`, - parentNode - ); - } - } - - buildCompound( - block: Block, - parentNode: string, - parentNodes: string, - branches, - dynamic, - { name, anchor, hasElse, if_name } - ) { - const select_block_type = this.compiler.getUniqueName(`select_block_type`); - const current_block_type = block.getUniqueName(`current_block_type`); - const current_block_type_and = hasElse ? '' : `${current_block_type} && `; - - block.builders.init.addBlock(deindent` - function ${select_block_type}(ctx) { - ${branches - .map(({ condition, block }) => `${condition ? `if (${condition}) ` : ''}return ${block};`) - .join('\n')} - } - `); - - block.builders.init.addBlock(deindent` - var ${current_block_type} = ${select_block_type}(ctx); - var ${name} = ${current_block_type_and}${current_block_type}(#component, ctx); - `); - - const mountOrIntro = branches[0].hasIntroMethod ? 'i' : 'm'; - - const initialMountNode = parentNode || '#target'; - const anchorNode = parentNode ? 'null' : 'anchor'; - block.builders.mount.addLine( - `${if_name}${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});` - ); - - const updateMountNode = this.getUpdateMountNode(anchor); - - const changeBlock = deindent` - ${hasElse - ? deindent` - ${name}.u(); - ${name}.d(); - ` - : deindent` - if (${name}) { - ${name}.u(); - ${name}.d(); - }`} - ${name} = ${current_block_type_and}${current_block_type}(#component, ctx); - ${if_name}${name}.c(); - ${if_name}${name}.${mountOrIntro}(${updateMountNode}, ${anchor}); - `; - - if (dynamic) { - block.builders.update.addBlock(deindent` - if (${current_block_type} === (${current_block_type} = ${select_block_type}(ctx)) && ${name}) { - ${name}.p(changed, ctx); - } else { - ${changeBlock} - } - `); - } else { - block.builders.update.addBlock(deindent` - if (${current_block_type} !== (${current_block_type} = ${select_block_type}(ctx))) { - ${changeBlock} - } - `); - } - - block.builders.unmount.addLine(`${if_name}${name}.u();`); - - block.builders.destroy.addLine(`${if_name}${name}.d();`); - } - - // if any of the siblings have outros, we need to keep references to the blocks - // (TODO does this only apply to bidi transitions?) - buildCompoundWithOutros( - block: Block, - parentNode: string, - parentNodes: string, - branches, - dynamic, - { name, anchor, hasElse } - ) { - const select_block_type = block.getUniqueName(`select_block_type`); - const current_block_type_index = block.getUniqueName(`current_block_type_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_type_index = hasElse - ? '' - : `if (~${current_block_type_index}) `; - - block.addVariable(current_block_type_index); - block.addVariable(name); - - block.builders.init.addBlock(deindent` - var ${if_block_creators} = [ - ${branches.map(branch => branch.block).join(',\n')} - ]; - - var ${if_blocks} = []; - - function ${select_block_type}(ctx) { - ${branches - .map(({ condition, block }, i) => `${condition ? `if (${condition}) ` : ''}return ${block ? i : -1};`) - .join('\n')} - } - `); - - if (hasElse) { - block.builders.init.addBlock(deindent` - ${current_block_type_index} = ${select_block_type}(ctx); - ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx); - `); - } else { - block.builders.init.addBlock(deindent` - if (~(${current_block_type_index} = ${select_block_type}(ctx))) { - ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx); - } - `); - } - - const mountOrIntro = branches[0].hasIntroMethod ? 'i' : 'm'; - const initialMountNode = parentNode || '#target'; - const anchorNode = parentNode ? 'null' : 'anchor'; - - block.builders.mount.addLine( - `${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${initialMountNode}, ${anchorNode});` - ); - - const updateMountNode = this.getUpdateMountNode(anchor); - - const destroyOldBlock = deindent` - ${name}.o(function() { - ${if_blocks}[ ${previous_block_index} ].u(); - ${if_blocks}[ ${previous_block_index} ].d(); - ${if_blocks}[ ${previous_block_index} ] = null; - }); - `; - - const createNewBlock = deindent` - ${name} = ${if_blocks}[${current_block_type_index}]; - if (!${name}) { - ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, ctx); - ${name}.c(); - } - ${name}.${mountOrIntro}(${updateMountNode}, ${anchor}); - `; - - const changeBlock = hasElse - ? deindent` - ${destroyOldBlock} - - ${createNewBlock} - ` - : deindent` - if (${name}) { - ${destroyOldBlock} - } - - if (~${current_block_type_index}) { - ${createNewBlock} - } else { - ${name} = null; - } - `; - - if (dynamic) { - block.builders.update.addBlock(deindent` - var ${previous_block_index} = ${current_block_type_index}; - ${current_block_type_index} = ${select_block_type}(ctx); - if (${current_block_type_index} === ${previous_block_index}) { - ${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, ctx); - } else { - ${changeBlock} - } - `); - } else { - block.builders.update.addBlock(deindent` - var ${previous_block_index} = ${current_block_type_index}; - ${current_block_type_index} = ${select_block_type}(ctx); - if (${current_block_type_index} !== ${previous_block_index}) { - ${changeBlock} - } - `); - } - - block.builders.destroy.addLine(deindent` - ${if_current_block_type_index}{ - ${if_blocks}[${current_block_type_index}].u(); - ${if_blocks}[${current_block_type_index}].d(); - } - `); - } - - buildSimple( - block: Block, - parentNode: string, - parentNodes: string, - branch, - dynamic, - { name, anchor, if_name } - ) { - block.builders.init.addBlock(deindent` - var ${name} = (${branch.condition}) && ${branch.block}(#component, ctx); - `); - - const mountOrIntro = branch.hasIntroMethod ? 'i' : 'm'; - const initialMountNode = parentNode || '#target'; - const anchorNode = parentNode ? 'null' : 'anchor'; - - block.builders.mount.addLine( - `if (${name}) ${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});` - ); - - const updateMountNode = this.getUpdateMountNode(anchor); - - const enter = dynamic - ? branch.hasIntroMethod - ? deindent` - if (${name}) { - ${name}.p(changed, ctx); - } else { - ${name} = ${branch.block}(#component, ctx); - if (${name}) ${name}.c(); - } - - ${name}.i(${updateMountNode}, ${anchor}); - ` - : deindent` - if (${name}) { - ${name}.p(changed, ctx); - } else { - ${name} = ${branch.block}(#component, ctx); - ${name}.c(); - ${name}.m(${updateMountNode}, ${anchor}); - } - ` - : branch.hasIntroMethod - ? deindent` - if (!${name}) { - ${name} = ${branch.block}(#component, ctx); - ${name}.c(); - } - ${name}.i(${updateMountNode}, ${anchor}); - ` - : deindent` - if (!${name}) { - ${name} = ${branch.block}(#component, ctx); - ${name}.c(); - ${name}.m(${updateMountNode}, ${anchor}); - } - `; - - // no `p()` here — we don't want to update outroing nodes, - // as that will typically result in glitching - const exit = branch.hasOutroMethod - ? deindent` - ${name}.o(function() { - ${name}.u(); - ${name}.d(); - ${name} = null; - }); - ` - : deindent` - ${name}.u(); - ${name}.d(); - ${name} = null; - `; - - block.builders.update.addBlock(deindent` - if (${branch.condition}) { - ${enter} - } else if (${name}) { - ${exit} - } - `); - - block.builders.unmount.addLine(`${if_name}${name}.u();`); - - block.builders.destroy.addLine(`${if_name}${name}.d();`); - } - - getBranches( - block: Block, - parentNode: string, - parentNodes: string, - node: IfBlock - ) { - const branches = [ - { - condition: node.expression.snippet, - block: node.block.name, - hasUpdateMethod: node.block.hasUpdateMethod, - hasIntroMethod: node.block.hasIntroMethod, - hasOutroMethod: node.block.hasOutroMethod, - }, - ]; - - this.visitChildren(block, node); - - if (isElseIf(node.else)) { - branches.push( - ...this.getBranches(block, parentNode, parentNodes, node.else.children[0]) - ); - } else { - branches.push({ - condition: null, - block: node.else ? node.else.block.name : null, - hasUpdateMethod: node.else ? node.else.block.hasUpdateMethod : false, - hasIntroMethod: node.else ? node.else.block.hasIntroMethod : false, - hasOutroMethod: node.else ? node.else.block.hasOutroMethod : false, - }); - - if (node.else) { - this.visitChildren(block, node.else); - } - } - - return branches; - } - - ssr() { - const { compiler } = this; - const { snippet } = this.expression; - - compiler.target.append('${ ' + snippet + ' ? `'); - - this.children.forEach((child: Node) => { - child.ssr(); - }); - - compiler.target.append('` : `'); - - if (this.else) { - this.else.children.forEach((child: Node) => { - child.ssr(); - }); - } - - compiler.target.append('` }'); - } - - visitChildren(block: Block, node: Node) { - node.children.forEach((child: Node) => { - child.build(node.block, null, 'nodes'); - }); - } -} \ No newline at end of file diff --git a/src/generators/nodes/shared/Node.ts b/src/generators/nodes/shared/Node.ts deleted file mode 100644 index a68b0e1544..0000000000 --- a/src/generators/nodes/shared/Node.ts +++ /dev/null @@ -1,172 +0,0 @@ -import Compiler from './../../Compiler'; -import Block from '../../dom/Block'; -import { trimStart, trimEnd } from '../../../utils/trim'; - -export default class Node { - readonly start: number; - readonly end: number; - readonly compiler: Compiler; - readonly parent: Node; - readonly type: string; - - prev?: Node; - next?: Node; - - canUseInnerHTML: boolean; - var: string; - - constructor(compiler: Compiler, parent, scope, info: any) { - this.start = info.start; - this.end = info.end; - this.type = info.type; - - // this makes properties non-enumerable, which makes logging - // bearable. might have a performance cost. TODO remove in prod? - Object.defineProperties(this, { - compiler: { - value: compiler - }, - parent: { - value: parent - } - }); - } - - cannotUseInnerHTML() { - if (this.canUseInnerHTML !== false) { - this.canUseInnerHTML = false; - if (this.parent) this.parent.cannotUseInnerHTML(); - } - } - - init( - block: Block, - stripWhitespace: boolean, - nextSibling: Node - ) { - // implemented by subclasses - } - - initChildren( - block: Block, - stripWhitespace: boolean, - nextSibling: Node - ) { - // glue text nodes together - const cleaned: Node[] = []; - let lastChild: Node; - - let windowComponent; - - this.children.forEach((child: Node) => { - if (child.type === 'Comment') return; - - // special case — this is an easy way to remove whitespace surrounding - // . lil hacky but it works - if (child.type === 'Window') { - windowComponent = child; - return; - } - - if (child.type === 'Text' && lastChild && lastChild.type === 'Text') { - lastChild.data += child.data; - lastChild.end = child.end; - } else { - if (child.type === 'Text' && stripWhitespace && cleaned.length === 0) { - child.data = trimStart(child.data); - if (child.data) cleaned.push(child); - } else { - cleaned.push(child); - } - } - - lastChild = child; - }); - - lastChild = null; - - cleaned.forEach((child: Node, i: number) => { - child.canUseInnerHTML = !this.compiler.options.hydratable; - - child.init(block, stripWhitespace, cleaned[i + 1] || nextSibling); - - if (child.shouldSkip) return; - - if (lastChild) lastChild.next = child; - child.prev = lastChild; - - lastChild = child; - }); - - // We want to remove trailing whitespace inside an element/component/block, - // *unless* there is no whitespace between this node and its next sibling - if (stripWhitespace && lastChild && lastChild.type === 'Text') { - const shouldTrim = ( - nextSibling ? (nextSibling.type === 'Text' && /^\s/.test(nextSibling.data)) : !this.hasAncestor('EachBlock') - ); - - if (shouldTrim) { - lastChild.data = trimEnd(lastChild.data); - if (!lastChild.data) { - cleaned.pop(); - lastChild = cleaned[cleaned.length - 1]; - lastChild.next = null; - } - } - } - - this.children = cleaned; - if (windowComponent) cleaned.unshift(windowComponent); - } - - build( - block: Block, - parentNode: string, - parentNodes: string - ) { - // implemented by subclasses - } - - isDomNode() { - return this.type === 'Element' || this.type === 'Text' || this.type === 'MustacheTag'; - } - - hasAncestor(type: string) { - return this.parent ? - this.parent.type === type || this.parent.hasAncestor(type) : - false; - } - - findNearest(selector: RegExp) { - if (selector.test(this.type)) return this; - if (this.parent) return this.parent.findNearest(selector); - } - - getOrCreateAnchor(block: Block, parentNode: string, parentNodes: string) { - // TODO use this in EachBlock and IfBlock — tricky because - // children need to be created first - const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode(); - const anchor = needsAnchor - ? block.getUniqueName(`${this.var}_anchor`) - : (this.next && this.next.var) || 'null'; - - if (needsAnchor) { - block.addElement( - anchor, - `@createComment()`, - parentNodes && `@createComment()`, - parentNode - ); - } - - return anchor; - } - - getUpdateMountNode(anchor: string) { - return this.parent.isDomNode() ? this.parent.var : `${anchor}.parentNode`; - } - - remount(name: string) { - return `${this.var}.m(${name}._slotted.default, null);`; - } -} \ No newline at end of file diff --git a/src/generators/server-side-rendering/index.ts b/src/generators/server-side-rendering/index.ts deleted file mode 100644 index 5f5a410a94..0000000000 --- a/src/generators/server-side-rendering/index.ts +++ /dev/null @@ -1,175 +0,0 @@ -import deindent from '../../utils/deindent'; -import Compiler from '../Compiler'; -import Stats from '../../Stats'; -import Stylesheet from '../../css/Stylesheet'; -import { removeNode, removeObjectKey } from '../../utils/removeNode'; -import getName from '../../utils/getName'; -import globalWhitelist from '../../utils/globalWhitelist'; -import { Ast, Node, CompileOptions } from '../../interfaces'; -import { AppendTarget } from '../../interfaces'; -import { stringify } from '../../utils/stringify'; - -export class SsrTarget { - bindings: string[]; - renderCode: string; - appendTargets: AppendTarget[]; - - constructor() { - this.bindings = []; - this.renderCode = ''; - this.appendTargets = []; - } - - append(code: string) { - if (this.appendTargets.length) { - const appendTarget = this.appendTargets[this.appendTargets.length - 1]; - const slotName = appendTarget.slotStack[appendTarget.slotStack.length - 1]; - appendTarget.slots[slotName] += code; - } else { - this.renderCode += code; - } - } -} - -export default function ssr( - ast: Ast, - source: string, - stylesheet: Stylesheet, - options: CompileOptions, - stats: Stats -) { - const format = options.format || 'cjs'; - - const target = new SsrTarget(); - const compiler = new Compiler(ast, source, options.name || 'SvelteComponent', stylesheet, options, stats, false, target); - - const { computations, name, templateProperties } = compiler; - - // create main render() function - trim(compiler.fragment.children).forEach((node: Node) => { - node.ssr(); - }); - - const css = compiler.customElement ? - { code: null, map: null } : - compiler.stylesheet.render(options.filename, true); - - // generate initial state object - const expectedProperties = Array.from(compiler.expectedProperties); - const globals = expectedProperties.filter(prop => globalWhitelist.has(prop)); - const storeProps = expectedProperties.filter(prop => prop[0] === '$'); - - const initialState = []; - if (globals.length > 0) { - initialState.push(`{ ${globals.map(prop => `${prop} : ${prop}`).join(', ')} }`); - } - - if (storeProps.length > 0) { - const initialize = `_init([${storeProps.map(prop => `"${prop.slice(1)}"`)}])` - initialState.push(`options.store.${initialize}`); - } - - if (templateProperties.data) { - initialState.push(`%data()`); - } else if (globals.length === 0 && storeProps.length === 0) { - initialState.push('{}'); - } - - initialState.push('ctx'); - - const helpers = new Set(); - - // TODO concatenate CSS maps - const result = deindent` - ${compiler.javascript} - - var ${name} = {}; - - ${options.filename && `${name}.filename = ${stringify(options.filename)}`}; - - ${name}.data = function() { - return ${templateProperties.data ? `%data()` : `{}`}; - }; - - ${name}.render = function(state, options = {}) { - var components = new Set(); - - function addComponent(component) { - components.add(component); - } - - var result = { head: '', addComponent }; - var html = ${name}._render(result, state, options); - - var cssCode = Array.from(components).map(c => c.css && c.css.code).filter(Boolean).join('\\n'); - - return { - html, - head: result.head, - css: { code: cssCode, map: null }, - toString() { - return html; - } - }; - } - - ${name}._render = function(__result, ctx, options) { - ${templateProperties.store && `options.store = %store();`} - __result.addComponent(${name}); - - ctx = Object.assign(${initialState.join(', ')}); - - ${computations.map( - ({ key, deps }) => - `ctx.${key} = %computed-${key}(ctx);` - )} - - ${target.bindings.length && - deindent` - var settled = false; - var tmp; - - while (!settled) { - settled = true; - - ${target.bindings.join('\n\n')} - } - `} - - return \`${target.renderCode}\`; - }; - - ${name}.css = { - code: ${css.code ? stringify(css.code) : `''`}, - map: ${css.map ? stringify(css.map.toString()) : 'null'} - }; - - var warned = false; - - ${templateProperties.preload && `${name}.preload = %preload;`} - `; - - return compiler.generate(result, options, { name, format }); -} - -function trim(nodes) { - let start = 0; - for (; start < nodes.length; start += 1) { - const node = nodes[start]; - if (node.type !== 'Text') break; - - node.data = node.data.replace(/^\s+/, ''); - if (node.data) break; - } - - let end = nodes.length; - for (; end > start; end -= 1) { - const node = nodes[end - 1]; - if (node.type !== 'Text') break; - - node.data = node.data.replace(/\s+$/, ''); - if (node.data) break; - } - - return nodes.slice(start, end); -} diff --git a/src/validate/index.ts b/src/validate/index.ts index 57b717ffdf..3724a42d9c 100644 --- a/src/validate/index.ts +++ b/src/validate/index.ts @@ -5,7 +5,6 @@ import getCodeFrame from '../utils/getCodeFrame'; import Stats from '../Stats'; import error from '../utils/error'; import Stylesheet from '../css/Stylesheet'; -import Stats from '../Stats'; import { Node, Ast, CompileOptions, Warning } from '../interfaces'; export class Validator {