@open-file-viewer/core 0.1.22 → 0.1.24

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
@@ -602,7 +602,36 @@ var defaultMessages = {
602
602
  officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
603
603
  officeUnsupportedSupportedFormats: "\u5F53\u524D\u7248\u672C\u4F18\u5148\u652F\u6301 docx\u3001rtf\u3001odt/fodt\u3001xlsx/xls/csv/ods\u3001pptx/ppsx\u3001odp/fodp \u7684\u57FA\u7840\u5185\u5BB9\u9884\u89C8\u3002",
604
604
  officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
605
- officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
605
+ officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002",
606
+ officeConvertedTitle: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
607
+ officeConvertedPdfFailed: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
608
+ pdfEncryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
609
+ pdfEncryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
610
+ pdfPreviewFailedTitle: "PDF \u9884\u89C8\u5931\u8D25",
611
+ pdfCorruptedMessage: "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002",
612
+ pdfCannotLoadMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002",
613
+ pdfDownload: "\u4E0B\u8F7D PDF",
614
+ pdfPageLoading: "\u9875\u9762 {page} \u52A0\u8F7D\u4E2D...",
615
+ pdfPageEmpty: "\u8BE5\u9875\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u663E\u793A\u7684 PDF \u517C\u5BB9\u5185\u5BB9\u3002\u82E5\u8FD9\u662F Illustrator/AI \u6587\u4EF6\uFF0C\u53EF\u80FD\u53EA\u5305\u542B\u79C1\u6709\u7F16\u8F91\u6570\u636E\uFF0C\u5EFA\u8BAE\u5BFC\u51FA\u4E3A PDF/SVG/PNG \u540E\u9884\u89C8\u3002",
616
+ pdfPageRenderFailed: "\u65E0\u6CD5\u6E32\u67D3\u8BE5\u9875\u9762\u3002\u8BE5\u9875\u53EF\u80FD\u5305\u542B\u6D4F\u89C8\u5668 PDF \u5F15\u64CE\u6682\u4E0D\u652F\u6301\u7684\u56FE\u5F62\u3001\u5B57\u4F53\u6216\u538B\u7F29\u7279\u6027\u3002",
617
+ pdfPreviousPage: "\u4E0A\u4E00\u9875",
618
+ pdfNextPage: "\u4E0B\u4E00\u9875",
619
+ pdfPageInput: "\u5F53\u524D\u9875\u7801",
620
+ pdfPagePosition: "/ {total}",
621
+ pdfPageLabel: "\u7B2C {page} \u9875",
622
+ pdfSummaryPages: "\u9875\u6570",
623
+ pdfSummaryPageSizes: "\u9875\u9762\u5C3A\u5BF8",
624
+ pdfSummaryFit: "\u9002\u914D",
625
+ pdfSummaryActualSize: "\u539F\u59CB\u5927\u5C0F",
626
+ pdfSummaryFitWidth: "\u9002\u5408\u5BBD\u5EA6",
627
+ pdfSummaryZoom: "\u7F29\u653E",
628
+ imagePreviewFailedTitle: "\u56FE\u7247\u9884\u89C8\u5931\u8D25",
629
+ imagePreviewFailedMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u76F4\u63A5\u663E\u793A\u8BE5\u56FE\u7247\uFF0C\u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u7F16\u7801\u6682\u4E0D\u53D7\u652F\u6301\u3002",
630
+ imageDownload: "\u4E0B\u8F7D\u56FE\u7247",
631
+ imageZoomOut: "\u7F29\u5C0F",
632
+ imageZoomIn: "\u653E\u5927",
633
+ imageRotate: "\u65CB\u8F6C\u56FE\u7247",
634
+ imageReset: "\u91CD\u7F6E\u56FE\u7247\u89C6\u56FE"
606
635
  },
