pptxtojson 1.1.0 → 1.2.0

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
@@ -7,7 +7,7 @@ import { getVerticalAlign } from './align'
7
7
  import { getPosition, getSize } from './position'
8
8
  import { genTextBody } from './text'
9
9
  import { getCustomShapePath } from './shape'
10
- import { extractFileExtension, base64ArrayBuffer, getTextByPathList, angleToDegrees, getMimeType, isVideoLink, escapeHtml } from './utils'
10
+ import { extractFileExtension, base64ArrayBuffer, getTextByPathList, angleToDegrees, getMimeType, isVideoLink, escapeHtml, hasValidText } from './utils'
11
11
  import { getShadow } from './shadow'
12
12
  import { getTableBorders, getTableCellParams, getTableRowParams } from './table'
13
13
  import { RATIO_EMUs_Points } from './constants'
@@ -20,7 +20,7 @@ export async function parse(file) {
20
20
 
21
21
  const filesInfo = await getContentTypes(zip)
22
22
  const { width, height, defaultTextStyle } = await getSlideInfo(zip)
23
- const themeContent = await loadTheme(zip)
23
+ const { themeContent, themeColors } = await getTheme(zip)
24
24
 
25
25
  for (const filename of filesInfo.slides) {
26
26
  const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle)
@@ -29,6 +29,7 @@ export async function parse(file) {
29
29
 
30
30
  return {
31
31
  slides,
32
+ themeColors,
32
33
  size: {
33
34
  width,
34
35
  height,
@@ -79,7 +80,7 @@ async function getSlideInfo(zip) {
79
80
  }
80
81
  }
81
82
 
82
- async function loadTheme(zip) {
83
+ async function getTheme(zip) {
83
84
  const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels')
84
85
  const relationshipArray = preResContent['Relationships']['Relationship']
85
86
  let themeURI
@@ -95,103 +96,109 @@ async function loadTheme(zip) {
95
96
  else if (relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
96
97
  themeURI = relationshipArray['attrs']['Target']
97
98
  }
98
- if (!themeURI) throw Error(`Can't open theme file.`)
99
99
 
100
- return await readXmlFile(zip, 'ppt/' + themeURI)
100
+ const themeContent = await readXmlFile(zip, 'ppt/' + themeURI)
101
+
102
+ const themeColors = []
103
+ const clrScheme = getTextByPathList(themeContent, ['a:theme', 'a:themeElements', 'a:clrScheme'])
104
+ if (clrScheme) {
105
+ for (let i = 1; i <= 6; i++) {
106
+ if (clrScheme[`a:accent${i}`] === undefined) break
107
+ const color = getTextByPathList(clrScheme, [`a:accent${i}`, 'a:srgbClr', 'attrs', 'val'])
108
+ if (color) themeColors.push('#' + color)
109
+ }
110
+ }
111
+
112
+ return { themeContent, themeColors }
101
113
  }
102
114
 
103
115
  async function processSingleSlide(zip, sldFileName, themeContent, defaultTextStyle) {
104
116
  const resName = sldFileName.replace('slides/slide', 'slides/_rels/slide') + '.rels'
105
117
  const resContent = await readXmlFile(zip, resName)
106
118
  let relationshipArray = resContent['Relationships']['Relationship']
119
+ if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
120
+
121
+ let noteFilename = ''
107
122
  let layoutFilename = ''
123
+ let masterFilename = ''
124
+ let themeFilename = ''
108
125
  let diagramFilename = ''
109
- let notesFilename = ''
110
126
  const slideResObj = {}
127
+ const layoutResObj = {}
128
+ const masterResObj = {}
129
+ const themeResObj = {}
130
+ const diagramResObj = {}
111
131
 
112
- if (relationshipArray.constructor === Array) {
113
- for (const relationshipArrayItem of relationshipArray) {
114
- switch (relationshipArrayItem['attrs']['Type']) {
115
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout':
116
- layoutFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
117
- break
118
- case 'http://schemas.microsoft.com/office/2007/relationships/diagramDrawing':
119
- diagramFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
120
- slideResObj[relationshipArrayItem['attrs']['Id']] = {
121
- type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
122
- target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
123
- }
124
- break
125
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide':
126
- notesFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
127
- break
128
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image':
129
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart':
130
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink':
131
- default:
132
- slideResObj[relationshipArrayItem['attrs']['Id']] = {
133
- type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
134
- target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
135
- }
136
- }
132
+ for (const relationshipArrayItem of relationshipArray) {
133
+ switch (relationshipArrayItem['attrs']['Type']) {
134
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout':
135
+ layoutFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
136
+ break
137
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide':
138
+ noteFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
139
+ break
140
+ case 'http://schemas.microsoft.com/office/2007/relationships/diagramDrawing':
141
+ diagramFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
142
+ slideResObj[relationshipArrayItem['attrs']['Id']] = {
143
+ type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
144
+ target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
145
+ }
146
+ break
147
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image':
148
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart':
149
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink':
150
+ default:
151
+ slideResObj[relationshipArrayItem['attrs']['Id']] = {
152
+ type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
153
+ target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
154
+ }
137
155
  }
138
- }
139
- else layoutFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
156
+ }
140
157
 
141
- const slideNotesContent = await readXmlFile(zip, notesFilename)
158
+ const slideNotesContent = await readXmlFile(zip, noteFilename)
142
159
  const note = getNote(slideNotesContent)
143
160
 
144
161
  const slideLayoutContent = await readXmlFile(zip, layoutFilename)
145
162
  const slideLayoutTables = await indexNodes(slideLayoutContent)
146
-
147
163
  const slideLayoutResFilename = layoutFilename.replace('slideLayouts/slideLayout', 'slideLayouts/_rels/slideLayout') + '.rels'
148
164
  const slideLayoutResContent = await readXmlFile(zip, slideLayoutResFilename)
149
165
  relationshipArray = slideLayoutResContent['Relationships']['Relationship']
166
+ if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
150
167
 
151
- let masterFilename = ''
152
- const layoutResObj = {}
153
- if (relationshipArray.constructor === Array) {
154
- for (const relationshipArrayItem of relationshipArray) {
155
- switch (relationshipArrayItem['attrs']['Type']) {
156
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster':
157
- masterFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
158
- break
159
- default:
160
- layoutResObj[relationshipArrayItem['attrs']['Id']] = {
161
- type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
162
- target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
163
- }
164
- }
168
+ for (const relationshipArrayItem of relationshipArray) {
169
+ switch (relationshipArrayItem['attrs']['Type']) {
170
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster':
171
+ masterFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
172
+ break
173
+ default:
174
+ layoutResObj[relationshipArrayItem['attrs']['Id']] = {
175
+ type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
176
+ target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
177
+ }
165
178
  }
166
- }
167
- else masterFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
179
+ }
168
180
 
169
181
  const slideMasterContent = await readXmlFile(zip, masterFilename)
170
182
  const slideMasterTextStyles = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:txStyles'])
171
183
  const slideMasterTables = indexNodes(slideMasterContent)
172
-
173
184
  const slideMasterResFilename = masterFilename.replace('slideMasters/slideMaster', 'slideMasters/_rels/slideMaster') + '.rels'
174
185
  const slideMasterResContent = await readXmlFile(zip, slideMasterResFilename)
175
186
  relationshipArray = slideMasterResContent['Relationships']['Relationship']
187
+ if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
176
188
 
177
- let themeFilename = ''
178
- const masterResObj = {}
179
- if (relationshipArray.constructor === Array) {
180
- for (const relationshipArrayItem of relationshipArray) {
181
- switch (relationshipArrayItem['attrs']['Type']) {
182
- case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
183
- break
184
- default:
185
- masterResObj[relationshipArrayItem['attrs']['Id']] = {
186
- type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
187
- target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
188
- }
189
- }
189
+ for (const relationshipArrayItem of relationshipArray) {
190
+ switch (relationshipArrayItem['attrs']['Type']) {
191
+ case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
192
+ themeFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
193
+ break
194
+ default:
195
+ masterResObj[relationshipArrayItem['attrs']['Id']] = {
196
+ type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
197
+ target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/'),
198
+ }
190
199
  }
191
200
  }
192
- else themeFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
193
201
 
194
- const themeResObj = {}
195
202
  if (themeFilename) {
196
203
  const themeName = themeFilename.split('/').pop()
197
204
  const themeResFileName = themeFilename.replace(themeName, '_rels/' + themeName) + '.rels'
@@ -199,50 +206,34 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
199
206
  if (themeResContent) {
200
207
  relationshipArray = themeResContent['Relationships']['Relationship']
201
208
  if (relationshipArray) {
202
- if (relationshipArray.constructor === Array) {
203
- for (const relationshipArrayItem of relationshipArray) {
204
- themeResObj[relationshipArrayItem['attrs']['Id']] = {
205
- 'type': relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
206
- 'target': relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
207
- }
208
- }
209
- }
210
- else {
211
- themeResObj[relationshipArray['attrs']['Id']] = {
212
- 'type': relationshipArray['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
213
- 'target': relationshipArray['attrs']['Target'].replace('../', 'ppt/')
209
+ if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
210
+ for (const relationshipArrayItem of relationshipArray) {
211
+ themeResObj[relationshipArrayItem['attrs']['Id']] = {
212
+ 'type': relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
213
+ 'target': relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
214
214
  }
215
215
  }
216
216
  }
217
217
  }
218
218
  }
219
219
 
220
- const diagramResObj = {}
221
220
  let digramFileContent = {}
222
221
  if (diagramFilename) {
223
222
  const diagName = diagramFilename.split('/').pop()
224
223
  const diagramResFileName = diagramFilename.replace(diagName, '_rels/' + diagName) + '.rels'
225
224
  digramFileContent = await readXmlFile(zip, diagramFilename)
226
- if (digramFileContent && digramFileContent && digramFileContent) {
227
- let digramFileContentObjToStr = JSON.stringify(digramFileContent)
228
- digramFileContentObjToStr = digramFileContentObjToStr.replace(/dsp:/g, 'p:')
225
+ if (digramFileContent) {
226
+ const digramFileContentObjToStr = JSON.stringify(digramFileContent).replace(/dsp:/g, 'p:')
229
227
  digramFileContent = JSON.parse(digramFileContentObjToStr)
230
228
  }
231
229
  const digramResContent = await readXmlFile(zip, diagramResFileName)
232
230
  if (digramResContent) {
233
231
  relationshipArray = digramResContent['Relationships']['Relationship']
234
- if (relationshipArray.constructor === Array) {
235
- for (const relationshipArrayItem of relationshipArray) {
236
- diagramResObj[relationshipArrayItem['attrs']['Id']] = {
237
- 'type': relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
238
- 'target': relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
239
- }
240
- }
241
- }
242
- else {
243
- diagramResObj[relationshipArray['attrs']['Id']] = {
244
- 'type': relationshipArray['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
245
- 'target': relationshipArray['attrs']['Target'].replace('../', 'ppt/')
232
+ if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
233
+ for (const relationshipArrayItem of relationshipArray) {
234
+ diagramResObj[relationshipArrayItem['attrs']['Id']] = {
235
+ 'type': relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
236
+ 'target': relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
246
237
  }
247
238
  }
248
239
  }
@@ -270,26 +261,22 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
270
261
  diagramResObj,
271
262
  defaultTextStyle,
272
263
  }
273
- // const bgElements = await getBackground(warpObj)
274
- const bgColor = await getSlideBackgroundFill(warpObj)
264
+ const layoutElements = await getLayoutElements(warpObj)
265
+ const fill = await getSlideBackgroundFill(warpObj)
275
266
 
276
267
  const elements = []
277
268
  for (const nodeKey in nodes) {
278
- if (nodes[nodeKey].constructor === Array) {
279
- for (const node of nodes[nodeKey]) {
280
- const ret = await processNodesInSlide(nodeKey, node, warpObj, 'slide')
281
- if (ret) elements.push(ret)
282
- }
283
- }
284
- else {
285
- const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj, 'slide')
269
+ if (nodes[nodeKey].constructor !== Array) nodes[nodeKey] = [nodes[nodeKey]]
270
+ for (const node of nodes[nodeKey]) {
271
+ const ret = await processNodesInSlide(nodeKey, node, warpObj, 'slide')
286
272
  if (ret) elements.push(ret)
287
273
  }
288
274
  }
289
275
 
290
276
  return {
291
- fill: bgColor,
277
+ fill,
292
278
  elements,
279
+ layoutElements,
293
280
  note,
294
281
  }
295
282
  }
@@ -307,56 +294,62 @@ function getNote(noteContent) {
307
294
  if (rNodes.constructor !== Array) rNodes = [rNodes]
308
295
  for (const rNode of rNodes) {
309
296
  const t = getTextByPathList(rNode, ['a:t'])
310
- if (t) text += t
297
+ if (t && typeof t === 'string') text += t
311
298
  }
312
299
  }
313
300
  return text
314
301
  }
315
302
 
316
- // async function getBackground(warpObj) {
317
- // const elements = []
318
- // const slideLayoutContent = warpObj['slideLayoutContent']
319
- // const slideMasterContent = warpObj['slideMasterContent']
320
- // const nodesSldLayout = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:cSld', 'p:spTree'])
321
- // const nodesSldMaster = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:cSld', 'p:spTree'])
322
-
323
- // const showMasterSp = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'attrs', 'showMasterSp'])
324
- // if (nodesSldLayout) {
325
- // for (const nodeKey in nodesSldLayout) {
326
- // if (nodesSldLayout[nodeKey].constructor === Array) {
327
- // for (let i = 0; i < nodesSldLayout[nodeKey].length; i++) {
328
- // const ph_type = getTextByPathList(nodesSldLayout[nodeKey][i], ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
329
- // if (ph_type !== 'pic') {
330
- // const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey][i], warpObj, 'slideLayoutBg')
331
- // if (ret) elements.push(ret)
332
- // }
333
- // }
334
- // }
335
- // else {
336
- // const ph_type = getTextByPathList(nodesSldLayout[nodeKey], ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
337
- // if (ph_type !== 'pic') {
338
- // const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey], warpObj, 'slideLayoutBg')
339
- // if (ret) elements.push(ret)
340
- // }
341
- // }
342
- // }
343
- // }
344
- // if (nodesSldMaster && (showMasterSp === '1' || showMasterSp)) {
345
- // for (const nodeKey in nodesSldMaster) {
346
- // if (nodesSldMaster[nodeKey].constructor === Array) {
347
- // for (let i = 0; i < nodesSldMaster[nodeKey].length; i++) {
348
- // const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey][i], warpObj, 'slideMasterBg')
349
- // if (ret) elements.push(ret)
350
- // }
351
- // }
352
- // else {
353
- // const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey], warpObj, 'slideMasterBg')
354
- // if (ret) elements.push(ret)
355
- // }
356
- // }
357
- // }
358
- // return elements
359
- // }
303
+ async function getLayoutElements(warpObj) {
304
+ const elements = []
305
+ const slideLayoutContent = warpObj['slideLayoutContent']
306
+ const slideMasterContent = warpObj['slideMasterContent']
307
+ const nodesSldLayout = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:cSld', 'p:spTree'])
308
+ const nodesSldMaster = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:cSld', 'p:spTree'])
309
+
310
+ const showMasterSp = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'attrs', 'showMasterSp'])
311
+ if (nodesSldLayout) {
312
+ for (const nodeKey in nodesSldLayout) {
313
+ if (nodesSldLayout[nodeKey].constructor === Array) {
314
+ for (let i = 0; i < nodesSldLayout[nodeKey].length; i++) {
315
+ const ph = getTextByPathList(nodesSldLayout[nodeKey][i], ['p:nvSpPr', 'p:nvPr', 'p:ph'])
316
+ if (!ph) {
317
+ const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey][i], warpObj, 'slideLayoutBg')
318
+ if (ret) elements.push(ret)
319
+ }
320
+ }
321
+ }
322
+ else {
323
+ const ph = getTextByPathList(nodesSldLayout[nodeKey], ['p:nvSpPr', 'p:nvPr', 'p:ph'])
324
+ if (!ph) {
325
+ const ret = await processNodesInSlide(nodeKey, nodesSldLayout[nodeKey], warpObj, 'slideLayoutBg')
326
+ if (ret) elements.push(ret)
327
+ }
328
+ }
329
+ }
330
+ }
331
+ if (nodesSldMaster && showMasterSp !== '0') {
332
+ for (const nodeKey in nodesSldMaster) {
333
+ if (nodesSldMaster[nodeKey].constructor === Array) {
334
+ for (let i = 0; i < nodesSldMaster[nodeKey].length; i++) {
335
+ const ph = getTextByPathList(nodesSldMaster[nodeKey][i], ['p:nvSpPr', 'p:nvPr', 'p:ph'])
336
+ if (!ph) {
337
+ const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey][i], warpObj, 'slideMasterBg')
338
+ if (ret) elements.push(ret)
339
+ }
340
+ }
341
+ }
342
+ else {
343
+ const ph = getTextByPathList(nodesSldMaster[nodeKey], ['p:nvSpPr', 'p:nvPr', 'p:ph'])
344
+ if (!ph) {
345
+ const ret = await processNodesInSlide(nodeKey, nodesSldMaster[nodeKey], warpObj, 'slideMasterBg')
346
+ if (ret) elements.push(ret)
347
+ }
348
+ }
349
+ }
350
+ }
351
+ return elements
352
+ }
360
353
 
361
354
  function indexNodes(content) {
362
355
  const keys = Object.keys(content)
@@ -402,13 +395,13 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
402
395
 
403
396
  switch (nodeKey) {
404
397
  case 'p:sp': // Shape, Text
405
- json = processSpNode(nodeValue, warpObj, source)
398
+ json = await processSpNode(nodeValue, warpObj, source)
406
399
  break
407
400
  case 'p:cxnSp': // Shape, Text
408
- json = processCxnSpNode(nodeValue, warpObj, source)
401
+ json = await processCxnSpNode(nodeValue, warpObj, source)
409
402
  break
410
403
  case 'p:pic': // Image, Video, Audio
411
- json = processPicNode(nodeValue, warpObj, source)
404
+ json = await processPicNode(nodeValue, warpObj, source)
412
405
  break
413
406
  case 'p:graphicFrame': // Chart, Diagram, Table
414
407
  json = await processGraphicFrameNode(nodeValue, warpObj, source)
@@ -421,7 +414,7 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
421
414
  json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj, source)
422
415
  }
423
416
  else if (getTextByPathList(nodeValue, ['mc:Choice'])) {
424
- json = await processMathNode(getTextByPathList(nodeValue, ['mc:Choice']))
417
+ json = processMathNode(getTextByPathList(nodeValue, ['mc:Choice']))
425
418
  }
426
419
  break
427
420
  default:
@@ -431,6 +424,7 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
431
424
  }
432
425
 
433
426
  function processMathNode(node) {
427
+ const order = node['attrs']['order']
434
428
  const xfrmNode = getTextByPathList(node, ['p:sp', 'p:spPr', 'a:xfrm'])
435
429
  const { top, left } = getPosition(xfrmNode, undefined, undefined)
436
430
  const { width, height } = getSize(xfrmNode, undefined, undefined)
@@ -445,10 +439,12 @@ function processMathNode(node) {
445
439
  width,
446
440
  height,
447
441
  latex,
442
+ order,
448
443
  }
449
444
  }
450
445
 
451
446
  async function processGroupSpNode(node, warpObj, source) {
447
+ const order = node['attrs']['order']
452
448
  const xfrmNode = getTextByPathList(node, ['p:grpSpPr', 'a:xfrm'])
453
449
  if (!xfrmNode) return null
454
450
 
@@ -488,6 +484,7 @@ async function processGroupSpNode(node, warpObj, source) {
488
484
  width: cx,
489
485
  height: cy,
490
486
  rotate,
487
+ order,
491
488
  elements: elements.map(element => ({
492
489
  ...element,
493
490
  left: (element.left - chx) * ws,
@@ -498,10 +495,11 @@ async function processGroupSpNode(node, warpObj, source) {
498
495
  }
499
496
  }
500
497
 
501
- function processSpNode(node, warpObj, source) {
498
+ async function processSpNode(node, warpObj, source) {
502
499
  const name = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'name'])
503
500
  const idx = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'idx'])
504
501
  let type = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
502
+ const order = getTextByPathList(node, ['attrs', 'order'])
505
503
 
506
504
  let slideLayoutSpNode, slideMasterSpNode
507
505
 
@@ -532,17 +530,18 @@ function processSpNode(node, warpObj, source) {
532
530
  else type = 'obj'
533
531
  }
534
532
 
535
- return genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj)
533
+ return await genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, order, warpObj, source)
536
534
  }
537
535
 
538
- function processCxnSpNode(node, warpObj) {
536
+ async function processCxnSpNode(node, warpObj, source) {
539
537
  const name = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['name']
540
538
  const type = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['type']
539
+ const order = node['attrs']['order']
541
540
 
542
- return genShape(node, undefined, undefined, name, type, warpObj)
541
+ return await genShape(node, undefined, undefined, name, type, order, warpObj, source)
543
542
  }
544
543
 
545
- function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj) {
544
+ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, order, warpObj, source) {
546
545
  const xfrmList = ['p:spPr', 'a:xfrm']
547
546
  const slideXfrmNode = getTextByPathList(node, xfrmList)
548
547
  const slideLayoutXfrmNode = getTextByPathList(slideLayoutSpNode, xfrmList)
@@ -571,7 +570,7 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
571
570
  if (node['p:txBody']) content = genTextBody(node['p:txBody'], node, slideLayoutSpNode, type, warpObj)
572
571
 
573
572
  const { borderColor, borderWidth, borderType, strokeDasharray } = getBorder(node, type, warpObj)
574
- const fillColor = getShapeFill(node, undefined, warpObj) || ''
573
+ const fill = await getShapeFill(node, undefined, warpObj, source) || ''
575
574
 
576
575
  let shadow
577
576
  const outerShdwNode = getTextByPathList(node, ['p:spPr', 'a:effectLst', 'a:outerShdw'])
@@ -589,13 +588,14 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
589
588
  borderWidth,
590
589
  borderType,
591
590
  borderStrokeDasharray: strokeDasharray,
592
- fillColor,
591
+ fill,
593
592
  content,
594
593
  isFlipV,
595
594
  isFlipH,
596
595
  rotate,
597
596
  vAlign,
598
597
  name,
598
+ order,
599
599
  }
600
600
 
601
601
  if (shadow) data.shadow = shadow
@@ -605,6 +605,7 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
605
605
  const w = parseInt(ext['cx']) * RATIO_EMUs_Points
606
606
  const h = parseInt(ext['cy']) * RATIO_EMUs_Points
607
607
  const d = getCustomShapePath(custShapType, w, h)
608
+ if (data.content && !hasValidText(data.content)) data.content = ''
608
609
 
609
610
  return {
610
611
  ...data,
@@ -614,6 +615,7 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
614
615
  }
615
616
  }
616
617
  if (shapType && (type === 'obj' || !type)) {
618
+ if (data.content && !hasValidText(data.content)) data.content = ''
617
619
  return {
618
620
  ...data,
619
621
  type: 'shape',
@@ -633,6 +635,8 @@ async function processPicNode(node, warpObj, source) {
633
635
  if (source === 'slideMasterBg') resObj = warpObj['masterResObj']
634
636
  else if (source === 'slideLayoutBg') resObj = warpObj['layoutResObj']
635
637
  else resObj = warpObj['slideResObj']
638
+
639
+ const order = node['attrs']['order']
636
640
 
637
641
  const rid = node['p:blipFill']['a:blip']['attrs']['r:embed']
638
642
  const imgName = resObj[rid]['target']
@@ -697,6 +701,7 @@ async function processPicNode(node, warpObj, source) {
697
701
  height,
698
702
  rotate,
699
703
  blob: videoBlob,
704
+ order,
700
705
  }
701
706
  }
702
707
  if (videoNode && isVdeoLink) {
@@ -708,6 +713,7 @@ async function processPicNode(node, warpObj, source) {
708
713
  height,
709
714
  rotate,
710
715
  src: videoFile,
716
+ order,
711
717
  }
712
718
  }
713
719
  if (audioNode) {
@@ -719,6 +725,7 @@ async function processPicNode(node, warpObj, source) {
719
725
  height,
720
726
  rotate,
721
727
  blob: audioBlob,
728
+ order,
722
729
  }
723
730
  }
724
731
  return {
@@ -730,7 +737,8 @@ async function processPicNode(node, warpObj, source) {
730
737
  rotate,
731
738
  src,
732
739
  isFlipV,
733
- isFlipH
740
+ isFlipH,
741
+ order,
734
742
  }
735
743
  }
736
744
 
@@ -740,25 +748,26 @@ async function processGraphicFrameNode(node, warpObj, source) {
740
748
  let result
741
749
  switch (graphicTypeUri) {
742
750
  case 'http://schemas.openxmlformats.org/drawingml/2006/table':
743
- result = genTable(node, warpObj)
751
+ result = await genTable(node, warpObj)
744
752
  break
745
753
  case 'http://schemas.openxmlformats.org/drawingml/2006/chart':
746
754
  result = await genChart(node, warpObj)
747
755
  break
748
756
  case 'http://schemas.openxmlformats.org/drawingml/2006/diagram':
749
- result = genDiagram(node, warpObj)
757
+ result = await genDiagram(node, warpObj)
750
758
  break
751
759
  case 'http://schemas.openxmlformats.org/presentationml/2006/ole':
752
760
  let oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'mc:AlternateContent', 'mc:Fallback', 'p:oleObj'])
753
761
  if (!oleObjNode) oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'p:oleObj'])
754
- else processGroupSpNode(oleObjNode, warpObj, source)
762
+ if (oleObjNode) result = await processGroupSpNode(oleObjNode, warpObj, source)
755
763
  break
756
764
  default:
757
765
  }
758
766
  return result
759
767
  }
760
768
 
761
- function genTable(node, warpObj) {
769
+ async function genTable(node, warpObj) {
770
+ const order = node['attrs']['order']
762
771
  const tableNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl'])
763
772
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
764
773
  const { top, left } = getPosition(xfrmNode, undefined, undefined)
@@ -875,7 +884,7 @@ function genTable(node, warpObj) {
875
884
  }
876
885
  }
877
886
  const text = genTextBody(tcNode['a:txBody'], tcNode, undefined, undefined, warpObj)
878
- const cell = getTableCellParams(tcNode, thisTblStyle, a_sorce, warpObj)
887
+ const cell = await getTableCellParams(tcNode, thisTblStyle, a_sorce, warpObj)
879
888
  const td = { text }
880
889
  if (cell.rowSpan) td.rowSpan = cell.rowSpan
881
890
  if (cell.colSpan) td.colSpan = cell.colSpan
@@ -906,7 +915,7 @@ function genTable(node, warpObj) {
906
915
  }
907
916
 
908
917
  const text = genTextBody(tcNodes['a:txBody'], tcNodes, undefined, undefined, warpObj)
909
- const cell = getTableCellParams(tcNodes, thisTblStyle, a_sorce, warpObj)
918
+ const cell = await getTableCellParams(tcNodes, thisTblStyle, a_sorce, warpObj)
910
919
  const td = { text }
911
920
  if (cell.rowSpan) td.rowSpan = cell.rowSpan
912
921
  if (cell.colSpan) td.colSpan = cell.colSpan
@@ -928,11 +937,13 @@ function genTable(node, warpObj) {
928
937
  width,
929
938
  height,
930
939
  data,
940
+ order,
931
941
  ...(tbl_border || {}),
932
942
  }
933
943
  }
934
944
 
935
945
  async function genChart(node, warpObj) {
946
+ const order = node['attrs']['order']
936
947
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
937
948
  const { top, left } = getPosition(xfrmNode, undefined, undefined)
938
949
  const { width, height } = getSize(xfrmNode, undefined, undefined)
@@ -942,7 +953,7 @@ async function genChart(node, warpObj) {
942
953
  const content = await readXmlFile(warpObj['zip'], refName)
943
954
  const plotArea = getTextByPathList(content, ['c:chartSpace', 'c:chart', 'c:plotArea'])
944
955
 
945
- const chart = getChartInfo(plotArea)
956
+ const chart = getChartInfo(plotArea, warpObj)
946
957
 
947
958
  if (!chart) return {}
948
959
 
@@ -953,7 +964,9 @@ async function genChart(node, warpObj) {
953
964
  width,
954
965
  height,
955
966
  data: chart.data,
967
+ colors: chart.colors,
956
968
  chartType: chart.type,
969
+ order,
957
970
  }
958
971
  if (chart.marker !== undefined) data.marker = chart.marker
959
972
  if (chart.barDir !== undefined) data.barDir = chart.barDir
@@ -964,7 +977,8 @@ async function genChart(node, warpObj) {
964
977
  return data
965
978
  }
966
979
 
967
- function genDiagram(node, warpObj) {
980
+ async function genDiagram(node, warpObj) {
981
+ const order = node['attrs']['order']
968
982
  const xfrmNode = getTextByPathList(node, ['p:xfrm'])
969
983
  const { left, top } = getPosition(xfrmNode, undefined, undefined)
970
984
  const { width, height } = getSize(xfrmNode, undefined, undefined)
@@ -973,7 +987,7 @@ function genDiagram(node, warpObj) {
973
987
  const elements = []
974
988
  if (dgmDrwSpArray) {
975
989
  for (const item of dgmDrwSpArray) {
976
- const el = processSpNode(item, warpObj, 'diagramBg')
990
+ const el = await processSpNode(item, warpObj, 'diagramBg')
977
991
  if (el) elements.push(el)
978
992
  }
979
993
  }
@@ -985,5 +999,6 @@ function genDiagram(node, warpObj) {
985
999
  width,
986
1000
  height,
987
1001
  elements,
1002
+ order,
988
1003
  }
989
1004
  }