pptxtojson 0.1.1 → 0.1.3

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/src/pptxtojson.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import JSZip from 'jszip'
2
2
  import { readXmlFile } from './readXmlFile'
3
3
  import { getBorder } from './border'
4
- import { getSlideBackgroundFill, getShapeFill } from './fill'
4
+ import { getSlideBackgroundFill, getShapeFill, getSolidFill } from './fill'
5
5
  import { getChartInfo } from './chart'
6
6
  import { getVerticalAlign } from './align'
7
7
  import { getPosition, getSize } from './position'
@@ -10,30 +10,24 @@ import { getCustomShapePath } from './shape'
10
10
  import { extractFileExtension, base64ArrayBuffer, getTextByPathList, angleToDegrees, getMimeType, isVideoLink, escapeHtml } from './utils'
11
11
  import { getShadow } from './shadow'
12
12
 
13
- let SLIDE_FACTOR = 96 / 914400
14
- let FONTSIZE_FACTOR = 100 / 75
15
-
16
- const defaultOptions = {
17
- slideFactor: SLIDE_FACTOR,
18
- fontsizeFactor: FONTSIZE_FACTOR,
19
- }
20
-
21
13
  export async function parse(file, options = {}) {
22
- options = { ...defaultOptions, ...options }
14
+ const defaultOptions = {
15
+ slideFactor: 96 / 914400,
16
+ fontsizeFactor: 100 / 75,
17
+ }
23
18
 
24
- if (options.slideFactor) SLIDE_FACTOR = options.slideFactor
25
- if (options.fontsizeFactor) FONTSIZE_FACTOR = options.fontsizeFactor
19
+ options = { ...defaultOptions, ...options }
26
20
 
27
21
  const slides = []
28
22
 
29
23
  const zip = await JSZip.loadAsync(file)
30
24
 
31
25
  const filesInfo = await getContentTypes(zip)
32
- const { width, height, defaultTextStyle } = await getSlideInfo(zip)
26
+ const { width, height, defaultTextStyle } = await getSlideInfo(zip, options)
33
27
  const themeContent = await loadTheme(zip)
34
28
 
35
29
  for (const filename of filesInfo.slides) {
36
- const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle)
30
+ const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle, options)
37
31
  slides.push(singleSlide)
38
32
  }
39
33
 
@@ -78,13 +72,13 @@ async function getContentTypes(zip) {
78
72
  }
79
73
  }
80
74
 
81
- async function getSlideInfo(zip) {
75
+ async function getSlideInfo(zip, options) {
82
76
  const content = await readXmlFile(zip, 'ppt/presentation.xml')
83
77
  const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs']
84
78
  const defaultTextStyle = content['p:presentation']['p:defaultTextStyle']
85
79
  return {
86
- width: parseInt(sldSzAttrs['cx']) * SLIDE_FACTOR,
87
- height: parseInt(sldSzAttrs['cy']) * SLIDE_FACTOR,
80
+ width: parseInt(sldSzAttrs['cx']) * options.slideFactor,
81
+ height: parseInt(sldSzAttrs['cy']) * options.slideFactor,
88
82
  defaultTextStyle,
89
83
  }
90
84
  }
@@ -110,7 +104,7 @@ async function loadTheme(zip) {
110
104
  return await readXmlFile(zip, 'ppt/' + themeURI)
111
105
  }
112
106
 
113
- async function processSingleSlide(zip, sldFileName, themeContent, defaultTextStyle) {
107
+ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextStyle, options) {
114
108
  const resName = sldFileName.replace('slides/slide', 'slides/_rels/slide') + '.rels'
115
109
  const resContent = await readXmlFile(zip, resName)
116
110
  let relationshipArray = resContent['Relationships']['Relationship']
@@ -252,37 +246,42 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
252
246
  }
253
247
  }
254
248
 
249
+ const tableStyles = await readXmlFile(zip, 'ppt/tableStyles.xml')
250
+
255
251
  const slideContent = await readXmlFile(zip, sldFileName)
256
252
  const nodes = slideContent['p:sld']['p:cSld']['p:spTree']
