pptxtojson 0.1.2 → 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/LICENSE +21 -661
- package/README.md +169 -3
- package/dist/index.d.ts +2 -4
- 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 +2 -2
- package/src/align.js +43 -14
- package/src/fill.js +10 -1
- package/src/fontStyle.js +3 -3
- package/src/position.js +4 -4
- package/src/pptxtojson.js +137 -95
- package/src/shadow.js +5 -4
- package/src/text.js +10 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptxtojson",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A javascript tool for parsing .pptx file",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.umd.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"lint": "eslint src --ext .js,.jsx,.ts,.tsx"
|
|
13
13
|
},
|
|
14
14
|
"author": "",
|
|
15
|
-
"license": "
|
|
15
|
+
"license": "MIT",
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"registry": "https://registry.npmjs.com/"
|
|
18
18
|
},
|
package/src/align.js
CHANGED
|
@@ -1,26 +1,55 @@
|
|
|
1
1
|
import { getTextByPathList } from './utils'
|
|
2
2
|
|
|
3
|
-
export function getHorizontalAlign(node,
|
|
3
|
+
export function getHorizontalAlign(node, pNode, type, warpObj) {
|
|
4
4
|
let algn = getTextByPathList(node, ['a:pPr', 'attrs', 'algn'])
|
|
5
|
+
if (!algn) algn = getTextByPathList(pNode, ['a:pPr', 'attrs', 'algn'])
|
|
5
6
|
|
|
6
|
-
if (!algn) algn = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
7
|
-
if (!algn) algn = getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
8
7
|
if (!algn) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
if (type === 'title' || type === 'ctrTitle' || type === 'subTitle') {
|
|
9
|
+
let lvlIdx = 1
|
|
10
|
+
const lvlNode = getTextByPathList(pNode, ['a:pPr', 'attrs', 'lvl'])
|
|
11
|
+
if (lvlNode) {
|
|
12
|
+
lvlIdx = parseInt(lvlNode) + 1
|
|
13
|
+
}
|
|
14
|
+
const lvlStr = 'a:lvl' + lvlIdx + 'pPr'
|
|
15
|
+
algn = getTextByPathList(warpObj, ['slideLayoutTables', 'typeTable', type, 'p:txBody', 'a:lstStyle', lvlStr, 'attrs', 'algn'])
|
|
16
|
+
if (!algn) algn = getTextByPathList(warpObj, ['slideMasterTables', 'typeTable', type, 'p:txBody', 'a:lstStyle', lvlStr, 'attrs', 'algn'])
|
|
17
|
+
if (!algn) algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:titleStyle', lvlStr, 'attrs', 'algn'])
|
|
18
|
+
if (!algn && type === 'subTitle') {
|
|
19
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:bodyStyle', lvlStr, 'attrs', 'algn'])
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (type === 'body') {
|
|
23
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:bodyStyle', 'a:lvl1pPr', 'attrs', 'algn'])
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
algn = getTextByPathList(warpObj, ['slideMasterTables', 'typeTable', type, 'p:txBody', 'a:lstStyle', 'a:lvl1pPr', 'attrs', 'algn'])
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let align = 'left'
|
|
31
|
+
if (algn) {
|
|
32
|
+
switch (algn) {
|
|
33
|
+
case 'l':
|
|
34
|
+
align = 'left'
|
|
35
|
+
break
|
|
36
|
+
case 'r':
|
|
37
|
+
align = 'right'
|
|
38
|
+
break
|
|
39
|
+
case 'ctr':
|
|
40
|
+
align = 'center'
|
|
41
|
+
break
|
|
42
|
+
case 'just':
|
|
43
|
+
align = 'justify'
|
|
44
|
+
break
|
|
45
|
+
case 'dist':
|
|
46
|
+
align = 'justify'
|
|
14
47
|
break
|
|
15
48
|
default:
|
|
16
|
-
|
|
49
|
+
align = 'inherit'
|
|
17
50
|
}
|
|
18
51
|
}
|
|
19
|
-
|
|
20
|
-
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') return 'center'
|
|
21
|
-
else if (type === 'sldNum') return 'right'
|
|
22
|
-
}
|
|
23
|
-
return algn === 'ctr' ? 'center' : algn === 'r' ? 'right' : 'left'
|
|
52
|
+
return align
|
|
24
53
|
}
|
|
25
54
|
|
|
26
55
|
export function getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode) {
|
package/src/fill.js
CHANGED
|
@@ -244,7 +244,7 @@ export function getShapeFill(node, isSvgMode, warpObj) {
|
|
|
244
244
|
if (isNaN(lumOff)) lumOff = 0
|
|
245
245
|
|
|
246
246
|
const color = tinycolor(fillColor).toHsl()
|
|
247
|
-
const lum = color.l *
|
|
247
|
+
const lum = color.l * lumMod + lumOff
|
|
248
248
|
return tinycolor({ h: color.h, s: color.s, l: lum, a: color.a }).toHexString()
|
|
249
249
|
}
|
|
250
250
|
|
|
@@ -264,6 +264,15 @@ export function getSolidFill(solidFill, clrMap, phClr, warpObj) {
|
|
|
264
264
|
else if (solidFill['a:schemeClr']) {
|
|
265
265
|
const schemeClr = 'a:' + getTextByPathList(solidFill['a:schemeClr'], ['attrs', 'val'])
|
|
266
266
|
color = getSchemeColorFromTheme(schemeClr, warpObj)
|
|
267
|
+
|
|
268
|
+
let lumMod = parseInt(getTextByPathList(solidFill, ['a:schemeClr', 'a:lumMod', 'attrs', 'val'])) / 100000
|
|
269
|
+
let lumOff = parseInt(getTextByPathList(solidFill, ['a:schemeClr', 'a:lumOff', 'attrs', 'val'])) / 100000
|
|
270
|
+
if (isNaN(lumMod)) lumMod = 1.0
|
|
271
|
+
if (isNaN(lumOff)) lumOff = 0
|
|
272
|
+
|
|
273
|
+
color = tinycolor(color).toHsl()
|
|
274
|
+
const lum = color.l * lumMod + lumOff
|
|
275
|
+
return tinycolor({ h: color.h, s: color.s, l: lum, a: color.a }).toHex()
|
|
267
276
|
}
|
|
268
277
|
else if (solidFill['a:scrgbClr']) {
|
|
269
278
|
clrNode = solidFill['a:scrgbClr']
|
package/src/fontStyle.js
CHANGED
|
@@ -58,7 +58,7 @@ export function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles
|
|
|
58
58
|
|
|
59
59
|
fontSize = (isNaN(fontSize) || !fontSize) ? 18 : fontSize
|
|
60
60
|
|
|
61
|
-
return fontSize * fontsizeFactor + 'px'
|
|
61
|
+
return parseFloat((fontSize * fontsizeFactor).toFixed(2)) + (fontsizeFactor === 1 ? 'pt' : 'px')
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
export function getFontBold(node) {
|
|
@@ -88,10 +88,10 @@ export function getFontSubscript(node) {
|
|
|
88
88
|
return parseInt(baseline) > 0 ? 'super' : 'sub'
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export function getFontShadow(node, warpObj
|
|
91
|
+
export function getFontShadow(node, warpObj) {
|
|
92
92
|
const txtShadow = getTextByPathList(node, ['a:rPr', 'a:effectLst', 'a:outerShdw'])
|
|
93
93
|
if (txtShadow) {
|
|
94
|
-
const shadow = getShadow(txtShadow, warpObj
|
|
94
|
+
const shadow = getShadow(txtShadow, warpObj)
|
|
95
95
|
if (shadow) {
|
|
96
96
|
const { h, v, blur, color } = shadow
|
|
97
97
|
if (!isNaN(v) && !isNaN(h)) {
|
package/src/position.js
CHANGED
|
@@ -8,8 +8,8 @@ export function getPosition(slideSpNode, slideLayoutSpNode, slideMasterSpNode, f
|
|
|
8
8
|
if (!off) return { top: 0, left: 0 }
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
|
-
top: parseInt(off['y']) * factor,
|
|
12
|
-
left: parseInt(off['x']) * factor,
|
|
11
|
+
top: parseFloat((parseInt(off['y']) * factor).toFixed(2)),
|
|
12
|
+
left: parseFloat((parseInt(off['x']) * factor).toFixed(2)),
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ export function getSize(slideSpNode, slideLayoutSpNode, slideMasterSpNode, facto
|
|
|
23
23
|
if (!ext) return { width: 0, height: 0 }
|
|
24
24
|
|
|
25
25
|
return {
|
|
26
|
-
width: parseInt(ext['cx']) * factor,
|
|
27
|
-
height: parseInt(ext['cy']) * factor,
|
|
26
|
+
width: parseFloat((parseInt(ext['cx']) * factor).toFixed(2)),
|
|
27
|
+
height: parseFloat((parseInt(ext['cy']) * factor).toFixed(2)),
|
|
28
28
|
}
|
|
29
29
|
}
|
package/src/pptxtojson.js
CHANGED
|
@@ -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
|
-
|
|
14
|
+
const defaultOptions = {
|
|
15
|
+
slideFactor: 96 / 914400,
|
|
16
|
+
fontsizeFactor: 100 / 75,
|
|
17
|
+
}
|
|
23
18
|
|
|
24
|
-
|
|
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']) *
|
|
87
|
-
height: parseInt(sldSzAttrs['cy']) *
|
|
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']
|
|
@@ -258,34 +252,36 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
258
252
|
const nodes = slideContent['p:sld']['p:cSld']['p:spTree']
|
|
259
253
|
const warpObj = {
|
|
260
254
|
zip,
|
|
261
|
-
slideLayoutContent
|
|
262
|
-
slideLayoutTables
|
|
263
|
-
slideMasterContent
|
|
264
|
-
slideMasterTables
|
|
265
|
-
slideContent
|
|
266
|
-
tableStyles
|
|
267
|
-
slideResObj
|
|
268
|
-
slideMasterTextStyles
|
|
269
|
-
layoutResObj
|
|
270
|
-
masterResObj
|
|
271
|
-
themeContent
|
|
272
|
-
themeResObj
|
|
273
|
-
digramFileContent
|
|
274
|
-
diagramResObj
|
|
275
|
-
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,
|
|
276
271
|
}
|
|
272
|
+
// const bgElements = await getBackground(warpObj)
|
|
277
273
|
const bgColor = await getSlideBackgroundFill(warpObj)
|
|
278
274
|
|
|
279
275
|
const elements = []
|
|
280
276
|
for (const nodeKey in nodes) {
|
|
281
277
|
if (nodes[nodeKey].constructor === Array) {
|
|
282
278
|
for (const node of nodes[nodeKey]) {
|
|
283
|
-
const ret = await processNodesInSlide(nodeKey, node, warpObj)
|
|
279
|
+
const ret = await processNodesInSlide(nodeKey, node, warpObj, 'slide')
|
|
284
280
|
if (ret) elements.push(ret)
|
|
285
281
|
}
|
|
286
282
|
}
|
|
287
283
|
else {
|
|
288
|
-
const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj)
|
|
284
|
+
const ret = await processNodesInSlide(nodeKey, nodes[nodeKey], warpObj, 'slide')
|
|
289
285
|
if (ret) elements.push(ret)
|
|
290
286
|
}
|
|
291
287
|
}
|
|
@@ -296,6 +292,51 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
296
292
|
}
|
|
297
293
|
}
|
|
298
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
|
+
|
|
299
340
|
function indexNodes(content) {
|
|
300
341
|
const keys = Object.keys(content)
|
|
301
342
|
const spTreeNode = content[keys[0]]['p:cSld']['p:spTree']
|
|
@@ -335,27 +376,27 @@ function indexNodes(content) {
|
|
|
335
376
|
return { idTable, idxTable, typeTable }
|
|
336
377
|
}
|
|
337
378
|
|
|
338
|
-
async function processNodesInSlide(nodeKey, nodeValue, warpObj) {
|
|
379
|
+
async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
|
|
339
380
|
let json
|
|
340
381
|
|
|
341
382
|
switch (nodeKey) {
|
|
342
383
|
case 'p:sp': // Shape, Text
|
|
343
|
-
json = processSpNode(nodeValue, warpObj)
|
|
384
|
+
json = processSpNode(nodeValue, warpObj, source)
|
|
344
385
|
break
|
|
345
386
|
case 'p:cxnSp': // Shape, Text
|
|
346
|
-
json = processCxnSpNode(nodeValue, warpObj)
|
|
387
|
+
json = processCxnSpNode(nodeValue, warpObj, source)
|
|
347
388
|
break
|
|
348
389
|
case 'p:pic': // Image, Video, Audio
|
|
349
|
-
json = processPicNode(nodeValue, warpObj)
|
|
390
|
+
json = processPicNode(nodeValue, warpObj, source)
|
|
350
391
|
break
|
|
351
392
|
case 'p:graphicFrame': // Chart, Diagram, Table
|
|
352
|
-
json = await processGraphicFrameNode(nodeValue, warpObj)
|
|
393
|
+
json = await processGraphicFrameNode(nodeValue, warpObj, source)
|
|
353
394
|
break
|
|
354
395
|
case 'p:grpSp':
|
|
355
|
-
json = await processGroupSpNode(nodeValue, warpObj)
|
|
396
|
+
json = await processGroupSpNode(nodeValue, warpObj, source)
|
|
356
397
|
break
|
|
357
398
|
case 'mc:AlternateContent':
|
|
358
|
-
json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj)
|
|
399
|
+
json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj, source)
|
|
359
400
|
break
|
|
360
401
|
default:
|
|
361
402
|
}
|
|
@@ -363,45 +404,55 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj) {
|
|
|
363
404
|
return json
|
|
364
405
|
}
|
|
365
406
|
|
|
366
|
-
async function processGroupSpNode(node, warpObj) {
|
|
407
|
+
async function processGroupSpNode(node, warpObj, source) {
|
|
367
408
|
const xfrmNode = getTextByPathList(node, ['p:grpSpPr', 'a:xfrm'])
|
|
368
409
|
if (!xfrmNode) return null
|
|
369
410
|
|
|
370
|
-
const x = parseInt(xfrmNode['a:off']['attrs']['x']) *
|
|
371
|
-
const y = parseInt(xfrmNode['a:off']['attrs']['y']) *
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
|
|
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
|
|
378
424
|
|
|
379
425
|
const elements = []
|
|
380
426
|
for (const nodeKey in node) {
|
|
381
427
|
if (node[nodeKey].constructor === Array) {
|
|
382
428
|
for (const item of node[nodeKey]) {
|
|
383
|
-
const ret = await processNodesInSlide(nodeKey, item, warpObj)
|
|
429
|
+
const ret = await processNodesInSlide(nodeKey, item, warpObj, source)
|
|
384
430
|
if (ret) elements.push(ret)
|
|
385
431
|
}
|
|
386
432
|
}
|
|
387
433
|
else {
|
|
388
|
-
const ret = await processNodesInSlide(nodeKey, node[nodeKey], warpObj)
|
|
434
|
+
const ret = await processNodesInSlide(nodeKey, node[nodeKey], warpObj, source)
|
|
389
435
|
if (ret) elements.push(ret)
|
|
390
436
|
}
|
|
391
437
|
}
|
|
392
438
|
|
|
393
439
|
return {
|
|
394
440
|
type: 'group',
|
|
395
|
-
top: y
|
|
396
|
-
left: x
|
|
397
|
-
width: cx
|
|
398
|
-
height: cy
|
|
399
|
-
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
|
+
}))
|
|
400
452
|
}
|
|
401
453
|
}
|
|
402
454
|
|
|
403
455
|
function processSpNode(node, warpObj, source) {
|
|
404
|
-
const id = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'id'])
|
|
405
456
|
const name = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'name'])
|
|
406
457
|
const idx = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'idx'])
|
|
407
458
|
let type = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
@@ -435,19 +486,17 @@ function processSpNode(node, warpObj, source) {
|
|
|
435
486
|
else type = 'obj'
|
|
436
487
|
}
|
|
437
488
|
|
|
438
|
-
return genShape(node, slideLayoutSpNode, slideMasterSpNode,
|
|
489
|
+
return genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj)
|
|
439
490
|
}
|
|
440
491
|
|
|
441
492
|
function processCxnSpNode(node, warpObj) {
|
|
442
|
-
const id = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['id']
|
|
443
493
|
const name = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['name']
|
|
444
|
-
const idx = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['idx']
|
|
445
494
|
const type = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['type']
|
|
446
495
|
|
|
447
|
-
return genShape(node, undefined, undefined,
|
|
496
|
+
return genShape(node, undefined, undefined, name, type, warpObj)
|
|
448
497
|
}
|
|
449
498
|
|
|
450
|
-
function genShape(node, slideLayoutSpNode, slideMasterSpNode,
|
|
499
|
+
function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj) {
|
|
451
500
|
const xfrmList = ['p:spPr', 'a:xfrm']
|
|
452
501
|
const slideXfrmNode = getTextByPathList(node, xfrmList)
|
|
453
502
|
const slideLayoutXfrmNode = getTextByPathList(slideLayoutSpNode, xfrmList)
|
|
@@ -456,8 +505,8 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
|
|
|
456
505
|
const shapType = getTextByPathList(node, ['p:spPr', 'a:prstGeom', 'attrs', 'prst'])
|
|
457
506
|
const custShapType = getTextByPathList(node, ['p:spPr', 'a:custGeom'])
|
|
458
507
|
|
|
459
|
-
const { top, left } = getPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode,
|
|
460
|
-
const { width, height } = getSize(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode,
|
|
508
|
+
const { top, left } = getPosition(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, warpObj.options.slideFactor)
|
|
509
|
+
const { width, height } = getSize(slideXfrmNode, slideLayoutXfrmNode, slideMasterXfrmNode, warpObj.options.slideFactor)
|
|
461
510
|
|
|
462
511
|
const isFlipV = getTextByPathList(slideXfrmNode, ['attrs', 'flipV']) === '1'
|
|
463
512
|
const isFlipH = getTextByPathList(slideXfrmNode, ['attrs', 'flipH']) === '1'
|
|
@@ -473,14 +522,14 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
|
|
|
473
522
|
else txtRotate = rotate
|
|
474
523
|
|
|
475
524
|
let content = ''
|
|
476
|
-
if (node['p:txBody']) content = genTextBody(node['p:txBody'],
|
|
525
|
+
if (node['p:txBody']) content = genTextBody(node['p:txBody'], node, slideLayoutSpNode, type, warpObj)
|
|
477
526
|
|
|
478
527
|
const { borderColor, borderWidth, borderType, strokeDasharray } = getBorder(node, type, warpObj)
|
|
479
528
|
const fillColor = getShapeFill(node, undefined, warpObj) || ''
|
|
480
529
|
|
|
481
530
|
let shadow
|
|
482
531
|
const outerShdwNode = getTextByPathList(node, ['p:spPr', 'a:effectLst', 'a:outerShdw'])
|
|
483
|
-
if (outerShdwNode) shadow = getShadow(outerShdwNode, warpObj
|
|
532
|
+
if (outerShdwNode) shadow = getShadow(outerShdwNode, warpObj)
|
|
484
533
|
|
|
485
534
|
const vAlign = getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode, type)
|
|
486
535
|
const isVertical = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'vert']) === 'eaVert'
|
|
@@ -500,40 +549,28 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
|
|
|
500
549
|
isFlipH,
|
|
501
550
|
rotate,
|
|
502
551
|
vAlign,
|
|
503
|
-
id,
|
|
504
552
|
name,
|
|
505
|
-
idx,
|
|
506
553
|
}
|
|
507
554
|
|
|
508
555
|
if (shadow) data.shadow = shadow
|
|
509
556
|
|
|
510
557
|
if (custShapType && type !== 'diagram') {
|
|
511
558
|
const ext = getTextByPathList(slideXfrmNode, ['a:ext', 'attrs'])
|
|
512
|
-
const
|
|
513
|
-
const
|
|
514
|
-
const w = parseInt(ext['cx']) * SLIDE_FACTOR
|
|
515
|
-
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
|
|
516
561
|
const d = getCustomShapePath(custShapType, w, h)
|
|
517
562
|
|
|
518
563
|
return {
|
|
519
564
|
...data,
|
|
520
565
|
type: 'shape',
|
|
521
|
-
cx,
|
|
522
|
-
cy,
|
|
523
566
|
shapType: 'custom',
|
|
524
567
|
path: d,
|
|
525
568
|
}
|
|
526
569
|
}
|
|
527
570
|
if (shapType && type !== 'text') {
|
|
528
|
-
const ext = getTextByPathList(slideXfrmNode, ['a:ext', 'attrs'])
|
|
529
|
-
const cx = parseInt(ext['cx']) * SLIDE_FACTOR
|
|
530
|
-
const cy = parseInt(ext['cy']) * SLIDE_FACTOR
|
|
531
|
-
|
|
532
571
|
return {
|
|
533
572
|
...data,
|
|
534
573
|
type: 'shape',
|
|
535
|
-
cx,
|
|
536
|
-
cy,
|
|
537
574
|
shapType,
|
|
538
575
|
}
|
|
539
576
|
}
|
|
@@ -559,10 +596,13 @@ async function processPicNode(node, warpObj, source) {
|
|
|
559
596
|
const xfrmNode = node['p:spPr']['a:xfrm']
|
|
560
597
|
|
|
561
598
|
const mimeType = getMimeType(imgFileExt)
|
|
562
|
-
const { top, left } = getPosition(xfrmNode, undefined, undefined,
|
|
563
|
-
const { width, height } = getSize(xfrmNode, undefined, undefined,
|
|
599
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
600
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
564
601
|
const src = `data:${mimeType};base64,${base64ArrayBuffer(imgArrayBuffer)}`
|
|
565
602
|
|
|
603
|
+
const isFlipV = getTextByPathList(xfrmNode, ['attrs', 'flipV']) === '1'
|
|
604
|
+
const isFlipH = getTextByPathList(xfrmNode, ['attrs', 'flipH']) === '1'
|
|
605
|
+
|
|
566
606
|
let rotate = 0
|
|
567
607
|
const rotateNode = getTextByPathList(node, ['p:spPr', 'a:xfrm', 'attrs', 'rot'])
|
|
568
608
|
if (rotateNode) rotate = angleToDegrees(rotateNode)
|
|
@@ -643,10 +683,12 @@ async function processPicNode(node, warpObj, source) {
|
|
|
643
683
|
height,
|
|
644
684
|
rotate,
|
|
645
685
|
src,
|
|
686
|
+
isFlipV,
|
|
687
|
+
isFlipH
|
|
646
688
|
}
|
|
647
689
|
}
|
|
648
690
|
|
|
649
|
-
async function processGraphicFrameNode(node, warpObj) {
|
|
691
|
+
async function processGraphicFrameNode(node, warpObj, source) {
|
|
650
692
|
const graphicTypeUri = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'attrs', 'uri'])
|
|
651
693
|
|
|
652
694
|
let result
|
|
@@ -663,7 +705,7 @@ async function processGraphicFrameNode(node, warpObj) {
|
|
|
663
705
|
case 'http://schemas.openxmlformats.org/presentationml/2006/ole':
|
|
664
706
|
let oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'mc:AlternateContent', 'mc:Fallback', 'p:oleObj'])
|
|
665
707
|
if (!oleObjNode) oleObjNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'p:oleObj'])
|
|
666
|
-
else processGroupSpNode(oleObjNode, warpObj)
|
|
708
|
+
else processGroupSpNode(oleObjNode, warpObj, source)
|
|
667
709
|
break
|
|
668
710
|
default:
|
|
669
711
|
}
|
|
@@ -673,8 +715,8 @@ async function processGraphicFrameNode(node, warpObj) {
|
|
|
673
715
|
function genTable(node, warpObj) {
|
|
674
716
|
const tableNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl'])
|
|
675
717
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
676
|
-
const { top, left } = getPosition(xfrmNode, undefined, undefined,
|
|
677
|
-
const { width, height } = getSize(xfrmNode, undefined, undefined,
|
|
718
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
719
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
678
720
|
|
|
679
721
|
const getTblPr = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl', 'a:tblPr'])
|
|
680
722
|
|
|
@@ -719,7 +761,7 @@ function genTable(node, warpObj) {
|
|
|
719
761
|
|
|
720
762
|
if (tcNodes.constructor === Array) {
|
|
721
763
|
for (const tcNode of tcNodes) {
|
|
722
|
-
const text = genTextBody(tcNode['a:txBody'],
|
|
764
|
+
const text = genTextBody(tcNode['a:txBody'], tcNode, undefined, undefined, warpObj)
|
|
723
765
|
const rowSpan = getTextByPathList(tcNode, ['attrs', 'rowSpan'])
|
|
724
766
|
const colSpan = getTextByPathList(tcNode, ['attrs', 'gridSpan'])
|
|
725
767
|
const vMerge = getTextByPathList(tcNode, ['attrs', 'vMerge'])
|
|
@@ -729,7 +771,7 @@ function genTable(node, warpObj) {
|
|
|
729
771
|
}
|
|
730
772
|
}
|
|
731
773
|
else {
|
|
732
|
-
const text = genTextBody(tcNodes['a:txBody'],
|
|
774
|
+
const text = genTextBody(tcNodes['a:txBody'], tcNodes, undefined, undefined, warpObj)
|
|
733
775
|
tr.push({ text })
|
|
734
776
|
}
|
|
735
777
|
data.push(tr)
|
|
@@ -741,12 +783,12 @@ function genTable(node, warpObj) {
|
|
|
741
783
|
|
|
742
784
|
if (tcNodes.constructor === Array) {
|
|
743
785
|
for (const tcNode of tcNodes) {
|
|
744
|
-
const text = genTextBody(tcNode['a:txBody'],
|
|
786
|
+
const text = genTextBody(tcNode['a:txBody'], tcNode, undefined, undefined, warpObj)
|
|
745
787
|
tr.push({ text })
|
|
746
788
|
}
|
|
747
789
|
}
|
|
748
790
|
else {
|
|
749
|
-
const text = genTextBody(tcNodes['a:txBody'],
|
|
791
|
+
const text = genTextBody(tcNodes['a:txBody'], tcNodes, undefined, undefined, warpObj)
|
|
750
792
|
tr.push({ text })
|
|
751
793
|
}
|
|
752
794
|
data.push(tr)
|
|
@@ -765,8 +807,8 @@ function genTable(node, warpObj) {
|
|
|
765
807
|
|
|
766
808
|
async function genChart(node, warpObj) {
|
|
767
809
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
768
|
-
const { top, left } = getPosition(xfrmNode, undefined, undefined,
|
|
769
|
-
const { width, height } = getSize(xfrmNode, undefined, undefined,
|
|
810
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
811
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
770
812
|
|
|
771
813
|
const rid = node['a:graphic']['a:graphicData']['c:chart']['attrs']['r:id']
|
|
772
814
|
const refName = warpObj['slideResObj'][rid]['target']
|
|
@@ -797,8 +839,8 @@ async function genChart(node, warpObj) {
|
|
|
797
839
|
|
|
798
840
|
function genDiagram(node, warpObj) {
|
|
799
841
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
800
|
-
const { left, top } = getPosition(xfrmNode, undefined, undefined,
|
|
801
|
-
const { width, height } = getSize(xfrmNode, undefined, undefined,
|
|
842
|
+
const { left, top } = getPosition(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
843
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined, warpObj.options.slideFactor)
|
|
802
844
|
|
|
803
845
|
const dgmDrwSpArray = getTextByPathList(warpObj['digramFileContent'], ['p:drawing', 'p:spTree', 'p:sp'])
|
|
804
846
|
const elements = []
|
package/src/shadow.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { getSolidFill } from './fill'
|
|
2
2
|
|
|
3
|
-
export function getShadow(node, warpObj
|
|
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
|
}
|