1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | 1× 1× 1× 597× 597× 597× 597× 597× 597× 489× 489× 6× 108× 108× 108× 2× 106× 27× 597× 597× 597× 597× 533× 533× 1× 597× 597× 591× 591× 483× 1× 1484× 1484× 1096× 611× 887× 611× 1× 887× 1× 485× 761× 485× 485× 485× 761× 761× 304× 457× 761× 761× 421× | import { HtmlTagNames, SvgTagNames, VNode, VNodeProps } from '../types' import { MostlyVNode, addSvgNamespace } from './VNode' import { isPrimitive, isString } from '../helpers' export const h: HyperscriptFn = function(): VNode { const tagName: string | ComponentFn = arguments[0] // required const childrenOrText: HyperscriptChildren = slice(2, arguments) // optional let props: VNodeProps = {} let children: Array<VNode> | undefined let text: string | undefined if (childrenOrText) { props = arguments[1] || {} if (isArrayLike(childrenOrText)) children = flattenArrayLike(childrenOrText) as Array<VNode> else Eif (isPrimitive(childrenOrText)) text = String(childrenOrText) } else Eif (arguments[1]) { const childrenOrTextOrProps = arguments[1] if (isArrayLike(childrenOrTextOrProps)) children = flattenArrayLike(childrenOrTextOrProps) as Array<VNode> else if (isPrimitive(childrenOrTextOrProps)) text = String(childrenOrTextOrProps) else props = childrenOrTextOrProps || {} } Iif (typeof tagName === 'function') { const childVNodes = Array.isArray(children) ? children : text ? [ MostlyVNode.createText(text) ] : [] const computedVNode = tagName(props, childVNodes) if (Array.isArray(computedVNode.children)) { computedVNode.children = sanitizeChildren(computedVNode.children, computedVNode) } return computedVNode } const isSvg = tagName === 'svg' const vNode = isSvg ? MostlyVNode.createSvg(tagName, props, undefined, text) : MostlyVNode.create(tagName, props, undefined, text) if (Array.isArray(children)) vNode.children = sanitizeChildren(children, vNode) if (isSvg) addSvgNamespace(vNode) return vNode } function slice<A>(from: number, arrLike: ArrayLike<VNode | string | number>): HyperscriptChildren { const arr = [] as Array<VNode | string | number> if (arrLike.length === 1) return arrLike[0] for (let i = from; i < arrLike.length; ++i) arr.push(arrLike[i]) if (arr.length === 0) return null return arr } function isArrayLike<T>(x: any): x is ArrayLike<T> { const typeOf = typeof x return x && typeof x.length === 'number' && typeOf !== 'function' && typeOf !== 'string' } function flattenArrayLike<A>(arrayLike: ArrayLike<A | ArrayLike<A>>, arr: Array<A> = []): Array<A> { forEach( (x: A | ArrayLike<A>) => (isArrayLike(x) ? flattenArrayLike(x, arr) : arr.push(x)), arrayLike ) return arr } function forEach<A>(fn: (value: A) => void, list: ArrayLike<A>): void { for (let i = 0; i < list.length; ++i) fn(list[i]) } function sanitizeChildren(childrenOrText: Array<VNode>, parent: VNode): Array<VNode> { childrenOrText = childrenOrText .filter((x) => x !== null || x !== undefined) // remove possible null values const childCount: number = childrenOrText.length const children: Array<VNode> = Array(childCount) for (let i = 0; i < childCount; ++i) { const vNodeOrText = childrenOrText[i] if (isString(vNodeOrText) || typeof vNodeOrText === 'number') children[i] = MostlyVNode.createText(String(vNodeOrText)) else children[i] = vNodeOrText if (parent.scope && !children[i].scope) children[i].scope = parent.scope children[i].parent = parent } return children } export type VNodeChildren = string | number | null | VNode export type HyperscriptChildren = | VNodeChildren | ArrayLike<VNodeChildren> | ArrayLike<VNodeChildren | ArrayLike<VNodeChildren>> | ArrayLike<ArrayLike<VNodeChildren>> export interface ComponentFn { (props: VNodeProps, children: Array<string | null | VNode>): VNode } export type ValidTagNames = HtmlTagNames | SvgTagNames | ComponentFn export interface HyperscriptFn { (tagName: ValidTagNames): VNode (tagName: ValidTagNames, props: VNodeProps<any>): VNode (tagName: ValidTagNames, children: HyperscriptChildren): VNode (tagName: ValidTagNames, props: VNodeProps<any>, children: HyperscriptChildren): VNode <T extends Node, Props extends VNodeProps<Element> = VNodeProps<Element>>( tagName: ValidTagNames ): VNode<T, Props> <T extends Node, Props extends VNodeProps<Element> = VNodeProps<Element>>( tagName: ValidTagNames, props: Props ): VNode<T> <T extends Node, Props extends VNodeProps<Element> = VNodeProps<Element>>( tagName: ValidTagNames, children: HyperscriptChildren ): VNode<T, Props> <T extends Node, Props extends VNodeProps<Element> = VNodeProps<Element>>( tagName: ValidTagNames, props: Props, children: HyperscriptChildren ): VNode<T, Props> } |