@lofcz/pptxtojson 2.2.2 → 2.2.3

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 CHANGED
@@ -190,6 +190,19 @@ All numeric length values in the output JSON use `pt` (point) as the unit.
190
190
  - Duration `duration`
191
191
  - Direction `direction`
192
192
 
193
+ - Element animations `animations` (from `p:timing`, presenter order)
194
+ - Target shape id `spid` (matches the element's `id` / `p:cNvPr@id`)
195
+ - Trigger `trigger`: `onClick` | `withPrevious` | `afterPrevious`
196
+ - Preset class `class`: `entr` | `exit` | `emph` | `path` | `verb` | `mediacall`
197
+ - Preset id `presetId` and subtype `presetSubtype` (direction / variant)
198
+ - Duration `duration` and delay `delay` (milliseconds)
199
+ - Optional effect filter `filter` (fade, wipe, barn, …)
200
+
201
+ - Build list `builds` (from `p:bldLst`)
202
+ - Target shape id `spid`
203
+ - Type `type`: `paragraph` | `diagram` | `graphic` | `oleChart`
204
+ - Animate background `animBg`
205
+
193
206
  - Slide elements `elements` / master layout elements `layoutElements`
194
207
  - OOXML ID `id`
195
208
  - Text
package/dist/index.cjs CHANGED
@@ -9463,6 +9463,164 @@ function parseTransition(transitionNode) {
9463
9463
  }
9464
9464
  return transition;
9465
9465
  }
