import { assign } from './assign' import { Component } from './Component' import { EXTRA, FILL, PATH, SLICE } from './consts/attributeNames' import { FUNCTION } from './consts/typeNames' import { CHILDREN, PROPS } from './consts/vNodeAttributeNames' import { deepGet } from './deepGet' import { isVNode } from './isVNode' import { Props } from './Props' import { remodelProps } from './remodelProps' import { ResolvedVNode } from './ResolvedVNode' import { VNode } from './VNode' import { x } from './x' export type Resolver = ( node?: VNode, parent?: VNode | ResolvedVNode ) => ResolvedVNode[] function resolveChildren ( _: Resolver, recursion: Resolver, children: VNode[], parentNode?: VNode | ResolvedVNode ) { return children.reduce( (childs, child) => { childs.push.apply(childs, recursion(child, parentNode)) return childs }, [] as ResolvedVNode[] ) } export function resolver ( getContext, setContext, next: Resolver, recursion: Resolver, node?: VNode, parentNode?: VNode | ResolvedVNode ): ResolvedVNode[] { if (!node) { return [] } if (x === node.name) { // Fragment return resolveChildren(next, recursion, node[CHILDREN], parentNode) } const rawProps = node[PROPS] const parentProps = (parentNode && parentNode[PROPS]) || {} let path = deepGet(rawProps, PATH) as string if (!path) { const parentPath = deepGet(parentProps, PATH) || '' let slice = deepGet(rawProps, SLICE) if (slice != null) { slice = `${slice}` } path = parentPath && slice ? `${parentPath}.${slice}` : ((slice || parentPath) as string) } let sliced = getContext(path, false) if (!sliced) { sliced = {} setContext(sliced, path) } const fill: any = deepGet(rawProps, FILL) if (fill) { for (const key in fill) { if (fill.hasOwnProperty(key) && !(key in sliced)) { sliced[key] = fill[key] } } } const context = sliced const extra = assign( assign({}, deepGet(rawProps, EXTRA) || {}), (parentNode && deepGet(parentNode, `${PROPS}.${EXTRA}`)) || {} ) const props = remodelProps(rawProps, context, extra, path) let nodes if (typeof node.name === FUNCTION) { const proceeded = (node!.name as Component)( props as Props, node[CHILDREN], context, extra ) nodes = isVNode(proceeded) ? recursion(proceeded, node) : [] } else { nodes = [node] } const resolveds = nodes.reduce( (acc, resolved) => { if (isVNode(resolved)) { resolved![CHILDREN] = resolveChildren( next, recursion, resolved![CHILDREN], resolved ) acc.push(resolved as ResolvedVNode) } return acc }, [] as ResolvedVNode[] ) return resolveds }