@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.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, {
@@ -655,7 +714,36 @@ var defaultMessages = {
655
714
  officeUnsupportedIntro: "\u5DF2\u8FDB\u5165 Office \u63D2\u4EF6\u3002{message}",
656
715
  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",
657
716
  officeErrorWithMessage: "\u89E3\u6790\u5668\u8FD4\u56DE\uFF1A{message}",
658
- officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002"
717
+ officeErrorWithoutMessage: "\u89E3\u6790\u5668\u672A\u8FD4\u56DE\u5177\u4F53\u9519\u8BEF\u4FE1\u606F\u3002",
718
+ officeConvertedTitle: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
719
+ officeConvertedPdfFailed: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
720
+ pdfEncryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
721
+ pdfEncryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
722
+ pdfPreviewFailedTitle: "PDF \u9884\u89C8\u5931\u8D25",
723
+ pdfCorruptedMessage: "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002",
724
+ pdfCannotLoadMessage: "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002",
725
+ pdfDownload: "\u4E0B\u8F7D PDF",
726
+ pdfPageLoading: "\u9875\u9762 {page} \u52A0\u8F7D\u4E2D...",
727
+ 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",
728
+ 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",
729
+ pdfPreviousPage: "\u4E0A\u4E00\u9875",
730
+ pdfNextPage: "\u4E0B\u4E00\u9875",
731
+ pdfPageInput: "\u5F53\u524D\u9875\u7801",
732
+ pdfPagePosition: "/ {total}",
733
+ pdfPageLabel: "\u7B2C {page} \u9875",
734
+ pdfSummaryPages: "\u9875\u6570",
735
+ pdfSummaryPageSizes: "\u9875\u9762\u5C3A\u5BF8",
736
+ pdfSummaryFit: "\u9002\u914D",
737
+ pdfSummaryActualSize: "\u539F\u59CB\u5927\u5C0F",
738
+ pdfSummaryFitWidth: "\u9002\u5408\u5BBD\u5EA6",
739
+ pdfSummaryZoom: "\u7F29\u653E",
740
+ imagePreviewFailedTitle: "\u56FE\u7247\u9884\u89C8\u5931\u8D25",
741
+ 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",
742
+ imageDownload: "\u4E0B\u8F7D\u56FE\u7247",
743
+ imageZoomOut: "\u7F29\u5C0F",
744
+ imageZoomIn: "\u653E\u5927",
745
+ imageRotate: "\u65CB\u8F6C\u56FE\u7247",
746
+ imageReset: "\u91CD\u7F6E\u56FE\u7247\u89C6\u56FE"
659
747
  },
660
748
  "en-US": {
661
749
  loading: "Loading preview...",
@@ -704,7 +792,36 @@ var defaultMessages = {
704
792
  officeUnsupportedIntro: "is handled by the Office plugin. {message}",
705
793
  officeUnsupportedSupportedFormats: "This version prioritizes basic previews for docx, rtf, odt/fodt, xlsx/xls/csv/ods, pptx/ppsx, and odp/fodp files.",
706
794
  officeErrorWithMessage: "Parser returned: {message}",
707
- officeErrorWithoutMessage: "Parser did not return a specific error."
795
+ officeErrorWithoutMessage: "Parser did not return a specific error.",
796
+ officeConvertedTitle: "High-fidelity Office conversion preview",
797
+ officeConvertedPdfFailed: "The converted Office PDF could not be previewed",
798
+ pdfEncryptedTitle: "This PDF is encrypted and cannot be previewed online",
799
+ pdfEncryptedMessage: "Download and open it with the password, or upload a decrypted PDF file.",
800
+ pdfPreviewFailedTitle: "PDF preview failed",
801
+ pdfCorruptedMessage: "The PDF may be corrupted or use an invalid format.",
802
+ pdfCannotLoadMessage: "This browser could not load the PDF.",
803
+ pdfDownload: "Download PDF",
804
+ pdfPageLoading: "Loading page {page}...",
805
+ 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.",
806
+ pdfPageRenderFailed: "This page could not be rendered. It may contain graphics, fonts, or compression features that the browser PDF engine does not support.",
807
+ pdfPreviousPage: "Previous page",
808
+ pdfNextPage: "Next page",
809
+ pdfPageInput: "Current page",
810
+ pdfPagePosition: "/ {total}",
811
+ pdfPageLabel: "Page {page}",
812
+ pdfSummaryPages: "Pages",
813
+ pdfSummaryPageSizes: "Page sizes",
814
+ pdfSummaryFit: "Fit",
815
+ pdfSummaryActualSize: "Actual size",
816
+ pdfSummaryFitWidth: "Fit width",
817
+ pdfSummaryZoom: "Zoom",
818
+ imagePreviewFailedTitle: "Image preview failed",
819
+ imagePreviewFailedMessage: "This browser cannot display the image. The file may be corrupted or use an unsupported encoding.",
820
+ imageDownload: "Download image",
821
+ imageZoomOut: "Zoom out",
822
+ imageZoomIn: "Zoom in",
823
+ imageRotate: "Rotate image",
824
+ imageReset: "Reset image view"
708
825
  }
709
826
  };
710
827
  function resolveMessages(options) {
@@ -2215,7 +2332,7 @@ function imagePlugin() {
2215
2332
  infoBar.hidden = false;
2216
2333
  infoBar.removeAttribute("aria-hidden");
2217
2334
  infoBar.style.removeProperty("display");
2218
- stage.replaceChildren(createImageFallback(ctx.file.name, url));
2335
+ stage.replaceChildren(createImageFallback(ctx.file.name, url, ctx.options.messages));
2219
2336
  ctx.toolbar?.refreshCommandSupport();
2220
2337
  };
2221
2338
  const setScale = (nextScale) => {
@@ -2240,13 +2357,13 @@ function imagePlugin() {
2240
2357
  return () => button.removeEventListener("click", action);
2241
2358
  };
2242
2359
  const disposers = showInlineControls ? [
2243
- addButton("-", "Zoom out", () => setScale(scale - 0.25)),
2244
- addButton("+", "Zoom in", () => setScale(scale + 0.25)),
2245
- addButton("Rotate", "Rotate image", () => {
2360
+ addButton("-", ctx.options.messages.imageZoomOut, () => setScale(scale - 0.25)),
2361
+ addButton("+", ctx.options.messages.imageZoomIn, () => setScale(scale + 0.25)),
2362
+ addButton(ctx.options.messages.imageRotate, ctx.options.messages.imageRotate, () => {
2246
2363
  rotation += 90;
2247
2364
  updateTransform();
2248
2365
  }),
2249
- addButton("Reset", "Reset image view", reset)
2366
+ addButton(ctx.options.messages.imageReset, ctx.options.messages.imageReset, reset)
2250
2367
  ] : [];
2251
2368
  if (showInlineControls) {
2252
2369
  controls.append(zoomLabel);
@@ -2461,17 +2578,17 @@ function getTiffDimensions(ifd) {
2461
2578
  height: Number(ifd.height || ifd.t257 || 0)
2462
2579
  };
2463
2580
  }
2464
- function createImageFallback(fileName, url) {
2581
+ function createImageFallback(fileName, url, messages) {
2465
2582
  const fallback = document.createElement("div");
2466
2583
  fallback.className = "ofv-fallback";
2467
2584
  const title = document.createElement("strong");
2468
- title.textContent = "\u56FE\u7247\u9884\u89C8\u5931\u8D25";
2585
+ title.textContent = messages.imagePreviewFailedTitle;
2469
2586
  const meta = document.createElement("span");
2470
- 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";
2587
+ meta.textContent = messages.imagePreviewFailedMessage;
2471
2588
  const download = document.createElement("a");
2472
2589
  download.href = url;
2473
2590
  download.download = fileName;
2474
- download.textContent = "\u4E0B\u8F7D\u56FE\u7247";
2591
+ download.textContent = messages.imageDownload;
2475
2592
  fallback.append(title, meta, download);
2476
2593
  return fallback;
2477
2594
  }
@@ -4233,6 +4350,7 @@ var mimeLangMap = {
4233
4350
  };
4234
4351
  var MAX_HIGHLIGHT_CHARS = 18e4;
4235
4352
  var MAX_RENDER_CHARS = 6e5;
4353
+ var prismLanguageLoads = /* @__PURE__ */ new Map();
4236
4354
  function textPlugin() {
4237
4355
  return {
4238
4356
  name: "text",
@@ -4264,10 +4382,10 @@ function textPlugin() {
4264
4382
  ]);
4265
4383
  const parseMarkdown = markedModule.marked?.parse || markedModule.parse || markedModule.default?.parse;
4266
4384
  const Prism2 = PrismModule2.default || PrismModule2;
4267
- const DOMPurify4 = DOMPurifyModule.default || DOMPurifyModule;
4385
+ const DOMPurify3 = DOMPurifyModule.default || DOMPurifyModule;
4268
4386
  const container = document.createElement("div");
4269
4387
  container.className = "ofv-markdown-body";
4270
- container.innerHTML = DOMPurify4.sanitize(parseMarkdown(text), {
4388
+ container.innerHTML = DOMPurify3.sanitize(parseMarkdown(text), {
4271
4389
  USE_PROFILES: { html: true },
4272
4390
  ADD_ATTR: ["target"]
4273
4391
  });
@@ -4276,6 +4394,14 @@ function textPlugin() {
4276
4394
  try {
4277
4395
  const codeBlocks = container.querySelectorAll("pre code");
4278
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)));
4279
4405
  codeBlocks.forEach((block) => {
4280
4406
  const parent = block.parentElement;
4281
4407
  if (parent && !parent.className.includes("language-")) {
@@ -4304,97 +4430,7 @@ function textPlugin() {
4304
4430
  const Prism = PrismModule.default || PrismModule;
4305
4431
  if (lang !== "none") {
4306
4432
  try {
4307
- if (lang === "typescript" || lang === "tsx") {
4308
- await import("prismjs/components/prism-typescript");
4309
- } else if (lang === "python") {
4310
- await import("prismjs/components/prism-python");
4311
- } else if (lang === "json") {
4312
- await import("prismjs/components/prism-json");
4313
- } else if (lang === "json5") {
4314
- await import("prismjs/components/prism-json5");
4315
- } else if (lang === "yaml") {
4316
- await import("prismjs/components/prism-yaml");
4317
- } else if (lang === "toml") {
4318
- await import("prismjs/components/prism-toml");
4319
- } else if (lang === "ini") {
4320
- await import("prismjs/components/prism-ini");
4321
- } else if (lang === "properties") {
4322
- await import("prismjs/components/prism-properties");
4323
- } else if (lang === "editorconfig") {
4324
- await import("prismjs/components/prism-editorconfig");
4325
- } else if (lang === "ignore") {
4326
- await import("prismjs/components/prism-ignore");
4327
- } else if (lang === "protobuf") {
4328
- await import("prismjs/components/prism-protobuf");
4329
- } else if (lang === "hcl") {
4330
- await import("prismjs/components/prism-hcl");
4331
- } else if (lang === "latex") {
4332
- await import("prismjs/components/prism-latex");
4333
- } else if (lang === "dot") {
4334
- await import("prismjs/components/prism-dot");
4335
- } else if (lang === "http") {
4336
- await import("prismjs/components/prism-http");
4337
- } else if (lang === "bash") {
4338
- await import("prismjs/components/prism-bash");
4339
- } else if (lang === "powershell") {
4340
- await import("prismjs/components/prism-powershell");
4341
- } else if (lang === "batch") {
4342
- await import("prismjs/components/prism-batch");
4343
- } else if (lang === "docker") {
4344
- await import("prismjs/components/prism-docker");
4345
- } else if (lang === "makefile") {
4346
- await import("prismjs/components/prism-makefile");
4347
- } else if (lang === "ruby") {
4348
- await import("prismjs/components/prism-ruby");
4349
- } else if (lang === "nginx") {
4350
- await import("prismjs/components/prism-nginx");
4351
- } else if (lang === "groovy") {
4352
- await import("prismjs/components/prism-groovy");
4353
- } else if (lang === "graphql") {
4354
- await import("prismjs/components/prism-graphql");
4355
- } else if (lang === "csharp") {
4356
- await import("prismjs/components/prism-csharp");
4357
- } else if (lang === "rust") {
4358
- await import("prismjs/components/prism-rust");
4359
- } else if (lang === "go") {
4360
- await import("prismjs/components/prism-go");
4361
- } else if (lang === "ruby") {
4362
- await import("prismjs/components/prism-ruby");
4363
- } else if (lang === "swift") {
4364
- await import("prismjs/components/prism-swift");
4365
- } else if (lang === "kotlin") {
4366
- await import("prismjs/components/prism-kotlin");
4367
- } else if (lang === "scala") {
4368
- await import("prismjs/components/prism-scala");
4369
- } else if (lang === "lua") {
4370
- await import("prismjs/components/prism-lua");
4371
- } else if (lang === "r") {
4372
- await import("prismjs/components/prism-r");
4373
- } else if (lang === "dart") {
4374
- await import("prismjs/components/prism-dart");
4375
- } else if (lang === "elm") {
4376
- await import("prismjs/components/prism-elm");
4377
- } else if (lang === "elixir") {
4378
- await import("prismjs/components/prism-elixir");
4379
- } else if (lang === "clojure") {
4380
- await import("prismjs/components/prism-clojure");
4381
- } else if (lang === "erlang") {
4382
- await import("prismjs/components/prism-erlang");
4383
- } else if (lang === "fsharp") {
4384
- await import("prismjs/components/prism-fsharp");
4385
- } else if (lang === "haskell") {
4386
- await import("prismjs/components/prism-haskell");
4387
- } else if (lang === "sql") {
4388
- await import("prismjs/components/prism-sql");
4389
- } else if (lang === "cpp") {
4390
- await import("prismjs/components/prism-c");
4391
- await import("prismjs/components/prism-cpp");
4392
- } else if (lang === "java") {
4393
- await import("prismjs/components/prism-java");
4394
- } else if (lang === "php") {
4395
- await import("prismjs/components/prism-markup-templating");
4396
- await import("prismjs/components/prism-php");
4397
- }
4433
+ await loadPrismLanguage(lang);
4398
4434
  } catch (e) {
4399
4435
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4400
4436
  }
@@ -4519,6 +4555,183 @@ function textPlugin() {
4519
4555
  }
4520
4556
  };
4521
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
+ }
4522
4735
  function createTextZoomController(target, cssVariable, ctx) {
4523
4736
  let zoom = getInitialZoom(ctx, 0.5, 3);
4524
4737
  const apply = () => {
@@ -4832,17 +5045,20 @@ function pdfPlugin(options = {}) {
4832
5045
  fit: ctx.options.fit,
4833
5046
  zoom: ctx.options.zoom,
4834
5047
  toolbar: ctx.toolbar,
4835
- encryptedTitle: "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
4836
- encryptedMessage: "\u8BF7\u4E0B\u8F7D\u540E\u4F7F\u7528\u5BC6\u7801\u6253\u5F00\uFF0C\u6216\u4E0A\u4F20\u89E3\u5BC6\u540E\u7684 PDF \u6587\u4EF6\u3002",
4837
- encryptedAction: "\u4E0B\u8F7D PDF",
5048
+ messages: ctx.options.messages,
4838
5049
  revokeUrlOnDestroy: true
4839
5050
  });
4840
5051
  }
4841
5052
  };
4842
5053
  }
4843
5054
  async function renderPdfDocumentPreview(options) {
5055
+ const useLegacyCompatibility = shouldUseLegacyPdfCompatibility(options.compatibilityMode);
5056
+ if (useLegacyCompatibility) {
5057
+ installPromiseWithResolversPolyfill();
5058
+ }
4844
5059
  const pdf = options.pdfjs || await import("pdfjs-dist");
4845
- configurePdfWorker(pdf, options.workerSrc);
5060
+ const messages = { ...defaultMessages["en-US"], ...options.messages };
5061
+ configurePdfWorker(pdf, options.workerSrc, useLegacyCompatibility);
4846
5062
  const viewer = document.createElement("div");
4847
5063
  viewer.className = "ofv-pdf-viewer";
4848
5064
  if (options.title) {
@@ -4871,10 +5087,10 @@ async function renderPdfDocumentPreview(options) {
4871
5087
  url: options.fileUrl
4872
5088
  };
4873
5089
  const fallback = isEncryptedError(error) ? createEncryptedFallback(fileLike, options.fileUrl, {
4874
- title: options.encryptedTitle || "PDF \u5DF2\u52A0\u5BC6\uFF0C\u65E0\u6CD5\u5728\u7EBF\u9884\u89C8",
4875
- 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",
4876
- action: options.encryptedAction || "\u4E0B\u8F7D PDF"
4877
- }) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error), options.fallbackTitle);
5090
+ title: options.encryptedTitle || messages.pdfEncryptedTitle,
5091
+ message: options.encryptedMessage || messages.pdfEncryptedMessage,
5092
+ action: options.encryptedAction || messages.pdfDownload
5093
+ }) : createPdfFallback(options.fileName, options.fileUrl, normalizePdfError(error, messages), messages, options.fallbackTitle);
4878
5094
  if (!fallback.classList.contains("ofv-pdf-web-fallback")) {
4879
5095
  options.viewport.classList.add("ofv-center");
4880
5096
  }
@@ -4941,8 +5157,43 @@ async function renderPdfDocumentPreview(options) {
4941
5157
  let currentSize = options.size;
4942
5158
  let zoomFactor = getInitialZoom({ options: { zoom: options.zoom ?? 1 } }, 0.25, 4);
4943
5159
  let rotation = 0;
5160
+ let currentPage = 1;
5161
+ const goToPage = (page, scroll = true) => {
5162
+ currentPage = Math.min(pdfDocument.numPages, Math.max(1, Math.round(page) || 1));
5163
+ pageNavigator.setCurrent(currentPage);
5164
+ const wrapper = pageStates[currentPage - 1]?.wrapper;
5165
+ if (!scroll || !wrapper) {
5166
+ return;
5167
+ }
5168
+ const top = Math.max(0, wrapper.offsetTop - 16);
5169
+ if (typeof scroller.scrollTo === "function") {
5170
+ scroller.scrollTo({ top, behavior: "smooth" });
5171
+ } else {
5172
+ scroller.scrollTop = top;
5173
+ }
5174
+ };
5175
+ const pageNavigator = createPdfPageNavigator(pdfDocument.numPages, messages, (page) => goToPage(page));
5176
+ viewer.insertBefore(pageNavigator.element, summary);
5177
+ const handleScrollerScroll = () => {
5178
+ const scrollerRect = scroller.getBoundingClientRect();
5179
+ const targetY = scrollerRect.top + Math.min(Math.max(scroller.clientHeight * 0.25, 40), 180);
5180
+ let nearestPage = currentPage;
5181
+ let nearestDistance = Number.POSITIVE_INFINITY;
5182
+ pageStates.forEach((state, index) => {
5183
+ const distance = Math.abs(state.wrapper.getBoundingClientRect().top - targetY);
5184
+ if (distance < nearestDistance) {
5185
+ nearestDistance = distance;
5186
+ nearestPage = index + 1;
5187
+ }
5188
+ });
5189
+ if (nearestPage !== currentPage) {
5190
+ currentPage = nearestPage;
5191
+ pageNavigator.setCurrent(currentPage);
5192
+ }
5193
+ };
5194
+ scroller.addEventListener("scroll", handleScrollerScroll, { passive: true });
4944
5195
  const updateSummary = () => {
4945
- renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor);
5196
+ renderPdfSummary(summary, pdfDocument.numPages, pagesMeta, options.fit, zoomFactor, messages);
4946
5197
  options.toolbar?.setZoom(zoomFactor);
4947
5198
  };
4948
5199
  const clearPage = (pageIdx) => {
@@ -4958,7 +5209,9 @@ async function renderPdfDocumentPreview(options) {
4958
5209
  state.canvas = null;
4959
5210
  state.rendered = false;
4960
5211
  state.wrapper.replaceChildren();
4961
- state.wrapper.append(createPageStatus("ofv-pdf-skeleton", `\u9875\u9762 ${pageIdx + 1} \u52A0\u8F7D\u4E2D...`));
5212
+ state.wrapper.append(
5213
+ createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: pageIdx + 1 }))
5214
+ );
4962
5215
  };
4963
5216
  const renderPage = async (pageIdx, size) => {
4964
5217
  const state = pageStates[pageIdx];
@@ -5026,7 +5279,7 @@ async function renderPdfDocumentPreview(options) {
5026
5279
  state.wrapper.appendChild(
5027
5280
  createPageStatus(
5028
5281
  "ofv-pdf-empty",
5029
- "\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"
5282
+ messages.pdfPageEmpty
5030
5283
  )
5031
5284
  );
5032
5285
  }
@@ -5034,7 +5287,7 @@ async function renderPdfDocumentPreview(options) {
5034
5287
  console.error(`Failed to render PDF page ${pageIdx + 1}:`, err);
5035
5288
  state.rendered = false;
5036
5289
  state.wrapper.replaceChildren(
5037
- 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")
5290
+ createPageStatus("ofv-pdf-error", messages.pdfPageRenderFailed)
5038
5291
  );
5039
5292
  }
5040
5293
  };
@@ -5075,9 +5328,10 @@ async function renderPdfDocumentPreview(options) {
5075
5328
  const wrapper = document.createElement("div");
5076
5329
  wrapper.className = "ofv-pdf-page-wrapper";
5077
5330
  wrapper.setAttribute("data-page-index", String(i));
5331
+ wrapper.setAttribute("aria-label", formatPreviewMessage(messages.pdfPageLabel, { page: i + 1 }));
5078
5332
  wrapper.style.width = `${w}px`;
5079
5333
  wrapper.style.height = `${h}px`;
5080
- wrapper.append(createPageStatus("ofv-pdf-skeleton", `\u9875\u9762 ${i + 1} \u52A0\u8F7D\u4E2D...`));
5334
+ wrapper.append(createPageStatus("ofv-pdf-skeleton", formatPreviewMessage(messages.pdfPageLoading, { page: i + 1 })));
5081
5335
  scroller.appendChild(wrapper);
5082
5336
  pageStates.push({
5083
5337
  wrapper,
@@ -5099,6 +5353,7 @@ async function renderPdfDocumentPreview(options) {
5099
5353
  }
5100
5354
  }, 0);
5101
5355
  }
5356
+ goToPage(currentPage, false);
5102
5357
  };
5103
5358
  renderLayout(options.size);
5104
5359
  let resizeTimer;
@@ -5139,6 +5394,8 @@ async function renderPdfDocumentPreview(options) {
5139
5394
  },
5140
5395
  destroy() {
5141
5396
  options.toolbar?.setZoom(void 0);
5397
+ pageNavigator.destroy();
5398
+ scroller.removeEventListener("scroll", handleScrollerScroll);
5142
5399
  window.clearTimeout(resizeTimer);
5143
5400
  observer?.disconnect();
5144
5401
  pageStates.forEach((state) => {
@@ -5184,15 +5441,15 @@ function getPdfAvailableWidth(width) {
5184
5441
  const gutter = width < 160 ? 16 : 32;
5185
5442
  return Math.max(1, width - gutter);
5186
5443
  }
5187
- function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor) {
5444
+ function renderPdfSummary(summary, pages, pagesMeta, fit, zoomFactor, messages) {
5188
5445
  summary.replaceChildren();
5189
- appendPdfSummary(summary, "\u9875\u6570", String(pages));
5446
+ appendPdfSummary(summary, messages.pdfSummaryPages, String(pages));
5190
5447
  const pageSizes = formatPdfPageSizes(pagesMeta);
5191
5448
  if (pageSizes) {
5192
- appendPdfSummary(summary, "\u9875\u9762\u5C3A\u5BF8", pageSizes);
5449
+ appendPdfSummary(summary, messages.pdfSummaryPageSizes, pageSizes);
5193
5450
  }
5194
- appendPdfSummary(summary, "\u9002\u914D", fit === "actual" ? "\u539F\u59CB\u5927\u5C0F" : "\u9002\u5408\u5BBD\u5EA6");
5195
- appendPdfSummary(summary, "\u7F29\u653E", `${Math.round(zoomFactor * 100)}%`);
5451
+ appendPdfSummary(summary, messages.pdfSummaryFit, fit === "actual" ? messages.pdfSummaryActualSize : messages.pdfSummaryFitWidth);
5452
+ appendPdfSummary(summary, messages.pdfSummaryZoom, `${Math.round(zoomFactor * 100)}%`);
5196
5453
  }
5197
5454
  function appendPdfSummary(parent, label, value) {
5198
5455
  const item = document.createElement("span");
@@ -5282,7 +5539,7 @@ function createPageStatus(className, text) {
5282
5539
  status.textContent = text;
5283
5540
  return status;
5284
5541
  }
5285
- function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8\u5931\u8D25") {
5542
+ function createPdfFallback(fileName, url, message, messages, titleText = messages.pdfPreviewFailedTitle) {
5286
5543
  if (isEmbeddableRemoteUrl(url)) {
5287
5544
  return createPdfWebFallback(fileName, url);
5288
5545
  }
@@ -5295,7 +5552,7 @@ function createPdfFallback(fileName, url, message, titleText = "PDF \u9884\u89C8
5295
5552
  const download = document.createElement("a");
5296
5553
  download.href = url;
5297
5554
  download.download = fileName;
5298
- download.textContent = "\u4E0B\u8F7D PDF";
5555
+ download.textContent = messages.pdfDownload;
5299
5556
  fallback.append(title, meta, download);
5300
5557
  return fallback;
5301
5558
  }
@@ -5314,24 +5571,110 @@ function createPdfWebFallback(fileName, url) {
5314
5571
  function isEmbeddableRemoteUrl(url) {
5315
5572
  return /^https?:\/\//i.test(url);
5316
5573
  }
5317
- function normalizePdfError(error) {
5574
+ function normalizePdfError(error, messages) {
5318
5575
  const message = error instanceof Error ? error.message : String(error || "");
5319
5576
  const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
5320
5577
  const lower = `${name} ${message}`.toLowerCase();
5321
5578
  if (lower.includes("invalid") || lower.includes("missing") || lower.includes("corrupt")) {
5322
- return "\u8BE5 PDF \u6587\u4EF6\u53EF\u80FD\u5DF2\u635F\u574F\u6216\u683C\u5F0F\u65E0\u6548\u3002";
5579
+ return messages.pdfCorruptedMessage;
5323
5580
  }
5324
- return "\u5F53\u524D\u6D4F\u89C8\u5668\u65E0\u6CD5\u52A0\u8F7D\u8BE5 PDF\u3002";
5581
+ return messages.pdfCannotLoadMessage;
5582
+ }
5583
+ function createPdfPageNavigator(total, messages, onChange) {
5584
+ const element = document.createElement("div");
5585
+ element.className = "ofv-pdf-page-navigator";
5586
+ const previous = document.createElement("button");
5587
+ previous.type = "button";
5588
+ previous.textContent = "\u2039";
5589
+ previous.title = messages.pdfPreviousPage;
5590
+ previous.setAttribute("aria-label", messages.pdfPreviousPage);
5591
+ const input = document.createElement("input");
5592
+ input.type = "number";
5593
+ input.min = "1";
5594
+ input.max = String(total);
5595
+ input.value = "1";
5596
+ input.inputMode = "numeric";
5597
+ input.setAttribute("aria-label", messages.pdfPageInput);
5598
+ const position = document.createElement("span");
5599
+ position.textContent = formatPreviewMessage(messages.pdfPagePosition, { total });
5600
+ const next = document.createElement("button");
5601
+ next.type = "button";
5602
+ next.textContent = "\u203A";
5603
+ next.title = messages.pdfNextPage;
5604
+ next.setAttribute("aria-label", messages.pdfNextPage);
5605
+ const commit = () => onChange(Number(input.value));
5606
+ const handleKeydown = (event) => {
5607
+ if (event.key === "Enter") {
5608
+ commit();
5609
+ }
5610
+ };
5611
+ const handlePrevious = () => onChange(Number(input.value) - 1);
5612
+ const handleNext = () => onChange(Number(input.value) + 1);
5613
+ input.addEventListener("change", commit);
5614
+ input.addEventListener("keydown", handleKeydown);
5615
+ previous.addEventListener("click", handlePrevious);
5616
+ next.addEventListener("click", handleNext);
5617
+ element.append(previous, input, position, next);
5618
+ return {
5619
+ element,
5620
+ setCurrent(page) {
5621
+ input.value = String(page);
5622
+ previous.disabled = page <= 1;
5623
+ next.disabled = page >= total;
5624
+ },
5625
+ destroy() {
5626
+ input.removeEventListener("change", commit);
5627
+ input.removeEventListener("keydown", handleKeydown);
5628
+ previous.removeEventListener("click", handlePrevious);
5629
+ next.removeEventListener("click", handleNext);
5630
+ }
5631
+ };
5325
5632
  }
5326
- function configurePdfWorker(pdf, workerSrc) {
5633
+ function configurePdfWorker(pdf, workerSrc, legacy = false) {
5327
5634
  if (workerSrc) {
5328
5635
  pdf.GlobalWorkerOptions.workerSrc = workerSrc;
5329
5636
  return;
5330
5637
  }
5331
5638
  if (!pdf.GlobalWorkerOptions.workerSrc && typeof window !== "undefined") {
5332
- pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/build/pdf.worker.mjs`;
5639
+ const build = legacy ? "legacy/build" : "build";
5640
+ pdf.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdf.version}/${build}/pdf.worker.mjs`;
5333
5641
  }
5334
5642
  }
5643
+ function shouldUseLegacyPdfCompatibility(mode = "auto") {
5644
+ if (mode === "legacy") {
5645
+ return true;
5646
+ }
5647
+ if (mode === "modern") {
5648
+ return false;
5649
+ }
5650
+ const promise = Promise;
5651
+ if (typeof promise.withResolvers !== "function") {
5652
+ return true;
5653
+ }
5654
+ if (typeof navigator === "undefined") {
5655
+ return false;
5656
+ }
5657
+ return /(?:QIHU|360SE|360EE)/i.test(navigator.userAgent);
5658
+ }
5659
+ function installPromiseWithResolversPolyfill() {
5660
+ const promise = Promise;
5661
+ if (typeof promise.withResolvers === "function") {
5662
+ return;
5663
+ }
5664
+ Object.defineProperty(promise, "withResolvers", {
5665
+ configurable: true,
5666
+ writable: true,
5667
+ value: () => {
5668
+ let resolve;
5669
+ let reject;
5670
+ const pending = new Promise((resolvePromise, rejectPromise) => {
5671
+ resolve = resolvePromise;
5672
+ reject = rejectPromise;
5673
+ });
5674
+ return { promise: pending, resolve, reject };
5675
+ }
5676
+ });
5677
+ }
5335
5678
 
5336
5679
  // src/plugins/epub.ts
5337
5680
  var import_jszip = __toESM(require("jszip"), 1);
@@ -7725,8 +8068,9 @@ async function renderConvertedOfficePreview(panel, ctx, options, conversionConte
7725
8068
  fit: ctx.options.fit,
7726
8069
  zoom: ctx.options.zoom,
7727
8070
  toolbar: ctx.toolbar,
7728
- title: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
7729
- fallbackTitle: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
8071
+ messages: ctx.options.messages,
8072
+ title: ctx.options.messages.officeConvertedTitle,
8073
+ fallbackTitle: ctx.options.messages.officeConvertedPdfFailed,
7730
8074
  revokeUrlOnDestroy: converted.revokeUrlOnDestroy
7731
8075
  });
7732
8076
  }
@@ -12799,9 +13143,9 @@ function getIcon(name, dir) {
12799
13143
  }
12800
13144
 
12801
13145
  // src/plugins/email.ts
12802
- var import_dompurify3 = __toESM(require("dompurify"), 1);
12803
13146
  var emailExtensions = /* @__PURE__ */ new Set(["eml", "msg", "mbox"]);
12804
13147
  var emailMimeTypes = /* @__PURE__ */ new Set(["message/rfc822", "application/vnd.ms-outlook", "application/mbox"]);
13148
+ var domPurifyLoader;
12805
13149
  var emailMimeFormatMap = {
12806
13150
  "message/rfc822": "eml",
12807
13151
  "application/vnd.ms-outlook": "msg",
@@ -12814,6 +13158,8 @@ function emailPlugin() {
12814
13158
  return emailExtensions.has(file.extension) || emailMimeTypes.has(file.mimeType);
12815
13159
  },
12816
13160
  async render(ctx) {
13161
+ const DOMPurifyModule = await (domPurifyLoader ||= import("dompurify"));
13162
+ const DOMPurify3 = DOMPurifyModule.default;
12817
13163
  const panel = createPanel("ofv-email");
12818
13164
  ctx.viewport.append(panel);
12819
13165
  const url = createObjectUrl(ctx.file);
@@ -12947,7 +13293,7 @@ function emailPlugin() {
12947
13293
  }
12948
13294
  });
12949
13295
  html = nextHtml;
12950
- const sanitizedHtml = sanitizeEmailHtml(html);
13296
+ const sanitizedHtml = sanitizeEmailHtml(html, DOMPurify3);
12951
13297
  const iframe = document.createElement("iframe");
12952
13298
  iframe.className = "ofv-email-body-iframe";
12953
13299
  iframe.setAttribute("sandbox", "allow-same-origin allow-popups allow-popups-to-escape-sandbox");
@@ -13240,8 +13586,8 @@ function getMimeType(name) {
13240
13586
  };
13241
13587
  return ext ? map[ext] || "application/octet-stream" : "application/octet-stream";
13242
13588
  }
13243
- function sanitizeEmailHtml(html) {
13244
- return import_dompurify3.default.sanitize(html, {
13589
+ function sanitizeEmailHtml(html, purifier) {
13590
+ return purifier.sanitize(html, {
13245
13591
  USE_PROFILES: { html: true },
13246
13592
  ADD_ATTR: ["target"],
13247
13593
  ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|blob|cid):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i