@xpadev-net/niconicomments 0.1.0 → 0.1.6

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.
Files changed (2) hide show
  1. package/dist/bundle.js +311 -149
  2. package/package.json +2 -4
package/dist/bundle.js CHANGED
@@ -1,3 +1,8 @@
1
+ /*!
2
+ niconicomments.js v0.1.6
3
+ (c) 2021 xpadev-net https://xpadevn.et
4
+ Released under the MIT License.
5
+ */
1
6
  (function (global, factory) {
2
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
8
  typeof define === 'function' && define.amd ? define(factory) :
@@ -18,21 +23,48 @@
18
23
  this.context.strokeStyle = "rgba(0,0,0,0.7)";
19
24
  this.context.textAlign = "left";
20
25
  this.context.textBaseline = "top";
21
- this.context.lineWidth = "6";
22
- this.commentYOffset = 0.25;
23
- this.commentYMarginTop = 10;
26
+ this.context.lineWidth = 2;
27
+
28
+ if (useLegacy) {
29
+ this.commentYOffset = 0.25;
30
+ } else {
31
+ this.commentYOffset = 0.2;
32
+ }
33
+
34
+ this.commentYMarginTop = 0.08;
24
35
  this.fontSize = {
25
36
  "small": {
26
- "default": 45,
27
- "resized": 20
37
+ "default": 47,
38
+ "resized": 27.5
28
39
  },
29
40
  "medium": {
30
- "default": 70,
31
- "resized": 35
41
+ "default": 76,
42
+ "resized": 39
32
43
  },
33
44
  "big": {
34
- "default": 120,
35
- "resized": 57.5
45
+ "default": 118,
46
+ "resized": 62.5
47
+ }
48
+ };
49
+ this.defaultCommandValue = {
50
+ loc: "naka",
51
+ size: "medium",
52
+ fontSize: this.fontSize.medium.default,
53
+ color: "#ffffff",
54
+ font: 'defont',
55
+ full: false,
56
+ ender: false,
57
+ _live: false,
58
+ invisible: false
59
+ };
60
+ this.doubleResizeMaxWidth = {
61
+ full: {
62
+ legacy: 3020,
63
+ default: 3220
64
+ },
65
+ normal: {
66
+ legacy: 2540,
67
+ default: 2740
36
68
  }
37
69
  };
38
70
 
@@ -47,7 +79,8 @@
47
79
  this.showCommentCount = false;
48
80
  this.timeline = {};
49
81
  this.nicoScripts = {
50
- "reverse": []
82
+ "reverse": [],
83
+ "default": []
51
84
  };
52
85
  this.collision_right = {};
53
86
  this.collision_left = {};
@@ -118,6 +151,7 @@
118
151
  this.getFont();
119
152
  this.getCommentSize();
120
153
  this.getCommentPos();
154
+ this.sortComment();
121
155
  }
122
156
  /**
123
157
  * コマンドをもとに各コメントに適用するフォントを決定する
@@ -127,7 +161,7 @@
127
161
  getFont() {
128
162
  for (let i in this.data) {
129
163
  let comment = this.data[i];
130
- let command = this.parseCommand(comment);
164
+ let command = this.parseCommandAndNicoscript(comment);
131
165
  this.data[i].loc = command.loc;
132
166
  this.data[i].size = command.size;
133
167
  this.data[i].fontSize = command.fontSize;
@@ -136,6 +170,8 @@
136
170
  this.data[i].full = command.full;
137
171
  this.data[i].ender = command.ender;
138
172
  this.data[i]._live = command._live;
173
+ this.data[i].long = command.long;
174
+ this.data[i].invisible = command.invisible;
139
175
  this.data[i].content = this.data[i].content.replaceAll("\t", " ");
140
176
  }
141
177
  }
@@ -153,6 +189,11 @@
153
189
 
154
190
  for (let k in tmpData[i][j]) {
155
191
  let comment = tmpData[i][j][k];
192
+
193
+ if (comment.invisible) {
194
+ continue;
195
+ }
196
+
156
197
  let measure = this.measureText(comment);
157
198
  this.data[comment.index].height = measure.height;
158
199
  this.data[comment.index].width = measure.width;
@@ -178,6 +219,10 @@
178
219
  for (let i in data) {
179
220
  let comment = data[i];
180
221
 
222
+ if (comment.invisible) {
223
+ continue;
224
+ }
225
+
181
226
  for (let j = 0; j < 500; j++) {
182
227
  if (!this.timeline[comment.vpos + j]) {
183
228
  this.timeline[comment.vpos + j] = [];
@@ -208,73 +253,77 @@
208
253
  is_change = true,
209
254
  count = 0;
210
255
 
211
- while (is_change && count < 10) {
212
- is_change = false;
213
- count++;
214
-
215
- for (let j = 0; j < 500; j++) {
216
- let vpos = comment.vpos + j;
217
- let left_pos = 1920 - (1920 + comment.width_max) * j / 500;
218
-
219
- if (left_pos + comment.width_max >= 1880) {
220
- for (let k in this.collision_right[vpos]) {
221
- let l = this.collision_right[vpos][k];
256
+ if (1080 < comment.height) {
257
+ posY = (comment.height - 1080) / -2;
258
+ } else {
259
+ while (is_change && count < 10) {
260
+ is_change = false;
261
+ count++;
262
+
263
+ for (let j = 0; j < 500; j++) {
264
+ let vpos = comment.vpos + j;
265
+ let left_pos = 1920 - (1920 + comment.width_max) * j / 500;
266
+
267
+ if (left_pos + comment.width_max >= 1880) {
268
+ for (let k in this.collision_right[vpos]) {
269
+ let l = this.collision_right[vpos][k];
270
+
271
+ if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
272
+ if (data[l].posY + data[l].height > posY) {
273
+ posY = data[l].posY + data[l].height;
274
+ is_change = true;
275
+ }
222
276
 
223
- if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
224
- if (data[l].posY + data[l].height > posY) {
225
- posY = data[l].posY + data[l].height;
226
- is_change = true;
227
- }
277
+ if (posY + comment.height > 1080) {
278
+ if (1080 < comment.height) {
279
+ posY = (comment.height - 1080) / -2;
280
+ } else {
281
+ posY = Math.floor(Math.random() * (1080 - comment.height));
282
+ }
228
283
 
229
- if (posY + comment.height > 1080) {
230
- if (1080 < comment.height) {
231
- posY = 0;
232
- } else {
233
- posY = Math.floor(Math.random() * (1080 - comment.height));
284
+ is_break = true;
285
+ break;
234
286
  }
235
-
236
- is_break = true;
237
- break;
238
287
  }
239
288
  }
240
- }
241
289
 
242
- if (is_break) {
243
- break;
290
+ if (is_break) {
291
+ break;
292
+ }
244
293
  }
245
- }
246
294
 
247
- if (left_pos <= 40 && is_break === false) {
248
- for (let k in this.collision_left[vpos]) {
249
- let l = this.collision_left[vpos][k];
295
+ if (left_pos <= 40 && is_break === false) {
296
+ for (let k in this.collision_left[vpos]) {
297
+ let l = this.collision_left[vpos][k];
250
298
 
251
- if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
252
- if (data[l].posY + data[l].height > posY) {
253
- posY = data[l].posY + data[l].height;
254
- is_change = true;
255
- }
256
-
257
- if (posY + comment.height > 1080) {
258
- if (1080 < comment.height) {
259
- posY = 0;
260
- } else {
261
- posY = Math.random() * (1080 - comment.height);
299
+ if (posY < data[l].posY + data[l].height && posY + comment.height > data[l].posY && data[l].owner === comment.owner) {
300
+ if (data[l].posY + data[l].height > posY) {
301
+ posY = data[l].posY + data[l].height;
302
+ is_change = true;
262
303
  }
263
304
 
264
- is_break = true;
265
- break;
305
+ if (posY + comment.height > 1080) {
306
+ if (1080 < comment.height) {
307
+ posY = 0;
308
+ } else {
309
+ posY = Math.random() * (1080 - comment.height);
310
+ }
311
+
312
+ is_break = true;
313
+ break;
314
+ }
266
315
  }
267
316
  }
317
+
318
+ if (is_break) {
319
+ break;
320
+ }
268
321
  }
269
322
 
270
323
  if (is_break) {
271
324
  break;
272
325
  }
273
326
  }
274
-
275
- if (is_break) {
276
- break;
277
- }
278
327
  }
279
328
  }
280
329
 
@@ -341,7 +390,7 @@
341
390
  }
342
391
  }
343
392
 
344
- for (let j = 0; j < 300; j++) {
393
+ for (let j = 0; j < comment.long; j++) {
345
394
  let vpos = comment.vpos + j;
346
395
  arrayPush(this.timeline, vpos, i);
347
396
 
@@ -356,6 +405,23 @@
356
405
  }
357
406
  }
358
407
  }
408
+
409
+ sortComment() {
410
+ for (let vpos in this.timeline) {
411
+ this.timeline[vpos].sort((a, b) => {
412
+ const A = this.data[a];
413
+ const B = this.data[b];
414
+
415
+ if (!A.owner && B.owner) {
416
+ return -1;
417
+ } else if (A.owner && !B.owner) {
418
+ return 1;
419
+ } else {
420
+ return 0;
421
+ }
422
+ });
423
+ }
424
+ }
359
425
  /**
360
426
  * context.measureTextの複数行対応版
361
427
  * 画面外にはみ出すコメントの縮小も行う
@@ -399,7 +465,7 @@
399
465
  width = width_arr.reduce((p, c) => p + c, 0) / width_arr.length;
400
466
  width_max = Math.max(...width_arr);
401
467
  width_min = Math.min(...width_arr);
402
- height = (comment.fontSize + this.commentYMarginTop) * lines.length;
468
+ height = (comment.fontSize + this.commentYMarginTop * comment.fontSize) * lines.length;
403
469
 
404
470
  if (comment.loc !== "naka" && !comment.tateRisized) {
405
471
  if (comment.full && width_max > 1920) {
@@ -415,23 +481,19 @@
415
481
  this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
416
482
  return this.measureText(comment);
417
483
  }
418
- } else if (comment.tateRisized && (comment.full && width_max > 1920 || !comment.full && width_max > 1440) && !comment.yokoResized) {
484
+ } else if (comment.loc !== "naka" && comment.tateRisized && (comment.full && width_max > 1920 || !comment.full && width_max > 1440) && !comment.yokoResized) {
419
485
  comment.fontSize = this.fontSize[comment.size].default;
420
486
  comment.resized = true;
421
487
  comment.yokoResized = true;
422
488
  this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
423
489
  return this.measureText(comment);
424
- } else if (comment.tateRisized && comment.yokoResized) {
425
- if (comment.full && width_max > 3420) {
490
+ } else if (comment.loc !== "naka" && comment.tateRisized && comment.yokoResized) {
491
+ if (comment.full && width_max > this.doubleResizeMaxWidth.full[this.useLegacy ? "legacy" : "default"]) {
426
492
  comment.fontSize -= 1;
427
- comment.resized = true;
428
- comment.yokoResized = true;
429
493
  this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
430
494
  return this.measureText(comment);
431
- } else if (!comment.full && width_max > 2940) {
432
- comment.fontSize -= 1;
433
- comment.resized = true;
434
- comment.yokoResized = true;
495
+ } else if (!comment.full && width_max > this.doubleResizeMaxWidth.normal[this.useLegacy ? "legacy" : "default"]) {
496
+ comment.fontSize -= 1.;
435
497
  this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
436
498
  return this.measureText(comment);
437
499
  }
@@ -471,32 +533,16 @@
471
533
  let lines = comment.content.split("\n"),
472
534
  posX = (1920 - comment.width_max) / 2;
473
535
 
474
- if (comment.loc === "shita") {
475
- for (let i in lines) {
476
- let line = lines[i];
477
- let posY = 1080 - comment.posY + i * (comment.fontSize + this.commentYMarginTop) - comment.height + this.commentYOffset * comment.fontSize;
478
- this.context.strokeText(line, posX, posY);
479
- this.context.fillText(line, posX, posY);
480
- }
481
- } else {
482
- if (comment.loc === "naka") {
483
- if (reverse) {
484
- posX = (1920 + comment.width_max) * (vpos - comment.vpos) / 500 - comment.width_max;
485
- } else {
486
- posX = 1920 - (1920 + comment.width_max) * (vpos - comment.vpos) / 500;
487
- }
488
- }
489
-
490
- for (let i in lines) {
491
- let line = lines[i];
492
- let posY = comment.posY + i * (comment.fontSize + this.commentYMarginTop) + this.commentYOffset * comment.fontSize;
493
- this.context.strokeText(line, posX, posY);
494
- this.context.fillText(line, posX, posY);
536
+ if (comment.loc === "naka") {
537
+ if (reverse) {
538
+ posX = (1920 + comment.width_max) * (vpos - comment.vpos) / 500 - comment.width_max;
539
+ } else {
540
+ posX = 1920 - (1920 + comment.width_max) * (vpos - comment.vpos) / 500;
495
541
  }
496
542
  }
497
543
 
498
544
  if (this.showCollision) {
499
- this.context.strokeStyle = "rgba(255,255,0,1)";
545
+ this.context.strokeStyle = "rgba(0,255,255,1)";
500
546
 
501
547
  if (comment.loc === "shita") {
502
548
  this.context.strokeRect(posX, 1080 - comment.posY - comment.height, comment.width_max, comment.height);
@@ -504,60 +550,67 @@
504
550
  this.context.strokeRect(posX, comment.posY, comment.width_max, comment.height);
505
551
  }
506
552
 
507
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
553
+ if (comment.color === "#000000") {
554
+ this.context.strokeStyle = "rgba(255,255,255,0.7)";
555
+ } else {
556
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
557
+ }
558
+ }
559
+
560
+ for (let i in lines) {
561
+ let line = lines[i],
562
+ posY;
563
+
564
+ if (comment.loc === "shita") {
565
+ posY = 1080 - comment.posY + i * (comment.fontSize + this.commentYMarginTop * comment.fontSize) - comment.height + this.commentYOffset * comment.fontSize;
566
+ } else {
567
+ posY = comment.posY + i * (comment.fontSize + this.commentYMarginTop * comment.fontSize) + this.commentYOffset * comment.fontSize;
568
+ }
569
+
570
+ this.context.strokeText(line, posX, posY);
571
+ this.context.fillText(line, posX, posY);
572
+
573
+ if (this.showCollision) {
574
+ this.context.strokeStyle = "rgba(255,255,0,0.5)";
575
+ this.context.strokeRect(posX, posY, comment.width_max, comment.fontSize);
576
+
577
+ if (comment.color === "#000000") {
578
+ this.context.strokeStyle = "rgba(255,255,255,0.7)";
579
+ } else {
580
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
581
+ }
582
+ }
508
583
  }
509
584
  }
510
585
  /**
511
586
  * コメントに含まれるコマンドを解釈する
512
587
  * @param comment- 独自フォーマットのコメントデータ
513
- * @returns {{loc: string, size: string, color: string, fontSize: number, ender: boolean, font: string, full: boolean, _live: boolean}}
588
+ * @returns {{loc: string|null, size: string|null, color: string|null, fontSize: number|null, ender: boolean, font: string|null, full: boolean, _live: boolean, invisible: boolean, long:number|null}}
514
589
  */
515
590
 
516
591
 
517
592
  parseCommand(comment) {
518
593
  let metadata = comment.mail,
519
- loc = "naka",
520
- size = "medium",
521
- fontSize = this.fontSize.medium.default,
522
- color = "#ffffff",
523
- font = 'defont',
594
+ loc = null,
595
+ size = null,
596
+ fontSize = null,
597
+ color = null,
598
+ font = null,
524
599
  full = false,
525
600
  ender = false,
526
- reverse = comment.content.match(/@逆 ?(全|コメ|投コメ)?/),
527
- _live = false;
528
-
529
- if (reverse) {
530
- if (!reverse[1]) {
531
- reverse[1] = "全";
532
- }
533
-
534
- let length = false;
535
-
536
- for (let i in metadata) {
537
- let match = metadata[i].match(/@([0-9]+)/);
538
-
539
- if (match) {
540
- length = match[1];
541
- break;
542
- }
543
- }
544
-
545
- if (!length) {
546
- length = 30;
547
- }
548
-
549
- this.nicoScripts.reverse.push({
550
- "start": comment.vpos,
551
- "end": comment.vpos + length * 100,
552
- "target": reverse[1]
553
- });
554
- fontSize = 0;
555
- }
601
+ _live = false,
602
+ invisible = false,
603
+ long = null;
556
604
 
557
605
  for (let i in metadata) {
558
606
  let command = metadata[i].toLowerCase();
607
+ const match = command.match(/^@([0-9.]+)/);
559
608
 
560
- if (loc === "naka") {
609
+ if (match) {
610
+ long = match[1];
611
+ }
612
+
613
+ if (loc === null) {
561
614
  switch (command) {
562
615
  case "ue":
563
616
  loc = "ue";
@@ -569,7 +622,7 @@
569
622
  }
570
623
  }
571
624
 
572
- if (size === "medium") {
625
+ if (size === null) {
573
626
  switch (command) {
574
627
  case "big":
575
628
  size = "big";
@@ -583,7 +636,7 @@
583
636
  }
584
637
  }
585
638
 
586
- if (color === "#ffffff") {
639
+ if (color === null) {
587
640
  switch (command) {
588
641
  case "white":
589
642
  color = "#FFFFFF";
@@ -683,7 +736,7 @@
683
736
  }
684
737
  }
685
738
 
686
- if (font === 'defont') {
739
+ if (font === null) {
687
740
  switch (command) {
688
741
  case "gothic":
689
742
  font = "gothic";
@@ -706,6 +759,11 @@
706
759
 
707
760
  case "_live":
708
761
  _live = true;
762
+ break;
763
+
764
+ case "invisible":
765
+ invisible = true;
766
+ break;
709
767
  }
710
768
  }
711
769
 
@@ -717,9 +775,106 @@
717
775
  font,
718
776
  full,
719
777
  ender,
720
- _live
778
+ _live,
779
+ invisible,
780
+ long
721
781
  };
722
782
  }
783
+
784
+ parseCommandAndNicoscript(comment) {
785
+ let data = this.parseCommand(comment),
786
+ nicoscript = comment.content.match(/^@(デフォルト|置換|逆|コメント禁止|シーク禁止|ジャンプ)/);
787
+
788
+ if (nicoscript) {
789
+ switch (nicoscript[1]) {
790
+ case "デフォルト":
791
+ this.nicoScripts.default.push({
792
+ start: comment.vpos,
793
+ long: data.long === null ? null : Math.floor(data.long * 100),
794
+ color: data.color,
795
+ size: data.size,
796
+ font: data.font,
797
+ loc: data.loc
798
+ });
799
+ break;
800
+
801
+ case "逆":
802
+ let reverse = comment.content.match(/^@逆 ?(全|コメ|投コメ)?/);
803
+
804
+ if (!reverse[1]) {
805
+ reverse[1] = "全";
806
+ }
807
+
808
+ if (data.long === null) {
809
+ data.long = 30;
810
+ }
811
+
812
+ this.nicoScripts.reverse.push({
813
+ "start": comment.vpos,
814
+ "end": comment.vpos + data.long * 100,
815
+ "target": reverse[1]
816
+ });
817
+ break;
818
+ }
819
+
820
+ data.invisible = true;
821
+ }
822
+
823
+ let color = "#FFFFFF",
824
+ size = "medium",
825
+ font = "defont",
826
+ loc = "naka";
827
+
828
+ for (let i in this.nicoScripts.default) {
829
+ if (this.nicoScripts.default[i].long !== null && this.nicoScripts.default[i].start + this.nicoScripts.default[i].long < comment.vpos) {
830
+ this.nicoScripts.default = this.nicoScripts.default.splice(Number(i), 1);
831
+ continue;
832
+ }
833
+
834
+ if (this.nicoScripts.default[i].loc) {
835
+ loc = this.nicoScripts.default[i].loc;
836
+ }
837
+
838
+ if (this.nicoScripts.default[i].color) {
839
+ color = this.nicoScripts.default[i].color;
840
+ }
841
+
842
+ if (this.nicoScripts.default[i].size) {
843
+ size = this.nicoScripts.default[i].size;
844
+ }
845
+
846
+ if (this.nicoScripts.default[i].font) {
847
+ font = this.nicoScripts.default[i].font;
848
+ }
849
+ }
850
+
851
+ if (!data.loc) {
852
+ data.loc = loc;
853
+ }
854
+
855
+ if (!data.color) {
856
+ data.color = color;
857
+ }
858
+
859
+ if (!data.size) {
860
+ data.size = size;
861
+ data.fontSize = this.fontSize[data.size].default;
862
+ }
863
+
864
+ if (!data.font) {
865
+ data.font = font;
866
+ }
867
+
868
+ if (data.loc !== "naka") {
869
+ if (!data.long) {
870
+ data.long = 300;
871
+ } else {
872
+ data.long = Math.floor(data.long * 100);
873
+ }
874
+ }
875
+
876
+ return data;
877
+ }
723
878
  /**
724
879
  * キャンバスを描画する
725
880
  * @param vpos - 動画の現在位置の100倍 ニコニコから吐き出されるコメントの位置情報は主にこれ
@@ -730,25 +885,32 @@
730
885
  this.fpsCount++;
731
886
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
732
887
 
733
- for (let index in this.timeline[vpos]) {
734
- let comment = this.data[this.timeline[vpos][index]];
735
- this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
888
+ if (this.timeline[vpos]) {
889
+ for (let index in this.timeline[vpos]) {
890
+ let comment = this.data[this.timeline[vpos][index]];
736
891
 
737
- if (comment._live) {
738
- let rgb = hex2rgb(comment.color);
739
- this.context.fillStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},0.5)`;
740
- } else {
741
- this.context.fillStyle = comment.color;
742
- }
892
+ if (comment.invisible) {
893
+ continue;
894
+ }
743
895
 
744
- if (comment.color === "#000000") {
745
- this.context.strokeStyle = "rgba(255,255,255,0.7)";
746
- }
896
+ this.context.font = parseFont(comment.font, comment.fontSize, this.useLegacy);
747
897
 
748
- this.drawText(comment, vpos);
898
+ if (comment._live) {
899
+ let rgb = hex2rgb(comment.color);
900
+ this.context.fillStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},0.5)`;
901
+ } else {
902
+ this.context.fillStyle = comment.color;
903
+ }
749
904
 
750
- if (comment.color === "#000000") {
751
- this.context.strokeStyle = "rgba(0,0,0,0.7)";
905
+ if (comment.color === "#000000") {
906
+ this.context.strokeStyle = "rgba(255,255,255,0.7)";
907
+ }
908
+
909
+ this.drawText(comment, vpos);
910
+
911
+ if (comment.color === "#000000") {
912
+ this.context.strokeStyle = "rgba(0,0,0,0.7)";
913
+ }
752
914
  }
753
915
  }
754
916
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpadev-net/niconicomments",
3
- "version": "0.1.0",
3
+ "version": "0.1.6",
4
4
  "description": "NiconiComments is a comment drawing library that is somewhat compatible with the official Nico Nico Douga player.",
5
5
  "main": "dist/bundle.js",
6
6
  "scripts": {
@@ -25,9 +25,7 @@
25
25
  "homepage": "https://xpadev.net/niconicomments/docs/",
26
26
  "license": "MIT",
27
27
  "devDependencies": {
28
- "rollup": "^2.61.1"
29
- },
30
- "dependencies": {
28
+ "rollup": "^2.61.1",
31
29
  "@rollup/plugin-babel": "^5.3.0"
32
30
  }
33
31
  }