@lofcz/pptxtojson 2.2.3 → 2.2.5
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/dist/index.cjs +170 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +170 -26
- 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/dist/index.js
CHANGED
|
@@ -3162,17 +3162,18 @@ function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMasterSpNode,
|
|
|
3162
3162
|
const align = getHorizontalAlign(pNode, spNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj);
|
|
3163
3163
|
const spacing = getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3164
3164
|
const indent = getParagraphIndent(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3165
|
-
const listType = getListType(pNode);
|
|
3165
|
+
const listType = getListType(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3166
3166
|
const listLevel = getListLevel(pNode);
|
|
3167
3167
|
let alignStyle = align;
|
|
3168
3168
|
if ('distribute' === align) alignStyle = 'justify';
|
|
3169
|
-
let styleText = `text-align: ${alignStyle}
|
|
3169
|
+
let styleText = `text-align: ${alignStyle};`;
|
|
3170
3170
|
if ('distribute' === align) styleText += "text-align-last: justify;text-justify: distribute;";
|
|
3171
3171
|
if (spacing) {
|
|
3172
3172
|
if (spacing.lineSpacing) styleText += `line-height: ${spacing.lineSpacing};`;
|
|
3173
|
+
else styleText += "line-height: 1.2;";
|
|
3173
3174
|
if (spacing.spaceBefore) styleText += `margin-top: ${spacing.spaceBefore};`;
|
|
3174
3175
|
if (spacing.spaceAfter) styleText += `margin-bottom: ${spacing.spaceAfter};`;
|
|
3175
|
-
}
|
|
3176
|
+
} else styleText += "line-height: 1.2;";
|
|
3176
3177
|
if (indent) {
|
|
3177
3178
|
if (!listType && indent.marginLeft) styleText += `margin-left: ${indent.marginLeft};`;
|
|
3178
3179
|
if (!listType && indent.textIndent) styleText += `text-indent: ${indent.textIndent};`;
|
|
@@ -3267,19 +3268,21 @@ function getMathRunStyleText(mathRun, siblingRun, pNode, textBodyNode, pFontStyl
|
|
|
3267
3268
|
if (fontColor && 'string' == typeof fontColor) styleText += `color: ${fontColor};`;
|
|
3268
3269
|
return styleText;
|
|
3269
3270
|
}
|
|
3270
|
-
function getListType(node) {
|
|
3271
|
-
const pPrNode = node['a:pPr'];
|
|
3272
|
-
if (!pPrNode) return '';
|
|
3273
|
-
if (pPrNode['a:buNone']) return '';
|
|
3271
|
+
function getListType(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
3274
3272
|
const hasContent = node['a:r'] || node['a:br'] || node['a:fld'];
|
|
3275
3273
|
if (!hasContent) return '';
|
|
3276
|
-
|
|
3277
|
-
if (
|
|
3274
|
+
const styleNodes = getParagraphStyleNodes(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3275
|
+
if (!styleNodes) return '';
|
|
3276
|
+
for (const styleNode of styleNodes){
|
|
3277
|
+
if (styleNode['a:buNone']) break;
|
|
3278
|
+
if (styleNode['a:buChar'] || styleNode['a:buBlip']) return 'ul';
|
|
3279
|
+
if (styleNode['a:buAutoNum']) return 'ol';
|
|
3280
|
+
}
|
|
3278
3281
|
return '';
|
|
3279
3282
|
}
|
|
3280
3283
|
function getListLevel(node) {
|
|
3281
3284
|
const pPrNode = node['a:pPr'];
|
|
3282
|
-
if (!pPrNode) return
|
|
3285
|
+
if (!pPrNode) return 0;
|
|
3283
3286
|
const lvlNode = getTextByPathList(pPrNode, [
|
|
3284
3287
|
'attrs',
|
|
3285
3288
|
'lvl'
|
|
@@ -3287,6 +3290,30 @@ function getListLevel(node) {
|
|
|
3287
3290
|
if (void 0 !== lvlNode) return parseInt(lvlNode);
|
|
3288
3291
|
return 0;
|
|
3289
3292
|
}
|
|
3293
|
+
function schemeColorToCss(color) {
|
|
3294
|
+
if (!color) return '';
|
|
3295
|
+
return color.startsWith('#') ? color : `#${color}`;
|
|
3296
|
+
}
|
|
3297
|
+
function applyHyperlinkRunStyle(styleText, node, warpObj) {
|
|
3298
|
+
let next = styleText;
|
|
3299
|
+
const runStyleNode = getTextByPathList(node, [
|
|
3300
|
+
'a:rPr'
|
|
3301
|
+
]);
|
|
3302
|
+
const runFill = runStyleNode ? getFillType(runStyleNode) : '';
|
|
3303
|
+
const runHasOwnColor = 'SOLID_FILL' === runFill || 'GRADIENT_FILL' === runFill;
|
|
3304
|
+
if (!runHasOwnColor) {
|
|
3305
|
+
const hlinkColor = schemeColorToCss(getSchemeColorFromTheme('a:hlink', warpObj)) || '#0563C1';
|
|
3306
|
+
if (/color\s*:/.test(next)) next = next.replace(/color\s*:\s*[^;]+;/, `color: ${hlinkColor};`);
|
|
3307
|
+
else next += `color: ${hlinkColor};`;
|
|
3308
|
+
}
|
|
3309
|
+
const runUnderline = getTextByPathList(node, [
|
|
3310
|
+
'a:rPr',
|
|
3311
|
+
'attrs',
|
|
3312
|
+
'u'
|
|
3313
|
+
]);
|
|
3314
|
+
if ('none' !== runUnderline && !/text-decoration\s*:\s*underline/.test(next)) next += 'text-decoration: underline;';
|
|
3315
|
+
return next;
|
|
3316
|
+
}
|
|
3290
3317
|
function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj) {
|
|
3291
3318
|
const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj);
|
|
3292
3319
|
const processedText = text.replace(/\t/g, ' ').replace(/\s/g, ' ');
|
|
@@ -3343,6 +3370,7 @@ function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNo
|
|
|
3343
3370
|
'r:id'
|
|
3344
3371
|
]);
|
|
3345
3372
|
const hasLink = linkID && warpObj['slideResObj'][linkID];
|
|
3373
|
+
if (hasLink) styleText = applyHyperlinkRunStyle(styleText, node, warpObj);
|
|
3346
3374
|
return {
|
|
3347
3375
|
styleText,
|
|
3348
3376
|
text,
|
|
@@ -9786,27 +9814,143 @@ async function parse(file, options = {}) {
|
|
|
9786
9814
|
}
|
|
9787
9815
|
};
|
|
9788
9816
|
}
|
|
9817
|
+
function asNodeArray(node) {
|
|
9818
|
+
if (!node) return [];
|
|
9819
|
+
return node.constructor === Array ? node : [
|
|
9820
|
+
node
|
|
9821
|
+
];
|
|
9822
|
+
}
|
|
9823
|
+
function sortSlideXml(p1, p2) {
|
|
9824
|
+
const n1 = +(/(\d+)\.xml/.exec(p1)?.[1] || 0);
|
|
9825
|
+
const n2 = +(/(\d+)\.xml/.exec(p2)?.[1] || 0);
|
|
9826
|
+
return n1 - n2;
|
|
9827
|
+
}
|
|
9828
|
+
function normalizePartName(name) {
|
|
9829
|
+
return String(name || '').replace(/\\/g, '/').replace(/^\//, '');
|
|
9830
|
+
}
|
|
9831
|
+
function relationshipsPartFor(partName) {
|
|
9832
|
+
const name = normalizePartName(partName);
|
|
9833
|
+
const slash = name.lastIndexOf('/');
|
|
9834
|
+
const dir = -1 === slash ? '' : name.slice(0, slash + 1);
|
|
9835
|
+
const file = -1 === slash ? name : name.slice(slash + 1);
|
|
9836
|
+
return `${dir}_rels/${file}.rels`;
|
|
9837
|
+
}
|
|
9838
|
+
function resolvePartTarget(sourcePart, target) {
|
|
9839
|
+
const raw = String(target || '').replace(/\\/g, '/');
|
|
9840
|
+
if (!raw) return '';
|
|
9841
|
+
if (raw.startsWith('/')) return normalizePartName(raw);
|
|
9842
|
+
const source = normalizePartName(sourcePart);
|
|
9843
|
+
const slash = source.lastIndexOf('/');
|
|
9844
|
+
const dir = -1 === slash ? '' : source.slice(0, slash + 1);
|
|
9845
|
+
const out = [];
|
|
9846
|
+
for (const seg of `${dir}${raw}`.split('/'))if (seg && '.' !== seg) if ('..' === seg) out.pop();
|
|
9847
|
+
else out.push(seg);
|
|
9848
|
+
return out.join('/');
|
|
9849
|
+
}
|
|
9850
|
+
function relationshipRid(attrs) {
|
|
9851
|
+
if (!attrs) return '';
|
|
9852
|
+
return attrs['r:id'] || attrs.rId || '';
|
|
9853
|
+
}
|
|
9854
|
+
async function getPresentationPart(zip) {
|
|
9855
|
+
const rels = asNodeArray(getTextByPathList(await readXmlFile(zip, '_rels/.rels'), [
|
|
9856
|
+
'Relationships',
|
|
9857
|
+
'Relationship'
|
|
9858
|
+
]));
|
|
9859
|
+
for (const rel of rels){
|
|
9860
|
+
const type = getTextByPathList(rel, [
|
|
9861
|
+
'attrs',
|
|
9862
|
+
'Type'
|
|
9863
|
+
]);
|
|
9864
|
+
const target = getTextByPathList(rel, [
|
|
9865
|
+
'attrs',
|
|
9866
|
+
'Target'
|
|
9867
|
+
]);
|
|
9868
|
+
const targetMode = getTextByPathList(rel, [
|
|
9869
|
+
'attrs',
|
|
9870
|
+
'TargetMode'
|
|
9871
|
+
]);
|
|
9872
|
+
if (!targetMode || 'external' !== String(targetMode).toLowerCase()) {
|
|
9873
|
+
if ('officeDocument' === getRelTypeName(type) && target) {
|
|
9874
|
+
const loc = resolvePartTarget('', target);
|
|
9875
|
+
if (loc) return loc;
|
|
9876
|
+
}
|
|
9877
|
+
}
|
|
9878
|
+
}
|
|
9879
|
+
return 'ppt/presentation.xml';
|
|
9880
|
+
}
|
|
9881
|
+
async function getSlidesFromPresentation(zip) {
|
|
9882
|
+
const presentationPart = await getPresentationPart(zip);
|
|
9883
|
+
const relItems = asNodeArray(getTextByPathList(await readXmlFile(zip, relationshipsPartFor(presentationPart)), [
|
|
9884
|
+
'Relationships',
|
|
9885
|
+
'Relationship'
|
|
9886
|
+
]));
|
|
9887
|
+
const relsMap = {};
|
|
9888
|
+
const slideTargets = [];
|
|
9889
|
+
for (const rel of relItems){
|
|
9890
|
+
const id = getTextByPathList(rel, [
|
|
9891
|
+
'attrs',
|
|
9892
|
+
'Id'
|
|
9893
|
+
]);
|
|
9894
|
+
const type = getTextByPathList(rel, [
|
|
9895
|
+
'attrs',
|
|
9896
|
+
'Type'
|
|
9897
|
+
]);
|
|
9898
|
+
const target = getTextByPathList(rel, [
|
|
9899
|
+
'attrs',
|
|
9900
|
+
'Target'
|
|
9901
|
+
]);
|
|
9902
|
+
const targetMode = getTextByPathList(rel, [
|
|
9903
|
+
'attrs',
|
|
9904
|
+
'TargetMode'
|
|
9905
|
+
]);
|
|
9906
|
+
if (!id || !target) continue;
|
|
9907
|
+
if (targetMode && 'external' === String(targetMode).toLowerCase()) continue;
|
|
9908
|
+
const loc = resolvePartTarget(presentationPart, target);
|
|
9909
|
+
if (loc) {
|
|
9910
|
+
relsMap[id] = loc;
|
|
9911
|
+
if ('slide' === getRelTypeName(type)) slideTargets.push(loc);
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9914
|
+
const presentation = await readXmlFile(zip, presentationPart);
|
|
9915
|
+
const sldIds = asNodeArray(getTextByPathList(presentation, [
|
|
9916
|
+
'p:presentation',
|
|
9917
|
+
'p:sldIdLst',
|
|
9918
|
+
'p:sldId'
|
|
9919
|
+
]));
|
|
9920
|
+
const ordered = [];
|
|
9921
|
+
for (const sldId of sldIds){
|
|
9922
|
+
const rid = relationshipRid(sldId?.attrs);
|
|
9923
|
+
if (rid && relsMap[rid]) ordered.push(relsMap[rid]);
|
|
9924
|
+
}
|
|
9925
|
+
if (ordered.length) return ordered;
|
|
9926
|
+
return slideTargets;
|
|
9927
|
+
}
|
|
9789
9928
|
async function getContentTypes(zip) {
|
|
9790
9929
|
const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
|
|
9791
|
-
const
|
|
9792
|
-
|
|
9930
|
+
const overrides = asNodeArray(getTextByPathList(ContentTypesJson, [
|
|
9931
|
+
'Types',
|
|
9932
|
+
'Override'
|
|
9933
|
+
]));
|
|
9934
|
+
const overrideSlides = [];
|
|
9793
9935
|
let slideLayoutsLocArray = [];
|
|
9794
|
-
for (const item of
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9936
|
+
for (const item of overrides){
|
|
9937
|
+
const contentType = item?.attrs?.ContentType;
|
|
9938
|
+
const partName = item?.attrs?.PartName;
|
|
9939
|
+
if (!contentType || !partName) continue;
|
|
9940
|
+
const loc = String(partName).replace(/^\//, '');
|
|
9941
|
+
switch(contentType){
|
|
9942
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
|
|
9943
|
+
overrideSlides.push(loc);
|
|
9944
|
+
break;
|
|
9945
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
|
|
9946
|
+
slideLayoutsLocArray.push(loc);
|
|
9947
|
+
break;
|
|
9948
|
+
default:
|
|
9949
|
+
}
|
|
9802
9950
|
}
|
|
9803
|
-
const sortSlideXml = (p1, p2)=>{
|
|
9804
|
-
const n1 = +/(\d+)\.xml/.exec(p1)[1];
|
|
9805
|
-
const n2 = +/(\d+)\.xml/.exec(p2)[1];
|
|
9806
|
-
return n1 - n2;
|
|
9807
|
-
};
|
|
9808
|
-
slidesLocArray = slidesLocArray.sort(sortSlideXml);
|
|
9809
9951
|
slideLayoutsLocArray = slideLayoutsLocArray.sort(sortSlideXml);
|
|
9952
|
+
let slidesLocArray = await getSlidesFromPresentation(zip);
|
|
9953
|
+
if (!slidesLocArray.length) slidesLocArray = overrideSlides.sort(sortSlideXml);
|
|
9810
9954
|
return {
|
|
9811
9955
|
slides: slidesLocArray,
|
|
9812
9956
|
slideLayouts: slideLayoutsLocArray
|