@office-kit/pptx-dev 0.9.1 → 0.13.0

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/editor.js ADDED
@@ -0,0 +1,24 @@
1
+ import{H as F,J as q}from"./editor-chunks/chunk-Q3KT5ZGJ.js";function $(e,t,o){return F.set(t,o),q(e,t)}var j=class{#e;constructor(){this.#e=new Promise((t,o)=>{let r=indexedDB.open("office-pptx-editor-drafts",1);r.onupgradeneeded=()=>{r.result.createObjectStore("drafts",{keyPath:"id"}).createIndex("projectId","projectId")},r.onsuccess=()=>t(r.result),r.onerror=()=>o(r.error)}),this.#e.catch(()=>{})}async list(t){let o=await this.#e;return new Promise((r,n)=>{let d=o.transaction("drafts").objectStore("drafts").index("projectId").getAll(t);d.onsuccess=()=>r(d.result.filter(l=>l.projectId===t).sort((l,v)=>v.updated-l.updated)),d.onerror=()=>n(d.error)})}async put(t){let o=await this.#e;return new Promise((r,n)=>{let d=o.transaction("drafts","readwrite"),l=d.objectStore("drafts"),v=l.get(t.id);v.onsuccess=()=>{(!v.result||v.result.version<=t.version)&&l.put(t)},d.oncomplete=()=>r(),d.onabort=()=>n(d.error),d.onerror=()=>n(d.error)})}async remove(t,o){let r=await this.#e;return new Promise((n,d)=>{let l=r.transaction("drafts","readwrite"),v=l.objectStore("drafts"),p=v.get(t);p.onsuccess=()=>{(o===void 0||p.result?.version===o)&&v.delete(t)},l.oncomplete=()=>n(),l.onabort=()=>d(l.error),l.onerror=()=>d(l.error)})}};var Z={"Saving\u2026":"\u4FDD\u5B58\u4E2D\u2026","Loading presentation\u2026":"\u30D7\u30EC\u30BC\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u2026","Unsaved changes":"\u672A\u4FDD\u5B58\u306E\u5909\u66F4","Saved to this project":"\u3053\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u4FDD\u5B58\u6E08\u307F","Building source\u2026":"\u30BD\u30FC\u30B9\u3092\u30D3\u30EB\u30C9\u4E2D\u2026","Use source":"\u30BD\u30FC\u30B9\u3092\u4F7F\u7528","Replace editor changes with the current source?":"\u30A8\u30C7\u30A3\u30BF\u30FC\u3067\u306E\u5909\u66F4\u3092\u73FE\u5728\u306E\u30BD\u30FC\u30B9\u3067\u7F6E\u304D\u63DB\u3048\u307E\u3059\u304B\uFF1F","Preview unavailable":"\u30D7\u30EC\u30D3\u30E5\u30FC\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093","Preview changed. Try again.":"\u30D7\u30EC\u30D3\u30E5\u30FC\u304C\u66F4\u65B0\u3055\u308C\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002","Reconnecting\u2026":"\u518D\u63A5\u7D9A\u4E2D\u2026",Retry:"\u518D\u8A66\u884C","Save failed":"\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F","Source changed":"\u30BD\u30FC\u30B9\u306E\u5909\u66F4","Recover unsaved changes":"\u672A\u4FDD\u5B58\u306E\u5909\u66F4\u3092\u5FA9\u5143","This browser has a recovery copy for this project. Restore it or discard it to continue.":"\u3053\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u5FA9\u5143\u7528\u30B3\u30D4\u30FC\u304C\u30D6\u30E9\u30A6\u30B6\u30FC\u306B\u6B8B\u3063\u3066\u3044\u307E\u3059\u3002\u5FA9\u5143\u3059\u308B\u304B\u7834\u68C4\u3057\u3066\u7D9A\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002","Could not access the recovery copy. Try again.":"\u5FA9\u5143\u7528\u30B3\u30D4\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002","Restore changes":"\u5909\u66F4\u3092\u5FA9\u5143","Discard recovery copy":"\u5FA9\u5143\u7528\u30B3\u30D4\u30FC\u3092\u7834\u68C4","Could not save a recovery copy in this browser. Keep this tab open until the project is saved.":"\u3053\u306E\u30D6\u30E9\u30A6\u30B6\u30FC\u306B\u5FA9\u5143\u7528\u30B3\u30D4\u30FC\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3078\u306E\u4FDD\u5B58\u304C\u5B8C\u4E86\u3059\u308B\u307E\u3067\u3001\u3053\u306E\u30BF\u30D6\u3092\u958B\u3044\u305F\u307E\u307E\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},ee=`
2
+ .dev-status { display: contents; }
3
+ .save-status, .dev-status .conflict { display:flex; align-items:center; flex-wrap:wrap; gap:10px; padding:5px 12px; font:12px system-ui; color:#304050; background:#eaf3ed; }
4
+ .compact-host .save-status { gap:6px; padding:3px 8px; font-size:11px; }
5
+ .save-status span:first-child { flex:1; }
6
+ .dev-status .conflict { background:#fff0cd; color:#583b00; }
7
+ /* A wrapping status would change the bar's height whenever it updates and
8
+ shift the canvas mid-gesture; the title bar keeps one line. */
9
+ .topbar.compact .save-status { flex:0 1 auto; min-height:24px; white-space:nowrap; }
10
+ .topbar.compact .dev-status .conflict { flex-basis:100%; }
11
+ .dev-status button, .recovery button { font:inherit; color:inherit; cursor:pointer; }
12
+ .recovery::backdrop { background:#0005; }
13
+ .recovery { max-width:650px; max-height:80vh; overflow:auto; padding:24px; border:0; background:white; color:#263544; border-radius:12px; box-shadow:0 8px 32px #0003; }
14
+ .recovery h2 { margin-top:0; }
15
+ .recovery-entry { display:flex; flex-wrap:wrap; align-items:center; gap:12px; padding:12px 0; border-top:1px solid #ddd; }
16
+ .recovery-entry span { flex:1; }
17
+ .loading { position:fixed; inset:110px 0 0; z-index:51; background:#ffffff90; }
18
+ @media (prefers-color-scheme: dark) {
19
+ .recovery { background:#2b2b2b; color:#f0f0f0; }
20
+ .recovery-entry { border-top-color:#3d3d3d; }
21
+ .save-status { color:#cfe8d6; background:#23382b; }
22
+ .dev-status .conflict { background:#4a3a12; color:#ffe2a3; }
23
+ .loading { background:#1f1f1f90; }
24
+ }`,te="https://github.com/office-kit/pptx/issues",M=e=>e instanceof Error?e.message:String(e),I=async e=>new Uint8Array(await e.arrayBuffer());function s(e,t={},...o){let r=Object.assign(document.createElement(e),t);return r.append(...o),r}var V=document.createElement("style");V.textContent=ee;document.head.append(V);var U=s("div",{className:"dev-status"}),re={isolate:!1,compact:!0,autoSave:!0,status:U,onSave:ae},c=$(document.body,re,{previewFrame:window.parent!==window,feedback:{url:te}}),a=e=>c.locale==="ja"?Z[e]??e:e,x,y={revision:"",hash:void 0,bytes:null},b=!1,u=!1,m="",L=!1,E=!1,P=!1,N=!1,D=!1,T=!1,S,f=[],z=!1,g=!1,A=!1,k=!1,X=crypto.randomUUID(),R,B=Promise.resolve(),H=0;try{S=new j}catch{k=!0}function O(e){let t=++H,o=x?.projectId,{hash:r,revision:n}=y,d=x?.fileName??"presentation.pptx",l=e.then(p=>({value:p}),p=>({error:p})),v=B.then(async()=>{let p=await l;if("error"in p)throw p.error;if(!S||!o)throw new Error("Recovery storage unavailable");await S.put({id:X,projectId:o,baseHash:r,baseRevision:n,fileName:d,bytes:p.value,version:t,updated:Date.now()}),k=!1});return B=v.catch(()=>{k=!0,i()}),v.then(()=>!0,()=>!1)}async function oe(){let e=H;await B;try{await S?.remove(X,e),R&&(await S?.remove(R.id,R.version),R=void 0)}catch{k=!0,i()}}function J(e,t){y={revision:e.revision,hash:e.documentHash,bytes:t}}function Y(e){x=e,window.parent.postMessage({type:"editor-revision",revision:e.previewRevision??0},window.location.origin)}async function ae(e){let t=x;if(u||g||f.length||!b||P||!t||t.building||t.error||t.conflict&&!D)return N=!0,!1;u=!0,m="",i();try{await O(Promise.resolve(e));let o=await fetch("/editor/document",{method:"PUT",headers:{"Content-Type":"application/octet-stream","If-Match":D?t.revision:y.revision,...D?{"X-Editor-Resolve":"edits"}:{}},body:new Blob([new Uint8Array(e)])}),r=await o.json();if(Y(r),o.status===409)return N=!0,!1;if(!o.ok)throw new Error(r.message??a("Save failed"));return D=!1,y=r.uploadRevision?{revision:r.uploadRevision,hash:void 0,bytes:e}:{revision:r.revision,hash:r.documentHash,bytes:e},!0}catch(o){return m=M(o),N=!0,!1}finally{u=!1,i(),w()}}function ie(){!N||u||m||P||(N=!1,c.dirty&&c.save())}async function _(e){if(!(await fetch("/editor/resolve",{method:"POST",headers:{"If-Match":e}})).ok)throw new Error(a("Preview changed. Try again."))}async function G(e,t){P=!0,i();try{return await c.propose(e,t,{label:a("Source changed"),from:"source"})}finally{P=!1,i()}}async function W(e,t){if(e.status==="took-theirs"){await _(t.revision);return}(e.status==="kept-mine"||t.conflict)&&(D=t.conflict,N=!1,await c.save())}async function ne(e){let[t,o]=await Promise.all([fetch("/editor/base"),fetch("/editor/source")]);if(!o.ok)throw new Error(a("Preview unavailable"));if(o.headers.get("etag")!==e.revision){E=!0;return}let r=await G(t.ok?await I(t):null,await I(o));await W(r,e)}async function w(){if(L||u||g||P){E=!0;return}L=!0;try{let e=await fetch("/editor/state");if(!e.ok)throw new Error(a("Preview unavailable"));let t=await e.json();if(g){E=!0;return}if(Y(t),i(),!t.available)return;if(!z){z=!0;try{f=await S?.list(t.projectId)??[]}catch{k=!0}i()}if(b&&f.length)return;if(b&&!T&&t.documentHash===y.hash)y={...y,revision:t.revision};else{let o=await fetch("/editor/document");if(!o.ok)throw new Error(a("Preview unavailable"));let r=await I(o);if(u||g||o.headers.get("etag")!==t.revision){E=!0;return}if(!b||T)await c.open(r,{fileName:t.fileName}),b=!0,T=!1,J(t,r);else{let n=await G(y.bytes,r);J(t,r),await W(n,{...t,conflict:!1})}}t.conflict&&!D&&!f.length&&await ne(t)}catch(e){m=M(e)}finally{L=!1,i(),E&&!u?(E=!1,w()):ie()}}async function se(){if(!x||u||P||!confirm(a("Replace editor changes with the current source?")))return;u=!0,m="",i();let e=H;try{await _(x.revision),T=e===H}catch(t){m=M(t)}finally{u=!1,i(),w()}}async function ce(e){if(!g){g=!0,A=!1,i();try{if(await c.open(e.bytes,{fileName:e.fileName,unsaved:!0}),R=e,f=[],e.baseHash!==x?.documentHash){let t=e.baseRevision?await fetch(`/editor/document?revision=${encodeURIComponent(e.baseRevision)}`):void 0;y={revision:e.baseRevision??"",hash:e.baseHash,bytes:t?.ok?await I(t):null}}await O(c.snapshot())&&(await S?.remove(e.id,e.version),R=void 0)}catch{A=!0,k=!0}finally{g=!1,i(),E=!1,w()}}}async function de(e){try{await S?.remove(e.id,e.version),f=f.filter(t=>t.id!==e.id)}catch{A=!0}i(),f.length||w()}var h=s("dialog",{className:"recovery"});h.addEventListener("cancel",e=>e.preventDefault());h.addEventListener("keydown",e=>e.stopPropagation());var C=s("div",{className:"loading"}),Q="";function i(){let e=x,t={locale:c.locale,text:u?"Saving\u2026":b?c.dirty?"Unsaved changes":"Saved to this project":"Loading presentation\u2026",building:!!e?.building,useSource:!!e?.hasEdits&&!e.conflict&&!P,useSourceDisabled:u||!!e?.building,draftFailure:k,failure:m||e?.error||"",recovery:b&&f.length?f.map(n=>n.id):[],recovering:g,recoveryFailure:A,loaded:b},o=JSON.stringify(t);if(o===Q)return;Q=o;let r=s("div",{className:"save-status",role:"status"},s("span",{},a(t.text)));t.building&&r.append(s("span",{},a("Building source\u2026"))),t.useSource&&r.append(s("button",{disabled:t.useSourceDisabled,onclick:()=>{se()}},a("Use source"))),U.replaceChildren(r),t.draftFailure&&U.append(s("div",{className:"conflict",role:"alert"},a("Could not save a recovery copy in this browser. Keep this tab open until the project is saved."))),t.failure&&U.append(s("div",{className:"conflict",role:"alert"},t.failure,s("button",{onclick:()=>{m="",i(),w()}},a("Retry")))),t.recovery.length?(h.ariaLabel=a("Recover unsaved changes"),h.replaceChildren(s("h2",{},a("Recover unsaved changes")),s("p",{},a("This browser has a recovery copy for this project. Restore it or discard it to continue.")),...t.recoveryFailure?[s("p",{role:"alert"},a("Could not access the recovery copy. Try again."))]:[],...f.map(n=>s("div",{className:"recovery-entry"},s("span",{},`${n.fileName} \u2014 ${new Date(n.updated).toLocaleString(t.locale)}`),s("button",{disabled:g,onclick:()=>{ce(n)}},a("Restore changes")),s("button",{disabled:g,onclick:()=>{de(n)}},a("Discard recovery copy"))))),h.isConnected||(document.body.append(h),h.showModal())):h.isConnected&&(h.close(),h.remove()),t.loaded?C.remove():document.body.append(C),C.ariaLabel=a("Loading presentation\u2026")}c.on("change",()=>{b&&c.dirty&&!f.length&&O(c.snapshot()),i()});c.on("dirtychange",({dirty:e})=>{e||oe(),i()});c.on("localechange",i);window.addEventListener("beforeunload",e=>{c.dirty&&(e.preventDefault(),e.returnValue="")});await c.ready;i();var K=new EventSource("/events");K.onmessage=()=>{w()};K.onerror=()=>{m=a("Reconnecting\u2026"),i()};K.onopen=()=>{m="",w()};w();
package/dist/index.d.mts CHANGED
@@ -1,12 +1,47 @@
1
- import { validatePresentation } from "@office-kit/pptx";
1
+ import { JsxSource } from "@office-kit/pptx-dsl";
2
+ import { MediaPlayback, ShapeBounds, ShapeMedia, getSlideAnimations, getSlideShowProperties, getSlideTransition, getSlides, validatePresentation } from "@office-kit/pptx";
2
3
 
4
+ //#region src/media-manifest.d.ts
5
+ /** Media information exposed to the dev preview for a single slide shape. */
6
+ interface PreviewMedia {
7
+ readonly slideIndex: number;
8
+ readonly shapeId: number;
9
+ readonly kind: ShapeMedia['kind'];
10
+ /** A data URL for embedded media, or the external URL for online media. */
11
+ readonly src: string;
12
+ /** Present for embedded media and suitable for an HTML media element. */
13
+ readonly contentType?: string;
14
+ /** Original shape geometry in EMUs. */
15
+ readonly bounds: ShapeBounds;
16
+ readonly playback: MediaPlayback | null;
17
+ }
18
+ //#endregion
3
19
  //#region src/build.d.ts
4
20
  interface BuildResult {
5
21
  bytes: Uint8Array;
6
22
  slides: string[];
7
23
  slideTexts: string[];
24
+ notes: (string | null)[];
25
+ hiddenSlides: boolean[];
26
+ transitions: ReturnType<typeof getSlideTransition>[];
27
+ /** What each slide animates, in click order — the preview's player reads this. */
28
+ animations: ReturnType<typeof getSlideAnimations>[];
29
+ showProperties: ReturnType<typeof getSlideShowProperties>;
30
+ customShows: {
31
+ id: number;
32
+ name: string;
33
+ slideIndices: number[];
34
+ }[];
35
+ /** Media clips keyed by slide and shape id for HTML playback in preview mode. */
36
+ media: PreviewMedia[];
8
37
  aspectRatio: number;
9
38
  dependencies: string[];
39
+ /**
40
+ * Slide index → shape id → the JSX elements being evaluated when the shape
41
+ * was made, outermost first. Only decks built from TSX have it; a saved
42
+ * editor deck has no source to point at.
43
+ */
44
+ shapeSources?: Record<number, Record<number, readonly JsxSource[]>>;
10
45
  diagnostics: ReturnType<typeof validatePresentation>;
11
46
  }
12
47
  //#endregion
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { i as initProject, n as exportDeck, r as inspectTemplate, t as buildDeck } from "./src-YH6kAXbA.mjs";
1
+ import { i as initProject, n as exportDeck, r as inspectTemplate, t as buildDeck } from "./src-DASlwPDd.mjs";
2
2
  export { buildDeck, exportDeck, initProject, inspectTemplate };
@@ -0,0 +1 @@
1
+ var X="http://www.w3.org/2000/svg",K="http://www.w3.org/1999/xhtml";function Y(p){let d=p.onCommand!==void 0,y=[],M=!1,I=p.locale==="ja"?"\u518D\u751F\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F \xB7 \u518D\u8A66\u884C":"Unable to play media \xB7 Retry",T=p.locale==="ja"?"\u30E1\u30C7\u30A3\u30A2\u3092\u518D\u751F":"Play media",G=p.locale==="ja"?"\u30E1\u30C7\u30A3\u30A2\u3092\u4E00\u6642\u505C\u6B62":"Pause media";for(let t of p.clips){if(t.kind==="online")continue;let a=p.root.querySelector(`[data-pptx-shape-id="${t.shapeId}"]`)?.querySelector("image");if(!(a instanceof SVGImageElement))continue;let r=document.createElementNS(X,"foreignObject");for(let n of["x","y","width","height","transform","clip-path","filter","opacity"]){let o=a.getAttribute(n);o!==null&&r.setAttribute(n,o)}r.dataset.pptxMedia=String(t.shapeId);let f=t.kind==="audio"&&t.playback?.hideWhenStopped;f&&(r.style.visibility="hidden");let h=document.createElementNS(K,"div");h.style.cssText="position:relative;width:100%;height:100%;";let s=t.kind==="video"&&t.playback?.fullScreen?document.createElement("div"):void 0,l;s&&(s.dataset.pptxMediaFullscreen=String(t.shapeId),s.style.cssText=`position:${d?"absolute":"fixed"};inset:0;background:black;z-index:5;`,s.hidden=!0,p.overlayRoot.append(s));let b=!1,e=document.createElement(t.kind),c=Math.max(0,t.playback?.trim?.startMs??0)/1e3,k=Math.max(0,t.playback?.trim?.endMs??0)/1e3,P=c>0||k>0,H=Math.max(0,t.playback?.fade?.inMs??0)/1e3,V=Math.max(0,t.playback?.fade?.outMs??0)/1e3,$=t.playback?.volume??.5,g=!1,F=!1,R,v;e.src=t.src,e.preload="metadata",e.controls=!d,e.loop=(t.playback?.loop??!1)&&c===0&&k===0,e.volume=$,e.muted=d||(t.playback?.muted??!1),e.setAttribute("aria-label",t.kind==="video"?"Video":"Audio"),e.style.cssText="display:block;width:100%;height:100%;object-fit:fill;",s&&(e.style.objectFit="contain"),e instanceof HTMLVideoElement?(e.playsInline=!0,e.poster=a.href.baseVal):h.style.background=`center / contain no-repeat url("${a.href.baseVal}")`;let u=document.createElement("button");u.type="button",u.hidden=!0,u.style.cssText="position:absolute;inset:0;margin:auto;max-width:100%;height:fit-content;";let O,W,N=()=>{clearTimeout(W),W=void 0},_=()=>{clearTimeout(R),R=void 0},A=()=>{let n=e.duration;return!Number.isFinite(n)||n<=0?Number.POSITIVE_INFINITY:Math.max(c,n-k)},j=n=>Math.min(Math.max(n,c),A()),S=()=>{let n=A(),o=Number.isFinite(e.currentTime)?e.currentTime:c,m=1;H>0&&(m=Math.min(m,Math.max(0,(o-c)/H))),V>0&&Number.isFinite(n)&&(m=Math.min(m,Math.max(0,(n-o)/V))),e.volume=Math.max(0,Math.min(1,$*m))},w=()=>{g=!1;let n=Number.isFinite(e.duration)?j(c):c;Math.abs(e.currentTime-n)>.001&&(e.currentTime=n),S()},U=()=>{if(g||b)return;g=!0,e.pause();let n=A();if(Number.isFinite(n)&&Math.abs(e.currentTime-n)>.001&&(e.currentTime=n),S(),t.playback?.hideWhenStopped&&(r.style.visibility="hidden"),s){let o=s.contains(document.activeElement);s.hidden=!0,l&&(l.hidden=!1),o&&!d&&(t.playback?.hideWhenStopped?p.overlayRoot.focus():l?.focus())}if(t.playback?.loop){w(),r.style.visibility=f?"hidden":"",s&&(s.hidden=!1,l&&(l.hidden=!0)),e.play().catch(o=>{M||b||o instanceof DOMException&&o.name==="AbortError"||(u.textContent=I,u.hidden=!1)});return}t.playback?.rewindAfterPlaying&&(w(),g=!0)},B=()=>{if(F){if(!P){S();return}e.currentTime<c-.001?e.currentTime=c:e.currentTime>=A()-.001&&!e.paused&&(d?e.pause():U()),S()}},q=()=>{_(),!(M||b||e.paused||!P&&H===0&&V===0)&&(R=setTimeout(()=>{B(),q()},50))},D=async()=>{N(),u.hidden=!0,(g||F&&e.currentTime<c-.001)&&w(),B(),r.style.visibility=f?"hidden":"",s&&(s.hidden=!1,l&&(l.hidden=!0),d||e.focus());try{await e.play()}catch(n){if(M||b||n instanceof DOMException&&n.name==="AbortError")return;u.textContent=n instanceof DOMException&&n.name==="NotAllowedError"?T:I,r.style.visibility="",u.hidden=!1}},C=()=>{if(d){p.onCommand?.({shapeId:t.shapeId,action:"play"});return}D()};if(d){let n=document.createElement("button");n.type="button",n.textContent=T,n.setAttribute("aria-label",T);let o=document.createElement("input");o.type="range",o.min="0",o.max="100",o.step="0.1",o.value="0",o.setAttribute("aria-label",p.locale==="ja"?"\u30E1\u30C7\u30A3\u30A2\u4F4D\u7F6E":"Media position");let m=document.createElement("div");m.style.cssText="position:absolute;left:4px;right:4px;bottom:4px;z-index:2;display:flex;align-items:center;gap:4px;padding:3px;background:rgb(0 0 0 / 65%);",o.style.cssText="min-width:0;flex:1;",n.onclick=()=>{let x=v;(x?!x.paused&&!x.ended:!e.paused)?p.onCommand?.({shapeId:t.shapeId,action:"pause"}):C()},o.oninput=()=>{let x=v?.duration||e.duration,z=Number(o.value);Number.isFinite(x)&&x>0&&Number.isFinite(z)&&p.onCommand?.({shapeId:t.shapeId,action:"seek",time:x*z/100})},m.append(n,o),O={toggle:n,position:o},(s??h).append(m)}u.onclick=()=>{d&&(u.hidden=!0),e.error&&e.load(),C()};for(let n of["click","dblclick","pointerdown","keydown"]){let o=m=>{(!(m instanceof KeyboardEvent)||m.key!=="Escape")&&m.stopPropagation()};h.addEventListener(n,o),s?.addEventListener(n,o)}e.addEventListener("error",()=>{M||b||(u.textContent=I,u.hidden=!1)}),e.addEventListener("loadedmetadata",()=>{if(F=!0,!d&&e.currentTime<c-.001&&w(),S(),!d||!v)return;let n=j(Math.max(0,v.currentTime));Math.abs(e.currentTime-n)>.3&&(e.currentTime=n),!v.paused&&!v.ended&&e.play().catch(()=>{M||b||(u.textContent=I,u.hidden=!1)})}),e.addEventListener("timeupdate",B),e.addEventListener("seeking",()=>{if(!F)return;let n=j(e.currentTime);Math.abs(e.currentTime-n)>.001&&(e.currentTime=n),S()});for(let n of["play","ended"])e.addEventListener(n,()=>{if(!(M||b)){if(n==="play"&&N(),n==="play"&&q(),!d&&n==="ended"&&P){U();return}if(!d&&n==="ended"&&t.playback?.rewindAfterPlaying&&!g&&(e.pause(),w()),!d&&n==="ended"&&t.playback?.hideWhenStopped&&(r.style.visibility="hidden"),!d&&n==="play"&&(r.style.visibility=f?"hidden":""),s){let o=n==="ended"&&s.contains(document.activeElement);d||(s.hidden=n==="ended"),l&&n==="ended"&&(l.hidden=!1),o&&!d&&(t.playback?.hideWhenStopped?p.overlayRoot.focus():l?.focus())}}});if(e.addEventListener("pause",_),s?(h.style.background=`center / contain no-repeat url("${a.href.baseVal}")`,l=document.createElement("button"),l.type="button",l.setAttribute("aria-label",T),l.title=T,l.style.cssText="position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;background:transparent;cursor:pointer;",l.onclick=()=>{C()},h.append(l),s.append(e,u)):h.append(e,u),r.append(h),a.replaceWith(r),y.push({clip:t,release:()=>{b=!0,N(),_(),!d&&s?.contains(document.activeElement)&&p.overlayRoot.focus(),e.pause(),e.removeAttribute("src"),e.load(),r.replaceWith(a),s?.remove(),e.remove()},retain:n=>{N(),e.parentNode!==n&&(n.append(e),r.replaceWith(a),D())},element:e,image:a,host:r,shapeId:t.shapeId,play:C,cancelStart:N,isTrimEnded:()=>g,status:u,...l?{start:l}:{},...O?{controls:O}:{},setTarget:n=>{v=n},...s?{overlay:s}:{}}),!d&&t.playback?.autoplay){let n=performance.now()+(t.playback.delayMs??0),o=()=>{if(M||b)return;let m=n-performance.now();m>0?W=setTimeout(o,Math.min(m,2147483647)):D()};o()}}let L=new Map(y.map(t=>[t.shapeId,t]));return{get progress(){return y.map(t=>{let{element:i,host:a,shapeId:r,overlay:f}=t;return{shapeId:r,currentTime:Number.isFinite(i.currentTime)?i.currentTime:0,duration:Number.isFinite(i.duration)?i.duration:0,paused:i.paused,ended:i.ended||t.isTrimEnded(),visible:a.style.visibility!=="hidden",fullScreen:!!(f&&!f.hidden)}})},command(t){let i=L.get(t.shapeId);if(i){if(d){if(t.action==="seek"&&(!Number.isFinite(t.time)||(t.time??0)<0))return;p.onCommand?.(t);return}if(t.action==="play")i.play();else if(t.action==="pause")i.cancelStart(),i.element.pause();else if(t.action==="seek"&&Number.isFinite(t.time)&&(t.time??0)>=0){let a=i.element.duration,r=i.clip.playback?.trim,f=Math.max(0,r?.startMs??0)/1e3,h=Math.max(0,r?.endMs??0)/1e3,E=Number.isFinite(a)?Math.max(f,a-h):a;i.element.currentTime=Number.isFinite(E)?Math.min(Math.max(t.time??0,f),E):Math.max(t.time??0,f)}}},sync(t){if(d)for(let i of t){let a=L.get(i.shapeId);if(!a)continue;let{element:r,host:f,overlay:h}=a;if(a.setTarget(i),a.start&&(a.start.hidden=i.fullScreen),a.controls){let c=!i.paused&&!i.ended;a.controls.toggle.textContent=c?G:T,a.controls.toggle.setAttribute("aria-label",c?G:T);let k=i.duration;a.controls.position.value=k>0?String(Math.max(0,Math.min(100,i.currentTime/k*100))):"0"}let E=a.clip.playback?.trim,s=Math.max(0,E?.startMs??0)/1e3,l=Math.max(0,E?.endMs??0)/1e3,b=Number.isFinite(i.duration)?Math.max(s,i.duration-l):i.duration,e=Number.isFinite(b)?Math.min(Math.max(s,i.currentTime),b):Math.max(s,i.currentTime);Math.abs(r.currentTime-e)>.3&&(r.currentTime=e),i.ended&&r.pause(),f.style.visibility=i.visible?"":"hidden",h&&(h.hidden=!i.fullScreen),i.paused||i.ended?r.pause():r.paused&&a.status.hidden&&r.play().catch(c=>{M||(a.status.textContent=c instanceof DOMException&&c.name==="NotAllowedError"?T:I,a.status.hidden=!1)})}},retainAcrossSlides(t,i){for(let a=y.length-1;a>=0;a--){let r=y[a],f=r.clip.playback?.slideCount??1;!d&&r.clip.kind==="audio"&&t>0&&t<f&&!r.element.paused&&!r.element.ended?r.retain(i):(r.release(),L.delete(r.shapeId),y.splice(a,1))}return y.length>0},dispose(){M=!0;for(let t of y)t.release();y.length=0,L.clear()}}}export{Y as createMediaPlayer};
@@ -1,11 +1,15 @@
1
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
1
+ import { n as renderDeck } from "./build-cpmt-r9Q.mjs";
2
+ import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
2
3
  import { Worker } from "node:worker_threads";
3
- import { join, resolve, sep } from "node:path";
4
+ import { basename, dirname, join, resolve, sep } from "node:path";
4
5
  import { mkdtempSync } from "node:fs";
5
6
  import { tmpdir } from "node:os";
6
7
  import { context, transform } from "esbuild";
7
8
  import { fileURLToPath, pathToFileURL } from "node:url";
9
+ import { createHash, randomUUID } from "node:crypto";
10
+ import { strFromU8, strToU8, unzipSync, zipSync } from "fflate";
8
11
  import { getShapeId, getShapeKind, getShapeName, getShapePlaceholderIdx, getShapePlaceholderType, getSlideLayoutName, getSlideLayoutPartName, getSlideLayoutType, getSlideLayouts, getSlidePartName, getSlideShapes, getSlideTitle, getSlides, loadPresentation } from "@office-kit/pptx";
12
+ import { comparablePart, describeConflict, mergeDecks } from "@office-kit/pptx-editor/merge";
9
13
  //#region src/bundle.ts
10
14
  const resolvePackage = (name) => fileURLToPath(import.meta.resolve(name));
11
15
  async function createDeckCompiler(entry) {
@@ -157,6 +161,79 @@ function createDeckBuilder(entry, keepWarm = true) {
157
161
  };
158
162
  }
159
163
  //#endregion
164
+ //#region src/fingerprint.ts
165
+ /** ZIP container dates and generated core timestamps are not source edits. */
166
+ function sourceFingerprint(bytes) {
167
+ const parts = unzipSync(bytes);
168
+ const hash = createHash("sha256");
169
+ for (const name of Object.keys(parts).sort()) {
170
+ const content = comparablePart(name, parts[name]);
171
+ hash.update(JSON.stringify([name, createHash("sha256").update(content).digest("hex")]));
172
+ }
173
+ return hash.digest("hex");
174
+ }
175
+ //#endregion
176
+ //#region src/editor-store.ts
177
+ const STORE_VERSION = 2;
178
+ /** One atomic sidecar keeps the saved deck and its source basis in agreement. */
179
+ function editorStore(entry) {
180
+ const path = join(dirname(resolve(entry)), ".office-kit", `${basename(entry)}.editor.zip`);
181
+ return {
182
+ path,
183
+ async read() {
184
+ let bytes;
185
+ try {
186
+ bytes = await readFile(path);
187
+ } catch (cause) {
188
+ if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") return;
189
+ throw cause;
190
+ }
191
+ const parts = unzipSync(bytes);
192
+ if (!parts["state.json"] || !parts["document.pptx"]) throw new Error(`Invalid editor file: ${path}`);
193
+ const state = JSON.parse(strFromU8(parts["state.json"]));
194
+ if (!state || typeof state !== "object" || !("version" in state) || state.version !== 1 && state.version !== STORE_VERSION || !("sourceHash" in state) || typeof state.sourceHash !== "string" || !/^[a-f0-9]{64}$/.test(state.sourceHash)) throw new Error(`Invalid editor metadata: ${path}`);
195
+ const base = parts["base.pptx"];
196
+ if (state.version === STORE_VERSION && !base) throw new Error(`Invalid editor file: ${path}`);
197
+ return {
198
+ sourceHash: state.sourceHash,
199
+ bytes: parts["document.pptx"],
200
+ base: base ?? null
201
+ };
202
+ },
203
+ async write(edits) {
204
+ await mkdir(dirname(path), { recursive: true });
205
+ const temporary = `${path}.${randomUUID()}.tmp`;
206
+ try {
207
+ await writeFile(temporary, zipSync({
208
+ "state.json": strToU8(JSON.stringify({
209
+ version: STORE_VERSION,
210
+ sourceHash: edits.sourceHash
211
+ })),
212
+ "document.pptx": edits.bytes,
213
+ "base.pptx": edits.base
214
+ }), { flag: "wx" });
215
+ await rename(temporary, path);
216
+ } finally {
217
+ await rm(temporary, { force: true });
218
+ }
219
+ },
220
+ async clear() {
221
+ await rm(path, { force: true });
222
+ }
223
+ };
224
+ }
225
+ async function applySavedEdits(entry, source) {
226
+ const edits = await editorStore(entry).read();
227
+ if (!edits) return source;
228
+ let bytes = edits.bytes;
229
+ if (edits.sourceHash !== sourceFingerprint(source.bytes)) {
230
+ const merged = edits.base ? mergeDecks(edits.base, edits.bytes, source.bytes) : null;
231
+ if (!merged?.ok) throw new Error(["Source changed since the last editor save. Open office-pptx dev and resolve the editor conflict before exporting.", ...merged?.conflicts.map(describeConflict) ?? []].join("\n"));
232
+ bytes = merged.bytes;
233
+ }
234
+ return (await renderDeck(bytes, source.dependencies)).result;
235
+ }
236
+ //#endregion
160
237
  //#region src/init.ts
161
238
  const starter = `import { Presentation } from '@office-kit/pptx-dsl';
162
239
  import { Cover } from './slides/cover.tsx';
@@ -169,7 +246,7 @@ export default (
169
246
  `;
170
247
  const theme = `export const theme = {
171
248
  background: '#15171C',
172
- accent: '#E5481F',
249
+ accent: '#D6336C',
173
250
  text: '#FFFFFF',
174
251
  muted: '#B4B9C4',
175
252
  } as const;
@@ -229,7 +306,7 @@ for shared design values. The JSX runtime is
229
306
  new URL('./image.png', import.meta.url) when loading local assets.
230
307
  - Preserve existing slides and formatting unless the request calls for changes.
231
308
  Never rasterize a chart/table as a shortcut. Raw-only features are not DSL coverage.
232
- - Preview is a rendering aid, not a guarantee of identical PowerPoint rendering.
309
+ - Preview is a rendering aid, not a guarantee of identical rendering in other apps.
233
310
  Check the exported file in the target application for final delivery.
234
311
 
235
312
  VSCode uses tsconfig.json for completion and diagnostics. Start the
@@ -364,7 +441,7 @@ async function inspectTemplate(file) {
364
441
  async function buildDeck(entry) {
365
442
  const builder = createDeckBuilder(entry, false);
366
443
  try {
367
- return await builder.build();
444
+ return await applySavedEdits(entry, await builder.build());
368
445
  } finally {
369
446
  await builder.close();
370
447
  }
@@ -375,6 +452,6 @@ async function exportDeck(entry, output) {
375
452
  return result;
376
453
  }
377
454
  //#endregion
378
- export { createDeckBuilder as a, initProject as i, exportDeck as n, inspectTemplate as r, buildDeck as t };
455
+ export { editorStore as a, initProject as i, exportDeck as n, sourceFingerprint as o, inspectTemplate as r, createDeckBuilder as s, buildDeck as t };
379
456
 
380
- //# sourceMappingURL=src-YH6kAXbA.mjs.map
457
+ //# sourceMappingURL=src-DASlwPDd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-DASlwPDd.mjs","names":[],"sources":["../src/bundle.ts","../src/build-runner.ts","../src/fingerprint.ts","../src/editor-store.ts","../src/init.ts","../src/inspect.ts","../src/index.ts"],"sourcesContent":["import { context, transform } from 'esbuild';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { resolve, sep } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\n\nconst resolvePackage = (name: string) => fileURLToPath(import.meta.resolve(name));\n\nexport async function createDeckCompiler(entry: string) {\n const transformedSources = new Map<string, { source: string; code: string }>();\n const compiler = await context({\n entryPoints: [resolve(entry)],\n outfile: 'deck.mjs',\n write: false,\n bundle: true,\n platform: 'node',\n format: 'esm',\n target: 'node22',\n jsx: 'automatic',\n jsxImportSource: '@office-kit/pptx-dsl',\n sourcemap: 'inline',\n sourceRoot: pathToFileURL(process.cwd() + sep).href,\n metafile: true,\n logLevel: 'silent',\n plugins: [\n {\n name: 'source-location',\n setup(builder) {\n // A bundled module lives in a temporary directory. Keep source-relative\n // asset URLs pointing at each original module, including imported files.\n builder.onLoad({ filter: /\\.[cm]?[jt]sx?$/ }, async ({ path }) => {\n const source = await readFile(path, 'utf8');\n const cached = transformedSources.get(path);\n if (cached?.source === source) return { contents: cached.code, loader: 'js' };\n const loader = path.endsWith('.tsx')\n ? 'tsx'\n : path.endsWith('.ts') || path.endsWith('.mts') || path.endsWith('.cts')\n ? 'ts'\n : path.endsWith('.jsx')\n ? 'jsx'\n : 'js';\n const transformed = await transform(source, {\n loader,\n sourcefile: path,\n sourcemap: 'inline',\n jsx: 'automatic',\n jsxDev: true,\n jsxImportSource: '@office-kit/pptx-dsl',\n define: { 'import.meta.url': JSON.stringify(pathToFileURL(path).href) },\n });\n transformedSources.set(path, { source, code: transformed.code });\n return { contents: transformed.code, loader: 'js' };\n });\n },\n },\n {\n name: 'shared-office-kit',\n setup(builder) {\n // Core uses symbol-backed handles; all consumers must share its instance.\n builder.onResolve({ filter: /^@office-kit\\/pptx(?:-dsl)?(?:\\/.*)?$/ }, ({ path }) => ({\n path: resolvePackage(path),\n external: true,\n }));\n },\n },\n ],\n });\n return {\n async build(output: string) {\n const result = await compiler.rebuild();\n await writeFile(output, result.outputFiles[0]!.contents);\n const dependencies = Object.keys(result.metafile!.inputs).map((path) => resolve(path));\n const used = new Set(dependencies);\n for (const path of transformedSources.keys())\n if (!used.has(path)) transformedSources.delete(path);\n return dependencies;\n },\n cancel: () => compiler.cancel(),\n close: () => compiler.dispose(),\n };\n}\n","import { Worker } from 'node:worker_threads';\nimport { join } from 'node:path';\nimport { mkdtempSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport type { BuildResult } from './build.ts';\nimport type { PreviewCache } from './preview-cache.ts';\nimport { createDeckCompiler } from './bundle.ts';\n\nconst BUILD_TIMEOUT_MS = 60_000;\n\nfunction prepareWorker() {\n const directory = mkdtempSync(join(tmpdir(), 'office-pptx-'));\n const worker = new Worker(new URL('./worker.mjs', import.meta.url), {\n workerData: { directory },\n execArgv: ['--enable-source-maps'],\n });\n const result = new Promise<{ result: BuildResult; cache: PreviewCache }>(\n (resolveBuild, reject) => {\n worker.once('message', resolveBuild);\n worker.once('error', reject);\n worker.once('exit', (code) =>\n reject(new Error(`Build worker exited without a result (code ${code}).`)),\n );\n },\n );\n // Startup may fail before the next edit asks to use this worker.\n void result.catch(() => {});\n return { worker, result, directory };\n}\n\n/** Internal watch session. Preload libraries, but never reuse a user module cache. */\nexport function createDeckBuilder(entry: string, keepWarm = true) {\n const compiler = createDeckCompiler(entry);\n void compiler.catch(() => {});\n let prepared: ReturnType<typeof prepareWorker> | undefined = prepareWorker();\n let cache: PreviewCache | undefined;\n let closed = false;\n let active = false;\n return {\n async build(): Promise<BuildResult> {\n if (closed || active) throw new Error('Deck builder is closed or already building.');\n active = true;\n const current = prepared ?? prepareWorker();\n prepared = current;\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n const built = await Promise.race([\n (async () => {\n const dependencies = await (await compiler).build(join(current.directory, 'deck.mjs'));\n current.worker.postMessage({ dependencies, cache });\n return current.result;\n })(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(\n 'Build exceeded 60 seconds. Check the deck for loops or unresolved promises.',\n ),\n ),\n BUILD_TIMEOUT_MS,\n );\n }),\n ]);\n cache = built.cache;\n return built.result;\n } finally {\n clearTimeout(timer);\n await compiler.then(\n (compiler) => compiler.cancel(),\n () => {},\n );\n await current.worker.terminate();\n await rm(current.directory, { recursive: true, force: true });\n active = false;\n prepared = !closed && keepWarm ? prepareWorker() : undefined;\n }\n },\n async cancel() {\n if (!active) return;\n const current = prepared;\n await compiler.then(\n (compiler) => compiler.cancel(),\n () => {},\n );\n await current?.worker.terminate();\n },\n async close() {\n closed = true;\n const current = prepared;\n await compiler.then(\n (compiler) => compiler.cancel(),\n () => {},\n );\n await current?.worker.terminate();\n await compiler.then(\n (compiler) => compiler.close(),\n () => {},\n );\n if (current) await rm(current.directory, { recursive: true, force: true });\n },\n };\n}\n","import { createHash } from 'node:crypto';\nimport { comparablePart } from '@office-kit/pptx-editor/merge';\nimport { unzipSync } from 'fflate';\n\n/** ZIP container dates and generated core timestamps are not source edits. */\nexport function sourceFingerprint(bytes: Uint8Array): string {\n const parts = unzipSync(bytes);\n const hash = createHash('sha256');\n for (const name of Object.keys(parts).sort()) {\n const content = comparablePart(name, parts[name]!);\n hash.update(JSON.stringify([name, createHash('sha256').update(content).digest('hex')]));\n }\n return hash.digest('hex');\n}\n","import { randomUUID } from 'node:crypto';\nimport { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { strFromU8, strToU8, unzipSync, zipSync } from 'fflate';\nimport { renderDeck, type BuildResult } from './build.ts';\nimport { describeConflict, mergeDecks } from '@office-kit/pptx-editor/merge';\nimport { sourceFingerprint } from './fingerprint.ts';\n\nexport interface SavedEdits {\n sourceHash: string;\n bytes: Uint8Array;\n /**\n * The source build the edits were made against, which lets a later source\n * change merge with them. Version 1 sidecars did not store it.\n */\n base: Uint8Array | null;\n}\n\nconst STORE_VERSION = 2;\n\n/** One atomic sidecar keeps the saved deck and its source basis in agreement. */\nexport function editorStore(entry: string) {\n const path = join(dirname(resolve(entry)), '.office-kit', `${basename(entry)}.editor.zip`);\n return {\n path,\n async read(): Promise<SavedEdits | undefined> {\n let bytes: Uint8Array;\n try {\n bytes = await readFile(path);\n } catch (cause) {\n if (cause instanceof Error && 'code' in cause && cause.code === 'ENOENT') return;\n throw cause;\n }\n const parts = unzipSync(bytes);\n if (!parts['state.json'] || !parts['document.pptx'])\n throw new Error(`Invalid editor file: ${path}`);\n const state: unknown = JSON.parse(strFromU8(parts['state.json']));\n if (\n !state ||\n typeof state !== 'object' ||\n !('version' in state) ||\n (state.version !== 1 && state.version !== STORE_VERSION) ||\n !('sourceHash' in state) ||\n typeof state.sourceHash !== 'string' ||\n !/^[a-f0-9]{64}$/.test(state.sourceHash)\n ) {\n throw new Error(`Invalid editor metadata: ${path}`);\n }\n const base = parts['base.pptx'];\n if (state.version === STORE_VERSION && !base) throw new Error(`Invalid editor file: ${path}`);\n return { sourceHash: state.sourceHash, bytes: parts['document.pptx'], base: base ?? null };\n },\n async write(edits: SavedEdits & { base: Uint8Array }): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const temporary = `${path}.${randomUUID()}.tmp`;\n try {\n await writeFile(\n temporary,\n zipSync({\n 'state.json': strToU8(\n JSON.stringify({ version: STORE_VERSION, sourceHash: edits.sourceHash }),\n ),\n 'document.pptx': edits.bytes,\n 'base.pptx': edits.base,\n }),\n { flag: 'wx' },\n );\n await rename(temporary, path);\n } finally {\n await rm(temporary, { force: true });\n }\n },\n async clear(): Promise<void> {\n await rm(path, { force: true });\n },\n };\n}\n\nexport async function applySavedEdits(entry: string, source: BuildResult): Promise<BuildResult> {\n const edits = await editorStore(entry).read();\n if (!edits) return source;\n let bytes = edits.bytes;\n if (edits.sourceHash !== sourceFingerprint(source.bytes)) {\n const merged = edits.base ? mergeDecks(edits.base, edits.bytes, source.bytes) : null;\n if (!merged?.ok) {\n throw new Error(\n [\n 'Source changed since the last editor save. Open office-pptx dev and resolve the editor conflict before exporting.',\n ...(merged?.conflicts.map(describeConflict) ?? []),\n ].join('\\n'),\n );\n }\n bytes = merged.bytes;\n }\n return (await renderDeck(bytes, source.dependencies)).result;\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\n\nconst starter = `import { Presentation } from '@office-kit/pptx-dsl';\nimport { Cover } from './slides/cover.tsx';\n\nexport default (\n <Presentation>\n <Cover />\n </Presentation>\n);\n`;\n\nconst theme = `export const theme = {\n background: '#15171C',\n accent: '#D6336C',\n text: '#FFFFFF',\n muted: '#B4B9C4',\n} as const;\n`;\n\nconst cover = `import { Slide, Text, Shape } from '@office-kit/pptx-dsl';\nimport { theme } from '../theme.ts';\n\nexport function Cover() {\n return (\n <Slide background={theme.background}>\n <Shape preset=\"rect\" x={0.9} y={2.55} width={0.14} height={1.75} fill={theme.accent} stroke={false} />\n <Text x={1.25} y={2.4} width={10} height={1.1} size={48} bold color={theme.text}>\n Your next presentation\n </Text>\n <Text x={1.25} y={3.55} width={10} height={0.6} size={22} color={theme.muted}>\n Edit this TSX and save to update the preview.\n </Text>\n </Slide>\n );\n}\n`;\n\nconst guide = `# Writing this presentation\n\nUse deck.tsx for slide order, slides/*.tsx for individual slides, and theme.ts\nfor shared design values. The JSX runtime is\n@office-kit/pptx-dsl, with no React or Vue dependency.\n\n- Run npm run dev, then open its local URL to preview. Saving source files\n updates the preview. A failed build retains the last successful output.\n- Select an area in the preview to request a focused AI edit, or use Edit text\n for a direct text save. Changes are persisted in TSX. Use the thumbnails, zoom\n and Present to review slides. After edits, inspect every screenshot supplied\n by the preview and correct clipping, overlap, spacing and contrast.\n- For a local revision, locate the slide through deck.tsx or a text search and\n read only the relevant source and dependencies. Patch the requested text, data\n or props; do not regenerate the deck or reformat unrelated code. Keep descriptive\n filenames stable when reordering slides. Preserve existing project structures.\n- Change shared theme values/components only for changes intended for all their\n consumers; use a local prop override for a one-slide exception.\n- Keep the preview running during revisions and inspect affected slides after\n saving. Review all affected consumers for shared changes. Do not run a separate\n export for every intermediate edit. Before delivery, run npm run check and\n npm run build to export deck.pptx, then review the whole deck.\n- Coordinates and dimensions are inches; font sizes and stroke widths are points.\n The default 16:9 canvas is 13.333 × 7.5 inches.\n- Use native Text, Shape, Image, Table and Chart elements. Use JS functions,\n arrays and map to compose elements; do not import React.\n- Chart takes the core ChartSpec in its spec prop. Text accepts rich ParagraphSpec\n arrays through paragraphs. Raw is an escape hatch for public core APIs.\n- For templates: readFile(new URL('./template.pptx', import.meta.url)), then use\n Presentation source={bytes} mode=\"edit\" and Slide target={{index: 0}}.\n Fill target={{name: 'Title 1'}} changes an existing shape. Indices are zero-based.\n Use office-pptx inspect template.pptx to discover names, layouts and placeholders.\n- Use mode=\"compose\" and Slide from={{index: 0}} to build a new sequence from a\n source deck. This intentionally removes the original slide sequence.\n- Keep assets inside this project so the dev server sees changes. Use source-relative\n new URL('./image.png', import.meta.url) when loading local assets.\n- Preserve existing slides and formatting unless the request calls for changes.\n Never rasterize a chart/table as a shortcut. Raw-only features are not DSL coverage.\n- Preview is a rendering aid, not a guarantee of identical rendering in other apps.\n Check the exported file in the target application for final delivery.\n\nVSCode uses tsconfig.json for completion and diagnostics. Start the\n\"Preview presentation\" task, then run \"Simple Browser: Show\" with the printed URL\nand move that editor to a side group. Type errors appear in the Problems panel.\n`;\n\n/** Creates a new directory; existing projects are never overwritten. */\nexport async function initProject(directory: string): Promise<string> {\n const root = resolve(directory);\n const packageLocations = [\n import.meta.resolve('@office-kit/pptx/package.json'),\n import.meta.resolve('@office-kit/pptx-dsl/package.json'),\n new URL('../package.json', import.meta.url),\n ];\n const versions = await Promise.all(\n packageLocations.map(async (location) => {\n const manifest: { version: string } = JSON.parse(await readFile(new URL(location), 'utf8'));\n return `^${manifest.version}`;\n }),\n );\n await mkdir(root);\n const files: Record<string, string> = {\n 'package.json':\n JSON.stringify(\n {\n name: 'my-presentation',\n private: true,\n type: 'module',\n scripts: {\n dev: 'office-pptx dev deck.tsx',\n build: 'office-pptx build deck.tsx --out deck.pptx',\n check: 'tsc --noEmit',\n },\n dependencies: { '@office-kit/pptx': versions[0]!, '@office-kit/pptx-dsl': versions[1]! },\n devDependencies: {\n '@office-kit/pptx-dev': versions[2]!,\n '@types/node': '^24.13.2',\n typescript: '^6.0.3',\n },\n },\n null,\n 2,\n ) + '\\n',\n 'tsconfig.json':\n JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'Bundler',\n jsx: 'react-jsx',\n jsxImportSource: '@office-kit/pptx-dsl',\n strict: true,\n exactOptionalPropertyTypes: true,\n noEmit: true,\n allowImportingTsExtensions: true,\n types: ['node'],\n },\n include: ['**/*.ts', '**/*.tsx'],\n exclude: ['node_modules'],\n },\n null,\n 2,\n ) + '\\n',\n 'deck.tsx': starter,\n 'theme.ts': theme,\n 'slides/cover.tsx': cover,\n // Same text under both names on purpose: Claude Code loads CLAUDE.md,\n // Codex loads AGENTS.md, and an agent that starts without the guide\n // reaches for its own slide tooling instead of editing the TSX.\n 'CLAUDE.md': guide,\n 'AGENTS.md': guide,\n 'README.md':\n '# Your slides\\n\\nInstall once with `npm install`, then run `npm run dev` (or `npx office-pptx dev deck.tsx`). Open the printed URL.\\n\\nEdit `slides/cover.tsx`, select an area for an AI instruction, or choose Edit text in the preview. Start Claude Code in an agent pane before sending instructions. An installed Chrome enables automatic screenshot review.\\n\\nRun `npm run check` and `npm run build` to check and export `deck.pptx`.\\n',\n '.gitignore': 'node_modules/\\ndeck.pptx\\n.office-kit/\\n',\n '.vscode/tasks.json':\n JSON.stringify(\n {\n version: '2.0.0',\n tasks: [\n {\n label: 'Preview presentation',\n type: 'shell',\n command: 'npm run dev',\n isBackground: true,\n problemMatcher: {\n pattern: { regexp: '^NEVER_MATCH$', file: 1, message: 2 },\n background: {\n activeOnStart: true,\n beginsPattern: '^.*office-pptx dev',\n endsPattern: '^Preview: ',\n },\n },\n },\n {\n label: 'Check presentation',\n type: 'shell',\n command: 'npm run check',\n problemMatcher: '$tsc',\n },\n {\n label: 'Export presentation',\n type: 'shell',\n command: 'npm run build',\n problemMatcher: [],\n },\n ],\n },\n null,\n 2,\n ) + '\\n',\n };\n await Promise.all(['.vscode', 'slides'].map((directory) => mkdir(join(root, directory))));\n await Promise.all(\n Object.entries(files).map(([name, content]) =>\n writeFile(join(root, name), content, { flag: 'wx' }),\n ),\n );\n return root;\n}\n","import { readFile } from 'node:fs/promises';\nimport {\n loadPresentation,\n getSlides,\n getSlidePartName,\n getSlideTitle,\n getSlideShapes,\n getShapeName,\n getShapeId,\n getShapeKind,\n getShapePlaceholderType,\n getShapePlaceholderIdx,\n getSlideLayouts,\n getSlideLayoutName,\n getSlideLayoutPartName,\n getSlideLayoutType,\n} from '@office-kit/pptx';\n\n/** Source references usable directly in Slide, Fill and Remove props. */\nexport async function inspectTemplate(file: string) {\n const presentation = await loadPresentation(await readFile(file));\n return {\n slides: getSlides(presentation).map((slide, index) => ({\n index,\n part: getSlidePartName(slide),\n title: getSlideTitle(slide),\n shapes: getSlideShapes(slide).map((shape) => ({\n id: getShapeId(shape),\n name: getShapeName(shape),\n kind: getShapeKind(shape),\n placeholder: { type: getShapePlaceholderType(shape), idx: getShapePlaceholderIdx(shape) },\n })),\n })),\n layouts: getSlideLayouts(presentation).map((layout) => ({\n part: getSlideLayoutPartName(layout),\n name: getSlideLayoutName(layout),\n type: getSlideLayoutType(layout),\n })),\n };\n}\n","import { writeFile } from 'node:fs/promises';\nimport { createDeckBuilder } from './build-runner.ts';\nimport type { BuildResult } from './build.ts';\nimport { applySavedEdits } from './editor-store.ts';\nexport type { BuildResult } from './build.ts';\nexport { initProject } from './init.ts';\nexport { inspectTemplate } from './inspect.ts';\n\n/** Each evaluation gets a fresh module cache and releases it when finished. */\nexport async function buildDeck(entry: string): Promise<BuildResult> {\n const builder = createDeckBuilder(entry, false);\n try {\n return await applySavedEdits(entry, await builder.build());\n } finally {\n await builder.close();\n }\n}\nexport async function exportDeck(entry: string, output: string): Promise<BuildResult> {\n const result = await buildDeck(entry);\n await writeFile(output, result.bytes);\n return result;\n}\n"],"mappings":"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"}