efront 4.33.3 → 4.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/#/345/233/275/351/231/205/345/214/226.yml +12 -0
- package/apps/_index.html +1 -4
- package/apps/pivot/link/chat.js +3 -3
- package/apps/pivot/link/list.html +1 -1
- package/coms/basic/renderExpress.js +2 -2
- package/coms/basic/renderExpress_test.js +1 -0
- package/coms/basic_/Symbol.js +12 -7
- package/coms/compile/autoenum.js +25 -4
- package/coms/compile/downLevel.js +14 -8
- package/coms/frame/chat-rtc.xht +1 -1
- package/coms/frame/chat.html +20 -11
- package/coms/frame/chat.js +159 -46
- package/coms/frame/chat.less +30 -0
- package/coms/zimoli/copyToClipboard.js +46 -0
- package/coms/zimoli/removeUnsafeTags.js +21 -0
- package/coms/zimoli/render.js +56 -10
- package/package.json +1 -1
- package/public/efront.js +1 -1
- package/public//346/226/207/344/273/266/347/263/273/347/273/237//344/270/273/351/241/265.jsp +2 -2
package/coms/frame/chat.js
CHANGED
|
@@ -11,7 +11,7 @@ function clickfile(event) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function msg(elem, { m }, parentScopes) {
|
|
14
|
-
if (m.sender === parentScopes[parentScopes.length - 1].
|
|
14
|
+
if (m.sender === parentScopes[parentScopes.length - 1].cid) {
|
|
15
15
|
elem.setAttribute("self", "");
|
|
16
16
|
}
|
|
17
17
|
if (m) switch (m.type) {
|
|
@@ -33,20 +33,24 @@ function msg(elem, { m }, parentScopes) {
|
|
|
33
33
|
elem.innerText = m.content;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
var userManager = function (users, map) {
|
|
37
|
-
for (var cx =
|
|
36
|
+
var userManager = function (users, map, page) {
|
|
37
|
+
for (var cx = users.length - 1; cx >= 0; cx--) {
|
|
38
38
|
var u = users[cx];
|
|
39
39
|
if (u.id in map) {
|
|
40
40
|
var m = map[u.id];
|
|
41
41
|
if (m.deleted) users.splice(cx, 1);
|
|
42
42
|
else Object.assign(u, m);
|
|
43
|
-
delete map[u.id];
|
|
44
|
-
|
|
43
|
+
if (!u.shake) delete map[u.id];
|
|
44
|
+
else users.splice(cx, 1);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
var ms = Object.keys(map).map(k => map[k]);
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
var us = ms.filter(a => !a.shake);
|
|
49
|
+
for (var u of us) {
|
|
50
|
+
u.msgread = 0;
|
|
51
|
+
}
|
|
52
|
+
users.push.apply(users, us);
|
|
53
|
+
return ms.filter(a => a.shake);
|
|
50
54
|
};
|
|
51
55
|
var saved_event, moving = null;
|
|
52
56
|
var dragpage = {
|
|
@@ -113,8 +117,8 @@ var getRtc = function (userid) {
|
|
|
113
117
|
return rtc;
|
|
114
118
|
}
|
|
115
119
|
async function pullFileWithRTC(scope, file) {
|
|
116
|
-
var
|
|
117
|
-
var rtc = getRtc(
|
|
120
|
+
var rid = scope.remoteUser.cid;
|
|
121
|
+
var rtc = getRtc(rid);
|
|
118
122
|
var h = await window.showSaveFilePicker({ suggestedName: file.name });
|
|
119
123
|
var writable = await h.createWritable();
|
|
120
124
|
var channel = await rtc.createChannel();
|
|
@@ -156,7 +160,7 @@ async function pullFileWithRTC(scope, file) {
|
|
|
156
160
|
// <!-- console.log('接收端异常',event) -->
|
|
157
161
|
};
|
|
158
162
|
var ondate = function (date) {
|
|
159
|
-
scope.send("didate", date,
|
|
163
|
+
scope.send("didate", date, rid);
|
|
160
164
|
};
|
|
161
165
|
var offer = await rtc.init(ondate);
|
|
162
166
|
scope.send('accept', { file: file.id, channel: channel.id, offer })
|
|
@@ -217,6 +221,24 @@ async function pushFileWithRTC(scope, file, msg) {
|
|
|
217
221
|
// <!-- console.log("发送端打开") -->
|
|
218
222
|
};
|
|
219
223
|
}
|
|
224
|
+
var shakeing = [];
|
|
225
|
+
var shakeUser = async function (page, shakes) {
|
|
226
|
+
if (shakeing.length) return shakeing.push.apply(shakeing, shakes);
|
|
227
|
+
shakeing.push.apply(shakeing, shakes);
|
|
228
|
+
while (shakeing.length) {
|
|
229
|
+
var user = shakeing.shift();
|
|
230
|
+
if (page.autoAllow);
|
|
231
|
+
else {
|
|
232
|
+
var options = [i18n`允许`, i18n`不允许` + '#danger'];
|
|
233
|
+
var res = await confirm(i18n`是否允许来自${user.name}(${user.id})的公网会话?`, options);
|
|
234
|
+
if (res === options[1]) continue;
|
|
235
|
+
}
|
|
236
|
+
delete user.shake;
|
|
237
|
+
page.push([user]);
|
|
238
|
+
await wait(function () { return page.localUser }, 10000);
|
|
239
|
+
page.send(page.localUser, 'user', user.cid);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
220
242
|
|
|
221
243
|
|
|
222
244
|
function chat(title = '会话窗口') {
|
|
@@ -224,7 +246,6 @@ function chat(title = '会话窗口') {
|
|
|
224
246
|
page.innerHTML = template;
|
|
225
247
|
drag.on(page.firstElementChild, page);
|
|
226
248
|
resize.on(page);
|
|
227
|
-
var localid = title.id || (new Date / 1000 | 0) + Math.sin(Math.random());
|
|
228
249
|
var users = [];
|
|
229
250
|
var addToMsgList = function (list, msgs) {
|
|
230
251
|
list.push.apply(list, msgs);
|
|
@@ -234,7 +255,7 @@ function chat(title = '会话窗口') {
|
|
|
234
255
|
if (msgs.length && (!lastmsg || lastmsg.offsetTop + lastmsg.offsetHeight === chat.scrollHeight)) {
|
|
235
256
|
chat.go(list.length ? list.length - 1 : 0);
|
|
236
257
|
}
|
|
237
|
-
if (ps.
|
|
258
|
+
if (ps.remoteUser) ps.remoteUser.msgread = list.length;
|
|
238
259
|
}
|
|
239
260
|
else {
|
|
240
261
|
ps.totalunread += msgs.length;
|
|
@@ -243,8 +264,41 @@ function chat(title = '会话窗口') {
|
|
|
243
264
|
var msgTemp = Object.create(null);
|
|
244
265
|
page.push = function (msgs) {
|
|
245
266
|
var { msglist } = ps;
|
|
246
|
-
var userMap = null;
|
|
247
267
|
var cached = [], cachedi = 0;
|
|
268
|
+
var userMap = null;
|
|
269
|
+
var cidMap = null;
|
|
270
|
+
var addUser = function (m) {
|
|
271
|
+
|
|
272
|
+
if (!userMap) {
|
|
273
|
+
cidMap = Object.create(null);
|
|
274
|
+
users.forEach((u, i) => {
|
|
275
|
+
cidMap[u.cid] = i;
|
|
276
|
+
})
|
|
277
|
+
userMap = Object.create(null);
|
|
278
|
+
}
|
|
279
|
+
if (m.cid in cidMap) {
|
|
280
|
+
var ci = cidMap[m.cid];
|
|
281
|
+
var c = users[ci];
|
|
282
|
+
if (c.shaking) {
|
|
283
|
+
delete userMap[m.id];
|
|
284
|
+
cidMap[m.cid] = m;
|
|
285
|
+
users[ci] = m;
|
|
286
|
+
if (ps.localUser === c) ps.localUser = m;
|
|
287
|
+
if (ps.remoteUser === c) ps.remoteUser = m;
|
|
288
|
+
}
|
|
289
|
+
else if (m.shaking) m = cidMap[m.cid];
|
|
290
|
+
}
|
|
291
|
+
if (!m.icon) {
|
|
292
|
+
if (m.shaking) {
|
|
293
|
+
m.name = "正在开启..";
|
|
294
|
+
m.id = 'loading';
|
|
295
|
+
m.icon = 'chrm';
|
|
296
|
+
}
|
|
297
|
+
else if (m.id) m.icon = m.id.replace(/[\.\d]+$/, '');
|
|
298
|
+
}
|
|
299
|
+
cidMap[m.cid] = m;
|
|
300
|
+
userMap[m.id] = m;
|
|
301
|
+
};
|
|
248
302
|
msgs = msgs.filter(m => {
|
|
249
303
|
if (!m) return false;
|
|
250
304
|
if (isString(m)) {
|
|
@@ -271,11 +325,7 @@ function chat(title = '会话窗口') {
|
|
|
271
325
|
return true;
|
|
272
326
|
}
|
|
273
327
|
switch (m.type) {
|
|
274
|
-
case 'user':
|
|
275
|
-
if (!userMap) userMap = Object.create(null);
|
|
276
|
-
if (!m.icon) m.icon = m.id.replace(/[\.\d]+$/, '');
|
|
277
|
-
userMap[m.id] = m;
|
|
278
|
-
break;
|
|
328
|
+
case 'user': addUser(m); break;
|
|
279
329
|
}
|
|
280
330
|
return false;
|
|
281
331
|
});
|
|
@@ -287,12 +337,20 @@ function chat(title = '会话窗口') {
|
|
|
287
337
|
ps.pushFile(m.content);
|
|
288
338
|
return false;
|
|
289
339
|
}
|
|
340
|
+
if (m.type === "user") {
|
|
341
|
+
addUser(m);
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
290
344
|
return true;
|
|
291
345
|
});
|
|
292
346
|
if (userMap) {
|
|
293
|
-
userManager(users, userMap);
|
|
294
|
-
|
|
347
|
+
var shakes = userManager(users, userMap, send1);
|
|
348
|
+
shakeUser(page, shakes);
|
|
349
|
+
if (users.indexOf(ps.remoteUser) < 0) ps.remoteUser = users[0];
|
|
295
350
|
if (users.length > 0 && ps.showList === 0) ps.showList = true;
|
|
351
|
+
for (let u of users) {
|
|
352
|
+
if (u.cid === ps.cid) ps.localUser = u;
|
|
353
|
+
}
|
|
296
354
|
}
|
|
297
355
|
if (msgs.length) {
|
|
298
356
|
var msgMap = Object.create(null);
|
|
@@ -328,9 +386,9 @@ function chat(title = '会话窗口') {
|
|
|
328
386
|
}
|
|
329
387
|
}
|
|
330
388
|
if (users.length) for (var u of users) {
|
|
331
|
-
if (u.
|
|
389
|
+
if (u.cid in msgMap) {
|
|
332
390
|
if (!u.msglist) u.msglist = [];
|
|
333
|
-
addToMsgList(u.msglist, msgMap[u.
|
|
391
|
+
addToMsgList(u.msglist, msgMap[u.cid]);
|
|
334
392
|
}
|
|
335
393
|
}
|
|
336
394
|
else {
|
|
@@ -341,13 +399,14 @@ function chat(title = '会话窗口') {
|
|
|
341
399
|
page.$renders = [function () {
|
|
342
400
|
ps.resize(ps.body);
|
|
343
401
|
}];
|
|
344
|
-
|
|
345
|
-
Object.defineProperty(page, '
|
|
402
|
+
|
|
403
|
+
Object.defineProperty(page, 'rid', {
|
|
346
404
|
get() {
|
|
347
|
-
var user = ps.
|
|
348
|
-
if (user) return user.
|
|
405
|
+
var user = ps.remoteUser;
|
|
406
|
+
if (user) return user.cid;
|
|
349
407
|
}
|
|
350
408
|
});
|
|
409
|
+
|
|
351
410
|
page.setAttribute('ng-class', "{showList:showList}");
|
|
352
411
|
var fid = 0;
|
|
353
412
|
var filesMap = Object.create(null);
|
|
@@ -357,19 +416,20 @@ function chat(title = '会话窗口') {
|
|
|
357
416
|
ps.send('rtc-video', data);
|
|
358
417
|
break;
|
|
359
418
|
case "hangup":
|
|
360
|
-
ps.send('rtc-close', "", ps.
|
|
419
|
+
ps.send('rtc-close', "", ps.remoteRtc);
|
|
361
420
|
break;
|
|
362
421
|
case "accept":
|
|
363
|
-
ps.send('rtc-accept', data, ps.
|
|
422
|
+
ps.send('rtc-accept', data, ps.remoteRtc);
|
|
364
423
|
break;
|
|
365
424
|
case "didate":
|
|
366
|
-
ps.send('rtc-didate', data, ps.
|
|
425
|
+
ps.send('rtc-didate', data, ps.remoteRtc);
|
|
367
426
|
break;
|
|
368
427
|
}
|
|
369
428
|
}
|
|
370
429
|
function send1(msg, sendto) {
|
|
371
430
|
cast(page, 'send', [sendto, msg]);
|
|
372
431
|
}
|
|
432
|
+
page.autoAllow = true;
|
|
373
433
|
var ps = {
|
|
374
434
|
chat: zimoli$list,
|
|
375
435
|
title,
|
|
@@ -377,45 +437,92 @@ function chat(title = '会话窗口') {
|
|
|
377
437
|
showList: 0,
|
|
378
438
|
users,
|
|
379
439
|
text: '',
|
|
440
|
+
get autoAllow() {
|
|
441
|
+
return page.autoAllow;
|
|
442
|
+
},
|
|
443
|
+
set autoAllow(v) {
|
|
444
|
+
return page.autoAllow = v;
|
|
445
|
+
},
|
|
380
446
|
calling: null,
|
|
381
|
-
|
|
382
|
-
|
|
447
|
+
remoteRtc: null,
|
|
448
|
+
get localUser() {
|
|
449
|
+
return page.localUser
|
|
450
|
+
},
|
|
451
|
+
set localUser(v) {
|
|
452
|
+
page.localUser = v;
|
|
453
|
+
},
|
|
454
|
+
get shaking() {
|
|
455
|
+
var u = this.remoteUser;
|
|
456
|
+
if (u) return u.shaking;
|
|
457
|
+
},
|
|
458
|
+
get localid() {
|
|
459
|
+
return page.clientid;
|
|
460
|
+
},
|
|
461
|
+
set localid(v) {
|
|
462
|
+
page.clientid = v;
|
|
463
|
+
},
|
|
464
|
+
get cid() {
|
|
465
|
+
return this.localid;
|
|
466
|
+
},
|
|
467
|
+
get rid() {
|
|
468
|
+
if (this.remoteUser) return this.remoteUser.cid;
|
|
469
|
+
},
|
|
470
|
+
text: '',
|
|
383
471
|
totalunread: 0,
|
|
384
|
-
|
|
385
|
-
|
|
472
|
+
get linkurl() {
|
|
473
|
+
var href = location.href.replace(/[?#][\s\S]*$/, '') + "?" + this.cid;
|
|
474
|
+
return href;
|
|
475
|
+
},
|
|
476
|
+
async qr(canvas) {
|
|
477
|
+
var qrcode = await init("thirdParty$qrcode");
|
|
478
|
+
var qr = qrcode(0, 'L');
|
|
479
|
+
var href = this.linkurl;
|
|
480
|
+
qr.addData(href);
|
|
481
|
+
qr.make();
|
|
482
|
+
var size = qr.getModuleCount();
|
|
483
|
+
canvas.width = canvas.height = size;
|
|
484
|
+
while (size < 128) size = size << 1;
|
|
485
|
+
css(canvas, { width: size, height: size });
|
|
486
|
+
qr.renderTo2dContext(canvas.getContext("2d"), 1);
|
|
487
|
+
},
|
|
488
|
+
cplink() {
|
|
489
|
+
copyToClipboard(this.linkurl);
|
|
490
|
+
},
|
|
491
|
+
call(remote = this.rid, offer) {
|
|
386
492
|
if (this.calling) return;
|
|
387
|
-
this.
|
|
493
|
+
this.remoteRtc = isObject(remote) ? remote.cid : remote;
|
|
494
|
+
console.log(remote)
|
|
388
495
|
if (typeof remote === 'string') {
|
|
389
496
|
for (var u of this.users) {
|
|
390
|
-
if (u.
|
|
497
|
+
if (u.cid === remote) {
|
|
391
498
|
remote = u;
|
|
392
499
|
break;
|
|
393
500
|
}
|
|
394
501
|
}
|
|
395
502
|
}
|
|
396
503
|
if (!remote) return;
|
|
397
|
-
var c = chatRtc(remote, this.
|
|
504
|
+
var c = chatRtc(remote, this.cid, offer);
|
|
398
505
|
this.calling = c;
|
|
399
506
|
|
|
400
507
|
on('remove')(c, function () {
|
|
401
508
|
ps.calling = null;
|
|
402
|
-
ps.
|
|
509
|
+
ps.remoteRtc = null;
|
|
403
510
|
})
|
|
404
511
|
care(c, rtcMessage);
|
|
405
512
|
popup(c);
|
|
406
513
|
},
|
|
407
514
|
fileIcon: shapes$file,
|
|
408
|
-
set
|
|
515
|
+
set remoteUser(v) {
|
|
409
516
|
if (!v.msglist) v.msglist = []
|
|
410
517
|
if (v.msgread !== v.msglist.length) {
|
|
411
518
|
v.msgread = v.msglist.length;
|
|
412
519
|
this.totalunread -= v.msglist.length - v.msgread;
|
|
413
520
|
}
|
|
414
521
|
this.msglist = v.msglist;
|
|
415
|
-
|
|
522
|
+
page.remoteUser = v;
|
|
416
523
|
},
|
|
417
|
-
get
|
|
418
|
-
return
|
|
524
|
+
get remoteUser() {
|
|
525
|
+
return page.remoteUser;
|
|
419
526
|
},
|
|
420
527
|
msg,
|
|
421
528
|
remove() {
|
|
@@ -470,10 +577,15 @@ function chat(title = '会话窗口') {
|
|
|
470
577
|
body.resizeCell(textarea, 'top', textarea.clientHeight - targetHeight - 2);
|
|
471
578
|
},
|
|
472
579
|
|
|
473
|
-
send(type, content, sendto = page.
|
|
474
|
-
|
|
580
|
+
send(type, content, sendto = page.rid) {
|
|
581
|
+
console.log(type, content, 'send', sendto, this.text)
|
|
582
|
+
if (type instanceof Object) {
|
|
583
|
+
var msg = type;
|
|
584
|
+
if (!msg.type) msg.type = content;
|
|
585
|
+
}
|
|
586
|
+
else var msg = {
|
|
475
587
|
type,
|
|
476
|
-
sender: this.
|
|
588
|
+
sender: this.localUser.cid,
|
|
477
589
|
content,
|
|
478
590
|
};
|
|
479
591
|
var data = JSAM.stringify(msg);
|
|
@@ -481,7 +593,7 @@ function chat(title = '会话窗口') {
|
|
|
481
593
|
if (data.length > 16000) {
|
|
482
594
|
return alert("信息太长,无法发送!");
|
|
483
595
|
}
|
|
484
|
-
if (this.
|
|
596
|
+
if (this.remoteUser && this.remoteUser.cid !== this.cid) a: {
|
|
485
597
|
switch (type) {
|
|
486
598
|
case "accept":
|
|
487
599
|
case "didate":
|
|
@@ -505,7 +617,7 @@ function chat(title = '会话窗口') {
|
|
|
505
617
|
else {
|
|
506
618
|
send1(data, sendto);
|
|
507
619
|
}
|
|
508
|
-
this.body.lastElementChild.focus();
|
|
620
|
+
if (this.body) this.body.lastElementChild.focus();
|
|
509
621
|
this.text = '';
|
|
510
622
|
}
|
|
511
623
|
};
|
|
@@ -520,5 +632,6 @@ function chat(title = '会话窗口') {
|
|
|
520
632
|
}
|
|
521
633
|
});
|
|
522
634
|
moveupon(page, dragpage);
|
|
635
|
+
page.send = ps.send.bind(ps);
|
|
523
636
|
return page;
|
|
524
637
|
}
|
package/coms/frame/chat.less
CHANGED
|
@@ -25,6 +25,36 @@
|
|
|
25
25
|
max-height: 100%;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
.fade {
|
|
29
|
+
filter: grayscale(1);
|
|
30
|
+
opacity: .5;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.qrcode {
|
|
34
|
+
position: relative;
|
|
35
|
+
height: 0;
|
|
36
|
+
overflow: visible;
|
|
37
|
+
z-index: 2;
|
|
38
|
+
padding: 0;
|
|
39
|
+
width: 100%;
|
|
40
|
+
text-align: center;
|
|
41
|
+
margin-bottom: -52px;
|
|
42
|
+
|
|
43
|
+
>p {
|
|
44
|
+
background: #fff;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
>canvas {
|
|
48
|
+
background: #fff;
|
|
49
|
+
border: 10px solid #fff;
|
|
50
|
+
image-rendering: pixelated;
|
|
51
|
+
display: block;
|
|
52
|
+
margin: 52px auto 10px auto;
|
|
53
|
+
width: 256px;
|
|
54
|
+
height: 256px;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
28
58
|
>list {
|
|
29
59
|
width: @leftwidth;
|
|
30
60
|
position: absolute;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
var ClipboardItem = window.ClipboardItem;
|
|
2
|
+
|
|
3
|
+
async function copyToClipboard(text, mime = 'text/plain') {
|
|
4
|
+
mime = mime.toLowerCase();
|
|
5
|
+
if (ClipboardItem && ClipboardItem.supports(mime)) {
|
|
6
|
+
const clipboardItem = new ClipboardItem({ [mime]: text });
|
|
7
|
+
try {
|
|
8
|
+
await navigator.clipboard.write([clipboardItem]);
|
|
9
|
+
alert("已复制");
|
|
10
|
+
return;
|
|
11
|
+
} catch (e) { console.log(e) };
|
|
12
|
+
}
|
|
13
|
+
var span = document.createElement('span');
|
|
14
|
+
span.setAttribute('user-select', 'all');
|
|
15
|
+
setOpacity(span, 0);
|
|
16
|
+
css(span, "position:absolute;top:-1000000px;left:-1000000px;")
|
|
17
|
+
switch (mime) {
|
|
18
|
+
case "text/plain": span.innerText = text; break;
|
|
19
|
+
case "text/html": span.innerHTML = text; removeUnsafeTags(span); break;
|
|
20
|
+
default:
|
|
21
|
+
if (/^image\//i.test(mime)) {
|
|
22
|
+
span.innerHTML = `<img src=${strings.encode(text)}/>`;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return alert(i18n`复制失败!`, 'error');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
document.body.appendChild(span);
|
|
30
|
+
var selection = document.getSelection();
|
|
31
|
+
var ranges = [];
|
|
32
|
+
for (var cx = 0, dx = selection.rangeCount; cx < dx; cx++) {
|
|
33
|
+
var range = selection.getRangeAt(cx);
|
|
34
|
+
ranges.push(range);
|
|
35
|
+
}
|
|
36
|
+
selection.removeAllRanges();
|
|
37
|
+
document.getSelection().setBaseAndExtent(span, 0, span, 1);
|
|
38
|
+
var res = document.execCommand('copy');
|
|
39
|
+
selection.removeAllRanges();
|
|
40
|
+
for (var range of ranges) {
|
|
41
|
+
selection.addRange(range);
|
|
42
|
+
}
|
|
43
|
+
remove(span);
|
|
44
|
+
if (res) alert("已复制");
|
|
45
|
+
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function removeJavascript(a, attr) {
|
|
2
|
+
if (!a.hasAttribute(attr)) return;
|
|
3
|
+
var value = a.getAttribute(attr);
|
|
4
|
+
if (/^javascript\:/i.test(value)) a.removeAttribute(attr);
|
|
5
|
+
}
|
|
6
|
+
function removeTags(a, tagName) {
|
|
7
|
+
var scripts = a.getElementsByTagName(tagName);
|
|
8
|
+
remove(scripts);
|
|
9
|
+
}
|
|
10
|
+
function removeUnsafeTags(a) {
|
|
11
|
+
removeTags(a, 'script');
|
|
12
|
+
removeTags(a, 'iframe');
|
|
13
|
+
removeTags(a, 'style');
|
|
14
|
+
removeTags(a, 'meta');
|
|
15
|
+
if (a.hasAttribute('onload')) a.removeAttribute('onload');
|
|
16
|
+
if (a.hasAttribute('onerror')) a.removeAttribute('onerror');
|
|
17
|
+
removeJavascript(a, 'src');
|
|
18
|
+
removeJavascript(a, 'href');
|
|
19
|
+
for (var c of a.children) removeUnsafeTags(c);
|
|
20
|
+
return a;
|
|
21
|
+
}
|
package/coms/zimoli/render.js
CHANGED
|
@@ -675,8 +675,17 @@ var gtValue = function () { return this.value };
|
|
|
675
675
|
var stValue = function (v) { this.value = v };
|
|
676
676
|
var gtChecked = function () { return this.checked };
|
|
677
677
|
var stChecked = function (v) { this.checked = v };
|
|
678
|
-
var gtHtml = function () {
|
|
679
|
-
|
|
678
|
+
var gtHtml = function () {
|
|
679
|
+
removeUnsafeTags(this);
|
|
680
|
+
return this.innerHTML;
|
|
681
|
+
};
|
|
682
|
+
var stHtml = function (v) {
|
|
683
|
+
var span = document.createElement('span');
|
|
684
|
+
span.innerHTML = v;
|
|
685
|
+
removeUnsafeTags(span);
|
|
686
|
+
this.innerHTML = '';
|
|
687
|
+
appendChild(this, span.childNodes);
|
|
688
|
+
};
|
|
680
689
|
class Model {
|
|
681
690
|
constructor(getScope, setScope, target) {
|
|
682
691
|
this.gs = getScope;
|
|
@@ -713,6 +722,7 @@ class Model {
|
|
|
713
722
|
return;
|
|
714
723
|
}
|
|
715
724
|
this.ss.call(this.target, value);
|
|
725
|
+
console.log(value, this.value, this.gs.call(this.target))
|
|
716
726
|
this.value = value;
|
|
717
727
|
this.bd.value = this.gs.call(this.target, value);
|
|
718
728
|
if (isFunction(this.emit?.call)) {
|
|
@@ -734,7 +744,7 @@ class Model {
|
|
|
734
744
|
}
|
|
735
745
|
}
|
|
736
746
|
var createSetter = function (elem, search) {
|
|
737
|
-
return $$eval.bind(elem, search + "=arguments[
|
|
747
|
+
return $$eval.bind(elem, search + "=arguments[1]", scopeList, elem);
|
|
738
748
|
};
|
|
739
749
|
var directives = {
|
|
740
750
|
text: createBinder2(function (value) {
|
|
@@ -812,6 +822,14 @@ var binders = {
|
|
|
812
822
|
""(attr, search) {
|
|
813
823
|
var getter = createGetter(this, search);
|
|
814
824
|
var oldValue;
|
|
825
|
+
if (/contenteditable/i.test(attr)) {
|
|
826
|
+
var v = this.value;
|
|
827
|
+
Object.defineProperty(this, 'value', {
|
|
828
|
+
get: gtHtml,
|
|
829
|
+
set: stHtml
|
|
830
|
+
});
|
|
831
|
+
if (isHandled(v)) this.value = v;
|
|
832
|
+
}
|
|
815
833
|
var hook = function () {
|
|
816
834
|
var value = getter(this);
|
|
817
835
|
if (deepEqual(value, oldValue)) return;
|
|
@@ -1138,21 +1156,49 @@ var getDeepContext = function (deep) {
|
|
|
1138
1156
|
var length = deep;
|
|
1139
1157
|
var deepL = deepcontexts.length;
|
|
1140
1158
|
while (deep-- > deepL) {
|
|
1141
|
-
deepcontexts[deep] = `with(
|
|
1159
|
+
deepcontexts[deep] = `with($$[${deep}])`;
|
|
1142
1160
|
}
|
|
1143
1161
|
return deepcontexts.slice(0, length).join('');
|
|
1144
1162
|
}
|
|
1145
|
-
var
|
|
1146
|
-
|
|
1163
|
+
var isRowCode = function (code) {
|
|
1164
|
+
var reg = /["';]/g;
|
|
1165
|
+
reg.lastIndex = 0;
|
|
1166
|
+
var reg1 = /\\[\s\S]|'/g;
|
|
1167
|
+
var reg2 = /\\[\s\S]|"/g;
|
|
1168
|
+
do {
|
|
1169
|
+
var r = reg.exec(code)
|
|
1170
|
+
if (!r) return true;
|
|
1171
|
+
var regtmp = null;
|
|
1172
|
+
if (r) switch (r[0]) {
|
|
1173
|
+
case "'": regtmp = reg1; break;
|
|
1174
|
+
case `"`: regtmp = reg2; break;
|
|
1175
|
+
case ";": return false;
|
|
1176
|
+
}
|
|
1177
|
+
if (regtmp) {
|
|
1178
|
+
regtmp.lastIndex = reg.lastIndex;
|
|
1179
|
+
do {
|
|
1180
|
+
var r = regtmp.exec(code);
|
|
1181
|
+
if (r) {
|
|
1182
|
+
r = r[0];
|
|
1183
|
+
if (r.length === 1) break;
|
|
1184
|
+
}
|
|
1185
|
+
} while (r);
|
|
1186
|
+
reg.lastIndex = regtmp.lastIndex;
|
|
1187
|
+
}
|
|
1188
|
+
} while (r);
|
|
1189
|
+
return true;
|
|
1190
|
+
}
|
|
1191
|
+
var createEval = function (deep, code) {
|
|
1192
|
+
if (isRowCode(code)) code = `return ${code}`;
|
|
1193
|
+
else code = `{${code}}`;
|
|
1194
|
+
return new Function("$$", 'event', `${getDeepContext(deep)}${code}`);
|
|
1147
1195
|
};
|
|
1148
1196
|
|
|
1149
|
-
var evalcontexts = [createEval(0)];
|
|
1150
1197
|
|
|
1151
1198
|
function $$eval(search, scopes, target = this, event) {
|
|
1152
1199
|
var length = scopes.length;
|
|
1153
|
-
var eval2 =
|
|
1154
|
-
|
|
1155
|
-
var res = eval2.call(target, scopes, search, event);
|
|
1200
|
+
var eval2 = createEval(length, search);
|
|
1201
|
+
var res = eval2.call(target, scopes, event);
|
|
1156
1202
|
return res;
|
|
1157
1203
|
}
|
|
1158
1204
|
|