@open-file-viewer/core 0.1.23 → 0.1.25

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/index.js CHANGED
@@ -4238,6 +4238,7 @@ var mimeLangMap = {
4238
4238
  };
4239
4239
  var MAX_HIGHLIGHT_CHARS = 18e4;
4240
4240
  var MAX_RENDER_CHARS = 6e5;
4241
+ var prismLanguageLoads = /* @__PURE__ */ new Map();
4241
4242
  function textPlugin() {
4242
4243
  return {
4243
4244
  name: "text",
@@ -4269,10 +4270,10 @@ function textPlugin() {
4269
4270
  ]);
4270
4271
  const parseMarkdown = markedModule.marked?.parse || markedModule.parse || markedModule.default?.parse;
4271
4272
  const Prism2 = PrismModule2.default || PrismModule2;
4272
- const DOMPurify4 = DOMPurifyModule.default || DOMPurifyModule;
4273
+ const DOMPurify3 = DOMPurifyModule.default || DOMPurifyModule;
4273
4274
  const container = document.createElement("div");
4274
4275
  container.className = "ofv-markdown-body";
4275
- container.innerHTML = DOMPurify4.sanitize(parseMarkdown(text), {
4276
+ container.innerHTML = DOMPurify3.sanitize(parseMarkdown(text), {
4276
4277
  USE_PROFILES: { html: true },
4277
4278
  ADD_ATTR: ["target"]
4278
4279
  });
@@ -4281,6 +4282,14 @@ function textPlugin() {
4281
4282
  try {
4282
4283
  const codeBlocks = container.querySelectorAll("pre code");
4283
4284
  if (codeBlocks.length > 0) {
4285
+ const languages = /* @__PURE__ */ new Set();
4286
+ codeBlocks.forEach((block) => {
4287
+ const language = getPrismLanguageFromElement(block) || getPrismLanguageFromElement(block.parentElement);
4288
+ if (language) {
4289
+ languages.add(language);
4290
+ }
4291
+ });
4292
+ await Promise.all([...languages].map((language) => loadPrismLanguage(language)));
4284
4293
  codeBlocks.forEach((block) => {
4285
4294
  const parent = block.parentElement;
4286
4295
  if (parent && !parent.className.includes("language-")) {
@@ -4309,97 +4318,7 @@ function textPlugin() {
4309
4318
  const Prism = PrismModule.default || PrismModule;
4310
4319
  if (lang !== "none") {
4311
4320
  try {
4312
- if (lang === "typescript" || lang === "tsx") {
4313
- await import("prismjs/components/prism-typescript");
4314
- } else if (lang === "python") {
4315
- await import("prismjs/components/prism-python");
4316
- } else if (lang === "json") {
4317
- await import("prismjs/components/prism-json");
4318
- } else if (lang === "json5") {
4319
- await import("prismjs/components/prism-json5");
4320
- } else if (lang === "yaml") {
4321
- await import("prismjs/components/prism-yaml");
4322
- } else if (lang === "toml") {
4323
- await import("prismjs/components/prism-toml");
4324
- } else if (lang === "ini") {
4325
- await import("prismjs/components/prism-ini");
4326
- } else if (lang === "properties") {
4327
- await import("prismjs/components/prism-properties");
4328
- } else if (lang === "editorconfig") {
4329
- await import("prismjs/components/prism-editorconfig");
4330
- } else if (lang === "ignore") {
4331
- await import("prismjs/components/prism-ignore");
4332
- } else if (lang === "protobuf") {
4333
- await import("prismjs/components/prism-protobuf");
4334
- } else if (lang === "hcl") {
4335
- await import("prismjs/components/prism-hcl");
4336
- } else if (lang === "latex") {
4337
- await import("prismjs/components/prism-latex");
4338
- } else if (lang === "dot") {
4339
- await import("prismjs/components/prism-dot");
4340
- } else if (lang === "http") {
4341
- await import("prismjs/components/prism-http");
4342
- } else if (lang === "bash") {
4343
- await import("prismjs/components/prism-bash");
4344
- } else if (lang === "powershell") {
4345
- await import("prismjs/components/prism-powershell");
4346
- } else if (lang === "batch") {
4347
- await import("prismjs/components/prism-batch");
4348
- } else if (lang === "docker") {
4349
- await import("prismjs/components/prism-docker");
4350
- } else if (lang === "makefile") {
4351
- await import("prismjs/components/prism-makefile");
4352
- } else if (lang === "ruby") {
4353
- await import("prismjs/components/prism-ruby");
4354
- } else if (lang === "nginx") {
4355
- await import("prismjs/components/prism-nginx");
4356
- } else if (lang === "groovy") {
4357
- await import("prismjs/components/prism-groovy");
4358
- } else if (lang === "graphql") {
4359
- await import("prismjs/components/prism-graphql");
4360
- } else if (lang === "csharp") {
4361
- await import("prismjs/components/prism-csharp");
4362
- } else if (lang === "rust") {
4363
- await import("prismjs/components/prism-rust");
4364
- } else if (lang === "go") {
4365
- await import("prismjs/components/prism-go");
4366
- } else if (lang === "ruby") {
4367
- await import("prismjs/components/prism-ruby");
4368
- } else if (lang === "swift") {
4369
- await import("prismjs/components/prism-swift");
4370
- } else if (lang === "kotlin") {
4371
- await import("prismjs/components/prism-kotlin");
4372
- } else if (lang === "scala") {
4373
- await import("prismjs/components/prism-scala");
4374
- } else if (lang === "lua") {
4375
- await import("prismjs/components/prism-lua");
4376
- } else if (lang === "r") {
4377
- await import("prismjs/components/prism-r");
4378
- } else if (lang === "dart") {
4379
- await import("prismjs/components/prism-dart");
4380
- } else if (lang === "elm") {
4381
- await import("prismjs/components/prism-elm");
4382
- } else if (lang === "elixir") {
4383
- await import("prismjs/components/prism-elixir");
4384
- } else if (lang === "clojure") {
4385
- await import("prismjs/components/prism-clojure");
4386
- } else if (lang === "erlang") {
4387
- await import("prismjs/components/prism-erlang");
4388
- } else if (lang === "fsharp") {
4389
- await import("prismjs/components/prism-fsharp");
4390
- } else if (lang === "haskell") {
4391
- await import("prismjs/components/prism-haskell");
4392
- } else if (lang === "sql") {
4393
- await import("prismjs/components/prism-sql");
4394
- } else if (lang === "cpp") {
4395
- await import("prismjs/components/prism-c");
4396
- await import("prismjs/components/prism-cpp");
4397
- } else if (lang === "java") {
4398
- await import("prismjs/components/prism-java");
4399
- } else if (lang === "php") {
4400
- await import("prismjs/components/prism-markup-templating");
4401
- await import("prismjs/components/prism-php");
4402
- }
4321
+ await loadPrismLanguage(lang);
4403
4322
  } catch (e) {
4404
4323
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4405
4324
  }
@@ -4524,6 +4443,183 @@ function textPlugin() {
4524
4443
  }
4525
4444
  };
4526
4445
  }
4446
+ function getPrismLanguageFromElement(element) {
4447
+ if (!element) {
4448
+ return void 0;
4449
+ }
4450
+ for (const className of element.classList) {
4451
+ if (className.startsWith("language-") && className.length > 9) {
4452
+ return className.slice(9).toLowerCase();
4453
+ }
4454
+ }
4455
+ return void 0;
4456
+ }
4457
+ async function loadPrismLanguage(language) {
4458
+ if (["none", "plain", "plaintext", "text", "markup", "css", "clike", "javascript"].includes(language)) {
4459
+ return;
4460
+ }
4461
+ const existing = prismLanguageLoads.get(language);
4462
+ if (existing) {
4463
+ return existing;
4464
+ }
4465
+ const loading = loadPrismLanguageComponent(language).catch((error) => {
4466
+ prismLanguageLoads.delete(language);
4467
+ throw error;
4468
+ });
4469
+ prismLanguageLoads.set(language, loading);
4470
+ return loading;
4471
+ }
4472
+ async function loadPrismLanguageComponent(language) {
4473
+ switch (language) {
4474
+ case "typescript":
4475
+ await import("prismjs/components/prism-typescript");
4476
+ break;
4477
+ case "jsx":
4478
+ await import("prismjs/components/prism-jsx");
4479
+ break;
4480
+ case "tsx":
4481
+ await import("./tsx-A26VGWUK.js");
4482
+ break;
4483
+ case "python":
4484
+ await import("prismjs/components/prism-python");
4485
+ break;
4486
+ case "json":
4487
+ await import("prismjs/components/prism-json");
4488
+ break;
4489
+ case "json5":
4490
+ await import("./json5-EAGAEIPM.js");
4491
+ break;
4492
+ case "yaml":
4493
+ await import("prismjs/components/prism-yaml");
4494
+ break;
4495
+ case "toml":
4496
+ await import("prismjs/components/prism-toml");
4497
+ break;
4498
+ case "ini":
4499
+ await import("prismjs/components/prism-ini");
4500
+ break;
4501
+ case "properties":
4502
+ await import("prismjs/components/prism-properties");
4503
+ break;
4504
+ case "editorconfig":
4505
+ await import("prismjs/components/prism-editorconfig");
4506
+ break;
4507
+ case "ignore":
4508
+ await import("prismjs/components/prism-ignore");
4509
+ break;
4510
+ case "protobuf":
4511
+ await import("prismjs/components/prism-protobuf");
4512
+ break;
4513
+ case "hcl":
4514
+ await import("prismjs/components/prism-hcl");
4515
+ break;
4516
+ case "latex":
4517
+ await import("prismjs/components/prism-latex");
4518
+ break;
4519
+ case "dot":
4520
+ await import("prismjs/components/prism-dot");
4521
+ break;
4522
+ case "http":
4523
+ await import("prismjs/components/prism-http");
4524
+ break;
4525
+ case "bash":
4526
+ await import("prismjs/components/prism-bash");
4527
+ break;
4528
+ case "powershell":
4529
+ await import("prismjs/components/prism-powershell");
4530
+ break;
4531
+ case "batch":
4532
+ await import("prismjs/components/prism-batch");
4533
+ break;
4534
+ case "docker":
4535
+ await import("prismjs/components/prism-docker");
4536
+ break;
4537
+ case "makefile":
4538
+ await import("prismjs/components/prism-makefile");
4539
+ break;
4540
+ case "ruby":
4541
+ await import("prismjs/components/prism-ruby");
4542
+ break;
4543
+ case "nginx":
4544
+ await import("prismjs/components/prism-nginx");
4545
+ break;
4546
+ case "groovy":
4547
+ await import("prismjs/components/prism-groovy");
4548
+ break;
4549
+ case "graphql":
4550
+ await import("prismjs/components/prism-graphql");
4551
+ break;
4552
+ case "csharp":
4553
+ await import("prismjs/components/prism-csharp");
4554
+ break;
4555
+ case "rust":
4556
+ await import("prismjs/components/prism-rust");
4557
+ break;
4558
+ case "go":
4559
+ await import("prismjs/components/prism-go");
4560
+ break;
4561
+ case "swift":
4562
+ await import("prismjs/components/prism-swift");
4563
+ break;
4564
+ case "kotlin":
4565
+ await import("prismjs/components/prism-kotlin");
4566
+ break;
4567
+ case "java":
4568
+ await import("prismjs/components/prism-java");
4569
+ break;
4570
+ case "scala":
4571
+ await import("./scala-V5QQ35QA.js");
4572
+ break;
4573
+ case "lua":
4574
+ await import("prismjs/components/prism-lua");
4575
+ break;
4576
+ case "r":
4577
+ await import("prismjs/components/prism-r");
4578
+ break;
4579
+ case "dart":
4580
+ await import("prismjs/components/prism-dart");
4581
+ break;
4582
+ case "elm":
4583
+ await import("prismjs/components/prism-elm");
4584
+ break;
4585
+ case "elixir":
4586
+ await import("prismjs/components/prism-elixir");
4587
+ break;
4588
+ case "clojure":
4589
+ await import("prismjs/components/prism-clojure");
4590
+ break;
4591
+ case "erlang":
4592
+ await import("prismjs/components/prism-erlang");
4593
+ break;
4594
+ case "fsharp":
4595
+ await import("prismjs/components/prism-fsharp");
4596
+ break;
4597
+ case "haskell":
4598
+ await import("prismjs/components/prism-haskell");
4599
+ break;
4600
+ case "sql":
4601
+ await import("prismjs/components/prism-sql");
4602
+ break;
4603
+ case "c":
4604
+ await import("prismjs/components/prism-c");
4605
+ break;
4606
+ case "cpp":
4607
+ await import("./cpp-EDJNJWGR.js");
4608
+ break;
4609
+ case "scss":
4610
+ await import("prismjs/components/prism-scss");
4611
+ break;
4612
+ case "less":
4613
+ await import("prismjs/components/prism-less");
4614
+ break;
4615
+ case "markup-templating":
4616
+ await import("prismjs/components/prism-markup-templating");
4617
+ break;
4618
+ case "php":
4619
+ await import("./php-TTFBGZ5Q.js");
4620
+ break;
4621
+ }
4622
+ }
4527
4623
  function createTextZoomController(target, cssVariable, ctx) {
4528
4624
  let zoom = getInitialZoom(ctx, 0.5, 3);
4529
4625
  const apply = () => {
@@ -10370,6 +10466,7 @@ async function renderPptx(panel, arrayBuffer) {
10370
10466
  container.className = "ofv-pptx-viewer";
10371
10467
  let insight;
10372
10468
  let zip;
10469
+ let placeholderFontCorrections = [];
10373
10470
  try {
10374
10471
  zip = await JSZip3.loadAsync(arrayBuffer);
10375
10472
  insight = await inspectPptxPresentation(zip);
@@ -10377,11 +10474,18 @@ async function renderPptx(panel, arrayBuffer) {
10377
10474
  } catch (error) {
10378
10475
  console.warn("PPTX structure insight extraction failed:", error);
10379
10476
  }
10477
+ if (zip) {
10478
+ try {
10479
+ placeholderFontCorrections = await inspectPptxPlaceholderFontCorrections(zip);
10480
+ } catch (error) {
10481
+ console.warn("PPTX placeholder font extraction failed:", error);
10482
+ }
10483
+ }
10380
10484
  panel.append(container);
10381
10485
  try {
10382
10486
  const { PptxViewer } = await import("@aiden0z/pptx-renderer");
10383
10487
  await withTimeout(PptxViewer.open(arrayBuffer, container), pptxRenderTimeoutMs());
10384
- normalizePptxLayout(container);
10488
+ normalizePptxLayout(container, placeholderFontCorrections);
10385
10489
  } catch (error) {
10386
10490
  container.replaceChildren();
10387
10491
  if (insight) {
@@ -10433,15 +10537,168 @@ function pptxRenderTimeoutMs() {
10433
10537
  const override = globalThis.__OFV_PPTX_RENDER_TIMEOUT_MS__;
10434
10538
  return typeof override === "number" && override > 0 ? override : DEFAULT_PPTX_RENDER_TIMEOUT_MS;
10435
10539
  }
10436
- function normalizePptxLayout(container) {
10540
+ function normalizePptxLayout(container, placeholderFontCorrections) {
10437
10541
  const slideCanvases = findPptxSlideCanvases(container);
10438
10542
  for (const slide of slideCanvases) {
10439
10543
  if (!hasInlineBackground(slide)) {
10440
10544
  slide.style.backgroundColor = "#FFFFFF";
10441
10545
  }
10442
10546
  }
10547
+ normalizePptxPlaceholderFonts(container, placeholderFontCorrections);
10443
10548
  normalizePptxMirroredText(container);
10444
10549
  }
10550
+ async function inspectPptxPlaceholderFontCorrections(zip) {
10551
+ const presentationXml = await zip.file("ppt/presentation.xml")?.async("text");
10552
+ const presentation = presentationXml ? parseOfficeXml(presentationXml) : void 0;
10553
+ const slideSize = presentation ? Array.from(presentation.getElementsByTagName("*")).find((element) => element.localName === "sldSz") : void 0;
10554
+ const slideWidth = Number(slideSize?.getAttribute("cx"));
10555
+ const slideHeight = Number(slideSize?.getAttribute("cy"));
10556
+ if (!(slideWidth > 0) || !(slideHeight > 0)) {
10557
+ return [];
10558
+ }
10559
+ const slideEntries = Object.values(zip.files).filter((entry) => !entry.dir && /^ppt\/slides\/slide\d+\.xml$/i.test(entry.name)).sort((a, b) => slideNumberFromPath(a.name) - slideNumberFromPath(b.name));
10560
+ const corrections = [];
10561
+ for (const [slideIndex, entry] of slideEntries.entries()) {
10562
+ const slideXml = await entry.async("text");
10563
+ const slide = parseOfficeXml(slideXml);
10564
+ if (!slide) {
10565
+ continue;
10566
+ }
10567
+ const relationships = await readPptxRelationships(zip, entry.name);
10568
+ const layoutTarget = resolvePptxRelationshipTarget(
10569
+ entry.name,
10570
+ relationships.find((relationship) => /\/slideLayout$/i.test(relationship.type))?.target
10571
+ );
10572
+ const layoutXml = layoutTarget ? await zip.file(layoutTarget)?.async("text") : void 0;
10573
+ const layout = layoutXml ? parseOfficeXml(layoutXml) : void 0;
10574
+ if (!layout) {
10575
+ continue;
10576
+ }
10577
+ const layoutFontSizes = readPptxLayoutPlaceholderFontSizes(layout);
10578
+ const shapes = Array.from(slide.getElementsByTagName("*")).filter((element) => element.localName === "sp");
10579
+ for (const shape of shapes) {
10580
+ const placeholder = findPptxDescendant(shape, "ph");
10581
+ const placeholderIndex = placeholder?.getAttribute("idx");
10582
+ const fontSizePt = placeholderIndex ? layoutFontSizes.get(placeholderIndex) : void 0;
10583
+ const textBody = findPptxDescendant(shape, "txBody");
10584
+ if (!textBody?.textContent?.trim() || !fontSizePt || hasExplicitPptxTextSize(textBody)) {
10585
+ continue;
10586
+ }
10587
+ const transform = findPptxDescendant(shape, "xfrm");
10588
+ const offset = transform ? findPptxChild(transform, "off") : void 0;
10589
+ const extent = transform ? findPptxChild(transform, "ext") : void 0;
10590
+ const left = Number(offset?.getAttribute("x"));
10591
+ const top = Number(offset?.getAttribute("y"));
10592
+ const width = Number(extent?.getAttribute("cx"));
10593
+ const height = Number(extent?.getAttribute("cy"));
10594
+ if (![left, top, width, height].every((value) => Number.isFinite(value)) || width <= 0 || height <= 0) {
10595
+ continue;
10596
+ }
10597
+ corrections.push({
10598
+ slideIndex,
10599
+ leftRatio: left / slideWidth,
10600
+ topRatio: top / slideHeight,
10601
+ widthRatio: width / slideWidth,
10602
+ heightRatio: height / slideHeight,
10603
+ fontSizePt
10604
+ });
10605
+ }
10606
+ }
10607
+ return corrections;
10608
+ }
10609
+ function readPptxLayoutPlaceholderFontSizes(layout) {
10610
+ const result = /* @__PURE__ */ new Map();
10611
+ const shapes = Array.from(layout.getElementsByTagName("*")).filter((element) => element.localName === "sp");
10612
+ for (const shape of shapes) {
10613
+ const placeholderIndex = findPptxDescendant(shape, "ph")?.getAttribute("idx");
10614
+ if (!placeholderIndex) {
10615
+ continue;
10616
+ }
10617
+ const textBody = findPptxDescendant(shape, "txBody");
10618
+ const defaultRunProperties = textBody ? Array.from(textBody.getElementsByTagName("*")).find(
10619
+ (element) => element.localName === "defRPr" && Number(element.getAttribute("sz")) > 0
10620
+ ) : void 0;
10621
+ const size = Number(defaultRunProperties?.getAttribute("sz"));
10622
+ if (size > 0) {
10623
+ result.set(placeholderIndex, size / 100);
10624
+ }
10625
+ }
10626
+ return result;
10627
+ }
10628
+ function hasExplicitPptxTextSize(textBody) {
10629
+ return Array.from(textBody.getElementsByTagName("*")).some(
10630
+ (element) => (element.localName === "rPr" || element.localName === "defRPr" || element.localName === "endParaRPr") && Number(element.getAttribute("sz")) > 0
10631
+ );
10632
+ }
10633
+ function findPptxDescendant(element, localName) {
10634
+ return Array.from(element.getElementsByTagName("*")).find((child) => child.localName === localName);
10635
+ }
10636
+ function findPptxChild(element, localName) {
10637
+ return Array.from(element.children).find((child) => child.localName === localName);
10638
+ }
10639
+ function normalizePptxPlaceholderFonts(container, corrections) {
10640
+ for (const correction of corrections) {
10641
+ const wrapper = container.querySelector(`div[data-slide-index="${correction.slideIndex}"]`);
10642
+ if (!wrapper) {
10643
+ continue;
10644
+ }
10645
+ const match = findPptxPlaceholderElement(wrapper, correction);
10646
+ if (!match) {
10647
+ continue;
10648
+ }
10649
+ const styledText = Array.from(match.querySelectorAll("[style]")).filter(
10650
+ (element) => parseFloat(element.style.fontSize) > 0
10651
+ );
10652
+ for (const element of styledText) {
10653
+ element.style.fontSize = `${correction.fontSizePt}pt`;
10654
+ }
10655
+ if (styledText.length > 0) {
10656
+ match.dataset.ofvPptxPlaceholderFont = String(correction.fontSizePt);
10657
+ }
10658
+ }
10659
+ }
10660
+ function findPptxPlaceholderElement(wrapper, correction) {
10661
+ let best;
10662
+ for (const canvas of findPptxSlideCanvases(wrapper)) {
10663
+ const canvasWidth = parseCssPixelValue(canvas.style.width);
10664
+ const canvasHeight = parseCssPixelValue(canvas.style.height);
10665
+ if (!(canvasWidth > 0) || !(canvasHeight > 0)) {
10666
+ continue;
10667
+ }
10668
+ const expected = {
10669
+ left: correction.leftRatio * canvasWidth,
10670
+ top: correction.topRatio * canvasHeight,
10671
+ width: correction.widthRatio * canvasWidth,
10672
+ height: correction.heightRatio * canvasHeight
10673
+ };
10674
+ const candidates = Array.from(canvas.querySelectorAll("div")).filter(
10675
+ (element) => element.style.position === "absolute" && Boolean(element.textContent?.trim())
10676
+ );
10677
+ for (const element of candidates) {
10678
+ const actual = {
10679
+ left: parseCssPixelValue(element.style.left),
10680
+ top: parseCssPixelValue(element.style.top),
10681
+ width: parseCssPixelValue(element.style.width),
10682
+ height: parseCssPixelValue(element.style.height)
10683
+ };
10684
+ const deltas = [
10685
+ Math.abs(actual.left - expected.left),
10686
+ Math.abs(actual.top - expected.top),
10687
+ Math.abs(actual.width - expected.width),
10688
+ Math.abs(actual.height - expected.height)
10689
+ ];
10690
+ const tolerance = Math.max(2, Math.min(canvasWidth, canvasHeight) * 5e-3);
10691
+ if (deltas.some((delta) => delta > tolerance)) {
10692
+ continue;
10693
+ }
10694
+ const score = deltas.reduce((sum, delta) => sum + delta, 0);
10695
+ if (!best || score < best.score) {
10696
+ best = { element, score };
10697
+ }
10698
+ }
10699
+ }
10700
+ return best?.element;
10701
+ }
10445
10702
  function hasInlineBackground(element) {
10446
10703
  return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
10447
10704
  }
@@ -12935,9 +13192,9 @@ function getIcon(name, dir) {
12935
13192
  }
12936
13193
 
12937
13194
  // src/plugins/email.ts
12938
- import DOMPurify3 from "dompurify";
12939
13195
  var emailExtensions = /* @__PURE__ */ new Set(["eml", "msg", "mbox"]);
12940
13196
  var emailMimeTypes = /* @__PURE__ */ new Set(["message/rfc822", "application/vnd.ms-outlook", "application/mbox"]);
13197
+ var domPurifyLoader;
12941
13198
  var emailMimeFormatMap = {
12942
13199
  "message/rfc822": "eml",
12943
13200
  "application/vnd.ms-outlook": "msg",
@@ -12950,6 +13207,8 @@ function emailPlugin() {
12950
13207
  return emailExtensions.has(file.extension) || emailMimeTypes.has(file.mimeType);
12951
13208
  },
12952
13209
  async render(ctx) {
13210
+ const DOMPurifyModule = await (domPurifyLoader ||= import("dompurify"));
13211
+ const DOMPurify3 = DOMPurifyModule.default;
12953
13212
  const panel = createPanel("ofv-email");
12954
13213
  ctx.viewport.append(panel);
12955
13214
  const url = createObjectUrl(ctx.file);
@@ -13083,7 +13342,7 @@ function emailPlugin() {
13083
13342
  }
13084
13343
  });
13085
13344
  html = nextHtml;
13086
- const sanitizedHtml = sanitizeEmailHtml(html);
13345
+ const sanitizedHtml = sanitizeEmailHtml(html, DOMPurify3);
13087
13346
  const iframe = document.createElement("iframe");
13088
13347
  iframe.className = "ofv-email-body-iframe";
13089
13348
  iframe.setAttribute("sandbox", "allow-same-origin allow-popups allow-popups-to-escape-sandbox");
@@ -13376,8 +13635,8 @@ function getMimeType(name) {
13376
13635
  };
13377
13636
  return ext ? map[ext] || "application/octet-stream" : "application/octet-stream";
13378
13637
  }
13379
- function sanitizeEmailHtml(html) {
13380
- return DOMPurify3.sanitize(html, {
13638
+ function sanitizeEmailHtml(html, purifier) {
13639
+ return purifier.sanitize(html, {
13381
13640
  USE_PROFILES: { html: true },
13382
13641
  ADD_ATTR: ["target"],
13383
13642
  ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|blob|cid):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i