607
636
  "en-US": {
608
637
  loading: "Loading preview...",
@@ -651,7 +680,36 @@ var defaultMessages = {
651
680
  officeUnsupportedIntro: "is handled by the Office plugin. {message}",
652
681
  officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
653
682
  officeErrorWithMessage: "Parser returned: {message}",
654
- officeErrorWithoutMessage: "Parser did not return a specific error."
683
+ officeErrorWithoutMessage: "Parser did not return a specific error.",
684
+ officeConvertedTitle: "High-fidelity Office conversion preview",
685
+ officeConvertedPdfFailed: "The converted Office PDF could not be previewed",
686
+ pdfEncryptedTitle: "This PDF is encrypted and cannot be previewed online",
687
+ pdfEncryptedMessage: "Download and open it with the password, or upload a decrypted PDF file.",
688
+ pdfPreviewFailedTitle: "PDF preview failed",
689
+ pdfCorruptedMessage: "The PDF may be corrupted or use an invalid format.",
690
+ pdfCannotLoadMessage: "This browser could not load the PDF.",
691
+ pdfDownload: "Download PDF",
692
+ pdfPageLoading: "Loading page {page}...",
693
+ pdfPageEmpty: "No displayable PDF-compatible content was detected on this page. If this is an Illustrator/AI file, export it as PDF, SVG, or PNG before previewing.",
694
+ pdfPageRenderFailed: "This page could not be rendered. It may contain graphics, fonts, or compression features that the browser PDF engine does not support.",
695
+ pdfPreviousPage: "Previous page",
696
+ pdfNextPage: "Next page",
697
+ pdfPageInput: "Current page",
698
+ pdfPagePosition: "/ {total}",
699
+ pdfPageLabel: "Page {page}",
700
+ pdfSummaryPages: "Pages",
701
+ pdfSummaryPageSizes: "Page sizes",
702
+ pdfSummaryFit: "Fit",
703
+ pdfSummaryActualSize: "Actual size",
704
+ pdfSummaryFitWidth: "Fit width",
705
+ pdfSummaryZoom: "Zoom",
706
+ imagePreviewFailedTitle: "Image preview failed",
707
+ imagePreviewFailedMessage: "This browser cannot display the image. The file may be corrupted or use an unsupported encoding.",
708
+ imageDownload: "Download image",
709
+ imageZoomOut: "Zoom out",
710
+ imageZoomIn: "Zoom in",
711
+ imageRotate: "Rotate image",
712
+ imageReset: "Reset image view"
655
713
  }
656
714
  };
