imba-source 0.14.1 → 0.14.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/imba/source/version.rb +1 -1
- data/lib/imba/source.rb +1 -1
- data/vendor/imba/dist/imba.dev.js +4048 -0
- data/vendor/imba/dist/imba.js +2 -0
- data/vendor/imba/dist/imbac.dev.js +13739 -0
- data/vendor/imba/dist/imbac.js +9 -0
- data/vendor/imba/dist/imbac.worker.dev.js +13957 -0
- data/vendor/imba/dist/imbac.worker.js +9 -0
- metadata +8 -9
- data/vendor/imba/lib/browser/imba.js +0 -3997
- data/vendor/imba/lib/browser/imba.min.js +0 -30
- data/vendor/imba/lib/browser/imbac.js +0 -15884
- data/vendor/imba/lib/browser/imbac.min.js +0 -2037
- data/vendor/imba/lib/browser/imbac.worker.js +0 -15814
- data/vendor/imba/lib/browser/imbac.worker.min.js +0 -2033
@@ -0,0 +1,4048 @@
|
|
1
|
+
/******/ (function(modules) { // webpackBootstrap
|
2
|
+
/******/ // The module cache
|
3
|
+
/******/ var installedModules = {};
|
4
|
+
/******/
|
5
|
+
/******/ // The require function
|
6
|
+
/******/ function __webpack_require__(moduleId) {
|
7
|
+
/******/
|
8
|
+
/******/ // Check if module is in cache
|
9
|
+
/******/ if(installedModules[moduleId])
|
10
|
+
/******/ return installedModules[moduleId].exports;
|
11
|
+
/******/
|
12
|
+
/******/ // Create a new module (and put it into the cache)
|
13
|
+
/******/ var module = installedModules[moduleId] = {
|
14
|
+
/******/ exports: {},
|
15
|
+
/******/ id: moduleId,
|
16
|
+
/******/ loaded: false
|
17
|
+
/******/ };
|
18
|
+
/******/
|
19
|
+
/******/ // Execute the module function
|
20
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
21
|
+
/******/
|
22
|
+
/******/ // Flag the module as loaded
|
23
|
+
/******/ module.loaded = true;
|
24
|
+
/******/
|
25
|
+
/******/ // Return the exports of the module
|
26
|
+
/******/ return module.exports;
|
27
|
+
/******/ }
|
28
|
+
/******/
|
29
|
+
/******/
|
30
|
+
/******/ // expose the modules object (__webpack_modules__)
|
31
|
+
/******/ __webpack_require__.m = modules;
|
32
|
+
/******/
|
33
|
+
/******/ // expose the module cache
|
34
|
+
/******/ __webpack_require__.c = installedModules;
|
35
|
+
/******/
|
36
|
+
/******/ // __webpack_public_path__
|
37
|
+
/******/ __webpack_require__.p = "";
|
38
|
+
/******/
|
39
|
+
/******/ // Load entry module and return exports
|
40
|
+
/******/ return __webpack_require__(0);
|
41
|
+
/******/ })
|
42
|
+
/************************************************************************/
|
43
|
+
/******/ ([
|
44
|
+
/* 0 */
|
45
|
+
/***/ function(module, exports, __webpack_require__) {
|
46
|
+
|
47
|
+
(function(){
|
48
|
+
|
49
|
+
if (typeof Imba === 'undefined') {
|
50
|
+
__webpack_require__(1);
|
51
|
+
__webpack_require__(2);
|
52
|
+
__webpack_require__(3);
|
53
|
+
__webpack_require__(4);
|
54
|
+
__webpack_require__(5);
|
55
|
+
__webpack_require__(6);
|
56
|
+
__webpack_require__(7);
|
57
|
+
|
58
|
+
if (false) {
|
59
|
+
require('./dom.server');
|
60
|
+
};
|
61
|
+
|
62
|
+
if (true) {
|
63
|
+
__webpack_require__(8);
|
64
|
+
__webpack_require__(9);
|
65
|
+
__webpack_require__(10);
|
66
|
+
};
|
67
|
+
|
68
|
+
return __webpack_require__(11);
|
69
|
+
} else {
|
70
|
+
return console.warn(("Imba v" + (Imba.VERSION) + " is already loaded"));
|
71
|
+
};
|
72
|
+
|
73
|
+
})()
|
74
|
+
|
75
|
+
/***/ },
|
76
|
+
/* 1 */
|
77
|
+
/***/ function(module, exports, __webpack_require__) {
|
78
|
+
|
79
|
+
/* WEBPACK VAR INJECTION */(function(global) {(function(){
|
80
|
+
if (typeof window !== 'undefined') {
|
81
|
+
// should not go there
|
82
|
+
global = window;
|
83
|
+
};
|
84
|
+
|
85
|
+
var isClient = (typeof window == 'object' && this == window);
|
86
|
+
/*
|
87
|
+
Imba is the namespace for all runtime related utilities
|
88
|
+
@namespace
|
89
|
+
*/
|
90
|
+
|
91
|
+
Imba = {
|
92
|
+
VERSION: '0.14.3',
|
93
|
+
CLIENT: isClient,
|
94
|
+
SERVER: !(isClient),
|
95
|
+
DEBUG: false
|
96
|
+
};
|
97
|
+
|
98
|
+
var reg = /-./g;
|
99
|
+
|
100
|
+
/*
|
101
|
+
True if running in client environment.
|
102
|
+
@return {bool}
|
103
|
+
*/
|
104
|
+
|
105
|
+
Imba.isClient = function (){
|
106
|
+
return (true) == true;
|
107
|
+
};
|
108
|
+
|
109
|
+
/*
|
110
|
+
True if running in server environment.
|
111
|
+
@return {bool}
|
112
|
+
*/
|
113
|
+
|
114
|
+
Imba.isServer = function (){
|
115
|
+
return (false) == true;
|
116
|
+
};
|
117
|
+
|
118
|
+
Imba.subclass = function (obj,sup){
|
119
|
+
;
|
120
|
+
for (var k in sup){
|
121
|
+
if (sup.hasOwnProperty(k)) { obj[k] = sup[k] };
|
122
|
+
};
|
123
|
+
|
124
|
+
obj.prototype = Object.create(sup.prototype);
|
125
|
+
obj.__super__ = obj.prototype.__super__ = sup.prototype;
|
126
|
+
obj.prototype.initialize = obj.prototype.constructor = obj;
|
127
|
+
return obj;
|
128
|
+
};
|
129
|
+
|
130
|
+
/*
|
131
|
+
Lightweight method for making an object iterable in imbas for/in loops.
|
132
|
+
If the compiler cannot say for certain that a target in a for loop is an
|
133
|
+
array, it will cache the iterable version before looping.
|
134
|
+
|
135
|
+
```imba
|
136
|
+
# this is the whole method
|
137
|
+
def Imba.iterable o
|
138
|
+
return o ? (o:toArray ? o.toArray : o) : []
|
139
|
+
|
140
|
+
class CustomIterable
|
141
|
+
def toArray
|
142
|
+
[1,2,3]
|
143
|
+
|
144
|
+
# will return [2,4,6]
|
145
|
+
for x in CustomIterable.new
|
146
|
+
x * 2
|
147
|
+
|
148
|
+
```
|
149
|
+
*/
|
150
|
+
|
151
|
+
Imba.iterable = function (o){
|
152
|
+
return o ? ((o.toArray ? (o.toArray()) : (o))) : ([]);
|
153
|
+
};
|
154
|
+
|
155
|
+
/*
|
156
|
+
Coerces a value into a promise. If value is array it will
|
157
|
+
call `Promise.all(value)`, or if it is not a promise it will
|
158
|
+
wrap the value in `Promise.resolve(value)`. Used for experimental
|
159
|
+
await syntax.
|
160
|
+
@return {Promise}
|
161
|
+
*/
|
162
|
+
|
163
|
+
Imba.await = function (value){
|
164
|
+
if (value instanceof Array) {
|
165
|
+
return Promise.all(value);
|
166
|
+
} else if (value && value.then) {
|
167
|
+
return value;
|
168
|
+
} else {
|
169
|
+
return Promise.resolve(value);
|
170
|
+
};
|
171
|
+
};
|
172
|
+
|
173
|
+
Imba.toCamelCase = function (str){
|
174
|
+
return str.replace(reg,function(m) { return m.charAt(1).toUpperCase(); });
|
175
|
+
};
|
176
|
+
|
177
|
+
Imba.toCamelCase = function (str){
|
178
|
+
return str.replace(reg,function(m) { return m.charAt(1).toUpperCase(); });
|
179
|
+
};
|
180
|
+
|
181
|
+
Imba.indexOf = function (a,b){
|
182
|
+
return (b && b.indexOf) ? (b.indexOf(a)) : ([].indexOf.call(a,b));
|
183
|
+
};
|
184
|
+
|
185
|
+
Imba.prop = function (scope,name,opts){
|
186
|
+
if (scope.defineProperty) {
|
187
|
+
return scope.defineProperty(name,opts);
|
188
|
+
};
|
189
|
+
return;
|
190
|
+
};
|
191
|
+
|
192
|
+
return Imba.attr = function (scope,name,opts){
|
193
|
+
if (scope.defineAttribute) {
|
194
|
+
return scope.defineAttribute(name,opts);
|
195
|
+
};
|
196
|
+
|
197
|
+
var getName = Imba.toCamelCase(name);
|
198
|
+
var setName = Imba.toCamelCase('set-' + name);
|
199
|
+
|
200
|
+
scope.prototype[getName] = function() {
|
201
|
+
return this.getAttribute(name);
|
202
|
+
};
|
203
|
+
|
204
|
+
scope.prototype[setName] = function(value) {
|
205
|
+
this.setAttribute(name,value);
|
206
|
+
return this;
|
207
|
+
};
|
208
|
+
|
209
|
+
return;
|
210
|
+
};
|
211
|
+
|
212
|
+
})()
|
213
|
+
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
|
214
|
+
|
215
|
+
/***/ },
|
216
|
+
/* 2 */
|
217
|
+
/***/ function(module, exports) {
|
218
|
+
|
219
|
+
(function(){
|
220
|
+
|
221
|
+
|
222
|
+
function emit__(event,args,node){
|
223
|
+
// var node = cbs[event]
|
224
|
+
var prev,cb,ret;
|
225
|
+
|
226
|
+
while ((prev = node) && (node = node.next)){
|
227
|
+
if (cb = node.listener) {
|
228
|
+
if (node.path && cb[node.path]) {
|
229
|
+
ret = args ? (cb[node.path].apply(cb,args)) : (cb[node.path]());
|
230
|
+
} else {
|
231
|
+
// check if it is a method?
|
232
|
+
ret = args ? (cb.apply(node,args)) : (cb.call(node));
|
233
|
+
};
|
234
|
+
};
|
235
|
+
|
236
|
+
if (node.times && --node.times <= 0) {
|
237
|
+
prev.next = node.next;
|
238
|
+
node.listener = null;
|
239
|
+
};
|
240
|
+
};
|
241
|
+
return;
|
242
|
+
};
|
243
|
+
|
244
|
+
// method for registering a listener on object
|
245
|
+
Imba.listen = function (obj,event,listener,path){
|
246
|
+
var $1;
|
247
|
+
var cbs,list,tail;
|
248
|
+
cbs = obj.__listeners__ || (obj.__listeners__ = {});
|
249
|
+
list = cbs[($1 = event)] || (cbs[$1] = {});
|
250
|
+
tail = list.tail || (list.tail = (list.next = {}));
|
251
|
+
tail.listener = listener;
|
252
|
+
tail.path = path;
|
253
|
+
list.tail = tail.next = {};
|
254
|
+
return tail;
|
255
|
+
};
|
256
|
+
|
257
|
+
Imba.once = function (obj,event,listener){
|
258
|
+
var tail = Imba.listen(obj,event,listener);
|
259
|
+
tail.times = 1;
|
260
|
+
return tail;
|
261
|
+
};
|
262
|
+
|
263
|
+
Imba.unlisten = function (obj,event,cb,meth){
|
264
|
+
var node,prev;
|
265
|
+
var meta = obj.__listeners__;
|
266
|
+
if (!(meta)) { return };
|
267
|
+
|
268
|
+
if (node = meta[event]) {
|
269
|
+
while ((prev = node) && (node = node.next)){
|
270
|
+
if (node == cb || node.listener == cb) {
|
271
|
+
prev.next = node.next;
|
272
|
+
// check for correct path as well?
|
273
|
+
node.listener = null;
|
274
|
+
break;
|
275
|
+
};
|
276
|
+
};
|
277
|
+
};
|
278
|
+
return;
|
279
|
+
};
|
280
|
+
|
281
|
+
Imba.emit = function (obj,event,params){
|
282
|
+
var cb;
|
283
|
+
if (cb = obj.__listeners__) {
|
284
|
+
if (cb[event]) { emit__(event,params,cb[event]) };
|
285
|
+
if (cb.all) { emit__(event,[event,params],cb.all) }; // and event != 'all'
|
286
|
+
};
|
287
|
+
return;
|
288
|
+
};
|
289
|
+
|
290
|
+
return Imba.observeProperty = function (observer,key,trigger,target,prev){
|
291
|
+
if (prev && typeof prev == 'object') {
|
292
|
+
Imba.unlisten(prev,'all',observer,trigger);
|
293
|
+
};
|
294
|
+
if (target && typeof target == 'object') {
|
295
|
+
Imba.listen(target,'all',observer,trigger);
|
296
|
+
};
|
297
|
+
return this;
|
298
|
+
};
|
299
|
+
|
300
|
+
})()
|
301
|
+
|
302
|
+
/***/ },
|
303
|
+
/* 3 */
|
304
|
+
/***/ function(module, exports) {
|
305
|
+
|
306
|
+
/* WEBPACK VAR INJECTION */(function(global) {(function(){
|
307
|
+
function idx$(a,b){
|
308
|
+
return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
|
309
|
+
};
|
310
|
+
|
311
|
+
|
312
|
+
var raf; // very simple raf polyfill
|
313
|
+
raf || (raf = global.requestAnimationFrame);
|
314
|
+
raf || (raf = global.webkitRequestAnimationFrame);
|
315
|
+
raf || (raf = global.mozRequestAnimationFrame);
|
316
|
+
raf || (raf = function(blk) { return setTimeout(blk,1000 / 60); });
|
317
|
+
|
318
|
+
Imba.tick = function (d){
|
319
|
+
if (this._scheduled) { raf(Imba.ticker()) };
|
320
|
+
Imba.Scheduler.willRun();
|
321
|
+
this.emit(this,'tick',[d]);
|
322
|
+
Imba.Scheduler.didRun();
|
323
|
+
return;
|
324
|
+
};
|
325
|
+
|
326
|
+
Imba.ticker = function (){
|
327
|
+
var self = this;
|
328
|
+
return self._ticker || (self._ticker = function(e) { return self.tick(e); });
|
329
|
+
};
|
330
|
+
|
331
|
+
/*
|
332
|
+
|
333
|
+
Global alternative to requestAnimationFrame. Schedule a target
|
334
|
+
to tick every frame. You can specify which method to call on the
|
335
|
+
target (defaults to tick).
|
336
|
+
|
337
|
+
*/
|
338
|
+
|
339
|
+
Imba.schedule = function (target,method){
|
340
|
+
if(method === undefined) method = 'tick';
|
341
|
+
this.listen(this,'tick',target,method);
|
342
|
+
// start scheduling now if this was the first one
|
343
|
+
if (!this._scheduled) {
|
344
|
+
this._scheduled = true;
|
345
|
+
raf(Imba.ticker());
|
346
|
+
};
|
347
|
+
return this;
|
348
|
+
};
|
349
|
+
|
350
|
+
/*
|
351
|
+
|
352
|
+
Unschedule a previously scheduled target
|
353
|
+
|
354
|
+
*/
|
355
|
+
|
356
|
+
Imba.unschedule = function (target,method){
|
357
|
+
this.unlisten(this,'tick',target,method);
|
358
|
+
var cbs = this.__listeners__ || (this.__listeners__ = {});
|
359
|
+
if (!cbs.tick || !cbs.tick.next || !cbs.tick.next.listener) {
|
360
|
+
this._scheduled = false;
|
361
|
+
};
|
362
|
+
return this;
|
363
|
+
};
|
364
|
+
|
365
|
+
/*
|
366
|
+
|
367
|
+
Light wrapper around native setTimeout that expects the block / function
|
368
|
+
as last argument (instead of first). It also triggers an event to Imba
|
369
|
+
after the timeout to let schedulers update (to rerender etc) afterwards.
|
370
|
+
|
371
|
+
*/
|
372
|
+
|
373
|
+
Imba.setTimeout = function (delay,block){
|
374
|
+
return setTimeout(function() {
|
375
|
+
block();
|
376
|
+
return Imba.Scheduler.markDirty();
|
377
|
+
// Imba.emit(Imba,'timeout',[block])
|
378
|
+
},delay);
|
379
|
+
};
|
380
|
+
|
381
|
+
/*
|
382
|
+
|
383
|
+
Light wrapper around native setInterval that expects the block / function
|
384
|
+
as last argument (instead of first). It also triggers an event to Imba
|
385
|
+
after every interval to let schedulers update (to rerender etc) afterwards.
|
386
|
+
|
387
|
+
*/
|
388
|
+
|
389
|
+
Imba.setInterval = function (interval,block){
|
390
|
+
return setInterval(function() {
|
391
|
+
block();
|
392
|
+
return Imba.Scheduler.markDirty();
|
393
|
+
// Imba.emit(Imba,'interval',[block])
|
394
|
+
},interval);
|
395
|
+
};
|
396
|
+
|
397
|
+
/*
|
398
|
+
Clear interval with specified id
|
399
|
+
*/
|
400
|
+
|
401
|
+
Imba.clearInterval = function (interval){
|
402
|
+
return clearInterval(interval);
|
403
|
+
};
|
404
|
+
|
405
|
+
/*
|
406
|
+
Clear timeout with specified id
|
407
|
+
*/
|
408
|
+
|
409
|
+
Imba.clearTimeout = function (timeout){
|
410
|
+
return clearTimeout(timeout);
|
411
|
+
};
|
412
|
+
|
413
|
+
// should add an Imba.run / setImmediate that
|
414
|
+
// pushes listener onto the tick-queue with times - once
|
415
|
+
|
416
|
+
|
417
|
+
/*
|
418
|
+
|
419
|
+
Instances of Imba.Scheduler manages when to call `tick()` on their target,
|
420
|
+
at a specified framerate or when certain events occur. Root-nodes in your
|
421
|
+
applications will usually have a scheduler to make sure they rerender when
|
422
|
+
something changes. It is also possible to make inner components use their
|
423
|
+
own schedulers to control when they render.
|
424
|
+
|
425
|
+
@iname scheduler
|
426
|
+
|
427
|
+
*/
|
428
|
+
|
429
|
+
Imba.Scheduler = function Scheduler(target){
|
430
|
+
var self = this;
|
431
|
+
self._target = target;
|
432
|
+
self._marked = false;
|
433
|
+
self._active = false;
|
434
|
+
self._marker = function() { return self.mark(); };
|
435
|
+
self._ticker = function(e) { return self.tick(e); };
|
436
|
+
|
437
|
+
self._events = true;
|
438
|
+
self._fps = 1;
|
439
|
+
|
440
|
+
self._dt = 0;
|
441
|
+
self._timestamp = 0;
|
442
|
+
self._ticks = 0;
|
443
|
+
self._flushes = 0;
|
444
|
+
};
|
445
|
+
|
446
|
+
Imba.Scheduler.markDirty = function (){
|
447
|
+
this._dirty = true;
|
448
|
+
return this;
|
449
|
+
};
|
450
|
+
|
451
|
+
Imba.Scheduler.isDirty = function (){
|
452
|
+
return !(!this._dirty);
|
453
|
+
};
|
454
|
+
|
455
|
+
Imba.Scheduler.willRun = function (){
|
456
|
+
return this._active = true;
|
457
|
+
};
|
458
|
+
|
459
|
+
Imba.Scheduler.didRun = function (){
|
460
|
+
this._active = false;
|
461
|
+
return this._dirty = false;
|
462
|
+
};
|
463
|
+
|
464
|
+
Imba.Scheduler.isActive = function (){
|
465
|
+
return !(!this._active);
|
466
|
+
};
|
467
|
+
|
468
|
+
/*
|
469
|
+
Create a new Imba.Scheduler for specified target
|
470
|
+
@return {Imba.Scheduler}
|
471
|
+
*/
|
472
|
+
|
473
|
+
/*
|
474
|
+
Check whether the current scheduler is active or not
|
475
|
+
@return {bool}
|
476
|
+
*/
|
477
|
+
|
478
|
+
Imba.Scheduler.prototype.active = function (){
|
479
|
+
return this._active;
|
480
|
+
};
|
481
|
+
|
482
|
+
/*
|
483
|
+
Delta time between the two last ticks
|
484
|
+
@return {Number}
|
485
|
+
*/
|
486
|
+
|
487
|
+
Imba.Scheduler.prototype.dt = function (){
|
488
|
+
return this._dt;
|
489
|
+
};
|
490
|
+
|
491
|
+
/*
|
492
|
+
Configure the scheduler
|
493
|
+
@return {self}
|
494
|
+
*/
|
495
|
+
|
496
|
+
Imba.Scheduler.prototype.configure = function (pars){
|
497
|
+
if(!pars||pars.constructor !== Object) pars = {};
|
498
|
+
var fps = pars.fps !== undefined ? pars.fps : 1;
|
499
|
+
var events = pars.events !== undefined ? pars.events : true;
|
500
|
+
if (events != null) { this._events = events };
|
501
|
+
if (fps != null) { this._fps = fps };
|
502
|
+
return this;
|
503
|
+
};
|
504
|
+
|
505
|
+
/*
|
506
|
+
Mark the scheduler as dirty. This will make sure that
|
507
|
+
the scheduler calls `target.tick` on the next frame
|
508
|
+
@return {self}
|
509
|
+
*/
|
510
|
+
|
511
|
+
Imba.Scheduler.prototype.mark = function (){
|
512
|
+
this._marked = true;
|
513
|
+
return this;
|
514
|
+
};
|
515
|
+
|
516
|
+
/*
|
517
|
+
Instantly trigger target.tick and mark scheduler as clean (not dirty/marked).
|
518
|
+
This is called implicitly from tick, but can also be called manually if you
|
519
|
+
really want to force a tick without waiting for the next frame.
|
520
|
+
@return {self}
|
521
|
+
*/
|
522
|
+
|
523
|
+
Imba.Scheduler.prototype.flush = function (){
|
524
|
+
this._marked = false;
|
525
|
+
this._flushes++;
|
526
|
+
this._target.tick();
|
527
|
+
return this;
|
528
|
+
};
|
529
|
+
|
530
|
+
/*
|
531
|
+
@fixme this expects raf to run at 60 fps
|
532
|
+
|
533
|
+
Called automatically on every frame while the scheduler is active.
|
534
|
+
It will only call `target.tick` if the scheduler is marked dirty,
|
535
|
+
or when according to @fps setting.
|
536
|
+
|
537
|
+
If you have set up a scheduler with an fps of 1, tick will still be
|
538
|
+
called every frame, but `target.tick` will only be called once every
|
539
|
+
second, and it will *make sure* each `target.tick` happens in separate
|
540
|
+
seconds according to Date. So if you have a node that renders a clock
|
541
|
+
based on Date.now (or something similar), you can schedule it with 1fps,
|
542
|
+
never needing to worry about two ticks happening within the same second.
|
543
|
+
The same goes for 4fps, 10fps etc.
|
544
|
+
|
545
|
+
@protected
|
546
|
+
@return {self}
|
547
|
+
*/
|
548
|
+
|
549
|
+
Imba.Scheduler.prototype.tick = function (delta){
|
550
|
+
this._ticks++;
|
551
|
+
this._dt = delta;
|
552
|
+
|
553
|
+
var fps = this._fps;
|
554
|
+
|
555
|
+
if (fps == 60) {
|
556
|
+
this._marked = true;
|
557
|
+
} else if (fps == 30) {
|
558
|
+
if (this._ticks % 2) { this._marked = true };
|
559
|
+
} else if (fps) {
|
560
|
+
// if it is less round - we trigger based
|
561
|
+
// on date, for consistent rendering.
|
562
|
+
// ie, if you want to render every second
|
563
|
+
// it is important that no two renders
|
564
|
+
// happen during the same second (according to Date)
|
565
|
+
var period = ((60 / fps) / 60) * 1000;
|
566
|
+
var beat = Math.floor(Date.now() / period);
|
567
|
+
|
568
|
+
if (this._beat != beat) {
|
569
|
+
this._beat = beat;
|
570
|
+
this._marked = true;
|
571
|
+
};
|
572
|
+
};
|
573
|
+
|
574
|
+
if (this._marked || (this._events && Imba.Scheduler.isDirty())) this.flush();
|
575
|
+
// reschedule if @active
|
576
|
+
return this;
|
577
|
+
};
|
578
|
+
|
579
|
+
/*
|
580
|
+
Start the scheduler if it is not already active.
|
581
|
+
**While active**, the scheduler will override `target.commit`
|
582
|
+
to do nothing. By default Imba.tag#commit calls render, so
|
583
|
+
that rendering is cascaded through to children when rendering
|
584
|
+
a node. When a scheduler is active (for a node), Imba disables
|
585
|
+
this automatic rendering.
|
586
|
+
*/
|
587
|
+
|
588
|
+
Imba.Scheduler.prototype.activate = function (){
|
589
|
+
if (!this._active) {
|
590
|
+
this._active = true;
|
591
|
+
// override target#commit while this is active
|
592
|
+
this._commit = this._target.commit;
|
593
|
+
this._target.commit = function() { return this; };
|
594
|
+
Imba.schedule(this);
|
595
|
+
if (this._events) { Imba.listen(Imba,'event',this,'onevent') };
|
596
|
+
this._target && this._target.flag && this._target.flag('scheduled_');
|
597
|
+
this.tick(0); // start ticking
|
598
|
+
};
|
599
|
+
return this;
|
600
|
+
};
|
601
|
+
|
602
|
+
/*
|
603
|
+
Stop the scheduler if it is active.
|
604
|
+
*/
|
605
|
+
|
606
|
+
Imba.Scheduler.prototype.deactivate = function (){
|
607
|
+
if (this._active) {
|
608
|
+
this._active = false;
|
609
|
+
this._target.commit = this._commit;
|
610
|
+
Imba.unschedule(this);
|
611
|
+
Imba.unlisten(Imba,'event',this);
|
612
|
+
this._target && this._target.unflag && this._target.unflag('scheduled_');
|
613
|
+
};
|
614
|
+
return this;
|
615
|
+
};
|
616
|
+
|
617
|
+
Imba.Scheduler.prototype.track = function (){
|
618
|
+
return this._marker;
|
619
|
+
};
|
620
|
+
|
621
|
+
Imba.Scheduler.prototype.onevent = function (event){
|
622
|
+
var $1;
|
623
|
+
if (this._marked) { return this };
|
624
|
+
|
625
|
+
if (this._events instanceof Function) {
|
626
|
+
if (this._events(event)) this.mark();
|
627
|
+
} else if (this._events instanceof Array) {
|
628
|
+
if (idx$(($1 = event) && $1.type && $1.type(),this._events) >= 0) this.mark();
|
629
|
+
} else if (this._events) {
|
630
|
+
if (event._responder) this.mark();
|
631
|
+
};
|
632
|
+
return this;
|
633
|
+
};
|
634
|
+
return Imba.Scheduler;
|
635
|
+
|
636
|
+
})()
|
637
|
+
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
|
638
|
+
|
639
|
+
/***/ },
|
640
|
+
/* 4 */
|
641
|
+
/***/ function(module, exports) {
|
642
|
+
|
643
|
+
(function(){
|
644
|
+
function idx$(a,b){
|
645
|
+
return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
|
646
|
+
};
|
647
|
+
|
648
|
+
Imba.static = function (items,nr){
|
649
|
+
items.static = nr;
|
650
|
+
return items;
|
651
|
+
};
|
652
|
+
|
653
|
+
/*
|
654
|
+
This is the baseclass that all tags in imba inherit from.
|
655
|
+
@iname node
|
656
|
+
*/
|
657
|
+
|
658
|
+
Imba.Tag = function Tag(dom){
|
659
|
+
this.setDom(dom);
|
660
|
+
};
|
661
|
+
|
662
|
+
Imba.Tag.createNode = function (){
|
663
|
+
throw "Not implemented";
|
664
|
+
};
|
665
|
+
|
666
|
+
Imba.Tag.build = function (){
|
667
|
+
return new this(this.createNode());
|
668
|
+
};
|
669
|
+
|
670
|
+
Imba.Tag.prototype.object = function(v){ return this._object; }
|
671
|
+
Imba.Tag.prototype.setObject = function(v){ this._object = v; return this; };
|
672
|
+
|
673
|
+
Imba.Tag.prototype.dom = function (){
|
674
|
+
return this._dom;
|
675
|
+
};
|
676
|
+
|
677
|
+
Imba.Tag.prototype.setDom = function (dom){
|
678
|
+
dom._tag = this;
|
679
|
+
this._dom = dom;
|
680
|
+
return this;
|
681
|
+
};
|
682
|
+
|
683
|
+
/*
|
684
|
+
Setting references for tags like
|
685
|
+
`<div@header>` will compile to `tag('div').setRef('header',this).end()`
|
686
|
+
By default it adds the reference as a className to the tag.
|
687
|
+
@return {self}
|
688
|
+
*/
|
689
|
+
|
690
|
+
Imba.Tag.prototype.setRef = function (ref,ctx){
|
691
|
+
this.flag(this._ref = ref);
|
692
|
+
return this;
|
693
|
+
};
|
694
|
+
|
695
|
+
/*
|
696
|
+
Method that is called by the compiled tag-chains, for
|
697
|
+
binding events on tags to methods etc.
|
698
|
+
`<a :tap=fn>` compiles to `tag('a').setHandler('tap',fn,this).end()`
|
699
|
+
where this refers to the context in which the tag is created.
|
700
|
+
@return {self}
|
701
|
+
*/
|
702
|
+
|
703
|
+
Imba.Tag.prototype.setHandler = function (event,handler,ctx){
|
704
|
+
var key = 'on' + event;
|
705
|
+
|
706
|
+
if (handler instanceof Function) {
|
707
|
+
this[key] = handler;
|
708
|
+
} else if (handler instanceof Array) {
|
709
|
+
var fn = handler.shift();
|
710
|
+
this[key] = function(e) { return ctx[fn].apply(ctx,handler.concat(e)); };
|
711
|
+
} else {
|
712
|
+
this[key] = function(e) { return ctx[handler](e); };
|
713
|
+
};
|
714
|
+
return this;
|
715
|
+
};
|
716
|
+
|
717
|
+
Imba.Tag.prototype.setId = function (id){
|
718
|
+
this.dom().id = id;
|
719
|
+
return this;
|
720
|
+
};
|
721
|
+
|
722
|
+
Imba.Tag.prototype.id = function (){
|
723
|
+
return this.dom().id;
|
724
|
+
};
|
725
|
+
|
726
|
+
/*
|
727
|
+
Adds a new attribute or changes the value of an existing attribute
|
728
|
+
on the specified tag. If the value is null or false, the attribute
|
729
|
+
will be removed.
|
730
|
+
@return {self}
|
731
|
+
*/
|
732
|
+
|
733
|
+
Imba.Tag.prototype.setAttribute = function (name,value){
|
734
|
+
// should this not return self?
|
735
|
+
var old = this.dom().getAttribute(name);
|
736
|
+
|
737
|
+
if (old == value) {
|
738
|
+
return value;
|
739
|
+
} else if (value != null && value !== false) {
|
740
|
+
return this.dom().setAttribute(name,value);
|
741
|
+
} else {
|
742
|
+
return this.dom().removeAttribute(name);
|
743
|
+
};
|
744
|
+
};
|
745
|
+
|
746
|
+
/*
|
747
|
+
removes an attribute from the specified tag
|
748
|
+
*/
|
749
|
+
|
750
|
+
Imba.Tag.prototype.removeAttribute = function (name){
|
751
|
+
return this.dom().removeAttribute(name);
|
752
|
+
};
|
753
|
+
|
754
|
+
/*
|
755
|
+
returns the value of an attribute on the tag.
|
756
|
+
If the given attribute does not exist, the value returned
|
757
|
+
will either be null or "" (the empty string)
|
758
|
+
*/
|
759
|
+
|
760
|
+
Imba.Tag.prototype.getAttribute = function (name){
|
761
|
+
return this.dom().getAttribute(name);
|
762
|
+
};
|
763
|
+
|
764
|
+
/*
|
765
|
+
Override this to provide special wrapping etc.
|
766
|
+
@return {self}
|
767
|
+
*/
|
768
|
+
|
769
|
+
Imba.Tag.prototype.setContent = function (content,type){
|
770
|
+
this.setChildren(content,type);
|
771
|
+
return this;
|
772
|
+
};
|
773
|
+
|
774
|
+
/*
|
775
|
+
Set the children of node. type param is optional,
|
776
|
+
and should only be used by Imba when compiling tag trees.
|
777
|
+
@return {self}
|
778
|
+
*/
|
779
|
+
|
780
|
+
Imba.Tag.prototype.setChildren = function (nodes,type){
|
781
|
+
throw "Not implemented";
|
782
|
+
};
|
783
|
+
|
784
|
+
/*
|
785
|
+
Get text of node. Uses textContent behind the scenes (not innerText)
|
786
|
+
[https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent]()
|
787
|
+
@return {string} inner text of node
|
788
|
+
*/
|
789
|
+
|
790
|
+
Imba.Tag.prototype.text = function (v){
|
791
|
+
return this._dom.textContent;
|
792
|
+
};
|
793
|
+
|
794
|
+
/*
|
795
|
+
Set text of node. Uses textContent behind the scenes (not innerText)
|
796
|
+
[https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent]()
|
797
|
+
*/
|
798
|
+
|
799
|
+
Imba.Tag.prototype.setText = function (txt){
|
800
|
+
this._empty = false;
|
801
|
+
this._dom.textContent = txt == null ? (txt = "") : (txt);
|
802
|
+
return this;
|
803
|
+
};
|
804
|
+
|
805
|
+
|
806
|
+
/*
|
807
|
+
Method for getting and setting data-attributes. When called with zero
|
808
|
+
arguments it will return the actual dataset for the tag.
|
809
|
+
|
810
|
+
var node = <div data-name='hello'>
|
811
|
+
# get the whole dataset
|
812
|
+
node.dataset # {name: 'hello'}
|
813
|
+
# get a single value
|
814
|
+
node.dataset('name') # 'hello'
|
815
|
+
# set a single value
|
816
|
+
node.dataset('name','newname') # self
|
817
|
+
|
818
|
+
|
819
|
+
*/
|
820
|
+
|
821
|
+
Imba.Tag.prototype.dataset = function (key,val){
|
822
|
+
throw "Not implemented";
|
823
|
+
};
|
824
|
+
|
825
|
+
/*
|
826
|
+
Empty placeholder. Override to implement custom render behaviour.
|
827
|
+
Works much like the familiar render-method in React.
|
828
|
+
@return {self}
|
829
|
+
*/
|
830
|
+
|
831
|
+
Imba.Tag.prototype.render = function (){
|
832
|
+
return this;
|
833
|
+
};
|
834
|
+
|
835
|
+
/*
|
836
|
+
Called implicitly through Imba.Tag#end, upon creating a tag. All
|
837
|
+
properties will have been set before build is called, including
|
838
|
+
setContent.
|
839
|
+
@return {self}
|
840
|
+
*/
|
841
|
+
|
842
|
+
Imba.Tag.prototype.build = function (){
|
843
|
+
this.render();
|
844
|
+
return this;
|
845
|
+
};
|
846
|
+
|
847
|
+
/*
|
848
|
+
Called implicitly through Imba.Tag#end, for tags that are part of
|
849
|
+
a tag tree (that are rendered several times).
|
850
|
+
@return {self}
|
851
|
+
*/
|
852
|
+
|
853
|
+
Imba.Tag.prototype.commit = function (){
|
854
|
+
this.render();
|
855
|
+
return this;
|
856
|
+
};
|
857
|
+
|
858
|
+
/*
|
859
|
+
|
860
|
+
Called by the tag-scheduler (if this tag is scheduled)
|
861
|
+
By default it will call this.render. Do not override unless
|
862
|
+
you really understand it.
|
863
|
+
|
864
|
+
*/
|
865
|
+
|
866
|
+
Imba.Tag.prototype.tick = function (){
|
867
|
+
this.render();
|
868
|
+
return this;
|
869
|
+
};
|
870
|
+
|
871
|
+
/*
|
872
|
+
|
873
|
+
A very important method that you will practically never manually.
|
874
|
+
The tag syntax of Imba compiles to a chain of setters, which always
|
875
|
+
ends with .end. `<a.large>` compiles to `tag('a').flag('large').end()`
|
876
|
+
|
877
|
+
You are highly adviced to not override its behaviour. The first time
|
878
|
+
end is called it will mark the tag as built and call Imba.Tag#build,
|
879
|
+
and call Imba.Tag#commit on subsequent calls.
|
880
|
+
@return {self}
|
881
|
+
*/
|
882
|
+
|
883
|
+
Imba.Tag.prototype.end = function (){
|
884
|
+
if (this._built) {
|
885
|
+
this.commit();
|
886
|
+
} else {
|
887
|
+
this._built = true;
|
888
|
+
this.build();
|
889
|
+
};
|
890
|
+
return this;
|
891
|
+
};
|
892
|
+
|
893
|
+
/*
|
894
|
+
This is called instead of Imba.Tag#end for `<self>` tag chains.
|
895
|
+
Defaults to noop
|
896
|
+
@return {self}
|
897
|
+
*/
|
898
|
+
|
899
|
+
Imba.Tag.prototype.synced = function (){
|
900
|
+
return this;
|
901
|
+
};
|
902
|
+
|
903
|
+
// called when the node is awakened in the dom - either automatically
|
904
|
+
// upon attachment to the dom-tree, or the first time imba needs the
|
905
|
+
// tag for a domnode that has been rendered on the server
|
906
|
+
Imba.Tag.prototype.awaken = function (){
|
907
|
+
return this;
|
908
|
+
};
|
909
|
+
|
910
|
+
/*
|
911
|
+
List of flags for this node.
|
912
|
+
*/
|
913
|
+
|
914
|
+
Imba.Tag.prototype.flags = function (){
|
915
|
+
return this._dom.classList;
|
916
|
+
};
|
917
|
+
|
918
|
+
/*
|
919
|
+
Add speficied flag to current node.
|
920
|
+
If a second argument is supplied, it will be coerced into a Boolean,
|
921
|
+
and used to indicate whether we should remove the flag instead.
|
922
|
+
@return {self}
|
923
|
+
*/
|
924
|
+
|
925
|
+
Imba.Tag.prototype.flag = function (name,toggler){
|
926
|
+
// it is most natural to treat a second undefined argument as a no-switch
|
927
|
+
// so we need to check the arguments-length
|
928
|
+
if (arguments.length == 2 && !(toggler)) {
|
929
|
+
this._dom.classList.remove(name);
|
930
|
+
} else {
|
931
|
+
this._dom.classList.add(name);
|
932
|
+
};
|
933
|
+
return this;
|
934
|
+
};
|
935
|
+
|
936
|
+
/*
|
937
|
+
Remove specified flag from node
|
938
|
+
@return {self}
|
939
|
+
*/
|
940
|
+
|
941
|
+
Imba.Tag.prototype.unflag = function (name){
|
942
|
+
this._dom.classList.remove(name);
|
943
|
+
return this;
|
944
|
+
};
|
945
|
+
|
946
|
+
/*
|
947
|
+
Toggle specified flag on node
|
948
|
+
@return {self}
|
949
|
+
*/
|
950
|
+
|
951
|
+
Imba.Tag.prototype.toggleFlag = function (name){
|
952
|
+
this._dom.classList.toggle(name);
|
953
|
+
return this;
|
954
|
+
};
|
955
|
+
|
956
|
+
/*
|
957
|
+
Check whether current node has specified flag
|
958
|
+
@return {bool}
|
959
|
+
*/
|
960
|
+
|
961
|
+
Imba.Tag.prototype.hasFlag = function (name){
|
962
|
+
return this._dom.classList.contains(name);
|
963
|
+
};
|
964
|
+
|
965
|
+
/*
|
966
|
+
Get the scheduler for this node. A new scheduler will be created
|
967
|
+
if it does not already exist.
|
968
|
+
|
969
|
+
@return {Imba.Scheduler}
|
970
|
+
*/
|
971
|
+
|
972
|
+
Imba.Tag.prototype.scheduler = function (){
|
973
|
+
return this._scheduler == null ? (this._scheduler = new Imba.Scheduler(this)) : (this._scheduler);
|
974
|
+
};
|
975
|
+
|
976
|
+
/*
|
977
|
+
|
978
|
+
Shorthand to start scheduling a node. The method will basically
|
979
|
+
proxy the arguments through to scheduler.configure, and then
|
980
|
+
activate the scheduler.
|
981
|
+
|
982
|
+
@return {self}
|
983
|
+
*/
|
984
|
+
|
985
|
+
Imba.Tag.prototype.schedule = function (options){
|
986
|
+
if(options === undefined) options = {};
|
987
|
+
this.scheduler().configure(options).activate();
|
988
|
+
return this;
|
989
|
+
};
|
990
|
+
|
991
|
+
/*
|
992
|
+
Shorthand for deactivating scheduler (if tag has one).
|
993
|
+
@deprecated
|
994
|
+
*/
|
995
|
+
|
996
|
+
Imba.Tag.prototype.unschedule = function (){
|
997
|
+
if (this._scheduler) { this.scheduler().deactivate() };
|
998
|
+
return this;
|
999
|
+
};
|
1000
|
+
|
1001
|
+
|
1002
|
+
/*
|
1003
|
+
Get the parent of current node
|
1004
|
+
@return {Imba.Tag}
|
1005
|
+
*/
|
1006
|
+
|
1007
|
+
Imba.Tag.prototype.parent = function (){
|
1008
|
+
return tag$wrap(this.dom().parentNode);
|
1009
|
+
};
|
1010
|
+
|
1011
|
+
/*
|
1012
|
+
Shorthand for console.log on elements
|
1013
|
+
@return {self}
|
1014
|
+
*/
|
1015
|
+
|
1016
|
+
Imba.Tag.prototype.log = function (){
|
1017
|
+
var $0 = arguments, i = $0.length;
|
1018
|
+
var args = new Array(i>0 ? i : 0);
|
1019
|
+
while(i>0) args[i-1] = $0[--i];
|
1020
|
+
args.unshift(console);
|
1021
|
+
Function.prototype.call.apply(console.log,args);
|
1022
|
+
return this;
|
1023
|
+
};
|
1024
|
+
|
1025
|
+
Imba.Tag.prototype.css = function (key,val){
|
1026
|
+
if (key instanceof Object) {
|
1027
|
+
for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
|
1028
|
+
this.css(keys[i],key[keys[i]]);
|
1029
|
+
};
|
1030
|
+
} else if (val == null) {
|
1031
|
+
this.dom().style.removeProperty(key);
|
1032
|
+
} else if (val == undefined) {
|
1033
|
+
return this.dom().style[key];
|
1034
|
+
} else {
|
1035
|
+
if ((typeof val=='number'||val instanceof Number) && key.match(/width|height|left|right|top|bottom/)) {
|
1036
|
+
val = val + "px";
|
1037
|
+
};
|
1038
|
+
this.dom().style[key] = val;
|
1039
|
+
};
|
1040
|
+
return this;
|
1041
|
+
};
|
1042
|
+
|
1043
|
+
Imba.Tag.prototype.setTransform = function (value){
|
1044
|
+
this.css('transform',value);
|
1045
|
+
return this;
|
1046
|
+
};
|
1047
|
+
|
1048
|
+
Imba.Tag.prototype.transform = function (){
|
1049
|
+
return this.css('transform');
|
1050
|
+
};
|
1051
|
+
|
1052
|
+
|
1053
|
+
Imba.Tag.prototype.initialize = Imba.Tag;
|
1054
|
+
|
1055
|
+
HTML_TAGS = "a abbr address area article aside audio b base bdi bdo big blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hr html i iframe img input ins kbd keygen label legend li link main map mark menu menuitem meta meter nav noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strong style sub summary sup table tbody td textarea tfoot th thead time title tr track u ul var video wbr".split(" ");
|
1056
|
+
HTML_TAGS_UNSAFE = "article aside header section".split(" ");
|
1057
|
+
SVG_TAGS = "circle defs ellipse g line linearGradient mask path pattern polygon polyline radialGradient rect stop svg text tspan".split(" ");
|
1058
|
+
|
1059
|
+
|
1060
|
+
function extender(obj,sup){
|
1061
|
+
for (var i = 0, keys = Object.keys(sup), l = keys.length; i < l; i++){
|
1062
|
+
obj[($1 = keys[i])] == null ? (obj[$1] = sup[keys[i]]) : (obj[$1]);
|
1063
|
+
};
|
1064
|
+
|
1065
|
+
obj.prototype = Object.create(sup.prototype);
|
1066
|
+
obj.__super__ = obj.prototype.__super__ = sup.prototype;
|
1067
|
+
obj.prototype.initialize = obj.prototype.constructor = obj;
|
1068
|
+
if (sup.inherit) { sup.inherit(obj) };
|
1069
|
+
return obj;
|
1070
|
+
};
|
1071
|
+
|
1072
|
+
function Tag(){
|
1073
|
+
return function(dom) {
|
1074
|
+
this.setDom(dom);
|
1075
|
+
return this;
|
1076
|
+
};
|
1077
|
+
};
|
1078
|
+
|
1079
|
+
function TagSpawner(type){
|
1080
|
+
return function() { return type.build(); };
|
1081
|
+
};
|
1082
|
+
|
1083
|
+
Imba.Tags = function Tags(){
|
1084
|
+
this;
|
1085
|
+
};
|
1086
|
+
|
1087
|
+
Imba.Tags.prototype.__clone = function (ns){
|
1088
|
+
var clone = Object.create(this);
|
1089
|
+
clone._parent = this;
|
1090
|
+
return clone;
|
1091
|
+
};
|
1092
|
+
|
1093
|
+
Imba.Tags.prototype.defineNamespace = function (name){
|
1094
|
+
var clone = Object.create(this);
|
1095
|
+
clone._parent = this;
|
1096
|
+
clone._ns = name;
|
1097
|
+
this[name.toUpperCase()] = clone;
|
1098
|
+
return clone;
|
1099
|
+
};
|
1100
|
+
|
1101
|
+
Imba.Tags.prototype.baseType = function (name){
|
1102
|
+
return idx$(name,HTML_TAGS) >= 0 ? ('htmlelement') : ('div');
|
1103
|
+
};
|
1104
|
+
|
1105
|
+
Imba.Tags.prototype.defineTag = function (name,supr,body){
|
1106
|
+
if(body==undefined && typeof supr == 'function') body = supr,supr = '';
|
1107
|
+
if(supr==undefined) supr = '';
|
1108
|
+
supr || (supr = this.baseType(name));
|
1109
|
+
var supertype = this[supr];
|
1110
|
+
var tagtype = Tag();
|
1111
|
+
var norm = name.replace(/\-/g,'_');
|
1112
|
+
|
1113
|
+
|
1114
|
+
tagtype._name = name;
|
1115
|
+
extender(tagtype,supertype);
|
1116
|
+
|
1117
|
+
if (name[0] == '#') {
|
1118
|
+
this[name] = tagtype;
|
1119
|
+
Imba.SINGLETONS[name.slice(1)] = tagtype;
|
1120
|
+
} else {
|
1121
|
+
this[name] = tagtype;
|
1122
|
+
this['$' + norm] = TagSpawner(tagtype);
|
1123
|
+
};
|
1124
|
+
|
1125
|
+
if (body) {
|
1126
|
+
if (body.length == 2) {
|
1127
|
+
// create clone
|
1128
|
+
if (!tagtype.hasOwnProperty('TAGS')) {
|
1129
|
+
tagtype.TAGS = (supertype.TAGS || this).__clone();
|
1130
|
+
};
|
1131
|
+
};
|
1132
|
+
|
1133
|
+
body.call(tagtype,tagtype,tagtype.TAGS || this);
|
1134
|
+
};
|
1135
|
+
|
1136
|
+
return tagtype;
|
1137
|
+
};
|
1138
|
+
|
1139
|
+
Imba.Tags.prototype.defineSingleton = function (name,supr,body){
|
1140
|
+
return this.defineTag(name,supr,body);
|
1141
|
+
};
|
1142
|
+
|
1143
|
+
Imba.Tags.prototype.extendTag = function (name,supr,body){
|
1144
|
+
if(body==undefined && typeof supr == 'function') body = supr,supr = '';
|
1145
|
+
if(supr==undefined) supr = '';
|
1146
|
+
var klass = ((typeof name=='string'||name instanceof String) ? (this[name]) : (name));
|
1147
|
+
// allow for private tags here as well?
|
1148
|
+
if (body) { body && body.call(klass,klass,klass.prototype) };
|
1149
|
+
return klass;
|
1150
|
+
};
|
1151
|
+
|
1152
|
+
|
1153
|
+
Imba.TAGS = new Imba.Tags();
|
1154
|
+
Imba.TAGS.element = Imba.Tag;
|
1155
|
+
|
1156
|
+
var svg = Imba.TAGS.defineNamespace('svg');
|
1157
|
+
|
1158
|
+
svg.baseType = function (name){
|
1159
|
+
return 'svgelement';
|
1160
|
+
};
|
1161
|
+
|
1162
|
+
|
1163
|
+
Imba.SINGLETONS = {};
|
1164
|
+
|
1165
|
+
|
1166
|
+
Imba.defineTag = function (name,supr,body){
|
1167
|
+
if(body==undefined && typeof supr == 'function') body = supr,supr = '';
|
1168
|
+
if(supr==undefined) supr = '';
|
1169
|
+
return Imba.TAGS.defineTag(name,supr,body);
|
1170
|
+
};
|
1171
|
+
|
1172
|
+
Imba.defineSingletonTag = function (id,supr,body){
|
1173
|
+
if(body==undefined && typeof supr == 'function') body = supr,supr = 'div';
|
1174
|
+
if(supr==undefined) supr = 'div';
|
1175
|
+
return Imba.TAGS.defineTag(this.name(),supr,body);
|
1176
|
+
};
|
1177
|
+
|
1178
|
+
Imba.extendTag = function (name,body){
|
1179
|
+
return Imba.TAGS.extendTag(name,body);
|
1180
|
+
};
|
1181
|
+
|
1182
|
+
Imba.tag = function (name){
|
1183
|
+
var typ = Imba.TAGS[name];
|
1184
|
+
if (!(typ)) { throw new Error(("tag " + name + " is not defined")) };
|
1185
|
+
return new typ(typ.createNode());
|
1186
|
+
};
|
1187
|
+
|
1188
|
+
Imba.tagWithId = function (name,id){
|
1189
|
+
var typ = Imba.TAGS[name];
|
1190
|
+
if (!(typ)) { throw new Error(("tag " + name + " is not defined")) };
|
1191
|
+
var dom = typ.createNode();
|
1192
|
+
dom.id = id;
|
1193
|
+
return new typ(dom);
|
1194
|
+
};
|
1195
|
+
|
1196
|
+
// TODO: Can we move these out and into dom.imba in a clean way?
|
1197
|
+
// These methods depends on Imba.document.getElementById
|
1198
|
+
|
1199
|
+
Imba.getTagSingleton = function (id){
|
1200
|
+
var klass;
|
1201
|
+
var dom,node;
|
1202
|
+
|
1203
|
+
if (klass = Imba.SINGLETONS[id]) {
|
1204
|
+
if (klass && klass.Instance) { return klass.Instance };
|
1205
|
+
|
1206
|
+
// no instance - check for element
|
1207
|
+
if (dom = Imba.document().getElementById(id)) {
|
1208
|
+
// we have a live instance - when finding it through a selector we should awake it, no?
|
1209
|
+
// console.log('creating the singleton from existing node in dom?',id,type)
|
1210
|
+
node = klass.Instance = new klass(dom);
|
1211
|
+
node.awaken(dom); // should only awaken
|
1212
|
+
return node;
|
1213
|
+
};
|
1214
|
+
|
1215
|
+
dom = klass.createNode();
|
1216
|
+
dom.id = id;
|
1217
|
+
node = klass.Instance = new klass(dom);
|
1218
|
+
node.end().awaken(dom);
|
1219
|
+
return node;
|
1220
|
+
} else if (dom = Imba.document().getElementById(id)) {
|
1221
|
+
return Imba.getTagForDom(dom);
|
1222
|
+
};
|
1223
|
+
};
|
1224
|
+
|
1225
|
+
var svgSupport = typeof SVGElement !== 'undefined';
|
1226
|
+
|
1227
|
+
Imba.getTagForDom = function (dom){
|
1228
|
+
var m;
|
1229
|
+
if (!(dom)) { return null };
|
1230
|
+
if (dom._dom) { return dom }; // could use inheritance instead
|
1231
|
+
if (dom._tag) { return dom._tag };
|
1232
|
+
if (!dom.nodeName) { return null };
|
1233
|
+
|
1234
|
+
var ns = null;
|
1235
|
+
var id = dom.id;
|
1236
|
+
var type = dom.nodeName.toLowerCase();
|
1237
|
+
var tags = Imba.TAGS;
|
1238
|
+
var native$ = type;
|
1239
|
+
var cls = dom.className;
|
1240
|
+
|
1241
|
+
if (id && Imba.SINGLETONS[id]) {
|
1242
|
+
// FIXME control that it is the same singleton?
|
1243
|
+
// might collide -- not good?
|
1244
|
+
return Imba.getTagSingleton(id);
|
1245
|
+
};
|
1246
|
+
// look for id - singleton
|
1247
|
+
|
1248
|
+
// need better test here
|
1249
|
+
if (svgSupport && (dom instanceof SVGElement)) {
|
1250
|
+
ns = "svg";
|
1251
|
+
cls = dom.className.baseVal;
|
1252
|
+
tags = tags.SVG;
|
1253
|
+
};
|
1254
|
+
|
1255
|
+
var spawner;
|
1256
|
+
|
1257
|
+
if (cls) {
|
1258
|
+
// there can be several matches here - should choose the last
|
1259
|
+
// should fall back to less specific later? - otherwise things may fail
|
1260
|
+
// TODO rework this
|
1261
|
+
if (m = cls.match(/\b_([a-z\-]+)\b(?!\s*_[a-z\-]+)/)) {
|
1262
|
+
type = m[1]; // .replace(/-/g,'_')
|
1263
|
+
};
|
1264
|
+
|
1265
|
+
if (m = cls.match(/\b([A-Z\-]+)_\b/)) {
|
1266
|
+
ns = m[1];
|
1267
|
+
};
|
1268
|
+
};
|
1269
|
+
|
1270
|
+
|
1271
|
+
spawner = tags[type] || tags[native$];
|
1272
|
+
return spawner ? (new spawner(dom).awaken(dom)) : (null);
|
1273
|
+
};
|
1274
|
+
|
1275
|
+
tag$ = Imba.TAGS;
|
1276
|
+
t$ = Imba.tag;
|
1277
|
+
tc$ = Imba.tagWithFlags;
|
1278
|
+
ti$ = Imba.tagWithId;
|
1279
|
+
tic$ = Imba.tagWithIdAndFlags;
|
1280
|
+
id$ = Imba.getTagSingleton;
|
1281
|
+
return tag$wrap = Imba.getTagForDom;
|
1282
|
+
|
1283
|
+
|
1284
|
+
})()
|
1285
|
+
|
1286
|
+
/***/ },
|
1287
|
+
/* 5 */
|
1288
|
+
/***/ function(module, exports) {
|
1289
|
+
|
1290
|
+
(function(){
|
1291
|
+
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
|
1292
|
+
|
1293
|
+
Imba.document = function (){
|
1294
|
+
return window.document;
|
1295
|
+
};
|
1296
|
+
|
1297
|
+
/*
|
1298
|
+
Returns the body element wrapped in an Imba.Tag
|
1299
|
+
*/
|
1300
|
+
|
1301
|
+
Imba.root = function (){
|
1302
|
+
return tag$wrap(Imba.document().body);
|
1303
|
+
};
|
1304
|
+
|
1305
|
+
tag$.defineTag('htmlelement', 'element', function(tag){
|
1306
|
+
|
1307
|
+
/*
|
1308
|
+
Called when a tag type is being subclassed.
|
1309
|
+
*/
|
1310
|
+
|
1311
|
+
tag.inherit = function (child){
|
1312
|
+
child.prototype._empty = true;
|
1313
|
+
child._protoDom = null;
|
1314
|
+
|
1315
|
+
if (this._nodeType) {
|
1316
|
+
child._nodeType = this._nodeType;
|
1317
|
+
|
1318
|
+
var className = "_" + child._name.replace(/_/g,'-');
|
1319
|
+
if (child._name[0] != '#') { return child._classes = this._classes.concat(className) };
|
1320
|
+
} else {
|
1321
|
+
child._nodeType = child._name;
|
1322
|
+
return child._classes = [];
|
1323
|
+
};
|
1324
|
+
};
|
1325
|
+
|
1326
|
+
tag.buildNode = function (){
|
1327
|
+
var dom = Imba.document().createElement(this._nodeType);
|
1328
|
+
var cls = this._classes.join(" ");
|
1329
|
+
if (cls) { dom.className = cls };
|
1330
|
+
return dom;
|
1331
|
+
};
|
1332
|
+
|
1333
|
+
tag.createNode = function (){
|
1334
|
+
var proto = (this._protoDom || (this._protoDom = this.buildNode()));
|
1335
|
+
return proto.cloneNode(false);
|
1336
|
+
};
|
1337
|
+
|
1338
|
+
tag.dom = function (){
|
1339
|
+
return this._protoDom || (this._protoDom = this.buildNode());
|
1340
|
+
};
|
1341
|
+
|
1342
|
+
tag.prototype.id = function(v){ return this.getAttribute('id'); }
|
1343
|
+
tag.prototype.setId = function(v){ this.setAttribute('id',v); return this; };
|
1344
|
+
tag.prototype.tabindex = function(v){ return this.getAttribute('tabindex'); }
|
1345
|
+
tag.prototype.setTabindex = function(v){ this.setAttribute('tabindex',v); return this; };
|
1346
|
+
tag.prototype.title = function(v){ return this.getAttribute('title'); }
|
1347
|
+
tag.prototype.setTitle = function(v){ this.setAttribute('title',v); return this; };
|
1348
|
+
tag.prototype.role = function(v){ return this.getAttribute('role'); }
|
1349
|
+
tag.prototype.setRole = function(v){ this.setAttribute('role',v); return this; };
|
1350
|
+
|
1351
|
+
tag.prototype.width = function (){
|
1352
|
+
return this._dom.offsetWidth;
|
1353
|
+
};
|
1354
|
+
|
1355
|
+
tag.prototype.height = function (){
|
1356
|
+
return this._dom.offsetHeight;
|
1357
|
+
};
|
1358
|
+
|
1359
|
+
tag.prototype.setChildren = function (nodes,type){
|
1360
|
+
this._empty ? (this.append(nodes)) : (this.empty().append(nodes));
|
1361
|
+
this._children = null;
|
1362
|
+
return this;
|
1363
|
+
};
|
1364
|
+
|
1365
|
+
/*
|
1366
|
+
Set inner html of node
|
1367
|
+
*/
|
1368
|
+
|
1369
|
+
tag.prototype.setHtml = function (html){
|
1370
|
+
this._dom.innerHTML = html;
|
1371
|
+
return this;
|
1372
|
+
};
|
1373
|
+
|
1374
|
+
/*
|
1375
|
+
Get inner html of node
|
1376
|
+
*/
|
1377
|
+
|
1378
|
+
tag.prototype.html = function (){
|
1379
|
+
return this._dom.innerHTML;
|
1380
|
+
};
|
1381
|
+
|
1382
|
+
/*
|
1383
|
+
Remove all content inside node
|
1384
|
+
*/
|
1385
|
+
|
1386
|
+
tag.prototype.empty = function (){
|
1387
|
+
while (this._dom.firstChild){
|
1388
|
+
this._dom.removeChild(this._dom.firstChild);
|
1389
|
+
};
|
1390
|
+
this._children = null;
|
1391
|
+
this._empty = true;
|
1392
|
+
return this;
|
1393
|
+
};
|
1394
|
+
|
1395
|
+
/*
|
1396
|
+
Remove specified child from current node.
|
1397
|
+
*/
|
1398
|
+
|
1399
|
+
tag.prototype.remove = function (child){
|
1400
|
+
var par = this.dom();
|
1401
|
+
var el = child && child.dom();
|
1402
|
+
if (el && el.parentNode == par) { par.removeChild(el) };
|
1403
|
+
return this;
|
1404
|
+
};
|
1405
|
+
|
1406
|
+
tag.prototype.emit = function (name,pars){
|
1407
|
+
if(!pars||pars.constructor !== Object) pars = {};
|
1408
|
+
var data = pars.data !== undefined ? pars.data : null;
|
1409
|
+
var bubble = pars.bubble !== undefined ? pars.bubble : true;
|
1410
|
+
Imba.Events.trigger(name,this,{data: data,bubble: bubble});
|
1411
|
+
return this;
|
1412
|
+
};
|
1413
|
+
|
1414
|
+
tag.prototype.dataset = function (key,val){
|
1415
|
+
if (key instanceof Object) {
|
1416
|
+
for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
|
1417
|
+
this.dataset(keys[i],key[keys[i]]);
|
1418
|
+
};
|
1419
|
+
return this;
|
1420
|
+
};
|
1421
|
+
|
1422
|
+
if (arguments.length == 2) {
|
1423
|
+
this.setAttribute(("data-" + key),val);
|
1424
|
+
return this;
|
1425
|
+
};
|
1426
|
+
|
1427
|
+
if (key) {
|
1428
|
+
return this.getAttribute(("data-" + key));
|
1429
|
+
};
|
1430
|
+
|
1431
|
+
var dataset = this.dom().dataset;
|
1432
|
+
|
1433
|
+
if (!(dataset)) {
|
1434
|
+
dataset = {};
|
1435
|
+
for (var i = 0, ary = iter$(this.dom().attributes), len = ary.length, atr; i < len; i++) {
|
1436
|
+
atr = ary[i];
|
1437
|
+
if (atr.name.substr(0,5) == 'data-') {
|
1438
|
+
dataset[Imba.toCamelCase(atr.name.slice(5))] = atr.value;
|
1439
|
+
};
|
1440
|
+
};
|
1441
|
+
};
|
1442
|
+
|
1443
|
+
return dataset;
|
1444
|
+
};
|
1445
|
+
|
1446
|
+
/*
|
1447
|
+
Get descendants of current node, optionally matching selector
|
1448
|
+
@return {Imba.Selector}
|
1449
|
+
*/
|
1450
|
+
|
1451
|
+
tag.prototype.find = function (sel){
|
1452
|
+
return new Imba.Selector(sel,this);
|
1453
|
+
};
|
1454
|
+
|
1455
|
+
/*
|
1456
|
+
Get the first matching child of node
|
1457
|
+
|
1458
|
+
@return {Imba.Tag}
|
1459
|
+
*/
|
1460
|
+
|
1461
|
+
tag.prototype.first = function (sel){
|
1462
|
+
return sel ? (this.find(sel).first()) : (tag$wrap(this.dom().firstElementChild));
|
1463
|
+
};
|
1464
|
+
|
1465
|
+
/*
|
1466
|
+
Get the last matching child of node
|
1467
|
+
|
1468
|
+
node.last # returns the last child of node
|
1469
|
+
node.last %span # returns the last span inside node
|
1470
|
+
node.last do |el| el.text == 'Hi' # return last node with text Hi
|
1471
|
+
|
1472
|
+
@return {Imba.Tag}
|
1473
|
+
*/
|
1474
|
+
|
1475
|
+
tag.prototype.last = function (sel){
|
1476
|
+
return sel ? (this.find(sel).last()) : (tag$wrap(this.dom().lastElementChild));
|
1477
|
+
};
|
1478
|
+
|
1479
|
+
/*
|
1480
|
+
Get the child at index
|
1481
|
+
*/
|
1482
|
+
|
1483
|
+
tag.prototype.child = function (i){
|
1484
|
+
return tag$wrap(this.dom().children[i || 0]);
|
1485
|
+
};
|
1486
|
+
|
1487
|
+
tag.prototype.children = function (sel){
|
1488
|
+
var nodes = new Imba.Selector(null,this,this._dom.children);
|
1489
|
+
return sel ? (nodes.filter(sel)) : (nodes);
|
1490
|
+
};
|
1491
|
+
|
1492
|
+
tag.prototype.orphanize = function (){
|
1493
|
+
var par;
|
1494
|
+
if (par = this.dom().parentNode) { par.removeChild(this._dom) };
|
1495
|
+
return this;
|
1496
|
+
};
|
1497
|
+
|
1498
|
+
tag.prototype.matches = function (sel){
|
1499
|
+
var fn;
|
1500
|
+
if (sel instanceof Function) {
|
1501
|
+
return sel(this);
|
1502
|
+
};
|
1503
|
+
|
1504
|
+
if (sel.query) { sel = sel.query() };
|
1505
|
+
if (fn = (this._dom.matches || this._dom.matchesSelector || this._dom.webkitMatchesSelector || this._dom.msMatchesSelector || this._dom.mozMatchesSelector)) {
|
1506
|
+
return fn.call(this._dom,sel);
|
1507
|
+
};
|
1508
|
+
};
|
1509
|
+
|
1510
|
+
/*
|
1511
|
+
Get the first element matching supplied selector / filter
|
1512
|
+
traversing upwards, but including the node itself.
|
1513
|
+
@return {Imba.Tag}
|
1514
|
+
*/
|
1515
|
+
|
1516
|
+
tag.prototype.closest = function (sel){
|
1517
|
+
if (!(sel)) { return this.parent() }; // should return self?!
|
1518
|
+
var node = this;
|
1519
|
+
if (sel.query) { sel = sel.query() };
|
1520
|
+
|
1521
|
+
while (node){
|
1522
|
+
if (node.matches(sel)) { return node };
|
1523
|
+
node = node.parent();
|
1524
|
+
};
|
1525
|
+
return null;
|
1526
|
+
};
|
1527
|
+
|
1528
|
+
/*
|
1529
|
+
Get the closest ancestor of node that matches
|
1530
|
+
specified selector / matcher.
|
1531
|
+
|
1532
|
+
@return {Imba.Tag}
|
1533
|
+
*/
|
1534
|
+
|
1535
|
+
tag.prototype.up = function (sel){
|
1536
|
+
if (!(sel)) { return this.parent() };
|
1537
|
+
return this.parent() && this.parent().closest(sel);
|
1538
|
+
};
|
1539
|
+
|
1540
|
+
tag.prototype.path = function (sel){
|
1541
|
+
var node = this;
|
1542
|
+
var nodes = [];
|
1543
|
+
if (sel && sel.query) { sel = sel.query() };
|
1544
|
+
|
1545
|
+
while (node){
|
1546
|
+
if (!(sel) || node.matches(sel)) { nodes.push(node) };
|
1547
|
+
node = node.parent();
|
1548
|
+
};
|
1549
|
+
return nodes;
|
1550
|
+
};
|
1551
|
+
|
1552
|
+
tag.prototype.parents = function (sel){
|
1553
|
+
var par = this.parent();
|
1554
|
+
return par ? (par.path(sel)) : ([]);
|
1555
|
+
};
|
1556
|
+
|
1557
|
+
|
1558
|
+
|
1559
|
+
tag.prototype.siblings = function (sel){
|
1560
|
+
var par, self = this;
|
1561
|
+
if (!(par = this.parent())) { return [] }; // FIXME
|
1562
|
+
var ary = this.dom().parentNode.children;
|
1563
|
+
var nodes = new Imba.Selector(null,this,ary);
|
1564
|
+
return nodes.filter(function(n) { return n != self && (!(sel) || n.matches(sel)); });
|
1565
|
+
};
|
1566
|
+
|
1567
|
+
/*
|
1568
|
+
Get the immediately following sibling of node.
|
1569
|
+
*/
|
1570
|
+
|
1571
|
+
tag.prototype.next = function (sel){
|
1572
|
+
if (sel) {
|
1573
|
+
var el = this;
|
1574
|
+
while (el = el.next()){
|
1575
|
+
if (el.matches(sel)) { return el };
|
1576
|
+
};
|
1577
|
+
return null;
|
1578
|
+
};
|
1579
|
+
return tag$wrap(this.dom().nextElementSibling);
|
1580
|
+
};
|
1581
|
+
|
1582
|
+
/*
|
1583
|
+
Get the immediately preceeding sibling of node.
|
1584
|
+
*/
|
1585
|
+
|
1586
|
+
tag.prototype.prev = function (sel){
|
1587
|
+
if (sel) {
|
1588
|
+
var el = this;
|
1589
|
+
while (el = el.prev()){
|
1590
|
+
if (el.matches(sel)) { return el };
|
1591
|
+
};
|
1592
|
+
return null;
|
1593
|
+
};
|
1594
|
+
return tag$wrap(this.dom().previousElementSibling);
|
1595
|
+
};
|
1596
|
+
|
1597
|
+
tag.prototype.contains = function (node){
|
1598
|
+
return this.dom().contains(node && node._dom || node);
|
1599
|
+
};
|
1600
|
+
|
1601
|
+
tag.prototype.index = function (){
|
1602
|
+
var i = 0;
|
1603
|
+
var el = this.dom();
|
1604
|
+
while (el.previousSibling){
|
1605
|
+
el = el.previousSibling;
|
1606
|
+
i++;
|
1607
|
+
};
|
1608
|
+
return i;
|
1609
|
+
};
|
1610
|
+
|
1611
|
+
|
1612
|
+
/*
|
1613
|
+
|
1614
|
+
@deprecated
|
1615
|
+
*/
|
1616
|
+
|
1617
|
+
tag.prototype.insert = function (node,pars){
|
1618
|
+
if(!pars||pars.constructor !== Object) pars = {};
|
1619
|
+
var before = pars.before !== undefined ? pars.before : null;
|
1620
|
+
var after = pars.after !== undefined ? pars.after : null;
|
1621
|
+
if (after) { before = after.next() };
|
1622
|
+
if (node instanceof Array) {
|
1623
|
+
node = (tag$.$fragment().setContent(node,0).end());
|
1624
|
+
};
|
1625
|
+
if (before) {
|
1626
|
+
this.dom().insertBefore(node.dom(),before.dom());
|
1627
|
+
} else {
|
1628
|
+
this.append(node);
|
1629
|
+
};
|
1630
|
+
return this;
|
1631
|
+
};
|
1632
|
+
|
1633
|
+
/*
|
1634
|
+
Focus on current node
|
1635
|
+
@return {self}
|
1636
|
+
*/
|
1637
|
+
|
1638
|
+
tag.prototype.focus = function (){
|
1639
|
+
this.dom().focus();
|
1640
|
+
return this;
|
1641
|
+
};
|
1642
|
+
|
1643
|
+
/*
|
1644
|
+
Remove focus from current node
|
1645
|
+
@return {self}
|
1646
|
+
*/
|
1647
|
+
|
1648
|
+
tag.prototype.blur = function (){
|
1649
|
+
this.dom().blur();
|
1650
|
+
return this;
|
1651
|
+
};
|
1652
|
+
|
1653
|
+
tag.prototype.template = function (){
|
1654
|
+
return null;
|
1655
|
+
};
|
1656
|
+
|
1657
|
+
/*
|
1658
|
+
@todo Should support multiple arguments like append
|
1659
|
+
|
1660
|
+
The .prepend method inserts the specified content as the first
|
1661
|
+
child of the target node. If the content is already a child of
|
1662
|
+
node it will be moved to the start.
|
1663
|
+
|
1664
|
+
node.prepend <div.top> # prepend node
|
1665
|
+
node.prepend "some text" # prepend text
|
1666
|
+
node.prepend [<ul>,<ul>] # prepend array
|
1667
|
+
|
1668
|
+
*/
|
1669
|
+
|
1670
|
+
tag.prototype.prepend = function (item){
|
1671
|
+
var first = this._dom.childNodes[0];
|
1672
|
+
first ? (this.insertBefore(item,first)) : (this.appendChild(item));
|
1673
|
+
return this;
|
1674
|
+
};
|
1675
|
+
|
1676
|
+
/*
|
1677
|
+
The .append method inserts the specified content as the last child
|
1678
|
+
of the target node. If the content is already a child of node it
|
1679
|
+
will be moved to the end.
|
1680
|
+
|
1681
|
+
# example
|
1682
|
+
var root = <div.root>
|
1683
|
+
var item = <div.item> "This is an item"
|
1684
|
+
root.append item # appends item to the end of root
|
1685
|
+
|
1686
|
+
root.prepend "some text" # append text
|
1687
|
+
root.prepend [<ul>,<ul>] # append array
|
1688
|
+
*/
|
1689
|
+
|
1690
|
+
tag.prototype.append = function (item){
|
1691
|
+
// possible to append blank
|
1692
|
+
// possible to simplify on server?
|
1693
|
+
if (!(item)) { return this };
|
1694
|
+
|
1695
|
+
if (item instanceof Array) {
|
1696
|
+
for (var i = 0, ary = iter$(item), len = ary.length, member; i < len; i++) {
|
1697
|
+
member = ary[i];
|
1698
|
+
member && this.append(member);
|
1699
|
+
};
|
1700
|
+
} else if ((typeof item=='string'||item instanceof String) || (typeof item=='number'||item instanceof Number)) {
|
1701
|
+
var node = Imba.document().createTextNode(item);
|
1702
|
+
this._dom.appendChild(node);
|
1703
|
+
if (this._empty) { this._empty = false };
|
1704
|
+
} else {
|
1705
|
+
this._dom.appendChild(item._dom || item);
|
1706
|
+
if (this._empty) { this._empty = false };
|
1707
|
+
};
|
1708
|
+
|
1709
|
+
return this;
|
1710
|
+
};
|
1711
|
+
|
1712
|
+
/*
|
1713
|
+
Insert a node into the current node (self), before another.
|
1714
|
+
The relative node must be a child of current node.
|
1715
|
+
*/
|
1716
|
+
|
1717
|
+
tag.prototype.insertBefore = function (node,rel){
|
1718
|
+
if ((typeof node=='string'||node instanceof String)) { node = Imba.document().createTextNode(node) };
|
1719
|
+
if (node && rel) { this.dom().insertBefore((node._dom || node),(rel._dom || rel)) };
|
1720
|
+
return this;
|
1721
|
+
};
|
1722
|
+
|
1723
|
+
/*
|
1724
|
+
Append a single item (node or string) to the current node.
|
1725
|
+
If supplied item is a string it will automatically. This is used
|
1726
|
+
by Imba internally, but will practically never be used explicitly.
|
1727
|
+
*/
|
1728
|
+
|
1729
|
+
tag.prototype.appendChild = function (node){
|
1730
|
+
if ((typeof node=='string'||node instanceof String)) { node = Imba.document().createTextNode(node) };
|
1731
|
+
if (node) { this.dom().appendChild(node._dom || node) };
|
1732
|
+
return this;
|
1733
|
+
};
|
1734
|
+
|
1735
|
+
/*
|
1736
|
+
Remove a single child from the current node.
|
1737
|
+
Used by Imba internally.
|
1738
|
+
*/
|
1739
|
+
|
1740
|
+
tag.prototype.removeChild = function (node){
|
1741
|
+
if (node) { this.dom().removeChild(node._dom || node) };
|
1742
|
+
return this;
|
1743
|
+
};
|
1744
|
+
|
1745
|
+
tag.prototype.toString = function (){
|
1746
|
+
return this._dom.toString(); // really?
|
1747
|
+
};
|
1748
|
+
|
1749
|
+
/*
|
1750
|
+
@deprecated
|
1751
|
+
*/
|
1752
|
+
|
1753
|
+
tag.prototype.classes = function (){
|
1754
|
+
console.log('Imba.Tag#classes is deprecated');
|
1755
|
+
return this._dom.classList;
|
1756
|
+
};
|
1757
|
+
});
|
1758
|
+
|
1759
|
+
return tag$.defineTag('svgelement', 'htmlelement');
|
1760
|
+
|
1761
|
+
})()
|
1762
|
+
|
1763
|
+
/***/ },
|
1764
|
+
/* 6 */
|
1765
|
+
/***/ function(module, exports) {
|
1766
|
+
|
1767
|
+
(function(){
|
1768
|
+
|
1769
|
+
// predefine all supported html tags
|
1770
|
+
tag$.defineTag('fragment', 'htmlelement', function(tag){
|
1771
|
+
|
1772
|
+
tag.createNode = function (){
|
1773
|
+
return Imba.document().createDocumentFragment();
|
1774
|
+
};
|
1775
|
+
});
|
1776
|
+
|
1777
|
+
tag$.defineTag('a', function(tag){
|
1778
|
+
tag.prototype.href = function(v){ return this.getAttribute('href'); }
|
1779
|
+
tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
|
1780
|
+
});
|
1781
|
+
|
1782
|
+
tag$.defineTag('abbr');
|
1783
|
+
tag$.defineTag('address');
|
1784
|
+
tag$.defineTag('area');
|
1785
|
+
tag$.defineTag('article');
|
1786
|
+
tag$.defineTag('aside');
|
1787
|
+
tag$.defineTag('audio');
|
1788
|
+
tag$.defineTag('b');
|
1789
|
+
tag$.defineTag('base');
|
1790
|
+
tag$.defineTag('bdi');
|
1791
|
+
tag$.defineTag('bdo');
|
1792
|
+
tag$.defineTag('big');
|
1793
|
+
tag$.defineTag('blockquote');
|
1794
|
+
tag$.defineTag('body');
|
1795
|
+
tag$.defineTag('br');
|
1796
|
+
|
1797
|
+
tag$.defineTag('button', function(tag){
|
1798
|
+
tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
|
1799
|
+
tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
|
1800
|
+
tag.prototype.type = function(v){ return this.getAttribute('type'); }
|
1801
|
+
tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
|
1802
|
+
tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
|
1803
|
+
tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
|
1804
|
+
});
|
1805
|
+
|
1806
|
+
tag$.defineTag('canvas', function(tag){
|
1807
|
+
tag.prototype.setWidth = function (val){
|
1808
|
+
if (this.width() != val) { this.dom().width = val };
|
1809
|
+
return this;
|
1810
|
+
};
|
1811
|
+
|
1812
|
+
tag.prototype.setHeight = function (val){
|
1813
|
+
if (this.height() != val) { this.dom().height = val };
|
1814
|
+
return this;
|
1815
|
+
};
|
1816
|
+
|
1817
|
+
tag.prototype.width = function (){
|
1818
|
+
return this.dom().width;
|
1819
|
+
};
|
1820
|
+
|
1821
|
+
tag.prototype.height = function (){
|
1822
|
+
return this.dom().height;
|
1823
|
+
};
|
1824
|
+
|
1825
|
+
tag.prototype.context = function (type){
|
1826
|
+
if(type === undefined) type = '2d';
|
1827
|
+
return this.dom().getContext(type);
|
1828
|
+
};
|
1829
|
+
});
|
1830
|
+
|
1831
|
+
tag$.defineTag('caption');
|
1832
|
+
tag$.defineTag('cite');
|
1833
|
+
tag$.defineTag('code');
|
1834
|
+
tag$.defineTag('col');
|
1835
|
+
tag$.defineTag('colgroup');
|
1836
|
+
tag$.defineTag('data');
|
1837
|
+
tag$.defineTag('datalist');
|
1838
|
+
tag$.defineTag('dd');
|
1839
|
+
tag$.defineTag('del');
|
1840
|
+
tag$.defineTag('details');
|
1841
|
+
tag$.defineTag('dfn');
|
1842
|
+
tag$.defineTag('div');
|
1843
|
+
tag$.defineTag('dl');
|
1844
|
+
tag$.defineTag('dt');
|
1845
|
+
tag$.defineTag('em');
|
1846
|
+
tag$.defineTag('embed');
|
1847
|
+
tag$.defineTag('fieldset');
|
1848
|
+
tag$.defineTag('figcaption');
|
1849
|
+
tag$.defineTag('figure');
|
1850
|
+
tag$.defineTag('footer');
|
1851
|
+
|
1852
|
+
tag$.defineTag('form', function(tag){
|
1853
|
+
tag.prototype.method = function(v){ return this.getAttribute('method'); }
|
1854
|
+
tag.prototype.setMethod = function(v){ this.setAttribute('method',v); return this; };
|
1855
|
+
tag.prototype.action = function(v){ return this.getAttribute('action'); }
|
1856
|
+
tag.prototype.setAction = function(v){ this.setAttribute('action',v); return this; };
|
1857
|
+
});
|
1858
|
+
|
1859
|
+
tag$.defineTag('h1');
|
1860
|
+
tag$.defineTag('h2');
|
1861
|
+
tag$.defineTag('h3');
|
1862
|
+
tag$.defineTag('h4');
|
1863
|
+
tag$.defineTag('h5');
|
1864
|
+
tag$.defineTag('h6');
|
1865
|
+
tag$.defineTag('head');
|
1866
|
+
tag$.defineTag('header');
|
1867
|
+
tag$.defineTag('hr');
|
1868
|
+
tag$.defineTag('html');
|
1869
|
+
tag$.defineTag('i');
|
1870
|
+
|
1871
|
+
tag$.defineTag('iframe', function(tag){
|
1872
|
+
tag.prototype.src = function(v){ return this.getAttribute('src'); }
|
1873
|
+
tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
|
1874
|
+
});
|
1875
|
+
|
1876
|
+
tag$.defineTag('img', function(tag){
|
1877
|
+
tag.prototype.src = function(v){ return this.getAttribute('src'); }
|
1878
|
+
tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
|
1879
|
+
});
|
1880
|
+
|
1881
|
+
tag$.defineTag('input', function(tag){
|
1882
|
+
// can use attr instead
|
1883
|
+
tag.prototype.name = function(v){ return this.getAttribute('name'); }
|
1884
|
+
tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
|
1885
|
+
tag.prototype.type = function(v){ return this.getAttribute('type'); }
|
1886
|
+
tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
|
1887
|
+
tag.prototype.required = function(v){ return this.getAttribute('required'); }
|
1888
|
+
tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
|
1889
|
+
tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
|
1890
|
+
tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
|
1891
|
+
tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
|
1892
|
+
tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
|
1893
|
+
|
1894
|
+
tag.prototype.value = function (){
|
1895
|
+
return this.dom().value;
|
1896
|
+
};
|
1897
|
+
|
1898
|
+
tag.prototype.setValue = function (v){
|
1899
|
+
if (v != this.dom().value) { this.dom().value = v };
|
1900
|
+
return this;
|
1901
|
+
};
|
1902
|
+
|
1903
|
+
tag.prototype.setPlaceholder = function (v){
|
1904
|
+
if (v != this.dom().placeholder) { this.dom().placeholder = v };
|
1905
|
+
return this;
|
1906
|
+
};
|
1907
|
+
|
1908
|
+
tag.prototype.placeholder = function (){
|
1909
|
+
return this.dom().placeholder;
|
1910
|
+
};
|
1911
|
+
|
1912
|
+
tag.prototype.checked = function (){
|
1913
|
+
return this.dom().checked;
|
1914
|
+
};
|
1915
|
+
|
1916
|
+
tag.prototype.setChecked = function (bool){
|
1917
|
+
if (bool != this.dom().checked) { this.dom().checked = bool };
|
1918
|
+
return this;
|
1919
|
+
};
|
1920
|
+
});
|
1921
|
+
|
1922
|
+
tag$.defineTag('ins');
|
1923
|
+
tag$.defineTag('kbd');
|
1924
|
+
tag$.defineTag('keygen');
|
1925
|
+
tag$.defineTag('label');
|
1926
|
+
tag$.defineTag('legend');
|
1927
|
+
tag$.defineTag('li');
|
1928
|
+
|
1929
|
+
tag$.defineTag('link', function(tag){
|
1930
|
+
tag.prototype.rel = function(v){ return this.getAttribute('rel'); }
|
1931
|
+
tag.prototype.setRel = function(v){ this.setAttribute('rel',v); return this; };
|
1932
|
+
tag.prototype.type = function(v){ return this.getAttribute('type'); }
|
1933
|
+
tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
|
1934
|
+
tag.prototype.href = function(v){ return this.getAttribute('href'); }
|
1935
|
+
tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
|
1936
|
+
tag.prototype.media = function(v){ return this.getAttribute('media'); }
|
1937
|
+
tag.prototype.setMedia = function(v){ this.setAttribute('media',v); return this; };
|
1938
|
+
});
|
1939
|
+
|
1940
|
+
tag$.defineTag('main');
|
1941
|
+
tag$.defineTag('map');
|
1942
|
+
tag$.defineTag('mark');
|
1943
|
+
tag$.defineTag('menu');
|
1944
|
+
tag$.defineTag('menuitem');
|
1945
|
+
|
1946
|
+
tag$.defineTag('meta', function(tag){
|
1947
|
+
tag.prototype.name = function(v){ return this.getAttribute('name'); }
|
1948
|
+
tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
|
1949
|
+
tag.prototype.content = function(v){ return this.getAttribute('content'); }
|
1950
|
+
tag.prototype.setContent = function(v){ this.setAttribute('content',v); return this; };
|
1951
|
+
tag.prototype.charset = function(v){ return this.getAttribute('charset'); }
|
1952
|
+
tag.prototype.setCharset = function(v){ this.setAttribute('charset',v); return this; };
|
1953
|
+
});
|
1954
|
+
|
1955
|
+
tag$.defineTag('meter');
|
1956
|
+
tag$.defineTag('nav');
|
1957
|
+
tag$.defineTag('noscript');
|
1958
|
+
tag$.defineTag('object');
|
1959
|
+
tag$.defineTag('ol');
|
1960
|
+
tag$.defineTag('optgroup');
|
1961
|
+
|
1962
|
+
tag$.defineTag('option', function(tag){
|
1963
|
+
tag.prototype.value = function(v){ return this.getAttribute('value'); }
|
1964
|
+
tag.prototype.setValue = function(v){ this.setAttribute('value',v); return this; };
|
1965
|
+
});
|
1966
|
+
|
1967
|
+
tag$.defineTag('output');
|
1968
|
+
tag$.defineTag('p');
|
1969
|
+
tag$.defineTag('param');
|
1970
|
+
tag$.defineTag('pre');
|
1971
|
+
tag$.defineTag('progress');
|
1972
|
+
tag$.defineTag('q');
|
1973
|
+
tag$.defineTag('rp');
|
1974
|
+
tag$.defineTag('rt');
|
1975
|
+
tag$.defineTag('ruby');
|
1976
|
+
tag$.defineTag('s');
|
1977
|
+
tag$.defineTag('samp');
|
1978
|
+
|
1979
|
+
tag$.defineTag('script', function(tag){
|
1980
|
+
tag.prototype.src = function(v){ return this.getAttribute('src'); }
|
1981
|
+
tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
|
1982
|
+
tag.prototype.type = function(v){ return this.getAttribute('type'); }
|
1983
|
+
tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
|
1984
|
+
tag.prototype.async = function(v){ return this.getAttribute('async'); }
|
1985
|
+
tag.prototype.setAsync = function(v){ this.setAttribute('async',v); return this; };
|
1986
|
+
tag.prototype.defer = function(v){ return this.getAttribute('defer'); }
|
1987
|
+
tag.prototype.setDefer = function(v){ this.setAttribute('defer',v); return this; };
|
1988
|
+
});
|
1989
|
+
|
1990
|
+
tag$.defineTag('section');
|
1991
|
+
|
1992
|
+
tag$.defineTag('select', function(tag){
|
1993
|
+
tag.prototype.name = function(v){ return this.getAttribute('name'); }
|
1994
|
+
tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
|
1995
|
+
tag.prototype.multiple = function(v){ return this.getAttribute('multiple'); }
|
1996
|
+
tag.prototype.setMultiple = function(v){ this.setAttribute('multiple',v); return this; };
|
1997
|
+
tag.prototype.required = function(v){ return this.getAttribute('required'); }
|
1998
|
+
tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
|
1999
|
+
tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
|
2000
|
+
tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
|
2001
|
+
|
2002
|
+
tag.prototype.value = function (){
|
2003
|
+
return this.dom().value;
|
2004
|
+
};
|
2005
|
+
|
2006
|
+
tag.prototype.setValue = function (v){
|
2007
|
+
if (v != this.dom().value) { this.dom().value = v };
|
2008
|
+
return this;
|
2009
|
+
};
|
2010
|
+
});
|
2011
|
+
|
2012
|
+
|
2013
|
+
tag$.defineTag('small');
|
2014
|
+
tag$.defineTag('source');
|
2015
|
+
tag$.defineTag('span');
|
2016
|
+
tag$.defineTag('strong');
|
2017
|
+
tag$.defineTag('style');
|
2018
|
+
tag$.defineTag('sub');
|
2019
|
+
tag$.defineTag('summary');
|
2020
|
+
tag$.defineTag('sup');
|
2021
|
+
tag$.defineTag('table');
|
2022
|
+
tag$.defineTag('tbody');
|
2023
|
+
tag$.defineTag('td');
|
2024
|
+
|
2025
|
+
tag$.defineTag('textarea', function(tag){
|
2026
|
+
tag.prototype.name = function(v){ return this.getAttribute('name'); }
|
2027
|
+
tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
|
2028
|
+
tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
|
2029
|
+
tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
|
2030
|
+
tag.prototype.required = function(v){ return this.getAttribute('required'); }
|
2031
|
+
tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
|
2032
|
+
tag.prototype.rows = function(v){ return this.getAttribute('rows'); }
|
2033
|
+
tag.prototype.setRows = function(v){ this.setAttribute('rows',v); return this; };
|
2034
|
+
tag.prototype.cols = function(v){ return this.getAttribute('cols'); }
|
2035
|
+
tag.prototype.setCols = function(v){ this.setAttribute('cols',v); return this; };
|
2036
|
+
tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
|
2037
|
+
tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
|
2038
|
+
|
2039
|
+
tag.prototype.value = function (){
|
2040
|
+
return this.dom().value;
|
2041
|
+
};
|
2042
|
+
|
2043
|
+
tag.prototype.setValue = function (v){
|
2044
|
+
if (v != this.dom().value) { this.dom().value = v };
|
2045
|
+
return this;
|
2046
|
+
};
|
2047
|
+
|
2048
|
+
tag.prototype.setPlaceholder = function (v){
|
2049
|
+
if (v != this.dom().placeholder) { this.dom().placeholder = v };
|
2050
|
+
return this;
|
2051
|
+
};
|
2052
|
+
|
2053
|
+
tag.prototype.placeholder = function (){
|
2054
|
+
return this.dom().placeholder;
|
2055
|
+
};
|
2056
|
+
});
|
2057
|
+
|
2058
|
+
tag$.defineTag('tfoot');
|
2059
|
+
tag$.defineTag('th');
|
2060
|
+
tag$.defineTag('thead');
|
2061
|
+
tag$.defineTag('time');
|
2062
|
+
tag$.defineTag('title');
|
2063
|
+
tag$.defineTag('tr');
|
2064
|
+
tag$.defineTag('track');
|
2065
|
+
tag$.defineTag('u');
|
2066
|
+
tag$.defineTag('ul');
|
2067
|
+
tag$.defineTag('video');
|
2068
|
+
return tag$.defineTag('wbr');
|
2069
|
+
|
2070
|
+
})()
|
2071
|
+
|
2072
|
+
/***/ },
|
2073
|
+
/* 7 */
|
2074
|
+
/***/ function(module, exports) {
|
2075
|
+
|
2076
|
+
(function(){
|
2077
|
+
function idx$(a,b){
|
2078
|
+
return (b && b.indexOf) ? b.indexOf(a) : [].indexOf.call(a,b);
|
2079
|
+
};
|
2080
|
+
|
2081
|
+
|
2082
|
+
tag$.SVG.defineTag('svgelement', function(tag){
|
2083
|
+
|
2084
|
+
tag.namespaceURI = function (){
|
2085
|
+
return "http://www.w3.org/2000/svg";
|
2086
|
+
};
|
2087
|
+
|
2088
|
+
var types = "circle defs ellipse g line linearGradient mask path pattern polygon polyline radialGradient rect stop svg text tspan".split(" ");
|
2089
|
+
|
2090
|
+
tag.buildNode = function (){
|
2091
|
+
var dom = Imba.document().createElementNS(this.namespaceURI(),this._nodeType);
|
2092
|
+
var cls = this._classes.join(" ");
|
2093
|
+
if (cls) { dom.className.baseVal = cls };
|
2094
|
+
return dom;
|
2095
|
+
};
|
2096
|
+
|
2097
|
+
tag.inherit = function (child){
|
2098
|
+
child._protoDom = null;
|
2099
|
+
|
2100
|
+
if (idx$(child._name,types) >= 0) {
|
2101
|
+
child._nodeType = child._name;
|
2102
|
+
return child._classes = [];
|
2103
|
+
} else {
|
2104
|
+
child._nodeType = this._nodeType;
|
2105
|
+
var className = "_" + child._name.replace(/_/g,'-');
|
2106
|
+
return child._classes = this._classes.concat(className);
|
2107
|
+
};
|
2108
|
+
};
|
2109
|
+
|
2110
|
+
|
2111
|
+
Imba.attr(tag,'x');
|
2112
|
+
Imba.attr(tag,'y');
|
2113
|
+
|
2114
|
+
Imba.attr(tag,'width');
|
2115
|
+
Imba.attr(tag,'height');
|
2116
|
+
|
2117
|
+
Imba.attr(tag,'stroke');
|
2118
|
+
Imba.attr(tag,'stroke-width');
|
2119
|
+
});
|
2120
|
+
|
2121
|
+
tag$.SVG.defineTag('svg', function(tag){
|
2122
|
+
Imba.attr(tag,'viewbox');
|
2123
|
+
});
|
2124
|
+
|
2125
|
+
tag$.SVG.defineTag('g');
|
2126
|
+
|
2127
|
+
tag$.SVG.defineTag('defs');
|
2128
|
+
|
2129
|
+
tag$.SVG.defineTag('symbol', function(tag){
|
2130
|
+
Imba.attr(tag,'preserveAspectRatio');
|
2131
|
+
Imba.attr(tag,'viewBox');
|
2132
|
+
});
|
2133
|
+
|
2134
|
+
tag$.SVG.defineTag('marker', function(tag){
|
2135
|
+
Imba.attr(tag,'markerUnits');
|
2136
|
+
Imba.attr(tag,'refX');
|
2137
|
+
Imba.attr(tag,'refY');
|
2138
|
+
Imba.attr(tag,'markerWidth');
|
2139
|
+
Imba.attr(tag,'markerHeight');
|
2140
|
+
Imba.attr(tag,'orient');
|
2141
|
+
});
|
2142
|
+
|
2143
|
+
|
2144
|
+
// Basic shapes
|
2145
|
+
|
2146
|
+
tag$.SVG.defineTag('rect', function(tag){
|
2147
|
+
Imba.attr(tag,'rx');
|
2148
|
+
Imba.attr(tag,'ry');
|
2149
|
+
});
|
2150
|
+
|
2151
|
+
tag$.SVG.defineTag('circle', function(tag){
|
2152
|
+
Imba.attr(tag,'cx');
|
2153
|
+
Imba.attr(tag,'cy');
|
2154
|
+
Imba.attr(tag,'r');
|
2155
|
+
});
|
2156
|
+
|
2157
|
+
tag$.SVG.defineTag('ellipse', function(tag){
|
2158
|
+
Imba.attr(tag,'cx');
|
2159
|
+
Imba.attr(tag,'cy');
|
2160
|
+
Imba.attr(tag,'rx');
|
2161
|
+
Imba.attr(tag,'ry');
|
2162
|
+
});
|
2163
|
+
|
2164
|
+
tag$.SVG.defineTag('path', function(tag){
|
2165
|
+
Imba.attr(tag,'d');
|
2166
|
+
Imba.attr(tag,'pathLength');
|
2167
|
+
});
|
2168
|
+
|
2169
|
+
tag$.SVG.defineTag('line', function(tag){
|
2170
|
+
Imba.attr(tag,'x1');
|
2171
|
+
Imba.attr(tag,'x2');
|
2172
|
+
Imba.attr(tag,'y1');
|
2173
|
+
Imba.attr(tag,'y2');
|
2174
|
+
});
|
2175
|
+
|
2176
|
+
tag$.SVG.defineTag('polyline', function(tag){
|
2177
|
+
Imba.attr(tag,'points');
|
2178
|
+
});
|
2179
|
+
|
2180
|
+
tag$.SVG.defineTag('polygon', function(tag){
|
2181
|
+
Imba.attr(tag,'points');
|
2182
|
+
});
|
2183
|
+
|
2184
|
+
tag$.SVG.defineTag('text', function(tag){
|
2185
|
+
Imba.attr(tag,'dx');
|
2186
|
+
Imba.attr(tag,'dy');
|
2187
|
+
Imba.attr(tag,'text-anchor');
|
2188
|
+
Imba.attr(tag,'rotate');
|
2189
|
+
Imba.attr(tag,'textLength');
|
2190
|
+
Imba.attr(tag,'lengthAdjust');
|
2191
|
+
});
|
2192
|
+
|
2193
|
+
return tag$.SVG.defineTag('tspan', function(tag){
|
2194
|
+
Imba.attr(tag,'dx');
|
2195
|
+
Imba.attr(tag,'dy');
|
2196
|
+
Imba.attr(tag,'rotate');
|
2197
|
+
Imba.attr(tag,'textLength');
|
2198
|
+
Imba.attr(tag,'lengthAdjust');
|
2199
|
+
});
|
2200
|
+
|
2201
|
+
})()
|
2202
|
+
|
2203
|
+
/***/ },
|
2204
|
+
/* 8 */
|
2205
|
+
/***/ function(module, exports, __webpack_require__) {
|
2206
|
+
|
2207
|
+
(function(){
|
2208
|
+
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
|
2209
|
+
// Extending Imba.Tag#css to work without prefixes by inspecting
|
2210
|
+
// the properties of a CSSStyleDeclaration and creating a map
|
2211
|
+
|
2212
|
+
// var prefixes = ['-webkit-','-ms-','-moz-','-o-','-blink-']
|
2213
|
+
// var props = ['transform','transition','animation']
|
2214
|
+
|
2215
|
+
if (true) {
|
2216
|
+
var styles = window.getComputedStyle(document.documentElement,'');
|
2217
|
+
|
2218
|
+
Imba.CSSKeyMap = {};
|
2219
|
+
|
2220
|
+
for (var i = 0, ary = iter$(styles), len = ary.length, prefixed; i < len; i++) {
|
2221
|
+
prefixed = ary[i];
|
2222
|
+
var unprefixed = prefixed.replace(/^-(webkit|ms|moz|o|blink)-/,'');
|
2223
|
+
var camelCase = unprefixed.replace(/-(\w)/g,function(m,a) { return a.toUpperCase(); });
|
2224
|
+
|
2225
|
+
// if there exists an unprefixed version -- always use this
|
2226
|
+
if (prefixed != unprefixed) {
|
2227
|
+
if (styles.hasOwnProperty(unprefixed)) { continue; };
|
2228
|
+
};
|
2229
|
+
|
2230
|
+
// register the prefixes
|
2231
|
+
Imba.CSSKeyMap[unprefixed] = Imba.CSSKeyMap[camelCase] = prefixed;
|
2232
|
+
};
|
2233
|
+
|
2234
|
+
tag$.extendTag('element', function(tag){
|
2235
|
+
|
2236
|
+
// override the original css method
|
2237
|
+
tag.prototype.css = function (key,val){
|
2238
|
+
if (key instanceof Object) {
|
2239
|
+
for (var i = 0, keys = Object.keys(key), l = keys.length; i < l; i++){
|
2240
|
+
this.css(keys[i],key[keys[i]]);
|
2241
|
+
};
|
2242
|
+
return this;
|
2243
|
+
};
|
2244
|
+
|
2245
|
+
key = Imba.CSSKeyMap[key] || key;
|
2246
|
+
|
2247
|
+
if (val == null) {
|
2248
|
+
this.dom().style.removeProperty(key);
|
2249
|
+
} else if (val == undefined) {
|
2250
|
+
return this.dom().style[key];
|
2251
|
+
} else {
|
2252
|
+
if ((typeof val=='number'||val instanceof Number) && key.match(/width|height|left|right|top|bottom/)) {
|
2253
|
+
val = val + "px";
|
2254
|
+
};
|
2255
|
+
this.dom().style[key] = val;
|
2256
|
+
};
|
2257
|
+
return this;
|
2258
|
+
};
|
2259
|
+
});
|
2260
|
+
|
2261
|
+
if (!document.documentElement.classList) {
|
2262
|
+
tag$.extendTag('element', function(tag){
|
2263
|
+
|
2264
|
+
tag.prototype.hasFlag = function (ref){
|
2265
|
+
return new RegExp('(^|\\s)' + ref + '(\\s|$)').test(this._dom.className);
|
2266
|
+
};
|
2267
|
+
|
2268
|
+
tag.prototype.addFlag = function (ref){
|
2269
|
+
if (this.hasFlag(ref)) { return this };
|
2270
|
+
this._dom.className += (this._dom.className ? (' ') : ('')) + ref;
|
2271
|
+
return this;
|
2272
|
+
};
|
2273
|
+
|
2274
|
+
tag.prototype.unflag = function (ref){
|
2275
|
+
if (!this.hasFlag(ref)) { return this };
|
2276
|
+
var regex = new RegExp('(^|\\s)*' + ref + '(\\s|$)*','g');
|
2277
|
+
this._dom.className = this._dom.className.replace(regex,'');
|
2278
|
+
return this;
|
2279
|
+
};
|
2280
|
+
|
2281
|
+
tag.prototype.toggleFlag = function (ref){
|
2282
|
+
return this.hasFlag(ref) ? (this.unflag(ref)) : (this.flag(ref));
|
2283
|
+
};
|
2284
|
+
|
2285
|
+
tag.prototype.flag = function (ref,bool){
|
2286
|
+
if (arguments.length == 2 && !(!(bool)) === false) {
|
2287
|
+
return this.unflag(ref);
|
2288
|
+
};
|
2289
|
+
return this.addFlag(ref);
|
2290
|
+
};
|
2291
|
+
});
|
2292
|
+
return true;
|
2293
|
+
};
|
2294
|
+
};
|
2295
|
+
|
2296
|
+
})()
|
2297
|
+
|
2298
|
+
/***/ },
|
2299
|
+
/* 9 */
|
2300
|
+
/***/ function(module, exports) {
|
2301
|
+
|
2302
|
+
(function(){
|
2303
|
+
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
|
2304
|
+
var doc = document;
|
2305
|
+
var win = window;
|
2306
|
+
|
2307
|
+
var hasTouchEvents = window && window.ontouchstart !== undefined;
|
2308
|
+
|
2309
|
+
Imba.Pointer = function Pointer(){
|
2310
|
+
this.setButton(-1);
|
2311
|
+
this.setEvent({x: 0,y: 0,type: 'uninitialized'});
|
2312
|
+
return this;
|
2313
|
+
};
|
2314
|
+
|
2315
|
+
Imba.Pointer.prototype.phase = function(v){ return this._phase; }
|
2316
|
+
Imba.Pointer.prototype.setPhase = function(v){ this._phase = v; return this; };
|
2317
|
+
Imba.Pointer.prototype.prevEvent = function(v){ return this._prevEvent; }
|
2318
|
+
Imba.Pointer.prototype.setPrevEvent = function(v){ this._prevEvent = v; return this; };
|
2319
|
+
Imba.Pointer.prototype.button = function(v){ return this._button; }
|
2320
|
+
Imba.Pointer.prototype.setButton = function(v){ this._button = v; return this; };
|
2321
|
+
Imba.Pointer.prototype.event = function(v){ return this._event; }
|
2322
|
+
Imba.Pointer.prototype.setEvent = function(v){ this._event = v; return this; };
|
2323
|
+
Imba.Pointer.prototype.dirty = function(v){ return this._dirty; }
|
2324
|
+
Imba.Pointer.prototype.setDirty = function(v){ this._dirty = v; return this; };
|
2325
|
+
Imba.Pointer.prototype.events = function(v){ return this._events; }
|
2326
|
+
Imba.Pointer.prototype.setEvents = function(v){ this._events = v; return this; };
|
2327
|
+
Imba.Pointer.prototype.touch = function(v){ return this._touch; }
|
2328
|
+
Imba.Pointer.prototype.setTouch = function(v){ this._touch = v; return this; };
|
2329
|
+
|
2330
|
+
Imba.Pointer.prototype.update = function (e){
|
2331
|
+
this.setEvent(e);
|
2332
|
+
this.setDirty(true);
|
2333
|
+
return this;
|
2334
|
+
};
|
2335
|
+
|
2336
|
+
// this is just for regular mouse now
|
2337
|
+
Imba.Pointer.prototype.process = function (){
|
2338
|
+
var e1 = this.event();
|
2339
|
+
|
2340
|
+
if (this.dirty()) {
|
2341
|
+
this.setPrevEvent(e1);
|
2342
|
+
this.setDirty(false);
|
2343
|
+
|
2344
|
+
// button should only change on mousedown etc
|
2345
|
+
if (e1.type == 'mousedown') {
|
2346
|
+
this.setButton(e1.button);
|
2347
|
+
|
2348
|
+
// do not create touch for right click
|
2349
|
+
if (this.button() == 2 || (this.touch() && this.button() != 0)) {
|
2350
|
+
return;
|
2351
|
+
};
|
2352
|
+
|
2353
|
+
// cancel the previous touch
|
2354
|
+
if (this.touch()) { this.touch().cancel() };
|
2355
|
+
this.setTouch(new Imba.Touch(e1,this));
|
2356
|
+
this.touch().mousedown(e1,e1);
|
2357
|
+
} else if (e1.type == 'mousemove') {
|
2358
|
+
if (this.touch()) { this.touch().mousemove(e1,e1) };
|
2359
|
+
} else if (e1.type == 'mouseup') {
|
2360
|
+
this.setButton(-1);
|
2361
|
+
|
2362
|
+
if (this.touch() && this.touch().button() == e1.button) {
|
2363
|
+
this.touch().mouseup(e1,e1);
|
2364
|
+
this.setTouch(null);
|
2365
|
+
};
|
2366
|
+
// trigger pointerup
|
2367
|
+
};
|
2368
|
+
} else {
|
2369
|
+
if (this.touch()) { this.touch().idle() };
|
2370
|
+
};
|
2371
|
+
return this;
|
2372
|
+
};
|
2373
|
+
|
2374
|
+
Imba.Pointer.prototype.cleanup = function (){
|
2375
|
+
return Imba.POINTERS;
|
2376
|
+
};
|
2377
|
+
|
2378
|
+
Imba.Pointer.prototype.x = function (){
|
2379
|
+
return this.event().x;
|
2380
|
+
};
|
2381
|
+
Imba.Pointer.prototype.y = function (){
|
2382
|
+
return this.event().y;
|
2383
|
+
};
|
2384
|
+
|
2385
|
+
// deprecated -- should remove
|
2386
|
+
Imba.Pointer.update = function (){
|
2387
|
+
// console.log('update touch')
|
2388
|
+
for (var i = 0, ary = iter$(Imba.POINTERS), len = ary.length; i < len; i++) {
|
2389
|
+
ary[i].process();
|
2390
|
+
};
|
2391
|
+
// need to be able to prevent the default behaviour of touch, no?
|
2392
|
+
win.requestAnimationFrame(Imba.Pointer.update);
|
2393
|
+
return this;
|
2394
|
+
};
|
2395
|
+
|
2396
|
+
var lastNativeTouchTimeStamp = 0;
|
2397
|
+
var lastNativeTouchTimeout = 50;
|
2398
|
+
|
2399
|
+
// Imba.Touch
|
2400
|
+
// Began A finger touched the screen.
|
2401
|
+
// Moved A finger moved on the screen.
|
2402
|
+
// Stationary A finger is touching the screen but hasn't moved.
|
2403
|
+
// Ended A finger was lifted from the screen. This is the final phase of a touch.
|
2404
|
+
// Canceled The system cancelled tracking for the touch.
|
2405
|
+
|
2406
|
+
/*
|
2407
|
+
Consolidates mouse and touch events. Touch objects persist across a touch,
|
2408
|
+
from touchstart until end/cancel. When a touch starts, it will traverse
|
2409
|
+
down from the innermost target, until it finds a node that responds to
|
2410
|
+
ontouchstart. Unless the touch is explicitly redirected, the touch will
|
2411
|
+
call ontouchmove and ontouchend / ontouchcancel on the responder when appropriate.
|
2412
|
+
|
2413
|
+
tag draggable
|
2414
|
+
# called when a touch starts
|
2415
|
+
def ontouchstart touch
|
2416
|
+
flag 'dragging'
|
2417
|
+
self
|
2418
|
+
|
2419
|
+
# called when touch moves - same touch object
|
2420
|
+
def ontouchmove touch
|
2421
|
+
# move the node with touch
|
2422
|
+
css top: touch.dy, left: touch.dx
|
2423
|
+
|
2424
|
+
# called when touch ends
|
2425
|
+
def ontouchend touch
|
2426
|
+
unflag 'dragging'
|
2427
|
+
|
2428
|
+
@iname touch
|
2429
|
+
*/
|
2430
|
+
|
2431
|
+
Imba.Touch = function Touch(event,pointer){
|
2432
|
+
// @native = false
|
2433
|
+
this.setEvent(event);
|
2434
|
+
this.setData({});
|
2435
|
+
this.setActive(true);
|
2436
|
+
this._button = event && event.button || 0;
|
2437
|
+
this._suppress = false; // deprecated
|
2438
|
+
this._captured = false;
|
2439
|
+
this.setBubble(false);
|
2440
|
+
pointer = pointer;
|
2441
|
+
this.setUpdates(0);
|
2442
|
+
return this;
|
2443
|
+
};
|
2444
|
+
|
2445
|
+
var touches = [];
|
2446
|
+
var count = 0;
|
2447
|
+
var identifiers = {};
|
2448
|
+
|
2449
|
+
Imba.Touch.count = function (){
|
2450
|
+
return count;
|
2451
|
+
};
|
2452
|
+
|
2453
|
+
Imba.Touch.lookup = function (item){
|
2454
|
+
return item && (item.__touch__ || identifiers[item.identifier]);
|
2455
|
+
};
|
2456
|
+
|
2457
|
+
Imba.Touch.release = function (item,touch){
|
2458
|
+
var v_, $1;
|
2459
|
+
(((v_ = identifiers[item.identifier]),delete identifiers[item.identifier], v_));
|
2460
|
+
((($1 = item.__touch__),delete item.__touch__, $1));
|
2461
|
+
return;
|
2462
|
+
};
|
2463
|
+
|
2464
|
+
Imba.Touch.ontouchstart = function (e){
|
2465
|
+
for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
|
2466
|
+
t = ary[i];
|
2467
|
+
if (this.lookup(t)) { continue; };
|
2468
|
+
var touch = identifiers[t.identifier] = new this(e); // (e)
|
2469
|
+
t.__touch__ = touch;
|
2470
|
+
touches.push(touch);
|
2471
|
+
count++;
|
2472
|
+
touch.touchstart(e,t);
|
2473
|
+
};
|
2474
|
+
return this;
|
2475
|
+
};
|
2476
|
+
|
2477
|
+
Imba.Touch.ontouchmove = function (e){
|
2478
|
+
var touch;
|
2479
|
+
for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
|
2480
|
+
t = ary[i];
|
2481
|
+
if (touch = this.lookup(t)) {
|
2482
|
+
touch.touchmove(e,t);
|
2483
|
+
};
|
2484
|
+
};
|
2485
|
+
|
2486
|
+
return this;
|
2487
|
+
};
|
2488
|
+
|
2489
|
+
Imba.Touch.ontouchend = function (e){
|
2490
|
+
var touch;
|
2491
|
+
for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
|
2492
|
+
t = ary[i];
|
2493
|
+
if (touch = this.lookup(t)) {
|
2494
|
+
touch.touchend(e,t);
|
2495
|
+
this.release(t,touch);
|
2496
|
+
count--;
|
2497
|
+
};
|
2498
|
+
};
|
2499
|
+
|
2500
|
+
// e.preventDefault
|
2501
|
+
// not always supported!
|
2502
|
+
// touches = touches.filter(||)
|
2503
|
+
return this;
|
2504
|
+
};
|
2505
|
+
|
2506
|
+
Imba.Touch.ontouchcancel = function (e){
|
2507
|
+
var touch;
|
2508
|
+
for (var i = 0, ary = iter$(e.changedTouches), len = ary.length, t; i < len; i++) {
|
2509
|
+
t = ary[i];
|
2510
|
+
if (touch = this.lookup(t)) {
|
2511
|
+
touch.touchcancel(e,t);
|
2512
|
+
this.release(t,touch);
|
2513
|
+
count--;
|
2514
|
+
};
|
2515
|
+
};
|
2516
|
+
return this;
|
2517
|
+
};
|
2518
|
+
|
2519
|
+
Imba.Touch.onmousedown = function (e){
|
2520
|
+
return this;
|
2521
|
+
};
|
2522
|
+
|
2523
|
+
Imba.Touch.onmousemove = function (e){
|
2524
|
+
return this;
|
2525
|
+
};
|
2526
|
+
|
2527
|
+
Imba.Touch.onmouseup = function (e){
|
2528
|
+
return this;
|
2529
|
+
};
|
2530
|
+
|
2531
|
+
|
2532
|
+
Imba.Touch.prototype.phase = function(v){ return this._phase; }
|
2533
|
+
Imba.Touch.prototype.setPhase = function(v){ this._phase = v; return this; };
|
2534
|
+
Imba.Touch.prototype.active = function(v){ return this._active; }
|
2535
|
+
Imba.Touch.prototype.setActive = function(v){ this._active = v; return this; };
|
2536
|
+
Imba.Touch.prototype.event = function(v){ return this._event; }
|
2537
|
+
Imba.Touch.prototype.setEvent = function(v){ this._event = v; return this; };
|
2538
|
+
Imba.Touch.prototype.pointer = function(v){ return this._pointer; }
|
2539
|
+
Imba.Touch.prototype.setPointer = function(v){ this._pointer = v; return this; };
|
2540
|
+
Imba.Touch.prototype.target = function(v){ return this._target; }
|
2541
|
+
Imba.Touch.prototype.setTarget = function(v){ this._target = v; return this; };
|
2542
|
+
Imba.Touch.prototype.handler = function(v){ return this._handler; }
|
2543
|
+
Imba.Touch.prototype.setHandler = function(v){ this._handler = v; return this; };
|
2544
|
+
Imba.Touch.prototype.updates = function(v){ return this._updates; }
|
2545
|
+
Imba.Touch.prototype.setUpdates = function(v){ this._updates = v; return this; };
|
2546
|
+
Imba.Touch.prototype.suppress = function(v){ return this._suppress; }
|
2547
|
+
Imba.Touch.prototype.setSuppress = function(v){ this._suppress = v; return this; };
|
2548
|
+
Imba.Touch.prototype.data = function(v){ return this._data; }
|
2549
|
+
Imba.Touch.prototype.setData = function(v){ this._data = v; return this; };
|
2550
|
+
Imba.Touch.prototype.__bubble = {chainable: true,name: 'bubble'};
|
2551
|
+
Imba.Touch.prototype.bubble = function(v){ return v !== undefined ? (this.setBubble(v),this) : this._bubble; }
|
2552
|
+
Imba.Touch.prototype.setBubble = function(v){ this._bubble = v; return this; };
|
2553
|
+
|
2554
|
+
Imba.Touch.prototype.gestures = function(v){ return this._gestures; }
|
2555
|
+
Imba.Touch.prototype.setGestures = function(v){ this._gestures = v; return this; };
|
2556
|
+
|
2557
|
+
/*
|
2558
|
+
|
2559
|
+
|
2560
|
+
@internal
|
2561
|
+
@constructor
|
2562
|
+
*/
|
2563
|
+
|
2564
|
+
Imba.Touch.prototype.capture = function (){
|
2565
|
+
this._captured = true;
|
2566
|
+
this._event && this._event.preventDefault();
|
2567
|
+
return this;
|
2568
|
+
};
|
2569
|
+
|
2570
|
+
Imba.Touch.prototype.isCaptured = function (){
|
2571
|
+
return !(!this._captured);
|
2572
|
+
};
|
2573
|
+
|
2574
|
+
/*
|
2575
|
+
Extend the touch with a plugin / gesture.
|
2576
|
+
All events (touchstart,move etc) for the touch
|
2577
|
+
will be triggered on the plugins in the order they
|
2578
|
+
are added.
|
2579
|
+
*/
|
2580
|
+
|
2581
|
+
Imba.Touch.prototype.extend = function (plugin){
|
2582
|
+
// console.log "added gesture!!!"
|
2583
|
+
this._gestures || (this._gestures = []);
|
2584
|
+
this._gestures.push(plugin);
|
2585
|
+
return this;
|
2586
|
+
};
|
2587
|
+
|
2588
|
+
/*
|
2589
|
+
Redirect touch to specified target. ontouchstart will always be
|
2590
|
+
called on the new target.
|
2591
|
+
@return {Number}
|
2592
|
+
*/
|
2593
|
+
|
2594
|
+
Imba.Touch.prototype.redirect = function (target){
|
2595
|
+
this._redirect = target;
|
2596
|
+
return this;
|
2597
|
+
};
|
2598
|
+
|
2599
|
+
/*
|
2600
|
+
Suppress the default behaviour. Will call preventDefault for
|
2601
|
+
all native events that are part of the touch.
|
2602
|
+
*/
|
2603
|
+
|
2604
|
+
Imba.Touch.prototype.suppress = function (){
|
2605
|
+
// collision with the suppress property
|
2606
|
+
this._active = false;
|
2607
|
+
return this;
|
2608
|
+
};
|
2609
|
+
|
2610
|
+
Imba.Touch.prototype.setSuppress = function (value){
|
2611
|
+
console.warn('Imba.Touch#suppress= is deprecated');
|
2612
|
+
this._supress = value;
|
2613
|
+
return this;
|
2614
|
+
};
|
2615
|
+
|
2616
|
+
Imba.Touch.prototype.touchstart = function (e,t){
|
2617
|
+
this._event = e;
|
2618
|
+
this._touch = t;
|
2619
|
+
this._button = 0;
|
2620
|
+
this._x = t.clientX;
|
2621
|
+
this._y = t.clientY;
|
2622
|
+
this.began();
|
2623
|
+
if (e && this.isCaptured()) { e.preventDefault() };
|
2624
|
+
return this;
|
2625
|
+
};
|
2626
|
+
|
2627
|
+
Imba.Touch.prototype.touchmove = function (e,t){
|
2628
|
+
this._event = e;
|
2629
|
+
this._x = t.clientX;
|
2630
|
+
this._y = t.clientY;
|
2631
|
+
this.update();
|
2632
|
+
if (e && this.isCaptured()) { e.preventDefault() };
|
2633
|
+
return this;
|
2634
|
+
};
|
2635
|
+
|
2636
|
+
Imba.Touch.prototype.touchend = function (e,t){
|
2637
|
+
this._event = e;
|
2638
|
+
this._x = t.clientX;
|
2639
|
+
this._y = t.clientY;
|
2640
|
+
this.ended();
|
2641
|
+
|
2642
|
+
lastNativeTouchTimeStamp = e.timeStamp;
|
2643
|
+
|
2644
|
+
if (this._maxdr < 20) {
|
2645
|
+
var tap = new Imba.Event(e);
|
2646
|
+
tap.setType('tap');
|
2647
|
+
tap.process();
|
2648
|
+
if (tap._responder) { e.preventDefault() };
|
2649
|
+
};
|
2650
|
+
|
2651
|
+
if (e && this.isCaptured()) {
|
2652
|
+
e.preventDefault();
|
2653
|
+
};
|
2654
|
+
|
2655
|
+
return this;
|
2656
|
+
};
|
2657
|
+
|
2658
|
+
Imba.Touch.prototype.touchcancel = function (e,t){
|
2659
|
+
return this.cancel();
|
2660
|
+
};
|
2661
|
+
|
2662
|
+
Imba.Touch.prototype.mousedown = function (e,t){
|
2663
|
+
var self = this;
|
2664
|
+
self._event = e;
|
2665
|
+
self._button = e.button;
|
2666
|
+
self._x = t.clientX;
|
2667
|
+
self._y = t.clientY;
|
2668
|
+
self.began();
|
2669
|
+
|
2670
|
+
self._mousemove = function(e) { return self.mousemove(e,e); };
|
2671
|
+
doc.addEventListener('mousemove',self._mousemove,true);
|
2672
|
+
return self;
|
2673
|
+
};
|
2674
|
+
|
2675
|
+
Imba.Touch.prototype.mousemove = function (e,t){
|
2676
|
+
this._x = t.clientX;
|
2677
|
+
this._y = t.clientY;
|
2678
|
+
this._event = e;
|
2679
|
+
if (this.isCaptured()) { e.preventDefault() };
|
2680
|
+
this.update();
|
2681
|
+
this.move();
|
2682
|
+
return this;
|
2683
|
+
};
|
2684
|
+
|
2685
|
+
Imba.Touch.prototype.mouseup = function (e,t){
|
2686
|
+
this._x = t.clientX;
|
2687
|
+
this._y = t.clientY;
|
2688
|
+
this.ended();
|
2689
|
+
doc.removeEventListener('mousemove',this._mousemove,true);
|
2690
|
+
this._mousemove = null;
|
2691
|
+
return this;
|
2692
|
+
};
|
2693
|
+
|
2694
|
+
Imba.Touch.prototype.idle = function (){
|
2695
|
+
return this.update();
|
2696
|
+
};
|
2697
|
+
|
2698
|
+
Imba.Touch.prototype.began = function (){
|
2699
|
+
this._maxdr = this._dr = 0;
|
2700
|
+
this._x0 = this._x;
|
2701
|
+
this._y0 = this._y;
|
2702
|
+
|
2703
|
+
var dom = this.event().target;
|
2704
|
+
var node = null;
|
2705
|
+
|
2706
|
+
this._sourceTarget = dom && tag$wrap(dom);
|
2707
|
+
|
2708
|
+
while (dom){
|
2709
|
+
node = tag$wrap(dom);
|
2710
|
+
if (node && node.ontouchstart) {
|
2711
|
+
this._bubble = false;
|
2712
|
+
this.setTarget(node);
|
2713
|
+
this.target().ontouchstart(this);
|
2714
|
+
if (!this._bubble) { break; };
|
2715
|
+
};
|
2716
|
+
dom = dom.parentNode;
|
2717
|
+
};
|
2718
|
+
|
2719
|
+
this._updates++;
|
2720
|
+
return this;
|
2721
|
+
};
|
2722
|
+
|
2723
|
+
Imba.Touch.prototype.update = function (){
|
2724
|
+
var target_;
|
2725
|
+
if (!this._active) { return this };
|
2726
|
+
|
2727
|
+
var dr = Math.sqrt(this.dx() * this.dx() + this.dy() * this.dy());
|
2728
|
+
if (dr > this._dr) { this._maxdr = dr };
|
2729
|
+
this._dr = dr;
|
2730
|
+
|
2731
|
+
// catching a touch-redirect?!?
|
2732
|
+
if (this._redirect) {
|
2733
|
+
if (this._target && this._target.ontouchcancel) {
|
2734
|
+
this._target.ontouchcancel(this);
|
2735
|
+
};
|
2736
|
+
this.setTarget(this._redirect);
|
2737
|
+
this._redirect = null;
|
2738
|
+
if (this.target().ontouchstart) { this.target().ontouchstart(this) };
|
2739
|
+
};
|
2740
|
+
|
2741
|
+
|
2742
|
+
this._updates++;
|
2743
|
+
if (this._gestures) {
|
2744
|
+
for (var i = 0, ary = iter$(this._gestures), len = ary.length; i < len; i++) {
|
2745
|
+
ary[i].ontouchupdate(this);
|
2746
|
+
};
|
2747
|
+
};
|
2748
|
+
|
2749
|
+
(target_ = this.target()) && target_.ontouchupdate && target_.ontouchupdate(this);
|
2750
|
+
return this;
|
2751
|
+
};
|
2752
|
+
|
2753
|
+
Imba.Touch.prototype.move = function (){
|
2754
|
+
var target_;
|
2755
|
+
if (!this._active) { return this };
|
2756
|
+
|
2757
|
+
if (this._gestures) {
|
2758
|
+
for (var i = 0, ary = iter$(this._gestures), len = ary.length, g; i < len; i++) {
|
2759
|
+
g = ary[i];
|
2760
|
+
if (g.ontouchmove) { g.ontouchmove(this,this._event) };
|
2761
|
+
};
|
2762
|
+
};
|
2763
|
+
|
2764
|
+
(target_ = this.target()) && target_.ontouchmove && target_.ontouchmove(this,this._event);
|
2765
|
+
return this;
|
2766
|
+
};
|
2767
|
+
|
2768
|
+
Imba.Touch.prototype.ended = function (){
|
2769
|
+
var target_;
|
2770
|
+
if (!this._active) { return this };
|
2771
|
+
|
2772
|
+
this._updates++;
|
2773
|
+
|
2774
|
+
if (this._gestures) {
|
2775
|
+
for (var i = 0, ary = iter$(this._gestures), len = ary.length; i < len; i++) {
|
2776
|
+
ary[i].ontouchend(this);
|
2777
|
+
};
|
2778
|
+
};
|
2779
|
+
|
2780
|
+
(target_ = this.target()) && target_.ontouchend && target_.ontouchend(this);
|
2781
|
+
|
2782
|
+
return this;
|
2783
|
+
};
|
2784
|
+
|
2785
|
+
Imba.Touch.prototype.cancel = function (){
|
2786
|
+
if (!this._cancelled) {
|
2787
|
+
this._cancelled = true;
|
2788
|
+
this.cancelled();
|
2789
|
+
if (this._mousemove) { doc.removeEventListener('mousemove',this._mousemove,true) };
|
2790
|
+
};
|
2791
|
+
return this;
|
2792
|
+
};
|
2793
|
+
|
2794
|
+
Imba.Touch.prototype.cancelled = function (){
|
2795
|
+
var target_;
|
2796
|
+
if (!this._active) { return this };
|
2797
|
+
|
2798
|
+
this._cancelled = true;
|
2799
|
+
this._updates++;
|
2800
|
+
|
2801
|
+
if (this._gestures) {
|
2802
|
+
for (var i = 0, ary = iter$(this._gestures), len = ary.length, g; i < len; i++) {
|
2803
|
+
g = ary[i];
|
2804
|
+
if (g.ontouchcancel) { g.ontouchcancel(this) };
|
2805
|
+
};
|
2806
|
+
};
|
2807
|
+
|
2808
|
+
(target_ = this.target()) && target_.ontouchcancel && target_.ontouchcancel(this);
|
2809
|
+
return this;
|
2810
|
+
};
|
2811
|
+
|
2812
|
+
/*
|
2813
|
+
The absolute distance the touch has moved from starting position
|
2814
|
+
@return {Number}
|
2815
|
+
*/
|
2816
|
+
|
2817
|
+
Imba.Touch.prototype.dr = function (){
|
2818
|
+
return this._dr;
|
2819
|
+
};
|
2820
|
+
|
2821
|
+
/*
|
2822
|
+
The distance the touch has moved horizontally
|
2823
|
+
@return {Number}
|
2824
|
+
*/
|
2825
|
+
|
2826
|
+
Imba.Touch.prototype.dx = function (){
|
2827
|
+
return this._x - this._x0;
|
2828
|
+
};
|
2829
|
+
|
2830
|
+
/*
|
2831
|
+
The distance the touch has moved vertically
|
2832
|
+
@return {Number}
|
2833
|
+
*/
|
2834
|
+
|
2835
|
+
Imba.Touch.prototype.dy = function (){
|
2836
|
+
return this._y - this._y0;
|
2837
|
+
};
|
2838
|
+
|
2839
|
+
/*
|
2840
|
+
Initial horizontal position of touch
|
2841
|
+
@return {Number}
|
2842
|
+
*/
|
2843
|
+
|
2844
|
+
Imba.Touch.prototype.x0 = function (){
|
2845
|
+
return this._x0;
|
2846
|
+
};
|
2847
|
+
|
2848
|
+
/*
|
2849
|
+
Initial vertical position of touch
|
2850
|
+
@return {Number}
|
2851
|
+
*/
|
2852
|
+
|
2853
|
+
Imba.Touch.prototype.y0 = function (){
|
2854
|
+
return this._y0;
|
2855
|
+
};
|
2856
|
+
|
2857
|
+
/*
|
2858
|
+
Horizontal position of touch
|
2859
|
+
@return {Number}
|
2860
|
+
*/
|
2861
|
+
|
2862
|
+
Imba.Touch.prototype.x = function (){
|
2863
|
+
return this._x;
|
2864
|
+
};
|
2865
|
+
|
2866
|
+
/*
|
2867
|
+
Vertical position of touch
|
2868
|
+
@return {Number}
|
2869
|
+
*/
|
2870
|
+
|
2871
|
+
Imba.Touch.prototype.y = function (){
|
2872
|
+
return this._y;
|
2873
|
+
};
|
2874
|
+
|
2875
|
+
/*
|
2876
|
+
Horizontal position of touch relative to target
|
2877
|
+
@return {Number}
|
2878
|
+
*/
|
2879
|
+
|
2880
|
+
Imba.Touch.prototype.tx = function (){
|
2881
|
+
this._targetBox || (this._targetBox = this._target.dom().getBoundingClientRect());
|
2882
|
+
return this._x - this._targetBox.left;
|
2883
|
+
};
|
2884
|
+
|
2885
|
+
/*
|
2886
|
+
Vertical position of touch relative to target
|
2887
|
+
@return {Number}
|
2888
|
+
*/
|
2889
|
+
|
2890
|
+
Imba.Touch.prototype.ty = function (){
|
2891
|
+
this._targetBox || (this._targetBox = this._target.dom().getBoundingClientRect());
|
2892
|
+
return this._y - this._targetBox.top;
|
2893
|
+
};
|
2894
|
+
|
2895
|
+
/*
|
2896
|
+
Button pressed in this touch. Native touches defaults to left-click (0)
|
2897
|
+
@return {Number}
|
2898
|
+
*/
|
2899
|
+
|
2900
|
+
Imba.Touch.prototype.button = function (){
|
2901
|
+
return this._button;
|
2902
|
+
}; // @pointer ? @pointer.button : 0
|
2903
|
+
|
2904
|
+
Imba.Touch.prototype.sourceTarget = function (){
|
2905
|
+
return this._sourceTarget;
|
2906
|
+
};
|
2907
|
+
|
2908
|
+
|
2909
|
+
Imba.TouchGesture = function TouchGesture(){ };
|
2910
|
+
|
2911
|
+
Imba.TouchGesture.prototype.__active = {'default': false,name: 'active'};
|
2912
|
+
Imba.TouchGesture.prototype.active = function(v){ return this._active; }
|
2913
|
+
Imba.TouchGesture.prototype.setActive = function(v){ this._active = v; return this; }
|
2914
|
+
Imba.TouchGesture.prototype._active = false;
|
2915
|
+
|
2916
|
+
Imba.TouchGesture.prototype.ontouchstart = function (e){
|
2917
|
+
return this;
|
2918
|
+
};
|
2919
|
+
|
2920
|
+
Imba.TouchGesture.prototype.ontouchupdate = function (e){
|
2921
|
+
return this;
|
2922
|
+
};
|
2923
|
+
|
2924
|
+
Imba.TouchGesture.prototype.ontouchend = function (e){
|
2925
|
+
return this;
|
2926
|
+
};
|
2927
|
+
|
2928
|
+
|
2929
|
+
// A Touch-event is created on mousedown (always)
|
2930
|
+
// and while it exists, mousemove and mouseup will
|
2931
|
+
// be delegated to this active event.
|
2932
|
+
Imba.POINTER = new Imba.Pointer();
|
2933
|
+
Imba.POINTERS = [Imba.POINTER];
|
2934
|
+
|
2935
|
+
|
2936
|
+
// regular event stuff
|
2937
|
+
Imba.KEYMAP = {
|
2938
|
+
"8": 'backspace',
|
2939
|
+
"9": 'tab',
|
2940
|
+
"13": 'enter',
|
2941
|
+
"16": 'shift',
|
2942
|
+
"17": 'ctrl',
|
2943
|
+
"18": 'alt',
|
2944
|
+
"19": 'break',
|
2945
|
+
"20": 'caps',
|
2946
|
+
"27": 'esc',
|
2947
|
+
"32": 'space',
|
2948
|
+
"35": 'end',
|
2949
|
+
"36": 'home',
|
2950
|
+
"37": 'larr',
|
2951
|
+
"38": 'uarr',
|
2952
|
+
"39": 'rarr',
|
2953
|
+
"40": 'darr',
|
2954
|
+
"45": 'insert',
|
2955
|
+
"46": 'delete',
|
2956
|
+
"107": 'plus',
|
2957
|
+
"106": 'mult',
|
2958
|
+
"91": 'meta'
|
2959
|
+
};
|
2960
|
+
|
2961
|
+
Imba.CHARMAP = {
|
2962
|
+
"%": 'modulo',
|
2963
|
+
"*": 'multiply',
|
2964
|
+
"+": 'add',
|
2965
|
+
"-": 'sub',
|
2966
|
+
"/": 'divide',
|
2967
|
+
".": 'dot'
|
2968
|
+
};
|
2969
|
+
|
2970
|
+
/*
|
2971
|
+
Imba handles all events in the dom through a single manager,
|
2972
|
+
listening at the root of your document. If Imba finds a tag
|
2973
|
+
that listens to a certain event, the event will be wrapped
|
2974
|
+
in an `Imba.Event`, which normalizes some of the quirks and
|
2975
|
+
browser differences.
|
2976
|
+
|
2977
|
+
@iname event
|
2978
|
+
*/
|
2979
|
+
|
2980
|
+
Imba.Event = function Event(e){
|
2981
|
+
this.setEvent(e);
|
2982
|
+
this.setBubble(true);
|
2983
|
+
};
|
2984
|
+
|
2985
|
+
/* reference to the native event */
|
2986
|
+
|
2987
|
+
Imba.Event.prototype.event = function(v){ return this._event; }
|
2988
|
+
Imba.Event.prototype.setEvent = function(v){ this._event = v; return this; };
|
2989
|
+
|
2990
|
+
/* reference to the native event */
|
2991
|
+
|
2992
|
+
Imba.Event.prototype.prefix = function(v){ return this._prefix; }
|
2993
|
+
Imba.Event.prototype.setPrefix = function(v){ this._prefix = v; return this; };
|
2994
|
+
|
2995
|
+
Imba.Event.prototype.data = function(v){ return this._data; }
|
2996
|
+
Imba.Event.prototype.setData = function(v){ this._data = v; return this; };
|
2997
|
+
|
2998
|
+
/*
|
2999
|
+
should remove this alltogether?
|
3000
|
+
@deprecated
|
3001
|
+
*/
|
3002
|
+
|
3003
|
+
Imba.Event.prototype.source = function(v){ return this._source; }
|
3004
|
+
Imba.Event.prototype.setSource = function(v){ this._source = v; return this; };
|
3005
|
+
|
3006
|
+
/* A {Boolean} indicating whether the event bubbles up or not */
|
3007
|
+
|
3008
|
+
Imba.Event.prototype.__bubble = {type: Boolean,chainable: true,name: 'bubble'};
|
3009
|
+
Imba.Event.prototype.bubble = function(v){ return v !== undefined ? (this.setBubble(v),this) : this._bubble; }
|
3010
|
+
Imba.Event.prototype.setBubble = function(v){ this._bubble = v; return this; };
|
3011
|
+
|
3012
|
+
Imba.Event.wrap = function (e){
|
3013
|
+
return new this(e);
|
3014
|
+
};
|
3015
|
+
|
3016
|
+
Imba.Event.prototype.setType = function (type){
|
3017
|
+
this._type = type;
|
3018
|
+
return this;
|
3019
|
+
};
|
3020
|
+
|
3021
|
+
/*
|
3022
|
+
@return {String} The name of the event (case-insensitive)
|
3023
|
+
*/
|
3024
|
+
|
3025
|
+
Imba.Event.prototype.type = function (){
|
3026
|
+
return this._type || this.event().type;
|
3027
|
+
};
|
3028
|
+
|
3029
|
+
Imba.Event.prototype.name = function (){
|
3030
|
+
return this._name || (this._name = this.type().toLowerCase().replace(/\:/g,''));
|
3031
|
+
};
|
3032
|
+
|
3033
|
+
// mimc getset
|
3034
|
+
Imba.Event.prototype.bubble = function (v){
|
3035
|
+
if (v != undefined) {
|
3036
|
+
this.setBubble(v);
|
3037
|
+
return this;
|
3038
|
+
};
|
3039
|
+
return this._bubble;
|
3040
|
+
};
|
3041
|
+
|
3042
|
+
/*
|
3043
|
+
Prevents further propagation of the current event.
|
3044
|
+
@return {self}
|
3045
|
+
*/
|
3046
|
+
|
3047
|
+
Imba.Event.prototype.halt = function (){
|
3048
|
+
this.setBubble(false);
|
3049
|
+
return this;
|
3050
|
+
};
|
3051
|
+
|
3052
|
+
/*
|
3053
|
+
Cancel the event (if cancelable). In the case of native events it
|
3054
|
+
will call `preventDefault` on the wrapped event object.
|
3055
|
+
@return {self}
|
3056
|
+
*/
|
3057
|
+
|
3058
|
+
Imba.Event.prototype.cancel = function (){
|
3059
|
+
if (this.event().preventDefault) { this.event().preventDefault() };
|
3060
|
+
this._cancel = true;
|
3061
|
+
return this;
|
3062
|
+
};
|
3063
|
+
|
3064
|
+
Imba.Event.prototype.silence = function (){
|
3065
|
+
this._silenced = true;
|
3066
|
+
return this;
|
3067
|
+
};
|
3068
|
+
|
3069
|
+
Imba.Event.prototype.isSilenced = function (){
|
3070
|
+
return !(!this._silenced);
|
3071
|
+
};
|
3072
|
+
|
3073
|
+
/*
|
3074
|
+
Indicates whether or not event.cancel has been called.
|
3075
|
+
|
3076
|
+
@return {Boolean}
|
3077
|
+
*/
|
3078
|
+
|
3079
|
+
Imba.Event.prototype.isPrevented = function (){
|
3080
|
+
return this.event() && this.event().defaultPrevented || this._cancel;
|
3081
|
+
};
|
3082
|
+
|
3083
|
+
/*
|
3084
|
+
A reference to the initial target of the event.
|
3085
|
+
*/
|
3086
|
+
|
3087
|
+
Imba.Event.prototype.target = function (){
|
3088
|
+
return tag$wrap(this.event()._target || this.event().target);
|
3089
|
+
};
|
3090
|
+
|
3091
|
+
/*
|
3092
|
+
A reference to the object responding to the event.
|
3093
|
+
*/
|
3094
|
+
|
3095
|
+
Imba.Event.prototype.responder = function (){
|
3096
|
+
return this._responder;
|
3097
|
+
};
|
3098
|
+
|
3099
|
+
/*
|
3100
|
+
Redirect the event to new target
|
3101
|
+
*/
|
3102
|
+
|
3103
|
+
Imba.Event.prototype.redirect = function (node){
|
3104
|
+
this._redirect = node;
|
3105
|
+
return this;
|
3106
|
+
};
|
3107
|
+
|
3108
|
+
/*
|
3109
|
+
Get the normalized character for KeyboardEvent/TextEvent
|
3110
|
+
@return {String}
|
3111
|
+
*/
|
3112
|
+
|
3113
|
+
Imba.Event.prototype.keychar = function (){
|
3114
|
+
if (this.event() instanceof KeyboardEvent) {
|
3115
|
+
var ki = this.event().keyIdentifier;
|
3116
|
+
var sym = Imba.KEYMAP[this.event().keyCode];
|
3117
|
+
|
3118
|
+
if (!(sym) && ki.substr(0,2) == "U+") {
|
3119
|
+
sym = String.fromCharCode(parseInt(ki.substr(2),16));
|
3120
|
+
};
|
3121
|
+
return sym;
|
3122
|
+
} else if (this.event() instanceof (window.TextEvent || window.InputEvent)) {
|
3123
|
+
return this.event().data;
|
3124
|
+
};
|
3125
|
+
|
3126
|
+
return null;
|
3127
|
+
};
|
3128
|
+
|
3129
|
+
/*
|
3130
|
+
@deprecated
|
3131
|
+
*/
|
3132
|
+
|
3133
|
+
Imba.Event.prototype.keycombo = function (){
|
3134
|
+
var sym;
|
3135
|
+
if (!(sym = this.keychar())) { return };
|
3136
|
+
sym = Imba.CHARMAP[sym] || sym;
|
3137
|
+
var combo = [],e = this.event();
|
3138
|
+
if (e.ctrlKey) { combo.push('ctrl') };
|
3139
|
+
if (e.shiftKey) { combo.push('shift') };
|
3140
|
+
if (e.altKey) { combo.push('alt') };
|
3141
|
+
if (e.metaKey) { combo.push('cmd') };
|
3142
|
+
combo.push(sym);
|
3143
|
+
return combo.join("_").toLowerCase();
|
3144
|
+
};
|
3145
|
+
|
3146
|
+
|
3147
|
+
Imba.Event.prototype.process = function (){
|
3148
|
+
var node;
|
3149
|
+
var meth = ("on" + (this._prefix || '') + this.name());
|
3150
|
+
var args = null;
|
3151
|
+
var domtarget = this.event()._target || this.event().target;
|
3152
|
+
// var node = <{domtarget:_responder or domtarget}>
|
3153
|
+
// need to clean up and document this behaviour
|
3154
|
+
|
3155
|
+
var domnode = domtarget._responder || domtarget;
|
3156
|
+
// @todo need to stop infinite redirect-rules here
|
3157
|
+
|
3158
|
+
var $1;while (domnode){
|
3159
|
+
this._redirect = null;
|
3160
|
+
if (node = tag$wrap(domnode)) { // not only tag
|
3161
|
+
|
3162
|
+
if ((typeof node[($1 = meth)]=='string'||node[$1] instanceof String)) {
|
3163
|
+
// should remember the receiver of the event
|
3164
|
+
meth = node[meth];
|
3165
|
+
continue; // should not continue?
|
3166
|
+
};
|
3167
|
+
|
3168
|
+
if (node[meth] instanceof Array) {
|
3169
|
+
args = node[meth].concat(node);
|
3170
|
+
meth = args.shift();
|
3171
|
+
continue; // should not continue?
|
3172
|
+
};
|
3173
|
+
|
3174
|
+
if (node[meth] instanceof Function) {
|
3175
|
+
this._responder || (this._responder = node);
|
3176
|
+
// should autostop bubble here?
|
3177
|
+
args ? (node[meth].apply(node,args)) : (node[meth](this,this.data()));
|
3178
|
+
};
|
3179
|
+
};
|
3180
|
+
|
3181
|
+
// add node.nextEventResponder as a separate method here?
|
3182
|
+
if (!(this.bubble() && (domnode = (this._redirect || (node ? (node.parent()) : (domnode.parentNode)))))) {
|
3183
|
+
break;
|
3184
|
+
};
|
3185
|
+
};
|
3186
|
+
|
3187
|
+
this.processed();
|
3188
|
+
return this;
|
3189
|
+
};
|
3190
|
+
|
3191
|
+
|
3192
|
+
Imba.Event.prototype.processed = function (){
|
3193
|
+
if (!this._silenced) { Imba.emit(Imba,'event',[this]) };
|
3194
|
+
return this;
|
3195
|
+
};
|
3196
|
+
|
3197
|
+
/*
|
3198
|
+
Return the x/left coordinate of the mouse / pointer for this event
|
3199
|
+
@return {Number} x coordinate of mouse / pointer for event
|
3200
|
+
*/
|
3201
|
+
|
3202
|
+
Imba.Event.prototype.x = function (){
|
3203
|
+
return this.event().x;
|
3204
|
+
};
|
3205
|
+
|
3206
|
+
/*
|
3207
|
+
Return the y/top coordinate of the mouse / pointer for this event
|
3208
|
+
@return {Number} y coordinate of mouse / pointer for event
|
3209
|
+
*/
|
3210
|
+
|
3211
|
+
Imba.Event.prototype.y = function (){
|
3212
|
+
return this.event().y;
|
3213
|
+
};
|
3214
|
+
|
3215
|
+
/*
|
3216
|
+
Returns a Number representing a system and implementation
|
3217
|
+
dependent numeric code identifying the unmodified value of the
|
3218
|
+
pressed key; this is usually the same as keyCode.
|
3219
|
+
|
3220
|
+
For mouse-events, the returned value indicates which button was
|
3221
|
+
pressed on the mouse to trigger the event.
|
3222
|
+
|
3223
|
+
@return {Number}
|
3224
|
+
*/
|
3225
|
+
|
3226
|
+
Imba.Event.prototype.which = function (){
|
3227
|
+
return this.event().which;
|
3228
|
+
};
|
3229
|
+
|
3230
|
+
|
3231
|
+
/*
|
3232
|
+
|
3233
|
+
Manager for listening to and delegating events in Imba. A single instance
|
3234
|
+
is always created by Imba (as `Imba.Events`), which handles and delegates all
|
3235
|
+
events at the very root of the document. Imba does not capture all events
|
3236
|
+
by default, so if you want to make sure exotic or custom DOMEvents are delegated
|
3237
|
+
in Imba you will need to register them in `Imba.Events.register(myCustomEventName)`
|
3238
|
+
|
3239
|
+
@iname manager
|
3240
|
+
|
3241
|
+
*/
|
3242
|
+
|
3243
|
+
Imba.EventManager = function EventManager(node,pars){
|
3244
|
+
var self = this;
|
3245
|
+
if(!pars||pars.constructor !== Object) pars = {};
|
3246
|
+
var events = pars.events !== undefined ? pars.events : [];
|
3247
|
+
self.setRoot(node);
|
3248
|
+
self.setCount(0);
|
3249
|
+
self.setListeners([]);
|
3250
|
+
self.setDelegators({});
|
3251
|
+
self.setDelegator(function(e) {
|
3252
|
+
// console.log "delegating event?! {e}"
|
3253
|
+
self.delegate(e);
|
3254
|
+
return true;
|
3255
|
+
});
|
3256
|
+
|
3257
|
+
for (var i = 0, ary = iter$(events), len = ary.length; i < len; i++) {
|
3258
|
+
self.register(ary[i]);
|
3259
|
+
};
|
3260
|
+
|
3261
|
+
return self;
|
3262
|
+
};
|
3263
|
+
|
3264
|
+
Imba.EventManager.prototype.root = function(v){ return this._root; }
|
3265
|
+
Imba.EventManager.prototype.setRoot = function(v){ this._root = v; return this; };
|
3266
|
+
Imba.EventManager.prototype.count = function(v){ return this._count; }
|
3267
|
+
Imba.EventManager.prototype.setCount = function(v){ this._count = v; return this; };
|
3268
|
+
Imba.EventManager.prototype.__enabled = {'default': false,watch: 'enabledDidSet',name: 'enabled'};
|
3269
|
+
Imba.EventManager.prototype.enabled = function(v){ return this._enabled; }
|
3270
|
+
Imba.EventManager.prototype.setEnabled = function(v){
|
3271
|
+
var a = this.enabled();
|
3272
|
+
if(v != a) { this._enabled = v; }
|
3273
|
+
if(v != a) { this.enabledDidSet && this.enabledDidSet(v,a,this.__enabled) }
|
3274
|
+
return this;
|
3275
|
+
}
|
3276
|
+
Imba.EventManager.prototype._enabled = false;
|
3277
|
+
Imba.EventManager.prototype.listeners = function(v){ return this._listeners; }
|
3278
|
+
Imba.EventManager.prototype.setListeners = function(v){ this._listeners = v; return this; };
|
3279
|
+
Imba.EventManager.prototype.delegators = function(v){ return this._delegators; }
|
3280
|
+
Imba.EventManager.prototype.setDelegators = function(v){ this._delegators = v; return this; };
|
3281
|
+
Imba.EventManager.prototype.delegator = function(v){ return this._delegator; }
|
3282
|
+
Imba.EventManager.prototype.setDelegator = function(v){ this._delegator = v; return this; };
|
3283
|
+
|
3284
|
+
Imba.EventManager.prototype.enabledDidSet = function (bool){
|
3285
|
+
bool ? (this.onenable()) : (this.ondisable());
|
3286
|
+
return this;
|
3287
|
+
};
|
3288
|
+
|
3289
|
+
/*
|
3290
|
+
|
3291
|
+
Tell the current EventManager to intercept and handle event of a certain name.
|
3292
|
+
By default, Imba.Events will register interceptors for: *keydown*, *keyup*,
|
3293
|
+
*keypress*, *textInput*, *input*, *change*, *submit*, *focusin*, *focusout*,
|
3294
|
+
*blur*, *contextmenu*, *dblclick*, *mousewheel*, *wheel*
|
3295
|
+
|
3296
|
+
*/
|
3297
|
+
|
3298
|
+
Imba.EventManager.prototype.register = function (name,handler){
|
3299
|
+
if(handler === undefined) handler = true;
|
3300
|
+
if (name instanceof Array) {
|
3301
|
+
for (var i = 0, ary = iter$(name), len = ary.length; i < len; i++) {
|
3302
|
+
this.register(ary[i],handler);
|
3303
|
+
};
|
3304
|
+
return this;
|
3305
|
+
};
|
3306
|
+
|
3307
|
+
if (this.delegators()[name]) { return this };
|
3308
|
+
// console.log("register for event {name}")
|
3309
|
+
var fn = this.delegators()[name] = handler instanceof Function ? (handler) : (this.delegator());
|
3310
|
+
if (this.enabled()) { return this.root().addEventListener(name,fn,true) };
|
3311
|
+
};
|
3312
|
+
|
3313
|
+
Imba.EventManager.prototype.listen = function (name,handler,capture){
|
3314
|
+
if(capture === undefined) capture = true;
|
3315
|
+
this.listeners().push([name,handler,capture]);
|
3316
|
+
if (this.enabled()) { this.root().addEventListener(name,handler,capture) };
|
3317
|
+
return this;
|
3318
|
+
};
|
3319
|
+
|
3320
|
+
Imba.EventManager.prototype.delegate = function (e){
|
3321
|
+
this.setCount(this.count() + 1);
|
3322
|
+
var event = Imba.Event.wrap(e);
|
3323
|
+
event.process();
|
3324
|
+
return this;
|
3325
|
+
};
|
3326
|
+
|
3327
|
+
Imba.EventManager.prototype.create = function (type,target,pars){
|
3328
|
+
if(!pars||pars.constructor !== Object) pars = {};
|
3329
|
+
var data = pars.data !== undefined ? pars.data : null;
|
3330
|
+
var source = pars.source !== undefined ? pars.source : null;
|
3331
|
+
var event = Imba.Event.wrap({type: type,target: target});
|
3332
|
+
if (data) { (event.setData(data),data) };
|
3333
|
+
if (source) { (event.setSource(source),source) };
|
3334
|
+
return event;
|
3335
|
+
};
|
3336
|
+
|
3337
|
+
// use create instead?
|
3338
|
+
Imba.EventManager.prototype.trigger = function (){
|
3339
|
+
return this.create.apply(this,arguments).process();
|
3340
|
+
};
|
3341
|
+
|
3342
|
+
Imba.EventManager.prototype.onenable = function (){
|
3343
|
+
for (var o = this.delegators(), i = 0, keys = Object.keys(o), l = keys.length; i < l; i++){
|
3344
|
+
this.root().addEventListener(keys[i],o[keys[i]],true);
|
3345
|
+
};
|
3346
|
+
|
3347
|
+
for (var i = 0, ary = iter$(this.listeners()), len = ary.length, item; i < len; i++) {
|
3348
|
+
item = ary[i];
|
3349
|
+
this.root().addEventListener(item[0],item[1],item[2]);
|
3350
|
+
};
|
3351
|
+
return this;
|
3352
|
+
};
|
3353
|
+
|
3354
|
+
Imba.EventManager.prototype.ondisable = function (){
|
3355
|
+
for (var o = this.delegators(), i = 0, keys = Object.keys(o), l = keys.length; i < l; i++){
|
3356
|
+
this.root().removeEventListener(keys[i],o[keys[i]],true);
|
3357
|
+
};
|
3358
|
+
|
3359
|
+
for (var i = 0, ary = iter$(this.listeners()), len = ary.length, item; i < len; i++) {
|
3360
|
+
item = ary[i];
|
3361
|
+
this.root().removeEventListener(item[0],item[1],item[2]);
|
3362
|
+
};
|
3363
|
+
return this;
|
3364
|
+
};
|
3365
|
+
|
3366
|
+
|
3367
|
+
ED = Imba.Events = new Imba.EventManager(document,{events: [
|
3368
|
+
'keydown','keyup','keypress','textInput','input','change','submit',
|
3369
|
+
'focusin','focusout','blur','contextmenu','dblclick',
|
3370
|
+
'mousewheel','wheel','scroll'
|
3371
|
+
]});
|
3372
|
+
|
3373
|
+
// should set these up inside the Imba.Events object itself
|
3374
|
+
// so that we can have different EventManager for different roots
|
3375
|
+
|
3376
|
+
if (hasTouchEvents) {
|
3377
|
+
Imba.Events.listen('touchstart',function(e) {
|
3378
|
+
var Events_, v_;
|
3379
|
+
(((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
|
3380
|
+
return Imba.Touch.ontouchstart(e);
|
3381
|
+
});
|
3382
|
+
|
3383
|
+
Imba.Events.listen('touchmove',function(e) {
|
3384
|
+
var Events_, v_;
|
3385
|
+
(((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
|
3386
|
+
return Imba.Touch.ontouchmove(e);
|
3387
|
+
});
|
3388
|
+
|
3389
|
+
Imba.Events.listen('touchend',function(e) {
|
3390
|
+
var Events_, v_;
|
3391
|
+
(((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
|
3392
|
+
return Imba.Touch.ontouchend(e);
|
3393
|
+
});
|
3394
|
+
|
3395
|
+
Imba.Events.listen('touchcancel',function(e) {
|
3396
|
+
var Events_, v_;
|
3397
|
+
(((Events_ = Imba.Events).setCount(v_ = Events_.count() + 1),v_)) - 1;
|
3398
|
+
return Imba.Touch.ontouchcancel(e);
|
3399
|
+
});
|
3400
|
+
};
|
3401
|
+
|
3402
|
+
Imba.Events.register('click',function(e) {
|
3403
|
+
// Only for main mousebutton, no?
|
3404
|
+
if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
|
3405
|
+
var tap = new Imba.Event(e);
|
3406
|
+
tap.setType('tap');
|
3407
|
+
tap.process();
|
3408
|
+
if (tap._responder) {
|
3409
|
+
return e.preventDefault();
|
3410
|
+
};
|
3411
|
+
};
|
3412
|
+
// delegate the real click event
|
3413
|
+
return Imba.Events.delegate(e);
|
3414
|
+
});
|
3415
|
+
|
3416
|
+
Imba.Events.listen('mousedown',function(e) {
|
3417
|
+
if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
|
3418
|
+
if (Imba.POINTER) { return Imba.POINTER.update(e).process() };
|
3419
|
+
};
|
3420
|
+
});
|
3421
|
+
|
3422
|
+
// Imba.Events.listen(:mousemove) do |e|
|
3423
|
+
// # console.log 'mousemove',e:timeStamp
|
3424
|
+
// if (e:timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout
|
3425
|
+
// Imba.POINTER.update(e).process if Imba.POINTER # .process if touch # should not happen? We process through
|
3426
|
+
|
3427
|
+
Imba.Events.listen('mouseup',function(e) {
|
3428
|
+
// console.log 'mouseup',e:timeStamp
|
3429
|
+
if ((e.timeStamp - lastNativeTouchTimeStamp) > lastNativeTouchTimeout) {
|
3430
|
+
if (Imba.POINTER) { return Imba.POINTER.update(e).process() };
|
3431
|
+
};
|
3432
|
+
});
|
3433
|
+
|
3434
|
+
|
3435
|
+
Imba.Events.register(['mousedown','mouseup']);
|
3436
|
+
return (Imba.Events.setEnabled(true),true);
|
3437
|
+
|
3438
|
+
})()
|
3439
|
+
|
3440
|
+
/***/ },
|
3441
|
+
/* 10 */
|
3442
|
+
/***/ function(module, exports) {
|
3443
|
+
|
3444
|
+
(function(){
|
3445
|
+
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
|
3446
|
+
var ImbaTag = Imba.TAGS.element;
|
3447
|
+
|
3448
|
+
function removeNested(root,node,caret){
|
3449
|
+
// if node/nodes isa String
|
3450
|
+
// we need to use the caret to remove elements
|
3451
|
+
// for now we will simply not support this
|
3452
|
+
if (node instanceof ImbaTag) {
|
3453
|
+
root.removeChild(node);
|
3454
|
+
} else if (node instanceof Array) {
|
3455
|
+
for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
|
3456
|
+
removeNested(root,ary[i],caret);
|
3457
|
+
};
|
3458
|
+
} else {
|
3459
|
+
// what if this is not null?!?!?
|
3460
|
+
// take a chance and remove a text-elementng
|
3461
|
+
var next = caret ? (caret.nextSibling) : (root._dom.firstChild);
|
3462
|
+
if ((next instanceof Text) && next.textContent == node) {
|
3463
|
+
root.removeChild(next);
|
3464
|
+
} else {
|
3465
|
+
throw 'cannot remove string';
|
3466
|
+
};
|
3467
|
+
};
|
3468
|
+
|
3469
|
+
return caret;
|
3470
|
+
};
|
3471
|
+
|
3472
|
+
function appendNested(root,node){
|
3473
|
+
if (node instanceof ImbaTag) {
|
3474
|
+
root.appendChild(node);
|
3475
|
+
} else if (node instanceof Array) {
|
3476
|
+
for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
|
3477
|
+
appendNested(root,ary[i]);
|
3478
|
+
};
|
3479
|
+
} else if (node != null && node !== false) {
|
3480
|
+
root.appendChild(Imba.document().createTextNode(node));
|
3481
|
+
};
|
3482
|
+
|
3483
|
+
return;
|
3484
|
+
};
|
3485
|
+
|
3486
|
+
|
3487
|
+
// insert nodes before a certain node
|
3488
|
+
// does not need to return any tail, as before
|
3489
|
+
// will still be correct there
|
3490
|
+
// before must be an actual domnode
|
3491
|
+
function insertNestedBefore(root,node,before){
|
3492
|
+
if (node instanceof ImbaTag) {
|
3493
|
+
root.insertBefore(node,before);
|
3494
|
+
} else if (node instanceof Array) {
|
3495
|
+
for (var i = 0, ary = iter$(node), len = ary.length; i < len; i++) {
|
3496
|
+
insertNestedBefore(root,ary[i],before);
|
3497
|
+
};
|
3498
|
+
} else if (node != null && node !== false) {
|
3499
|
+
root.insertBefore(Imba.document().createTextNode(node),before);
|
3500
|
+
};
|
3501
|
+
|
3502
|
+
return before;
|
3503
|
+
};
|
3504
|
+
|
3505
|
+
// after must be an actual domnode
|
3506
|
+
function insertNestedAfter(root,node,after){
|
3507
|
+
var before = after ? (after.nextSibling) : (root._dom.firstChild);
|
3508
|
+
|
3509
|
+
if (before) {
|
3510
|
+
insertNestedBefore(root,node,before);
|
3511
|
+
return before.previousSibling;
|
3512
|
+
} else {
|
3513
|
+
appendNested(root,node);
|
3514
|
+
return root._dom.lastChild;
|
3515
|
+
};
|
3516
|
+
};
|
3517
|
+
|
3518
|
+
function reconcileCollectionChanges(root,new$,old,caret){
|
3519
|
+
|
3520
|
+
var newLen = new$.length;
|
3521
|
+
var lastNew = new$[newLen - 1];
|
3522
|
+
|
3523
|
+
// This re-order algorithm is based on the following principle:
|
3524
|
+
//
|
3525
|
+
// We build a "chain" which shows which items are already sorted.
|
3526
|
+
// If we're going from [1, 2, 3] -> [2, 1, 3], the tree looks like:
|
3527
|
+
//
|
3528
|
+
// 3 -> 0 (idx)
|
3529
|
+
// 2 -> -1 (idx)
|
3530
|
+
// 1 -> -1 (idx)
|
3531
|
+
//
|
3532
|
+
// This tells us that we have two chains of ordered items:
|
3533
|
+
//
|
3534
|
+
// (1, 3) and (2)
|
3535
|
+
//
|
3536
|
+
// The optimal re-ordering then becomes two keep the longest chain intact,
|
3537
|
+
// and move all the other items.
|
3538
|
+
|
3539
|
+
var newPosition = [];
|
3540
|
+
|
3541
|
+
// The tree/graph itself
|
3542
|
+
var prevChain = [];
|
3543
|
+
// The length of the chain
|
3544
|
+
var lengthChain = [];
|
3545
|
+
|
3546
|
+
// Keep track of the longest chain
|
3547
|
+
var maxChainLength = 0;
|
3548
|
+
var maxChainEnd = 0;
|
3549
|
+
|
3550
|
+
for (var idx = 0, ary = iter$(old), len = ary.length, node; idx < len; idx++) {
|
3551
|
+
node = ary[idx];
|
3552
|
+
var newPos = new$.indexOf(node);
|
3553
|
+
newPosition.push(newPos);
|
3554
|
+
|
3555
|
+
if (newPos == -1) {
|
3556
|
+
root.removeChild(node);
|
3557
|
+
prevChain.push(-1);
|
3558
|
+
lengthChain.push(-1);
|
3559
|
+
continue;
|
3560
|
+
};
|
3561
|
+
|
3562
|
+
var prevIdx = newPosition.length - 2;
|
3563
|
+
|
3564
|
+
// Build the chain:
|
3565
|
+
while (prevIdx >= 0){
|
3566
|
+
if (newPosition[prevIdx] == -1) {
|
3567
|
+
prevIdx--;
|
3568
|
+
} else if (newPos > newPosition[prevIdx]) {
|
3569
|
+
// Yay, we're bigger than the previous!
|
3570
|
+
break;
|
3571
|
+
} else {
|
3572
|
+
// Nope, let's walk back the chain
|
3573
|
+
prevIdx = prevChain[prevIdx];
|
3574
|
+
};
|
3575
|
+
};
|
3576
|
+
|
3577
|
+
prevChain.push(prevIdx);
|
3578
|
+
|
3579
|
+
var currLength = (prevIdx == -1) ? (0) : (lengthChain[prevIdx] + 1);
|
3580
|
+
|
3581
|
+
if (currLength > maxChainLength) {
|
3582
|
+
maxChainLength = currLength;
|
3583
|
+
maxChainEnd = idx;
|
3584
|
+
};
|
3585
|
+
|
3586
|
+
lengthChain.push(currLength);
|
3587
|
+
};
|
3588
|
+
|
3589
|
+
var stickyNodes = [];
|
3590
|
+
|
3591
|
+
// Now we can walk the longest chain backwards and mark them as "sticky",
|
3592
|
+
// which implies that they should not be moved
|
3593
|
+
var cursor = newPosition.length - 1;
|
3594
|
+
while (cursor >= 0){
|
3595
|
+
if (cursor == maxChainEnd && newPosition[cursor] != -1) {
|
3596
|
+
stickyNodes[newPosition[cursor]] = true;
|
3597
|
+
maxChainEnd = prevChain[maxChainEnd];
|
3598
|
+
};
|
3599
|
+
|
3600
|
+
cursor -= 1;
|
3601
|
+
};
|
3602
|
+
|
3603
|
+
// And let's iterate forward, but only move non-sticky nodes
|
3604
|
+
for (var idx1 = 0, ary = iter$(new$), len = ary.length; idx1 < len; idx1++) {
|
3605
|
+
if (!stickyNodes[idx1]) {
|
3606
|
+
var after = new$[idx1 - 1];
|
3607
|
+
insertNestedAfter(root,ary[idx1],(after && after._dom) || caret);
|
3608
|
+
};
|
3609
|
+
};
|
3610
|
+
|
3611
|
+
// should trust that the last item in new list is the caret
|
3612
|
+
return lastNew && lastNew._dom || caret;
|
3613
|
+
};
|
3614
|
+
|
3615
|
+
|
3616
|
+
// expects a flat non-sparse array of nodes in both new and old, always
|
3617
|
+
function reconcileCollection(root,new$,old,caret){
|
3618
|
+
var k = new$.length;
|
3619
|
+
var i = k;
|
3620
|
+
var last = new$[k - 1];
|
3621
|
+
|
3622
|
+
|
3623
|
+
if (k == old.length && new$[0] === old[0]) {
|
3624
|
+
// running through to compare
|
3625
|
+
while (i--){
|
3626
|
+
if (new$[i] !== old[i]) { break; };
|
3627
|
+
};
|
3628
|
+
};
|
3629
|
+
|
3630
|
+
if (i == -1) {
|
3631
|
+
return last && last._dom || caret;
|
3632
|
+
} else {
|
3633
|
+
return reconcileCollectionChanges(root,new$,old,caret);
|
3634
|
+
};
|
3635
|
+
};
|
3636
|
+
|
3637
|
+
// the general reconciler that respects conditions etc
|
3638
|
+
// caret is the current node we want to insert things after
|
3639
|
+
function reconcileNested(root,new$,old,caret){
|
3640
|
+
|
3641
|
+
// if new == null or new === false or new === true
|
3642
|
+
// if new === old
|
3643
|
+
// return caret
|
3644
|
+
// if old && new != old
|
3645
|
+
// removeNested(root,old,caret) if old
|
3646
|
+
//
|
3647
|
+
// return caret
|
3648
|
+
|
3649
|
+
// var skipnew = new == null or new === false or new === true
|
3650
|
+
var newIsNull = new$ == null || new$ === false;
|
3651
|
+
var oldIsNull = old == null || old === false;
|
3652
|
+
|
3653
|
+
|
3654
|
+
if (new$ === old) {
|
3655
|
+
// remember that the caret must be an actual dom element
|
3656
|
+
// we should instead move the actual caret? - trust
|
3657
|
+
if (newIsNull) {
|
3658
|
+
return caret;
|
3659
|
+
} else if (new$ && new$._dom) {
|
3660
|
+
return new$._dom;
|
3661
|
+
} else {
|
3662
|
+
return caret ? (caret.nextSibling) : (root._dom.firstChild);
|
3663
|
+
};
|
3664
|
+
} else if (new$ instanceof Array) {
|
3665
|
+
if (old instanceof Array) {
|
3666
|
+
if (new$.static || old.static) {
|
3667
|
+
// if the static is not nested - we could get a hint from compiler
|
3668
|
+
// and just skip it
|
3669
|
+
if (new$.static == old.static) {
|
3670
|
+
for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
|
3671
|
+
// this is where we could do the triple equal directly
|
3672
|
+
caret = reconcileNested(root,ary[i],old[i],caret);
|
3673
|
+
};
|
3674
|
+
return caret;
|
3675
|
+
} else {
|
3676
|
+
removeNested(root,old,caret);
|
3677
|
+
};
|
3678
|
+
|
3679
|
+
// if they are not the same we continue through to the default
|
3680
|
+
} else {
|
3681
|
+
return reconcileCollection(root,new$,old,caret);
|
3682
|
+
};
|
3683
|
+
} else if (old instanceof ImbaTag) {
|
3684
|
+
root.removeChild(old);
|
3685
|
+
} else if (!(oldIsNull)) {
|
3686
|
+
// old was a string-like object?
|
3687
|
+
root.removeChild(caret ? (caret.nextSibling) : (root._dom.firstChild));
|
3688
|
+
};
|
3689
|
+
|
3690
|
+
return insertNestedAfter(root,new$,caret);
|
3691
|
+
// remove old
|
3692
|
+
} else if (new$ instanceof ImbaTag) {
|
3693
|
+
if (!(oldIsNull)) { removeNested(root,old,caret) };
|
3694
|
+
insertNestedAfter(root,new$,caret);
|
3695
|
+
return new$;
|
3696
|
+
} else if (newIsNull) {
|
3697
|
+
if (!(oldIsNull)) { removeNested(root,old,caret) };
|
3698
|
+
return caret;
|
3699
|
+
} else {
|
3700
|
+
// if old did not exist we need to add a new directly
|
3701
|
+
var nextNode;
|
3702
|
+
// if old was array or imbatag we need to remove it and then add
|
3703
|
+
if (old instanceof Array) {
|
3704
|
+
removeNested(root,old,caret);
|
3705
|
+
} else if (old instanceof ImbaTag) {
|
3706
|
+
root.removeChild(old);
|
3707
|
+
} else if (!(oldIsNull)) {
|
3708
|
+
// ...
|
3709
|
+
nextNode = caret ? (caret.nextSibling) : (root._dom.firstChild);
|
3710
|
+
if ((nextNode instanceof Text) && nextNode.textContent != new$) {
|
3711
|
+
nextNode.textContent = new$;
|
3712
|
+
return nextNode;
|
3713
|
+
};
|
3714
|
+
};
|
3715
|
+
|
3716
|
+
// now add the textnode
|
3717
|
+
return insertNestedAfter(root,new$,caret);
|
3718
|
+
};
|
3719
|
+
};
|
3720
|
+
|
3721
|
+
|
3722
|
+
return tag$.extendTag('htmlelement', function(tag){
|
3723
|
+
|
3724
|
+
tag.prototype.setChildren = function (new$,typ){
|
3725
|
+
var old = this._children;
|
3726
|
+
// var isArray = nodes isa Array
|
3727
|
+
if (new$ === old) {
|
3728
|
+
return this;
|
3729
|
+
};
|
3730
|
+
|
3731
|
+
if (!(old)) {
|
3732
|
+
this.empty();
|
3733
|
+
appendNested(this,new$);
|
3734
|
+
} else if (typ == 2) {
|
3735
|
+
return this;
|
3736
|
+
} else if (typ == 1) {
|
3737
|
+
// here we _know _that it is an array with the same shape
|
3738
|
+
// every time
|
3739
|
+
var caret = null;
|
3740
|
+
for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
|
3741
|
+
// prev = old[i]
|
3742
|
+
caret = reconcileNested(this,ary[i],old[i],caret);
|
3743
|
+
};
|
3744
|
+
} else if (typ == 3) {
|
3745
|
+
// this is possibly fully dynamic. It often is
|
3746
|
+
// but the old or new could be static while the other is not
|
3747
|
+
// this is not handled now
|
3748
|
+
// what if it was previously a static array? edgecase - but must work
|
3749
|
+
if (new$ instanceof ImbaTag) {
|
3750
|
+
this.empty();
|
3751
|
+
this.appendChild(new$);
|
3752
|
+
} else if (new$ instanceof Array) {
|
3753
|
+
if (old instanceof Array) {
|
3754
|
+
// is this not the same as setting staticChildren now but with the
|
3755
|
+
reconcileCollection(this,new$,old,null);
|
3756
|
+
} else {
|
3757
|
+
this.empty();
|
3758
|
+
appendNested(this,new$);
|
3759
|
+
};
|
3760
|
+
} else {
|
3761
|
+
this.setText(new$);
|
3762
|
+
return this;
|
3763
|
+
};
|
3764
|
+
} else if ((new$ instanceof Array) && (old instanceof Array)) {
|
3765
|
+
reconcileCollection(this,new$,old,null);
|
3766
|
+
} else {
|
3767
|
+
this.empty();
|
3768
|
+
appendNested(this,new$);
|
3769
|
+
};
|
3770
|
+
|
3771
|
+
this._children = new$;
|
3772
|
+
return this;
|
3773
|
+
};
|
3774
|
+
|
3775
|
+
|
3776
|
+
// only ever called with array as argument
|
3777
|
+
tag.prototype.setStaticChildren = function (new$){
|
3778
|
+
var old = this._children;
|
3779
|
+
|
3780
|
+
var caret = null;
|
3781
|
+
for (var i = 0, ary = iter$(new$), len = ary.length; i < len; i++) {
|
3782
|
+
// prev = old[i]
|
3783
|
+
caret = reconcileNested(this,ary[i],old[i],caret);
|
3784
|
+
};
|
3785
|
+
|
3786
|
+
this._children = new$;
|
3787
|
+
return this;
|
3788
|
+
};
|
3789
|
+
|
3790
|
+
tag.prototype.content = function (){
|
3791
|
+
return this._content || this.children().toArray();
|
3792
|
+
};
|
3793
|
+
|
3794
|
+
tag.prototype.setText = function (text){
|
3795
|
+
if (text != this._children) {
|
3796
|
+
this._children = text;
|
3797
|
+
this.dom().textContent = text == null || text === false ? ('') : (text);
|
3798
|
+
};
|
3799
|
+
return this;
|
3800
|
+
};
|
3801
|
+
});
|
3802
|
+
|
3803
|
+
})()
|
3804
|
+
|
3805
|
+
/***/ },
|
3806
|
+
/* 11 */
|
3807
|
+
/***/ function(module, exports) {
|
3808
|
+
|
3809
|
+
(function(){
|
3810
|
+
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
|
3811
|
+
|
3812
|
+
/*
|
3813
|
+
The special syntax for selectors in Imba creates Imba.Selector
|
3814
|
+
instances.
|
3815
|
+
*/
|
3816
|
+
|
3817
|
+
Imba.Selector = function Selector(sel,scope,nodes){
|
3818
|
+
|
3819
|
+
this._query = sel instanceof Imba.Selector ? (sel.query()) : (sel);
|
3820
|
+
this._context = scope;
|
3821
|
+
|
3822
|
+
if (nodes) {
|
3823
|
+
for (var i = 0, ary = iter$(nodes), len = ary.length, res = []; i < len; i++) {
|
3824
|
+
res.push(tag$wrap(ary[i]));
|
3825
|
+
};
|
3826
|
+
this._nodes = res;
|
3827
|
+
};
|
3828
|
+
|
3829
|
+
this._lazy = !(nodes);
|
3830
|
+
return this;
|
3831
|
+
};
|
3832
|
+
|
3833
|
+
Imba.Selector.one = function (sel,scope){
|
3834
|
+
var el = (scope || Imba.document()).querySelector(sel);
|
3835
|
+
return el && tag$wrap(el) || null;
|
3836
|
+
};
|
3837
|
+
|
3838
|
+
Imba.Selector.all = function (sel,scope){
|
3839
|
+
return new Imba.Selector(sel,scope);
|
3840
|
+
};
|
3841
|
+
|
3842
|
+
Imba.Selector.prototype.query = function(v){ return this._query; }
|
3843
|
+
Imba.Selector.prototype.setQuery = function(v){ this._query = v; return this; };
|
3844
|
+
|
3845
|
+
Imba.Selector.prototype.reload = function (){
|
3846
|
+
this._nodes = null;
|
3847
|
+
return this;
|
3848
|
+
};
|
3849
|
+
|
3850
|
+
Imba.Selector.prototype.scope = function (){
|
3851
|
+
var ctx;
|
3852
|
+
if (this._scope) { return this._scope };
|
3853
|
+
if (!(ctx = this._context)) { return Imba.document() };
|
3854
|
+
return this._scope = ctx.toScope ? (ctx.toScope()) : (ctx);
|
3855
|
+
};
|
3856
|
+
|
3857
|
+
/*
|
3858
|
+
@returns {Imba.Tag} first node matching this selector
|
3859
|
+
*/
|
3860
|
+
|
3861
|
+
Imba.Selector.prototype.first = function (){
|
3862
|
+
if (this._lazy) { return tag$wrap(this._first || (this._first = this.scope().querySelector(this.query()))) } else {
|
3863
|
+
return this.nodes()[0];
|
3864
|
+
};
|
3865
|
+
};
|
3866
|
+
|
3867
|
+
/*
|
3868
|
+
@returns {Imba.Tag} last node matching this selector
|
3869
|
+
*/
|
3870
|
+
|
3871
|
+
Imba.Selector.prototype.last = function (){
|
3872
|
+
return this.nodes()[this._nodes.length - 1];
|
3873
|
+
};
|
3874
|
+
|
3875
|
+
/*
|
3876
|
+
@returns [Imba.Tag] all nodes matching this selector
|
3877
|
+
*/
|
3878
|
+
|
3879
|
+
Imba.Selector.prototype.nodes = function (){
|
3880
|
+
if (this._nodes) { return this._nodes };
|
3881
|
+
var items = this.scope().querySelectorAll(this.query());
|
3882
|
+
for (var i = 0, ary = iter$(items), len = ary.length, res = []; i < len; i++) {
|
3883
|
+
res.push(tag$wrap(ary[i]));
|
3884
|
+
};
|
3885
|
+
this._nodes = res;
|
3886
|
+
this._lazy = false;
|
3887
|
+
return this._nodes;
|
3888
|
+
};
|
3889
|
+
|
3890
|
+
/*
|
3891
|
+
The number of nodes matching this selector
|
3892
|
+
*/
|
3893
|
+
|
3894
|
+
Imba.Selector.prototype.count = function (){
|
3895
|
+
return this.nodes().length;
|
3896
|
+
};
|
3897
|
+
|
3898
|
+
Imba.Selector.prototype.len = function (){
|
3899
|
+
return this.nodes().length;
|
3900
|
+
};
|
3901
|
+
|
3902
|
+
/*
|
3903
|
+
@todo Add support for block or selector?
|
3904
|
+
*/
|
3905
|
+
|
3906
|
+
Imba.Selector.prototype.some = function (){
|
3907
|
+
return this.count() >= 1;
|
3908
|
+
};
|
3909
|
+
|
3910
|
+
/*
|
3911
|
+
Get node at index
|
3912
|
+
*/
|
3913
|
+
|
3914
|
+
Imba.Selector.prototype.at = function (idx){
|
3915
|
+
return this.nodes()[idx];
|
3916
|
+
};
|
3917
|
+
|
3918
|
+
/*
|
3919
|
+
Loop through nodes
|
3920
|
+
*/
|
3921
|
+
|
3922
|
+
Imba.Selector.prototype.forEach = function (block){
|
3923
|
+
this.nodes().forEach(block);
|
3924
|
+
return this;
|
3925
|
+
};
|
3926
|
+
|
3927
|
+
/*
|
3928
|
+
Map nodes
|
3929
|
+
*/
|
3930
|
+
|
3931
|
+
Imba.Selector.prototype.map = function (block){
|
3932
|
+
return this.nodes().map(block);
|
3933
|
+
};
|
3934
|
+
|
3935
|
+
/*
|
3936
|
+
Returns a plain array containing nodes. Implicitly called
|
3937
|
+
when iterating over a selector in Imba `(node for node in $(selector))`
|
3938
|
+
*/
|
3939
|
+
|
3940
|
+
Imba.Selector.prototype.toArray = function (){
|
3941
|
+
return this.nodes();
|
3942
|
+
};
|
3943
|
+
|
3944
|
+
// Get the first element that matches the selector,
|
3945
|
+
// beginning at the current element and progressing up through the DOM tree
|
3946
|
+
Imba.Selector.prototype.closest = function (sel){
|
3947
|
+
// seems strange that we alter this selector?
|
3948
|
+
this._nodes = this.map(function(node) { return node.closest(sel); });
|
3949
|
+
return this;
|
3950
|
+
};
|
3951
|
+
|
3952
|
+
// Get the siblings of each element in the set of matched elements,
|
3953
|
+
// optionally filtered by a selector.
|
3954
|
+
// TODO remove duplicates?
|
3955
|
+
Imba.Selector.prototype.siblings = function (sel){
|
3956
|
+
this._nodes = this.map(function(node) { return node.siblings(sel); });
|
3957
|
+
return this;
|
3958
|
+
};
|
3959
|
+
|
3960
|
+
// Get the descendants of each element in the current set of matched
|
3961
|
+
// elements, filtered by a selector.
|
3962
|
+
Imba.Selector.prototype.find = function (sel){
|
3963
|
+
this._nodes = this.__query__(sel.query(),this.nodes());
|
3964
|
+
return this;
|
3965
|
+
};
|
3966
|
+
|
3967
|
+
Imba.Selector.prototype.reject = function (blk){
|
3968
|
+
return this.filter(blk,false);
|
3969
|
+
};
|
3970
|
+
|
3971
|
+
/*
|
3972
|
+
Filter the nodes in selector by a function or other selector
|
3973
|
+
*/
|
3974
|
+
|
3975
|
+
Imba.Selector.prototype.filter = function (blk,bool){
|
3976
|
+
if(bool === undefined) bool = true;
|
3977
|
+
var fn = (blk instanceof Function) && blk || function(n) { return n.matches(blk); };
|
3978
|
+
var ary = this.nodes().filter(function(n) { return fn(n) == bool; });
|
3979
|
+
// if we want to return a new selector for this, we should do that for
|
3980
|
+
// others as well
|
3981
|
+
return new Imba.Selector("",this._scope,ary);
|
3982
|
+
};
|
3983
|
+
|
3984
|
+
Imba.Selector.prototype.__query__ = function (query,contexts){
|
3985
|
+
var nodes = [];
|
3986
|
+
var i = 0;
|
3987
|
+
var l = contexts.length;
|
3988
|
+
|
3989
|
+
while (i < l){
|
3990
|
+
nodes.push.apply(nodes,contexts[i++].querySelectorAll(query));
|
3991
|
+
};
|
3992
|
+
return nodes;
|
3993
|
+
};
|
3994
|
+
|
3995
|
+
Imba.Selector.prototype.__matches__ = function (){
|
3996
|
+
return true;
|
3997
|
+
};
|
3998
|
+
|
3999
|
+
/*
|
4000
|
+
Add specified flag to all nodes in selector
|
4001
|
+
*/
|
4002
|
+
|
4003
|
+
Imba.Selector.prototype.flag = function (flag){
|
4004
|
+
return this.forEach(function(n) { return n.flag(flag); });
|
4005
|
+
};
|
4006
|
+
|
4007
|
+
/*
|
4008
|
+
Remove specified flag from all nodes in selector
|
4009
|
+
*/
|
4010
|
+
|
4011
|
+
Imba.Selector.prototype.unflag = function (flag){
|
4012
|
+
return this.forEach(function(n) { return n.unflag(flag); });
|
4013
|
+
};
|
4014
|
+
|
4015
|
+
|
4016
|
+
// def Imba.querySelectorAll
|
4017
|
+
q$ = function(sel,scope) { return new Imba.Selector(sel,scope); };
|
4018
|
+
|
4019
|
+
// def Imba.Selector.one
|
4020
|
+
q$$ = function(sel,scope) {
|
4021
|
+
var el = (scope || Imba.document()).querySelector(sel);
|
4022
|
+
return el && tag$wrap(el) || null;
|
4023
|
+
};
|
4024
|
+
|
4025
|
+
|
4026
|
+
// extending tags with query-methods
|
4027
|
+
// must be a better way to reopen classes
|
4028
|
+
return tag$.extendTag('element', function(tag){
|
4029
|
+
tag.prototype.querySelectorAll = function (q){
|
4030
|
+
return this._dom.querySelectorAll(q);
|
4031
|
+
};
|
4032
|
+
tag.prototype.querySelector = function (q){
|
4033
|
+
return this._dom.querySelector(q);
|
4034
|
+
};
|
4035
|
+
|
4036
|
+
// should be moved to Imba.Tag instead?
|
4037
|
+
// or we should implement all of them here
|
4038
|
+
tag.prototype.find = function (sel){
|
4039
|
+
return new Imba.Selector(sel,this);
|
4040
|
+
};
|
4041
|
+
});
|
4042
|
+
|
4043
|
+
|
4044
|
+
})()
|
4045
|
+
|
4046
|
+
/***/ }
|
4047
|
+
/******/ ]);
|
4048
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgYmNmNDBhNWMzMzRhYzIxOTc1MzEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2luZGV4LmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2ltYmEuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvY29yZS5ldmVudHMuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvc2NoZWR1bGVyLmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL3RhZy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9kb20uaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLmh0bWwuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLnN2Zy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9kb20uY2xpZW50LmltYmEiLCJ3ZWJwYWNrOi8vL3NyYy9pbWJhL2RvbS5ldmVudHMuaW1iYSIsIndlYnBhY2s6Ly8vc3JjL2ltYmEvZG9tLnN0YXRpYy5pbWJhIiwid2VicGFjazovLy9zcmMvaW1iYS9zZWxlY3Rvci5pbWJhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1QkFBZTtBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7Ozs7RUNyQ0EsV0FBVSxLQUFLO0dBQ2Q7R0FDQTtHQUNBO0dBQ0E7R0FDQTtHQUNBO0dBQ0E7O0dBRUEsSUFBRyxLQUFLO0lBQ1A7OztHQUVELElBQUcsSUFBSztJQUNQO0lBQ0E7SUFDQTs7O1VBRUQ7O1VBRUEsUUFBUSxrQkFBYSxLQUFLOzs7Ozs7Ozs7O0VDcEIzQixXQUFVLE9BQU87O0dBRWhCLE9BQU8sRUFBRTs7O01BRU4sU0FBUyxVQUFVLE9BQU8sWUFBWSxRQUFTLEdB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ckM7OztFQUVSLEtBdklVOzs7Ozs7OztFQTZJVixLQTdJVTtlQThJVCw2QkFBZSxFQUFFLEtBQUs7Ozs7Ozs7RUFLdkIsS0FuSlU7ZUFvSlQsNkJBQWUsRUFBRSxPQUFPOzs7OztLQUl2QixtQ0FBaUIsS0FBSyxTQUFhLElBQUs7OztNQUd2QztPQUNDLEdBQUcsR0FBRyxNQUFNLEdBQUcsS0FBSyxZQUFVLGNBQWM7VUFDaEQsR0FBRyxZQUFPLElBQUk7Ozs7OztTQUtSO0dBQ047Z0JBQTBCLEtBQUssaUJBQWlCOztHQUNoRDtnQkFBdUIsS0FBSyxjQUFjOzs7OztHQUkxQztlQUFnQixLQUFLLFNBQWEiLCJmaWxlIjoiLi9kaXN0L2ltYmEuZGV2LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pXG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG5cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGV4cG9ydHM6IHt9LFxuIFx0XHRcdGlkOiBtb2R1bGVJZCxcbiBcdFx0XHRsb2FkZWQ6IGZhbHNlXG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmxvYWRlZCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oMCk7XG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiB3ZWJwYWNrL2Jvb3RzdHJhcCBiY2Y0MGE1YzMzNGFjMjE5NzUzMVxuICoqLyIsIlxuaWYgdHlwZW9mIEltYmEgPT09ICd1bmRlZmluZWQnXG5cdHJlcXVpcmUgJy4vaW1iYSdcblx0cmVxdWlyZSAnLi9jb3JlLmV2ZW50cydcblx0cmVxdWlyZSAnLi9zY2hlZHVsZXInXG5cdHJlcXVpcmUgJy4vdGFnJ1xuXHRyZXF1aXJlICcuL2RvbSdcblx0cmVxdWlyZSAnLi9kb20uaHRtbCdcblx0cmVxdWlyZSAnLi9kb20uc3ZnJ1xuXG5cdGlmIEltYmEuU0VSVkVSXG5cdFx0cmVxdWlyZSAnLi9kb20uc2VydmVyJ1xuXHRcblx0aWYgSW1iYS5DTElFTlRcblx0XHRyZXF1aXJlICcuL2RvbS5jbGllbnQnXG5cdFx0cmVxdWlyZSAnLi9kb20uZXZlbnRzJ1xuXHRcdHJlcXVpcmUgJy4vZG9tLnN0YXRpYydcblxuXHRyZXF1aXJlICcuL3NlbGVjdG9yJ1xuZWxzZVxuXHRjb25zb2xlLndhcm4gXCJJbWJhIHZ7SW1iYS5WRVJTSU9OfSBpcyBhbHJlYWR5IGxvYWRlZFwiXG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9pbmRleC5pbWJhXG4gKiovIiwiaWYgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcblx0IyBzaG91bGQgbm90IGdvIHRoZXJlXG5cdGdsb2JhbCA9IHdpbmRvd1xuXG52YXIgaXNDbGllbnQgPSAodHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyBhbmQgdGhpcyA9PSB3aW5kb3cpXG4jIyNcbkltYmEgaXMgdGhlIG5hbWVzcGFjZSBmb3IgYWxsIHJ1bnRpbWUgcmVsYXRlZCB1dGlsaXRpZXNcbkBuYW1lc3BhY2VcbiMjI1xuSW1iYSA9IHtcblx0VkVSU0lPTjogJzAuMTQuMydcblx0Q0xJRU5UOiBpc0NsaWVudFxuXHRTRVJWRVI6ICFpc0NsaWVudFxuXHRERUJVRzogbm9cbn1cblxudmFyIHJlZyA9IC8tLi9nXG5cbiMjI1xuVHJ1ZSBpZiBydW5uaW5nIGluIGNsaWVudCBlbnZpcm9ubWVudC5cbkByZXR1cm4ge2Jvb2x9XG4jIyNcbmRlZiBJbWJhLmlzQ2xpZW50XG5cdEltYmEuQ0xJRU5UID09IHllc1xuXG4jIyNcblRydWUgaWYgcnVubmluZyBpbiBzZXJ2ZXIgZW52aXJvbm1lbnQuXG5AcmV0dXJuIHtib29sfVxuIyMjXG5kZWYgSW1iYS5pc1NlcnZlclxuXHRJbWJhLlNFUlZFUiA9PSB5ZXNcblxuZGVmIEltYmEuc3ViY2xhc3Mgb2JqLCBzdXBcblx0Zm9yIGssdiBvZiBzdXBcblx0XHRvYmpba10gPSB2IGlmIHN1cC5oYXNPd25Qcm9wZXJ0eShrKVxuXG5cdG9iajpwcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cDpwcm90b3R5cGUpXG5cdG9iajpfX3N1cGVyX18gPSBvYmo6cHJvdG90eXBlOl9fc3VwZXJfXyA9IHN1cDpwcm90b3R5cGVcblx0b2JqOnByb3RvdHlwZTppbml0aWFsaXplID0gb2JqOnByb3RvdHlwZTpjb25zdHJ1Y3RvciA9IG9ialxuXHRyZXR1cm4gb2JqXG5cbiMjI1xuTGlnaHR3ZWlnaHQgbWV0aG9kIGZvciBtYWtpbmcgYW4gb2JqZWN0IGl0ZXJhYmxlIGluIGltYmFzIGZvci9pbiBsb29wcy5cbklmIHRoZSBjb21waWxlciBjYW5ub3Qgc2F5IGZvciBjZXJ0YWluIHRoYXQgYSB0YXJnZXQgaW4gYSBmb3IgbG9vcCBpcyBhblxuYXJyYXksIGl0IHdpbGwgY2FjaGUgdGhlIGl0ZXJhYmxlIHZlcnNpb24gYmVmb3JlIGxvb3BpbmcuXG5cbmBgYGltYmFcbiMgdGhpcyBpcyB0aGUgd2hvbGUgbWV0aG9kXG5kZWYgSW1iYS5pdGVyYWJsZSBvXG5cdHJldHVybiBvID8gKG86dG9BcnJheSA/IG8udG9BcnJheSA6IG8pIDogW11cblxuY2xhc3MgQ3VzdG9tSXRlcmFibGVcblx0ZGVmIHRvQXJyYXlcblx0XHRbMSwyLDNdXG5cbiMgd2lsbCByZXR1cm4gWzIsNCw2XVxuZm9yIHggaW4gQ3VzdG9tSXRlcmFibGUubmV3XG5cdHggKiAyXG5cbmBgYFxuIyMjXG5kZWYgSW1iYS5pdGVyYWJsZSBvXG5cdHJldHVybiBvID8gKG86dG9BcnJheSA/IG8udG9BcnJheSA6IG8pIDogW11cblxuIyMjXG5Db2VyY2VzIGEgdmFsdWUgaW50byBhIHByb21pc2UuIElmIHZhbHVlIGlzIGFycmF5IGl0IHdpbGxcbmNhbGwgYFByb21pc2UuYWxsKHZhbHVlKWAsIG9yIGlmIGl0IGlzIG5vdCBhIHByb21pc2UgaXQgd2lsbFxud3JhcCB0aGUgdmFsdWUgaW4gYFByb21pc2UucmVzb2x2ZSh2YWx1ZSlgLiBVc2VkIGZvciBleHBlcmltZW50YWxcbmF3YWl0IHN5bnRheC5cbkByZXR1cm4ge1Byb21pc2V9XG4jIyNcbmRlZiBJbWJhLmF3YWl0IHZhbHVlXG5cdGlmIHZhbHVlIGlzYSBBcnJheVxuXHRcdFByb21pc2UuYWxsKHZhbHVlKVxuXHRlbGlmIHZhbHVlIGFuZCB2YWx1ZTp0aGVuXG5cdFx0dmFsdWVcblx0ZWxzZVxuXHRcdFByb21pc2UucmVzb2x2ZSh2YWx1ZSlcblxuZGVmIEltYmEudG9DYW1lbENhc2Ugc3RyXG5cdHN0ci5yZXBsYWNlKHJlZykgZG8gfG18IG0uY2hhckF0KDEpLnRvVXBwZXJDYXNlXG5cbmRlZiBJbWJhLnRvQ2FtZWxDYXNlIHN0clxuXHRzdHIucmVwbGFjZShyZWcpIGRvIHxtfCBtLmNoYXJBdCgxKS50b1VwcGVyQ2FzZVxuXG5kZWYgSW1iYS5pbmRleE9mIGEsYlxuXHRyZXR1cm4gKGIgJiYgYjppbmRleE9mKSA/IGIuaW5kZXhPZihhKSA6IFtdOmluZGV4T2YuY2FsbChhLGIpXG5cbmRlZiBJbWJhLnByb3Agc2NvcGUsIG5hbWUsIG9wdHNcblx0aWYgc2NvcGU6ZGVmaW5lUHJvcGVydHlcblx0XHRyZXR1cm4gc2NvcGUuZGVmaW5lUHJvcGVydHkobmFtZSxvcHRzKVxuXHRyZXR1cm5cblxuZGVmIEltYmEuYXR0ciBzY29wZSwgbmFtZSwgb3B0c1xuXHRpZiBzY29wZTpkZWZpbmVBdHRyaWJ1dGVcblx0XHRyZXR1cm4gc2NvcGUuZGVmaW5lQXR0cmlidXRlKG5hbWUsb3B0cylcblxuXHRsZXQgZ2V0TmFtZSA9IEltYmEudG9DYW1lbENhc2UobmFtZSlcblx0bGV0IHNldE5hbWUgPSBJbWJhLnRvQ2FtZWxDYXNlKCdzZXQtJyArIG5hbWUpXG5cblx0c2NvcGU6cHJvdG90eXBlW2dldE5hbWVdID0gZG9cblx0XHRyZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUobmFtZSlcblxuXHRzY29wZTpwcm90b3R5cGVbc2V0TmFtZV0gPSBkbyB8dmFsdWV8XG5cdFx0dGhpcy5zZXRBdHRyaWJ1dGUobmFtZSx2YWx1ZSlcblx0XHRyZXR1cm4gdGhpc1xuXG5cdHJldHVyblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvaW1iYS5pbWJhXG4gKiovIiwiXG5cbmRlZiBlbWl0X18gZXZlbnQsIGFyZ3MsIG5vZGVcblx0IyB2YXIgbm9kZSA9IGNic1tldmVudF1cblx0dmFyIHByZXYsIGNiLCByZXRcblxuXHR3aGlsZSAocHJldiA9IG5vZGUpIGFuZCAobm9kZSA9IG5vZGU6bmV4dClcblx0XHRpZiBjYiA9IG5vZGU6bGlzdGVuZXJcblx0XHRcdGlmIG5vZGU6cGF0aCBhbmQgY2Jbbm9kZTpwYXRoXVxuXHRcdFx0XHRyZXQgPSBhcmdzID8gY2Jbbm9kZTpwYXRoXS5hcHBseShjYixhcmdzKSA6IGNiW25vZGU6cGF0aF0oKVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHQjIGNoZWNrIGlmIGl0IGlzIGEgbWV0aG9kP1xuXHRcdFx0XHRyZXQgPSBhcmdzID8gY2IuYXBwbHkobm9kZSwgYXJncykgOiBjYi5jYWxsKG5vZGUpXG5cblx0XHRpZiBub2RlOnRpbWVzICYmIC0tbm9kZTp0aW1lcyA8PSAwXG5cdFx0XHRwcmV2Om5leHQgPSBub2RlOm5leHRcblx0XHRcdG5vZGU6bGlzdGVuZXIgPSBudWxsXG5cdHJldHVyblxuXG4jIG1ldGhvZCBmb3IgcmVnaXN0ZXJpbmcgYSBsaXN0ZW5lciBvbiBvYmplY3RcbmRlZiBJbWJhLmxpc3RlbiBvYmosIGV2ZW50LCBsaXN0ZW5lciwgcGF0aFxuXHR2YXIgY2JzLCBsaXN0LCB0YWlsXG5cdGNicyA9IG9iajpfX2xpc3RlbmVyc19fIHx8PSB7fVxuXHRsaXN0ID0gY2JzW2V2ZW50XSB8fD0ge31cblx0dGFpbCA9IGxpc3Q6dGFpbCB8fCAobGlzdDp0YWlsID0gKGxpc3Q6bmV4dCA9IHt9KSlcblx0dGFpbDpsaXN0ZW5lciA9IGxpc3RlbmVyXG5cdHRhaWw6cGF0aCA9IHBhdGhcblx0bGlzdDp0YWlsID0gdGFpbDpuZXh0ID0ge31cblx0cmV0dXJuIHRhaWxcblxuZGVmIEltYmEub25jZSBvYmosIGV2ZW50LCBsaXN0ZW5lclxuXHR2YXIgdGFpbCA9IEltYmEubGlzdGVuKG9iaixldmVudCxsaXN0ZW5lcilcblx0dGFpbDp0aW1lcyA9IDFcblx0cmV0dXJuIHRhaWxcblxuZGVmIEltYmEudW5saXN0ZW4gb2JqLCBldmVudCwgY2IsIG1ldGhcblx0dmFyIG5vZGUsIHByZXZcblx0dmFyIG1ldGEgPSBvYmo6X19saXN0ZW5lcnNfX1xuXHRyZXR1cm4gdW5sZXNzIG1ldGFcblxuXHRpZiBub2RlID0gbWV0YVtldmVudF1cblx0XHR3aGlsZSAocHJldiA9IG5vZGUpIGFuZCAobm9kZSA9IG5vZGU6bmV4dClcblx0XHRcdGlmIG5vZGUgPT0gY2IgfHwgbm9kZTpsaXN0ZW5lciA9PSBjYlxuXHRcdFx0XHRwcmV2Om5leHQgPSBub2RlOm5leHRcblx0XHRcdFx0IyBjaGVjayBmb3IgY29ycmVjdCBwYXRoIGFzIHdlbGw/XG5cdFx0XHRcdG5vZGU6bGlzdGVuZXIgPSBudWxsXG5cdFx0XHRcdGJyZWFrXG5cdHJldHVyblxuXG5kZWYgSW1iYS5lbWl0IG9iaiwgZXZlbnQsIHBhcmFtc1xuXHRpZiB2YXIgY2IgPSBvYmo6X19saXN0ZW5lcnNfX1xuXHRcdGVtaXRfXyhldmVudCxwYXJhbXMsY2JbZXZlbnRdKSBpZiBjYltldmVudF1cblx0XHRlbWl0X18oZXZlbnQsW2V2ZW50LHBhcmFtc10sY2I6YWxsKSBpZiBjYjphbGwgIyBhbmQgZXZlbnQgIT0gJ2FsbCdcblx0cmV0dXJuXG5cbmRlZiBJbWJhLm9ic2VydmVQcm9wZXJ0eSBvYnNlcnZlciwga2V5LCB0cmlnZ2VyLCB0YXJnZXQsIHByZXZcblx0aWYgcHJldiBhbmQgdHlwZW9mIHByZXYgPT0gJ29iamVjdCdcblx0XHRJbWJhLnVubGlzdGVuKHByZXYsJ2FsbCcsb2JzZXJ2ZXIsdHJpZ2dlcilcblx0aWYgdGFyZ2V0IGFuZCB0eXBlb2YgdGFyZ2V0ID09ICdvYmplY3QnXG5cdFx0SW1iYS5saXN0ZW4odGFyZ2V0LCdhbGwnLG9ic2VydmVyLHRyaWdnZXIpXG5cdHNlbGZcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9jb3JlLmV2ZW50cy5pbWJhXG4gKiovIiwiXG52YXIgcmFmICMgdmVyeSBzaW1wbGUgcmFmIHBvbHlmaWxsXG5yYWYgfHw9IGdsb2JhbDpyZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbnJhZiB8fD0gZ2xvYmFsOndlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZVxucmFmIHx8PSBnbG9iYWw6bW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lXG5yYWYgfHw9IGRvIHxibGt8IHNldFRpbWVvdXQoYmxrLDEwMDAgLyA2MClcblxuZGVmIEltYmEudGljayBkXG5cdHJhZihJbWJhLnRpY2tlcikgaWYgQHNjaGVkdWxlZFxuXHRJbWJhLlNjaGVkdWxlci53aWxsUnVuXG5cdGVtaXQoc2VsZiwndGljaycsW2RdKVxuXHRJbWJhLlNjaGVkdWxlci5kaWRSdW5cblx0cmV0dXJuXG5cbmRlZiBJbWJhLnRpY2tlclxuXHRAdGlja2VyIHx8PSBkbyB8ZXwgdGljayhlKVxuXG4jIyNcblxuR2xvYmFsIGFsdGVybmF0aXZlIHRvIHJlcXVlc3RBbmltYXRpb25GcmFtZS4gU2NoZWR1bGUgYSB0YXJnZXRcbnRvIHRpY2sgZXZlcnkgZnJhbWUuIFlvdSBjYW4gc3BlY2lmeSB3aGljaCBtZXRob2QgdG8gY2FsbCBvbiB0aGVcbnRhcmdldCAoZGVmYXVsdHMgdG8gdGljaykuXG5cbiMjI1xuZGVmIEltYmEuc2NoZWR1bGUgdGFyZ2V0LCBtZXRob2QgPSAndGljaydcblx0bGlzdGVuKHNlbGYsJ3RpY2snLHRhcmdldCxtZXRob2QpXG5cdCMgc3RhcnQgc2NoZWR1bGluZyBub3cgaWYgdGhpcyB3YXMgdGhlIGZpcnN0IG9uZVxuXHR1bmxlc3MgQHNjaGVkdWxlZFxuXHRcdEBzY2hlZHVsZWQgPSB5ZXNcblx0XHRyYWYoSW1iYS50aWNrZXIpXG5cdHNlbGZcblxuIyMjXG5cblVuc2NoZWR1bGUgYSBwcmV2aW91c2x5IHNjaGVkdWxlZCB0YXJnZXRcblxuIyMjXG5kZWYgSW1iYS51bnNjaGVkdWxlIHRhcmdldCwgbWV0aG9kXG5cdHVubGlzdGVuKHNlbGYsJ3RpY2snLHRhcmdldCxtZXRob2QpXG5cdHZhciBjYnMgPSBzZWxmOl9fbGlzdGVuZXJzX18gfHw9IHt9XG5cdGlmICFjYnM6dGljayBvciAhY2JzOnRpY2s6bmV4dCBvciAhY2JzOnRpY2s6bmV4dDpsaXN0ZW5lclxuXHRcdEBzY2hlZHVsZWQgPSBub1xuXHRzZWxmXG5cbiMjI1xuXG5MaWdodCB3cmFwcGVyIGFyb3VuZCBuYXRpdmUgc2V0VGltZW91dCB0aGF0IGV4cGVjdHMgdGhlIGJsb2NrIC8gZnVuY3Rpb25cbmFzIGxhc3QgYXJndW1lbnQgKGluc3RlYWQgb2YgZmlyc3QpLiBJdCBhbHNvIHRyaWdnZXJzIGFuIGV2ZW50IHRvIEltYmFcbmFmdGVyIHRoZSB0aW1lb3V0IHRvIGxldCBzY2hlZHVsZXJzIHVwZGF0ZSAodG8gcmVyZW5kZXIgZXRjKSBhZnRlcndhcmRzLlxuXG4jIyNcbmRlZiBJbWJhLnNldFRpbWVvdXQgZGVsYXksICZibG9ja1xuXHRzZXRUaW1lb3V0KCYsZGVsYXkpIGRvXG5cdFx0YmxvY2soKVxuXHRcdEltYmEuU2NoZWR1bGVyLm1hcmtEaXJ0eVxuXHRcdCMgSW1iYS5lbWl0KEltYmEsJ3RpbWVvdXQnLFtibG9ja10pXG5cbiMjI1xuXG5MaWdodCB3cmFwcGVyIGFyb3VuZCBuYXRpdmUgc2V0SW50ZXJ2YWwgdGhhdCBleHBlY3RzIHRoZSBibG9jayAvIGZ1bmN0aW9uXG5hcyBsYXN0IGFyZ3VtZW50IChpbnN0ZWFkIG9mIGZpcnN0KS4gSXQgYWxzbyB0cmlnZ2VycyBhbiBldmVudCB0byBJbWJhXG5hZnRlciBldmVyeSBpbnRlcnZhbCB0byBsZXQgc2NoZWR1bGVycyB1cGRhdGUgKHRvIHJlcmVuZGVyIGV0YykgYWZ0ZXJ3YXJkcy5cblxuIyMjXG5kZWYgSW1iYS5zZXRJbnRlcnZhbCBpbnRlcnZhbCwgJmJsb2NrXG5cdHNldEludGVydmFsKCYsaW50ZXJ2YWwpIGRvXG5cdFx0YmxvY2soKVxuXHRcdEltYmEuU2NoZWR1bGVyLm1hcmtEaXJ0eVxuXHRcdCMgSW1iYS5lbWl0KEltYmEsJ2ludGVydmFsJyxbYmxvY2tdKVxuXG4jIyNcbkNsZWFyIGludGVydmFsIHdpdGggc3BlY2lmaWVkIGlkXG4jIyNcbmRlZiBJbWJhLmNsZWFySW50ZXJ2YWwgaW50ZXJ2YWxcblx0Y2xlYXJJbnRlcnZhbChpbnRlcnZhbClcblxuIyMjXG5DbGVhciB0aW1lb3V0IHdpdGggc3BlY2lmaWVkIGlkXG4jIyNcbmRlZiBJbWJhLmNsZWFyVGltZW91dCB0aW1lb3V0XG5cdGNsZWFyVGltZW91dCh0aW1lb3V0KVxuXG4jIHNob3VsZCBhZGQgYW4gSW1iYS5ydW4gLyBzZXRJbW1lZGlhdGUgdGhhdFxuIyBwdXNoZXMgbGlzdGVuZXIgb250byB0aGUgdGljay1xdWV1ZSB3aXRoIHRpbWVzIC0gb25jZVxuXG5cbiMjI1xuXG5JbnN0YW5jZXMgb2YgSW1iYS5TY2hlZHVsZXIgbWFuYWdlcyB3aGVuIHRvIGNhbGwgYHRpY2soKWAgb24gdGhlaXIgdGFyZ2V0LFxuYXQgYSBzcGVjaWZpZWQgZnJhbWVyYXRlIG9yIHdoZW4gY2VydGFpbiBldmVudHMgb2NjdXIuIFJvb3Qtbm9kZXMgaW4geW91clxuYXBwbGljYXRpb25zIHdpbGwgdXN1YWxseSBoYXZlIGEgc2NoZWR1bGVyIHRvIG1ha2Ugc3VyZSB0aGV5IHJlcmVuZGVyIHdoZW5cbnNvbWV0aGluZyBjaGFuZ2VzLiBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIG1ha2UgaW5uZXIgY29tcG9uZW50cyB1c2UgdGhlaXJcbm93biBzY2hlZHVsZXJzIHRvIGNvbnRyb2wgd2hlbiB0aGV5IHJlbmRlci5cblxuQGluYW1lIHNjaGVkdWxlclxuXG4jIyNcbmNsYXNzIEltYmEuU2NoZWR1bGVyXG5cblx0ZGVmIHNlbGYubWFya0RpcnR5XG5cdFx0QGRpcnR5ID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLmlzRGlydHlcblx0XHQhIUBkaXJ0eVxuXG5cdGRlZiBzZWxmLndpbGxSdW5cblx0XHRAYWN0aXZlID0geWVzXG5cblx0ZGVmIHNlbGYuZGlkUnVuXG5cdFx0QGFjdGl2ZSA9IG5vXG5cdFx0QGRpcnR5ID0gbm9cblxuXHRkZWYgc2VsZi5pc0FjdGl2ZVxuXHRcdCEhQGFjdGl2ZVxuXG5cdCMjI1xuXHRDcmVhdGUgYSBuZXcgSW1iYS5TY2hlZHVsZXIgZm9yIHNwZWNpZmllZCB0YXJnZXRcblx0QHJldHVybiB7SW1iYS5TY2hlZHVsZXJ9XG5cdCMjI1xuXHRkZWYgaW5pdGlhbGl6ZSB0YXJnZXRcblx0XHRAdGFyZ2V0ID0gdGFyZ2V0XG5cdFx0QG1hcmtlZCA9IG5vXG5cdFx0QGFjdGl2ZSA9IG5vXG5cdFx0QG1hcmtlciA9IGRvIG1hcmtcblx0XHRAdGlja2VyID0gZG8gfGV8IHRpY2soZSlcblx0XHRcblx0XHRAZXZlbnRzID0geWVzXG5cdFx0QGZwcyA9IDFcblxuXHRcdEBkdCA9IDBcblx0XHRAdGltZXN0YW1wID0gMFxuXHRcdEB0aWNrcyA9IDBcblx0XHRAZmx1c2hlcyA9IDBcblxuXHQjIyNcblx0Q2hlY2sgd2hldGhlciB0aGUgY3VycmVudCBzY2hlZHVsZXIgaXMgYWN0aXZlIG9yIG5vdFxuXHRAcmV0dXJuIHtib29sfVxuXHQjIyNcblx0ZGVmIGFjdGl2ZVxuXHRcdEBhY3RpdmVcblxuXHQjIyNcblx0RGVsdGEgdGltZSBiZXR3ZWVuIHRoZSB0d28gbGFzdCB0aWNrc1xuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgZHRcblx0XHRAZHRcblxuXHQjIyNcblx0Q29uZmlndXJlIHRoZSBzY2hlZHVsZXJcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBjb25maWd1cmUgZnBzOiAxLCBldmVudHM6IHllc1xuXHRcdEBldmVudHMgPSBldmVudHMgaWYgZXZlbnRzICE9IG51bGxcblx0XHRAZnBzID0gZnBzIGlmIGZwcyAhPSBudWxsXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRNYXJrIHRoZSBzY2hlZHVsZXIgYXMgZGlydHkuIFRoaXMgd2lsbCBtYWtlIHN1cmUgdGhhdFxuXHR0aGUgc2NoZWR1bGVyIGNhbGxzIGB0YXJnZXQudGlja2Agb24gdGhlIG5leHQgZnJhbWVcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBtYXJrXG5cdFx0QG1hcmtlZCA9IHllc1xuXHRcdHNlbGZcblxuXHQjIyNcblx0SW5zdGFudGx5IHRyaWdnZXIgdGFyZ2V0LnRpY2sgYW5kIG1hcmsgc2NoZWR1bGVyIGFzIGNsZWFuIChub3QgZGlydHkvbWFya2VkKS5cblx0VGhpcyBpcyBjYWxsZWQgaW1wbGljaXRseSBmcm9tIHRpY2ssIGJ1dCBjYW4gYWxzbyBiZSBjYWxsZWQgbWFudWFsbHkgaWYgeW91XG5cdHJlYWxseSB3YW50IHRvIGZvcmNlIGEgdGljayB3aXRob3V0IHdhaXRpbmcgZm9yIHRoZSBuZXh0IGZyYW1lLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGZsdXNoXG5cdFx0QG1hcmtlZCA9IG5vXG5cdFx0QGZsdXNoZXMrK1xuXHRcdEB0YXJnZXQudGlja1xuXHRcdHNlbGZcblxuXHQjIyNcblx0QGZpeG1lIHRoaXMgZXhwZWN0cyByYWYgdG8gcnVuIGF0IDYwIGZwcyBcblxuXHRDYWxsZWQgYXV0b21hdGljYWxseSBvbiBldmVyeSBmcmFtZSB3aGlsZSB0aGUgc2NoZWR1bGVyIGlzIGFjdGl2ZS5cblx0SXQgd2lsbCBvbmx5IGNhbGwgYHRhcmdldC50aWNrYCBpZiB0aGUgc2NoZWR1bGVyIGlzIG1hcmtlZCBkaXJ0eSxcblx0b3Igd2hlbiBhY2NvcmRpbmcgdG8gQGZwcyBzZXR0aW5nLlxuXG5cdElmIHlvdSBoYXZlIHNldCB1cCBhIHNjaGVkdWxlciB3aXRoIGFuIGZwcyBvZiAxLCB0aWNrIHdpbGwgc3RpbGwgYmVcblx0Y2FsbGVkIGV2ZXJ5IGZyYW1lLCBidXQgYHRhcmdldC50aWNrYCB3aWxsIG9ubHkgYmUgY2FsbGVkIG9uY2UgZXZlcnlcblx0c2Vjb25kLCBhbmQgaXQgd2lsbCAqbWFrZSBzdXJlKiBlYWNoIGB0YXJnZXQudGlja2AgaGFwcGVucyBpbiBzZXBhcmF0ZVxuXHRzZWNvbmRzIGFjY29yZGluZyB0byBEYXRlLiBTbyBpZiB5b3UgaGF2ZSBhIG5vZGUgdGhhdCByZW5kZXJzIGEgY2xvY2tcblx0YmFzZWQgb24gRGF0ZS5ub3cgKG9yIHNvbWV0aGluZyBzaW1pbGFyKSwgeW91IGNhbiBzY2hlZHVsZSBpdCB3aXRoIDFmcHMsXG5cdG5ldmVyIG5lZWRpbmcgdG8gd29ycnkgYWJvdXQgdHdvIHRpY2tzIGhhcHBlbmluZyB3aXRoaW4gdGhlIHNhbWUgc2Vjb25kLlxuXHRUaGUgc2FtZSBnb2VzIGZvciA0ZnBzLCAxMGZwcyBldGMuXG5cblx0QHByb3RlY3RlZFxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHRpY2sgZGVsdGFcblx0XHRAdGlja3MrK1xuXHRcdEBkdCA9IGRlbHRhXG5cblx0XHRsZXQgZnBzID0gQGZwc1xuXHRcdFxuXHRcdGlmIGZwcyA9PSA2MFxuXHRcdFx0QG1hcmtlZCA9IHllc1xuXHRcdGVsaWYgZnBzID09IDMwXG5cdFx0XHRAbWFya2VkID0geWVzIGlmIEB0aWNrcyAlIDJcblx0XHRlbGlmIGZwc1xuXHRcdFx0IyBpZiBpdCBpcyBsZXNzIHJvdW5kIC0gd2UgdHJpZ2dlciBiYXNlZFxuXHRcdFx0IyBvbiBkYXRlLCBmb3IgY29uc2lzdGVudCByZW5kZXJpbmcuXG5cdFx0XHQjIGllLCBpZiB5b3Ugd2FudCB0byByZW5kZXIgZXZlcnkgc2Vjb25kXG5cdFx0XHQjIGl0IGlzIGltcG9ydGFudCB0aGF0IG5vIHR3byByZW5kZXJzXG5cdFx0XHQjIGhhcHBlbiBkdXJpbmcgdGhlIHNhbWUgc2Vjb25kIChhY2NvcmRpbmcgdG8gRGF0ZSlcblx0XHRcdGxldCBwZXJpb2QgPSAoKDYwIC8gZnBzKSAvIDYwKSAqIDEwMDBcblx0XHRcdGxldCBiZWF0ID0gTWF0aC5mbG9vcihEYXRlLm5vdyAvIHBlcmlvZClcblxuXHRcdFx0aWYgQGJlYXQgIT0gYmVhdFxuXHRcdFx0XHRAYmVhdCA9IGJlYXRcblx0XHRcdFx0QG1hcmtlZCA9IHllc1xuXG5cdFx0Zmx1c2ggaWYgQG1hcmtlZCBvciAoQGV2ZW50cyBhbmQgSW1iYS5TY2hlZHVsZXIuaXNEaXJ0eSlcblx0XHQjIHJlc2NoZWR1bGUgaWYgQGFjdGl2ZVxuXHRcdHNlbGZcblxuXHQjIyNcblx0U3RhcnQgdGhlIHNjaGVkdWxlciBpZiBpdCBpcyBub3QgYWxyZWFkeSBhY3RpdmUuXG5cdCoqV2hpbGUgYWN0aXZlKiosIHRoZSBzY2hlZHVsZXIgd2lsbCBvdmVycmlkZSBgdGFyZ2V0LmNvbW1pdGBcblx0dG8gZG8gbm90aGluZy4gQnkgZGVmYXVsdCBJbWJhLnRhZyNjb21taXQgY2FsbHMgcmVuZGVyLCBzb1xuXHR0aGF0IHJlbmRlcmluZyBpcyBjYXNjYWRlZCB0aHJvdWdoIHRvIGNoaWxkcmVuIHdoZW4gcmVuZGVyaW5nXG5cdGEgbm9kZS4gV2hlbiBhIHNjaGVkdWxlciBpcyBhY3RpdmUgKGZvciBhIG5vZGUpLCBJbWJhIGRpc2FibGVzXG5cdHRoaXMgYXV0b21hdGljIHJlbmRlcmluZy5cblx0IyMjXG5cdGRlZiBhY3RpdmF0ZVxuXHRcdHVubGVzcyBAYWN0aXZlXG5cdFx0XHRAYWN0aXZlID0geWVzXG5cdFx0XHQjIG92ZXJyaWRlIHRhcmdldCNjb21taXQgd2hpbGUgdGhpcyBpcyBhY3RpdmVcblx0XHRcdEBjb21taXQgPSBAdGFyZ2V0OmNvbW1pdFxuXHRcdFx0QHRhcmdldDpjb21taXQgPSBkbyB0aGlzXG5cdFx0XHRJbWJhLnNjaGVkdWxlKHNlbGYpXG5cdFx0XHRJbWJhLmxpc3RlbihJbWJhLCdldmVudCcsc2VsZiwnb25ldmVudCcpIGlmIEBldmVudHNcblx0XHRcdEB0YXJnZXQ/LmZsYWcoJ3NjaGVkdWxlZF8nKVxuXHRcdFx0dGljaygwKSAjIHN0YXJ0IHRpY2tpbmdcblx0XHRyZXR1cm4gc2VsZlxuXG5cdCMjI1xuXHRTdG9wIHRoZSBzY2hlZHVsZXIgaWYgaXQgaXMgYWN0aXZlLlxuXHQjIyNcblx0ZGVmIGRlYWN0aXZhdGVcblx0XHRpZiBAYWN0aXZlXG5cdFx0XHRAYWN0aXZlID0gbm9cblx0XHRcdEB0YXJnZXQ6Y29tbWl0ID0gQGNvbW1pdFxuXHRcdFx0SW1iYS51bnNjaGVkdWxlKHNlbGYpXG5cdFx0XHRJbWJhLnVubGlzdGVuKEltYmEsJ2V2ZW50JyxzZWxmKVxuXHRcdFx0QHRhcmdldD8udW5mbGFnKCdzY2hlZHVsZWRfJylcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiB0cmFja1xuXHRcdEBtYXJrZXJcblxuXHRkZWYgb25ldmVudCBldmVudFxuXHRcdHJldHVybiBzZWxmIGlmIEBtYXJrZWRcblxuXHRcdGlmIEBldmVudHMgaXNhIEZ1bmN0aW9uXG5cdFx0XHRtYXJrIGlmIEBldmVudHMoZXZlbnQpXHRcblx0XHRlbGlmIEBldmVudHMgaXNhIEFycmF5XG5cdFx0XHRtYXJrIGlmIGV2ZW50Py50eXBlIGluIEBldmVudHNcblx0XHRlbGlmIEBldmVudHNcblx0XHRcdG1hcmsgaWYgZXZlbnQuQHJlc3BvbmRlclxuXHRcdHNlbGZcblxuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL3NjaGVkdWxlci5pbWJhXG4gKiovIiwiZGVmIEltYmEuc3RhdGljIGl0ZW1zLCBuclxuXHRpdGVtczpzdGF0aWMgPSBuclxuXHRyZXR1cm4gaXRlbXNcblxuIyMjXG5UaGlzIGlzIHRoZSBiYXNlY2xhc3MgdGhhdCBhbGwgdGFncyBpbiBpbWJhIGluaGVyaXQgZnJvbS5cbkBpbmFtZSBub2RlXG4jIyNcbmNsYXNzIEltYmEuVGFnXG5cblx0ZGVmIHNlbGYuY3JlYXRlTm9kZVxuXHRcdHRocm93IFwiTm90IGltcGxlbWVudGVkXCJcblxuXHRkZWYgc2VsZi5idWlsZFxuXHRcdHNlbGYubmV3KHNlbGYuY3JlYXRlTm9kZSlcblxuXHRwcm9wIG9iamVjdFxuXG5cdGRlZiBkb21cblx0XHRAZG9tXG5cblx0ZGVmIGluaXRpYWxpemUgZG9tXG5cdFx0c2VsZi5kb20gPSBkb21cblx0XHRcblx0ZGVmIHNldERvbSBkb21cblx0XHRkb20uQHRhZyA9IHNlbGZcblx0XHRAZG9tID0gZG9tXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRTZXR0aW5nIHJlZmVyZW5jZXMgZm9yIHRhZ3MgbGlrZVxuXHRgPGRpdkBoZWFkZXI+YCB3aWxsIGNvbXBpbGUgdG8gYHRhZygnZGl2Jykuc2V0UmVmKCdoZWFkZXInLHRoaXMpLmVuZCgpYFxuXHRCeSBkZWZhdWx0IGl0IGFkZHMgdGhlIHJlZmVyZW5jZSBhcyBhIGNsYXNzTmFtZSB0byB0aGUgdGFnLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHNldFJlZiByZWYsIGN0eFxuXHRcdGZsYWcoQHJlZiA9IHJlZilcblx0XHRzZWxmXG5cblx0IyMjXG5cdE1ldGhvZCB0aGF0IGlzIGNhbGxlZCBieSB0aGUgY29tcGlsZWQgdGFnLWNoYWlucywgZm9yXG5cdGJpbmRpbmcgZXZlbnRzIG9uIHRhZ3MgdG8gbWV0aG9kcyBldGMuXG5cdGA8YSA6dGFwPWZuPmAgY29tcGlsZXMgdG8gYHRhZygnYScpLnNldEhhbmRsZXIoJ3RhcCcsZm4sdGhpcykuZW5kKClgXG5cdHdoZXJlIHRoaXMgcmVmZXJzIHRvIHRoZSBjb250ZXh0IGluIHdoaWNoIHRoZSB0YWcgaXMgY3JlYXRlZC5cblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzZXRIYW5kbGVyIGV2ZW50LCBoYW5kbGVyLCBjdHhcblx0XHR2YXIga2V5ID0gJ29uJyArIGV2ZW50XG5cblx0XHRpZiBoYW5kbGVyIGlzYSBGdW5jdGlvblxuXHRcdFx0c2VsZltrZXldID0gaGFuZGxlclxuXHRcdGVsaWYgaGFuZGxlciBpc2EgQXJyYXlcblx0XHRcdHZhciBmbiA9IGhhbmRsZXIuc2hpZnRcblx0XHRcdHNlbGZba2V5XSA9IGRvIHxlfCBjdHhbZm5dLmFwcGx5KGN0eCxoYW5kbGVyLmNvbmNhdChlKSlcblx0XHRlbHNlXG5cdFx0XHRzZWxmW2tleV0gPSBkbyB8ZXwgY3R4W2hhbmRsZXJdKGUpXG5cdFx0c2VsZlxuXG5cdGRlZiBpZD0gaWRcblx0XHRkb206aWQgPSBpZFxuXHRcdHNlbGZcblxuXHRkZWYgaWRcblx0XHRkb206aWRcblxuXHQjIyNcblx0QWRkcyBhIG5ldyBhdHRyaWJ1dGUgb3IgY2hhbmdlcyB0aGUgdmFsdWUgb2YgYW4gZXhpc3RpbmcgYXR0cmlidXRlXG5cdG9uIHRoZSBzcGVjaWZpZWQgdGFnLiBJZiB0aGUgdmFsdWUgaXMgbnVsbCBvciBmYWxzZSwgdGhlIGF0dHJpYnV0ZVxuXHR3aWxsIGJlIHJlbW92ZWQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0QXR0cmlidXRlIG5hbWUsIHZhbHVlXG5cdFx0IyBzaG91bGQgdGhpcyBub3QgcmV0dXJuIHNlbGY/XG5cdFx0dmFyIG9sZCA9IGRvbS5nZXRBdHRyaWJ1dGUobmFtZSlcblxuXHRcdGlmIG9sZCA9PSB2YWx1ZVxuXHRcdFx0dmFsdWVcblx0XHRlbGlmIHZhbHVlICE9IG51bGwgJiYgdmFsdWUgIT09IGZhbHNlXG5cdFx0XHRkb20uc2V0QXR0cmlidXRlKG5hbWUsdmFsdWUpXG5cdFx0ZWxzZVxuXHRcdFx0ZG9tLnJlbW92ZUF0dHJpYnV0ZShuYW1lKVxuXG5cdCMjI1xuXHRyZW1vdmVzIGFuIGF0dHJpYnV0ZSBmcm9tIHRoZSBzcGVjaWZpZWQgdGFnXG5cdCMjI1xuXHRkZWYgcmVtb3ZlQXR0cmlidXRlIG5hbWVcblx0XHRkb20ucmVtb3ZlQXR0cmlidXRlKG5hbWUpXG5cblx0IyMjXG5cdHJldHVybnMgdGhlIHZhbHVlIG9mIGFuIGF0dHJpYnV0ZSBvbiB0aGUgdGFnLlxuXHRJZiB0aGUgZ2l2ZW4gYXR0cmlidXRlIGRvZXMgbm90IGV4aXN0LCB0aGUgdmFsdWUgcmV0dXJuZWRcblx0d2lsbCBlaXRoZXIgYmUgbnVsbCBvciBcIlwiICh0aGUgZW1wdHkgc3RyaW5nKVxuXHQjIyNcblx0ZGVmIGdldEF0dHJpYnV0ZSBuYW1lXG5cdFx0ZG9tLmdldEF0dHJpYnV0ZShuYW1lKVxuXG5cdCMjI1xuXHRPdmVycmlkZSB0aGlzIHRvIHByb3ZpZGUgc3BlY2lhbCB3cmFwcGluZyBldGMuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0Q29udGVudCBjb250ZW50LCB0eXBlXG5cdFx0c2V0Q2hpbGRyZW4gY29udGVudCwgdHlwZVxuXHRcdHNlbGZcblxuXHQjIyNcblx0U2V0IHRoZSBjaGlsZHJlbiBvZiBub2RlLiB0eXBlIHBhcmFtIGlzIG9wdGlvbmFsLFxuXHRhbmQgc2hvdWxkIG9ubHkgYmUgdXNlZCBieSBJbWJhIHdoZW4gY29tcGlsaW5nIHRhZyB0cmVlcy4gXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgc2V0Q2hpbGRyZW4gbm9kZXMsIHR5cGVcblx0XHR0aHJvdyBcIk5vdCBpbXBsZW1lbnRlZFwiXG5cblx0IyMjXG5cdEdldCB0ZXh0IG9mIG5vZGUuIFVzZXMgdGV4dENvbnRlbnQgYmVoaW5kIHRoZSBzY2VuZXMgKG5vdCBpbm5lclRleHQpXG5cdFtodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTm9kZS90ZXh0Q29udGVudF0oKVxuXHRAcmV0dXJuIHtzdHJpbmd9IGlubmVyIHRleHQgb2Ygbm9kZVxuXHQjIyNcblx0ZGVmIHRleHQgdlxuXHRcdEBkb206dGV4dENvbnRlbnRcblxuXHQjIyNcblx0U2V0IHRleHQgb2Ygbm9kZS4gVXNlcyB0ZXh0Q29udGVudCBiZWhpbmQgdGhlIHNjZW5lcyAobm90IGlubmVyVGV4dClcblx0W2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Ob2RlL3RleHRDb250ZW50XSgpXG5cdCMjI1xuXHRkZWYgdGV4dD0gdHh0XG5cdFx0QGVtcHR5ID0gbm9cblx0XHRAZG9tOnRleHRDb250ZW50ID0gdHh0ID89IFwiXCJcblx0XHRzZWxmXG5cblxuXHQjIyNcblx0TWV0aG9kIGZvciBnZXR0aW5nIGFuZCBzZXR0aW5nIGRhdGEtYXR0cmlidXRlcy4gV2hlbiBjYWxsZWQgd2l0aCB6ZXJvXG5cdGFyZ3VtZW50cyBpdCB3aWxsIHJldHVybiB0aGUgYWN0dWFsIGRhdGFzZXQgZm9yIHRoZSB0YWcuXG5cblx0XHR2YXIgbm9kZSA9IDxkaXYgZGF0YS1uYW1lPSdoZWxsbyc+XG5cdFx0IyBnZXQgdGhlIHdob2xlIGRhdGFzZXRcblx0XHRub2RlLmRhdGFzZXQgIyB7bmFtZTogJ2hlbGxvJ31cblx0XHQjIGdldCBhIHNpbmdsZSB2YWx1ZVxuXHRcdG5vZGUuZGF0YXNldCgnbmFtZScpICMgJ2hlbGxvJ1xuXHRcdCMgc2V0IGEgc2luZ2xlIHZhbHVlXG5cdFx0bm9kZS5kYXRhc2V0KCduYW1lJywnbmV3bmFtZScpICMgc2VsZlxuXG5cblx0IyMjXG5cdGRlZiBkYXRhc2V0IGtleSwgdmFsXG5cdFx0dGhyb3cgXCJOb3QgaW1wbGVtZW50ZWRcIlxuXG5cdCMjI1xuXHRFbXB0eSBwbGFjZWhvbGRlci4gT3ZlcnJpZGUgdG8gaW1wbGVtZW50IGN1c3RvbSByZW5kZXIgYmVoYXZpb3VyLlxuXHRXb3JrcyBtdWNoIGxpa2UgdGhlIGZhbWlsaWFyIHJlbmRlci1tZXRob2QgaW4gUmVhY3QuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgcmVuZGVyXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYWxsZWQgaW1wbGljaXRseSB0aHJvdWdoIEltYmEuVGFnI2VuZCwgdXBvbiBjcmVhdGluZyBhIHRhZy4gQWxsXG5cdHByb3BlcnRpZXMgd2lsbCBoYXZlIGJlZW4gc2V0IGJlZm9yZSBidWlsZCBpcyBjYWxsZWQsIGluY2x1ZGluZ1xuXHRzZXRDb250ZW50LlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGJ1aWxkXG5cdFx0cmVuZGVyXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYWxsZWQgaW1wbGljaXRseSB0aHJvdWdoIEltYmEuVGFnI2VuZCwgZm9yIHRhZ3MgdGhhdCBhcmUgcGFydCBvZlxuXHRhIHRhZyB0cmVlICh0aGF0IGFyZSByZW5kZXJlZCBzZXZlcmFsIHRpbWVzKS5cblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBjb21taXRcblx0XHRyZW5kZXJcblx0XHRzZWxmXG5cblx0IyMjXG5cblx0Q2FsbGVkIGJ5IHRoZSB0YWctc2NoZWR1bGVyIChpZiB0aGlzIHRhZyBpcyBzY2hlZHVsZWQpXG5cdEJ5IGRlZmF1bHQgaXQgd2lsbCBjYWxsIHRoaXMucmVuZGVyLiBEbyBub3Qgb3ZlcnJpZGUgdW5sZXNzXG5cdHlvdSByZWFsbHkgdW5kZXJzdGFuZCBpdC5cblxuXHQjIyNcblx0ZGVmIHRpY2tcblx0XHRyZW5kZXJcblx0XHRzZWxmXG5cblx0IyMjXG5cdFxuXHRBIHZlcnkgaW1wb3J0YW50IG1ldGhvZCB0aGF0IHlvdSB3aWxsIHByYWN0aWNhbGx5IG5ldmVyIG1hbnVhbGx5LlxuXHRUaGUgdGFnIHN5bnRheCBvZiBJbWJhIGNvbXBpbGVzIHRvIGEgY2hhaW4gb2Ygc2V0dGVycywgd2hpY2ggYWx3YXlzXG5cdGVuZHMgd2l0aCAuZW5kLiBgPGEubGFyZ2U+YCBjb21waWxlcyB0byBgdGFnKCdhJykuZmxhZygnbGFyZ2UnKS5lbmQoKWBcblx0XG5cdFlvdSBhcmUgaGlnaGx5IGFkdmljZWQgdG8gbm90IG92ZXJyaWRlIGl0cyBiZWhhdmlvdXIuIFRoZSBmaXJzdCB0aW1lXG5cdGVuZCBpcyBjYWxsZWQgaXQgd2lsbCBtYXJrIHRoZSB0YWcgYXMgYnVpbHQgYW5kIGNhbGwgSW1iYS5UYWcjYnVpbGQsXG5cdGFuZCBjYWxsIEltYmEuVGFnI2NvbW1pdCBvbiBzdWJzZXF1ZW50IGNhbGxzLlxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGVuZFxuXHRcdGlmIEBidWlsdFxuXHRcdFx0Y29tbWl0XG5cdFx0ZWxzZVxuXHRcdFx0QGJ1aWx0ID0geWVzXG5cdFx0XHRidWlsZFxuXHRcdHNlbGZcblxuXHQjIyNcblx0VGhpcyBpcyBjYWxsZWQgaW5zdGVhZCBvZiBJbWJhLlRhZyNlbmQgZm9yIGA8c2VsZj5gIHRhZyBjaGFpbnMuXG5cdERlZmF1bHRzIHRvIG5vb3Bcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzeW5jZWRcblx0XHRzZWxmXG5cblx0IyBjYWxsZWQgd2hlbiB0aGUgbm9kZSBpcyBhd2FrZW5lZCBpbiB0aGUgZG9tIC0gZWl0aGVyIGF1dG9tYXRpY2FsbHlcblx0IyB1cG9uIGF0dGFjaG1lbnQgdG8gdGhlIGRvbS10cmVlLCBvciB0aGUgZmlyc3QgdGltZSBpbWJhIG5lZWRzIHRoZVxuXHQjIHRhZyBmb3IgYSBkb21ub2RlIHRoYXQgaGFzIGJlZW4gcmVuZGVyZWQgb24gdGhlIHNlcnZlclxuXHRkZWYgYXdha2VuXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRMaXN0IG9mIGZsYWdzIGZvciB0aGlzIG5vZGUuIFxuXHQjIyNcblx0ZGVmIGZsYWdzXG5cdFx0QGRvbTpjbGFzc0xpc3RcblxuXHQjIyNcblx0QWRkIHNwZWZpY2llZCBmbGFnIHRvIGN1cnJlbnQgbm9kZS5cblx0SWYgYSBzZWNvbmQgYXJndW1lbnQgaXMgc3VwcGxpZWQsIGl0IHdpbGwgYmUgY29lcmNlZCBpbnRvIGEgQm9vbGVhbixcblx0YW5kIHVzZWQgdG8gaW5kaWNhdGUgd2hldGhlciB3ZSBzaG91bGQgcmVtb3ZlIHRoZSBmbGFnIGluc3RlYWQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgZmxhZyBuYW1lLCB0b2dnbGVyXG5cdFx0IyBpdCBpcyBtb3N0IG5hdHVyYWwgdG8gdHJlYXQgYSBzZWNvbmQgdW5kZWZpbmVkIGFyZ3VtZW50IGFzIGEgbm8tc3dpdGNoXG5cdFx0IyBzbyB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBhcmd1bWVudHMtbGVuZ3RoXG5cdFx0aWYgYXJndW1lbnRzOmxlbmd0aCA9PSAyIGFuZCAhdG9nZ2xlclxuXHRcdFx0QGRvbTpjbGFzc0xpc3QucmVtb3ZlKG5hbWUpXG5cdFx0ZWxzZVxuXHRcdFx0QGRvbTpjbGFzc0xpc3QuYWRkKG5hbWUpXG5cdFx0cmV0dXJuIHNlbGZcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBmbGFnIGZyb20gbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHVuZmxhZyBuYW1lXG5cdFx0QGRvbTpjbGFzc0xpc3QucmVtb3ZlKG5hbWUpXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRUb2dnbGUgc3BlY2lmaWVkIGZsYWcgb24gbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIHRvZ2dsZUZsYWcgbmFtZVxuXHRcdEBkb206Y2xhc3NMaXN0LnRvZ2dsZShuYW1lKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0Q2hlY2sgd2hldGhlciBjdXJyZW50IG5vZGUgaGFzIHNwZWNpZmllZCBmbGFnXG5cdEByZXR1cm4ge2Jvb2x9XG5cdCMjI1xuXHRkZWYgaGFzRmxhZyBuYW1lXG5cdFx0QGRvbTpjbGFzc0xpc3QuY29udGFpbnMobmFtZSlcblxuXHQjIyNcblx0R2V0IHRoZSBzY2hlZHVsZXIgZm9yIHRoaXMgbm9kZS4gQSBuZXcgc2NoZWR1bGVyIHdpbGwgYmUgY3JlYXRlZFxuXHRpZiBpdCBkb2VzIG5vdCBhbHJlYWR5IGV4aXN0LlxuXG5cdEByZXR1cm4ge0ltYmEuU2NoZWR1bGVyfVxuXHQjIyNcblx0ZGVmIHNjaGVkdWxlclxuXHRcdEBzY2hlZHVsZXIgPz0gSW1iYS5TY2hlZHVsZXIubmV3KHNlbGYpXG5cblx0IyMjXG5cblx0U2hvcnRoYW5kIHRvIHN0YXJ0IHNjaGVkdWxpbmcgYSBub2RlLiBUaGUgbWV0aG9kIHdpbGwgYmFzaWNhbGx5XG5cdHByb3h5IHRoZSBhcmd1bWVudHMgdGhyb3VnaCB0byBzY2hlZHVsZXIuY29uZmlndXJlLCBhbmQgdGhlblxuXHRhY3RpdmF0ZSB0aGUgc2NoZWR1bGVyLlxuXHRcblx0QHJldHVybiB7c2VsZn1cblx0IyMjXG5cdGRlZiBzY2hlZHVsZSBvcHRpb25zID0ge31cblx0XHRzY2hlZHVsZXIuY29uZmlndXJlKG9wdGlvbnMpLmFjdGl2YXRlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRTaG9ydGhhbmQgZm9yIGRlYWN0aXZhdGluZyBzY2hlZHVsZXIgKGlmIHRhZyBoYXMgb25lKS5cblx0QGRlcHJlY2F0ZWRcblx0IyMjXG5cdGRlZiB1bnNjaGVkdWxlXG5cdFx0c2NoZWR1bGVyLmRlYWN0aXZhdGUgaWYgQHNjaGVkdWxlclxuXHRcdHNlbGZcblxuXG5cdCMjI1xuXHRHZXQgdGhlIHBhcmVudCBvZiBjdXJyZW50IG5vZGVcblx0QHJldHVybiB7SW1iYS5UYWd9IFxuXHQjIyNcblx0ZGVmIHBhcmVudFxuXHRcdHRhZyhkb206cGFyZW50Tm9kZSlcblxuXHQjIyNcblx0U2hvcnRoYW5kIGZvciBjb25zb2xlLmxvZyBvbiBlbGVtZW50c1xuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGxvZyAqYXJnc1xuXHRcdGFyZ3MudW5zaGlmdChjb25zb2xlKVxuXHRcdEZ1bmN0aW9uOnByb3RvdHlwZTpjYWxsLmFwcGx5KGNvbnNvbGU6bG9nLCBhcmdzKVxuXHRcdHNlbGZcblxuXHRkZWYgY3NzIGtleSwgdmFsXG5cdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdGNzcyhrLHYpIGZvciBvd24gayx2IG9mIGtleVxuXHRcdGVsaWYgdmFsID09IG51bGxcblx0XHRcdGRvbTpzdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpXG5cdFx0ZWxpZiB2YWwgPT0gdW5kZWZpbmVkXG5cdFx0XHRyZXR1cm4gZG9tOnN0eWxlW2tleV1cblx0XHRlbHNlXG5cdFx0XHRpZiB2YWwgaXNhIE51bWJlciBhbmQga2V5Lm1hdGNoKC93aWR0aHxoZWlnaHR8bGVmdHxyaWdodHx0b3B8Ym90dG9tLylcblx0XHRcdFx0dmFsID0gdmFsICsgXCJweFwiXG5cdFx0XHRkb206c3R5bGVba2V5XSA9IHZhbFxuXHRcdHNlbGZcblxuXHRkZWYgdHJhbnNmb3JtPSB2YWx1ZVxuXHRcdGNzcyg6dHJhbnNmb3JtLCB2YWx1ZSlcblx0XHRzZWxmXG5cblx0ZGVmIHRyYW5zZm9ybVxuXHRcdGNzcyg6dHJhbnNmb3JtKVxuXG5cbkltYmEuVGFnOnByb3RvdHlwZTppbml0aWFsaXplID0gSW1iYS5UYWdcblxuSFRNTF9UQUdTID0gXCJhIGFiYnIgYWRkcmVzcyBhcmVhIGFydGljbGUgYXNpZGUgYXVkaW8gYiBiYXNlIGJkaSBiZG8gYmlnIGJsb2NrcXVvdGUgYm9keSBiciBidXR0b24gY2FudmFzIGNhcHRpb24gY2l0ZSBjb2RlIGNvbCBjb2xncm91cCBkYXRhIGRhdGFsaXN0IGRkIGRlbCBkZXRhaWxzIGRmbiBkaXYgZGwgZHQgZW0gZW1iZWQgZmllbGRzZXQgZmlnY2FwdGlvbiBmaWd1cmUgZm9vdGVyIGZvcm0gaDEgaDIgaDMgaDQgaDUgaDYgaGVhZCBoZWFkZXIgaHIgaHRtbCBpIGlmcmFtZSBpbWcgaW5wdXQgaW5zIGtiZCBrZXlnZW4gbGFiZWwgbGVnZW5kIGxpIGxpbmsgbWFpbiBtYXAgbWFyayBtZW51IG1lbnVpdGVtIG1ldGEgbWV0ZXIgbmF2IG5vc2NyaXB0IG9iamVjdCBvbCBvcHRncm91cCBvcHRpb24gb3V0cHV0IHAgcGFyYW0gcHJlIHByb2dyZXNzIHEgcnAgcnQgcnVieSBzIHNhbXAgc2NyaXB0IHNlY3Rpb24gc2VsZWN0IHNtYWxsIHNvdXJjZSBzcGFuIHN0cm9uZyBzdHlsZSBzdWIgc3VtbWFyeSBzdXAgdGFibGUgdGJvZHkgdGQgdGV4dGFyZWEgdGZvb3QgdGggdGhlYWQgdGltZSB0aXRsZSB0ciB0cmFjayB1IHVsIHZhciB2aWRlbyB3YnJcIi5zcGxpdChcIiBcIilcbkhUTUxfVEFHU19VTlNBRkUgPSBcImFydGljbGUgYXNpZGUgaGVhZGVyIHNlY3Rpb25cIi5zcGxpdChcIiBcIilcblNWR19UQUdTID0gXCJjaXJjbGUgZGVmcyBlbGxpcHNlIGcgbGluZSBsaW5lYXJHcmFkaWVudCBtYXNrIHBhdGggcGF0dGVybiBwb2x5Z29uIHBvbHlsaW5lIHJhZGlhbEdyYWRpZW50IHJlY3Qgc3RvcCBzdmcgdGV4dCB0c3BhblwiLnNwbGl0KFwiIFwiKVxuXG5cbmRlZiBleHRlbmRlciBvYmosIHN1cFxuXHRmb3Igb3duIGssdiBvZiBzdXBcblx0XHRvYmpba10gPz0gdlxuXG5cdG9iajpwcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cDpwcm90b3R5cGUpXG5cdG9iajpfX3N1cGVyX18gPSBvYmo6cHJvdG90eXBlOl9fc3VwZXJfXyA9IHN1cDpwcm90b3R5cGVcblx0b2JqOnByb3RvdHlwZTppbml0aWFsaXplID0gb2JqOnByb3RvdHlwZTpjb25zdHJ1Y3RvciA9IG9ialxuXHRzdXAuaW5oZXJpdChvYmopIGlmIHN1cDppbmhlcml0XG5cdHJldHVybiBvYmpcblxuZGVmIFRhZ1xuXHRyZXR1cm4gZG8gfGRvbXxcblx0XHR0aGlzLnNldERvbShkb20pXG5cdFx0cmV0dXJuIHRoaXNcblxuZGVmIFRhZ1NwYXduZXIgdHlwZVxuXHRyZXR1cm4gZG8gdHlwZS5idWlsZFxuXG5jbGFzcyBJbWJhLlRhZ3NcblxuXHRkZWYgaW5pdGlhbGl6ZVxuXHRcdHNlbGZcblxuXHRkZWYgX19jbG9uZSBuc1xuXHRcdHZhciBjbG9uZSA9IE9iamVjdC5jcmVhdGUoc2VsZilcblx0XHRjbG9uZS5AcGFyZW50ID0gc2VsZlxuXHRcdHJldHVybiBjbG9uZVxuXG5cdGRlZiBkZWZpbmVOYW1lc3BhY2UgbmFtZVxuXHRcdHZhciBjbG9uZSA9IE9iamVjdC5jcmVhdGUoc2VsZilcblx0XHRjbG9uZS5AcGFyZW50ID0gc2VsZlxuXHRcdGNsb25lLkBucyA9IG5hbWVcblx0XHRzZWxmW25hbWUudG9VcHBlckNhc2VdID0gY2xvbmVcblx0XHRyZXR1cm4gY2xvbmVcblxuXHRkZWYgYmFzZVR5cGUgbmFtZVxuXHRcdG5hbWUgaW4gSFRNTF9UQUdTID8gJ2h0bWxlbGVtZW50JyA6ICdkaXYnXG5cblx0ZGVmIGRlZmluZVRhZyBuYW1lLCBzdXByID0gJycsICZib2R5XG5cdFx0c3VwciB8fD0gYmFzZVR5cGUobmFtZSlcblx0XHRsZXQgc3VwZXJ0eXBlID0gc2VsZltzdXByXVxuXHRcdGxldCB0YWd0eXBlID0gVGFnKClcblx0XHRsZXQgbm9ybSA9IG5hbWUucmVwbGFjZSgvXFwtL2csJ18nKVxuXG5cblx0XHR0YWd0eXBlLkBuYW1lID0gbmFtZVxuXHRcdGV4dGVuZGVyKHRhZ3R5cGUsc3VwZXJ0eXBlKVxuXG5cdFx0aWYgbmFtZVswXSA9PSAnIydcblx0XHRcdHNlbGZbbmFtZV0gPSB0YWd0eXBlXG5cdFx0XHRJbWJhLlNJTkdMRVRPTlNbbmFtZS5zbGljZSgxKV0gPSB0YWd0eXBlXG5cdFx0ZWxzZVxuXHRcdFx0c2VsZltuYW1lXSA9IHRhZ3R5cGVcblx0XHRcdHNlbGZbJyQnK25vcm1dID0gVGFnU3Bhd25lcih0YWd0eXBlKVxuXG5cdFx0aWYgYm9keVxuXHRcdFx0aWYgYm9keTpsZW5ndGggPT0gMlxuXHRcdFx0XHQjIGNyZWF0ZSBjbG9uZVxuXHRcdFx0XHR1bmxlc3MgdGFndHlwZS5oYXNPd25Qcm9wZXJ0eSgnVEFHUycpXG5cdFx0XHRcdFx0dGFndHlwZS5UQUdTID0gKHN1cGVydHlwZS5UQUdTIG9yIHNlbGYpLl9fY2xvbmVcblxuXHRcdFx0Ym9keS5jYWxsKHRhZ3R5cGUsdGFndHlwZSwgdGFndHlwZS5UQUdTIG9yIHNlbGYpXG5cblx0XHRyZXR1cm4gdGFndHlwZVxuXG5cdGRlZiBkZWZpbmVTaW5nbGV0b24gbmFtZSwgc3VwciwgJmJvZHlcblx0XHRkZWZpbmVUYWcobmFtZSxzdXByLGJvZHkpXG5cblx0ZGVmIGV4dGVuZFRhZyBuYW1lLCBzdXByID0gJycsICZib2R5XG5cdFx0dmFyIGtsYXNzID0gKG5hbWUgaXNhIFN0cmluZyA/IHNlbGZbbmFtZV0gOiBuYW1lKVxuXHRcdCMgYWxsb3cgZm9yIHByaXZhdGUgdGFncyBoZXJlIGFzIHdlbGw/XG5cdFx0Ym9keSBhbmQgYm9keS5jYWxsKGtsYXNzLGtsYXNzLGtsYXNzOnByb3RvdHlwZSkgaWYgYm9keVxuXHRcdHJldHVybiBrbGFzc1xuXG5cbkltYmEuVEFHUyA9IEltYmEuVGFncy5uZXdcbkltYmEuVEFHU1s6ZWxlbWVudF0gPSBJbWJhLlRhZ1xuXG52YXIgc3ZnID0gSW1iYS5UQUdTLmRlZmluZU5hbWVzcGFjZSgnc3ZnJylcblxuZGVmIHN2Zy5iYXNlVHlwZSBuYW1lXG5cdCdzdmdlbGVtZW50J1xuXG5cbkltYmEuU0lOR0xFVE9OUyA9IHt9XG5cblxuZGVmIEltYmEuZGVmaW5lVGFnIG5hbWUsIHN1cHIgPSAnJywgJmJvZHlcblx0cmV0dXJuIEltYmEuVEFHUy5kZWZpbmVUYWcobmFtZSxzdXByLGJvZHkpXG5cbmRlZiBJbWJhLmRlZmluZVNpbmdsZXRvblRhZyBpZCwgc3VwciA9ICdkaXYnLCAmYm9keVxuXHRyZXR1cm4gSW1iYS5UQUdTLmRlZmluZVRhZyhuYW1lLHN1cHIsYm9keSlcblxuZGVmIEltYmEuZXh0ZW5kVGFnIG5hbWUsIGJvZHlcblx0cmV0dXJuIEltYmEuVEFHUy5leHRlbmRUYWcobmFtZSxib2R5KVxuXG5kZWYgSW1iYS50YWcgbmFtZVxuXHR2YXIgdHlwID0gSW1iYS5UQUdTW25hbWVdXG5cdHRocm93IEVycm9yLm5ldyhcInRhZyB7bmFtZX0gaXMgbm90IGRlZmluZWRcIikgaWYgIXR5cFxuXHRyZXR1cm4gdHlwLm5ldyh0eXAuY3JlYXRlTm9kZSlcblxuZGVmIEltYmEudGFnV2l0aElkIG5hbWUsIGlkXG5cdHZhciB0eXAgPSBJbWJhLlRBR1NbbmFtZV1cblx0dGhyb3cgRXJyb3IubmV3KFwidGFnIHtuYW1lfSBpcyBub3QgZGVmaW5lZFwiKSBpZiAhdHlwXG5cdHZhciBkb20gPSB0eXAuY3JlYXRlTm9kZVxuXHRkb206aWQgPSBpZFxuXHRyZXR1cm4gdHlwLm5ldyhkb20pXG5cbiMgVE9ETzogQ2FuIHdlIG1vdmUgdGhlc2Ugb3V0IGFuZCBpbnRvIGRvbS5pbWJhIGluIGEgY2xlYW4gd2F5P1xuIyBUaGVzZSBtZXRob2RzIGRlcGVuZHMgb24gSW1iYS5kb2N1bWVudC5nZXRFbGVtZW50QnlJZFxuXG5kZWYgSW1iYS5nZXRUYWdTaW5nbGV0b24gaWRcdFxuXHR2YXIgZG9tLCBub2RlXG5cblx0aWYgdmFyIGtsYXNzID0gSW1iYS5TSU5HTEVUT05TW2lkXVxuXHRcdHJldHVybiBrbGFzcy5JbnN0YW5jZSBpZiBrbGFzcyBhbmQga2xhc3MuSW5zdGFuY2UgXG5cblx0XHQjIG5vIGluc3RhbmNlIC0gY2hlY2sgZm9yIGVsZW1lbnRcblx0XHRpZiBkb20gPSBJbWJhLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKVxuXHRcdFx0IyB3ZSBoYXZlIGEgbGl2ZSBpbnN0YW5jZSAtIHdoZW4gZmluZGluZyBpdCB0aHJvdWdoIGEgc2VsZWN0b3Igd2Ugc2hvdWxkIGF3YWtlIGl0LCBubz9cblx0XHRcdCMgY29uc29sZS5sb2coJ2NyZWF0aW5nIHRoZSBzaW5nbGV0b24gZnJvbSBleGlzdGluZyBub2RlIGluIGRvbT8nLGlkLHR5cGUpXG5cdFx0XHRub2RlID0ga2xhc3MuSW5zdGFuY2UgPSBrbGFzcy5uZXcoZG9tKVxuXHRcdFx0bm9kZS5hd2FrZW4oZG9tKSAjIHNob3VsZCBvbmx5IGF3YWtlblxuXHRcdFx0cmV0dXJuIG5vZGVcblxuXHRcdGRvbSA9IGtsYXNzLmNyZWF0ZU5vZGVcblx0XHRkb206aWQgPSBpZFxuXHRcdG5vZGUgPSBrbGFzcy5JbnN0YW5jZSA9IGtsYXNzLm5ldyhkb20pXG5cdFx0bm9kZS5lbmQuYXdha2VuKGRvbSlcblx0XHRyZXR1cm4gbm9kZVxuXHRlbGlmIGRvbSA9IEltYmEuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpXG5cdFx0cmV0dXJuIEltYmEuZ2V0VGFnRm9yRG9tKGRvbSlcblxudmFyIHN2Z1N1cHBvcnQgPSB0eXBlb2YgU1ZHRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCdcblxuZGVmIEltYmEuZ2V0VGFnRm9yRG9tIGRvbVxuXHRyZXR1cm4gbnVsbCB1bmxlc3MgZG9tXG5cdHJldHVybiBkb20gaWYgZG9tLkBkb20gIyBjb3VsZCB1c2UgaW5oZXJpdGFuY2UgaW5zdGVhZFxuXHRyZXR1cm4gZG9tLkB0YWcgaWYgZG9tLkB0YWdcblx0cmV0dXJuIG51bGwgdW5sZXNzIGRvbTpub2RlTmFtZVxuXG5cdHZhciBucyAgID0gbnVsbFxuXHR2YXIgaWQgICA9IGRvbTppZFxuXHR2YXIgdHlwZSA9IGRvbTpub2RlTmFtZS50b0xvd2VyQ2FzZVxuXHR2YXIgdGFncyA9IEltYmEuVEFHU1xuXHR2YXIgbmF0aXZlID0gdHlwZVxuXHR2YXIgY2xzICA9IGRvbTpjbGFzc05hbWVcblxuXHRpZiBpZCBhbmQgSW1iYS5TSU5HTEVUT05TW2lkXVxuXHRcdCMgRklYTUUgY29udHJvbCB0aGF0IGl0IGlzIHRoZSBzYW1lIHNpbmdsZXRvbj9cblx0XHQjIG1pZ2h0IGNvbGxpZGUgLS0gbm90IGdvb2Q/XG5cdFx0cmV0dXJuIEltYmEuZ2V0VGFnU2luZ2xldG9uKGlkKVxuXHQjIGxvb2sgZm9yIGlkIC0gc2luZ2xldG9uXG5cblx0IyBuZWVkIGJldHRlciB0ZXN0IGhlcmVcblx0aWYgc3ZnU3VwcG9ydCBhbmQgZG9tIGlzYSBTVkdFbGVtZW50XG5cdFx0bnMgPSBcInN2Z1wiIFxuXHRcdGNscyA9IGRvbTpjbGFzc05hbWU6YmFzZVZhbFxuXHRcdHRhZ3MgPSB0YWdzLlNWR1xuXG5cdHZhciBzcGF3bmVyXG5cblx0aWYgY2xzXG5cdFx0IyB0aGVyZSBjYW4gYmUgc2V2ZXJhbCBtYXRjaGVzIGhlcmUgLSBzaG91bGQgY2hvb3NlIHRoZSBsYXN0XG5cdFx0IyBzaG91bGQgZmFsbCBiYWNrIHRvIGxlc3Mgc3BlY2lmaWMgbGF0ZXI/IC0gb3RoZXJ3aXNlIHRoaW5ncyBtYXkgZmFpbFxuXHRcdCMgVE9ETyByZXdvcmsgdGhpc1xuXHRcdGlmIHZhciBtID0gY2xzLm1hdGNoKC9cXGJfKFthLXpcXC1dKylcXGIoPyFcXHMqX1thLXpcXC1dKykvKVxuXHRcdFx0dHlwZSA9IG1bMV0gIyAucmVwbGFjZSgvLS9nLCdfJylcblxuXHRcdGlmIG0gPSBjbHMubWF0Y2goL1xcYihbQS1aXFwtXSspX1xcYi8pXG5cdFx0XHRucyA9IG1bMV1cblxuXG5cdHNwYXduZXIgPSB0YWdzW3R5cGVdIG9yIHRhZ3NbbmF0aXZlXVxuXHRzcGF3bmVyID8gc3Bhd25lci5uZXcoZG9tKS5hd2FrZW4oZG9tKSA6IG51bGxcblxudGFnJCA9IEltYmEuVEFHU1xudCQgPSBJbWJhOnRhZ1xudGMkID0gSW1iYTp0YWdXaXRoRmxhZ3NcbnRpJCA9IEltYmE6dGFnV2l0aElkXG50aWMkID0gSW1iYTp0YWdXaXRoSWRBbmRGbGFnc1xuaWQkID0gSW1iYTpnZXRUYWdTaW5nbGV0b25cbnRhZyR3cmFwID0gSW1iYTpnZXRUYWdGb3JEb21cblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvdGFnLmltYmFcbiAqKi8iLCJcbmRlZiBJbWJhLmRvY3VtZW50XG5cdHdpbmRvdzpkb2N1bWVudFxuXG4jIyNcblJldHVybnMgdGhlIGJvZHkgZWxlbWVudCB3cmFwcGVkIGluIGFuIEltYmEuVGFnXG4jIyNcbmRlZiBJbWJhLnJvb3Rcblx0dGFnKEltYmEuZG9jdW1lbnQ6Ym9keSlcblxudGFnIGh0bWxlbGVtZW50IDwgZWxlbWVudFxuXG5cdCMjI1xuXHRDYWxsZWQgd2hlbiBhIHRhZyB0eXBlIGlzIGJlaW5nIHN1YmNsYXNzZWQuXG5cdCMjI1xuXHRkZWYgc2VsZi5pbmhlcml0IGNoaWxkXG5cdFx0Y2hpbGQ6cHJvdG90eXBlLkBlbXB0eSA9IHllc1xuXHRcdGNoaWxkLkBwcm90b0RvbSA9IG51bGxcblxuXHRcdGlmIEBub2RlVHlwZVxuXHRcdFx0Y2hpbGQuQG5vZGVUeXBlID0gQG5vZGVUeXBlXG5cblx0XHRcdHZhciBjbGFzc05hbWUgPSBcIl9cIiArIGNoaWxkLkBuYW1lLnJlcGxhY2UoL18vZywgJy0nKVxuXHRcdFx0Y2hpbGQuQGNsYXNzZXMgPSBAY2xhc3Nlcy5jb25jYXQoY2xhc3NOYW1lKSB1bmxlc3MgY2hpbGQuQG5hbWVbMF0gPT0gJyMnXG5cdFx0ZWxzZVxuXHRcdFx0Y2hpbGQuQG5vZGVUeXBlID0gY2hpbGQuQG5hbWVcblx0XHRcdGNoaWxkLkBjbGFzc2VzID0gW11cblxuXHRkZWYgc2VsZi5idWlsZE5vZGVcblx0XHR2YXIgZG9tID0gSW1iYS5kb2N1bWVudC5jcmVhdGVFbGVtZW50KEBub2RlVHlwZSlcblx0XHR2YXIgY2xzID0gQGNsYXNzZXMuam9pbihcIiBcIilcblx0XHRkb206Y2xhc3NOYW1lID0gY2xzIGlmIGNsc1xuXHRcdGRvbVxuXG5cdGRlZiBzZWxmLmNyZWF0ZU5vZGVcblx0XHR2YXIgcHJvdG8gPSAoQHByb3RvRG9tIHx8PSBidWlsZE5vZGUpXG5cdFx0cHJvdG8uY2xvbmVOb2RlKGZhbHNlKVxuXG5cdGRlZiBzZWxmLmRvbVxuXHRcdEBwcm90b0RvbSB8fD0gYnVpbGROb2RlXG5cblx0YXR0ciBpZFxuXHRhdHRyIHRhYmluZGV4XG5cdGF0dHIgdGl0bGVcblx0YXR0ciByb2xlXG5cblx0ZGVmIHdpZHRoXG5cdFx0QGRvbTpvZmZzZXRXaWR0aFxuXG5cdGRlZiBoZWlnaHRcblx0XHRAZG9tOm9mZnNldEhlaWdodFxuXG5cdGRlZiBzZXRDaGlsZHJlbiBub2RlcywgdHlwZVxuXHRcdEBlbXB0eSA/IGFwcGVuZChub2RlcykgOiBlbXB0eS5hcHBlbmQobm9kZXMpXG5cdFx0QGNoaWxkcmVuID0gbnVsbFxuXHRcdHNlbGZcblxuXHQjIyNcblx0U2V0IGlubmVyIGh0bWwgb2Ygbm9kZVxuXHQjIyNcblx0ZGVmIGh0bWw9IGh0bWxcblx0XHRAZG9tOmlubmVySFRNTCA9IGh0bWxcblx0XHRzZWxmXG5cblx0IyMjXG5cdEdldCBpbm5lciBodG1sIG9mIG5vZGVcblx0IyMjXG5cdGRlZiBodG1sXG5cdFx0QGRvbTppbm5lckhUTUxcblxuXHQjIyNcblx0UmVtb3ZlIGFsbCBjb250ZW50IGluc2lkZSBub2RlXG5cdCMjI1xuXHRkZWYgZW1wdHlcblx0XHRAZG9tLnJlbW92ZUNoaWxkKEBkb206Zmlyc3RDaGlsZCkgd2hpbGUgQGRvbTpmaXJzdENoaWxkXG5cdFx0QGNoaWxkcmVuID0gbnVsbFxuXHRcdEBlbXB0eSA9IHllc1xuXHRcdHNlbGZcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBjaGlsZCBmcm9tIGN1cnJlbnQgbm9kZS5cblx0IyMjXG5cdGRlZiByZW1vdmUgY2hpbGRcblx0XHR2YXIgcGFyID0gZG9tXG5cdFx0dmFyIGVsID0gY2hpbGQgYW5kIGNoaWxkLmRvbVxuXHRcdHBhci5yZW1vdmVDaGlsZChlbCkgaWYgZWwgYW5kIGVsOnBhcmVudE5vZGUgPT0gcGFyXG5cdFx0c2VsZlxuXHRcdFxuXHRkZWYgZW1pdCBuYW1lLCBkYXRhOiBudWxsLCBidWJibGU6IHllc1xuXHRcdEltYmEuRXZlbnRzLnRyaWdnZXIgbmFtZSwgc2VsZiwgZGF0YTogZGF0YSwgYnViYmxlOiBidWJibGVcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBkYXRhc2V0IGtleSwgdmFsXG5cdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdGRhdGFzZXQoayx2KSBmb3Igb3duIGssdiBvZiBrZXlcblx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRpZiBhcmd1bWVudHM6bGVuZ3RoID09IDJcblx0XHRcdHNldEF0dHJpYnV0ZShcImRhdGEte2tleX1cIix2YWwpXG5cdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0aWYga2V5XG5cdFx0XHRyZXR1cm4gZ2V0QXR0cmlidXRlKFwiZGF0YS17a2V5fVwiKVxuXG5cdFx0dmFyIGRhdGFzZXQgPSBkb206ZGF0YXNldFxuXG5cdFx0dW5sZXNzIGRhdGFzZXRcblx0XHRcdGRhdGFzZXQgPSB7fVxuXHRcdFx0Zm9yIGF0cixpIGluIGRvbTphdHRyaWJ1dGVzXG5cdFx0XHRcdGlmIGF0cjpuYW1lLnN1YnN0cigwLDUpID09ICdkYXRhLSdcblx0XHRcdFx0XHRkYXRhc2V0W0ltYmEudG9DYW1lbENhc2UoYXRyOm5hbWUuc2xpY2UoNSkpXSA9IGF0cjp2YWx1ZVxuXG5cdFx0cmV0dXJuIGRhdGFzZXRcblxuXHQjIyNcblx0R2V0IGRlc2NlbmRhbnRzIG9mIGN1cnJlbnQgbm9kZSwgb3B0aW9uYWxseSBtYXRjaGluZyBzZWxlY3RvclxuXHRAcmV0dXJuIHtJbWJhLlNlbGVjdG9yfVxuXHQjIyNcblx0ZGVmIGZpbmQgc2VsXG5cdFx0SW1iYS5TZWxlY3Rvci5uZXcoc2VsLHNlbGYpXG5cblx0IyMjXG5cdEdldCB0aGUgZmlyc3QgbWF0Y2hpbmcgY2hpbGQgb2Ygbm9kZVxuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGZpcnN0IHNlbFxuXHRcdHNlbCA/IGZpbmQoc2VsKS5maXJzdCA6IHRhZyhkb206Zmlyc3RFbGVtZW50Q2hpbGQpXG5cblx0IyMjXG5cdEdldCB0aGUgbGFzdCBtYXRjaGluZyBjaGlsZCBvZiBub2RlXG5cblx0XHRub2RlLmxhc3QgIyByZXR1cm5zIHRoZSBsYXN0IGNoaWxkIG9mIG5vZGVcblx0XHRub2RlLmxhc3QgJXNwYW4gIyByZXR1cm5zIHRoZSBsYXN0IHNwYW4gaW5zaWRlIG5vZGVcblx0XHRub2RlLmxhc3QgZG8gfGVsfCBlbC50ZXh0ID09ICdIaScgIyByZXR1cm4gbGFzdCBub2RlIHdpdGggdGV4dCBIaVxuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGxhc3Qgc2VsXG5cdFx0c2VsID8gZmluZChzZWwpLmxhc3QgOiB0YWcoZG9tOmxhc3RFbGVtZW50Q2hpbGQpXG5cblx0IyMjXG5cdEdldCB0aGUgY2hpbGQgYXQgaW5kZXhcblx0IyMjXG5cdGRlZiBjaGlsZCBpXG5cdFx0dGFnKGRvbTpjaGlsZHJlbltpIG9yIDBdKVxuXG5cdGRlZiBjaGlsZHJlbiBzZWxcblx0XHR2YXIgbm9kZXMgPSBJbWJhLlNlbGVjdG9yLm5ldyhudWxsLCBzZWxmLCBAZG9tOmNoaWxkcmVuKVxuXHRcdHNlbCA/IG5vZGVzLmZpbHRlcihzZWwpIDogbm9kZXNcblx0XG5cdGRlZiBvcnBoYW5pemVcblx0XHRwYXIucmVtb3ZlQ2hpbGQoQGRvbSkgaWYgbGV0IHBhciA9IGRvbTpwYXJlbnROb2RlXG5cdFx0cmV0dXJuIHNlbGZcblx0XG5cdGRlZiBtYXRjaGVzIHNlbFxuXHRcdGlmIHNlbCBpc2EgRnVuY3Rpb25cblx0XHRcdHJldHVybiBzZWwoc2VsZilcblxuXHRcdHNlbCA9IHNlbC5xdWVyeSBpZiBzZWw6cXVlcnlcblx0XHRpZiB2YXIgZm4gPSAoQGRvbTptYXRjaGVzIG9yIEBkb206bWF0Y2hlc1NlbGVjdG9yIG9yIEBkb206d2Via2l0TWF0Y2hlc1NlbGVjdG9yIG9yIEBkb206bXNNYXRjaGVzU2VsZWN0b3Igb3IgQGRvbTptb3pNYXRjaGVzU2VsZWN0b3IpXG5cdFx0XHRyZXR1cm4gZm4uY2FsbChAZG9tLHNlbClcblxuXHQjIyNcblx0R2V0IHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHN1cHBsaWVkIHNlbGVjdG9yIC8gZmlsdGVyXG5cdHRyYXZlcnNpbmcgdXB3YXJkcywgYnV0IGluY2x1ZGluZyB0aGUgbm9kZSBpdHNlbGYuXG5cdEByZXR1cm4ge0ltYmEuVGFnfVxuXHQjIyNcblx0ZGVmIGNsb3Nlc3Qgc2VsXG5cdFx0cmV0dXJuIHBhcmVudCB1bmxlc3Mgc2VsICMgc2hvdWxkIHJldHVybiBzZWxmPyFcblx0XHR2YXIgbm9kZSA9IHNlbGZcblx0XHRzZWwgPSBzZWwucXVlcnkgaWYgc2VsOnF1ZXJ5XG5cblx0XHR3aGlsZSBub2RlXG5cdFx0XHRyZXR1cm4gbm9kZSBpZiBub2RlLm1hdGNoZXMoc2VsKVxuXHRcdFx0bm9kZSA9IG5vZGUucGFyZW50XG5cdFx0cmV0dXJuIG51bGxcblxuXHQjIyNcblx0R2V0IHRoZSBjbG9zZXN0IGFuY2VzdG9yIG9mIG5vZGUgdGhhdCBtYXRjaGVzXG5cdHNwZWNpZmllZCBzZWxlY3RvciAvIG1hdGNoZXIuXG5cblx0QHJldHVybiB7SW1iYS5UYWd9XG5cdCMjI1xuXHRkZWYgdXAgc2VsXG5cdFx0cmV0dXJuIHBhcmVudCB1bmxlc3Mgc2VsXG5cdFx0cGFyZW50IGFuZCBwYXJlbnQuY2xvc2VzdChzZWwpXG5cblx0ZGVmIHBhdGggc2VsXG5cdFx0dmFyIG5vZGUgPSBzZWxmXG5cdFx0dmFyIG5vZGVzID0gW11cblx0XHRzZWwgPSBzZWwucXVlcnkgaWYgc2VsIGFuZCBzZWw6cXVlcnlcblxuXHRcdHdoaWxlIG5vZGVcblx0XHRcdG5vZGVzLnB1c2gobm9kZSkgaWYgIXNlbCBvciBub2RlLm1hdGNoZXMoc2VsKVxuXHRcdFx0bm9kZSA9IG5vZGUucGFyZW50XG5cdFx0cmV0dXJuIG5vZGVzXG5cblx0ZGVmIHBhcmVudHMgc2VsXG5cdFx0dmFyIHBhciA9IHBhcmVudFxuXHRcdHBhciA/IHBhci5wYXRoKHNlbCkgOiBbXVxuXG5cdFxuXG5cdGRlZiBzaWJsaW5ncyBzZWxcblx0XHRyZXR1cm4gW10gdW5sZXNzIHZhciBwYXIgPSBwYXJlbnQgIyBGSVhNRVxuXHRcdHZhciBhcnkgPSBkb206cGFyZW50Tm9kZTpjaGlsZHJlblxuXHRcdHZhciBub2RlcyA9IEltYmEuU2VsZWN0b3IubmV3KG51bGwsIHNlbGYsIGFyeSlcblx0XHRub2Rlcy5maWx0ZXIofG58IG4gIT0gc2VsZiAmJiAoIXNlbCB8fCBuLm1hdGNoZXMoc2VsKSkpXG5cblx0IyMjXG5cdEdldCB0aGUgaW1tZWRpYXRlbHkgZm9sbG93aW5nIHNpYmxpbmcgb2Ygbm9kZS5cblx0IyMjXG5cdGRlZiBuZXh0IHNlbFxuXHRcdGlmIHNlbFxuXHRcdFx0dmFyIGVsID0gc2VsZlxuXHRcdFx0d2hpbGUgZWwgPSBlbC5uZXh0XG5cdFx0XHRcdHJldHVybiBlbCBpZiBlbC5tYXRjaGVzKHNlbClcblx0XHRcdHJldHVybiBudWxsXG5cdFx0dGFnKGRvbTpuZXh0RWxlbWVudFNpYmxpbmcpXG5cblx0IyMjXG5cdEdldCB0aGUgaW1tZWRpYXRlbHkgcHJlY2VlZGluZyBzaWJsaW5nIG9mIG5vZGUuXG5cdCMjI1xuXHRkZWYgcHJldiBzZWxcblx0XHRpZiBzZWxcblx0XHRcdHZhciBlbCA9IHNlbGZcblx0XHRcdHdoaWxlIGVsID0gZWwucHJldlxuXHRcdFx0XHRyZXR1cm4gZWwgaWYgZWwubWF0Y2hlcyhzZWwpXG5cdFx0XHRyZXR1cm4gbnVsbFxuXHRcdHRhZyhkb206cHJldmlvdXNFbGVtZW50U2libGluZylcblxuXHRkZWYgY29udGFpbnMgbm9kZVxuXHRcdGRvbS5jb250YWlucyhub2RlIGFuZCBub2RlLkBkb20gb3Igbm9kZSlcblxuXHRkZWYgaW5kZXhcblx0XHR2YXIgaSA9IDBcblx0XHR2YXIgZWwgPSBkb21cblx0XHR3aGlsZSBlbDpwcmV2aW91c1NpYmxpbmdcblx0XHRcdGVsID0gZWw6cHJldmlvdXNTaWJsaW5nXG5cdFx0XHRpKytcblx0XHRyZXR1cm4gaVxuXG5cblx0IyMjXG5cdFxuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0ZGVmIGluc2VydCBub2RlLCBiZWZvcmU6IG51bGwsIGFmdGVyOiBudWxsXG5cdFx0YmVmb3JlID0gYWZ0ZXIubmV4dCBpZiBhZnRlclxuXHRcdGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0XHRub2RlID0gKDxmcmFnbWVudD4gbm9kZSlcblx0XHRpZiBiZWZvcmVcblx0XHRcdGRvbS5pbnNlcnRCZWZvcmUobm9kZS5kb20sYmVmb3JlLmRvbSlcblx0XHRlbHNlXG5cdFx0XHRhcHBlbmQobm9kZSlcblx0XHRzZWxmXHRcblxuXHQjIyNcblx0Rm9jdXMgb24gY3VycmVudCBub2RlXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgZm9jdXNcblx0XHRkb20uZm9jdXNcblx0XHRzZWxmXG5cblx0IyMjXG5cdFJlbW92ZSBmb2N1cyBmcm9tIGN1cnJlbnQgbm9kZVxuXHRAcmV0dXJuIHtzZWxmfVxuXHQjIyNcblx0ZGVmIGJsdXJcblx0XHRkb20uYmx1clxuXHRcdHNlbGZcblxuXHRkZWYgdGVtcGxhdGVcblx0XHRudWxsXG5cblx0IyMjXG5cdEB0b2RvIFNob3VsZCBzdXBwb3J0IG11bHRpcGxlIGFyZ3VtZW50cyBsaWtlIGFwcGVuZFxuXG5cdFRoZSAucHJlcGVuZCBtZXRob2QgaW5zZXJ0cyB0aGUgc3BlY2lmaWVkIGNvbnRlbnQgYXMgdGhlIGZpcnN0XG5cdGNoaWxkIG9mIHRoZSB0YXJnZXQgbm9kZS4gSWYgdGhlIGNvbnRlbnQgaXMgYWxyZWFkeSBhIGNoaWxkIG9mIFxuXHRub2RlIGl0IHdpbGwgYmUgbW92ZWQgdG8gdGhlIHN0YXJ0LlxuXHRcbiAgICBcdG5vZGUucHJlcGVuZCA8ZGl2LnRvcD4gIyBwcmVwZW5kIG5vZGVcbiAgICBcdG5vZGUucHJlcGVuZCBcInNvbWUgdGV4dFwiICMgcHJlcGVuZCB0ZXh0XG4gICAgXHRub2RlLnByZXBlbmQgWzx1bD4sPHVsPl0gIyBwcmVwZW5kIGFycmF5XG5cblx0IyMjXG5cdGRlZiBwcmVwZW5kIGl0ZW1cblx0XHR2YXIgZmlyc3QgPSBAZG9tOmNoaWxkTm9kZXNbMF1cblx0XHRmaXJzdCA/IGluc2VydEJlZm9yZShpdGVtLCBmaXJzdCkgOiBhcHBlbmRDaGlsZChpdGVtKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0VGhlIC5hcHBlbmQgbWV0aG9kIGluc2VydHMgdGhlIHNwZWNpZmllZCBjb250ZW50IGFzIHRoZSBsYXN0IGNoaWxkXG5cdG9mIHRoZSB0YXJnZXQgbm9kZS4gSWYgdGhlIGNvbnRlbnQgaXMgYWxyZWFkeSBhIGNoaWxkIG9mIG5vZGUgaXRcblx0d2lsbCBiZSBtb3ZlZCB0byB0aGUgZW5kLlxuXHRcblx0IyBleGFtcGxlXG5cdCAgICB2YXIgcm9vdCA9IDxkaXYucm9vdD5cblx0ICAgIHZhciBpdGVtID0gPGRpdi5pdGVtPiBcIlRoaXMgaXMgYW4gaXRlbVwiXG5cdCAgICByb290LmFwcGVuZCBpdGVtICMgYXBwZW5kcyBpdGVtIHRvIHRoZSBlbmQgb2Ygcm9vdFxuXG5cdCAgICByb290LnByZXBlbmQgXCJzb21lIHRleHRcIiAjIGFwcGVuZCB0ZXh0XG5cdCAgICByb290LnByZXBlbmQgWzx1bD4sPHVsPl0gIyBhcHBlbmQgYXJyYXlcblx0IyMjXG5cdGRlZiBhcHBlbmQgaXRlbVxuXHRcdCMgcG9zc2libGUgdG8gYXBwZW5kIGJsYW5rXG5cdFx0IyBwb3NzaWJsZSB0byBzaW1wbGlmeSBvbiBzZXJ2ZXI/XG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIGl0ZW1cblxuXHRcdGlmIGl0ZW0gaXNhIEFycmF5XG5cdFx0XHRtZW1iZXIgJiYgYXBwZW5kKG1lbWJlcikgZm9yIG1lbWJlciBpbiBpdGVtXG5cblx0XHRlbGlmIGl0ZW0gaXNhIFN0cmluZyBvciBpdGVtIGlzYSBOdW1iZXJcblx0XHRcdHZhciBub2RlID0gSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShpdGVtKVxuXHRcdFx0QGRvbS5hcHBlbmRDaGlsZChub2RlKVxuXHRcdFx0QGVtcHR5ID0gbm8gaWYgQGVtcHR5XHRcdFx0XG5cdFx0ZWxzZVxuXHRcdFx0QGRvbS5hcHBlbmRDaGlsZChpdGVtLkBkb20gb3IgaXRlbSlcblx0XHRcdEBlbXB0eSA9IG5vIGlmIEBlbXB0eVxuXG5cdFx0cmV0dXJuIHNlbGZcblxuXHQjIyNcblx0SW5zZXJ0IGEgbm9kZSBpbnRvIHRoZSBjdXJyZW50IG5vZGUgKHNlbGYpLCBiZWZvcmUgYW5vdGhlci5cblx0VGhlIHJlbGF0aXZlIG5vZGUgbXVzdCBiZSBhIGNoaWxkIG9mIGN1cnJlbnQgbm9kZS4gXG5cdCMjI1xuXHRkZWYgaW5zZXJ0QmVmb3JlIG5vZGUsIHJlbFxuXHRcdG5vZGUgPSBJbWJhLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5vZGUpIGlmIG5vZGUgaXNhIFN0cmluZyBcblx0XHRkb20uaW5zZXJ0QmVmb3JlKCAobm9kZS5AZG9tIG9yIG5vZGUpLCAocmVsLkBkb20gb3IgcmVsKSApIGlmIG5vZGUgYW5kIHJlbFxuXHRcdHNlbGZcblxuXHQjIyNcblx0QXBwZW5kIGEgc2luZ2xlIGl0ZW0gKG5vZGUgb3Igc3RyaW5nKSB0byB0aGUgY3VycmVudCBub2RlLlxuXHRJZiBzdXBwbGllZCBpdGVtIGlzIGEgc3RyaW5nIGl0IHdpbGwgYXV0b21hdGljYWxseS4gVGhpcyBpcyB1c2VkXG5cdGJ5IEltYmEgaW50ZXJuYWxseSwgYnV0IHdpbGwgcHJhY3RpY2FsbHkgbmV2ZXIgYmUgdXNlZCBleHBsaWNpdGx5LlxuXHQjIyNcblx0ZGVmIGFwcGVuZENoaWxkIG5vZGVcblx0XHRub2RlID0gSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShub2RlKSBpZiBub2RlIGlzYSBTdHJpbmdcblx0XHRkb20uYXBwZW5kQ2hpbGQobm9kZS5AZG9tIG9yIG5vZGUpIGlmIG5vZGVcblx0XHRzZWxmXG5cblx0IyMjXG5cdFJlbW92ZSBhIHNpbmdsZSBjaGlsZCBmcm9tIHRoZSBjdXJyZW50IG5vZGUuXG5cdFVzZWQgYnkgSW1iYSBpbnRlcm5hbGx5LlxuXHQjIyNcblx0ZGVmIHJlbW92ZUNoaWxkIG5vZGVcblx0XHRkb20ucmVtb3ZlQ2hpbGQobm9kZS5AZG9tIG9yIG5vZGUpIGlmIG5vZGVcblx0XHRzZWxmXG5cblx0ZGVmIHRvU3RyaW5nXG5cdFx0QGRvbS50b1N0cmluZyAjIHJlYWxseT9cblxuXHQjIyNcblx0QGRlcHJlY2F0ZWRcblx0IyMjXG5cdGRlZiBjbGFzc2VzXG5cdFx0Y29uc29sZS5sb2cgJ0ltYmEuVGFnI2NsYXNzZXMgaXMgZGVwcmVjYXRlZCdcblx0XHRAZG9tOmNsYXNzTGlzdFxuXG50YWcgc3ZnZWxlbWVudCA8IGh0bWxlbGVtZW50XG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uaW1iYVxuICoqLyIsIlxuIyBwcmVkZWZpbmUgYWxsIHN1cHBvcnRlZCBodG1sIHRhZ3NcbnRhZyBmcmFnbWVudCA8IGh0bWxlbGVtZW50XG5cdFxuXHRkZWYgc2VsZi5jcmVhdGVOb2RlXG5cdFx0SW1iYS5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50XG5cbnRhZyBhXG5cdGF0dHIgaHJlZlxuXG50YWcgYWJiclxudGFnIGFkZHJlc3NcbnRhZyBhcmVhXG50YWcgYXJ0aWNsZVxudGFnIGFzaWRlXG50YWcgYXVkaW9cbnRhZyBiXG50YWcgYmFzZVxudGFnIGJkaVxudGFnIGJkb1xudGFnIGJpZ1xudGFnIGJsb2NrcXVvdGVcbnRhZyBib2R5XG50YWcgYnJcblxudGFnIGJ1dHRvblxuXHRhdHRyIGF1dG9mb2N1c1xuXHRhdHRyIHR5cGVcblx0YXR0ciBkaXNhYmxlZFxuXG50YWcgY2FudmFzXG5cdGRlZiB3aWR0aD0gdmFsXG5cdFx0ZG9tOndpZHRoID0gdmFsIHVubGVzcyB3aWR0aCA9PSB2YWxcblx0XHRzZWxmXG5cblx0ZGVmIGhlaWdodD0gdmFsXG5cdFx0ZG9tOmhlaWdodCA9IHZhbCB1bmxlc3MgaGVpZ2h0ID09IHZhbFxuXHRcdHNlbGZcblxuXHRkZWYgd2lkdGhcblx0XHRkb206d2lkdGhcblxuXHRkZWYgaGVpZ2h0XG5cdFx0ZG9tOmhlaWdodFxuXG5cdGRlZiBjb250ZXh0IHR5cGUgPSAnMmQnXG5cdFx0ZG9tLmdldENvbnRleHQodHlwZSlcblxudGFnIGNhcHRpb25cbnRhZyBjaXRlXG50YWcgY29kZVxudGFnIGNvbFxudGFnIGNvbGdyb3VwXG50YWcgZGF0YVxudGFnIGRhdGFsaXN0XG50YWcgZGRcbnRhZyBkZWxcbnRhZyBkZXRhaWxzXG50YWcgZGZuXG50YWcgZGl2XG50YWcgZGxcbnRhZyBkdFxudGFnIGVtXG50YWcgZW1iZWRcbnRhZyBmaWVsZHNldFxudGFnIGZpZ2NhcHRpb25cbnRhZyBmaWd1cmVcbnRhZyBmb290ZXJcblxudGFnIGZvcm1cblx0YXR0ciBtZXRob2Rcblx0YXR0ciBhY3Rpb25cblxudGFnIGgxXG50YWcgaDJcbnRhZyBoM1xudGFnIGg0XG50YWcgaDVcbnRhZyBoNlxudGFnIGhlYWRcbnRhZyBoZWFkZXJcbnRhZyBoclxudGFnIGh0bWxcbnRhZyBpXG5cbnRhZyBpZnJhbWVcblx0YXR0ciBzcmNcblxudGFnIGltZ1xuXHRhdHRyIHNyY1xuXG50YWcgaW5wdXRcblx0IyBjYW4gdXNlIGF0dHIgaW5zdGVhZFxuXHRhdHRyIG5hbWVcblx0YXR0ciB0eXBlXG5cdGF0dHIgcmVxdWlyZWRcblx0YXR0ciBkaXNhYmxlZFxuXHRhdHRyIGF1dG9mb2N1c1xuXG5cdGRlZiB2YWx1ZVxuXHRcdGRvbTp2YWx1ZVxuXG5cdGRlZiB2YWx1ZT0gdlxuXHRcdGRvbTp2YWx1ZSA9IHYgdW5sZXNzIHYgPT0gZG9tOnZhbHVlXG5cdFx0c2VsZlxuXG5cdGRlZiBwbGFjZWhvbGRlcj0gdlxuXHRcdGRvbTpwbGFjZWhvbGRlciA9IHYgdW5sZXNzIHYgPT0gZG9tOnBsYWNlaG9sZGVyXG5cdFx0c2VsZlxuXG5cdGRlZiBwbGFjZWhvbGRlclxuXHRcdGRvbTpwbGFjZWhvbGRlclxuXG5cdGRlZiBjaGVja2VkXG5cdFx0ZG9tOmNoZWNrZWRcblxuXHRkZWYgY2hlY2tlZD0gYm9vbFxuXHRcdGRvbTpjaGVja2VkID0gYm9vbCB1bmxlc3MgYm9vbCA9PSBkb206Y2hlY2tlZFxuXHRcdHNlbGZcblxudGFnIGluc1xudGFnIGtiZFxudGFnIGtleWdlblxudGFnIGxhYmVsXG50YWcgbGVnZW5kXG50YWcgbGlcblxudGFnIGxpbmtcblx0YXR0ciByZWxcblx0YXR0ciB0eXBlXG5cdGF0dHIgaHJlZlxuXHRhdHRyIG1lZGlhXG5cbnRhZyBtYWluXG50YWcgbWFwXG50YWcgbWFya1xudGFnIG1lbnVcbnRhZyBtZW51aXRlbVxuXG50YWcgbWV0YVxuXHRhdHRyIG5hbWVcblx0YXR0ciBjb250ZW50XG5cdGF0dHIgY2hhcnNldFxuXG50YWcgbWV0ZXJcbnRhZyBuYXZcbnRhZyBub3NjcmlwdFxudGFnIG9iamVjdFxudGFnIG9sXG50YWcgb3B0Z3JvdXBcblxudGFnIG9wdGlvblxuXHRhdHRyIHZhbHVlXG5cbnRhZyBvdXRwdXRcbnRhZyBwXG50YWcgcGFyYW1cbnRhZyBwcmVcbnRhZyBwcm9ncmVzc1xudGFnIHFcbnRhZyBycFxudGFnIHJ0XG50YWcgcnVieVxudGFnIHNcbnRhZyBzYW1wXG5cbnRhZyBzY3JpcHRcblx0YXR0ciBzcmNcblx0YXR0ciB0eXBlXG5cdGF0dHIgYXN5bmNcblx0YXR0ciBkZWZlclxuXG50YWcgc2VjdGlvblxuXG50YWcgc2VsZWN0XG5cdGF0dHIgbmFtZVxuXHRhdHRyIG11bHRpcGxlXG5cdGF0dHIgcmVxdWlyZWRcblx0YXR0ciBkaXNhYmxlZFxuXHRcblx0ZGVmIHZhbHVlXG5cdFx0ZG9tOnZhbHVlXG5cblx0ZGVmIHZhbHVlPSB2XG5cdFx0ZG9tOnZhbHVlID0gdiB1bmxlc3MgdiA9PSBkb206dmFsdWVcblx0XHRzZWxmXG5cblxudGFnIHNtYWxsXG50YWcgc291cmNlXG50YWcgc3BhblxudGFnIHN0cm9uZ1xudGFnIHN0eWxlXG50YWcgc3ViXG50YWcgc3VtbWFyeVxudGFnIHN1cFxudGFnIHRhYmxlXG50YWcgdGJvZHlcbnRhZyB0ZFxuXG50YWcgdGV4dGFyZWFcblx0YXR0ciBuYW1lXG5cdGF0dHIgZGlzYWJsZWRcblx0YXR0ciByZXF1aXJlZFxuXHRhdHRyIHJvd3Ncblx0YXR0ciBjb2xzXG5cdGF0dHIgYXV0b2ZvY3VzXG5cblx0ZGVmIHZhbHVlXG5cdFx0ZG9tOnZhbHVlXG5cblx0ZGVmIHZhbHVlPSB2XG5cdFx0ZG9tOnZhbHVlID0gdiB1bmxlc3MgdiA9PSBkb206dmFsdWVcblx0XHRzZWxmXG5cblx0ZGVmIHBsYWNlaG9sZGVyPSB2XG5cdFx0ZG9tOnBsYWNlaG9sZGVyID0gdiB1bmxlc3MgdiA9PSBkb206cGxhY2Vob2xkZXJcblx0XHRzZWxmXG5cblx0ZGVmIHBsYWNlaG9sZGVyXG5cdFx0ZG9tOnBsYWNlaG9sZGVyXG5cbnRhZyB0Zm9vdFxudGFnIHRoXG50YWcgdGhlYWRcbnRhZyB0aW1lXG50YWcgdGl0bGVcbnRhZyB0clxudGFnIHRyYWNrXG50YWcgdVxudGFnIHVsXG50YWcgdmlkZW9cbnRhZyB3YnJcblxuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL2RvbS5odG1sLmltYmFcbiAqKi8iLCJcbnRhZyBzdmc6c3ZnZWxlbWVudFxuXG5cdGRlZiBzZWxmLm5hbWVzcGFjZVVSSVxuXHRcdFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIlxuXG5cdGxldCB0eXBlcyA9IFwiY2lyY2xlIGRlZnMgZWxsaXBzZSBnIGxpbmUgbGluZWFyR3JhZGllbnQgbWFzayBwYXRoIHBhdHRlcm4gcG9seWdvbiBwb2x5bGluZSByYWRpYWxHcmFkaWVudCByZWN0IHN0b3Agc3ZnIHRleHQgdHNwYW5cIi5zcGxpdChcIiBcIilcblxuXHRkZWYgc2VsZi5idWlsZE5vZGVcblx0XHR2YXIgZG9tID0gSW1iYS5kb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlVVJJLEBub2RlVHlwZSlcblx0XHR2YXIgY2xzID0gQGNsYXNzZXMuam9pbihcIiBcIilcblx0XHRkb206Y2xhc3NOYW1lOmJhc2VWYWwgPSBjbHMgaWYgY2xzXG5cdFx0ZG9tXG5cblx0ZGVmIHNlbGYuaW5oZXJpdCBjaGlsZFxuXHRcdGNoaWxkLkBwcm90b0RvbSA9IG51bGxcblxuXHRcdGlmIGNoaWxkLkBuYW1lIGluIHR5cGVzXG5cdFx0XHRjaGlsZC5Abm9kZVR5cGUgPSBjaGlsZC5AbmFtZVxuXHRcdFx0Y2hpbGQuQGNsYXNzZXMgPSBbXVxuXHRcdGVsc2Vcblx0XHRcdGNoaWxkLkBub2RlVHlwZSA9IEBub2RlVHlwZVxuXHRcdFx0dmFyIGNsYXNzTmFtZSA9IFwiX1wiICsgY2hpbGQuQG5hbWUucmVwbGFjZSgvXy9nLCAnLScpXG5cdFx0XHRjaGlsZC5AY2xhc3NlcyA9IEBjbGFzc2VzLmNvbmNhdChjbGFzc05hbWUpXG5cblxuXHRhdHRyIHggaW5saW5lOiBub1xuXHRhdHRyIHkgaW5saW5lOiBub1xuXG5cdGF0dHIgd2lkdGggaW5saW5lOiBub1xuXHRhdHRyIGhlaWdodCBpbmxpbmU6IG5vXG5cblx0YXR0ciBzdHJva2UgaW5saW5lOiBub1xuXHRhdHRyIHN0cm9rZS13aWR0aCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6c3ZnXG5cdGF0dHIgdmlld2JveCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6Z1xuXG50YWcgc3ZnOmRlZnNcblxudGFnIHN2ZzpzeW1ib2xcblx0YXR0ciBwcmVzZXJ2ZUFzcGVjdFJhdGlvIGlubGluZTogbm9cblx0YXR0ciB2aWV3Qm94IGlubGluZTogbm9cblxudGFnIHN2ZzptYXJrZXJcblx0YXR0ciBtYXJrZXJVbml0cyBpbmxpbmU6IG5vXG5cdGF0dHIgcmVmWCBpbmxpbmU6IG5vXG5cdGF0dHIgcmVmWSBpbmxpbmU6IG5vXG5cdGF0dHIgbWFya2VyV2lkdGggaW5saW5lOiBub1xuXHRhdHRyIG1hcmtlckhlaWdodCBpbmxpbmU6IG5vXG5cdGF0dHIgb3JpZW50IGlubGluZTogbm9cblxuXG4jIEJhc2ljIHNoYXBlc1xuXG50YWcgc3ZnOnJlY3Rcblx0YXR0ciByeCBpbmxpbmU6IG5vXG5cdGF0dHIgcnkgaW5saW5lOiBub1xuXG50YWcgc3ZnOmNpcmNsZVxuXHRhdHRyIGN4IGlubGluZTogbm9cblx0YXR0ciBjeSBpbmxpbmU6IG5vXG5cdGF0dHIgciBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6ZWxsaXBzZVxuXHRhdHRyIGN4IGlubGluZTogbm9cblx0YXR0ciBjeSBpbmxpbmU6IG5vXG5cdGF0dHIgcnggaW5saW5lOiBub1xuXHRhdHRyIHJ5IGlubGluZTogbm9cblxudGFnIHN2ZzpwYXRoXG5cdGF0dHIgZCBpbmxpbmU6IG5vXG5cdGF0dHIgcGF0aExlbmd0aCBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6bGluZVxuXHRhdHRyIHgxIGlubGluZTogbm9cblx0YXR0ciB4MiBpbmxpbmU6IG5vXG5cdGF0dHIgeTEgaW5saW5lOiBub1xuXHRhdHRyIHkyIGlubGluZTogbm9cblxudGFnIHN2Zzpwb2x5bGluZVxuXHRhdHRyIHBvaW50cyBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6cG9seWdvblxuXHRhdHRyIHBvaW50cyBpbmxpbmU6IG5vXG5cbnRhZyBzdmc6dGV4dFxuXHRhdHRyIGR4IGlubGluZTogbm9cblx0YXR0ciBkeSBpbmxpbmU6IG5vXG5cdGF0dHIgdGV4dC1hbmNob3IgaW5saW5lOiBub1xuXHRhdHRyIHJvdGF0ZSBpbmxpbmU6IG5vXG5cdGF0dHIgdGV4dExlbmd0aCBpbmxpbmU6IG5vXG5cdGF0dHIgbGVuZ3RoQWRqdXN0IGlubGluZTogbm9cblxudGFnIHN2Zzp0c3BhblxuXHRhdHRyIGR4IGlubGluZTogbm9cblx0YXR0ciBkeSBpbmxpbmU6IG5vXG5cdGF0dHIgcm90YXRlIGlubGluZTogbm9cblx0YXR0ciB0ZXh0TGVuZ3RoIGlubGluZTogbm9cblx0YXR0ciBsZW5ndGhBZGp1c3QgaW5saW5lOiBub1xuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIHNyYy9pbWJhL2RvbS5zdmcuaW1iYVxuICoqLyIsIiMgRXh0ZW5kaW5nIEltYmEuVGFnI2NzcyB0byB3b3JrIHdpdGhvdXQgcHJlZml4ZXMgYnkgaW5zcGVjdGluZ1xuIyB0aGUgcHJvcGVydGllcyBvZiBhIENTU1N0eWxlRGVjbGFyYXRpb24gYW5kIGNyZWF0aW5nIGEgbWFwXG5cbiMgdmFyIHByZWZpeGVzID0gWyctd2Via2l0LScsJy1tcy0nLCctbW96LScsJy1vLScsJy1ibGluay0nXVxuIyB2YXIgcHJvcHMgPSBbJ3RyYW5zZm9ybScsJ3RyYW5zaXRpb24nLCdhbmltYXRpb24nXVxuXG5pZiBJbWJhLkNMSUVOVFxuXHR2YXIgc3R5bGVzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQ6ZG9jdW1lbnRFbGVtZW50LCAnJylcblxuXHRJbWJhLkNTU0tleU1hcCA9IHt9XG5cblx0Zm9yIHByZWZpeGVkIGluIHN0eWxlc1xuXHRcdHZhciB1bnByZWZpeGVkID0gcHJlZml4ZWQucmVwbGFjZSgvXi0od2Via2l0fG1zfG1venxvfGJsaW5rKS0vLCcnKVxuXHRcdHZhciBjYW1lbENhc2UgPSB1bnByZWZpeGVkLnJlcGxhY2UoLy0oXFx3KS9nKSBkbyB8bSxhfCBhLnRvVXBwZXJDYXNlXG5cblx0XHQjIGlmIHRoZXJlIGV4aXN0cyBhbiB1bnByZWZpeGVkIHZlcnNpb24gLS0gYWx3YXlzIHVzZSB0aGlzXG5cdFx0aWYgcHJlZml4ZWQgIT0gdW5wcmVmaXhlZFxuXHRcdFx0Y29udGludWUgaWYgc3R5bGVzLmhhc093blByb3BlcnR5KHVucHJlZml4ZWQpXG5cblx0XHQjIHJlZ2lzdGVyIHRoZSBwcmVmaXhlc1xuXHRcdEltYmEuQ1NTS2V5TWFwW3VucHJlZml4ZWRdID0gSW1iYS5DU1NLZXlNYXBbY2FtZWxDYXNlXSA9IHByZWZpeGVkXG5cblx0ZXh0ZW5kIHRhZyBlbGVtZW50XG5cblx0XHQjIG92ZXJyaWRlIHRoZSBvcmlnaW5hbCBjc3MgbWV0aG9kXG5cdFx0ZGVmIGNzcyBrZXksIHZhbFxuXHRcdFx0aWYga2V5IGlzYSBPYmplY3Rcblx0XHRcdFx0Y3NzKGssdikgZm9yIG93biBrLHYgb2Yga2V5XG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRcdGtleSA9IEltYmEuQ1NTS2V5TWFwW2tleV0gb3Iga2V5XG5cblx0XHRcdGlmIHZhbCA9PSBudWxsXG5cdFx0XHRcdGRvbTpzdHlsZS5yZW1vdmVQcm9wZXJ0eShrZXkpXG5cdFx0XHRlbGlmIHZhbCA9PSB1bmRlZmluZWRcblx0XHRcdFx0cmV0dXJuIGRvbTpzdHlsZVtrZXldXG5cdFx0XHRlbHNlXG5cdFx0XHRcdGlmIHZhbCBpc2EgTnVtYmVyIGFuZCBrZXkubWF0Y2goL3dpZHRofGhlaWdodHxsZWZ0fHJpZ2h0fHRvcHxib3R0b20vKVxuXHRcdFx0XHRcdHZhbCA9IHZhbCArIFwicHhcIlxuXHRcdFx0XHRkb206c3R5bGVba2V5XSA9IHZhbFxuXHRcdFx0c2VsZlxuXHRcdFx0XG5cdHVubGVzcyBkb2N1bWVudDpkb2N1bWVudEVsZW1lbnQ6Y2xhc3NMaXN0XG5cdFx0ZXh0ZW5kIHRhZyBlbGVtZW50XG5cblx0XHRcdGRlZiBoYXNGbGFnIHJlZlxuXHRcdFx0XHRyZXR1cm4gUmVnRXhwLm5ldygnKF58XFxcXHMpJyArIHJlZiArICcoXFxcXHN8JCknKS50ZXN0KEBkb206Y2xhc3NOYW1lKVxuXG5cdFx0XHRkZWYgYWRkRmxhZyByZWZcblx0XHRcdFx0cmV0dXJuIHNlbGYgaWYgaGFzRmxhZyhyZWYpXG5cdFx0XHRcdEBkb206Y2xhc3NOYW1lICs9IChAZG9tOmNsYXNzTmFtZSA/ICcgJyA6ICcnKSArIHJlZlxuXHRcdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0XHRkZWYgdW5mbGFnIHJlZlxuXHRcdFx0XHRyZXR1cm4gc2VsZiB1bmxlc3MgaGFzRmxhZyhyZWYpXG5cdFx0XHRcdHZhciByZWdleCA9IFJlZ0V4cC5uZXcoJyhefFxcXFxzKSonICsgcmVmICsgJyhcXFxcc3wkKSonLCAnZycpXG5cdFx0XHRcdEBkb206Y2xhc3NOYW1lID0gQGRvbTpjbGFzc05hbWUucmVwbGFjZShyZWdleCwgJycpXG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRcdGRlZiB0b2dnbGVGbGFnIHJlZlxuXHRcdFx0XHRoYXNGbGFnKHJlZikgPyB1bmZsYWcocmVmKSA6IGZsYWcocmVmKVxuXG5cdFx0XHRkZWYgZmxhZyByZWYsIGJvb2xcblx0XHRcdFx0aWYgYXJndW1lbnRzOmxlbmd0aCA9PSAyIGFuZCAhIWJvb2wgPT09IG5vXG5cdFx0XHRcdFx0cmV0dXJuIHVuZmxhZyhyZWYpXG5cdFx0XHRcdHJldHVybiBhZGRGbGFnKHJlZilcblx0XHR0cnVlXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvZG9tLmNsaWVudC5pbWJhXG4gKiovIiwidmFyIGRvYyA9IGRvY3VtZW50XG52YXIgd2luID0gd2luZG93XG5cbnZhciBoYXNUb3VjaEV2ZW50cyA9IHdpbmRvdyAmJiB3aW5kb3c6b250b3VjaHN0YXJ0ICE9PSB1bmRlZmluZWRcblxuY2xhc3MgSW1iYS5Qb2ludGVyXG5cblx0IyBiZWdhbiwgbW92ZWQsIHN0YXRpb25hcnksIGVuZGVkLCBjYW5jZWxsZWRcblxuXHRwcm9wIHBoYXNlXG5cdHByb3AgcHJldkV2ZW50XG5cdHByb3AgYnV0dG9uXG5cdHByb3AgZXZlbnRcblx0cHJvcCBkaXJ0eVxuXHRwcm9wIGV2ZW50c1xuXHRwcm9wIHRvdWNoXG5cblx0ZGVmIGluaXRpYWxpemVcblx0XHRidXR0b24gPSAtMVxuXHRcdGV2ZW50ID0ge3g6IDAsIHk6IDAsIHR5cGU6ICd1bmluaXRpYWxpemVkJ31cblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiB1cGRhdGUgZVxuXHRcdGV2ZW50ID0gZVxuXHRcdGRpcnR5ID0geWVzXG5cdFx0c2VsZlxuXG5cdCMgdGhpcyBpcyBqdXN0IGZvciByZWd1bGFyIG1vdXNlIG5vd1xuXHRkZWYgcHJvY2Vzc1xuXHRcdHZhciBlMSA9IGV2ZW50XG5cblx0XHRpZiBkaXJ0eVxuXHRcdFx0cHJldkV2ZW50ID0gZTFcblx0XHRcdGRpcnR5ID0gbm9cblxuXHRcdFx0IyBidXR0b24gc2hvdWxkIG9ubHkgY2hhbmdlIG9uIG1vdXNlZG93biBldGNcblx0XHRcdGlmIGUxOnR5cGUgPT0gJ21vdXNlZG93bidcblx0XHRcdFx0YnV0dG9uID0gZTE6YnV0dG9uXG5cblx0XHRcdFx0IyBkbyBub3QgY3JlYXRlIHRvdWNoIGZvciByaWdodCBjbGlja1xuXHRcdFx0XHRpZiBidXR0b24gPT0gMiBvciAodG91Y2ggYW5kIGJ1dHRvbiAhPSAwKVxuXHRcdFx0XHRcdHJldHVyblxuXG5cdFx0XHRcdCMgY2FuY2VsIHRoZSBwcmV2aW91cyB0b3VjaFxuXHRcdFx0XHR0b3VjaC5jYW5jZWwgaWYgdG91Y2hcblx0XHRcdFx0dG91Y2ggPSBJbWJhLlRvdWNoLm5ldyhlMSxzZWxmKVxuXHRcdFx0XHR0b3VjaC5tb3VzZWRvd24oZTEsZTEpXG5cblx0XHRcdGVsaWYgZTE6dHlwZSA9PSAnbW91c2Vtb3ZlJ1xuXHRcdFx0XHR0b3VjaC5tb3VzZW1vdmUoZTEsZTEpIGlmIHRvdWNoXG5cblx0XHRcdGVsaWYgZTE6dHlwZSA9PSAnbW91c2V1cCdcblx0XHRcdFx0YnV0dG9uID0gLTFcblxuXHRcdFx0XHRpZiB0b3VjaCBhbmQgdG91Y2guYnV0dG9uID09IGUxOmJ1dHRvblxuXHRcdFx0XHRcdHRvdWNoLm1vdXNldXAoZTEsZTEpXG5cdFx0XHRcdFx0dG91Y2ggPSBudWxsXG5cdFx0XHRcdCMgdHJpZ2dlciBwb2ludGVydXBcblx0XHRlbHNlXG5cdFx0XHR0b3VjaC5pZGxlIGlmIHRvdWNoXG5cdFx0c2VsZlxuXHRcdFxuXHRkZWYgY2xlYW51cFxuXHRcdEltYmEuUE9JTlRFUlNcblxuXHRkZWYgeCBkbyBldmVudDp4XG5cdGRlZiB5IGRvIGV2ZW50OnlcblxuXHQjIGRlcHJlY2F0ZWQgLS0gc2hvdWxkIHJlbW92ZVxuXHRkZWYgc2VsZi51cGRhdGUgXG5cdFx0IyBjb25zb2xlLmxvZygndXBkYXRlIHRvdWNoJylcblx0XHRmb3IgcHRyLGkgaW4gSW1iYS5QT0lOVEVSU1xuXHRcdFx0cHRyLnByb2Nlc3Ncblx0XHQjIG5lZWQgdG8gYmUgYWJsZSB0byBwcmV2ZW50IHRoZSBkZWZhdWx0IGJlaGF2aW91ciBvZiB0b3VjaCwgbm8/XG5cdFx0d2luLnJlcXVlc3RBbmltYXRpb25GcmFtZShJbWJhLlBvaW50ZXI6dXBkYXRlKVxuXHRcdHNlbGZcblxudmFyIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCA9IDBcbnZhciBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0ID0gNTBcblxuIyBJbWJhLlRvdWNoXG4jIEJlZ2FuXHRBIGZpbmdlciB0b3VjaGVkIHRoZSBzY3JlZW4uXG4jIE1vdmVkXHRBIGZpbmdlciBtb3ZlZCBvbiB0aGUgc2NyZWVuLlxuIyBTdGF0aW9uYXJ5XHRBIGZpbmdlciBpcyB0b3VjaGluZyB0aGUgc2NyZWVuIGJ1dCBoYXNuJ3QgbW92ZWQuXG4jIEVuZGVkXHRBIGZpbmdlciB3YXMgbGlmdGVkIGZyb20gdGhlIHNjcmVlbi4gVGhpcyBpcyB0aGUgZmluYWwgcGhhc2Ugb2YgYSB0b3VjaC5cbiMgQ2FuY2VsZWQgVGhlIHN5c3RlbSBjYW5jZWxsZWQgdHJhY2tpbmcgZm9yIHRoZSB0b3VjaC5cblxuIyMjXG5Db25zb2xpZGF0ZXMgbW91c2UgYW5kIHRvdWNoIGV2ZW50cy4gVG91Y2ggb2JqZWN0cyBwZXJzaXN0IGFjcm9zcyBhIHRvdWNoLFxuZnJvbSB0b3VjaHN0YXJ0IHVudGlsIGVuZC9jYW5jZWwuIFdoZW4gYSB0b3VjaCBzdGFydHMsIGl0IHdpbGwgdHJhdmVyc2VcbmRvd24gZnJvbSB0aGUgaW5uZXJtb3N0IHRhcmdldCwgdW50aWwgaXQgZmluZHMgYSBub2RlIHRoYXQgcmVzcG9uZHMgdG9cbm9udG91Y2hzdGFydC4gVW5sZXNzIHRoZSB0b3VjaCBpcyBleHBsaWNpdGx5IHJlZGlyZWN0ZWQsIHRoZSB0b3VjaCB3aWxsXG5jYWxsIG9udG91Y2htb3ZlIGFuZCBvbnRvdWNoZW5kIC8gb250b3VjaGNhbmNlbCBvbiB0aGUgcmVzcG9uZGVyIHdoZW4gYXBwcm9wcmlhdGUuXG5cblx0dGFnIGRyYWdnYWJsZVxuXHRcdCMgY2FsbGVkIHdoZW4gYSB0b3VjaCBzdGFydHNcblx0XHRkZWYgb250b3VjaHN0YXJ0IHRvdWNoXG5cdFx0XHRmbGFnICdkcmFnZ2luZydcblx0XHRcdHNlbGZcblx0XHRcblx0XHQjIGNhbGxlZCB3aGVuIHRvdWNoIG1vdmVzIC0gc2FtZSB0b3VjaCBvYmplY3Rcblx0XHRkZWYgb250b3VjaG1vdmUgdG91Y2hcblx0XHRcdCMgbW92ZSB0aGUgbm9kZSB3aXRoIHRvdWNoXG5cdFx0XHRjc3MgdG9wOiB0b3VjaC5keSwgbGVmdDogdG91Y2guZHhcblx0XHRcblx0XHQjIGNhbGxlZCB3aGVuIHRvdWNoIGVuZHNcblx0XHRkZWYgb250b3VjaGVuZCB0b3VjaFxuXHRcdFx0dW5mbGFnICdkcmFnZ2luZydcblxuQGluYW1lIHRvdWNoXG4jIyNcbmNsYXNzIEltYmEuVG91Y2hcblxuXHR2YXIgdG91Y2hlcyA9IFtdXG5cdHZhciBjb3VudCA9IDBcblx0dmFyIGlkZW50aWZpZXJzID0ge31cblxuXHRkZWYgc2VsZi5jb3VudFxuXHRcdGNvdW50XG5cblx0ZGVmIHNlbGYubG9va3VwIGl0ZW1cblx0XHRyZXR1cm4gaXRlbSBhbmQgKGl0ZW06X190b3VjaF9fIG9yIGlkZW50aWZpZXJzW2l0ZW06aWRlbnRpZmllcl0pXG5cblx0ZGVmIHNlbGYucmVsZWFzZSBpdGVtLHRvdWNoXG5cdFx0ZGVsZXRlIGlkZW50aWZpZXJzW2l0ZW06aWRlbnRpZmllcl1cblx0XHRkZWxldGUgaXRlbTpfX3RvdWNoX19cblx0XHRyZXR1cm5cblxuXHRkZWYgc2VsZi5vbnRvdWNoc3RhcnQgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGNvbnRpbnVlIGlmIGxvb2t1cCh0KVxuXHRcdFx0dmFyIHRvdWNoID0gaWRlbnRpZmllcnNbdDppZGVudGlmaWVyXSA9IHNlbGYubmV3KGUpICMgKGUpXG5cdFx0XHR0Ol9fdG91Y2hfXyA9IHRvdWNoXG5cdFx0XHR0b3VjaGVzLnB1c2godG91Y2gpXG5cdFx0XHRjb3VudCsrXG5cdFx0XHR0b3VjaC50b3VjaHN0YXJ0KGUsdClcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub250b3VjaG1vdmUgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGlmIHZhciB0b3VjaCA9IGxvb2t1cCh0KVxuXHRcdFx0XHR0b3VjaC50b3VjaG1vdmUoZSx0KVxuXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLm9udG91Y2hlbmQgZVxuXHRcdGZvciB0IGluIGU6Y2hhbmdlZFRvdWNoZXNcblx0XHRcdGlmIHZhciB0b3VjaCA9IGxvb2t1cCh0KVxuXHRcdFx0XHR0b3VjaC50b3VjaGVuZChlLHQpXG5cdFx0XHRcdHJlbGVhc2UodCx0b3VjaClcblx0XHRcdFx0Y291bnQtLVxuXG5cdFx0IyBlLnByZXZlbnREZWZhdWx0XG5cdFx0IyBub3QgYWx3YXlzIHN1cHBvcnRlZCFcblx0XHQjIHRvdWNoZXMgPSB0b3VjaGVzLmZpbHRlcih8fClcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub250b3VjaGNhbmNlbCBlXG5cdFx0Zm9yIHQgaW4gZTpjaGFuZ2VkVG91Y2hlc1xuXHRcdFx0aWYgdmFyIHRvdWNoID0gbG9va3VwKHQpXG5cdFx0XHRcdHRvdWNoLnRvdWNoY2FuY2VsKGUsdClcblx0XHRcdFx0cmVsZWFzZSh0LHRvdWNoKVxuXHRcdFx0XHRjb3VudC0tXG5cdFx0c2VsZlxuXG5cdGRlZiBzZWxmLm9ubW91c2Vkb3duIGVcblx0XHRzZWxmXG5cblx0ZGVmIHNlbGYub25tb3VzZW1vdmUgZVxuXHRcdHNlbGZcblxuXHRkZWYgc2VsZi5vbm1vdXNldXAgZVxuXHRcdHNlbGZcblxuXG5cdHByb3AgcGhhc2Vcblx0cHJvcCBhY3RpdmVcblx0cHJvcCBldmVudFxuXHRwcm9wIHBvaW50ZXJcblx0cHJvcCB0YXJnZXRcblx0cHJvcCBoYW5kbGVyXG5cdHByb3AgdXBkYXRlc1xuXHRwcm9wIHN1cHByZXNzXG5cdHByb3AgZGF0YVxuXHRwcm9wIGJ1YmJsZSBjaGFpbmFibGU6IHllc1xuXG5cdHByb3AgZ2VzdHVyZXNcblxuXHQjIyNcblx0XG5cblx0QGludGVybmFsXG5cdEBjb25zdHJ1Y3RvclxuXHQjIyNcblx0ZGVmIGluaXRpYWxpemUgZXZlbnQsIHBvaW50ZXJcblx0XHQjIEBuYXRpdmUgID0gZmFsc2Vcblx0XHRzZWxmLmV2ZW50ID0gZXZlbnRcblx0XHRkYXRhID0ge31cblx0XHRhY3RpdmUgPSB5ZXNcblx0XHRAYnV0dG9uID0gZXZlbnQgYW5kIGV2ZW50OmJ1dHRvbiBvciAwXG5cdFx0QHN1cHByZXNzID0gbm8gIyBkZXByZWNhdGVkXG5cdFx0QGNhcHR1cmVkID0gbm9cblx0XHRidWJibGUgPSBub1xuXHRcdHBvaW50ZXIgPSBwb2ludGVyXG5cdFx0dXBkYXRlcyA9IDBcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBjYXB0dXJlXG5cdFx0QGNhcHR1cmVkID0geWVzXG5cdFx0QGV2ZW50IGFuZCBAZXZlbnQucHJldmVudERlZmF1bHRcblx0XHRzZWxmXG5cblx0ZGVmIGlzQ2FwdHVyZWRcblx0XHQhIUBjYXB0dXJlZFxuXG5cdCMjI1xuXHRFeHRlbmQgdGhlIHRvdWNoIHdpdGggYSBwbHVnaW4gLyBnZXN0dXJlLiBcblx0QWxsIGV2ZW50cyAodG91Y2hzdGFydCxtb3ZlIGV0YykgZm9yIHRoZSB0b3VjaFxuXHR3aWxsIGJlIHRyaWdnZXJlZCBvbiB0aGUgcGx1Z2lucyBpbiB0aGUgb3JkZXIgdGhleVxuXHRhcmUgYWRkZWQuXG5cdCMjI1xuXHRkZWYgZXh0ZW5kIHBsdWdpblxuXHRcdCMgY29uc29sZS5sb2cgXCJhZGRlZCBnZXN0dXJlISEhXCJcblx0XHRAZ2VzdHVyZXMgfHw9IFtdXG5cdFx0QGdlc3R1cmVzLnB1c2gocGx1Z2luKVxuXHRcdHNlbGZcblxuXHQjIyNcblx0UmVkaXJlY3QgdG91Y2ggdG8gc3BlY2lmaWVkIHRhcmdldC4gb250b3VjaHN0YXJ0IHdpbGwgYWx3YXlzIGJlXG5cdGNhbGxlZCBvbiB0aGUgbmV3IHRhcmdldC5cblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHJlZGlyZWN0IHRhcmdldFxuXHRcdEByZWRpcmVjdCA9IHRhcmdldFxuXHRcdHNlbGZcblxuXHQjIyNcblx0U3VwcHJlc3MgdGhlIGRlZmF1bHQgYmVoYXZpb3VyLiBXaWxsIGNhbGwgcHJldmVudERlZmF1bHQgZm9yXG5cdGFsbCBuYXRpdmUgZXZlbnRzIHRoYXQgYXJlIHBhcnQgb2YgdGhlIHRvdWNoLlxuXHQjIyNcblx0ZGVmIHN1cHByZXNzXG5cdFx0IyBjb2xsaXNpb24gd2l0aCB0aGUgc3VwcHJlc3MgcHJvcGVydHlcblx0XHRAYWN0aXZlID0gbm9cblx0XHRzZWxmXG5cblx0ZGVmIHN1cHByZXNzPSB2YWx1ZVxuXHRcdGNvbnNvbGUud2FybiAnSW1iYS5Ub3VjaCNzdXBwcmVzcz0gaXMgZGVwcmVjYXRlZCdcblx0XHRAc3VwcmVzcyA9IHZhbHVlXG5cdFx0c2VsZlxuXG5cdGRlZiB0b3VjaHN0YXJ0IGUsdFxuXHRcdEBldmVudCA9IGVcblx0XHRAdG91Y2ggPSB0XG5cdFx0QGJ1dHRvbiA9IDBcblx0XHRAeCA9IHQ6Y2xpZW50WFxuXHRcdEB5ID0gdDpjbGllbnRZXG5cdFx0YmVnYW5cblx0XHRlLnByZXZlbnREZWZhdWx0IGlmIGUgYW5kIGlzQ2FwdHVyZWRcblx0XHRzZWxmXG5cblx0ZGVmIHRvdWNobW92ZSBlLHRcblx0XHRAZXZlbnQgPSBlXG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdHVwZGF0ZVxuXHRcdGUucHJldmVudERlZmF1bHQgaWYgZSBhbmQgaXNDYXB0dXJlZFxuXHRcdHNlbGZcblxuXHRkZWYgdG91Y2hlbmQgZSx0XG5cdFx0QGV2ZW50ID0gZVxuXHRcdEB4ID0gdDpjbGllbnRYXG5cdFx0QHkgPSB0OmNsaWVudFlcblx0XHRlbmRlZFxuXG5cdFx0bGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wID0gZTp0aW1lU3RhbXBcblxuXHRcdGlmIEBtYXhkciA8IDIwXG5cdFx0XHR2YXIgdGFwID0gSW1iYS5FdmVudC5uZXcoZSlcblx0XHRcdHRhcC50eXBlID0gJ3RhcCdcblx0XHRcdHRhcC5wcm9jZXNzXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0IGlmIHRhcC5AcmVzcG9uZGVyXHRcblxuXHRcdGlmIGUgYW5kIGlzQ2FwdHVyZWRcblx0XHRcdGUucHJldmVudERlZmF1bHRcblxuXHRcdHNlbGZcblxuXHRkZWYgdG91Y2hjYW5jZWwgZSx0XG5cdFx0Y2FuY2VsXG5cblx0ZGVmIG1vdXNlZG93biBlLHRcblx0XHRAZXZlbnQgPSBlXG5cdFx0QGJ1dHRvbiA9IGU6YnV0dG9uXG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdGJlZ2FuXG5cblx0XHRAbW91c2Vtb3ZlID0gKHxlfCBtb3VzZW1vdmUoZSxlKSApXG5cdFx0ZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsQG1vdXNlbW92ZSx5ZXMpXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3VzZW1vdmUgZSx0XG5cdFx0QHggPSB0OmNsaWVudFhcblx0XHRAeSA9IHQ6Y2xpZW50WVxuXHRcdEBldmVudCA9IGVcblx0XHRlLnByZXZlbnREZWZhdWx0IGlmIGlzQ2FwdHVyZWRcblx0XHR1cGRhdGVcblx0XHRtb3ZlXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3VzZXVwIGUsdFxuXHRcdEB4ID0gdDpjbGllbnRYXG5cdFx0QHkgPSB0OmNsaWVudFlcblx0XHRlbmRlZFxuXHRcdGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLEBtb3VzZW1vdmUseWVzKVxuXHRcdEBtb3VzZW1vdmUgPSBudWxsXG5cdFx0c2VsZlxuXG5cdGRlZiBpZGxlXG5cdFx0dXBkYXRlXG5cblx0ZGVmIGJlZ2FuXG5cdFx0QG1heGRyID0gQGRyID0gMFxuXHRcdEB4MCA9IEB4XG5cdFx0QHkwID0gQHlcblxuXHRcdHZhciBkb20gPSBldmVudDp0YXJnZXRcblx0XHR2YXIgbm9kZSA9IG51bGxcblxuXHRcdEBzb3VyY2VUYXJnZXQgPSBkb20gYW5kIHRhZyhkb20pXG5cblx0XHR3aGlsZSBkb21cblx0XHRcdG5vZGUgPSB0YWcoZG9tKVxuXHRcdFx0aWYgbm9kZSAmJiBub2RlOm9udG91Y2hzdGFydFxuXHRcdFx0XHRAYnViYmxlID0gbm9cblx0XHRcdFx0dGFyZ2V0ID0gbm9kZVxuXHRcdFx0XHR0YXJnZXQub250b3VjaHN0YXJ0KHNlbGYpXG5cdFx0XHRcdGJyZWFrIHVubGVzcyBAYnViYmxlXG5cdFx0XHRkb20gPSBkb206cGFyZW50Tm9kZVxuXG5cdFx0QHVwZGF0ZXMrK1xuXHRcdHNlbGZcblxuXHRkZWYgdXBkYXRlXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdHZhciBkciA9IE1hdGguc3FydChkeCpkeCArIGR5KmR5KVxuXHRcdEBtYXhkciA9IGRyIGlmIGRyID4gQGRyXG5cdFx0QGRyID0gZHJcblxuXHRcdCMgY2F0Y2hpbmcgYSB0b3VjaC1yZWRpcmVjdD8hP1xuXHRcdGlmIEByZWRpcmVjdFxuXHRcdFx0aWYgQHRhcmdldCBhbmQgQHRhcmdldDpvbnRvdWNoY2FuY2VsXG5cdFx0XHRcdEB0YXJnZXQub250b3VjaGNhbmNlbChzZWxmKVxuXHRcdFx0dGFyZ2V0ID0gQHJlZGlyZWN0XG5cdFx0XHRAcmVkaXJlY3QgPSBudWxsXG5cdFx0XHR0YXJnZXQub250b3VjaHN0YXJ0KHNlbGYpIGlmIHRhcmdldDpvbnRvdWNoc3RhcnRcblxuXG5cdFx0QHVwZGF0ZXMrK1xuXHRcdGlmIEBnZXN0dXJlc1xuXHRcdFx0Zy5vbnRvdWNodXBkYXRlKHNlbGYpIGZvciBnIGluIEBnZXN0dXJlc1xuXG5cdFx0dGFyZ2V0Py5vbnRvdWNodXBkYXRlKHNlbGYpXG5cdFx0c2VsZlxuXG5cdGRlZiBtb3ZlXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdGlmIEBnZXN0dXJlc1xuXHRcdFx0Zm9yIGcgaW4gQGdlc3R1cmVzXG5cdFx0XHRcdGcub250b3VjaG1vdmUoc2VsZixAZXZlbnQpIGlmIGc6b250b3VjaG1vdmVcblxuXHRcdHRhcmdldD8ub250b3VjaG1vdmUoc2VsZixAZXZlbnQpXG5cdFx0c2VsZlxuXG5cdGRlZiBlbmRlZFxuXHRcdHJldHVybiBzZWxmIHVubGVzcyBAYWN0aXZlXG5cblx0XHRAdXBkYXRlcysrXG5cblx0XHRpZiBAZ2VzdHVyZXNcblx0XHRcdGcub250b3VjaGVuZChzZWxmKSBmb3IgZyBpbiBAZ2VzdHVyZXNcblxuXHRcdHRhcmdldD8ub250b3VjaGVuZChzZWxmKVxuXG5cdFx0c2VsZlxuXG5cdGRlZiBjYW5jZWxcblx0XHR1bmxlc3MgQGNhbmNlbGxlZFxuXHRcdFx0QGNhbmNlbGxlZCA9IHllc1xuXHRcdFx0Y2FuY2VsbGVkXG5cdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJyxAbW91c2Vtb3ZlLHllcykgaWYgQG1vdXNlbW92ZVxuXHRcdHNlbGZcblxuXHRkZWYgY2FuY2VsbGVkXG5cdFx0cmV0dXJuIHNlbGYgdW5sZXNzIEBhY3RpdmVcblxuXHRcdEBjYW5jZWxsZWQgPSB5ZXNcblx0XHRAdXBkYXRlcysrXG5cblx0XHRpZiBAZ2VzdHVyZXNcblx0XHRcdGZvciBnIGluIEBnZXN0dXJlc1xuXHRcdFx0XHRnLm9udG91Y2hjYW5jZWwoc2VsZikgaWYgZzpvbnRvdWNoY2FuY2VsXG5cblx0XHR0YXJnZXQ/Lm9udG91Y2hjYW5jZWwoc2VsZilcblx0XHRzZWxmXG5cblx0IyMjXG5cdFRoZSBhYnNvbHV0ZSBkaXN0YW5jZSB0aGUgdG91Y2ggaGFzIG1vdmVkIGZyb20gc3RhcnRpbmcgcG9zaXRpb24gXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkciBkbyBAZHJcblxuXHQjIyNcblx0VGhlIGRpc3RhbmNlIHRoZSB0b3VjaCBoYXMgbW92ZWQgaG9yaXpvbnRhbGx5XG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkeCBkbyBAeCAtIEB4MFxuXG5cdCMjI1xuXHRUaGUgZGlzdGFuY2UgdGhlIHRvdWNoIGhhcyBtb3ZlZCB2ZXJ0aWNhbGx5XG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiBkeSBkbyBAeSAtIEB5MFxuXG5cdCMjI1xuXHRJbml0aWFsIGhvcml6b250YWwgcG9zaXRpb24gb2YgdG91Y2hcblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHgwIGRvIEB4MFxuXG5cdCMjI1xuXHRJbml0aWFsIHZlcnRpY2FsIHBvc2l0aW9uIG9mIHRvdWNoXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiB5MCBkbyBAeTBcblxuXHQjIyNcblx0SG9yaXpvbnRhbCBwb3NpdGlvbiBvZiB0b3VjaFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgeCBkbyBAeFxuXG5cdCMjI1xuXHRWZXJ0aWNhbCBwb3NpdGlvbiBvZiB0b3VjaFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgeSBkbyBAeVxuXG5cdCMjI1xuXHRIb3Jpem9udGFsIHBvc2l0aW9uIG9mIHRvdWNoIHJlbGF0aXZlIHRvIHRhcmdldFxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgdHggZG9cblx0XHRAdGFyZ2V0Qm94IHx8PSBAdGFyZ2V0LmRvbS5nZXRCb3VuZGluZ0NsaWVudFJlY3Rcblx0XHRAeCAtIEB0YXJnZXRCb3g6bGVmdFxuXG5cdCMjI1xuXHRWZXJ0aWNhbCBwb3NpdGlvbiBvZiB0b3VjaCByZWxhdGl2ZSB0byB0YXJnZXRcblx0QHJldHVybiB7TnVtYmVyfVxuXHQjIyNcblx0ZGVmIHR5XG5cdFx0QHRhcmdldEJveCB8fD0gQHRhcmdldC5kb20uZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG5cdFx0QHkgLSBAdGFyZ2V0Qm94OnRvcFxuXG5cdCMjI1xuXHRCdXR0b24gcHJlc3NlZCBpbiB0aGlzIHRvdWNoLiBOYXRpdmUgdG91Y2hlcyBkZWZhdWx0cyB0byBsZWZ0LWNsaWNrICgwKVxuXHRAcmV0dXJuIHtOdW1iZXJ9XG5cdCMjI1xuXHRkZWYgYnV0dG9uIGRvIEBidXR0b24gIyBAcG9pbnRlciA/IEBwb2ludGVyLmJ1dHRvbiA6IDBcblxuXHRkZWYgc291cmNlVGFyZ2V0XG5cdFx0QHNvdXJjZVRhcmdldFxuXG5cbmNsYXNzIEltYmEuVG91Y2hHZXN0dXJlXG5cblx0cHJvcCBhY3RpdmUgZGVmYXVsdDogbm9cblxuXHRkZWYgb250b3VjaHN0YXJ0IGVcblx0XHRzZWxmXG5cblx0ZGVmIG9udG91Y2h1cGRhdGUgZVxuXHRcdHNlbGZcblxuXHRkZWYgb250b3VjaGVuZCBlXG5cdFx0c2VsZlxuXG5cbiMgQSBUb3VjaC1ldmVudCBpcyBjcmVhdGVkIG9uIG1vdXNlZG93biAoYWx3YXlzKVxuIyBhbmQgd2hpbGUgaXQgZXhpc3RzLCBtb3VzZW1vdmUgYW5kIG1vdXNldXAgd2lsbFxuIyBiZSBkZWxlZ2F0ZWQgdG8gdGhpcyBhY3RpdmUgZXZlbnQuXG5JbWJhLlBPSU5URVIgPSBJbWJhLlBvaW50ZXIubmV3XG5JbWJhLlBPSU5URVJTID0gW0ltYmEuUE9JTlRFUl1cblxuXG4jIHJlZ3VsYXIgZXZlbnQgc3R1ZmZcbkltYmEuS0VZTUFQID0ge1xuXHRcIjhcIjogJ2JhY2tzcGFjZSdcblx0XCI5XCI6ICd0YWInXG5cdFwiMTNcIjogJ2VudGVyJ1xuXHRcIjE2XCI6ICdzaGlmdCdcblx0XCIxN1wiOiAnY3RybCdcblx0XCIxOFwiOiAnYWx0J1xuXHRcIjE5XCI6ICdicmVhaydcblx0XCIyMFwiOiAnY2Fwcydcblx0XCIyN1wiOiAnZXNjJ1xuXHRcIjMyXCI6ICdzcGFjZSdcblx0XCIzNVwiOiAnZW5kJ1xuXHRcIjM2XCI6ICdob21lJ1xuXHRcIjM3XCI6ICdsYXJyJ1xuXHRcIjM4XCI6ICd1YXJyJ1xuXHRcIjM5XCI6ICdyYXJyJ1xuXHRcIjQwXCI6ICdkYXJyJ1xuXHRcIjQ1XCI6ICdpbnNlcnQnXG5cdFwiNDZcIjogJ2RlbGV0ZSdcblx0XCIxMDdcIjogJ3BsdXMnXG5cdFwiMTA2XCI6ICdtdWx0J1xuXHRcIjkxXCI6ICdtZXRhJ1xufVxuXG5JbWJhLkNIQVJNQVAgPSB7XG5cdFwiJVwiOiAnbW9kdWxvJ1xuXHRcIipcIjogJ211bHRpcGx5J1xuXHRcIitcIjogJ2FkZCdcblx0XCItXCI6ICdzdWInXG5cdFwiL1wiOiAnZGl2aWRlJ1xuXHRcIi5cIjogJ2RvdCdcbn1cblxuIyMjXG5JbWJhIGhhbmRsZXMgYWxsIGV2ZW50cyBpbiB0aGUgZG9tIHRocm91Z2ggYSBzaW5nbGUgbWFuYWdlcixcbmxpc3RlbmluZyBhdCB0aGUgcm9vdCBvZiB5b3VyIGRvY3VtZW50LiBJZiBJbWJhIGZpbmRzIGEgdGFnXG50aGF0IGxpc3RlbnMgdG8gYSBjZXJ0YWluIGV2ZW50LCB0aGUgZXZlbnQgd2lsbCBiZSB3cmFwcGVkIFxuaW4gYW4gYEltYmEuRXZlbnRgLCB3aGljaCBub3JtYWxpemVzIHNvbWUgb2YgdGhlIHF1aXJrcyBhbmQgXG5icm93c2VyIGRpZmZlcmVuY2VzLlxuXG5AaW5hbWUgZXZlbnRcbiMjI1xuY2xhc3MgSW1iYS5FdmVudFxuXG5cdCMjIyByZWZlcmVuY2UgdG8gdGhlIG5hdGl2ZSBldmVudCAjIyNcblx0cHJvcCBldmVudFxuXG5cdCMjIyByZWZlcmVuY2UgdG8gdGhlIG5hdGl2ZSBldmVudCAjIyNcblx0cHJvcCBwcmVmaXhcblxuXHRwcm9wIGRhdGFcblxuXHQjIyNcblx0c2hvdWxkIHJlbW92ZSB0aGlzIGFsbHRvZ2V0aGVyP1xuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0cHJvcCBzb3VyY2VcblxuXHQjIyMgQSB7Qm9vbGVhbn0gaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBldmVudCBidWJibGVzIHVwIG9yIG5vdCAjIyNcblx0cHJvcCBidWJibGUgdHlwZTogQm9vbGVhbiwgY2hhaW5hYmxlOiB5ZXNcblxuXHRkZWYgc2VsZi53cmFwIGVcblx0XHRzZWxmLm5ldyhlKVxuXHRcblx0ZGVmIGluaXRpYWxpemUgZVxuXHRcdGV2ZW50ID0gZVxuXHRcdGJ1YmJsZSA9IHllc1xuXG5cdGRlZiB0eXBlPSB0eXBlXG5cdFx0QHR5cGUgPSB0eXBlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRAcmV0dXJuIHtTdHJpbmd9IFRoZSBuYW1lIG9mIHRoZSBldmVudCAoY2FzZS1pbnNlbnNpdGl2ZSlcblx0IyMjXG5cdGRlZiB0eXBlXG5cdFx0QHR5cGUgfHwgZXZlbnQ6dHlwZVxuXG5cdGRlZiBuYW1lXG5cdFx0QG5hbWUgfHw9IHR5cGUudG9Mb3dlckNhc2UucmVwbGFjZSgvXFw6L2csJycpXG5cblx0IyBtaW1jIGdldHNldFxuXHRkZWYgYnViYmxlIHZcblx0XHRpZiB2ICE9IHVuZGVmaW5lZFxuXHRcdFx0c2VsZi5idWJibGUgPSB2XG5cdFx0XHRyZXR1cm4gc2VsZlxuXHRcdHJldHVybiBAYnViYmxlXG5cblx0IyMjXG5cdFByZXZlbnRzIGZ1cnRoZXIgcHJvcGFnYXRpb24gb2YgdGhlIGN1cnJlbnQgZXZlbnQuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgaGFsdFxuXHRcdGJ1YmJsZSA9IG5vXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRDYW5jZWwgdGhlIGV2ZW50IChpZiBjYW5jZWxhYmxlKS4gSW4gdGhlIGNhc2Ugb2YgbmF0aXZlIGV2ZW50cyBpdFxuXHR3aWxsIGNhbGwgYHByZXZlbnREZWZhdWx0YCBvbiB0aGUgd3JhcHBlZCBldmVudCBvYmplY3QuXG5cdEByZXR1cm4ge3NlbGZ9XG5cdCMjI1xuXHRkZWYgY2FuY2VsXG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQgaWYgZXZlbnQ6cHJldmVudERlZmF1bHRcblx0XHRAY2FuY2VsID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBzaWxlbmNlXG5cdFx0QHNpbGVuY2VkID0geWVzXG5cdFx0c2VsZlxuXG5cdGRlZiBpc1NpbGVuY2VkXG5cdFx0ISFAc2lsZW5jZWRcblxuXHQjIyNcblx0SW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IGV2ZW50LmNhbmNlbCBoYXMgYmVlbiBjYWxsZWQuXG5cblx0QHJldHVybiB7Qm9vbGVhbn1cblx0IyMjXG5cdGRlZiBpc1ByZXZlbnRlZFxuXHRcdGV2ZW50IGFuZCBldmVudDpkZWZhdWx0UHJldmVudGVkIG9yIEBjYW5jZWxcblxuXHQjIyNcblx0QSByZWZlcmVuY2UgdG8gdGhlIGluaXRpYWwgdGFyZ2V0IG9mIHRoZSBldmVudC5cblx0IyMjXG5cdGRlZiB0YXJnZXRcblx0XHR0YWcoZXZlbnQ6X3RhcmdldCBvciBldmVudDp0YXJnZXQpXG5cblx0IyMjXG5cdEEgcmVmZXJlbmNlIHRvIHRoZSBvYmplY3QgcmVzcG9uZGluZyB0byB0aGUgZXZlbnQuXG5cdCMjI1xuXHRkZWYgcmVzcG9uZGVyXG5cdFx0QHJlc3BvbmRlclxuXG5cdCMjI1xuXHRSZWRpcmVjdCB0aGUgZXZlbnQgdG8gbmV3IHRhcmdldFxuXHQjIyNcblx0ZGVmIHJlZGlyZWN0IG5vZGVcblx0XHRAcmVkaXJlY3QgPSBub2RlXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRHZXQgdGhlIG5vcm1hbGl6ZWQgY2hhcmFjdGVyIGZvciBLZXlib2FyZEV2ZW50L1RleHRFdmVudFxuXHRAcmV0dXJuIHtTdHJpbmd9XG5cdCMjI1xuXHRkZWYga2V5Y2hhclxuXHRcdGlmIGV2ZW50IGlzYSBLZXlib2FyZEV2ZW50XG5cdFx0XHR2YXIga2kgPSBldmVudDprZXlJZGVudGlmaWVyXG5cdFx0XHR2YXIgc3ltID0gSW1iYS5LRVlNQVBbZXZlbnQ6a2V5Q29kZV1cblxuXHRcdFx0aWYgIXN5bSBhbmQga2kuc3Vic3RyKDAsMikgPT0gXCJVK1wiXG5cdFx0XHRcdHN5bSA9IFN0cmluZy5mcm9tQ2hhckNvZGUocGFyc2VJbnQoa2kuc3Vic3RyKDIpLCAxNikpXG5cdFx0XHRyZXR1cm4gc3ltXG5cblx0XHRlbGlmIGV2ZW50IGlzYSAod2luZG93LlRleHRFdmVudCBvciB3aW5kb3cuSW5wdXRFdmVudClcblx0XHRcdHJldHVybiBldmVudDpkYXRhXG5cblx0XHRyZXR1cm4gbnVsbFxuXG5cdCMjI1xuXHRAZGVwcmVjYXRlZFxuXHQjIyNcblx0ZGVmIGtleWNvbWJvXG5cdFx0cmV0dXJuIHVubGVzcyB2YXIgc3ltID0ga2V5Y2hhclxuXHRcdHN5bSA9IEltYmEuQ0hBUk1BUFtzeW1dIG9yIHN5bVxuXHRcdHZhciBjb21ibyA9IFtdLCBlID0gZXZlbnRcblx0XHRjb21iby5wdXNoKDpjdHJsKSBpZiBlOmN0cmxLZXlcblx0XHRjb21iby5wdXNoKDpzaGlmdCkgaWYgZTpzaGlmdEtleVxuXHRcdGNvbWJvLnB1c2goOmFsdCkgaWYgZTphbHRLZXlcblx0XHRjb21iby5wdXNoKDpjbWQpIGlmIGU6bWV0YUtleVxuXHRcdGNvbWJvLnB1c2goc3ltKVxuXHRcdGNvbWJvLmpvaW4oXCJfXCIpLnRvTG93ZXJDYXNlXG5cblxuXHRkZWYgcHJvY2Vzc1xuXHRcdHZhciBtZXRoID0gXCJvbntAcHJlZml4IG9yICcnfXtuYW1lfVwiXG5cdFx0dmFyIGFyZ3MgPSBudWxsXG5cdFx0dmFyIGRvbXRhcmdldCA9IGV2ZW50Ol90YXJnZXQgb3IgZXZlbnQ6dGFyZ2V0XHRcdFxuXHRcdCMgdmFyIG5vZGUgPSA8e2RvbXRhcmdldDpfcmVzcG9uZGVyIG9yIGRvbXRhcmdldH0+XG5cdFx0IyBuZWVkIHRvIGNsZWFuIHVwIGFuZCBkb2N1bWVudCB0aGlzIGJlaGF2aW91clxuXG5cdFx0dmFyIGRvbW5vZGUgPSBkb210YXJnZXQ6X3Jlc3BvbmRlciBvciBkb210YXJnZXRcblx0XHQjIEB0b2RvIG5lZWQgdG8gc3RvcCBpbmZpbml0ZSByZWRpcmVjdC1ydWxlcyBoZXJlXG5cblx0XHR3aGlsZSBkb21ub2RlXG5cdFx0XHRAcmVkaXJlY3QgPSBudWxsXG5cdFx0XHRpZiB2YXIgbm9kZSA9IHRhZyhkb21ub2RlKSAjIG5vdCBvbmx5IHRhZyBcblxuXHRcdFx0XHRpZiBub2RlW21ldGhdIGlzYSBTdHJpbmdcblx0XHRcdFx0XHQjIHNob3VsZCByZW1lbWJlciB0aGUgcmVjZWl2ZXIgb2YgdGhlIGV2ZW50XG5cdFx0XHRcdFx0bWV0aCA9IG5vZGVbbWV0aF1cblx0XHRcdFx0XHRjb250aW51ZSAjIHNob3VsZCBub3QgY29udGludWU/XG5cblx0XHRcdFx0aWYgbm9kZVttZXRoXSBpc2EgQXJyYXlcblx0XHRcdFx0XHRhcmdzID0gbm9kZVttZXRoXS5jb25jYXQobm9kZSlcblx0XHRcdFx0XHRtZXRoID0gYXJncy5zaGlmdFxuXHRcdFx0XHRcdGNvbnRpbnVlICMgc2hvdWxkIG5vdCBjb250aW51ZT9cblxuXHRcdFx0XHRpZiBub2RlW21ldGhdIGlzYSBGdW5jdGlvblxuXHRcdFx0XHRcdEByZXNwb25kZXIgfHw9IG5vZGVcblx0XHRcdFx0XHQjIHNob3VsZCBhdXRvc3RvcCBidWJibGUgaGVyZT9cblx0XHRcdFx0XHRhcmdzID8gbm9kZVttZXRoXS5hcHBseShub2RlLGFyZ3MpIDogbm9kZVttZXRoXShzZWxmLGRhdGEpXG5cdFx0XHRcdFx0XG5cdFx0XHQjIGFkZCBub2RlLm5leHRFdmVudFJlc3BvbmRlciBhcyBhIHNlcGFyYXRlIG1ldGhvZCBoZXJlP1xuXHRcdFx0dW5sZXNzIGJ1YmJsZSBhbmQgZG9tbm9kZSA9IChAcmVkaXJlY3Qgb3IgKG5vZGUgPyBub2RlLnBhcmVudCA6IGRvbW5vZGU6cGFyZW50Tm9kZSkpXG5cdFx0XHRcdGJyZWFrXG5cblx0XHRwcm9jZXNzZWRcblx0XHRyZXR1cm4gc2VsZlxuXG5cblx0ZGVmIHByb2Nlc3NlZFxuXHRcdEltYmEuZW1pdChJbWJhLCdldmVudCcsW3NlbGZdKSB1bmxlc3MgQHNpbGVuY2VkXG5cdFx0c2VsZlxuXG5cdCMjI1xuXHRSZXR1cm4gdGhlIHgvbGVmdCBjb29yZGluYXRlIG9mIHRoZSBtb3VzZSAvIHBvaW50ZXIgZm9yIHRoaXMgZXZlbnRcblx0QHJldHVybiB7TnVtYmVyfSB4IGNvb3JkaW5hdGUgb2YgbW91c2UgLyBwb2ludGVyIGZvciBldmVudFxuXHQjIyNcblx0ZGVmIHggZG8gZXZlbnQ6eFxuXG5cdCMjI1xuXHRSZXR1cm4gdGhlIHkvdG9wIGNvb3JkaW5hdGUgb2YgdGhlIG1vdXNlIC8gcG9pbnRlciBmb3IgdGhpcyBldmVudFxuXHRAcmV0dXJuIHtOdW1iZXJ9IHkgY29vcmRpbmF0ZSBvZiBtb3VzZSAvIHBvaW50ZXIgZm9yIGV2ZW50XG5cdCMjI1xuXHRkZWYgeSBkbyBldmVudDp5XG5cblx0IyMjXG5cdFJldHVybnMgYSBOdW1iZXIgcmVwcmVzZW50aW5nIGEgc3lzdGVtIGFuZCBpbXBsZW1lbnRhdGlvblxuXHRkZXBlbmRlbnQgbnVtZXJpYyBjb2RlIGlkZW50aWZ5aW5nIHRoZSB1bm1vZGlmaWVkIHZhbHVlIG9mIHRoZVxuXHRwcmVzc2VkIGtleTsgdGhpcyBpcyB1c3VhbGx5IHRoZSBzYW1lIGFzIGtleUNvZGUuXG5cblx0Rm9yIG1vdXNlLWV2ZW50cywgdGhlIHJldHVybmVkIHZhbHVlIGluZGljYXRlcyB3aGljaCBidXR0b24gd2FzXG5cdHByZXNzZWQgb24gdGhlIG1vdXNlIHRvIHRyaWdnZXIgdGhlIGV2ZW50LlxuXG5cdEByZXR1cm4ge051bWJlcn1cblx0IyMjXG5cdGRlZiB3aGljaCBkbyBldmVudDp3aGljaFxuXG5cbiMjI1xuXG5NYW5hZ2VyIGZvciBsaXN0ZW5pbmcgdG8gYW5kIGRlbGVnYXRpbmcgZXZlbnRzIGluIEltYmEuIEEgc2luZ2xlIGluc3RhbmNlXG5pcyBhbHdheXMgY3JlYXRlZCBieSBJbWJhIChhcyBgSW1iYS5FdmVudHNgKSwgd2hpY2ggaGFuZGxlcyBhbmQgZGVsZWdhdGVzIGFsbFxuZXZlbnRzIGF0IHRoZSB2ZXJ5IHJvb3Qgb2YgdGhlIGRvY3VtZW50LiBJbWJhIGRvZXMgbm90IGNhcHR1cmUgYWxsIGV2ZW50c1xuYnkgZGVmYXVsdCwgc28gaWYgeW91IHdhbnQgdG8gbWFrZSBzdXJlIGV4b3RpYyBvciBjdXN0b20gRE9NRXZlbnRzIGFyZSBkZWxlZ2F0ZWRcbmluIEltYmEgeW91IHdpbGwgbmVlZCB0byByZWdpc3RlciB0aGVtIGluIGBJbWJhLkV2ZW50cy5yZWdpc3RlcihteUN1c3RvbUV2ZW50TmFtZSlgXG5cbkBpbmFtZSBtYW5hZ2VyXG5cbiMjI1xuY2xhc3MgSW1iYS5FdmVudE1hbmFnZXJcblxuXHRwcm9wIHJvb3Rcblx0cHJvcCBjb3VudFxuXHRwcm9wIGVuYWJsZWQgZGVmYXVsdDogbm8sIHdhdGNoOiB5ZXNcblx0cHJvcCBsaXN0ZW5lcnNcblx0cHJvcCBkZWxlZ2F0b3JzXG5cdHByb3AgZGVsZWdhdG9yXG5cblx0ZGVmIGVuYWJsZWQtZGlkLXNldCBib29sXG5cdFx0Ym9vbCA/IG9uZW5hYmxlIDogb25kaXNhYmxlXG5cdFx0c2VsZlxuXG5cdGRlZiBpbml0aWFsaXplIG5vZGUsIGV2ZW50czogW11cblx0XHRyb290ID0gbm9kZVxuXHRcdGNvdW50ID0gMFxuXHRcdGxpc3RlbmVycyA9IFtdXG5cdFx0ZGVsZWdhdG9ycyA9IHt9XG5cdFx0ZGVsZWdhdG9yID0gZG8gfGV8IFxuXHRcdFx0IyBjb25zb2xlLmxvZyBcImRlbGVnYXRpbmcgZXZlbnQ/ISB7ZX1cIlxuXHRcdFx0ZGVsZWdhdGUoZSlcblx0XHRcdHJldHVybiB0cnVlXG5cblx0XHRmb3IgZXZlbnQgaW4gZXZlbnRzXG5cdFx0XHRyZWdpc3RlcihldmVudClcblxuXHRcdHJldHVybiBzZWxmXG5cblx0IyMjXG5cblx0VGVsbCB0aGUgY3VycmVudCBFdmVudE1hbmFnZXIgdG8gaW50ZXJjZXB0IGFuZCBoYW5kbGUgZXZlbnQgb2YgYSBjZXJ0YWluIG5hbWUuXG5cdEJ5IGRlZmF1bHQsIEltYmEuRXZlbnRzIHdpbGwgcmVnaXN0ZXIgaW50ZXJjZXB0b3JzIGZvcjogKmtleWRvd24qLCAqa2V5dXAqLCBcblx0KmtleXByZXNzKiwgKnRleHRJbnB1dCosICppbnB1dCosICpjaGFuZ2UqLCAqc3VibWl0KiwgKmZvY3VzaW4qLCAqZm9jdXNvdXQqLCBcblx0KmJsdXIqLCAqY29udGV4dG1lbnUqLCAqZGJsY2xpY2sqLCAqbW91c2V3aGVlbCosICp3aGVlbCpcblxuXHQjIyNcblx0ZGVmIHJlZ2lzdGVyIG5hbWUsIGhhbmRsZXIgPSB0cnVlXG5cdFx0aWYgbmFtZSBpc2EgQXJyYXlcblx0XHRcdHJlZ2lzdGVyKHYsaGFuZGxlcikgZm9yIHYgaW4gbmFtZVxuXHRcdFx0cmV0dXJuIHNlbGZcblxuXHRcdHJldHVybiBzZWxmIGlmIGRlbGVnYXRvcnNbbmFtZV1cblx0XHQjIGNvbnNvbGUubG9nKFwicmVnaXN0ZXIgZm9yIGV2ZW50IHtuYW1lfVwiKVxuXHRcdHZhciBmbiA9IGRlbGVnYXRvcnNbbmFtZV0gPSBoYW5kbGVyIGlzYSBGdW5jdGlvbiA/IGhhbmRsZXIgOiBkZWxlZ2F0b3Jcblx0XHRyb290LmFkZEV2ZW50TGlzdGVuZXIobmFtZSxmbix5ZXMpIGlmIGVuYWJsZWRcblxuXHRkZWYgbGlzdGVuIG5hbWUsIGhhbmRsZXIsIGNhcHR1cmUgPSB5ZXNcblx0XHRsaXN0ZW5lcnMucHVzaChbbmFtZSxoYW5kbGVyLGNhcHR1cmVdKVxuXHRcdHJvb3QuYWRkRXZlbnRMaXN0ZW5lcihuYW1lLGhhbmRsZXIsY2FwdHVyZSkgaWYgZW5hYmxlZFxuXHRcdHNlbGZcblxuXHRkZWYgZGVsZWdhdGUgZVxuXHRcdGNvdW50ICs9IDFcblx0XHR2YXIgZXZlbnQgPSBJbWJhLkV2ZW50LndyYXAoZSlcblx0XHRldmVudC5wcm9jZXNzXG5cdFx0c2VsZlxuXG5cdGRlZiBjcmVhdGUgdHlwZSwgdGFyZ2V0LCBkYXRhOiBudWxsLCBzb3VyY2U6IG51bGxcblx0XHR2YXIgZXZlbnQgPSBJbWJhLkV2ZW50LndyYXAgdHlwZTogdHlwZSwgdGFyZ2V0OiB0YXJnZXRcblx0XHRldmVudC5kYXRhID0gZGF0YSBpZiBkYXRhXG5cdFx0ZXZlbnQuc291cmNlID0gc291cmNlIGlmIHNvdXJjZVxuXHRcdGV2ZW50XG5cblx0IyB1c2UgY3JlYXRlIGluc3RlYWQ/XG5cdGRlZiB0cmlnZ2VyXG5cdFx0Y3JlYXRlKCphcmd1bWVudHMpLnByb2Nlc3NcblxuXHRkZWYgb25lbmFibGVcblx0XHRmb3Igb3duIG5hbWUsaGFuZGxlciBvZiBkZWxlZ2F0b3JzXG5cdFx0XHRyb290LmFkZEV2ZW50TGlzdGVuZXIobmFtZSxoYW5kbGVyLHllcylcblxuXHRcdGZvciBpdGVtIGluIGxpc3RlbmVyc1xuXHRcdFx0cm9vdC5hZGRFdmVudExpc3RlbmVyKGl0ZW1bMF0saXRlbVsxXSxpdGVtWzJdKVxuXHRcdHNlbGZcblxuXHRkZWYgb25kaXNhYmxlXG5cdFx0Zm9yIG93biBuYW1lLGhhbmRsZXIgb2YgZGVsZWdhdG9yc1xuXHRcdFx0cm9vdC5yZW1vdmVFdmVudExpc3RlbmVyKG5hbWUsaGFuZGxlcix5ZXMpXG5cblx0XHRmb3IgaXRlbSBpbiBsaXN0ZW5lcnNcblx0XHRcdHJvb3QucmVtb3ZlRXZlbnRMaXN0ZW5lcihpdGVtWzBdLGl0ZW1bMV0saXRlbVsyXSlcblx0XHRzZWxmXG5cdFx0XG5cbkVEID0gSW1iYS5FdmVudHMgPSBJbWJhLkV2ZW50TWFuYWdlci5uZXcoZG9jdW1lbnQsIGV2ZW50czogW1xuXHQ6a2V5ZG93biw6a2V5dXAsOmtleXByZXNzLDp0ZXh0SW5wdXQsOmlucHV0LDpjaGFuZ2UsOnN1Ym1pdCxcblx0OmZvY3VzaW4sOmZvY3Vzb3V0LDpibHVyLDpjb250ZXh0bWVudSw6ZGJsY2xpY2ssXG5cdDptb3VzZXdoZWVsLDp3aGVlbCw6c2Nyb2xsXG5dKVxuXG4jIHNob3VsZCBzZXQgdGhlc2UgdXAgaW5zaWRlIHRoZSBJbWJhLkV2ZW50cyBvYmplY3QgaXRzZWxmXG4jIHNvIHRoYXQgd2UgY2FuIGhhdmUgZGlmZmVyZW50IEV2ZW50TWFuYWdlciBmb3IgZGlmZmVyZW50IHJvb3RzXG5cbmlmIGhhc1RvdWNoRXZlbnRzXG5cdEltYmEuRXZlbnRzLmxpc3Rlbig6dG91Y2hzdGFydCkgZG8gfGV8XG5cdFx0SW1iYS5FdmVudHMuY291bnQrK1xuXHRcdEltYmEuVG91Y2gub250b3VjaHN0YXJ0KGUpXG5cblx0SW1iYS5FdmVudHMubGlzdGVuKDp0b3VjaG1vdmUpIGRvIHxlfFxuXHRcdEltYmEuRXZlbnRzLmNvdW50Kytcblx0XHRJbWJhLlRvdWNoLm9udG91Y2htb3ZlKGUpXG5cblx0SW1iYS5FdmVudHMubGlzdGVuKDp0b3VjaGVuZCkgZG8gfGV8XG5cdFx0SW1iYS5FdmVudHMuY291bnQrK1xuXHRcdEltYmEuVG91Y2gub250b3VjaGVuZChlKVxuXG5cdEltYmEuRXZlbnRzLmxpc3Rlbig6dG91Y2hjYW5jZWwpIGRvIHxlfFxuXHRcdEltYmEuRXZlbnRzLmNvdW50Kytcblx0XHRJbWJhLlRvdWNoLm9udG91Y2hjYW5jZWwoZSlcblxuSW1iYS5FdmVudHMucmVnaXN0ZXIoOmNsaWNrKSBkbyB8ZXxcblx0IyBPbmx5IGZvciBtYWluIG1vdXNlYnV0dG9uLCBubz9cblx0aWYgKGU6dGltZVN0YW1wIC0gbGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wKSA+IGxhc3ROYXRpdmVUb3VjaFRpbWVvdXRcblx0XHR2YXIgdGFwID0gSW1iYS5FdmVudC5uZXcoZSlcblx0XHR0YXAudHlwZSA9ICd0YXAnXG5cdFx0dGFwLnByb2Nlc3Ncblx0XHRpZiB0YXAuQHJlc3BvbmRlclxuXHRcdFx0cmV0dXJuIGUucHJldmVudERlZmF1bHRcblx0IyBkZWxlZ2F0ZSB0aGUgcmVhbCBjbGljayBldmVudFxuXHRJbWJhLkV2ZW50cy5kZWxlZ2F0ZShlKVxuXG5JbWJhLkV2ZW50cy5saXN0ZW4oOm1vdXNlZG93bikgZG8gfGV8XG5cdGlmIChlOnRpbWVTdGFtcCAtIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCkgPiBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0XG5cdFx0SW1iYS5QT0lOVEVSLnVwZGF0ZShlKS5wcm9jZXNzIGlmIEltYmEuUE9JTlRFUlxuXG4jIEltYmEuRXZlbnRzLmxpc3Rlbig6bW91c2Vtb3ZlKSBkbyB8ZXxcbiMgXHQjIGNvbnNvbGUubG9nICdtb3VzZW1vdmUnLGU6dGltZVN0YW1wXG4jIFx0aWYgKGU6dGltZVN0YW1wIC0gbGFzdE5hdGl2ZVRvdWNoVGltZVN0YW1wKSA+IGxhc3ROYXRpdmVUb3VjaFRpbWVvdXRcbiMgXHRcdEltYmEuUE9JTlRFUi51cGRhdGUoZSkucHJvY2VzcyBpZiBJbWJhLlBPSU5URVIgIyAucHJvY2VzcyBpZiB0b3VjaCAjIHNob3VsZCBub3QgaGFwcGVuPyBXZSBwcm9jZXNzIHRocm91Z2ggXG5cbkltYmEuRXZlbnRzLmxpc3Rlbig6bW91c2V1cCkgZG8gfGV8XG5cdCMgY29uc29sZS5sb2cgJ21vdXNldXAnLGU6dGltZVN0YW1wXG5cdGlmIChlOnRpbWVTdGFtcCAtIGxhc3ROYXRpdmVUb3VjaFRpbWVTdGFtcCkgPiBsYXN0TmF0aXZlVG91Y2hUaW1lb3V0XG5cdFx0SW1iYS5QT0lOVEVSLnVwZGF0ZShlKS5wcm9jZXNzIGlmIEltYmEuUE9JTlRFUlxuXG5cbkltYmEuRXZlbnRzLnJlZ2lzdGVyKFs6bW91c2Vkb3duLDptb3VzZXVwXSlcbkltYmEuRXZlbnRzLmVuYWJsZWQgPSB5ZXNcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uZXZlbnRzLmltYmFcbiAqKi8iLCJ2YXIgSW1iYVRhZyA9IEltYmEuVEFHUzplbGVtZW50XG5cbmRlZiByZW1vdmVOZXN0ZWQgcm9vdCwgbm9kZSwgY2FyZXRcblx0IyBpZiBub2RlL25vZGVzIGlzYSBTdHJpbmdcblx0IyBcdHdlIG5lZWQgdG8gdXNlIHRoZSBjYXJldCB0byByZW1vdmUgZWxlbWVudHNcblx0IyBcdGZvciBub3cgd2Ugd2lsbCBzaW1wbHkgbm90IHN1cHBvcnQgdGhpc1xuXHRpZiBub2RlIGlzYSBJbWJhVGFnXG5cdFx0cm9vdC5yZW1vdmVDaGlsZChub2RlKVxuXHRlbGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3QsbWVtYmVyLGNhcmV0KSBmb3IgbWVtYmVyIGluIG5vZGVcblx0ZWxzZVxuXHRcdCMgd2hhdCBpZiB0aGlzIGlzIG5vdCBudWxsPyE/IT9cblx0XHQjIHRha2UgYSBjaGFuY2UgYW5kIHJlbW92ZSBhIHRleHQtZWxlbWVudG5nXG5cdFx0bGV0IG5leHQgPSBjYXJldCA/IGNhcmV0Om5leHRTaWJsaW5nIDogcm9vdC5AZG9tOmZpcnN0Q2hpbGRcblx0XHRpZiBuZXh0IGlzYSBUZXh0IGFuZCBuZXh0OnRleHRDb250ZW50ID09IG5vZGVcblx0XHRcdHJvb3QucmVtb3ZlQ2hpbGQobmV4dClcblx0XHRlbHNlXG5cdFx0XHR0aHJvdyAnY2Fubm90IHJlbW92ZSBzdHJpbmcnXG5cblx0cmV0dXJuIGNhcmV0XG5cbmRlZiBhcHBlbmROZXN0ZWQgcm9vdCwgbm9kZVxuXHRpZiBub2RlIGlzYSBJbWJhVGFnXG5cdFx0cm9vdC5hcHBlbmRDaGlsZChub2RlKVxuXG5cdGVsaWYgbm9kZSBpc2EgQXJyYXlcblx0XHRhcHBlbmROZXN0ZWQocm9vdCxtZW1iZXIpIGZvciBtZW1iZXIgaW4gbm9kZVxuXG5cdGVsaWYgbm9kZSAhPSBudWxsIGFuZCBub2RlICE9PSBmYWxzZVxuXHRcdHJvb3QuYXBwZW5kQ2hpbGQgSW1iYS5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShub2RlKVxuXG5cdHJldHVyblxuXG5cbiMgaW5zZXJ0IG5vZGVzIGJlZm9yZSBhIGNlcnRhaW4gbm9kZVxuIyBkb2VzIG5vdCBuZWVkIHRvIHJldHVybiBhbnkgdGFpbCwgYXMgYmVmb3JlXG4jIHdpbGwgc3RpbGwgYmUgY29ycmVjdCB0aGVyZVxuIyBiZWZvcmUgbXVzdCBiZSBhbiBhY3R1YWwgZG9tbm9kZVxuZGVmIGluc2VydE5lc3RlZEJlZm9yZSByb290LCBub2RlLCBiZWZvcmVcblx0aWYgbm9kZSBpc2EgSW1iYVRhZ1xuXHRcdHJvb3QuaW5zZXJ0QmVmb3JlKG5vZGUsYmVmb3JlKVxuXHRlbGlmIG5vZGUgaXNhIEFycmF5XG5cdFx0aW5zZXJ0TmVzdGVkQmVmb3JlKHJvb3QsbWVtYmVyLGJlZm9yZSkgZm9yIG1lbWJlciBpbiBub2RlXG5cdGVsaWYgbm9kZSAhPSBudWxsIGFuZCBub2RlICE9PSBmYWxzZVxuXHRcdHJvb3QuaW5zZXJ0QmVmb3JlKEltYmEuZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobm9kZSksYmVmb3JlKVxuXG5cdHJldHVybiBiZWZvcmVcblxuIyBhZnRlciBtdXN0IGJlIGFuIGFjdHVhbCBkb21ub2RlXG5kZWYgaW5zZXJ0TmVzdGVkQWZ0ZXIgcm9vdCwgbm9kZSwgYWZ0ZXJcblx0dmFyIGJlZm9yZSA9IGFmdGVyID8gYWZ0ZXI6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXG5cdGlmIGJlZm9yZVxuXHRcdGluc2VydE5lc3RlZEJlZm9yZShyb290LG5vZGUsYmVmb3JlKVxuXHRcdHJldHVybiBiZWZvcmU6cHJldmlvdXNTaWJsaW5nXG5cdGVsc2Vcblx0XHRhcHBlbmROZXN0ZWQocm9vdCxub2RlKVxuXHRcdHJldHVybiByb290LkBkb206bGFzdENoaWxkXG5cbmRlZiByZWNvbmNpbGVDb2xsZWN0aW9uQ2hhbmdlcyByb290LCBuZXcsIG9sZCwgY2FyZXRcblxuXHR2YXIgbmV3TGVuID0gbmV3Omxlbmd0aFxuXHR2YXIgbGFzdE5ldyA9IG5ld1tuZXdMZW4gLSAxXVxuXG5cdCMgVGhpcyByZS1vcmRlciBhbGdvcml0aG0gaXMgYmFzZWQgb24gdGhlIGZvbGxvd2luZyBwcmluY2lwbGU6XG5cdCMgXG5cdCMgV2UgYnVpbGQgYSBcImNoYWluXCIgd2hpY2ggc2hvd3Mgd2hpY2ggaXRlbXMgYXJlIGFscmVhZHkgc29ydGVkLlxuXHQjIElmIHdlJ3JlIGdvaW5nIGZyb20gWzEsIDIsIDNdIC0+IFsyLCAxLCAzXSwgdGhlIHRyZWUgbG9va3MgbGlrZTpcblx0I1xuXHQjIFx0MyAtPiAgMCAoaWR4KVxuXHQjIFx0MiAtPiAtMSAoaWR4KVxuXHQjIFx0MSAtPiAtMSAoaWR4KVxuXHQjXG5cdCMgVGhpcyB0ZWxscyB1cyB0aGF0IHdlIGhhdmUgdHdvIGNoYWlucyBvZiBvcmRlcmVkIGl0ZW1zOlxuXHQjIFxuXHQjIFx0KDEsIDMpIGFuZCAoMilcblx0IyBcblx0IyBUaGUgb3B0aW1hbCByZS1vcmRlcmluZyB0aGVuIGJlY29tZXMgdHdvIGtlZXAgdGhlIGxvbmdlc3QgY2hhaW4gaW50YWN0LFxuXHQjIGFuZCBtb3ZlIGFsbCB0aGUgb3RoZXIgaXRlbXMuXG5cblx0dmFyIG5ld1Bvc2l0aW9uID0gW11cblxuXHQjIFRoZSB0cmVlL2dyYXBoIGl0c2VsZlxuXHR2YXIgcHJldkNoYWluID0gW11cblx0IyBUaGUgbGVuZ3RoIG9mIHRoZSBjaGFpblxuXHR2YXIgbGVuZ3RoQ2hhaW4gPSBbXVxuXG5cdCMgS2VlcCB0cmFjayBvZiB0aGUgbG9uZ2VzdCBjaGFpblxuXHR2YXIgbWF4Q2hhaW5MZW5ndGggPSAwXG5cdHZhciBtYXhDaGFpbkVuZCA9IDBcblxuXHRmb3Igbm9kZSwgaWR4IGluIG9sZFxuXHRcdHZhciBuZXdQb3MgPSBuZXcuaW5kZXhPZihub2RlKVxuXHRcdG5ld1Bvc2l0aW9uLnB1c2gobmV3UG9zKVxuXG5cdFx0aWYgbmV3UG9zID09IC0xXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG5vZGUpXG5cdFx0XHRwcmV2Q2hhaW4ucHVzaCgtMSlcblx0XHRcdGxlbmd0aENoYWluLnB1c2goLTEpXG5cdFx0XHRjb250aW51ZVxuXG5cdFx0dmFyIHByZXZJZHggPSBuZXdQb3NpdGlvbjpsZW5ndGggLSAyXG5cblx0XHQjIEJ1aWxkIHRoZSBjaGFpbjpcblx0XHR3aGlsZSBwcmV2SWR4ID49IDBcblx0XHRcdGlmIG5ld1Bvc2l0aW9uW3ByZXZJZHhdID09IC0xXG5cdFx0XHRcdHByZXZJZHgtLVxuXHRcdFx0ZWxpZiBuZXdQb3MgPiBuZXdQb3NpdGlvbltwcmV2SWR4XVxuXHRcdFx0XHQjIFlheSwgd2UncmUgYmlnZ2VyIHRoYW4gdGhlIHByZXZpb3VzIVxuXHRcdFx0XHRicmVha1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHQjIE5vcGUsIGxldCdzIHdhbGsgYmFjayB0aGUgY2hhaW5cblx0XHRcdFx0cHJldklkeCA9IHByZXZDaGFpbltwcmV2SWR4XVxuXG5cdFx0cHJldkNoYWluLnB1c2gocHJldklkeClcblxuXHRcdHZhciBjdXJyTGVuZ3RoID0gKHByZXZJZHggPT0gLTEpID8gMCA6IGxlbmd0aENoYWluW3ByZXZJZHhdKzFcblxuXHRcdGlmIGN1cnJMZW5ndGggPiBtYXhDaGFpbkxlbmd0aFxuXHRcdFx0bWF4Q2hhaW5MZW5ndGggPSBjdXJyTGVuZ3RoXG5cdFx0XHRtYXhDaGFpbkVuZCA9IGlkeFxuXG5cdFx0bGVuZ3RoQ2hhaW4ucHVzaChjdXJyTGVuZ3RoKVxuXG5cdHZhciBzdGlja3lOb2RlcyA9IFtdXG5cblx0IyBOb3cgd2UgY2FuIHdhbGsgdGhlIGxvbmdlc3QgY2hhaW4gYmFja3dhcmRzIGFuZCBtYXJrIHRoZW0gYXMgXCJzdGlja3lcIixcblx0IyB3aGljaCBpbXBsaWVzIHRoYXQgdGhleSBzaG91bGQgbm90IGJlIG1vdmVkXG5cdHZhciBjdXJzb3IgPSBuZXdQb3NpdGlvbjpsZW5ndGggLSAxXG5cdHdoaWxlIGN1cnNvciA+PSAwXG5cdFx0aWYgY3Vyc29yID09IG1heENoYWluRW5kIGFuZCBuZXdQb3NpdGlvbltjdXJzb3JdICE9IC0xXG5cdFx0XHRzdGlja3lOb2Rlc1tuZXdQb3NpdGlvbltjdXJzb3JdXSA9IHRydWVcblx0XHRcdG1heENoYWluRW5kID0gcHJldkNoYWluW21heENoYWluRW5kXVxuXHRcdFxuXHRcdGN1cnNvciAtPSAxXG5cblx0IyBBbmQgbGV0J3MgaXRlcmF0ZSBmb3J3YXJkLCBidXQgb25seSBtb3ZlIG5vbi1zdGlja3kgbm9kZXNcblx0Zm9yIG5vZGUsIGlkeCBpbiBuZXdcblx0XHRpZiAhc3RpY2t5Tm9kZXNbaWR4XVxuXHRcdFx0dmFyIGFmdGVyID0gbmV3W2lkeCAtIDFdXG5cdFx0XHRpbnNlcnROZXN0ZWRBZnRlcihyb290LCBub2RlLCAoYWZ0ZXIgYW5kIGFmdGVyLkBkb20pIG9yIGNhcmV0KVxuXG5cdCMgc2hvdWxkIHRydXN0IHRoYXQgdGhlIGxhc3QgaXRlbSBpbiBuZXcgbGlzdCBpcyB0aGUgY2FyZXRcblx0cmV0dXJuIGxhc3ROZXcgYW5kIGxhc3ROZXcuQGRvbSBvciBjYXJldFxuXG5cbiMgZXhwZWN0cyBhIGZsYXQgbm9uLXNwYXJzZSBhcnJheSBvZiBub2RlcyBpbiBib3RoIG5ldyBhbmQgb2xkLCBhbHdheXNcbmRlZiByZWNvbmNpbGVDb2xsZWN0aW9uIHJvb3QsIG5ldywgb2xkLCBjYXJldFxuXHR2YXIgayA9IG5ldzpsZW5ndGhcblx0dmFyIGkgPSBrXG5cdHZhciBsYXN0ID0gbmV3W2sgLSAxXVxuXG5cblx0aWYgayA9PSBvbGQ6bGVuZ3RoIGFuZCBuZXdbMF0gPT09IG9sZFswXVxuXHRcdCMgcnVubmluZyB0aHJvdWdoIHRvIGNvbXBhcmVcblx0XHR3aGlsZSBpLS1cblx0XHRcdGJyZWFrIGlmIG5ld1tpXSAhPT0gb2xkW2ldXG5cblx0aWYgaSA9PSAtMVxuXHRcdHJldHVybiBsYXN0IGFuZCBsYXN0LkBkb20gb3IgY2FyZXRcblx0ZWxzZVxuXHRcdHJldHVybiByZWNvbmNpbGVDb2xsZWN0aW9uQ2hhbmdlcyhyb290LG5ldyxvbGQsY2FyZXQpXG5cbiMgdGhlIGdlbmVyYWwgcmVjb25jaWxlciB0aGF0IHJlc3BlY3RzIGNvbmRpdGlvbnMgZXRjXG4jIGNhcmV0IGlzIHRoZSBjdXJyZW50IG5vZGUgd2Ugd2FudCB0byBpbnNlcnQgdGhpbmdzIGFmdGVyXG5kZWYgcmVjb25jaWxlTmVzdGVkIHJvb3QsIG5ldywgb2xkLCBjYXJldFxuXG5cdCMgaWYgbmV3ID09IG51bGwgb3IgbmV3ID09PSBmYWxzZSBvciBuZXcgPT09IHRydWVcblx0IyBcdGlmIG5ldyA9PT0gb2xkXG5cdCMgXHRcdHJldHVybiBjYXJldFxuXHQjIFx0aWYgb2xkICYmIG5ldyAhPSBvbGRcblx0IyBcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSBpZiBvbGRcblx0IyBcblx0IyBcdHJldHVybiBjYXJldFxuXG5cdCMgdmFyIHNraXBuZXcgPSBuZXcgPT0gbnVsbCBvciBuZXcgPT09IGZhbHNlIG9yIG5ldyA9PT0gdHJ1ZVxuXHR2YXIgbmV3SXNOdWxsID0gbmV3ID09IG51bGwgb3IgbmV3ID09PSBmYWxzZVxuXHR2YXIgb2xkSXNOdWxsID0gb2xkID09IG51bGwgb3Igb2xkID09PSBmYWxzZVxuXG5cblx0aWYgbmV3ID09PSBvbGRcblx0XHQjIHJlbWVtYmVyIHRoYXQgdGhlIGNhcmV0IG11c3QgYmUgYW4gYWN0dWFsIGRvbSBlbGVtZW50XG5cdFx0IyB3ZSBzaG91bGQgaW5zdGVhZCBtb3ZlIHRoZSBhY3R1YWwgY2FyZXQ/IC0gdHJ1c3Rcblx0XHRpZiBuZXdJc051bGxcblx0XHRcdHJldHVybiBjYXJldFxuXHRcdGVsaWYgbmV3IGFuZCBuZXcuQGRvbVxuXHRcdFx0cmV0dXJuIG5ldy5AZG9tXG5cdFx0ZWxzZVxuXHRcdFx0cmV0dXJuIGNhcmV0ID8gY2FyZXQ6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXG5cdGVsaWYgbmV3IGlzYSBBcnJheVxuXHRcdGlmIG9sZCBpc2EgQXJyYXlcblx0XHRcdGlmIG5ldzpzdGF0aWMgb3Igb2xkOnN0YXRpY1xuXHRcdFx0XHQjIGlmIHRoZSBzdGF0aWMgaXMgbm90IG5lc3RlZCAtIHdlIGNvdWxkIGdldCBhIGhpbnQgZnJvbSBjb21waWxlclxuXHRcdFx0XHQjIGFuZCBqdXN0IHNraXAgaXRcblx0XHRcdFx0aWYgbmV3OnN0YXRpYyA9PSBvbGQ6c3RhdGljXG5cdFx0XHRcdFx0Zm9yIGl0ZW0saSBpbiBuZXdcblx0XHRcdFx0XHRcdCMgdGhpcyBpcyB3aGVyZSB3ZSBjb3VsZCBkbyB0aGUgdHJpcGxlIGVxdWFsIGRpcmVjdGx5XG5cdFx0XHRcdFx0XHRjYXJldCA9IHJlY29uY2lsZU5lc3RlZChyb290LGl0ZW0sb2xkW2ldLGNhcmV0KVxuXHRcdFx0XHRcdHJldHVybiBjYXJldFxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KVxuXHRcdFx0XHRcdFxuXHRcdFx0XHQjIGlmIHRoZXkgYXJlIG5vdCB0aGUgc2FtZSB3ZSBjb250aW51ZSB0aHJvdWdoIHRvIHRoZSBkZWZhdWx0XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJldHVybiByZWNvbmNpbGVDb2xsZWN0aW9uKHJvb3QsbmV3LG9sZCxjYXJldClcblxuXHRcdGVsaWYgb2xkIGlzYSBJbWJhVGFnXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG9sZClcblx0XHRlbGlmICFvbGRJc051bGxcblx0XHRcdCMgb2xkIHdhcyBhIHN0cmluZy1saWtlIG9iamVjdD9cblx0XHRcdHJvb3QucmVtb3ZlQ2hpbGQoY2FyZXQgPyBjYXJldDpuZXh0U2libGluZyA6IHJvb3QuQGRvbTpmaXJzdENoaWxkKVx0XHRcdFxuXG5cdFx0cmV0dXJuIGluc2VydE5lc3RlZEFmdGVyKHJvb3QsbmV3LGNhcmV0KVxuXHRcdCMgcmVtb3ZlIG9sZFxuXG5cdGVsaWYgbmV3IGlzYSBJbWJhVGFnXG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSB1bmxlc3Mgb2xkSXNOdWxsXG5cdFx0aW5zZXJ0TmVzdGVkQWZ0ZXIocm9vdCxuZXcsY2FyZXQpXG5cdFx0cmV0dXJuIG5ld1xuXG5cdGVsaWYgbmV3SXNOdWxsXG5cdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KSB1bmxlc3Mgb2xkSXNOdWxsXG5cdFx0cmV0dXJuIGNhcmV0XG5cdGVsc2Vcblx0XHQjIGlmIG9sZCBkaWQgbm90IGV4aXN0IHdlIG5lZWQgdG8gYWRkIGEgbmV3IGRpcmVjdGx5XG5cdFx0bGV0IG5leHROb2RlXG5cdFx0IyBpZiBvbGQgd2FzIGFycmF5IG9yIGltYmF0YWcgd2UgbmVlZCB0byByZW1vdmUgaXQgYW5kIHRoZW4gYWRkXG5cdFx0aWYgb2xkIGlzYSBBcnJheVxuXHRcdFx0cmVtb3ZlTmVzdGVkKHJvb3Qsb2xkLGNhcmV0KVxuXHRcdGVsaWYgb2xkIGlzYSBJbWJhVGFnXG5cdFx0XHRyb290LnJlbW92ZUNoaWxkKG9sZClcblx0XHRlbGlmICFvbGRJc051bGxcblx0XHRcdCMgLi4uXG5cdFx0XHRuZXh0Tm9kZSA9IGNhcmV0ID8gY2FyZXQ6bmV4dFNpYmxpbmcgOiByb290LkBkb206Zmlyc3RDaGlsZFxuXHRcdFx0aWYgbmV4dE5vZGUgaXNhIFRleHQgYW5kIG5leHROb2RlOnRleHRDb250ZW50ICE9IG5ld1xuXHRcdFx0XHRuZXh0Tm9kZTp0ZXh0Q29udGVudCA9IG5ld1xuXHRcdFx0XHRyZXR1cm4gbmV4dE5vZGVcblxuXHRcdCMgbm93IGFkZCB0aGUgdGV4dG5vZGVcblx0XHRyZXR1cm4gaW5zZXJ0TmVzdGVkQWZ0ZXIocm9vdCxuZXcsY2FyZXQpXG5cblxuZXh0ZW5kIHRhZyBodG1sZWxlbWVudFxuXHRcblx0ZGVmIHNldENoaWxkcmVuIG5ldywgdHlwXG5cdFx0dmFyIG9sZCA9IEBjaGlsZHJlblxuXHRcdCMgdmFyIGlzQXJyYXkgPSBub2RlcyBpc2EgQXJyYXlcblx0XHRpZiBuZXcgPT09IG9sZFxuXHRcdFx0cmV0dXJuIHNlbGZcblxuXHRcdGlmICFvbGRcblx0XHRcdGVtcHR5XG5cdFx0XHRhcHBlbmROZXN0ZWQoc2VsZixuZXcpXG5cblx0XHRlbGlmIHR5cCA9PSAyXG5cdFx0XHRyZXR1cm4gc2VsZlxuXG5cdFx0ZWxpZiB0eXAgPT0gMVxuXHRcdFx0IyBoZXJlIHdlIF9rbm93IF90aGF0IGl0IGlzIGFuIGFycmF5IHdpdGggdGhlIHNhbWUgc2hhcGVcblx0XHRcdCMgZXZlcnkgdGltZVxuXHRcdFx0bGV0IGNhcmV0ID0gbnVsbFxuXHRcdFx0Zm9yIGl0ZW0saSBpbiBuZXdcblx0XHRcdFx0IyBwcmV2ID0gb2xkW2ldXG5cdFx0XHRcdGNhcmV0ID0gcmVjb25jaWxlTmVzdGVkKHNlbGYsaXRlbSxvbGRbaV0sY2FyZXQpXG5cblx0XHRlbGlmIHR5cCA9PSAzXG5cdFx0XHQjIHRoaXMgaXMgcG9zc2libHkgZnVsbHkgZHluYW1pYy4gSXQgb2Z0ZW4gaXNcblx0XHRcdCMgYnV0IHRoZSBvbGQgb3IgbmV3IGNvdWxkIGJlIHN0YXRpYyB3aGlsZSB0aGUgb3RoZXIgaXMgbm90XG5cdFx0XHQjIHRoaXMgaXMgbm90IGhhbmRsZWQgbm93XG5cdFx0XHQjIHdoYXQgaWYgaXQgd2FzIHByZXZpb3VzbHkgYSBzdGF0aWMgYXJyYXk/IGVkZ2VjYXNlIC0gYnV0IG11c3Qgd29ya1xuXHRcdFx0aWYgbmV3IGlzYSBJbWJhVGFnXG5cdFx0XHRcdGVtcHR5XG5cdFx0XHRcdGFwcGVuZENoaWxkKG5ldylcblxuXHRcdFx0IyBjaGVjayBpZiBvbGQgYW5kIG5ldyBpc2EgYXJyYXlcblx0XHRcdGVsaWYgbmV3IGlzYSBBcnJheVxuXHRcdFx0XHRpZiBvbGQgaXNhIEFycmF5XG5cdFx0XHRcdFx0IyBpcyB0aGlzIG5vdCB0aGUgc2FtZSBhcyBzZXR0aW5nIHN0YXRpY0NoaWxkcmVuIG5vdyBidXQgd2l0aCB0aGVcblx0XHRcdFx0XHRyZWNvbmNpbGVDb2xsZWN0aW9uKHNlbGYsbmV3LG9sZCxudWxsKVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0ZW1wdHlcblx0XHRcdFx0XHRhcHBlbmROZXN0ZWQoc2VsZixuZXcpXG5cdFx0XHRcdFxuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0ZXh0ID0gbmV3XG5cdFx0XHRcdHJldHVybiBzZWxmXG5cblx0XHRlbGlmIG5ldyBpc2EgQXJyYXkgYW5kIG9sZCBpc2EgQXJyYXlcblx0XHRcdHJlY29uY2lsZUNvbGxlY3Rpb24oc2VsZixuZXcsb2xkLG51bGwpXG5cdFx0ZWxzZVxuXHRcdFx0ZW1wdHlcblx0XHRcdGFwcGVuZE5lc3RlZChzZWxmLG5ldylcblxuXHRcdEBjaGlsZHJlbiA9IG5ld1xuXHRcdHJldHVybiBzZWxmXG5cblxuXHQjIG9ubHkgZXZlciBjYWxsZWQgd2l0aCBhcnJheSBhcyBhcmd1bWVudFxuXHRkZWYgc2V0U3RhdGljQ2hpbGRyZW4gbmV3XG5cdFx0dmFyIG9sZCA9IEBjaGlsZHJlblxuXG5cdFx0bGV0IGNhcmV0ID0gbnVsbFxuXHRcdGZvciBpdGVtLGkgaW4gbmV3XG5cdFx0XHQjIHByZXYgPSBvbGRbaV1cblx0XHRcdGNhcmV0ID0gcmVjb25jaWxlTmVzdGVkKHNlbGYsaXRlbSxvbGRbaV0sY2FyZXQpXG5cblx0XHRAY2hpbGRyZW4gPSBuZXdcblx0XHRyZXR1cm4gc2VsZlxuXG5cdGRlZiBjb250ZW50XG5cdFx0QGNvbnRlbnQgb3IgY2hpbGRyZW4udG9BcnJheVxuXG5cdGRlZiB0ZXh0PSB0ZXh0XG5cdFx0aWYgdGV4dCAhPSBAY2hpbGRyZW5cblx0XHRcdEBjaGlsZHJlbiA9IHRleHRcblx0XHRcdGRvbTp0ZXh0Q29udGVudCA9IHRleHQgPT0gbnVsbCBvciB0ZXh0ID09PSBmYWxzZSA/ICcnIDogdGV4dFxuXHRcdHNlbGZcblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBzcmMvaW1iYS9kb20uc3RhdGljLmltYmFcbiAqKi8iLCJcbiMjI1xuVGhlIHNwZWNpYWwgc3ludGF4IGZvciBzZWxlY3RvcnMgaW4gSW1iYSBjcmVhdGVzIEltYmEuU2VsZWN0b3Jcbmluc3RhbmNlcy5cbiMjI1xuY2xhc3MgSW1iYS5TZWxlY3RvclxuXHRcblx0ZGVmIHNlbGYub25lIHNlbCwgc2NvcGVcblx0XHR2YXIgZWwgPSAoc2NvcGUgfHwgSW1iYS5kb2N1bWVudCkucXVlcnlTZWxlY3RvcihzZWwpXG5cdFx0ZWwgJiYgdGFnKGVsKSB8fCBudWxsXG5cblx0ZGVmIHNlbGYuYWxsIHNlbCwgc2NvcGVcblx0XHRJbWJhLlNlbGVjdG9yLm5ldyhzZWwsc2NvcGUpXG5cblx0cHJvcCBxdWVyeVxuXG5cdGRlZiBpbml0aWFsaXplIHNlbCwgc2NvcGUsIG5vZGVzXG5cblx0XHRAcXVlcnkgPSBzZWwgaXNhIEltYmEuU2VsZWN0b3IgPyBzZWwucXVlcnkgOiBzZWxcblx0XHRAY29udGV4dCA9IHNjb3BlXG5cblx0XHRpZiBub2Rlc1xuXHRcdFx0QG5vZGVzID0gKHRhZyhub2RlKSBmb3Igbm9kZSBpbiBub2RlcylcblxuXHRcdEBsYXp5ID0gIW5vZGVzXG5cdFx0cmV0dXJuIHNlbGZcblxuXHRkZWYgcmVsb2FkXG5cdFx0QG5vZGVzID0gbnVsbFxuXHRcdHNlbGZcblxuXHRkZWYgc2NvcGVcblx0XHRyZXR1cm4gQHNjb3BlIGlmIEBzY29wZVxuXHRcdHJldHVybiBJbWJhLmRvY3VtZW50IHVubGVzcyB2YXIgY3R4ID0gQGNvbnRleHRcblx0XHRAc2NvcGUgPSBjdHg6dG9TY29wZSA/IGN0eC50b1Njb3BlIDogY3R4XG5cblx0IyMjXG5cdEByZXR1cm5zIHtJbWJhLlRhZ30gZmlyc3Qgbm9kZSBtYXRjaGluZyB0aGlzIHNlbGVjdG9yXG5cdCMjI1xuXHRkZWYgZmlyc3Rcblx0XHRpZiBAbGF6eSB0aGVuIHRhZyhAZmlyc3QgfHw9IHNjb3BlLnF1ZXJ5U2VsZWN0b3IocXVlcnkpKVxuXHRcdGVsc2Ugbm9kZXNbMF1cblxuXHQjIyNcblx0QHJldHVybnMge0ltYmEuVGFnfSBsYXN0IG5vZGUgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGxhc3Rcblx0XHRub2Rlc1tAbm9kZXM6bGVuZ3RoIC0gMV1cblxuXHQjIyNcblx0QHJldHVybnMgW0ltYmEuVGFnXSBhbGwgbm9kZXMgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIG5vZGVzXG5cdFx0cmV0dXJuIEBub2RlcyBpZiBAbm9kZXNcblx0XHR2YXIgaXRlbXMgPSBzY29wZS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KVxuXHRcdEBub2RlcyA9ICh0YWcobm9kZSkgZm9yIG5vZGUgaW4gaXRlbXMpXG5cdFx0QGxhenkgPSBub1xuXHRcdEBub2Rlc1xuXHRcblx0IyMjXG5cdFRoZSBudW1iZXIgb2Ygbm9kZXMgbWF0Y2hpbmcgdGhpcyBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGNvdW50IGRvIG5vZGVzOmxlbmd0aFxuXG5cdGRlZiBsZW4gZG8gbm9kZXM6bGVuZ3RoXG5cblx0IyMjXG5cdEB0b2RvIEFkZCBzdXBwb3J0IGZvciBibG9jayBvciBzZWxlY3Rvcj9cblx0IyMjXG5cdGRlZiBzb21lXG5cdFx0Y291bnQgPj0gMVxuXHRcblx0IyMjXG5cdEdldCBub2RlIGF0IGluZGV4XG5cdCMjI1xuXHRkZWYgYXQgaWR4XG5cdFx0bm9kZXNbaWR4XVxuXG5cdCMjI1xuXHRMb29wIHRocm91Z2ggbm9kZXNcblx0IyMjXG5cdGRlZiBmb3JFYWNoIGJsb2NrXG5cdFx0bm9kZXMuZm9yRWFjaChibG9jaylcblx0XHRzZWxmXG5cblx0IyMjXG5cdE1hcCBub2Rlc1xuXHQjIyNcblx0ZGVmIG1hcCBibG9ja1xuXHRcdG5vZGVzLm1hcChibG9jaylcblxuXHQjIyNcblx0UmV0dXJucyBhIHBsYWluIGFycmF5IGNvbnRhaW5pbmcgbm9kZXMuIEltcGxpY2l0bHkgY2FsbGVkXG5cdHdoZW4gaXRlcmF0aW5nIG92ZXIgYSBzZWxlY3RvciBpbiBJbWJhIGAobm9kZSBmb3Igbm9kZSBpbiAkKHNlbGVjdG9yKSlgXG5cdCMjI1xuXHRkZWYgdG9BcnJheVxuXHRcdG5vZGVzXG5cdFxuXHQjIEdldCB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNlbGVjdG9yLCBcblx0IyBiZWdpbm5pbmcgYXQgdGhlIGN1cnJlbnQgZWxlbWVudCBhbmQgcHJvZ3Jlc3NpbmcgdXAgdGhyb3VnaCB0aGUgRE9NIHRyZWVcblx0ZGVmIGNsb3Nlc3Qgc2VsXG5cdFx0IyBzZWVtcyBzdHJhbmdlIHRoYXQgd2UgYWx0ZXIgdGhpcyBzZWxlY3Rvcj9cblx0XHRAbm9kZXMgPSBtYXAgZG8gfG5vZGV8IG5vZGUuY2xvc2VzdChzZWwpXG5cdFx0c2VsZlxuXG5cdCMgR2V0IHRoZSBzaWJsaW5ncyBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIHNldCBvZiBtYXRjaGVkIGVsZW1lbnRzLCBcblx0IyBvcHRpb25hbGx5IGZpbHRlcmVkIGJ5IGEgc2VsZWN0b3IuXG5cdCMgVE9ETyByZW1vdmUgZHVwbGljYXRlcz9cblx0ZGVmIHNpYmxpbmdzIHNlbFxuXHRcdEBub2RlcyA9IG1hcCBkbyB8bm9kZXwgbm9kZS5zaWJsaW5ncyhzZWwpXG5cdFx0c2VsZlxuXG5cdCMgR2V0IHRoZSBkZXNjZW5kYW50cyBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIGN1cnJlbnQgc2V0IG9mIG1hdGNoZWQgXG5cdCMgZWxlbWVudHMsIGZpbHRlcmVkIGJ5IGEgc2VsZWN0b3IuXG5cdGRlZiBmaW5kIHNlbFxuXHRcdEBub2RlcyA9IF9fcXVlcnlfXyhzZWwucXVlcnksIG5vZGVzKVxuXHRcdHNlbGZcblxuXHRkZWYgcmVqZWN0IGJsa1xuXHRcdGZpbHRlcihibGssbm8pXG5cblx0IyMjXG5cdEZpbHRlciB0aGUgbm9kZXMgaW4gc2VsZWN0b3IgYnkgYSBmdW5jdGlvbiBvciBvdGhlciBzZWxlY3RvclxuXHQjIyNcblx0ZGVmIGZpbHRlciBibGssIGJvb2wgPSB5ZXNcblx0XHR2YXIgZm4gPSBibGsgaXNhIEZ1bmN0aW9uIGFuZCBibGsgb3IgKHxufCBuLm1hdGNoZXMoYmxrKSApXG5cdFx0dmFyIGFyeSA9IG5vZGVzLmZpbHRlcih8bnwgZm4obikgPT0gYm9vbClcblx0XHQjIGlmIHdlIHdhbnQgdG8gcmV0dXJuIGEgbmV3IHNlbGVjdG9yIGZvciB0aGlzLCB3ZSBzaG91bGQgZG8gdGhhdCBmb3Jcblx0XHQjIG90aGVycyBhcyB3ZWxsXG5cdFx0SW1iYS5TZWxlY3Rvci5uZXcoXCJcIiwgQHNjb3BlLCBhcnkpXG5cblx0ZGVmIF9fcXVlcnlfXyBxdWVyeSwgY29udGV4dHNcblx0XHR2YXIgbm9kZXMgPSBbXVxuXHRcdHZhciBpID0gMFxuXHRcdHZhciBsID0gY29udGV4dHM6bGVuZ3RoXG5cblx0XHR3aGlsZSBpIDwgbFxuXHRcdFx0bm9kZXMucHVzaCgqY29udGV4dHNbaSsrXS5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJ5KSlcblx0XHRyZXR1cm4gbm9kZXNcblxuXHRkZWYgX19tYXRjaGVzX19cblx0XHRyZXR1cm4geWVzXG5cblx0IyMjXG5cdEFkZCBzcGVjaWZpZWQgZmxhZyB0byBhbGwgbm9kZXMgaW4gc2VsZWN0b3Jcblx0IyMjXG5cdGRlZiBmbGFnIGZsYWdcblx0XHRmb3JFYWNoIGRvIHxufCBuLmZsYWcoZmxhZylcblxuXHQjIyNcblx0UmVtb3ZlIHNwZWNpZmllZCBmbGFnIGZyb20gYWxsIG5vZGVzIGluIHNlbGVjdG9yXG5cdCMjI1xuXHRkZWYgdW5mbGFnIGZsYWdcblx0XHRmb3JFYWNoIGRvIHxufCBuLnVuZmxhZyhmbGFnKVxuXG5cbiMgZGVmIEltYmEucXVlcnlTZWxlY3RvckFsbFxucSQgPSBkbyB8c2VsLHNjb3BlfCBJbWJhLlNlbGVjdG9yLm5ldyhzZWwsIHNjb3BlKVxuXG4jIGRlZiBJbWJhLlNlbGVjdG9yLm9uZVxucSQkID0gZG8gfHNlbCxzY29wZXwgXG5cdHZhciBlbCA9IChzY29wZSB8fCBJbWJhLmRvY3VtZW50KS5xdWVyeVNlbGVjdG9yKHNlbClcblx0ZWwgJiYgdGFnKGVsKSB8fCBuaWxcblxuXG4jIGV4dGVuZGluZyB0YWdzIHdpdGggcXVlcnktbWV0aG9kc1xuIyBtdXN0IGJlIGEgYmV0dGVyIHdheSB0byByZW9wZW4gY2xhc3Nlc1xuZXh0ZW5kIHRhZyBlbGVtZW50XG5cdGRlZiBxdWVyeVNlbGVjdG9yQWxsIHEgZG8gQGRvbS5xdWVyeVNlbGVjdG9yQWxsIHFcblx0ZGVmIHF1ZXJ5U2VsZWN0b3IgcSBkbyBAZG9tLnF1ZXJ5U2VsZWN0b3IgcVxuXG5cdCMgc2hvdWxkIGJlIG1vdmVkIHRvIEltYmEuVGFnIGluc3RlYWQ/XG5cdCMgb3Igd2Ugc2hvdWxkIGltcGxlbWVudCBhbGwgb2YgdGhlbSBoZXJlXG5cdGRlZiBmaW5kIHNlbCBkbyBJbWJhLlNlbGVjdG9yLm5ldyhzZWwsc2VsZilcblxuXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogc3JjL2ltYmEvc2VsZWN0b3IuaW1iYVxuICoqLyJdLCJzb3VyY2VSb290IjoiIn0=
|