pptxtojson 0.0.5 → 0.0.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.
- package/.eslintrc.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -1
- package/src/pptxtojson.js +1295 -1081
- package/src/utils.js +66 -0
package/src/pptxtojson.js
CHANGED
|
@@ -1,1082 +1,1296 @@
|
|
|
1
|
-
import JSZip from 'jszip'
|
|
2
|
-
import * as txml from 'txml/dist/txml.mjs'
|
|
3
|
-
import tinycolor from 'tinycolor2'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
for (const child
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
const
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
const
|
|
648
|
-
const
|
|
649
|
-
const
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
if (
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
if (!
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
if (
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
break
|
|
1010
|
-
case '
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
function
|
|
1026
|
-
|
|
1027
|
-
if (
|
|
1028
|
-
|
|
1029
|
-
if (
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1
|
+
import JSZip from 'jszip'
|
|
2
|
+
import * as txml from 'txml/dist/txml.mjs'
|
|
3
|
+
import tinycolor from 'tinycolor2'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
extractFileExtension,
|
|
7
|
+
base64ArrayBuffer,
|
|
8
|
+
eachElement,
|
|
9
|
+
getTextByPathList,
|
|
10
|
+
angleToDegrees,
|
|
11
|
+
escapeHtml,
|
|
12
|
+
getMimeType,
|
|
13
|
+
} from './utils'
|
|
14
|
+
|
|
15
|
+
const FACTOR = 75 / 914400
|
|
16
|
+
|
|
17
|
+
let themeContent = null
|
|
18
|
+
let defaultTextStyle = null
|
|
19
|
+
|
|
20
|
+
export async function parse(file) {
|
|
21
|
+
const slides = []
|
|
22
|
+
|
|
23
|
+
const zip = await JSZip.loadAsync(file)
|
|
24
|
+
|
|
25
|
+
const filesInfo = await getContentTypes(zip)
|
|
26
|
+
const { width, height, defaultTextStyle: _defaultTextStyle } = await getSlideSize(zip)
|
|
27
|
+
themeContent = await loadTheme(zip)
|
|
28
|
+
defaultTextStyle = _defaultTextStyle
|
|
29
|
+
|
|
30
|
+
for (const filename of filesInfo.slides) {
|
|
31
|
+
const singleSlide = await processSingleSlide(zip, filename)
|
|
32
|
+
slides.push(singleSlide)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
slides,
|
|
37
|
+
size: { width, height },
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function simplifyLostLess(children, parentAttributes = {}) {
|
|
42
|
+
const out = {}
|
|
43
|
+
if (!children.length) return out
|
|
44
|
+
|
|
45
|
+
if (children.length === 1 && typeof children[0] === 'string') {
|
|
46
|
+
return Object.keys(parentAttributes).length ? {
|
|
47
|
+
attrs: parentAttributes,
|
|
48
|
+
value: children[0],
|
|
49
|
+
} : children[0]
|
|
50
|
+
}
|
|
51
|
+
for (const child of children) {
|
|
52
|
+
if (typeof child !== 'object') return
|
|
53
|
+
if (child.tagName === '?xml') continue
|
|
54
|
+
|
|
55
|
+
if (!out[child.tagName]) out[child.tagName] = []
|
|
56
|
+
|
|
57
|
+
const kids = simplifyLostLess(child.children || [], child.attributes)
|
|
58
|
+
out[child.tagName].push(kids)
|
|
59
|
+
|
|
60
|
+
if (Object.keys(child.attributes).length) {
|
|
61
|
+
kids.attrs = child.attributes
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
for (const child in out) {
|
|
65
|
+
if (out[child].length === 1) out[child] = out[child][0]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return out
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function readXmlFile(zip, filename) {
|
|
72
|
+
const data = await zip.file(filename).async('string')
|
|
73
|
+
return simplifyLostLess(txml.parse(data))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function getContentTypes(zip) {
|
|
77
|
+
const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml')
|
|
78
|
+
const subObj = ContentTypesJson['Types']['Override']
|
|
79
|
+
const slidesLocArray = []
|
|
80
|
+
const slideLayoutsLocArray = []
|
|
81
|
+
|
|
82
|
+
for (const item of subObj) {
|
|
83
|
+
switch (item['attrs']['ContentType']) {
|
|
84
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
|
|
85
|
+
slidesLocArray.push(item['attrs']['PartName'].substr(1))
|
|
86
|
+
break
|
|
87
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
|
|
88
|
+
slideLayoutsLocArray.push(item['attrs']['PartName'].substr(1))
|
|
89
|
+
break
|
|
90
|
+
default:
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
slides: slidesLocArray,
|
|
95
|
+
slideLayouts: slideLayoutsLocArray,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function getSlideSize(zip) {
|
|
100
|
+
const content = await readXmlFile(zip, 'ppt/presentation.xml')
|
|
101
|
+
const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs']
|
|
102
|
+
const defaultTextStyle = content['p:presentation']['p:defaultTextStyle']
|
|
103
|
+
return {
|
|
104
|
+
width: parseInt(sldSzAttrs['cx']) * FACTOR,
|
|
105
|
+
height: parseInt(sldSzAttrs['cy']) * FACTOR,
|
|
106
|
+
defaultTextStyle,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function loadTheme(zip) {
|
|
111
|
+
const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels')
|
|
112
|
+
const relationshipArray = preResContent['Relationships']['Relationship']
|
|
113
|
+
let themeURI
|
|
114
|
+
|
|
115
|
+
if (relationshipArray.constructor === Array) {
|
|
116
|
+
for (const relationshipItem of relationshipArray) {
|
|
117
|
+
if (relationshipItem['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
|
|
118
|
+
themeURI = relationshipItem['attrs']['Target']
|
|
119
|
+
break
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
|
|
124
|
+
themeURI = relationshipArray['attrs']['Target']
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!themeURI) throw Error(`Can't open theme file.`)
|
|
128
|
+
|
|
129
|
+
return await readXmlFile(zip, 'ppt/' + themeURI)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function processSingleSlide(zip, sldFileName) {
|
|
133
|
+
const resName = sldFileName.replace('slides/slide', 'slides/_rels/slide') + '.rels'
|
|
134
|
+
const resContent = await readXmlFile(zip, resName)
|
|
135
|
+
let relationshipArray = resContent['Relationships']['Relationship']
|
|
136
|
+
let layoutFilename = ''
|
|
137
|
+
let diagramFilename = ''
|
|
138
|
+
const slideResObj = {}
|
|
139
|
+
|
|
140
|
+
if (relationshipArray.constructor === Array) {
|
|
141
|
+
for (const relationshipArrayItem of relationshipArray) {
|
|
142
|
+
switch (relationshipArrayItem['attrs']['Type']) {
|
|
143
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout':
|
|
144
|
+
layoutFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
145
|
+
break
|
|
146
|
+
case 'http://schemas.microsoft.com/office/2007/relationships/diagramDrawing':
|
|
147
|
+
diagramFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
148
|
+
slideResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
149
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
150
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
151
|
+
}
|
|
152
|
+
break
|
|
153
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide':
|
|
154
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image':
|
|
155
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart':
|
|
156
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink':
|
|
157
|
+
default:
|
|
158
|
+
slideResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
159
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
160
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else layoutFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
|
|
166
|
+
|
|
167
|
+
const slideLayoutContent = await readXmlFile(zip, layoutFilename)
|
|
168
|
+
const slideLayoutTables = await indexNodes(slideLayoutContent)
|
|
169
|
+
|
|
170
|
+
const slideLayoutResFilename = layoutFilename.replace('slideLayouts/slideLayout', 'slideLayouts/_rels/slideLayout') + '.rels'
|
|
171
|
+
const slideLayoutResContent = await readXmlFile(zip, slideLayoutResFilename)
|
|
172
|
+
relationshipArray = slideLayoutResContent['Relationships']['Relationship']
|
|
173
|
+
|
|
174
|
+
let masterFilename = ''
|
|
175
|
+
const layoutResObj = {}
|
|
176
|
+
if (relationshipArray.constructor === Array) {
|
|
177
|
+
for (const relationshipArrayItem of relationshipArray) {
|
|
178
|
+
switch (relationshipArrayItem['attrs']['Type']) {
|
|
179
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster':
|
|
180
|
+
masterFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
181
|
+
break
|
|
182
|
+
default:
|
|
183
|
+
layoutResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
184
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
185
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else masterFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
|
|
191
|
+
|
|
192
|
+
const slideMasterContent = await readXmlFile(zip, masterFilename)
|
|
193
|
+
const slideMasterTextStyles = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:txStyles'])
|
|
194
|
+
const slideMasterTables = indexNodes(slideMasterContent)
|
|
195
|
+
|
|
196
|
+
const slideMasterResFilename = masterFilename.replace('slideMasters/slideMaster', 'slideMasters/_rels/slideMaster') + '.rels'
|
|
197
|
+
const slideMasterResContent = await readXmlFile(zip, slideMasterResFilename)
|
|
198
|
+
relationshipArray = slideMasterResContent['Relationships']['Relationship']
|
|
199
|
+
const masterResObj = {}
|
|
200
|
+
if (relationshipArray.constructor === Array) {
|
|
201
|
+
for (const relationshipArrayItem of relationshipArray) {
|
|
202
|
+
switch (relationshipArrayItem['attrs']['Type']) {
|
|
203
|
+
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
|
|
204
|
+
break
|
|
205
|
+
default:
|
|
206
|
+
masterResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
207
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
208
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const diagramResObj = {}
|
|
215
|
+
let digramFileContent = {}
|
|
216
|
+
if (diagramFilename) {
|
|
217
|
+
const diagName = diagramFilename.split('/').pop()
|
|
218
|
+
const diagramResFileName = diagramFilename.replace(diagName, '_rels/' + diagName) + '.rels'
|
|
219
|
+
digramFileContent = await readXmlFile(zip, diagramFilename)
|
|
220
|
+
if (digramFileContent && digramFileContent && digramFileContent !== '') {
|
|
221
|
+
let digramFileContentObjToStr = JSON.stringify(digramFileContent)
|
|
222
|
+
digramFileContentObjToStr = digramFileContentObjToStr.replace(/dsp:/g, 'p:')
|
|
223
|
+
digramFileContent = JSON.parse(digramFileContentObjToStr)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const digramResContent = await readXmlFile(zip, diagramResFileName)
|
|
227
|
+
if (digramResContent) {
|
|
228
|
+
relationshipArray = digramResContent['Relationships']['Relationship']
|
|
229
|
+
if (relationshipArray.constructor === Array) {
|
|
230
|
+
for (const relationshipArrayItem of relationshipArray) {
|
|
231
|
+
diagramResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
232
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
233
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
diagramResObj[relationshipArray['attrs']['Id']] = {
|
|
239
|
+
type: relationshipArray['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
240
|
+
target: relationshipArray['attrs']['Target'].replace('../', 'ppt/'),
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const slideContent = await readXmlFile(zip, sldFileName)
|
|
247
|
+
const nodes = slideContent['p:sld']['p:cSld']['p:spTree']
|
|
248
|
+
const warpObj = {
|
|
249
|
+
zip,
|
|
250
|
+
slideLayoutContent: slideLayoutContent,
|
|
251
|
+
slideLayoutTables: slideLayoutTables,
|
|
252
|
+
slideMasterContent: slideMasterContent,
|
|
253
|
+
slideMasterTables: slideMasterTables,
|
|
254
|
+
slideContent: slideContent,
|
|
255
|
+
slideResObj: slideResObj,
|
|
256
|
+
slideMasterTextStyles: slideMasterTextStyles,
|
|
257
|
+
layoutResObj: layoutResObj,
|
|
258
|
+
masterResObj: masterResObj,
|
|
259
|
+
themeContent: themeContent,
|
|
260
|
+
digramFileContent: digramFileContent,
|
|
261
|
+
diagramResObj: diagramResObj,
|
|
262
|
+
defaultTextStyle: defaultTextStyle,
|
|
263
|
+
}
|
|
264
|
+
const bgColor = await getSlideBackgroundFill(warpObj)
|
|
265
|
+
|
|
266
|
+
const elements = []
|
|
267
|
+
for (const nodeKey in nodes) {
|
|
268
|
+
if (nodes[nodeKey].constructor === Array) {
|
|
269
|
+
for (const node of nodes[nodeKey]) {
|
|
270
|
+
const ret = await processNodesInSlide(nodeKey, node, warpObj)
|
|
271
|
+
if (ret) elements.push(ret)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj)
|
|
276
|
+
if (ret) elements.push(ret)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
fill: bgColor,
|
|
282
|
+
elements,
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function indexNodes(content) {
|
|
287
|
+
|
|
288
|
+
const keys = Object.keys(content)
|
|
289
|
+
const spTreeNode = content[keys[0]]['p:cSld']['p:spTree']
|
|
290
|
+
|
|
291
|
+
const idTable = {}
|
|
292
|
+
const idxTable = {}
|
|
293
|
+
const typeTable = {}
|
|
294
|
+
|
|
295
|
+
for (const key in spTreeNode) {
|
|
296
|
+
if (key === 'p:nvGrpSpPr' || key === 'p:grpSpPr') continue
|
|
297
|
+
|
|
298
|
+
const targetNode = spTreeNode[key]
|
|
299
|
+
|
|
300
|
+
if (targetNode.constructor === Array) {
|
|
301
|
+
for (const targetNodeItem of targetNode) {
|
|
302
|
+
const nvSpPrNode = targetNodeItem['p:nvSpPr']
|
|
303
|
+
const id = getTextByPathList(nvSpPrNode, ['p:cNvPr', 'attrs', 'id'])
|
|
304
|
+
const idx = getTextByPathList(nvSpPrNode, ['p:nvPr', 'p:ph', 'attrs', 'idx'])
|
|
305
|
+
const type = getTextByPathList(nvSpPrNode, ['p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
306
|
+
|
|
307
|
+
if (id) idTable[id] = targetNodeItem
|
|
308
|
+
if (idx) idxTable[idx] = targetNodeItem
|
|
309
|
+
if (type) typeTable[type] = targetNodeItem
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
const nvSpPrNode = targetNode['p:nvSpPr']
|
|
314
|
+
const id = getTextByPathList(nvSpPrNode, ['p:cNvPr', 'attrs', 'id'])
|
|
315
|
+
const idx = getTextByPathList(nvSpPrNode, ['p:nvPr', 'p:ph', 'attrs', 'idx'])
|
|
316
|
+
const type = getTextByPathList(nvSpPrNode, ['p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
317
|
+
|
|
318
|
+
if (id) idTable[id] = targetNode
|
|
319
|
+
if (idx) idxTable[idx] = targetNode
|
|
320
|
+
if (type) typeTable[type] = targetNode
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return { idTable, idxTable, typeTable }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async function processNodesInSlide(nodeKey, nodeValue, warpObj) {
|
|
328
|
+
let json
|
|
329
|
+
|
|
330
|
+
switch (nodeKey) {
|
|
331
|
+
case 'p:sp': // Shape, Text
|
|
332
|
+
json = processSpNode(nodeValue, warpObj)
|
|
333
|
+
break
|
|
334
|
+
case 'p:cxnSp': // Shape, Text (with connection)
|
|
335
|
+
json = processCxnSpNode(nodeValue, warpObj)
|
|
336
|
+
break
|
|
337
|
+
case 'p:pic': // Picture
|
|
338
|
+
json = processPicNode(nodeValue, warpObj)
|
|
339
|
+
break
|
|
340
|
+
case 'p:graphicFrame': // Chart, Diagram, Table
|
|
341
|
+
json = await processGraphicFrameNode(nodeValue, warpObj)
|
|
342
|
+
break
|
|
343
|
+
case 'p:grpSp':
|
|
344
|
+
json = await processGroupSpNode(nodeValue, warpObj)
|
|
345
|
+
break
|
|
346
|
+
default:
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return json
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async function processGroupSpNode(node, warpObj) {
|
|
353
|
+
const xfrmNode = node['p:grpSpPr']['a:xfrm']
|
|
354
|
+
const x = parseInt(xfrmNode['a:off']['attrs']['x']) * FACTOR
|
|
355
|
+
const y = parseInt(xfrmNode['a:off']['attrs']['y']) * FACTOR
|
|
356
|
+
const chx = parseInt(xfrmNode['a:chOff']['attrs']['x']) * FACTOR
|
|
357
|
+
const chy = parseInt(xfrmNode['a:chOff']['attrs']['y']) * FACTOR
|
|
358
|
+
const cx = parseInt(xfrmNode['a:ext']['attrs']['cx']) * FACTOR
|
|
359
|
+
const cy = parseInt(xfrmNode['a:ext']['attrs']['cy']) * FACTOR
|
|
360
|
+
const chcx = parseInt(xfrmNode['a:chExt']['attrs']['cx']) * FACTOR
|
|
361
|
+
const chcy = parseInt(xfrmNode['a:chExt']['attrs']['cy']) * FACTOR
|
|
362
|
+
|
|
363
|
+
const elements = []
|
|
364
|
+
for (const nodeKey in node) {
|
|
365
|
+
if (node[nodeKey].constructor === Array) {
|
|
366
|
+
for (const item of node[nodeKey]) {
|
|
367
|
+
const ret = await processNodesInSlide(nodeKey, item, warpObj)
|
|
368
|
+
if (ret) elements.push(ret)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
const ret = await processNodesInSlide(nodeKey, node[nodeKey], warpObj)
|
|
373
|
+
if (ret) elements.push(ret)
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return {
|
|
378
|
+
type: 'group',
|
|
379
|
+
top: y - chy,
|
|
380
|
+
left: x - chx,
|
|
381
|
+
width: cx - chcx,
|
|
382
|
+
height: cy - chcy,
|
|
383
|
+
elements,
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function processSpNode(node, warpObj) {
|
|
388
|
+
const id = node['p:nvSpPr']['p:cNvPr']['attrs']['id']
|
|
389
|
+
const name = node['p:nvSpPr']['p:cNvPr']['attrs']['name']
|
|
390
|
+
const idx = node['p:nvSpPr']['p:nvPr']['p:ph'] ? node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['idx'] : undefined
|
|
391
|
+
let type = node['p:nvSpPr']['p:nvPr']['p:ph'] ? node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['type'] : undefined
|
|
392
|
+
|
|
393
|
+
let slideLayoutSpNode, slideMasterSpNode
|
|
394
|
+
|
|
395
|
+
if (type) {
|
|
396
|
+
if (idx) {
|
|
397
|
+
slideLayoutSpNode = warpObj['slideLayoutTables']['typeTable'][type]
|
|
398
|
+
slideMasterSpNode = warpObj['slideMasterTables']['typeTable'][type]
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
slideLayoutSpNode = warpObj['slideLayoutTables']['typeTable'][type]
|
|
402
|
+
slideMasterSpNode = warpObj['slideMasterTables']['typeTable'][type]
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else if (idx) {
|
|
406
|
+
slideLayoutSpNode = warpObj['slideLayoutTables']['idxTable'][idx]
|
|
407
|
+
slideMasterSpNode = warpObj['slideMasterTables']['idxTable'][idx]
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (!type) {
|
|
411
|
+
const txBoxVal = getTextByPathList(node, ['p:nvSpPr', 'p:cNvSpPr', 'attrs', 'txBox'])
|
|
412
|
+
if (txBoxVal === '1') type = 'text'
|
|
413
|
+
}
|
|
414
|
+
if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
415
|
+
if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
416
|
+
|
|
417
|
+
return genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, warpObj)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function processCxnSpNode(node, warpObj) {
|
|
421
|
+
const id = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['id']
|
|
422
|
+
const name = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['name']
|
|
423
|
+
|
|
424
|
+
return genShape(node, undefined, undefined, id, name, undefined, undefined, warpObj)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, warpObj) {
|
|
428
|
+
const xfrmList = ['p:spPr', 'a:xfrm']
|
|
429
|
+
const slideXfrmNode = getTextByPathList(node, xfrmList)
|
|
430
|
+
const slideLayoutXfrmNode = getTextByPathList(slideLayoutSpNode, xfrmList)
|
|
431
|
+
const slideMasterXfrmNode = getTextByPathList(slideMasterSpNode, xfrmList)
|
|
432
|
+
|
|
433
|
+
const shapType = getTextByPathList(node, ['p:spPr', 'a:prstGeom', 'attrs', 'prst'])
|
|
434
|
+
|
|
435
|
+
const { top, left } = getPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode)
|
|
436
|
+
const { width, height } = getSize(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode)
|
|
437
|
+
|
|
438
|
+
let isFlipV = false
|
|
439
|
+
let isFlipH = false
|
|
440
|
+
if (getTextByPathList(slideXfrmNode, ['attrs', 'flipV']) === '1') {
|
|
441
|
+
isFlipV = true
|
|
442
|
+
}
|
|
443
|
+
if (getTextByPathList(slideXfrmNode, ['attrs', 'flipH']) === '1') {
|
|
444
|
+
isFlipH = true
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const rotate = angleToDegrees(getTextByPathList(slideXfrmNode, ['attrs', 'rot']))
|
|
448
|
+
|
|
449
|
+
const txtXframeNode = getTextByPathList(node, ['p:txXfrm'])
|
|
450
|
+
let txtRotate
|
|
451
|
+
if (txtXframeNode) {
|
|
452
|
+
const txtXframeRot = getTextByPathList(txtXframeNode, ['attrs', 'rot'])
|
|
453
|
+
if (txtXframeRot) txtRotate = angleToDegrees(txtXframeRot) + 90
|
|
454
|
+
}
|
|
455
|
+
else txtRotate = rotate
|
|
456
|
+
|
|
457
|
+
let content = ''
|
|
458
|
+
if (node['p:txBody']) content = genTextBody(node['p:txBody'], slideLayoutSpNode, slideMasterSpNode, type, warpObj)
|
|
459
|
+
|
|
460
|
+
if (shapType) {
|
|
461
|
+
const ext = getTextByPathList(slideXfrmNode, ['a:ext', 'attrs'])
|
|
462
|
+
const cx = parseInt(ext['cx']) * FACTOR
|
|
463
|
+
const cy = parseInt(ext['cy']) * FACTOR
|
|
464
|
+
|
|
465
|
+
const { borderColor, borderWidth, borderType } = getBorder(node)
|
|
466
|
+
const fillColor = getShapeFill(node, true)
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
type: type === 'text' ? 'text' : 'shape',
|
|
470
|
+
left,
|
|
471
|
+
top,
|
|
472
|
+
width,
|
|
473
|
+
height,
|
|
474
|
+
cx,
|
|
475
|
+
cy,
|
|
476
|
+
borderColor,
|
|
477
|
+
borderWidth,
|
|
478
|
+
borderType,
|
|
479
|
+
fillColor,
|
|
480
|
+
content,
|
|
481
|
+
isFlipV,
|
|
482
|
+
isFlipH,
|
|
483
|
+
rotate,
|
|
484
|
+
shapType,
|
|
485
|
+
id,
|
|
486
|
+
name,
|
|
487
|
+
idx,
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const { borderColor, borderWidth, borderType } = getBorder(node)
|
|
492
|
+
const fillColor = getShapeFill(node, false)
|
|
493
|
+
|
|
494
|
+
return {
|
|
495
|
+
type: 'text',
|
|
496
|
+
left,
|
|
497
|
+
top,
|
|
498
|
+
width,
|
|
499
|
+
height,
|
|
500
|
+
borderColor,
|
|
501
|
+
borderWidth,
|
|
502
|
+
borderType,
|
|
503
|
+
fillColor,
|
|
504
|
+
isFlipV,
|
|
505
|
+
isFlipH,
|
|
506
|
+
rotate: txtRotate,
|
|
507
|
+
content,
|
|
508
|
+
id,
|
|
509
|
+
name,
|
|
510
|
+
idx,
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
async function processPicNode(node, warpObj) {
|
|
515
|
+
const rid = node['p:blipFill']['a:blip']['attrs']['r:embed']
|
|
516
|
+
const imgName = warpObj['slideResObj'][rid]['target']
|
|
517
|
+
const imgFileExt = extractFileExtension(imgName).toLowerCase()
|
|
518
|
+
const zip = warpObj['zip']
|
|
519
|
+
const imgArrayBuffer = await zip.file(imgName).async('arraybuffer')
|
|
520
|
+
const xfrmNode = node['p:spPr']['a:xfrm']
|
|
521
|
+
let mimeType = ''
|
|
522
|
+
|
|
523
|
+
switch (imgFileExt) {
|
|
524
|
+
case 'jpg':
|
|
525
|
+
case 'jpeg':
|
|
526
|
+
mimeType = 'image/jpeg'
|
|
527
|
+
break
|
|
528
|
+
case 'png':
|
|
529
|
+
mimeType = 'image/png'
|
|
530
|
+
break
|
|
531
|
+
case 'gif':
|
|
532
|
+
mimeType = 'image/gif'
|
|
533
|
+
break
|
|
534
|
+
case 'emf':
|
|
535
|
+
mimeType = 'image/x-emf'
|
|
536
|
+
break
|
|
537
|
+
case 'wmf':
|
|
538
|
+
mimeType = 'image/x-wmf'
|
|
539
|
+
break
|
|
540
|
+
default:
|
|
541
|
+
mimeType = 'image/*'
|
|
542
|
+
}
|
|
543
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
544
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
545
|
+
const src = `data:${mimeType};base64,${base64ArrayBuffer(imgArrayBuffer)}`
|
|
546
|
+
|
|
547
|
+
let rotate = 0
|
|
548
|
+
const rotateNode = getTextByPathList(node, ['p:spPr', 'a:xfrm', 'attrs', 'rot'])
|
|
549
|
+
if (rotateNode) rotate = angleToDegrees(rotateNode)
|
|
550
|
+
|
|
551
|
+
return {
|
|
552
|
+
type: 'image',
|
|
553
|
+
top,
|
|
554
|
+
left,
|
|
555
|
+
width,
|
|
556
|
+
height,
|
|
557
|
+
src,
|
|
558
|
+
rotate,
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
async function processGraphicFrameNode(node, warpObj) {
|
|
563
|
+
const graphicTypeUri = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'attrs', 'uri'])
|
|
564
|
+
|
|
565
|
+
let result
|
|
566
|
+
switch (graphicTypeUri) {
|
|
567
|
+
case 'http://schemas.openxmlformats.org/drawingml/2006/table':
|
|
568
|
+
result = genTable(node, warpObj)
|
|
569
|
+
break
|
|
570
|
+
case 'http://schemas.openxmlformats.org/drawingml/2006/chart':
|
|
571
|
+
result = await genChart(node, warpObj)
|
|
572
|
+
break
|
|
573
|
+
case 'http://schemas.openxmlformats.org/drawingml/2006/diagram':
|
|
574
|
+
result = genDiagram(node, warpObj)
|
|
575
|
+
break
|
|
576
|
+
default:
|
|
577
|
+
}
|
|
578
|
+
return result
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function genTextBody(textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, warpObj) {
|
|
582
|
+
if (!textBodyNode) return ''
|
|
583
|
+
|
|
584
|
+
let text = ''
|
|
585
|
+
const slideMasterTextStyles = warpObj['slideMasterTextStyles']
|
|
586
|
+
|
|
587
|
+
const pNode = textBodyNode['a:p']
|
|
588
|
+
const pNodes = pNode.constructor === Array ? pNode : [pNode]
|
|
589
|
+
|
|
590
|
+
let isList = ''
|
|
591
|
+
|
|
592
|
+
for (const pNode of pNodes) {
|
|
593
|
+
const rNode = pNode['a:r']
|
|
594
|
+
const align = getHorizontalAlign(pNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles)
|
|
595
|
+
|
|
596
|
+
const listType = getListType(pNode)
|
|
597
|
+
if (listType) {
|
|
598
|
+
if (!isList) {
|
|
599
|
+
text += `<${listType}>`
|
|
600
|
+
isList = listType
|
|
601
|
+
}
|
|
602
|
+
else if (isList && isList !== listType) {
|
|
603
|
+
text += `</${isList}>`
|
|
604
|
+
text += `<${listType}>`
|
|
605
|
+
isList = listType
|
|
606
|
+
}
|
|
607
|
+
text += `<li style="text-align: ${align};">`
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
if (isList) {
|
|
611
|
+
text += `</${isList}>`
|
|
612
|
+
isList = ''
|
|
613
|
+
}
|
|
614
|
+
text += `<p style="text-align: ${align};">`
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (!rNode) text += genSpanElement(pNode, slideLayoutSpNode, type, warpObj)
|
|
618
|
+
else if (rNode.constructor === Array) {
|
|
619
|
+
for (const rNodeItem of rNode) text += genSpanElement(rNodeItem, slideLayoutSpNode, type, warpObj)
|
|
620
|
+
}
|
|
621
|
+
else text += genSpanElement(rNode, slideLayoutSpNode, type, warpObj)
|
|
622
|
+
|
|
623
|
+
if (listType) text += '</li>'
|
|
624
|
+
else text += '</p>'
|
|
625
|
+
}
|
|
626
|
+
return text
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function getListType(node) {
|
|
630
|
+
const pPrNode = node['a:pPr']
|
|
631
|
+
if (!pPrNode) return ''
|
|
632
|
+
|
|
633
|
+
if (pPrNode['a:buChar']) return 'ul'
|
|
634
|
+
if (pPrNode['a:buAutoNum']) return 'ol'
|
|
635
|
+
|
|
636
|
+
return ''
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function genSpanElement(node, slideLayoutSpNode, type, warpObj) {
|
|
640
|
+
const slideMasterTextStyles = warpObj['slideMasterTextStyles']
|
|
641
|
+
|
|
642
|
+
let text = node['a:t']
|
|
643
|
+
if (typeof text !== 'string') text = getTextByPathList(node, ['a:fld', 'a:t'])
|
|
644
|
+
if (typeof text !== 'string') text = ' '
|
|
645
|
+
|
|
646
|
+
let styleText = ''
|
|
647
|
+
const fontColor = getFontColor(node)
|
|
648
|
+
const fontSize = getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles)
|
|
649
|
+
const fontType = getFontType(node, type)
|
|
650
|
+
const fontBold = getFontBold(node)
|
|
651
|
+
const fontItalic = getFontItalic(node)
|
|
652
|
+
const fontDecoration = getFontDecoration(node)
|
|
653
|
+
if (fontColor) styleText += `color: ${fontColor};`
|
|
654
|
+
if (fontSize) styleText += `font-size: ${fontSize};`
|
|
655
|
+
if (fontType) styleText += `font-family: ${fontType};`
|
|
656
|
+
if (fontBold) styleText += `font-weight: ${fontBold};`
|
|
657
|
+
if (fontItalic) styleText += `font-style: ${fontItalic};`
|
|
658
|
+
if (fontDecoration) styleText += `text-decoration: ${fontDecoration};`
|
|
659
|
+
|
|
660
|
+
const linkID = getTextByPathList(node, ['a:rPr', 'a:hlinkClick', 'attrs', 'r:id'])
|
|
661
|
+
if (linkID) {
|
|
662
|
+
const linkURL = warpObj['slideResObj'][linkID]['target']
|
|
663
|
+
return `<span style="${styleText}"><a href="${linkURL}" target="_blank">${text.replace(/\s/i, ' ')}</a></span>`
|
|
664
|
+
}
|
|
665
|
+
return `<span style="${styleText}">${text.replace(/\s/i, ' ')}</span>`
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
function genTable(node, warpObj) {
|
|
669
|
+
const tableNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl'])
|
|
670
|
+
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
671
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
672
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
673
|
+
|
|
674
|
+
const trNodes = tableNode['a:tr']
|
|
675
|
+
|
|
676
|
+
const data = []
|
|
677
|
+
if (trNodes.constructor === Array) {
|
|
678
|
+
for (const trNode of trNodes) {
|
|
679
|
+
const tcNodes = trNode['a:tc']
|
|
680
|
+
const tr = []
|
|
681
|
+
|
|
682
|
+
if (tcNodes.constructor === Array) {
|
|
683
|
+
for (const tcNode of tcNodes) {
|
|
684
|
+
const text = genTextBody(tcNode['a:txBody'], undefined, undefined, undefined, warpObj)
|
|
685
|
+
const rowSpan = getTextByPathList(tcNode, ['attrs', 'rowSpan'])
|
|
686
|
+
const colSpan = getTextByPathList(tcNode, ['attrs', 'gridSpan'])
|
|
687
|
+
const vMerge = getTextByPathList(tcNode, ['attrs', 'vMerge'])
|
|
688
|
+
const hMerge = getTextByPathList(tcNode, ['attrs', 'hMerge'])
|
|
689
|
+
|
|
690
|
+
tr.push({ text, rowSpan, colSpan, vMerge, hMerge })
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
const text = genTextBody(tcNodes['a:txBody'])
|
|
695
|
+
tr.push({ text })
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
data.push(tr)
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
const tcNodes = trNodes['a:tc']
|
|
703
|
+
const tr = []
|
|
704
|
+
|
|
705
|
+
if (tcNodes.constructor === Array) {
|
|
706
|
+
for (const tcNode of tcNodes) {
|
|
707
|
+
const text = genTextBody(tcNode['a:txBody'])
|
|
708
|
+
tr.push({ text })
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
const text = genTextBody(tcNodes['a:txBody'])
|
|
713
|
+
tr.push({ text })
|
|
714
|
+
}
|
|
715
|
+
data.push(tr)
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
return {
|
|
719
|
+
type: 'table',
|
|
720
|
+
top,
|
|
721
|
+
left,
|
|
722
|
+
width,
|
|
723
|
+
height,
|
|
724
|
+
data,
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
async function genChart(node, warpObj) {
|
|
729
|
+
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
730
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
731
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
732
|
+
|
|
733
|
+
const rid = node['a:graphic']['a:graphicData']['c:chart']['attrs']['r:id']
|
|
734
|
+
const refName = warpObj['slideResObj'][rid]['target']
|
|
735
|
+
const content = await readXmlFile(warpObj['zip'], refName)
|
|
736
|
+
const plotArea = getTextByPathList(content, ['c:chartSpace', 'c:chart', 'c:plotArea'])
|
|
737
|
+
|
|
738
|
+
let chart = null
|
|
739
|
+
for (const key in plotArea) {
|
|
740
|
+
switch (key) {
|
|
741
|
+
case 'c:lineChart':
|
|
742
|
+
chart = {
|
|
743
|
+
type: 'lineChart',
|
|
744
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
745
|
+
}
|
|
746
|
+
break
|
|
747
|
+
case 'c:barChart':
|
|
748
|
+
chart = {
|
|
749
|
+
type: getTextByPathList(plotArea[key], ['c:grouping', 'attrs', 'val']) === 'stacked' ? 'stackedBarChart' : 'barChart',
|
|
750
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
751
|
+
}
|
|
752
|
+
break
|
|
753
|
+
case 'c:pieChart':
|
|
754
|
+
chart = {
|
|
755
|
+
type: 'pieChart',
|
|
756
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
757
|
+
}
|
|
758
|
+
break
|
|
759
|
+
case 'c:pie3DChart':
|
|
760
|
+
chart = {
|
|
761
|
+
type: 'pie3DChart',
|
|
762
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
763
|
+
}
|
|
764
|
+
break
|
|
765
|
+
case 'c:areaChart':
|
|
766
|
+
chart = {
|
|
767
|
+
type: getTextByPathList(plotArea[key], ['c:grouping', 'attrs', 'val']) === 'percentStacked' ? 'stackedAreaChart' : 'areaChart',
|
|
768
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
769
|
+
}
|
|
770
|
+
break
|
|
771
|
+
case 'c:scatterChart':
|
|
772
|
+
chart = {
|
|
773
|
+
type: 'scatterChart',
|
|
774
|
+
data: extractChartData(plotArea[key]['c:ser']),
|
|
775
|
+
}
|
|
776
|
+
break
|
|
777
|
+
case 'c:catAx':
|
|
778
|
+
break
|
|
779
|
+
case 'c:valAx':
|
|
780
|
+
break
|
|
781
|
+
default:
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (!chart) return {}
|
|
786
|
+
return {
|
|
787
|
+
type: 'chart',
|
|
788
|
+
top,
|
|
789
|
+
left,
|
|
790
|
+
width,
|
|
791
|
+
height,
|
|
792
|
+
data: chart.data,
|
|
793
|
+
chartType: chart.type,
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function genDiagram(node) {
|
|
798
|
+
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
799
|
+
const { left, top } = getPosition(xfrmNode, undefined, undefined)
|
|
800
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
801
|
+
|
|
802
|
+
return {
|
|
803
|
+
type: 'diagram',
|
|
804
|
+
left,
|
|
805
|
+
top,
|
|
806
|
+
width,
|
|
807
|
+
height,
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function getPosition(slideSpNode, slideLayoutSpNode, slideMasterSpNode) {
|
|
812
|
+
let off
|
|
813
|
+
|
|
814
|
+
if (slideSpNode) off = slideSpNode['a:off']['attrs']
|
|
815
|
+
else if (slideLayoutSpNode) off = slideLayoutSpNode['a:off']['attrs']
|
|
816
|
+
else if (slideMasterSpNode) off = slideMasterSpNode['a:off']['attrs']
|
|
817
|
+
|
|
818
|
+
if (!off) return { top: 0, left: 0 }
|
|
819
|
+
|
|
820
|
+
return {
|
|
821
|
+
top: parseInt(off['y']) * FACTOR,
|
|
822
|
+
left: parseInt(off['x']) * FACTOR,
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function getSize(slideSpNode, slideLayoutSpNode, slideMasterSpNode) {
|
|
827
|
+
let ext
|
|
828
|
+
|
|
829
|
+
if (slideSpNode) ext = slideSpNode['a:ext']['attrs']
|
|
830
|
+
else if (slideLayoutSpNode) ext = slideLayoutSpNode['a:ext']['attrs']
|
|
831
|
+
else if (slideMasterSpNode) ext = slideMasterSpNode['a:ext']['attrs']
|
|
832
|
+
|
|
833
|
+
if (!ext) return { width: 0, height: 0 }
|
|
834
|
+
|
|
835
|
+
return {
|
|
836
|
+
width: parseInt(ext['cx']) * FACTOR,
|
|
837
|
+
height: parseInt(ext['cy']) * FACTOR,
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function getHorizontalAlign(node, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles) {
|
|
842
|
+
let algn = getTextByPathList(node, ['a:pPr', 'attrs', 'algn'])
|
|
843
|
+
|
|
844
|
+
if (!algn) algn = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
845
|
+
if (!algn) algn = getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
846
|
+
if (!algn) {
|
|
847
|
+
switch (type) {
|
|
848
|
+
case 'title':
|
|
849
|
+
case 'subTitle':
|
|
850
|
+
case 'ctrTitle':
|
|
851
|
+
algn = getTextByPathList(slideMasterTextStyles, ['p:titleStyle', 'a:lvl1pPr', 'attrs', 'alng'])
|
|
852
|
+
break
|
|
853
|
+
default:
|
|
854
|
+
algn = getTextByPathList(slideMasterTextStyles, ['p:otherStyle', 'a:lvl1pPr', 'attrs', 'alng'])
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
if (!algn) {
|
|
858
|
+
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') return 'center'
|
|
859
|
+
else if (type === 'sldNum') return 'right'
|
|
860
|
+
}
|
|
861
|
+
return algn === 'ctr' ? 'center' : algn === 'r' ? 'right' : 'left'
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
function getFontType(node, type) {
|
|
865
|
+
let typeface = getTextByPathList(node, ['a:rPr', 'a:latin', 'attrs', 'typeface'])
|
|
866
|
+
|
|
867
|
+
if (!typeface) {
|
|
868
|
+
const fontSchemeNode = getTextByPathList(themeContent, ['a:theme', 'a:themeElements', 'a:fontScheme'])
|
|
869
|
+
|
|
870
|
+
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') {
|
|
871
|
+
typeface = getTextByPathList(fontSchemeNode, ['a:majorFont', 'a:latin', 'attrs', 'typeface'])
|
|
872
|
+
}
|
|
873
|
+
else if (type === 'body') {
|
|
874
|
+
typeface = getTextByPathList(fontSchemeNode, ['a:minorFont', 'a:latin', 'attrs', 'typeface'])
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
typeface = getTextByPathList(fontSchemeNode, ['a:minorFont', 'a:latin', 'attrs', 'typeface'])
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
return typeface || ''
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function getFontColor(node) {
|
|
885
|
+
const color = getTextByPathList(node, ['a:rPr', 'a:solidFill', 'a:srgbClr', 'attrs', 'val'])
|
|
886
|
+
return color ? `#${color}` : ''
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles) {
|
|
890
|
+
let fontSize
|
|
891
|
+
|
|
892
|
+
if (node['a:rPr']) fontSize = parseInt(node['a:rPr']['attrs']['sz']) / 100
|
|
893
|
+
|
|
894
|
+
if ((isNaN(fontSize) || !fontSize)) {
|
|
895
|
+
const sz = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:lstStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
896
|
+
fontSize = parseInt(sz) / 100
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
if (isNaN(fontSize) || !fontSize) {
|
|
900
|
+
let sz
|
|
901
|
+
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') {
|
|
902
|
+
sz = getTextByPathList(slideMasterTextStyles, ['p:titleStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
903
|
+
}
|
|
904
|
+
else if (type === 'body') {
|
|
905
|
+
sz = getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
906
|
+
}
|
|
907
|
+
else if (type === 'dt' || type === 'sldNum') {
|
|
908
|
+
sz = '1200'
|
|
909
|
+
}
|
|
910
|
+
else if (!type) {
|
|
911
|
+
sz = getTextByPathList(slideMasterTextStyles, ['p:otherStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
912
|
+
}
|
|
913
|
+
if (sz) fontSize = parseInt(sz) / 100
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const baseline = getTextByPathList(node, ['a:rPr', 'attrs', 'baseline'])
|
|
917
|
+
if (baseline && !isNaN(fontSize)) fontSize -= 10
|
|
918
|
+
|
|
919
|
+
return (isNaN(fontSize) || !fontSize) ? '18.75px' : (fontSize / 0.75 * (75 / 96) + 'px')
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function getFontBold(node) {
|
|
923
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['b'] === '1') ? 'bold' : ''
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function getFontItalic(node) {
|
|
927
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['i'] === '1') ? 'italic' : ''
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function getFontDecoration(node) {
|
|
931
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['u'] === 'sng') ? 'underline' : ''
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function getBorder(node) {
|
|
935
|
+
const lineNode = node['p:spPr']['a:ln']
|
|
936
|
+
|
|
937
|
+
let borderWidth = parseInt(getTextByPathList(lineNode, ['attrs', 'w'])) / 12700
|
|
938
|
+
if (isNaN(borderWidth)) {
|
|
939
|
+
if (lineNode) borderWidth = 0
|
|
940
|
+
else borderWidth = 1
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
let borderColor = getTextByPathList(lineNode, ['a:solidFill', 'a:srgbClr', 'attrs', 'val'])
|
|
944
|
+
if (!borderColor) {
|
|
945
|
+
const schemeClrNode = getTextByPathList(lineNode, ['a:solidFill', 'a:schemeClr'])
|
|
946
|
+
const schemeClr = 'a:' + getTextByPathList(schemeClrNode, ['attrs', 'val'])
|
|
947
|
+
borderColor = getSchemeColorFromTheme(schemeClr)
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
if (!borderColor) {
|
|
951
|
+
const schemeClrNode = getTextByPathList(node, ['p:style', 'a:lnRef', 'a:schemeClr'])
|
|
952
|
+
const schemeClr = 'a:' + getTextByPathList(schemeClrNode, ['attrs', 'val'])
|
|
953
|
+
borderColor = getSchemeColorFromTheme(schemeClr)
|
|
954
|
+
|
|
955
|
+
if (borderColor) {
|
|
956
|
+
let shade = getTextByPathList(schemeClrNode, ['a:shade', 'attrs', 'val'])
|
|
957
|
+
|
|
958
|
+
if (shade) {
|
|
959
|
+
shade = parseInt(shade) / 100000
|
|
960
|
+
|
|
961
|
+
const color = tinycolor('#' + borderColor).toHsl()
|
|
962
|
+
borderColor = tinycolor({ h: color.h, s: color.s, l: color.l * shade, a: color.a }).toHex()
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
if (!borderColor) borderColor = '#000'
|
|
968
|
+
else borderColor = `#${borderColor}`
|
|
969
|
+
|
|
970
|
+
const type = getTextByPathList(lineNode, ['a:prstDash', 'attrs', 'val'])
|
|
971
|
+
let borderType = 'solid'
|
|
972
|
+
let strokeDasharray = '0'
|
|
973
|
+
switch (type) {
|
|
974
|
+
case 'solid':
|
|
975
|
+
borderType = 'solid'
|
|
976
|
+
strokeDasharray = '0'
|
|
977
|
+
break
|
|
978
|
+
case 'dash':
|
|
979
|
+
borderType = 'dashed'
|
|
980
|
+
strokeDasharray = '5'
|
|
981
|
+
break
|
|
982
|
+
case 'dashDot':
|
|
983
|
+
borderType = 'dashed'
|
|
984
|
+
strokeDasharray = '5, 5, 1, 5'
|
|
985
|
+
break
|
|
986
|
+
case 'dot':
|
|
987
|
+
borderType = 'dotted'
|
|
988
|
+
strokeDasharray = '1, 5'
|
|
989
|
+
break
|
|
990
|
+
case 'lgDash':
|
|
991
|
+
borderType = 'dashed'
|
|
992
|
+
strokeDasharray = '10, 5'
|
|
993
|
+
break
|
|
994
|
+
case 'lgDashDotDot':
|
|
995
|
+
borderType = 'dashed'
|
|
996
|
+
strokeDasharray = '10, 5, 1, 5, 1, 5'
|
|
997
|
+
break
|
|
998
|
+
case 'sysDash':
|
|
999
|
+
borderType = 'dashed'
|
|
1000
|
+
strokeDasharray = '5, 2'
|
|
1001
|
+
break
|
|
1002
|
+
case 'sysDashDot':
|
|
1003
|
+
borderType = 'dashed'
|
|
1004
|
+
strokeDasharray = '5, 2, 1, 5'
|
|
1005
|
+
break
|
|
1006
|
+
case 'sysDashDotDot':
|
|
1007
|
+
borderType = 'dashed'
|
|
1008
|
+
strokeDasharray = '5, 2, 1, 5, 1, 5'
|
|
1009
|
+
break
|
|
1010
|
+
case 'sysDot':
|
|
1011
|
+
borderType = 'dotted'
|
|
1012
|
+
strokeDasharray = '2, 5'
|
|
1013
|
+
break
|
|
1014
|
+
default:
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return {
|
|
1018
|
+
borderColor,
|
|
1019
|
+
borderWidth,
|
|
1020
|
+
borderType,
|
|
1021
|
+
strokeDasharray,
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function getFillType(node) {
|
|
1026
|
+
let fillType = ''
|
|
1027
|
+
if (node['a:noFill']) fillType = 'NO_FILL'
|
|
1028
|
+
if (node['a:solidFill']) fillType = 'SOLID_FILL'
|
|
1029
|
+
if (node['a:gradFill']) fillType = 'GRADIENT_FILL'
|
|
1030
|
+
if (node['a:pattFill']) fillType = 'PATTERN_FILL'
|
|
1031
|
+
if (node['a:blipFill']) fillType = 'PIC_FILL'
|
|
1032
|
+
if (node['a:grpFill']) fillType = 'GROUP_FILL'
|
|
1033
|
+
|
|
1034
|
+
return fillType
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
async function getPicFill(type, node, warpObj) {
|
|
1038
|
+
let img
|
|
1039
|
+
const rId = node['a:blip']['attrs']['r:embed']
|
|
1040
|
+
let imgPath
|
|
1041
|
+
if (type === 'slideBg' || type === 'slide') {
|
|
1042
|
+
imgPath = getTextByPathList(warpObj, ['slideResObj', rId, 'target'])
|
|
1043
|
+
}
|
|
1044
|
+
else if (type === 'slideLayoutBg') {
|
|
1045
|
+
imgPath = getTextByPathList(warpObj, ['layoutResObj', rId, 'target'])
|
|
1046
|
+
}
|
|
1047
|
+
else if (type === 'slideMasterBg') {
|
|
1048
|
+
imgPath = getTextByPathList(warpObj, ['masterResObj', rId, 'target'])
|
|
1049
|
+
}
|
|
1050
|
+
else if (type === 'themeBg') {
|
|
1051
|
+
imgPath = getTextByPathList(warpObj, ['themeResObj', rId, 'target'])
|
|
1052
|
+
}
|
|
1053
|
+
else if (type === 'diagramBg') {
|
|
1054
|
+
imgPath = getTextByPathList(warpObj, ['diagramResObj', rId, 'target'])
|
|
1055
|
+
}
|
|
1056
|
+
if (!imgPath) return imgPath
|
|
1057
|
+
|
|
1058
|
+
img = getTextByPathList(warpObj, ['loaded-images', imgPath])
|
|
1059
|
+
if (!img) {
|
|
1060
|
+
imgPath = escapeHtml(imgPath)
|
|
1061
|
+
|
|
1062
|
+
const imgExt = imgPath.split('.').pop()
|
|
1063
|
+
if (imgExt === 'xml') return undefined
|
|
1064
|
+
|
|
1065
|
+
const imgArrayBuffer = await warpObj['zip'].file(imgPath).async('arraybuffer')
|
|
1066
|
+
const imgMimeType = getMimeType(imgExt)
|
|
1067
|
+
img = 'data:' + imgMimeType + 'base64,' + base64ArrayBuffer(imgArrayBuffer)
|
|
1068
|
+
}
|
|
1069
|
+
return img
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
async function getBgPicFill(bgPr, sorce, warpObj) {
|
|
1073
|
+
const picBase64 = await getPicFill(sorce, bgPr['a:blipFill'], warpObj)
|
|
1074
|
+
const aBlipNode = bgPr['a:blipFill']['a:blip']
|
|
1075
|
+
|
|
1076
|
+
const aphaModFixNode = getTextByPathList(aBlipNode, ['a:alphaModFix', 'attrs'])
|
|
1077
|
+
let opacity = 1
|
|
1078
|
+
if (aphaModFixNode && aphaModFixNode['amt'] && aphaModFixNode['amt'] !== '') {
|
|
1079
|
+
opacity = parseInt(aphaModFixNode['amt']) / 100000
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
return {
|
|
1083
|
+
picBase64,
|
|
1084
|
+
opacity,
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
async function getSlideBackgroundFill(warpObj) {
|
|
1089
|
+
const slideContent = warpObj['slideContent']
|
|
1090
|
+
const slideLayoutContent = warpObj['slideLayoutContent']
|
|
1091
|
+
const slideMasterContent = warpObj['slideMasterContent']
|
|
1092
|
+
|
|
1093
|
+
let bgPr = getTextByPathList(slideContent, ['p:sld', 'p:cSld', 'p:bg', 'p:bgPr'])
|
|
1094
|
+
|
|
1095
|
+
let background = '#fff'
|
|
1096
|
+
let backgroundType = 'color'
|
|
1097
|
+
|
|
1098
|
+
if (bgPr) {
|
|
1099
|
+
const bgFillTyp = getFillType(bgPr)
|
|
1100
|
+
|
|
1101
|
+
if (bgFillTyp === 'SOLID_FILL') {
|
|
1102
|
+
const sldFill = bgPr['a:solidFill']
|
|
1103
|
+
let clrMapOvr
|
|
1104
|
+
const sldClrMapOvr = getTextByPathList(slideContent, ['p:sld', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
|
|
1105
|
+
if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
|
|
1106
|
+
else {
|
|
1107
|
+
const sldClrMapOvr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
|
|
1108
|
+
if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
|
|
1109
|
+
else clrMapOvr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
|
|
1110
|
+
}
|
|
1111
|
+
const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
|
|
1112
|
+
background = `#${sldBgClr}`
|
|
1113
|
+
}
|
|
1114
|
+
else if (bgFillTyp === 'PIC_FILL') {
|
|
1115
|
+
background = await getBgPicFill(bgPr, 'slideBg', warpObj)
|
|
1116
|
+
backgroundType = 'image'
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
bgPr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:cSld', 'p:bg', 'p:bgPr'])
|
|
1121
|
+
|
|
1122
|
+
let clrMapOvr
|
|
1123
|
+
const sldClrMapOvr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
|
|
1124
|
+
if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
|
|
1125
|
+
else clrMapOvr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
|
|
1126
|
+
|
|
1127
|
+
if (bgPr) {
|
|
1128
|
+
const bgFillTyp = getFillType(bgPr)
|
|
1129
|
+
if (bgFillTyp === 'SOLID_FILL') {
|
|
1130
|
+
const sldFill = bgPr['a:solidFill']
|
|
1131
|
+
const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
|
|
1132
|
+
background = `#${sldBgClr}`
|
|
1133
|
+
}
|
|
1134
|
+
else if (bgFillTyp === 'PIC_FILL') {
|
|
1135
|
+
background = await getBgPicFill(bgPr, 'slideLayoutBg', warpObj)
|
|
1136
|
+
backgroundType = 'image'
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
else {
|
|
1140
|
+
bgPr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:cSld', 'p:bg', 'p:bgPr'])
|
|
1141
|
+
|
|
1142
|
+
const clrMap = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
|
|
1143
|
+
if (bgPr) {
|
|
1144
|
+
const bgFillTyp = getFillType(bgPr)
|
|
1145
|
+
if (bgFillTyp === 'SOLID_FILL') {
|
|
1146
|
+
const sldFill = bgPr['a:solidFill']
|
|
1147
|
+
const sldBgClr = getSolidFill(sldFill, clrMap, undefined, warpObj)
|
|
1148
|
+
background = `#${sldBgClr}`
|
|
1149
|
+
}
|
|
1150
|
+
else if (bgFillTyp === 'PIC_FILL') {
|
|
1151
|
+
background = await getBgPicFill(bgPr, 'slideMasterBg', warpObj)
|
|
1152
|
+
backgroundType = 'image'
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return {
|
|
1158
|
+
type: backgroundType,
|
|
1159
|
+
value: background,
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
function getShapeFill(node, isSvgMode) {
|
|
1164
|
+
if (getTextByPathList(node, ['p:spPr', 'a:noFill'])) {
|
|
1165
|
+
return isSvgMode ? 'none' : 'background-color: initial;'
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
let fillColor
|
|
1169
|
+
if (!fillColor) {
|
|
1170
|
+
fillColor = getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:srgbClr', 'attrs', 'val'])
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
if (!fillColor) {
|
|
1174
|
+
const schemeClr = 'a:' + getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'attrs', 'val'])
|
|
1175
|
+
fillColor = getSchemeColorFromTheme(schemeClr)
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
if (!fillColor) {
|
|
1179
|
+
const schemeClr = 'a:' + getTextByPathList(node, ['p:style', 'a:fillRef', 'a:schemeClr', 'attrs', 'val'])
|
|
1180
|
+
fillColor = getSchemeColorFromTheme(schemeClr)
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
if (fillColor) {
|
|
1184
|
+
fillColor = `#${fillColor}`
|
|
1185
|
+
|
|
1186
|
+
let lumMod = parseInt(getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'a:lumMod', 'attrs', 'val'])) / 100000
|
|
1187
|
+
let lumOff = parseInt(getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'a:lumOff', 'attrs', 'val'])) / 100000
|
|
1188
|
+
if (isNaN(lumMod)) lumMod = 1.0
|
|
1189
|
+
if (isNaN(lumOff)) lumOff = 0
|
|
1190
|
+
|
|
1191
|
+
const color = tinycolor(fillColor).toHsl()
|
|
1192
|
+
const lum = color.l * (1 + lumOff)
|
|
1193
|
+
return tinycolor({ h: color.h, s: color.s, l: lum, a: color.a }).toHexString()
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
if (isSvgMode) return 'none'
|
|
1197
|
+
return fillColor
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
function getSolidFill(solidFill) {
|
|
1201
|
+
if (!solidFill) return solidFill
|
|
1202
|
+
|
|
1203
|
+
let color = 'fff'
|
|
1204
|
+
|
|
1205
|
+
if (solidFill['a:srgbClr']) {
|
|
1206
|
+
color = getTextByPathList(solidFill['a:srgbClr'], ['attrs', 'val'])
|
|
1207
|
+
}
|
|
1208
|
+
else if (solidFill['a:schemeClr']) {
|
|
1209
|
+
const schemeClr = 'a:' + getTextByPathList(solidFill['a:schemeClr'], ['attrs', 'val'])
|
|
1210
|
+
color = getSchemeColorFromTheme(schemeClr)
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
return color
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
function getSchemeColorFromTheme(schemeClr) {
|
|
1217
|
+
switch (schemeClr) {
|
|
1218
|
+
case 'a:tx1':
|
|
1219
|
+
schemeClr = 'a:dk1'
|
|
1220
|
+
break
|
|
1221
|
+
case 'a:tx2':
|
|
1222
|
+
schemeClr = 'a:dk2'
|
|
1223
|
+
break
|
|
1224
|
+
case 'a:bg1':
|
|
1225
|
+
schemeClr = 'a:lt1'
|
|
1226
|
+
break
|
|
1227
|
+
case 'a:bg2':
|
|
1228
|
+
schemeClr = 'a:lt2'
|
|
1229
|
+
break
|
|
1230
|
+
default:
|
|
1231
|
+
break
|
|
1232
|
+
}
|
|
1233
|
+
const refNode = getTextByPathList(themeContent, ['a:theme', 'a:themeElements', 'a:clrScheme', schemeClr])
|
|
1234
|
+
let color = getTextByPathList(refNode, ['a:srgbClr', 'attrs', 'val'])
|
|
1235
|
+
if (!color) color = getTextByPathList(refNode, ['a:sysClr', 'attrs', 'lastClr'])
|
|
1236
|
+
return color
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function extractChartData(serNode) {
|
|
1240
|
+
const dataMat = []
|
|
1241
|
+
if (!serNode) return dataMat
|
|
1242
|
+
|
|
1243
|
+
if (serNode['c:xVal']) {
|
|
1244
|
+
let dataRow = []
|
|
1245
|
+
eachElement(serNode['c:xVal']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
1246
|
+
dataRow.push(parseFloat(innerNode['c:v']))
|
|
1247
|
+
return ''
|
|
1248
|
+
})
|
|
1249
|
+
dataMat.push(dataRow)
|
|
1250
|
+
dataRow = []
|
|
1251
|
+
eachElement(serNode['c:yVal']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
1252
|
+
dataRow.push(parseFloat(innerNode['c:v']))
|
|
1253
|
+
return ''
|
|
1254
|
+
})
|
|
1255
|
+
dataMat.push(dataRow)
|
|
1256
|
+
}
|
|
1257
|
+
else {
|
|
1258
|
+
eachElement(serNode, (innerNode, index) => {
|
|
1259
|
+
const dataRow = []
|
|
1260
|
+
const colName = getTextByPathList(innerNode, ['c:tx', 'c:strRef', 'c:strCache', 'c:pt', 'c:v']) || index
|
|
1261
|
+
|
|
1262
|
+
const rowNames = {}
|
|
1263
|
+
if (getTextByPathList(innerNode, ['c:cat', 'c:strRef', 'c:strCache', 'c:pt'])) {
|
|
1264
|
+
eachElement(innerNode['c:cat']['c:strRef']['c:strCache']['c:pt'], innerNode => {
|
|
1265
|
+
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
1266
|
+
return ''
|
|
1267
|
+
})
|
|
1268
|
+
}
|
|
1269
|
+
else if (getTextByPathList(innerNode, ['c:cat', 'c:numRef', 'c:numCache', 'c:pt'])) {
|
|
1270
|
+
eachElement(innerNode['c:cat']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
1271
|
+
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
1272
|
+
return ''
|
|
1273
|
+
})
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
if (getTextByPathList(innerNode, ['c:val', 'c:numRef', 'c:numCache', 'c:pt'])) {
|
|
1277
|
+
eachElement(innerNode['c:val']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
1278
|
+
dataRow.push({
|
|
1279
|
+
x: innerNode['attrs']['idx'],
|
|
1280
|
+
y: parseFloat(innerNode['c:v']),
|
|
1281
|
+
})
|
|
1282
|
+
return ''
|
|
1283
|
+
})
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
dataMat.push({
|
|
1287
|
+
key: colName,
|
|
1288
|
+
values: dataRow,
|
|
1289
|
+
xlabels: rowNames,
|
|
1290
|
+
})
|
|
1291
|
+
return ''
|
|
1292
|
+
})
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
return dataMat
|
|
1082
1296
|
}
|