@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 +9 -0
- package/dist/cpp-EDJNJWGR.js +4 -0
- package/dist/cpp-EDJNJWGR.js.map +1 -0
- package/dist/index.cjs +417 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +358 -99
- package/dist/index.js.map +1 -1
- package/dist/json5-EAGAEIPM.js +4 -0
- package/dist/json5-EAGAEIPM.js.map +1 -0
- package/dist/php-TTFBGZ5Q.js +4 -0
- package/dist/php-TTFBGZ5Q.js.map +1 -0
- package/dist/scala-V5QQ35QA.js +4 -0
- package/dist/scala-V5QQ35QA.js.map +1 -0
- package/dist/tsx-A26VGWUK.js +5 -0
- package/dist/tsx-A26VGWUK.js.map +1 -0
- package/package.json +1 -1
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
|
|
4273
|
+
const DOMPurify3 = DOMPurifyModule.default || DOMPurifyModule;
|
|
4273
4274
|
const container = document.createElement("div");
|
|
4274
4275
|
container.className = "ofv-markdown-body";
|
|
4275
|
-
container.innerHTML =
|
|
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
|
-
|
|
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
|
|
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
|