@mdgate/ppt 0.1.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/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # @mdgate/ppt
2
+
3
+ Convert legacy binary PowerPoint presentations to Markdown. Outputs GitHub-Flavored Markdown. Works in Node, Edge, and
4
+ browsers. No native addons.
5
+
6
+ Handles: `.ppt`, `.pps`, `.pot` (binary PowerPoint)
7
+
8
+ ## Usage
9
+
10
+ ```ts
11
+ import { toMarkdown } from '@mdgate/ppt';
12
+
13
+ const markdown = await toMarkdown(bytes);
14
+ ```
15
+
16
+ Compose with other converters:
17
+
18
+ ```ts
19
+ import { create } from '@mdgate/core';
20
+ import { ppt } from '@mdgate/ppt';
21
+
22
+ const convert = create([ppt()]);
23
+ ```
24
+
25
+ Part of [mdgate converters](https://github.com/mdgate/converters); install
26
+ `@mdgate/converters` for every format at once.
@@ -0,0 +1,2 @@
1
+ export { ppt } from './ppt.js';
2
+ export { toMarkdown } from './to-markdown.js';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{detectOleDoc as w8}from"@mdgate/containers";import{documentToMarkdown as B8}from"@mdgate/document";import{fileExtension as X8}from"@mdgate/utils";import{CompoundFile as s,getU32 as X,MAX_ENTRY_BYTES as t,MAX_RECORD_DEPTH as n,MAX_RECORDS as p,readOleStream as d}from"@mdgate/containers";import{ConvertError as P}from"@mdgate/core";import{inlinesAreEmpty as e,inlinesToPlainText as z8,PLAIN as G8,stylesEqual as H8}from"@mdgate/document";import{AssetSink as J8,decodeBlip as K8,fbseBlip as Q8,flushList as L,rebaseEmphasis as V8,recordAt as D,resolveDelta as W8}from"@mdgate/office-common";import{cleanText as v,debug as o,warn as Z8}from"@mdgate/utils";import{getU16 as U,getU32 as R}from"@mdgate/containers";import{debug as f}from"@mdgate/utils";function x(){return{paragraphs:[],chars:[]}}function u(){return{bullet:void 0,bold:void 0,italic:void 0}}function b(H,J){let z=x(),G=0,Q=0;while(Q<=J){let K=R(H,G);if(K===void 0)break;let V=U(H,G+4);if(V===void 0)break;G+=6;let W=y(H,G);if(W===void 0)return f("unparseable paragraph style run; keeping styling parsed so far"),z;if(G=W.next,z.paragraphs.push({count:K,depth:V,bullet:W.bullet}),Q+=K,K===0)break}Q=0;while(Q<=J){let K=R(H,G);if(K===void 0)break;G+=4;let V=l(H,G);if(V===void 0){f("unparseable character style run; dropping remaining styling");break}if(G=V.next,z.chars.push({count:K,bold:V.bold,italic:V.italic}),Q+=K,K===0)break}return z}function y(H,J){let z=J,G=R(H,z);if(G===void 0)return;z+=4;let Q;if((G&15)!==0){let K=U(H,z);if(K===void 0)return;if((G&1)!==0)Q=(K&1)!==0;z+=2}if((G&128)!==0)z+=2;if((G&16)!==0)z+=2;if((G&64)!==0)z+=2;if((G&32)!==0)z+=4;if((G&2048)!==0)z+=2;if((G&4096)!==0)z+=2;if((G&8192)!==0)z+=2;if((G&16384)!==0)z+=2;if((G&256)!==0)z+=2;if((G&1024)!==0)z+=2;if((G&32768)!==0)z+=2;if((G&1048576)!==0){let K=U(H,z);if(K===void 0)return;z+=2+K*4}if((G&65536)!==0)z+=2;if((G&917504)!==0)z+=2;if((G&2097152)!==0)z+=2;if(z>H.length)return;return{bullet:Q,next:z}}function l(H,J){let z=J,G=R(H,z);if(G===void 0)return;z+=4;let Q,K;if((G&65535)!==0){let V=U(H,z);if(V===void 0)return;if((G&1)!==0)Q=(V&1)!==0;if((G&2)!==0)K=(V&2)!==0;z+=2}if((G&65536)!==0)z+=2;if((G&2097152)!==0)z+=2;if((G&4194304)!==0)z+=2;if((G&8388608)!==0)z+=2;if((G&131072)!==0)z+=2;if((G&262144)!==0)z+=4;if((G&524288)!==0)z+=2;if(z>H.length)return;return{bold:Q,italic:K,next:z}}function c(H,J){let z=U(H,0);if(z===void 0)return[];let G=2,Q=[],K=Math.min(z,10);for(let V=0;V<K;V+=1){if(J>=5)G+=2;let W=y(H,G);if(W===void 0)break;G=W.next;let Z=l(H,G);if(Z===void 0)break;G=Z.next,Q.push({bullet:W.bullet,bold:Z.bold,italic:Z.italic})}return Q}function r(H){let J;try{J=s.open(H)}catch(V){if(V instanceof P&&V.code!=="malformed")throw V;let W=V instanceof P&&V.detail!==void 0?V.detail:V instanceof Error?V.message:String(V);throw P.malformed(`not an OLE2 compound file: ${W}`)}let z=d(J,"PowerPoint Document"),G=a(J,"Current User")??new Uint8Array;if(X(G,12)===4090610911)throw P.encrypted();let Q=new g;if(!Q.parseSlides(z,G))Z8("ppt persist directory unusable; recovering text in raw stream order"),Q=new g,Q.recovering=!0,Q.walk(z),Q.endSegment(void 0);if(Q.encrypted)throw P.encrypted();let K=$8(J);return{blocks:Q.intoBlocks(),notes:[],assets:K}}function a(H,J){try{return d(H,J)}catch{return}}function $8(H){let J=a(H,"Pictures");if(J===void 0)return[];let z=new J8,G=0,Q=0;for(;;){let K=D(J,G);if(K===void 0)break;let[V,W,Z]=K;if(G+=8+Z.length,Q+=1,Q>1e5)break;let $=t,j=W===61447?Q8(Z,$):K8(V,W,Z,$);if(j!==void 0)z.add(j.mediaType,`pictures/${Q}.${j.extension}`,j.bytes);else o(`skipping unsupported Pictures record 0x${W.toString(16).padStart(4,"0")}`)}return z.assets}function*A(H){let J=0;for(;;){let z=D(H,J);if(z===void 0)return;J+=8+z[2].length,yield z}}function q8(H){let J=H.length&-2;return new TextDecoder("utf-16le").decode(H.subarray(0,J))}function j8(H){return new TextDecoder("latin1").decode(H)}class g{segments=[];current=[];currentIsNotes=!1;listRun=[];pending;masters=[];activeMaster=0;shapeCounter=0;encrypted=!1;recovering=!1;records=0;parseSlides(H,J){let z=F8(H,J);if(z===void 0)return!1;if(this.masters=Y8(z.masterList,z.persist,H),this.walkSlideList(z.slideList,z.persist,H,!1,1006),z.notesList!==void 0)this.walkSlideList(z.notesList,z.persist,H,!0,1008);return!0}walkSlideList(H,J,z,G,Q){let K;for(let[W,Z,$]of A(H))if(Z===1011){let j=this.finishSlide(K,J,z,Q,G);this.endSegment(j),this.currentIsNotes=G;let _=X($,0);if(K=_===void 0?void 0:[_,X($,12)??0],!G)this.selectMaster(K!==void 0?K[0]:void 0,J,z)}else this.record(W,Z,$);let V=this.finishSlide(K,J,z,Q,G);this.endSegment(V)}finishSlide(H,J,z,G,Q){if(H===void 0)return;let[K,V]=H,W=Q?void 0:V!==0?V:void 0,Z=J.get(K);if(Z!==void 0){let $=D(z,Z);if($!==void 0&&$[1]===G){let j=$[2];if(Q){for(let[,_,M]of A(j))if(_===1009){let F=X(M,0);W=F!==void 0&&F!==0?F:void 0;break}}this.walk(j)}}return W}endSegment(H){if(this.flushShape(),L(this.current,this.listRun),this.current.length>0)this.segments.push({blocks:this.current,id:H,isNotes:this.currentIsNotes}),this.current=[]}intoBlocks(){this.endSegment(void 0);let H=[],J=[];for(let Q of this.segments)if(Q.isNotes)J.push({id:Q.id,blocks:Q.blocks});else H.push({id:Q.id,blocks:Q.blocks});let z=J.map(()=>!1),G=[];for(let Q of H){G.push(...Q.blocks);for(let K=0;K<J.length;K+=1)if(!z[K]&&Q.id!==void 0&&J[K].id===Q.id)z[K]=!0,G.push({type:"blockQuote",blocks:J[K].blocks}),J[K].blocks=[]}for(let Q=0;Q<J.length;Q+=1)if(!z[Q]&&J[Q].blocks.length>0)G.push({type:"blockQuote",blocks:J[Q].blocks});return G}selectMaster(H,J,z){let G=0;if(H!==void 0){let Q=J.get(H);if(Q!==void 0){let K=D(z,Q);if(K!==void 0&&K[1]===1006){for(let[,V,W]of A(K[2]))if(V===1007){let Z=X(W,12);if(Z!==void 0){let $=this.masters.findIndex(([j])=>j===Z);if($>=0)G=$}break}}}}this.activeMaster=G}walk(H){let J=[{buf:H,pos:0}];while(J.length>0){let z=J[J.length-1],G=D(z.buf,z.pos);if(G===void 0){J.pop();continue}let[Q,K,V]=G;if(z.pos+=8+V.length,this.chargeRecord(),(Q&15)!==15){this.atom(K,V);continue}if(K===12052){this.encrypted=!0;continue}if(K===1008&&this.recovering){let W=!1;for(let[,Z,$]of A(V))if(Z===1009){let j=X($,0);W=j!==void 0&&(j&2147483648)!==0;break}if(!W)this.endSegment(void 0),this.currentIsNotes=!0,this.walk(V),this.endSegment(void 0),this.currentIsNotes=!1;continue}if(K===1008||K===1016||K===4041)continue;if(K===4080&&Q>>>4!==0)continue;if(J.length>=n)throw P.resourceLimit("max_record_depth",`record nesting exceeds ${n}`);J.push({buf:V,pos:0})}}record(H,J,z){if(this.chargeRecord(),(H&15)===15)if(J===12052)this.encrypted=!0;else if(J===1008||J===1016||J===4041);else if(J===4080&&H>>>4!==0);else this.walk(z);else this.atom(J,z)}chargeRecord(){if(this.records+=1,this.records>p)throw P.resourceLimit("max_records",`record stream exceeds ${p} records`)}atom(H,J){switch(H){case 3999:{this.flushShape(),this.pending={txType:J[0]??1,text:"",styles:void 0};break}case 4000:{this.pushText(q8(J));break}case 4008:{this.pushText(j8(J));break}case 4001:{if(this.pending!==void 0)this.pending.styles=b(J,this.pending.text.length);break}case 4051:{o("ppt hyperlink records present; targets are not resolved");break}default:break}}pushText(H){if(this.pending!==void 0)this.pending.text+=H;else this.pending={txType:1,text:H,styles:void 0}}flushShape(){let H=this.pending;if(this.pending=void 0,H===void 0||H.text.length===0)return;this.shapeCounter+=1;let J=this.shapeCounter,z=H.txType===0||H.txType===6,G=H.styles??x(),Q=this.masters[this.activeMaster]?.[1].get(H.txType)??[],K=(q)=>Q[q]??u(),V=0,W=G.chars[0],Z=W?.count??Number.MAX_SAFE_INTEGER,$=0,j=G.paragraphs[0],_=j?.count??Number.MAX_SAFE_INTEGER,M=[],F=[],Y="",w={...G8},S=(q)=>q!==void 0?[q.depth,q.bullet]:[0,void 0];for(let q of H.text){let C=K(S(j)[0]),O={bold:W?.bold??C.bold??!1,italic:W?.italic??C.italic??!1,strike:!1,code:!1};if(q==="\r"){if(Y.length>0){let E=v(Y);if(Y="",E.length>0)F.push({type:"text",text:E,style:{...w}})}let[B,I]=S(j);M.push([F,B,I]),F=[]}else if(q==="\v"){if(Y.length>0){let B=v(Y);if(Y="",B.length>0)F.push({type:"text",text:B,style:{...w}})}F.push({type:"lineBreak"})}else{if(!H8(O,w)&&Y.length>0){let B=v(Y);if(Y="",B.length>0)F.push({type:"text",text:B,style:{...w}})}w=O,Y+=q}let N=q.length;if(Z=Math.max(0,Z-N),Z===0)V+=1,W=G.chars[V],Z=W?.count??Number.MAX_SAFE_INTEGER;if(_=Math.max(0,_-N),_===0)$+=1,j=G.paragraphs[$],_=j?.count??Number.MAX_SAFE_INTEGER}if(Y.length>0){let q=v(Y);if(q.length>0)F.push({type:"text",text:q,style:{...w}})}if(F.length>0){let[q,C]=S(j);M.push([F,q,C])}for(let[q,C,O]of M){if(e(q)){L(this.current,this.listRun);continue}if(z){L(this.current,this.listRun);let B=K(C),I={bold:B.bold,italic:B.italic,strike:void 0,code:void 0};V8(q,W8(I));let E=z8(q);this.current.push({type:"heading",level:2,anchor:E,content:q});continue}if(O??K(C).bullet??!1)this.listRun.push({level:C,key:{instance:J,marker:"bullet"},number:0,label:void 0,blocks:[{type:"paragraph",inlines:q}]});else L(this.current,this.listRun),this.current.push({type:"paragraph",inlines:q})}}}function F8(H,J){let z=new Map,G,Q=X(J,16);if(Q===void 0)return;let K=Q;for(let M=0;M<100;M+=1){if(K===0)break;let F=D(H,K);if(F===void 0)return;let Y=F[1],w=F[2];if(Y!==4085)return;if(G===void 0)G=X(w,16);let S=X(w,12);if(S===void 0)return;let q=D(H,S);if(q!==void 0&&q[1]===6002){let O=q[2],N=0;while(N+4<=O.length){let B=X(O,N);if(B===void 0)return;let I=B&1048575,E=B>>>20;N+=4;for(let k=0;k<E;k+=1){let T=X(O,N);if(T===void 0)return;let m=I+k>>>0;if(!z.has(m))z.set(m,T);N+=4}}}let C=X(w,8);if(C===void 0)return;if(C===K)break;K=C}if(G===void 0)return;let V=z.get(G);if(V===void 0)return;let W=D(H,V);if(W===void 0||W[1]!==1000)return;let Z=W[2],$,j,_;for(let[M,F,Y]of A(Z)){if(F!==4080)continue;let w=M>>>4;if(w===0&&$===void 0)$=Y;else if(w===2&&j===void 0)j=Y;else if(w===1&&_===void 0)_=Y}if($===void 0)return;return{persist:z,slideList:$,notesList:j,masterList:_}}function i(H){let J=new Map;for(let[z,G,Q]of A(H))if(G===4003){let K=z>>>4;if(!J.has(K))J.set(K,c(Q,K))}return J}function Y8(H,J,z){let G=[];if(H!==void 0)for(let[,Q,K]of A(H)){if(Q!==1011)continue;let V=X(K,0),W=X(K,12);if(V===void 0||W===void 0)continue;let Z=J.get(V);if(Z===void 0)continue;let $=D(z,Z);if($!==void 0&&$[1]===1016)G.push([W,i($[2])])}if(G.length===0){let Q=[...J.values()].sort((K,V)=>K-V);for(let K of Q){let V=D(z,K);if(V!==void 0&&V[1]===1016)G.push([0,i(V[2])])}}return G}var _8=new Set(["ppt","pps","pot"]);function h(){return{id:"ppt",sniff(H,J){if(w8(H)==="ppt")return 2;if(J?.path!==void 0&&_8.has(X8(J.path)??""))return 1;return 0},convert(H){return{markdown:B8(r(H))}}}}import{create as C8}from"@mdgate/core";var M8=C8([h()]);function D8(H,J){return M8(H,J)}export{D8 as toMarkdown,h as ppt};
package/dist/ppt.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { Converter } from '@mdgate/core';
2
+ export declare function ppt(): Converter;
@@ -0,0 +1,6 @@
1
+ import { type ConvertHint } from '@mdgate/core';
2
+ /**
3
+ * Convert a single file's bytes to Markdown with the ppt converter.
4
+ * `hint.path` is only a sniff hint; it is never read from disk.
5
+ */
6
+ export declare function toMarkdown(bytes: Uint8Array, hint?: ConvertHint): Promise<string>;
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@mdgate/ppt",
3
+ "version": "0.1.0",
4
+ "description": "mdgate legacy PowerPoint converter (binary .ppt)",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist/**/*.js",
18
+ "dist/**/*.d.ts"
19
+ ],
20
+ "scripts": {
21
+ "build": "bun ../../scripts/build-package.ts",
22
+ "prepublishOnly": "bun run build"
23
+ },
24
+ "dependencies": {
25
+ "@mdgate/containers": "0.1.0",
26
+ "@mdgate/core": "0.1.3",
27
+ "@mdgate/document": "0.1.0",
28
+ "@mdgate/office-common": "0.1.0",
29
+ "@mdgate/utils": "0.1.2"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "engines": {
35
+ "node": ">=20"
36
+ },
37
+ "keywords": [
38
+ "mdgate",
39
+ "markdown",
40
+ "ppt",
41
+ "powerpoint"
42
+ ]
43
+ }