@esportsplus/template 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/build/attributes.js +4 -4
  2. package/build/constants.d.ts +2 -9
  3. package/build/constants.js +3 -10
  4. package/build/event.js +47 -45
  5. package/build/html/index.d.ts +3 -2106
  6. package/build/html/index.js +34 -8
  7. package/build/html/{cache.d.ts → parser.d.ts} +1 -1
  8. package/build/html/{cache.js → parser.js} +13 -7
  9. package/build/index.d.ts +1 -1
  10. package/build/render.js +3 -2
  11. package/build/slot/cleanup.js +2 -1
  12. package/build/slot/effect.js +22 -17
  13. package/build/slot/index.js +4 -9
  14. package/build/slot/reactive.d.ts +1 -1
  15. package/build/slot/reactive.js +26 -16
  16. package/build/slot/render.d.ts +2 -2
  17. package/build/slot/render.js +24 -45
  18. package/build/types.d.ts +5 -13
  19. package/build/utilities/element.d.ts +11 -0
  20. package/build/utilities/element.js +9 -0
  21. package/build/utilities/fragment.d.ts +3 -0
  22. package/build/utilities/fragment.js +11 -0
  23. package/build/utilities/node.d.ts +9 -0
  24. package/build/utilities/node.js +10 -0
  25. package/build/utilities/queue.d.ts +3 -0
  26. package/build/utilities/queue.js +4 -0
  27. package/build/utilities/text.d.ts +2 -0
  28. package/build/utilities/text.js +9 -0
  29. package/package.json +2 -2
  30. package/src/attributes.ts +23 -26
  31. package/src/constants.ts +3 -20
  32. package/src/event.ts +55 -52
  33. package/src/html/index.ts +50 -11
  34. package/src/html/{cache.ts → parser.ts} +15 -7
  35. package/src/index.ts +1 -1
  36. package/src/render.ts +3 -3
  37. package/src/slot/cleanup.ts +3 -4
  38. package/src/slot/effect.ts +33 -35
  39. package/src/slot/index.ts +6 -16
  40. package/src/slot/reactive.ts +33 -23
  41. package/src/slot/render.ts +28 -59
  42. package/src/types.ts +6 -19
  43. package/src/utilities/element.ts +28 -0
  44. package/src/utilities/fragment.ts +21 -0
  45. package/src/utilities/node.ts +29 -0
  46. package/src/utilities/queue.ts +9 -0
  47. package/src/utilities/text.ts +15 -0
  48. package/build/html/hydrate.d.ts +0 -3
  49. package/build/html/hydrate.js +0 -34
  50. package/build/utilities.d.ts +0 -28
  51. package/build/utilities.js +0 -37
  52. package/src/html/hydrate.ts +0 -53
  53. package/src/utilities.ts +0 -89
package/src/event.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { root } from '@esportsplus/reactivity';
2
2
  import { defineProperty } from '@esportsplus/utilities';
3
3
  import { Element } from './types';
4
- import { addEventListener, parentElement, raf } from './utilities';
4
+ import { addEventListener } from './utilities/element';
5
+ import { parentElement } from './utilities/node';
6
+ import { raf } from './utilities/queue';
5
7
  import { ondisconnect } from './slot/cleanup';
6
8
 
7
9
 
@@ -24,35 +26,7 @@ let capture = new Set<`on${string}`>(['onblur', 'onfocus', 'onscroll']),
24
26
  });
25
27
 
26
28
 
