spikijs 1.0.6 → 1.0.7
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/README.md +1 -1
- package/package.json +11 -1
- package/spiki.esm.js +394 -285
- package/spiki.esm.min.js +1 -1
- package/spiki.js +393 -284
- package/spiki.min.js +1 -1
package/spiki.esm.js
CHANGED
|
@@ -1,457 +1,566 @@
|
|
|
1
|
-
var spiki = (
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
var spiki = (() => {
|
|
2
|
+
// --- State & Storage ---
|
|
3
|
+
var componentRegistry = Object.create(null);
|
|
4
|
+
var eventMetadataMap = new WeakMap();
|
|
5
|
+
var dependencyMap = new WeakMap();
|
|
6
|
+
var proxyCache = new WeakMap();
|
|
7
|
+
var pathSplitCache = new Map();
|
|
8
|
+
var schedulerQueue = new Set();
|
|
9
|
+
|
|
10
|
+
var loopRegex = /^\s*(.*?)\s+in\s+(.+)\s*$/;
|
|
11
|
+
|
|
12
|
+
// --- Global State Variables ---
|
|
13
|
+
var currentActiveEffect;
|
|
14
|
+
var isFlushingQueue;
|
|
15
|
+
var globalStore;
|
|
16
|
+
var shouldTriggerEffects = true;
|
|
17
|
+
var resolvedPromise = Promise.resolve();
|
|
18
|
+
|
|
19
|
+
// -------------------------------------------------------------------------
|
|
14
20
|
// 1. Array Interceptors
|
|
21
|
+
// -------------------------------------------------------------------------
|
|
15
22
|
var arrayInstrumentations = {};
|
|
16
|
-
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(
|
|
17
|
-
arrayInstrumentations[
|
|
23
|
+
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(methodName => {
|
|
24
|
+
arrayInstrumentations[methodName] = function () {
|
|
18
25
|
var args = [];
|
|
19
|
-
for (var
|
|
20
|
-
args[
|
|
26
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
27
|
+
args[i] = arguments[i];
|
|
21
28
|
}
|
|
22
|
-
|
|
29
|
+
|
|
30
|
+
shouldTriggerEffects = false;
|
|
23
31
|
try {
|
|
24
|
-
var
|
|
25
|
-
return
|
|
32
|
+
var result = Array.prototype[methodName].apply(this, args);
|
|
33
|
+
return result;
|
|
26
34
|
} finally {
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
shouldTriggerEffects = true;
|
|
36
|
+
triggerDependency(this, 'length');
|
|
29
37
|
}
|
|
30
38
|
};
|
|
31
39
|
});
|
|
32
40
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
// -------------------------------------------------------------------------
|
|
42
|
+
// 2. Helper Functions
|
|
43
|
+
// -------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
var createScope = (parentScope) => {
|
|
46
|
+
var proto = Object.create(parentScope);
|
|
36
47
|
return new Proxy(proto, {
|
|
37
|
-
set:
|
|
38
|
-
if (target.hasOwnProperty(key))
|
|
48
|
+
set: (target, key, value, receiver) => {
|
|
49
|
+
if (target.hasOwnProperty(key)) {
|
|
50
|
+
return Reflect.set(target, key, value, receiver);
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
var cursor = target;
|
|
40
54
|
while (cursor && !Object.prototype.hasOwnProperty.call(cursor, key)) {
|
|
41
55
|
cursor = Object.getPrototypeOf(cursor);
|
|
42
56
|
}
|
|
57
|
+
|
|
43
58
|
return Reflect.set(cursor || target, key, value);
|
|
44
59
|
}
|
|
45
60
|
});
|
|
46
61
|
};
|
|
47
62
|
|
|
48
|
-
var
|
|
49
|
-
if (typeof path !== 'string') return {
|
|
63
|
+
var evaluatePath = (scope, path) => {
|
|
64
|
+
if (typeof path !== 'string') return { value: path, context: scope };
|
|
50
65
|
|
|
51
66
|
if (path.indexOf('.') === -1) {
|
|
52
|
-
return {
|
|
67
|
+
return { value: scope ? scope[path] : undefined, context: scope };
|
|
53
68
|
}
|
|
54
69
|
|
|
55
|
-
var parts =
|
|
70
|
+
var parts = pathSplitCache.get(path);
|
|
56
71
|
if (!parts) {
|
|
57
|
-
if (
|
|
72
|
+
if (pathSplitCache.size > 1000) pathSplitCache.clear();
|
|
58
73
|
parts = path.split('.');
|
|
59
|
-
|
|
74
|
+
pathSplitCache.set(path, parts);
|
|
60
75
|
}
|
|
61
76
|
|
|
62
|
-
var
|
|
77
|
+
var currentValue = scope;
|
|
78
|
+
var currentContext = scope;
|
|
79
|
+
|
|
63
80
|
for (var i = 0; i < parts.length; i++) {
|
|
64
81
|
var part = parts[i];
|
|
65
|
-
if (
|
|
66
|
-
return {
|
|
82
|
+
if (currentValue == null) {
|
|
83
|
+
return { value: currentValue, context: null };
|
|
67
84
|
}
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
currentContext = currentValue;
|
|
86
|
+
currentValue = currentValue[part];
|
|
70
87
|
}
|
|
71
|
-
return {
|
|
88
|
+
return { value: currentValue, context: currentContext };
|
|
72
89
|
};
|
|
73
90
|
|
|
74
|
-
var nextTick =
|
|
75
|
-
return !
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
var nextTick = (fn) => {
|
|
92
|
+
return !schedulerQueue.has(fn) &&
|
|
93
|
+
schedulerQueue.add(fn) &&
|
|
94
|
+
!isFlushingQueue &&
|
|
95
|
+
(isFlushingQueue = true) &&
|
|
96
|
+
resolvedPromise.then(() => {
|
|
97
|
+
schedulerQueue.forEach(job => job());
|
|
98
|
+
schedulerQueue.clear();
|
|
99
|
+
isFlushingQueue = false;
|
|
100
|
+
});
|
|
81
101
|
};
|
|
82
102
|
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
// 3. Reactivity System
|
|
105
|
+
// -------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
var trackDependency = (target, key) => {
|
|
108
|
+
if (!currentActiveEffect) return;
|
|
109
|
+
|
|
110
|
+
var depsMap = dependencyMap.get(target);
|
|
111
|
+
if (!depsMap) {
|
|
112
|
+
depsMap = new Map();
|
|
113
|
+
dependencyMap.set(target, depsMap);
|
|
90
114
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
115
|
+
|
|
116
|
+
var depSet = depsMap.get(key);
|
|
117
|
+
if (!depSet) {
|
|
118
|
+
depSet = new Set();
|
|
119
|
+
depsMap.set(key, depSet);
|
|
95
120
|
}
|
|
96
|
-
|
|
97
|
-
|
|
121
|
+
|
|
122
|
+
depSet.add(currentActiveEffect);
|
|
123
|
+
currentActiveEffect.dependencies.add(depSet);
|
|
98
124
|
};
|
|
99
125
|
|
|
100
|
-
var
|
|
101
|
-
var depsMap,
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
|
|
126
|
+
var triggerDependency = (target, key) => {
|
|
127
|
+
var depsMap, depSet;
|
|
128
|
+
if (shouldTriggerEffects && (depsMap = dependencyMap.get(target)) && (depSet = depsMap.get(key))) {
|
|
129
|
+
depSet.forEach(effectFn => {
|
|
130
|
+
effectFn.scheduler ? effectFn.scheduler(effectFn) : effectFn();
|
|
105
131
|
});
|
|
106
132
|
}
|
|
107
133
|
};
|
|
108
134
|
|
|
109
|
-
var
|
|
110
|
-
var runner =
|
|
111
|
-
runner.
|
|
112
|
-
runner.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
135
|
+
var createEffect = (fn, scheduler) => {
|
|
136
|
+
var runner = () => {
|
|
137
|
+
runner.dependencies.forEach(depSet => depSet.delete(runner));
|
|
138
|
+
runner.dependencies.clear();
|
|
139
|
+
|
|
140
|
+
var previousEffect = currentActiveEffect;
|
|
141
|
+
currentActiveEffect = runner;
|
|
142
|
+
try {
|
|
143
|
+
fn();
|
|
144
|
+
} finally {
|
|
145
|
+
currentActiveEffect = previousEffect;
|
|
146
|
+
}
|
|
116
147
|
};
|
|
117
|
-
|
|
118
|
-
runner.
|
|
148
|
+
|
|
149
|
+
runner.dependencies = new Set();
|
|
150
|
+
runner.scheduler = scheduler;
|
|
119
151
|
runner();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
runner.
|
|
123
|
-
|
|
152
|
+
|
|
153
|
+
return () => {
|
|
154
|
+
runner.dependencies.forEach(depSet => depSet.delete(runner));
|
|
155
|
+
runner.dependencies.clear();
|
|
156
|
+
schedulerQueue.delete(runner);
|
|
124
157
|
};
|
|
125
158
|
};
|
|
126
159
|
|
|
127
|
-
var
|
|
128
|
-
if (!obj || typeof obj !== 'object' || obj.
|
|
129
|
-
|
|
130
|
-
|
|
160
|
+
var makeReactive = (obj) => {
|
|
161
|
+
if (!obj || typeof obj !== 'object' || obj.__isProxy || obj instanceof Node) return obj;
|
|
162
|
+
|
|
163
|
+
var existingProxy = proxyCache.get(obj);
|
|
164
|
+
if (existingProxy) return existingProxy;
|
|
131
165
|
|
|
132
166
|
var proxy = new Proxy(obj, {
|
|
133
|
-
get:
|
|
134
|
-
if (
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
167
|
+
get: (target, key, receiver) => {
|
|
168
|
+
if (key === '__raw') return target;
|
|
169
|
+
if (key === '__isProxy') return true;
|
|
170
|
+
|
|
171
|
+
if (Array.isArray(target) && arrayInstrumentations.hasOwnProperty(key)) {
|
|
172
|
+
return arrayInstrumentations[key];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
trackDependency(target, key);
|
|
176
|
+
|
|
177
|
+
var result = Reflect.get(target, key, receiver);
|
|
178
|
+
return result && typeof result === 'object' && !(result instanceof Node)
|
|
179
|
+
? makeReactive(result)
|
|
180
|
+
: result;
|
|
139
181
|
},
|
|
140
|
-
set:
|
|
141
|
-
var
|
|
142
|
-
var hadKey = Array.isArray(
|
|
143
|
-
|
|
144
|
-
|
|
182
|
+
set: (target, key, value, receiver) => {
|
|
183
|
+
var oldValue = target[key];
|
|
184
|
+
var hadKey = Array.isArray(target)
|
|
185
|
+
? Number(key) < target.length
|
|
186
|
+
: Object.prototype.hasOwnProperty.call(target, key);
|
|
187
|
+
|
|
188
|
+
var result = Reflect.set(target, key, value, receiver);
|
|
189
|
+
|
|
190
|
+
if (shouldTriggerEffects) {
|
|
145
191
|
if (!hadKey) {
|
|
146
|
-
|
|
147
|
-
if (Array.isArray(
|
|
148
|
-
} else if (
|
|
149
|
-
|
|
192
|
+
triggerDependency(target, key);
|
|
193
|
+
if (Array.isArray(target)) triggerDependency(target, 'length');
|
|
194
|
+
} else if (oldValue !== value) {
|
|
195
|
+
triggerDependency(target, key);
|
|
150
196
|
}
|
|
151
197
|
}
|
|
152
|
-
return
|
|
198
|
+
return result;
|
|
153
199
|
},
|
|
154
|
-
deleteProperty:
|
|
155
|
-
var hadKey = Object.prototype.hasOwnProperty.call(
|
|
156
|
-
var
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
if (Array.isArray(
|
|
200
|
+
deleteProperty: (target, key) => {
|
|
201
|
+
var hadKey = Object.prototype.hasOwnProperty.call(target, key);
|
|
202
|
+
var result = Reflect.deleteProperty(target, key);
|
|
203
|
+
if (result && hadKey) {
|
|
204
|
+
triggerDependency(target, key);
|
|
205
|
+
if (Array.isArray(target)) triggerDependency(target, 'length');
|
|
160
206
|
}
|
|
161
|
-
return
|
|
207
|
+
return result;
|
|
162
208
|
}
|
|
163
209
|
});
|
|
164
|
-
|
|
210
|
+
|
|
211
|
+
proxyCache.set(obj, proxy);
|
|
165
212
|
return proxy;
|
|
166
213
|
};
|
|
167
214
|
|
|
168
|
-
globalStore =
|
|
215
|
+
globalStore = makeReactive({});
|
|
169
216
|
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
217
|
+
// -------------------------------------------------------------------------
|
|
218
|
+
// 4. DOM Operations
|
|
219
|
+
// -------------------------------------------------------------------------
|
|
220
|
+
var domOperations = {
|
|
221
|
+
text: (el, value) => {
|
|
222
|
+
el.textContent = (value !== null && value !== undefined) ? value : '';
|
|
223
|
+
},
|
|
224
|
+
html: (el, value) => {
|
|
225
|
+
el.innerHTML = (value !== null && value !== undefined) ? value : '';
|
|
226
|
+
},
|
|
227
|
+
value: (el, value) => {
|
|
175
228
|
if (el.type === 'checkbox') {
|
|
176
|
-
el.checked = !!
|
|
229
|
+
el.checked = !!value;
|
|
177
230
|
} else if (el.type === 'radio' && el.name) {
|
|
178
|
-
el.checked = el.value ==
|
|
231
|
+
el.checked = el.value == value;
|
|
179
232
|
} else {
|
|
180
|
-
if (el.value !=
|
|
233
|
+
if (el.value != value) {
|
|
234
|
+
el.value = (value !== null && value !== undefined) ? value : '';
|
|
235
|
+
}
|
|
181
236
|
}
|
|
182
237
|
},
|
|
183
|
-
attr:
|
|
184
|
-
(
|
|
238
|
+
attr: (el, value, attributeName) => {
|
|
239
|
+
(value == null || value === false)
|
|
240
|
+
? el.removeAttribute(attributeName)
|
|
241
|
+
: el.setAttribute(attributeName, value === true ? '' : value);
|
|
185
242
|
},
|
|
186
|
-
class:
|
|
187
|
-
if (typeof
|
|
188
|
-
|
|
189
|
-
if (
|
|
243
|
+
class: (el, value) => {
|
|
244
|
+
if (typeof value === 'string') {
|
|
245
|
+
value.split(/\s+/).forEach(cls => {
|
|
246
|
+
if (cls) {
|
|
247
|
+
var isNegative = cls[0] === '!';
|
|
248
|
+
var className = isNegative ? cls.slice(1) : cls;
|
|
249
|
+
el.classList[isNegative ? 'remove' : 'add'](className);
|
|
250
|
+
}
|
|
190
251
|
});
|
|
191
252
|
}
|
|
192
253
|
},
|
|
193
|
-
init:
|
|
194
|
-
destroy:
|
|
254
|
+
init: () => { },
|
|
255
|
+
destroy: () => { }
|
|
195
256
|
};
|
|
196
257
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
258
|
+
// -------------------------------------------------------------------------
|
|
259
|
+
// 5. Engine / Mounting Logic
|
|
260
|
+
// -------------------------------------------------------------------------
|
|
261
|
+
var mountComponent = (rootElement) => {
|
|
262
|
+
if (rootElement.__isMounted) return;
|
|
263
|
+
rootElement.__isMounted = 1;
|
|
264
|
+
|
|
265
|
+
var componentName = rootElement.getAttribute('s-data');
|
|
266
|
+
var componentFactory = componentRegistry[componentName];
|
|
267
|
+
if (!componentFactory) return;
|
|
203
268
|
|
|
204
|
-
var state =
|
|
269
|
+
var state = makeReactive(componentFactory());
|
|
205
270
|
state.$refs = {};
|
|
206
|
-
state.$root =
|
|
271
|
+
state.$root = rootElement;
|
|
207
272
|
state.$store = globalStore;
|
|
208
273
|
|
|
209
|
-
var
|
|
274
|
+
var cleanupCallbacks = [];
|
|
210
275
|
|
|
211
|
-
var handleEvent =
|
|
212
|
-
var
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
var
|
|
216
|
-
var
|
|
217
|
-
var
|
|
276
|
+
var handleEvent = (e) => {
|
|
277
|
+
var target = e.target;
|
|
278
|
+
|
|
279
|
+
if (target.__modelPath && (e.type === 'input' || e.type === 'change')) {
|
|
280
|
+
var path = target.__modelPath;
|
|
281
|
+
var value = target.type === 'checkbox' ? target.checked : target.value;
|
|
282
|
+
var evaluation = evaluatePath(target.__scope || state, path);
|
|
283
|
+
var parentObject = evaluation.context;
|
|
218
284
|
|
|
219
285
|
if (path.indexOf('.') === -1) {
|
|
220
|
-
(
|
|
221
|
-
} else if (
|
|
286
|
+
(target.__scope || state)[path] = value;
|
|
287
|
+
} else if (parentObject) {
|
|
222
288
|
var parts = path.split('.');
|
|
223
|
-
|
|
289
|
+
parentObject[parts[parts.length - 1]] = value;
|
|
224
290
|
}
|
|
225
291
|
}
|
|
226
292
|
|
|
227
|
-
var
|
|
228
|
-
while (
|
|
229
|
-
var meta =
|
|
230
|
-
if (meta && (
|
|
231
|
-
var
|
|
232
|
-
var
|
|
233
|
-
var
|
|
234
|
-
|
|
293
|
+
var handlerName;
|
|
294
|
+
while (target && target !== rootElement.parentNode) {
|
|
295
|
+
var meta = eventMetadataMap.get(target);
|
|
296
|
+
if (meta && (handlerName = meta[e.type])) {
|
|
297
|
+
var evalResult = evaluatePath(target.__scope || state, handlerName);
|
|
298
|
+
var handlerFn = evalResult.value;
|
|
299
|
+
var handlerContext = evalResult.context;
|
|
300
|
+
|
|
301
|
+
if (typeof handlerFn === 'function') {
|
|
302
|
+
handlerFn.call(handlerContext, e);
|
|
303
|
+
}
|
|
235
304
|
}
|
|
236
|
-
|
|
305
|
+
target = target.parentNode;
|
|
237
306
|
}
|
|
238
307
|
};
|
|
239
308
|
|
|
240
|
-
var
|
|
309
|
+
var walkDOM = (el, currentScope, cleanupList) => {
|
|
241
310
|
if (el.nodeType !== 1 || el.hasAttribute('s-ignore')) return;
|
|
242
311
|
|
|
243
|
-
if (el !==
|
|
244
|
-
var
|
|
245
|
-
if (
|
|
312
|
+
if (el !== rootElement && el.hasAttribute('s-data')) {
|
|
313
|
+
var childComponent = mountComponent(el);
|
|
314
|
+
if (childComponent) cleanupList.push(childComponent.unmount);
|
|
246
315
|
return;
|
|
247
316
|
}
|
|
248
317
|
|
|
249
|
-
var
|
|
250
|
-
|
|
318
|
+
var attributeValue;
|
|
319
|
+
|
|
320
|
+
if ((attributeValue = el.getAttribute('s-if'))) {
|
|
251
321
|
var anchor = document.createTextNode('');
|
|
252
|
-
var
|
|
322
|
+
var branchCleanups = [];
|
|
253
323
|
el.replaceWith(anchor);
|
|
254
|
-
var
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
var
|
|
262
|
-
var
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
324
|
+
var activeNode;
|
|
325
|
+
|
|
326
|
+
cleanupList.push(() => {
|
|
327
|
+
branchCleanups.forEach(cb => cb());
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
return cleanupList.push(createEffect(() => {
|
|
331
|
+
var evaluation = evaluatePath(currentScope, attributeValue);
|
|
332
|
+
var result = evaluation.value;
|
|
333
|
+
var context = evaluation.context;
|
|
334
|
+
|
|
335
|
+
var isTruthy = typeof result === 'function' ? result.call(context, el) : result;
|
|
336
|
+
|
|
337
|
+
if (isTruthy) {
|
|
338
|
+
if (!activeNode) {
|
|
339
|
+
activeNode = el.cloneNode(true);
|
|
340
|
+
activeNode.removeAttribute('s-if');
|
|
341
|
+
walkDOM(activeNode, currentScope, branchCleanups);
|
|
342
|
+
anchor.parentNode.insertBefore(activeNode, anchor);
|
|
270
343
|
}
|
|
271
|
-
} else if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
344
|
+
} else if (activeNode) {
|
|
345
|
+
branchCleanups.forEach(cb => cb());
|
|
346
|
+
branchCleanups.length = 0;
|
|
347
|
+
activeNode.remove();
|
|
348
|
+
activeNode = null;
|
|
276
349
|
}
|
|
277
350
|
}, nextTick));
|
|
278
351
|
}
|
|
279
352
|
|
|
280
|
-
if (el.tagName === 'TEMPLATE' && (
|
|
281
|
-
var match =
|
|
353
|
+
if (el.tagName === 'TEMPLATE' && (attributeValue = el.getAttribute('s-for'))) {
|
|
354
|
+
var match = attributeValue.match(loopRegex);
|
|
282
355
|
if (!match) return;
|
|
283
|
-
|
|
356
|
+
|
|
357
|
+
var leftHandSide = match[1].replace(/[()]/g, '');
|
|
284
358
|
var listKey = match[2];
|
|
285
|
-
var splitLhs =
|
|
286
|
-
var
|
|
287
|
-
var
|
|
288
|
-
|
|
289
|
-
var
|
|
290
|
-
var
|
|
291
|
-
el.replaceWith(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
359
|
+
var splitLhs = leftHandSide.split(',');
|
|
360
|
+
var itemAlias = splitLhs[0].trim();
|
|
361
|
+
var indexAlias = splitLhs[1] ? splitLhs[1].trim() : null;
|
|
362
|
+
|
|
363
|
+
var keyAttribute = el.getAttribute('s-key');
|
|
364
|
+
var anchorForLoop = document.createTextNode('');
|
|
365
|
+
el.replaceWith(anchorForLoop);
|
|
366
|
+
|
|
367
|
+
var nodePool = new Map();
|
|
368
|
+
|
|
369
|
+
cleanupList.push(() => {
|
|
370
|
+
nodePool.forEach(row => {
|
|
371
|
+
row.cleanups.forEach(cb => cb());
|
|
297
372
|
});
|
|
298
373
|
});
|
|
299
374
|
|
|
300
|
-
return
|
|
301
|
-
var
|
|
302
|
-
var rawItems =
|
|
375
|
+
return cleanupList.push(createEffect(() => {
|
|
376
|
+
var evaluation = evaluatePath(currentScope, listKey);
|
|
377
|
+
var rawItems = evaluation.value;
|
|
303
378
|
var items = rawItems;
|
|
304
|
-
|
|
379
|
+
|
|
380
|
+
if (Array.isArray(items)) trackDependency(items, 'length');
|
|
305
381
|
|
|
306
|
-
var
|
|
382
|
+
var domCursor = anchorForLoop;
|
|
307
383
|
var iterable = Array.isArray(items) ? items : items ? Object.keys(items) : [];
|
|
308
|
-
var
|
|
384
|
+
var nextNodePool = new Map();
|
|
309
385
|
|
|
310
|
-
iterable.forEach(
|
|
311
|
-
var key = Array.isArray(items) ?
|
|
312
|
-
var
|
|
386
|
+
iterable.forEach((rawItem, index) => {
|
|
387
|
+
var key = Array.isArray(items) ? index : rawItem;
|
|
388
|
+
var itemValue = Array.isArray(items) ? rawItem : items[rawItem];
|
|
313
389
|
|
|
314
|
-
var
|
|
315
|
-
if (
|
|
316
|
-
else
|
|
390
|
+
var rowUniqueKey;
|
|
391
|
+
if (keyAttribute && itemValue) rowUniqueKey = itemValue[keyAttribute];
|
|
392
|
+
else rowUniqueKey = (typeof itemValue === 'object' && itemValue)
|
|
393
|
+
? itemValue
|
|
394
|
+
: key + '_' + itemValue;
|
|
317
395
|
|
|
318
|
-
var row =
|
|
396
|
+
var row = nodePool.get(rowUniqueKey);
|
|
319
397
|
|
|
320
|
-
var defineAlias =
|
|
321
|
-
Object.defineProperty(targetObj,
|
|
398
|
+
var defineAlias = (targetObj) => {
|
|
399
|
+
Object.defineProperty(targetObj, itemAlias, {
|
|
322
400
|
configurable: true, enumerable: true,
|
|
323
|
-
get:
|
|
324
|
-
set:
|
|
401
|
+
get: () => items[key],
|
|
402
|
+
set: (v) => { items[key] = v; }
|
|
325
403
|
});
|
|
326
404
|
};
|
|
327
405
|
|
|
328
406
|
if (!row) {
|
|
329
407
|
var clone = el.content.cloneNode(true);
|
|
330
|
-
var
|
|
331
|
-
var
|
|
332
|
-
|
|
333
|
-
defineAlias(
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
var
|
|
337
|
-
var
|
|
338
|
-
while (
|
|
339
|
-
|
|
340
|
-
var
|
|
341
|
-
|
|
342
|
-
|
|
408
|
+
var rowScope = createScope(currentScope);
|
|
409
|
+
var rowCleanups = [];
|
|
410
|
+
|
|
411
|
+
defineAlias(rowScope);
|
|
412
|
+
if (indexAlias) rowScope[indexAlias] = key;
|
|
413
|
+
|
|
414
|
+
var rowNodes = [];
|
|
415
|
+
var childNode = clone.firstChild;
|
|
416
|
+
while (childNode) {
|
|
417
|
+
rowNodes.push(childNode);
|
|
418
|
+
var nextSibling = childNode.nextSibling;
|
|
419
|
+
walkDOM(childNode, rowScope, rowCleanups);
|
|
420
|
+
childNode = nextSibling;
|
|
343
421
|
}
|
|
344
|
-
row = {
|
|
422
|
+
row = { nodes: rowNodes, scope: rowScope, cleanups: rowCleanups };
|
|
345
423
|
} else {
|
|
346
|
-
defineAlias(row.
|
|
347
|
-
if (
|
|
424
|
+
defineAlias(row.scope);
|
|
425
|
+
if (indexAlias) row.scope[indexAlias] = key;
|
|
348
426
|
}
|
|
349
427
|
|
|
350
|
-
if (row.
|
|
351
|
-
var
|
|
352
|
-
row.
|
|
353
|
-
|
|
428
|
+
if (row.nodes[0] !== domCursor.nextSibling) {
|
|
429
|
+
var fragment = document.createDocumentFragment();
|
|
430
|
+
row.nodes.forEach(n => fragment.appendChild(n));
|
|
431
|
+
domCursor.parentNode.insertBefore(fragment, domCursor.nextSibling);
|
|
354
432
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
433
|
+
|
|
434
|
+
domCursor = row.nodes[row.nodes.length - 1];
|
|
435
|
+
nextNodePool.set(rowUniqueKey, row);
|
|
436
|
+
nodePool.delete(rowUniqueKey);
|
|
358
437
|
});
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
row.
|
|
438
|
+
|
|
439
|
+
nodePool.forEach(row => {
|
|
440
|
+
row.cleanups.forEach(cb => cb());
|
|
441
|
+
row.nodes.forEach(n => n.remove());
|
|
362
442
|
});
|
|
363
|
-
|
|
443
|
+
nodePool = nextNodePool;
|
|
364
444
|
}, nextTick));
|
|
365
445
|
}
|
|
366
446
|
|
|
367
|
-
var
|
|
368
|
-
for (var i =
|
|
369
|
-
(
|
|
447
|
+
var attributes = el.attributes;
|
|
448
|
+
for (var i = attributes.length - 1; i >= 0; i--) {
|
|
449
|
+
((attr) => {
|
|
370
450
|
var name = attr.name;
|
|
371
451
|
var value = attr.value;
|
|
372
452
|
|
|
373
453
|
if (name[0] === ':') {
|
|
374
|
-
|
|
375
|
-
var
|
|
376
|
-
var
|
|
377
|
-
var
|
|
378
|
-
|
|
454
|
+
cleanupList.push(createEffect(() => {
|
|
455
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
456
|
+
var result = evaluation.value;
|
|
457
|
+
var context = evaluation.context;
|
|
458
|
+
var opName = name.slice(1) === 'class' ? 'class' : 'attr';
|
|
459
|
+
|
|
460
|
+
domOperations[opName](
|
|
461
|
+
el,
|
|
462
|
+
typeof result === 'function' ? result.call(context, el) : result,
|
|
463
|
+
name.slice(1)
|
|
464
|
+
);
|
|
379
465
|
}, nextTick));
|
|
380
466
|
|
|
381
467
|
} else if (name[0] === 's' && name[1] === '-') {
|
|
382
|
-
var
|
|
383
|
-
|
|
468
|
+
var directiveType = name.slice(2);
|
|
469
|
+
|
|
470
|
+
if (directiveType === 'ref') {
|
|
384
471
|
state.$refs[value] = el;
|
|
385
|
-
} else if (
|
|
386
|
-
|
|
387
|
-
var
|
|
388
|
-
|
|
472
|
+
} else if (directiveType === 'model') {
|
|
473
|
+
cleanupList.push(createEffect(() => {
|
|
474
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
475
|
+
domOperations.value(el, evaluation.value);
|
|
389
476
|
}, nextTick));
|
|
477
|
+
|
|
390
478
|
if (/^(INPUT|SELECT|TEXTAREA)$/.test(el.tagName)) {
|
|
391
|
-
el.
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
479
|
+
el.__scope = currentScope;
|
|
480
|
+
el.__modelPath = value;
|
|
481
|
+
var eventType = (el.type === 'checkbox' || el.type === 'radio' || el.tagName === 'SELECT')
|
|
482
|
+
? 'change'
|
|
483
|
+
: 'input';
|
|
484
|
+
|
|
485
|
+
if (!rootElement.__listeningEvents) rootElement.__listeningEvents = new Set();
|
|
486
|
+
if (!rootElement.__listeningEvents.has(eventType)) {
|
|
487
|
+
rootElement.__listeningEvents.add(eventType);
|
|
488
|
+
rootElement.addEventListener(eventType, handleEvent);
|
|
397
489
|
}
|
|
398
490
|
}
|
|
399
|
-
} else if (
|
|
400
|
-
|
|
401
|
-
var
|
|
402
|
-
var
|
|
403
|
-
var
|
|
404
|
-
|
|
491
|
+
} else if (domOperations[directiveType]) {
|
|
492
|
+
cleanupList.push(createEffect(() => {
|
|
493
|
+
var evaluation = evaluatePath(currentScope, value);
|
|
494
|
+
var result = evaluation.value;
|
|
495
|
+
var context = evaluation.context;
|
|
496
|
+
domOperations[directiveType](
|
|
497
|
+
el,
|
|
498
|
+
typeof result === 'function' ? result.call(context, el) : result
|
|
499
|
+
);
|
|
405
500
|
}, nextTick));
|
|
406
501
|
} else {
|
|
407
|
-
el.
|
|
408
|
-
var meta =
|
|
502
|
+
el.__scope = currentScope;
|
|
503
|
+
var meta = eventMetadataMap.get(el);
|
|
409
504
|
if (!meta) {
|
|
410
505
|
meta = {};
|
|
411
|
-
|
|
506
|
+
eventMetadataMap.set(el, meta);
|
|
412
507
|
}
|
|
413
|
-
meta[
|
|
414
|
-
|
|
415
|
-
if (!
|
|
416
|
-
|
|
417
|
-
|
|
508
|
+
meta[directiveType] = value;
|
|
509
|
+
|
|
510
|
+
if (!rootElement.__listeningEvents) rootElement.__listeningEvents = new Set();
|
|
511
|
+
if (!rootElement.__listeningEvents.has(directiveType)) {
|
|
512
|
+
rootElement.__listeningEvents.add(directiveType);
|
|
513
|
+
rootElement.addEventListener(directiveType, handleEvent);
|
|
418
514
|
}
|
|
419
515
|
}
|
|
420
516
|
}
|
|
421
|
-
})(
|
|
517
|
+
})(attributes[i]);
|
|
422
518
|
}
|
|
423
519
|
|
|
424
520
|
var child = el.firstElementChild;
|
|
425
521
|
while (child) {
|
|
426
522
|
var next = child.nextElementSibling;
|
|
427
|
-
|
|
523
|
+
walkDOM(child, currentScope, cleanupList);
|
|
428
524
|
child = next;
|
|
429
525
|
}
|
|
430
526
|
};
|
|
431
527
|
|
|
432
|
-
|
|
528
|
+
walkDOM(rootElement, state, cleanupCallbacks);
|
|
433
529
|
if (state.init) state.init();
|
|
434
530
|
|
|
435
531
|
return {
|
|
436
|
-
unmount:
|
|
532
|
+
unmount: () => {
|
|
437
533
|
if (state.destroy) state.destroy.call(state);
|
|
438
|
-
|
|
439
|
-
if (
|
|
440
|
-
|
|
534
|
+
cleanupCallbacks.forEach(cb => cb());
|
|
535
|
+
if (rootElement.__listeningEvents) {
|
|
536
|
+
rootElement.__listeningEvents.forEach(evt => {
|
|
537
|
+
rootElement.removeEventListener(evt, handleEvent);
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
rootElement.__isMounted = 0;
|
|
441
541
|
}
|
|
442
542
|
};
|
|
443
543
|
};
|
|
444
544
|
|
|
445
545
|
return {
|
|
446
|
-
data:
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
546
|
+
data: (name, factoryFn) => {
|
|
547
|
+
componentRegistry[name] = factoryFn;
|
|
548
|
+
},
|
|
549
|
+
start: () => {
|
|
550
|
+
var elements = document.querySelectorAll('[s-data]');
|
|
551
|
+
for (var i = 0; i < elements.length; i++) {
|
|
552
|
+
mountComponent(elements[i]);
|
|
451
553
|
}
|
|
452
554
|
},
|
|
453
|
-
store:
|
|
555
|
+
store: (key, value) => {
|
|
556
|
+
return value === undefined
|
|
557
|
+
? globalStore[key]
|
|
558
|
+
: (globalStore[key] = value);
|
|
559
|
+
},
|
|
560
|
+
raw: (obj) => {
|
|
561
|
+
return (obj && obj.__raw) || obj;
|
|
562
|
+
}
|
|
454
563
|
};
|
|
455
564
|
})();
|
|
456
565
|
|
|
457
|
-
export default spiki;
|
|
566
|
+
export default spiki;
|