@esportsplus/template 0.18.0 → 0.19.1

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.
@@ -1,12 +1,22 @@
1
- import { RENDERABLE, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY } from '../constants.js';
2
- import hydrate from './hydrate.js';
1
+ import { RENDERABLE, RENDERABLE_HTML_REACTIVE_ARRAY } from '../constants.js';
2
+ import { cloneNode } from '../utilities/node.js';
3
3
  import parser from './parser.js';
4
4
  const html = (literals, ...values) => {
5
- return {
6
- [RENDERABLE]: RENDERABLE_HTML_FRAGMENT,
7
- fragment: hydrate(parser.parse(literals), values),
8
- literals
9
- };
5
+ let { fragment, slots } = parser.parse(literals), clone = cloneNode.call(fragment, true);
6
+ if (slots !== null) {
7
+ let node, nodePath;
8
+ for (let i = slots.length - 1; i >= 0; i--) {
9
+ let { fn, path, slot } = slots[i];
10
+ if (nodePath !== path) {
11
+ node = clone;
12
+ for (let i = 0, n = path.length; i < n; i++) {
13
+ node = path[i].call(node);
14
+ }
15
+ }
16
+ fn(node, values[slot]);
17
+ }
18
+ }
19
+ return clone;
10
20
  };
11
21
  html.reactive = (array, template) => {
12
22
  return {
@@ -1,8 +1,8 @@
1
1
  import { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH } from '../constants.js';
2
2
  import { firstElementChild, nextElementSibling } from '../utilities/element.js';
3
- import { fragment } from '../utilities/fragment.js';
4
3
  import { firstChild, nextSibling } from '../utilities/node.js';
5
4
  import { spread } from '../attributes.js';
5
+ import { fragment } from '../utilities/fragment.js';
6
6
  import s from '../slot/index.js';
7
7
  let cache = new WeakMap();
8
8
  function build(literals) {
@@ -27,15 +27,11 @@ function build(literals) {
27
27
  ? methods(parent.elements, parent.path, firstElementChild, nextElementSibling)
28
28
  : methods(parent.children, [], firstChild, nextSibling);
29
29
  if (attr) {
30
- let i = attr.indexOf(SLOT_MARKER), p = {
31
- absolute: path,
32
- parent: parent.path,
33
- relative: path.slice(parent.path.length)
34
- };
30
+ let i = attr.indexOf(SLOT_MARKER);
35
31
  while (i !== -1) {
36
32
  slots.push({
37
33
  fn: spread,
38
- path: p,
34
+ path,
39
35
  slot
40
36
  });
41
37
  buffer += parsed[slot++];
@@ -52,15 +48,10 @@ function build(literals) {
52
48
  parent.elements++;
53
49
  }
54
50
  else if (type === NODE_SLOT) {
55
- let relative = methods(parent.children, [], firstChild, nextSibling);
56
51
  buffer += parsed[slot] + SLOT_HTML;
57
52
  slots.push({
58
53
  fn: s,
59
- path: {
60
- absolute: [...parent.path, ...relative],
61
- parent: parent.path,
62
- relative
63
- },
54
+ path: methods(parent.children, parent.path, firstChild, nextSibling),
64
55
  slot: slot++
65
56
  });
66
57
  }
@@ -87,16 +78,20 @@ function methods(children, copy, first, next) {
87
78
  return methods;
88
79
  }
89
80
  function set(literals, html, slots = null) {
90
- let template = {
81
+ let value = {
91
82
  fragment: fragment(html),
92
83
  html,
93
84
  literals,
94
85
  slots
95
86
  };
96
- cache.set(literals, template);
97
- return template;
87
+ cache.set(literals, value);
88
+ return value;
98
89
  }
99
90
  const parse = (literals) => {
100
- return cache.get(literals) || build(literals);
91
+ let result = cache.get(literals);
92
+ if (result === undefined) {
93
+ result = build(literals);
94
+ }
95
+ return result;
101
96
  };
102
97
  export default { parse };
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default as html } from './html/index.js';
2
2
  export { default as render } from './render.js';
3
3
  export { default as svg } from './svg.js';
4
- export type { Attributes, Element, Elements, Renderable, RenderableValue } from './types.js';
4
+ export type { Attributes, Element, Renderable, RenderableValue } from './types.js';
@@ -2,17 +2,18 @@ import { effect } from '@esportsplus/reactivity';
2
2
  import { STATE_HYDRATING, STATE_NONE } from '../constants.js';
3
3
  import { firstChild, lastChild, nodeValue } from '../utilities/node.js';
4
4
  import { raf } from '../utilities/queue.js';
5
- import { ondisconnect } from '../slot/cleanup.js';
6
5
  import { remove } from './cleanup.js';
7
6
  import text from '../utilities/text.js';
8
7
  import render from './render.js';
9
8
  function update(anchor, value) {
10
- let type = typeof value;
11
9
  if (this.group) {
12
10
  remove([this.group]);
13
11
  this.group = undefined;
14
12
  }
15
- if (value == null || type !== 'object') {
13
+ if (value == null || value === false) {
14
+ value = '';
15
+ }
16
+ if (typeof value !== 'object') {
16
17
  let textnode = this.textnode;
17
18
  if (textnode) {
18
19
  nodeValue.call(textnode, String(value));
@@ -25,15 +26,14 @@ function update(anchor, value) {
25
26
  }
26
27
  }
27
28
  else {
28
- let fragment = render(anchor, value);
29
- if (!fragment) {
30
- return;
29
+ let fragment = render(anchor, value), head = firstChild.call(fragment);
30
+ if (head) {
31
+ this.group = {
32
+ head,
33
+ tail: lastChild.call(fragment)
34
+ };
35
+ anchor.after(fragment);
31
36
  }
32
- this.group = {
33
- head: firstChild.call(fragment),
34
- tail: lastChild.call(fragment)
35
- };
36
- anchor.after(fragment);
37
37
  }
38
38
  }
39
39
  export default (anchor, fn) => {
@@ -41,7 +41,7 @@ export default (anchor, fn) => {
41
41
  group: undefined,
42
42
  textnode: undefined
43
43
  }, state = STATE_HYDRATING;
44
- ondisconnect(anchor, effect(() => {
44
+ effect(() => {
45
45
  let value = fn();
46
46
  if (state === STATE_HYDRATING) {
47
47
  update.call(context, anchor, value);
@@ -52,5 +52,5 @@ export default (anchor, fn) => {
52
52
  update.call(context, anchor, value);
53
53
  });
54
54
  }
55
- }));
55
+ });
56
56
  };
@@ -2,7 +2,9 @@ import effect from './effect.js';
2
2
  import render from './render.js';
3
3
  export default (anchor, value) => {
4
4
  if (typeof value === 'function') {
5
- return effect(anchor, value);
5
+ effect(anchor, value);
6
+ }
7
+ else {
8
+ anchor.after(render(anchor, value));
6
9
  }
7
- anchor.after(render(anchor, value));
8
10
  };
@@ -1,3 +1,3 @@
1
- import { Fragment, RenderableReactive } from '../types.js';
2
- declare const _default: (anchor: Element, renderable: RenderableReactive) => Fragment;
1
+ import { RenderableReactive } from '../types.js';
2
+ declare const _default: (anchor: Element, renderable: RenderableReactive) => Node;
3
3
  export default _default;
@@ -2,45 +2,47 @@ import { root } from '@esportsplus/reactivity';
2
2
  import { EMPTY_FRAGMENT } from '../constants.js';
3
3
  import { append } from '../utilities/fragment.js';
4
4
  import { cloneNode, firstChild, lastChild } from '../utilities/node.js';
5
- import { remove } from './cleanup.js';
5
+ import { ondisconnect, remove } from './cleanup.js';
6
6
  class ReactiveArraySlot {
7
7
  array;
8
- fragment = cloneNode.call(EMPTY_FRAGMENT);
8
+ fragment;
9
9
  marker;
10
10
  nodes = [];
11
11
  template;
12
12
  constructor(anchor, array, template) {
13
- let fragment = this.fragment;
13
+ let fragment = this.fragment = cloneNode.call(EMPTY_FRAGMENT);
14
14
  this.array = array;
15
15
  this.marker = anchor;
16
16
  this.template = function (data, i) {
17
- let frag = template.call(this, data, i).fragment, group = {
17
+ let dispose, frag = root((d) => {
18
+ dispose = d;
19
+ return template.call(this, data, i);
20
+ }), group = {
18
21
  head: firstChild.call(frag),
19
22
  tail: lastChild.call(frag)
20
23
  };
21
24
  append.call(fragment, frag);
25
+ ondisconnect(group.head, dispose);
22
26
  return group;
23
27
  };
24
- let render = () => {
25
- root(() => this.render());
26
- };
27
28
  array.on('clear', () => this.clear());
28
- array.on('reverse', render);
29
+ array.on('reverse', () => {
30
+ root(() => this.render());
31
+ });
29
32
  array.on('pop', () => this.pop());
30
33
  array.on('push', ({ items }) => {
31
34
  root(() => this.push(items));
32
35
  });
33
36
  array.on('shift', () => this.shift());
34
- array.on('sort', render);
37
+ array.on('sort', () => {
38
+ root(() => this.render());
39
+ });
35
40
  array.on('splice', ({ deleteCount, items, start }) => {
36
41
  root(() => this.splice(start, deleteCount, ...items));
37
42
  });
38
43
  array.on('unshift', ({ items }) => {
39
44
  root(() => this.unshift(items));
40
45
  });
41
- if (array.length) {
42
- render();
43
- }
44
46
  }
45
47
  get length() {
46
48
  return this.nodes.length;
@@ -1,81 +1,37 @@
1
1
  import { isArray } from '@esportsplus/utilities';
2
- import { EMPTY_FRAGMENT, RENDERABLE, RENDERABLE_ARRAY, RENDERABLE_FRAGMENT, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY, RENDERABLE_NODE, RENDERABLE_NODE_LIST, RENDERABLE_TEXT, RENDERABLE_VOID } from '../constants.js';
3
- import { cloneNode } from '../utilities/node.js';
2
+ import { EMPTY_FRAGMENT, RENDERABLE } from '../constants.js';
3
+ import { cloneNode, lastChild } from '../utilities/node.js';
4
4
  import { append } from '../utilities/fragment.js';
5
5
  import text from '../utilities/text.js';
6
6
  import reactive from './reactive.js';
7
- function type(input) {
8
- if (input === false || input == null || input === '') {
9
- return RENDERABLE_VOID;
7
+ export default function render(anchor, input) {
8
+ if (input == null || input === false || input === '') {
9
+ return EMPTY_FRAGMENT;
10
10
  }
11
11
  if (typeof input !== 'object') {
12
- return RENDERABLE_TEXT;
12
+ return text(input);
13
+ }
14
+ if ('nodeType' in input) {
15
+ return input;
13
16
  }
14
17
  if (RENDERABLE in input) {
15
- return input[RENDERABLE];
18
+ return reactive(anchor, input);
16
19
  }
17
20
  if (isArray(input)) {
18
- return RENDERABLE_ARRAY;
19
- }
20
- let nodeType = input.nodeType;
21
- if (nodeType === 11) {
22
- return RENDERABLE_FRAGMENT;
23
- }
24
- if (nodeType !== undefined) {
25
- return RENDERABLE_NODE;
21
+ let fragment = cloneNode.call(EMPTY_FRAGMENT);
22
+ for (let i = 0, n = input.length; i < n; i++) {
23
+ append.call(fragment, render(anchor, input[i]));
24
+ anchor = lastChild.call(fragment);
25
+ }
26
+ return fragment;
26
27
  }
27
28
  if (input instanceof NodeList) {
28
- return RENDERABLE_NODE_LIST;
29
- }
30
- return RENDERABLE_TEXT;
31
- }
32
- function loop(fragment, input) {
33
- let t = type(input);
34
- switch (t) {
35
- case RENDERABLE_HTML_REACTIVE_ARRAY:
36
- throw new Error('@esportsplus/template: reactive arrays cannot be defined within an slot array value');
37
- case RENDERABLE_VOID:
38
- return;
39
- case RENDERABLE_ARRAY:
40
- for (let i = 0, n = input.length; i < n; i++) {
41
- loop(fragment, input[i]);
42
- }
43
- return;
44
- case RENDERABLE_NODE_LIST:
45
- append.call(fragment, ...input);
46
- return;
47
- default:
48
- append.call(fragment, input);
49
- return;
50
- }
51
- }
52
- let scratchpad = cloneNode.call(EMPTY_FRAGMENT);
53
- export default function render(anchor, input) {
54
- let fragment = scratchpad, t = type(input);
55
- switch (t) {
56
- case RENDERABLE_VOID:
57
- break;
58
- case RENDERABLE_TEXT:
59
- append.call(fragment, text(input));
60
- break;
61
- case RENDERABLE_HTML_FRAGMENT:
62
- return input.fragment;
63
- case RENDERABLE_HTML_REACTIVE_ARRAY:
64
- return reactive(anchor, input);
65
- case RENDERABLE_ARRAY:
66
- for (let i = 0, n = input.length; i < n; i++) {
67
- loop(fragment, input[i]);
68
- }
69
- break;
70
- case RENDERABLE_FRAGMENT:
71
- return input;
72
- case RENDERABLE_NODE:
73
- append.call(fragment, input);
74
- break;
75
- case RENDERABLE_NODE_LIST:
76
- append.call(fragment, ...input);
77
- break;
29
+ let fragment = cloneNode.call(EMPTY_FRAGMENT), nodes = Array.from(input);
30
+ for (let i = 0, n = nodes.length; i < n; i++) {
31
+ append.call(fragment, nodes[i]);
32
+ }
33
+ return fragment;
78
34
  }
79
- return fragment;
35
+ return text(input);
80
36
  }
81
37
  ;
package/build/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactiveArray } from '@esportsplus/reactivity';
2
- import { RENDERABLE, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY } from './constants.js';
2
+ import { RENDERABLE, RENDERABLE_HTML_REACTIVE_ARRAY } from './constants.js';
3
3
  import { firstChild } from './utilities/node.js';
4
4
  import attributes from './attributes.js';
5
5
  import slot from './slot/index.js';
@@ -20,22 +20,14 @@ type Attributes = {
20
20
  type Effect<T> = () => EffectResponse<T>;
21
21
  type EffectResponse<T> = T extends [] ? (Primitive | Renderable)[] : Primitive | Renderable;
22
22
  type Element = HTMLElement & Attributes & Record<PropertyKey, unknown>;
23
- type Elements = Element[];
24
- type Fragment = (DocumentFragment | Node) & Record<PropertyKey, unknown>;
25
23
  type Primitive = bigint | boolean | null | number | string | undefined;
26
- type Renderable = Fragment | Primitive | RenderableReactive | RenderableTemplate;
24
+ type Renderable = DocumentFragment | Node | NodeList | Primitive | RenderableReactive | Renderable[];
27
25
  type RenderableReactive = Readonly<{
28
26
  [RENDERABLE]: typeof RENDERABLE_HTML_REACTIVE_ARRAY;
29
27
  array: ReactiveArray<unknown[]>;
30
28
  template: (this: ReactiveArray<unknown[]>, ...args: Parameters<Parameters<ReactiveArray<unknown[]>['map']>[0]>) => ReturnType<typeof html>;
31
29
  }>;
32
- type RenderableTemplate = {
33
- [RENDERABLE]: typeof RENDERABLE_HTML_FRAGMENT;
34
- fragment: Fragment;
35
- literals: TemplateStringsArray;
36
- };
37
- type RenderableValue<T = unknown> = Attributes | Readonly<Attributes> | Readonly<Attributes[]> | Effect<T> | Fragment | Primitive | RenderableReactive;
38
- type RenderableValues = RenderableValue | RenderableValue[];
30
+ type RenderableValue<T = unknown> = Attributes | Readonly<Attributes> | Readonly<Attributes[]> | Effect<T> | Primitive | RenderableReactive;
39
31
  type SlotGroup = {
40
32
  head: Element;
41
33
  tail: Element;
@@ -46,12 +38,8 @@ type Template = {
46
38
  literals: TemplateStringsArray;
47
39
  slots: {
48
40
  fn: typeof attributes.spread | typeof slot;
49
- path: {
50
- absolute: typeof firstChild[];
51
- parent: typeof firstChild[];
52
- relative: typeof firstChild[];
53
- };
41
+ path: typeof firstChild[];
54
42
  slot: number;
55
43
  }[] | null;
56
44
  };
57
- export type { Attributes, Effect, Element, Elements, Fragment, Renderable, RenderableReactive, RenderableTemplate, RenderableValue, RenderableValues, SlotGroup, Template };
45
+ export type { Attributes, Effect, Element, Renderable, RenderableReactive, RenderableValue, SlotGroup, Template };
@@ -1,11 +1,11 @@
1
1
  import { innerHTML } from './element.js';
2
2
  import { cloneNode } from './node.js';
3
- let prototype = DocumentFragment.prototype, template = document.createElement('template');
4
- const append = prototype.append;
3
+ let scratchpad = document.createElement('template');
4
+ const append = DocumentFragment.prototype.append;
5
5
  const fragment = (html) => {
6
- innerHTML.call(template, html);
7
- let content = template.content;
8
- template = cloneNode.call(template);
6
+ innerHTML.call(scratchpad, html);
7
+ let content = scratchpad.content;
8
+ scratchpad = cloneNode.call(scratchpad);
9
9
  return content;
10
10
  };
11
11
  export { append, fragment };
@@ -1,3 +1,4 @@
1
+ declare const appendChild: <T extends Node>(node: T) => T;
1
2
  declare const cloneNode: (subtree?: boolean) => Node;
2
3
  declare const firstChild: () => any;
3
4
  declare const lastChild: () => any;
@@ -5,4 +6,4 @@ declare const nextSibling: () => any;
5
6
  declare const nodeValue: (v: any) => void;
6
7
  declare const parentElement: () => any;
7
8
  declare const previousSibling: () => any;
8
- export { cloneNode, firstChild, lastChild, nextSibling, nodeValue, parentElement, previousSibling };
9
+ export { appendChild, cloneNode, firstChild, lastChild, nextSibling, nodeValue, parentElement, previousSibling };
@@ -1,4 +1,5 @@
1
1
  let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, prototype = Node.prototype;
2
+ const appendChild = prototype.appendChild;
2
3
  const cloneNode = prototype.cloneNode;
3
4
  const firstChild = getOwnPropertyDescriptor(prototype, 'firstChild').get;
4
5
  const lastChild = getOwnPropertyDescriptor(prototype, 'lastChild').get;
@@ -6,4 +7,4 @@ const nextSibling = getOwnPropertyDescriptor(prototype, 'nextSibling').get;
6
7
  const nodeValue = getOwnPropertyDescriptor(prototype, 'nodeValue').set;
7
8
  const parentElement = getOwnPropertyDescriptor(prototype, 'parentElement').get;
8
9
  const previousSibling = getOwnPropertyDescriptor(prototype, 'previousSibling').get;
9
- export { cloneNode, firstChild, lastChild, nextSibling, nodeValue, parentElement, previousSibling };
10
+ export { appendChild, cloneNode, firstChild, lastChild, nextSibling, nodeValue, parentElement, previousSibling };
@@ -1,3 +1,2 @@
1
- import { Element } from '../types.js';
2
- declare const _default: (value: string) => Element;
1
+ declare const _default: (value: string) => Node;
3
2
  export default _default;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "ICJR",
3
3
  "dependencies": {
4
4
  "@esportsplus/queue": "^0.1.0",
5
- "@esportsplus/reactivity": "^0.15.0",
5
+ "@esportsplus/reactivity": "^0.16.1",
6
6
  "@esportsplus/tasks": "^0.2.1",
7
7
  "@esportsplus/utilities": "^0.22.1"
8
8
  },
@@ -14,7 +14,7 @@
14
14
  "private": false,
15
15
  "type": "module",
16
16
  "types": "./build/index.d.ts",
17
- "version": "0.18.0",
17
+ "version": "0.19.1",
18
18
  "scripts": {
19
19
  "build": "tsc && tsc-alias",
20
20
  "-": "-"
package/src/attributes.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { effect } from '@esportsplus/reactivity';
2
2
  import { isArray, isObject, isString } from '@esportsplus/utilities';
3
- import { ondisconnect } from './slot/cleanup';
4
3
  import { STATE_HYDRATING, STATE_NONE, STATE_WAITING } from './constants';
5
4
  import { Attributes, Element } from './types';
6
5
  import { className, removeAttribute, setAttribute } from './utilities/element';
@@ -9,6 +8,9 @@ import q from '@esportsplus/queue';
9
8
  import event from './event';
10
9
 
11
10
 
11
+ // TODO: Refactor
12
+
13
+
12
14
  const EFFECT = Symbol();
13
15
 
14
16
  const STORE = Symbol();
@@ -74,31 +76,28 @@ function set(context: Context, name: string, value: unknown, state: State) {
74
76
 
75
77
  let id = (context.store[EFFECT] as number)++;
76
78
 
77
- ondisconnect(
78
- context.element,
79
- effect(() => {
80
- let v = (value as Function)(context.element);
81
-
82
- if (isArray(v)) {
83
- let last = v.length - 1;
84
-
85
- for (let i = 0, n = v.length; i < n; i++) {
86
- update(
87
- context,
88
- id,
89
- name,
90
- v[i],
91
- state === STATE_HYDRATING
92
- ? state
93
- : i !== last ? STATE_WAITING : state
94
- );
95
- }
96
- }
97
- else {
98
- update(context, id, name, v, state);
79
+ effect(() => {
80
+ let v = (value as Function)(context.element);
81
+
82
+ if (isArray(v)) {
83
+ let last = v.length - 1;
84
+
85
+ for (let i = 0, n = v.length; i < n; i++) {
86
+ update(
87
+ context,
88
+ id,
89
+ name,
90
+ v[i],
91
+ state === STATE_HYDRATING
92
+ ? state
93
+ : i !== last ? STATE_WAITING : state
94
+ );
99
95
  }
100
- })
101
- );
96
+ }
97
+ else {
98
+ update(context, id, name, v, state);
99
+ }
100
+ });
102
101
 
103
102
  state = STATE_NONE;
104
103
  }
package/src/constants.ts CHANGED
@@ -47,21 +47,7 @@ const REGEX_SLOT_NODES = /<([\w-]+|[\/!])(?:([^><]*{{\$}}[^><]*)|(?:[^><]*))?>|{
47
47
 
48
48
  const RENDERABLE = Symbol();
49
49
 
50
- const RENDERABLE_ARRAY = 0;
51
-
52
- const RENDERABLE_FRAGMENT = 1;
53
-
54
- const RENDERABLE_HTML_FRAGMENT = 2;
55
-
56
- const RENDERABLE_HTML_REACTIVE_ARRAY = 3;
57
-
58
- const RENDERABLE_NODE = 4;
59
-
60
- const RENDERABLE_NODE_LIST = 5;
61
-
62
- const RENDERABLE_TEXT = 6;
63
-
64
- const RENDERABLE_VOID = 7;
50
+ const RENDERABLE_HTML_REACTIVE_ARRAY = 1;
65
51
 
66
52
 
67
53
  const SLOT_HTML = '<!--$-->';
@@ -83,10 +69,7 @@ export {
83
69
  EMPTY_FRAGMENT,
84
70
  NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST,
85
71
  REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES,
86
- RENDERABLE, RENDERABLE_ARRAY, RENDERABLE_FRAGMENT,
87
- RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY,
88
- RENDERABLE_NODE, RENDERABLE_NODE_LIST, RENDERABLE_TEXT,
89
- RENDERABLE_VOID,
72
+ RENDERABLE, RENDERABLE_HTML_REACTIVE_ARRAY,
90
73
  SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH,
91
74
  STATE_HYDRATING, STATE_NONE, STATE_WAITING
92
75
  };
package/src/html/index.ts CHANGED
@@ -1,19 +1,68 @@
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';
2
+ import { RENDERABLE, RENDERABLE_HTML_REACTIVE_ARRAY } from '~/constants';
3
+ import { RenderableReactive, RenderableValue } from '~/types';
4
+ import { cloneNode } from '~/utilities/node';
5
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(parser.parse(literals), values),
12
- literals
13
- };
8
+ const html = (literals: TemplateStringsArray, ...values: (RenderableValue | RenderableValue[])[]) => {
9
+ let { fragment, slots } = parser.parse(literals),
10
+ clone = cloneNode.call(fragment, true);
11
+
12
+ if (slots !== null) {
13
+ let node, nodePath; // , parent, parentPath;
14
+
15
+ // TODO: when a new slot is added it breaks pathfinding for the next slot
16
+ // for (let i = 0, n = slots.length; i < n; i++) {
17
+ for (let i = slots.length - 1; i >= 0; i--) {
18
+ let { fn, path, slot } = slots[i];
19
+
20
+ // pp = path.parent,
21
+ // pr = path.relative;
22
+
23
+ // if (pp !== parentPath) {
24
+ // if (pp === nodePath) {
25
+ // parent = node;
26
+ // parentPath = nodePath;
27
+
28
+ // nodePath = undefined;
29
+ // }
30
+ // else {
31
+ // parent = clone;
32
+ // parentPath = pp;
33
+
34
+ // for (let i = 0, n = pp.length; i < n; i++) {
35
+ // parent = pp[i].call(parent);
36
+ // }
37
+ // }
38
+ // }
39
+
40
+ // if (pr !== nodePath) {
41
+ // node = parent;
42
+ // nodePath = path.absolute;
43
+
44
+ // for (let i = 0, n = pr.length; i < n; i++) {
45
+ // node = pr[i].call(node);
46
+ // }
47
+ // }
48
+
49
+ if (nodePath !== path) {
50
+ node = clone;
51
+
52
+ for (let i = 0, n = path.length; i < n; i++) {
53
+ node = path[i].call(node);
54
+ }
55
+ }
56
+
57
+ // @ts-ignore
58
+ fn(node, values[slot]);
59
+ }
60
+ }
61
+
62
+ return clone;
14
63
  };
15
64
 
16
- html.reactive = <T>(array: ReactiveArray<T[]>, template: RenderableReactive['template']) => {
65
+ html.reactive = <T>(array: ReactiveArray<T[]>, template: RenderableReactive['template']): RenderableReactive => {
17
66
  return {
18
67
  [RENDERABLE]: RENDERABLE_HTML_REACTIVE_ARRAY,
19
68
  array,