pptxtojson 2.0.2 → 2.0.4
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/README.md +7 -3
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -2
- 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/index.html +10 -2
- package/package.json +1 -1
- package/src/chart.js +58 -48
- package/src/paragraph.js +156 -126
- package/src/pptxtojson.js +47 -32
- package/src/text.js +21 -17
- package/src/textInsets.js +64 -0
package/index.html
CHANGED
|
@@ -432,11 +432,13 @@
|
|
|
432
432
|
loadingOverlay.classList.add('show')
|
|
433
433
|
|
|
434
434
|
try {
|
|
435
|
+
const parseStart = performance.now()
|
|
435
436
|
const json = await pptxtojson.parse(e.target.result, {
|
|
436
437
|
imageMode: 'both',
|
|
437
438
|
videoMode: 'blob',
|
|
438
439
|
audioMode: 'blob',
|
|
439
440
|
})
|
|
441
|
+
console.log('parse time:', ((performance.now() - parseStart) / 1000).toFixed(3) + 's')
|
|
440
442
|
editor.set(json)
|
|
441
443
|
console.log(json)
|
|
442
444
|
jsonString = JSON.stringify(json, null, 2)
|
|
@@ -459,7 +461,13 @@
|
|
|
459
461
|
loadingOverlay.classList.add('show')
|
|
460
462
|
|
|
461
463
|
try {
|
|
462
|
-
const
|
|
464
|
+
const parseStart = performance.now()
|
|
465
|
+
const json = await pptxtojson.parse(file, {
|
|
466
|
+
imageMode: 'both',
|
|
467
|
+
videoMode: 'blob',
|
|
468
|
+
audioMode: 'blob',
|
|
469
|
+
})
|
|
470
|
+
console.log('parse time:', ((performance.now() - parseStart) / 1000).toFixed(3) + 's')
|
|
463
471
|
editor.set(json)
|
|
464
472
|
console.log(json)
|
|
465
473
|
jsonString = JSON.stringify(json, null, 2)
|
|
@@ -542,4 +550,4 @@
|
|
|
542
550
|
})
|
|
543
551
|
</script>
|
|
544
552
|
</body>
|
|
545
|
-
</html>
|
|
553
|
+
</html>
|
package/package.json
CHANGED
package/src/chart.js
CHANGED
|
@@ -31,56 +31,66 @@ function extractChartData(serNode) {
|
|
|
31
31
|
const dataMat = []
|
|
32
32
|
if (!serNode) return dataMat
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
dataRow.push(parseFloat(innerNode['c:v']))
|
|
38
|
-
return ''
|
|
39
|
-
})
|
|
40
|
-
dataMat.push(dataRow)
|
|
41
|
-
dataRow = []
|
|
42
|
-
eachElement(serNode['c:yVal']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
43
|
-
dataRow.push(parseFloat(innerNode['c:v']))
|
|
44
|
-
return ''
|
|
45
|
-
})
|
|
46
|
-
dataMat.push(dataRow)
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
eachElement(serNode, (innerNode, index) => {
|
|
50
|
-
const dataRow = []
|
|
51
|
-
const colName = getTextByPathList(innerNode, ['c:tx', 'c:strRef', 'c:strCache', 'c:pt', 'c:v']) || index
|
|
52
|
-
|
|
53
|
-
const rowNames = {}
|
|
54
|
-
if (getTextByPathList(innerNode, ['c:cat', 'c:strRef', 'c:strCache', 'c:pt'])) {
|
|
55
|
-
eachElement(innerNode['c:cat']['c:strRef']['c:strCache']['c:pt'], innerNode => {
|
|
56
|
-
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
57
|
-
return ''
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
else if (getTextByPathList(innerNode, ['c:cat', 'c:numRef', 'c:numCache', 'c:pt'])) {
|
|
61
|
-
eachElement(innerNode['c:cat']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
62
|
-
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
63
|
-
return ''
|
|
64
|
-
})
|
|
65
|
-
}
|
|
34
|
+
eachElement(serNode, (innerNode, index) => {
|
|
35
|
+
const dataRow = []
|
|
36
|
+
const colName = getTextByPathList(innerNode, ['c:tx', 'c:strRef', 'c:strCache', 'c:pt', 'c:v']) || index
|
|
66
37
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
38
|
+
const rowNames = {}
|
|
39
|
+
if (getTextByPathList(innerNode, ['c:cat', 'c:strRef', 'c:strCache', 'c:pt'])) {
|
|
40
|
+
eachElement(innerNode['c:cat']['c:strRef']['c:strCache']['c:pt'], innerNode => {
|
|
41
|
+
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
42
|
+
return ''
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
else if (getTextByPathList(innerNode, ['c:cat', 'c:numRef', 'c:numCache', 'c:pt'])) {
|
|
46
|
+
eachElement(innerNode['c:cat']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
47
|
+
rowNames[innerNode['attrs']['idx']] = innerNode['c:v']
|
|
48
|
+
return ''
|
|
49
|
+
})
|
|
50
|
+
}
|
|
76
51
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
52
|
+
if (getTextByPathList(innerNode, ['c:val', 'c:numRef', 'c:numCache', 'c:pt'])) {
|
|
53
|
+
eachElement(innerNode['c:val']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
54
|
+
dataRow.push({
|
|
55
|
+
x: innerNode['attrs']['idx'],
|
|
56
|
+
y: parseFloat(innerNode['c:v']),
|
|
57
|
+
})
|
|
58
|
+
return ''
|
|
81
59
|
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
dataMat.push({
|
|
63
|
+
key: colName,
|
|
64
|
+
values: dataRow,
|
|
65
|
+
xlabels: rowNames,
|
|
66
|
+
})
|
|
67
|
+
return ''
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
return dataMat
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function extractScatterChartData(serNode) {
|
|
74
|
+
const dataMat = []
|
|
75
|
+
if (!serNode) return dataMat
|
|
76
|
+
|
|
77
|
+
const serNodes = serNode.constructor === Array ? serNode : [serNode]
|
|
78
|
+
const firstSerNode = serNodes[0]
|
|
79
|
+
const xData = []
|
|
80
|
+
|
|
81
|
+
eachElement(firstSerNode['c:xVal']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
82
|
+
xData.push(parseFloat(innerNode['c:v']))
|
|
83
|
+
return ''
|
|
84
|
+
})
|
|
85
|
+
dataMat.push(xData)
|
|
86
|
+
|
|
87
|
+
for (const node of serNodes) {
|
|
88
|
+
const yData = []
|
|
89
|
+
eachElement(node['c:yVal']['c:numRef']['c:numCache']['c:pt'], innerNode => {
|
|
90
|
+
yData.push(parseFloat(innerNode['c:v']))
|
|
82
91
|
return ''
|
|
83
92
|
})
|
|
93
|
+
dataMat.push(yData)
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
return dataMat
|
|
@@ -168,7 +178,7 @@ export function getChartInfo(plotArea, warpObj) {
|
|
|
168
178
|
case 'c:scatterChart':
|
|
169
179
|
chart = {
|
|
170
180
|
type: 'scatterChart',
|
|
171
|
-
data:
|
|
181
|
+
data: extractScatterChartData(plotArea[key]['c:ser']),
|
|
172
182
|
colors: extractChartColors(plotArea[key]['c:ser'], warpObj),
|
|
173
183
|
style: getTextByPathList(plotArea[key], ['c:scatterStyle', 'attrs', 'val']),
|
|
174
184
|
}
|
|
@@ -176,7 +186,7 @@ export function getChartInfo(plotArea, warpObj) {
|
|
|
176
186
|
case 'c:bubbleChart':
|
|
177
187
|
chart = {
|
|
178
188
|
type: 'bubbleChart',
|
|
179
|
-
data:
|
|
189
|
+
data: extractScatterChartData(plotArea[key]['c:ser']),
|
|
180
190
|
colors: extractChartColors(plotArea[key]['c:ser'], warpObj),
|
|
181
191
|
}
|
|
182
192
|
break
|
|
@@ -214,4 +224,4 @@ export function getChartInfo(plotArea, warpObj) {
|
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
return chart
|
|
217
|
-
}
|
|
227
|
+
}
|
package/src/paragraph.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { RATIO_EMUs_Points } from './constants'
|
|
2
|
+
import { getTextByPathList, numberToFixed } from './utils'
|
|
3
|
+
|
|
4
|
+
function getParagraphLevel(node) {
|
|
5
|
+
let lvlIdx = 1
|
|
6
|
+
const lvlNode = getTextByPathList(node, ['a:pPr', 'attrs', 'lvl'])
|
|
7
|
+
if (lvlNode !== undefined) lvlIdx = parseInt(lvlNode) + 1
|
|
8
|
+
return lvlIdx
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getAlignFromTextNode(node, lvlStr) {
|
|
12
|
+
if (!node) return ''
|
|
13
|
+
|
|
14
|
+
let algn = getTextByPathList(node, ['p:txBody', 'a:lstStyle', lvlStr, 'attrs', 'algn'])
|
|
15
|
+
if (!algn) algn = getTextByPathList(node, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
15
16
|
|
|
16
17
|
return algn || ''
|
|
17
18
|
}
|
|
@@ -109,115 +110,144 @@ export function getTextAutoFit(node, slideLayoutSpNode, slideMasterSpNode) {
|
|
|
109
110
|
|
|
110
111
|
const masterCheck = checkBodyPr(getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:bodyPr']))
|
|
111
112
|
if (masterCheck) return masterCheck.result
|
|
112
|
-
|
|
113
|
-
return null
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function pushParagraphStyleNode(styleNodes, styleNode) {
|
|
117
|
-
if (styleNode) styleNodes.push(styleNode)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function appendTextBodyParagraphStyleNodes(styleNodes, textBodyNode, lvl) {
|
|
121
|
-
if (!textBodyNode) return
|
|
122
|
-
|
|
123
|
-
const lvlPath = `a:lvl${lvl}pPr`
|
|
124
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(textBodyNode, ['a:lstStyle', lvlPath]))
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function appendShapeParagraphStyleNodes(styleNodes, shapeNode, lvl) {
|
|
128
|
-
if (!shapeNode) return
|
|
129
|
-
|
|
130
|
-
const lvlPath = `a:lvl${lvl}pPr`
|
|
131
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(shapeNode, ['p:txBody', 'a:lstStyle', lvlPath]))
|
|
132
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(shapeNode, ['p:txBody', 'a:p', 'a:pPr']))
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function appendMasterTextParagraphStyleNodes(styleNodes, type, lvl, slideMasterTextStyles) {
|
|
136
|
-
if (!slideMasterTextStyles) return
|
|
137
|
-
|
|
138
|
-
const lvlPath = `a:lvl${lvl}pPr`
|
|
139
|
-
|
|
140
|
-
if (type === 'title' || type === 'ctrTitle' || type === 'subTitle') {
|
|
141
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:titleStyle', lvlPath]))
|
|
142
|
-
if (type === 'subTitle') {
|
|
143
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', lvlPath]))
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
else if (type === 'body') {
|
|
147
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', lvlPath]))
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:otherStyle', lvlPath]))
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function appendDefaultTextParagraphStyleNodes(styleNodes, defaultTextStyle, lvl) {
|
|
155
|
-
if (!defaultTextStyle) return
|
|
156
|
-
|
|
157
|
-
const lvlPath = `a:lvl${lvl}pPr`
|
|
158
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(defaultTextStyle, [lvlPath]))
|
|
159
|
-
pushParagraphStyleNode(styleNodes, getTextByPathList(defaultTextStyle, ['a:defPPr']))
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
163
|
-
if (!pNode) return null
|
|
164
|
-
|
|
165
|
-
const pPrNode = pNode['a:pPr']
|
|
166
|
-
const lvl = getParagraphLevel(pNode)
|
|
167
|
-
const styleNodes = []
|
|
168
|
-
|
|
169
|
-
pushParagraphStyleNode(styleNodes, pPrNode)
|
|
170
|
-
appendTextBodyParagraphStyleNodes(styleNodes, textBodyNode, lvl)
|
|
171
|
-
appendShapeParagraphStyleNodes(styleNodes, slideLayoutSpNode, lvl)
|
|
172
|
-
appendShapeParagraphStyleNodes(styleNodes, slideMasterSpNode, lvl)
|
|
173
|
-
appendMasterTextParagraphStyleNodes(styleNodes, type, lvl, slideMasterTextStyles)
|
|
174
|
-
appendDefaultTextParagraphStyleNodes(styleNodes, getTextByPathList(warpObj, ['defaultTextStyle']), lvl)
|
|
175
|
-
|
|
176
|
-
return styleNodes
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function getLineSpacingValue(spacingNode) {
|
|
180
|
-
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
181
|
-
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
182
|
-
|
|
183
|
-
if (spcPct) return parseInt(spcPct) / 1000 / 100
|
|
184
|
-
if (spcPts) return parseInt(spcPts) / 100 + 'pt'
|
|
185
|
-
|
|
186
|
-
return undefined
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function getParagraphSpacingValue(spacingNode) {
|
|
190
|
-
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
191
|
-
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
192
|
-
|
|
193
|
-
if (spcPct) return parseInt(spcPct) / 1000 + 'em'
|
|
194
|
-
if (spcPts) return parseInt(spcPts) / 100 + 'pt'
|
|
195
|
-
|
|
196
|
-
return undefined
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
113
|
+
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function pushParagraphStyleNode(styleNodes, styleNode) {
|
|
118
|
+
if (styleNode) styleNodes.push(styleNode)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function appendTextBodyParagraphStyleNodes(styleNodes, textBodyNode, lvl) {
|
|
122
|
+
if (!textBodyNode) return
|
|
123
|
+
|
|
124
|
+
const lvlPath = `a:lvl${lvl}pPr`
|
|
125
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(textBodyNode, ['a:lstStyle', lvlPath]))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function appendShapeParagraphStyleNodes(styleNodes, shapeNode, lvl) {
|
|
129
|
+
if (!shapeNode) return
|
|
130
|
+
|
|
131
|
+
const lvlPath = `a:lvl${lvl}pPr`
|
|
132
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(shapeNode, ['p:txBody', 'a:lstStyle', lvlPath]))
|
|
133
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(shapeNode, ['p:txBody', 'a:p', 'a:pPr']))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function appendMasterTextParagraphStyleNodes(styleNodes, type, lvl, slideMasterTextStyles) {
|
|
137
|
+
if (!slideMasterTextStyles) return
|
|
138
|
+
|
|
139
|
+
const lvlPath = `a:lvl${lvl}pPr`
|
|
140
|
+
|
|
141
|
+
if (type === 'title' || type === 'ctrTitle' || type === 'subTitle') {
|
|
142
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:titleStyle', lvlPath]))
|
|
143
|
+
if (type === 'subTitle') {
|
|
144
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', lvlPath]))
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (type === 'body') {
|
|
148
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', lvlPath]))
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(slideMasterTextStyles, ['p:otherStyle', lvlPath]))
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function appendDefaultTextParagraphStyleNodes(styleNodes, defaultTextStyle, lvl) {
|
|
156
|
+
if (!defaultTextStyle) return
|
|
157
|
+
|
|
158
|
+
const lvlPath = `a:lvl${lvl}pPr`
|
|
159
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(defaultTextStyle, [lvlPath]))
|
|
160
|
+
pushParagraphStyleNode(styleNodes, getTextByPathList(defaultTextStyle, ['a:defPPr']))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
164
|
+
if (!pNode) return null
|
|
165
|
+
|
|
166
|
+
const pPrNode = pNode['a:pPr']
|
|
167
|
+
const lvl = getParagraphLevel(pNode)
|
|
168
|
+
const styleNodes = []
|
|
169
|
+
|
|
170
|
+
pushParagraphStyleNode(styleNodes, pPrNode)
|
|
171
|
+
appendTextBodyParagraphStyleNodes(styleNodes, textBodyNode, lvl)
|
|
172
|
+
appendShapeParagraphStyleNodes(styleNodes, slideLayoutSpNode, lvl)
|
|
173
|
+
appendShapeParagraphStyleNodes(styleNodes, slideMasterSpNode, lvl)
|
|
174
|
+
appendMasterTextParagraphStyleNodes(styleNodes, type, lvl, slideMasterTextStyles)
|
|
175
|
+
appendDefaultTextParagraphStyleNodes(styleNodes, getTextByPathList(warpObj, ['defaultTextStyle']), lvl)
|
|
176
|
+
|
|
177
|
+
return styleNodes
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function getLineSpacingValue(spacingNode) {
|
|
181
|
+
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
182
|
+
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
183
|
+
|
|
184
|
+
if (spcPct) return parseInt(spcPct) / 1000 / 100
|
|
185
|
+
if (spcPts) return parseInt(spcPts) / 100 + 'pt'
|
|
186
|
+
|
|
187
|
+
return undefined
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function getParagraphSpacingValue(spacingNode) {
|
|
191
|
+
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
192
|
+
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
193
|
+
|
|
194
|
+
if (spcPct) return parseInt(spcPct) / 1000 + 'em'
|
|
195
|
+
if (spcPts) return parseInt(spcPts) / 100 + 'pt'
|
|
196
|
+
|
|
197
|
+
return undefined
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function getParagraphIndentValue(styleNode, attrName) {
|
|
201
|
+
const val = getTextByPathList(styleNode, ['attrs', attrName])
|
|
202
|
+
|
|
203
|
+
if (val !== undefined && val !== '') return numberToFixed(parseInt(val) * RATIO_EMUs_Points) + 'pt'
|
|
204
|
+
|
|
205
|
+
return undefined
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
209
|
+
const styleNodes = getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
210
|
+
if (!styleNodes) return null
|
|
211
|
+
|
|
212
|
+
const spacing = {}
|
|
213
|
+
|
|
214
|
+
for (const styleNode of styleNodes) {
|
|
215
|
+
if (spacing.lineSpacing === undefined) {
|
|
216
|
+
const lineSpacing = getLineSpacingValue(styleNode['a:lnSpc'])
|
|
217
|
+
if (lineSpacing !== undefined) spacing.lineSpacing = lineSpacing
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (spacing.spaceBefore === undefined) {
|
|
221
|
+
const spaceBefore = getParagraphSpacingValue(styleNode['a:spcBef'])
|
|
222
|
+
if (spaceBefore !== undefined) spacing.spaceBefore = spaceBefore
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (spacing.spaceAfter === undefined) {
|
|
226
|
+
const spaceAfter = getParagraphSpacingValue(styleNode['a:spcAft'])
|
|
227
|
+
if (spaceAfter !== undefined) spacing.spaceAfter = spaceAfter
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return Object.keys(spacing).length > 0 ? spacing : null
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function getParagraphIndent(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
235
|
+
const styleNodes = getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
236
|
+
if (!styleNodes) return null
|
|
237
|
+
|
|
238
|
+
const indent = {}
|
|
239
|
+
|
|
240
|
+
for (const styleNode of styleNodes) {
|
|
241
|
+
if (indent.marginLeft === undefined) {
|
|
242
|
+
const marginLeft = getParagraphIndentValue(styleNode, 'marL')
|
|
243
|
+
if (marginLeft !== undefined) indent.marginLeft = marginLeft
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (indent.textIndent === undefined) {
|
|
247
|
+
const textIndent = getParagraphIndentValue(styleNode, 'indent')
|
|
248
|
+
if (textIndent !== undefined) indent.textIndent = textIndent
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return Object.keys(indent).length > 0 ? indent : null
|
|
253
|
+
}
|
package/src/pptxtojson.js
CHANGED
|
@@ -4,6 +4,7 @@ import { getBorder } from './border'
|
|
|
4
4
|
import { getSlideBackgroundFill, getShapeFill, getSolidFill, getPicFill, getPicFilters, getImageData, getVideoData, getAudioData } from './fill'
|
|
5
5
|
import { getChartInfo } from './chart'
|
|
6
6
|
import { getVerticalAlign, getTextAutoFit } from './paragraph'
|
|
7
|
+
import { getTextInsets } from './textInsets'
|
|
7
8
|
import { getPosition, getSize } from './position'
|
|
8
9
|
import { genTextBody, getTextNodeValue } from './text'
|
|
9
10
|
import { getCustomShapePath, identifyShape } from './shape'
|
|
@@ -21,6 +22,7 @@ export async function parse(file, options = {}) {
|
|
|
21
22
|
const loadedImages = {}
|
|
22
23
|
const loadedVideos = {}
|
|
23
24
|
const loadedAudios = {}
|
|
25
|
+
const xmlCache = {}
|
|
24
26
|
const parseOptions = {
|
|
25
27
|
...options,
|
|
26
28
|
imageMode: options.imageMode || 'base64',
|
|
@@ -36,7 +38,7 @@ export async function parse(file, options = {}) {
|
|
|
36
38
|
const usedFonts = await getUsedFonts(zip)
|
|
37
39
|
|
|
38
40
|
for (const filename of filesInfo.slides) {
|
|
39
|
-
const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle, loadedImages, loadedVideos, loadedAudios, parseOptions)
|
|
41
|
+
const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle, loadedImages, loadedVideos, loadedAudios, parseOptions, xmlCache)
|
|
40
42
|
slides.push(singleSlide)
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -142,7 +144,16 @@ async function getTheme(zip) {
|
|
|
142
144
|
return { themeContent, themeColors }
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
async function
|
|
147
|
+
async function readXmlFileCached(zip, filename, xmlCache) {
|
|
148
|
+
if (!filename) return null
|
|
149
|
+
if (Object.prototype.hasOwnProperty.call(xmlCache, filename)) return xmlCache[filename]
|
|
150
|
+
|
|
151
|
+
const content = await readXmlFile(zip, filename)
|
|
152
|
+
xmlCache[filename] = content
|
|
153
|
+
return content
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function processSingleSlide(zip, sldFileName, themeContent, defaultTextStyle, loadedImages, loadedVideos, loadedAudios, options, xmlCache) {
|
|
146
157
|
const resName = sldFileName.replace('slides/slide', 'slides/_rels/slide') + '.rels'
|
|
147
158
|
const resContent = await readXmlFile(zip, resName)
|
|
148
159
|
let relationshipArray = resContent['Relationships']['Relationship']
|
|
@@ -205,10 +216,10 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
205
216
|
const slideNotesContent = await readXmlFile(zip, noteFilename)
|
|
206
217
|
const note = getNote(slideNotesContent)
|
|
207
218
|
|
|
208
|
-
const slideLayoutContent = await
|
|
209
|
-
const slideLayoutTables =
|
|
219
|
+
const slideLayoutContent = await readXmlFileCached(zip, layoutFilename, xmlCache)
|
|
220
|
+
const slideLayoutTables = indexNodes(slideLayoutContent)
|
|
210
221
|
const slideLayoutResFilename = layoutFilename.replace('slideLayouts/slideLayout', 'slideLayouts/_rels/slideLayout') + '.rels'
|
|
211
|
-
const slideLayoutResContent = await
|
|
222
|
+
const slideLayoutResContent = await readXmlFileCached(zip, slideLayoutResFilename, xmlCache)
|
|
212
223
|
relationshipArray = slideLayoutResContent['Relationships']['Relationship']
|
|
213
224
|
if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
|
|
214
225
|
|
|
@@ -230,11 +241,11 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
230
241
|
}
|
|
231
242
|
}
|
|
232
243
|
|
|
233
|
-
const slideMasterContent = await
|
|
244
|
+
const slideMasterContent = await readXmlFileCached(zip, masterFilename, xmlCache)
|
|
234
245
|
const slideMasterTextStyles = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:txStyles'])
|
|
235
246
|
const slideMasterTables = indexNodes(slideMasterContent)
|
|
236
247
|
const slideMasterResFilename = masterFilename.replace('slideMasters/slideMaster', 'slideMasters/_rels/slideMaster') + '.rels'
|
|
237
|
-
const slideMasterResContent = await
|
|
248
|
+
const slideMasterResContent = await readXmlFileCached(zip, slideMasterResFilename, xmlCache)
|
|
238
249
|
relationshipArray = slideMasterResContent['Relationships']['Relationship']
|
|
239
250
|
if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
|
|
240
251
|
|
|
@@ -274,7 +285,7 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
274
285
|
}
|
|
275
286
|
}
|
|
276
287
|
|
|
277
|
-
const tableStyles = await
|
|
288
|
+
const tableStyles = await readXmlFileCached(zip, 'ppt/tableStyles.xml', xmlCache)
|
|
278
289
|
|
|
279
290
|
const slideContent = await readXmlFile(zip, sldFileName)
|
|
280
291
|
const nodes = slideContent['p:sld']['p:cSld']['p:spTree']
|
|
@@ -397,7 +408,7 @@ function getNote(noteContent) {
|
|
|
397
408
|
text += `<${listType}>`
|
|
398
409
|
listTypes[listLevel] = listType
|
|
399
410
|
}
|
|
400
|
-
text += `<li style="text-align:${align};">`
|
|
411
|
+
text += `<li><p style="text-align:${align};">`
|
|
401
412
|
}
|
|
402
413
|
else {
|
|
403
414
|
while (listTypes.length > 0) {
|
|
@@ -415,7 +426,7 @@ function getNote(noteContent) {
|
|
|
415
426
|
}
|
|
416
427
|
}
|
|
417
428
|
|
|
418
|
-
if (listType) text += '</li>'
|
|
429
|
+
if (listType) text += '</p></li>'
|
|
419
430
|
else text += '</p>'
|
|
420
431
|
}
|
|
421
432
|
while (listTypes.length > 0) {
|
|
@@ -558,6 +569,8 @@ async function processMathNode(node, warpObj, source) {
|
|
|
558
569
|
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
559
570
|
|
|
560
571
|
const oMath = findOMath(choice)[0]
|
|
572
|
+
if (!oMath) return null
|
|
573
|
+
|
|
561
574
|
const latex = latexFormart(parseOMath(oMath))
|
|
562
575
|
|
|
563
576
|
const blipFill = getTextByPathList(fallback, ['p:sp', 'p:spPr', 'a:blipFill'])
|
|
@@ -640,13 +653,13 @@ async function processGroupSpNode(node, warpObj, source, parentGroupHierarchy =
|
|
|
640
653
|
if (depth > 10) return elements
|
|
641
654
|
|
|
642
655
|
return elements.map(element => {
|
|
643
|
-
const processed = {
|
|
644
|
-
...element,
|
|
645
|
-
left: numberToFixed(element.left * ws),
|
|
646
|
-
top: numberToFixed(element.top * hs),
|
|
647
|
-
width: numberToFixed(element.width * ws),
|
|
648
|
-
height: numberToFixed(element.height * hs),
|
|
649
|
-
}
|
|
656
|
+
const processed = {
|
|
657
|
+
...element,
|
|
658
|
+
left: numberToFixed(element.left * ws),
|
|
659
|
+
top: numberToFixed(element.top * hs),
|
|
660
|
+
width: numberToFixed(element.width * ws),
|
|
661
|
+
height: numberToFixed(element.height * hs),
|
|
662
|
+
}
|
|
650
663
|
if (element.type === 'group' && element.elements) {
|
|
651
664
|
processed.elements = processNestedGroupElements(element.elements, ws, hs, depth + 1)
|
|
652
665
|
}
|
|
@@ -698,11 +711,11 @@ async function processSpNode(node, warpObj, source, groupHierarchy = []) {
|
|
|
698
711
|
const txBoxVal = getTextByPathList(node, ['p:nvSpPr', 'p:cNvSpPr', 'attrs', 'txBox'])
|
|
699
712
|
if (txBoxVal === '1') type = 'text'
|
|
700
713
|
}
|
|
701
|
-
if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
702
|
-
if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
703
|
-
if (!slideMasterSpNode && type === 'ctrTitle') slideMasterSpNode = warpObj['slideMasterTables']['typeTable']['title']
|
|
704
|
-
|
|
705
|
-
if (!type) {
|
|
714
|
+
if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
715
|
+
if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
716
|
+
if (!slideMasterSpNode && type === 'ctrTitle') slideMasterSpNode = warpObj['slideMasterTables']['typeTable']['title']
|
|
717
|
+
|
|
718
|
+
if (!type) {
|
|
706
719
|
if (source === 'diagramBg') type = 'diagram'
|
|
707
720
|
else type = 'obj'
|
|
708
721
|
}
|
|
@@ -775,6 +788,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
775
788
|
const vAlign = getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode, type)
|
|
776
789
|
const isVertical = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'vert']) === 'eaVert'
|
|
777
790
|
const autoFit = getTextAutoFit(node, slideLayoutSpNode, slideMasterSpNode)
|
|
791
|
+
const textInset = getTextInsets(node, slideLayoutSpNode, slideMasterSpNode)
|
|
778
792
|
|
|
779
793
|
const data = {
|
|
780
794
|
left,
|
|
@@ -798,6 +812,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
798
812
|
if (shadow) data.shadow = shadow
|
|
799
813
|
if (autoFit) data.autoFit = autoFit
|
|
800
814
|
if (link) data.link = link
|
|
815
|
+
if (textInset) data.textInset = textInset
|
|
801
816
|
|
|
802
817
|
const isHasValidText = data.content && hasValidText(data.content)
|
|
803
818
|
|
|
@@ -1188,11 +1203,11 @@ async function genTable(node, warpObj) {
|
|
|
1188
1203
|
if (cell.rowSpan) td.rowSpan = cell.rowSpan
|
|
1189
1204
|
if (cell.colSpan) td.colSpan = cell.colSpan
|
|
1190
1205
|
if (cell.vMerge) td.vMerge = cell.vMerge
|
|
1191
|
-
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1192
|
-
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1193
|
-
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1194
|
-
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1195
|
-
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
1206
|
+
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1207
|
+
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1208
|
+
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1209
|
+
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1210
|
+
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
1196
1211
|
if (cell.borders) td.borders = cell.borders
|
|
1197
1212
|
|
|
1198
1213
|
tr.push(td)
|
|
@@ -1221,11 +1236,11 @@ async function genTable(node, warpObj) {
|
|
|
1221
1236
|
if (cell.rowSpan) td.rowSpan = cell.rowSpan
|
|
1222
1237
|
if (cell.colSpan) td.colSpan = cell.colSpan
|
|
1223
1238
|
if (cell.vMerge) td.vMerge = cell.vMerge
|
|
1224
|
-
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1225
|
-
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1226
|
-
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1227
|
-
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1228
|
-
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
1239
|
+
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1240
|
+
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1241
|
+
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1242
|
+
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1243
|
+
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
1229
1244
|
if (cell.borders) td.borders = cell.borders
|
|
1230
1245
|
|
|
1231
1246
|
tr.push(td)
|