slidemind 0.2.4 → 0.3.1

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.
@@ -1,9 +1,10 @@
1
1
  import { readText } from "./zip.mjs";
2
2
  import { relsFor, relsPathFor, resolvePartPath } from "./ooxml.mjs";
3
+ import { slideHasForeignTags, slideReferencesEmbeddedWorkbook } from "./tags.mjs";
3
4
 
4
5
  const CONTENT_TYPES = "[Content_Types].xml";
5
6
 
6
- export function stripHiddenOleGraphicFrames(files) {
7
+ export function stripHiddenOleGraphicFrames(files, { keepSlideOle = null } = {}) {
7
8
  let changed = false;
8
9
  const removedTargets = new Set();
9
10
  const candidates = Object.keys(files).filter((part) =>
@@ -14,6 +15,26 @@ export function stripHiddenOleGraphicFrames(files) {
14
15
  const before = readText(files, part);
15
16
  if (!before) continue;
16
17
 
18
+ // Coexistence rule C4 (intern-slidemind docs/deck-embedded-source-spec.md
19
+ // §13): a SLIDE that carries another add-in's state — foreign tags or an
20
+ // embedded workbook/OLE part (think-cell "slide workbook" pattern) — keeps
21
+ // its hidden OLE frames untouched; stripping them would destroy that
22
+ // add-in's data. Slidemind's own rendered/template output never has
23
+ // foreign tags, so the strip stays fully active there. Masters/layouts
24
+ // (template chain) keep the old behavior. The verdict is constant per
25
+ // slide CONTENT, so a caller running the strip once per pick over the
26
+ // same package (foldPickedSlides) precomputes it and passes `keepSlideOle`
27
+ // instead of paying the rels + tag-part parse again on every pick.
28
+ if (
29
+ part.startsWith("ppt/slides/") &&
30
+ (keepSlideOle
31
+ ? keepSlideOle(part)
32
+ : slideHasForeignTags(files, part) ||
33
+ slideReferencesEmbeddedWorkbook(files, part))
34
+ ) {
35
+ continue;
36
+ }
37
+
17
38
  const removedIds = new Set();
18
39
  const after = before.replace(
19
40
  /<p:graphicFrame\b[\s\S]*?<\/p:graphicFrame>/g,
@@ -31,6 +31,10 @@ import {
31
31
  } from "./ooxml.mjs";
32
32
  import { stripHiddenOleGraphicFrames } from "./hidden-ole.mjs";
33
33
  import { stripRiskyImageExtensions } from "./image-extensions.mjs";
34
+ import {
35
+ slideHasForeignTags,
36
+ slideReferencesEmbeddedWorkbook,
37
+ } from "./tags.mjs";
34
38
 
35
39
  // The four package parts we always keep and rewrite for standalone validity.
36
40
  const SKELETON = [
@@ -63,6 +67,19 @@ export function foldPickedSlides(buffer, picks, { sourceName = "reused" } = {})
63
67
  const lowest = firstSlidePath(files);
64
68
  const lowestRels = relsPathFor(lowest);
65
69
 
70
+ // The C4 keep-OLE verdict (foreign tags / embedded workbook) is per slide
71
+ // CONTENT and constant across picks — computed inside the strip it re-parsed
72
+ // every slide's rels and tag parts once per pick, O(picks × slides) on a big
73
+ // adopt. One pass here; the per-pick lookup follows the slide swap below
74
+ // (the lowest slot holds the picked slide's content).
75
+ const keepOleByPart = new Map(
76
+ order.map((part) => [
77
+ part,
78
+ slideHasForeignTags(files, part) ||
79
+ slideReferencesEmbeddedWorkbook(files, part),
80
+ ]),
81
+ );
82
+
66
83
  return picks.map((n) => {
67
84
  const picked = order[n - 1];
68
85
  const sldId = entries[n - 1] ? entries[n - 1].sldId : null;
@@ -89,7 +106,12 @@ export function foldPickedSlides(buffer, picks, { sourceName = "reused" } = {})
89
106
  copy[lowestRels] = stripNotesRel(copy[lowestRels]);
90
107
  notesStripped = true;
91
108
  }
92
- const hiddenOleStripped = stripHiddenOleGraphicFrames(copy);
109
+ const hiddenOleStripped = stripHiddenOleGraphicFrames(copy, {
110
+ keepSlideOle: (part) =>
111
+ keepOleByPart.get(
112
+ part === lowest ? picked : part === picked ? lowest : part,
113
+ ) ?? false,
114
+ });
93
115
  const riskyImagesStripped = stripRiskyImageExtensions(copy);
94
116
 
95
117
  // Prune to the lowest slide's dependency closure + trimmed skeleton.