pptx-react-viewer 1.0.0 → 1.0.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present pptx-viewer contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,16 @@
1
+ pptx-viewer
2
+ Copyright (c) 2025-present pptx-viewer contributors
3
+
4
+ This package is licensed under the MIT License. See the LICENSE file for details.
5
+
6
+ This package bundles the following component under a different license:
7
+
8
+ mtx-decompressor — MicroType Express (MTX) font decompressor
9
+ License: Mozilla Public License 2.0 (MPL-2.0)
10
+ Source: https://github.com/ChristopherVR/pptx-viewer/tree/main/packages/mtx-decompressor
11
+ Origin: Ported from libeot (https://github.com/nicowilliams/libeot)
12
+ by Brennan T. Vincent, licensed under MPL-2.0.
13
+
14
+ Under MPL-2.0, the source code of the mtx-decompressor component remains
15
+ available under the terms of the Mozilla Public License 2.0. The full text
16
+ of the MPL-2.0 can be found at: https://mozilla.org/MPL/2.0/
package/README.md CHANGED
@@ -296,123 +296,17 @@ import {
296
296
 
297
297
  ### High-Level Component Tree
298
298
 
299
- ```mermaid
300
- flowchart TB
301
- PPV["PowerPointViewer<br/>(root orchestrator)"]
302
-
303
- PPV --> VTS["ViewerToolbarSection<br/>Toolbar + ModeSwitcher"]
304
- PPV --> VMC["ViewerMainContent<br/>Canvas + sidebars + inspector"]
305
- PPV --> VBP["ViewerBottomPanels<br/>Notes + status bar"]
306
- PPV --> VDG["ViewerDialogGroup<br/>All modal dialogs"]
307
- PPV --> VO["ViewerOverlays<br/>Shortcuts, accessibility, slide sorter"]
308
- PPV --> VPL["ViewerPresentationLayer<br/>Fullscreen slideshow"]
309
-
310
- VMC --> VSP["ViewerSidePanels<br/>Slides pane + master pane"]
311
- VMC --> VCA["ViewerCanvasArea<br/>SlideCanvas + overlays"]
312
- VMC --> VI["ViewerInspector<br/>Properties panel"]
313
-
314
- VCA --> SC["SlideCanvas<br/>Main slide rendering"]
315
- SC --> ER["ElementRenderer<br/>Per-element dispatch"]
316
- ER --> SH["Shape / Text"]
317
- ER --> IM["Image"]
318
- ER --> TB["Table"]
319
- ER --> CH["Chart (SVG)"]
320
- ER --> CN["Connector"]
321
- ER --> SA["SmartArt"]
322
- ER --> M3["3D Model"]
323
- ER --> MD["Media (audio/video)"]
324
- ER --> IK["Ink"]
325
- ```
299
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
326
300
 
327
301
  ### Hook Composition
328
302
 
329
303
  The viewer's logic is decomposed into 67+ custom hooks, composed in `PowerPointViewer.tsx`:
330
304
 
331
- ```mermaid
332
- flowchart TD
333
- subgraph "Core State"
334
- VS["useViewerState<br/>All mutable state"]
335
- VCS["useViewerCoreState<br/>Slides, selection, canvas"]
336
- VUI["useViewerUIState<br/>Panels, dialogs, UI flags"]
337
- end
338
-
339
- subgraph "Derived State"
340
- DSS["useDerivedSlideState<br/>Visible indexes, sections"]
341
- DES["useDerivedElementState<br/>Selected element computed props"]
342
- end
343
-
344
- subgraph "Core Operations"
345
- EH["useEditorHistory<br/>Undo/redo snapshot stack"]
346
- ZV["useZoomViewport<br/>Zoom level + viewport"]
347
- EO["useEditorOperations<br/>Compose all editor ops"]
348
- end
349
-
350
- subgraph "Feature Hooks"
351
- LC["useLoadContent<br/>Parse PPTX on mount"]
352
- PM["usePresentationMode<br/>Slideshow navigation"]
353
- PA["usePresentationAnnotations<br/>Pen/highlighter tools"]
354
- IE["useInsertElements<br/>Shape/image/table insertion"]
355
- EM["useElementManipulation<br/>Move/resize/delete"]
356
- PH["usePointerHandlers<br/>Mouse/touch events"]
357
- KS["useKeyboardShortcuts<br/>Hotkey bindings"]
358
- EX["useExportHandlers<br/>PNG/SVG/PDF/video export"]
359
- PR["usePrintHandlers<br/>Print dialog"]
360
- SM["useSlideManagement<br/>Add/delete/reorder slides"]
361
- TO["useTableOperations<br/>Row/column/cell ops"]
362
- FR["useFindReplace<br/>Text search"]
363
- CM["useComments<br/>Comment management"]
364
- end
365
-
366
- subgraph "Collaboration"
367
- YJS["useYjsProvider<br/>WebSocket lifecycle"]
368
- PT["usePresenceTracking<br/>Remote cursors"]
369
- CS["useCollaborativeState<br/>CRDT shared state"]
370
- CH2["useCollaborativeHistory<br/>Collab undo/redo"]
371
- end
372
-
373
- VS --> VCS
374
- VS --> VUI
375
- VCS --> DSS
376
- VS --> EH
377
- VS --> ZV
378
- EH --> EO
379
- ZV --> EO
380
- EO --> IE
381
- EO --> EM
382
- EO --> PH
383
- EO --> SM
384
- EO --> TO
385
- EO --> FR
386
- EO --> CM
387
- ```
305
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
388
306
 
389
307
  ### Data Flow
390
308
 
391
- ```mermaid
392
- sequenceDiagram
393
- participant P as Parent App
394
- participant V as PowerPointViewer
395
- participant H as PptxHandler (core)
396
- participant S as State (hooks)
397
- participant C as SlideCanvas
398
-
399
- P->>V: content={arrayBuffer}
400
- V->>S: useViewerState({ content })
401
- S->>H: handler.load(buffer)
402
- H-->>S: PptxData { slides, theme, ... }
403
- S-->>V: { slides, activeSlide, canvasSize, ... }
404
- V->>C: Render active slide
405
- C->>C: Map elements -> React components
406
-
407
- Note over C: User edits element
408
- C->>S: setState(updatedSlides)
409
- S->>S: Push undo snapshot
410
- S-->>V: Re-render with updated state
411
-
412
- Note over V: User saves
413
- V->>H: handler.save(slides)
414
- H-->>P: Uint8Array via onContentChange
415
- ```
309
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
416
310
 
417
311
  ### Rendering Pipeline
418
312
 
@@ -423,37 +317,7 @@ Slides are rendered using **CSS positioning and transforms**, not HTML Canvas. T
423
317
  - DOM-based interaction (click, drag, resize)
424
318
  - Standard CSS effects (shadows, gradients, borders)
425
319
 
426
- ```mermaid
427
- flowchart LR
428
- subgraph "Data Model"
429
- E["PptxElement<br/>(from core)"]
430
- end
431
-
432
- subgraph "React Components"
433
- ER["ElementRenderer<br/>Type dispatch"]
434
- EB["ElementBody<br/>Visual rendering"]
435
- RH["ResizeHandles<br/>Selection UI"]
436
- end
437
-
438
- subgraph "CSS Output"
439
- POS["position: absolute<br/>left/top/width/height"]
440
- ROT["transform: rotate()"]
441
- FIL["background: fill style"]
442
- BOR["border: stroke style"]
443
- SHD["box-shadow: effects"]
444
- TXT["text styling (font, color, align)"]
445
- end
446
-
447
- E --> ER
448
- ER --> EB
449
- ER --> RH
450
- EB --> POS
451
- EB --> ROT
452
- EB --> FIL
453
- EB --> BOR
454
- EB --> SHD
455
- EB --> TXT
456
- ```
320
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
457
321
 
458
322
  ---
459
323
 
@@ -601,27 +465,7 @@ The right-side inspector (`InspectorPane`) displays contextual property editors:
601
465
 
602
466
  Activated by setting `mode` to `"present"`. The `ViewerPresentationLayer` takes over with:
603
467
 
604
- ```mermaid
605
- flowchart TD
606
- PM["usePresentationMode"] --> SN["useSlideNavigation<br/>Next/prev/goto slide"]
607
- PM --> AP["useAnimationPlayback<br/>Trigger animations in sequence"]
608
- PM --> PK["usePresentationKeyboard<br/>Arrow keys, Esc, N-key toggle"]
609
- PM --> RT["useRehearsalTimings<br/>Practice mode with timer"]
610
-
611
- subgraph "Rendering"
612
- ST["Slide Transition<br/>(CSS + framer-motion)"]
613
- AN["Animation Overlays<br/>(keyframe sequences)"]
614
- AO["Annotation Overlay<br/>(pen/highlighter SVG)"]
615
- PV["Presenter View<br/>(dual-screen notes + preview + timer)"]
616
- TB2["Slideshow Toolbar<br/>(auto-hide on mouse idle)"]
617
- end
618
-
619
- SN --> ST
620
- AP --> AN
621
- PM --> AO
622
- PM --> PV
623
- PM --> TB2
624
- ```
468
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
625
469
 
626
470
  **Slide transitions** (`slide-transitions.ts`, `transition-keyframes.ts`):
627
471
 
@@ -636,25 +480,7 @@ flowchart TD
636
480
 
637
481
  The animation system (`viewer/utils/animation*.ts`, ~14 files) processes OOXML timing trees:
638
482
 
639
- ```mermaid
640
- flowchart LR
641
- A["PptxElementAnimation<br/>(from core)"] --> B["animation-timeline.ts<br/>Build timeline"]
642
- B --> C["animation-sequencer.ts<br/>Resolve triggers:<br/>onClick, afterPrevious,<br/>withPrevious"]
643
- C --> D["animation-keyframes.ts<br/>Generate CSS @keyframes"]
644
- D --> E["animation-effects.ts<br/>Apply to DOM elements"]
645
-
646
- subgraph "Effect Types"
647
- F["Entrance<br/>(appear, fly in, fade, zoom)"]
648
- G["Emphasis<br/>(pulse, spin, grow/shrink, color)"]
649
- H["Exit<br/>(disappear, fly out, fade)"]
650
- I["Motion Path<br/>(custom path with auto-rotation)"]
651
- end
652
-
653
- D --> F
654
- D --> G
655
- D --> H
656
- D --> I
657
- ```
483
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
658
484
 
659
485
  Supports 40+ animation presets with configurable duration, delay, repeat, color animations, motion path auto-rotation, and text-build options (by word, by letter, by paragraph).
660
486
 
@@ -685,26 +511,7 @@ Chart chrome (axes, legends, titles, gridlines, data labels, data tables, displa
685
511
 
686
512
  The export pipeline (`viewer/utils/export*.ts`, `viewer/hooks/useExportHandlers.ts`):
687
513
 
688
- ```mermaid
689
- flowchart TD
690
- A["Export Request"] --> B{Format?}
691
-
692
- B -->|PNG/JPEG| C["renderToCanvas (html2canvas)<br/>-> canvas.toDataURL()"]
693
- B -->|SVG| D["DOM -> SVG serialisation<br/>(export-svg.ts)"]
694
- B -->|PDF| E["jspdf + renderToCanvas<br/>-> multi-page PDF<br/>(with notes pages + overflow)"]
695
- B -->|GIF| F["export-gif-encoder.ts<br/>-> animated GIF frames"]
696
- B -->|Video| G["export-video.ts<br/>-> MediaRecorder API"]
697
- B -->|PPTX| H["PptxHandler.save()<br/>-> Uint8Array download"]
698
- B -->|Slides| I["PptxHandler.exportSlides()<br/>-> per-slide PPTX files"]
699
-
700
- C --> J["Download / Blob URL"]
701
- D --> J
702
- E --> J
703
- F --> J
704
- G --> J
705
- H --> J
706
- I --> J
707
- ```
514
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
708
515
 
709
516
  The `renderToCanvas` wrapper (`lib/canvas-export.ts`) patches `html2canvas` to work around oklch colour space parsing issues in browsers that don't fully support it.
710
517
 
@@ -712,14 +519,7 @@ The `renderToCanvas` wrapper (`lib/canvas-export.ts`) patches `html2canvas` to w
712
519
 
713
520
  Connectors between shapes use a graph-based routing algorithm:
714
521
 
715
- ```mermaid
716
- flowchart LR
717
- A["Start Shape<br/>(connection point)"] --> B["connector-router.ts<br/>A* pathfinding"]
718
- B --> C["connector-router-graph.ts<br/>Build obstacle grid"]
719
- C --> D["connector-router-astar.ts<br/>Find shortest path"]
720
- D --> E["connector-path.tsx<br/>SVG path rendering"]
721
- E --> F["Arrow markers<br/>(start/end heads)"]
722
- ```
522
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/react/README.md) for visual representations._
723
523
 
724
524
  The router avoids overlapping shapes by building an obstacle grid and using A\* pathfinding with Manhattan distance heuristics. Supports straight, elbow (bent), and curved connector types.
725
525
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present pptx-viewer contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -104,169 +104,25 @@ Converts a WMF binary buffer to a PNG data URL.
104
104
 
105
105
  The converter follows a three-phase pipeline: **Parse → Replay → Export**.
106
106
 
107
- ```mermaid
108
- flowchart LR
109
- A[/"Binary Buffer<br/>(ArrayBuffer)"/] --> B{Format?}
110
- B -->|EMF| C[Parse EMF Header]
111
- B -->|WMF| D[Parse WMF Header]
112
- C --> E[Create Canvas]
113
- D --> E
114
- E --> F{Replay Records}
115
- F -->|GDI Records| G[GDI Record Handlers]
116
- F -->|EMF+ Comments| H[EMF+ Record Handlers]
117
- F -->|WMF Records| I[WMF Record Handlers]
118
- G --> J[Canvas 2D Context]
119
- H --> J
120
- I --> J
121
- J --> K[Process Deferred Images]
122
- K --> L[Export to PNG Data URL]
123
- L --> M[/"data:image/png;base64,..."/]
124
- ```
107
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
125
108
 
126
109
  ### Module Map
127
110
 
128
111
  Every source file has a specific responsibility. Here's how they connect:
129
112
 
130
- ```mermaid
131
- graph TB
132
- subgraph "Public API"
133
- A[emf-converter.ts]
134
- B[index.ts]
135
- end
136
-
137
- subgraph "Header & Setup"
138
- C[emf-header-parser.ts]
139
- D[emf-canvas-helpers.ts]
140
- E[emf-constants.ts]
141
- F[emf-types.ts]
142
- G[emf-logging.ts]
143
- end
144
-
145
- subgraph "EMF GDI Replay"
146
- H[emf-record-replay.ts]
147
- I[emf-gdi-state-handlers.ts]
148
- J[emf-gdi-draw-handlers.ts]
149
- K[emf-gdi-poly-path-handlers.ts]
150
- L[emf-gdi-transform-handlers.ts]
151
- M[emf-gdi-object-handlers.ts]
152
- N[emf-gdi-draw-shapes.ts]
153
- O[emf-gdi-draw-text-bitmap.ts]
154
- P[emf-gdi-coord.ts]
155
- Q[emf-gdi-polypolygon-helpers.ts]
156
- end
157
-
158
- subgraph "EMF+ GDI+ Replay"
159
- R[emf-plus-replay.ts]
160
- S[emf-plus-object-parser.ts]
161
- T[emf-plus-draw-handlers.ts]
162
- U[emf-plus-text-image-handlers.ts]
163
- V[emf-plus-state-handlers.ts]
164
- W[emf-plus-path.ts]
165
- X[emf-plus-read-helpers.ts]
166
- Y[emf-plus-object-complex.ts]
167
- Z[emf-plus-bitmap-decoder.ts]
168
- end
169
-
170
- subgraph "WMF Replay"
171
- AA[wmf-replay.ts]
172
- AB[wmf-draw-handlers.ts]
173
- end
174
-
175
- subgraph "Bitmap Decoding"
176
- AC[emf-dib-decoder.ts]
177
- AD[emf-dib-rle-decoder.ts]
178
- AE[emf-dib-uncompressed.ts]
179
- end
180
-
181
- subgraph "Color Helpers"
182
- AF[emf-color-helpers.ts]
183
- end
184
-
185
- B --> A
186
- A --> C
187
- A --> D
188
- A --> H
189
- A --> AA
190
-
191
- H --> I
192
- H --> J
193
- H --> K
194
- H --> R
195
-
196
- I --> L
197
- I --> M
198
- J --> N
199
- J --> O
200
-
201
- AA --> AB
202
- ```
113
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
203
114
 
204
115
  ### EMF Record Replay Loop
205
116
 
206
117
  The core of the EMF converter is a sequential record-scanning loop that dispatches each record to the appropriate handler:
207
118
 
208
- ```mermaid
209
- flowchart TD
210
- Start([Start Replay]) --> Read["Read record at offset:<br/>type = uint32, size = uint32"]
211
- Read --> Check{Record Type?}
212
-
213
- Check -->|EMR_COMMENT| Plus["Check for EMF+ signature<br/>(0x2B464D45 = 'EMF+')"]
214
- Plus -->|EMF+ found| PlusReplay["replayEmfPlusRecords()<br/>Returns deferred images"]
215
- Plus -->|Not EMF+| Skip1[Skip record]
216
-
217
- Check -->|EMR_EOF| Done([End — return deferred images])
218
-
219
- Check -->|State records| State["handleEmfGdiStateRecord()<br/>SaveDC, RestoreDC, SetTextColor,<br/>SetBkMode, transforms, objects"]
220
-
221
- Check -->|Draw records| Draw["handleEmfGdiDrawRecord()<br/>Shapes → emf-gdi-draw-shapes<br/>Text/Bitmap → emf-gdi-draw-text-bitmap"]
222
-
223
- Check -->|Poly/Path records| Poly["handleEmfGdiPolyPathRecord()<br/>Polygon, Polyline, Bezier,<br/>BeginPath, FillPath, StrokePath"]
224
-
225
- Check -->|Ignored| Skip2["Skip: EMR_HEADER,<br/>EMR_SETBRUSHORGEX, etc."]
226
-
227
- PlusReplay --> Next
228
- Skip1 --> Next
229
- State --> Next
230
- Draw --> Next
231
- Poly --> Next
232
- Skip2 --> Next
233
-
234
- Next["offset += recSize"] --> Guard{"offset + 8 ≤ bufferLen<br/>AND recordCount < 50,000?"}
235
- Guard -->|Yes| Read
236
- Guard -->|No| Done
237
- ```
119
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
238
120
 
239
121
  ### EMF+ Dual-Mode Processing
240
122
 
241
123
  EMF files can contain embedded EMF+ records inside `EMR_COMMENT` records. When detected, these are processed by a parallel GDI+ replay engine:
242
124
 
243
- ```mermaid
244
- flowchart LR
245
- subgraph "EMF Record Stream"
246
- E1[EMR_HEADER]
247
- E2[EMR_SELECTOBJECT]
248
- E3["EMR_COMMENT<br/>(EMF+ signature)"]
249
- E4[EMR_RECTANGLE]
250
- E5["EMR_COMMENT<br/>(EMF+ signature)"]
251
- E6[EMR_EOF]
252
- end
253
-
254
- subgraph "EMF+ Record Stream (inside comments)"
255
- P1[EMFPLUS_HEADER]
256
- P2[EMFPLUS_OBJECT ×N]
257
- P3[EMFPLUS_FillRects]
258
- P4[EMFPLUS_DrawPath]
259
- P5[EMFPLUS_DrawString]
260
- P6[EMFPLUS_DrawImage]
261
- end
262
-
263
- E3 --> P1
264
- E3 --> P2
265
- E3 --> P3
266
- E5 --> P4
267
- E5 --> P5
268
- E5 --> P6
269
- ```
125
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
270
126
 
271
127
  The EMF+ state (object table, world transform, save stack) **persists across multiple `EMR_COMMENT` records** within the same file, allowing complex drawings to span several comment blocks.
272
128
 
@@ -274,24 +130,7 @@ The EMF+ state (object table, world transform, save stack) **persists across mul
274
130
 
275
131
  WMF uses a simpler 16-bit record format with word-aligned record sizes:
276
132
 
277
- ```mermaid
278
- flowchart TD
279
- Start([Parse WMF Header]) --> Magic{"Magic bytes?"}
280
- Magic -->|0x9AC6CDD7<br/>Aldus Placeable| APM["Read bounds & DPI<br/>from APM header"]
281
- Magic -->|Standard| Std["Use default bounds<br/>(800×600)"]
282
-
283
- APM --> Main
284
- Std --> Main
285
-
286
- Main["Sequential Record Loop"] --> RecType{"Record Type?"}
287
- RecType -->|Drawing| WDraw["handleWmfDrawRecord()<br/>MoveTo, LineTo, Rectangle,<br/>Ellipse, Polygon, Text, etc."]
288
- RecType -->|State| WState["Inline handlers:<br/>SetWindowOrg, SetWindowExt,<br/>SaveDC, RestoreDC, CreatePen,<br/>CreateBrush, CreateFont,<br/>SelectObject, DeleteObject"]
289
- RecType -->|META_EOF| WDone([Done])
290
-
291
- WDraw --> Next2[offset += recSize]
292
- WState --> Next2
293
- Next2 --> Main
294
- ```
133
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
295
134
 
296
135
  ---
297
136
 
@@ -368,21 +207,7 @@ The EMF+ replay engine (`emf-plus-replay.ts`) dispatches to:
368
207
 
369
208
  The converter manages multiple coordinate mapping systems:
370
209
 
371
- ```mermaid
372
- graph TD
373
- subgraph "EMF GDI Coordinates"
374
- A["Logical Coordinates<br/>(from metafile)"] -->|"Simple Scale"| B["Canvas Pixels<br/>x = (logX - bounds.left) × sx<br/>y = (logY - bounds.top) × sy"]
375
- A -->|"Mapping Mode"| C["Window/Viewport Transform<br/>x = ((logX - winOrg.x) / winExt.cx) × vpExt.cx + vpOrg.x"]
376
- end
377
-
378
- subgraph "EMF+ GDI+ Coordinates"
379
- D["GDI+ Logical Units"] -->|"World Transform"| E["Canvas via 6-element<br/>affine matrix [a,b,c,d,e,f]"]
380
- end
381
-
382
- subgraph "WMF Coordinates"
383
- F["WMF Logical Units"] -->|"Window → Canvas"| G["mx(x) = ((x - winOrg.x) / winExt.cx) × canvasW"]
384
- end
385
- ```
210
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
386
211
 
387
212
  **GDI coordinates** (`emf-gdi-coord.ts`) use either simple bounds-based scaling or full window/viewport mapping mode, activated when the metafile sets `SetWindowExtEx`/`SetViewportExtEx`.
388
213
 
@@ -394,34 +219,7 @@ graph TD
394
219
 
395
220
  Both GDI and GDI+ maintain their own object tables — essentially registries of reusable drawing resources:
396
221
 
397
- ```mermaid
398
- graph LR
399
- subgraph "GDI Object Table (Map<number, GdiObject>)"
400
- P1["Slot 0: Pen<br/>style=0 (solid), width=2, color=#000"]
401
- B1["Slot 1: Brush<br/>style=0 (solid), color=#ff0000"]
402
- F1["Slot 2: Font<br/>height=12, weight=700, family=Arial"]
403
- end
404
-
405
- subgraph "EMF+ Object Table (Map<number, EmfPlusObject>)"
406
- PB["Slot 0: plus-brush<br/>color=rgba(0,0,255,1)"]
407
- PP["Slot 1: plus-pen<br/>color=#000, width=1.5"]
408
- PH["Slot 3: plus-path<br/>points=[...], types=[...]"]
409
- PI["Slot 5: plus-image<br/>data=ArrayBuffer, type=Bitmap"]
410
- PF["Slot 6: plus-font<br/>emSize=14, family=Calibri"]
411
- end
412
-
413
- CR["CreatePen / CreateBrushIndirect /<br/>ExtCreateFontIndirectW"] --> P1
414
- CR --> B1
415
- CR --> F1
416
- SO["SelectObject(slot)"] -.->|"Applies to state"| Canvas["Canvas Context"]
417
-
418
- OBJ["EMFPLUS_OBJECT"] --> PB
419
- OBJ --> PP
420
- OBJ --> PH
421
- OBJ --> PI
422
- OBJ --> PF
423
- DRAW["FillPath(pathId) /<br/>DrawString(fontId)"] -.->|"References by ID"| Canvas
424
- ```
222
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
425
223
 
426
224
  **GDI objects** are created via `EMR_CREATEPEN`, `EMR_CREATEBRUSHINDIRECT`, `EMR_EXTCREATEFONTINDIRECTW`, etc., and selected into the drawing context with `EMR_SELECTOBJECT`. Stock objects (base index `0x80000000`) provide system defaults like `WHITE_BRUSH`, `BLACK_PEN`, etc.
427
225
 
@@ -431,33 +229,7 @@ graph LR
431
229
 
432
230
  Metafiles can contain embedded bitmaps as Device-Independent Bitmaps (DIBs). The decoder pipeline handles:
433
231
 
434
- ```mermaid
435
- flowchart TD
436
- A["DIB Header<br/>(40+ bytes BITMAPINFOHEADER)"] --> B{Compression?}
437
- B -->|BI_RGB| C["emf-dib-uncompressed.ts<br/>Decode raw pixel rows"]
438
- B -->|BI_RLE8| D["emf-dib-rle-decoder.ts<br/>Run-length decode 8bpp"]
439
- B -->|BI_RLE4| E["emf-dib-rle-decoder.ts<br/>Run-length decode 4bpp"]
440
- B -->|BI_BITFIELDS| F["emf-dib-uncompressed.ts<br/>Custom R/G/B channel masks"]
441
-
442
- C --> G{Bit Depth}
443
- F --> G
444
- G -->|1 bpp| H["Monochrome with colour table"]
445
- G -->|4 bpp| I["16-colour indexed"]
446
- G -->|8 bpp| J["256-colour indexed"]
447
- G -->|16 bpp| K["5-5-5 or bitfield masks"]
448
- G -->|24 bpp| L["B-G-R byte triplets"]
449
- G -->|32 bpp| M["B-G-R-A quadruplets"]
450
-
451
- H --> N["ImageData (RGBA pixels)"]
452
- I --> N
453
- J --> N
454
- K --> N
455
- L --> N
456
- M --> N
457
-
458
- D --> N
459
- E --> N
460
- ```
232
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
461
233
 
462
234
  EMF+ also has its own bitmap format (`emf-plus-bitmap-decoder.ts`) supporting GDI+ pixel formats:
463
235
 
@@ -470,30 +242,7 @@ EMF+ also has its own bitmap format (`emf-plus-bitmap-decoder.ts`) supporting GD
470
242
 
471
243
  Image draws (both GDI `StretchDIBits`/`BitBlt` and EMF+ `DrawImage`/`DrawImagePoints`) that reference bitmaps or embedded metafiles are collected as **deferred images** during the synchronous replay phase. After all records are processed, these are resolved asynchronously:
472
244
 
473
- ```mermaid
474
- sequenceDiagram
475
- participant R as Record Replay (sync)
476
- participant D as Deferred Queue
477
- participant P as Post-Processor (async)
478
- participant C as Canvas Context
479
-
480
- R->>D: Push image draw {data, position, transform, isMetafile}
481
- R->>D: Push image draw ...
482
- R->>D: Push image draw ...
483
- Note over R: EMR_EOF — replay complete
484
-
485
- P->>D: Iterate deferred images
486
- loop For each deferred image
487
- alt Is embedded metafile
488
- P->>P: Recursively call convertEmfToDataUrl() / convertWmfToDataUrl()
489
- P->>C: drawImage(bitmap, dx, dy, dw, dh)
490
- else Is raster bitmap
491
- P->>P: createImageBitmap(blob)
492
- P->>C: drawImage(bitmap, dx, dy, dw, dh)
493
- end
494
- end
495
- Note over C: Canvas now has all images composited
496
- ```
245
+ _See the [architecture diagrams on GitHub](https://github.com/ChristopherVR/pptx-viewer/blob/main/packages/emf-converter/README.md) for visual representations._
497
246
 
498
247
  This two-phase approach is necessary because `createImageBitmap()` is asynchronous, while the GDI record replay loop is synchronous for performance.
499
248
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "1.0.0",
3
+ "version": "1.0.7",
4
4
  "description": "Convert EMF/WMF metafile binaries to PNG data URLs using Canvas",
5
5
  "keywords": [
6
6
  "canvas",
@@ -11,9 +11,20 @@
11
11
  "windows-metafile",
12
12
  "wmf"
13
13
  ],
14
+ "homepage": "https://github.com/ChristopherVR/pptx-viewer",
15
+ "bugs": {
16
+ "url": "https://github.com/ChristopherVR/pptx-viewer/issues"
17
+ },
14
18
  "license": "MIT",
19
+ "author": "ChristopherVR",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/ChristopherVR/pptx-viewer.git",
23
+ "directory": "packages/emf-converter"
24
+ },
15
25
  "files": [
16
26
  "dist/",
27
+ "LICENSE",
17
28
  "README.md"
18
29
  ],
19
30
  "main": "dist/index.js",