657
715
  function resolveMessages(options) {
@@ -2162,7 +2220,7 @@ function imagePlugin() {
2162
2220
  infoBar.hidden = false;
2163
2221
  infoBar.removeAttribute("aria-hidden");
2164
2222
  infoBar.style.removeProperty("display");
2165
- stage.replaceChildren(createImageFallback(ctx.file.name, url));
2223
+ stage.replaceChildren(createImageFallback(ctx.file.name, url, ctx.options.messages));
2166
2224
  ctx.toolbar?.refreshCommandSupport();
2167
2225
  };
2168
2226
  const setScale = (nextScale) => {
@@ -2187,13 +2245,13 @@ function imagePlugin() {
2187
2245
  return () => button.removeEventListener("click", action);
2188
2246
  };
2189
2247
  const disposers = showInlineControls ? [
2190
- addButton("-", "Zoom out", () => setScale(scale - 0.25)),
2191
- addButton("+", "Zoom in", () => setScale(scale + 0.25)),
2192
- addButton("Rotate", "Rotate image", () => {
2248
+ addButton("-", ctx.options.messages.imageZoomOut, () => setScale(scale - 0.25)),
2249
+ addButton("+", ctx.options.messages.imageZoomIn, () => setScale(scale + 0.25)),
2250
+ addButton(ctx.options.messages.imageRotate, ctx.options.messages.imageRotate, () => {
2193
2251
  rotation += 90;
2194
2252
  updateTransform();
2195
2253
  }),
2196
- addButton("Reset", "Reset image view", reset)
2254
+ addButton(ctx.options.messages.imageReset, ctx.options.messages.imageReset, reset)
2197
2255
  ] : [];
2198
2256
  if (showInlineControls) {
2199
2257
  controls.append(zoomLabel);
@@ -2408,17 +2466,17 @@ function getTiffDimensions(ifd) {
2408
2466
  height: Number(ifd.height || ifd.t257 || 0)
2409
2467
  };
2410
2468
  }
2411
- function createImageFallback(fileName, url) {
2469
+ function createImageFallback(fileName, url, messages) {
2412
2470
  const fallback = document.createElement("div");
2413
2471
  fallback.className = "ofv-fallback";
2414
2472
  const title = document.createElement("strong");
2415
- title.textContent = "\u56FE\u7247\u9884\u89C8\u5931\u8D25";
2473
+ title.textContent = messages.imagePreviewFailedTitle;
2416
2474
  const meta = document.createElement("span");
2417
- meta.textContent = "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u76F4\u63A5\u663E\u793A\u8BE5\u56FE\u7247\uFF0C\u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u7F16\u7801\u6682\u4E0D\u53D7\u652F\u6301\u3002";
2475
+ meta.textContent = messages.imagePreviewFailedMessage;
2418
2476
  const download = document.createElement("a");
2419
2477
  download.href = url;
2420
2478
  download.download = fileName;
2421
- download.textContent = "\u4E0B\u8F7D\u56FE\u7247";
2479
+ download.textContent = messages.imageDownload;
2422
2480
  fallback.append(title, meta, download);
2423
2481
  return fallback;
2424
2482
  }
@@ -4180,6 +4238,7 @@ var mimeLangMap = {
4180
4238
  };
4181
4239
  var MAX_HIGHLIGHT_CHARS = 18e4;
4182
4240
  var MAX_RENDER_CHARS = 6e5;
4241
+ var prismLanguageLoads = /* @__PURE__ */ new Map();
4183
4242
  function textPlugin() {
4184
4243
  return {
4185
4244
  name: "text",
@@ -4211,10 +4270,10 @@ function textPlugin() {
4211
4270
  ]);
4212
4271
  const parseMarkdown = markedModule.marked?.parse || markedModule.parse || markedModule.default?.parse;
4213
4272
  const Prism2 = PrismModule2.default || PrismModule2;
4214
- const DOMPurify4 = DOMPurifyModule.default || DOMPurifyModule;
4273
+ const DOMPurify3 = DOMPurifyModule.default || DOMPurifyModule;
4215
4274
  const container = document.createElement("div");
4216
4275
  container.className = "ofv-markdown-body";
4217
- container.innerHTML = DOMPurify4.sanitize(parseMarkdown(text), {
4276
+ container.innerHTML = DOMPurify3.sanitize(parseMarkdown(text), {
4218
4277
  USE_PROFILES: { html: true },
4219
4278
  ADD_ATTR: ["target"]
4220
4279
  });
@@ -4223,6 +4282,14 @@ function textPlugin() {
4223
4282
  try {
4224
4283
  const codeBlocks = container.querySelectorAll("pre code");
4225
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)));
4226
4293
  codeBlocks.forEach((block) => {
4227
4294
  const parent = block.parentElement;
4228
4295
  if (parent && !parent.className.includes("language-")) {
@@ -4251,97 +4318,7 @@ function textPlugin() {
4251
4318
  const Prism = PrismModule.default || PrismModule;
4252
4319
  if (lang !== "none") {
4253
4320
  try {
4254
- if (lang === "typescript" || lang === "tsx") {
4255
- await import("prismjs/components/prism-typescript");
4256
- } else if (lang === "python") {
4257
- await import("prismjs/components/prism-python");
4258
- } else if (lang === "json") {
4259
- await import("prismjs/components/prism-json");
4260
- } else if (lang === "json5") {
4261
- await import("prismjs/components/prism-json5");
4262
- } else if (lang === "yaml") {
4263
- await import("prismjs/components/prism-yaml");
4264
- } else if (lang === "toml") {
4265
- await import("prismjs/components/prism-toml");
4266
- } else if (lang === "ini") {
4267
- await import("prismjs/components/prism-ini");
4268
- } else if (lang === "properties") {
4269
- await import("prismjs/components/prism-properties");
4270
- } else if (lang === "editorconfig") {
4271
- await import("prismjs/components/prism-editorconfig");
4272
- } else if (lang === "ignore") {
4273
- await import("prismjs/components/prism-ignore");
4274
- } else if (lang === "protobuf") {
4275
- await import("prismjs/components/prism-protobuf");
4276
- } else if (lang === "hcl") {
4277
- await import("prismjs/components/prism-hcl");
4278
- } else if (lang === "latex") {
4279
- await import("prismjs/components/prism-latex");
4280
- } else if (lang === "dot") {
4281
- await import("prismjs/components/prism-dot");
4282
- } else if (lang === "http") {
4283
- await import("prismjs/components/prism-http");
4284
- } else if (lang === "bash") {
4285
- await import("prismjs/components/prism-bash");
4286
- } else if (lang === "powershell") {
4287
- await import("prismjs/components/prism-powershell");
4288
- } else if (lang === "batch") {
4289
- await import("prismjs/components/prism-batch");
4290
- } else if (lang === "docker") {
4291
- await import("prismjs/components/prism-docker");
4292
- } else if (lang === "makefile") {
4293
- await import("prismjs/components/prism-makefile");
4294
- } else if (lang === "ruby") {
4295
- await import("prismjs/components/prism-ruby");
4296
- } else if (lang === "nginx") {
4297
- await import("prismjs/components/prism-nginx");
4298
- } else if (lang === "groovy") {
4299
- await import("prismjs/components/prism-groovy");
4300
- } else if (lang === "graphql") {
4301
- await import("prismjs/components/prism-graphql");
4302
- } else if (lang === "csharp") {
4303
- await import("prismjs/components/prism-csharp");
4304
- } else if (lang === "rust") {
4305
- await import("prismjs/components/prism-rust");
4306
- } else if (lang === "go") {
4307
- await import("prismjs/components/prism-go");
4308
- } else if (lang === "ruby") {
4309
- await import("prismjs/components/prism-ruby");
4310
- } else if (lang === "swift") {
4311
- await import("prismjs/components/prism-swift");
4312
- } else if (lang === "kotlin") {
4313
- await import("prismjs/components/prism-kotlin");
4314
- } else if (lang === "scala") {
4315
- await import("prismjs/components/prism-scala");
4316
- } else if (lang === "lua") {
4317
- await import("prismjs/components/prism-lua");
4318
- } else if (lang === "r") {
4319
- await import("prismjs/components/prism-r");
4320
- } else if (lang === "dart") {
4321
- await import("prismjs/components/prism-dart");
4322
- } else if (lang === "elm") {
4323
- await import("prismjs/components/prism-elm");
4324
- } else if (lang === "elixir") {
4325
- await import("prismjs/components/prism-elixir");
4326
- } else if (lang === "clojure") {
4327
- await import("prismjs/components/prism-clojure");
4328
- } else if (lang === "erlang") {
4329
- await import("prismjs/components/prism-erlang");
4330
- } else if (lang === "fsharp") {
4331
- await import("prismjs/components/prism-fsharp");
4332
- } else if (lang === "haskell") {
4333
- await import("prismjs/components/prism-haskell");
4334
- } else if (lang === "sql") {
4335
- await import("prismjs/components/prism-sql");
4336
- } else if (lang === "cpp") {
4337
- await import("prismjs/components/prism-c");
4338
- await import("prismjs/components/prism-cpp");
4339
- } else if (lang === "java") {
4340
- await import("prismjs/components/prism-java");
4341
- } else if (lang === "php") {
4342
- await import("prismjs/components/prism-markup-templating");
4343
- await import("prismjs/components/prism-php");
4344
- }
4321
+ await loadPrismLanguage(lang);
4345
4322
  } catch (e) {
4346
4323
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4347
4324
  }
@@ -4466,6 +4443,183 @@ function textPlugin() {
4466
4443
  }
4467
4444
  };
4468
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
+ }
4469
4623
  function createTextZoomController(target, cssVariable, ctx) {
4470
4624
  let zoom = getInitialZoom(ctx, 0.5, 3);
4471
4625
  const apply = () => {
@@ -4779,17 +4933,20 @@ function pdfPlugin(options = {}) {
4779
4933
  fit: ctx.options.fit,
4780
4934
  zoom: ctx.options.zoom,
4781
4935
  toolbar: ctx.toolbar,
4782
- encryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
4783
- encryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
4784
- encryptedAction: "\u4E0B\u8F7D PDF",
4936
+ messages: ctx.options.messages,
4785
4937
  revokeUrlOnDestroy: true
4786
4938
  });
4787
4939
  }
4788
4940
  };
4789
4941
  }
4790
4942
  async function renderPdfDocumentPreview(options) {
4943
+ const useLegacyCompatibility = shouldUseLegacyPdfCompatibility(options.compatibilityMode);
4944
+ if (useLegacyCompatibility) {
4945
+ installPromiseWithResolversPolyfill();
4946
+ }
4791
4947
  const pdf = options.pdfjs || await import("pdfjs-dist");
4792
- configurePdfWorker(pdf, options.workerSrc);
4948
+ const messages = { ...defaultMessages["en-US"], ...options.messages };
4949
+ configurePdfWorker(pdf, options.workerSrc, useLegacyCompatibility);
4793
4950
  const viewer = document.createElement("div");
4794
4951
  viewer.className = "ofv-pdf-viewer";
4795
4952
  if (options.title) {
@@ -4818,10 +4975,10 @@ async function renderPdfDocumentPreview(options) {
4818
4975
  url: options.fileUrl
4819
4976
  };
4820
4977
  const fallback = isEncryptedError(error) ? createEncryptedFallback(fileLike, options.fileUrl, {
4821
- title: options.encryptedTitle || "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
4822
- message: options.encryptedMessage || "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
4823
- action: options.encryptedAction || "\u4E0B\u8F7D PDF"
4824
- }) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error), options.fallbackTitle);
4978
+ title: options.encryptedTitle || messages.pdfEncryptedTitle,
4979
+ message: options.encryptedMessage || messages.pdfEncryptedMessage,
4980
+ action: options.encryptedAction || messages.pdfDownload
4981
+ }) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error, messages), messages, options.fallbackTitle);
4825
4982
  if (!fallback.classList.contains("ofv-pdf-web-fallback")) {
4826
4983
  options.viewport.classList.add("ofv-center");
4827
4984
  }
@@ -4888,8 +5045,43 @@ async function renderPdfDocumentPreview(options) {
4888
5045
  let currentSize = options.size;
4889
5046
  let zoomFactor = getInitialZoom({ options: { zoom: options.zoom ?? 1 } }, 0.25, 4);
4890
5047
  let rotation = 0;
5048
+ let currentPage = 1;
5049
+ const goToPage = (page, scroll = true) => {
5050
+ currentPage = Math.min(pdfDocument.numPages, Math.max(1, Math.round(page) || 1));
5051
+ pageNavigator.setCurrent(currentPage);
5052
+ const wrapper = pageStates[currentPage - 1]?.wrapper;
5053
+ if (!scroll || !wrapper) {
5054
+ return;
5055
+ }
5056
+ const top = Math.max(0, wrapper.offsetTop - 16);
5057
+ if (typeof scroller.scrollTo === "function") {
5058
+ scroller.scrollTo({ top, behavior: "smooth" });
5059
+ } else {
5060
+ scroller.scrollTop = top;
5061
+ }
5062
+ };
5063
+ const pageNavigator = createPdfPageNavigator(pdfDocument.numPages, messages, (page) => goToPage(page));
5064
+ viewer.insertBefore(pageNavigator.element, summary);
5065
+ const handleScrollerScroll = () => {
5066
+ const scrollerRect = scroller.getBoundingClientRect();
5067
+ const targetY = scrollerRect.top + Math.min(Math.max(scroller.clientHeight * 0.25, 40), 180);
5068
+ let nearestPage = currentPage;
5069
+ let nearestDistance = Number.POSITIVE_INFINITY;
5070
+ pageStates.forEach((state, index) => {
5071
+ const distance = Math.abs(state.wrapper.getBoundingClientRect().top - targetY);
5072
+ if (distance < nearestDistance) {
5073
+ nearestDistance = distance;
5074
+ nearestPage = index + 1;
5075
+ }
5076
+ });
5077
+ if (nearestPage !== currentPage) {
5078
+ currentPage = nearestPage;
5079
+ pageNavigator.setCurrent(currentPage);
5080
+ }
5081
+ };
5082
+ scroller.addEventListener("scroll", handleScrollerScroll, { passive: true });
4891
5083
  const updateSummary = () => {
4892
- renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor);
5084
+ renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor, messages);
4893
5085
  options.toolbar?.setZoom(zoomFactor);
4894
5086
  };
4895
5087
  const clearPage = (pageIdx) => {
@@ -4905,7 +5097,9 @@ async function renderPdfDocumentPreview(options) {
4905
5097
  state.canvas = null;
4906
5098
  state.rendered = false;
4907
5099
  state.wrapper.replaceChildren();
4908
- state.wrapper.append(createPageStatus("ofv-pdf-skeleton", `\u9875\u9762 ${pageIdx + 1} \u52A0\u8F7D\u4E2D...`));
5100
+ state.wrapper.append(
5101
+ createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: pageIdx + 1 }))
5102
+ );
4909
5103
  };
4910
5104
  const renderPage = async (pageIdx, size) => {
4911
5105
  const state = pageStates[pageIdx];
@@ -4973,7 +5167,7 @@ async function renderPdfDocumentPreview(options) {
4973
5167
  state.wrapper.appendChild(
4974
5168
  createPageStatus(
4975
5169
  "ofv-pdf-empty",
4976
- "\u8BE5\u9875\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u663E\u793A\u7684 PDF \u517C\u5BB9\u5185\u5BB9\u3002\u82E5\u8FD9\u662F Illustrator/AI \u6587\u4EF6\uFF0C\u53EF\u80FD\u53EA\u5305\u542B\u79C1\u6709\u7F16\u8F91\u6570\u636E\uFF0C\u5EFA\u8BAE\u5BFC\u51FA\u4E3A PDF/SVG/PNG \u540E\u9884\u89C8\u3002"
5170
+ messages.pdfPageEmpty
4977
5171
  )
4978
5172
  );
4979
5173
  }
@@ -4981,7 +5175,7 @@ async function renderPdfDocumentPreview(options) {
4981
5175
  console.error(`Failed to render PDF page ${pageIdx + 1}:`, err);
4982
5176
  state.rendered = false;
4983
5177
  state.wrapper.replaceChildren(
4984
- createPageStatus("ofv-pdf-error", "\u65E0\u6CD5\u6E32\u67D3\u8BE5\u9875\u9762\u3002\u8BE5\u9875\u53EF\u80FD\u5305\u542B\u6D4F\u89C8\u5668 PDF \u5F15\u64CE\u6682\u4E0D\u652F\u6301\u7684\u56FE\u5F62\u3001\u5B57\u4F53\u6216\u538B\u7F29\u7279\u6027\u3002")
5178
+ createPageStatus("ofv-pdf-error", messages.pdfPageRenderFailed)
4985
5179
  );
4986
5180
  }
4987
5181
  };
@@ -5022,9 +5216,10 @@ async function renderPdfDocumentPreview(options) {
5022
5216
  const wrapper = document.createElement("div");
5023
5217
  wrapper.className = "ofv-pdf-page-wrapper";
5024
5218
  wrapper.setAttribute("data-page-index", String(i));
5219
+ wrapper.setAttribute("aria-label", formatPreviewMessage(messages.pdfPageLabel, { page: i + 1 }));
5025
5220
  wrapper.style.width = `${w}px`;
5026
5221
  wrapper.style.height = `${h}px`;
5027
- wrapper.append(createPageStatus("ofv-pdf-skeleton", `\u9875\u9762 ${i + 1} \u52A0\u8F7D\u4E2D...`));
5222
+ wrapper.append(createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: i + 1 })));
5028
5223
  scroller.appendChild(wrapper);
