pptxtojson 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -13
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -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/package.json +1 -1
- package/src/fontStyle.js +11 -2
- package/src/paragraph.js +223 -0
- package/src/pptxtojson.js +28 -2
- package/src/table.js +15 -13
- package/src/text.js +12 -11
- package/src/textInsets.js +64 -0
- package/src/align.js +0 -164
package/package.json
CHANGED
package/src/fontStyle.js
CHANGED
|
@@ -44,6 +44,14 @@ function appendMasterTextStyleNodes(styleNodes, type, lvl, slideMasterTextStyles
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
function appendDefaultTextStyleNodes(styleNodes, lvl, defaultTextStyle) {
|
|
48
|
+
if (!defaultTextStyle) return
|
|
49
|
+
|
|
50
|
+
const lvlPath = getLevelPath(lvl)
|
|
51
|
+
pushStyleNode(styleNodes, getTextByPathList(defaultTextStyle, [lvlPath, 'a:defRPr']))
|
|
52
|
+
pushStyleNode(styleNodes, getTextByPathList(defaultTextStyle, ['a:defPPr', 'a:defRPr']))
|
|
53
|
+
}
|
|
54
|
+
|
|
47
55
|
function getBaseFontStyleNodes(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, lvl) {
|
|
48
56
|
const styleNodes = []
|
|
49
57
|
const runStyleNode = getTextByPathList(node, ['a:rPr'])
|
|
@@ -180,8 +188,9 @@ export function getFontColor(node, pNode, textBodyNode, slideLayoutSpNode, slide
|
|
|
180
188
|
return color || ''
|
|
181
189
|
}
|
|
182
190
|
|
|
183
|
-
export function getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl) {
|
|
191
|
+
export function getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, defaultTextStyle) {
|
|
184
192
|
const styleNodes = getFontStyleNodes(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
|
|
193
|
+
appendDefaultTextStyleNodes(styleNodes, lvl, defaultTextStyle)
|
|
185
194
|
const sz = getFontAttr(styleNodes, 'sz')
|
|
186
195
|
let fontSize = sz ? parseInt(sz) / 100 : undefined
|
|
187
196
|
|
|
@@ -235,4 +244,4 @@ export function getFontShadow(node, pNode, textBodyNode, slideLayoutSpNode, slid
|
|
|
235
244
|
}
|
|
236
245
|
}
|
|
237
246
|
return ''
|
|
238
|
-
}
|
|
247
|
+
}
|
package/src/paragraph.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { getTextByPathList } from './utils'
|
|
2
|
+
|
|
3
|
+
function getParagraphLevel(node) {
|
|
4
|
+
let lvlIdx = 1
|
|
5
|
+
const lvlNode = getTextByPathList(node, ['a:pPr', 'attrs', 'lvl'])
|
|
6
|
+
if (lvlNode !== undefined) lvlIdx = parseInt(lvlNode) + 1
|
|
7
|
+
return lvlIdx
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getAlignFromTextNode(node, lvlStr) {
|
|
11
|
+
if (!node) return ''
|
|
12
|
+
|
|
13
|
+
let algn = getTextByPathList(node, ['p:txBody', 'a:lstStyle', lvlStr, 'attrs', 'algn'])
|
|
14
|
+
if (!algn) algn = getTextByPathList(node, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
15
|
+
|
|
16
|
+
return algn || ''
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getHorizontalAlign(node, pNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj) {
|
|
20
|
+
let algn = getTextByPathList(node, ['a:pPr', 'attrs', 'algn'])
|
|
21
|
+
|
|
22
|
+
if (!algn) algn = getTextByPathList(pNode, ['p:txBody', 'a:p', 'a:pPr', 'attrs', 'algn'])
|
|
23
|
+
|
|
24
|
+
if (!algn) {
|
|
25
|
+
const lvlIdx = getParagraphLevel(node)
|
|
26
|
+
const lvlStr = 'a:lvl' + lvlIdx + 'pPr'
|
|
27
|
+
|
|
28
|
+
algn = getAlignFromTextNode(slideLayoutSpNode, lvlStr)
|
|
29
|
+
if (!algn) algn = getAlignFromTextNode(slideMasterSpNode, lvlStr)
|
|
30
|
+
|
|
31
|
+
if (!algn && (type === 'title' || type === 'ctrTitle' || type === 'subTitle')) {
|
|
32
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:titleStyle', lvlStr, 'attrs', 'algn'])
|
|
33
|
+
if (!algn && type === 'subTitle') {
|
|
34
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:bodyStyle', lvlStr, 'attrs', 'algn'])
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (!algn && type === 'body') {
|
|
38
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:bodyStyle', lvlStr, 'attrs', 'algn'])
|
|
39
|
+
}
|
|
40
|
+
else if (!algn) {
|
|
41
|
+
algn = getTextByPathList(warpObj, ['slideMasterTextStyles', 'p:otherStyle', lvlStr, 'attrs', 'algn'])
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let align = 'left'
|
|
46
|
+
if (algn) {
|
|
47
|
+
switch (algn) {
|
|
48
|
+
case 'l':
|
|
49
|
+
align = 'left'
|
|
50
|
+
break
|
|
51
|
+
case 'r':
|
|
52
|
+
align = 'right'
|
|
53
|
+
break
|
|
54
|
+
case 'ctr':
|
|
55
|
+
align = 'center'
|
|
56
|
+
break
|
|
57
|
+
case 'just':
|
|
58
|
+
align = 'justify'
|
|
59
|
+
break
|
|
60
|
+
case 'dist':
|
|
61
|
+
align = 'justify'
|
|
62
|
+
break
|
|
63
|
+
default:
|
|
64
|
+
align = 'inherit'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return align
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode) {
|
|
71
|
+
let anchor = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'anchor'])
|
|
72
|
+
if (!anchor) {
|
|
73
|
+
anchor = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:bodyPr', 'attrs', 'anchor'])
|
|
74
|
+
if (!anchor) {
|
|
75
|
+
anchor = getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:bodyPr', 'attrs', 'anchor'])
|
|
76
|
+
if (!anchor) anchor = 't'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return (anchor === 'ctr') ? 'mid' : ((anchor === 'b') ? 'down' : 'up')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getTextAutoFit(node, slideLayoutSpNode, slideMasterSpNode) {
|
|
83
|
+
function checkBodyPr(bodyPr) {
|
|
84
|
+
if (!bodyPr) return null
|
|
85
|
+
|
|
86
|
+
if (bodyPr['a:noAutofit']) return { result: null }
|
|
87
|
+
else if (bodyPr['a:spAutoFit']) return { result: { type: 'shape' } }
|
|
88
|
+
else if (bodyPr['a:normAutofit']) {
|
|
89
|
+
const fontScale = getTextByPathList(bodyPr['a:normAutofit'], ['attrs', 'fontScale'])
|
|
90
|
+
if (fontScale) {
|
|
91
|
+
const scalePercent = parseInt(fontScale) / 1000
|
|
92
|
+
return {
|
|
93
|
+
result: {
|
|
94
|
+
type: 'text',
|
|
95
|
+
fontScale: scalePercent,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { result: { type: 'text' } }
|
|
100
|
+
}
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const nodeCheck = checkBodyPr(getTextByPathList(node, ['p:txBody', 'a:bodyPr']))
|
|
105
|
+
if (nodeCheck) return nodeCheck.result
|
|
106
|
+
|
|
107
|
+
const layoutCheck = checkBodyPr(getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:bodyPr']))
|
|
108
|
+
if (layoutCheck) return layoutCheck.result
|
|
109
|
+
|
|
110
|
+
const masterCheck = checkBodyPr(getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:bodyPr']))
|
|
111
|
+
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
|
+
export function getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
200
|
+
const styleNodes = getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
201
|
+
if (!styleNodes) return null
|
|
202
|
+
|
|
203
|
+
const spacing = {}
|
|
204
|
+
|
|
205
|
+
for (const styleNode of styleNodes) {
|
|
206
|
+
if (spacing.lineSpacing === undefined) {
|
|
207
|
+
const lineSpacing = getLineSpacingValue(styleNode['a:lnSpc'])
|
|
208
|
+
if (lineSpacing !== undefined) spacing.lineSpacing = lineSpacing
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (spacing.spaceBefore === undefined) {
|
|
212
|
+
const spaceBefore = getParagraphSpacingValue(styleNode['a:spcBef'])
|
|
213
|
+
if (spaceBefore !== undefined) spacing.spaceBefore = spaceBefore
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (spacing.spaceAfter === undefined) {
|
|
217
|
+
const spaceAfter = getParagraphSpacingValue(styleNode['a:spcAft'])
|
|
218
|
+
if (spaceAfter !== undefined) spacing.spaceAfter = spaceAfter
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return Object.keys(spacing).length > 0 ? spacing : null
|
|
223
|
+
}
|
package/src/pptxtojson.js
CHANGED
|
@@ -3,7 +3,8 @@ import { readXmlFile } from './readXmlFile'
|
|
|
3
3
|
import { getBorder } from './border'
|
|
4
4
|
import { getSlideBackgroundFill, getShapeFill, getSolidFill, getPicFill, getPicFilters, getImageData, getVideoData, getAudioData } from './fill'
|
|
5
5
|
import { getChartInfo } from './chart'
|
|
6
|
-
import { getVerticalAlign, getTextAutoFit } from './
|
|
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'
|
|
@@ -33,6 +34,7 @@ export async function parse(file, options = {}) {
|
|
|
33
34
|
const filesInfo = await getContentTypes(zip)
|
|
34
35
|
const { width, height, defaultTextStyle } = await getSlideInfo(zip)
|
|
35
36
|
const { themeContent, themeColors } = await getTheme(zip)
|
|
37
|
+
const usedFonts = await getUsedFonts(zip)
|
|
36
38
|
|
|
37
39
|
for (const filename of filesInfo.slides) {
|
|
38
40
|
const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle, loadedImages, loadedVideos, loadedAudios, parseOptions)
|
|
@@ -41,6 +43,7 @@ export async function parse(file, options = {}) {
|
|
|
41
43
|
|
|
42
44
|
return {
|
|
43
45
|
slides,
|
|
46
|
+
usedFonts,
|
|
44
47
|
themeColors,
|
|
45
48
|
size: {
|
|
46
49
|
width,
|
|
@@ -81,6 +84,22 @@ async function getContentTypes(zip) {
|
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
async function getUsedFonts(zip) {
|
|
88
|
+
const content = await readXmlFile(zip, 'ppt/presentation.xml')
|
|
89
|
+
const embeddedFontList = getTextByPathList(content, ['p:presentation', 'p:embeddedFontLst', 'p:embeddedFont'])
|
|
90
|
+
const usedFonts = []
|
|
91
|
+
|
|
92
|
+
if (!embeddedFontList) return usedFonts
|
|
93
|
+
|
|
94
|
+
const embeddedFonts = embeddedFontList.constructor === Array ? embeddedFontList : [embeddedFontList]
|
|
95
|
+
for (const embeddedFont of embeddedFonts) {
|
|
96
|
+
const typeface = getTextByPathList(embeddedFont, ['p:font', 'attrs', 'typeface'])
|
|
97
|
+
if (typeface && !usedFonts.includes(typeface)) usedFonts.push(typeface)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return usedFonts
|
|
101
|
+
}
|
|
102
|
+
|
|
84
103
|
async function getSlideInfo(zip) {
|
|
85
104
|
const content = await readXmlFile(zip, 'ppt/presentation.xml')
|
|
86
105
|
const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs']
|
|
@@ -624,6 +643,8 @@ async function processGroupSpNode(node, warpObj, source, parentGroupHierarchy =
|
|
|
624
643
|
return elements.map(element => {
|
|
625
644
|
const processed = {
|
|
626
645
|
...element,
|
|
646
|
+
left: numberToFixed(element.left * ws),
|
|
647
|
+
top: numberToFixed(element.top * hs),
|
|
627
648
|
width: numberToFixed(element.width * ws),
|
|
628
649
|
height: numberToFixed(element.height * hs),
|
|
629
650
|
}
|
|
@@ -680,6 +701,7 @@ async function processSpNode(node, warpObj, source, groupHierarchy = []) {
|
|
|
680
701
|
}
|
|
681
702
|
if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
682
703
|
if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
704
|
+
if (!slideMasterSpNode && type === 'ctrTitle') slideMasterSpNode = warpObj['slideMasterTables']['typeTable']['title']
|
|
683
705
|
|
|
684
706
|
if (!type) {
|
|
685
707
|
if (source === 'diagramBg') type = 'diagram'
|
|
@@ -754,6 +776,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
754
776
|
const vAlign = getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode, type)
|
|
755
777
|
const isVertical = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'vert']) === 'eaVert'
|
|
756
778
|
const autoFit = getTextAutoFit(node, slideLayoutSpNode, slideMasterSpNode)
|
|
779
|
+
const textInset = getTextInsets(node, slideLayoutSpNode, slideMasterSpNode)
|
|
757
780
|
|
|
758
781
|
const data = {
|
|
759
782
|
left,
|
|
@@ -777,6 +800,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
777
800
|
if (shadow) data.shadow = shadow
|
|
778
801
|
if (autoFit) data.autoFit = autoFit
|
|
779
802
|
if (link) data.link = link
|
|
803
|
+
if (textInset) data.textInset = textInset
|
|
780
804
|
|
|
781
805
|
const isHasValidText = data.content && hasValidText(data.content)
|
|
782
806
|
|
|
@@ -1168,6 +1192,7 @@ async function genTable(node, warpObj) {
|
|
|
1168
1192
|
if (cell.colSpan) td.colSpan = cell.colSpan
|
|
1169
1193
|
if (cell.vMerge) td.vMerge = cell.vMerge
|
|
1170
1194
|
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1195
|
+
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1171
1196
|
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1172
1197
|
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1173
1198
|
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
@@ -1200,6 +1225,7 @@ async function genTable(node, warpObj) {
|
|
|
1200
1225
|
if (cell.colSpan) td.colSpan = cell.colSpan
|
|
1201
1226
|
if (cell.vMerge) td.vMerge = cell.vMerge
|
|
1202
1227
|
if (cell.hMerge) td.hMerge = cell.hMerge
|
|
1228
|
+
if (cell.vAlign) td.vAlign = cell.vAlign
|
|
1203
1229
|
if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
|
|
1204
1230
|
if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
|
|
1205
1231
|
if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
|
|
@@ -1298,4 +1324,4 @@ async function genDiagram(node, warpObj) {
|
|
|
1298
1324
|
textList,
|
|
1299
1325
|
order,
|
|
1300
1326
|
}
|
|
1301
|
-
}
|
|
1327
|
+
}
|
package/src/table.js
CHANGED
|
@@ -49,14 +49,15 @@ export function getTableBorders(node, warpObj) {
|
|
|
49
49
|
return borders
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export async function getTableCellParams(tcNode, thisTblStyle, cellSource, warpObj) {
|
|
53
|
-
const rowSpan = getTextByPathList(tcNode, ['attrs', 'rowSpan'])
|
|
54
|
-
const colSpan = getTextByPathList(tcNode, ['attrs', 'gridSpan'])
|
|
55
|
-
const vMerge = getTextByPathList(tcNode, ['attrs', 'vMerge'])
|
|
56
|
-
const hMerge = getTextByPathList(tcNode, ['attrs', 'hMerge'])
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
let
|
|
52
|
+
export async function getTableCellParams(tcNode, thisTblStyle, cellSource, warpObj) {
|
|
53
|
+
const rowSpan = getTextByPathList(tcNode, ['attrs', 'rowSpan'])
|
|
54
|
+
const colSpan = getTextByPathList(tcNode, ['attrs', 'gridSpan'])
|
|
55
|
+
const vMerge = getTextByPathList(tcNode, ['attrs', 'vMerge'])
|
|
56
|
+
const hMerge = getTextByPathList(tcNode, ['attrs', 'hMerge'])
|
|
57
|
+
const anchor = getTextByPathList(tcNode, ['a:tcPr', 'attrs', 'anchor'])
|
|
58
|
+
let fillColor
|
|
59
|
+
let fontColor
|
|
60
|
+
let fontBold
|
|
60
61
|
|
|
61
62
|
const getCelFill = getTextByPathList(tcNode, ['a:tcPr'])
|
|
62
63
|
if (getCelFill) {
|
|
@@ -113,10 +114,11 @@ export async function getTableCellParams(tcNode, thisTblStyle, cellSource, warpO
|
|
|
113
114
|
fillColor,
|
|
114
115
|
fontColor,
|
|
115
116
|
fontBold,
|
|
116
|
-
borders,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
borders,
|
|
118
|
+
vAlign: (anchor === 'ctr') ? 'mid' : ((anchor === 'b') ? 'down' : 'up'),
|
|
119
|
+
rowSpan: rowSpan ? +rowSpan : undefined,
|
|
120
|
+
colSpan: colSpan ? +colSpan : undefined,
|
|
121
|
+
vMerge: vMerge ? +vMerge : undefined,
|
|
120
122
|
hMerge: hMerge ? +hMerge : undefined,
|
|
121
123
|
}
|
|
122
124
|
}
|
|
@@ -202,4 +204,4 @@ export function getTableRowParams(trNodes, i, tblStylAttrObj, thisTblStyle, warp
|
|
|
202
204
|
fontColor,
|
|
203
205
|
fontBold,
|
|
204
206
|
}
|
|
205
|
-
}
|
|
207
|
+
}
|
package/src/text.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getHorizontalAlign, getParagraphSpacing } from './
|
|
1
|
+
import { getHorizontalAlign, getParagraphSpacing } from './paragraph'
|
|
2
2
|
import { getTextByPathList } from './utils'
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -25,8 +25,9 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMaster
|
|
|
25
25
|
|
|
26
26
|
let text = ''
|
|
27
27
|
|
|
28
|
-
const pFontStyle = getTextByPathList(spNode, ['p:style', 'a:fontRef'])
|
|
29
|
-
const slideMasterTextStyles = spNode && spNode['a:tcPr'] ? undefined : warpObj['slideMasterTextStyles']
|
|
28
|
+
const pFontStyle = getTextByPathList(spNode, ['p:style', 'a:fontRef'])
|
|
29
|
+
const slideMasterTextStyles = spNode && spNode['a:tcPr'] ? undefined : warpObj['slideMasterTextStyles']
|
|
30
|
+
const defaultTextStyle = spNode && spNode['a:tcPr'] ? warpObj['defaultTextStyle'] : undefined
|
|
30
31
|
|
|
31
32
|
const pNode = textBodyNode['a:p']
|
|
32
33
|
const pNodes = pNode.constructor === Array ? pNode : [pNode]
|
|
@@ -58,7 +59,7 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMaster
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
const align = getHorizontalAlign(pNode, spNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj)
|
|
61
|
-
const spacing = getParagraphSpacing(pNode)
|
|
62
|
+
const spacing = getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
62
63
|
|
|
63
64
|
let styleText = `text-align: ${align};`
|
|
64
65
|
if (spacing) {
|
|
@@ -96,14 +97,14 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMaster
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
if (!rNode) {
|
|
99
|
-
text += genSpanElement(pNode, spNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
100
|
+
text += genSpanElement(pNode, spNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj)
|
|
100
101
|
}
|
|
101
102
|
else {
|
|
102
103
|
let prevStyleInfo = null
|
|
103
104
|
let accumulatedText = ''
|
|
104
105
|
|
|
105
106
|
for (const rNodeItem of rNode) {
|
|
106
|
-
const styleInfo = getSpanStyleInfo(rNodeItem, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
107
|
+
const styleInfo = getSpanStyleInfo(rNodeItem, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj)
|
|
107
108
|
|
|
108
109
|
if (!prevStyleInfo || prevStyleInfo.styleText !== styleInfo.styleText || prevStyleInfo.hasLink !== styleInfo.hasLink || styleInfo.hasLink) {
|
|
109
110
|
if (accumulatedText) {
|
|
@@ -160,8 +161,8 @@ export function getListLevel(node) {
|
|
|
160
161
|
return 0
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
164
|
-
const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
164
|
+
export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj) {
|
|
165
|
+
const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj)
|
|
165
166
|
const processedText = text.replace(/\t/g, ' ').replace(/\s/g, ' ')
|
|
166
167
|
|
|
167
168
|
if (hasLink) {
|
|
@@ -170,7 +171,7 @@ export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayou
|
|
|
170
171
|
return `<span style="${styleText}">${processedText}</span>`
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
174
|
+
export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj) {
|
|
174
175
|
let lvl = 1
|
|
175
176
|
const pPrNode = pNode['a:pPr']
|
|
176
177
|
const lvlNode = getTextByPathList(pPrNode, ['attrs', 'lvl'])
|
|
@@ -182,7 +183,7 @@ export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLay
|
|
|
182
183
|
|
|
183
184
|
let styleText = ''
|
|
184
185
|
const fontColor = getFontColor(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, pFontStyle, warpObj)
|
|
185
|
-
const fontSize = getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
|
|
186
|
+
const fontSize = getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, defaultTextStyle)
|
|
186
187
|
const fontType = getFontType(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, warpObj)
|
|
187
188
|
const fontBold = getFontBold(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
|
|
188
189
|
const fontItalic = getFontItalic(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
|
|
@@ -220,4 +221,4 @@ export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLay
|
|
|
220
221
|
hasLink,
|
|
221
222
|
linkURL: hasLink ? warpObj['slideResObj'][linkID]['target'] : null
|
|
222
223
|
}
|
|
223
|
-
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getTextByPathList, numberToFixed } from './utils'
|
|
2
|
+
import { RATIO_EMUs_Points } from './constants'
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INSET_EMU = {
|
|
5
|
+
lIns: 91440, // 0.1 in
|
|
6
|
+
rIns: 91440, // 0.1 in
|
|
7
|
+
tIns: 45720, // 0.05 in
|
|
8
|
+
bIns: 45720, // 0.05 in
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getInsetAttr(slideNode, layoutNode, masterNode, attrName) {
|
|
12
|
+
let v = getTextByPathList(slideNode, ['p:txBody', 'a:bodyPr', 'attrs', attrName])
|
|
13
|
+
if (v !== undefined && v !== null && v !== '') return v
|
|
14
|
+
|
|
15
|
+
v = getTextByPathList(layoutNode, ['p:txBody', 'a:bodyPr', 'attrs', attrName])
|
|
16
|
+
if (v !== undefined && v !== null && v !== '') return v
|
|
17
|
+
|
|
18
|
+
return getTextByPathList(masterNode, ['p:txBody', 'a:bodyPr', 'attrs', attrName])
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function emuToPt(emuStr) {
|
|
22
|
+
if (emuStr === undefined || emuStr === null || emuStr === '') return null
|
|
23
|
+
const v = parseInt(emuStr, 10)
|
|
24
|
+
if (!Number.isFinite(v)) return null
|
|
25
|
+
return numberToFixed(v * RATIO_EMUs_Points)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getTextInsets(node, slideLayoutSpNode, slideMasterSpNode) {
|
|
29
|
+
const nodeBodyPr = getTextByPathList(node, ['p:txBody', 'a:bodyPr'])
|
|
30
|
+
const layoutBodyPr = getTextByPathList(slideLayoutSpNode, ['p:txBody', 'a:bodyPr'])
|
|
31
|
+
const masterBodyPr = getTextByPathList(slideMasterSpNode, ['p:txBody', 'a:bodyPr'])
|
|
32
|
+
|
|
33
|
+
if (!nodeBodyPr) {
|
|
34
|
+
if (!layoutBodyPr) {
|
|
35
|
+
if (!masterBodyPr) return null
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let li = getInsetAttr(node, slideLayoutSpNode, slideMasterSpNode, 'lIns')
|
|
40
|
+
if (li === undefined || li === null || li === '') li = DEFAULT_INSET_EMU.lIns
|
|
41
|
+
|
|
42
|
+
let ti = getInsetAttr(node, slideLayoutSpNode, slideMasterSpNode, 'tIns')
|
|
43
|
+
if (ti === undefined || ti === null || ti === '') ti = DEFAULT_INSET_EMU.tIns
|
|
44
|
+
|
|
45
|
+
let ri = getInsetAttr(node, slideLayoutSpNode, slideMasterSpNode, 'rIns')
|
|
46
|
+
if (ri === undefined || ri === null || ri === '') ri = DEFAULT_INSET_EMU.rIns
|
|
47
|
+
|
|
48
|
+
let bi = getInsetAttr(node, slideLayoutSpNode, slideMasterSpNode, 'bIns')
|
|
49
|
+
if (bi === undefined || bi === null || bi === '') bi = DEFAULT_INSET_EMU.bIns
|
|
50
|
+
|
|
51
|
+
let l = emuToPt(li)
|
|
52
|
+
if (l === null) l = 0
|
|
53
|
+
|
|
54
|
+
let t = emuToPt(ti)
|
|
55
|
+
if (t === null) t = 0
|
|
56
|
+
|
|
57
|
+
let r = emuToPt(ri)
|
|
58
|
+
if (r === null) r = 0
|
|
59
|
+
|
|
60
|
+
let b = emuToPt(bi)
|
|
61
|
+
if (b === null) b = 0
|
|
62
|
+
|
|
63
|
+
return { l, t, r, b }
|
|
64
|
+
}
|