@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/README.md CHANGED
@@ -24,6 +24,15 @@ PDF preview requires `pdfjs-dist`:
24
24
  npm install pdfjs-dist
25
25
  ```
26
26
 
27
+ ### Vite / Rollup dependency chunks
28
+
29
+ Text grammars, Markdown, and email parsers load asynchronously when their plugins are first used.
30
+ Prism language chunks are loaded in dependency order, so applications do not need to preload parent
31
+ grammars such as Java before Scala. In monorepos, `resolve.dedupe: ["prismjs"]` prevents duplicate
32
+ Prism runtimes. Keep `/prismjs/components/` out of catch-all vendor `manualChunks` rules so the
33
+ side-effectful language modules remain separate on-demand chunks and execute in dependency order.
34
+ `postal-mime` and `@kenjiuno/msgreader` may optionally share an `ofv-email` chunk.
35
+
27
36
  DWG geometry preview uses optional LibreDWG WASM. The package can be installed by applications that want the default built-in DWG linework path:
28
37
 
29
38
  ```bash
@@ -0,0 +1,4 @@
1
+ // src/plugins/prism-languages/cpp.ts
2
+ import "prismjs/components/prism-c";
3
+ import "prismjs/components/prism-cpp";
4
+ //# sourceMappingURL=cpp-EDJNJWGR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/prism-languages/cpp.ts"],"sourcesContent":["import \"prismjs/components/prism-c\";\nimport \"prismjs/components/prism-cpp\";\n"],"mappings":";AAAA,OAAO;AACP,OAAO;","names":[]}
package/dist/index.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,6 +30,62 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // src/plugins/prism-languages/tsx.ts
34
+ var tsx_exports = {};
35
+ var import_prism_jsx, import_prism_typescript, import_prism_tsx;
36
+ var init_tsx = __esm({
37
+ "src/plugins/prism-languages/tsx.ts"() {
38
+ "use strict";
39
+ import_prism_jsx = require("prismjs/components/prism-jsx");
40
+ import_prism_typescript = require("prismjs/components/prism-typescript");
41
+ import_prism_tsx = require("prismjs/components/prism-tsx");
42
+ }
43
+ });
44
+
45
+ // src/plugins/prism-languages/json5.ts
46
+ var json5_exports = {};
47
+ var import_prism_json, import_prism_json5;
48
+ var init_json5 = __esm({
49
+ "src/plugins/prism-languages/json5.ts"() {
50
+ "use strict";
51
+ import_prism_json = require("prismjs/components/prism-json");
52
+ import_prism_json5 = require("prismjs/components/prism-json5");
53
+ }
54
+ });
55
+
56
+ // src/plugins/prism-languages/scala.ts
57
+ var scala_exports = {};
58
+ var import_prism_java, import_prism_scala;
59
+ var init_scala = __esm({
60
+ "src/plugins/prism-languages/scala.ts"() {
61
+ "use strict";
62
+ import_prism_java = require("prismjs/components/prism-java");
63
+ import_prism_scala = require("prismjs/components/prism-scala");
64
+ }
65
+ });
66
+
67
+ // src/plugins/prism-languages/cpp.ts
68
+ var cpp_exports = {};
69
+ var import_prism_c, import_prism_cpp;
70
+ var init_cpp = __esm({
71
+ "src/plugins/prism-languages/cpp.ts"() {
72
+ "use strict";
73
+ import_prism_c = require("prismjs/components/prism-c");
74
+ import_prism_cpp = require("prismjs/components/prism-cpp");
75
+ }
76
+ });
77
+
78
+ // src/plugins/prism-languages/php.ts
79
+ var php_exports = {};
80
+ var import_prism_markup_templating, import_prism_php;
81
+ var init_php = __esm({
82
+ "src/plugins/prism-languages/php.ts"() {
83
+ "use strict";
84
+ import_prism_markup_templating = require("prismjs/components/prism-markup-templating");
85
+ import_prism_php = require("prismjs/components/prism-php");
86
+ }
87
+ });
88
+
30
89
  // src/index.ts
