pptxtojson 0.0.12 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/fill.js ADDED
@@ -0,0 +1,330 @@
1
+ import tinycolor from 'tinycolor2'
2
+ import { getSchemeColorFromTheme } from './schemeColor'
3
+ import {
4
+ applyShade,
5
+ applyTint,
6
+ applyLumOff,
7
+ applyLumMod,
8
+ applyHueMod,
9
+ applySatMod,
10
+ hslToRgb,
11
+ } from './color'
12
+
13
+ import {
14
+ base64ArrayBuffer,
15
+ getTextByPathList,
16
+ angleToDegrees,
17
+ escapeHtml,
18
+ getMimeType,
19
+ toHex,
20
+ } from './utils'
21
+
22
+ export function getFillType(node) {
23
+ let fillType = ''
24
+ if (node['a:noFill']) fillType = 'NO_FILL'
25
+ if (node['a:solidFill']) fillType = 'SOLID_FILL'
26
+ if (node['a:gradFill']) fillType = 'GRADIENT_FILL'
27
+ if (node['a:pattFill']) fillType = 'PATTERN_FILL'
28
+ if (node['a:blipFill']) fillType = 'PIC_FILL'
29
+ if (node['a:grpFill']) fillType = 'GROUP_FILL'
30
+
31
+ return fillType
32
+ }
33
+
34
+ export async function getPicFill(type, node, warpObj) {
35
+ let img
36
+ const rId = node['a:blip']['attrs']['r:embed']
37
+ let imgPath
38
+ if (type === 'slideBg' || type === 'slide') {
39
+ imgPath = getTextByPathList(warpObj, ['slideResObj', rId, 'target'])
40
+ }
41
+ else if (type === 'slideLayoutBg') {
42
+ imgPath = getTextByPathList(warpObj, ['layoutResObj', rId, 'target'])
43
+ }
44
+ else if (type === 'slideMasterBg') {
45
+ imgPath = getTextByPathList(warpObj, ['masterResObj', rId, 'target'])
46
+ }
47
+ else if (type === 'themeBg') {
48
+ imgPath = getTextByPathList(warpObj, ['themeResObj', rId, 'target'])
49
+ }
50
+ if (!imgPath) return imgPath
51
+
52
+ img = getTextByPathList(warpObj, ['loaded-images', imgPath])
53
+ if (!img) {
54
+ imgPath = escapeHtml(imgPath)
55
+
56
+ const imgExt = imgPath.split('.').pop()
57
+ if (imgExt === 'xml') return undefined
58
+
59
+ const imgArrayBuffer = await warpObj['zip'].file(imgPath).async('arraybuffer')
60
+ const imgMimeType = getMimeType(imgExt)
61
+ img = `data:${imgMimeType};base64,${base64ArrayBuffer(imgArrayBuffer)}`
62
+ }
63
+ return img
64
+ }
65
+
66
+ export async function getBgPicFill(bgPr, sorce, warpObj) {
67
+ const picBase64 = await getPicFill(sorce, bgPr['a:blipFill'], warpObj)
68
+ const aBlipNode = bgPr['a:blipFill']['a:blip']
69
+
70
+ const aphaModFixNode = getTextByPathList(aBlipNode, ['a:alphaModFix', 'attrs'])
71
+ let opacity = 1
72
+ if (aphaModFixNode && aphaModFixNode['amt'] && aphaModFixNode['amt'] !== '') {
73
+ opacity = parseInt(aphaModFixNode['amt']) / 100000
74
+ }
75
+
76
+ return {
77
+ picBase64,
78
+ opacity,
79
+ }
80
+ }
81
+
82
+ export function getBgGradientFill(bgPr, phClr, slideMasterContent, warpObj) {
83
+ if (bgPr) {
84
+ const grdFill = bgPr['a:gradFill']
85
+ const gsLst = grdFill['a:gsLst']['a:gs']
86
+ const color_ary = []
87
+
88
+ for (let i = 0; i < gsLst.length; i++) {
89
+ const lo_color = getSolidFill(gsLst[i], slideMasterContent['p:sldMaster']['p:clrMap']['attrs'], phClr, warpObj)
90
+ const pos = getTextByPathList(gsLst[i], ['attrs', 'pos'])
91
+
92
+ color_ary[i] = {
93
+ pos: pos ? (pos / 1000 + '%') : '',
94
+ color: `#${lo_color}`,
95
+ }
96
+ }
97
+ const lin = grdFill['a:lin']
98
+ let rot = 90
99
+ if (lin) {
100
+ rot = angleToDegrees(lin['attrs']['ang'])
101
+ rot = rot + 90
102
+ }
103
+
104
+ return {
105
+ rot,
106
+ colors: color_ary.sort((a, b) => parseInt(a.pos) - parseInt(b.pos)),
107
+ }
108
+ }
109
+ else if (phClr) return `#${phClr}`
110
+ return null
111
+ }
112
+
113
+ export async function getSlideBackgroundFill(warpObj) {
114
+ const slideContent = warpObj['slideContent']
115
+ const slideLayoutContent = warpObj['slideLayoutContent']
116
+ const slideMasterContent = warpObj['slideMasterContent']
117
+
118
+ let bgPr = getTextByPathList(slideContent, ['p:sld', 'p:cSld', 'p:bg', 'p:bgPr'])
119
+
120
+ let background = '#fff'
121
+ let backgroundType = 'color'
122
+
123
+ if (bgPr) {
124
+ const bgFillTyp = getFillType(bgPr)
125
+
126
+ if (bgFillTyp === 'SOLID_FILL') {
127
+ const sldFill = bgPr['a:solidFill']
128
+ let clrMapOvr
129
+ const sldClrMapOvr = getTextByPathList(slideContent, ['p:sld', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
130
+ if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
131
+ else {
132
+ const sldClrMapOvr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
133
+ if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
134
+ else clrMapOvr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
135
+ }
136
+ const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
137
+ background = `#${sldBgClr}`
138
+ }
139
+ else if (bgFillTyp === 'GRADIENT_FILL') {
140
+ const gradientFill = getBgGradientFill(bgPr, undefined, slideMasterContent, warpObj)
141
+ if (typeof gradientFill === 'string') {
142
+ background = gradientFill
143
+ }
144
+ else if (gradientFill) {
145
+ background = gradientFill
146
+ backgroundType = 'gradient'
147
+ }
148
+ }
149
+ else if (bgFillTyp === 'PIC_FILL') {
150
+ background = await getBgPicFill(bgPr, 'slideBg', warpObj)
151
+ backgroundType = 'image'
152
+ }
153
+ }
154
+ else {
155
+ bgPr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:cSld', 'p:bg', 'p:bgPr'])
156
+
157
+ let clrMapOvr
158
+ const sldClrMapOvr = getTextByPathList(slideLayoutContent, ['p:sldLayout', 'p:clrMapOvr', 'a:overrideClrMapping', 'attrs'])
159
+ if (sldClrMapOvr) clrMapOvr = sldClrMapOvr
160
+ else clrMapOvr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
161
+
162
+ if (bgPr) {
163
+ const bgFillTyp = getFillType(bgPr)
164
+ if (bgFillTyp === 'SOLID_FILL') {
165
+ const sldFill = bgPr['a:solidFill']
166
+ const sldBgClr = getSolidFill(sldFill, clrMapOvr, undefined, warpObj)
167
+ background = `#${sldBgClr}`
168
+ }
169
+ else if (bgFillTyp === 'GRADIENT_FILL') {
170
+ const gradientFill = getBgGradientFill(bgPr, undefined, slideMasterContent, warpObj)
171
+ if (typeof gradientFill === 'string') {
172
+ background = gradientFill
173
+ }
174
+ else if (gradientFill) {
175
+ background = gradientFill
176
+ backgroundType = 'gradient'
177
+ }
178
+ }
179
+ else if (bgFillTyp === 'PIC_FILL') {
180
+ background = await getBgPicFill(bgPr, 'slideLayoutBg', warpObj)
181
+ backgroundType = 'image'
182
+ }
183
+ }
184
+ else {
185
+ bgPr = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:cSld', 'p:bg', 'p:bgPr'])
186
+
187
+ const clrMap = getTextByPathList(slideMasterContent, ['p:sldMaster', 'p:clrMap', 'attrs'])
188
+ if (bgPr) {
189
+ const bgFillTyp = getFillType(bgPr)
190
+ if (bgFillTyp === 'SOLID_FILL') {
191
+ const sldFill = bgPr['a:solidFill']
192
+ const sldBgClr = getSolidFill(sldFill, clrMap, undefined, warpObj)
193
+ background = `#${sldBgClr}`
194
+ }
195
+ else if (bgFillTyp === 'GRADIENT_FILL') {
196
+ const gradientFill = getBgGradientFill(bgPr, undefined, slideMasterContent, warpObj)
197
+ if (typeof gradientFill === 'string') {
198
+ background = gradientFill
199
+ }
200
+ else if (gradientFill) {
201
+ background = gradientFill
202
+ backgroundType = 'gradient'
203
+ }
204
+ }
205
+ else if (bgFillTyp === 'PIC_FILL') {
206
+ background = await getBgPicFill(bgPr, 'slideMasterBg', warpObj)
207
+ backgroundType = 'image'
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return {
213
+ type: backgroundType,
214
+ value: background,
215
+ }
216
+ }
217
+
218
+ export function getShapeFill(node, isSvgMode, warpObj) {
219
+ if (getTextByPathList(node, ['p:spPr', 'a:noFill'])) {
220
+ return isSvgMode ? 'none' : ''
221
+ }
222
+
223
+ let fillColor
224
+ if (!fillColor) {
225
+ fillColor = getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:srgbClr', 'attrs', 'val'])
226
+ }
227
+
228
+ if (!fillColor) {
229
+ const schemeClr = 'a:' + getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'attrs', 'val'])
230
+ fillColor = getSchemeColorFromTheme(schemeClr, warpObj)
231
+ }
232
+
233
+ if (!fillColor) {
234
+ const schemeClr = 'a:' + getTextByPathList(node, ['p:style', 'a:fillRef', 'a:schemeClr', 'attrs', 'val'])
235
+ fillColor = getSchemeColorFromTheme(schemeClr, warpObj)
236
+ }
237
+
238
+ if (fillColor) {
239
+ fillColor = `#${fillColor}`
240
+
241
+ let lumMod = parseInt(getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'a:lumMod', 'attrs', 'val'])) / 100000
242
+ let lumOff = parseInt(getTextByPathList(node, ['p:spPr', 'a:solidFill', 'a:schemeClr', 'a:lumOff', 'attrs', 'val'])) / 100000
243
+ if (isNaN(lumMod)) lumMod = 1.0
244
+ if (isNaN(lumOff)) lumOff = 0
245
+
246
+ const color = tinycolor(fillColor).toHsl()
247
+ const lum = color.l * (1 + lumOff)
248
+ return tinycolor({ h: color.h, s: color.s, l: lum, a: color.a }).toHexString()
249
+ }
250
+
251
+ if (isSvgMode) return 'none'
252
+ return fillColor
253
+ }
254
+
255
+ export function getSolidFill(solidFill, clrMap, phClr, warpObj) {
256
+ if (!solidFill) return solidFill
257
+
258
+ let color = 'fff'
259
+ let clrNode
260
+
261
+ if (solidFill['a:srgbClr']) {
262
+ color = getTextByPathList(solidFill['a:srgbClr'], ['attrs', 'val'])
263
+ }
264
+ else if (solidFill['a:schemeClr']) {
265
+ const schemeClr = 'a:' + getTextByPathList(solidFill['a:schemeClr'], ['attrs', 'val'])
266
+ color = getSchemeColorFromTheme(schemeClr, warpObj)
267
+ }
268
+ else if (solidFill['a:scrgbClr']) {
269
+ clrNode = solidFill['a:scrgbClr']
270
+ const defBultColorVals = clrNode['attrs']
271
+ const red = (defBultColorVals['r'].indexOf('%') !== -1) ? defBultColorVals['r'].split('%').shift() : defBultColorVals['r']
272
+ const green = (defBultColorVals['g'].indexOf('%') !== -1) ? defBultColorVals['g'].split('%').shift() : defBultColorVals['g']
273
+ const blue = (defBultColorVals['b'].indexOf('%') !== -1) ? defBultColorVals['b'].split('%').shift() : defBultColorVals['b']
274
+ color = toHex(255 * (Number(red) / 100)) + toHex(255 * (Number(green) / 100)) + toHex(255 * (Number(blue) / 100))
275
+ }
276
+ else if (solidFill['a:prstClr']) {
277
+ clrNode = solidFill['a:prstClr']
278
+ color = getTextByPathList(clrNode, ['attrs', 'val'])
279
+ }
280
+ else if (solidFill['a:hslClr']) {
281
+ clrNode = solidFill['a:hslClr']
282
+ const defBultColorVals = clrNode['attrs']
283
+ const hue = Number(defBultColorVals['hue']) / 100000
284
+ const sat = Number((defBultColorVals['sat'].indexOf('%') !== -1) ? defBultColorVals['sat'].split('%').shift() : defBultColorVals['sat']) / 100
285
+ const lum = Number((defBultColorVals['lum'].indexOf('%') !== -1) ? defBultColorVals['lum'].split('%').shift() : defBultColorVals['lum']) / 100
286
+ const hsl2rgb = hslToRgb(hue, sat, lum)
287
+ color = toHex(hsl2rgb.r) + toHex(hsl2rgb.g) + toHex(hsl2rgb.b)
288
+ }
289
+ else if (solidFill['a:sysClr']) {
290
+ clrNode = solidFill['a:sysClr']
291
+ const sysClr = getTextByPathList(clrNode, ['attrs', 'lastClr'])
292
+ if (sysClr) color = sysClr
293
+ }
294
+
295
+ let isAlpha = false
296
+ const alpha = parseInt(getTextByPathList(clrNode, ['a:alpha', 'attrs', 'val'])) / 100000
297
+ if (!isNaN(alpha)) {
298
+ const al_color = tinycolor(color)
299
+ al_color.setAlpha(alpha)
300
+ color = al_color.toHex8()
301
+ isAlpha = true
302
+ }
303
+
304
+ const hueMod = parseInt(getTextByPathList(clrNode, ['a:hueMod', 'attrs', 'val'])) / 100000
305
+ if (!isNaN(hueMod)) {
306
+ color = applyHueMod(color, hueMod, isAlpha)
307
+ }
308
+ const lumMod = parseInt(getTextByPathList(clrNode, ['a:lumMod', 'attrs', 'val'])) / 100000
309
+ if (!isNaN(lumMod)) {
310
+ color = applyLumMod(color, lumMod, isAlpha)
311
+ }
312
+ const lumOff = parseInt(getTextByPathList(clrNode, ['a:lumOff', 'attrs', 'val'])) / 100000
313
+ if (!isNaN(lumOff)) {
314
+ color = applyLumOff(color, lumOff, isAlpha)
315
+ }
316
+ const satMod = parseInt(getTextByPathList(clrNode, ['a:satMod', 'attrs', 'val'])) / 100000
317
+ if (!isNaN(satMod)) {
318
+ color = applySatMod(color, satMod, isAlpha)
319
+ }
320
+ const shade = parseInt(getTextByPathList(clrNode, ['a:shade', 'attrs', 'val'])) / 100000
321
+ if (!isNaN(shade)) {
322
+ color = applyShade(color, shade, isAlpha)
323
+ }
324
+ const tint = parseInt(getTextByPathList(clrNode, ['a:tint', 'attrs', 'val'])) / 100000
325
+ if (!isNaN(tint)) {
326
+ color = applyTint(color, tint, isAlpha)
327
+ }
328
+
329
+ return color
330
+ }
@@ -0,0 +1,105 @@
1
+ import { getTextByPathList } from './utils'
2
+ import { getShadow } from './shadow'
3
+
4
+ export function getFontType(node, type, warpObj) {
5
+ let typeface = getTextByPathList(node, ['a:rPr', 'a:latin', 'attrs', 'typeface'])
6
+
7
+ if (!typeface) {
8
+ const fontSchemeNode = getTextByPathList(warpObj['themeContent'], ['a:theme', 'a:themeElements', 'a:fontScheme'])
9
+
10
+ if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') {
11
+ typeface = getTextByPathList(fontSchemeNode, ['a:majorFont', 'a:latin', 'attrs', 'typeface'])
12
+ }
13
+ else if (type === 'body') {
14
+ typeface = getTextByPathList(fontSchemeNode, ['a:minorFont', 'a:latin', 'attrs', 'typeface'])
15
+ }
16
+ else {
17
+ typeface = getTextByPathList(fontSchemeNode, ['a:minorFont', 'a:latin', 'attrs', 'typeface'])
18
+ }
19
+ }
20
+
21
+ return typeface || ''
22
+ }
23
+
24
+ export function getFontColor(node) {
25
+ const color = getTextByPathList(node, ['a:rPr', 'a:solidFill', 'a:srgbClr', 'attrs', 'val'])
26
+ return color ? `#${color}` : ''
27
+ }
28
+
29
+ export function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles, fontsizeFactor) {
30
+ let fontSize
31
+
32
+ if (node['a:rPr']) fontSize = parseInt(node['a:rPr']['attrs']['sz']) / 100
33
+
34
+ if ((isNaN(fontSize) || !fontSize)) {
35
+ const sz = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:lstStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
36
+ fontSize = parseInt(sz) / 100
37
+ }
38
+
39
+ if (isNaN(fontSize) || !fontSize) {
40
+ let sz
41
+ if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') {
42
+ sz = getTextByPathList(slideMasterTextStyles, ['p:titleStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
43
+ }
44
+ else if (type === 'body') {
45
+ sz = getTextByPathList(slideMasterTextStyles, ['p:bodyStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
46
+ }
47
+ else if (type === 'dt' || type === 'sldNum') {
48
+ sz = '1200'
49
+ }
50
+ else if (!type) {
51
+ sz = getTextByPathList(slideMasterTextStyles, ['p:otherStyle', 'a:lvl1pPr', 'a:defRPr', 'attrs', 'sz'])
52
+ }
53
+ if (sz) fontSize = parseInt(sz) / 100
54
+ }
55
+
56
+ const baseline = getTextByPathList(node, ['a:rPr', 'attrs', 'baseline'])
57
+ if (baseline && !isNaN(fontSize)) fontSize -= 10
58
+
59
+ fontSize = (isNaN(fontSize) || !fontSize) ? 18 : fontSize
60
+
61
+ return fontSize * fontsizeFactor + 'px'
62
+ }
63
+
64
+ export function getFontBold(node) {
65
+ return getTextByPathList(node, ['a:rPr', 'attrs', 'b']) === '1' ? 'bold' : ''
66
+ }
67
+
68
+ export function getFontItalic(node) {
69
+ return getTextByPathList(node, ['a:rPr', 'attrs', 'i']) === '1' ? 'italic' : ''
70
+ }
71
+
72
+ export function getFontDecoration(node) {
73
+ const underline = getTextByPathList(node, ['a:rPr', 'attrs', 'u']) === 'sng' ? 'underline' : ''
74
+ const strike = getTextByPathList(node, ['a:rPr', 'attrs', 'strike']) === 'sngStrike' ? 'line-through' : ''
75
+
76
+ if (!underline && !strike) return ''
77
+ else if (underline && !strike) return underline
78
+ else if (!underline && strike) return strike
79
+ return `${underline} ${strike}`
80
+ }
81
+
82
+ export function getFontSpace(node, fontsizeFactor) {
83
+ const spc = getTextByPathList(node, ['a:rPr', 'attrs', 'spc'])
84
+ return spc ? (parseInt(spc) / 100 * fontsizeFactor + 'px') : ''
85
+ }
86
+
87
+ export function getFontSubscript(node) {
88
+ const baseline = getTextByPathList(node, ['a:rPr', 'attrs', 'baseline'])
89
+ if (!baseline) return ''
90
+ return parseInt(baseline) > 0 ? 'super' : 'sub'
91
+ }
92
+
93
+ export function getFontShadow(node, warpObj, slideFactor) {
94
+ const txtShadow = getTextByPathList(node, ['a:rPr', 'a:effectLst', 'a:outerShdw'])
95
+ if (txtShadow) {
96
+ const shadow = getShadow(txtShadow, warpObj, slideFactor)
97
+ if (shadow) {
98
+ const { h, v, blur, color } = shadow
99
+ if (!isNaN(v) && !isNaN(h)) {
100
+ return h + 'px ' + v + 'px ' + (blur ? blur + 'px' : '') + ' ' + color
101
+ }
102
+ }
103
+ }
104
+ return ''
105
+ }
@@ -0,0 +1,29 @@
1
+ export function getPosition(slideSpNode, slideLayoutSpNode, slideMasterSpNode, factor) {
2
+ let off
3
+
4
+ if (slideSpNode) off = slideSpNode['a:off']['attrs']
5
+ else if (slideLayoutSpNode) off = slideLayoutSpNode['a:off']['attrs']
6
+ else if (slideMasterSpNode) off = slideMasterSpNode['a:off']['attrs']
7
+
8
+ if (!off) return { top: 0, left: 0 }
9
+
10
+ return {
11
+ top: parseInt(off['y']) * factor,
12
+ left: parseInt(off['x']) * factor,
13
+ }
14
+ }
15
+
16
+ export function getSize(slideSpNode, slideLayoutSpNode, slideMasterSpNode, factor) {
17
+ let ext
18
+
19
+ if (slideSpNode) ext = slideSpNode['a:ext']['attrs']
20
+ else if (slideLayoutSpNode) ext = slideLayoutSpNode['a:ext']['attrs']
21
+ else if (slideMasterSpNode) ext = slideMasterSpNode['a:ext']['attrs']
22
+
23
+ if (!ext) return { width: 0, height: 0 }
24
+
25
+ return {
26
+ width: parseInt(ext['cx']) * factor,
27
+ height: parseInt(ext['cy']) * factor,
28
+ }
29
+ }