@file-viewer/renderer-email 2.4.0 → 3.0.1

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/email.d.ts CHANGED
@@ -1,2 +1,29 @@
1
1
  import type { FileRenderContext, FileViewerRenderedInstance } from '@file-viewer/core';
2
+ type EmailKind = 'eml' | 'msg' | 'mbox';
3
+ interface EmailAddress {
4
+ name?: string;
5
+ address?: string;
6
+ }
7
+ interface EmailAttachmentView {
8
+ id: string;
9
+ name: string;
10
+ mimeType?: string;
11
+ size: number;
12
+ contentId?: string;
13
+ load(): Promise<ArrayBuffer>;
14
+ }
15
+ export interface ParsedEmailView {
16
+ kind: EmailKind;
17
+ subject: string;
18
+ from: EmailAddress[];
19
+ to: EmailAddress[];
20
+ cc: EmailAddress[];
21
+ date?: string;
22
+ text?: string;
23
+ html?: string;
24
+ headers?: string;
25
+ attachments: EmailAttachmentView[];
26
+ }
27
+ export declare const parseEml: (buffer: ArrayBuffer, filename: string, objectUrls: string[], cidUrls: Map<string, string>) => Promise<ParsedEmailView>;
2
28
  export default function renderEmail(buffer: ArrayBuffer, target: HTMLDivElement, type?: string, context?: FileRenderContext): Promise<FileViewerRenderedInstance>;
29
+ export {};
package/dist/email.js CHANGED
@@ -123,7 +123,9 @@ const createPostalAttachments = (email, objectUrls, cidUrls) => {
123
123
  cidUrls.set(normalizeContentId(attachment.contentId), url);
124
124
  })).then(() => attachments);
125
125
  };