31
90
  var index_exports = {};
32
91
  __export(index_exports, {
@@ -4291,6 +4350,7 @@ var mimeLangMap = {
4291
4350
  };
4292
4351
  var MAX_HIGHLIGHT_CHARS = 18e4;
4293
4352
  var MAX_RENDER_CHARS = 6e5;
4353
+ var prismLanguageLoads = /* @__PURE__ */ new Map();
4294
4354
  function textPlugin() {
4295
4355
  return {
4296
4356
  name: "text",
@@ -4322,10 +4382,10 @@ function textPlugin() {
4322
4382
  ]);
4323
4383
  const parseMarkdown = markedModule.marked?.parse || markedModule.parse || markedModule.default?.parse;
4324
4384
  const Prism2 = PrismModule2.default || PrismModule2;
4325
- const DOMPurify4 = DOMPurifyModule.default || DOMPurifyModule;
4385
+ const DOMPurify3 = DOMPurifyModule.default || DOMPurifyModule;
4326
4386
  const container = document.createElement("div");
4327
4387
  container.className = "ofv-markdown-body";
4328
- container.innerHTML = DOMPurify4.sanitize(parseMarkdown(text), {
4388
+ container.innerHTML = DOMPurify3.sanitize(parseMarkdown(text), {
4329
4389
  USE_PROFILES: { html: true },
4330
4390
  ADD_ATTR: ["target"]
4331
4391
  });
@@ -4334,6 +4394,14 @@ function textPlugin() {
4334
4394
  try {
4335
4395
  const codeBlocks = container.querySelectorAll("pre code");
4336
4396
  if (codeBlocks.length > 0) {
4397
+ const languages = /* @__PURE__ */ new Set();
4398
+ codeBlocks.forEach((block) => {
4399
+ const language = getPrismLanguageFromElement(block) || getPrismLanguageFromElement(block.parentElement);
4400
+ if (language) {
4401
+ languages.add(language);
4402
+ }
4403
+ });
4404
+ await Promise.all([...languages].map((language) => loadPrismLanguage(language)));
4337
4405
  codeBlocks.forEach((block) => {
4338
4406
  const parent = block.parentElement;
4339
4407
  if (parent && !parent.className.includes("language-")) {
@@ -4362,97 +4430,7 @@ function textPlugin() {
4362
4430
  const Prism = PrismModule.default || PrismModule;
4363
4431
  if (lang !== "none") {
4364
4432
  try {
4365
- if (lang === "typescript" || lang === "tsx") {
4366
- await import("prismjs/components/prism-typescript");
4367
- } else if (lang === "python") {
4368
- await import("prismjs/components/prism-python");
4369
- } else if (lang === "json") {
4370
- await import("prismjs/components/prism-json");
4371
- } else if (lang === "json5") {
4372
- await import("prismjs/components/prism-json5");
4373
- } else if (lang === "yaml") {
4374
- await import("prismjs/components/prism-yaml");
4375
- } else if (lang === "toml") {
4376
- await import("prismjs/components/prism-toml");
4377
- } else if (lang === "ini") {
4378
- await import("prismjs/components/prism-ini");
4379
- } else if (lang === "properties") {
4380
- await import("prismjs/components/prism-properties");
4381
- } else if (lang === "editorconfig") {
4382
- await import("prismjs/components/prism-editorconfig");
4383
- } else if (lang === "ignore") {
4384
- await import("prismjs/components/prism-ignore");
4385
- } else if (lang === "protobuf") {
4386
- await import("prismjs/components/prism-protobuf");
4387
- } else if (lang === "hcl") {
4388
- await import("prismjs/components/prism-hcl");
4389
- } else if (lang === "latex") {
4390
- await import("prismjs/components/prism-latex");
4391
- } else if (lang === "dot") {
4392
- await import("prismjs/components/prism-dot");
4393
- } else if (lang === "http") {
4394
- await import("prismjs/components/prism-http");
4395
- } else if (lang === "bash") {
4396
- await import("prismjs/components/prism-bash");
4397
- } else if (lang === "powershell") {
4398
- await import("prismjs/components/prism-powershell");
4399
- } else if (lang === "batch") {
4400
- await import("prismjs/components/prism-batch");
4401
- } else if (lang === "docker") {
4402
- await import("prismjs/components/prism-docker");
4403
- } else if (lang === "makefile") {
4404
- await import("prismjs/components/prism-makefile");
4405
- } else if (lang === "ruby") {
4406
- await import("prismjs/components/prism-ruby");
4407
- } else if (lang === "nginx") {
4408
- await import("prismjs/components/prism-nginx");
4409
- } else if (lang === "groovy") {
4410
- await import("prismjs/components/prism-groovy");
4411
- } else if (lang === "graphql") {
4412
- await import("prismjs/components/prism-graphql");
4413
- } else if (lang === "csharp") {
4414
- await import("prismjs/components/prism-csharp");
4415
- } else if (lang === "rust") {
4416
- await import("prismjs/components/prism-rust");
4417
- } else if (lang === "go") {
4418
- await import("prismjs/components/prism-go");
4419
- } else if (lang === "ruby") {
4420
- await import("prismjs/components/prism-ruby");
4421
- } else if (lang === "swift") {
4422
- await import("prismjs/components/prism-swift");
4423
- } else if (lang === "kotlin") {
4424
- await import("prismjs/components/prism-kotlin");
4425
- } else if (lang === "scala") {
4426
- await import("prismjs/components/prism-scala");
4427
- } else if (lang === "lua") {
4428
- await import("prismjs/components/prism-lua");
4429
- } else if (lang === "r") {
4430
- await import("prismjs/components/prism-r");
4431
- } else if (lang === "dart") {
4432
- await import("prismjs/components/prism-dart");
4433
- } else if (lang === "elm") {
4434
- await import("prismjs/components/prism-elm");
4435
- } else if (lang === "elixir") {
4436
- await import("prismjs/components/prism-elixir");
4437
- } else if (lang === "clojure") {
4438
- await import("prismjs/components/prism-clojure");
4439
- } else if (lang === "erlang") {
4440
- await import("prismjs/components/prism-erlang");
4441
- } else if (lang === "fsharp") {
4442
- await import("prismjs/components/prism-fsharp");
4443
- } else if (lang === "haskell") {
4444
- await import("prismjs/components/prism-haskell");
4445
- } else if (lang === "sql") {
4446
- await import("prismjs/components/prism-sql");
4447
- } else if (lang === "cpp") {
4448
- await import("prismjs/components/prism-c");
4449
- await import("prismjs/components/prism-cpp");
4450
- } else if (lang === "java") {
4451
- await import("prismjs/components/prism-java");
4452
- } else if (lang === "php") {
4453
- await import("prismjs/components/prism-markup-templating");
4454
- await import("prismjs/components/prism-php");
4455
- }
4433
+ await loadPrismLanguage(lang);
4456
4434
  } catch (e) {
4457
4435
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4458
4436
  }
@@ -4577,6 +4555,183 @@ function textPlugin() {
4577
4555
  }
4578
4556
  };
4579
4557
  }
4558
+ function getPrismLanguageFromElement(element) {
4559
+ if (!element) {
4560
+ return void 0;
4561
+ }
4562
+ for (const className of element.classList) {
4563
+ if (className.startsWith("language-") && className.length > 9) {
4564
+ return className.slice(9).toLowerCase();
4565
+ }
4566
+ }
4567
+ return void 0;
4568
+ }
4569
+ async function loadPrismLanguage(language) {
4570
+ if (["none", "plain", "plaintext", "text", "markup", "css", "clike", "javascript"].includes(language)) {
4571
+ return;
4572
+ }
4573
+ const existing = prismLanguageLoads.get(language);
4574
+ if (existing) {
4575
+ return existing;
4576
+ }
4577
+ const loading = loadPrismLanguageComponent(language).catch((error) => {
4578
+ prismLanguageLoads.delete(language);
4579
+ throw error;
4580
+ });
4581
+ prismLanguageLoads.set(language, loading);
4582
+ return loading;
4583
+ }
4584
+ async function loadPrismLanguageComponent(language) {
4585
+ switch (language) {
4586
+ case "typescript":
4587
+ await import("prismjs/components/prism-typescript");
4588
+ break;
4589
+ case "jsx":
4590
+ await import("prismjs/components/prism-jsx");
4591
+ break;
4592
+ case "tsx":
4593
+ await Promise.resolve().then(() => (init_tsx(), tsx_exports));
4594
+ break;
4595
+ case "python":
4596
+ await import("prismjs/components/prism-python");
4597
+ break;
4598
+ case "json":
4599
+ await import("prismjs/components/prism-json");
4600
+ break;
4601
+ case "json5":
4602
+ await Promise.resolve().then(() => (init_json5(), json5_exports));
4603
+ break;
4604
+ case "yaml":
4605
+ await import("prismjs/components/prism-yaml");
4606
+ break;
4607
+ case "toml":
4608
+ await import("prismjs/components/prism-toml");
4609
+ break;
4610
+ case "ini":
4611
+ await import("prismjs/components/prism-ini");
4612
+ break;
4613
+ case "properties":
4614
+ await import("prismjs/components/prism-properties");
4615
+ break;
4616
+ case "editorconfig":
4617
+ await import("prismjs/components/prism-editorconfig");
4618
+ break;
4619
+ case "ignore":
4620
+ await import("prismjs/components/prism-ignore");
4621
+ break;
4622
+ case "protobuf":
4623
+ await import("prismjs/components/prism-protobuf");
4624
+ break;
4625
+ case "hcl":
4626
+ await import("prismjs/components/prism-hcl");
4627
+ break;
4628
+ case "latex":
4629
+ await import("prismjs/components/prism-latex");
4630
+ break;
4631
+ case "dot":
4632
+ await import("prismjs/components/prism-dot");
4633
+ break;
4634
+ case "http":
4635
+ await import("prismjs/components/prism-http");
4636
+ break;
4637
+ case "bash":
4638
+ await import("prismjs/components/prism-bash");
4639
+ break;
4640
+ case "powershell":
4641
+ await import("prismjs/components/prism-powershell");
4642
+ break;
4643
+ case "batch":
4644
+ await import("prismjs/components/prism-batch");
4645
+ break;
4646
+ case "docker":
4647
+ await import("prismjs/components/prism-docker");
4648
+ break;
4649
+ case "makefile":
4650
+ await import("prismjs/components/prism-makefile");
4651
+ break;
4652
+ case "ruby":
4653
+ await import("prismjs/components/prism-ruby");
4654
+ break;
4655
+ case "nginx":
4656
+ await import("prismjs/components/prism-nginx");
4657
+ break;
4658
+ case "groovy":
4659
+ await import("prismjs/components/prism-groovy");
4660
+ break;
4661
+ case "graphql":
4662
+ await import("prismjs/components/prism-graphql");
4663
+ break;
4664
+ case "csharp":
4665
+ await import("prismjs/components/prism-csharp");
4666
+ break;
4667
+ case "rust":
4668
+ await import("prismjs/components/prism-rust");
4669
+ break;
4670
+ case "go":
4671
+ await import("prismjs/components/prism-go");
4672
+ break;
4673
+ case "swift":
4674
+ await import("prismjs/components/prism-swift");
4675
+ break;
4676
+ case "kotlin":
4677
+ await import("prismjs/components/prism-kotlin");
4678
+ break;
4679
+ case "java":
4680
+ await import("prismjs/components/prism-java");
4681
+ break;
4682
+ case "scala":
4683
+ await Promise.resolve().then(() => (init_scala(), scala_exports));
4684
+ break;
4685
+ case "lua":
4686
+ await import("prismjs/components/prism-lua");
4687
+ break;
4688
+ case "r":
4689
+ await import("prismjs/components/prism-r");
4690
+ break;
4691
+ case "dart":
4692
+ await import("prismjs/components/prism-dart");
4693
+ break;
4694
+ case "elm":
4695
+ await import("prismjs/components/prism-elm");
4696
+ break;
4697
+ case "elixir":
4698
+ await import("prismjs/components/prism-elixir");
4699
+ break;
4700
+ case "clojure":
4701
+ await import("prismjs/components/prism-clojure");
4702
+ break;
4703
+ case "erlang":
4704
+ await import("prismjs/components/prism-erlang");
4705
+ break;
4706
+ case "fsharp":
4707
+ await import("prismjs/components/prism-fsharp");
4708
+ break;
4709
+ case "haskell":
4710
+ await import("prismjs/components/prism-haskell");
4711
+ break;
4712
+ case "sql":
4713
+ await import("prismjs/components/prism-sql");
4714
+ break;
4715
+ case "c":
4716
+ await import("prismjs/components/prism-c");
4717
+ break;
4718
+ case "cpp":
4719
+ await Promise.resolve().then(() => (init_cpp(), cpp_exports));
4720
+ break;
4721
+ case "scss":
4722
+ await import("prismjs/components/prism-scss");
4723
+ break;
4724
+ case "less":
4725
+ await import("prismjs/components/prism-less");
4726
+ break;
4727
+ case "markup-templating":
4728
+ await import("prismjs/components/prism-markup-templating");
4729
+ break;
4730
+ case "php":
4731
+ await Promise.resolve().then(() => (init_php(), php_exports));
4732
+ break;
4733
+ }
4734
+ }
4580
4735
  function createTextZoomController(target, cssVariable, ctx) {
4581
4736
  let zoom = getInitialZoom(ctx, 0.5, 3);
4582
4737
  const apply = () => {
@@ -10423,6 +10578,7 @@ async function renderPptx(panel, arrayBuffer) {
10423
10578
  container.className = "ofv-pptx-viewer";
10424
10579
  let insight;
10425
10580
  let zip;
10581
+ let placeholderFontCorrections = [];
10426
10582
  try {
10427
10583
  zip = await import_jszip3.default.loadAsync(arrayBuffer);
10428
10584
  insight = await inspectPptxPresentation(zip);
@@ -10430,11 +10586,18 @@ async function renderPptx(panel, arrayBuffer) {
10430
10586
  } catch (error) {
10431
10587
  console.warn("PPTX structure insight extraction failed:", error);
10432
10588
  }
10589
+ if (zip) {
10590
+ try {
10591
+ placeholderFontCorrections = await inspectPptxPlaceholderFontCorrections(zip);
10592
+ } catch (error) {
10593
+ console.warn("PPTX placeholder font extraction failed:", error);
10594
+ }
10595
+ }
10433
10596
  panel.append(container);
10434
10597
  try {
10435
10598
  const { PptxViewer } = await import("@aiden0z/pptx-renderer");
10436
10599
  await withTimeout(PptxViewer.open(arrayBuffer, container), pptxRenderTimeoutMs());
10437
- normalizePptxLayout(container);
10600
+ normalizePptxLayout(container, placeholderFontCorrections);
10438
10601
  } catch (error) {
10439
10602
  container.replaceChildren();
10440
10603
  if (insight) {
@@ -10486,15 +10649,168 @@ function pptxRenderTimeoutMs() {
10486
10649
  const override = globalThis.__OFV_PPTX_RENDER_TIMEOUT_MS__;
10487
10650
  return typeof override === "number" && override > 0 ? override : DEFAULT_PPTX_RENDER_TIMEOUT_MS;
10488
10651
  }
10489
- function normalizePptxLayout(container) {
10652
+ function normalizePptxLayout(container, placeholderFontCorrections) {
10490
10653
  const slideCanvases = findPptxSlideCanvases(container);
10491
10654
  for (const slide of slideCanvases) {
10492
10655
  if (!hasInlineBackground(slide)) {
10493
10656
  slide.style.backgroundColor = "#FFFFFF";
10494
10657
  }
10495
10658
  }
10659
+ normalizePptxPlaceholderFonts(container, placeholderFontCorrections);
10496
10660
  normalizePptxMirroredText(container);
10497
10661
  }
10662
+ async function inspectPptxPlaceholderFontCorrections(zip) {
10663
+ const presentationXml = await zip.file("ppt/presentation.xml")?.async("text");
10664
+ const presentation = presentationXml ? parseOfficeXml(presentationXml) : void 0;
10665
+ const slideSize = presentation ? Array.from(presentation.getElementsByTagName("*")).find((element) => element.localName === "sldSz") : void 0;
10666
+ const slideWidth = Number(slideSize?.getAttribute("cx"));
10667
+ const slideHeight = Number(slideSize?.getAttribute("cy"));
10668
+ if (!(slideWidth > 0) || !(slideHeight > 0)) {
10669
+ return [];
10670
+ }
10671
+ 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));
10672
+ const corrections = [];
10673
+ for (const [slideIndex, entry] of slideEntries.entries()) {
10674
+ const slideXml = await entry.async("text");
10675
+ const slide = parseOfficeXml(slideXml);
10676
+ if (!slide) {
10677
+ continue;
10678
+ }
10679
+ const relationships = await readPptxRelationships(zip, entry.name);
10680
+ const layoutTarget = resolvePptxRelationshipTarget(
10681
+ entry.name,
10682
+ relationships.find((relationship) => /\/slideLayout$/i.test(relationship.type))?.target
10683
+ );
10684
+ const layoutXml = layoutTarget ? await zip.file(layoutTarget)?.async("text") : void 0;
10685
+ const layout = layoutXml ? parseOfficeXml(layoutXml) : void 0;
10686
+ if (!layout) {
10687
+ continue;
10688
+ }
10689
+ const layoutFontSizes = readPptxLayoutPlaceholderFontSizes(layout);
10690
+ const shapes = Array.from(slide.getElementsByTagName("*")).filter((element) => element.localName === "sp");
10691
+ for (const shape of shapes) {
10692
+ const placeholder = findPptxDescendant(shape, "ph");
10693
+ const placeholderIndex = placeholder?.getAttribute("idx");
10694
+ const fontSizePt = placeholderIndex ? layoutFontSizes.get(placeholderIndex) : void 0;
10695
+ const textBody = findPptxDescendant(shape, "txBody");
10696
+ if (!textBody?.textContent?.trim() || !fontSizePt || hasExplicitPptxTextSize(textBody)) {
10697
+ continue;
10698
+ }
10699
+ const transform = findPptxDescendant(shape, "xfrm");
10700
+ const offset = transform ? findPptxChild(transform, "off") : void 0;
10701
+ const extent = transform ? findPptxChild(transform, "ext") : void 0;
10702
+ const left = Number(offset?.getAttribute("x"));
10703
+ const top = Number(offset?.getAttribute("y"));
10704
+ const width = Number(extent?.getAttribute("cx"));
10705
+ const height = Number(extent?.getAttribute("cy"));
10706
+ if (![left, top, width, height].every((value) => Number.isFinite(value)) || width <= 0 || height <= 0) {
10707
+ continue;
10708
+ }
10709
+ corrections.push({
10710
+ slideIndex,
10711
+ leftRatio: left / slideWidth,
10712
+ topRatio: top / slideHeight,
10713
+ widthRatio: width / slideWidth,
10714
+ heightRatio: height / slideHeight,
10715
+ fontSizePt
10716
+ });
10717
+ }
10718
+ }
10719
+ return corrections;
10720
+ }
10721
+ function readPptxLayoutPlaceholderFontSizes(layout) {
10722
+ const result = /* @__PURE__ */ new Map();
10723
+ const shapes = Array.from(layout.getElementsByTagName("*")).filter((element) => element.localName === "sp");
10724
+ for (const shape of shapes) {
10725
+ const placeholderIndex = findPptxDescendant(shape, "ph")?.getAttribute("idx");
10726
+ if (!placeholderIndex) {
10727
+ continue;
10728
+ }
10729
+ const textBody = findPptxDescendant(shape, "txBody");
10730
+ const defaultRunProperties = textBody ? Array.from(textBody.getElementsByTagName("*")).find(
10731
+ (element) => element.localName === "defRPr" && Number(element.getAttribute("sz")) > 0
10732
+ ) : void 0;
10733
+ const size = Number(defaultRunProperties?.getAttribute("sz"));
10734
+ if (size > 0) {
10735
+ result.set(placeholderIndex, size / 100);
10736
+ }
10737
+ }
10738
+ return result;
10739
+ }
10740
+ function hasExplicitPptxTextSize(textBody) {
10741
+ return Array.from(textBody.getElementsByTagName("*")).some(
10742
+ (element) => (element.localName === "rPr" || element.localName === "defRPr" || element.localName === "endParaRPr") && Number(element.getAttribute("sz")) > 0
10743
+ );
10744
+ }
10745
+ function findPptxDescendant(element, localName) {
10746
+ return Array.from(element.getElementsByTagName("*")).find((child) => child.localName === localName);
10747
+ }
10748
+ function findPptxChild(element, localName) {
10749
+ return Array.from(element.children).find((child) => child.localName === localName);
10750
+ }
10751
+ function normalizePptxPlaceholderFonts(container, corrections) {
10752
+ for (const correction of corrections) {
10753
+ const wrapper = container.querySelector(`div[data-slide-index="${correction.slideIndex}"]`);
10754
+ if (!wrapper) {
10755
+ continue;
10756
+ }
10757
+ const match = findPptxPlaceholderElement(wrapper, correction);
10758
+ if (!match) {
10759
+ continue;
10760
+ }
10761
+ const styledText = Array.from(match.querySelectorAll("[style]")).filter(
10762
+ (element) => parseFloat(element.style.fontSize) > 0
10763
+ );
10764
+ for (const element of styledText) {
10765
+ element.style.fontSize = `${correction.fontSizePt}pt`;
10766
+ }
10767
+ if (styledText.length > 0) {
10768
+ match.dataset.ofvPptxPlaceholderFont = String(correction.fontSizePt);
10769
+ }
10770
+ }
10771
+ }
10772
+ function findPptxPlaceholderElement(wrapper, correction) {
10773
+ let best;
10774
+ for (const canvas of findPptxSlideCanvases(wrapper)) {
10775
+ const canvasWidth = parseCssPixelValue(canvas.style.width);
10776
+ const canvasHeight = parseCssPixelValue(canvas.style.height);
10777
+ if (!(canvasWidth > 0) || !(canvasHeight > 0)) {
10778
+ continue;
10779
+ }
10780
+ const expected = {
10781
+ left: correction.leftRatio * canvasWidth,
10782
+ top: correction.topRatio * canvasHeight,
10783
+ width: correction.widthRatio * canvasWidth,
10784
+ height: correction.heightRatio * canvasHeight
10785
+ };
10786
+ const candidates = Array.from(canvas.querySelectorAll("div")).filter(
10787
+ (element) => element.style.position === "absolute" && Boolean(element.textContent?.trim())
10788
+ );
10789
+ for (const element of candidates) {
10790
+ const actual = {
10791
+ left: parseCssPixelValue(element.style.left),
10792
+ top: parseCssPixelValue(element.style.top),
10793
+ width: parseCssPixelValue(element.style.width),
10794
+ height: parseCssPixelValue(element.style.height)
10795
+ };
10796
+ const deltas = [
10797
+ Math.abs(actual.left - expected.left),
10798
+ Math.abs(actual.top - expected.top),
10799
+ Math.abs(actual.width - expected.width),
10800
+ Math.abs(actual.height - expected.height)
10801
+ ];
10802
+ const tolerance = Math.max(2, Math.min(canvasWidth, canvasHeight) * 5e-3);
10803
+ if (deltas.some((delta) => delta > tolerance)) {
10804
+ continue;
10805
+ }
10806
+ const score = deltas.reduce((sum, delta) => sum + delta, 0);
10807
+ if (!best || score < best.score) {
10808
+ best = { element, score };
10809
+ }
10810
+ }
10811
+ }
10812
+ return best?.element;
10813
+ }
10498
10814
  function hasInlineBackground(element) {
10499
10815
  return Boolean(element.style.background || element.style.backgroundColor || element.style.backgroundImage);
10500
10816
  }
@@ -12988,9 +13304,9 @@ function getIcon(name, dir) {
12988
13304
  }
12989
13305
 
12990
13306
  // src/plugins/email.ts
12991
- var import_dompurify3 = __toESM(require("dompurify"), 1);
12992
13307
  var emailExtensions = /* @__PURE__ */ new Set(["eml", "msg", "mbox"]);
12993
13308
  var emailMimeTypes = /* @__PURE__ */ new Set(["message/rfc822", "application/vnd.ms-outlook", "application/mbox"]);
13309
+ var domPurifyLoader;
12994
13310
  var emailMimeFormatMap = {
12995
13311
  "message/rfc822": "eml",
12996
13312
  "application/vnd.ms-outlook": "msg",
@@ -13003,6 +13319,8 @@ function emailPlugin() {
13003
13319
  return emailExtensions.has(file.extension) || emailMimeTypes.has(file.mimeType);
13004
13320
  },
13005
13321
  async render(ctx) {
13322
+ const DOMPurifyModule = await (domPurifyLoader ||= import("dompurify"));
13323
+ const DOMPurify3 = DOMPurifyModule.default;
13006
13324
  const panel = createPanel("ofv-email");
13007
13325
  ctx.viewport.append(panel);
13008
13326
  const url = createObjectUrl(ctx.file);
@@ -13136,7 +13454,7 @@ function emailPlugin() {
13136
13454
  }
13137
13455
  });
13138
13456
  html = nextHtml;
13139
- const sanitizedHtml = sanitizeEmailHtml(html);
13457
+ const sanitizedHtml = sanitizeEmailHtml(html, DOMPurify3);
13140
13458
  const iframe = document.createElement("iframe");
13141
13459
  iframe.className = "ofv-email-body-iframe";
13142
13460
  iframe.setAttribute("sandbox", "allow-same-origin allow-popups allow-popups-to-escape-sandbox");
@@ -13429,8 +13747,8 @@ function getMimeType(name) {
13429
13747
  };
13430
13748
  return ext ? map[ext] || "application/octet-stream" : "application/octet-stream";
13431
13749
  }
13432
- function sanitizeEmailHtml(html) {
13433
- return import_dompurify3.default.sanitize(html, {
13750
+ function sanitizeEmailHtml(html, purifier) {
13751
+ return purifier.sanitize(html, {
13434
13752
  USE_PROFILES: { html: true },
13435
13753
  ADD_ATTR: ["target"],
13436
13754
  ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|blob|cid):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i