pptxtojson 1.0.3 → 1.1.1
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 +133 -143
- package/dist/index.d.ts +22 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/index.html +13 -3
- package/package.json +2 -2
- package/src/math.js +184 -0
- package/src/pptxtojson.js +79 -7
- package/src/readXmlFile.js +8 -4
- package/src/utils.js +9 -0
package/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
-
<meta name="description" content="
|
|
8
|
-
<meta name="keywords" content="ppt,powerpoint,
|
|
7
|
+
<meta name="description" content="Office PowerPoint(.pptx) file to JSON | 将 PPTX 文件转为可读的 JSON 数据" />
|
|
8
|
+
<meta name="keywords" content="pptx2json,pptxtojson,ppt,powerpoint,json,javascript,PPT解析,PPT转JSON" />
|
|
9
9
|
<link rel="icon" href="favicon.ico">
|
|
10
10
|
<title>pptxtojson - PPTX转JSON</title>
|
|
11
11
|
|
|
@@ -80,6 +80,13 @@
|
|
|
80
80
|
.upload-input {
|
|
81
81
|
display: none;
|
|
82
82
|
}
|
|
83
|
+
.link {
|
|
84
|
+
display: flex;
|
|
85
|
+
}
|
|
86
|
+
.link a {
|
|
87
|
+
padding: 5px 10px;
|
|
88
|
+
color: #d14424;
|
|
89
|
+
}
|
|
83
90
|
</style>
|
|
84
91
|
</head>
|
|
85
92
|
|
|
@@ -90,7 +97,10 @@
|
|
|
90
97
|
<input class="upload-input" type="file" accept="application/vnd.openxmlformats-officedocument.presentationml.presentation"/>
|
|
91
98
|
</div>
|
|
92
99
|
|
|
93
|
-
<
|
|
100
|
+
<div class="link">
|
|
101
|
+
<a target="_blank" href="https://github.com/pipipi-pikachu/pptx2json">Github仓库</a>
|
|
102
|
+
<a target="_blank" href="https://pipipi-pikachu.github.io/PPTist/">可视化测试</a>
|
|
103
|
+
</div>
|
|
94
104
|
</div>
|
|
95
105
|
<div id="jsoneditor"></div>
|
|
96
106
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptxtojson",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A javascript tool for parsing .pptx file",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.umd.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"homepage": "https://github.com/pipipi-pikachu/pptxtojson",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"publishConfig": {
|
|
27
|
-
"registry": "https://registry.npmjs.
|
|
27
|
+
"registry": "https://registry.npmjs.com"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"jszip": "^3.10.1",
|
package/src/math.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { getTextByPathList } from './utils'
|
|
2
|
+
|
|
3
|
+
export function findOMath(obj) {
|
|
4
|
+
let results = []
|
|
5
|
+
if (typeof obj !== 'object') return results
|
|
6
|
+
if (obj['m:oMath']) results = results.concat(obj['m:oMath'])
|
|
7
|
+
|
|
8
|
+
Object.values(obj).forEach(value => {
|
|
9
|
+
if (Array.isArray(value) || typeof value === 'object') {
|
|
10
|
+
results = results.concat(findOMath(value))
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
return results
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function parseFraction(fraction) {
|
|
17
|
+
const numerator = parseOMath(fraction['m:num'])
|
|
18
|
+
const denominator = parseOMath(fraction['m:den'])
|
|
19
|
+
return `\\frac{${numerator}}{${denominator}}`
|
|
20
|
+
}
|
|
21
|
+
export function parseSuperscript(superscript) {
|
|
22
|
+
const base = parseOMath(superscript['m:e'])
|
|
23
|
+
const sup = parseOMath(superscript['m:sup'])
|
|
24
|
+
return `${base}^{${sup}}`
|
|
25
|
+
}
|
|
26
|
+
export function parseSubscript(subscript) {
|
|
27
|
+
const base = parseOMath(subscript['m:e'])
|
|
28
|
+
const sub = parseOMath(subscript['m:sub'])
|
|
29
|
+
return `${base}_{${sub}}`
|
|
30
|
+
}
|
|
31
|
+
export function parseRadical(radical) {
|
|
32
|
+
const degree = parseOMath(radical['m:deg'])
|
|
33
|
+
const expression = parseOMath(radical['m:e'])
|
|
34
|
+
return degree ? `\\sqrt[${degree}]{${expression}}` : `\\sqrt{${expression}}`
|
|
35
|
+
}
|
|
36
|
+
export function parseMatrix(matrix) {
|
|
37
|
+
const rows = matrix['m:mr']
|
|
38
|
+
const matrixRows = rows.map((row) => {
|
|
39
|
+
return row['m:e'].map((element) => parseOMath(element)).join(' & ')
|
|
40
|
+
})
|
|
41
|
+
return `\\begin{matrix} ${matrixRows.join(' \\\\ ')} \\end{matrix}`
|
|
42
|
+
}
|
|
43
|
+
export function parseNary(nary) {
|
|
44
|
+
const op = getTextByPathList(nary, ['m:naryPr', 'm:chr', 'attrs', 'm:val']) || '∫'
|
|
45
|
+
const sub = parseOMath(nary['m:sub'])
|
|
46
|
+
const sup = parseOMath(nary['m:sup'])
|
|
47
|
+
const e = parseOMath(nary['m:e'])
|
|
48
|
+
return `${op}_{${sub}}^{${sup}}{${e}}`
|
|
49
|
+
}
|
|
50
|
+
export function parseLimit(limit, type) {
|
|
51
|
+
const base = parseOMath(limit['m:e'])
|
|
52
|
+
const lim = parseOMath(limit['m:lim'])
|
|
53
|
+
return type === 'low' ? `${base}_{${lim}}` : `${base}^{${lim}}`
|
|
54
|
+
}
|
|
55
|
+
export function parseDelimiter(delimiter) {
|
|
56
|
+
let left = getTextByPathList(delimiter, ['m:dPr', 'm:begChr', 'attrs', 'm:val'])
|
|
57
|
+
let right = getTextByPathList(delimiter, ['m:dPr', 'm:endChr', 'attrs', 'm:val'])
|
|
58
|
+
if (!left && !right) {
|
|
59
|
+
left = '('
|
|
60
|
+
right = ')'
|
|
61
|
+
}
|
|
62
|
+
if (left && right) {
|
|
63
|
+
left = `\\left${left}`
|
|
64
|
+
right = `\\right${right}`
|
|
65
|
+
}
|
|
66
|
+
const e = parseOMath(delimiter['m:e'])
|
|
67
|
+
return `${left}${e}${right}`
|
|
68
|
+
}
|
|
69
|
+
export function parseFunction(func) {
|
|
70
|
+
const name = parseOMath(func['m:fName'])
|
|
71
|
+
const arg = parseOMath(func['m:e'])
|
|
72
|
+
return `\\${name}{${arg}}`
|
|
73
|
+
}
|
|
74
|
+
export function parseGroupChr(groupChr) {
|
|
75
|
+
const chr = getTextByPathList(groupChr, ['m:groupChrPr', 'm:chr', 'attrs', 'm:val'])
|
|
76
|
+
const e = parseOMath(groupChr['m:e'])
|
|
77
|
+
return `${chr}${e}${chr}`
|
|
78
|
+
}
|
|
79
|
+
export function parseEqArr(eqArr) {
|
|
80
|
+
const equations = eqArr['m:e'].map((eq) => parseOMath(eq)).join(' \\\\ ')
|
|
81
|
+
return `\\begin{cases} ${equations} \\end{cases}`
|
|
82
|
+
}
|
|
83
|
+
export function parseBar(bar) {
|
|
84
|
+
const e = parseOMath(bar['m:e'])
|
|
85
|
+
const pos = getTextByPathList(bar, ['m:barPr', 'm:pos', 'attrs', 'm:val'])
|
|
86
|
+
return pos === 'top' ? `\\overline{${e}}` : `\\underline{${e}}`
|
|
87
|
+
}
|
|
88
|
+
export function parseAccent(accent) {
|
|
89
|
+
const chr = getTextByPathList(accent, ['m:accPr', 'm:chr', 'attrs', 'm:val']) || '^'
|
|
90
|
+
const e = parseOMath(accent['m:e'])
|
|
91
|
+
switch (chr) {
|
|
92
|
+
case '\u0301':
|
|
93
|
+
return `\\acute{${e}}`
|
|
94
|
+
case '\u0300':
|
|
95
|
+
return `\\grave{${e}}`
|
|
96
|
+
case '\u0302':
|
|
97
|
+
return `\\hat{${e}}`
|
|
98
|
+
case '\u0303':
|
|
99
|
+
return `\\tilde{${e}}`
|
|
100
|
+
case '\u0304':
|
|
101
|
+
return `\\bar{${e}}`
|
|
102
|
+
case '\u0306':
|
|
103
|
+
return `\\breve{${e}}`
|
|
104
|
+
case '\u0307':
|
|
105
|
+
return `\\dot{${e}}`
|
|
106
|
+
case '\u0308':
|
|
107
|
+
return `\\ddot{${e}}`
|
|
108
|
+
case '\u030A':
|
|
109
|
+
return `\\mathring{${e}}`
|
|
110
|
+
case '\u030B':
|
|
111
|
+
return `\\H{${e}}`
|
|
112
|
+
case '\u030C':
|
|
113
|
+
return `\\check{${e}}`
|
|
114
|
+
case '\u0327':
|
|
115
|
+
return `\\c{${e}}`
|
|
116
|
+
default:
|
|
117
|
+
return `\\${chr}{${e}}`
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function parseBox(box) {
|
|
121
|
+
const e = parseOMath(box['m:e'])
|
|
122
|
+
return `\\boxed{${e}}`
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
export function parseOMath(oMath) {
|
|
127
|
+
if (!oMath) return ''
|
|
128
|
+
|
|
129
|
+
if (Array.isArray(oMath)) {
|
|
130
|
+
return oMath.map(item => parseOMath(item)).join('')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const oMathList = []
|
|
134
|
+
const keys = Object.keys(oMath)
|
|
135
|
+
for (const key of keys) {
|
|
136
|
+
if (Array.isArray(oMath[key])) {
|
|
137
|
+
oMathList.push(...oMath[key].map(item => ({ key, value: item })))
|
|
138
|
+
}
|
|
139
|
+
else oMathList.push({ key, value: oMath[key] })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
oMathList.sort((a, b) => {
|
|
143
|
+
let oA = 0
|
|
144
|
+
if (a.key === 'm:r' && a.value && a.value['a:rPr']) oA = a.value['a:rPr']['attrs']['order']
|
|
145
|
+
else if (a.value[`${a.key}Pr`] && a.value[`${a.key}Pr`]['m:ctrlPr'] && a.value[`${a.key}Pr`]['m:ctrlPr']['a:rPr']) {
|
|
146
|
+
oA = a.value[`${a.key}Pr`] && a.value[`${a.key}Pr`]['m:ctrlPr'] && a.value[`${a.key}Pr`]['m:ctrlPr']['a:rPr'] && a.value[`${a.key}Pr`]['m:ctrlPr']['a:rPr']['attrs']['order']
|
|
147
|
+
}
|
|
148
|
+
let oB = 0
|
|
149
|
+
if (b.key === 'm:r' && b.value && b.value['a:rPr']) oB = b.value['a:rPr']['attrs']['order']
|
|
150
|
+
else if (b.value[`${b.key}Pr`] && b.value[`${b.key}Pr`]['m:ctrlPr'] && b.value[`${b.key}Pr`]['m:ctrlPr']['a:rPr']) {
|
|
151
|
+
oB = b.value[`${b.key}Pr`] && b.value[`${b.key}Pr`]['m:ctrlPr'] && b.value[`${b.key}Pr`]['m:ctrlPr']['a:rPr'] && b.value[`${b.key}Pr`]['m:ctrlPr']['a:rPr']['attrs']['order']
|
|
152
|
+
}
|
|
153
|
+
return oA - oB
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
return oMathList.map(({ key, value }) => {
|
|
157
|
+
if (key === 'm:f') return parseFraction(value)
|
|
158
|
+
if (key === 'm:sSup') return parseSuperscript(value)
|
|
159
|
+
if (key === 'm:sSub') return parseSubscript(value)
|
|
160
|
+
if (key === 'm:rad') return parseRadical(value)
|
|
161
|
+
if (key === 'm:nary') return parseNary(value)
|
|
162
|
+
if (key === 'm:limLow') return parseLimit(value, 'low')
|
|
163
|
+
if (key === 'm:limUpp') return parseLimit(value, 'upp')
|
|
164
|
+
if (key === 'm:d') return parseDelimiter(value)
|
|
165
|
+
if (key === 'm:func') return parseFunction(value)
|
|
166
|
+
if (key === 'm:groupChr') return parseGroupChr(value)
|
|
167
|
+
if (key === 'm:eqArr') return parseEqArr(value)
|
|
168
|
+
if (key === 'm:bar') return parseBar(value)
|
|
169
|
+
if (key === 'm:acc') return parseAccent(value)
|
|
170
|
+
if (key === 'm:borderBox') return parseBox(value)
|
|
171
|
+
if (key === 'm:m') return parseMatrix(value)
|
|
172
|
+
if (key === 'm:r') return parseOMath(value)
|
|
173
|
+
if (key === 'm:t') return value
|
|
174
|
+
return ''
|
|
175
|
+
}).join('')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function latexFormart(latex) {
|
|
179
|
+
return latex.replaceAll(/</g, '<')
|
|
180
|
+
.replaceAll(/>/g, '>')
|
|
181
|
+
.replaceAll(/&/g, '&')
|
|
182
|
+
.replaceAll(/'/g, "'")
|
|
183
|
+
.replaceAll(/"/g, '"')
|
|
184
|
+
}
|
package/src/pptxtojson.js
CHANGED
|
@@ -7,10 +7,11 @@ 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'
|
|
14
|
+
import { findOMath, latexFormart, parseOMath } from './math'
|
|
14
15
|
|
|
15
16
|
export async function parse(file) {
|
|
16
17
|
const slides = []
|
|
@@ -105,6 +106,7 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
105
106
|
let relationshipArray = resContent['Relationships']['Relationship']
|
|
106
107
|
let layoutFilename = ''
|
|
107
108
|
let diagramFilename = ''
|
|
109
|
+
let notesFilename = ''
|
|
108
110
|
const slideResObj = {}
|
|
109
111
|
|
|
110
112
|
if (relationshipArray.constructor === Array) {
|
|
@@ -121,6 +123,8 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
121
123
|
}
|
|
122
124
|
break
|
|
123
125
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide':
|
|
126
|
+
notesFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
127
|
+
break
|
|
124
128
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image':
|
|
125
129
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart':
|
|
126
130
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink':
|
|
@@ -133,6 +137,9 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
else layoutFilename = relationshipArray['attrs']['Target'].replace('../', 'ppt/')
|
|
140
|
+
|
|
141
|
+
const slideNotesContent = await readXmlFile(zip, notesFilename)
|
|
142
|
+
const note = getNote(slideNotesContent)
|
|
136
143
|
|
|
137
144
|
const slideLayoutContent = await readXmlFile(zip, layoutFilename)
|
|
138
145
|
const slideLayoutTables = await indexNodes(slideLayoutContent)
|
|
@@ -283,9 +290,29 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
283
290
|
return {
|
|
284
291
|
fill: bgColor,
|
|
285
292
|
elements,
|
|
293
|
+
note,
|
|
286
294
|
}
|
|
287
295
|
}
|
|
288
296
|
|
|
297
|
+
function getNote(noteContent) {
|
|
298
|
+
let text = ''
|
|
299
|
+
let spNodes = getTextByPathList(noteContent, ['p:notes', 'p:cSld', 'p:spTree', 'p:sp'])
|
|
300
|
+
if (!spNodes) return ''
|
|
301
|
+
|
|
302
|
+
if (spNodes.constructor !== Array) spNodes = [spNodes]
|
|
303
|
+
for (const spNode of spNodes) {
|
|
304
|
+
let rNodes = getTextByPathList(spNode, ['p:txBody', 'a:p', 'a:r'])
|
|
305
|
+
if (!rNodes) continue
|
|
306
|
+
|
|
307
|
+
if (rNodes.constructor !== Array) rNodes = [rNodes]
|
|
308
|
+
for (const rNode of rNodes) {
|
|
309
|
+
const t = getTextByPathList(rNode, ['a:t'])
|
|
310
|
+
if (t) text += t
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return text
|
|
314
|
+
}
|
|
315
|
+
|
|
289
316
|
// async function getBackground(warpObj) {
|
|
290
317
|
// const elements = []
|
|
291
318
|
// const slideLayoutContent = warpObj['slideLayoutContent']
|
|
@@ -390,7 +417,12 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
|
|
|
390
417
|
json = await processGroupSpNode(nodeValue, warpObj, source)
|
|
391
418
|
break
|
|
392
419
|
case 'mc:AlternateContent':
|
|
393
|
-
|
|
420
|
+
if (getTextByPathList(nodeValue, ['mc:Fallback', 'p:grpSpPr', 'a:xfrm'])) {
|
|
421
|
+
json = await processGroupSpNode(getTextByPathList(nodeValue, ['mc:Fallback']), warpObj, source)
|
|
422
|
+
}
|
|
423
|
+
else if (getTextByPathList(nodeValue, ['mc:Choice'])) {
|
|
424
|
+
json = await processMathNode(getTextByPathList(nodeValue, ['mc:Choice']))
|
|
425
|
+
}
|
|
394
426
|
break
|
|
395
427
|
default:
|
|
396
428
|
}
|
|
@@ -398,7 +430,28 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source) {
|
|
|
398
430
|
return json
|
|
399
431
|
}
|
|
400
432
|
|
|
433
|
+
function processMathNode(node) {
|
|
434
|
+
const order = node['attrs']['order']
|
|
435
|
+
const xfrmNode = getTextByPathList(node, ['p:sp', 'p:spPr', 'a:xfrm'])
|
|
436
|
+
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
437
|
+
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
438
|
+
|
|
439
|
+
const oMath = findOMath(node)[0]
|
|
440
|
+
const latex = latexFormart(parseOMath(oMath))
|
|
441
|
+
|
|
442
|
+
return {
|
|
443
|
+
type: 'math',
|
|
444
|
+
top,
|
|
445
|
+
left,
|
|
446
|
+
width,
|
|
447
|
+
height,
|
|
448
|
+
latex,
|
|
449
|
+
order,
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
401
453
|
async function processGroupSpNode(node, warpObj, source) {
|
|
454
|
+
const order = node['attrs']['order']
|
|
402
455
|
const xfrmNode = getTextByPathList(node, ['p:grpSpPr', 'a:xfrm'])
|
|
403
456
|
if (!xfrmNode) return null
|
|
404
457
|
|
|
@@ -438,6 +491,7 @@ async function processGroupSpNode(node, warpObj, source) {
|
|
|
438
491
|
width: cx,
|
|
439
492
|
height: cy,
|
|
440
493
|
rotate,
|
|
494
|
+
order,
|
|
441
495
|
elements: elements.map(element => ({
|
|
442
496
|
...element,
|
|
443
497
|
left: (element.left - chx) * ws,
|
|
@@ -452,6 +506,7 @@ function processSpNode(node, warpObj, source) {
|
|
|
452
506
|
const name = getTextByPathList(node, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'name'])
|
|
453
507
|
const idx = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'idx'])
|
|
454
508
|
let type = getTextByPathList(node, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
509
|
+
const order = getTextByPathList(node, ['attrs', 'order'])
|
|
455
510
|
|
|
456
511
|
let slideLayoutSpNode, slideMasterSpNode
|
|
457
512
|
|
|
@@ -482,17 +537,18 @@ function processSpNode(node, warpObj, source) {
|
|
|
482
537
|
else type = 'obj'
|
|
483
538
|
}
|
|
484
539
|
|
|
485
|
-
return genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj)
|
|
540
|
+
return genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, order, warpObj)
|
|
486
541
|
}
|
|
487
542
|
|
|
488
543
|
function processCxnSpNode(node, warpObj) {
|
|
489
544
|
const name = node['p:nvCxnSpPr']['p:cNvPr']['attrs']['name']
|
|
490
545
|
const type = (node['p:nvCxnSpPr']['p:nvPr']['p:ph'] === undefined) ? undefined : node['p:nvSpPr']['p:nvPr']['p:ph']['attrs']['type']
|
|
546
|
+
const order = node['attrs']['order']
|
|
491
547
|
|
|
492
|
-
return genShape(node, undefined, undefined, name, type, warpObj)
|
|
548
|
+
return genShape(node, undefined, undefined, name, type, order, warpObj)
|
|
493
549
|
}
|
|
494
550
|
|
|
495
|
-
function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpObj) {
|
|
551
|
+
function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, order, warpObj) {
|
|
496
552
|
const xfrmList = ['p:spPr', 'a:xfrm']
|
|
497
553
|
const slideXfrmNode = getTextByPathList(node, xfrmList)
|
|
498
554
|
const slideLayoutXfrmNode = getTextByPathList(slideLayoutSpNode, xfrmList)
|
|
@@ -518,7 +574,10 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
|
|
|
518
574
|
else txtRotate = rotate
|
|
519
575
|
|
|
520
576
|
let content = ''
|
|
521
|
-
if (node['p:txBody'])
|
|
577
|
+
if (node['p:txBody']) {
|
|
578
|
+
content = genTextBody(node['p:txBody'], node, slideLayoutSpNode, type, warpObj)
|
|
579
|
+
if (!hasValidText(content)) content = ''
|
|
580
|
+
}
|
|
522
581
|
|
|
523
582
|
const { borderColor, borderWidth, borderType, strokeDasharray } = getBorder(node, type, warpObj)
|
|
524
583
|
const fillColor = getShapeFill(node, undefined, warpObj) || ''
|
|
@@ -546,6 +605,7 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type, warpOb
|
|
|
546
605
|
rotate,
|
|
547
606
|
vAlign,
|
|
548
607
|
name,
|
|
608
|
+
order,
|
|
549
609
|
}
|
|
550
610
|
|
|
551
611
|
if (shadow) data.shadow = shadow
|
|
@@ -583,6 +643,8 @@ async function processPicNode(node, warpObj, source) {
|
|
|
583
643
|
if (source === 'slideMasterBg') resObj = warpObj['masterResObj']
|
|
584
644
|
else if (source === 'slideLayoutBg') resObj = warpObj['layoutResObj']
|
|
585
645
|
else resObj = warpObj['slideResObj']
|
|
646
|
+
|
|
647
|
+
const order = node['attrs']['order']
|
|
586
648
|
|
|
587
649
|
const rid = node['p:blipFill']['a:blip']['attrs']['r:embed']
|
|
588
650
|
const imgName = resObj[rid]['target']
|
|
@@ -647,6 +709,7 @@ async function processPicNode(node, warpObj, source) {
|
|
|
647
709
|
height,
|
|
648
710
|
rotate,
|
|
649
711
|
blob: videoBlob,
|
|
712
|
+
order,
|
|
650
713
|
}
|
|
651
714
|
}
|
|
652
715
|
if (videoNode && isVdeoLink) {
|
|
@@ -658,6 +721,7 @@ async function processPicNode(node, warpObj, source) {
|
|
|
658
721
|
height,
|
|
659
722
|
rotate,
|
|
660
723
|
src: videoFile,
|
|
724
|
+
order,
|
|
661
725
|
}
|
|
662
726
|
}
|
|
663
727
|
if (audioNode) {
|
|
@@ -669,6 +733,7 @@ async function processPicNode(node, warpObj, source) {
|
|
|
669
733
|
height,
|
|
670
734
|
rotate,
|
|
671
735
|
blob: audioBlob,
|
|
736
|
+
order,
|
|
672
737
|
}
|
|
673
738
|
}
|
|
674
739
|
return {
|
|
@@ -680,7 +745,8 @@ async function processPicNode(node, warpObj, source) {
|
|
|
680
745
|
rotate,
|
|
681
746
|
src,
|
|
682
747
|
isFlipV,
|
|
683
|
-
isFlipH
|
|
748
|
+
isFlipH,
|
|
749
|
+
order,
|
|
684
750
|
}
|
|
685
751
|
}
|
|
686
752
|
|
|
@@ -709,6 +775,7 @@ async function processGraphicFrameNode(node, warpObj, source) {
|
|
|
709
775
|
}
|
|
710
776
|
|
|
711
777
|
function genTable(node, warpObj) {
|
|
778
|
+
const order = node['attrs']['order']
|
|
712
779
|
const tableNode = getTextByPathList(node, ['a:graphic', 'a:graphicData', 'a:tbl'])
|
|
713
780
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
714
781
|
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
@@ -878,11 +945,13 @@ function genTable(node, warpObj) {
|
|
|
878
945
|
width,
|
|
879
946
|
height,
|
|
880
947
|
data,
|
|
948
|
+
order,
|
|
881
949
|
...(tbl_border || {}),
|
|
882
950
|
}
|
|
883
951
|
}
|
|
884
952
|
|
|
885
953
|
async function genChart(node, warpObj) {
|
|
954
|
+
const order = node['attrs']['order']
|
|
886
955
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
887
956
|
const { top, left } = getPosition(xfrmNode, undefined, undefined)
|
|
888
957
|
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
@@ -904,6 +973,7 @@ async function genChart(node, warpObj) {
|
|
|
904
973
|
height,
|
|
905
974
|
data: chart.data,
|
|
906
975
|
chartType: chart.type,
|
|
976
|
+
order,
|
|
907
977
|
}
|
|
908
978
|
if (chart.marker !== undefined) data.marker = chart.marker
|
|
909
979
|
if (chart.barDir !== undefined) data.barDir = chart.barDir
|
|
@@ -915,6 +985,7 @@ async function genChart(node, warpObj) {
|
|
|
915
985
|
}
|
|
916
986
|
|
|
917
987
|
function genDiagram(node, warpObj) {
|
|
988
|
+
const order = node['attrs']['order']
|
|
918
989
|
const xfrmNode = getTextByPathList(node, ['p:xfrm'])
|
|
919
990
|
const { left, top } = getPosition(xfrmNode, undefined, undefined)
|
|
920
991
|
const { width, height } = getSize(xfrmNode, undefined, undefined)
|
|
@@ -935,5 +1006,6 @@ function genDiagram(node, warpObj) {
|
|
|
935
1006
|
width,
|
|
936
1007
|
height,
|
|
937
1008
|
elements,
|
|
1009
|
+
order,
|
|
938
1010
|
}
|
|
939
1011
|
}
|
package/src/readXmlFile.js
CHANGED
|
@@ -19,11 +19,15 @@ export function simplifyLostLess(children, parentAttributes = {}) {
|
|
|
19
19
|
if (!out[child.tagName]) out[child.tagName] = []
|
|
20
20
|
|
|
21
21
|
const kids = simplifyLostLess(child.children || [], child.attributes)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
kids.attrs =
|
|
22
|
+
|
|
23
|
+
if (typeof kids === 'object') {
|
|
24
|
+
if (!kids.attrs) kids.attrs = { order: cust_attr_order++ }
|
|
25
|
+
else kids.attrs.order = cust_attr_order++
|
|
26
26
|
}
|
|
27
|
+
if (Object.keys(child.attributes || {}).length) {
|
|
28
|
+
kids.attrs = { ...kids.attrs, ...child.attributes }
|
|
29
|
+
}
|
|
30
|
+
out[child.tagName].push(kids)
|
|
27
31
|
}
|
|
28
32
|
for (const child in out) {
|
|
29
33
|
if (out[child].length === 1) out[child] = out[child][0]
|
package/src/utils.js
CHANGED
|
@@ -150,4 +150,13 @@ export function toHex(n) {
|
|
|
150
150
|
hex = '0' + hex
|
|
151
151
|
}
|
|
152
152
|
return hex
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function hasValidText(htmlString) {
|
|
156
|
+
if (!DOMParser) return true
|
|
157
|
+
|
|
158
|
+
const parser = new DOMParser()
|
|
159
|
+
const doc = parser.parseFromString(htmlString, 'text/html')
|
|
160
|
+
const text = doc.body.textContent || doc.body.innerText
|
|
161
|
+
return text.trim() !== ''
|
|
153
162
|
}
|