native-document 1.0.110 → 1.0.111

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.
@@ -0,0 +1,135 @@
1
+ import { ElementCreator } from "../ElementCreator";
2
+
3
+ export const OPERATIONS = {
4
+ HYDRATE_TEXT: 1,
5
+ ATTACH_METHOD: 2,
6
+ HYDRATE_ATTRIBUTES: 3,
7
+ HYDRATE_FULL: 4,
8
+ };
9
+
10
+
11
+
12
+ const pathProcess = (target, path, data) => {
13
+ if(path.operation === OPERATIONS.HYDRATE_TEXT) {
14
+ const value = path.value;
15
+ ElementCreator.bindTextNode(target, path.isString ? data[0][value] : value.apply(null, data));
16
+ return;
17
+ }
18
+ if(path.operation === OPERATIONS.ATTACH_METHOD || path.operation === OPERATIONS.HYDRATE_FULL) {
19
+ const bindingData = path.bindingData;
20
+ for(let i = 0, length = bindingData._attachLength; i < length; i++) {
21
+ const method = bindingData.attach[i];
22
+ target.nd[method.methodName](function() {
23
+ method.fn.call(this, ...data, ...arguments);
24
+ });
25
+ }
26
+ }
27
+ if(path.operation === OPERATIONS.HYDRATE_ATTRIBUTES || path.operation === OPERATIONS.HYDRATE_FULL) {
28
+ path.hydrator(target, path.bindingData, data);
29
+ }
30
+ };
31
+
32
+ const buildAttributesCache = (bindDingData) => {
33
+ const cache = { };
34
+ if(bindDingData.attributes) cache.attributes = {};
35
+ if(bindDingData.classes) cache.class = {};
36
+ if(bindDingData.styles) cache.style = {};
37
+ bindDingData._cache = cache;
38
+ };
39
+
40
+ const prepareBindingMetadata = (bindDingData) => {
41
+ const attributes = [];
42
+ const classAndStyles = [];
43
+
44
+ if(bindDingData.attributes) {
45
+ for (const attr in bindDingData.attributes) {
46
+ attributes.push({
47
+ name: attr,
48
+ value: bindDingData.attributes[attr]
49
+ });
50
+ }
51
+ }
52
+
53
+ if(bindDingData.classes) {
54
+ for (const className in bindDingData.classes) {
55
+ bindDingData._hasClassAttribute = true;
56
+ classAndStyles.push({
57
+ name: 'class',
58
+ key: className,
59
+ value: bindDingData.classes[className]
60
+ });
61
+ }
62
+ }
63
+
64
+ if(bindDingData.styles) {
65
+ for (const property in bindDingData.styles) {
66
+ bindDingData._hasStyleAttribute = true;
67
+ classAndStyles.push({
68
+ name: 'style',
69
+ key: property,
70
+ value: bindDingData.styles[property]
71
+ });
72
+ }
73
+ }
74
+
75
+ bindDingData._flatAttributes = attributes;
76
+ bindDingData._flatAttributesLength = attributes.length;
77
+ bindDingData._flatDynamique = classAndStyles;
78
+ bindDingData._flatDynamiqueLength = classAndStyles.length;
79
+ bindDingData._attachLength = bindDingData.attach.length;
80
+ };
81
+
82
+
83
+ export const $hydrateFn = function(hydrateFunction, targetType, element, property) {
84
+ if(!cloneBindingsDataCache.has(element)) {
85
+ cloneBindingsDataCache.set(element, { attach: [] });
86
+ }
87
+ const hydrationState = cloneBindingsDataCache.get(element);
88
+
89
+ if(targetType === 'value') {
90
+ hydrationState.value = hydrateFunction;
91
+ return;
92
+ }
93
+ if(targetType === 'attach') {
94
+ hydrationState.attach = hydrationState.attach || [];
95
+ hydrationState.attach.push({ methodName: property, fn: hydrateFunction});
96
+ return;
97
+ }
98
+ hydrationState[targetType] = hydrationState[targetType] || {};
99
+ hydrationState[targetType][property] = hydrateFunction;
100
+ };
101
+
102
+ export const bindAttachMethods = (node, bindDingData, data) => {
103
+ for(let i = 0, length = bindDingData._attachLength; i < length; i++) {
104
+ const method = bindDingData.attach[i];
105
+ node.nd[method.methodName](function() {
106
+ method.fn.call(this, ...data, ...arguments);
107
+ });
108
+ }
109
+ };
110
+
111
+ export const optimizeBindingData = (bindDingData) => {
112
+ buildAttributesCache(bindDingData);
113
+ prepareBindingMetadata(bindDingData);
114
+ };
115
+
116
+
117
+ const $applyBindingParents = [];
118
+ export const hydrateClonedNode = (root, data, paths, pathSize) => {
119
+ const rootPath = paths[pathSize];
120
+ $applyBindingParents[rootPath.id] = root;
121
+ pathProcess(root, rootPath, data);
122
+
123
+ let target = null, path = null;
124
+ for(let i = 0; i < pathSize; i++) {
125
+ path = paths[i];
126
+ target = $applyBindingParents[path.parentId].childNodes[path.index];
127
+ $applyBindingParents[path.id] = target;
128
+
129
+ pathProcess(target, path, data);
130
+ }
131
+
132
+ for (let i = 0; i <= pathSize; i++) {
133
+ $applyBindingParents[i] = null;
134
+ }
135
+ };
@@ -1,376 +0,0 @@
1
- import {ElementCreator} from "./ElementCreator";
2
- import TemplateBinding from "./TemplateBinding";
3
-
4
- const cloneBindingsDataCache = new WeakMap();
5
-
6
- const OPERATIONS = {
7
- HYDRATE_TEXT: 1,
8
- ATTACH_METHOD: 2,
9
- HYDRATE_ATTRIBUTES: 3,
10
- HYDRATE_FULL: 4,
11
- };
12
-
13
- const hydrateFull = (node, bindDingData, data) => {
14
- const cacheAttributes = bindDingData._cache;
15
-
16
- for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
17
- const attr = bindDingData._flatAttributes[i];
18
- cacheAttributes[attr.name] = attr.value.apply(null, data);
19
- }
20
-
21
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
22
- const dyn = bindDingData._flatDynamique[i];
23
- cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
24
- }
25
-
26
- ElementCreator.processAttributesDirect(node, cacheAttributes);
27
- return true;
28
- };
29
-
30
- const hydrateDynamic = (node, bindDingData, data) => {
31
- const cacheAttributes = bindDingData._cache;
32
-
33
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
34
- const dyn = bindDingData._flatDynamique[i];
35
- cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
36
- }
37
-
38
- ElementCreator.processClassAttribute(node, cacheAttributes.class);
39
- ElementCreator.processStyleAttribute(node, cacheAttributes.style);
40
- return true;
41
- };
42
-
43
- const hydrateClassAttribute = (node, bindDingData, data) => {
44
- const classAttributes = bindDingData._cache.class;
45
-
46
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
47
- const dyn = bindDingData._flatDynamique[i];
48
- classAttributes[dyn.key] = dyn.value.apply(null, data);
49
- }
50
-
51
- ElementCreator.processClassAttribute(node, classAttributes);
52
- return true;
53
- };
54
-
55
- const hydrateStyleAttribute = (node, bindDingData, data) => {
56
- const styleAttributes = bindDingData._cache;
57
-
58
- for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
59
- const dyn = bindDingData._flatDynamique[i];
60
- styleAttributes[dyn.key] = dyn.value.apply(null, data);
61
- }
62
-
63
- ElementCreator.processStyleAttribute(node, styleAttributes);
64
- return true;
65
- };
66
-
67
- const hydrateAttributes = (node, bindDingData, data) => {
68
- const cacheAttributes = bindDingData._cache;
69
-
70
- for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
71
- const attr = bindDingData._flatAttributes[i];
72
- cacheAttributes[attr.name] = attr.value.apply(null, data);
73
- }
74
-
75
- ElementCreator.processAttributesDirect(node, cacheAttributes);
76
- return true;
77
- };
78
-
79
- const getHydrator = (bindDingData) => {
80
- if(!bindDingData._cache) {
81
- return noUpdate;
82
- }
83
- if(bindDingData._flatAttributesLength && bindDingData._flatDynamiqueLength) {
84
- return hydrateFull;
85
- }
86
- if(bindDingData._flatAttributesLength) {
87
- return hydrateAttributes;
88
- }
89
- if(bindDingData._hasClassAttribute && bindDingData._hasStyleAttribute) {
90
- return hydrateDynamic;
91
- }
92
- if(bindDingData._hasClassAttribute) {
93
- return hydrateClassAttribute;
94
- }
95
- return hydrateStyleAttribute;
96
- };
97
-
98
- const $hydrateFn = function(hydrateFunction, targetType, element, property) {
99
- if(!cloneBindingsDataCache.has(element)) {
100
- cloneBindingsDataCache.set(element, { attach: [] });
101
- }
102
- const hydrationState = cloneBindingsDataCache.get(element);
103
-
104
- if(targetType === 'value') {
105
- hydrationState.value = hydrateFunction;
106
- return;
107
- }
108
- if(targetType === 'attach') {
109
- hydrationState.attach = hydrationState.attach || [];
110
- hydrationState.attach.push({ methodName: property, fn: hydrateFunction});
111
- return;
112
- }
113
- hydrationState[targetType] = hydrationState[targetType] || {};
114
- hydrationState[targetType][property] = hydrateFunction;
115
- };
116
-
117
- const bindAttachMethods = (node, bindDingData, data) => {
118
- for(let i = 0, length = bindDingData._attachLength; i < length; i++) {
119
- const method = bindDingData.attach[i];
120
- node.nd[method.methodName](function() {
121
- method.fn.call(this, ...data, ...arguments);
122
- });
123
- }
124
- };
125
-
126
-
127
- const $applyBindingParents = [];
128
- const pathProcess = (target, path, data) => {
129
- if(path.operation === OPERATIONS.HYDRATE_TEXT) {
130
- const value = path.value;
131
- ElementCreator.bindTextNode(target, path.isString ? data[0][value] : value.apply(null, data));
132
- return;
133
- }
134
- if(path.operation === OPERATIONS.ATTACH_METHOD || path.operation === OPERATIONS.HYDRATE_FULL) {
135
- const bindingData = path.bindingData;
136
- for(let i = 0, length = bindingData._attachLength; i < length; i++) {
137
- const method = bindingData.attach[i];
138
- target.nd[method.methodName](function() {
139
- method.fn.call(this, ...data, ...arguments);
140
- });
141
- }
142
- }
143
- if(path.operation === OPERATIONS.HYDRATE_ATTRIBUTES || path.operation === OPERATIONS.HYDRATE_FULL) {
144
- path.hydrator(target, path.bindingData, data);
145
- }
146
- };
147
-
148
- const applyBindingTreePath = (root, data, paths, pathSize) => {
149
- const rootPath = paths[pathSize];
150
- $applyBindingParents[rootPath.id] = root;
151
- pathProcess(root, rootPath, data);
152
-
153
- let target = null, path = null;
154
- for(let i = 0; i < pathSize; i++) {
155
- path = paths[i];
156
- target = $applyBindingParents[path.parentId].childNodes[path.index];
157
- $applyBindingParents[path.id] = target;
158
-
159
- pathProcess(target, path, data);
160
- }
161
-
162
- for (let i = 0; i <= pathSize; i++) {
163
- $applyBindingParents[i] = null;
164
- }
165
- };
166
- const buildAttributesCache = (bindDingData) => {
167
- const cache = { };
168
- if(bindDingData.attributes) cache.attributes = {};
169
- if(bindDingData.classes) cache.class = {};
170
- if(bindDingData.styles) cache.style = {};
171
- bindDingData._cache = cache;
172
- };
173
-
174
- const prepareBindingMetadata = (bindDingData) => {
175
- const attributes = [];
176
- const classAndStyles = [];
177
-
178
- if(bindDingData.attributes) {
179
- for (const attr in bindDingData.attributes) {
180
- attributes.push({
181
- name: attr,
182
- value: bindDingData.attributes[attr]
183
- });
184
- }
185
- }
186
-
187
- if(bindDingData.classes) {
188
- for (const className in bindDingData.classes) {
189
- bindDingData._hasClassAttribute = true;
190
- classAndStyles.push({
191
- name: 'class',
192
- key: className,
193
- value: bindDingData.classes[className]
194
- });
195
- }
196
- }
197
-
198
- if(bindDingData.styles) {
199
- for (const property in bindDingData.styles) {
200
- bindDingData._hasStyleAttribute = true;
201
- classAndStyles.push({
202
- name: 'style',
203
- key: property,
204
- value: bindDingData.styles[property]
205
- });
206
- }
207
- }
208
-
209
- bindDingData._flatAttributes = attributes;
210
- bindDingData._flatAttributesLength = attributes.length;
211
- bindDingData._flatDynamique = classAndStyles;
212
- bindDingData._flatDynamiqueLength = classAndStyles.length;
213
- bindDingData._attachLength = bindDingData.attach.length;
214
- };
215
-
216
- const optimizeBindingData = (bindDingData) => {
217
- buildAttributesCache(bindDingData);
218
- prepareBindingMetadata(bindDingData);
219
- };
220
-
221
- const noUpdate = () => {};
222
- export function TemplateCloner($fn) {
223
- let $node = null;
224
- let $hasBindingData = false;
225
-
226
- let $bindingTreePathSize = 0;
227
- const $bindingTreePath = [
228
- {
229
- id: 0,
230
- parentId: null
231
- }
232
- ];
233
-
234
- let pathCounter = 0;
235
- const clone = (node, data, currentPath) => {
236
- const bindDingData = cloneBindingsDataCache.get(node);
237
- if(bindDingData) {
238
- optimizeBindingData(bindDingData);
239
- }
240
- if(node.nodeType === 3) {
241
- if(bindDingData && bindDingData.value) {
242
- const value = bindDingData.value;
243
- const textNode = node.cloneNode();
244
- currentPath.value = value;
245
- currentPath.operation = OPERATIONS.HYDRATE_TEXT;
246
- currentPath.isString = (typeof value === 'string');
247
- ElementCreator.bindTextNode(textNode, (currentPath.isString ? data[0][value] : value.apply(null, data)));
248
- return textNode;
249
- }
250
- return node.cloneNode(true);
251
- }
252
- const nodeCloned = node.cloneNode();
253
- if(bindDingData) {
254
- const hydrator = getHydrator(bindDingData);
255
- hydrator(nodeCloned, bindDingData, data);
256
- bindAttachMethods(nodeCloned, bindDingData, data);
257
-
258
- const hasAttributes = bindDingData.classes || bindDingData.styles || bindDingData.attributes;
259
- const hasAttachMethods = bindDingData.attach.length;
260
-
261
- currentPath.bindingData = bindDingData;
262
- currentPath.hydrator = hydrator;
263
-
264
- if(hasAttributes && hasAttachMethods) {
265
- currentPath.operation = OPERATIONS.HYDRATE_FULL;
266
- }
267
- else if(hasAttributes) {
268
- currentPath.operation = OPERATIONS.HYDRATE_ATTRIBUTES;
269
- }
270
- else if(hasAttachMethods) {
271
- currentPath.operation = OPERATIONS.ATTACH_METHOD;
272
- }
273
- }
274
- const childNodes = node.childNodes;
275
- const parentId = currentPath.id;
276
-
277
- for(let i = 0, length = childNodes.length; i < length; i++) {
278
- const childNode = childNodes[i];
279
- const path = { parentId, id: ++pathCounter, index: i };
280
- const childNodeCloned = clone(childNode, data, path);
281
- if(path.hasChildren || path.operation) {
282
- $bindingTreePath.push(path);
283
- currentPath.hasChildren = true;
284
- }
285
- nodeCloned.appendChild(childNodeCloned);
286
- }
287
- return nodeCloned;
288
- };
289
-
290
- const cloneWithBindingPaths = (data) => {
291
- let root = $node.cloneNode(true);
292
-
293
- applyBindingTreePath(root, data, $bindingTreePath, $bindingTreePathSize);
294
- return root;
295
- };
296
-
297
- this.clone = (data) => {
298
- const binder = createTemplateCloner(this);
299
- $node = $fn(binder);
300
- if(!$hasBindingData) {
301
- this.clone = () => $node.cloneNode(true);
302
- return $node.cloneNode(true);
303
- }
304
-
305
- const firstClone = clone($node, data, $bindingTreePath[0]);
306
- $bindingTreePath.reverse();
307
- $bindingTreePathSize = $bindingTreePath.length - 1;
308
-
309
- this.clone = cloneWithBindingPaths;
310
- return firstClone;
311
- };
312
-
313
-
314
- const createBinding = (hydrateFunction, targetType) => {
315
- return new TemplateBinding((element, property) => {
316
- $hasBindingData = true;
317
- $hydrateFn(hydrateFunction, targetType, element, property)
318
- });
319
- };
320
-
321
- this.style = (fn) => {
322
- return createBinding(fn, 'styles');
323
- };
324
- this.class = (fn) => {
325
- return createBinding(fn, 'classes');
326
- };
327
- this.property = (propertyName) => {
328
- return this.value(propertyName);
329
- }
330
- this.value = (callbackOrProperty) => {
331
- return createBinding(callbackOrProperty, 'value');
332
- };
333
- this.text = this.value;
334
- this.attr = (fn) => {
335
- return createBinding(fn, 'attributes');
336
- };
337
- this.attach = (fn) => {
338
- return createBinding(fn, 'attach');
339
- };
340
- this.callback = this.attach;
341
-
342
- }
343
-
344
- function createTemplateCloner($binder) {
345
- return new Proxy($binder, {
346
- get(target, prop) {
347
- if(prop in target) {
348
- return target[prop];
349
- }
350
- if (typeof prop === 'symbol') return target[prop];
351
- return target.value(prop);
352
- }
353
- });
354
- }
355
-
356
- export function useCache(fn) {
357
- let $cache = null;
358
-
359
- let wrapper = function(args) {
360
- $cache = new TemplateCloner(fn);
361
-
362
- wrapper = function(args) {
363
- return $cache.clone(args);
364
- };
365
- return $cache.clone(args);
366
- };
367
-
368
- if(fn.length < 2) {
369
- return function(...args) {
370
- return wrapper(args);
371
- };
372
- }
373
- return function(_, __, ...args) {
374
- return wrapper([_, __, ...args]);
375
- };
376
- }