126
- const parseEml = async (buffer, filename, objectUrls, cidUrls) => {
126
+ // Exported for the package-local #232 regression gate (verify-github-232.mjs); it
127
+ // stays out of the public exports map, so the shipped API surface is unchanged.
128
+ export const parseEml = async (buffer, filename, objectUrls, cidUrls) => {
127
129
  var _a, _b;
128
130
  const PostalMime = (await import('postal-mime')).default;
129
131
  const email = await PostalMime.parse(buffer, {
@@ -265,6 +267,9 @@ export default async function renderEmail(buffer, target, type = 'eml', context)
265
267
  const darkMode = resolveFileViewerColorScheme((_d = context === null || context === void 0 ? void 0 : context.options) === null || _d === void 0 ? void 0 : _d.theme, systemDark) === 'dark';
266
268
  const cleanups = [];
267
269
  let nestedRendered;
270
+ let attachmentPreviewVersion = 0;
271
+ let attachmentAbortController;
272
+ let disposed = false;
268
273
  let overlay = null;
269
274
  let errorElement = null;
270
275
  const root = createElement('section', 'email-viewer');
@@ -395,6 +400,18 @@ export default async function renderEmail(buffer, target, type = 'eml', context)
395
400
  });
396
401
  };
397
402
  const previewAttachment = async (attachment) => {
403
+ var _a, _b, _c;
404
+ const previewVersion = ++attachmentPreviewVersion;
405
+ attachmentAbortController === null || attachmentAbortController === void 0 ? void 0 : attachmentAbortController.abort();
406
+ const previewAbortController = new AbortController();
407
+ attachmentAbortController = previewAbortController;
408
+ const abortFromParent = () => { var _a; return previewAbortController.abort((_a = context === null || context === void 0 ? void 0 : context.signal) === null || _a === void 0 ? void 0 : _a.reason); };
409
+ if ((_a = context === null || context === void 0 ? void 0 : context.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
410
+ abortFromParent();
411
+ }
412
+ else {
413
+ (_b = context === null || context === void 0 ? void 0 : context.signal) === null || _b === void 0 ? void 0 : _b.addEventListener('abort', abortFromParent, { once: true });
414
+ }
398
415
  activeAttachment = attachment;
399
416
  syncAttachmentState();
400
417
  attachmentPreview.hidden = false;
@@ -408,22 +425,37 @@ export default async function renderEmail(buffer, target, type = 'eml', context)
408
425
  attachmentTarget.append(child);
409
426
  const extension = getAttachmentExtension(attachment.name);
410
427
  if (context === null || context === void 0 ? void 0 : context.renderNestedBuffer) {
411
- nestedRendered = await context.renderNestedBuffer(attachmentBuffer, extension, child, {
428
+ const nextRendered = await context.renderNestedBuffer(attachmentBuffer, extension, child, {
412
429
  ...context,
413
430
  filename: attachment.name,
414
431
  options: context.options,
432
+ signal: previewAbortController.signal,
415
433
  });
434
+ if (disposed || previewVersion !== attachmentPreviewVersion || previewAbortController.signal.aborted) {
435
+ await disposeFileViewerRendered(nextRendered);
436
+ return;
437
+ }
438
+ nestedRendered = nextRendered;
416
439
  }
417
440
  else {
418
441
  child.append(createElement('div', undefined, t('email.attachments.nestedUnavailable', { name: attachment.name })));
419
442
  }
420
443
  }
421
444
  catch (nextError) {
445
+ if (disposed || previewVersion !== attachmentPreviewVersion || previewAbortController.signal.aborted) {
446
+ return;
447
+ }
422
448
  console.error(nextError);
423
449
  showError(nextError instanceof Error ? nextError.message : String(nextError));
424
450
  }
425
451
  finally {
426
- hideLoading();
452
+ (_c = context === null || context === void 0 ? void 0 : context.signal) === null || _c === void 0 ? void 0 : _c.removeEventListener('abort', abortFromParent);
453
+ if (attachmentAbortController === previewAbortController) {
454
+ attachmentAbortController = undefined;
455
+ }
456
+ if (!disposed && previewVersion === attachmentPreviewVersion) {
457
+ hideLoading();
458
+ }
427
459
  }
428
460
  };
429
461
  parsed.attachments.forEach(attachment => {
@@ -466,6 +498,10 @@ export default async function renderEmail(buffer, target, type = 'eml', context)
466
498
  return {
467
499
  $el: root,
468
500
  async unmount() {
501
+ disposed = true;
502
+ attachmentPreviewVersion += 1;
503
+ attachmentAbortController === null || attachmentAbortController === void 0 ? void 0 : attachmentAbortController.abort();
504
+ attachmentAbortController = undefined;
469
505
  await clearAttachmentPreview();
470
506
  cleanups.splice(0).forEach(cleanup => cleanup());
471
507
  objectUrls.forEach(url => URL.revokeObjectURL(url));
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "../../../ecosystem/capability-manifest.schema.json",
3
+ "schemaVersion": 1,
4
+ "id": "email",
5
+ "packageName": "@file-viewer/renderer-email",
6
+ "rendererIds": ["email"],
7
+ "formats": ["eml", "msg", "mbox"],
8
+ "assets": { "rendererIds": [] },
9
+ "license": { "spdx": "Apache-2.0", "policy": "permissive" },
10
+ "weight": "light",
11
+ "profiles": ["standard", "all"]
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-email",
3
- "version": "2.4.0",
3
+ "version": "3.0.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone email renderer plugin for File Viewer with EML, MSG, MBOX, attachments, and nested previews.",
@@ -50,21 +50,27 @@
50
50
  },
51
51
  "files": [
52
52
  "dist",
53
+ "file-viewer.capability.json",
53
54
  "README.md",
54
55
  "README.en.md",
55
56
  "LICENSE"
56
57
  ],
57
58
  "dependencies": {
58
- "@file-viewer/core": "2.4.0",
59
+ "@file-viewer/core": "3.0.1",
59
60
  "@kenjiuno/msgreader": "^1.28.0",
60
- "postal-mime": "^2.7.4"
61
+ "buffer": "^6.0.3",
62
+ "postal-mime": "^3.0.0"
61
63
  },
62
64
  "devDependencies": {
63
65
  "typescript": "^6.0.3"
64
66
  },
67
+ "fileViewer": {
68
+ "capabilityManifest": "./file-viewer.capability.json"
69
+ },
65
70
  "license": "Apache-2.0",
66
71
  "scripts": {
67
72
  "build": "tsc -b tsconfig.json",
68
- "type-check": "tsc -b tsconfig.json"
73
+ "type-check": "tsc -b tsconfig.json",
74
+ "verify:github-232": "pnpm --filter @file-viewer/core build && pnpm build && node scripts/verify-github-232.mjs"
69
75
  }
70
76
  }