pptxtojson 2.1.0 → 2.2.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 +355 -350
- package/README_zh.md +18 -13
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +46 -32
- 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/diagram.js +7 -5
- package/src/paragraph.js +21 -16
- package/src/pptxtojson.js +51 -19
package/package.json
CHANGED
package/src/diagram.js
CHANGED
|
@@ -67,10 +67,12 @@ export async function getDiagramNodeContext(node, warpObj) {
|
|
|
67
67
|
let relationshipArray = digramResContent['Relationships']['Relationship']
|
|
68
68
|
if (relationshipArray && relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
|
|
69
69
|
if (relationshipArray) {
|
|
70
|
-
for (const relationshipArrayItem of relationshipArray) {
|
|
71
|
-
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
for (const relationshipArrayItem of relationshipArray) {
|
|
71
|
+
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
72
|
+
relTarget = relTarget.replace(/\\/g, '/')
|
|
73
|
+
if (relTarget.indexOf('/ppt/') === 0) relTarget = relTarget.substr(1)
|
|
74
|
+
else if (relTarget.indexOf('../') !== -1) relTarget = relTarget.replace('../', 'ppt/')
|
|
75
|
+
else relTarget = drawingTarget.replace(drawingName, '') + relTarget
|
|
74
76
|
|
|
75
77
|
diagramResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
76
78
|
type: relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
@@ -129,4 +131,4 @@ export function getSmartArtTextData(dataContent) {
|
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
return result
|
|
132
|
-
}
|
|
134
|
+
}
|
package/src/paragraph.js
CHANGED
|
@@ -177,12 +177,16 @@ function getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMas
|
|
|
177
177
|
return styleNodes
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
function getLineSpacingValue(spacingNode) {
|
|
181
|
-
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
182
|
-
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
183
|
-
|
|
184
|
-
if (spcPct
|
|
185
|
-
|
|
180
|
+
function getLineSpacingValue(spacingNode, singleLineSpacingFactor = 1) {
|
|
181
|
+
const spcPct = getTextByPathList(spacingNode, ['a:spcPct', 'attrs', 'val'])
|
|
182
|
+
const spcPts = getTextByPathList(spacingNode, ['a:spcPts', 'attrs', 'val'])
|
|
183
|
+
|
|
184
|
+
if (spcPct !== undefined) {
|
|
185
|
+
const value = String(spcPct).trim()
|
|
186
|
+
const percentage = value.endsWith('%') ? Number.parseFloat(value) / 100 : Number.parseInt(value, 10) / 100000
|
|
187
|
+
if (Number.isFinite(percentage)) return percentage * singleLineSpacingFactor
|
|
188
|
+
}
|
|
189
|
+
if (spcPts) return parseInt(spcPts) / 100 + 'pt'
|
|
186
190
|
|
|
187
191
|
return undefined
|
|
188
192
|
}
|
|
@@ -205,16 +209,17 @@ function getParagraphIndentValue(styleNode, attrName) {
|
|
|
205
209
|
return undefined
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
export function getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
209
|
-
const styleNodes = getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
210
|
-
if (!styleNodes) return null
|
|
211
|
-
|
|
212
|
-
const spacing = {}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
export function getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
213
|
+
const styleNodes = getParagraphStyleNodes(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj)
|
|
214
|
+
if (!styleNodes) return null
|
|
215
|
+
|
|
216
|
+
const spacing = {}
|
|
217
|
+
const singleLineSpacingFactor = getTextByPathList(warpObj, ['options', 'singleLineSpacingFactor'])
|
|
218
|
+
|
|
219
|
+
for (const styleNode of styleNodes) {
|
|
220
|
+
if (spacing.lineSpacing === undefined) {
|
|
221
|
+
const lineSpacing = getLineSpacingValue(styleNode['a:lnSpc'], singleLineSpacingFactor)
|
|
222
|
+
if (lineSpacing !== undefined) spacing.lineSpacing = lineSpacing
|
|
218
223
|
}
|
|
219
224
|
|
|
220
225
|
if (spacing.spaceBefore === undefined) {
|
package/src/pptxtojson.js
CHANGED
|
@@ -25,10 +25,11 @@ export async function parse(file, options = {}) {
|
|
|
25
25
|
const xmlCache = {}
|
|
26
26
|
const parseOptions = {
|
|
27
27
|
...options,
|
|
28
|
-
imageMode: options.imageMode || 'base64',
|
|
29
|
-
videoMode: options.videoMode || 'none',
|
|
30
|
-
audioMode: options.audioMode || 'none',
|
|
31
|
-
|
|
28
|
+
imageMode: options.imageMode || 'base64',
|
|
29
|
+
videoMode: options.videoMode || 'none',
|
|
30
|
+
audioMode: options.audioMode || 'none',
|
|
31
|
+
singleLineSpacingFactor: Number.isFinite(options.singleLineSpacingFactor) && options.singleLineSpacingFactor > 0 ? options.singleLineSpacingFactor : 1,
|
|
32
|
+
}
|
|
32
33
|
|
|
33
34
|
const zip = await JSZip.loadAsync(file)
|
|
34
35
|
|
|
@@ -129,7 +130,12 @@ async function getTheme(zip) {
|
|
|
129
130
|
themeURI = relationshipArray['attrs']['Target']
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
let themeContent = null
|
|
134
|
+
if (themeURI) {
|
|
135
|
+
themeURI = themeURI.replace(/\\/g, '/')
|
|
136
|
+
const themeFilename = themeURI.indexOf('/ppt/') === 0 ? themeURI.substr(1) : 'ppt/' + themeURI
|
|
137
|
+
themeContent = await readXmlFile(zip, themeFilename)
|
|
138
|
+
}
|
|
133
139
|
|
|
134
140
|
const themeColors = []
|
|
135
141
|
const clrScheme = getTextByPathList(themeContent, ['a:theme', 'a:themeElements', 'a:clrScheme'])
|
|
@@ -173,7 +179,9 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
173
179
|
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
174
180
|
const isExternal = relationshipArrayItem['attrs']['TargetMode'] === 'External'
|
|
175
181
|
if (!isExternal) {
|
|
176
|
-
|
|
182
|
+
relTarget = relTarget.replace(/\\/g, '/')
|
|
183
|
+
if (relTarget.indexOf('/ppt/') === 0) relTarget = relTarget.substr(1)
|
|
184
|
+
else if (relTarget.indexOf('../') !== -1) relTarget = relTarget.replace('../', 'ppt/')
|
|
177
185
|
else relTarget = 'ppt/slides/' + relTarget
|
|
178
186
|
}
|
|
179
187
|
|
|
@@ -226,7 +234,9 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
226
234
|
for (const relationshipArrayItem of relationshipArray) {
|
|
227
235
|
const relType = relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', '')
|
|
228
236
|
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
229
|
-
|
|
237
|
+
relTarget = relTarget.replace(/\\/g, '/')
|
|
238
|
+
if (relTarget.indexOf('/ppt/') === 0) relTarget = relTarget.substr(1)
|
|
239
|
+
else if (relTarget.indexOf('../') !== -1) relTarget = relTarget.replace('../', 'ppt/')
|
|
230
240
|
else relTarget = 'ppt/slideLayouts/' + relTarget
|
|
231
241
|
|
|
232
242
|
switch (relationshipArrayItem['attrs']['Type']) {
|
|
@@ -252,7 +262,9 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
252
262
|
for (const relationshipArrayItem of relationshipArray) {
|
|
253
263
|
const relType = relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', '')
|
|
254
264
|
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
255
|
-
|
|
265
|
+
relTarget = relTarget.replace(/\\/g, '/')
|
|
266
|
+
if (relTarget.indexOf('/ppt/') === 0) relTarget = relTarget.substr(1)
|
|
267
|
+
else if (relTarget.indexOf('../') !== -1) relTarget = relTarget.replace('../', 'ppt/')
|
|
256
268
|
else relTarget = 'ppt/slideMasters/' + relTarget
|
|
257
269
|
|
|
258
270
|
switch (relationshipArrayItem['attrs']['Type']) {
|
|
@@ -267,10 +279,10 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
281
|
|
|
270
|
-
let currentThemeContent = themeContent
|
|
271
|
-
if (themeFilename) {
|
|
272
|
-
currentThemeContent =
|
|
273
|
-
const themeName = themeFilename.split('/').pop()
|
|
282
|
+
let currentThemeContent = themeContent
|
|
283
|
+
if (themeFilename) {
|
|
284
|
+
currentThemeContent = await readXmlFileCached(zip, themeFilename, xmlCache) || currentThemeContent
|
|
285
|
+
const themeName = themeFilename.split('/').pop()
|
|
274
286
|
const themeResFileName = themeFilename.replace(themeName, '_rels/' + themeName) + '.rels'
|
|
275
287
|
const themeResContent = await readXmlFile(zip, themeResFileName)
|
|
276
288
|
if (themeResContent) {
|
|
@@ -278,9 +290,14 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
|
|
|
278
290
|
if (relationshipArray) {
|
|
279
291
|
if (relationshipArray.constructor !== Array) relationshipArray = [relationshipArray]
|
|
280
292
|
for (const relationshipArrayItem of relationshipArray) {
|
|
293
|
+
let relTarget = relationshipArrayItem['attrs']['Target']
|
|
294
|
+
relTarget = relTarget.replace(/\\/g, '/')
|
|
295
|
+
if (relTarget.indexOf('/ppt/') === 0) relTarget = relTarget.substr(1)
|
|
296
|
+
else relTarget = relTarget.replace('../', 'ppt/')
|
|
297
|
+
|
|
281
298
|
themeResObj[relationshipArrayItem['attrs']['Id']] = {
|
|
282
299
|
'type': relationshipArrayItem['attrs']['Type'].replace('http://schemas.openxmlformats.org/officeDocument/2006/relationships/', ''),
|
|
283
|
-
'target':
|
|
300
|
+
'target': relTarget
|
|
284
301
|
}
|
|
285
302
|
}
|
|
286
303
|
}
|
|
@@ -558,6 +575,19 @@ async function processNodesInSlide(nodeKey, nodeValue, warpObj, source, groupHie
|
|
|
558
575
|
default:
|
|
559
576
|
}
|
|
560
577
|
|
|
578
|
+
if (json && typeof json === 'object' && !json.id) {
|
|
579
|
+
const id = getTextByPathList(nodeValue, ['p:nvSpPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
580
|
+
getTextByPathList(nodeValue, ['p:nvPicPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
581
|
+
getTextByPathList(nodeValue, ['p:nvCxnSpPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
582
|
+
getTextByPathList(nodeValue, ['p:nvGrpSpPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
583
|
+
getTextByPathList(nodeValue, ['p:nvGraphicFramePr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
584
|
+
getTextByPathList(nodeValue, ['mc:Choice', 'p:sp', 'p:nvSpPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
585
|
+
getTextByPathList(nodeValue, ['mc:Fallback', 'p:sp', 'p:nvSpPr', 'p:cNvPr', 'attrs', 'id']) ||
|
|
586
|
+
getTextByPathList(nodeValue, ['mc:Fallback', 'p:nvGrpSpPr', 'p:cNvPr', 'attrs', 'id'])
|
|
587
|
+
|
|
588
|
+
json.id = id || ''
|
|
589
|
+
}
|
|
590
|
+
|
|
561
591
|
return json
|
|
562
592
|
}
|
|
563
593
|
|
|
@@ -795,7 +825,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
795
825
|
let content = ''
|
|
796
826
|
if (node['p:txBody']) content = genTextBody(node['p:txBody'], node, slideLayoutSpNode, slideMasterSpNode, type, warpObj)
|
|
797
827
|
|
|
798
|
-
const { borderColor, borderWidth, borderType, strokeDasharray, headEnd, tailEnd } = getBorder(node, type, warpObj)
|
|
828
|
+
const { borderColor, borderWidth, borderType, strokeDasharray, headEnd, tailEnd } = getBorder(node, type, warpObj)
|
|
799
829
|
const fill = await getShapeFill(node, warpObj, source, {
|
|
800
830
|
groupHierarchy,
|
|
801
831
|
slideLayoutSpNode,
|
|
@@ -808,6 +838,7 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
808
838
|
|
|
809
839
|
const vAlign = getVerticalAlign(node, slideLayoutSpNode, slideMasterSpNode, type)
|
|
810
840
|
const isVertical = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'vert']) === 'eaVert'
|
|
841
|
+
const wrap = getTextByPathList(node, ['p:txBody', 'a:bodyPr', 'attrs', 'wrap']) !== 'none'
|
|
811
842
|
const autoFit = getTextAutoFit(node, slideLayoutSpNode, slideMasterSpNode)
|
|
812
843
|
const textInset = getTextInsets(node, slideLayoutSpNode, slideMasterSpNode)
|
|
813
844
|
|
|
@@ -826,16 +857,17 @@ async function genShape(node, slideLayoutSpNode, slideMasterSpNode, name, type,
|
|
|
826
857
|
isFlipH,
|
|
827
858
|
rotate,
|
|
828
859
|
vAlign,
|
|
860
|
+
wrap,
|
|
829
861
|
name,
|
|
830
862
|
order,
|
|
831
863
|
}
|
|
832
864
|
|
|
833
865
|
if (shadow) data.shadow = shadow
|
|
834
|
-
if (autoFit) data.autoFit = autoFit
|
|
835
|
-
if (link) data.link = link
|
|
836
|
-
if (textInset) data.textInset = textInset
|
|
837
|
-
if (headEnd) data.headEnd = headEnd
|
|
838
|
-
if (tailEnd) data.tailEnd = tailEnd
|
|
866
|
+
if (autoFit) data.autoFit = autoFit
|
|
867
|
+
if (link) data.link = link
|
|
868
|
+
if (textInset) data.textInset = textInset
|
|
869
|
+
if (headEnd) data.headEnd = headEnd
|
|
870
|
+
if (tailEnd) data.tailEnd = tailEnd
|
|
839
871
|
|
|
840
872
|
const isHasValidText = data.content && hasValidText(data.content)
|
|
841
873
|
|