pptxtojson 1.6.1 → 1.8.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/README.md +7 -5
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +4 -4
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/fill.js +156 -4
- package/src/fontStyle.js +43 -3
- package/src/position.js +5 -4
- package/src/pptxtojson.js +26 -12
- package/src/text.js +59 -9
- package/src/utils.js +4 -0
package/package.json
CHANGED
package/src/fill.js
CHANGED
|
@@ -85,6 +85,79 @@ export function getPicFillOpacity(node) {
|
|
|
85
85
|
return opacity
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
export function getPicFilters(node) {
|
|
89
|
+
if (!node) return null
|
|
90
|
+
|
|
91
|
+
const aBlipNode = node['a:blip']
|
|
92
|
+
if (!aBlipNode) return null
|
|
93
|
+
|
|
94
|
+
const filters = {}
|
|
95
|
+
|
|
96
|
+
// 从a:extLst中获取滤镜效果(Microsoft Office 2010+扩展)
|
|
97
|
+
const extLstNode = aBlipNode['a:extLst']
|
|
98
|
+
if (extLstNode && extLstNode['a:ext']) {
|
|
99
|
+
const extNodes = Array.isArray(extLstNode['a:ext']) ? extLstNode['a:ext'] : [extLstNode['a:ext']]
|
|
100
|
+
|
|
101
|
+
for (const extNode of extNodes) {
|
|
102
|
+
if (!extNode['a14:imgProps'] || !extNode['a14:imgProps']['a14:imgLayer']) continue
|
|
103
|
+
|
|
104
|
+
const imgLayerNode = extNode['a14:imgProps']['a14:imgLayer']
|
|
105
|
+
const imgEffects = imgLayerNode['a14:imgEffect']
|
|
106
|
+
|
|
107
|
+
if (!imgEffects) continue
|
|
108
|
+
|
|
109
|
+
const effectArray = Array.isArray(imgEffects) ? imgEffects : [imgEffects]
|
|
110
|
+
|
|
111
|
+
for (const effect of effectArray) {
|
|
112
|
+
// 饱和度
|
|
113
|
+
if (effect['a14:saturation']) {
|
|
114
|
+
const satAttr = getTextByPathList(effect, ['a14:saturation', 'attrs', 'sat'])
|
|
115
|
+
if (satAttr) {
|
|
116
|
+
filters.saturation = parseInt(satAttr) / 100000
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 亮度、对比度
|
|
121
|
+
if (effect['a14:brightnessContrast']) {
|
|
122
|
+
const brightAttr = getTextByPathList(effect, ['a14:brightnessContrast', 'attrs', 'bright'])
|
|
123
|
+
const contrastAttr = getTextByPathList(effect, ['a14:brightnessContrast', 'attrs', 'contrast'])
|
|
124
|
+
|
|
125
|
+
if (brightAttr) {
|
|
126
|
+
filters.brightness = parseInt(brightAttr) / 100000
|
|
127
|
+
}
|
|
128
|
+
if (contrastAttr) {
|
|
129
|
+
filters.contrast = parseInt(contrastAttr) / 100000
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 锐化/柔化
|
|
134
|
+
if (effect['a14:sharpenSoften']) {
|
|
135
|
+
const amountAttr = getTextByPathList(effect, ['a14:sharpenSoften', 'attrs', 'amount'])
|
|
136
|
+
if (amountAttr) {
|
|
137
|
+
const amount = parseInt(amountAttr) / 100000
|
|
138
|
+
if (amount > 0) {
|
|
139
|
+
filters.sharpen = amount
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
filters.soften = Math.abs(amount)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 色温
|
|
148
|
+
if (effect['a14:colorTemperature']) {
|
|
149
|
+
const tempAttr = getTextByPathList(effect, ['a14:colorTemperature', 'attrs', 'colorTemp'])
|
|
150
|
+
if (tempAttr) {
|
|
151
|
+
filters.colorTemperature = parseInt(tempAttr)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return Object.keys(filters).length > 0 ? filters : null
|
|
159
|
+
}
|
|
160
|
+
|
|
88
161
|
export async function getBgPicFill(bgPr, sorce, warpObj) {
|
|
89
162
|
const picBase64 = await getPicFill(sorce, bgPr['a:blipFill'], warpObj)
|
|
90
163
|
const aBlipNode = bgPr['a:blipFill']['a:blip']
|
|
@@ -107,7 +180,7 @@ export function getGradientFill(node, warpObj) {
|
|
|
107
180
|
for (let i = 0; i < gsLst.length; i++) {
|
|
108
181
|
const lo_color = getSolidFill(gsLst[i], undefined, undefined, warpObj)
|
|
109
182
|
const pos = getTextByPathList(gsLst[i], ['attrs', 'pos'])
|
|
110
|
-
|
|
183
|
+
|
|
111
184
|
colors[i] = {
|
|
112
185
|
pos: pos ? (pos / 1000 + '%') : '',
|
|
113
186
|
color: lo_color,
|
|
@@ -119,7 +192,7 @@ export function getGradientFill(node, warpObj) {
|
|
|
119
192
|
if (lin) rot = angleToDegrees(lin['attrs']['ang'])
|
|
120
193
|
else {
|
|
121
194
|
const path = node['a:path']
|
|
122
|
-
if (path && path['attrs'] && path['attrs']['path']) pathType = path['attrs']['path']
|
|
195
|
+
if (path && path['attrs'] && path['attrs']['path']) pathType = path['attrs']['path']
|
|
123
196
|
}
|
|
124
197
|
return {
|
|
125
198
|
rot,
|
|
@@ -128,6 +201,35 @@ export function getGradientFill(node, warpObj) {
|
|
|
128
201
|
}
|
|
129
202
|
}
|
|
130
203
|
|
|
204
|
+
export function getPatternFill(node, warpObj) {
|
|
205
|
+
if (!node) return null
|
|
206
|
+
|
|
207
|
+
const pattFill = node['a:pattFill']
|
|
208
|
+
if (!pattFill) return null
|
|
209
|
+
|
|
210
|
+
const type = getTextByPathList(pattFill, ['attrs', 'prst'])
|
|
211
|
+
|
|
212
|
+
const fgColorNode = pattFill['a:fgClr']
|
|
213
|
+
const bgColorNode = pattFill['a:bgClr']
|
|
214
|
+
|
|
215
|
+
let foregroundColor = '#000000'
|
|
216
|
+
let backgroundColor = '#FFFFFF'
|
|
217
|
+
|
|
218
|
+
if (fgColorNode) {
|
|
219
|
+
foregroundColor = getSolidFill(fgColorNode, undefined, undefined, warpObj)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (bgColorNode) {
|
|
223
|
+
backgroundColor = getSolidFill(bgColorNode, undefined, undefined, warpObj)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
type,
|
|
228
|
+
foregroundColor,
|
|
229
|
+
backgroundColor,
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
131
233
|
export function getBgGradientFill(bgPr, phClr, slideMasterContent, warpObj) {
|
|
132
234
|
if (bgPr) {
|
|
133
235
|
const grdFill = bgPr['a:gradFill']
|
|
@@ -204,6 +306,13 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
204
306
|
background = await getBgPicFill(bgPr, 'slideBg', warpObj)
|
|
205
307
|
backgroundType = 'image'
|
|
206
308
|
}
|
|
309
|
+
else if (bgFillTyp === 'PATTERN_FILL') {
|
|
310
|
+
const patternFill = getPatternFill(bgPr, warpObj)
|
|
311
|
+
if (patternFill) {
|
|
312
|
+
background = patternFill
|
|
313
|
+
backgroundType = 'pattern'
|
|
314
|
+
}
|
|
315
|
+
}
|
|
207
316
|
}
|
|
208
317
|
else if (bgRef) {
|
|
209
318
|
let clrMapOvr
|
|
@@ -301,6 +410,13 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
301
410
|
background = await getBgPicFill(bgPr, 'slideLayoutBg', warpObj)
|
|
302
411
|
backgroundType = 'image'
|
|
303
412
|
}
|
|
413
|
+
else if (bgFillTyp === 'PATTERN_FILL') {
|
|
414
|
+
const patternFill = getPatternFill(bgPr, warpObj)
|
|
415
|
+
if (patternFill) {
|
|
416
|
+
background = patternFill
|
|
417
|
+
backgroundType = 'pattern'
|
|
418
|
+
}
|
|
419
|
+
}
|
|
304
420
|
}
|
|
305
421
|
else if (bgRef) {
|
|
306
422
|
const phClr = getSolidFill(bgRef, clrMapOvr, undefined, warpObj)
|
|
@@ -347,7 +463,7 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
347
463
|
const sldFill = bgFillLstIdx['a:solidFill']
|
|
348
464
|
const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
|
|
349
465
|
background = sldBgClr
|
|
350
|
-
}
|
|
466
|
+
}
|
|
351
467
|
else if (bgFillTyp === 'GRADIENT_FILL') {
|
|
352
468
|
const gradientFill = getBgGradientFill(bgFillLstIdx, phClr, slideMasterContent, warpObj)
|
|
353
469
|
if (typeof gradientFill === 'string') {
|
|
@@ -362,6 +478,13 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
362
478
|
background = await getBgPicFill(bgFillLstIdx, 'themeBg', warpObj)
|
|
363
479
|
backgroundType = 'image'
|
|
364
480
|
}
|
|
481
|
+
else if (bgFillTyp === 'PATTERN_FILL') {
|
|
482
|
+
const patternFill = getPatternFill(bgFillLstIdx, warpObj)
|
|
483
|
+
if (patternFill) {
|
|
484
|
+
background = patternFill
|
|
485
|
+
backgroundType = 'pattern'
|
|
486
|
+
}
|
|
487
|
+
}
|
|
365
488
|
}
|
|
366
489
|
}
|
|
367
490
|
else {
|
|
@@ -390,6 +513,13 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
390
513
|
background = await getBgPicFill(bgPr, 'slideMasterBg', warpObj)
|
|
391
514
|
backgroundType = 'image'
|
|
392
515
|
}
|
|
516
|
+
else if (bgFillTyp === 'PATTERN_FILL') {
|
|
517
|
+
const patternFill = getPatternFill(bgPr, warpObj)
|
|
518
|
+
if (patternFill) {
|
|
519
|
+
background = patternFill
|
|
520
|
+
backgroundType = 'pattern'
|
|
521
|
+
}
|
|
522
|
+
}
|
|
393
523
|
}
|
|
394
524
|
else if (bgRef) {
|
|
395
525
|
const phClr = getSolidFill(bgRef, clrMap, undefined, warpObj)
|
|
@@ -436,7 +566,7 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
436
566
|
const sldFill = bgFillLstIdx['a:solidFill']
|
|
437
567
|
const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
|
|
438
568
|
background = sldBgClr
|
|
439
|
-
}
|
|
569
|
+
}
|
|
440
570
|
else if (bgFillTyp === 'GRADIENT_FILL') {
|
|
441
571
|
const gradientFill = getBgGradientFill(bgFillLstIdx, phClr, slideMasterContent, warpObj)
|
|
442
572
|
if (typeof gradientFill === 'string') {
|
|
@@ -451,6 +581,13 @@ export async function getSlideBackgroundFill(warpObj) {
|
|
|
451
581
|
background = await getBgPicFill(bgFillLstIdx, 'themeBg', warpObj)
|
|
452
582
|
backgroundType = 'image'
|
|
453
583
|
}
|
|
584
|
+
else if (bgFillTyp === 'PATTERN_FILL') {
|
|
585
|
+
const patternFill = getPatternFill(bgFillLstIdx, warpObj)
|
|
586
|
+
if (patternFill) {
|
|
587
|
+
background = patternFill
|
|
588
|
+
backgroundType = 'pattern'
|
|
589
|
+
}
|
|
590
|
+
}
|
|
454
591
|
}
|
|
455
592
|
}
|
|
456
593
|
}
|
|
@@ -488,6 +625,11 @@ export async function getShapeFill(node, pNode, isSvgMode, warpObj, source, grou
|
|
|
488
625
|
}
|
|
489
626
|
type = 'image'
|
|
490
627
|
}
|
|
628
|
+
else if (fillType === 'PATTERN_FILL') {
|
|
629
|
+
const shpFill = node['p:spPr']['a:pattFill']
|
|
630
|
+
fillValue = getPatternFill({ 'a:pattFill': shpFill }, warpObj)
|
|
631
|
+
type = 'pattern'
|
|
632
|
+
}
|
|
491
633
|
else if (fillType === 'GROUP_FILL') {
|
|
492
634
|
return findFillInGroupHierarchy(groupHierarchy, warpObj, source)
|
|
493
635
|
}
|
|
@@ -547,6 +689,16 @@ async function findFillInGroupHierarchy(groupHierarchy, warpObj, source) {
|
|
|
547
689
|
}
|
|
548
690
|
}
|
|
549
691
|
}
|
|
692
|
+
else if (fillType === 'PATTERN_FILL') {
|
|
693
|
+
const shpFill = grpSpPr['a:pattFill']
|
|
694
|
+
const fillValue = getPatternFill({ 'a:pattFill': shpFill }, warpObj)
|
|
695
|
+
if (fillValue) {
|
|
696
|
+
return {
|
|
697
|
+
type: 'pattern',
|
|
698
|
+
value: fillValue,
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
550
702
|
}
|
|
551
703
|
|
|
552
704
|
return null
|
package/src/fontStyle.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getTextByPathList } from './utils'
|
|
2
2
|
import { getShadow } from './shadow'
|
|
3
|
-
import { getFillType, getSolidFill } from './fill'
|
|
3
|
+
import { getFillType, getGradientFill, getSolidFill } from './fill'
|
|
4
4
|
|
|
5
5
|
export function getFontType(node, type, warpObj) {
|
|
6
6
|
let typeface = getTextByPathList(node, ['a:rPr', 'a:latin', 'attrs', 'typeface'])
|
|
@@ -31,6 +31,11 @@ export function getFontColor(node, pNode, lstStyle, pFontStyle, lvl, warpObj) {
|
|
|
31
31
|
const solidFillNode = rPrNode['a:solidFill']
|
|
32
32
|
color = getSolidFill(solidFillNode, undefined, undefined, warpObj)
|
|
33
33
|
}
|
|
34
|
+
if (filTyp === 'GRADIENT_FILL') {
|
|
35
|
+
const gradientFillNode = rPrNode['a:gradFill']
|
|
36
|
+
const gradient = getGradientFill(gradientFillNode, warpObj)
|
|
37
|
+
return gradient
|
|
38
|
+
}
|
|
34
39
|
}
|
|
35
40
|
if (!color && getTextByPathList(lstStyle, ['a:lvl' + lvl + 'pPr', 'a:defRPr'])) {
|
|
36
41
|
const lstStyledefRPr = getTextByPathList(lstStyle, ['a:lvl' + lvl + 'pPr', 'a:defRPr'])
|
|
@@ -48,14 +53,49 @@ export function getFontColor(node, pNode, lstStyle, pFontStyle, lvl, warpObj) {
|
|
|
48
53
|
return color || ''
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
export function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles) {
|
|
56
|
+
export function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles, textBodyNode, pNode) {
|
|
52
57
|
let fontSize
|
|
53
58
|
|
|
54
59
|
if (getTextByPathList(node, ['a:rPr', 'attrs', 'sz'])) fontSize = getTextByPathList(node, ['a:rPr', 'attrs', 'sz']) / 100
|
|
55
60
|
|
|
61
|
+
if ((isNaN(fontSize) || !fontSize) && pNode) {
|
|
62
|
+
if (getTextByPathList(pNode, ['a:endParaRPr', 'attrs', 'sz'])) {
|
|
63
|
+
fontSize = getTextByPathList(pNode, ['a:endParaRPr', 'attrs', 'sz']) / 100
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if ((isNaN(fontSize) || !fontSize) && textBodyNode) {
|
|
68
|
+
const lstStyle = getTextByPathList(textBodyNode, ['a:lstStyle'])
|
|
69
|
+
if (lstStyle) {
|
|
70
|
+
let lvl = 1
|
|
71
|
+
if (pNode) {
|
|
72
|
+
const lvlNode = getTextByPathList(pNode, ['a:pPr', 'attrs', 'lvl'])
|
|
73
|
+
if (lvlNode !== undefined) lvl = parseInt(lvlNode) + 1
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const sz = getTextByPathList(lstStyle, [`a:lvl${lvl}pPr`, 'a:defRPr', 'attrs', 'sz'])
|
|
77
|
+
if (sz) fontSize = parseInt(sz) / 100
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
56
81
|
if ((isNaN(fontSize) || !fontSize)) {
|
|
57
82
|
const sz = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:lstStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
58
|
-
fontSize = parseInt(sz) / 100
|
|
83
|
+
if (sz) fontSize = parseInt(sz) / 100
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ((isNaN(fontSize) || !fontSize) && slideLayoutSpNode) {
|
|
87
|
+
let lvl = 1
|
|
88
|
+
if (pNode) {
|
|
89
|
+
const lvlNode = getTextByPathList(pNode, ['a:pPr', 'attrs', 'lvl'])
|
|
90
|
+
if (lvlNode !== undefined) lvl = parseInt(lvlNode) + 1
|
|
91
|
+
}
|
|
92
|
+
const layoutSz = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:lstStyle', `a:lvl${lvl}pPr`, 'a:defRPr', 'attrs', 'sz'])
|
|
93
|
+
if (layoutSz) fontSize = parseInt(layoutSz) / 100
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if ((isNaN(fontSize) || !fontSize) && pNode) {
|
|
97
|
+
const paraSz = getTextByPathList(pNode, ['a:pPr', 'a:defRPr', 'attrs', 'sz'])
|
|
98
|
+
if (paraSz) fontSize = parseInt(paraSz) / 100
|
|
59
99
|
}
|
|
60
100
|
|
|
61
101
|
if (isNaN(fontSize) || !fontSize) {
|
package/src/position.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RATIO_EMUs_Points } from './constants'
|
|
2
|
+
import { numberToFixed } from './utils'
|
|
2
3
|
|
|
3
4
|
export function getPosition(slideSpNode, slideLayoutSpNode, slideMasterSpNode) {
|
|
4
5
|
let off
|
|
@@ -10,8 +11,8 @@ export function getPosition(slideSpNode, slideLayoutSpNode, slideMasterSpNode) {
|
|
|
10
11
|
if (!off) return { top: 0, left: 0 }
|
|
11
12
|
|
|
12
13
|
return {
|
|
13
|
-
top: parseInt(off['y']) * RATIO_EMUs_Points,
|
|
14
|
-
left: parseInt(off['x']) * RATIO_EMUs_Points,
|
|
14
|
+
top: numberToFixed(parseInt(off['y']) * RATIO_EMUs_Points),
|
|
15
|
+
left: numberToFixed(parseInt(off['x']) * RATIO_EMUs_Points),
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -25,7 +26,7 @@ export function getSize(slideSpNode, slideLayoutSpNode, slideMasterSpNode) {
|
|
|
25
26
|
if (!ext) return { width: 0, height: 0 }
|
|
26
27
|
|
|
27
28
|
return {
|
|
28
|
-
width: parseInt(ext['cx']) * RATIO_EMUs_Points,
|
|
29
|
-
height: parseInt(ext['cy']) * RATIO_EMUs_Points,
|
|
29
|
+
width: numberToFixed(parseInt(ext['cx']) * RATIO_EMUs_Points),
|
|
30
|
+
height: numberToFixed(parseInt(ext['cy']) * RATIO_EMUs_Points),
|
|
30
31
|
}
|
|
31
32
|
}
|
package/src/pptxtojson.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import JSZip from 'jszip'
|
|
2
2
|
import { readXmlFile } from './readXmlFile'
|
|
3
3
|
import { getBorder } from './border'
|
|
4
|
-
import { getSlideBackgroundFill, getShapeFill, getSolidFill, getPicFill } from './fill'
|
|
4
|
+
import { getSlideBackgroundFill, getShapeFill, getSolidFill, getPicFill, getPicFilters } from './fill'
|
|
5
5
|
import { getChartInfo } from './chart'
|
|
6
6
|
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, hasValidText } from './utils'
|
|
10
|
+
import { extractFileExtension, base64ArrayBuffer, getTextByPathList, angleToDegrees, getMimeType, isVideoLink, escapeHtml, hasValidText, numberToFixed } from './utils'
|
|
11
11
|
import { getShadow } from './shadow'
|
|
12
12
|
import { getTableBorders, getTableCellParams, getTableRowParams } from './table'
|
|
13
13
|
import { RATIO_EMUs_Points } from './constants'
|
|
@@ -135,9 +135,17 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
135
135
|
switch (relationshipArrayItem['attrs']['Type']) {
|
|
136
136
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout':
|
|
137
137
|
layoutFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
138
|
+
slideResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
139
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
140
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
141
|
+
}
|
|
138
142
|
break
|
|
139
143
|
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide':
|
|
140
144
|
noteFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
145
|
+
slideResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
146
|
+
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
147
|
+
target: relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
148
|
+
}
|
|
141
149
|
break
|
|
142
150
|
case 'http://schemas.microsoft.com/office/2007/relationships/diagramDrawing':
|
|
143
151
|
diagramFilename = relationshipArrayItem['attrs']['Target'].replace('../', 'ppt/')
|
|
@@ -508,20 +516,20 @@ async function processGroupSpNode(node, warpObj, source, parentGroupHierarchy =
|
|
|
508
516
|
|
|
509
517
|
return {
|
|
510
518
|
type: 'group',
|
|
511
|
-
top: y,
|
|
512
|
-
left: x,
|
|
513
|
-
width: cx,
|
|
514
|
-
height: cy,
|
|
519
|
+
top: numberToFixed(y),
|
|
520
|
+
left: numberToFixed(x),
|
|
521
|
+
width: numberToFixed(cx),
|
|
522
|
+
height: numberToFixed(cy),
|
|
515
523
|
rotate,
|
|
516
524
|
order,
|
|
517
525
|
isFlipV,
|
|
518
526
|
isFlipH,
|
|
519
527
|
elements: elements.map(element => ({
|
|
520
528
|
...element,
|
|
521
|
-
left: (element.left - chx) * ws,
|
|
522
|
-
top: (element.top - chy) * hs,
|
|
523
|
-
width: element.width * ws,
|
|
524
|
-
height: element.height * hs,
|
|
529
|
+
left: numberToFixed((element.left - chx) * ws),
|
|
530
|
+
top: numberToFixed((element.top - chy) * hs),
|
|
531
|
+
width: numberToFixed(element.width * ws),
|
|
532
|
+
height: numberToFixed(element.height * hs),
|
|
525
533
|
}))
|
|
526
534
|
}
|
|
527
535
|
}
|
|
@@ -794,11 +802,13 @@ async function processPicNode(node, warpObj, source) {
|
|
|
794
802
|
|
|
795
803
|
const { borderColor, borderWidth, borderType, strokeDasharray } = getBorder(node, undefined, warpObj)
|
|
796
804
|
|
|
797
|
-
|
|
805
|
+
const filters = getPicFilters(node['p:blipFill'])
|
|
806
|
+
|
|
807
|
+
const imageData = {
|
|
798
808
|
type: 'image',
|
|
799
809
|
top,
|
|
800
810
|
left,
|
|
801
|
-
width,
|
|
811
|
+
width,
|
|
802
812
|
height,
|
|
803
813
|
rotate,
|
|
804
814
|
src,
|
|
@@ -812,6 +822,10 @@ async function processPicNode(node, warpObj, source) {
|
|
|
812
822
|
borderType,
|
|
813
823
|
borderStrokeDasharray: strokeDasharray,
|
|
814
824
|
}
|
|
825
|
+
|
|
826
|
+
if (filters) imageData.filters = filters
|
|
827
|
+
|
|
828
|
+
return imageData
|
|
815
829
|
}
|
|
816
830
|
|
|
817
831
|
async function processGraphicFrameNode(node, warpObj, source) {
|
package/src/text.js
CHANGED
|
@@ -73,10 +73,39 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, type, warpO
|
|
|
73
73
|
text += `<p style="text-align: ${align};">`
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
if (!rNode)
|
|
76
|
+
if (!rNode) {
|
|
77
|
+
text += genSpanElement(pNode, spNode, textBodyNode, pFontStyle, slideLayoutSpNode, type, warpObj)
|
|
78
|
+
}
|
|
77
79
|
else {
|
|
80
|
+
let prevStyleInfo = null
|
|
81
|
+
let accumulatedText = ''
|
|
82
|
+
|
|
78
83
|
for (const rNodeItem of rNode) {
|
|
79
|
-
|
|
84
|
+
const styleInfo = getSpanStyleInfo(rNodeItem, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, type, warpObj)
|
|
85
|
+
|
|
86
|
+
if (!prevStyleInfo || prevStyleInfo.styleText !== styleInfo.styleText || prevStyleInfo.hasLink !== styleInfo.hasLink || styleInfo.hasLink) {
|
|
87
|
+
if (accumulatedText) {
|
|
88
|
+
const processedText = accumulatedText.replace(/\t/g, ' ').replace(/\s/g, ' ')
|
|
89
|
+
text += `<span style="${prevStyleInfo.styleText}">${processedText}</span>`
|
|
90
|
+
accumulatedText = ''
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (styleInfo.hasLink) {
|
|
94
|
+
const processedText = styleInfo.text.replace(/\t/g, ' ').replace(/\s/g, ' ')
|
|
95
|
+
text += `<span style="${styleInfo.styleText}"><a href="${styleInfo.linkURL}" target="_blank">${processedText}</a></span>`
|
|
96
|
+
prevStyleInfo = null
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
prevStyleInfo = styleInfo
|
|
100
|
+
accumulatedText = styleInfo.text
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else accumulatedText += styleInfo.text
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (accumulatedText && prevStyleInfo) {
|
|
107
|
+
const processedText = accumulatedText.replace(/\t/g, ' ').replace(/\s/g, ' ')
|
|
108
|
+
text += `<span style="${prevStyleInfo.styleText}">${processedText}</span>`
|
|
80
109
|
}
|
|
81
110
|
}
|
|
82
111
|
|
|
@@ -97,6 +126,16 @@ export function getListType(node) {
|
|
|
97
126
|
}
|
|
98
127
|
|
|
99
128
|
export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, type, warpObj) {
|
|
129
|
+
const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, type, warpObj)
|
|
130
|
+
const processedText = text.replace(/\t/g, ' ').replace(/\s/g, ' ')
|
|
131
|
+
|
|
132
|
+
if (hasLink) {
|
|
133
|
+
return `<span style="${styleText}"><a href="${linkURL}" target="_blank">${processedText}</a></span>`
|
|
134
|
+
}
|
|
135
|
+
return `<span style="${styleText}">${processedText}</span>`
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, type, warpObj) {
|
|
100
139
|
const lstStyle = textBodyNode['a:lstStyle']
|
|
101
140
|
const slideMasterTextStyles = warpObj['slideMasterTextStyles']
|
|
102
141
|
|
|
@@ -111,7 +150,7 @@ export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayou
|
|
|
111
150
|
|
|
112
151
|
let styleText = ''
|
|
113
152
|
const fontColor = getFontColor(node, pNode, lstStyle, pFontStyle, lvl, warpObj)
|
|
114
|
-
const fontSize = getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles)
|
|
153
|
+
const fontSize = getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles, textBodyNode, pNode)
|
|
115
154
|
const fontType = getFontType(node, type, warpObj)
|
|
116
155
|
const fontBold = getFontBold(node)
|
|
117
156
|
const fontItalic = getFontItalic(node)
|
|
@@ -121,7 +160,15 @@ export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayou
|
|
|
121
160
|
const shadow = getFontShadow(node, warpObj)
|
|
122
161
|
const subscript = getFontSubscript(node)
|
|
123
162
|
|
|
124
|
-
if (fontColor)
|
|
163
|
+
if (fontColor) {
|
|
164
|
+
if (typeof fontColor === 'string') styleText += `color: ${fontColor};`
|
|
165
|
+
else if (fontColor.colors) {
|
|
166
|
+
const { colors, rot } = fontColor
|
|
167
|
+
const stops = colors.map(item => `${item.color} ${item.pos}`).join(', ')
|
|
168
|
+
const gradientStyle = `linear-gradient(${rot + 90}deg, ${stops})`
|
|
169
|
+
styleText += `background: ${gradientStyle}; background-clip: text; color: transparent;`
|
|
170
|
+
}
|
|
171
|
+
}
|
|
125
172
|
if (fontSize) styleText += `font-size: ${fontSize};`
|
|
126
173
|
if (fontType) styleText += `font-family: ${fontType};`
|
|
127
174
|
if (fontBold) styleText += `font-weight: ${fontBold};`
|
|
@@ -133,9 +180,12 @@ export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayou
|
|
|
133
180
|
if (shadow) styleText += `text-shadow: ${shadow};`
|
|
134
181
|
|
|
135
182
|
const linkID = getTextByPathList(node, ['a:rPr', 'a:hlinkClick', 'attrs', 'r:id'])
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
183
|
+
const hasLink = linkID && warpObj['slideResObj'][linkID]
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
styleText,
|
|
187
|
+
text,
|
|
188
|
+
hasLink,
|
|
189
|
+
linkURL: hasLink ? warpObj['slideResObj'][linkID]['target'] : null
|
|
190
|
+
}
|
|
141
191
|
}
|
package/src/utils.js
CHANGED
|
@@ -160,4 +160,8 @@ export function hasValidText(htmlString) {
|
|
|
160
160
|
const doc = parser.parseFromString(htmlString, 'text/html')
|
|
161
161
|
const text = doc.body.textContent || doc.body.innerText
|
|
162
162
|
return text.trim() !== ''
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function numberToFixed(num, fractionDigits = 4) {
|
|
166
|
+
return parseFloat(num.toFixed(fractionDigits))
|
|
163
167
|
}
|