1 | import {h, VNode, vnode as vnodeFn} from 'snabbdom';
|
2 | import {classNameFromVNode, selectorParser} from 'snabbdom-selector';
|
3 | import {isDocFrag} from './utils';
|
4 |
|
5 | export 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 | }
|