UNPKG

1.72 kBPlain TextView Raw
1import {h, VNode, vnode as vnodeFn} from 'snabbdom';
2import {classNameFromVNode, selectorParser} from 'snabbdom-selector';
3import {isDocFrag} from './utils';
4
5export class VNodeWrapper {
6 constructor(public rootElement: Element | DocumentFragment) {}
7
8 public call(vnode: VNode | null): VNode {
9 if (isDocFrag(this.rootElement)) {
10 return this.wrapDocFrag(vnode === null ? [] : [vnode]);
11 }
12 if (vnode === null) {
13 return this.wrap([]);
14 }
15 const {tagName: selTagName, id: selId} = selectorParser(vnode);
16 const vNodeClassName = classNameFromVNode(vnode);
17 const vNodeData = vnode.data || {};
18 const vNodeDataProps = vNodeData.props || {};
19 const {id: vNodeId = selId} = vNodeDataProps;
20
21 const isVNodeAndRootElementIdentical =
22 typeof vNodeId === 'string' &&
23 vNodeId.toUpperCase() === this.rootElement.id.toUpperCase() &&
24 selTagName.toUpperCase() === this.rootElement.tagName.toUpperCase() &&
25 vNodeClassName.toUpperCase() === this.rootElement.className.toUpperCase();
26
27 if (isVNodeAndRootElementIdentical) {
28 return vnode;
29 }
30
31 return this.wrap([vnode]);
32 }
33
34 private wrapDocFrag(children: Array<VNode>) {
35 return vnodeFn('', {isolate: []}, children, undefined, this
36 .rootElement as any);
37 }
38
39 private wrap(children: Array<VNode>) {
40 const {tagName, id, className} = this.rootElement as Element;
41 const selId = id ? `#${id}` : '';
42 const selClass = className ? `.${className.split(` `).join(`.`)}` : '';
43 const vnode = h(
44 `${tagName.toLowerCase()}${selId}${selClass}`,
45 {},
46 children
47 );
48 vnode.data = vnode.data || {};
49 vnode.data.isolate = vnode.data.isolate || [];
50 return vnode;
51 }
52}