257
253
  const warpObj = {
258
254
  zip,
259
- slideLayoutContent: slideLayoutContent,
260
- slideLayoutTables: slideLayoutTables,
261
- slideMasterContent: slideMasterContent,
262
- slideMasterTables: slideMasterTables,
263
- slideContent: slideContent,
264
- slideResObj: slideResObj,
265
- slideMasterTextStyles: slideMasterTextStyles,
266
- layoutResObj: layoutResObj,
267
- masterResObj: masterResObj,
268
- themeContent: themeContent,
269
- themeResObj: themeResObj,
270
- digramFileContent: digramFileContent,
271
- diagramResObj: diagramResObj,
272
- defaultTextStyle: defaultTextStyle,
255
+ slideLayoutContent,
256
+ slideLayoutTables,
257
+ slideMasterContent,
258
+ slideMasterTables,
259
+ slideContent,
260
+ tableStyles,
261
+ slideResObj,
262
+ slideMasterTextStyles,
263
+ layoutResObj,
264
+ masterResObj,
265
+ themeContent,
266
+ themeResObj,
267
+ digramFileContent,
268
+ diagramResObj,
269
+ defaultTextStyle,
270
+ options,
273
271
  }
272
+ // const bgElements = await getBackground(warpObj)
274
273
  const bgColor = await getSlideBackgroundFill(warpObj)
275
274
 
276
275
  const elements = []
277
276
  for (const nodeKey in nodes) {
278
277
  if (nodes[nodeKey].constructor === Array) {
279
278
  for (const node of nodes[nodeKey]) {
280
- const ret = await processNodesInSlide(nodeKey, node, warpObj)
279
+ const ret = await processNodesInSlide(nodeKey, node, warpObj, 'slide')
281
280
  if (ret) elements.push(ret)
282
281
  }
283
282
  }
284
283
  else {
285
- const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj)
284
+ const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj, 'slide')
286
285
  if (ret) elements.push(ret)
287
286
  }
288
287
  }
@@ -293,6 +292,51 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
293
292
  }
294
293
  }
295
294
 
295
+ // async function getBackground(warpObj) {
296
+ // const elements = []
297
+ // const slideLayoutContent = warpObj['slideLayoutContent']
298
+ // const slideMasterContent = warpObj['slideMasterContent']
299
+ // const nodesSldLayout = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:cSld', 'p:spTree'])
300
+ // const nodesSldMaster = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:cSld', 'p:spTree'])
301
+
302
+ // const showMasterSp = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'attrs', 'showMasterSp'])
303
+ // if (nodesSldLayout) {
304
+ // for (const nodeKey in nodesSldLayout) {
305
+ // if (nodesSldLayout[nodeKey].constructor === Array) {
306
+ // for (let i = 0; i < nodesSldLayout[nodeKey].length; i++) {
307
+ // const ph_type = getTextByPathList(nodesSldLayout[nodeKey][i], ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
308
+ // if (ph_type !== 'pic') {
309
+ // const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey][i], warpObj, 'slideLayoutBg')
310
+ // if (ret) elements.push(ret)
311
+ // }
312
+ // }
313
+ // }
314
+ // else {
315
+ // const ph_type = getTextByPathList(nodesSldLayout[nodeKey], ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
316
+ // if (ph_type !== 'pic') {
317
+ // const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey], warpObj, 'slideLayoutBg')
318
+ // if (ret) elements.push(ret)
319
+ // }
320
+ // }
321
+ // }
322
+ // }
323
+ // if (nodesSldMaster && (showMasterSp === '1' || showMasterSp)) {
324
+ // for (const nodeKey in nodesSldMaster) {
325
+ // if (nodesSldMaster[nodeKey].constructor === Array) {
326
+ // for (let i = 0; i < nodesSldMaster[nodeKey].length; i++) {
327
+ // const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey][i], warpObj, 'slideMasterBg')
328
+ // if (ret) elements.push(ret)
329
+ // }
330
+ // }
331
+ // else {
332
+ // const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey], warpObj, 'slideMasterBg')
333
+ // if (ret) elements.push(ret)
334
+ // }
335
+ // }
336
+ // }
337
+ // return elements
338
+ // }
339
+
296
340
  function indexNodes(content) {
297
341
  const keys = Object.keys(content)
298
342
  const spTreeNode = content[keys[0]]['p:cSld']['p:spTree']
@@ -332,27 +376,27 @@ function indexNodes(content) {
332
376
  return { idTable, idxTable, typeTable }
333
377
  }
334
378
 
335
- async function processNodesInSlide(nodeKey, nodeValue, warpObj) {
379
+ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
336
380
  let json
337
381
 
338
382
  switch (nodeKey) {
339
383
  case 'p:sp': // Shape, Text
340
- json = processSpNode(nodeValue, warpObj)
384
+ json = processSpNode(nodeValue, warpObj, source)
341
385
  break
342
386
  case 'p:cxnSp': // Shape, Text
343
- json = processCxnSpNode(nodeValue, warpObj)
387
+ json = processCxnSpNode(nodeValue, warpObj, source)
344
388
  break
345
389
  case 'p:pic': // Image, Video, Audio
346
- json = processPicNode(nodeValue, warpObj)
390
+ json = processPicNode(nodeValue, warpObj, source)
347
391
  break
348
392
  case 'p:graphicFrame': // Chart, Diagram, Table
349
- json = await processGraphicFrameNode(nodeValue, warpObj)
393
+ json = await processGraphicFrameNode(nodeValue, warpObj, source)
350
394
  break
351
395
  case 'p:grpSp':
352
- json = await processGroupSpNode(nodeValue, warpObj)
396
+ json = await processGroupSpNode(nodeValue, warpObj, source)
353
397
  break
354
398
  case 'mc:AlternateContent':
355
- json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj)
399
+ json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj, source)
356
400
  break
357
401
  default:
358
402
  }
