@lofcz/pptxtojson 2.2.4 → 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 +100 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +100 -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.cjs
CHANGED
|
@@ -3194,17 +3194,18 @@ function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMasterSpNode,
|
|
|
3194
3194
|
const align = getHorizontalAlign(pNode, spNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj);
|
|
3195
3195
|
const spacing = getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3196
3196
|
const indent = getParagraphIndent(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3197
|
-
const listType = getListType(pNode);
|
|
3197
|
+
const listType = getListType(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3198
3198
|
const listLevel = getListLevel(pNode);
|
|
3199
3199
|
let alignStyle = align;
|
|
3200
3200
|
if ('distribute' === align) alignStyle = 'justify';
|
|
3201
|
-
let styleText = `text-align: ${alignStyle}
|
|
3201
|
+
let styleText = `text-align: ${alignStyle};`;
|
|
3202
3202
|
if ('distribute' === align) styleText += "text-align-last: justify;text-justify: distribute;";
|
|
3203
3203
|
if (spacing) {
|
|
3204
3204
|
if (spacing.lineSpacing) styleText += `line-height: ${spacing.lineSpacing};`;
|
|
3205
|
+
else styleText += "line-height: 1.2;";
|
|
3205
3206
|
if (spacing.spaceBefore) styleText += `margin-top: ${spacing.spaceBefore};`;
|
|
3206
3207
|
if (spacing.spaceAfter) styleText += `margin-bottom: ${spacing.spaceAfter};`;
|
|
3207
|
-
}
|
|
3208
|
+
} else styleText += "line-height: 1.2;";
|
|
3208
3209
|
if (indent) {
|
|
3209
3210
|
if (!listType && indent.marginLeft) styleText += `margin-left: ${indent.marginLeft};`;
|
|
3210
3211
|
if (!listType && indent.textIndent) styleText += `text-indent: ${indent.textIndent};`;
|
|
@@ -3299,19 +3300,21 @@ function getMathRunStyleText(mathRun, siblingRun, pNode, textBodyNode, pFontStyl
|
|
|
3299
3300
|
if (fontColor && 'string' == typeof fontColor) styleText += `color: ${fontColor};`;
|
|
3300
3301
|
return styleText;
|
|
3301
3302
|
}
|
|
3302
|
-
function getListType(node) {
|
|
3303
|
-
const pPrNode = node['a:pPr'];
|
|
3304
|
-
if (!pPrNode) return '';
|
|
3305
|
-
if (pPrNode['a:buNone']) return '';
|
|
3303
|
+
function getListType(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
|
|
3306
3304
|
const hasContent = node['a:r'] || node['a:br'] || node['a:fld'];
|
|
3307
3305
|
if (!hasContent) return '';
|
|
3308
|
-
|
|
3309
|
-
if (
|
|
3306
|
+
const styleNodes = getParagraphStyleNodes(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
|
|
3307
|
+
if (!styleNodes) return '';
|
|
3308
|
+
for (const styleNode of styleNodes){
|
|
3309
|
+
if (styleNode['a:buNone']) break;
|
|
3310
|
+
if (styleNode['a:buChar'] || styleNode['a:buBlip']) return 'ul';
|
|
3311
|
+
if (styleNode['a:buAutoNum']) return 'ol';
|
|
3312
|
+
}
|
|
3310
3313
|
return '';
|
|
3311
3314
|
}
|
|
3312
3315
|
function getListLevel(node) {
|
|
3313
3316
|
const pPrNode = node['a:pPr'];
|
|
3314
|
-
if (!pPrNode) return
|
|
3317
|
+
if (!pPrNode) return 0;
|
|
3315
3318
|
const lvlNode = getTextByPathList(pPrNode, [
|
|
3316
3319
|
'attrs',
|
|
3317
3320
|
'lvl'
|
|
@@ -3319,6 +3322,30 @@ function getListLevel(node) {
|
|
|
3319
3322
|
if (void 0 !== lvlNode) return parseInt(lvlNode);
|
|
3320
3323
|
return 0;
|
|
3321
3324
|
}
|
|
3325
|
+
function schemeColorToCss(color) {
|
|
3326
|
+
if (!color) return '';
|
|
3327
|
+
return color.startsWith('#') ? color : `#${color}`;
|
|
3328
|
+
}
|
|
3329
|
+
function applyHyperlinkRunStyle(styleText, node, warpObj) {
|
|
3330
|
+
let next = styleText;
|
|
3331
|
+
const runStyleNode = getTextByPathList(node, [
|
|
3332
|
+
'a:rPr'
|
|
3333
|
+
]);
|
|
3334
|
+
const runFill = runStyleNode ? getFillType(runStyleNode) : '';
|
|
3335
|
+
const runHasOwnColor = 'SOLID_FILL' === runFill || 'GRADIENT_FILL' === runFill;
|
|
3336
|
+
if (!runHasOwnColor) {
|
|
3337
|
+
const hlinkColor = schemeColorToCss(getSchemeColorFromTheme('a:hlink', warpObj)) || '#0563C1';
|
|
3338
|
+
if (/color\s*:/.test(next)) next = next.replace(/color\s*:\s*[^;]+;/, `color: ${hlinkColor};`);
|
|
3339
|
+
else next += `color: ${hlinkColor};`;
|
|
3340
|
+
}
|
|
3341
|
+
const runUnderline = getTextByPathList(node, [
|
|
3342
|
+
'a:rPr',
|
|
3343
|
+
'attrs',
|
|
3344
|
+
'u'
|
|
3345
|
+
]);
|
|
3346
|
+
if ('none' !== runUnderline && !/text-decoration\s*:\s*underline/.test(next)) next += 'text-decoration: underline;';
|
|
3347
|
+
return next;
|
|
3348
|
+
}
|
|
3322
3349
|
function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj) {
|
|
3323
3350
|
const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj);
|
|
3324
3351
|
const processedText = text.replace(/\t/g, ' ').replace(/\s/g, ' ');
|
|
@@ -3375,6 +3402,7 @@ function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNo
|
|
|
3375
3402
|
'r:id'
|
|
3376
3403
|
]);
|
|
3377
3404
|
const hasLink = linkID && warpObj['slideResObj'][linkID];
|
|
3405
|
+
if (hasLink) styleText = applyHyperlinkRunStyle(styleText, node, warpObj);
|
|
3378
3406
|
return {
|
|
3379
3407
|
styleText,
|
|
3380
3408
|
text,
|
|
@@ -9829,21 +9857,62 @@ function sortSlideXml(p1, p2) {
|
|
|
9829
9857
|
const n2 = +(/(\d+)\.xml/.exec(p2)?.[1] || 0);
|
|
9830
9858
|
return n1 - n2;
|
|
9831
9859
|
}
|
|
9832
|
-
function
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9860
|
+
function normalizePartName(name) {
|
|
9861
|
+
return String(name || '').replace(/\\/g, '/').replace(/^\//, '');
|
|
9862
|
+
}
|
|
9863
|
+
function relationshipsPartFor(partName) {
|
|
9864
|
+
const name = normalizePartName(partName);
|
|
9865
|
+
const slash = name.lastIndexOf('/');
|
|
9866
|
+
const dir = -1 === slash ? '' : name.slice(0, slash + 1);
|
|
9867
|
+
const file = -1 === slash ? name : name.slice(slash + 1);
|
|
9868
|
+
return `${dir}_rels/${file}.rels`;
|
|
9869
|
+
}
|
|
9870
|
+
function resolvePartTarget(sourcePart, target) {
|
|
9871
|
+
const raw = String(target || '').replace(/\\/g, '/');
|
|
9872
|
+
if (!raw) return '';
|
|
9873
|
+
if (raw.startsWith('/')) return normalizePartName(raw);
|
|
9874
|
+
const source = normalizePartName(sourcePart);
|
|
9875
|
+
const slash = source.lastIndexOf('/');
|
|
9876
|
+
const dir = -1 === slash ? '' : source.slice(0, slash + 1);
|
|
9877
|
+
const out = [];
|
|
9878
|
+
for (const seg of `${dir}${raw}`.split('/'))if (seg && '.' !== seg) if ('..' === seg) out.pop();
|
|
9879
|
+
else out.push(seg);
|
|
9880
|
+
return out.join('/');
|
|
9839
9881
|
}
|
|
9840
9882
|
function relationshipRid(attrs) {
|
|
9841
9883
|
if (!attrs) return '';
|
|
9842
9884
|
return attrs['r:id'] || attrs.rId || '';
|
|
9843
9885
|
}
|
|
9886
|
+
async function getPresentationPart(zip) {
|
|
9887
|
+
const rels = asNodeArray(getTextByPathList(await readXmlFile(zip, '_rels/.rels'), [
|
|
9888
|
+
'Relationships',
|
|
9889
|
+
'Relationship'
|
|
9890
|
+
]));
|
|
9891
|
+
for (const rel of rels){
|
|
9892
|
+
const type = getTextByPathList(rel, [
|
|
9893
|
+
'attrs',
|
|
9894
|
+
'Type'
|
|
9895
|
+
]);
|
|
9896
|
+
const target = getTextByPathList(rel, [
|
|
9897
|
+
'attrs',
|
|
9898
|
+
'Target'
|
|
9899
|
+
]);
|
|
9900
|
+
const targetMode = getTextByPathList(rel, [
|
|
9901
|
+
'attrs',
|
|
9902
|
+
'TargetMode'
|
|
9903
|
+
]);
|
|
9904
|
+
if (!targetMode || 'external' !== String(targetMode).toLowerCase()) {
|
|
9905
|
+
if ('officeDocument' === getRelTypeName(type) && target) {
|
|
9906
|
+
const loc = resolvePartTarget('', target);
|
|
9907
|
+
if (loc) return loc;
|
|
9908
|
+
}
|
|
9909
|
+
}
|
|
9910
|
+
}
|
|
9911
|
+
return 'ppt/presentation.xml';
|
|
9912
|
+
}
|
|
9844
9913
|
async function getSlidesFromPresentation(zip) {
|
|
9845
|
-
const
|
|
9846
|
-
const relItems = asNodeArray(getTextByPathList(
|
|
9914
|
+
const presentationPart = await getPresentationPart(zip);
|
|
9915
|
+
const relItems = asNodeArray(getTextByPathList(await readXmlFile(zip, relationshipsPartFor(presentationPart)), [
|
|
9847
9916
|
'Relationships',
|
|
9848
9917
|
'Relationship'
|
|
9849
9918
|
]));
|
|
@@ -9862,14 +9931,19 @@ async function getSlidesFromPresentation(zip) {
|
|
|
9862
9931
|
'attrs',
|
|
9863
9932
|
'Target'
|
|
9864
9933
|
]);
|
|
9934
|
+
const targetMode = getTextByPathList(rel, [
|
|
9935
|
+
'attrs',
|
|
9936
|
+
'TargetMode'
|
|
9937
|
+
]);
|
|
9865
9938
|
if (!id || !target) continue;
|
|
9866
|
-
|
|
9939
|
+
if (targetMode && 'external' === String(targetMode).toLowerCase()) continue;
|
|
9940
|
+
const loc = resolvePartTarget(presentationPart, target);
|
|
9867
9941
|
if (loc) {
|
|
9868
9942
|
relsMap[id] = loc;
|
|
9869
9943
|
if ('slide' === getRelTypeName(type)) slideTargets.push(loc);
|
|
9870
9944
|
}
|
|
9871
9945
|
}
|
|
9872
|
-
const presentation = await readXmlFile(zip,
|
|
9946
|
+
const presentation = await readXmlFile(zip, presentationPart);
|
|
9873
9947
|
const sldIds = asNodeArray(getTextByPathList(presentation, [
|
|
9874
9948
|
'p:presentation',
|
|
9875
9949
|
'p:sldIdLst',
|
|
@@ -9881,7 +9955,7 @@ async function getSlidesFromPresentation(zip) {
|
|
|
9881
9955
|
if (rid && relsMap[rid]) ordered.push(relsMap[rid]);
|
|
9882
9956
|
}
|
|
9883
9957
|
if (ordered.length) return ordered;
|
|
9884
|
-
return slideTargets
|
|
9958
|
+
return slideTargets;
|
|
9885
9959
|
}
|
|
9886
9960
|
async function getContentTypes(zip) {
|
|
9887
9961
|
const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
|
|
@@ -9889,7 +9963,7 @@ async function getContentTypes(zip) {
|
|
|
9889
9963
|
'Types',
|
|
9890
9964
|
'Override'
|
|
9891
9965
|
]));
|
|
9892
|
-
|
|
9966
|
+
const overrideSlides = [];
|
|
9893
9967
|
let slideLayoutsLocArray = [];
|
|
9894
9968
|
for (const item of overrides){
|
|
9895
9969
|
const contentType = item?.attrs?.ContentType;
|
|
@@ -9898,7 +9972,7 @@ async function getContentTypes(zip) {
|
|
|
9898
9972
|
const loc = String(partName).replace(/^\//, '');
|
|
9899
9973
|
switch(contentType){
|
|
9900
9974
|
case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
|
|
9901
|
-
|
|
9975
|
+
overrideSlides.push(loc);
|
|
9902
9976
|
break;
|
|
9903
9977
|
case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
|
|
9904
9978
|
slideLayoutsLocArray.push(loc);
|
|
@@ -9906,9 +9980,9 @@ async function getContentTypes(zip) {
|
|
|
9906
9980
|
default:
|
|
9907
9981
|
}
|
|
9908
9982
|
}
|
|
9909
|
-
slidesLocArray = slidesLocArray.sort(sortSlideXml);
|
|
9910
9983
|
slideLayoutsLocArray = slideLayoutsLocArray.sort(sortSlideXml);
|
|
9911
|
-
|
|
9984
|
+
let slidesLocArray = await getSlidesFromPresentation(zip);
|
|
9985
|
+
if (!slidesLocArray.length) slidesLocArray = overrideSlides.sort(sortSlideXml);
|
|
9912
9986
|
return {
|
|
9913
9987
|
slides: slidesLocArray,
|
|
9914
9988
|
slideLayouts: slideLayoutsLocArray
|