@mdgate/iwork-common 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,8 @@
1
+ # @mdgate/iwork-common
2
+
3
+ Shared Apple iWork archive parsing used by `@mdgate/pages`, `@mdgate/numbers`,
4
+ and `@mdgate/keynote`: ZIP/`Index.zip` opening, Snappy IWA chunks, protobuf wire
5
+ decoding, TSWP text storage, and TST tables.
6
+
7
+ Internal shared library for the mdgate converters. Install a converter package
8
+ instead of depending on this directly.
@@ -0,0 +1,13 @@
1
+ import { type IwaObject } from './iwa.js';
2
+ import { type ProtoField } from './protobuf.js';
3
+ import { type IWorkKind } from './types.js';
4
+ export interface IWorkArchive {
5
+ kind: IWorkKind;
6
+ objects: Map<number, IwaObject>;
7
+ }
8
+ /** Open a `.pages` / `.numbers` / `.key` package and load every `.iwa` object. */
9
+ export declare function openIWork(bytes: Uint8Array, expected?: IWorkKind): IWorkArchive;
10
+ export declare function detectIWorkKind(bytes: Uint8Array): IWorkKind | undefined;
11
+ export declare function getObject(archive: IWorkArchive, id: number | undefined): IwaObject | undefined;
12
+ export declare function deref(archive: IWorkArchive, fields: readonly ProtoField[], field: number): IwaObject | undefined;
13
+ export declare function derefAll(archive: IWorkArchive, fields: readonly ProtoField[], field: number): IwaObject[];
@@ -0,0 +1,23 @@
1
+ import type { Block } from '@mdgate/document';
2
+ import type { IWorkArchive } from './archive.js';
3
+ import { type ProtoField } from './protobuf.js';
4
+ /** Walk a drawable reference tree collecting text and tables. */
5
+ export declare function collectDrawableBlocks(archive: IWorkArchive, objId: number | undefined): Block[];
6
+ export declare function collectDrawableObject(archive: IWorkArchive, obj: {
7
+ id: number;
8
+ type: number;
9
+ fields: ProtoField[];
10
+ }): Block[];
11
+ export declare function findDocumentObject(archive: IWorkArchive, type: number): {
12
+ id: number;
13
+ type: number;
14
+ fields: ProtoField[];
15
+ } | undefined;
16
+ export declare function bodyStorageFromPages(archive: IWorkArchive): ProtoField[] | undefined;
17
+ export declare function numbersSheets(archive: IWorkArchive): {
18
+ name: string;
19
+ drawables: number[];
20
+ }[];
21
+ export declare function keynoteSlides(archive: IWorkArchive): number[];
22
+ /** Collect text blocks from a Keynote slide archive. */
23
+ export declare function slideToBlocks(archive: IWorkArchive, slideId: number): Block[];
@@ -0,0 +1,8 @@
1
+ export { deref, derefAll, detectIWorkKind, getObject, type IWorkArchive, openIWork, } from './archive.js';
2
+ export { bodyStorageFromPages, collectDrawableBlocks, collectDrawableObject, findDocumentObject, keynoteSlides, numbersSheets, slideToBlocks, } from './drawables.js';
3
+ export { buildIwa, type IwaObject, parseIwa } from './iwa.js';
4
+ export { decodeMessage, encodeBytesField, encodeMessageField, encodeStringField, encodeVarintField, fieldAllBytes, fieldBytes, fieldMessages, fieldString, fieldVarint, type ProtoField, readReference, readReferences, } from './protobuf.js';
5
+ export { snappyDecode, snappyEncodeLiterals } from './snappy.js';
6
+ export { shapeStorageBlocks, storageObjectToBlocks, storageToBlocks } from './storage.js';
7
+ export { type SheetData, sheetsToDocument, tableBlocksFromInfo, tableInfoToRows, } from './table.js';
8
+ export { type IWorkKind, TYPE } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import{Package as Wq}from"@mdgate/containers";import{ConvertError as R}from"@mdgate/core";import{warn as jq}from"@mdgate/utils";import{ConvertError as T}from"@mdgate/core";import{ConvertError as I}from"@mdgate/core";import{ConvertError as Jq}from"@mdgate/core";var Pq=67108864;function f(q,J=Pq){let H=0,[Q,$]=E(q,0);if(H=$,Q>J)throw Jq.resourceLimit("max_entry_bytes",`snappy block declares ${Q} decompressed bytes`);let W=new Uint8Array(Q),G=0;while(H<q.length&&G<Q){let U=q[H];H+=1;let X=U&3;if(X===0){let K=U>>2;if(K<60)K+=1;else{let F=K-59;K=0;for(let D=0;D<F;D+=1){if(H>=q.length)throw P("truncated snappy literal length");K|=q[H]<<8*D,H+=1}K+=1}if(H+K>q.length||G+K>W.length)throw P("truncated snappy literal");W.set(q.subarray(H,H+K),G),H+=K,G+=K;continue}let Z,z;if(X===1){if(H>=q.length)throw P("truncated snappy copy");Z=(U>>2&7)+4,z=U>>5<<8|q[H],H+=1}else if(X===2){if(H+2>q.length)throw P("truncated snappy copy");Z=(U>>2)+1,z=q[H]|q[H+1]<<8,H+=2}else{if(H+4>q.length)throw P("truncated snappy copy");Z=(U>>2)+1,z=q[H]|q[H+1]<<8|q[H+2]<<16|q[H+3]<<24,H+=4}if(z===0||z>G||G+Z>W.length)throw P("invalid snappy copy");for(let K=0;K<Z;K+=1)W[G]=W[G-z],G+=1}if(G!==Q)throw P("snappy length mismatch");return W}function n(q){let J=[];d(J,q.length);let H=0;while(H<q.length){let Q=q.length-H,$=Math.min(Q,65536);Eq(J,q.subarray(H,H+$)),H+=$}return Uint8Array.from(J)}function Eq(q,J){let H=J.length;if(H<=60)q.push(H-1<<2|0);else if(H<=256)q.push(240,H-1);else if(H<=65536)q.push(244,H-1&255,H-1>>8&255);else throw Error("literal too large");for(let Q=0;Q<J.length;Q+=1)q.push(J[Q])}function E(q,J){let H=0,Q=0,$=J;while($<q.length&&Q<=63){let W=q[$];if($+=1,H+=(W&127)*2**Q,(W&128)===0)return[H,$];Q+=7}throw P("truncated varint")}function d(q,J){let H=J>>>0;while(H>=128)q.push(H&127|128),H>>>=7;q.push(H)}function P(q){return Jq.malformed(q)}function M(q){let J=[],H=0;while(H<q.length){let[Q,$]=E(q,H);H=$;let W=Q>>>3,G=Q&7;if(W===0)break;if(G===0){let[U,X]=E(q,H);H=X,J.push({field:W,value:{kind:"varint",value:U}})}else if(G===1){if(H+8>q.length)throw I.malformed("truncated fixed64");let U=new DataView(q.buffer,q.byteOffset+H,8);J.push({field:W,value:{kind:"fixed64",value:U.getBigUint64(0,!0)}}),H+=8}else if(G===5){if(H+4>q.length)throw I.malformed("truncated fixed32");let U=new DataView(q.buffer,q.byteOffset+H,4);J.push({field:W,value:{kind:"fixed32",value:U.getUint32(0,!0)}}),H+=4}else if(G===2){let[U,X]=E(q,H);if(H=X,H+U>q.length)throw I.malformed("truncated length-delimited");J.push({field:W,value:{kind:"bytes",value:q.subarray(H,H+U)}}),H+=U}else throw I.malformed(`unsupported protobuf wire type ${G}`)}return J}function _(q,J){for(let H of q)if(H.field===J&&H.value.kind==="bytes")return H.value.value;return}function Y(q,J){for(let H of q)if(H.field===J&&H.value.kind==="varint")return H.value.value;return}function k(q,J){let H=_(q,J);if(H===void 0)return;return new TextDecoder("utf-8").decode(H)}function S(q,J){let H=[];for(let Q of q)if(Q.field===J&&Q.value.kind==="bytes")H.push(M(Q.value.value));return H}function wq(q,J){let H=[];for(let Q of q)if(Q.field===J&&Q.value.kind==="bytes")H.push(Q.value.value);return H}function A(q){if(q===void 0)return;return Y(M(q),1)}function L(q,J){let H=[];for(let Q of S(q,J)){let $=Y(Q,1);if($!==void 0)H.push($)}return H}function Bq(q,J){let H=[];return Qq(H,q,0),o(H,J),H}function l(q,J){let H=[];Qq(H,q,2),o(H,J.length);for(let Q=0;Q<J.length;Q+=1)H.push(J[Q]);return H}function Iq(q,J){return l(q,new TextEncoder().encode(J))}function kq(q,J){return l(q,Uint8Array.from(J))}function Qq(q,J,H){o(q,J<<3|H)}function o(q,J){let H=J>>>0;while(H>=128)q.push(H&127|128),H>>>=7;q.push(H)}function a(q){let J=[],H=[],Q=0,$=0;while($+4<=q.length){let U=q[$],X=q[$+1]|q[$+2]<<8|q[$+3]<<16;if($+=4,X===0)continue;if($+X>q.length)throw T.malformed("truncated IWA snappy chunk");let Z=q.subarray($,$+X);if($+=X,U!==0)continue;let z=f(Z);if(Q+=z.length,Q>$q)throw T.resourceLimit("max_entry_bytes",`IWA stream exceeds ${$q} decompressed bytes`);H.push(z)}if(H.length===0)return J;if(H.length===1)return Gq(H[0],J),J;let W=new Uint8Array(Q),G=0;for(let U of H)W.set(U,G),G+=U.length;return Gq(W,J),J}var $q=67108864;function Gq(q,J){let H=0;while(H<q.length){let[Q,$]=E(q,H);if(Q===0)break;if($+Q>q.length)throw T.malformed("truncated ArchiveInfo");let W=q.subarray($,$+Q);H=$+Q;let G=M(W),U=Y(G,1)??0,X=S(G,2);for(let Z of X){let z=Y(Z,1)??0,K=Y(Z,3)??0;if(H+K>q.length)throw T.malformed("truncated IWA payload");let F=q.subarray(H,H+K);H+=K,J.push({id:U,type:z,payload:F,fields:M(F)})}}}function Tq(q){let J=[];for(let $ of q){let W=[...r(1,$.type),...r(3,$.payload.length)],G=[...r(1,$.id),...mq(2,Uint8Array.from(W))];d(J,G.length);for(let U of G)J.push(U);for(let U=0;U<$.payload.length;U+=1)J.push($.payload[U])}let H=n(Uint8Array.from(J)),Q=new Uint8Array(4+H.length);return Q[0]=0,Q[1]=H.length&255,Q[2]=H.length>>8&255,Q[3]=H.length>>16&255,Q.set(H,4),Q}function r(q,J){let H=[];return m(H,q<<3|0),m(H,J),H}function mq(q,J){let H=[];m(H,q<<3|2),m(H,J.length);for(let Q=0;Q<J.length;Q+=1)H.push(J[Q]);return H}function m(q,J){let H=J>>>0;while(H>=128)q.push(H&127|128),H>>>=7;q.push(H)}var N={TP_DOCUMENT:1e4,TP_PLACEHOLDER:7,TN_DOCUMENT:1,TN_SHEET:2,KN_DOCUMENT:1,KN_SHOW:2,KN_SLIDE_NODE:4,KN_SLIDE:5,KN_SLIDE_ALT:6,KN_PLACEHOLDER:12,TSWP_STORAGE:2001,TSWP_STORAGE_ALT:2005,TSWP_SHAPE_INFO:2011,TSWP_CHARACTER_STYLE:2021,TSWP_PARAGRAPH_STYLE:2022,TSWP_LIST_STYLE:2023,TSWP_HYPERLINK:2032,TSWP_DRAWABLE_ATTACHMENT:2003,TSD_DRAWABLE:3002,TSD_SHAPE:3004,TSD_IMAGE:3005,TSD_GROUP:3008,TST_TABLE_INFO:6000,TST_TABLE_MODEL:6001,TST_TILE:6002,TST_TABLE_DATA_LIST:6005,TST_TABLE_DATA_LIST_ALT:6201,TST_RICH_TEXT_PAYLOAD:6218,TST_WP_TABLE_INFO:6007};function Kq(q,J){if(!Zq(q))throw R.malformed("not a readable iWork package");let H;try{H=Wq.open(q)}catch(G){if(G instanceof R)throw G;throw R.malformed(`not a readable iWork package: ${G instanceof Error?G.message:String(G)}`)}if(uq(H))throw R.encrypted();let Q=new Map;Uq(H,Q);let $=H.optionalPart("Index.zip");if($!==void 0){let G;try{G=Wq.open($)}catch(U){throw R.malformed(`unreadable Index.zip: ${U instanceof Error?U.message:String(U)}`)}Uq(G,Q)}if(Q.size===0)throw R.malformed("no IWA objects found");let W=hq(Q)??J;if(W===void 0)throw R.malformed("unrecognized iWork document kind");if(J!==void 0&&W!==J)throw R.malformed(`expected ${J} document, found ${W}`);return{kind:W,objects:Q}}function gq(q){if(!Zq(q))return;try{return Kq(q).kind}catch(J){if(J instanceof R&&J.code==="encrypted")return;return}}function O(q,J){if(J===void 0)return;return q.objects.get(J)}function V(q,J,H){let Q=A(_(J,H));return O(q,Q)}function j(q,J,H){let Q=[];for(let $ of L(J,H)){let W=q.objects.get($);if(W!==void 0)Q.push(W)}return Q}function Uq(q,J){for(let H of q.partNames()){if(!H.toLowerCase().endsWith(".iwa"))continue;let Q=q.optionalPart(H);if(Q===void 0)continue;let $;try{$=a(Q)}catch(W){if(W instanceof R&&(W.code==="encrypted"||W.isFatal()))throw W;jq(`skipping unreadable IWA ${H}: ${W instanceof Error?W.message:String(W)}`);continue}for(let W of $)if(!J.has(W.id))J.set(W.id,W)}}function hq(q){for(let H of q.values())if(H.type===N.TP_DOCUMENT)return"pages";let J=q.get(1);if(J!==void 0&&J.type===1)return Xq(J.fields);for(let H of q.values())if(H.type===1){let Q=Xq(H.fields);if(Q!==void 0)return Q}for(let H of q.values()){if(H.type===N.KN_SLIDE||H.type===N.KN_SLIDE_ALT||H.type===N.KN_SHOW)return"keynote";if(H.type===N.TN_SHEET)return"numbers"}return}function Xq(q){let J=L(q,1),H=A(_(q,2)),Q=_(q,8)!==void 0,$=_(q,3)!==void 0&&!Q;if(J.length>0||Q)return"numbers";if(H!==void 0||$)return"keynote";return}function uq(q){for(let J of q.partNames()){let H=J.toLowerCase();if(H.includes("encrypted")||H.endsWith(".iwae"))return!0}return!1}function Zq(q){return q.length>=4&&q[0]===80&&q[1]===75&&q[2]===3&&q[3]===4}import{inlinesAreEmpty as _q,inlinesToPlainText as vq,PLAIN as g,plain as CH}from"@mdgate/document";function w(q,J){let H=yq(J,3);if(H.length===0)return[];let $=[...H.join("")],W=i(J,5),G=i(J,8),U=i(J,7),X=[];if(W.length===0){let Z=zq(q,$,0,$.length,G);if(!_q(Z))X.push({type:"paragraph",inlines:Z});return X}for(let Z=0;Z<W.length;Z+=1){let z=W[Z].index,K=Z+1<W.length?W[Z+1].index:$.length;if(z>=K||z>=$.length)continue;let F=O(q,W[Z].objectId),{level:D,emphasis:C}=Fq(q,F?.fields),x=zq(q,$,z,K,G,C);if(_q(x))continue;if(D!==void 0&&D>=1&&D<=6)X.push({type:"heading",level:D,anchor:vq(x),content:x});else X.push({type:"paragraph",inlines:x})}return X}function pq(q,J){let H=O(q,J);if(H===void 0)return[];if(H.type!==N.TSWP_STORAGE&&H.type!==N.TSWP_STORAGE_ALT);return w(q,H.fields)}function i(q,J){let H=_(q,J);if(H===void 0)return[];let Q=[];for(let $ of S(M(H),1)){let W=Y($,1);if(W===void 0)continue;Q.push({index:W,objectId:A(_($,2))})}return Q}function yq(q,J){let H=[];for(let Q of q){if(Q.field!==J||Q.value.kind!=="bytes")continue;H.push(new TextDecoder("utf-8").decode(Q.value.value))}return H}function zq(q,J,H,Q,$,W=g){let G=[],U=H,X=$.filter((z)=>z.index>=H&&z.index<Q),Z=(z,K,F)=>{if(z>=K)return;let D=J.slice(z,K).join("");if(D.length===0)return;G.push({type:"text",text:D,style:F})};if(X.length===0)return Z(H,Math.min(Q,J.length),W),G;for(let z=0;z<X.length;z+=1){let K=X[z].index,F=z+1<X.length?X[z+1].index:Q,D=Math.min(F,Q);if(K>U)Z(U,Math.min(K,Q),W),U=K;if(K>=Q)break;let C=O(q,X[z].objectId),x=t(W,Dq(q,C?.fields));Z(K,D,x),U=D}if(U<Q)Z(U,Math.min(Q,J.length),W);return bq(G)}function bq(q){let J=q.map((Q)=>{if(Q.type!=="text")return Q;return{...Q,text:Q.text.replace(/\u2029/g,"").replace(/\u2028/g,`
2
+ `)}}),H=J[J.length-1];if(H?.type==="text"&&H.text.endsWith(`
3
+ `)){let Q=H.text.replace(/\n+$/,"");if(Q.length===0)return J.slice(0,-1);return[...J.slice(0,-1),{...H,text:Q}]}return J}function Fq(q,J){if(J===void 0)return{level:void 0,emphasis:g};let H=_(J,12),Q=_(J,11),$;if(H!==void 0)$=Y(M(H),27);let W=_(J,1);if(W!==void 0){let G=A(_(M(W),3)),U=O(q,G);if(U!==void 0){let X=Fq(q,U.fields);if($===void 0)$=X.level;return{level:$,emphasis:t(X.emphasis,s(Q))}}}return{level:$,emphasis:s(Q)}}function Dq(q,J){if(J===void 0)return g;let H=_(J,11),Q=s(H),$=_(J,1);if($!==void 0){let W=A(_(M($),3)),G=O(q,W);if(G!==void 0)return t(Dq(q,G.fields),Q)}return Q}function s(q){if(q===void 0)return g;let J=M(q),H=Y(J,1)===1,Q=Y(J,2)===1,$=(Y(J,12)??0)>0;return{bold:H,italic:Q,strike:$,code:!1}}function t(q,J){return{bold:J.bold||q.bold,italic:J.italic||q.italic,strike:J.strike||q.strike,code:J.code||q.code}}function h(q,J){if(J.type===N.TSWP_SHAPE_INFO||J.type===N.TP_PLACEHOLDER||J.type===N.KN_PLACEHOLDER){let H=J.fields;if(J.type===N.TP_PLACEHOLDER||J.type===N.KN_PLACEHOLDER){let $=V(q,H,1);if($!==void 0)H=$.fields}let Q=V(q,H,2);if(Q!==void 0)return w(q,Q.fields)}return[]}import{cellFromInlines as cq,emptyDocument as fq,heading as nq,plain as Nq,tableFromRows as dq}from"@mdgate/document";function Aq(q,J){let H=J,Q=V(q,J,1),$=V(q,H,2);if($===void 0&&Q!==void 0)H=Q.fields,$=V(q,H,2);if($===void 0)return[];return lq(q,$.fields)}function lq(q,J){let H=Y(J,6)??0,Q=Y(J,7)??0;if(H===0||Q===0)return[];let $=_(J,4);if($===void 0)return[];let W=M($),G=oq(q,A(_(W,4))),U=rq(q,A(_(W,17))),X=Array.from({length:H},()=>Array.from({length:Q},()=>"")),Z=_(W,3);if(Z===void 0)return X;let z=M(Z);for(let K of S(z,1)){let F=O(q,A(_(K,2)));if(F===void 0)continue;let D=S(F.fields,5);for(let C of D){let x=Y(C,1)??0,Lq=_(C,6)??_(C,3)??new Uint8Array,y=_(C,7)??_(C,4)??new Uint8Array;if(y.length<2)continue;let b=new Uint8Array(y.byteLength);b.set(y);let qq=new Uint16Array(b.buffer,0,Math.floor(b.length/2));for(let B=0;B<qq.length&&B<Q;B+=1){let Hq=qq[B];if(Hq===65535)continue;let c=x;if(c<0||c>=H)continue;X[c][B]=aq(Lq,Hq,G,U,q)}}}return sq(X)}function Oq(q){let J=fq(),H=q.length>1;for(let Q of q){if(Q.rows.length===0)continue;if(H)J.blocks.push(nq(2,[Nq(Q.name)]));let $=Q.rows.map((G)=>G.map((U)=>cq([Nq(U)]))),W=Q.rows.length>1?1:0;J.blocks.push({type:"table",table:dq($,W,"data")})}return J}function Mq(q,J){let H=Aq(q,J);if(H.length===0)return[];return Oq([{name:"",rows:H}]).blocks}function oq(q,J){let H=new Map,Q=O(q,J);if(Q===void 0)return H;for(let $ of S(Q.fields,3)){let W=Y($,1),G=k($,3);if(W!==void 0&&G!==void 0)H.set(W,G)}return H}function rq(q,J){let H=new Map,Q=O(q,J);if(Q===void 0)return H;for(let $ of S(Q.fields,3)){let W=Y($,1),G=A(_($,9));if(W!==void 0&&G!==void 0)H.set(W,G)}return H}function aq(q,J,H,Q,$){if(J+8>q.length)return"";let W=q[J],G,U,X,Z;if(W===5||q[J]>=5)return G=q[J+1],U=q[J+8]|q[J+9]<<8|q[J+10]<<16|q[J+11]<<24,X=4,Z=J+12,iq(q,G,U,Z,H,Q,$);if(q[J]===4)G=q[J+1],U=q[J+4]|q[J+5]<<8,X=2,Z=J+8;else G=q[J+2],U=q[J+4]|q[J+5]<<8,X=2,Z=J+8;let z=Yq(U&65535),K=Z+z*4;if(K=Z+Yq(U)*4,G===0)return"";if(G===2||G===5||G===6||G===7){if(K+8>q.length)return"";let F=u(q,K);if(G===6)return F!==0?"TRUE":"FALSE";if(G===5)return Sq(F);return Vq(F)}if(G===3||G===9){if(K+4>q.length)return"";let F=q[K]|q[K+1]<<8|q[K+2]<<16|q[K+3]<<24;if(G===3)return H.get(F>>>0)??"";let D=Q.get(F>>>0);return Cq($,D)}return""}function iq(q,J,H,Q,$,W,G){let U=Q,X=(D,C)=>{if((H&D)===0)return;if(U+C>q.length)return;let x=q.subarray(U,U+C);return U+=C,x};X(1,16);let Z=X(2,8),z=X(4,8),K=X(8,4),F=X(16,4);if(X(32,4),X(64,4),X(128,4),X(256,4),X(512,4),X(1024,4),X(2048,4),J===0)return"";if(J===2&&Z!==void 0)return Vq(u(Z,0));if(J===5&&z!==void 0)return Sq(u(z,0));if(J===6&&Z!==void 0)return u(Z,0)!==0?"TRUE":"FALSE";if(J===3&&K!==void 0){let D=K[0]|K[1]<<8|K[2]<<16|K[3]<<24;return $.get(D>>>0)??""}if(J===9&&F!==void 0){let D=F[0]|F[1]<<8|F[2]<<16|F[3]<<24;return Cq(G,W.get(D>>>0))}if(K!==void 0){let D=K[0]|K[1]<<8|K[2]<<16|K[3]<<24,C=$.get(D>>>0);if(C!==void 0)return C}return""}function Cq(q,J){let H=O(q,J);if(H===void 0)return"";let Q=A(_(H.fields,1)),$=O(q,Q);if($===void 0)return"";return w(q,$.fields).map((G)=>{if(G.type==="paragraph")return G.inlines.map((U)=>U.type==="text"?U.text:"").join("");if(G.type==="heading")return G.content.map((U)=>U.type==="text"?U.text:"").join("");return""}).filter(Boolean).join(" ")}function u(q,J){let H=new Uint8Array(8);return H.set(q.subarray(J,J+8)),new DataView(H.buffer).getFloat64(0,!0)}function sq(q){let J=-1,H=-1;for(let Q=0;Q<q.length;Q+=1)for(let $=0;$<q[Q].length;$+=1)if(q[Q][$]!==""){if(Q>J)J=Q;if($>H)H=$}if(J<0)return[];return q.slice(0,J+1).map((Q)=>Q.slice(0,H+1))}function Yq(q){let J=q&65535,H=0;while(J)J&=J-1,H+=1;return H}function Vq(q){if(!Number.isFinite(q))return"";if(Number.isInteger(q))return String(q);return String(Number(q.toPrecision(12)))}function Sq(q){let J=(q+978307200)*1000,H=new Date(J);if(Number.isNaN(H.getTime()))return"";return H.toISOString().slice(0,10)}function xq(q,J){if(J.type===N.TST_TABLE_INFO||J.type===N.TST_WP_TABLE_INFO)return Mq(q,J.fields);return[]}function v(q,J){let H=O(q,J);if(H===void 0)return[];return e(q,H)}function e(q,J){let H=xq(q,J);if(H.length>0)return H;let Q=h(q,J);if(Q.length>0)return Q;if(J.type===N.TSD_GROUP){let $=[];for(let W of j(q,J.fields,2))$.push(...e(q,W));return $}if(J.type===N.TSWP_DRAWABLE_ATTACHMENT){let $=A(_(J.fields,1));return v(q,$)}return[]}function p(q,J){let H=q.objects.get(1);if(H!==void 0&&H.type===J)return H;for(let Q of q.objects.values())if(Q.type===J)return Q;return}function tq(q){let J=p(q,N.TP_DOCUMENT);if(J===void 0)return;return V(q,J.fields,4)?.fields}function eq(q){let J=p(q,N.TN_DOCUMENT)??[...q.objects.values()].find((Q)=>Q.type===1&&L(Q.fields,1).length>0);if(J===void 0)return[];let H=[];for(let Q of j(q,J.fields,1)){let $=_(Q.fields,1),W=$!==void 0?new TextDecoder().decode($):"Sheet";H.push({name:W,drawables:L(Q.fields,2)})}return H}function qH(q){let J=p(q,N.KN_DOCUMENT)??[...q.objects.values()].find((G)=>{if(G.type!==1)return!1;return A(_(G.fields,2))!==void 0});if(J===void 0)return[];let H=V(q,J.fields,2);if(H===void 0)return[];let Q=_(H.fields,3),$;if(Q!==void 0){let G=A(Q);if(G!==void 0&&O(q,G)?.type===N.KN_SLIDE_NODE)$=G;else $=A(_(M(Q),1))??G}let W=[];return Rq(q,$,W),W}function Rq(q,J,H){let Q=O(q,J);if(Q===void 0)return;let $=A(_(Q.fields,2));if($!==void 0){let W=O(q,$);if(W!==void 0){let G=Y(W.fields,19);if(G===void 0||G!==0)H.push($)}}for(let W of L(Q.fields,1))Rq(q,W,H)}function HH(q,J){let H=O(q,J);if(H===void 0)return[];let Q=[],$=(G)=>{Q.push(...v(q,A(_(H.fields,G))))};$(5),$(6),$(30);for(let G of L(H.fields,7))Q.push(...v(q,G));let W=V(q,H.fields,27);if(W!==void 0){let G=h(q,W);if(G.length>0)Q.push({type:"blockQuote",blocks:G});else{let U=w(q,W.fields);if(U.length>0)Q.push({type:"blockQuote",blocks:U})}}return Q}export{Aq as tableInfoToRows,Mq as tableBlocksFromInfo,w as storageToBlocks,pq as storageObjectToBlocks,n as snappyEncodeLiterals,f as snappyDecode,HH as slideToBlocks,Oq as sheetsToDocument,h as shapeStorageBlocks,L as readReferences,A as readReference,a as parseIwa,Kq as openIWork,eq as numbersSheets,qH as keynoteSlides,O as getObject,p as findDocumentObject,Y as fieldVarint,k as fieldString,S as fieldMessages,_ as fieldBytes,wq as fieldAllBytes,Bq as encodeVarintField,Iq as encodeStringField,kq as encodeMessageField,l as encodeBytesField,gq as detectIWorkKind,j as derefAll,V as deref,M as decodeMessage,e as collectDrawableObject,v as collectDrawableBlocks,Tq as buildIwa,tq as bodyStorageFromPages,N as TYPE};
package/dist/iwa.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { type ProtoField } from './protobuf.js';
2
+ export interface IwaObject {
3
+ id: number;
4
+ type: number;
5
+ payload: Uint8Array;
6
+ fields: ProtoField[];
7
+ }
8
+ /**
9
+ * Parse one `.iwa` component into archived objects.
10
+ * Layout: repeated { chunkType=0, u24le length, snappy block }. Decompressed
11
+ * chunks form one stream of { varint ArchiveInfoLen, ArchiveInfo, payloads… };
12
+ * ArchiveInfo records routinely span the 64 KiB snappy block boundary.
13
+ */
14
+ export declare function parseIwa(bytes: Uint8Array): IwaObject[];
15
+ /** Wrap ArchiveInfo+payloads in a single snappy IWA chunk (fixtures / tests). */
16
+ export declare function buildIwa(objects: {
17
+ id: number;
18
+ type: number;
19
+ payload: Uint8Array;
20
+ }[]): Uint8Array;
@@ -0,0 +1,35 @@
1
+ /** One decoded protobuf field. Length-delimited values stay as bytes. */
2
+ export type ProtoValue = {
3
+ kind: 'varint';
4
+ value: number;
5
+ } | {
6
+ kind: 'fixed64';
7
+ value: bigint;
8
+ } | {
9
+ kind: 'fixed32';
10
+ value: number;
11
+ } | {
12
+ kind: 'bytes';
13
+ value: Uint8Array;
14
+ };
15
+ export interface ProtoField {
16
+ field: number;
17
+ value: ProtoValue;
18
+ }
19
+ /** Decode all top-level fields of a protobuf message (proto2/3 wire). */
20
+ export declare function decodeMessage(bytes: Uint8Array): ProtoField[];
21
+ export declare function fieldBytes(fields: readonly ProtoField[], field: number): Uint8Array | undefined;
22
+ export declare function fieldVarint(fields: readonly ProtoField[], field: number): number | undefined;
23
+ export declare function fieldString(fields: readonly ProtoField[], field: number): string | undefined;
24
+ export declare function fieldMessages(fields: readonly ProtoField[], field: number): ProtoField[][];
25
+ export declare function fieldAllBytes(fields: readonly ProtoField[], field: number): Uint8Array[];
26
+ export declare function fieldAllVarints(fields: readonly ProtoField[], field: number): number[];
27
+ /** TSP.Reference — identifier at field 1. */
28
+ export declare function readReference(bytes: Uint8Array | undefined): number | undefined;
29
+ export declare function readReferences(fields: readonly ProtoField[], field: number): number[];
30
+ export declare function encodeVarintField(field: number, value: number): number[];
31
+ export declare function encodeBytesField(field: number, value: Uint8Array): number[];
32
+ export declare function encodeStringField(field: number, value: string): number[];
33
+ export declare function encodeMessageField(field: number, message: number[]): number[];
34
+ /** IEEE754 little-endian float64 bits as protobuf fixed64 payload bytes. */
35
+ export declare function float64Bytes(value: number): Uint8Array;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Decompress a raw Snappy block (not the framing format). iWork IWA chunks
3
+ * store one such block after a 4-byte header.
4
+ */
5
+ export declare function snappyDecode(input: Uint8Array, maxOut?: number): Uint8Array;
6
+ /**
7
+ * Compress with literals only. Used by tests / fixture builders; production
8
+ * converters only decompress.
9
+ */
10
+ export declare function snappyEncodeLiterals(input: Uint8Array): Uint8Array;
11
+ /**
12
+ * Protobuf / Snappy unsigned varint. Up to 10 bytes (64-bit). Values above
13
+ * 2^53 are returned as an imprecise number; callers that only need the
14
+ * consumed width still advance correctly.
15
+ */
16
+ export declare function readVarint(bytes: Uint8Array, offset: number): [number, number];
17
+ export declare function writeVarint(out: number[], value: number): void;
@@ -0,0 +1,16 @@
1
+ import { type Block } from '@mdgate/document';
2
+ import type { IWorkArchive } from './archive.js';
3
+ import { type ProtoField } from './protobuf.js';
4
+ /**
5
+ * Convert a TSWP.StorageArchive into document blocks (paragraphs / headings).
6
+ * Character styles map to bold/italic/strike; outline_level → heading.
7
+ */
8
+ export declare function storageToBlocks(archive: IWorkArchive, storage: ProtoField[]): Block[];
9
+ export declare function storageObjectToBlocks(archive: IWorkArchive, objId: number | undefined): Block[];
10
+ /** Follow a shape / placeholder drawable to its contained TSWP storage. */
11
+ export declare function shapeStorageBlocks(archive: IWorkArchive, obj: {
12
+ type: number;
13
+ fields: ProtoField[];
14
+ }): Block[];
15
+ export declare function plainParagraph(text: string): Block;
16
+ export declare function fieldStringOrEmpty(fields: readonly ProtoField[], field: number): string;
@@ -0,0 +1,17 @@
1
+ import { type Block, type Document } from '@mdgate/document';
2
+ import type { IWorkArchive } from './archive.js';
3
+ import { type ProtoField } from './protobuf.js';
4
+ export interface SheetData {
5
+ name: string;
6
+ rows: string[][];
7
+ }
8
+ /** Read TST.TableInfoArchive / WPTableInfoArchive into a string grid. */
9
+ export declare function tableInfoToRows(archive: IWorkArchive, tableInfo: ProtoField[]): string[][];
10
+ export declare function tableModelToRows(archive: IWorkArchive, model: ProtoField[]): string[][];
11
+ export declare function sheetsToDocument(sheets: SheetData[]): Document;
12
+ export declare function tableBlocksFromInfo(archive: IWorkArchive, fields: ProtoField[]): Block[];
13
+ /** Try to interpret any drawable as a table. */
14
+ export declare function drawableAsTable(archive: IWorkArchive, obj: {
15
+ type: number;
16
+ fields: ProtoField[];
17
+ }): Block[];
@@ -0,0 +1,33 @@
1
+ /** Common / app message type ids used for extraction (TSPRegistry subset). */
2
+ export declare const TYPE: {
3
+ readonly TP_DOCUMENT: 10000;
4
+ readonly TP_PLACEHOLDER: 7;
5
+ readonly TN_DOCUMENT: 1;
6
+ readonly TN_SHEET: 2;
7
+ readonly KN_DOCUMENT: 1;
8
+ readonly KN_SHOW: 2;
9
+ readonly KN_SLIDE_NODE: 4;
10
+ readonly KN_SLIDE: 5;
11
+ readonly KN_SLIDE_ALT: 6;
12
+ readonly KN_PLACEHOLDER: 12;
13
+ readonly TSWP_STORAGE: 2001;
14
+ readonly TSWP_STORAGE_ALT: 2005;
15
+ readonly TSWP_SHAPE_INFO: 2011;
16
+ readonly TSWP_CHARACTER_STYLE: 2021;
17
+ readonly TSWP_PARAGRAPH_STYLE: 2022;
18
+ readonly TSWP_LIST_STYLE: 2023;
19
+ readonly TSWP_HYPERLINK: 2032;
20
+ readonly TSWP_DRAWABLE_ATTACHMENT: 2003;
21
+ readonly TSD_DRAWABLE: 3002;
22
+ readonly TSD_SHAPE: 3004;
23
+ readonly TSD_IMAGE: 3005;
24
+ readonly TSD_GROUP: 3008;
25
+ readonly TST_TABLE_INFO: 6000;
26
+ readonly TST_TABLE_MODEL: 6001;
27
+ readonly TST_TILE: 6002;
28
+ readonly TST_TABLE_DATA_LIST: 6005;
29
+ readonly TST_TABLE_DATA_LIST_ALT: 6201;
30
+ readonly TST_RICH_TEXT_PAYLOAD: 6218;
31
+ readonly TST_WP_TABLE_INFO: 6007;
32
+ };
33
+ export type IWorkKind = 'pages' | 'numbers' | 'keynote';
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@mdgate/iwork-common",
3
+ "version": "0.1.0",
4
+ "description": "mdgate shared Apple iWork (Pages/Numbers/Keynote) IWA parsing",
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/utils": "0.1.2"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "keywords": [
37
+ "mdgate",
38
+ "iwork",
39
+ "pages",
40
+ "numbers",
41
+ "keynote"
42
+ ]
43
+ }