@xpadev-net/niconicomments 0.2.20 → 0.2.21

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/dist/bundle.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- niconicomments.js v0.2.20
2
+ niconicomments.js v0.2.21
3
3
  (c) 2021 xpadev-net https://xpadev.net
4
4
  Released under the MIT License.
5
5
  */
@@ -25,1010 +25,1317 @@
25
25
  return _assign.apply(this, arguments);
26
26
  };
27
27
 
28
- var isDebug = false;
29
- var NiconiComments = (function () {
30
- function NiconiComments(canvas, data, initOptions) {
31
- if (initOptions === void 0) { initOptions = {
32
- useLegacy: false,
33
- formatted: false,
34
- video: null,
35
- showCollision: false,
36
- showFPS: false,
37
- showCommentCount: false,
38
- drawAllImageOnLoad: false,
39
- debug: false,
40
- enableLegacyPiP: false,
41
- keepCA: false
42
- }; }
43
- var _this = this;
44
- var options = Object.assign({
45
- useLegacy: false,
46
- formatted: false,
47
- video: null,
48
- showCollision: false,
49
- showFPS: false,
50
- showCommentCount: false,
51
- drawAllImageOnLoad: false,
52
- debug: false,
53
- enableLegacyPiP: false,
54
- keepCA: true
55
- }, initOptions);
56
- isDebug = options.debug;
57
- var constructorStart = performance.now();
58
- this.canvas = canvas;
59
- var context = canvas.getContext("2d");
60
- if (!context)
61
- throw new Error("Fail to get CanvasRenderingContext2D");
62
- this.context = context;
63
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
64
- this.context.textAlign = "start";
65
- this.context.textBaseline = "alphabetic";
66
- this.context.lineWidth = 4;
67
- this.commentYPaddingTop = 0.08;
68
- this.commentYMarginBottom = 0.24;
69
- this.fontSize = {
70
- "small": {
71
- "default": 47,
72
- "resized": 26.1
73
- },
74
- "medium": {
75
- "default": 74,
76
- "resized": 38.7
77
- },
78
- "big": {
79
- "default": 110,
80
- "resized": 61
81
- }
82
- };
83
- this.lineHeight = {
84
- "small": {
85
- "default": 1,
86
- "resized": 1
87
- },
88
- "medium": {
89
- "default": 1,
90
- "resized": 1
91
- },
92
- "big": {
93
- "default": 1.03,
94
- "resized": 1.01
95
- }
96
- };
97
- this.doubleResizeMaxWidth = {
98
- full: {
99
- legacy: 3020,
100
- default: 3550
101
- },
102
- normal: {
103
- legacy: 2540,
104
- default: 2650
105
- }
106
- };
107
- var parsedData = options.formatted ? data : this.parseData(data);
108
- this.video = options.video ? options.video : null;
109
- this.showCollision = options.showCollision;
110
- this.showFPS = options.showFPS;
111
- this.showCommentCount = options.showCommentCount;
112
- this.enableLegacyPiP = options.enableLegacyPiP;
113
- this.keepCA = options.keepCA;
114
- this.timeline = {};
115
- this.nicoScripts = { reverse: [], default: [], replace: [], ban: [] };
116
- this.collision_right = {};
117
- this.collision_left = {};
118
- this.collision_ue = {};
119
- this.collision_shita = {};
120
- this.data = [];
121
- this.lastVpos = -1;
122
- this.useLegacy = options.useLegacy;
123
- this.preRendering(parsedData, options.drawAllImageOnLoad);
124
- this.fpsCount = 0;
125
- this.fps = 0;
126
- window.setInterval(function () {
127
- _this.fps = _this.fpsCount * 2;
128
- _this.fpsCount = 0;
129
- }, 500);
130
- logger("constructor complete: ".concat(performance.now() - constructorStart, "ms"));
131
- }
132
- NiconiComments.prototype.parseData = function (data) {
133
- var parseDataStart = performance.now();
134
- var data_ = [], userList = [];
135
- for (var i = 0; i < data.length; i++) {
136
- var val = data[i];
137
- if (!val)
138
- continue;
139
- for (var key in val) {
140
- var value = val[key];
141
- if (isApiChat(value) && value["deleted"] !== 1) {
142
- var tmpParam = {
143
- "id": value["no"],
144
- "vpos": value["vpos"],
145
- "content": value["content"],
146
- "date": value["date"],
147
- "date_usec": value["date_usec"],
148
- "owner": !value["user_id"],
149
- "premium": value["premium"] === 1,
150
- "mail": [],
151
- "user_id": -1,
152
- "layer": -1
153
- };
154
- if (value["mail"]) {
155
- tmpParam["mail"] = value["mail"].split(/[\s ]/g);
156
- }
157
- if (value["content"].startsWith("/") && !value["user_id"]) {
158
- tmpParam["mail"].push("invisible");
159
- }
160
- var isUserExist = userList.indexOf(value["user_id"]);
161
- if (isUserExist === -1) {
162
- tmpParam.user_id = userList.length;
163
- userList.push(value.user_id);
164
- }
165
- else {
166
- tmpParam.user_id = isUserExist;
167
- }
168
- data_.push(tmpParam);
169
- }
170
- }
171
- }
172
- data_.sort(function (a, b) {
173
- if (a.vpos < b.vpos)
174
- return -1;
175
- if (a.vpos > b.vpos)
176
- return 1;
177
- if (a.date < b.date)
178
- return -1;
179
- if (a.date > b.date)
180
- return 1;
181
- if (a.date_usec < b.date_usec)
182
- return -1;
183
- if (a.date_usec > b.date_usec)
184
- return 1;
185
- return 0;
186
- });
187
- logger("parseData complete: ".concat(performance.now() - parseDataStart, "ms"));
188
- return data_;
189
- };
190
- NiconiComments.prototype.preRendering = function (rawData, drawAll) {
191
- var preRenderingStart = performance.now();
192
- if (this.keepCA) {
193
- rawData = changeCALayer(rawData);
194
- }
195
- var parsedData = this.getCommentPos(this.getCommentSize(this.getFont(rawData)));
196
- this.data = this.sortComment(parsedData);
197
- if (drawAll) {
198
- for (var i in parsedData) {
199
- this.getTextImage(Number(i), true);
200
- }
201
- }
202
- logger("preRendering complete: ".concat(performance.now() - preRenderingStart, "ms"));
203
- };
204
- NiconiComments.prototype.getFont = function (parsedData) {
205
- var getFontStart = performance.now();
206
- var result = [];
207
- for (var i in parsedData) {
208
- var value = parsedData[i];
209
- if (!value)
210
- continue;
211
- value.content = value.content.replace(/\t/g, "\u2003\u2003");
212
- result[i] = this.parseCommandAndNicoscript(value);
213
- }
214
- logger("getFont complete: ".concat(performance.now() - getFontStart, "ms"));
215
- return result;
216
- };
217
- NiconiComments.prototype.getCommentSize = function (parsedData) {
218
- var getCommentSizeStart = performance.now();
219
- var tmpData = groupBy(parsedData, "font", "fontSize");
220
- var result = [];
221
- for (var i in tmpData) {
222
- for (var j in tmpData[i]) {
223
- this.context.font = parseFont(i, j, this.useLegacy);
224
- for (var k in tmpData[i][j]) {
225
- var comment = tmpData[i][j][k];
226
- if (comment.invisible) {
227
- continue;
228
- }
229
- var measure = this.measureText(comment);
230
- var size = parsedData[comment.index];
231
- size.height = measure.height;
232
- size.width = measure.width;
233
- size.width_max = measure.width_max;
234
- size.width_min = measure.width_min;
235
- size.lineHeight = measure.lineHeight;
236
- if (measure.resized) {
237
- size.fontSize = measure.fontSize;
238
- this.context.font = parseFont(i, j, this.useLegacy);
239
- }
240
- result[comment.index] = size;
241
- }
242
- }
243
- }
244
- logger("getCommentSize complete: ".concat(performance.now() - getCommentSizeStart, "ms"));
245
- return result;
246
- };
247
- NiconiComments.prototype.getCommentPos = function (parsedData) {
248
- var getCommentPosStart = performance.now();
249
- var data = parsedData;
250
- for (var i in data) {
251
- var comment = data[i];
252
- if (!comment || comment.invisible) {
253
- continue;
254
- }
255
- for (var j = 0; j < comment.long * 4 / 3 + 100; j++) {
256
- if (!this.timeline[comment.vpos + j]) {
257
- this.timeline[comment.vpos + j] = [];
258
- }
259
- if (!this.collision_right[comment.vpos + j]) {
260
- this.collision_right[comment.vpos + j] = [];
261
- }
262
- if (!this.collision_left[comment.vpos + j]) {
263
- this.collision_left[comment.vpos + j] = [];
264
- }
265
- if (!this.collision_ue[comment.vpos + j]) {
266
- this.collision_ue[comment.vpos + j] = [];
267
- }
268
- if (!this.collision_shita[comment.vpos + j]) {
269
- this.collision_shita[comment.vpos + j] = [];
270
- }
271
- }
272
- if (comment.loc === "naka") {
273
- var posY = 0, is_break = false, is_change = true, count = 0, beforeVpos = Math.round(-240 / ((1680 + comment.width_max) / (comment.long + 125))) - 100;
274
- if (1080 < comment.height) {
275
- posY = (comment.height - 1080) / -2;
276
- }
277
- else {
278
- while (is_change && count < 10) {
279
- is_change = false;
280
- count++;
281
- for (var j = beforeVpos; j < comment.long; j++) {
282
- var vpos = comment.vpos + j;
283
- var left_pos = 1680 - (1680 + comment.width_max) / (comment.long + 125) * j;
284
- if (left_pos + comment.width_max >= 1880) {
285
- for (var k in this.collision_right[vpos]) {
286
- var l = this.collision_right[vpos][k];
287
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
288
- if (data[l].posY + data[l].height > posY) {
289
- posY = data[l].posY + data[l].height;
290
- is_change = true;
291
- }
292
- if (posY + comment.height > 1080) {
293
- if (1080 < comment.height) {
294
- posY = (comment.height - 1080) / -2;
295
- }
296
- else {
297
- posY = Math.floor(Math.random() * (1080 - comment.height));
298
- }
299
- is_break = true;
300
- break;
301
- }
302
- }
303
- }
304
- if (is_break) {
305
- break;
306
- }
307
- }
308
- if (left_pos <= 40) {
309
- for (var k in this.collision_left[vpos]) {
310
- var l = this.collision_left[vpos][k];
311
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
312
- if (data[l].posY + data[l].height > posY) {
313
- posY = data[l].posY + data[l].height;
314
- is_change = true;
315
- }
316
- if (posY + comment.height > 1080) {
317
- if (1080 < comment.height) {
318
- posY = 0;
319
- }
320
- else {
321
- posY = Math.random() * (1080 - comment.height);
322
- }
323
- is_break = true;
324
- break;
325
- }
326
- }
327
- }
328
- if (is_break) {
329
- break;
330
- }
331
- }
332
- }
333
- if (is_break) {
334
- break;
335
- }
336
- }
337
- }
338
- for (var j = beforeVpos; j < comment.long + 125; j++) {
339
- var vpos = comment.vpos + j;
340
- var left_pos = 1680 - (1680 + comment.width_max) / (comment.long + 125) * j;
341
- arrayPush(this.timeline, vpos, i);
342
- if (left_pos + comment.width_max >= 1880) {
343
- arrayPush(this.collision_right, vpos, i);
344
- }
345
- if (left_pos <= 40) {
346
- arrayPush(this.collision_left, vpos, i);
347
- }
348
- }
349
- parsedData[i].posY = posY;
350
- }
351
- else {
352
- var posY = 0, is_break = false, is_change = true, count = 0, collision = void 0;
353
- if (comment.loc === "ue") {
354
- collision = this.collision_ue;
355
- }
356
- else if (comment.loc === "shita") {
357
- collision = this.collision_shita;
358
- }
359
- while (is_change && count < 10) {
360
- is_change = false;
361
- count++;
362
- for (var j = 0; j < comment.long; j++) {
363
- var vpos = comment.vpos + j;
364
- for (var k in collision[vpos]) {
365
- var l = collision[vpos][k];
366
- if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
367
- if (data[l].posY + data[l].height > posY) {
368
- posY = data[l].posY + data[l].height;
369
- is_change = true;
370
- }
371
- if (posY + comment.height > 1080) {
372
- if (1000 <= comment.height) {
373
- posY = 0;
374
- }
375
- else {
376
- posY = Math.floor(Math.random() * (1080 - comment.height));
377
- }
378
- is_break = true;
379
- break;
380
- }
381
- }
382
- }
383
- if (is_break) {
384
- break;
385
- }
386
- }
387
- }
388
- for (var j = 0; j < comment.long; j++) {
389
- var vpos = comment.vpos + j;
390
- arrayPush(this.timeline, vpos, i);
391
- if (comment.loc === "ue") {
392
- arrayPush(this.collision_ue, vpos, i);
393
- }
394
- else {
395
- arrayPush(this.collision_shita, vpos, i);
396
- }
397
- }
398
- parsedData[i].posY = posY;
399
- }
400
- }
401
- logger("getCommentPos complete: ".concat(performance.now() - getCommentPosStart, "ms"));
402
- return parsedData;
403
- };
404
- NiconiComments.prototype.sortComment = function (parsedData) {
405
- var sortCommentStart = performance.now();
406
- for (var vpos in this.timeline) {
407
- if (!this.timeline[vpos])
408
- continue;
409
- var owner = [], user = [];
410
- for (var _i = 0, _a = this.timeline[vpos]; _i < _a.length; _i++) {
411
- var i = _a[_i];
412
- if (parsedData[i].owner) {
413
- owner.push(i);
414
- }
415
- else {
416
- user.push(i);
417
- }
418
- }
419
- this.timeline[vpos] = owner.concat(user);
420
- }
421
- logger("parseData complete: ".concat(performance.now() - sortCommentStart, "ms"));
422
- return parsedData;
423
- };
424
- NiconiComments.prototype.measureText = function (comment) {
425
- var width, width_max, width_min, height, width_arr = [], lines = comment.content.split("\n");
426
- if (!comment.lineHeight)
427
- comment.lineHeight = this.lineHeight[comment.size].default;
428
- if (!comment.resized && !comment.ender) {
429
- if (comment.size === "big" && lines.length > 2) {
430
- comment.fontSize = this.fontSize.big.resized;
431
- comment.lineHeight = this.lineHeight.big.resized;
432
- comment.resized = true;
433
- comment.tateresized = true;
434
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
435
- }
436
- else if (comment.size === "medium" && lines.length > 4) {
437
- comment.fontSize = this.fontSize.medium.resized;
438
- comment.lineHeight = this.lineHeight.medium.resized;
439
- comment.resized = true;
440
- comment.tateresized = true;
441
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
442
- }
443
- else if (comment.size === "small" && lines.length > 6) {
444
- comment.fontSize = this.fontSize.small.resized;
445
- comment.lineHeight = this.lineHeight.small.resized;
446
- comment.resized = true;
447
- comment.tateresized = true;
448
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
449
- }
450
- }
451
- for (var i = 0; i < lines.length; i++) {
452
- var measure = this.context.measureText(lines[i]);
453
- width_arr.push(measure.width);
454
- }
455
- width = width_arr.reduce(function (p, c) { return p + c; }, 0) / width_arr.length;
456
- width_max = Math.max.apply(Math, width_arr);
457
- width_min = Math.min.apply(Math, width_arr);
458
- height = (comment.fontSize * comment.lineHeight * (1 + this.commentYPaddingTop) * lines.length) + (this.commentYMarginBottom * comment.fontSize);
459
- if (comment.loc !== "naka" && !comment.tateresized) {
460
- if (comment.full && width_max > 1930) {
461
- comment.fontSize -= 2;
462
- comment.resized = true;
463
- comment.yokoResized = true;
464
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
465
- return this.measureText(comment);
466
- }
467
- else if (!comment.full && width_max > 1440) {
468
- comment.fontSize -= 1;
469
- comment.resized = true;
470
- comment.yokoResized = true;
471
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
472
- return this.measureText(comment);
473
- }
474
- }
475
- else if (comment.loc !== "naka" && comment.tateresized && (comment.full && width_max > 2120 || !comment.full && width_max > 1440) && !comment.yokoResized) {
476
- comment.fontSize = this.fontSize[comment.size].default;
477
- comment.lineHeight = this.lineHeight[comment.size].default * 1.05;
478
- comment.resized = true;
479
- comment.yokoResized = true;
480
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
481
- return this.measureText(comment);
482
- }
483
- else if (comment.loc !== "naka" && comment.tateresized && comment.yokoResized) {
484
- if (comment.full && width_max > this.doubleResizeMaxWidth.full[this.useLegacy ? "legacy" : "default"]) {
485
- comment.fontSize -= 1;
486
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
487
- return this.measureText(comment);
488
- }
489
- else if (!comment.full && width_max > this.doubleResizeMaxWidth.normal[this.useLegacy ? "legacy" : "default"]) {
490
- comment.fontSize -= 1;
491
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
492
- return this.measureText(comment);
493
- }
494
- }
495
- return {
496
- "width": width,
497
- "width_max": width_max,
498
- "width_min": width_min,
499
- "height": height,
500
- "resized": comment.resized,
501
- "fontSize": comment.fontSize,
502
- "lineHeight": comment.lineHeight
503
- };
504
- };
505
- NiconiComments.prototype.drawText = function (comment, vpos) {
506
- var reverse = false;
507
- for (var i in this.nicoScripts.reverse) {
508
- var range = this.nicoScripts.reverse[i];
509
- if ((range.target === "コメ" && comment.owner) || (range.target === "投コメ" && !comment.owner)) {
510
- break;
511
- }
512
- if (range.start < vpos && vpos < range.end) {
513
- reverse = true;
514
- }
515
- }
516
- for (var i in this.nicoScripts.ban) {
517
- var range = this.nicoScripts.ban[i];
518
- if (range.start < vpos && vpos < range.end) {
519
- return;
520
- }
521
- }
522
- var posX = (1920 - comment.width_max) / 2, posY = comment.posY;
523
- if (comment.loc === "naka") {
524
- if (reverse) {
525
- posX = 240 + (1680 + comment.width_max) / (comment.long + 125) * (vpos - comment.vpos + 100) - comment.width_max;
526
- }
527
- else {
528
- posX = 1680 - (1680 + comment.width_max) / (comment.long + 125) * (vpos - comment.vpos + 100);
529
- }
530
- }
531
- else if (comment.loc === "shita") {
532
- posY = 1080 - comment.posY - comment.height;
533
- }
534
- if (comment.image && comment.image !== true) {
535
- this.context.drawImage(comment.image, posX, posY);
536
- }
537
- if (this.showCollision) {
538
- this.context.strokeStyle = "rgba(0,255,255,1)";
539
- this.context.strokeRect(posX, posY, comment.width_max, comment.height);
540
- var lines = comment.content.split("\n");
541
- for (var i in lines) {
542
- var linePosY = (Number(i) + 1) * (comment.fontSize * comment.lineHeight) * (1 + this.commentYPaddingTop);
543
- this.context.strokeStyle = "rgba(255,255,0,0.5)";
544
- this.context.strokeRect(posX, posY + linePosY, comment.width_max, comment.fontSize * comment.lineHeight * -1);
545
- }
546
- }
547
- };
548
- NiconiComments.prototype.getTextImage = function (i, preRendering) {
549
- var _this = this;
550
- if (preRendering === void 0) { preRendering = false; }
551
- var value = this.data[i];
552
- if (!value || value.invisible)
553
- return;
554
- var image = document.createElement("canvas");
555
- image.width = value.width_max;
556
- image.height = value.height;
557
- var context = image.getContext("2d");
558
- if (!context)
559
- throw new Error("Fail to get CanvasRenderingContext2D");
560
- context.strokeStyle = "rgba(0,0,0,0.7)";
561
- context.textAlign = "start";
562
- context.textBaseline = "alphabetic";
563
- context.lineWidth = 4;
564
- context.font = parseFont(value.font, value.fontSize, this.useLegacy);
565
- if (value._live) {
566
- var rgb = hex2rgb(value.color);
567
- context.fillStyle = "rgba(".concat(rgb[0], ",").concat(rgb[1], ",").concat(rgb[2], ",0.5)");
568
- }
569
- else {
570
- context.fillStyle = value.color;
571
- }
572
- if (value.color === "#000000") {
573
- context.strokeStyle = "rgba(255,255,255,0.7)";
574
- }
575
- var lines = value.content.split("\n");
576
- for (var i_1 in lines) {
577
- var line = lines[i_1], posY = void 0;
578
- posY = (Number(i_1) + 1) * (value.fontSize * value.lineHeight) * (1 + this.commentYPaddingTop);
579
- context.strokeText(line, 0, posY);
580
- context.fillText(line, 0, posY);
581
- }
582
- this.data[i].image = image;
583
- if (preRendering)
584
- return;
585
- setTimeout(function () {
586
- if (_this.data[i].image)
587
- delete _this.data[i].image;
588
- }, 5000);
589
- };
590
- NiconiComments.prototype.parseCommand = function (comment) {
591
- var metadata = comment.mail, loc = null, size = null, fontSize = null, color = null, font = null, full = false, ender = false, _live = false, invisible = false, long = null;
592
- for (var i in metadata) {
593
- var command = metadata[i].toLowerCase();
594
- var match = command.match(/^@([0-9.]+)/);
595
- if (match) {
596
- long = match[1];
597
- }
598
- if (loc === null) {
599
- switch (command) {
600
- case "ue":
601
- loc = "ue";
602
- break;
603
- case "shita":
604
- loc = "shita";
605
- break;
606
- }
607
- }
608
- if (size === null) {
609
- switch (command) {
610
- case "big":
611
- size = "big";
612
- fontSize = this.fontSize.big.default;
613
- break;
614
- case "small":
615
- size = "small";
616
- fontSize = this.fontSize.small.default;
617
- break;
618
- }
619
- }
620
- if (color === null) {
621
- switch (command) {
622
- case "white":
623
- color = "#FFFFFF";
624
- break;
625
- case "red":
626
- color = "#FF0000";
627
- break;
628
- case "pink":
629
- color = "#FF8080";
630
- break;
631
- case "orange":
632
- color = "#FFC000";
633
- break;
634
- case "yellow":
635
- color = "#FFFF00";
636
- break;
637
- case "green":
638
- color = "#00FF00";
639
- break;
640
- case "cyan":
641
- color = "#00FFFF";
642
- break;
643
- case "blue":
644
- color = "#0000FF";
645
- break;
646
- case "purple":
647
- color = "#C000FF";
648
- break;
649
- case "black":
650
- color = "#000000";
651
- break;
652
- case "white2":
653
- case "niconicowhite":
654
- color = "#CCCC99";
655
- break;
656
- case "red2":
657
- case "truered":
658
- color = "#CC0033";
659
- break;
660
- case "pink2":
661
- color = "#FF33CC";
662
- break;
663
- case "orange2":
664
- case "passionorange":
665
- color = "#FF6600";
666
- break;
667
- case "yellow2":
668
- case "madyellow":
669
- color = "#999900";
670
- break;
671
- case "green2":
672
- case "elementalgreen":
673
- color = "#00CC66";
674
- break;
675
- case "cyan2":
676
- color = "#00CCCC";
677
- break;
678
- case "blue2":
679
- case "marineblue":
680
- color = "#3399FF";
681
- break;
682
- case "purple2":
683
- case "nobleviolet":
684
- color = "#6633CC";
685
- break;
686
- case "black2":
687
- color = "#666666";
688
- break;
689
- default:
690
- var match_1 = command.match(/#[0-9a-z]{3,6}/);
691
- if (match_1 && comment.premium) {
692
- color = match_1[0].toUpperCase();
693
- }
694
- break;
695
- }
696
- }
697
- if (font === null) {
698
- switch (command) {
699
- case "gothic":
700
- font = "gothic";
701
- break;
702
- case "mincho":
703
- font = "mincho";
704
- break;
705
- }
706
- }
707
- switch (command) {
708
- case "full":
709
- full = true;
710
- break;
711
- case "ender":
712
- ender = true;
713
- break;
714
- case "_live":
715
- _live = true;
716
- break;
717
- case "invisible":
718
- invisible = true;
719
- break;
720
- }
721
- }
722
- return { loc: loc, size: size, fontSize: fontSize, color: color, font: font, full: full, ender: ender, _live: _live, invisible: invisible, long: long };
723
- };
724
- NiconiComments.prototype.parseCommandAndNicoscript = function (comment) {
725
- var data = this.parseCommand(comment), nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
726
- if (nicoscript) {
727
- switch (nicoscript[1]) {
728
- case "デフォルト":
729
- this.nicoScripts.default.push({
730
- start: comment.vpos,
731
- long: data.long === null ? null : Math.floor(data.long * 100),
732
- color: data.color,
733
- size: data.size,
734
- font: data.font,
735
- loc: data.loc
736
- });
737
- break;
738
- case "逆":
739
- var reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
740
- if (!reverse)
741
- reverse = [];
742
- if (!reverse[1]) {
743
- reverse[1] = "全";
744
- }
745
- if (data.long === null) {
746
- data.long = 30;
747
- }
748
- this.nicoScripts.reverse.push({
749
- start: comment.vpos,
750
- end: comment.vpos + (data.long * 100),
751
- target: reverse[1]
752
- });
753
- break;
754
- case "コメント禁止":
755
- if (data.long === null) {
756
- data.long = 30;
757
- }
758
- this.nicoScripts.reverse.push({
759
- start: comment.vpos,
760
- end: comment.vpos + (data.long * 100),
761
- });
762
- break;
763
- case "置換":
764
- var content = comment.content.split(""), quote = "", last_i = "", string = "", result = [];
765
- for (var _i = 0, _a = content.slice(4); _i < _a.length; _i++) {
766
- var i = _a[_i];
767
- if (i.match(/["'「]/) && quote === "") {
768
- quote = i;
769
- }
770
- else if (i.match(/["']/) && quote === i && last_i !== "\\") {
771
- result.push(replaceAll(string, "\\n", "\n"));
772
- quote = "";
773
- string = "";
774
- }
775
- else if (i.match(/」/) && quote === "「") {
776
- result.push(string);
777
- quote = "";
778
- string = "";
779
- }
780
- else if (quote === "" && i.match(/[\s ]/)) {
781
- if (string) {
782
- result.push(string);
783
- string = "";
784
- }
785
- }
786
- else {
787
- string += i;
788
- }
789
- last_i = i;
790
- }
791
- result.push(string);
792
- this.nicoScripts.replace.push({
793
- start: comment.vpos,
794
- long: data.long === null ? null : Math.floor(data.long * 100),
795
- keyword: result[0],
796
- replace: result[1] || "",
797
- range: result[2] || "単",
798
- target: result[3] || "コメ",
799
- condition: result[4] || "部分一致",
800
- color: data.color,
801
- size: data.size,
802
- font: data.font,
803
- loc: data.loc
804
- });
805
- break;
806
- }
807
- data.invisible = true;
808
- }
809
- var color = "#FFFFFF", size = "medium", font = "defont", loc = "naka";
810
- for (var i in this.nicoScripts.default) {
811
- if (this.nicoScripts.default[i].long !== null && this.nicoScripts.default[i].start + this.nicoScripts.default[i].long < comment.vpos) {
812
- this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
813
- continue;
814
- }
815
- if (this.nicoScripts.default[i].loc) {
816
- loc = this.nicoScripts.default[i].loc;
817
- }
818
- if (this.nicoScripts.default[i].color) {
819
- color = this.nicoScripts.default[i].color;
820
- }
821
- if (this.nicoScripts.default[i].size) {
822
- size = this.nicoScripts.default[i].size;
823
- }
824
- if (this.nicoScripts.default[i].font) {
825
- font = this.nicoScripts.default[i].font;
826
- }
827
- }
828
- for (var i in this.nicoScripts.replace) {
829
- if (this.nicoScripts.replace[i].long !== null && this.nicoScripts.replace[i].start + this.nicoScripts.replace[i].long < comment.vpos) {
830
- this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
831
- continue;
832
- }
833
- var item = this.nicoScripts.replace[i];
834
- if ((item.target === "コメ" && comment.owner) || (item.target === "投コメ" && !comment.owner) || (item.target === "含まない" && comment.owner))
835
- continue;
836
- if ((item.condition === "完全一致" && comment.content === item.keyword) || (item.condition === "部分一致" && comment.content.indexOf(item.keyword) !== -1)) {
837
- if (item.range === "単") {
838
- comment.content = replaceAll(comment.content, item.keyword, item.replace);
839
- }
840
- else {
841
- comment.content = item.replace;
842
- }
843
- if (item.loc) {
844
- loc = item.loc;
845
- }
846
- if (item.color) {
847
- color = item.color;
848
- }
849
- if (item.size) {
850
- size = item.size;
851
- }
852
- if (item.font) {
853
- font = item.font;
854
- }
855
- }
856
- }
857
- if (!data.loc) {
858
- data.loc = loc;
859
- }
860
- if (!data.color) {
861
- data.color = color;
862
- }
863
- if (!data.size) {
864
- data.size = size;
865
- data.fontSize = this.fontSize[data.size].default;
866
- }
867
- if (!data.font) {
868
- data.font = font;
869
- }
870
- if (!data.long) {
871
- data.long = 300;
872
- }
873
- else {
874
- data.long = Math.floor(Number(data.long) * 100);
875
- }
876
- return _assign(_assign({}, comment), data);
877
- };
878
- NiconiComments.prototype.drawCanvas = function (vpos) {
879
- var drawCanvasStart = performance.now();
880
- if (this.lastVpos === vpos)
881
- return;
882
- this.lastVpos = vpos;
883
- this.fpsCount++;
884
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
885
- if (this.video) {
886
- var offsetX = void 0, offsetY = void 0, scale = void 0, height = this.canvas.height / this.video.videoHeight, width = this.canvas.width / this.video.videoWidth;
887
- if (this.enableLegacyPiP ? height > width : height < width) {
888
- scale = width;
889
- }
890
- else {
891
- scale = height;
892
- }
893
- offsetX = (this.canvas.width - this.video.videoWidth * scale) * 0.5;
894
- offsetY = (this.canvas.height - this.video.videoHeight * scale) * 0.5;
895
- this.context.drawImage(this.video, offsetX, offsetY, this.video.videoWidth * scale, this.video.videoHeight * scale);
896
- }
897
- if (this.timeline[vpos]) {
898
- for (var i in this.timeline[vpos]) {
899
- var index = this.timeline[vpos][Number(i)];
900
- var comment = this.data[index];
901
- if (!comment || comment.invisible) {
902
- continue;
903
- }
904
- if (comment.image === undefined) {
905
- this.getTextImage(index);
906
- }
907
- try {
908
- this.drawText(comment, vpos);
909
- }
910
- catch (e) {
911
- comment.image = false;
912
- }
913
- }
914
- }
915
- if (this.showFPS) {
916
- this.context.font = parseFont("defont", 60, this.useLegacy);
917
- this.context.fillStyle = "#00FF00";
918
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
919
- this.context.strokeText("FPS:" + this.fps, 100, 100);
920
- this.context.fillText("FPS:" + this.fps, 100, 100);
921
- }
922
- if (this.showCommentCount) {
923
- this.context.font = parseFont("defont", 60, this.useLegacy);
924
- this.context.fillStyle = "#00FF00";
925
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
926
- if (this.timeline[vpos]) {
927
- this.context.strokeText("Count:" + this.timeline[vpos].length, 100, 200);
928
- this.context.fillText("Count:" + this.timeline[vpos].length, 100, 200);
929
- }
930
- else {
931
- this.context.strokeText("Count:0", 100, 200);
932
- this.context.fillText("Count:0", 100, 200);
933
- }
934
- }
935
- logger("drawCanvas complete: ".concat(performance.now() - drawCanvasStart, "ms"));
936
- };
937
- NiconiComments.prototype.clear = function () {
938
- this.context.clearRect(0, 0, 1920, 1080);
939
- };
940
- return NiconiComments;
941
- }());
942
- var groupBy = function (array, key, key2) {
943
- var data = {};
944
- for (var i in array) {
945
- if (!data[array[i][key]]) {
946
- data[array[i][key]] = {};
947
- }
948
- if (!data[array[i][key]][array[i][key2]]) {
949
- data[array[i][key]][array[i][key2]] = [];
950
- }
951
- array[i].index = i;
952
- data[array[i][key]][array[i][key2]].push(array[i]);
953
- }
954
- return data;
955
- };
956
- var parseFont = function (font, size, useLegacy) {
957
- switch (font) {
958
- case "gothic":
959
- return "normal 400 ".concat(size, "px \"\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53\", \"\u6E38\u30B4\u30B7\u30C3\u30AF\", \"Yu Gothic\", YuGothic, yugothic, YuGo-Medium");
960
- case "mincho":
961
- return "normal 400 ".concat(size, "px \"\u6E38\u660E\u671D\u4F53\", \"\u6E38\u660E\u671D\", \"Yu Mincho\", YuMincho, yumincho, YuMin-Medium");
962
- default:
963
- if (useLegacy) {
964
- return "normal 600 ".concat(size, "px Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
965
- }
966
- else {
967
- return "normal 600 ".concat(size, "px sans-serif, Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
968
- }
969
- }
970
- };
971
- var arrayPush = function (array, key, push) {
972
- if (!array) {
973
- array = {};
974
- }
975
- if (!array[key]) {
976
- array[key] = [];
977
- }
978
- array[key].push(push);
979
- };
980
- var hex2rgb = function (hex) {
981
- if (hex.slice(0, 1) === "#")
982
- hex = hex.slice(1);
983
- if (hex.length === 3)
984
- hex = hex.slice(0, 1) + hex.slice(0, 1) + hex.slice(1, 2) + hex.slice(1, 2) + hex.slice(2, 3) + hex.slice(2, 3);
985
- return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)].map(function (str) {
986
- return parseInt(str, 16);
987
- });
28
+ var typeGuard = {
29
+ formatted: {
30
+ comment: function (i) {
31
+ return typeVerify(i, ["id", "vpos", "content", "date", "date_usec", "owner", "premium", "mail", "user_id", "layer"]);
32
+ },
33
+ comments: function (i) {
34
+ if (typeof i !== "object")
35
+ return false;
36
+ for (var _i = 0, i_1 = i; _i < i_1.length; _i++) {
37
+ var item = i_1[_i];
38
+ if (!typeGuard.formatted.comment(item))
39
+ return false;
40
+ }
41
+ return true;
42
+ },
43
+ legacyComment: function (i) {
44
+ return typeVerify(i, ["id", "vpos", "content", "date", "owner", "premium", "mail"]);
45
+ },
46
+ legacyComments: function (i) {
47
+ if (typeof i !== "object")
48
+ return false;
49
+ for (var _i = 0, i_2 = i; _i < i_2.length; _i++) {
50
+ var item = i_2[_i];
51
+ if (!typeGuard.formatted.legacyComment(item))
52
+ return false;
53
+ }
54
+ return true;
55
+ }
56
+ },
57
+ legacy: {
58
+ rawApiResponses: function (i) {
59
+ if (typeof i !== "object")
60
+ return false;
61
+ for (var _i = 0, i_3 = i; _i < i_3.length; _i++) {
62
+ var itemWrapper = i_3[_i];
63
+ for (var _a = 0, itemWrapper_1 = itemWrapper; _a < itemWrapper_1.length; _a++) {
64
+ var item = itemWrapper_1[_a];
65
+ if (!(item.chat && typeGuard.legacy.apiChat(item) || typeGuard.legacy.apiGlobalNumRes(item) || typeGuard.legacy.apiLeaf(item) || typeGuard.legacy.apiPing(item) || typeGuard.legacy.apiThread(item))) {
66
+ return false;
67
+ }
68
+ }
69
+ }
70
+ return true;
71
+ },
72
+ apiChat: function (i) {
73
+ return typeVerify(i, ["anonymity", "content", "date", "date_usec", "no", "thread", "vpos"]);
74
+ },
75
+ apiGlobalNumRes: function (i) {
76
+ return typeVerify(i, ["num_res", "thread"]);
77
+ },
78
+ apiLeaf: function (i) {
79
+ return typeVerify(i, ["count", "thread"]);
80
+ },
81
+ apiPing: function (i) {
82
+ return typeVerify(i, ["content"]);
83
+ },
84
+ apiThread: function (i) {
85
+ return typeVerify(i, ["resultcode", "revision", "server_time", "thread", "ticket"]);
86
+ },
87
+ },
88
+ niconicome: {
89
+ xmlDocument: function (i) {
90
+ if (!i.documentElement || i.documentElement.nodeName !== "packet")
91
+ return false;
92
+ if (!i.documentElement.children)
93
+ return false;
94
+ for (var index in Array.from(i.documentElement.children)) {
95
+ var value = i.documentElement.children[index];
96
+ if (index === "0") {
97
+ if (value.nodeName !== "thread" || !typeAttributeVerify(value, ["resultcode", "thread", "server_time", "last_res", "revision"]))
98
+ return false;
99
+ }
100
+ else {
101
+ if (value.nodeName !== "chat" || !typeAttributeVerify(value, ["thread", "no", "vpos", "date", "date_usec", "anonymity", "user_id", "mail", "leaf", "premium", "score"]))
102
+ return false;
103
+ }
104
+ }
105
+ return true;
106
+ }
107
+ },
108
+ legacyOwner: {
109
+ comments: function (i) {
110
+ var lists = i.split("\n");
111
+ for (var list in lists) {
112
+ if (list.split(":").length < 3) {
113
+ return false;
114
+ }
115
+ }
116
+ return true;
117
+ }
118
+ },
119
+ owner: {
120
+ comment: function (i) {
121
+ return typeVerify(i, ["time", "command", "comment"]);
122
+ },
123
+ comments: function (i) {
124
+ if (typeof i !== "object")
125
+ return false;
126
+ for (var _i = 0, i_4 = i; _i < i_4.length; _i++) {
127
+ var item = i_4[_i];
128
+ if (!typeGuard.owner.comment(item))
129
+ return false;
130
+ }
131
+ return true;
132
+ }
133
+ },
134
+ v1: {
135
+ comment: function (i) {
136
+ return typeVerify(i, ["id", "no", "vposMs", "body", "commands", "userId", "isPremium", "score", "postedAt", "nicoruCount", "nicoruId", "source", "isMyPost"]);
137
+ },
138
+ thread: function (i) {
139
+ if (!typeVerify(i, ["id", "fork", "commentCount", "comments"]))
140
+ return false;
141
+ for (var _i = 0, _a = i.comments; _i < _a.length; _i++) {
142
+ var item = _a[_i];
143
+ if (!typeGuard.v1.comment(item))
144
+ return false;
145
+ }
146
+ return true;
147
+ },
148
+ threads: function (i) {
149
+ if (typeof i !== "object")
150
+ return false;
151
+ for (var _i = 0, i_5 = i; _i < i_5.length; _i++) {
152
+ var item = i_5[_i];
153
+ if (!typeGuard.v1.thread(item))
154
+ return false;
155
+ }
156
+ return true;
157
+ },
158
+ }
159
+ };
160
+ var typeVerify = function (item, keys) {
161
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
162
+ var key = keys_1[_i];
163
+ if (item[key] === undefined)
164
+ return false;
165
+ }
166
+ return true;
167
+ };
168
+ var typeAttributeVerify = function (item, keys) {
169
+ for (var _i = 0, keys_2 = keys; _i < keys_2.length; _i++) {
170
+ var key = keys_2[_i];
171
+ if (item.getAttribute(key) === null)
172
+ return false;
173
+ }
174
+ return true;
988
175
  };
989
- var replaceAll = function (string, target, replace) {
990
- var count = 0;
991
- while (string.indexOf(target) !== -1 && count < 100) {
992
- string = string.replace(target, replace);
993
- count++;
994
- }
995
- return string;
996
- };
997
- var isApiChat = function (item) {
998
- return item.no && item.vpos && item.content;
999
- };
1000
- var logger = function (msg) {
1001
- if (isDebug)
1002
- console.debug(msg);
176
+
177
+ var convert2formattedComment = function (data, type) {
178
+ var result = [];
179
+ if (typeGuard.niconicome.xmlDocument(data) && type === "niconicome") {
180
+ result = fromNiconicome(data);
181
+ }
182
+ else if (typeGuard.formatted.legacyComments(data) && type === "formatted") {
183
+ result = fromFormatted(data);
184
+ }
185
+ else if (typeGuard.legacy.rawApiResponses(data) && type === "legacy") {
186
+ result = fromLegacy(data);
187
+ }
188
+ else if (typeGuard.owner.comments(data) && type === "owner") {
189
+ result = fromOwner(data);
190
+ }
191
+ else if (typeGuard.v1.threads(data) && type === "v1") {
192
+ result = fromV1(data);
193
+ }
194
+ else {
195
+ throw new Error("unknown input format");
196
+ }
197
+ return sort(result);
198
+ };
199
+ var fromNiconicome = function (data) {
200
+ var data_ = [], userList = [];
201
+ for (var _i = 0, _a = Array.from(data.documentElement.children); _i < _a.length; _i++) {
202
+ var item = _a[_i];
203
+ if (item.nodeName !== "chat")
204
+ continue;
205
+ var tmpParam = {
206
+ id: Number(item.getAttribute("no")),
207
+ vpos: Number(item.getAttribute("vpos")),
208
+ content: item.innerHTML,
209
+ date: Number(item.getAttribute("date")),
210
+ date_usec: Number(item.getAttribute("date_usec")),
211
+ owner: !item.getAttribute("user_id"),
212
+ premium: item.getAttribute("premium") === "1",
213
+ mail: [],
214
+ user_id: -1,
215
+ layer: -1
216
+ };
217
+ if (item.getAttribute("mail")) {
218
+ tmpParam.mail = item.getAttribute("mail").split(/[\s ]/g);
219
+ }
220
+ if (tmpParam.content.startsWith("/") && tmpParam.owner) {
221
+ tmpParam.mail.push("invisible");
222
+ }
223
+ var isUserExist = userList.indexOf(item.getAttribute("user_id"));
224
+ if (isUserExist === -1) {
225
+ tmpParam.user_id = userList.length;
226
+ userList.push(item.getAttribute("user_id"));
227
+ }
228
+ else {
229
+ tmpParam.user_id = isUserExist;
230
+ }
231
+ data_.push(tmpParam);
232
+ }
233
+ return data_;
234
+ };
235
+ var fromFormatted = function (data) {
236
+ var tmpData = data;
237
+ if (!typeGuard.formatted.comments(data)) {
238
+ for (var i in tmpData) {
239
+ tmpData[i].layer = -1;
240
+ tmpData[i].user_id = 0;
241
+ if (!tmpData[i].date_usec)
242
+ tmpData[i].date_usec = 0;
243
+ }
244
+ }
245
+ return tmpData;
246
+ };
247
+ var fromLegacy = function (data) {
248
+ var data_ = [], userList = [];
249
+ for (var i = 0; i < data.length; i++) {
250
+ var val = data[i];
251
+ if (!val)
252
+ continue;
253
+ for (var key in val) {
254
+ var value = val[key];
255
+ if (typeGuard.legacy.apiChat(value) && value.deleted !== 1) {
256
+ var tmpParam = {
257
+ id: value.no,
258
+ vpos: value.vpos,
259
+ content: value.content,
260
+ date: value.date,
261
+ date_usec: value.date_usec || 0,
262
+ owner: !value.user_id,
263
+ premium: value.premium === 1,
264
+ mail: [],
265
+ user_id: -1,
266
+ layer: -1
267
+ };
268
+ if (value.mail) {
269
+ tmpParam.mail = value.mail.split(/[\s ]/g);
270
+ }
271
+ if (value.content.startsWith("/") && !value.user_id) {
272
+ tmpParam.mail.push("invisible");
273
+ }
274
+ var isUserExist = userList.indexOf(value.mail);
275
+ if (isUserExist === -1) {
276
+ tmpParam.user_id = userList.length;
277
+ userList.push(value.user_id);
278
+ }
279
+ else {
280
+ tmpParam.user_id = isUserExist;
281
+ }
282
+ data_.push(tmpParam);
283
+ }
284
+ }
285
+ }
286
+ return data_;
287
+ };
288
+ var fromOwner = function (data) {
289
+ var data_ = [];
290
+ for (var i = 0; i < data.length; i++) {
291
+ var value = data[i];
292
+ var tmpParam = {
293
+ id: i,
294
+ vpos: time2vpos(value.time),
295
+ content: value.comment,
296
+ date: i,
297
+ date_usec: 0,
298
+ owner: true,
299
+ premium: true,
300
+ mail: [],
301
+ user_id: -1,
302
+ layer: -1
303
+ };
304
+ if (value.command) {
305
+ tmpParam.mail = value.command.split(/[\s ]/g);
306
+ }
307
+ if (tmpParam.content.startsWith("/")) {
308
+ tmpParam.mail.push("invisible");
309
+ }
310
+ data_.push(tmpParam);
311
+ }
312
+ return data_;
313
+ };
314
+ var fromV1 = function (data) {
315
+ var data_ = [], userList = [];
316
+ for (var i = 0; i < data.length; i++) {
317
+ var val = data[i].comments, forkName = data[i].fork;
318
+ for (var key in val) {
319
+ var value = val[key];
320
+ var tmpParam = {
321
+ id: value.no,
322
+ vpos: Math.floor(value.vposMs * 10),
323
+ content: value.body,
324
+ date: date2time(value.postedAt),
325
+ date_usec: 0,
326
+ owner: forkName === "owner",
327
+ premium: value.isPremium,
328
+ mail: value.commands,
329
+ user_id: -1,
330
+ layer: -1
331
+ };
332
+ if (tmpParam.content.startsWith("/") && tmpParam.owner) {
333
+ tmpParam.mail.push("invisible");
334
+ }
335
+ var isUserExist = userList.indexOf(value.userId);
336
+ if (isUserExist === -1) {
337
+ tmpParam.user_id = userList.length;
338
+ userList.push(value.userId);
339
+ }
340
+ else {
341
+ tmpParam.user_id = isUserExist;
342
+ }
343
+ data_.push(tmpParam);
344
+ }
345
+ }
346
+ return data_;
347
+ };
348
+ var sort = function (data) {
349
+ data.sort(function (a, b) {
350
+ if (a.vpos < b.vpos)
351
+ return -1;
352
+ if (a.vpos > b.vpos)
353
+ return 1;
354
+ if (a.date < b.date)
355
+ return -1;
356
+ if (a.date > b.date)
357
+ return 1;
358
+ if (a.date_usec < b.date_usec)
359
+ return -1;
360
+ if (a.date_usec > b.date_usec)
361
+ return 1;
362
+ return 0;
363
+ });
364
+ return data;
365
+ };
366
+ var time2vpos = function (time_str) {
367
+ var time = time_str.match(/^(\d+):(\d+)\.(\d+)|(\d+):(\d+)|(\d+)\.(\d+)|(\d+)$/);
368
+ if (time) {
369
+ if (time[1] !== undefined && time[2] !== undefined && time[3] !== undefined) {
370
+ return (Number(time[1]) * 60 + Number(time[2])) * 100 + Number(time[3]) / Math.pow(10, time[3].length - 2);
371
+ }
372
+ else if (time[4] !== undefined && time[5] !== undefined) {
373
+ return (Number(time[4]) * 60 + Number(time[5])) * 100;
374
+ }
375
+ else if (time[6] !== undefined && time[7] !== undefined) {
376
+ return Number(time[6]) * 100 + Number(time[7]) / Math.pow(10, time[7].length - 2);
377
+ }
378
+ else if (time[8] !== undefined) {
379
+ return Number(time[8]) * 100;
380
+ }
381
+ }
382
+ return 0;
383
+ };
384
+ var date2time = function (date) {
385
+ return Math.floor(new Date(date).getTime() / 1000);
1003
386
  };
1004
- var changeCALayer = function (rawData) {
1005
- var userList = {};
1006
- var data = [], index = [];
1007
- for (var i in rawData) {
1008
- var value = rawData[i];
1009
- if (value.user_id === undefined || value.user_id === -1)
1010
- continue;
1011
- if (userList[value.user_id] === undefined)
1012
- userList[value.user_id] = 0;
1013
- if (value.mail.indexOf("ca") > -1 || value.mail.indexOf("patissier") > -1 || value.mail.indexOf("ender") > -1) {
1014
- userList[value.user_id] += 5;
1015
- }
1016
- if ((value.content.match(/\r\n|\n|\r/g) || []).length > 2) {
1017
- userList[value.user_id] += 1;
1018
- }
1019
- var key = "".concat(value.content, "@@").concat(Array.from(new Set(value.mail.sort())).filter(function (e) { return !e.match(/@[\d.]+|184|device:.+|patissier|ca/); }).join(""), "@@").concat(Math.floor(value.vpos * 10));
1020
- if (index.indexOf(key) === -1) {
1021
- index.push(key);
1022
- data.push(value);
1023
- }
1024
- }
1025
- for (var i in data) {
1026
- var value = data[i];
1027
- if (userList[value.user_id] !== undefined && userList[value.user_id] >= 10) {
1028
- value.layer = value.user_id;
1029
- }
1030
- }
1031
- return data;
387
+
388
+ var isDebug = false;
389
+ var NiconiComments = (function () {
390
+ function NiconiComments(canvas, data, initOptions) {
391
+ if (initOptions === void 0) { initOptions = {}; }
392
+ var _this = this;
393
+ var defaultOptions = {
394
+ drawAllImageOnLoad: false,
395
+ format: "default",
396
+ formatted: false,
397
+ debug: false,
398
+ enableLegacyPiP: false,
399
+ keepCA: false,
400
+ showCollision: false,
401
+ showCommentCount: false,
402
+ showFPS: false,
403
+ useLegacy: false,
404
+ video: null,
405
+ };
406
+ var options = Object.assign(defaultOptions, initOptions);
407
+ isDebug = options.debug;
408
+ var constructorStart = performance.now();
409
+ this.canvas = canvas;
410
+ var context = canvas.getContext("2d");
411
+ if (!context)
412
+ throw new Error("Fail to get CanvasRenderingContext2D");
413
+ this.context = context;
414
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
415
+ this.context.textAlign = "start";
416
+ this.context.textBaseline = "alphabetic";
417
+ this.context.lineWidth = 4;
418
+ this.commentYPaddingTop = 0.08;
419
+ this.commentYMarginBottom = 0.24;
420
+ this.fontSize = {
421
+ "small": {
422
+ "default": 47,
423
+ "resized": 26.1
424
+ },
425
+ "medium": {
426
+ "default": 74,
427
+ "resized": 38.7
428
+ },
429
+ "big": {
430
+ "default": 110,
431
+ "resized": 61
432
+ }
433
+ };
434
+ this.lineHeight = {
435
+ "small": {
436
+ "default": 1,
437
+ "resized": 1
438
+ },
439
+ "medium": {
440
+ "default": 1,
441
+ "resized": 1
442
+ },
443
+ "big": {
444
+ "default": 1.03,
445
+ "resized": 1.01
446
+ }
447
+ };
448
+ this.doubleResizeMaxWidth = {
449
+ full: {
450
+ legacy: 3020,
451
+ default: 3550
452
+ },
453
+ normal: {
454
+ legacy: 2540,
455
+ default: 2650
456
+ }
457
+ };
458
+ var formatType = options.format;
459
+ if (options.formatted) {
460
+ console.warn("Deprecated: options.formatted is no longer recommended. Please use options.format");
461
+ }
462
+ if (formatType === "default") {
463
+ formatType = options.formatted ? "formatted" : "legacy";
464
+ }
465
+ var parsedData = convert2formattedComment(data, formatType);
466
+ this.video = options.video ? options.video : null;
467
+ this.showCollision = options.showCollision;
468
+ this.showFPS = options.showFPS;
469
+ this.showCommentCount = options.showCommentCount;
470
+ this.enableLegacyPiP = options.enableLegacyPiP;
471
+ this.keepCA = options.keepCA;
472
+ this.timeline = {};
473
+ this.nicoScripts = { reverse: [], default: [], replace: [], ban: [] };
474
+ this.collision_right = {};
475
+ this.collision_left = {};
476
+ this.collision_ue = {};
477
+ this.collision_shita = {};
478
+ this.data = [];
479
+ this.lastVpos = -1;
480
+ this.useLegacy = options.useLegacy;
481
+ this.preRendering(parsedData, options.drawAllImageOnLoad);
482
+ this.fpsCount = 0;
483
+ this.fps = 0;
484
+ window.setInterval(function () {
485
+ _this.fps = _this.fpsCount * 2;
486
+ _this.fpsCount = 0;
487
+ }, 500);
488
+ logger("constructor complete: ".concat(performance.now() - constructorStart, "ms"));
489
+ }
490
+ NiconiComments.prototype.preRendering = function (rawData, drawAll) {
491
+ var preRenderingStart = performance.now();
492
+ if (this.keepCA) {
493
+ rawData = changeCALayer(rawData);
494
+ }
495
+ var parsedData = this.getCommentPos(this.getCommentSize(this.getFont(rawData)));
496
+ this.data = this.sortComment(parsedData);
497
+ if (drawAll) {
498
+ for (var i in parsedData) {
499
+ this.getTextImage(Number(i), true);
500
+ }
501
+ }
502
+ logger("preRendering complete: ".concat(performance.now() - preRenderingStart, "ms"));
503
+ };
504
+ NiconiComments.prototype.getFont = function (parsedData) {
505
+ var getFontStart = performance.now();
506
+ var result = [];
507
+ for (var i in parsedData) {
508
+ var value = parsedData[i];
509
+ if (!value)
510
+ continue;
511
+ value.content = value.content.replace(/\t/g, "\u2003\u2003");
512
+ result[i] = this.parseCommandAndNicoscript(value);
513
+ }
514
+ logger("getFont complete: ".concat(performance.now() - getFontStart, "ms"));
515
+ return result;
516
+ };
517
+ NiconiComments.prototype.getCommentSize = function (parsedData) {
518
+ var getCommentSizeStart = performance.now();
519
+ var tmpData = groupBy(parsedData, "font", "fontSize");
520
+ var result = [];
521
+ for (var i in tmpData) {
522
+ for (var j in tmpData[i]) {
523
+ this.context.font = parseFont(i, j, this.useLegacy);
524
+ for (var k in tmpData[i][j]) {
525
+ var comment = tmpData[i][j][k];
526
+ if (comment.invisible) {
527
+ continue;
528
+ }
529
+ var measure = this.measureText(comment);
530
+ var size = parsedData[comment.index];
531
+ size.height = measure.height;
532
+ size.width = measure.width;
533
+ size.width_max = measure.width_max;
534
+ size.width_min = measure.width_min;
535
+ size.lineHeight = measure.lineHeight;
536
+ if (measure.resized) {
537
+ size.fontSize = measure.fontSize;
538
+ this.context.font = parseFont(i, j, this.useLegacy);
539
+ }
540
+ result[comment.index] = size;
541
+ }
542
+ }
543
+ }
544
+ logger("getCommentSize complete: ".concat(performance.now() - getCommentSizeStart, "ms"));
545
+ return result;
546
+ };
547
+ NiconiComments.prototype.getCommentPos = function (parsedData) {
548
+ var getCommentPosStart = performance.now();
549
+ var data = parsedData;
550
+ for (var i in data) {
551
+ var comment = data[i];
552
+ if (!comment || comment.invisible) {
553
+ continue;
554
+ }
555
+ for (var j = 0; j < comment.long * 4 / 3 + 100; j++) {
556
+ if (!this.timeline[comment.vpos + j]) {
557
+ this.timeline[comment.vpos + j] = [];
558
+ }
559
+ if (!this.collision_right[comment.vpos + j]) {
560
+ this.collision_right[comment.vpos + j] = [];
561
+ }
562
+ if (!this.collision_left[comment.vpos + j]) {
563
+ this.collision_left[comment.vpos + j] = [];
564
+ }
565
+ if (!this.collision_ue[comment.vpos + j]) {
566
+ this.collision_ue[comment.vpos + j] = [];
567
+ }
568
+ if (!this.collision_shita[comment.vpos + j]) {
569
+ this.collision_shita[comment.vpos + j] = [];
570
+ }
571
+ }
572
+ if (comment.loc === "naka") {
573
+ var posY = 0, is_break = false, is_change = true, count = 0, beforeVpos = Math.round(-240 / ((1680 + comment.width_max) / (comment.long + 125))) - 100;
574
+ if (1080 < comment.height) {
575
+ posY = (comment.height - 1080) / -2;
576
+ }
577
+ else {
578
+ while (is_change && count < 10) {
579
+ is_change = false;
580
+ count++;
581
+ for (var j = beforeVpos; j < comment.long; j++) {
582
+ var vpos = comment.vpos + j;
583
+ var left_pos = 1680 - (1680 + comment.width_max) / (comment.long + 125) * j;
584
+ if (left_pos + comment.width_max >= 1880) {
585
+ for (var k in this.collision_right[vpos]) {
586
+ var l = this.collision_right[vpos][k];
587
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
588
+ if (data[l].posY + data[l].height > posY) {
589
+ posY = data[l].posY + data[l].height;
590
+ is_change = true;
591
+ }
592
+ if (posY + comment.height > 1080) {
593
+ if (1080 < comment.height) {
594
+ posY = (comment.height - 1080) / -2;
595
+ }
596
+ else {
597
+ posY = Math.floor(Math.random() * (1080 - comment.height));
598
+ }
599
+ is_break = true;
600
+ break;
601
+ }
602
+ }
603
+ }
604
+ if (is_break) {
605
+ break;
606
+ }
607
+ }
608
+ if (left_pos <= 40) {
609
+ for (var k in this.collision_left[vpos]) {
610
+ var l = this.collision_left[vpos][k];
611
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
612
+ if (data[l].posY + data[l].height > posY) {
613
+ posY = data[l].posY + data[l].height;
614
+ is_change = true;
615
+ }
616
+ if (posY + comment.height > 1080) {
617
+ if (1080 < comment.height) {
618
+ posY = 0;
619
+ }
620
+ else {
621
+ posY = Math.random() * (1080 - comment.height);
622
+ }
623
+ is_break = true;
624
+ break;
625
+ }
626
+ }
627
+ }
628
+ if (is_break) {
629
+ break;
630
+ }
631
+ }
632
+ }
633
+ if (is_break) {
634
+ break;
635
+ }
636
+ }
637
+ }
638
+ for (var j = beforeVpos; j < comment.long + 125; j++) {
639
+ var vpos = comment.vpos + j;
640
+ var left_pos = 1680 - (1680 + comment.width_max) / (comment.long + 125) * j;
641
+ arrayPush(this.timeline, vpos, i);
642
+ if (left_pos + comment.width_max >= 1880) {
643
+ arrayPush(this.collision_right, vpos, i);
644
+ }
645
+ if (left_pos <= 40) {
646
+ arrayPush(this.collision_left, vpos, i);
647
+ }
648
+ }
649
+ parsedData[i].posY = posY;
650
+ }
651
+ else {
652
+ var posY = 0, is_break = false, is_change = true, count = 0, collision = void 0;
653
+ if (comment.loc === "ue") {
654
+ collision = this.collision_ue;
655
+ }
656
+ else if (comment.loc === "shita") {
657
+ collision = this.collision_shita;
658
+ }
659
+ while (is_change && count < 10) {
660
+ is_change = false;
661
+ count++;
662
+ for (var j = 0; j < comment.long; j++) {
663
+ var vpos = comment.vpos + j;
664
+ for (var k in collision[vpos]) {
665
+ var l = collision[vpos][k];
666
+ if ((posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY) && data[l].owner === comment.owner && data[l].layer === comment.layer) {
667
+ if (data[l].posY + data[l].height > posY) {
668
+ posY = data[l].posY + data[l].height;
669
+ is_change = true;
670
+ }
671
+ if (posY + comment.height > 1080) {
672
+ if (1000 <= comment.height) {
673
+ posY = 0;
674
+ }
675
+ else {
676
+ posY = Math.floor(Math.random() * (1080 - comment.height));
677
+ }
678
+ is_break = true;
679
+ break;
680
+ }
681
+ }
682
+ }
683
+ if (is_break) {
684
+ break;
685
+ }
686
+ }
687
+ }
688
+ for (var j = 0; j < comment.long; j++) {
689
+ var vpos = comment.vpos + j;
690
+ arrayPush(this.timeline, vpos, i);
691
+ if (comment.loc === "ue") {
692
+ arrayPush(this.collision_ue, vpos, i);
693
+ }
694
+ else {
695
+ arrayPush(this.collision_shita, vpos, i);
696
+ }
697
+ }
698
+ parsedData[i].posY = posY;
699
+ }
700
+ }
701
+ logger("getCommentPos complete: ".concat(performance.now() - getCommentPosStart, "ms"));
702
+ return parsedData;
703
+ };
704
+ NiconiComments.prototype.sortComment = function (parsedData) {
705
+ var sortCommentStart = performance.now();
706
+ for (var vpos in this.timeline) {
707
+ if (!this.timeline[vpos])
708
+ continue;
709
+ var owner = [], user = [];
710
+ for (var _i = 0, _a = this.timeline[vpos]; _i < _a.length; _i++) {
711
+ var i = _a[_i];
712
+ if (parsedData[i].owner) {
713
+ owner.push(i);
714
+ }
715
+ else {
716
+ user.push(i);
717
+ }
718
+ }
719
+ this.timeline[vpos] = owner.concat(user);
720
+ }
721
+ logger("parseData complete: ".concat(performance.now() - sortCommentStart, "ms"));
722
+ return parsedData;
723
+ };
724
+ NiconiComments.prototype.measureText = function (comment) {
725
+ var width, width_max, width_min, height, width_arr = [], lines = comment.content.split("\n");
726
+ if (!comment.lineHeight)
727
+ comment.lineHeight = this.lineHeight[comment.size].default;
728
+ if (!comment.resized && !comment.ender) {
729
+ if (comment.size === "big" && lines.length > 2) {
730
+ comment.fontSize = this.fontSize.big.resized;
731
+ comment.lineHeight = this.lineHeight.big.resized;
732
+ comment.resized = true;
733
+ comment.tateresized = true;
734
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
735
+ }
736
+ else if (comment.size === "medium" && lines.length > 4) {
737
+ comment.fontSize = this.fontSize.medium.resized;
738
+ comment.lineHeight = this.lineHeight.medium.resized;
739
+ comment.resized = true;
740
+ comment.tateresized = true;
741
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
742
+ }
743
+ else if (comment.size === "small" && lines.length > 6) {
744
+ comment.fontSize = this.fontSize.small.resized;
745
+ comment.lineHeight = this.lineHeight.small.resized;
746
+ comment.resized = true;
747
+ comment.tateresized = true;
748
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
749
+ }
750
+ }
751
+ for (var i = 0; i < lines.length; i++) {
752
+ var measure = this.context.measureText(lines[i]);
753
+ width_arr.push(measure.width);
754
+ }
755
+ width = width_arr.reduce(function (p, c) { return p + c; }, 0) / width_arr.length;
756
+ width_max = Math.max.apply(Math, width_arr);
757
+ width_min = Math.min.apply(Math, width_arr);
758
+ height = (comment.fontSize * comment.lineHeight * (1 + this.commentYPaddingTop) * lines.length) + (this.commentYMarginBottom * comment.fontSize);
759
+ if (comment.loc !== "naka" && !comment.tateresized) {
760
+ if (comment.full && width_max > 1930) {
761
+ comment.fontSize -= 2;
762
+ comment.resized = true;
763
+ comment.yokoResized = true;
764
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
765
+ return this.measureText(comment);
766
+ }
767
+ else if (!comment.full && width_max > 1440) {
768
+ comment.fontSize -= 1;
769
+ comment.resized = true;
770
+ comment.yokoResized = true;
771
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
772
+ return this.measureText(comment);
773
+ }
774
+ }
775
+ else if (comment.loc !== "naka" && comment.tateresized && (comment.full && width_max > 2120 || !comment.full && width_max > 1440) && !comment.yokoResized) {
776
+ comment.fontSize = this.fontSize[comment.size].default;
777
+ comment.lineHeight = this.lineHeight[comment.size].default * 1.05;
778
+ comment.resized = true;
779
+ comment.yokoResized = true;
780
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
781
+ return this.measureText(comment);
782
+ }
783
+ else if (comment.loc !== "naka" && comment.tateresized && comment.yokoResized) {
784
+ if (comment.full && width_max > this.doubleResizeMaxWidth.full[this.useLegacy ? "legacy" : "default"]) {
785
+ comment.fontSize -= 1;
786
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
787
+ return this.measureText(comment);
788
+ }
789
+ else if (!comment.full && width_max > this.doubleResizeMaxWidth.normal[this.useLegacy ? "legacy" : "default"]) {
790
+ comment.fontSize -= 1;
791
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
792
+ return this.measureText(comment);
793
+ }
794
+ }
795
+ return {
796
+ "width": width,
797
+ "width_max": width_max,
798
+ "width_min": width_min,
799
+ "height": height,
800
+ "resized": comment.resized,
801
+ "fontSize": comment.fontSize,
802
+ "lineHeight": comment.lineHeight
803
+ };
804
+ };
805
+ NiconiComments.prototype.drawText = function (comment, vpos) {
806
+ var reverse = false;
807
+ for (var i in this.nicoScripts.reverse) {
808
+ var range = this.nicoScripts.reverse[i];
809
+ if ((range.target === "コメ" && comment.owner) || (range.target === "投コメ" && !comment.owner)) {
810
+ break;
811
+ }
812
+ if (range.start < vpos && vpos < range.end) {
813
+ reverse = true;
814
+ }
815
+ }
816
+ for (var i in this.nicoScripts.ban) {
817
+ var range = this.nicoScripts.ban[i];
818
+ if (range.start < vpos && vpos < range.end) {
819
+ return;
820
+ }
821
+ }
822
+ var posX = (1920 - comment.width_max) / 2, posY = comment.posY;
823
+ if (comment.loc === "naka") {
824
+ if (reverse) {
825
+ posX = 240 + (1680 + comment.width_max) / (comment.long + 125) * (vpos - comment.vpos + 100) - comment.width_max;
826
+ }
827
+ else {
828
+ posX = 1680 - (1680 + comment.width_max) / (comment.long + 125) * (vpos - comment.vpos + 100);
829
+ }
830
+ }
831
+ else if (comment.loc === "shita") {
832
+ posY = 1080 - comment.posY - comment.height;
833
+ }
834
+ if (comment.image && comment.image !== true) {
835
+ this.context.drawImage(comment.image, posX, posY);
836
+ }
837
+ if (this.showCollision) {
838
+ this.context.strokeStyle = "rgba(0,255,255,1)";
839
+ this.context.strokeRect(posX, posY, comment.width_max, comment.height);
840
+ var lines = comment.content.split("\n");
841
+ for (var i in lines) {
842
+ var linePosY = (Number(i) + 1) * (comment.fontSize * comment.lineHeight) * (1 + this.commentYPaddingTop);
843
+ this.context.strokeStyle = "rgba(255,255,0,0.5)";
844
+ this.context.strokeRect(posX, posY + linePosY, comment.width_max, comment.fontSize * comment.lineHeight * -1);
845
+ }
846
+ }
847
+ };
848
+ NiconiComments.prototype.getTextImage = function (i, preRendering) {
849
+ var _this = this;
850
+ if (preRendering === void 0) { preRendering = false; }
851
+ var value = this.data[i];
852
+ if (!value || value.invisible)
853
+ return;
854
+ var image = document.createElement("canvas");
855
+ image.width = value.width_max;
856
+ image.height = value.height;
857
+ var context = image.getContext("2d");
858
+ if (!context)
859
+ throw new Error("Fail to get CanvasRenderingContext2D");
860
+ context.strokeStyle = "rgba(0,0,0,0.7)";
861
+ context.textAlign = "start";
862
+ context.textBaseline = "alphabetic";
863
+ context.lineWidth = 4;
864
+ context.font = parseFont(value.font, value.fontSize, this.useLegacy);
865
+ if (value._live) {
866
+ var rgb = hex2rgb(value.color);
867
+ context.fillStyle = "rgba(".concat(rgb[0], ",").concat(rgb[1], ",").concat(rgb[2], ",0.5)");
868
+ }
869
+ else {
870
+ context.fillStyle = value.color;
871
+ }
872
+ if (value.color === "#000000") {
873
+ context.strokeStyle = "rgba(255,255,255,0.7)";
874
+ }
875
+ var lines = value.content.split("\n");
876
+ for (var i_1 in lines) {
877
+ var line = lines[i_1], posY = void 0;
878
+ posY = (Number(i_1) + 1) * (value.fontSize * value.lineHeight) * (1 + this.commentYPaddingTop);
879
+ context.strokeText(line, 0, posY);
880
+ context.fillText(line, 0, posY);
881
+ }
882
+ this.data[i].image = image;
883
+ if (preRendering)
884
+ return;
885
+ setTimeout(function () {
886
+ if (_this.data[i].image)
887
+ delete _this.data[i].image;
888
+ }, 5000);
889
+ };
890
+ NiconiComments.prototype.parseCommand = function (comment) {
891
+ var metadata = comment.mail, loc = null, size = null, fontSize = null, color = null, font = null, full = false, ender = false, _live = false, invisible = false, long = null;
892
+ for (var i in metadata) {
893
+ var command = metadata[i].toLowerCase();
894
+ var match = command.match(/^@([0-9.]+)/);
895
+ if (match) {
896
+ long = match[1];
897
+ }
898
+ if (loc === null) {
899
+ switch (command) {
900
+ case "ue":
901
+ loc = "ue";
902
+ break;
903
+ case "shita":
904
+ loc = "shita";
905
+ break;
906
+ }
907
+ }
908
+ if (size === null) {
909
+ switch (command) {
910
+ case "big":
911
+ size = "big";
912
+ fontSize = this.fontSize.big.default;
913
+ break;
914
+ case "small":
915
+ size = "small";
916
+ fontSize = this.fontSize.small.default;
917
+ break;
918
+ }
919
+ }
920
+ if (color === null) {
921
+ switch (command) {
922
+ case "white":
923
+ color = "#FFFFFF";
924
+ break;
925
+ case "red":
926
+ color = "#FF0000";
927
+ break;
928
+ case "pink":
929
+ color = "#FF8080";
930
+ break;
931
+ case "orange":
932
+ color = "#FFC000";
933
+ break;
934
+ case "yellow":
935
+ color = "#FFFF00";
936
+ break;
937
+ case "green":
938
+ color = "#00FF00";
939
+ break;
940
+ case "cyan":
941
+ color = "#00FFFF";
942
+ break;
943
+ case "blue":
944
+ color = "#0000FF";
945
+ break;
946
+ case "purple":
947
+ color = "#C000FF";
948
+ break;
949
+ case "black":
950
+ color = "#000000";
951
+ break;
952
+ case "white2":
953
+ case "niconicowhite":
954
+ color = "#CCCC99";
955
+ break;
956
+ case "red2":
957
+ case "truered":
958
+ color = "#CC0033";
959
+ break;
960
+ case "pink2":
961
+ color = "#FF33CC";
962
+ break;
963
+ case "orange2":
964
+ case "passionorange":
965
+ color = "#FF6600";
966
+ break;
967
+ case "yellow2":
968
+ case "madyellow":
969
+ color = "#999900";
970
+ break;
971
+ case "green2":
972
+ case "elementalgreen":
973
+ color = "#00CC66";
974
+ break;
975
+ case "cyan2":
976
+ color = "#00CCCC";
977
+ break;
978
+ case "blue2":
979
+ case "marineblue":
980
+ color = "#3399FF";
981
+ break;
982
+ case "purple2":
983
+ case "nobleviolet":
984
+ color = "#6633CC";
985
+ break;
986
+ case "black2":
987
+ color = "#666666";
988
+ break;
989
+ default:
990
+ var match_1 = command.match(/#[0-9a-z]{3,6}/);
991
+ if (match_1 && comment.premium) {
992
+ color = match_1[0].toUpperCase();
993
+ }
994
+ break;
995
+ }
996
+ }
997
+ if (font === null) {
998
+ switch (command) {
999
+ case "gothic":
1000
+ font = "gothic";
1001
+ break;
1002
+ case "mincho":
1003
+ font = "mincho";
1004
+ break;
1005
+ }
1006
+ }
1007
+ switch (command) {
1008
+ case "full":
1009
+ full = true;
1010
+ break;
1011
+ case "ender":
1012
+ ender = true;
1013
+ break;
1014
+ case "_live":
1015
+ _live = true;
1016
+ break;
1017
+ case "invisible":
1018
+ invisible = true;
1019
+ break;
1020
+ }
1021
+ }
1022
+ return { loc: loc, size: size, fontSize: fontSize, color: color, font: font, full: full, ender: ender, _live: _live, invisible: invisible, long: long };
1023
+ };
1024
+ NiconiComments.prototype.parseCommandAndNicoscript = function (comment) {
1025
+ var data = this.parseCommand(comment), nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
1026
+ if (nicoscript) {
1027
+ switch (nicoscript[1]) {
1028
+ case "デフォルト":
1029
+ this.nicoScripts.default.push({
1030
+ start: comment.vpos,
1031
+ long: data.long === null ? null : Math.floor(data.long * 100),
1032
+ color: data.color,
1033
+ size: data.size,
1034
+ font: data.font,
1035
+ loc: data.loc
1036
+ });
1037
+ break;
1038
+ case "逆":
1039
+ var reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
1040
+ if (!reverse)
1041
+ reverse = [];
1042
+ if (!reverse[1]) {
1043
+ reverse[1] = "全";
1044
+ }
1045
+ if (data.long === null) {
1046
+ data.long = 30;
1047
+ }
1048
+ this.nicoScripts.reverse.push({
1049
+ start: comment.vpos,
1050
+ end: comment.vpos + (data.long * 100),
1051
+ target: reverse[1]
1052
+ });
1053
+ break;
1054
+ case "コメント禁止":
1055
+ if (data.long === null) {
1056
+ data.long = 30;
1057
+ }
1058
+ this.nicoScripts.reverse.push({
1059
+ start: comment.vpos,
1060
+ end: comment.vpos + (data.long * 100),
1061
+ });
1062
+ break;
1063
+ case "置換":
1064
+ var content = comment.content.split(""), quote = "", last_i = "", string = "", result = [];
1065
+ for (var _i = 0, _a = content.slice(4); _i < _a.length; _i++) {
1066
+ var i = _a[_i];
1067
+ if (i.match(/["'「]/) && quote === "") {
1068
+ quote = i;
1069
+ }
1070
+ else if (i.match(/["']/) && quote === i && last_i !== "\\") {
1071
+ result.push(replaceAll(string, "\\n", "\n"));
1072
+ quote = "";
1073
+ string = "";
1074
+ }
1075
+ else if (i.match(/」/) && quote === "「") {
1076
+ result.push(string);
1077
+ quote = "";
1078
+ string = "";
1079
+ }
1080
+ else if (quote === "" && i.match(/[\s ]/)) {
1081
+ if (string) {
1082
+ result.push(string);
1083
+ string = "";
1084
+ }
1085
+ }
1086
+ else {
1087
+ string += i;
1088
+ }
1089
+ last_i = i;
1090
+ }
1091
+ result.push(string);
1092
+ this.nicoScripts.replace.push({
1093
+ start: comment.vpos,
1094
+ long: data.long === null ? null : Math.floor(data.long * 100),
1095
+ keyword: result[0],
1096
+ replace: result[1] || "",
1097
+ range: result[2] || "単",
1098
+ target: result[3] || "コメ",
1099
+ condition: result[4] || "部分一致",
1100
+ color: data.color,
1101
+ size: data.size,
1102
+ font: data.font,
1103
+ loc: data.loc
1104
+ });
1105
+ break;
1106
+ }
1107
+ data.invisible = true;
1108
+ }
1109
+ var color = "#FFFFFF", size = "medium", font = "defont", loc = "naka";
1110
+ for (var i in this.nicoScripts.default) {
1111
+ if (this.nicoScripts.default[i].long !== null && this.nicoScripts.default[i].start + this.nicoScripts.default[i].long < comment.vpos) {
1112
+ this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
1113
+ continue;
1114
+ }
1115
+ if (this.nicoScripts.default[i].loc) {
1116
+ loc = this.nicoScripts.default[i].loc;
1117
+ }
1118
+ if (this.nicoScripts.default[i].color) {
1119
+ color = this.nicoScripts.default[i].color;
1120
+ }
1121
+ if (this.nicoScripts.default[i].size) {
1122
+ size = this.nicoScripts.default[i].size;
1123
+ }
1124
+ if (this.nicoScripts.default[i].font) {
1125
+ font = this.nicoScripts.default[i].font;
1126
+ }
1127
+ }
1128
+ for (var i in this.nicoScripts.replace) {
1129
+ if (this.nicoScripts.replace[i].long !== null && this.nicoScripts.replace[i].start + this.nicoScripts.replace[i].long < comment.vpos) {
1130
+ this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
1131
+ continue;
1132
+ }
1133
+ var item = this.nicoScripts.replace[i];
1134
+ if ((item.target === "コメ" && comment.owner) || (item.target === "投コメ" && !comment.owner) || (item.target === "含まない" && comment.owner))
1135
+ continue;
1136
+ if ((item.condition === "完全一致" && comment.content === item.keyword) || (item.condition === "部分一致" && comment.content.indexOf(item.keyword) !== -1)) {
1137
+ if (item.range === "単") {
1138
+ comment.content = replaceAll(comment.content, item.keyword, item.replace);
1139
+ }
1140
+ else {
1141
+ comment.content = item.replace;
1142
+ }
1143
+ if (item.loc) {
1144
+ loc = item.loc;
1145
+ }
1146
+ if (item.color) {
1147
+ color = item.color;
1148
+ }
1149
+ if (item.size) {
1150
+ size = item.size;
1151
+ }
1152
+ if (item.font) {
1153
+ font = item.font;
1154
+ }
1155
+ }
1156
+ }
1157
+ if (!data.loc) {
1158
+ data.loc = loc;
1159
+ }
1160
+ if (!data.color) {
1161
+ data.color = color;
1162
+ }
1163
+ if (!data.size) {
1164
+ data.size = size;
1165
+ data.fontSize = this.fontSize[data.size].default;
1166
+ }
1167
+ if (!data.font) {
1168
+ data.font = font;
1169
+ }
1170
+ if (!data.long) {
1171
+ data.long = 300;
1172
+ }
1173
+ else {
1174
+ data.long = Math.floor(Number(data.long) * 100);
1175
+ }
1176
+ return _assign(_assign({}, comment), data);
1177
+ };
1178
+ NiconiComments.prototype.drawCanvas = function (vpos) {
1179
+ var drawCanvasStart = performance.now();
1180
+ if (this.lastVpos === vpos)
1181
+ return;
1182
+ this.lastVpos = vpos;
1183
+ this.fpsCount++;
1184
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
1185
+ if (this.video) {
1186
+ var offsetX = void 0, offsetY = void 0, scale = void 0, height = this.canvas.height / this.video.videoHeight, width = this.canvas.width / this.video.videoWidth;
1187
+ if (this.enableLegacyPiP ? height > width : height < width) {
1188
+ scale = width;
1189
+ }
1190
+ else {
1191
+ scale = height;
1192
+ }
1193
+ offsetX = (this.canvas.width - this.video.videoWidth * scale) * 0.5;
1194
+ offsetY = (this.canvas.height - this.video.videoHeight * scale) * 0.5;
1195
+ this.context.drawImage(this.video, offsetX, offsetY, this.video.videoWidth * scale, this.video.videoHeight * scale);
1196
+ }
1197
+ if (this.timeline[vpos]) {
1198
+ for (var i in this.timeline[vpos]) {
1199
+ var index = this.timeline[vpos][Number(i)];
1200
+ var comment = this.data[index];
1201
+ if (vpos > 23000 && vpos < 23100)
1202
+ console.log(comment);
1203
+ if (!comment || comment.invisible) {
1204
+ continue;
1205
+ }
1206
+ if (comment.image === undefined) {
1207
+ this.getTextImage(index);
1208
+ }
1209
+ try {
1210
+ this.drawText(comment, vpos);
1211
+ }
1212
+ catch (e) {
1213
+ comment.image = false;
1214
+ }
1215
+ }
1216
+ }
1217
+ if (this.showFPS) {
1218
+ this.context.font = parseFont("defont", 60, this.useLegacy);
1219
+ this.context.fillStyle = "#00FF00";
1220
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
1221
+ this.context.strokeText("FPS:" + this.fps, 100, 100);
1222
+ this.context.fillText("FPS:" + this.fps, 100, 100);
1223
+ }
1224
+ if (this.showCommentCount) {
1225
+ this.context.font = parseFont("defont", 60, this.useLegacy);
1226
+ this.context.fillStyle = "#00FF00";
1227
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
1228
+ if (this.timeline[vpos]) {
1229
+ this.context.strokeText("Count:" + this.timeline[vpos].length, 100, 200);
1230
+ this.context.fillText("Count:" + this.timeline[vpos].length, 100, 200);
1231
+ }
1232
+ else {
1233
+ this.context.strokeText("Count:0", 100, 200);
1234
+ this.context.fillText("Count:0", 100, 200);
1235
+ }
1236
+ }
1237
+ logger("drawCanvas complete: ".concat(performance.now() - drawCanvasStart, "ms"));
1238
+ };
1239
+ NiconiComments.prototype.clear = function () {
1240
+ this.context.clearRect(0, 0, 1920, 1080);
1241
+ };
1242
+ return NiconiComments;
1243
+ }());
1244
+ var groupBy = function (array, key, key2) {
1245
+ var data = {};
1246
+ for (var i in array) {
1247
+ if (!data[array[i][key]]) {
1248
+ data[array[i][key]] = {};
1249
+ }
1250
+ if (!data[array[i][key]][array[i][key2]]) {
1251
+ data[array[i][key]][array[i][key2]] = [];
1252
+ }
1253
+ array[i].index = i;
1254
+ data[array[i][key]][array[i][key2]].push(array[i]);
1255
+ }
1256
+ return data;
1257
+ };
1258
+ var parseFont = function (font, size, useLegacy) {
1259
+ switch (font) {
1260
+ case "gothic":
1261
+ return "normal 400 ".concat(size, "px \"\u6E38\u30B4\u30B7\u30C3\u30AF\u4F53\", \"\u6E38\u30B4\u30B7\u30C3\u30AF\", \"Yu Gothic\", YuGothic, yugothic, YuGo-Medium");
1262
+ case "mincho":
1263
+ return "normal 400 ".concat(size, "px \"\u6E38\u660E\u671D\u4F53\", \"\u6E38\u660E\u671D\", \"Yu Mincho\", YuMincho, yumincho, YuMin-Medium");
1264
+ default:
1265
+ if (useLegacy) {
1266
+ return "normal 600 ".concat(size, "px Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
1267
+ }
1268
+ else {
1269
+ return "normal 600 ".concat(size, "px sans-serif, Arial, \"\uFF2D\uFF33 \uFF30\u30B4\u30B7\u30C3\u30AF\", \"MS PGothic\", MSPGothic, MS-PGothic");
1270
+ }
1271
+ }
1272
+ };
1273
+ var arrayPush = function (array, key, push) {
1274
+ if (!array) {
1275
+ array = {};
1276
+ }
1277
+ if (!array[key]) {
1278
+ array[key] = [];
1279
+ }
1280
+ array[key].push(push);
1281
+ };
1282
+ var hex2rgb = function (hex) {
1283
+ if (hex.slice(0, 1) === "#")
1284
+ hex = hex.slice(1);
1285
+ if (hex.length === 3)
1286
+ hex = hex.slice(0, 1) + hex.slice(0, 1) + hex.slice(1, 2) + hex.slice(1, 2) + hex.slice(2, 3) + hex.slice(2, 3);
1287
+ return [hex.slice(0, 2), hex.slice(2, 4), hex.slice(4, 6)].map(function (str) {
1288
+ return parseInt(str, 16);
1289
+ });
1290
+ };
1291
+ var replaceAll = function (string, target, replace) {
1292
+ var count = 0;
1293
+ while (string.indexOf(target) !== -1 && count < 100) {
1294
+ string = string.replace(target, replace);
1295
+ count++;
1296
+ }
1297
+ return string;
1298
+ };
1299
+ var logger = function (msg) {
1300
+ if (isDebug)
1301
+ console.debug(msg);
1302
+ };
1303
+ var changeCALayer = function (rawData) {
1304
+ var userList = {};
1305
+ var data = [], index = {};
1306
+ for (var i in rawData) {
1307
+ var value = rawData[i];
1308
+ if (value.user_id === undefined || value.user_id === -1)
1309
+ continue;
1310
+ if (userList[value.user_id] === undefined)
1311
+ userList[value.user_id] = 0;
1312
+ if (value.mail.indexOf("ca") > -1 || value.mail.indexOf("patissier") > -1 || value.mail.indexOf("ender") > -1 || value.mail.indexOf("full") > -1) {
1313
+ userList[value.user_id] += 5;
1314
+ }
1315
+ if ((value.content.match(/\r\n|\n|\r/g) || []).length > 2) {
1316
+ userList[value.user_id] += (value.content.match(/\r\n|\n|\r/g) || []).length / 2;
1317
+ }
1318
+ var key = "".concat(value.content, "@@").concat(Array.from(new Set(JSON.parse(JSON.stringify(value.mail)).sort())).filter(function (e) { return !e.match(/@[\d.]+|184|device:.+|patissier|ca/); }).join("")), lastComment = index[key];
1319
+ if (lastComment !== undefined) {
1320
+ if (value.vpos > 29800 && 30200 > value.vpos)
1321
+ console.log(value.vpos - lastComment.vpos, Math.abs(value.date - lastComment.date));
1322
+ if (value.vpos - lastComment.vpos > 100 || Math.abs(value.date - lastComment.date) < 3600) {
1323
+ data.push(value);
1324
+ index[key] = value;
1325
+ }
1326
+ }
1327
+ else {
1328
+ data.push(value);
1329
+ index[key] = value;
1330
+ }
1331
+ }
1332
+ for (var i in data) {
1333
+ var value = data[i];
1334
+ if (userList[value.user_id] !== undefined && userList[value.user_id] >= 10) {
1335
+ value.layer = value.user_id;
1336
+ }
1337
+ }
1338
+ return data;
1032
1339
  };
1033
1340
 
1034
1341
  return NiconiComments;