pptxtojson 2.0.0 → 2.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptxtojson",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "A javascript tool for parsing .pptx file",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.js",
package/src/diagram.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { readXmlFile } from './readXmlFile'
2
+ import { getTextNodeValue } from './text'
2
3
  import { getTextByPathList } from './utils'
3
4
 
4
5
  export async function loadDiagramFile(warpObj, filename, transformDrawing = false) {
@@ -112,7 +113,7 @@ export function getSmartArtTextData(dataContent) {
112
113
  if (!Array.isArray(runs)) runs = [runs]
113
114
 
114
115
  runs.forEach(r => {
115
- const t = getTextByPathList(r, ['a:t'])
116
+ const t = getTextNodeValue(getTextByPathList(r, ['a:t']))
116
117
  if (t && typeof t === 'string') nodeText += t
117
118
  })
118
119
  }
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
+ }
@@ -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,9 +3,9 @@ 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 './align'
6
+ import { getVerticalAlign, getTextAutoFit } from './paragraph'
7
7
  import { getPosition, getSize } from './position'
8
- import { genTextBody } from './text'
8
+ import { genTextBody, getTextNodeValue } from './text'
9
9
  import { getCustomShapePath, identifyShape } from './shape'
10
10
  import { extractFileExtension, getTextByPathList, angleToDegrees, isVideoLink, escapeHtml, hasValidText, numberToFixed } from './utils'
11
11
  import { getShadow } from './shadow'