@@ -360,45 +404,55 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj) {
360
404
  return json
361
405
  }
362
406
 
363
- async function processGroupSpNode(node, warpObj) {
407
+ async function processGroupSpNode(node, warpObj, source) {
364
408
  const xfrmNode = getTextByPathList(node, ['p:grpSpPr', 'a:xfrm'])
365
409
  if (!xfrmNode) return null
366
410
 
367
- const x = parseInt(xfrmNode['a:off']['attrs']['x']) * SLIDE_FACTOR
368
- const y = parseInt(xfrmNode['a:off']['attrs']['y']) * SLIDE_FACTOR
369
- const chx = parseInt(xfrmNode['a:chOff']['attrs']['x']) * SLIDE_FACTOR
370
- const chy = parseInt(xfrmNode['a:chOff']['attrs']['y']) * SLIDE_FACTOR
371
- const cx = parseInt(xfrmNode['a:ext']['attrs']['cx']) * SLIDE_FACTOR
372
- const cy = parseInt(xfrmNode['a:ext']['attrs']['cy']) * SLIDE_FACTOR
373
- const chcx = parseInt(xfrmNode['a:chExt']['attrs']['cx']) * SLIDE_FACTOR
374
- const chcy = parseInt(xfrmNode['a:chExt']['attrs']['cy']) * SLIDE_FACTOR
411
+ const x = parseInt(xfrmNode['a:off']['attrs']['x']) * warpObj.options.slideFactor
412
+ const y = parseInt(xfrmNode['a:off']['attrs']['y']) * warpObj.options.slideFactor
413
+ // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.drawing.childoffset?view=openxml-2.8.1
414
+ const chx = parseInt(xfrmNode['a:chOff']['attrs']['x']) * warpObj.options.slideFactor
415
+ const chy = parseInt(xfrmNode['a:chOff']['attrs']['y']) * warpObj.options.slideFactor
416
+ const cx = parseInt(xfrmNode['a:ext']['attrs']['cx']) * warpObj.options.slideFactor
417
+ const cy = parseInt(xfrmNode['a:ext']['attrs']['cy']) * warpObj.options.slideFactor
418
+ // https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.drawing.childextents?view=openxml-2.8.1
419
+ const chcx = parseInt(xfrmNode['a:chExt']['attrs']['cx']) * warpObj.options.slideFactor
420
+ const chcy = parseInt(xfrmNode['a:chExt']['attrs']['cy']) * warpObj.options.slideFactor
421
+ // children coordinate
422
+ const ws = cx / chcx
423
+ const hs = cy / chcy
375
424
 
376
425
  const elements = []
377
426
  for (const nodeKey in node) {
378
427
  if (node[nodeKey].constructor === Array) {
379
428
  for (const item of node[nodeKey]) {
380
- const ret = await processNodesInSlide(nodeKey, item, warpObj)
429
+ const ret = await processNodesInSlide(nodeKey, item, warpObj, source)
381
430
  if (ret) elements.push(ret)
382
431
  }
383
432
  }
384
433
  else {
385
- const ret = await processNodesInSlide(nodeKey, node[nodeKey], warpObj)
434
+ const ret = await processNodesInSlide(nodeKey, node[nodeKey], warpObj, source)
386
435
  if (ret) elements.push(ret)
387
436
  }
388
437
  }
389
438
 
390
439
  return {
391
440
  type: 'group',
392
- top: y - chy,
393
- left: x - chx,
394
- width: cx - chcx,
395
- height: cy - chcy,
396
- elements,
441
+ top: parseFloat(y.toFixed(2)),
442
+ left: parseFloat(x.toFixed(2)),
443
+ width: parseFloat(cx.toFixed(2)),
444
+ height: parseFloat(cy.toFixed(2)),
445
+ elements: elements.map(element => ({
446
+ ...element,
447
+ left: parseFloat(((element.left - chx) * ws).toFixed(2)),
448
+ top: parseFloat(((element.top - chy) * hs).toFixed(2)),
449
+ width: parseFloat((element.width * ws).toFixed(2)),
450
+ height: parseFloat((element.height * hs).toFixed(2)),
451
+ }))
397
452
  }
398
453
  }
399
454
 
400
455
  function processSpNode(node, warpObj, source) {
401
- const id = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'id'])
402
456
  const name = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'name'])