5029
5224
  pageStates.push({
5030
5225
  wrapper,
@@ -5046,6 +5241,7 @@ async function renderPdfDocumentPreview(options) {
5046
5241
  }
5047
5242
  }, 0);
5048
5243
  }
5244
+ goToPage(currentPage, false);
5049
5245
  };
5050
5246
  renderLayout(options.size);
5051
5247
  let resizeTimer;
@@ -5086,6 +5282,8 @@ async function renderPdfDocumentPreview(options) {
5086
5282
  },
5087
5283
  destroy() {
5088
5284
  options.toolbar?.setZoom(void 0);
5285
+ pageNavigator.destroy();
5286
+ scroller.removeEventListener("scroll", handleScrollerScroll);
5089
5287
  window.clearTimeout(resizeTimer);
5090
5288
  observer?.disconnect();
5091
5289
  pageStates.forEach((state) => {
@@ -5131,15 +5329,15 @@ function getPdfAvailableWidth(width) {
5131
5329
  const gutter = width < 160 ? 16 : 32;
5132
5330
  return Math.max(1, width - gutter);
5133
5331
  }
5134
- function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor) {
5332
+ function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor, messages) {
5135
5333
  summary.replaceChildren();
5136
- appendPdfSummary(summary, "\u9875\u6570", String(pages));
5334
+ appendPdfSummary(summary, messages.pdfSummaryPages, String(pages));
5137
5335
  const pageSizes = formatPdfPageSizes(pagesMeta);
5138
5336
  if (pageSizes) {
5139
- appendPdfSummary(summary, "\u9875\u9762\u5C3A\u5BF8", pageSizes);
5337
+ appendPdfSummary(summary, messages.pdfSummaryPageSizes, pageSizes);
5140
5338
  }
5141
- appendPdfSummary(summary, "\u9002\u914D", fit === "actual" ? "\u539F\u59CB\u5927\u5C0F" : "\u9002\u5408\u5BBD\u5EA6");
5142
- appendPdfSummary(summary, "\u7F29\u653E", `${Math.round(zoomFactor * 100)}%`);
5339
+ appendPdfSummary(summary, messages.pdfSummaryFit, fit === "actual" ? messages.pdfSummaryActualSize : messages.pdfSummaryFitWidth);
5340
+ appendPdfSummary(summary, messages.pdfSummaryZoom, `${Math.round(zoomFactor * 100)}%`);
5143
5341
  }
5144
5342
  function appendPdfSummary(parent, label, value) {
5145
5343
  const item = document.createElement("span");
@@ -5229,7 +5427,7 @@ function createPageStatus(className, text) {
5229
5427
  status.textContent = text;
5230
5428
  return status;
5231
5429
  }
5232
- function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8\u5931\u8D25") {
5430
+ function createPdfFallback(fileName, url, message, messages, titleText = messages.pdfPreviewFailedTitle) {
5233
5431
  if (isEmbeddableRemoteUrl(url)) {
5234
5432
  return createPdfWebFallback(fileName, url);
5235
5433
  }
@@ -5242,7 +5440,7 @@ function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8
5242
5440
  const download = document.createElement("a");
5243
5441
  download.href = url;
5244
5442
  download.download = fileName;
5245
- download.textContent = "\u4E0B\u8F7D PDF";
5443
+ download.textContent = messages.pdfDownload;
5246
5444
  fallback.append(title, meta, download);
5247
5445
  return fallback;
5248
5446
  }
@@ -5261,23 +5459,109 @@ function createPdfWebFallback(fileName, url) {
5261
5459
  function isEmbeddableRemoteUrl(url) {
5262
5460
  return /^https?:\/\//i.test(url);
5263
5461
  }
5264
- function normalizePdfError(error) {
5462
+ function normalizePdfError(error, messages) {
5265
5463
  const message = error instanceof Error ? error.message : String(error || "");
5266
5464
  const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
5267
5465
  const lower = `${name} ${message}`.toLowerCase();
5268
5466
  if (lower.includes("invalid") || lower.includes("missing") || lower.includes("corrupt")) {
5269
- return "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002";
5467
+ return messages.pdfCorruptedMessage;
5270
5468
  }
5271
- return "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002";
5469
+ return messages.pdfCannotLoadMessage;
5272
5470
  }
5273
- function configurePdfWorker(pdf, workerSrc) {
5471
+ function createPdfPageNavigator(total, messages, onChange) {
5472
+ const element = document.createElement("div");
5473
+ element.className = "ofv-pdf-page-navigator";
5474
+ const previous = document.createElement("button");
5475
+ previous.type = "button";
5476
+ previous.textContent = "\u2039";
5477
+ previous.title = messages.pdfPreviousPage;
5478
+ previous.setAttribute("aria-label", messages.pdfPreviousPage);
5479
+ const input = document.createElement("input");
5480
+ input.type = "number";
5481
+ input.min = "1";
5482
+ input.max = String(total);
5483
+ input.value = "1";
5484
+ input.inputMode = "numeric";
5485
+ input.setAttribute("aria-label", messages.pdfPageInput);
5486
+ const position = document.createElement("span");
5487
+ position.textContent = formatPreviewMessage(messages.pdfPagePosition, { total });
5488
+ const next = document.createElement("button");
5489
+ next.type = "button";
5490
+ next.textContent = "\u203A";
5491
+ next.title = messages.pdfNextPage;
5492
+ next.setAttribute("aria-label", messages.pdfNextPage);
5493
+ const commit = () => onChange(Number(input.value));
5494
+ const handleKeydown = (event) => {
5495
+ if (event.key === "Enter") {
5496
+ commit();
5497
+ }
5498
+ };
5499
+ const handlePrevious = () => onChange(Number(input.value) - 1);
5500
+ const handleNext = () => onChange(Number(input.value) + 1);
5501
+ input.addEventListener("change", commit);
5502
+ input.addEventListener("keydown", handleKeydown);
5503
+ previous.addEventListener("click", handlePrevious);
5504
+ next.addEventListener("click", handleNext);
5505
+ element.append(previous, input, position, next);
5506
+ return {
5507
+ element,
5508
+ setCurrent(page) {
5509
+ input.value = String(page);
5510
+ previous.disabled = page <= 1;
5511
+ next.disabled = page >= total;
5512
+ },
5513
+ destroy() {
5514
+ input.removeEventListener("change", commit);
5515
+ input.removeEventListener("keydown", handleKeydown);
5516
+ previous.removeEventListener("click", handlePrevious);
5517
+ next.removeEventListener("click", handleNext);
5518
+ }
5519
+ };
5520
+ }
5521
+ function configurePdfWorker(pdf, workerSrc, legacy = false) {
5274
5522
  if (workerSrc) {
5275
5523
  pdf.GlobalWorkerOptions.workerSrc = workerSrc;
5276
5524
  return;
5277
5525
  }
5278
5526
  if (!pdf.GlobalWorkerOptions.workerSrc && typeof window !== "undefined") {
5279
- pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/build/pdf.worker.mjs`;
5527
+ const build = legacy ? "legacy/build" : "build";
5528
+ pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/${build}/pdf.worker.mjs`;
5529
+ }
5530
+ }
5531
+ function shouldUseLegacyPdfCompatibility(mode = "auto") {
5532
+ if (mode === "legacy") {
5533
+ return true;
5534
+ }
5535
+ if (mode === "modern") {
5536
+ return false;
5537
+ }
5538
+ const promise = Promise;
5539
+ if (typeof promise.withResolvers !== "function") {
5540
+ return true;
5541
+ }
5542
+ if (typeof navigator === "undefined") {
5543
+ return false;
5280
5544
  }
5545
+ return /(?:QIHU|360SE|360EE)/i.test(navigator.userAgent);
5546
+ }
5547
+ function installPromiseWithResolversPolyfill() {
5548
+ const promise = Promise;
5549
+ if (typeof promise.withResolvers === "function") {
5550
+ return;
5551
+ }
5552
+ Object.defineProperty(promise, "withResolvers", {
5553
+ configurable: true,
5554
+ writable: true,
5555
+ value: () => {
5556
+ let resolve;
5557
+ let reject;
5558
+ const pending = new Promise((resolvePromise, rejectPromise) => {
5559
+ resolve = resolvePromise;
5560
+ reject = rejectPromise;
5561
+ });
5562
+ return { promise: pending, resolve, reject };
5563
+ }
5564
+ });
5281
5565
  }
5282
5566
 
5283
5567
  // src/plugins/epub.ts
@@ -7672,8 +7956,9 @@ async function renderConvertedOfficePreview(panel, ctx, options, conversionConte
7672
7956
  fit: ctx.options.fit,
7673
7957
  zoom: ctx.options.zoom,
7674
7958
  toolbar: ctx.toolbar,
7675
- title: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
7676
- fallbackTitle: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
7959
+ messages: ctx.options.messages,
7960
+ title: ctx.options.messages.officeConvertedTitle,
7961
+ fallbackTitle: ctx.options.messages.officeConvertedPdfFailed,
7677
7962
  revokeUrlOnDestroy: converted.revokeUrlOnDestroy
7678
7963
  });
7679
7964
  }
@@ -12746,9 +13031,9 @@ function getIcon(name, dir) {
12746
13031
  }
12747
13032
 
12748
13033
  // src/plugins/email.ts
12749
- import DOMPurify3 from "dompurify";
12750
13034
  var emailExtensions = /* @__PURE__ */ new Set(["eml", "msg", "mbox"]);
12751
13035
  var emailMimeTypes = /* @__PURE__ */ new Set(["message/rfc822", "application/vnd.ms-outlook", "application/mbox"]);
13036
+ var domPurifyLoader;
12752
13037
  var emailMimeFormatMap = {
12753
13038
  "message/rfc822": "eml",
12754
13039
  "application/vnd.ms-outlook": "msg",
@@ -12761,6 +13046,8 @@ function emailPlugin() {
12761
13046
  return emailExtensions.has(file.extension) || emailMimeTypes.has(file.mimeType);
12762
13047
  },
12763
13048
  async render(ctx) {
13049
+ const DOMPurifyModule = await (domPurifyLoader ||= import("dompurify"));
13050
+ const DOMPurify3 = DOMPurifyModule.default;
12764
13051
  const panel = createPanel("ofv-email");
12765
13052
  ctx.viewport.append(panel);
12766
13053
  const url = createObjectUrl(ctx.file);
@@ -12894,7 +13181,7 @@ function emailPlugin() {
12894
13181
  }
12895
13182
  });
12896
13183
  html = nextHtml;
12897
- const sanitizedHtml = sanitizeEmailHtml(html);
13184
+ const sanitizedHtml = sanitizeEmailHtml(html, DOMPurify3);
12898
13185
  const iframe = document.createElement("iframe");
12899
13186
  iframe.className = "ofv-email-body-iframe";
12900
13187
  iframe.setAttribute("sandbox", "allow-same-origin allow-popups allow-popups-to-escape-sandbox");
@@ -13187,8 +13474,8 @@ function getMimeType(name) {
13187
13474
  };
13188
13475
  return ext ? map[ext] || "application/octet-stream" : "application/octet-stream";
13189
13476
  }
13190
- function sanitizeEmailHtml(html) {
13191
- return DOMPurify3.sanitize(html, {
13477
+ function sanitizeEmailHtml(html, purifier) {
13478
+ return purifier.sanitize(html, {
13192
13479
  USE_PROFILES: { html: true },
13193
13480
  ADD_ATTR: ["target"],
13194
13481
  ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|blob|cid):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i