9466
+ const PRESET_CLASSES = new Set([
9467
+ 'entr',
9468
+ 'exit',
9469
+ 'emph',
9470
+ 'path',
9471
+ 'verb',
9472
+ 'mediacall'
9473
+ ]);
9474
+ const NODE_TYPE_TO_TRIGGER = {
9475
+ clickEffect: 'onClick',
9476
+ withEffect: 'withPrevious',
9477
+ afterEffect: 'afterPrevious',
9478
+ clickPar: 'onClick',
9479
+ withGroup: 'withPrevious',
9480
+ afterGroup: 'afterPrevious',
9481
+ interactiveSeq: 'onClick'
9482
+ };
9483
+ function asArray(value) {
9484
+ if (null == value) return [];
9485
+ return Array.isArray(value) ? value : [
9486
+ value
9487
+ ];
9488
+ }
9489
+ function parseMs(value) {
9490
+ if (null == value || '' === value || 'indefinite' === value) return null;
9491
+ const ms = parseInt(value, 10);
9492
+ return Number.isFinite(ms) ? ms : null;
9493
+ }
9494
+ function findTimingNode(content) {
9495
+ if (!content) return null;
9496
+ return getTextByPathList(content, [
9497
+ 'p:sld',
9498
+ 'p:timing'
9499
+ ]) || getTextByPathList(content, [
9500
+ 'p:sld',
9501
+ 'mc:AlternateContent',
9502
+ 'mc:Choice',
9503
+ 'p:timing'
9504
+ ]) || getTextByPathList(content, [
9505
+ 'p:sld',
9506
+ 'mc:AlternateContent',
9507
+ 'mc:Fallback',
9508
+ 'p:timing'
9509
+ ]);
9510
+ }
9511
+ function collectSpids(node, out = []) {
9512
+ if (!node || 'object' != typeof node) return out;
9513
+ const spid = node.attrs?.spid;
9514
+ if (null != spid && '' !== spid) out.push(String(spid));
9515
+ for (const key of Object.keys(node))if ('attrs' !== key && 'value' !== key) for (const child of asArray(node[key]))collectSpids(child, out);
9516
+ return out;
9517
+ }
9518
+ function collectDuration(node) {
9519
+ let found = null;
9520
+ const walk = (n)=>{
9521
+ if (!n || 'object' != typeof n) return;
9522
+ const ms = parseMs(n.attrs?.dur);
9523
+ if (null != ms && ms >= 0) found = ms;
9524
+ for (const key of Object.keys(n))if ('attrs' !== key && 'value' !== key) for (const child of asArray(n[key]))walk(child);
9525
+ };
9526
+ walk(node);
9527
+ return found;
9528
+ }
9529
+ function collectFilter(node) {
9530
+ let filter = '';
9531
+ const walk = (n)=>{
9532
+ if (!n || 'object' != typeof n) return;
9533
+ if (n.attrs?.filter) filter = n.attrs.filter;
9534
+ for (const key of Object.keys(n))if ('attrs' !== key && 'value' !== key) for (const child of asArray(n[key]))walk(child);
9535
+ };
9536
+ walk(node);
9537
+ return filter;
9538
+ }
9539
+ function collectDelay(node, inherited = 0) {
9540
+ const fromAttr = parseMs(node?.attrs?.delay);
9541
+ if (null != fromAttr && fromAttr >= 0) return fromAttr;
9542
+ const condRoot = node?.['p:stCondLst'];
9543
+ for (const cond of asArray(condRoot?.['p:cond'] || condRoot)){
9544
+ const fromCond = parseMs(cond?.attrs?.delay);
9545
+ if (null != fromCond && fromCond >= 0) return fromCond;
9546
+ }
9547
+ return inherited;
9548
+ }
9549
+ function collectEffects(node, inheritedTrigger = 'onClick', inheritedDelay = 0, results = []) {
9550
+ if (!node || 'object' != typeof node) return results;
9551
+ const attrs = node.attrs || {};
9552
+ const trigger = NODE_TYPE_TO_TRIGGER[attrs.nodeType] || inheritedTrigger;
9553
+ const delay = collectDelay(node, inheritedDelay);
9554
+ if (attrs.presetClass && PRESET_CLASSES.has(attrs.presetClass)) {
9555
+ const spids = [
9556
+ ...new Set(collectSpids(node))
9557
+ ];
9558
+ const duration = collectDuration(node);
9559
+ const filter = collectFilter(node);
9560
+ const effectTrigger = NODE_TYPE_TO_TRIGGER[attrs.nodeType] || trigger;
9561
+ for (const spid of spids){
9562
+ const animation = {
9563
+ spid,
9564
+ trigger: effectTrigger,
9565
+ class: attrs.presetClass,
9566
+ presetId: parseInt(attrs.presetID || '0', 10) || 0,
9567
+ presetSubtype: parseInt(attrs.presetSubtype || '0', 10) || 0,
9568
+ duration: null != duration ? duration : 1000,
9569
+ delay
9570
+ };
9571
+ if (filter) animation.filter = filter;
9572
+ results.push(animation);
9573
+ }
9574
+ return results;
9575
+ }
9576
+ for (const key of Object.keys(node))if ('attrs' !== key && 'value' !== key) for (const child of asArray(node[key]))collectEffects(child, trigger, delay, results);
9577
+ return results;
9578
+ }
9579
+ function parseBuildList(timing) {
9580
+ const bldLst = timing?.['p:bldLst'];
9581
+ if (!bldLst) return [];
9582
+ const kinds = [
9583
+ [
9584
+ 'p:bldP',
9585
+ 'paragraph'
9586
+ ],
9587
+ [
9588
+ 'p:bldDgm',
9589
+ 'diagram'
9590
+ ],
9591
+ [
9592
+ 'p:bldGraphic',
9593
+ 'graphic'
9594
+ ],
9595
+ [
9596
+ 'p:bldOleChart',
9597
+ 'oleChart'
9598
+ ]
9599
+ ];
9600
+ const builds = [];
9601
+ for (const [tag, type] of kinds)for (const node of asArray(bldLst[tag])){
9602
+ const spid = node?.attrs?.spid;
9603
+ if (null == spid || '' === spid) continue;
9604
+ const item = {
9605
+ spid: String(spid),
9606
+ type
9607
+ };
9608
+ if (node.attrs?.animBg === '1' || node.attrs?.animBg === 'true') item.animBg = true;
9609
+ builds.push(item);
9610
+ }
9611
+ return builds;
9612
+ }
9613
+ function parseTiming(slideContent) {
9614
+ const timing = findTimingNode(slideContent);
9615
+ if (!timing) return {
9616
+ animations: [],
9617
+ builds: []
9618
+ };
9619
+ return {
9620
+ animations: collectEffects(timing),
9621
+ builds: parseBuildList(timing)
9622
+ };
9623
+ }
9466
9624
  async function loadDiagramFile(warpObj, filename, transformDrawing = false) {
9467
9625
  if (!filename) return null;
9468
9626
  const cacheKey = `${transformDrawing ? 'drawing:' : 'xml:'}${filename}`;
@@ -9976,6 +10134,7 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
9976
10134
  if (!transitionNode) transitionNode = findTransitionNode(slideLayoutContent, 'p:sldLayout');
9977
10135
  if (!transitionNode) transitionNode = findTransitionNode(slideMasterContent, 'p:sldMaster');
9978
10136
  const transition = parseTransition(transitionNode);
10137
+ const { animations, builds } = parseTiming(slideContent);
9979
10138
  const showMasterSpOnSlide = getTextByPathList(slideContent, [
9980
10139
  'p:sld',
9981
10140
  'attrs',
@@ -9989,7 +10148,9 @@ async function processSingleSlide(zip, sldFileName, themeContent, defaultTextSty
9989
10148
  layoutElements,
9990
10149
  note,
9991
10150
  transition,
9992
- hideBackground
10151
+ hideBackground,
10152
+ animations,
10153
+ builds
9993
10154
  };
9994
10155
  }
9995
10156
  function getHyperlinkFromCNvPr(cNvPr, warpObj) {