403
457
  const idx = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'idx'])
404
458
  let type = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
@@ -432,19 +486,17 @@ function processSpNode(node, warpObj, source) {
432
486
  else type = 'obj'
433
487
  }
434
488
 
435
- return genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, warpObj)
489
+ return genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj)
436
490
  }
437
491
 
438
492
  function processCxnSpNode(node, warpObj) {
439
- const id = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['id']
440
493
  const name = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['name']
441
- const idx = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['idx']
442
494
  const type = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['type']
443
495
 
444
- return genShape(node, undefined, undefined, id, name, idx, type, warpObj)
496
+ return genShape(node, undefined, undefined, name, type, warpObj)
445
497
  }
446
498
 
447
- function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, type, warpObj) {
499
+ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj) {
448
500
  const xfrmList = ['p:spPr', 'a:xfrm']
449
501
  const slideXfrmNode = getTextByPathList(node, xfrmList)
450
502
  const slideLayoutXfrmNode = getTextByPathList(slideLayoutSpNode, xfrmList)
@@ -453,8 +505,8 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
453
505
  const shapType = getTextByPathList(node, ['p:spPr', 'a:prstGeom', 'attrs', 'prst'])
454
506
  const custShapType = getTextByPathList(node, ['p:spPr', 'a:custGeom'])
455
507
 
456
- const { top, left } = getPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, SLIDE_FACTOR)
457
- const { width, height } = getSize(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, SLIDE_FACTOR)
508
+ const { top, left } = getPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, warpObj.options.slideFactor)
509
+ const { width, height } = getSize(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, warpObj.options.slideFactor)
458
510
 
459
511
  const isFlipV = getTextByPathList(slideXfrmNode, ['attrs', 'flipV']) === '1'
460
512
  const isFlipH = getTextByPathList(slideXfrmNode, ['attrs', 'flipH']) === '1'
@@ -470,14 +522,14 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
470
522
  else txtRotate = rotate
471
523
 
472
524
  let content = ''
