@lofcz/pptxtojson 2.2.4 → 2.2.6

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 CHANGED
@@ -2732,10 +2732,25 @@ function findOMath(obj) {
2732
2732
  });
2733
2733
  return results;
2734
2734
  }
2735
+ function localName(tag) {
2736
+ if (!tag) return '';
2737
+ const i = tag.indexOf(':');
2738
+ return i >= 0 ? tag.slice(i + 1) : tag;
2739
+ }
2740
+ function firstRawOMath(node) {
2741
+ if (!node || 'object' != typeof node) return null;
2742
+ if ('oMath' === localName(node.tagName)) return node;
2743
+ for (const child of node.children || [])if ('object' == typeof child) {
2744
+ const found = firstRawOMath(child);
2745
+ if (found) return found;
2746
+ }
2747
+ return null;
2748
+ }
2735
2749
  function oMathToLatex(simplifiedNode) {
2736
2750
  const rawNode = simplifiedNode && simplifiedNode.__rawNode;
2737
2751
  if (!rawNode) return '';
2738
- return latexFormart((0, external_dwml_ts_namespaceObject.ommlNodeToLatex)(rawNode)).trim();
2752
+ const math = firstRawOMath(rawNode) || rawNode;
2753
+ return latexFormart((0, external_dwml_ts_namespaceObject.ommlNodeToLatex)(math)).trim();
2739
2754
  }
2740
2755
  const toArray = (value)=>{
2741
2756
  if (!value) return [];
@@ -2743,6 +2758,17 @@ const toArray = (value)=>{
2743
2758
  value
2744
2759
  ];
2745
2760
  };
2761
+ function mathPayloads(container) {
2762
+ const direct = toArray(container && container['m:oMath']);
2763
+ if (direct.length) return direct;
2764
+ const out = [];
2765
+ for (const para of toArray(container && container['m:oMathPara'])){
2766
+ const inner = toArray(para['m:oMath']);
2767
+ if (inner.length) out.push(...inner);
2768
+ else out.push(para);
2769
+ }
2770
+ return out;
2771
+ }
2746
2772
  function getInlineMathRuns(pNode) {
2747
2773
  const runs = [];
2748
2774
  const push = (node, order)=>{
@@ -2758,15 +2784,9 @@ function getInlineMathRuns(pNode) {
2758
2784
  };
2759
2785
  for (const wrapper of toArray(pNode['a14:m'])){
2760
2786
  const order = wrapper && wrapper.attrs && wrapper.attrs.order || 0;
2761
- for (const key of [
2762
- 'm:oMath',
2763
- 'm:oMathPara'
2764
- ])for (const node of toArray(wrapper[key]))push(node, order);
2765
- }
2766
- for (const key of [
2767
- 'm:oMath',
2768
- 'm:oMathPara'
2769
- ])for (const node of toArray(pNode[key]))push(node, node && node.attrs && node.attrs.order || 0);
2787
+ for (const node of mathPayloads(wrapper))push(node, order);
2788
+ }
2789
+ for (const node of mathPayloads(pNode))push(node, node && node.attrs && node.attrs.order || 0);
2770
2790
  return runs;
2771
2791
  }
