jit-viewer 1.0.2 → 1.0.4

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
@@ -26,7 +26,9 @@ const EXTENSION_MAP = {
26
26
  "txt": "txt",
27
27
  "md": "md",
28
28
  "markdown": "markdown",
29
- "ofd": "ofd"
29
+ "ofd": "ofd",
30
+ "html": "html",
31
+ "htm": "html"
30
32
  };
31
33
  const MIME_MAP = {
32
34
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
@@ -38,7 +40,9 @@ const MIME_MAP = {
38
40
  "text/plain": "txt",
39
41
  "text/markdown": "md",
40
42
  "text/x-markdown": "md",
41
- "application/ofd": "ofd"
43
+ "application/ofd": "ofd",
44
+ "text/html": "html",
45
+ "application/xhtml+xml": "html"
42
46
  };
43
47
  function getFileExtension(filename) {
44
48
  const match = filename.toLowerCase().match(/\.([a-z0-9]+)$/);
@@ -94,7 +98,7 @@ function getFilename(source, fallback) {
94
98
  }
95
99
  return fallback || "unknown";
96
100
  }
97
- async function fileToArrayBuffer(source) {
101
+ async function fileToArrayBuffer(source, options) {
98
102
  if (source instanceof ArrayBuffer) {
99
103
  return source;
100
104
  }
@@ -110,34 +114,93 @@ async function fileToArrayBuffer(source) {
110
114
  return source.arrayBuffer();
111
115
  }
112
116
  if (typeof source === "string") {
113
- const response = await fetch(source);
114
- if (!response.ok) {
115
- throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`);
116
- }
117
- return response.arrayBuffer();
117
+ return fetchWithProxy(source, {}, options);
118
118
  }
119
119
  if (typeof source === "object" && "url" in source) {
120
120
  const { url, headers = {}, method = "GET", body } = source;
121
+ return fetchWithProxy(url, { headers, method, body }, options);
122
+ }
123
+ throw new Error("Unsupported file source type");
124
+ }
125
+ const BUILTIN_CORS_PROXIES = [
126
+ "https://corsproxy.io/?",
127
+ "https://api.allorigins.win/raw?url="
128
+ ];
129
+ function isCrossOriginUrl(url) {
130
+ try {
131
+ const urlObj = new URL(url, window.location.origin);
132
+ if (urlObj.origin === window.location.origin) {
133
+ return false;
134
+ }
135
+ return urlObj.protocol === "http:" || urlObj.protocol === "https:";
136
+ } catch {
137
+ return false;
138
+ }
139
+ }
140
+ async function fetchWithProxy(url, fetchOptions, proxyOptions) {
141
+ if (proxyOptions == null ? void 0 : proxyOptions.requestAdapter) {
142
+ return proxyOptions.requestAdapter(url, fetchOptions);
143
+ }
144
+ if (proxyOptions == null ? void 0 : proxyOptions.proxyUrl) {
145
+ return fetchViaProxy(url, fetchOptions, proxyOptions.proxyUrl);
146
+ }
147
+ try {
121
148
  const response = await fetch(url, {
122
- method,
123
- headers,
124
- body
149
+ ...fetchOptions,
150
+ mode: "cors"
125
151
  });
126
- if (!response.ok) {
127
- throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`);
152
+ if (response.ok) {
153
+ return response.arrayBuffer();
128
154
  }
129
- return response.arrayBuffer();
155
+ throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`);
156
+ } catch (error) {
157
+ if (isCrossOriginUrl(url) && isCorsError(error)) {
158
+ console.warn("[jit-viewer] Direct fetch failed due to CORS, trying builtin proxy...");
159
+ return fetchViaBuiltinProxy(url, fetchOptions);
160
+ }
161
+ throw error;
130
162
  }
131
- throw new Error("Unsupported file source type");
132
163
  }
133
- async function fileToBlob(source) {
164
+ function isCorsError(error) {
165
+ var _a;
166
+ const message = ((_a = error == null ? void 0 : error.message) == null ? void 0 : _a.toLowerCase()) || "";
167
+ return message.includes("cors") || message.includes("failed to fetch") || message.includes("network error") || (error == null ? void 0 : error.name) === "TypeError";
168
+ }
169
+ async function fetchViaProxy(url, fetchOptions, proxyUrl) {
170
+ const finalUrl = proxyUrl.includes("?") ? `${proxyUrl}${encodeURIComponent(url)}` : `${proxyUrl}?url=${encodeURIComponent(url)}`;
171
+ const response = await fetch(finalUrl, {
172
+ method: "GET",
173
+ headers: fetchOptions.headers
174
+ });
175
+ if (!response.ok) {
176
+ throw new Error(`Proxy request failed: ${response.status} ${response.statusText}`);
177
+ }
178
+ return response.arrayBuffer();
179
+ }
180
+ async function fetchViaBuiltinProxy(url, fetchOptions) {
181
+ let lastError = null;
182
+ for (const proxyUrl of BUILTIN_CORS_PROXIES) {
183
+ try {
184
+ const buffer = await fetchViaProxy(url, fetchOptions, proxyUrl);
185
+ console.log(`[jit-viewer] Successfully fetched via proxy: ${proxyUrl}`);
186
+ return buffer;
187
+ } catch (error) {
188
+ lastError = error;
189
+ console.warn(`[jit-viewer] Proxy ${proxyUrl} failed:`, error.message);
190
+ }
191
+ }
192
+ throw new Error(
193
+ `Failed to fetch file. All CORS proxies failed. Last error: ${(lastError == null ? void 0 : lastError.message) || "Unknown error"}. Please consider: 1) Upload the file instead of using URL, 2) Configure your own proxy server via 'proxyUrl' option`
194
+ );
195
+ }
196
+ async function fileToBlob(source, options) {
134
197
  if (source instanceof Blob) {
135
198
  return source;
136
199
  }
137
200
  if (source instanceof ArrayBuffer) {
138
201
  return new Blob([source]);
139
202
  }
140
- const buffer = await fileToArrayBuffer(source);
203
+ const buffer = await fileToArrayBuffer(source, options);
141
204
  return new Blob([buffer]);
142
205
  }
143
206
  async function fileToUrl(source) {
@@ -175,7 +238,8 @@ function isSupportedType(type) {
175
238
  "txt",
176
239
  "md",
177
240
  "markdown",
178
- "ofd"
241
+ "ofd",
242
+ "html"
179
243
  ].includes(type);
180
244
  }
181
245
  function createEventBus() {
@@ -830,13 +894,13 @@ function useViewerState() {
830
894
  }
831
895
  return context;
832
896
  }
833
- const _hoisted_1$9 = ["disabled", "title"];
834
- const _hoisted_2$6 = { class: "jv-toolbar-btn__icon" };
897
+ const _hoisted_1$a = ["disabled", "title"];
898
+ const _hoisted_2$7 = { class: "jv-toolbar-btn__icon" };
835
899
  const _hoisted_3$2 = {
836
900
  key: 0,
837
901
  class: "jv-toolbar-btn__label"
838
902
  };
839
- const _sfc_main$d = /* @__PURE__ */ defineComponent({
903
+ const _sfc_main$e = /* @__PURE__ */ defineComponent({
840
904
  __name: "ActionButton",
841
905
  props: {
842
906
  type: {},
@@ -860,11 +924,11 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
860
924
  title: __props.title,
861
925
  onClick: handleClick
862
926
  }, [
863
- createElementVNode("span", _hoisted_2$6, [
927
+ createElementVNode("span", _hoisted_2$7, [
864
928
  renderSlot(_ctx.$slots, "default", {}, void 0, true)
865
929
  ]),
866
930
  __props.label ? (openBlock(), createElementBlock("span", _hoisted_3$2, toDisplayString(__props.label), 1)) : createCommentVNode("", true)
867
- ], 10, _hoisted_1$9);
931
+ ], 10, _hoisted_1$a);
868
932
  };
869
933
  }
870
934
  });
@@ -875,11 +939,11 @@ const _export_sfc = (sfc, props) => {
875
939
  }
876
940
  return target;
877
941
  };
878
- const ActionButton = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-9abd52f0"]]);
879
- const _hoisted_1$8 = { class: "jv-zoom-control" };
880
- const _hoisted_2$5 = { class: "jv-zoom-control__value" };
942
+ const ActionButton = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["__scopeId", "data-v-9abd52f0"]]);
943
+ const _hoisted_1$9 = { class: "jv-zoom-control" };
944
+ const _hoisted_2$6 = { class: "jv-zoom-control__value" };
881
945
  const ZOOM_STEP = 0.1;
882
- const _sfc_main$c = /* @__PURE__ */ defineComponent({
946
+ const _sfc_main$d = /* @__PURE__ */ defineComponent({
883
947
  __name: "ZoomControl",
884
948
  setup(__props) {
885
949
  const { t } = useLocale();
@@ -894,7 +958,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
894
958
  resetTransform();
895
959
  }
896
960
  return (_ctx, _cache) => {
897
- return openBlock(), createElementBlock("div", _hoisted_1$8, [
961
+ return openBlock(), createElementBlock("div", _hoisted_1$9, [
898
962
  createVNode(ActionButton, {
899
963
  type: "zoom-out",
900
964
  title: unref(t)("toolbar.zoomOut"),
@@ -928,7 +992,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
928
992
  ])]),
929
993
  _: 1
930
994
  }, 8, ["title"]),
931
- createElementVNode("span", _hoisted_2$5, toDisplayString(Math.round(unref(zoom) * 100)) + "%", 1),
995
+ createElementVNode("span", _hoisted_2$6, toDisplayString(Math.round(unref(zoom) * 100)) + "%", 1),
932
996
  createVNode(ActionButton, {
933
997
  type: "zoom-in",
934
998
  title: unref(t)("toolbar.zoomIn"),
@@ -1002,10 +1066,10 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1002
1066
  };
1003
1067
  }
1004
1068
  });
1005
- const ZoomControl = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-874ddbac"]]);
1006
- const _hoisted_1$7 = { class: "jv-rotate-control" };
1069
+ const ZoomControl = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-874ddbac"]]);
1070
+ const _hoisted_1$8 = { class: "jv-rotate-control" };
1007
1071
  const ROTATE_STEP = 90;
1008
- const _sfc_main$b = /* @__PURE__ */ defineComponent({
1072
+ const _sfc_main$c = /* @__PURE__ */ defineComponent({
1009
1073
  __name: "RotateControl",
1010
1074
  setup(__props) {
1011
1075
  const { t } = useLocale();
@@ -1017,7 +1081,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1017
1081
  setRotate(ROTATE_STEP);
1018
1082
  }
1019
1083
  return (_ctx, _cache) => {
1020
- return openBlock(), createElementBlock("div", _hoisted_1$7, [
1084
+ return openBlock(), createElementBlock("div", _hoisted_1$8, [
1021
1085
  createVNode(ActionButton, {
1022
1086
  type: "rotate-left",
1023
1087
  title: unref(t)("toolbar.rotateLeft"),
@@ -1056,22 +1120,22 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1056
1120
  };
1057
1121
  }
1058
1122
  });
1059
- const RotateControl = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-ad291658"]]);
1060
- const _hoisted_1$6 = {
1123
+ const RotateControl = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-ad291658"]]);
1124
+ const _hoisted_1$7 = {
1061
1125
  key: 0,
1062
1126
  viewBox: "0 0 24 24",
1063
1127
  fill: "none",
1064
1128
  stroke: "currentColor",
1065
1129
  "stroke-width": "2"
1066
1130
  };
1067
- const _hoisted_2$4 = {
1131
+ const _hoisted_2$5 = {
1068
1132
  key: 1,
1069
1133
  viewBox: "0 0 24 24",
1070
1134
  fill: "none",
1071
1135
  stroke: "currentColor",
1072
1136
  "stroke-width": "2"
1073
1137
  };
1074
- const _sfc_main$a = /* @__PURE__ */ defineComponent({
1138
+ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1075
1139
  __name: "FullscreenButton",
1076
1140
  setup(__props) {
1077
1141
  const { t } = useLocale();
@@ -1100,9 +1164,9 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1100
1164
  onClick: toggleFullscreen
1101
1165
  }, {
1102
1166
  default: withCtx(() => [
1103
- !isFullscreen.value ? (openBlock(), createElementBlock("svg", _hoisted_1$6, [..._cache[0] || (_cache[0] = [
1167
+ !isFullscreen.value ? (openBlock(), createElementBlock("svg", _hoisted_1$7, [..._cache[0] || (_cache[0] = [
1104
1168
  createElementVNode("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }, null, -1)
1105
- ])])) : (openBlock(), createElementBlock("svg", _hoisted_2$4, [..._cache[1] || (_cache[1] = [
1169
+ ])])) : (openBlock(), createElementBlock("svg", _hoisted_2$5, [..._cache[1] || (_cache[1] = [
1106
1170
  createElementVNode("path", { d: "M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" }, null, -1)
1107
1171
  ])]))
1108
1172
  ]),
@@ -1111,18 +1175,18 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1111
1175
  };
1112
1176
  }
1113
1177
  });
1114
- const _hoisted_1$5 = {
1178
+ const _hoisted_1$6 = {
1115
1179
  key: 0,
1116
1180
  class: "jv-pagination"
1117
1181
  };
1118
- const _hoisted_2$3 = { class: "jv-pagination__info" };
1119
- const _sfc_main$9 = /* @__PURE__ */ defineComponent({
1182
+ const _hoisted_2$4 = { class: "jv-pagination__info" };
1183
+ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1120
1184
  __name: "Pagination",
1121
1185
  setup(__props) {
1122
1186
  const { t } = useLocale();
1123
1187
  const { currentPage, totalPages, prevPage, nextPage } = useViewerState();
1124
1188
  return (_ctx, _cache) => {
1125
- return unref(totalPages) > 1 ? (openBlock(), createElementBlock("div", _hoisted_1$5, [
1189
+ return unref(totalPages) > 1 ? (openBlock(), createElementBlock("div", _hoisted_1$6, [
1126
1190
  createVNode(ActionButton, {
1127
1191
  type: "prev",
1128
1192
  title: unref(t)("toolbar.prevPage"),
@@ -1141,7 +1205,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
1141
1205
  ])]),
1142
1206
  _: 1
1143
1207
  }, 8, ["title", "disabled", "onClick"]),
1144
- createElementVNode("span", _hoisted_2$3, toDisplayString(unref(t)("toolbar.pageInfo", { current: unref(currentPage).toString(), total: unref(totalPages).toString() })), 1),
1208
+ createElementVNode("span", _hoisted_2$4, toDisplayString(unref(t)("toolbar.pageInfo", { current: unref(currentPage).toString(), total: unref(totalPages).toString() })), 1),
1145
1209
  createVNode(ActionButton, {
1146
1210
  type: "next",
1147
1211
  title: unref(t)("toolbar.nextPage"),
@@ -1164,12 +1228,12 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
1164
1228
  };
1165
1229
  }
1166
1230
  });
1167
- const Pagination = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-97c0759f"]]);
1168
- const _hoisted_1$4 = {
1231
+ const Pagination = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-97c0759f"]]);
1232
+ const _hoisted_1$5 = {
1169
1233
  key: 0,
1170
1234
  class: "jv-toolbar__top"
1171
1235
  };
1172
- const _hoisted_2$2 = { class: "jv-toolbar__left" };
1236
+ const _hoisted_2$3 = { class: "jv-toolbar__left" };
1173
1237
  const _hoisted_3$1 = {
1174
1238
  key: 0,
1175
1239
  class: "jv-toolbar__filename"
@@ -1181,9 +1245,9 @@ const _hoisted_6$1 = {
1181
1245
  class: "jv-toolbar__bottom"
1182
1246
  };
1183
1247
  const _hoisted_7$1 = { class: "jv-toolbar__left" };
1184
- const _hoisted_8 = { class: "jv-toolbar__center" };
1248
+ const _hoisted_8$1 = { class: "jv-toolbar__center" };
1185
1249
  const _hoisted_9 = { class: "jv-toolbar__right" };
1186
- const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1250
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
1187
1251
  __name: "Toolbar",
1188
1252
  props: {
1189
1253
  config: {},
@@ -1376,8 +1440,8 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1376
1440
  return openBlock(), createElementBlock("div", {
1377
1441
  class: normalizeClass(["jv-toolbar", [positionClass.value, { "jv-toolbar--hidden": !__props.visible }]])
1378
1442
  }, [
1379
- showTop.value ? (openBlock(), createElementBlock("div", _hoisted_1$4, [
1380
- createElementVNode("div", _hoisted_2$2, [
1443
+ showTop.value ? (openBlock(), createElementBlock("div", _hoisted_1$5, [
1444
+ createElementVNode("div", _hoisted_2$3, [
1381
1445
  renderSlot(_ctx.$slots, "top-left", {}, () => [
1382
1446
  unref(filename) ? (openBlock(), createElementBlock("span", _hoisted_3$1, toDisplayString(unref(filename)), 1)) : createCommentVNode("", true)
1383
1447
  ], true)
@@ -1389,7 +1453,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1389
1453
  renderSlot(_ctx.$slots, "top-right", {}, () => [
1390
1454
  hasItem("zoom") ? (openBlock(), createBlock(ZoomControl, { key: 0 })) : createCommentVNode("", true),
1391
1455
  hasItem("rotate") ? (openBlock(), createBlock(RotateControl, { key: 1 })) : createCommentVNode("", true),
1392
- hasItem("fullscreen") ? (openBlock(), createBlock(_sfc_main$a, { key: 2 })) : createCommentVNode("", true)
1456
+ hasItem("fullscreen") ? (openBlock(), createBlock(_sfc_main$b, { key: 2 })) : createCommentVNode("", true)
1393
1457
  ], true)
1394
1458
  ])
1395
1459
  ])) : createCommentVNode("", true),
@@ -1399,7 +1463,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1399
1463
  hasItem("pagination") ? (openBlock(), createBlock(Pagination, { key: 0 })) : createCommentVNode("", true)
1400
1464
  ], true)
1401
1465
  ]),
1402
- createElementVNode("div", _hoisted_8, [
1466
+ createElementVNode("div", _hoisted_8$1, [
1403
1467
  renderSlot(_ctx.$slots, "bottom-center", {}, void 0, true)
1404
1468
  ]),
1405
1469
  createElementVNode("div", _hoisted_9, [
@@ -1450,12 +1514,14 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1450
1514
  };
1451
1515
  }
1452
1516
  });
1453
- const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-715b4e5f"]]);
1454
- const _sfc_main$7 = /* @__PURE__ */ defineComponent({
1517
+ const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-715b4e5f"]]);
1518
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
1455
1519
  __name: "DocxRender",
1456
1520
  props: {
1457
1521
  source: {},
1458
- zoom: {}
1522
+ zoom: {},
1523
+ proxyUrl: {},
1524
+ requestAdapter: { type: Function }
1459
1525
  },
1460
1526
  emits: ["load", "error"],
1461
1527
  setup(__props, { emit: __emit }) {
@@ -1471,7 +1537,10 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
1471
1537
  async function loadFile() {
1472
1538
  try {
1473
1539
  loading.value = true;
1474
- src.value = await fileToArrayBuffer(props.source);
1540
+ src.value = await fileToArrayBuffer(props.source, {
1541
+ proxyUrl: props.proxyUrl,
1542
+ requestAdapter: props.requestAdapter
1543
+ });
1475
1544
  } catch (error) {
1476
1545
  handleError(error);
1477
1546
  }
@@ -1501,12 +1570,14 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
1501
1570
  };
1502
1571
  }
1503
1572
  });
1504
- const DocxRender = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-64a29f11"]]);
1505
- const _sfc_main$6 = /* @__PURE__ */ defineComponent({
1573
+ const DocxRender = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-9181c8b1"]]);
1574
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
1506
1575
  __name: "ExcelRender",
1507
1576
  props: {
1508
1577
  source: {},
1509
- zoom: {}
1578
+ zoom: {},
1579
+ proxyUrl: {},
1580
+ requestAdapter: { type: Function }
1510
1581
  },
1511
1582
  emits: ["load", "error"],
1512
1583
  setup(__props, { emit: __emit }) {
@@ -1522,7 +1593,10 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
1522
1593
  async function loadFile() {
1523
1594
  try {
1524
1595
  loading.value = true;
1525
- src.value = await fileToArrayBuffer(props.source);
1596
+ src.value = await fileToArrayBuffer(props.source, {
1597
+ proxyUrl: props.proxyUrl,
1598
+ requestAdapter: props.requestAdapter
1599
+ });
1526
1600
  } catch (error) {
1527
1601
  handleError(error);
1528
1602
  }
@@ -1552,12 +1626,14 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
1552
1626
  };
1553
1627
  }
1554
1628
  });
1555
- const ExcelRender = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-ebc546c0"]]);
1556
- const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1629
+ const ExcelRender = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-a8c7c89f"]]);
1630
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
1557
1631
  __name: "PdfRender",
1558
1632
  props: {
1559
1633
  source: {},
1560
- zoom: {}
1634
+ zoom: {},
1635
+ proxyUrl: {},
1636
+ requestAdapter: { type: Function }
1561
1637
  },
1562
1638
  emits: ["load", "error"],
1563
1639
  setup(__props, { emit: __emit }) {
@@ -1573,7 +1649,10 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1573
1649
  async function loadFile() {
1574
1650
  try {
1575
1651
  loading.value = true;
1576
- src.value = await fileToArrayBuffer(props.source);
1652
+ src.value = await fileToArrayBuffer(props.source, {
1653
+ proxyUrl: props.proxyUrl,
1654
+ requestAdapter: props.requestAdapter
1655
+ });
1577
1656
  } catch (error) {
1578
1657
  handleError(error);
1579
1658
  }
@@ -1603,12 +1682,14 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1603
1682
  };
1604
1683
  }
1605
1684
  });
1606
- const PdfRender = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-cf0a921e"]]);
1607
- const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1685
+ const PdfRender = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-db81b2b3"]]);
1686
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1608
1687
  __name: "PptxRender",
1609
1688
  props: {
1610
1689
  source: {},
1611
- zoom: {}
1690
+ zoom: {},
1691
+ proxyUrl: {},
1692
+ requestAdapter: { type: Function }
1612
1693
  },
1613
1694
  emits: ["load", "error"],
1614
1695
  setup(__props, { emit: __emit }) {
@@ -1624,7 +1705,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1624
1705
  async function loadFile() {
1625
1706
  try {
1626
1707
  loading.value = true;
1627
- src.value = await fileToArrayBuffer(props.source);
1708
+ src.value = await fileToArrayBuffer(props.source, {
1709
+ proxyUrl: props.proxyUrl,
1710
+ requestAdapter: props.requestAdapter
1711
+ });
1628
1712
  } catch (error) {
1629
1713
  handleError(error);
1630
1714
  }
@@ -1654,9 +1738,9 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1654
1738
  };
1655
1739
  }
1656
1740
  });
1657
- const PptxRender = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-a181a5b5"]]);
1658
- const _hoisted_1$3 = { class: "jv-text-content" };
1659
- const _sfc_main$3 = /* @__PURE__ */ defineComponent({
1741
+ const PptxRender = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-b31abca4"]]);
1742
+ const _hoisted_1$4 = { class: "jv-text-content" };
1743
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1660
1744
  __name: "TextRender",
1661
1745
  props: {
1662
1746
  source: {}
@@ -1688,14 +1772,14 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
1688
1772
  ref: containerRef,
1689
1773
  class: "jv-file-render jv-file-render--text"
1690
1774
  }, [
1691
- createElementVNode("pre", _hoisted_1$3, toDisplayString(content.value), 1)
1775
+ createElementVNode("pre", _hoisted_1$4, toDisplayString(content.value), 1)
1692
1776
  ], 512);
1693
1777
  };
1694
1778
  }
1695
1779
  });
1696
- const TextRender = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-f5957104"]]);
1697
- const _hoisted_1$2 = ["innerHTML"];
1698
- const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1780
+ const TextRender = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-f5957104"]]);
1781
+ const _hoisted_1$3 = ["innerHTML"];
1782
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
1699
1783
  __name: "MarkdownRender",
1700
1784
  props: {
1701
1785
  source: {}
@@ -1737,12 +1821,12 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1737
1821
  createElementVNode("div", {
1738
1822
  class: "jv-markdown-content",
1739
1823
  innerHTML: renderedContent.value
1740
- }, null, 8, _hoisted_1$2)
1824
+ }, null, 8, _hoisted_1$3)
1741
1825
  ], 512);
1742
1826
  };
1743
1827
  }
1744
1828
  });
1745
- const MarkdownRender = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-9b60bb2a"]]);
1829
+ const MarkdownRender = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-9b60bb2a"]]);
1746
1830
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
1747
1831
  var dist = { exports: {} };
1748
1832
  /*! For license information please see index.js.LICENSE.txt */
@@ -27306,11 +27390,13 @@ const installHighDpiCanvasPatch = (totalPages) => {
27306
27390
  };
27307
27391
  };
27308
27392
  class LiteOfdAdapter {
27309
- constructor(pageStyle = DEFAULT_PAGE_STYLE) {
27393
+ constructor(pageStyle = DEFAULT_PAGE_STYLE, proxyOptions) {
27310
27394
  __publicField(this, "instance", null);
27311
27395
  __publicField(this, "pageStyle");
27312
27396
  __publicField(this, "restoreCanvasPatch", null);
27397
+ __publicField(this, "proxyOptions");
27313
27398
  this.pageStyle = pageStyle;
27399
+ this.proxyOptions = proxyOptions;
27314
27400
  }
27315
27401
  get currentPage() {
27316
27402
  var _a;
@@ -27330,7 +27416,7 @@ class LiteOfdAdapter {
27330
27416
  async load(source) {
27331
27417
  var _a, _b, _c, _d, _e;
27332
27418
  this.destroy();
27333
- const buffer = await fileToArrayBuffer(source);
27419
+ const buffer = await fileToArrayBuffer(source, this.proxyOptions);
27334
27420
  const liteOfd = new distExports.LiteOfd();
27335
27421
  const parsedDocument = await liteOfd.parse(buffer);
27336
27422
  try {
@@ -27375,16 +27461,18 @@ class LiteOfdAdapter {
27375
27461
  this.instance = null;
27376
27462
  }
27377
27463
  }
27378
- const _hoisted_1$1 = {
27464
+ const _hoisted_1$2 = {
27379
27465
  key: 0,
27380
27466
  class: "jv-ofd-error"
27381
27467
  };
27382
- const _hoisted_2$1 = { class: "jv-ofd-loading" };
27383
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27468
+ const _hoisted_2$2 = { class: "jv-ofd-loading" };
27469
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
27384
27470
  __name: "OfdRender",
27385
27471
  props: {
27386
27472
  source: {},
27387
- zoom: { default: 1 }
27473
+ zoom: { default: 1 },
27474
+ proxyUrl: {},
27475
+ requestAdapter: {}
27388
27476
  },
27389
27477
  emits: ["error", "load", "pageChange"],
27390
27478
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -27518,7 +27606,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27518
27606
  async function loadFile() {
27519
27607
  if (!ofdContainer.value) return;
27520
27608
  const loadToken = ++activeLoadToken;
27521
- const nextAdapter = new LiteOfdAdapter();
27609
+ const nextAdapter = new LiteOfdAdapter(void 0, {
27610
+ proxyUrl: props.proxyUrl,
27611
+ requestAdapter: props.requestAdapter
27612
+ });
27522
27613
  cleanup();
27523
27614
  loading.value = true;
27524
27615
  error.value = "";
@@ -27606,7 +27697,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27606
27697
  ref: containerRef,
27607
27698
  class: "jv-file-render jv-file-render--ofd"
27608
27699
  }, [
27609
- error.value ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
27700
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_1$2, [
27610
27701
  createElementVNode("span", null, toDisplayString(error.value), 1)
27611
27702
  ])) : (openBlock(), createElementBlock("div", {
27612
27703
  key: 1,
@@ -27625,7 +27716,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27625
27716
  }, null, 512)
27626
27717
  ], 4)
27627
27718
  ], 512)),
27628
- withDirectives(createElementVNode("div", _hoisted_2$1, [
27719
+ withDirectives(createElementVNode("div", _hoisted_2$2, [
27629
27720
  createElementVNode("span", null, toDisplayString(t("loading")), 1)
27630
27721
  ], 512), [
27631
27722
  [vShow, loading.value]
@@ -27634,7 +27725,184 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27634
27725
  };
27635
27726
  }
27636
27727
  });
27637
- const OfdRender = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-36ea2d3f"]]);
27728
+ const OfdRender = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-f933a20c"]]);
27729
+ const _hoisted_1$1 = { class: "jv-html-loading" };
27730
+ const _hoisted_2$1 = {
27731
+ key: 0,
27732
+ class: "jv-html-error"
27733
+ };
27734
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
27735
+ __name: "HtmlRender",
27736
+ props: {
27737
+ source: {},
27738
+ zoom: { default: 1 },
27739
+ proxyUrl: {},
27740
+ requestAdapter: {}
27741
+ },
27742
+ emits: ["load", "error"],
27743
+ setup(__props, { emit: __emit }) {
27744
+ const props = __props;
27745
+ const emit = __emit;
27746
+ const containerRef = ref();
27747
+ const iframeRef = ref();
27748
+ const loading = ref(true);
27749
+ const error = ref("");
27750
+ const renderStyle = computed(() => {
27751
+ if (props.zoom === 1) {
27752
+ return {};
27753
+ }
27754
+ return {
27755
+ transform: `scale(${props.zoom})`,
27756
+ transformOrigin: "top left",
27757
+ width: `${100 / props.zoom}%`,
27758
+ height: `${100 / props.zoom}%`
27759
+ };
27760
+ });
27761
+ async function loadContent() {
27762
+ console.log("[HtmlRender] loadContent called, iframe ready:", !!iframeRef.value, "source:", props.source);
27763
+ if (!iframeRef.value) {
27764
+ console.log("[HtmlRender] iframe not ready, retrying in 100ms...");
27765
+ setTimeout(() => loadContent(), 100);
27766
+ return;
27767
+ }
27768
+ loading.value = true;
27769
+ error.value = "";
27770
+ try {
27771
+ if (!props.source) {
27772
+ console.log("[HtmlRender] no source provided");
27773
+ loading.value = false;
27774
+ return;
27775
+ }
27776
+ if (typeof props.source === "string") {
27777
+ const url = props.source;
27778
+ console.log("[HtmlRender] source is string:", url.substring(0, 100));
27779
+ if (url.startsWith("http://") || url.startsWith("https://")) {
27780
+ console.log("[HtmlRender] loading web URL:", url);
27781
+ iframeRef.value.src = url;
27782
+ loading.value = false;
27783
+ emit("load");
27784
+ return;
27785
+ }
27786
+ if (url.startsWith("data:") || url.startsWith("blob:")) {
27787
+ iframeRef.value.src = url;
27788
+ loading.value = false;
27789
+ emit("load");
27790
+ return;
27791
+ }
27792
+ }
27793
+ if (props.source instanceof File || props.source instanceof Blob) {
27794
+ console.log("[HtmlRender] source is File/Blob");
27795
+ const htmlContent = await readHtmlContent(props.source);
27796
+ console.log("[HtmlRender] read content length:", htmlContent.length);
27797
+ writeHtmlToIframe(htmlContent);
27798
+ return;
27799
+ }
27800
+ if (props.source instanceof ArrayBuffer) {
27801
+ console.log("[HtmlRender] source is ArrayBuffer");
27802
+ const decoder = new TextDecoder();
27803
+ const htmlContent = decoder.decode(props.source);
27804
+ writeHtmlToIframe(htmlContent);
27805
+ return;
27806
+ }
27807
+ if (typeof props.source === "object" && "url" in props.source) {
27808
+ console.log("[HtmlRender] source is config object");
27809
+ const { url } = props.source;
27810
+ if (url.startsWith("http://") || url.startsWith("https://")) {
27811
+ iframeRef.value.src = url;
27812
+ loading.value = false;
27813
+ emit("load");
27814
+ return;
27815
+ }
27816
+ const buffer = await fileToArrayBuffer(props.source, {
27817
+ proxyUrl: props.proxyUrl,
27818
+ requestAdapter: props.requestAdapter
27819
+ });
27820
+ const decoder = new TextDecoder();
27821
+ const htmlContent = decoder.decode(buffer);
27822
+ writeHtmlToIframe(htmlContent);
27823
+ }
27824
+ console.log("[HtmlRender] unknown source type");
27825
+ } catch (err) {
27826
+ console.error("[HtmlRender] load error:", err);
27827
+ handleError(err);
27828
+ }
27829
+ }
27830
+ async function readHtmlContent(source) {
27831
+ return new Promise((resolve, reject) => {
27832
+ const reader = new FileReader();
27833
+ reader.onload = () => resolve(reader.result);
27834
+ reader.onerror = () => reject(new Error("Failed to read HTML file"));
27835
+ reader.readAsText(source);
27836
+ });
27837
+ }
27838
+ function writeHtmlToIframe(html) {
27839
+ if (!iframeRef.value) {
27840
+ handleError(new Error("iframe not ready"));
27841
+ return;
27842
+ }
27843
+ console.log("[HtmlRender] writing HTML to iframe, length:", html.length);
27844
+ try {
27845
+ iframeRef.value.srcdoc = html;
27846
+ requestAnimationFrame(() => {
27847
+ var _a;
27848
+ try {
27849
+ const doc = (_a = iframeRef.value) == null ? void 0 : _a.contentDocument;
27850
+ if (doc) {
27851
+ doc.open();
27852
+ doc.write(html);
27853
+ doc.close();
27854
+ }
27855
+ } catch (e) {
27856
+ console.warn("[HtmlRender] document write failed, but srcdoc is set");
27857
+ }
27858
+ loading.value = false;
27859
+ emit("load");
27860
+ });
27861
+ } catch (err) {
27862
+ console.error("[HtmlRender] write error:", err);
27863
+ handleError(err);
27864
+ }
27865
+ }
27866
+ function handleError(err) {
27867
+ loading.value = false;
27868
+ error.value = err.message || "HTML加载失败";
27869
+ emit("error", err);
27870
+ }
27871
+ watch(() => props.source, (newSource, oldSource) => {
27872
+ if (newSource !== oldSource) {
27873
+ nextTick(() => loadContent());
27874
+ }
27875
+ }, { immediate: false });
27876
+ onMounted(() => {
27877
+ nextTick(() => loadContent());
27878
+ });
27879
+ return (_ctx, _cache) => {
27880
+ return openBlock(), createElementBlock("div", {
27881
+ ref_key: "containerRef",
27882
+ ref: containerRef,
27883
+ class: "jv-file-render jv-file-render--html"
27884
+ }, [
27885
+ createElementVNode("iframe", {
27886
+ ref_key: "iframeRef",
27887
+ ref: iframeRef,
27888
+ class: "jv-html-iframe",
27889
+ style: normalizeStyle(renderStyle.value),
27890
+ sandbox: "allow-scripts allow-same-origin allow-popups allow-forms allow-top-navigation"
27891
+ }, null, 4),
27892
+ withDirectives(createElementVNode("div", _hoisted_1$1, [..._cache[0] || (_cache[0] = [
27893
+ createElementVNode("div", { class: "jv-loading-spinner" }, null, -1),
27894
+ createElementVNode("span", null, "加载中...", -1)
27895
+ ])], 512), [
27896
+ [vShow, loading.value]
27897
+ ]),
27898
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_2$1, [
27899
+ createElementVNode("span", null, toDisplayString(error.value), 1)
27900
+ ])) : createCommentVNode("", true)
27901
+ ], 512);
27902
+ };
27903
+ }
27904
+ });
27905
+ const HtmlRender = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-af6df043"]]);
27638
27906
  const _hoisted_1 = {
27639
27907
  key: 0,
27640
27908
  class: "jv-viewer__error"
@@ -27648,7 +27916,11 @@ const _hoisted_4 = { class: "jv-empty-text" };
27648
27916
  const _hoisted_5 = { class: "jv-viewer__loading-overlay" };
27649
27917
  const _hoisted_6 = { class: "jv-loading-text" };
27650
27918
  const _hoisted_7 = {
27651
- key: 7,
27919
+ key: 8,
27920
+ class: "jv-viewer__unsupported"
27921
+ };
27922
+ const _hoisted_8 = {
27923
+ key: 9,
27652
27924
  class: "jv-viewer__unsupported"
27653
27925
  };
27654
27926
  const _sfc_main = /* @__PURE__ */ defineComponent({
@@ -27666,6 +27938,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27666
27938
  height: { default: "100%" },
27667
27939
  className: {},
27668
27940
  style: {},
27941
+ proxyUrl: {},
27942
+ requestAdapter: {},
27669
27943
  onReady: {},
27670
27944
  onError: {},
27671
27945
  onLoad: {},
@@ -27726,6 +28000,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27726
28000
  }
27727
28001
  return ((_a2 = props.toolbar) == null ? void 0 : _a2.visible) !== false;
27728
28002
  });
28003
+ const proxyUrl = computed(() => props.proxyUrl);
28004
+ const requestAdapter = computed(() => props.requestAdapter);
27729
28005
  function handleLoad() {
27730
28006
  var _a2;
27731
28007
  setLoading(false);
@@ -27930,27 +28206,35 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27930
28206
  key: 0,
27931
28207
  source: unref(fileSource),
27932
28208
  zoom: unref(zoom),
28209
+ "proxy-url": proxyUrl.value,
28210
+ "request-adapter": requestAdapter.value,
27933
28211
  onLoad: handleLoad,
27934
28212
  onError: handleError
27935
- }, null, 8, ["source", "zoom"])) : unref(fileType) === "xlsx" || unref(fileType) === "xls" ? (openBlock(), createBlock(unref(ExcelRender), {
28213
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "xlsx" || unref(fileType) === "xls" ? (openBlock(), createBlock(unref(ExcelRender), {
27936
28214
  key: 1,
27937
28215
  source: unref(fileSource),
27938
28216
  zoom: unref(zoom),
28217
+ "proxy-url": proxyUrl.value,
28218
+ "request-adapter": requestAdapter.value,
27939
28219
  onLoad: handleLoad,
27940
28220
  onError: handleError
27941
- }, null, 8, ["source", "zoom"])) : unref(fileType) === "pdf" ? (openBlock(), createBlock(unref(PdfRender), {
28221
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "pdf" ? (openBlock(), createBlock(unref(PdfRender), {
27942
28222
  key: 2,
27943
28223
  source: unref(fileSource),
27944
28224
  zoom: unref(zoom),
28225
+ "proxy-url": proxyUrl.value,
28226
+ "request-adapter": requestAdapter.value,
27945
28227
  onLoad: handleLoad,
27946
28228
  onError: handleError
27947
- }, null, 8, ["source", "zoom"])) : unref(fileType) === "pptx" || unref(fileType) === "ppt" ? (openBlock(), createBlock(unref(PptxRender), {
28229
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "pptx" || unref(fileType) === "ppt" ? (openBlock(), createBlock(unref(PptxRender), {
27948
28230
  key: 3,
27949
28231
  source: unref(fileSource),
27950
28232
  zoom: unref(zoom),
28233
+ "proxy-url": proxyUrl.value,
28234
+ "request-adapter": requestAdapter.value,
27951
28235
  onLoad: handleLoad,
27952
28236
  onError: handleError
27953
- }, null, 8, ["source", "zoom"])) : unref(fileType) === "txt" ? (openBlock(), createBlock(unref(TextRender), {
28237
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "txt" ? (openBlock(), createBlock(unref(TextRender), {
27954
28238
  key: 4,
27955
28239
  source: unref(fileSource),
27956
28240
  onLoad: handleLoad,
@@ -27966,10 +28250,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27966
28250
  ref: ofdRenderRef,
27967
28251
  source: unref(fileSource),
27968
28252
  zoom: unref(zoom),
28253
+ "proxy-url": proxyUrl.value,
28254
+ "request-adapter": requestAdapter.value,
27969
28255
  onLoad: handleLoad,
27970
28256
  onError: handleError,
27971
28257
  onPageChange: handleOfdPageChange
27972
- }, null, 8, ["source", "zoom"])) : (openBlock(), createElementBlock("div", _hoisted_7, [
28258
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "html" ? (openBlock(), createBlock(unref(HtmlRender), {
28259
+ key: 7,
28260
+ source: unref(fileSource),
28261
+ zoom: unref(zoom),
28262
+ "proxy-url": proxyUrl.value,
28263
+ "request-adapter": requestAdapter.value,
28264
+ onLoad: handleLoad,
28265
+ onError: handleError
28266
+ }, null, 8, ["source", "zoom", "proxy-url", "request-adapter"])) : unref(fileType) === "unknown" && unref(fileSource) ? (openBlock(), createElementBlock("div", _hoisted_7, [..._cache[2] || (_cache[2] = [
28267
+ createElementVNode("span", null, "未知文件类型", -1)
28268
+ ])])) : (openBlock(), createElementBlock("div", _hoisted_8, [
27973
28269
  createElementVNode("span", null, toDisplayString(unref(t)("error.unsupportedType")), 1)
27974
28270
  ]))
27975
28271
  ], 4))
@@ -27978,7 +28274,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27978
28274
  };
27979
28275
  }
27980
28276
  });
27981
- const Viewer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-bd59f5e4"]]);
28277
+ const Viewer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-452e9e91"]]);
27982
28278
  function createViewer(options) {
27983
28279
  const events = createEventBus();
27984
28280
  let app = null;
@@ -28129,6 +28425,7 @@ const JitViewer = {
28129
28425
  export {
28130
28426
  DocxRender,
28131
28427
  ExcelRender,
28428
+ HtmlRender,
28132
28429
  MarkdownRender,
28133
28430
  OfdRender,
28134
28431
  PdfRender,