@thi.ng/hdom 9.3.31 → 9.4.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-18T13:41:20Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [9.4.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/hdom@9.4.0) (2023-12-11)
13
+
14
+ #### 🚀 Features
15
+
16
+ - update setAttrib(), more alignment w/ rdom logic ([639ca71](https://github.com/thi-ng/umbrella/commit/639ca71))
17
+
12
18
  ### [9.3.27](https://github.com/thi-ng/umbrella/tree/@thi.ng/hdom@9.3.27) (2023-11-09)
13
19
 
14
20
  #### ♻️ Refactoring
package/README.md CHANGED
@@ -157,7 +157,7 @@ yarn install
157
157
  yarn start
158
158
  ```
159
159
 
160
- Package sizes (brotli'd, pre-treeshake): ESM: 3.42 KB
160
+ Package sizes (brotli'd, pre-treeshake): ESM: 3.49 KB
161
161
 
162
162
  ## Dependencies
163
163
 
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/default.js CHANGED
@@ -1,31 +1,42 @@
1
1
  import { diffTree } from "./diff.js";
2
- import { createElement, createTextElement, createTree, getChild, hydrateTree, removeAttribs, removeChild, replaceChild, setAttrib, setContent, } from "./dom.js";
2
+ import {
3
+ createElement,
4
+ createTextElement,
5
+ createTree,
6
+ getChild,
7
+ hydrateTree,
8
+ removeAttribs,
9
+ removeChild,
10
+ replaceChild,
11
+ setAttrib,
12
+ setContent
13
+ } from "./dom.js";
3
14
  import { normalizeTree } from "./normalize.js";
4
- /**
5
- * Default target implementation to manipulate browser DOM.
6
- */
7
- export const DEFAULT_IMPL = {
8
- createTree(opts, parent, tree, child, init) {
9
- return createTree(opts, this, parent, tree, child, init);
10
- },
11
- hydrateTree(opts, parent, tree, child) {
12
- return hydrateTree(opts, this, parent, tree, child);
13
- },
14
- diffTree(opts, parent, prev, curr, child) {
15
- diffTree(opts, this, parent, prev, curr, child);
16
- },
17
- normalizeTree,
18
- getElementById(id) {
19
- return document.getElementById(id);
20
- },
21
- getChild,
22
- createElement,
23
- createTextElement,
24
- replaceChild(opts, parent, child, tree, init) {
25
- replaceChild(opts, this, parent, child, tree, init);
26
- },
27
- removeChild,
28
- setContent,
29
- removeAttribs,
30
- setAttrib,
15
+ const DEFAULT_IMPL = {
16
+ createTree(opts, parent, tree, child, init) {
17
+ return createTree(opts, this, parent, tree, child, init);
18
+ },
19
+ hydrateTree(opts, parent, tree, child) {
20
+ return hydrateTree(opts, this, parent, tree, child);
21
+ },
22
+ diffTree(opts, parent, prev, curr, child) {
23
+ diffTree(opts, this, parent, prev, curr, child);
24
+ },
25
+ normalizeTree,
26
+ getElementById(id) {
27
+ return document.getElementById(id);
28
+ },
29
+ getChild,
30
+ createElement,
31
+ createTextElement,
32
+ replaceChild(opts, parent, child, tree, init) {
33
+ replaceChild(opts, this, parent, child, tree, init);
34
+ },
35
+ removeChild,
36
+ setContent,
37
+ removeAttribs,
38
+ setAttrib
39
+ };
40
+ export {
41
+ DEFAULT_IMPL
31
42
  };
package/diff.js CHANGED
@@ -1,285 +1,248 @@
1
1
  import { SEMAPHORE } from "@thi.ng/api/api";
2
2
  import { diffArray } from "@thi.ng/diff/array";
3
3
  import { diffObject } from "@thi.ng/diff/object";
4
- import { equiv as _equiv, equivArrayLike, equivMap, equivObject, equivSet, } from "@thi.ng/equiv";
4
+ import {
5
+ equiv as _equiv,
6
+ equivArrayLike,
7
+ equivMap,
8
+ equivObject,
9
+ equivSet
10
+ } from "@thi.ng/equiv";
5
11
  const isArray = Array.isArray;
6
12
  const max = Math.max;
7
13
  const OBJP = Object.getPrototypeOf({});
8
14
  const FN = "function";
9
15
  const STR = "string";
10
- // child index tracking template buffer
11
16
  const INDEX = (() => {
12
- const res = new Array(2048);
13
- for (let i = 2, n = res.length; i < n; i++) {
14
- res[i] = i - 2;
15
- }
16
- return res;
17
+ const res = new Array(2048);
18
+ for (let i = 2, n = res.length; i < n; i++) {
19
+ res[i] = i - 2;
20
+ }
21
+ return res;
17
22
  })();
18
23
  const buildIndex = (n) => {
19
- if (n <= INDEX.length) {
20
- return INDEX.slice(0, n);
21
- }
22
- const res = new Array(n);
23
- while (n-- > 2) {
24
- res[n] = n - 2;
25
- }
26
- return res;
24
+ if (n <= INDEX.length) {
25
+ return INDEX.slice(0, n);
26
+ }
27
+ const res = new Array(n);
28
+ while (n-- > 2) {
29
+ res[n] = n - 2;
30
+ }
31
+ return res;
27
32
  };
28
- /**
29
- * See {@link HDOMImplementation} interface for further details.
30
- *
31
- * @param opts - hdom config options
32
- * @param impl - hdom implementation
33
- * @param parent - parent element (DOM node)
34
- * @param prev - previous tree
35
- * @param curr - current tree
36
- * @param child - child index
37
- */
38
- export const diffTree = (opts, impl, parent, prev, curr, child = 0) => {
39
- const attribs = curr[1];
40
- if (attribs.__skip) {
41
- return;
42
- }
43
- // always replace element if __diff = false
44
- if (attribs.__diff === false) {
45
- releaseTree(prev);
46
- impl.replaceChild(opts, parent, child, curr);
47
- return;
48
- }
49
- const pattribs = prev[1];
50
- if (pattribs && pattribs.__skip) {
51
- impl.replaceChild(opts, parent, child, curr, false);
52
- return;
53
- }
54
- // delegate to branch-local implementation
55
- let _impl = attribs.__impl;
56
- if (_impl && _impl !== impl) {
57
- return _impl.diffTree(opts, _impl, parent, prev, curr, child);
58
- }
59
- const delta = diffArray(prev, curr, "only-distance-linear", equiv);
60
- if (delta.distance === 0) {
61
- return;
62
- }
63
- const edits = delta.linear;
64
- const el = impl.getChild(parent, child);
65
- let i;
66
- let ii;
67
- let status;
68
- let val;
69
- if (edits[0] !== 0 || prev[1].key !== attribs.key) {
70
- // LOGGER.fine("replace:", prev, curr);
71
- releaseTree(prev);
72
- impl.replaceChild(opts, parent, child, curr);
73
- return;
74
- }
75
- if ((val = prev.__release) && val !== curr.__release) {
76
- releaseTree(prev);
77
- }
78
- if (edits[3] !== 0) {
79
- diffAttributes(impl, el, prev[1], curr[1]);
80
- // if attribs changed & distance == 2 then we're done here...
81
- if (delta.distance === 2) {
82
- return;
83
- }
84
- }
85
- const numEdits = edits.length;
86
- const prevLength = prev.length - 1;
87
- const equivKeys = extractEquivElements(edits);
88
- const offsets = buildIndex(prevLength + 1);
89
- for (i = 2, ii = 6; ii < numEdits; i++, ii += 3) {
90
- status = edits[ii];
91
- if (!status)
92
- continue;
93
- if (status === -1) {
94
- diffDeleted(opts, impl, el, prev, curr, edits, ii, equivKeys, offsets, prevLength);
95
- }
96
- else {
97
- diffAdded(opts, impl, el, edits, ii, equivKeys, offsets, prevLength);
98
- }
99
- }
100
- // call __init after all children have been added/updated
101
- if ((val = curr.__init) && val != prev.__init) {
102
- val.apply(curr, [el, ...curr.__args]);
103
- }
33
+ const diffTree = (opts, impl, parent, prev, curr, child = 0) => {
34
+ const attribs = curr[1];
35
+ if (attribs.__skip) {
36
+ return;
37
+ }
38
+ if (attribs.__diff === false) {
39
+ releaseTree(prev);
40
+ impl.replaceChild(opts, parent, child, curr);
41
+ return;
42
+ }
43
+ const pattribs = prev[1];
44
+ if (pattribs && pattribs.__skip) {
45
+ impl.replaceChild(opts, parent, child, curr, false);
46
+ return;
47
+ }
48
+ let _impl = attribs.__impl;
49
+ if (_impl && _impl !== impl) {
50
+ return _impl.diffTree(opts, _impl, parent, prev, curr, child);
51
+ }
52
+ const delta = diffArray(prev, curr, "only-distance-linear", equiv);
53
+ if (delta.distance === 0) {
54
+ return;
55
+ }
56
+ const edits = delta.linear;
57
+ const el = impl.getChild(parent, child);
58
+ let i;
59
+ let ii;
60
+ let status;
61
+ let val;
62
+ if (edits[0] !== 0 || prev[1].key !== attribs.key) {
63
+ releaseTree(prev);
64
+ impl.replaceChild(opts, parent, child, curr);
65
+ return;
66
+ }
67
+ if ((val = prev.__release) && val !== curr.__release) {
68
+ releaseTree(prev);
69
+ }
70
+ if (edits[3] !== 0) {
71
+ diffAttributes(impl, el, prev[1], curr[1]);
72
+ if (delta.distance === 2) {
73
+ return;
74
+ }
75
+ }
76
+ const numEdits = edits.length;
77
+ const prevLength = prev.length - 1;
78
+ const equivKeys = extractEquivElements(edits);
79
+ const offsets = buildIndex(prevLength + 1);
80
+ for (i = 2, ii = 6; ii < numEdits; i++, ii += 3) {
81
+ status = edits[ii];
82
+ if (!status)
83
+ continue;
84
+ if (status === -1) {
85
+ diffDeleted(
86
+ opts,
87
+ impl,
88
+ el,
89
+ prev,
90
+ curr,
91
+ edits,
92
+ ii,
93
+ equivKeys,
94
+ offsets,
95
+ prevLength
96
+ );
97
+ } else {
98
+ diffAdded(
99
+ opts,
100
+ impl,
101
+ el,
102
+ edits,
103
+ ii,
104
+ equivKeys,
105
+ offsets,
106
+ prevLength
107
+ );
108
+ }
109
+ }
110
+ if ((val = curr.__init) && val != prev.__init) {
111
+ val.apply(curr, [el, ...curr.__args]);
112
+ }
104
113
  };
105
114
  const diffDeleted = (opts, impl, el, prev, curr, edits, ii, equivKeys, offsets, prevLength) => {
106
- const val = edits[ii + 2];
107
- if (isArray(val)) {
108
- let k = val[1].key;
109
- if (k !== undefined && equivKeys[k][2] !== undefined) {
110
- const eq = equivKeys[k];
111
- k = eq[0];
112
- // LOGGER.fine(`diff equiv key @ ${k}:`, prev[k], curr[eq[2]]);
113
- diffTree(opts, impl, el, prev[k], curr[eq[2]], offsets[k]);
114
- }
115
- else {
116
- const idx = edits[ii + 1];
117
- // LOGGER.fine("remove @", offsets[idx], val);
118
- releaseTree(val);
119
- impl.removeChild(el, offsets[idx]);
120
- incOffsets(offsets, prevLength, idx);
121
- }
122
- }
123
- else if (typeof val === STR) {
124
- impl.setContent(el, "");
125
- }
115
+ const val = edits[ii + 2];
116
+ if (isArray(val)) {
117
+ let k = val[1].key;
118
+ if (k !== void 0 && equivKeys[k][2] !== void 0) {
119
+ const eq = equivKeys[k];
120
+ k = eq[0];
121
+ diffTree(opts, impl, el, prev[k], curr[eq[2]], offsets[k]);
122
+ } else {
123
+ const idx = edits[ii + 1];
124
+ releaseTree(val);
125
+ impl.removeChild(el, offsets[idx]);
126
+ incOffsets(offsets, prevLength, idx);
127
+ }
128
+ } else if (typeof val === STR) {
129
+ impl.setContent(el, "");
130
+ }
126
131
  };
127
132
  const diffAdded = (opts, impl, el, edits, ii, equivKeys, offsets, prevLength) => {
128
- const val = edits[ii + 2];
129
- if (typeof val === STR) {
130
- impl.setContent(el, val);
131
- }
132
- else if (isArray(val)) {
133
- const k = val[1].key;
134
- if (k === undefined || equivKeys[k][0] === undefined) {
135
- const idx = edits[ii + 1];
136
- // LOGGER.fine("insert @", offsets[idx], val);
137
- impl.createTree(opts, el, val, offsets[idx]);
138
- decOffsets(offsets, prevLength, idx);
139
- }
140
- }
133
+ const val = edits[ii + 2];
134
+ if (typeof val === STR) {
135
+ impl.setContent(el, val);
136
+ } else if (isArray(val)) {
137
+ const k = val[1].key;
138
+ if (k === void 0 || equivKeys[k][0] === void 0) {
139
+ const idx = edits[ii + 1];
140
+ impl.createTree(opts, el, val, offsets[idx]);
141
+ decOffsets(offsets, prevLength, idx);
142
+ }
143
+ }
141
144
  };
142
145
  const incOffsets = (offsets, j, idx) => {
143
- for (; j > idx; j--) {
144
- offsets[j] = max(offsets[j] - 1, 0);
145
- }
146
+ for (; j > idx; j--) {
147
+ offsets[j] = max(offsets[j] - 1, 0);
148
+ }
146
149
  };
147
150
  const decOffsets = (offsets, j, idx) => {
148
- for (; j >= idx; j--) {
149
- offsets[j]++;
150
- }
151
+ for (; j >= idx; j--) {
152
+ offsets[j]++;
153
+ }
154
+ };
155
+ const diffAttributes = (impl, el, prev, curr) => {
156
+ const delta = diffObject(prev, curr, "full", _equiv);
157
+ impl.removeAttribs(el, delta.dels, prev);
158
+ let val = SEMAPHORE;
159
+ let i, e, edits;
160
+ for (edits = delta.edits, i = edits.length; (i -= 2) >= 0; ) {
161
+ e = edits[i];
162
+ e[0] === "o" && e[1] === "n" && impl.removeAttribs(el, [e], prev);
163
+ e !== "value" ? impl.setAttrib(el, e, edits[i + 1], curr) : val = edits[i + 1];
164
+ }
165
+ for (edits = delta.adds, i = edits.length; i-- > 0; ) {
166
+ e = edits[i];
167
+ e !== "value" ? impl.setAttrib(el, e, curr[e], curr) : val = curr[e];
168
+ }
169
+ val !== SEMAPHORE && impl.setAttrib(el, "value", val, curr);
151
170
  };
152
- /**
153
- * Helper function for {@link diffTree} to compute & apply the difference
154
- * between a node's `prev` and `curr` attributes.
155
- *
156
- * @param impl - hdom implementation
157
- * @param el - DOM element
158
- * @param prev - previous attributes
159
- * @param curr - current attributes
160
- *
161
- * @internal
162
- */
163
- export const diffAttributes = (impl, el, prev, curr) => {
164
- const delta = diffObject(prev, curr, "full", _equiv);
165
- impl.removeAttribs(el, delta.dels, prev);
166
- let val = SEMAPHORE;
167
- let i, e, edits;
168
- for (edits = delta.edits, i = edits.length; (i -= 2) >= 0;) {
169
- e = edits[i];
170
- e[0] === "o" && e[1] === "n" && impl.removeAttribs(el, [e], prev);
171
- e !== "value"
172
- ? impl.setAttrib(el, e, edits[i + 1], curr)
173
- : (val = edits[i + 1]);
171
+ const releaseTree = (tree) => {
172
+ if (isArray(tree)) {
173
+ let x;
174
+ if ((x = tree[1]) && x.__release === false) {
175
+ return;
174
176
  }
175
- for (edits = delta.adds, i = edits.length; i-- > 0;) {
176
- e = edits[i];
177
- e !== "value" ? impl.setAttrib(el, e, curr[e], curr) : (val = curr[e]);
177
+ if (tree.__release) {
178
+ tree.__release.apply(tree.__this, tree.__args);
179
+ delete tree.__release;
178
180
  }
179
- val !== SEMAPHORE && impl.setAttrib(el, "value", val, curr);
180
- };
181
- /**
182
- * Recursively attempts to call the {@link ILifecycle.release} lifecycle
183
- * method on every element in given tree (branch), using depth-first
184
- * descent. Each element is checked for the presence of the `__release`
185
- * control attribute. If (and only if) it is set to `false`, further
186
- * descent into that element's branch is skipped.
187
- *
188
- * @param tree - hdom sub-tree
189
- *
190
- * @internal
191
- */
192
- export const releaseTree = (tree) => {
193
- if (isArray(tree)) {
194
- let x;
195
- if ((x = tree[1]) && x.__release === false) {
196
- return;
197
- }
198
- if (tree.__release) {
199
- // LOGGER.fine("call __release", tag);
200
- tree.__release.apply(tree.__this, tree.__args);
201
- delete tree.__release;
202
- }
203
- for (x = tree.length; x-- > 2;) {
204
- releaseTree(tree[x]);
205
- }
181
+ for (x = tree.length; x-- > 2; ) {
182
+ releaseTree(tree[x]);
206
183
  }
184
+ }
207
185
  };
208
186
  const extractEquivElements = (edits) => {
209
- let k;
210
- let val;
211
- let ek;
212
- const equiv = {};
213
- for (let i = edits.length; (i -= 3) >= 0;) {
214
- val = edits[i + 2];
215
- if (isArray(val) && (k = val[1].key) !== undefined) {
216
- ek = equiv[k];
217
- !ek && (equiv[k] = ek = [, ,]);
218
- ek[edits[i] + 1] = edits[i + 1];
219
- }
220
- }
221
- return equiv;
187
+ let k;
188
+ let val;
189
+ let ek;
190
+ const equiv2 = {};
191
+ for (let i = edits.length; (i -= 3) >= 0; ) {
192
+ val = edits[i + 2];
193
+ if (isArray(val) && (k = val[1].key) !== void 0) {
194
+ ek = equiv2[k];
195
+ !ek && (equiv2[k] = ek = [, ,]);
196
+ ek[edits[i] + 1] = edits[i + 1];
197
+ }
198
+ }
199
+ return equiv2;
222
200
  };
223
- /**
224
- * Customized version
225
- * [`equiv()`](https://docs.thi.ng/umbrella/equiv/functions/equiv.html) which
226
- * takes `__diff` attributes into account (at any nesting level). If an hdom
227
- * element's attribute object contains `__diff: false`, the object will ALWAYS
228
- * be considered unequal, even if all other attributes in the object are
229
- * equivalent.
230
- *
231
- * @param a -
232
- * @param b -
233
- *
234
- * @internal
235
- */
236
- export const equiv = (a, b) => {
237
- let proto;
238
- if (a === b) {
239
- return true;
240
- }
241
- if (a != null) {
242
- if (typeof a.equiv === FN) {
243
- return a.equiv(b);
244
- }
245
- }
246
- else {
247
- return a == b;
248
- }
249
- if (b != null) {
250
- if (typeof b.equiv === FN) {
251
- return b.equiv(a);
252
- }
253
- }
254
- else {
255
- return a == b;
256
- }
257
- if (typeof a === STR || typeof b === STR) {
258
- return false;
259
- }
260
- if (((proto = Object.getPrototypeOf(a)), proto == null || proto === OBJP) &&
261
- ((proto = Object.getPrototypeOf(b)), proto == null || proto === OBJP)) {
262
- return (!(a.__diff === false || b.__diff === false) &&
263
- equivObject(a, b, equiv));
264
- }
265
- if (typeof a !== FN &&
266
- a.length !== undefined &&
267
- typeof b !== FN &&
268
- b.length !== undefined) {
269
- return equivArrayLike(a, b, equiv);
270
- }
271
- if (a instanceof Set && b instanceof Set) {
272
- return equivSet(a, b, equiv);
273
- }
274
- if (a instanceof Map && b instanceof Map) {
275
- return equivMap(a, b, equiv);
276
- }
277
- if (a instanceof Date && b instanceof Date) {
278
- return a.getTime() === b.getTime();
279
- }
280
- if (a instanceof RegExp && b instanceof RegExp) {
281
- return a.toString() === b.toString();
282
- }
283
- // NaN
284
- return a !== a && b !== b;
201
+ const equiv = (a, b) => {
202
+ let proto;
203
+ if (a === b) {
204
+ return true;
205
+ }
206
+ if (a != null) {
207
+ if (typeof a.equiv === FN) {
208
+ return a.equiv(b);
209
+ }
210
+ } else {
211
+ return a == b;
212
+ }
213
+ if (b != null) {
214
+ if (typeof b.equiv === FN) {
215
+ return b.equiv(a);
216
+ }
217
+ } else {
218
+ return a == b;
219
+ }
220
+ if (typeof a === STR || typeof b === STR) {
221
+ return false;
222
+ }
223
+ if ((proto = Object.getPrototypeOf(a), proto == null || proto === OBJP) && (proto = Object.getPrototypeOf(b), proto == null || proto === OBJP)) {
224
+ return !(a.__diff === false || b.__diff === false) && equivObject(a, b, equiv);
225
+ }
226
+ if (typeof a !== FN && a.length !== void 0 && typeof b !== FN && b.length !== void 0) {
227
+ return equivArrayLike(a, b, equiv);
228
+ }
229
+ if (a instanceof Set && b instanceof Set) {
230
+ return equivSet(a, b, equiv);
231
+ }
232
+ if (a instanceof Map && b instanceof Map) {
233
+ return equivMap(a, b, equiv);
234
+ }
235
+ if (a instanceof Date && b instanceof Date) {
236
+ return a.getTime() === b.getTime();
237
+ }
238
+ if (a instanceof RegExp && b instanceof RegExp) {
239
+ return a.toString() === b.toString();
240
+ }
241
+ return a !== a && b !== b;
242
+ };
243
+ export {
244
+ diffAttributes,
245
+ diffTree,
246
+ equiv,
247
+ releaseTree
285
248
  };