2772
2792
  const findMathRunPr = (node, skipCtrlPr)=>{
@@ -3194,17 +3214,18 @@ function genTextBody(textBodyNode, spNode, slideLayoutSpNode, slideMasterSpNode,
3194
3214
  const align = getHorizontalAlign(pNode, spNode, type, slideLayoutSpNode, slideMasterSpNode, warpObj);
3195
3215
  const spacing = getParagraphSpacing(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
3196
3216
  const indent = getParagraphIndent(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
3197
- const listType = getListType(pNode);
3217
+ const listType = getListType(pNode, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
3198
3218
  const listLevel = getListLevel(pNode);
3199
3219
  let alignStyle = align;
3200
3220
  if ('distribute' === align) alignStyle = 'justify';
3201
- let styleText = `text-align: ${alignStyle};line-height: 1.2;`;
3221
+ let styleText = `text-align: ${alignStyle};`;
3202
3222
  if ('distribute' === align) styleText += "text-align-last: justify;text-justify: distribute;";
3203
3223
  if (spacing) {
3204
3224
  if (spacing.lineSpacing) styleText += `line-height: ${spacing.lineSpacing};`;
3225
+ else styleText += "line-height: 1.2;";
3205
3226
  if (spacing.spaceBefore) styleText += `margin-top: ${spacing.spaceBefore};`;
3206
3227
  if (spacing.spaceAfter) styleText += `margin-bottom: ${spacing.spaceAfter};`;
3207
- }
3228
+ } else styleText += "line-height: 1.2;";
3208
3229
  if (indent) {
3209
3230
  if (!listType && indent.marginLeft) styleText += `margin-left: ${indent.marginLeft};`;
3210
3231
  if (!listType && indent.textIndent) styleText += `text-indent: ${indent.textIndent};`;
@@ -3299,19 +3320,21 @@ function getMathRunStyleText(mathRun, siblingRun, pNode, textBodyNode, pFontStyl
3299
3320
  if (fontColor && 'string' == typeof fontColor) styleText += `color: ${fontColor};`;
3300
3321
  return styleText;
3301
3322
  }
3302
- function getListType(node) {
3303
- const pPrNode = node['a:pPr'];
3304
- if (!pPrNode) return '';
3305
- if (pPrNode['a:buNone']) return '';
3323
+ function getListType(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj) {
3306
3324
  const hasContent = node['a:r'] || node['a:br'] || node['a:fld'];
3307
3325
  if (!hasContent) return '';
3308
- if (pPrNode['a:buChar']) return 'ul';
3309
- if (pPrNode['a:buAutoNum']) return 'ol';
3326
+ const styleNodes = getParagraphStyleNodes(node, textBodyNode, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, warpObj);
3327
+ if (!styleNodes) return '';
3328
+ for (const styleNode of styleNodes){
3329
+ if (styleNode['a:buNone']) break;
3330
+ if (styleNode['a:buChar'] || styleNode['a:buBlip']) return 'ul';
3331
+ if (styleNode['a:buAutoNum']) return 'ol';
3332
+ }
3310
3333
  return '';
3311
3334
  }
3312
3335
  function getListLevel(node) {
3313
3336
  const pPrNode = node['a:pPr'];
3314
- if (!pPrNode) return -1;
3337
+ if (!pPrNode) return 0;
3315
3338
  const lvlNode = getTextByPathList(pPrNode, [
3316
3339
  'attrs',
3317
3340
  'lvl'
@@ -3319,6 +3342,30 @@ function getListLevel(node) {
3319
3342
  if (void 0 !== lvlNode) return parseInt(lvlNode);
3320
3343
  return 0;
3321
3344
  }
3345
+ function schemeColorToCss(color) {
3346
+ if (!color) return '';
3347
+ return color.startsWith('#') ? color : `#${color}`;
3348
+ }
3349
+ function applyHyperlinkRunStyle(styleText, node, warpObj) {
3350
+ let next = styleText;
3351
+ const runStyleNode = getTextByPathList(node, [
3352
+ 'a:rPr'
3353
+ ]);
3354
+ const runFill = runStyleNode ? getFillType(runStyleNode) : '';
3355
+ const runHasOwnColor = 'SOLID_FILL' === runFill || 'GRADIENT_FILL' === runFill;
3356
+ if (!runHasOwnColor) {
3357
+ const hlinkColor = schemeColorToCss(getSchemeColorFromTheme('a:hlink', warpObj)) || '#0563C1';
3358
+ if (/color\s*:/.test(next)) next = next.replace(/color\s*:\s*[^;]+;/, `color: ${hlinkColor};`);
3359
+ else next += `color: ${hlinkColor};`;
3360
+ }
3361
+ const runUnderline = getTextByPathList(node, [
3362
+ 'a:rPr',
3363
+ 'attrs',
3364
+ 'u'
3365
+ ]);
3366
+ if ('none' !== runUnderline && !/text-decoration\s*:\s*underline/.test(next)) next += 'text-decoration: underline;';
3367
+ return next;
3368
+ }
3322
3369
  function genSpanElement(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj) {
3323
3370
  const { styleText, text, hasLink, linkURL } = getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNode, slideMasterSpNode, type, slideMasterTextStyles, defaultTextStyle, warpObj);
3324
3371
  const processedText = text.replace(/\t/g, '    ').replace(/\s/g, ' ');
@@ -3375,6 +3422,7 @@ function getSpanStyleInfo(node, pNode, textBodyNode, pFontStyle, slideLayoutSpNo
3375
3422
  'r:id'
3376
3423
  ]);
3377
3424
  const hasLink = linkID && warpObj['slideResObj'][linkID];
3425
+ if (hasLink) styleText = applyHyperlinkRunStyle(styleText, node, warpObj);
3378
3426
  return {
3379
3427
  styleText,
3380
3428
  text,
@@ -9829,21 +9877,62 @@ function sortSlideXml(p1, p2) {
9829
9877
  const n2 = +(/(\d+)\.xml/.exec(p2)?.[1] || 0);
9830
9878
  return n1 - n2;
9831
9879
  }
9832
- function resolvePresentationTarget(target) {
9833
- let relTarget = String(target || '').replace(/\\/g, '/');
9834
- if (!relTarget) return '';
9835
- if (0 === relTarget.indexOf('/ppt/')) return relTarget.substr(1);
9836
- if (-1 !== relTarget.indexOf('../')) return relTarget.replace('../', 'ppt/');
9837
- if (0 === relTarget.indexOf('ppt/')) return relTarget;
9838
- return 'ppt/' + relTarget.replace(/^\//, '');
9880
+ function normalizePartName(name) {
9881
+ return String(name || '').replace(/\\/g, '/').replace(/^\//, '');
9882
+ }
9883
+ function relationshipsPartFor(partName) {
9884
+ const name = normalizePartName(partName);
9885
+ const slash = name.lastIndexOf('/');
9886
+ const dir = -1 === slash ? '' : name.slice(0, slash + 1);
9887
+ const file = -1 === slash ? name : name.slice(slash + 1);
9888
+ return `${dir}_rels/${file}.rels`;
9889
+ }
9890
+ function resolvePartTarget(sourcePart, target) {
9891
+ const raw = String(target || '').replace(/\\/g, '/');
9892
+ if (!raw) return '';
9893
+ if (raw.startsWith('/')) return normalizePartName(raw);
9894
+ const source = normalizePartName(sourcePart);
9895
+ const slash = source.lastIndexOf('/');
9896
+ const dir = -1 === slash ? '' : source.slice(0, slash + 1);
9897
+ const out = [];
9898
+ for (const seg of `${dir}${raw}`.split('/'))if (seg && '.' !== seg) if ('..' === seg) out.pop();
9899
+ else out.push(seg);
9900
+ return out.join('/');
9839
9901
  }
9840
9902
  function relationshipRid(attrs) {
9841
9903
  if (!attrs) return '';
9842
9904
  return attrs['r:id'] || attrs.rId || '';
9843
9905
  }
9906
+ async function getPresentationPart(zip) {
9907
+ const rels = asNodeArray(getTextByPathList(await readXmlFile(zip, '_rels/.rels'), [
9908
+ 'Relationships',
9909
+ 'Relationship'
9910
+ ]));
9911
+ for (const rel of rels){
9912
+ const type = getTextByPathList(rel, [
9913
+ 'attrs',
9914
+ 'Type'
9915
+ ]);
9916
+ const target = getTextByPathList(rel, [
9917
+ 'attrs',
9918
+ 'Target'
9919
+ ]);
9920
+ const targetMode = getTextByPathList(rel, [
9921
+ 'attrs',
9922
+ 'TargetMode'
9923
+ ]);
9924
+ if (!targetMode || 'external' !== String(targetMode).toLowerCase()) {
9925
+ if ('officeDocument' === getRelTypeName(type) && target) {
9926
+ const loc = resolvePartTarget('', target);
9927
+ if (loc) return loc;
9928
+ }
9929
+ }
9930
+ }
9931
+ return 'ppt/presentation.xml';
9932
+ }
9844
9933
  async function getSlidesFromPresentation(zip) {
9845
- const relsContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels');
9846
- const relItems = asNodeArray(getTextByPathList(relsContent, [
9934
+ const presentationPart = await getPresentationPart(zip);
9935
+ const relItems = asNodeArray(getTextByPathList(await readXmlFile(zip, relationshipsPartFor(presentationPart)), [
9847
9936
  'Relationships',
9848
9937
  'Relationship'
9849
9938
  ]));
@@ -9862,14 +9951,19 @@ async function getSlidesFromPresentation(zip) {
9862
9951
  'attrs',
9863
9952
  'Target'
9864
9953
  ]);
9954
+ const targetMode = getTextByPathList(rel, [
9955
+ 'attrs',
9956
+ 'TargetMode'
9957
+ ]);
9865
9958
  if (!id || !target) continue;
9866
- const loc = resolvePresentationTarget(target);
9959
+ if (targetMode && 'external' === String(targetMode).toLowerCase()) continue;
9960
+ const loc = resolvePartTarget(presentationPart, target);
9867
9961
  if (loc) {
9868
9962
  relsMap[id] = loc;
9869
9963
  if ('slide' === getRelTypeName(type)) slideTargets.push(loc);
9870
9964
  }
9871
9965
  }
9872
- const presentation = await readXmlFile(zip, 'ppt/presentation.xml');
9966
+ const presentation = await readXmlFile(zip, presentationPart);
9873
9967
  const sldIds = asNodeArray(getTextByPathList(presentation, [
9874
9968
  'p:presentation',
9875
9969
  'p:sldIdLst',
@@ -9881,7 +9975,7 @@ async function getSlidesFromPresentation(zip) {
9881
9975
  if (rid && relsMap[rid]) ordered.push(relsMap[rid]);
9882
9976
  }
9883
9977
  if (ordered.length) return ordered;
9884
- return slideTargets.sort(sortSlideXml);
9978
+ return slideTargets;
9885
9979
  }
9886
9980
  async function getContentTypes(zip) {
9887
9981
  const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
@@ -9889,7 +9983,7 @@ async function getContentTypes(zip) {
9889
9983
  'Types',
9890
9984
  'Override'
9891
9985
  ]));
9892
- let slidesLocArray = [];
9986
+ const overrideSlides = [];
9893
9987
  let slideLayoutsLocArray = [];
9894
9988
  for (const item of overrides){
9895
9989
  const contentType = item?.attrs?.ContentType;
@@ -9898,7 +9992,7 @@ async function getContentTypes(zip) {
9898
9992
  const loc = String(partName).replace(/^\//, '');
9899
9993
  switch(contentType){
9900
9994
  case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
9901
- slidesLocArray.push(loc);
9995
+ overrideSlides.push(loc);
9902
9996
  break;
9903
9997
  case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
9904
9998
  slideLayoutsLocArray.push(loc);
@@ -9906,9 +10000,9 @@ async function getContentTypes(zip) {
9906
10000
  default:
9907
10001
  }
9908
10002
  }
9909
- slidesLocArray = slidesLocArray.sort(sortSlideXml);
9910
10003
  slideLayoutsLocArray = slideLayoutsLocArray.sort(sortSlideXml);
9911
- if (!slidesLocArray.length) slidesLocArray = await getSlidesFromPresentation(zip);
10004
+ let slidesLocArray = await getSlidesFromPresentation(zip);
10005
+ if (!slidesLocArray.length) slidesLocArray = overrideSlides.sort(sortSlideXml);
9912
10006
  return {
9913
10007
  slides: slidesLocArray,
9914
10008
  slideLayouts: slideLayoutsLocArray