@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.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,
|
|
@@ -9818,27 +9846,143 @@ async function parse(file, options = {}) {
|
|
|
9818
9846
|
}
|
|
9819
9847
|
};
|
|
9820
9848
|
}
|
|
9849
|
+
function asNodeArray(node) {
|
|
9850
|
+
if (!node) return [];
|
|
9851
|
+
return node.constructor === Array ? node : [
|
|
9852
|
+
node
|
|
9853
|
+
];
|
|
9854
|
+
}
|
|
9855
|
+
function sortSlideXml(p1, p2) {
|
|
9856
|
+
const n1 = +(/(\d+)\.xml/.exec(p1)?.[1] || 0);
|
|
9857
|
+
const n2 = +(/(\d+)\.xml/.exec(p2)?.[1] || 0);
|
|
9858
|
+
return n1 - n2;
|
|
9859
|
+
}
|
|
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('/');
|
|
9881
|
+
}
|
|
9882
|
+
function relationshipRid(attrs) {
|
|
9883
|
+
if (!attrs) return '';
|
|
9884
|
+
return attrs['r:id'] || attrs.rId || '';
|
|
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
|
+
}
|
|
9913
|
+
async function getSlidesFromPresentation(zip) {
|
|
9914
|
+
const presentationPart = await getPresentationPart(zip);
|
|
9915
|
+
const relItems = asNodeArray(getTextByPathList(await readXmlFile(zip, relationshipsPartFor(presentationPart)), [
|
|
9916
|
+
'Relationships',
|
|
9917
|
+
'Relationship'
|
|
9918
|
+
]));
|
|
9919
|
+
const relsMap = {};
|
|
9920
|
+
const slideTargets = [];
|
|
9921
|
+
for (const rel of relItems){
|
|
9922
|
+
const id = getTextByPathList(rel, [
|
|
9923
|
+
'attrs',
|
|
9924
|
+
'Id'
|
|
9925
|
+
]);
|
|
9926
|
+
const type = getTextByPathList(rel, [
|
|
9927
|
+
'attrs',
|
|
9928
|
+
'Type'
|
|
9929
|
+
]);
|
|
9930
|
+
const target = getTextByPathList(rel, [
|
|
9931
|
+
'attrs',
|
|
9932
|
+
'Target'
|
|
9933
|
+
]);
|
|
9934
|
+
const targetMode = getTextByPathList(rel, [
|
|
9935
|
+
'attrs',
|
|
9936
|
+
'TargetMode'
|
|
9937
|
+
]);
|
|
9938
|
+
if (!id || !target) continue;
|
|
9939
|
+
if (targetMode && 'external' === String(targetMode).toLowerCase()) continue;
|
|
9940
|
+
const loc = resolvePartTarget(presentationPart, target);
|
|
9941
|
+
if (loc) {
|
|
9942
|
+
relsMap[id] = loc;
|
|
9943
|
+
if ('slide' === getRelTypeName(type)) slideTargets.push(loc);
|
|
9944
|
+
}
|
|
9945
|
+
}
|
|
9946
|
+
const presentation = await readXmlFile(zip, presentationPart);
|
|
9947
|
+
const sldIds = asNodeArray(getTextByPathList(presentation, [
|
|
9948
|
+
'p:presentation',
|
|
9949
|
+
'p:sldIdLst',
|
|
9950
|
+
'p:sldId'
|
|
9951
|
+
]));
|
|
9952
|
+
const ordered = [];
|
|
9953
|
+
for (const sldId of sldIds){
|
|
9954
|
+
const rid = relationshipRid(sldId?.attrs);
|
|
9955
|
+
if (rid && relsMap[rid]) ordered.push(relsMap[rid]);
|
|
9956
|
+
}
|
|
9957
|
+
if (ordered.length) return ordered;
|
|
9958
|
+
return slideTargets;
|
|
9959
|
+
}
|
|
9821
9960
|
async function getContentTypes(zip) {
|
|
9822
9961
|
const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
|
|
9823
|
-
const
|
|
9824
|
-
|
|
9962
|
+
const overrides = asNodeArray(getTextByPathList(ContentTypesJson, [
|
|
9963
|
+
'Types',
|
|
9964
|
+
'Override'
|
|
9965
|
+
]));
|
|
9966
|
+
const overrideSlides = [];
|
|
9825
9967
|
let slideLayoutsLocArray = [];
|
|
9826
|
-
for (const item of
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9968
|
+
for (const item of overrides){
|
|
9969
|
+
const contentType = item?.attrs?.ContentType;
|
|
9970
|
+
const partName = item?.attrs?.PartName;
|
|
9971
|
+
if (!contentType || !partName) continue;
|
|
9972
|
+
const loc = String(partName).replace(/^\//, '');
|
|
9973
|
+
switch(contentType){
|
|
9974
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
|
|
9975
|
+
overrideSlides.push(loc);
|
|
9976
|
+
break;
|
|
9977
|
+
case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
|
|
9978
|
+
slideLayoutsLocArray.push(loc);
|
|
9979
|
+
break;
|
|
9980
|
+
default:
|
|
9981
|
+
}
|
|
9834
9982
|
}
|
|
9835
|
-
const sortSlideXml = (p1, p2)=>{
|
|
9836
|
-
const n1 = +/(\d+)\.xml/.exec(p1)[1];
|
|
9837
|
-
const n2 = +/(\d+)\.xml/.exec(p2)[1];
|
|
9838
|
-
return n1 - n2;
|
|
9839
|
-
};
|
|
9840
|
-
slidesLocArray = slidesLocArray.sort(sortSlideXml);
|
|
9841
9983
|
slideLayoutsLocArray = slideLayoutsLocArray.sort(sortSlideXml);
|
|
9984
|
+
let slidesLocArray = await getSlidesFromPresentation(zip);
|
|
9985
|
+
if (!slidesLocArray.length) slidesLocArray = overrideSlides.sort(sortSlideXml);
|
|
9842
9986
|
return {
|
|
9843
9987
|
slides: slidesLocArray,
|
|
9844
9988
|
slideLayouts: slideLayoutsLocArray
|