@file-viewer/pptx 2.2.3 → 2.2.5
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/chart.d.ts +5 -1
- package/dist/chart.js +49 -11
- package/dist/viewer.d.ts +8 -0
- package/dist/viewer.js +125 -5
- package/dist/worker/pptx.worker.js +11 -12
- package/package.json +1 -1
package/dist/chart.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type PptxPostProcessingHandle = {
|
|
2
|
+
destroy: () => void;
|
|
3
|
+
};
|
|
4
|
+
export declare const findPptxChartTarget: (root: ParentNode, chartID: string) => HTMLElement | null;
|
|
5
|
+
export declare const renderPptxPostProcessing: (charts: unknown, root: ParentNode) => Promise<PptxPostProcessingHandle>;
|
package/dist/chart.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
const asChartQueue = (charts) => {
|
|
2
2
|
return Array.isArray(charts === null || charts === void 0 ? void 0 : charts.MsgQueue) ? charts.MsgQueue : [];
|
|
3
3
|
};
|
|
4
|
+
export const findPptxChartTarget = (root, chartID) => {
|
|
5
|
+
const rootElement = root;
|
|
6
|
+
if (rootElement.id === chartID) {
|
|
7
|
+
return rootElement;
|
|
8
|
+
}
|
|
9
|
+
return Array.from(root.querySelectorAll('[id]'))
|
|
10
|
+
.find(element => element.id === chartID) || null;
|
|
11
|
+
};
|
|
4
12
|
const getNumericBulletText = (type, index) => {
|
|
5
13
|
switch (type) {
|
|
6
14
|
case 'arabicPeriod':
|
|
@@ -141,18 +149,24 @@ const fitOverflowingTextBlocks = (root) => {
|
|
|
141
149
|
.querySelectorAll('.slide div.content, .slide div.content-rtl')
|
|
142
150
|
.forEach(fitOverflowingTextBlock);
|
|
143
151
|
};
|
|
144
|
-
const renderChart = async (message) => {
|
|
152
|
+
const renderChart = async (message, root) => {
|
|
145
153
|
var _a;
|
|
146
154
|
const payload = message.data;
|
|
147
155
|
if (!(payload === null || payload === void 0 ? void 0 : payload.chartID) || !payload.chartType || !payload.chartData) {
|
|
148
156
|
return;
|
|
149
157
|
}
|
|
158
|
+
const chartTarget = findPptxChartTarget(root, payload.chartID);
|
|
159
|
+
if (!chartTarget) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
150
162
|
const billboard = await import('billboard.js');
|
|
151
163
|
const d3Format = await import('d3-format');
|
|
152
164
|
const bb = billboard.default || billboard;
|
|
153
165
|
const { area, bar, line, pie, scatter } = billboard;
|
|
154
166
|
const chart = {
|
|
155
|
-
|
|
167
|
+
// A selector makes Billboard query the main document. That misses chart
|
|
168
|
+
// placeholders inside the viewer Shadow DOM and makes it fall back to body.
|
|
169
|
+
bindto: chartTarget,
|
|
156
170
|
};
|
|
157
171
|
const chartData = payload.chartData;
|
|
158
172
|
const axis = {
|
|
@@ -249,20 +263,44 @@ const renderChart = async (message) => {
|
|
|
249
263
|
return;
|
|
250
264
|
}
|
|
251
265
|
if (chart.data) {
|
|
252
|
-
bb.generate(chart);
|
|
266
|
+
return bb.generate(chart);
|
|
253
267
|
}
|
|
254
268
|
};
|
|
255
269
|
export const renderPptxPostProcessing = async (charts, root) => {
|
|
256
270
|
restoreNumericBullets(root);
|
|
257
271
|
fitOverflowingTextBlocks(root);
|
|
258
272
|
const queue = asChartQueue(charts);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
273
|
+
const chartInstances = [];
|
|
274
|
+
if (queue.length) {
|
|
275
|
+
const results = await Promise.allSettled(queue.map(message => renderChart(message, root)));
|
|
276
|
+
for (const result of results) {
|
|
277
|
+
if (result.status === 'fulfilled') {
|
|
278
|
+
if (result.value) {
|
|
279
|
+
chartInstances.push(result.value);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
console.warn('PPTX chart rendering skipped:', result.reason);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
267
286
|
}
|
|
287
|
+
let destroyed = false;
|
|
288
|
+
return {
|
|
289
|
+
destroy() {
|
|
290
|
+
var _a;
|
|
291
|
+
if (destroyed) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
destroyed = true;
|
|
295
|
+
for (const chart of chartInstances) {
|
|
296
|
+
try {
|
|
297
|
+
(_a = chart.destroy) === null || _a === void 0 ? void 0 : _a.call(chart);
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// The DOM may already be detached during framework unmount.
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
chartInstances.length = 0;
|
|
304
|
+
},
|
|
305
|
+
};
|
|
268
306
|
};
|
package/dist/viewer.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export declare class PptxViewer {
|
|
|
20
20
|
private slideWindowListeners;
|
|
21
21
|
private slideWindowFrame;
|
|
22
22
|
private charts;
|
|
23
|
+
private readonly chartHandles;
|
|
24
|
+
private readonly mediaRecords;
|
|
23
25
|
private disposed;
|
|
24
26
|
private completed;
|
|
25
27
|
private readonly handleSlideWindowChange;
|
|
@@ -59,6 +61,12 @@ export declare class PptxViewer {
|
|
|
59
61
|
cloneForExport(): Promise<HTMLElement>;
|
|
60
62
|
private complete;
|
|
61
63
|
private fail;
|
|
64
|
+
private trackChartHandle;
|
|
65
|
+
private releaseChartHandle;
|
|
66
|
+
private releaseCharts;
|
|
67
|
+
private storeMedia;
|
|
68
|
+
private hydrateMedia;
|
|
69
|
+
private releaseMedia;
|
|
62
70
|
private attachResizeObserver;
|
|
63
71
|
private scheduleResize;
|
|
64
72
|
private resize;
|
package/dist/viewer.js
CHANGED
|
@@ -100,6 +100,8 @@ export class PptxViewer {
|
|
|
100
100
|
this.slideWindowListeners = [];
|
|
101
101
|
this.slideWindowFrame = 0;
|
|
102
102
|
this.charts = null;
|
|
103
|
+
this.chartHandles = new Set();
|
|
104
|
+
this.mediaRecords = new Map();
|
|
103
105
|
this.disposed = false;
|
|
104
106
|
this.completed = false;
|
|
105
107
|
this.handleSlideWindowChange = () => this.scheduleSlideWindowUpdate();
|
|
@@ -139,6 +141,8 @@ export class PptxViewer {
|
|
|
139
141
|
var _a, _b, _c, _d;
|
|
140
142
|
this.disposed = true;
|
|
141
143
|
this.previewThumbnailDataUrl = null;
|
|
144
|
+
this.releaseCharts();
|
|
145
|
+
this.releaseMedia();
|
|
142
146
|
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
143
147
|
this.worker = null;
|
|
144
148
|
(_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
@@ -155,6 +159,8 @@ export class PptxViewer {
|
|
|
155
159
|
startWorker() {
|
|
156
160
|
var _a;
|
|
157
161
|
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
162
|
+
this.releaseCharts();
|
|
163
|
+
this.releaseMedia();
|
|
158
164
|
this.completed = false;
|
|
159
165
|
this.charts = null;
|
|
160
166
|
this.previewThumbnailDataUrl = null;
|
|
@@ -195,11 +201,15 @@ export class PptxViewer {
|
|
|
195
201
|
}
|
|
196
202
|
else {
|
|
197
203
|
const element = appendHtml(this.content, String(message.data || ''));
|
|
204
|
+
this.hydrateMedia(element);
|
|
198
205
|
this.scheduleResize();
|
|
199
206
|
(_b = (_a = this.options).onSlideRendered) === null || _b === void 0 ? void 0 : _b.call(_a, Number(message.slide_num || 0), element);
|
|
200
207
|
}
|
|
201
208
|
break;
|
|
202
209
|
}
|
|
210
|
+
case 'media':
|
|
211
|
+
this.storeMedia(message.data);
|
|
212
|
+
break;
|
|
203
213
|
case 'slide-error': {
|
|
204
214
|
const slideNumber = Number(message.slide_num || 0);
|
|
205
215
|
const error = message.data;
|
|
@@ -320,6 +330,8 @@ export class PptxViewer {
|
|
|
320
330
|
notified: false,
|
|
321
331
|
postProcessed: false,
|
|
322
332
|
postProcessPromise: null,
|
|
333
|
+
postProcessVersion: 0,
|
|
334
|
+
chartHandle: null,
|
|
323
335
|
};
|
|
324
336
|
}
|
|
325
337
|
getDesignerCanvases(record) {
|
|
@@ -333,9 +345,11 @@ export class PptxViewer {
|
|
|
333
345
|
const designerCanvases = this.getDesignerCanvases(record);
|
|
334
346
|
record.slot.replaceChildren();
|
|
335
347
|
record.element = appendHtml(record.slot, record.html);
|
|
348
|
+
this.hydrateMedia(record.element);
|
|
336
349
|
record.slot.append(...designerCanvases);
|
|
337
350
|
record.rendered = true;
|
|
338
351
|
record.postProcessed = false;
|
|
352
|
+
record.postProcessVersion += 1;
|
|
339
353
|
this.updateMeasuredSlideHeight(record);
|
|
340
354
|
if (!record.notified) {
|
|
341
355
|
record.notified = true;
|
|
@@ -351,6 +365,9 @@ export class PptxViewer {
|
|
|
351
365
|
return;
|
|
352
366
|
}
|
|
353
367
|
this.updateMeasuredSlideHeight(record);
|
|
368
|
+
this.releaseChartHandle(record.chartHandle);
|
|
369
|
+
record.chartHandle = null;
|
|
370
|
+
record.postProcessVersion += 1;
|
|
354
371
|
record.slot.replaceChildren();
|
|
355
372
|
record.element = null;
|
|
356
373
|
record.rendered = false;
|
|
@@ -530,7 +547,8 @@ export class PptxViewer {
|
|
|
530
547
|
}
|
|
531
548
|
async postProcessRenderedContent(charts) {
|
|
532
549
|
if (!this.shouldWindowSlides()) {
|
|
533
|
-
await renderPptxPostProcessing(charts, this.content);
|
|
550
|
+
const handle = await renderPptxPostProcessing(charts, this.content);
|
|
551
|
+
this.trackChartHandle(handle);
|
|
534
552
|
return;
|
|
535
553
|
}
|
|
536
554
|
await Promise.all(this.slideRecords
|
|
@@ -542,16 +560,24 @@ export class PptxViewer {
|
|
|
542
560
|
return;
|
|
543
561
|
}
|
|
544
562
|
if (!record.postProcessPromise) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
563
|
+
const version = record.postProcessVersion;
|
|
564
|
+
const postProcessPromise = (async () => {
|
|
565
|
+
const handle = await renderPptxPostProcessing(this.charts, record.slot);
|
|
566
|
+
if (this.disposed || !record.rendered || record.postProcessVersion !== version) {
|
|
567
|
+
handle === null || handle === void 0 ? void 0 : handle.destroy();
|
|
548
568
|
return;
|
|
549
569
|
}
|
|
570
|
+
this.releaseChartHandle(record.chartHandle);
|
|
571
|
+
record.chartHandle = handle;
|
|
572
|
+
this.trackChartHandle(handle);
|
|
550
573
|
record.postProcessed = true;
|
|
551
574
|
this.updateMeasuredSlideHeight(record);
|
|
552
575
|
})().finally(() => {
|
|
553
|
-
record.postProcessPromise
|
|
576
|
+
if (record.postProcessPromise === postProcessPromise) {
|
|
577
|
+
record.postProcessPromise = null;
|
|
578
|
+
}
|
|
554
579
|
});
|
|
580
|
+
record.postProcessPromise = postProcessPromise;
|
|
555
581
|
}
|
|
556
582
|
await record.postProcessPromise;
|
|
557
583
|
}
|
|
@@ -603,9 +629,103 @@ export class PptxViewer {
|
|
|
603
629
|
this.completed = true;
|
|
604
630
|
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
605
631
|
this.worker = null;
|
|
632
|
+
this.releaseCharts();
|
|
633
|
+
this.releaseMedia();
|
|
606
634
|
this.content.dataset.renderState = 'error';
|
|
607
635
|
(_c = (_b = this.options).onError) === null || _c === void 0 ? void 0 : _c.call(_b, error);
|
|
608
636
|
}
|
|
637
|
+
trackChartHandle(handle) {
|
|
638
|
+
if (!handle) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (this.disposed) {
|
|
642
|
+
handle.destroy();
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
this.chartHandles.add(handle);
|
|
646
|
+
}
|
|
647
|
+
releaseChartHandle(handle) {
|
|
648
|
+
if (!handle) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
this.chartHandles.delete(handle);
|
|
652
|
+
handle.destroy();
|
|
653
|
+
}
|
|
654
|
+
releaseCharts() {
|
|
655
|
+
for (const handle of this.chartHandles) {
|
|
656
|
+
handle.destroy();
|
|
657
|
+
}
|
|
658
|
+
this.chartHandles.clear();
|
|
659
|
+
for (const record of this.slideRecords) {
|
|
660
|
+
record.chartHandle = null;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
storeMedia(data) {
|
|
664
|
+
if (!data || typeof data !== 'object') {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
const media = data;
|
|
668
|
+
if (typeof media.id !== 'string' ||
|
|
669
|
+
!media.id ||
|
|
670
|
+
typeof media.mimeType !== 'string' ||
|
|
671
|
+
!(media.buffer instanceof ArrayBuffer)) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
this.releaseMedia(media.id);
|
|
675
|
+
this.mediaRecords.set(media.id, {
|
|
676
|
+
buffer: media.buffer,
|
|
677
|
+
mimeType: media.mimeType,
|
|
678
|
+
objectUrl: null,
|
|
679
|
+
revokeObjectUrl: null,
|
|
680
|
+
});
|
|
681
|
+
this.hydrateMedia(this.content);
|
|
682
|
+
}
|
|
683
|
+
hydrateMedia(root) {
|
|
684
|
+
var _a;
|
|
685
|
+
if (!root) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
const elements = Array.from(root.querySelectorAll('[data-pptx-media-id]'));
|
|
689
|
+
if (root.matches('[data-pptx-media-id]')) {
|
|
690
|
+
elements.unshift(root);
|
|
691
|
+
}
|
|
692
|
+
for (const element of elements) {
|
|
693
|
+
const mediaId = element.dataset.pptxMediaId;
|
|
694
|
+
const record = mediaId ? this.mediaRecords.get(mediaId) : undefined;
|
|
695
|
+
if (!record) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
if (!record.objectUrl) {
|
|
699
|
+
const view = this.target.ownerDocument.defaultView;
|
|
700
|
+
const BlobCtor = (view === null || view === void 0 ? void 0 : view.Blob) || globalThis.Blob;
|
|
701
|
+
const UrlApi = (view === null || view === void 0 ? void 0 : view.URL) || globalThis.URL;
|
|
702
|
+
if (typeof BlobCtor !== 'function' ||
|
|
703
|
+
typeof (UrlApi === null || UrlApi === void 0 ? void 0 : UrlApi.createObjectURL) !== 'function') {
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
const objectUrl = UrlApi.createObjectURL(new BlobCtor([record.buffer], { type: record.mimeType }));
|
|
707
|
+
record.objectUrl = objectUrl;
|
|
708
|
+
record.revokeObjectUrl = () => UrlApi.revokeObjectURL(objectUrl);
|
|
709
|
+
}
|
|
710
|
+
if (element.src !== record.objectUrl) {
|
|
711
|
+
element.src = record.objectUrl;
|
|
712
|
+
(_a = element.load) === null || _a === void 0 ? void 0 : _a.call(element);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
releaseMedia(mediaId) {
|
|
717
|
+
var _a, _b;
|
|
718
|
+
if (mediaId) {
|
|
719
|
+
const record = this.mediaRecords.get(mediaId);
|
|
720
|
+
(_a = record === null || record === void 0 ? void 0 : record.revokeObjectUrl) === null || _a === void 0 ? void 0 : _a.call(record);
|
|
721
|
+
this.mediaRecords.delete(mediaId);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
for (const record of this.mediaRecords.values()) {
|
|
725
|
+
(_b = record.revokeObjectUrl) === null || _b === void 0 ? void 0 : _b.call(record);
|
|
726
|
+
}
|
|
727
|
+
this.mediaRecords.clear();
|
|
728
|
+
}
|
|
609
729
|
attachResizeObserver() {
|
|
610
730
|
if (typeof ResizeObserver === 'undefined') {
|
|
611
731
|
return;
|