27
- export default (element: Element, event: `on${string}`, listener: Function): void => {
28
- if (event === 'onconnect') {
29
- let retry = 60,
30
- task = () => {
31
- retry--;
32
-
33
- if (element.isConnected) {
34
- retry = 0;
35
- root(() => listener(element));
36
- }
37
-
38
- if (retry) {
39
- raf.add(task);
40
- }
41
- };
42
-
43
- raf.add(task);
44
-
45
- return;
46
- }
47
- else if (event === 'ondisconnect') {
48
- ondisconnect(element, () => listener(element));
49
- return;
50
- }
51
- else if (event === 'onrender') {
52
- root(() => listener(element));
53
- return;
54
- }
55
-
29
+ function register(element: Element, event: `on${string}`) {
56
30
  let controller = controllers.get(event),
57
31
  signal: AbortController['signal'] | undefined;
58
32
 
@@ -83,34 +57,63 @@ export default (element: Element, event: `on${string}`, listener: Function): voi
83
57
  signal = controller.signal;
84
58
  }
85
59
 
86
- let key = keys[event];
60
+ let key = keys[event] = Symbol();
61
+
62
+ addEventListener.call(window.document, event.slice(2), (e) => {
63
+ let node = e.target as Element | null;
87
64
 
88
- if (!key) {
89
- key = keys[event] = Symbol();
65
+ while (node) {
66
+ if (key in node) {
67
+ defineProperty(e, 'currentTarget', {
68
+ configurable: true,
69
+ get() {
70
+ return node || window.document;
71
+ }
72
+ });
90
73
 
91
- addEventListener.call(window.document, event.slice(2), (e) => {
92
- let node = e.target as Element | null;
74
+ return (node[key] as Function).call(node, e);
75
+ }
76
+
77
+ node = parentElement.call(node);
78
+ }
79
+ }, {
80
+ capture: capture.has(event),
81
+ passive: passive.has(event),
82
+ signal
83
+ });
93
84
 
94
- while (node) {
95
- if (key in node) {
96
- defineProperty(e, 'currentTarget', {
97
- configurable: true,
98
- get() {
99
- return node || window.document;
100
- }
101
- });
85
+ return key;
86
+ }
102
87
 
103
- return (node[key] as Function).call(node, e);
88
+
89
+ export default (element: Element, event: `on${string}`, listener: Function): void => {
90
+ if (event === 'onconnect') {
91
+ let retry = 60,
92
+ task = () => {
93
+ retry--;
94
+
95
+ if (element.isConnected) {
96
+ retry = 0;
97
+ root(() => listener(element));
104
98
  }
105
99
 
106
- node = parentElement.call(node);
107
- }
108
- }, {
109
- capture: capture.has(event),
110
- passive: passive.has(event),
111
- signal
112
- });
100
+ if (retry) {
101
+ raf.add(task);
102
+ }
103
+ };
104
+
105
+ raf.add(task);
106
+
107
+ return;
108
+ }
109
+ else if (event === 'ondisconnect') {
110
+ ondisconnect(element, () => listener(element));
111
+ return;
112
+ }
113
+ else if (event === 'onrender') {
114
+ root(() => listener(element));
115
+ return;
113
116
  }
114
117
 
115
- element[key] = listener;
118
+ element[ keys[event] || register(element, event) ] = listener;
116
119
  };
package/src/html/index.ts CHANGED
@@ -1,19 +1,58 @@
1
1
  import { ReactiveArray } from '@esportsplus/reactivity';
2
- import { RENDERABLE, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY } from '~/constants';
3
- import { RenderableReactive, RenderableTemplate, RenderableValues } from '~/types';
4
- import hydrate from './hydrate';
5
- import cache from './cache';
2
+ import { RENDERABLE, RENDERABLE_HTML_REACTIVE_ARRAY } from '~/constants';
3
+ import { RenderableReactive, RenderableValue } from '~/types';
4
+ import { cloneNode } from '~/utilities/node';
5
+ import parser from './parser';
6
6
 
7
7
 
8
- const html = (literals: TemplateStringsArray, ...values: RenderableValues[]): RenderableTemplate => {
9
- return {
10
- [RENDERABLE]: RENDERABLE_HTML_FRAGMENT,
11
- fragment: hydrate(cache.get(literals), values),
12
- literals
13
- };
8
+ const html = (literals: TemplateStringsArray, ...values: (RenderableValue | RenderableValue[])[]): DocumentFragment => {
9
+ let { fragment, slots } = parser.parse(literals);
10
+
11
+ fragment = cloneNode.call(fragment, true) as DocumentFragment;
12
+
13
+ if (slots !== null) {
14
+ let node, nodePath, parent, parentPath;
15
+
16
+ for (let i = 0, n = slots.length; i < n; i++) {
17
+ let { fn, path, slot } = slots[i],
18
+ pp = path.parent,
19
+ pr = path.relative;
20
+
21
+ if (pp !== parentPath) {
22
+ if (pp === nodePath) {
23
+ parent = node;
24
+ parentPath = nodePath;
25
+
26
+ nodePath = undefined;
27
+ }
28
+ else {
29
+ parent = fragment;
30
+ parentPath = pp;
31
+
32
+ for (let i = 0, n = pp.length; i < n; i++) {
33
+ parent = pp[i].call(parent);
34
+ }
35
+ }
36
+ }
37
+
38
+ if (pr !== nodePath) {
39
+ node = parent;
40
+ nodePath = path.absolute;
41
+
42
+ for (let i = 0, n = pr.length; i < n; i++) {
43
+ node = pr[i].call(node);
44
+ }
45
+ }
46
+
47
+ // @ts-ignore
48
+ fn(node, values[slot]);
49
+ }
50
+ }
51
+
52
+ return fragment;
14
53
  };
15
54
 
16
- html.reactive = <T>(array: ReactiveArray<T[]>, template: RenderableReactive['template']) => {
55
+ html.reactive = <T>(array: ReactiveArray<T[]>, template: RenderableReactive['template']): RenderableReactive => {
17
56
  return {
18
57
  [RENDERABLE]: RENDERABLE_HTML_REACTIVE_ARRAY,
19
58
  array,
@@ -3,8 +3,10 @@ import {
3
3
  REGEX_SLOT_NODES, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH
4
4
  } from '~/constants';
5
5
  import { Template } from '~/types';
6
- import { firstChild, firstElementChild, fragment, nextElementSibling, nextSibling } from '~/utilities';
6
+ import { firstElementChild, nextElementSibling } from '~/utilities/element';
7
+ import { firstChild, nextSibling } from '~/utilities/node';
7
8
  import { spread } from '~/attributes';
9
+ import { fragment } from '~/utilities/fragment';
8
10
  import s from '~/slot';
9
11
 
10
12
 
@@ -124,22 +126,28 @@ function methods(children: number, copy: (typeof firstChild)[], first: (typeof f
124
126
  }
125
127
 
126
128
  function set(literals: TemplateStringsArray, html: string, slots: Template['slots'] = null) {
127
- let template = {
129
+ let value = {
128
130
  fragment: fragment(html),
129
131
  html,
130
132
  literals,
131
133
  slots
132
134
  };
133
135
 
134
- cache.set(literals, template);
136
+ cache.set(literals, value);
135
137
 
136
- return template;
138
+ return value;
137
139
  }
138
140
 
139
141
 
140
- const get = (literals: TemplateStringsArray) => {
141
- return cache.get(literals) || build(literals);
142
+ const parse = (literals: TemplateStringsArray) => {
143
+ let result = cache.get(literals);
144
+
145
+ if (result === undefined) {
146
+ result = build(literals);
147
+ }
148
+
149
+ return result;
142
150
  };
143
151
 
144
152
 
145
- export default { get };
153
+ export default { parse };
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default as html } from './html';
2
2
  export { default as render } from './render';
3
3
  export { default as svg } from './svg';
4
- export type { Attributes, Element, Elements, Renderable, RenderableValue } from './types';
4
+ export type { Attributes, Element, Renderable, RenderableValue } from './types';
package/src/render.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { SLOT_HTML } from './constants';
2
2
  import { Renderable } from './types';
3
- import { firstChild, fragment, nodeValue } from './utilities';
3
+ import { fragment } from './utilities/fragment';
4
+ import { firstChild, nodeValue } from './utilities/node';
4
5
  import slot from './slot';
5
6
 
6
7
 
@@ -9,9 +10,8 @@ let anchor,
9
10
 
10
11
 
11
12
  export default (parent: HTMLElement, renderable: Renderable) => {
12
- // parent.nodeValue = '';
13
13
  nodeValue.call(parent, '');
14
14
  parent.append(anchor = marker.cloneNode());
15
15
 
16
- return slot(anchor, renderable);
16
+ slot(anchor, renderable);
17
17
  };
@@ -1,6 +1,7 @@
1
1
  import queue from '@esportsplus/queue';
2
2
  import { CLEANUP } from '~/constants';
3
- import { microtask, previousSibling } from '~/utilities';
3
+ import { microtask } from '~/utilities/queue';
4
+ import { previousSibling } from '~/utilities/node';
4
5
  import { SlotGroup } from '~/types';
5
6
 
6
7
 
@@ -19,8 +20,7 @@ function schedule() {
19
20
 
20
21
  function task() {
21
22
  try {
22
- let fns,
23
- fn,
23
+ let fns, fn,
24
24
  n = cleanup.length;
25
25
 
26
26
  while ((fns = cleanup.next()) && n--) {
@@ -51,7 +51,6 @@ const remove = (groups: SlotGroup[]) => {
51
51
  head = group.head;
52
52
  tail = group.tail || head;
53
53
 
54
- // for (let node: Element | null = tail; node; node = node.previousSibling as Element | null) {
55
54
  for (let node = tail; node; node = previousSibling.call(node)) {
56
55
  if (CLEANUP in node) {
57
56
  cleanup.add( node[CLEANUP] as VoidFunction[] );
@@ -1,25 +1,27 @@
1
1
  import { effect } from '@esportsplus/reactivity';
2
- import { EMPTY_FRAGMENT, STATE_HYDRATING, STATE_NONE } from '~/constants';
3
- import { Element, Fragment, SlotGroup } from '~/types';
4
- import { cloneNode, firstChild, lastChild, nodeValue, raf, text } from '~/utilities'
5
- import { ondisconnect } from '~/slot/cleanup';
2
+ import { STATE_HYDRATING, STATE_NONE } from '~/constants';
3
+ import { Element, SlotGroup } from '~/types';
4
+ import { firstChild, lastChild, nodeValue } from '~/utilities/node'
5
+ import { raf } from '~/utilities/queue'
6
6
  import { remove } from './cleanup';
7
+ import text from '~/utilities/text';
7
8
  import render from './render';
8
9
 
9
10
 
10
- function update(this: { group?: SlotGroup, textnode?: Element }, anchor: Element, fragment: Fragment, value: unknown) {
11
- let type = typeof value;
12
-
11
+ function update(this: { group?: SlotGroup, textnode?: Node }, anchor: Element, value: unknown) {
13
12
  if (this.group) {
14
13
  remove([this.group]);
15
14
  this.group = undefined;
16
15
  }
17
16
 
18
- if (value == null || type !== 'object') {
17
+ if (value == null || value === false) {
18
+ value = '';
19
+ }
20
+
21
+ if (typeof value !== 'object') {
19
22
  let textnode = this.textnode;
20
23
 
21
24
  if (textnode) {
22
- // textnode.nodeValue = String(value);
23
25
  nodeValue.call(textnode, String(value));
24
26
  }
25
27
  else {
@@ -31,16 +33,17 @@ function update(this: { group?: SlotGroup, textnode?: Element }, anchor: Element
31
33
  }
32
34
  }
33
35
  else {
34
- render(anchor, fragment, value);
36
+ let fragment = render(anchor, value),
37
+ head = firstChild.call(fragment);
35
38
 
36
- this.group = {
37
- // head: fragment.firstChild as Element,
38
- // tail: fragment.lastChild as Element
39
- head: firstChild.call(fragment),
40
- tail: lastChild.call(fragment)
41
- };
39
+ if (head) {
40
+ this.group = {
41
+ head,
42
+ tail: lastChild.call(fragment)
43
+ };
42
44
 
43
- anchor.after(fragment);
45
+ anchor.after(fragment);
46
+ }
44
47
  }
45
48
  }
46
49
 
@@ -48,26 +51,21 @@ function update(this: { group?: SlotGroup, textnode?: Element }, anchor: Element
48
51
  export default (anchor: Element, fn: Function) => {
49
52
  let context = {
50
53
  group: undefined as SlotGroup | undefined,
51
- textnode: undefined as Element | undefined
54
+ textnode: undefined as Node | undefined
52
55
  },
53
- // fragment = EMPTY_FRAGMENT.cloneNode() as Fragment,
54
- fragment = cloneNode.call(EMPTY_FRAGMENT) as Fragment,
55
56
  state = STATE_HYDRATING;
56
57
 
57
- ondisconnect(
58
- anchor,
59
- effect(() => {
60
- let value = fn();
58
+ effect(() => {
59
+ let value = fn();
61
60
 
62
- if (state === STATE_HYDRATING) {
63
- update.call(context, anchor, fragment, value);
64
- state = STATE_NONE;
65
- }
66
- else if (state === STATE_NONE) {
67
- raf.add(() => {
68
- update.call(context, anchor, fragment, value);
69
- });
70
- }
71
- })
72
- );
61
+ if (state === STATE_HYDRATING) {
62
+ update.call(context, anchor, value);
63
+ state = STATE_NONE;
64
+ }
65
+ else if (state === STATE_NONE) {
66
+ raf.add(() => {
67
+ update.call(context, anchor, value);
68
+ });
69
+ }
70
+ });
73
71
  };
package/src/slot/index.ts CHANGED
@@ -1,23 +1,13 @@
1
- import { EMPTY_FRAGMENT } from '~/constants';
2
- import { Element, Fragment } from '~/types';
3
- import { cloneNode } from '~/utilities';
1
+ import { Element } from '~/types';
4
2
  import effect from './effect';
5
3
  import render from './render';
6
4
 
7
5
 
8
- function slot(anchor: Element, input: unknown) {
9
- let fragment = cloneNode.call(EMPTY_FRAGMENT) as Fragment;
10
-
11
- render(anchor, fragment, input);
12
-
13
- anchor.after(fragment);
14
- }
15
-
16
-
17
- export default (anchor: Element, value: unknown) => {
6
+ export default (anchor: Element, value: unknown): void => {
18
7
  if (typeof value === 'function') {
19
- return effect(anchor, value as Function);
8
+ effect(anchor, value as Function);
9
+ }
10
+ else {
11
+ anchor.after( render(anchor, value) );
20
12
  }
21
-
22
- return slot(anchor, value);
23
13
  };
@@ -1,13 +1,14 @@
1
1
  import { root, ReactiveArray } from '@esportsplus/reactivity';
2
2
  import { EMPTY_FRAGMENT } from '~/constants';
3
- import { Fragment, RenderableReactive, SlotGroup } from '~/types';
4
- import { append, cloneNode, firstChild, lastChild } from '~/utilities';
5
- import { remove } from './cleanup';
3
+ import { RenderableReactive, SlotGroup } from '~/types';
4
+ import { append } from '~/utilities/fragment';
5
+ import { cloneNode, firstChild, lastChild } from '~/utilities/node';
6
+ import { ondisconnect, remove } from './cleanup';
6
7
 
7
8
 
8
9
  class ReactiveArraySlot<T> {
9
10
  array: ReactiveArray<T[]>;
10
- fragment = cloneNode.call(EMPTY_FRAGMENT) as Fragment;
11
+ fragment: Node;
11
12
  marker: Element;
12
13
  nodes: SlotGroup[] = [];
13
14
  template: (
@@ -17,45 +18,45 @@ class ReactiveArraySlot<T> {
17
18
 
18
19
 
19
20
  constructor(anchor: Element, array: ReactiveArray<T[]>, template: RenderableReactive['template']) {
20
- let fragment = this.fragment;
21
+ let fragment = this.fragment = cloneNode.call(EMPTY_FRAGMENT);
21
22
 
22
23
  this.array = array;
23
24
  this.marker = anchor;
24
25
  this.template = function (data, i) {
25
- let frag = template.call(this, data, i).fragment,
26
+ let dispose: VoidFunction,
27
+ frag = root((d) => {
28
+ dispose = d;
29
+ return template.call(this, data, i);
30
+ }),
26
31
  group = {
27
32
  head: firstChild.call(frag),
28
33
  tail: lastChild.call(frag)
29
34
  };
30
35
 
31
36
  append.call(fragment, frag);
37
+ ondisconnect(group.head, dispose!);
32
38
 
33
39
  return group;
34
40
  };
35
41
 
36
-
37
- let render = () => {
38
- root(() => this.render());
39
- };
40
-
41
42
  array.on('clear', () => this.clear());
42
- array.on('reverse', render);
43
+ array.on('reverse', () => {
44
+ root(() => this.render());
45
+ });
43
46
  array.on('pop', () => this.pop());
44
47
  array.on('push', ({ items }) => {
45
48
  root(() => this.push(items));
46
49
  });
47
50
  array.on('shift', () => this.shift());
48
- array.on('sort', render);
51
+ array.on('sort', () => {
52
+ root(() => this.render());
53
+ });
49
54
  array.on('splice', ({ deleteCount, items, start }) => {
50
55
  root(() => this.splice(start, deleteCount, ...items));
51
56
  });
52
57
  array.on('unshift', ({ items }) => {
53
58
  root(() => this.unshift(items));
54
59
  });
55
-
56
- if (array.length) {
57
- render();
58
- }
59
60
  }
60
61
 
61
62
 
@@ -100,14 +101,14 @@ class ReactiveArraySlot<T> {
100
101
 
101
102
  push(items: T[]) {
102
103
  let anchor = this.anchor(),
103
- array = this.array;
104
+ array = this.array,
105
+ length = this.nodes.length;
106
+
107
+ this.nodes.length = length + items.length;
104
108
 
105
109
  for (let i = 0, n = items.length; i < n; i++) {
106
- this.nodes.push(
107
- this.template.call(array, items[i], i)
108
- );
110
+ this.nodes[i + length] = this.template.call(array, items[i], i);
109
111
  }
110
-
111
112
  anchor.after(this.fragment);
112
113
  }
113
114
 
@@ -163,5 +164,14 @@ class ReactiveArraySlot<T> {
163
164
 
164
165
 
165
166
  export default (anchor: Element, renderable: RenderableReactive) => {
166
- new ReactiveArraySlot(anchor, renderable.array, renderable.template);
167
+ let { array, template } = renderable,
168
+ slot = new ReactiveArraySlot(anchor, array, template);
169
+
170
+ if (array.length) {
171
+ root(() => {
172
+ slot.nodes = array.map(slot.template);
173
+ });
174
+ }
175
+
176
+ return slot.fragment;
167
177
  };
@@ -1,81 +1,50 @@
1
1
  import { isArray } from '@esportsplus/utilities';
2
- import {
3
- RENDERABLE,
4
- RENDERABLE_ARRAY, RENDERABLE_FRAGMENT, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY,
5
- RENDERABLE_NODE, RENDERABLE_NODE_LIST, RENDERABLE_TEXT, RENDERABLE_VOID
6
- } from '~/constants';
7
- import { Element, Fragment, RenderableReactive, RenderableTemplate } from '~/types';
8
- import { append, text } from '~/utilities';
2
+ import { EMPTY_FRAGMENT, RENDERABLE } from '~/constants';
3
+ import { Element, RenderableReactive } from '~/types';
4
+ import { cloneNode, lastChild } from '~/utilities/node';
5
+ import { append } from '~/utilities/fragment';
6
+ import text from '~/utilities/text';
9
7
  import reactive from './reactive';
10
8
 
11
9
 
12
- function type(input: unknown) {
13
- if (input === false || input == null || input === '') {
14
- return RENDERABLE_VOID;
10
+ export default function render(anchor: Element, input: unknown): Node {
11
+ if (input == null || input === false || input === '') {
12
+ return EMPTY_FRAGMENT;
15
13
  }
16
14
 
17
15
  if (typeof input !== 'object') {
18
- return RENDERABLE_TEXT;
16
+ return text(input as any);
19
17
  }
20
18
 
21
- if (RENDERABLE in input) {
22
- return input[RENDERABLE];
19
+ if ('nodeType' in input) {
20
+ return input as Node;
23
21
  }
24
22
 
25
- if (isArray(input)) {
26
- return RENDERABLE_ARRAY;
23
+ if (RENDERABLE in input) {
24
+ return reactive(anchor, input as RenderableReactive);
27
25
  }
28
26
 
29
- let nodeType = (input as any).nodeType;
27
+ if (isArray(input)) {
28
+ let fragment = cloneNode.call(EMPTY_FRAGMENT);
30
29
 
31
- if (nodeType === 11) {
32
- return RENDERABLE_FRAGMENT;
33
- }
30
+ for (let i = 0, n = (input as unknown[]).length; i < n; i++) {
31
+ append.call(fragment, render(anchor, (input as unknown[])[i]));
32
+ anchor = lastChild.call(fragment);
33
+ }
34
34
 
35
- if (nodeType !== undefined) {
36
- return RENDERABLE_NODE;
35
+ return fragment;
37
36
  }
38
37
 
39
38
  if (input instanceof NodeList) {
40
- return RENDERABLE_NODE_LIST;
41
- }
42
- }
43
-
44
-
45
- export default function render(anchor: Element, fragment: Fragment, input: unknown) {
46
- let t = type(input);
39
+ let fragment = cloneNode.call(EMPTY_FRAGMENT),
40
+ nodes = Array.from(input as NodeList);
47
41
 
48
- switch (t) {
49
- case RENDERABLE_VOID:
50
- return;
42
+ for (let i = 0, n = nodes.length; i < n; i++) {
43
+ append.call(fragment, nodes[i]);
44
+ }
51
45
 
52
- case RENDERABLE_TEXT:
53
- append.call(fragment, text(String(input)));
54
- return;
55
-
56
- case RENDERABLE_HTML_FRAGMENT:
57
- append.call(fragment, (input as RenderableTemplate).fragment);
58
- return;
59
-
60
- case RENDERABLE_HTML_REACTIVE_ARRAY:
61
- return reactive(anchor, input as RenderableReactive);
62
-
63
- case RENDERABLE_ARRAY:
64
- for (let i = 0, n = (input as unknown[]).length; i < n; i++) {
65
- render(anchor, fragment, (input as unknown[])[i]);
66
- }
67
- return;
68
-
69
- case RENDERABLE_FRAGMENT:
70
- append.call(fragment, input as Fragment);
71
- return;
72
-
73
- case RENDERABLE_NODE:
74
- append.call(fragment, input as Node);
75
- return;
76
-
77
- case RENDERABLE_NODE_LIST:
78
- append.call(fragment, ...(input as NodeList));
79
- return;
46
+ return fragment;
80
47
  }
48
+
49
+ return text(input as any);
81
50
  };