473
- if (node['p:txBody']) content = genTextBody(node['p:txBody'], slideLayoutSpNode, slideMasterSpNode, type, warpObj, FONTSIZE_FACTOR, SLIDE_FACTOR)
525
+ if (node['p:txBody']) content = genTextBody(node['p:txBody'], node, slideLayoutSpNode, type, warpObj)
474
526
 
475
527
  const { borderColor, borderWidth, borderType, strokeDasharray } = getBorder(node, type, warpObj)
476
528
  const fillColor = getShapeFill(node, undefined, warpObj) || ''
477
529
 
478
530
  let shadow
479
531
  const outerShdwNode = getTextByPathList(node, ['p:spPr', 'a:effectLst', 'a:outerShdw'])
480
- if (outerShdwNode) shadow = getShadow(outerShdwNode, warpObj, SLIDE_FACTOR)
532
+ if (outerShdwNode) shadow = getShadow(outerShdwNode, warpObj)
481
533
 
482
534
  const vAlign = getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode, type)
483
535
  const isVertical = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'vert']) === 'eaVert'
@@ -497,40 +549,28 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
497
549
  isFlipH,
498
550
  rotate,
499
551
  vAlign,
500
- id,
501
552
  name,
502
- idx,
503
553
  }
504
554
 
505
555
  if (shadow) data.shadow = shadow
506
556
 
507
557
  if (custShapType && type !== 'diagram') {
508
558
  const ext = getTextByPathList(slideXfrmNode, ['a:ext', 'attrs'])
509
- const cx = parseInt(ext['cx']) * SLIDE_FACTOR
510
- const cy = parseInt(ext['cy']) * SLIDE_FACTOR
511
- const w = parseInt(ext['cx']) * SLIDE_FACTOR
512
- const h = parseInt(ext['cy']) * SLIDE_FACTOR
559
+ const w = parseInt(ext['cx']) * warpObj.options.slideFactor
560
+ const h = parseInt(ext['cy']) * warpObj.options.slideFactor
513
561
  const d = getCustomShapePath(custShapType, w, h)
514
562
 
515
563
  return {
516
564
  ...data,
517
565
  type: 'shape',
518
- cx,
519
- cy,
520
566
  shapType: 'custom',
521
567
  path: d,
522
568
  }
523
569
  }
524
570
  if (shapType && type !== 'text') {
525
- const ext = getTextByPathList(slideXfrmNode, ['a:ext', 'attrs'])
526
- const cx = parseInt(ext['cx']) * SLIDE_FACTOR
527
- const cy = parseInt(ext['cy']) * SLIDE_FACTOR
528
-
529
571
  return {
530
572
  ...data,
531
573
  type: 'shape',
532
- cx,
533
- cy,
534
574
  shapType,
535
575
  }
536
576
  }
@@ -556,10 +596,13 @@ async function processPicNode(node, warpObj, source) {
556
596
  const xfrmNode = node['p:spPr']['a:xfrm']
557
597
 
558
598
  const mimeType = getMimeType(imgFileExt)
559
- const { top, left } = getPosition(xfrmNode, undefined, undefined, SLIDE_FACTOR)
560
- const { width, height } = getSize(xfrmNode, undefined, undefined, SLIDE_FACTOR)
599
+ const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
600
+ const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
561
601
  const src = `data:${mimeType};base64,${base64ArrayBuffer(imgArrayBuffer)}`
562
602
 
603
+ const isFlipV = getTextByPathList(xfrmNode, ['attrs', 'flipV']) === '1'
604
+ const isFlipH = getTextByPathList(xfrmNode, ['attrs', 'flipH']) === '1'
605
+
563
606
  let rotate = 0
564
607
  const rotateNode = getTextByPathList(node, ['p:spPr', 'a:xfrm', 'attrs', 'rot'])
565
608
  if (rotateNode) rotate = angleToDegrees(rotateNode)
@@ -640,10 +683,12 @@ async function processPicNode(node, warpObj, source) {
640
683
  height,
641
684
  rotate,
642
685
  src,
686
+ isFlipV,
687
+ isFlipH
643
688
  }
644
689
  }
