pptxtojson 0.0.1 → 0.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/README.md +24 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/index.html +4 -1
- package/package.json +4 -3
- package/rollup.config.js +5 -2
- package/src/pptxtojson.js +68 -68
- package/src/utils.js +2 -2
- package/dist/index.esm.js +0 -1
package/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jsoneditor@9.9.2/dist/jsoneditor.min.css">
|
|
13
13
|
<script src="https://cdn.jsdelivr.net/npm/jsoneditor@9.9.2/dist/jsoneditor.min.js"></script>
|
|
14
|
-
<script src="dist/index.js"></script>
|
|
14
|
+
<script src="dist/index.umd.js"></script>
|
|
15
15
|
|
|
16
16
|
<style>
|
|
17
17
|
* {
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
text-align: center;
|
|
76
76
|
cursor: pointer;
|
|
77
77
|
user-select: none;
|
|
78
|
+
margin-bottom: 20px;
|
|
78
79
|
}
|
|
79
80
|
.upload-input {
|
|
80
81
|
display: none;
|
|
@@ -88,6 +89,8 @@
|
|
|
88
89
|
点击上传 .pptx 文件
|
|
89
90
|
<input class="upload-input" type="file" accept="application/vnd.openxmlformats-officedocument.presentationml.presentation"/>
|
|
90
91
|
</div>
|
|
92
|
+
|
|
93
|
+
<a href="https://github.com/pipipi-pikachu/pptx2json">Github</a>
|
|
91
94
|
</div>
|
|
92
95
|
<div id="jsoneditor"></div>
|
|
93
96
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptxtojson",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A javascript tool for parsing .pptx file",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.
|
|
6
|
+
"main": "./dist/index.umd.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
8
9
|
"scripts": {
|
|
9
10
|
"clean:dist": "rimraf dist",
|
|
10
11
|
"dev": "rollup -c -w",
|
package/rollup.config.js
CHANGED
|
@@ -17,13 +17,16 @@ export default {
|
|
|
17
17
|
onwarn,
|
|
18
18
|
output: [
|
|
19
19
|
{
|
|
20
|
-
file: 'dist/index.js',
|
|
20
|
+
file: 'dist/index.umd.js',
|
|
21
21
|
format: 'umd',
|
|
22
22
|
name: 'pptxtojson',
|
|
23
|
+
sourcemap: true,
|
|
23
24
|
},
|
|
24
25
|
{
|
|
25
|
-
file: 'dist/index.
|
|
26
|
+
file: 'dist/index.js',
|
|
26
27
|
format: 'es',
|
|
28
|
+
name: 'pptxtojson',
|
|
29
|
+
sourcemap: true,
|
|
27
30
|
},
|
|
28
31
|
],
|
|
29
32
|
plugins: [
|
package/src/pptxtojson.js
CHANGED
|
@@ -4,7 +4,7 @@ import tinycolor from 'tinycolor2'
|
|
|
4
4
|
|
|
5
5
|
import { extractFileExtension, base64ArrayBuffer, eachElement, getTextByPathList, angleToDegrees } from './utils'
|
|
6
6
|
|
|
7
|
-
const FACTOR =
|
|
7
|
+
const FACTOR = 75 / 914400
|
|
8
8
|
|
|
9
9
|
let themeContent = null
|
|
10
10
|
|
|
@@ -321,6 +321,10 @@ function processSpNode(node, warpObj) {
|
|
|
321
321
|
slideMasterSpNode = warpObj['slideMasterTables']['idxTable'][idx]
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
if (!type) {
|
|
325
|
+
const txBoxVal = getTextByPathList(node, ['p:nvSpPr', 'p:cNvSpPr', 'attrs', 'txBox'])
|
|
326
|
+
if (txBoxVal === '1') type = 'text'
|
|
327
|
+
}
|
|
324
328
|
if (!type) type = getTextByPathList(slideLayoutSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
325
329
|
if (!type) type = getTextByPathList(slideMasterSpNode, ['p:nvSpPr', 'p:nvPr', 'p:ph', 'attrs', 'type'])
|
|
326
330
|
|
|
@@ -376,7 +380,7 @@ function genShape(node, slideLayoutSpNode, slideMasterSpNode, id, name, idx, typ
|
|
|
376
380
|
const fillColor = getShapeFill(node, true)
|
|
377
381
|
|
|
378
382
|
return {
|
|
379
|
-
type: 'shape',
|
|
383
|
+
type: type === 'text' ? 'text' : 'shape',
|
|
380
384
|
left,
|
|
381
385
|
top,
|
|
382
386
|
width,
|
|
@@ -494,59 +498,56 @@ function genTextBody(textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, w
|
|
|
494
498
|
let text = ''
|
|
495
499
|
const slideMasterTextStyles = warpObj['slideMasterTextStyles']
|
|
496
500
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
else if (rNode.constructor === Array) {
|
|
504
|
-
for (const rNodeItem of rNode) text += genSpanElement(rNodeItem, slideLayoutSpNode, type, warpObj)
|
|
505
|
-
}
|
|
506
|
-
else text += genSpanElement(rNode, slideLayoutSpNode, type, warpObj)
|
|
507
|
-
text += '</div>'
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
else {
|
|
511
|
-
const pNode = textBodyNode['a:p']
|
|
501
|
+
const pNode = textBodyNode['a:p']
|
|
502
|
+
const pNodes = pNode.constructor === Array ? pNode : [pNode]
|
|
503
|
+
|
|
504
|
+
let isList = ''
|
|
505
|
+
|
|
506
|
+
for (const pNode of pNodes) {
|
|
512
507
|
const rNode = pNode['a:r']
|
|
513
|
-
|
|
514
|
-
|
|
508
|
+
const align = getHorizontalAlign(pNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles)
|
|
509
|
+
|
|
510
|
+
const listType = getListType(pNode)
|
|
511
|
+
if (listType) {
|
|
512
|
+
if (!isList) {
|
|
513
|
+
text += `<${listType}>`
|
|
514
|
+
isList = listType
|
|
515
|
+
}
|
|
516
|
+
else if (isList && isList !== listType) {
|
|
517
|
+
text += `</${isList}>`
|
|
518
|
+
text += `<${listType}>`
|
|
519
|
+
isList = listType
|
|
520
|
+
}
|
|
521
|
+
text += `<li style="text-align: ${align};">`
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
if (isList) {
|
|
525
|
+
text += `</${isList}>`
|
|
526
|
+
isList = ''
|
|
527
|
+
}
|
|
528
|
+
text += `<p style="text-align: ${align};">`
|
|
529
|
+
}
|
|
530
|
+
|
|
515
531
|
if (!rNode) text += genSpanElement(pNode, slideLayoutSpNode, type, warpObj)
|
|
516
532
|
else if (rNode.constructor === Array) {
|
|
517
533
|
for (const rNodeItem of rNode) text += genSpanElement(rNodeItem, slideLayoutSpNode, type, warpObj)
|
|
518
534
|
}
|
|
519
535
|
else text += genSpanElement(rNode, slideLayoutSpNode, type, warpObj)
|
|
520
|
-
|
|
536
|
+
|
|
537
|
+
if (listType) text += '</li>'
|
|
538
|
+
else text += '</p>'
|
|
521
539
|
}
|
|
522
540
|
return text
|
|
523
541
|
}
|
|
524
542
|
|
|
525
|
-
function
|
|
543
|
+
function getListType(node) {
|
|
526
544
|
const pPrNode = node['a:pPr']
|
|
545
|
+
if (!pPrNode) return ''
|
|
527
546
|
|
|
528
|
-
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (buChar) {
|
|
533
|
-
const buFontAttrs = getTextByPathList(pPrNode, ['a:buFont', 'attrs'])
|
|
534
|
-
|
|
535
|
-
let marginLeft = parseInt(getTextByPathList(pPrNode, ['attrs', 'marL'])) * FACTOR
|
|
536
|
-
if (buFontAttrs) {
|
|
537
|
-
let marginRight = parseInt(buFontAttrs['pitchFamily'])
|
|
538
|
-
|
|
539
|
-
if (isNaN(marginLeft)) marginLeft = 328600 * FACTOR
|
|
540
|
-
if (isNaN(marginRight)) marginRight = 0
|
|
541
|
-
|
|
542
|
-
const typeface = buFontAttrs['typeface']
|
|
543
|
-
|
|
544
|
-
return `<span style="font-family: ${typeface}; margin-left: ${marginLeft * lvl}px; margin-right: ${marginRight}px; font-size: 20pt;">${buChar}</span>`
|
|
545
|
-
}
|
|
546
|
-
marginLeft = 328600 * FACTOR * lvl
|
|
547
|
-
return `<span style="margin-left: ${marginLeft}px;">${buChar}</span>`
|
|
548
|
-
}
|
|
549
|
-
return `<span style="margin-left: ${328600 * FACTOR * lvl}px; margin-right: 0;"></span>`
|
|
547
|
+
if (pPrNode['a:buChar']) return 'ul'
|
|
548
|
+
if (pPrNode['a:buAutoNum']) return 'ol'
|
|
549
|
+
|
|
550
|
+
return ''
|
|
550
551
|
}
|
|
551
552
|
|
|
552
553
|
function genSpanElement(node, slideLayoutSpNode, type, warpObj) {
|
|
@@ -556,22 +557,26 @@ function genSpanElement(node, slideLayoutSpNode, type, warpObj) {
|
|
|
556
557
|
if (typeof text !== 'string') text = getTextByPathList(node, ['a:fld', 'a:t'])
|
|
557
558
|
if (typeof text !== 'string') text = ' '
|
|
558
559
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
`
|
|
560
|
+
let styleText = ''
|
|
561
|
+
const fontColor = getFontColor(node)
|
|
562
|
+
const fontSize = getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles)
|
|
563
|
+
const fontType = getFontType(node, type)
|
|
564
|
+
const fontBold = getFontBold(node)
|
|
565
|
+
const fontItalic = getFontItalic(node)
|
|
566
|
+
const fontDecoration = getFontDecoration(node)
|
|
567
|
+
if (fontColor) styleText += `color: ${fontColor};`
|
|
568
|
+
if (fontSize) styleText += `font-size: ${fontSize};`
|
|
569
|
+
if (fontType) styleText += `font-family: ${fontType};`
|
|
570
|
+
if (fontBold) styleText += `font-weight: ${fontBold};`
|
|
571
|
+
if (fontItalic) styleText += `font-style: ${fontItalic};`
|
|
572
|
+
if (fontDecoration) styleText += `text-decoration: ${fontDecoration};`
|
|
568
573
|
|
|
569
574
|
const linkID = getTextByPathList(node, ['a:rPr', 'a:hlinkClick', 'attrs', 'r:id'])
|
|
570
575
|
if (linkID) {
|
|
571
576
|
const linkURL = warpObj['slideResObj'][linkID]['target']
|
|
572
|
-
return `<span
|
|
577
|
+
return `<span style="${styleText}"><a href="${linkURL}" target="_blank">${text.replace(/\s/i, ' ')}</a></span>`
|
|
573
578
|
}
|
|
574
|
-
return `<span
|
|
579
|
+
return `<span style="${styleText}">${text.replace(/\s/i, ' ')}</span>`
|
|
575
580
|
}
|
|
576
581
|
|
|
577
582
|
function genTable(node, warpObj) {
|
|
@@ -764,10 +769,10 @@ function getHorizontalAlign(node, slideLayoutSpNode, slideMasterSpNode, type, sl
|
|
|
764
769
|
}
|
|
765
770
|
}
|
|
766
771
|
if (!algn) {
|
|
767
|
-
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') return '
|
|
768
|
-
else if (type === 'sldNum') return '
|
|
772
|
+
if (type === 'title' || type === 'subTitle' || type === 'ctrTitle') return 'center'
|
|
773
|
+
else if (type === 'sldNum') return 'right'
|
|
769
774
|
}
|
|
770
|
-
return algn === 'ctr' ? '
|
|
775
|
+
return algn === 'ctr' ? 'center' : algn === 'r' ? 'right' : 'left'
|
|
771
776
|
}
|
|
772
777
|
|
|
773
778
|
function getFontType(node, type) {
|
|
@@ -787,12 +792,12 @@ function getFontType(node, type) {
|
|
|
787
792
|
}
|
|
788
793
|
}
|
|
789
794
|
|
|
790
|
-
return typeface || '
|
|
795
|
+
return typeface || ''
|
|
791
796
|
}
|
|
792
797
|
|
|
793
798
|
function getFontColor(node) {
|
|
794
799
|
const color = getTextByPathList(node, ['a:rPr', 'a:solidFill', 'a:srgbClr', 'attrs', 'val'])
|
|
795
|
-
return color ? `#${color}` : '
|
|
800
|
+
return color ? `#${color}` : ''
|
|
796
801
|
}
|
|
797
802
|
|
|
798
803
|
function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles) {
|
|
@@ -825,24 +830,19 @@ function getFontSize(node, slideLayoutSpNode, type, slideMasterTextStyles) {
|
|
|
825
830
|
const baseline = getTextByPathList(node, ['a:rPr', 'attrs', 'baseline'])
|
|
826
831
|
if (baseline && !isNaN(fontSize)) fontSize -= 10
|
|
827
832
|
|
|
828
|
-
return (isNaN(fontSize) || !fontSize) ? '
|
|
833
|
+
return (isNaN(fontSize) || !fontSize) ? '24px' : (fontSize / 0.75 + 'px')
|
|
829
834
|
}
|
|
830
835
|
|
|
831
836
|
function getFontBold(node) {
|
|
832
|
-
return (node['a:rPr'] && node['a:rPr']['attrs']['b'] === '1') ? 'bold' : '
|
|
837
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['b'] === '1') ? 'bold' : ''
|
|
833
838
|
}
|
|
834
839
|
|
|
835
840
|
function getFontItalic(node) {
|
|
836
|
-
return (node['a:rPr'] && node['a:rPr']['attrs']['i'] === '1') ? 'italic' : '
|
|
841
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['i'] === '1') ? 'italic' : ''
|
|
837
842
|
}
|
|
838
843
|
|
|
839
844
|
function getFontDecoration(node) {
|
|
840
|
-
return (node['a:rPr'] && node['a:rPr']['attrs']['u'] === 'sng') ? 'underline' : '
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
function getTextVerticalAlign(node) {
|
|
844
|
-
const baseline = getTextByPathList(node, ['a:rPr', 'attrs', 'baseline'])
|
|
845
|
-
return baseline ? (parseInt(baseline) / 1000) + '%' : 'baseline'
|
|
845
|
+
return (node['a:rPr'] && node['a:rPr']['attrs']['u'] === 'sng') ? 'underline' : ''
|
|
846
846
|
}
|
|
847
847
|
|
|
848
848
|
function getBorder(node, isSvgMode) {
|
package/src/utils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export function base64ArrayBuffer(arrayBuffer) {
|
|
2
|
-
let base64 = ''
|
|
3
2
|
const encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
4
3
|
const bytes = new Uint8Array(arrayBuffer)
|
|
5
4
|
const byteLength = bytes.byteLength
|
|
6
5
|
const byteRemainder = byteLength % 3
|
|
7
6
|
const mainLength = byteLength - byteRemainder
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
let base64 = ''
|
|
9
9
|
let a, b, c, d
|
|
10
10
|
let chunk
|
|
11
11
|
|