@@ -33,6 +33,7 @@ export async function parse(file, options = {}) {
33
33
  const filesInfo = await getContentTypes(zip)
34
34
  const { width, height, defaultTextStyle } = await getSlideInfo(zip)
35
35
  const { themeContent, themeColors } = await getTheme(zip)
36
+ const usedFonts = await getUsedFonts(zip)
36
37
 
37
38
  for (const filename of filesInfo.slides) {
38
39
  const singleSlide = await processSingleSlide(zip, filename, themeContent, defaultTextStyle, loadedImages, loadedVideos, loadedAudios, parseOptions)
@@ -41,6 +42,7 @@ export async function parse(file, options = {}) {
41
42
 
42
43
  return {
43
44
  slides,
45
+ usedFonts,
44
46
  themeColors,
45
47
  size: {
46
48
  width,
@@ -81,6 +83,22 @@ async function getContentTypes(zip) {
81
83
  }
82
84
  }
83
85
 
86
+ async function getUsedFonts(zip) {
87
+ const content = await readXmlFile(zip, 'ppt/presentation.xml')
88
+ const embeddedFontList = getTextByPathList(content, ['p:presentation', 'p:embeddedFontLst', 'p:embeddedFont'])
89
+ const usedFonts = []
90
+
91
+ if (!embeddedFontList) return usedFonts
92
+
93
+ const embeddedFonts = embeddedFontList.constructor === Array ? embeddedFontList : [embeddedFontList]
94
+ for (const embeddedFont of embeddedFonts) {
95
+ const typeface = getTextByPathList(embeddedFont, ['p:font', 'attrs', 'typeface'])
96
+ if (typeface && !usedFonts.includes(typeface)) usedFonts.push(typeface)
97
+ }
98
+
99
+ return usedFonts
100
+ }
101
+
84
102
  async function getSlideInfo(zip) {
85
103
  const content = await readXmlFile(zip, 'ppt/presentation.xml')
86
104
  const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs']
@@ -392,7 +410,7 @@ function getNote(noteContent) {
392
410
  if (rNodes) {
393
411
  if (rNodes.constructor !== Array) rNodes = [rNodes]
394
412
  for (const r of rNodes) {
395
- const t = getTextByPathList(r, ['a:t'])
413
+ const t = getTextNodeValue(getTextByPathList(r, ['a:t']))
396
414
  if (t && typeof t === 'string') text += t
397
415
  }
398
416
  }
@@ -622,11 +640,13 @@ async function processGroupSpNode(node, warpObj, source, parentGroupHierarchy =
622
640
  if (depth > 10) return elements
623
641
 
624
642
  return elements.map(element => {
625
- const processed = {
626
- ...element,
627
- width: numberToFixed(element.width * ws),
628
- height: numberToFixed(element.height * hs),
629
- }
643
+ const processed = {
644
+ ...element,
645
+ left: numberToFixed(element.left * ws),
646
+ top: numberToFixed(element.top * hs),
647
+ width: numberToFixed(element.width * ws),
648
+ height: numberToFixed(element.height * hs),
649
+ }
630
650
  if (element.type === 'group' && element.elements) {
631
651
  processed.elements = processNestedGroupElements(element.elements, ws, hs, depth + 1)
632
652
  }
@@ -678,10 +698,11 @@ async function processSpNode(node, warpObj, source, groupHierarchy = []) {
678
698
  const txBoxVal = getTextByPathList(node, ['p:nvSpPr', 'p:cNvSpPr', 'attrs', 'txBox'])
679
699
  if (txBoxVal === '1') type = 'text'
680
700
  }
681
- if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
682
- if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
683
-
684
- if (!type) {
701
+ if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
702
+ if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
703
+ if (!slideMasterSpNode && type === 'ctrTitle') slideMasterSpNode = warpObj['slideMasterTables']['typeTable']['title']
704
+
705
+ if (!type) {
685
706
  if (source === 'diagramBg') type = 'diagram'
686
707
  else type = 'obj'
687
708
  }
@@ -1167,10 +1188,11 @@ async function genTable(node, warpObj) {
1167
1188
  if (cell.rowSpan) td.rowSpan = cell.rowSpan
1168
1189
  if (cell.colSpan) td.colSpan = cell.colSpan
1169
1190
  if (cell.vMerge) td.vMerge = cell.vMerge
1170
- if (cell.hMerge) td.hMerge = cell.hMerge
1171
- if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
1172
- if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
1173
- if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
1191
+ if (cell.hMerge) td.hMerge = cell.hMerge
1192
+ if (cell.vAlign) td.vAlign = cell.vAlign
1193
+ if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
1194
+ if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
1195
+ if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
1174
1196
  if (cell.borders) td.borders = cell.borders
1175
1197
 
1176
1198
  tr.push(td)
@@ -1199,10 +1221,11 @@ async function genTable(node, warpObj) {
1199
1221
  if (cell.rowSpan) td.rowSpan = cell.rowSpan
1200
1222
  if (cell.colSpan) td.colSpan = cell.colSpan
1201
1223
  if (cell.vMerge) td.vMerge = cell.vMerge
1202
- if (cell.hMerge) td.hMerge = cell.hMerge
1203
- if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
1204
- if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
1205
- if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
1224
+ if (cell.hMerge) td.hMerge = cell.hMerge
1225
+ if (cell.vAlign) td.vAlign = cell.vAlign
1226
+ if (cell.fontBold || fontBold) td.fontBold = cell.fontBold || fontBold
1227
+ if (cell.fontColor || fontColor) td.fontColor = cell.fontColor || fontColor
1228
+ if (cell.fillColor || fillColor || tbl_bgcolor) td.fillColor = cell.fillColor || fillColor || tbl_bgcolor
1206
1229
  if (cell.borders) td.borders = cell.borders
1207
1230
 
1208
1231
  tr.push(td)
@@ -1298,4 +1321,4 @@ async function genDiagram(node, warpObj) {
1298
1321
  textList,
1299
1322
  order,
1300
1323
  }
1301
- }
1324
+ }
@@ -2,6 +2,10 @@ import * as txml from 'txml/dist/txml.mjs'
2
2
 
3
3
  let cust_attr_order = 0
4
4
 
5
+ function isWhitespaceTextNode(node) {
6
+ return typeof node === 'string' && node.trim() === ''
7
+ }
8
+
5
9
  export function simplifyLostLess(children, parentAttributes = {}) {
6
10
  const out = {}
7
11
  if (!children.length) return out
@@ -13,6 +17,7 @@ export function simplifyLostLess(children, parentAttributes = {}) {
13
17
  } : children[0]
14
18
  }
15
19
  for (const child of children) {
20
+ if (isWhitespaceTextNode(child)) continue
16
21
  if (typeof child !== 'object') return
17
22
  if (child.tagName === '?xml') continue
18
23
 
@@ -39,7 +44,7 @@ export function simplifyLostLess(children, parentAttributes = {}) {
39
44
  export async function readXmlFile(zip, filename) {
40
45
  try {
41
46
  const data = await zip.file(filename).async('string')
42
- return simplifyLostLess(txml.parse(data))
47
+ return simplifyLostLess(txml.parse(data, { keepWhitespace: true }))
43
48
  }
44
49
  catch {
45
50
  return null
package/src/shapePath.js CHANGED
@@ -4,28 +4,33 @@ import { RATIO_EMUs_Points } from './constants'
4
4
  import { getTextByPathList } from './utils'
5
5
 
6
6
  function shapePie(H, w, adj1, adj2, isClose) {
7
- const pieVal = parseInt(adj2)
8
- const piAngle = parseInt(adj1)
7
+ const pieVal = parseFloat(adj2)
8
+ const piAngle = parseFloat(adj1)
9
9
  const size = parseInt(H)
10
- const radius = size / 2
10
+ const radiusY = size / 2
11
+ const radiusX = w / 2
12
+ const centerX = radiusX
13
+ const centerY = radiusY
11
14
 
12
15
  let value = pieVal - piAngle
13
16
  if (value < 0) value = 360 + value
14
17
  value = Math.min(Math.max(value, 0), 360)
15
18
 
16
- const x = Math.cos((2 * Math.PI) / (360 / value))
17
- const y = Math.sin((2 * Math.PI) / (360 / value))
19
+ const startRadians = piAngle * Math.PI / 180
20
+ const endRadians = (piAngle + value) * Math.PI / 180
21
+ const startX = centerX + Math.cos(startRadians) * radiusX
22
+ const startY = centerY + Math.sin(startRadians) * radiusY
23
+ const endX = centerX + Math.cos(endRadians) * radiusX
24
+ const endY = centerY + Math.sin(endRadians) * radiusY
18
25
 
19
26
  let longArc, d
20
27
  if (isClose) {
21
28
  longArc = (value <= 180) ? 0 : 1
22
- d = `M${radius},${radius} L${radius},0 A${radius},${radius} 0 ${longArc},1 ${radius + y * radius},${radius - x * radius} z`
29
+ d = `M${centerX},${centerY} L${startX},${startY} A${radiusX},${radiusY} 0 ${longArc},1 ${endX},${endY} z`
23
30
  }
24
31
  else {
25
32
  longArc = (value <= 180) ? 0 : 1
26
- const radius1 = radius
27
- const radius2 = w / 2
28
- d = `M${radius1},0 A${radius2},${radius1} 0 ${longArc},1 ${radius2 + y * radius2},${radius1 - x * radius1}`
33
+ d = `M${startX},${startY} A${radiusX},${radiusY} 0 ${longArc},1 ${endX},${endY}`
29
34
  }
30
35
 
31
36
  return d
@@ -1434,17 +1439,18 @@ export function getShapePath(shapType, w, h, node) {
1434
1439
  }
1435
1440
 
1436
1441
  if (shapAdjst) {
1437
- let shapAdjst1 = getTextByPathList(shapAdjst, ['attrs', 'fmla'])
1438
- let shapAdjst2 = shapAdjst1
1439
- if (shapAdjst1 === undefined) {
1440
- shapAdjst1 = shapAdjst[0]['attrs']['fmla']
1441
- shapAdjst2 = shapAdjst[1]['attrs']['fmla']
1442
- }
1443
- if (shapAdjst1) {
1444
- adj1 = parseInt(shapAdjst1.substring(4)) / 60000
1445
- }
1446
- if (shapAdjst2) {
1447
- adj2 = parseInt(shapAdjst2.substring(4)) / 60000
1442
+ const shapAdjstAry = Array.isArray(shapAdjst) ? shapAdjst : [shapAdjst]
1443
+ for (const adj of shapAdjstAry) {
1444
+ const name = getTextByPathList(adj, ['attrs', 'name'])
1445
+ const fmla = getTextByPathList(adj, ['attrs', 'fmla'])
1446
+ if (!name || !fmla) continue
1447
+
1448
+ if (name === 'adj1') {
1449
+ adj1 = parseInt(fmla.substring(4)) / 60000
1450
+ }
1451
+ else if (name === 'adj2') {
1452
+ adj2 = parseInt(fmla.substring(4)) / 60000
1453
+ }
1448
1454
  }
1449
1455
  }
1450
1456
 
@@ -4628,4 +4634,4 @@ export function getShapePath(shapType, w, h, node) {
4628
4634
  }
4629
4635
 
4630
4636
  return pathData
4631
- }
4637
+ }
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
- let fillColor
58
- let fontColor
59
- let fontBold
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
- rowSpan: rowSpan ? +rowSpan : undefined,
118
- colSpan: colSpan ? +colSpan : undefined,
119
- vMerge: vMerge ? +vMerge : undefined,
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 './align'
1
+ import { getHorizontalAlign, getParagraphSpacing } from './paragraph'
2
2
  import { getTextByPathList } from './utils'
3
3
 
4
4
  import {
@@ -14,13 +14,20 @@ import {
14
14
  getFontShadow,
15
15
  } from './fontStyle'
16
16
 
17
+ export function getTextNodeValue(node) {
18
+ if (typeof node === 'string') return node
19
+ if (node && typeof node.value === 'string') return node.value
20
+ return undefined
21
+ }
22
+
17
23
  export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMasterSpNode, type, warpObj) {
18
24
  if (!textBodyNode) return ''
19
25
 
20
26
  let text = ''
21
27
 
22
- const pFontStyle = getTextByPathList(spNode, ['p:style', 'a:fontRef'])
23
- 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
24
31
 
25
32
  const pNode = textBodyNode['a:p']
26
33
  const pNodes = pNode.constructor === Array ? pNode : [pNode]
@@ -52,7 +59,7 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMaster
52
59
  }
53
60
 
54
61
  const align = getHorizontalAlign(pNode, spNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj)
55
- const spacing = getParagraphSpacing(pNode)
62
+ const spacing = getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
56
63
 
57
64
  let styleText = `text-align: ${align};`
58
65
  if (spacing) {
@@ -90,14 +97,14 @@ export function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMaster
90
97
  }
91
98
 
92
99
  if (!rNode) {
93
- text += genSpanElement(pNode, spNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
100
+ text += genSpanElement(pNode, spNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj)
94
101
  }
95
102
  else {
96
103
  let prevStyleInfo = null
97
104
  let accumulatedText = ''
98
105
 
99
106
  for (const rNodeItem of rNode) {
100
- 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)
101
108
 
102
109
  if (!prevStyleInfo || prevStyleInfo.styleText !== styleInfo.styleText || prevStyleInfo.hasLink !== styleInfo.hasLink || styleInfo.hasLink) {
103
110
  if (accumulatedText) {
@@ -154,8 +161,8 @@ export function getListLevel(node) {
154
161
  return 0
155
162
  }
156
163
 
157
- export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
158
- 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)
159
166
  const processedText = text.replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;').replace(/\s/g, '&nbsp;')
160
167
 
161
168
  if (hasLink) {
@@ -164,19 +171,19 @@ export function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayou
164
171
  return `<span style="${styleText}">${processedText}</span>`
165
172
  }
166
173
 
167
- 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) {
168
175
  let lvl = 1
169
176
  const pPrNode = pNode['a:pPr']
170
177
  const lvlNode = getTextByPathList(pPrNode, ['attrs', 'lvl'])
171
178
  if (lvlNode !== undefined) lvl = parseInt(lvlNode) + 1
172
179
 
173
- let text = node['a:t']
174
- if (typeof text !== 'string') text = getTextByPathList(node, ['a:fld', 'a:t'])
180
+ let text = getTextNodeValue(node['a:t'])
181
+ if (typeof text !== 'string') text = getTextNodeValue(getTextByPathList(node, ['a:fld', 'a:t']))
175
182
  if (typeof text !== 'string') text = '&nbsp;'
176
183
 
177
184
  let styleText = ''
178
185
  const fontColor = getFontColor(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, pFontStyle, warpObj)
179
- const fontSize = getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
186
+ const fontSize = getFontSize(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, defaultTextStyle)
180
187
  const fontType = getFontType(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl, warpObj)
181
188
  const fontBold = getFontBold(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
182
189
  const fontItalic = getFontItalic(node, pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, lvl)
@@ -214,4 +221,4 @@ export function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLay
214
221
  hasLink,
215
222
  linkURL: hasLink ? warpObj['slideResObj'][linkID]['target'] : null
216
223
  }
217
- }
224
+ }