645
690
 
646
- async function processGraphicFrameNode(node, warpObj) {
691
+ async function processGraphicFrameNode(node, warpObj, source) {
647
692
  const graphicTypeUri = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'attrs', 'uri'])
648
693
 
649
694
  let result
@@ -660,7 +705,7 @@ async function processGraphicFrameNode(node, warpObj) {
660
705
  case 'http://schemas.openxmlformats.org/presentationml/2006/ole':
661
706
  let oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'mc:AlternateContent', 'mc:Fallback', 'p:oleObj'])
662
707
  if (!oleObjNode) oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'p:oleObj'])
663
- else processGroupSpNode(oleObjNode, warpObj)
708
+ else processGroupSpNode(oleObjNode, warpObj, source)
664
709
  break
665
710
  default:
666
711
  }
@@ -670,8 +715,41 @@ async function processGraphicFrameNode(node, warpObj) {
670
715
  function genTable(node, warpObj) {
671
716
  const tableNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl'])
672
717
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
673
- const { top, left } = getPosition(xfrmNode, undefined, undefined, SLIDE_FACTOR)
674
- const { width, height } = getSize(xfrmNode, undefined, undefined, SLIDE_FACTOR)
718
+ const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
719
+ const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
720
+
721
+ const getTblPr = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl', 'a:tblPr'])
722
+
723
+ let thisTblStyle
724
+ const tbleStyleId = getTblPr['a:tableStyleId']
725
+ if (tbleStyleId) {
726
+ const tbleStylList = warpObj['tableStyles']['a:tblStyleLst']['a:tblStyle']
727
+ if (tbleStylList) {
728
+ if (tbleStylList.constructor === Array) {
729
+ for (let k = 0; k < tbleStylList.length; k++) {
730
+ if (tbleStylList[k]['attrs']['styleId'] === tbleStyleId) {
731
+ thisTblStyle = tbleStylList[k]
732
+ }
733
+ }
734
+ }
735
+ else {
736
+ if (tbleStylList['attrs']['styleId'] === tbleStyleId) {
737
+ thisTblStyle = tbleStylList
738
+ }
739
+ }
740
+ }
741
+ }
742
+
743
+ let themeColor = ''
744
+ let tbl_bgFillschemeClr = getTextByPathList(thisTblStyle, ['a:tblBg', 'a:fillRef'])
745
+ if (tbl_bgFillschemeClr) {
746
+ themeColor = getSolidFill(tbl_bgFillschemeClr, undefined, undefined, warpObj)
747
+ }
748
+ if (tbl_bgFillschemeClr === undefined) {
749
+ tbl_bgFillschemeClr = getTextByPathList(thisTblStyle, ['a:wholeTbl', 'a:tcStyle', 'a:fill', 'a:solidFill'])
750
+ themeColor = getSolidFill(tbl_bgFillschemeClr, undefined, undefined, warpObj)
751
+ }
752
+ if (themeColor !== '') themeColor = '#' + themeColor
675
753
 
676
754
  const trNodes = tableNode['a:tr']
677
755
 
@@ -683,7 +761,7 @@ function genTable(node, warpObj) {
683
761
 
684
762
  if (tcNodes.constructor === Array) {
685
763
  for (const tcNode of tcNodes) {
686
- const text = genTextBody(tcNode['a:txBody'], undefined, undefined, undefined, warpObj, FONTSIZE_FACTOR, SLIDE_FACTOR)
764
+ const text = genTextBody(tcNode['a:txBody'], tcNode, undefined, undefined, warpObj)
687
765
  const rowSpan = getTextByPathList(tcNode, ['attrs', 'rowSpan'])
688
766
  const colSpan = getTextByPathList(tcNode, ['attrs', 'gridSpan'])
689
767
  const vMerge = getTextByPathList(tcNode, ['attrs', 'vMerge'])
@@ -693,7 +771,7 @@ function genTable(node, warpObj) {
693
771
  }
694
772
  }
695
773
  else {
696
- const text = genTextBody(tcNodes['a:txBody'], undefined, undefined, undefined, warpObj, FONTSIZE_FACTOR, SLIDE_FACTOR)
774
+ const text = genTextBody(tcNodes['a:txBody'], tcNodes, undefined, undefined, warpObj)
697
775
  tr.push({ text })
698
776
  }
699
777
  data.push(tr)
@@ -705,12 +783,12 @@ function genTable(node, warpObj) {
705
783
 
706
784
  if (tcNodes.constructor === Array) {
707
785
  for (const tcNode of tcNodes) {
708
- const text = genTextBody(tcNode['a:txBody'], undefined, undefined, undefined, warpObj, FONTSIZE_FACTOR, SLIDE_FACTOR)
786
+ const text = genTextBody(tcNode['a:txBody'], tcNode, undefined, undefined, warpObj)
709
787
  tr.push({ text })
710
788
  }
711
789
  }
712
790
  else {
713
- const text = genTextBody(tcNodes['a:txBody'], undefined, undefined, undefined, warpObj, FONTSIZE_FACTOR, SLIDE_FACTOR)
791
+ const text = genTextBody(tcNodes['a:txBody'], tcNodes, undefined, undefined, warpObj)
714
792
  tr.push({ text })
715
793
  }
716
794
  data.push(tr)
@@ -723,13 +801,14 @@ function genTable(node, warpObj) {
723
801
  width,
724
802
  height,
725
803
  data,
804
+ themeColor,
726
805
  }
727
806
  }
728
807
 
729
808
  async function genChart(node, warpObj) {
730
809
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
731
- const { top, left } = getPosition(xfrmNode, undefined, undefined, SLIDE_FACTOR)
732
- const { width, height } = getSize(xfrmNode, undefined, undefined, SLIDE_FACTOR)
810
+ const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
811
+ const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
733
812
 
734
813
  const rid = node['a:graphic']['a:graphicData']['c:chart']['attrs']['r:id']
735
814
  const refName = warpObj['slideResObj'][rid]['target']
@@ -760,8 +839,8 @@ async function genChart(node, warpObj) {
760
839
 
761
840
  function genDiagram(node, warpObj) {
762
841
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
763
- const { left, top } = getPosition(xfrmNode, undefined, undefined, SLIDE_FACTOR)
764
- const { width, height } = getSize(xfrmNode, undefined, undefined, SLIDE_FACTOR)
842
+ const { left, top } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
843
+ const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
765
844
 
766
845
  const dgmDrwSpArray = getTextByPathList(warpObj['digramFileContent'], ['p:drawing', 'p:spTree', 'p:sp'])
767
846
  const elements = []
@@ -1,12 +1,14 @@
1
1
  import * as txml from 'txml/dist/txml.mjs'
2
2
 
3
+ let cust_attr_order = 0
4
+
3
5
  export function simplifyLostLess(children, parentAttributes = {}) {
4
6
  const out = {}
5
7
  if (!children.length) return out
6
8
 
7
9
  if (children.length === 1 && typeof children[0] === 'string') {
8
10
  return Object.keys(parentAttributes).length ? {
9
- attrs: parentAttributes,
11
+ attrs: { order: cust_attr_order++, ...parentAttributes },
10
12
  value: children[0],
11
13
  } : children[0]
12
14
  }
@@ -20,7 +22,7 @@ export function simplifyLostLess(children, parentAttributes = {}) {
20
22
  out[child.tagName].push(kids)
21
23
 
22
24
  if (Object.keys(child.attributes).length) {
23
- kids.attrs = child.attributes
25
+ kids.attrs = { order: cust_attr_order++, ...child.attributes }
24
26
  }
25
27
  }
26
28
  for (const child in out) {
package/src/shadow.js CHANGED
@@ -1,17 +1,18 @@
1
1
  import { getSolidFill } from './fill'
2
2
 
3
- export function getShadow(node, warpObj, slideFactor) {
3
+ export function getShadow(node, warpObj) {
4
+ const slideFactor = warpObj.options.slideFactor
4
5
  const chdwClrNode = getSolidFill(node, undefined, undefined, warpObj)
5
6
  const outerShdwAttrs = node['attrs']
6
7
  const dir = (outerShdwAttrs['dir']) ? (parseInt(outerShdwAttrs['dir']) / 60000) : 0
7
8
  const dist = parseInt(outerShdwAttrs['dist']) * slideFactor
8
- const blurRad = outerShdwAttrs['blurRad'] ? (parseInt(outerShdwAttrs['blurRad']) * slideFactor) : ''
9
+ const blurRad = outerShdwAttrs['blurRad'] ? parseFloat((parseInt(outerShdwAttrs['blurRad']) * slideFactor).toFixed(2)) : ''
9
10
  const vx = dist * Math.sin(dir * Math.PI / 180)
10
11
  const hx = dist * Math.cos(dir * Math.PI / 180)
11
12
 
12
13
  return {
13
- h: hx,
14
- v: vx,
14
+ h: parseFloat(hx.toFixed(2)),
15
+ v: parseFloat(vx.toFixed(2)),
15
16
  blur: blurRad,
16
17
  color: '#' + chdwClrNode,
17
18
  }
package/src/shape.js CHANGED
@@ -57,11 +57,12 @@ export function getCustomShapePath(custShapType, w, h) {
57
57
  const moveToNoPt = moveToPtNode[key]
58
58
  const spX = moveToNoPt['attrs', 'x']
59
59
  const spY = moveToNoPt['attrs', 'y']
60
-
60
+ const order = moveToNoPt['attrs', 'order']
61
61
  multiSapeAry.push({
62
62
  type: 'movto',
63
63
  x: spX,
64
64
  y: spY,
65
+ order,
65
66
  })
66
67
  })
67
68
  }
@@ -74,10 +75,12 @@ export function getCustomShapePath(custShapType, w, h) {
74
75
  const lnToNoPt = lnToPtNode[key]
75
76
  const ptX = lnToNoPt['attrs', 'x']
76
77
  const ptY = lnToNoPt['attrs', 'y']
78
+ const order = lnToNoPt['attrs', 'order']
77
79
  multiSapeAry.push({
78
80
  type: 'lnto',
79
81
  x: ptX,
80
82
  y: ptY,
83
+ order,
81
84
  })
82
85
  })
83
86
  }
@@ -101,14 +104,17 @@ export function getCustomShapePath(custShapType, w, h) {
101
104
  }
102
105
  pts_ary.push(pt_obj)
103
106
  })
107
+ const order = key[0]['attrs']['order']
104
108
  multiSapeAry.push({
105
109
  type: 'cubicBezTo',
106
- cubBzPt: pts_ary
110
+ cubBzPt: pts_ary,
111
+ order,
107
112
  })
108
113
  })
109
114
  }
110
115
  if (arcToNodes) {
111
116
  const arcToNodesAttrs = arcToNodes['attrs']
117
+ const order = arcToNodesAttrs['order']
112
118
  const hR = arcToNodesAttrs['hR']
113
119
  const wR = arcToNodesAttrs['wR']
114
120
  const stAng = arcToNodesAttrs['stAng']
@@ -128,6 +134,7 @@ export function getCustomShapePath(custShapType, w, h) {
128
134
  swAng: swAng,
129
135
  shftX: shftX,
130
136
  shftY: shftY,
137
+ order,
131
138
  })
132
139
  }
133
140
  if (closeNode) {
@@ -135,13 +142,15 @@ export function getCustomShapePath(custShapType, w, h) {
135
142
  Object.keys(closeNode).forEach(() => {
136
143
  multiSapeAry.push({
137
144
  type: 'close',
145
+ order: Infinity,
138
146
  })
139
147
  })
140
148
  }
141
149
 
150
+ multiSapeAry.sort((a, b) => a.order - b.order)
151
+
142
152
  let k = 0
143
153
  while (k < multiSapeAry.length) {
144
-
145
154
  if (multiSapeAry[k].type === 'movto') {
146
155
  const spX = parseInt(multiSapeAry[k].x) * cX
147
156
  const spY = parseInt(multiSapeAry[k].y) * cY