@open-file-viewer/core 0.1.15 → 0.1.17

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
@@ -1930,12 +1930,12 @@ function imagePlugin() {
1930
1930
  let url = "";
1931
1931
  let convertedBlob = null;
1932
1932
  let isExternal = Boolean(ctx.file.url);
1933
- let canvasSource = null;
1933
+ let tiffSource = null;
1934
1934
  if (isTiff) {
1935
1935
  ctx.setLoading(true);
1936
1936
  try {
1937
1937
  const bytes = await sourceBytesPromise;
1938
- canvasSource = await createTiffCanvas(bytes);
1938
+ tiffSource = await createTiffPreview(bytes, ctx.file.name);
1939
1939
  } catch (err) {
1940
1940
  console.error("TIFF image conversion failed:", err);
1941
1941
  url = createObjectUrl(ctx.file);
@@ -1995,12 +1995,15 @@ function imagePlugin() {
1995
1995
  if (url) {
1996
1996
  image.src = url;
1997
1997
  }
1998
- const visual = canvasSource || image;
1999
- if (canvasSource) {
2000
- canvasSource.classList.add("ofv-media", "ofv-image-content", "ofv-tiff-canvas");
2001
- canvasSource.setAttribute("role", "img");
2002
- canvasSource.setAttribute("aria-label", ctx.file.name);
1998
+ const visual = tiffSource || image;
1999
+ if (tiffSource) {
2000
+ tiffSource.classList.add("ofv-image-content");
2001
+ if (tiffSource.classList.contains("ofv-tiff-pages")) {
2002
+ stage.classList.add("ofv-image-stage-pages");
2003
+ }
2003
2004
  }
2005
+ const visualBox = document.createElement("div");
2006
+ visualBox.className = "ofv-image-scrollbox";
2004
2007
  let scale = getInitialZoom(ctx);
2005
2008
  let rotation = 0;
2006
2009
  let offsetX = 0;
@@ -2014,7 +2017,23 @@ function imagePlugin() {
2014
2017
  let previewAvailable = true;
2015
2018
  const zoomLabel = document.createElement("span");
2016
2019
  zoomLabel.className = "ofv-image-zoom";
2020
+ const updateScrollBox = () => {
2021
+ if (visual.classList.contains("ofv-tiff-pages")) {
2022
+ visualBox.style.removeProperty("width");
2023
+ visualBox.style.removeProperty("height");
2024
+ return;
2025
+ }
2026
+ const baseWidth = visual.offsetWidth || visual.getBoundingClientRect().width || visual.naturalWidth || 0;
2027
+ const baseHeight = visual.offsetHeight || visual.getBoundingClientRect().height || visual.naturalHeight || 0;
2028
+ if (baseWidth > 0) {
2029
+ visualBox.style.width = `${Math.ceil(baseWidth * scale)}px`;
2030
+ }
2031
+ if (baseHeight > 0) {
2032
+ visualBox.style.height = `${Math.ceil(baseHeight * scale)}px`;
2033
+ }
2034
+ };
2017
2035
  const updateTransform = () => {
2036
+ updateScrollBox();
2018
2037
  visual.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale}) rotate(${rotation}deg)`;
2019
2038
  zoomLabel.textContent = `${Math.round(scale * 100)}%`;
2020
2039
  ctx.toolbar?.setZoom(previewAvailable ? scale : void 0);
@@ -2134,11 +2153,13 @@ function imagePlugin() {
2134
2153
  stage.addEventListener("lostpointercapture", onLostPointerCapture);
2135
2154
  stage.addEventListener("pointerleave", onPointerLeave);
2136
2155
  stage.addEventListener("wheel", onWheel, { passive: false });
2137
- if (!canvasSource) {
2156
+ if (!tiffSource) {
2138
2157
  image.addEventListener("error", showImageFallback);
2158
+ image.addEventListener("load", updateScrollBox);
2139
2159
  }
2140
2160
  window.addEventListener("blur", onWindowBlur);
2141
- stage.append(visual);
2161
+ visualBox.append(visual);
2162
+ stage.append(visualBox);
2142
2163
  wrapper.append(...showInlineControls ? [controls, stage, infoBar] : [stage, infoBar]);
2143
2164
  ctx.viewport.append(wrapper);
2144
2165
  updateTransform();
@@ -2176,7 +2197,12 @@ function imagePlugin() {
2176
2197
  },
2177
2198
  resize(size) {
2178
2199
  visual.style.maxWidth = `${size.width}px`;
2179
- visual.style.maxHeight = `${Math.max(0, size.height - controls.offsetHeight)}px`;
2200
+ if (visual.classList.contains("ofv-tiff-pages")) {
2201
+ visual.style.removeProperty("max-height");
2202
+ } else {
2203
+ visual.style.maxHeight = `${Math.max(0, size.height - controls.offsetHeight)}px`;
2204
+ }
2205
+ updateScrollBox();
2180
2206
  },
2181
2207
  destroy() {
2182
2208
  ctx.toolbar?.setZoom(void 0);
@@ -2191,6 +2217,7 @@ function imagePlugin() {
2191
2217
  stage.removeEventListener("pointerleave", onPointerLeave);
2192
2218
  stage.removeEventListener("wheel", onWheel);
2193
2219
  image.removeEventListener("error", showImageFallback);
2220
+ image.removeEventListener("load", updateScrollBox);
2194
2221
  window.removeEventListener("blur", onWindowBlur);
2195
2222
  finishDrag();
2196
2223
  wrapper.remove();
@@ -2204,33 +2231,64 @@ function imagePlugin() {
2204
2231
  }
2205
2232
  };
2206
2233
  }
2207
- async function createTiffCanvas(bytes) {
2234
+ async function createTiffPreview(bytes, fileName) {
2208
2235
  if (bytes.byteLength === 0) {
2209
2236
  throw new Error("\u65E0\u6CD5\u8BFB\u53D6 TIFF \u6587\u4EF6\u5185\u5BB9\u3002");
2210
2237
  }
2211
2238
  const UTIF = await import("utif");
2212
2239
  const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
2213
2240
  const ifds = UTIF.decode(buffer);
2214
- const ifd = ifds.find((item) => Number(item.width || 0) > 0 || Number(item.t256 || 0) > 0) || ifds[0];
2215
- if (!ifd) {
2241
+ const imageIfds = ifds.filter((item) => hasTiffDimensions(item));
2242
+ if (imageIfds.length === 0) {
2216
2243
  throw new Error("TIFF \u6587\u4EF6\u6CA1\u6709\u53EF\u89E3\u7801\u7684\u56FE\u50CF\u76EE\u5F55\u3002");
2217
2244
  }
2245
+ const pages = imageIfds.map((ifd, index) => createTiffPage(UTIF, buffer, ifd, index, imageIfds.length, fileName));
2246
+ if (pages.length === 1) {
2247
+ return pages[0].canvas;
2248
+ }
2249
+ const container = document.createElement("div");
2250
+ container.className = "ofv-tiff-pages";
2251
+ container.setAttribute("role", "group");
2252
+ container.setAttribute("aria-label", `${fileName}\uFF0C\u5171 ${pages.length} \u9875`);
2253
+ for (const page of pages) {
2254
+ const figure = document.createElement("figure");
2255
+ figure.className = "ofv-tiff-page";
2256
+ const caption = document.createElement("figcaption");
2257
+ caption.textContent = `\u7B2C ${page.index + 1} / ${pages.length} \u9875 \xB7 ${page.width} x ${page.height}px`;
2258
+ figure.append(page.canvas, caption);
2259
+ container.append(figure);
2260
+ }
2261
+ return container;
2262
+ }
2263
+ function createTiffPage(UTIF, buffer, ifd, index, total, fileName) {
2218
2264
  UTIF.decodeImage(buffer, ifd);
2219
2265
  const rgba = UTIF.toRGBA8(ifd);
2220
- const width = Number(ifd.width || ifd.t256 || 0);
2221
- const height = Number(ifd.height || ifd.t257 || 0);
2266
+ const { width, height } = getTiffDimensions(ifd);
2222
2267
  if (!width || !height || rgba.length < width * height * 4) {
2223
2268
  throw new Error("TIFF \u56FE\u50CF\u50CF\u7D20\u6570\u636E\u4E0D\u5B8C\u6574\u3002");
2224
2269
  }
2225
2270
  const canvas = document.createElement("canvas");
2271
+ canvas.className = "ofv-tiff-canvas";
2226
2272
  canvas.width = width;
2227
2273
  canvas.height = height;
2274
+ canvas.setAttribute("role", "img");
2275
+ canvas.setAttribute("aria-label", total > 1 ? `${fileName} \u7B2C ${index + 1} \u9875` : fileName);
2228
2276
  const context = canvas.getContext("2d");
2229
2277
  if (!context) {
2230
2278
  throw new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 Canvas 2D\uFF0C\u65E0\u6CD5\u5C55\u793A TIFF\u3002");
2231
2279
  }
2232
2280
  context.putImageData(new ImageData(new Uint8ClampedArray(rgba), width, height), 0, 0);
2233
- return canvas;
2281
+ return { canvas, width, height, index };
2282
+ }
2283
+ function hasTiffDimensions(ifd) {
2284
+ const { width, height } = getTiffDimensions(ifd);
2285
+ return width > 0 && height > 0;
2286
+ }
2287
+ function getTiffDimensions(ifd) {
2288
+ return {
2289
+ width: Number(ifd.width || ifd.t256 || 0),
2290
+ height: Number(ifd.height || ifd.t257 || 0)
2291
+ };
2234
2292
  }
2235
2293
  function createImageFallback(fileName, url) {
2236
2294
  const fallback = document.createElement("div");
@@ -2559,6 +2617,7 @@ function parseTiffInfo(bytes) {
2559
2617
  return { format: magic === 43 ? "BigTIFF" : "TIFF", note: "IFD \u504F\u79FB\u8D85\u51FA\u6587\u4EF6\u8303\u56F4" };
2560
2618
  }
2561
2619
  const count = magic === 43 ? readTiffUint64AsNumber(bytes, ifdOffset, littleEndian) : readTiffUint16(bytes, ifdOffset, littleEndian);
2620
+ const imageCount = countTiffIfds(bytes, ifdOffset, magic === 43, littleEndian);
2562
2621
  const entrySize = magic === 43 ? 20 : 12;
2563
2622
  const entriesStart = ifdOffset + (magic === 43 ? 8 : 2);
2564
2623
  let width;
@@ -2585,9 +2644,26 @@ function parseTiffInfo(bytes) {
2585
2644
  height,
2586
2645
  bitDepth: bitDepth ? `${bitDepth} bit` : void 0,
2587
2646
  color: compression ? tiffCompressionName(compression) : void 0,
2588
- count: Number.isFinite(count) ? count : void 0
2647
+ count: imageCount || void 0
2589
2648
  };
2590
2649
  }
2650
+ function countTiffIfds(bytes, firstOffset, bigTiff, littleEndian) {
2651
+ const seen = /* @__PURE__ */ new Set();
2652
+ let offset = firstOffset;
2653
+ let count = 0;
2654
+ while (Number.isFinite(offset) && offset > 0 && offset < bytes.length && !seen.has(offset) && count < 512) {
2655
+ seen.add(offset);
2656
+ const entryCount = bigTiff ? readTiffUint64AsNumber(bytes, offset, littleEndian) : readTiffUint16(bytes, offset, littleEndian);
2657
+ const entrySize = bigTiff ? 20 : 12;
2658
+ const nextOffsetPosition = offset + (bigTiff ? 8 : 2) + entryCount * entrySize;
2659
+ if (!Number.isFinite(entryCount) || nextOffsetPosition + (bigTiff ? 8 : 4) > bytes.length) {
2660
+ break;
2661
+ }
2662
+ count++;
2663
+ offset = bigTiff ? readTiffUint64AsNumber(bytes, nextOffsetPosition, littleEndian) : readTiffUint32(bytes, nextOffsetPosition, littleEndian);
2664
+ }
2665
+ return count;
2666
+ }
2591
2667
  function readTiffInlineValue(bytes, offset, type, littleEndian) {
2592
2668
  if (offset + 4 > bytes.length) {
2593
2669
  return void 0;
@@ -3986,26 +4062,6 @@ var mimeLangMap = {
3986
4062
  };
3987
4063
  var MAX_HIGHLIGHT_CHARS = 18e4;
3988
4064
  var MAX_RENDER_CHARS = 6e5;
3989
- function loadPrismCss(theme) {
3990
- const lightId = "ofv-prism-css-light";
3991
- const darkId = "ofv-prism-css-dark";
3992
- const activeId = theme === "dark" ? darkId : lightId;
3993
- const inactiveId = theme === "dark" ? lightId : darkId;
3994
- document.getElementById(inactiveId)?.remove();
3995
- if (document.getElementById(activeId)) {
3996
- return Promise.resolve();
3997
- }
3998
- const href = theme === "dark" ? "https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.min.css" : "https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css";
3999
- return new Promise((resolve, reject) => {
4000
- const link = document.createElement("link");
4001
- link.id = activeId;
4002
- link.rel = "stylesheet";
4003
- link.href = href;
4004
- link.onload = () => resolve();
4005
- link.onerror = () => reject(new Error(`Failed to load Prism CSS: ${href}`));
4006
- document.head.appendChild(link);
4007
- });
4008
- }
4009
4065
  function textPlugin() {
4010
4066
  return {
4011
4067
  name: "text",
@@ -4029,7 +4085,6 @@ function textPlugin() {
4029
4085
  }
4030
4086
  };
4031
4087
  }
4032
- const isDark = ctx.host.parentElement?.classList.contains("ofv-theme-dark") || document.body.classList.contains("ofv-theme-dark") || ctx.options.theme === "auto" && window.matchMedia?.("(prefers-color-scheme: dark)").matches || ctx.options.theme === "dark";
4033
4088
  if (isMarkdown) {
4034
4089
  const [markedModule, PrismModule2, DOMPurifyModule] = await Promise.all([
4035
4090
  import("marked"),
@@ -4050,7 +4105,6 @@ function textPlugin() {
4050
4105
  try {
4051
4106
  const codeBlocks = container.querySelectorAll("pre code");
4052
4107
  if (codeBlocks.length > 0) {
4053
- await loadPrismCss(isDark ? "dark" : "light");
4054
4108
  codeBlocks.forEach((block) => {
4055
4109
  const parent = block.parentElement;
4056
4110
  if (parent && !parent.className.includes("language-")) {
@@ -4174,9 +4228,6 @@ function textPlugin() {
4174
4228
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4175
4229
  }
4176
4230
  }
4177
- await loadPrismCss(isDark ? "dark" : "light").catch((error) => {
4178
- console.warn("Prism CSS failed to load; rendering code without external theme:", error);
4179
- });
4180
4231
  const codeText = text.length > MAX_RENDER_CHARS ? text.slice(0, MAX_RENDER_CHARS) : text;
4181
4232
  const totalLines = countLines(text);
4182
4233
  const shownLines = countLines(codeText);
@@ -4704,10 +4755,11 @@ async function renderPdfDocumentPreview(options) {
4704
4755
  const baseViewport = page.getViewport({ scale: 1 });
4705
4756
  pagesMeta.push({
4706
4757
  width: baseViewport.width,
4707
- height: baseViewport.height
4758
+ height: baseViewport.height,
4759
+ rotation: getPdfPageRotation(page)
4708
4760
  });
4709
4761
  } catch {
4710
- pagesMeta.push({ width: 612, height: 792 });
4762
+ pagesMeta.push({ width: 612, height: 792, rotation: 0 });
4711
4763
  }
4712
4764
  }
4713
4765
  const pageStates = [];
@@ -4742,7 +4794,7 @@ async function renderPdfDocumentPreview(options) {
4742
4794
  const page = await pdfDocument.getPage(pageIdx + 1);
4743
4795
  const meta = pagesMeta[pageIdx];
4744
4796
  const scale = options.fit === "actual" ? zoomFactor : Math.max(0.05, Math.min(5, getPdfAvailableWidth(size.width) / rotatedPdfWidth(meta, rotation) * zoomFactor));
4745
- const viewport = page.getViewport({ scale, rotation });
4797
+ const viewport = page.getViewport({ scale, rotation: getPdfRenderRotation(meta, rotation) });
4746
4798
  const outputScale = getPdfOutputScale();
4747
4799
  const cssWidth = Math.floor(viewport.width);
4748
4800
  const cssHeight = Math.floor(viewport.height);
@@ -4781,6 +4833,8 @@ async function renderPdfDocumentPreview(options) {
4781
4833
  const span = document.createElement("span");
4782
4834
  span.textContent = str;
4783
4835
  span.style.fontSize = `${fontHeight}px`;
4836
+ span.style.lineHeight = "1";
4837
+ span.style.height = `${fontHeight}px`;
4784
4838
  span.style.fontFamily = item.fontName || "sans-serif";
4785
4839
  span.style.left = `${tx[4]}px`;
4786
4840
  span.style.top = `${tx[5] - fontHeight}px`;
@@ -4978,6 +5032,13 @@ function appendPdfSummary(parent, label, value) {
4978
5032
  function normalizePdfRotation(value) {
4979
5033
  return (value % 360 + 360) % 360;
4980
5034
  }
5035
+ function getPdfPageRotation(page) {
5036
+ const rotation = Number(page.rotate);
5037
+ return Number.isFinite(rotation) ? normalizePdfRotation(rotation) : 0;
5038
+ }
5039
+ function getPdfRenderRotation(meta, userRotation) {
5040
+ return normalizePdfRotation((meta.rotation || 0) + userRotation);
5041
+ }
4981
5042
  function isPdfRotatedSideways(rotation) {
4982
5043
  const normalized = normalizePdfRotation(rotation);
4983
5044
  return normalized === 90 || normalized === 270;
@@ -5862,6 +5923,1100 @@ function decodeXml(value) {
5862
5923
  // src/plugins/office.ts
5863
5924
  var import_jszip3 = __toESM(require("jszip"), 1);
5864
5925
  var import_dompurify2 = __toESM(require("dompurify"), 1);
5926
+
5927
+ // src/plugins/msdoc.ts
5928
+ var CFB_SIGNATURE = [208, 207, 17, 224, 161, 177, 26, 225];
5929
+ var FREE_SECTOR = 4294967295;
5930
+ var END_OF_CHAIN = 4294967294;
5931
+ var FAT_SECTOR = 4294967293;
5932
+ var DIFAT_SECTOR = 4294967292;
5933
+ var MINI_STREAM_CUTOFF = 4096;
5934
+ var STSH_FC_LCB_INDEX = 1;
5935
+ var CLX_FC_LCB_INDEX = 33;
5936
+ var WORD_PAGE_BREAK = "\f";
5937
+ function parseLegacyWordDocument(input) {
5938
+ const cfb = parseCompoundFile(new Uint8Array(input));
5939
+ const wordDocument = cfb.getStream("WordDocument");
5940
+ if (!wordDocument) {
5941
+ throw new Error("\u672A\u627E\u5230 WordDocument \u6D41");
5942
+ }
5943
+ const fib = parseFib(wordDocument);
5944
+ if (fib.encrypted) {
5945
+ throw new Error("\u6682\u4E0D\u652F\u6301\u52A0\u5BC6\u7684 .doc \u6587\u4EF6");
5946
+ }
5947
+ const tableStreamName = fib.useOneTable ? "1Table" : "0Table";
5948
+ const tableStream = cfb.getStream(tableStreamName);
5949
+ if (!tableStream) {
5950
+ throw new Error(`\u672A\u627E\u5230 ${tableStreamName} \u8868\u6D41`);
5951
+ }
5952
+ const assets = extractImageAssets(cfb);
5953
+ const styles = parseStyleTable(tableStream, fib);
5954
+ const pieces = parseClxPieces(tableStream, fib.fcClx, fib.lcbClx);
5955
+ const text = pieces.length > 0 ? readPieceTableText(wordDocument, pieces, fib.ccpText) : readFibTextFallback(wordDocument, fib);
5956
+ const paragraphs = splitWordParagraphs(text);
5957
+ if (paragraphs.length === 0) {
5958
+ throw new Error("\u672A\u89E3\u6790\u5230\u53EF\u663E\u793A\u7684\u6B63\u6587\u6BB5\u843D");
5959
+ }
5960
+ const bodyParagraphs = removeTrailingFooterArtifacts(paragraphs);
5961
+ const blocks = buildWordBlocks(bodyParagraphs);
5962
+ const layout = inferLayoutHints(paragraphs, assets);
5963
+ return {
5964
+ title: inferDocumentTitle(paragraphs),
5965
+ paragraphs: bodyParagraphs,
5966
+ blocks,
5967
+ layout,
5968
+ assets,
5969
+ styles,
5970
+ stats: {
5971
+ streamCount: cfb.entries.length,
5972
+ pieceCount: pieces.length,
5973
+ characterCount: bodyParagraphs.join("\n").length,
5974
+ styleCount: styles.length,
5975
+ tableStream: tableStreamName
5976
+ },
5977
+ warnings: pieces.length === 0 ? ["\u672A\u627E\u5230 CLX piece table\uFF0C\u5DF2\u6309 FIB \u6587\u672C\u533A\u95F4\u5C1D\u8BD5\u6062\u590D\u6B63\u6587\u3002"] : []
5978
+ };
5979
+ }
5980
+ function renderLegacyWordDocument(panel, document2) {
5981
+ panel.replaceChildren();
5982
+ const article = window.document.createElement("article");
5983
+ article.className = "ofv-msdoc-document";
5984
+ const pages = paginateWordBlocks(document2.blocks.slice(0, 600), document2.layout);
5985
+ const pageCount = inferDisplayedPageCount(document2.blocks, pages.length);
5986
+ const page = window.document.createElement("section");
5987
+ page.className = "ofv-msdoc-page";
5988
+ appendPageChrome(page, document2, 1, pageCount);
5989
+ const meta = window.document.createElement("dl");
5990
+ meta.className = "ofv-msdoc-meta";
5991
+ appendMeta4(meta, "\u683C\u5F0F", "Word 97-2003 Binary");
5992
+ appendMeta4(meta, "\u6B63\u6587\u6BB5\u843D", `${document2.paragraphs.length}`);
5993
+ appendMeta4(meta, "Piece Table", `${document2.stats.pieceCount || 0} \u6BB5`);
5994
+ appendMeta4(meta, "\u6837\u5F0F\u8868", `${document2.stats.styleCount || 0} \u4E2A\u6837\u5F0F`);
5995
+ appendMeta4(meta, "\u8868\u6D41", document2.stats.tableStream);
5996
+ if (document2.styles.length > 0) {
5997
+ appendMeta4(meta, "\u6837\u5F0F\u540D\u79F0", document2.styles.slice(0, 30).map((style) => style.name).join("\u3001"));
5998
+ }
5999
+ meta.hidden = true;
6000
+ page.append(meta);
6001
+ appendBlocksToPage(page, pages[0] || [], document2.layout);
6002
+ appendWarnings(page, document2);
6003
+ article.append(page);
6004
+ for (const pageBlocks of pages.slice(1)) {
6005
+ const nextPage = window.document.createElement("section");
6006
+ nextPage.className = "ofv-msdoc-page";
6007
+ appendPageChrome(nextPage, document2, article.children.length + 1, pageCount);
6008
+ appendBlocksToPage(nextPage, pageBlocks, document2.layout);
6009
+ article.append(nextPage);
6010
+ }
6011
+ panel.append(article);
6012
+ }
6013
+ function inferDisplayedPageCount(blocks, renderedPageCount) {
6014
+ const tocPageNumbers = blocks.filter((block) => block.type === "toc" && Boolean(block.page)).map((block) => Number.parseInt(block.page || "", 10)).filter((page) => Number.isFinite(page) && page > 0);
6015
+ if (tocPageNumbers.length === 0) {
6016
+ return renderedPageCount;
6017
+ }
6018
+ return Math.max(renderedPageCount, ...tocPageNumbers);
6019
+ }
6020
+ function appendPageChrome(page, document2, pageNumber, pageCount) {
6021
+ if (document2.layout.lineNumbers) {
6022
+ page.classList.add("ofv-msdoc-line-numbered");
6023
+ }
6024
+ page.setAttribute("aria-label", document2.title || "Word \u6587\u6863");
6025
+ if (document2.layout.headerBrand === "oasis") {
6026
+ page.append(createOasisHeader(document2.assets.find((asset) => asset.id === document2.layout.headerImageId)));
6027
+ }
6028
+ if (document2.layout.footer) {
6029
+ page.append(createPageFooter(document2.layout.footer, pageNumber, pageCount));
6030
+ }
6031
+ }
6032
+ function appendBlocksToPage(page, blocks, layout) {
6033
+ let lineNumber = 1;
6034
+ for (const block of blocks) {
6035
+ if (block.type === "pageBreak") {
6036
+ continue;
6037
+ }
6038
+ const element = renderWordBlock(block);
6039
+ if (layout.lineNumbers && element instanceof HTMLElement && !element.classList.contains("ofv-msdoc-page-header")) {
6040
+ element.dataset.line = String(lineNumber);
6041
+ lineNumber += estimatedLineCount(block);
6042
+ }
6043
+ page.append(element);
6044
+ }
6045
+ }
6046
+ function appendWarnings(page, document2) {
6047
+ if (document2.warnings.length === 0) {
6048
+ return;
6049
+ }
6050
+ const warning = window.document.createElement("p");
6051
+ warning.className = "ofv-msdoc-warning";
6052
+ warning.textContent = document2.warnings.join(" ");
6053
+ warning.hidden = true;
6054
+ page.append(warning);
6055
+ }
6056
+ function createOasisHeader(image) {
6057
+ const header = window.document.createElement("header");
6058
+ header.className = "ofv-msdoc-page-header ofv-msdoc-oasis-header";
6059
+ const logo = image ? createImageLogo(image) : createFallbackOasisLogo();
6060
+ header.append(logo);
6061
+ return header;
6062
+ }
6063
+ function createImageLogo(image) {
6064
+ const wrapper = window.document.createElement("div");
6065
+ wrapper.className = "ofv-msdoc-oasis-logo ofv-msdoc-oasis-logo-image";
6066
+ const img = window.document.createElement("img");
6067
+ img.src = image.dataUrl;
6068
+ img.alt = "OASIS";
6069
+ if (image.width) {
6070
+ img.width = image.width;
6071
+ }
6072
+ if (image.height) {
6073
+ img.height = image.height;
6074
+ }
6075
+ wrapper.append(img);
6076
+ return wrapper;
6077
+ }
6078
+ function createFallbackOasisLogo() {
6079
+ const logo = window.document.createElement("div");
6080
+ logo.className = "ofv-msdoc-oasis-logo";
6081
+ const word = window.document.createElement("span");
6082
+ word.textContent = "OASIS";
6083
+ const mark = window.document.createElement("span");
6084
+ mark.className = "ofv-msdoc-oasis-mark";
6085
+ mark.setAttribute("aria-hidden", "true");
6086
+ logo.append(word, mark);
6087
+ return logo;
6088
+ }
6089
+ function createPageFooter(footer, pageNumber, pageCount) {
6090
+ const element = window.document.createElement("footer");
6091
+ element.className = "ofv-msdoc-page-footer";
6092
+ const top = window.document.createElement("div");
6093
+ top.className = "ofv-msdoc-footer-row";
6094
+ const documentId = window.document.createElement("span");
6095
+ documentId.textContent = footer.documentId || "";
6096
+ const date = window.document.createElement("span");
6097
+ date.textContent = footer.date || "";
6098
+ top.append(documentId, date);
6099
+ const bottom = window.document.createElement("div");
6100
+ bottom.className = "ofv-msdoc-footer-row";
6101
+ const copyright = window.document.createElement("span");
6102
+ copyright.textContent = footer.copyright || "";
6103
+ const page = window.document.createElement("span");
6104
+ page.textContent = `Page ${pageNumber} of ${pageCount}`;
6105
+ bottom.append(copyright, page);
6106
+ element.append(top, bottom);
6107
+ return element;
6108
+ }
6109
+ function renderWordBlock(block) {
6110
+ if (block.type === "pageBreak") {
6111
+ const marker = window.document.createElement("span");
6112
+ marker.className = "ofv-msdoc-page-break";
6113
+ marker.hidden = true;
6114
+ return marker;
6115
+ }
6116
+ if (block.type === "table") {
6117
+ const table = window.document.createElement("table");
6118
+ table.className = "ofv-msdoc-table";
6119
+ const revisionColumnWidths = getRevisionTableColumnWidths(block.rows);
6120
+ if (revisionColumnWidths) {
6121
+ table.classList.add("ofv-msdoc-revision-table");
6122
+ const colgroup = window.document.createElement("colgroup");
6123
+ for (const width of revisionColumnWidths) {
6124
+ const col = window.document.createElement("col");
6125
+ col.style.width = `calc(${width}px * var(--ofv-office-zoom, 1))`;
6126
+ colgroup.append(col);
6127
+ }
6128
+ table.append(colgroup);
6129
+ }
6130
+ const tbody = window.document.createElement("tbody");
6131
+ for (const row of block.rows) {
6132
+ const tr = window.document.createElement("tr");
6133
+ const cellTag = row === block.rows[0] && block.rows.length > 1 ? "th" : "td";
6134
+ for (const cellText of row) {
6135
+ const cell = window.document.createElement(cellTag);
6136
+ cell.textContent = cellText;
6137
+ tr.append(cell);
6138
+ }
6139
+ tbody.append(tr);
6140
+ }
6141
+ table.append(tbody);
6142
+ return table;
6143
+ }
6144
+ if (block.type === "toc") {
6145
+ const paragraph2 = window.document.createElement("p");
6146
+ paragraph2.className = `ofv-msdoc-toc ofv-msdoc-toc-level-${block.level}`;
6147
+ const title = window.document.createElement("span");
6148
+ title.textContent = block.title;
6149
+ paragraph2.append(title);
6150
+ if (block.page) {
6151
+ const page = window.document.createElement("span");
6152
+ page.textContent = block.page;
6153
+ paragraph2.append(page);
6154
+ }
6155
+ return paragraph2;
6156
+ }
6157
+ const paragraph = window.document.createElement("p");
6158
+ const levelClass = block.type === "heading" ? ` ofv-msdoc-heading-level-${block.level}` : "";
6159
+ const listClass = block.type === "listItem" ? ` ofv-msdoc-list-level-${block.level}` : "";
6160
+ paragraph.className = `ofv-msdoc-${block.type}${levelClass}${listClass}${"indent" in block && block.indent ? " ofv-msdoc-indent" : ""}`;
6161
+ appendInlineRuns(paragraph, block.text, block.type === "code");
6162
+ return paragraph;
6163
+ }
6164
+ function appendInlineRuns(element, text, preserveTabs = false) {
6165
+ if (preserveTabs) {
6166
+ appendInlineText(element, text, true);
6167
+ return;
6168
+ }
6169
+ const pattern = /(https?:\/\/\S+|[\w.+-]+@[\w.-]+\.[A-Za-z]{2,}|\[[^\]]+\]|<\/?[A-Za-z][A-Za-z0-9:-]*>|(?:\b(?:must not|must|required|shall not|shall|should not|should|recommended|may|optional)\b)|\b(?:attributeNames|DataType|OtherKeyword|variable)\b)/gi;
6170
+ let offset = 0;
6171
+ for (const match of text.matchAll(pattern)) {
6172
+ const value = match[0];
6173
+ const index = match.index || 0;
6174
+ if (index > offset) {
6175
+ appendInlineText(element, text.slice(offset, index), preserveTabs);
6176
+ }
6177
+ if (value.startsWith("[") && value.endsWith("]")) {
6178
+ appendBracketRun(element, value);
6179
+ } else if (isCodeStyleRun(value)) {
6180
+ const code = window.document.createElement("code");
6181
+ code.className = "ofv-msdoc-inline-code";
6182
+ code.textContent = value;
6183
+ element.append(code);
6184
+ } else if (isVariableStyleRun(value)) {
6185
+ const em = window.document.createElement("em");
6186
+ em.className = "ofv-msdoc-variable";
6187
+ em.textContent = value;
6188
+ element.append(em);
6189
+ } else if (isRequirementKeywordRun(value)) {
6190
+ const em = window.document.createElement("em");
6191
+ em.className = "ofv-msdoc-keyword";
6192
+ em.textContent = value;
6193
+ element.append(em);
6194
+ } else {
6195
+ const link = splitLinkRun(value);
6196
+ const anchor = window.document.createElement("a");
6197
+ anchor.className = "ofv-msdoc-link-text";
6198
+ anchor.href = link.href;
6199
+ anchor.target = "_blank";
6200
+ anchor.rel = "noreferrer noopener";
6201
+ anchor.textContent = link.text;
6202
+ element.append(anchor);
6203
+ if (link.trailing) {
6204
+ appendInlineText(element, link.trailing, preserveTabs);
6205
+ }
6206
+ }
6207
+ offset = index + value.length;
6208
+ }
6209
+ if (offset < text.length) {
6210
+ appendInlineText(element, text.slice(offset), preserveTabs);
6211
+ }
6212
+ }
6213
+ function appendBracketRun(element, value) {
6214
+ const tagName = isReferenceTerm(value) ? "strong" : "em";
6215
+ const run = window.document.createElement(tagName);
6216
+ run.className = isReferenceTerm(value) ? "ofv-msdoc-ref-term" : "ofv-msdoc-instruction-run";
6217
+ run.textContent = value;
6218
+ element.append(run);
6219
+ }
6220
+ function getRevisionTableColumnWidths(rows) {
6221
+ const header = rows[0]?.map((cell) => cell.toLowerCase());
6222
+ if (!header || header.length !== 4) {
6223
+ return void 0;
6224
+ }
6225
+ if (header[0] === "rev" && header[1] === "date" && /whom/.test(header[2]) && header[3] === "what") {
6226
+ return [59, 81, 106, 191];
6227
+ }
6228
+ return void 0;
6229
+ }
6230
+ function appendInlineText(element, text, preserveTabs) {
6231
+ element.append(window.document.createTextNode(preserveTabs ? text : text.replace(/\t+/g, " ")));
6232
+ }
6233
+ function isReferenceTerm(value) {
6234
+ return /^\[[A-Z0-9][A-Z0-9.-]{1,24}\]$/.test(value);
6235
+ }
6236
+ function isCodeStyleRun(value) {
6237
+ return /^<\/?[A-Za-z][A-Za-z0-9:-]*>$/.test(value) || /^(?:attributeNames|DataType|OtherKeyword)$/.test(value);
6238
+ }
6239
+ function isVariableStyleRun(value) {
6240
+ return value === "variable";
6241
+ }
6242
+ function isRequirementKeywordRun(value) {
6243
+ return /^(?:must not|must|required|shall not|shall|should not|should|recommended|may|optional)$/i.test(value);
6244
+ }
6245
+ function splitLinkRun(value) {
6246
+ let text = value;
6247
+ let trailing = "";
6248
+ while (/[),.;:]$/.test(text)) {
6249
+ trailing = text.slice(-1) + trailing;
6250
+ text = text.slice(0, -1);
6251
+ }
6252
+ const href = /^https?:\/\//i.test(text) ? text : `mailto:${text}`;
6253
+ return { text, href, trailing };
6254
+ }
6255
+ function extractImageAssets(cfb) {
6256
+ const assets = [];
6257
+ const seen = /* @__PURE__ */ new Set();
6258
+ for (const entry of cfb.entries) {
6259
+ if (entry.type !== 2) {
6260
+ continue;
6261
+ }
6262
+ const stream = cfb.getStream(entry.name);
6263
+ if (!stream || stream.length < 16) {
6264
+ continue;
6265
+ }
6266
+ for (const image of extractImagesFromBytes(stream, entry.name)) {
6267
+ const key = `${image.mimeType}:${image.bytes.length}:${image.bytes[0]}:${image.bytes[image.bytes.length - 1]}`;
6268
+ if (seen.has(key)) {
6269
+ continue;
6270
+ }
6271
+ seen.add(key);
6272
+ const id = `image-${assets.length + 1}`;
6273
+ assets.push({
6274
+ id,
6275
+ kind: "image",
6276
+ mimeType: image.mimeType,
6277
+ dataUrl: `data:${image.mimeType};base64,${bytesToBase64(image.bytes)}`,
6278
+ width: image.width,
6279
+ height: image.height
6280
+ });
6281
+ }
6282
+ }
6283
+ return assets;
6284
+ }
6285
+ function parseStyleTable(tableStream, fib) {
6286
+ if (fib.lcbStshf <= 0 || fib.fcStshf < 0 || fib.fcStshf >= tableStream.length) {
6287
+ return [];
6288
+ }
6289
+ const bytes = tableStream.subarray(fib.fcStshf, Math.min(tableStream.length, fib.fcStshf + fib.lcbStshf));
6290
+ if (bytes.length < 8) {
6291
+ return [];
6292
+ }
6293
+ const view3 = dataView2(bytes);
6294
+ const cbStshi = view3.getUint16(0, true);
6295
+ const stshiOffset = 2;
6296
+ const cstd = stshiOffset + 2 <= bytes.length ? view3.getUint16(stshiOffset, true) : 0;
6297
+ const cbSTDBaseInFile = stshiOffset + 4 <= bytes.length ? view3.getUint16(stshiOffset + 2, true) : 10;
6298
+ let offset = 2 + cbStshi;
6299
+ const styles = [];
6300
+ for (let id = 0; id < cstd && offset + 2 <= bytes.length; id += 1) {
6301
+ const cbStd = view3.getUint16(offset, true);
6302
+ const stdStart = offset + 2;
6303
+ const stdEnd = stdStart + cbStd;
6304
+ if (cbStd > 0 && stdStart < bytes.length) {
6305
+ const style = parseStyleDefinition(bytes.subarray(stdStart, Math.min(stdEnd, bytes.length)), Math.max(10, cbSTDBaseInFile), id);
6306
+ if (style.name) {
6307
+ styles.push(style);
6308
+ }
6309
+ }
6310
+ offset = alignEven(stdEnd);
6311
+ }
6312
+ return styles;
6313
+ }
6314
+ function parseStyleDefinition(bytes, baseSize, id) {
6315
+ const base = bytes.length >= 6 ? parseStyleBase(bytes) : void 0;
6316
+ const nameOffset = Math.min(bytes.length, Math.max(10, baseSize));
6317
+ const name = parseXstz(bytes, nameOffset);
6318
+ return {
6319
+ id,
6320
+ name,
6321
+ type: styleTypeFromStk(base?.stk),
6322
+ basedOn: base?.basedOn,
6323
+ next: base?.next
6324
+ };
6325
+ }
6326
+ function parseStyleBase(bytes) {
6327
+ const view3 = dataView2(bytes);
6328
+ const w2 = view3.getUint16(2, true);
6329
+ const w3 = view3.getUint16(4, true);
6330
+ return {
6331
+ stk: w2 & 15,
6332
+ basedOn: w2 >> 4 & 4095,
6333
+ next: w3 >> 4 & 4095
6334
+ };
6335
+ }
6336
+ function styleTypeFromStk(stk) {
6337
+ if (stk === 1) {
6338
+ return "paragraph";
6339
+ }
6340
+ if (stk === 2) {
6341
+ return "character";
6342
+ }
6343
+ if (stk === 3) {
6344
+ return "table";
6345
+ }
6346
+ if (stk === 4) {
6347
+ return "numbering";
6348
+ }
6349
+ return "unknown";
6350
+ }
6351
+ function parseXstz(bytes, offset) {
6352
+ if (offset + 2 > bytes.length) {
6353
+ return "";
6354
+ }
6355
+ const view3 = dataView2(bytes);
6356
+ const charCount = view3.getUint16(offset, true);
6357
+ const start = offset + 2;
6358
+ const end = Math.min(bytes.length, start + charCount * 2);
6359
+ if (end <= start) {
6360
+ return "";
6361
+ }
6362
+ return decodeUtf16Le(bytes.subarray(start, end)).replace(/\0+$/g, "");
6363
+ }
6364
+ function extractImagesFromBytes(bytes, sourceName) {
6365
+ const images = [];
6366
+ for (const start of findSignatureOffsets(bytes, PNG_SIGNATURE)) {
6367
+ const end = findPngEnd(bytes, start);
6368
+ if (end > start) {
6369
+ const imageBytes = bytes.slice(start, end);
6370
+ const dimensions = readPngDimensions(imageBytes);
6371
+ images.push({ bytes: imageBytes, mimeType: "image/png", width: dimensions?.width, height: dimensions?.height });
6372
+ }
6373
+ }
6374
+ for (const start of findSignatureOffsets(bytes, JPEG_SIGNATURE)) {
6375
+ const end = findJpegEnd(bytes, start);
6376
+ if (end > start) {
6377
+ images.push({ bytes: bytes.slice(start, end), mimeType: "image/jpeg" });
6378
+ }
6379
+ }
6380
+ if (/picture|image|data/i.test(sourceName)) {
6381
+ const gifStart = bytes.findIndex((byte, index) => index + 4 <= bytes.length && bytes[index] === 71 && bytes[index + 1] === 73 && bytes[index + 2] === 70 && bytes[index + 3] === 56);
6382
+ if (gifStart >= 0) {
6383
+ images.push({ bytes: bytes.slice(gifStart), mimeType: "image/gif" });
6384
+ }
6385
+ }
6386
+ return images;
6387
+ }
6388
+ var PNG_SIGNATURE = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10]);
6389
+ var JPEG_SIGNATURE = Uint8Array.from([255, 216, 255]);
6390
+ function findSignatureOffsets(bytes, signature) {
6391
+ const offsets = [];
6392
+ for (let index = 0; index <= bytes.length - signature.length; index += 1) {
6393
+ let matches = true;
6394
+ for (let sigIndex = 0; sigIndex < signature.length; sigIndex += 1) {
6395
+ if (bytes[index + sigIndex] !== signature[sigIndex]) {
6396
+ matches = false;
6397
+ break;
6398
+ }
6399
+ }
6400
+ if (matches) {
6401
+ offsets.push(index);
6402
+ }
6403
+ }
6404
+ return offsets;
6405
+ }
6406
+ function findPngEnd(bytes, start) {
6407
+ for (let offset = start + PNG_SIGNATURE.length; offset + 12 <= bytes.length; ) {
6408
+ const length = readUint32Be4(bytes, offset);
6409
+ const typeOffset = offset + 4;
6410
+ const next = offset + 12 + length;
6411
+ if (next > bytes.length) {
6412
+ return 0;
6413
+ }
6414
+ if (bytes[typeOffset] === 73 && bytes[typeOffset + 1] === 69 && bytes[typeOffset + 2] === 78 && bytes[typeOffset + 3] === 68) {
6415
+ return next;
6416
+ }
6417
+ offset = next;
6418
+ }
6419
+ return 0;
6420
+ }
6421
+ function findJpegEnd(bytes, start) {
6422
+ for (let index = start + 2; index + 1 < bytes.length; index += 1) {
6423
+ if (bytes[index] === 255 && bytes[index + 1] === 217) {
6424
+ return index + 2;
6425
+ }
6426
+ }
6427
+ return 0;
6428
+ }
6429
+ function readPngDimensions(bytes) {
6430
+ if (bytes.length < 24 || !PNG_SIGNATURE.every((value, index) => bytes[index] === value)) {
6431
+ return void 0;
6432
+ }
6433
+ return {
6434
+ width: readUint32Be4(bytes, 16),
6435
+ height: readUint32Be4(bytes, 20)
6436
+ };
6437
+ }
6438
+ function readUint32Be4(bytes, offset) {
6439
+ return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
6440
+ }
6441
+ function bytesToBase64(bytes) {
6442
+ let binary = "";
6443
+ const chunkSize = 32768;
6444
+ for (let offset = 0; offset < bytes.length; offset += chunkSize) {
6445
+ binary += String.fromCharCode(...bytes.subarray(offset, Math.min(bytes.length, offset + chunkSize)));
6446
+ }
6447
+ return btoa(binary);
6448
+ }
6449
+ function parseCompoundFile(bytes) {
6450
+ if (!hasCompoundSignature(bytes)) {
6451
+ throw new Error("\u4E0D\u662F\u6807\u51C6 OLE Compound File");
6452
+ }
6453
+ const view3 = dataView2(bytes);
6454
+ const sectorSize = 1 << view3.getUint16(30, true);
6455
+ const miniSectorSize = 1 << view3.getUint16(32, true);
6456
+ const fatSectorCount = view3.getUint32(44, true);
6457
+ const firstDirectorySector = view3.getUint32(48, true);
6458
+ const miniStreamCutoff = view3.getUint32(56, true) || MINI_STREAM_CUTOFF;
6459
+ const firstMiniFatSector = view3.getUint32(60, true);
6460
+ const miniFatSectorCount = view3.getUint32(64, true);
6461
+ const firstDifatSector = view3.getUint32(68, true);
6462
+ const difatSectorCount = view3.getUint32(72, true);
6463
+ const difat = readDifat(view3, sectorSize, firstDifatSector, difatSectorCount);
6464
+ const fat = readFat(view3, sectorSize, difat.slice(0, fatSectorCount));
6465
+ const directoryBytes = readRegularStream(bytes, sectorSize, fat, firstDirectorySector);
6466
+ const entries = parseDirectoryEntries(directoryBytes);
6467
+ const root = entries.find((entry) => entry.type === 5);
6468
+ const miniStream = root ? readRegularStream(bytes, sectorSize, fat, root.startSector, root.size) : new Uint8Array();
6469
+ const miniFat = firstMiniFatSector < END_OF_CHAIN ? readFat(view3, sectorSize, sectorChain(fat, firstMiniFatSector).slice(0, miniFatSectorCount)) : [];
6470
+ return {
6471
+ entries,
6472
+ getStream(name) {
6473
+ const wanted = normalizeStreamName(name);
6474
+ const entry = entries.find((item) => item.type === 2 && normalizeStreamName(item.name) === wanted);
6475
+ if (!entry) {
6476
+ return void 0;
6477
+ }
6478
+ if (entry.size < miniStreamCutoff && miniFat.length > 0) {
6479
+ return readMiniStream(miniStream, miniSectorSize, miniFat, entry.startSector, entry.size);
6480
+ }
6481
+ return readRegularStream(bytes, sectorSize, fat, entry.startSector, entry.size);
6482
+ }
6483
+ };
6484
+ }
6485
+ function hasCompoundSignature(bytes) {
6486
+ return CFB_SIGNATURE.every((value, index) => bytes[index] === value);
6487
+ }
6488
+ function readDifat(view3, sectorSize, firstDifatSector, difatSectorCount) {
6489
+ const difat = [];
6490
+ for (let offset = 76; offset < 512; offset += 4) {
6491
+ const sector = view3.getUint32(offset, true);
6492
+ if (isUsableSector(sector)) {
6493
+ difat.push(sector);
6494
+ }
6495
+ }
6496
+ let next = firstDifatSector;
6497
+ for (let index = 0; index < difatSectorCount && isUsableSector(next); index += 1) {
6498
+ const offset = sectorOffset(next, sectorSize);
6499
+ const entriesPerSector = sectorSize / 4 - 1;
6500
+ for (let item = 0; item < entriesPerSector; item += 1) {
6501
+ const sector = view3.getUint32(offset + item * 4, true);
6502
+ if (isUsableSector(sector)) {
6503
+ difat.push(sector);
6504
+ }
6505
+ }
6506
+ next = view3.getUint32(offset + entriesPerSector * 4, true);
6507
+ }
6508
+ return difat;
6509
+ }
6510
+ function readFat(view3, sectorSize, sectors) {
6511
+ const fat = [];
6512
+ for (const sector of sectors) {
6513
+ if (!isUsableSector(sector) && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR) {
6514
+ continue;
6515
+ }
6516
+ const offset = sectorOffset(sector, sectorSize);
6517
+ for (let item = 0; item < sectorSize / 4; item += 1) {
6518
+ fat.push(view3.getUint32(offset + item * 4, true));
6519
+ }
6520
+ }
6521
+ return fat;
6522
+ }
6523
+ function parseDirectoryEntries(bytes) {
6524
+ const view3 = dataView2(bytes);
6525
+ const entries = [];
6526
+ for (let offset = 0; offset + 128 <= bytes.length; offset += 128) {
6527
+ const nameLength = view3.getUint16(offset + 64, true);
6528
+ const type = bytes[offset + 66] || 0;
6529
+ if (type === 0 || nameLength < 2) {
6530
+ continue;
6531
+ }
6532
+ const nameBytes = bytes.subarray(offset, offset + Math.max(0, nameLength - 2));
6533
+ const name = decodeUtf16Le(nameBytes).replace(/\0+$/g, "");
6534
+ const startSector = view3.getUint32(offset + 116, true);
6535
+ const lowSize = view3.getUint32(offset + 120, true);
6536
+ const highSize = view3.getUint32(offset + 124, true);
6537
+ const size = highSize > 0 ? Number(BigInt(highSize) << 32n) + lowSize : lowSize;
6538
+ entries.push({ name, type, startSector, size });
6539
+ }
6540
+ return entries;
6541
+ }
6542
+ function readRegularStream(bytes, sectorSize, fat, startSector, size) {
6543
+ const chunks = [];
6544
+ for (const sector of sectorChain(fat, startSector)) {
6545
+ const offset = sectorOffset(sector, sectorSize);
6546
+ chunks.push(bytes.subarray(offset, Math.min(bytes.length, offset + sectorSize)));
6547
+ }
6548
+ return concatChunks(chunks, size);
6549
+ }
6550
+ function readMiniStream(miniStream, miniSectorSize, miniFat, startSector, size) {
6551
+ const chunks = [];
6552
+ for (const sector of sectorChain(miniFat, startSector)) {
6553
+ const offset = sector * miniSectorSize;
6554
+ chunks.push(miniStream.subarray(offset, Math.min(miniStream.length, offset + miniSectorSize)));
6555
+ }
6556
+ return concatChunks(chunks, size);
6557
+ }
6558
+ function sectorChain(fat, startSector) {
6559
+ const chain = [];
6560
+ const seen = /* @__PURE__ */ new Set();
6561
+ let current = startSector;
6562
+ while (isUsableSector(current) && current < fat.length && !seen.has(current)) {
6563
+ seen.add(current);
6564
+ chain.push(current);
6565
+ current = fat[current];
6566
+ }
6567
+ return chain;
6568
+ }
6569
+ function parseFib(wordDocument) {
6570
+ const view3 = dataView2(wordDocument);
6571
+ if (view3.getUint16(0, true) !== 42476) {
6572
+ throw new Error("WordDocument FIB \u6807\u8BC6\u65E0\u6548");
6573
+ }
6574
+ const flags = view3.getUint16(10, true);
6575
+ const fcMin = view3.getUint32(24, true);
6576
+ const fcMac = view3.getUint32(28, true);
6577
+ let offset = 32;
6578
+ const csw = view3.getUint16(offset, true);
6579
+ offset += 2 + csw * 2;
6580
+ const fibRgLwOffset = offset + 2;
6581
+ const cslw = view3.getUint16(offset, true);
6582
+ const ccpText = fibRgLwOffset + 16 <= wordDocument.length ? Math.max(0, view3.getInt32(fibRgLwOffset + 12, true)) : 0;
6583
+ offset += 2 + cslw * 4;
6584
+ const cbRgFcLcb = view3.getUint16(offset, true);
6585
+ const fcLcbOffset = offset + 2;
6586
+ const stshOffset = fcLcbOffset + STSH_FC_LCB_INDEX * 8;
6587
+ const clxOffset = fcLcbOffset + CLX_FC_LCB_INDEX * 8;
6588
+ return {
6589
+ encrypted: (flags & 256) !== 0,
6590
+ useOneTable: (flags & 512) !== 0,
6591
+ textIsUnicode: (flags & 4096) !== 0,
6592
+ fcMin,
6593
+ fcMac,
6594
+ ccpText,
6595
+ fcStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset, true) : 0,
6596
+ lcbStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset + 4, true) : 0,
6597
+ fcClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset, true) : 0,
6598
+ lcbClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset + 4, true) : 0
6599
+ };
6600
+ }
6601
+ function parseClxPieces(tableStream, fcClx, lcbClx) {
6602
+ if (lcbClx <= 0 || fcClx < 0 || fcClx >= tableStream.length) {
6603
+ return [];
6604
+ }
6605
+ const end = Math.min(tableStream.length, fcClx + lcbClx);
6606
+ const view3 = dataView2(tableStream);
6607
+ let offset = fcClx;
6608
+ while (offset < end) {
6609
+ const marker = tableStream[offset];
6610
+ if (marker === 1) {
6611
+ const size = offset + 3 <= end ? view3.getUint16(offset + 1, true) : 0;
6612
+ offset += 3 + size;
6613
+ continue;
6614
+ }
6615
+ if (marker === 2) {
6616
+ if (offset + 5 > end) {
6617
+ break;
6618
+ }
6619
+ const plcSize = view3.getUint32(offset + 1, true);
6620
+ const plcOffset = offset + 5;
6621
+ return parsePlcPcd(tableStream, plcOffset, Math.min(end, plcOffset + plcSize));
6622
+ }
6623
+ offset += 1;
6624
+ }
6625
+ return [];
6626
+ }
6627
+ function parsePlcPcd(tableStream, offset, end) {
6628
+ const size = end - offset;
6629
+ if (size < 16 || (size - 4) % 12 !== 0) {
6630
+ return [];
6631
+ }
6632
+ const view3 = dataView2(tableStream);
6633
+ const pieceCount = Math.floor((size - 4) / 12);
6634
+ const pcdOffset = offset + (pieceCount + 1) * 4;
6635
+ const pieces = [];
6636
+ for (let index = 0; index < pieceCount; index += 1) {
6637
+ const cpStart = view3.getUint32(offset + index * 4, true);
6638
+ const cpEnd = view3.getUint32(offset + (index + 1) * 4, true);
6639
+ const descriptorOffset = pcdOffset + index * 8;
6640
+ const fcCompressed = view3.getUint32(descriptorOffset + 2, true);
6641
+ const compressed = (fcCompressed & 1073741824) !== 0;
6642
+ const fileOffset = compressed ? (fcCompressed & 1073741823) / 2 : fcCompressed;
6643
+ if (cpEnd > cpStart) {
6644
+ pieces.push({ cpStart, cpEnd, fileOffset, compressed });
6645
+ }
6646
+ }
6647
+ return pieces;
6648
+ }
6649
+ function readPieceTableText(wordDocument, pieces, ccpText) {
6650
+ let output = "";
6651
+ for (const piece of pieces) {
6652
+ const cpEnd = ccpText > 0 ? Math.min(piece.cpEnd, ccpText) : piece.cpEnd;
6653
+ const charCount = Math.max(0, cpEnd - piece.cpStart);
6654
+ if (charCount === 0) {
6655
+ continue;
6656
+ }
6657
+ const byteLength = charCount * (piece.compressed ? 1 : 2);
6658
+ const bytes = wordDocument.subarray(piece.fileOffset, Math.min(wordDocument.length, piece.fileOffset + byteLength));
6659
+ output += piece.compressed ? decodeWindows1252(bytes) : decodeUtf16Le(bytes);
6660
+ }
6661
+ return output;
6662
+ }
6663
+ function readFibTextFallback(wordDocument, fib) {
6664
+ const bytes = wordDocument.subarray(fib.fcMin, Math.min(wordDocument.length, fib.fcMac));
6665
+ return fib.textIsUnicode ? decodeUtf16Le(bytes) : decodeWindows1252(bytes);
6666
+ }
6667
+ function splitWordParagraphs(text) {
6668
+ const normalized = text.replace(/\u0000/g, "").replace(/\u0007/g, " ").replace(/\u000b/g, "\n");
6669
+ const paragraphs = [];
6670
+ for (const segment of normalized.split(/(\u000c)/)) {
6671
+ if (segment === "\f") {
6672
+ paragraphs.push(WORD_PAGE_BREAK);
6673
+ continue;
6674
+ }
6675
+ paragraphs.push(
6676
+ ...segment.split(/\r|\n{2,}/).map((paragraph) => cleanWordText(paragraph)).filter((paragraph) => paragraph.length > 0 && isDisplayableParagraph(paragraph))
6677
+ );
6678
+ }
6679
+ return paragraphs.slice(0, 1e3);
6680
+ }
6681
+ function removeTrailingFooterArtifacts(paragraphs) {
6682
+ const tailStart = Math.max(0, paragraphs.length - 32);
6683
+ const tail = paragraphs.slice(tailStart);
6684
+ const relativePageFieldIndex = tail.findIndex(isFooterPageField);
6685
+ if (relativePageFieldIndex < 0) {
6686
+ return paragraphs;
6687
+ }
6688
+ let start = tailStart + relativePageFieldIndex;
6689
+ for (let index = start - 1; index >= tailStart; index -= 1) {
6690
+ const paragraph = paragraphs[index];
6691
+ if (paragraph === WORD_PAGE_BREAK || isLikelyFooterArtifact(paragraph)) {
6692
+ start = index;
6693
+ continue;
6694
+ }
6695
+ break;
6696
+ }
6697
+ const artifactSlice = paragraphs.slice(start);
6698
+ const footerCueCount = artifactSlice.filter(isLikelyFooterArtifact).length;
6699
+ if (footerCueCount < 2) {
6700
+ return paragraphs;
6701
+ }
6702
+ return paragraphs.slice(0, start);
6703
+ }
6704
+ function isFooterPageField(paragraph) {
6705
+ return /^(?:PAGE|Page)(?:\s+(?:PAGE|\d+))?(?:\s+of\s+(?:NUMPAGES|\d+))?$/i.test(paragraph.trim()) || /\bNUMPAGES\b/i.test(paragraph);
6706
+ }
6707
+ function isLikelyFooterArtifact(paragraph) {
6708
+ const value = paragraph.trim();
6709
+ return value === WORD_PAGE_BREAK || isFooterPageField(value) || /^wd-[\w.-]+$/i.test(value) || /^\d{1,2}\s+[A-Za-z]+\s+\d{4}$/.test(value) || /^Copyright\s+©?\s*(?:OASIS|2002 OASIS)/i.test(value);
6710
+ }
6711
+ function buildWordBlocks(paragraphs) {
6712
+ const blocks = [];
6713
+ let index = 0;
6714
+ while (index < paragraphs.length) {
6715
+ const paragraph = paragraphs[index];
6716
+ if (paragraph === WORD_PAGE_BREAK) {
6717
+ blocks.push({ type: "pageBreak" });
6718
+ index += 1;
6719
+ continue;
6720
+ }
6721
+ const toc = parseTocEntry(paragraph);
6722
+ if (toc) {
6723
+ blocks.push(toc);
6724
+ index += 1;
6725
+ continue;
6726
+ }
6727
+ if (isTableRowCandidate(paragraph)) {
6728
+ const rows = [];
6729
+ while (index < paragraphs.length && isTableRowCandidate(paragraphs[index])) {
6730
+ rows.push(...normalizeTableRows(splitTableRow(paragraphs[index])));
6731
+ index += 1;
6732
+ }
6733
+ blocks.push({ type: "table", rows });
6734
+ continue;
6735
+ }
6736
+ blocks.push(classifyParagraphBlock(paragraph, blocks));
6737
+ index += 1;
6738
+ }
6739
+ return blocks;
6740
+ }
6741
+ function inferLayoutHints(paragraphs, assets) {
6742
+ const sample = paragraphs.slice(0, 40).join("\n");
6743
+ const isOasisSpec = /Word Specification Sample/.test(sample) && /\bOASIS\b/i.test(paragraphs.join("\n"));
6744
+ const oasisImage = isOasisSpec ? assets.find((asset) => asset.mimeType === "image/png" && asset.width && asset.height && asset.width / asset.height > 2.5) : void 0;
6745
+ return {
6746
+ lineNumbers: isOasisSpec,
6747
+ headerBrand: isOasisSpec ? "oasis" : void 0,
6748
+ headerImageId: oasisImage?.id,
6749
+ footer: isOasisSpec ? inferOasisFooter(paragraphs) : void 0
6750
+ };
6751
+ }
6752
+ function inferOasisFooter(paragraphs) {
6753
+ const documentId = findValueAfterLabel(paragraphs, "Document identifier:") || paragraphs.find((paragraph) => /^wd-[\w.-]+/i.test(paragraph));
6754
+ const subtitle = paragraphs.find((paragraph) => /\b(?:draft|version)\b/i.test(paragraph) && /\d{4}/.test(paragraph));
6755
+ const date = subtitle?.match(/\b\d{1,2}\s+[A-Za-z]+\s+\d{4}\b/)?.[0];
6756
+ const copyright = paragraphs.find((paragraph) => /Copyright.*OASIS.*All Rights Reserved/i.test(paragraph)) || "Copyright \xA9 OASIS Open 2002. All Rights Reserved.";
6757
+ return { documentId, date, copyright };
6758
+ }
6759
+ function findValueAfterLabel(paragraphs, label) {
6760
+ const index = paragraphs.findIndex((paragraph) => paragraph.toLowerCase() === label.toLowerCase());
6761
+ if (index < 0) {
6762
+ return void 0;
6763
+ }
6764
+ return paragraphs.slice(index + 1).find((paragraph) => paragraph !== WORD_PAGE_BREAK && paragraph.length > 0);
6765
+ }
6766
+ function paginateWordBlocks(blocks, layout) {
6767
+ const maxLines = layout.lineNumbers ? 33 : 46;
6768
+ const pages = [];
6769
+ let current = [];
6770
+ let usedLines = 0;
6771
+ for (const block of blocks) {
6772
+ if (block.type === "pageBreak") {
6773
+ if (current.length > 0) {
6774
+ pages.push(current);
6775
+ }
6776
+ current = [];
6777
+ usedLines = 0;
6778
+ continue;
6779
+ }
6780
+ const lines = estimatedLineCount(block);
6781
+ const shouldBreak = current.length > 0 && (usedLines + lines > maxLines || block.type === "heading" && usedLines > Math.floor(maxLines * 0.72));
6782
+ if (shouldBreak) {
6783
+ pages.push(current);
6784
+ current = [];
6785
+ usedLines = 0;
6786
+ }
6787
+ current.push(block);
6788
+ usedLines += lines;
6789
+ }
6790
+ if (current.length > 0 || pages.length === 0) {
6791
+ pages.push(current);
6792
+ }
6793
+ return pages;
6794
+ }
6795
+ function estimatedLineCount(block) {
6796
+ if (block.type === "pageBreak") {
6797
+ return 0;
6798
+ }
6799
+ if (block.type === "table") {
6800
+ return Math.max(1, block.rows.length);
6801
+ }
6802
+ if (block.type === "toc") {
6803
+ return 1;
6804
+ }
6805
+ const baseWidth = "indent" in block && block.indent ? 78 : 96;
6806
+ return Math.max(1, Math.ceil(block.text.length / baseWidth));
6807
+ }
6808
+ function classifyParagraphBlock(text, previousBlocks) {
6809
+ const visibleIndex = previousBlocks.filter((block) => block.type !== "toc").length;
6810
+ if (visibleIndex === 0 && text.length <= 140) {
6811
+ return { type: "title", text };
6812
+ }
6813
+ if (visibleIndex === 1 && /draft|version|20\d{2}|19\d{2}/i.test(text) && text.length <= 140) {
6814
+ return { type: "subtitle", text };
6815
+ }
6816
+ const headingLevel = inferHeadingLevel(text, previousBlocks);
6817
+ if (headingLevel) {
6818
+ return { type: "heading", text, level: headingLevel };
6819
+ }
6820
+ if (/^[\w\s/().-]{2,45}:$/.test(text)) {
6821
+ return { type: "label", text };
6822
+ }
6823
+ if (isInstructionParagraph(text)) {
6824
+ return { type: "instruction", text, indent: shouldIndentParagraph(previousBlocks) };
6825
+ }
6826
+ if (/^\[[-\w.]+\]\s+/.test(text)) {
6827
+ return { type: "reference", text };
6828
+ }
6829
+ const listLevel = inferListItemLevel(text);
6830
+ if (listLevel) {
6831
+ return { type: "listItem", text, level: listLevel };
6832
+ }
6833
+ if (isCodeLikeParagraph(text)) {
6834
+ return { type: "code", text, indent: shouldIndentParagraph(previousBlocks) };
6835
+ }
6836
+ return { type: "paragraph", text, indent: shouldIndentParagraph(previousBlocks) };
6837
+ }
6838
+ function isInstructionParagraph(text) {
6839
+ return /^\[[^\]]{8,}\]$/.test(text.trim());
6840
+ }
6841
+ function inferHeadingLevel(text, previousBlocks) {
6842
+ if (text.length > 120) {
6843
+ return void 0;
6844
+ }
6845
+ if (/^table of contents$/i.test(text)) {
6846
+ return 1;
6847
+ }
6848
+ if (/^(?:introduction|word styles|references|appendix\b.*|acknowledgments|revision history|notices)$/i.test(text)) {
6849
+ return 1;
6850
+ }
6851
+ const numbered = text.match(/^([1-9](?:\.\d+)*)\s+.+/);
6852
+ if (numbered) {
6853
+ return Math.min(3, numbered[1].split(".").length);
6854
+ }
6855
+ if (/^(?:terminology|overall style|title page|headings|paragraphs|lists|tables|code examples|character styles|normative)$/i.test(text)) {
6856
+ return 2;
6857
+ }
6858
+ const previousHeading = [...previousBlocks].reverse().find((block) => block.type === "heading");
6859
+ if (previousHeading?.type === "heading" && previousHeading.level === 1 && /^[A-Z][A-Za-z0-9 ()/-]{2,80}$/.test(text)) {
6860
+ return 2;
6861
+ }
6862
+ return void 0;
6863
+ }
6864
+ function shouldIndentParagraph(previousBlocks) {
6865
+ for (let index = previousBlocks.length - 1; index >= 0; index -= 1) {
6866
+ const block = previousBlocks[index];
6867
+ if (block.type === "toc" || block.type === "table") {
6868
+ continue;
6869
+ }
6870
+ if (block.type === "label") {
6871
+ return true;
6872
+ }
6873
+ if ((block.type === "paragraph" || block.type === "code") && block.indent) {
6874
+ return true;
6875
+ }
6876
+ return false;
6877
+ }
6878
+ return false;
6879
+ }
6880
+ function inferListItemLevel(text) {
6881
+ if (/^(?:list bullet|definition term)$/i.test(text)) {
6882
+ return 1;
6883
+ }
6884
+ if (/^(?:list bullet 2|list continue 2|definition for the term\.)$/i.test(text)) {
6885
+ return 2;
6886
+ }
6887
+ return void 0;
6888
+ }
6889
+ function parseTocEntry(text) {
6890
+ const tabCells = splitTableRow(text);
6891
+ if (tabCells.length >= 2 && /^\d{1,3}$/.test(tabCells[tabCells.length - 1] || "")) {
6892
+ const title2 = tabCells.slice(0, -1).join(" ").trim();
6893
+ if (isLikelyTocTitle(title2)) {
6894
+ const number2 = title2.match(/^(\d+(?:\.\d+)*)\b/)?.[1] || "";
6895
+ return { type: "toc", title: title2, page: tabCells[tabCells.length - 1], level: number2.includes(".") ? Math.min(3, number2.split(".").length) : 1 };
6896
+ }
6897
+ }
6898
+ const cleaned = text.replace(/\s+/g, " ").trim();
6899
+ const match = cleaned.match(/^(?:(\d+(?:\.\d+)*)\s+)?(.+?)\s+(\d{1,3})$/);
6900
+ if (!match || cleaned.length > 140) {
6901
+ return void 0;
6902
+ }
6903
+ const number = match[1] || "";
6904
+ const title = `${number ? `${number} ` : ""}${match[2] || ""}`.trim();
6905
+ const page = match[3];
6906
+ if (!title || !page || !/^(?:appendix\b|references\b|introduction\b|[A-Z0-9])/i.test(title)) {
6907
+ return void 0;
6908
+ }
6909
+ if (!isLikelyTocTitle(title)) {
6910
+ return void 0;
6911
+ }
6912
+ const level = number.includes(".") ? Math.min(3, number.split(".").length) : 1;
6913
+ return { type: "toc", title, page, level };
6914
+ }
6915
+ function isLikelyTocTitle(title) {
6916
+ return /^(?:appendix\b|references\b|introduction\b|[1-9](?:\.\d+)*\b|[A-Z][\w\s.-]{2,80}$)/i.test(title);
6917
+ }
6918
+ function isTableRowCandidate(text) {
6919
+ if (/^\[[-\w.]+\]\t+/.test(text)) {
6920
+ return false;
6921
+ }
6922
+ const cells = splitTableRow(text);
6923
+ return cells.length >= 2 && cells.some((cell) => cell.length > 0);
6924
+ }
6925
+ function splitTableRow(text) {
6926
+ return text.split(/\t+/).map((cell) => cell.trim()).filter(Boolean);
6927
+ }
6928
+ function normalizeTableRows(cells) {
6929
+ if (cells.length >= 8) {
6930
+ const columnCount = inferTableColumnCount(cells);
6931
+ if (columnCount > 1 && cells.length % columnCount === 0) {
6932
+ const rows = [];
6933
+ for (let offset = 0; offset < cells.length; offset += columnCount) {
6934
+ rows.push(cells.slice(offset, offset + columnCount));
6935
+ }
6936
+ return rows;
6937
+ }
6938
+ }
6939
+ return [cells];
6940
+ }
6941
+ function inferTableColumnCount(cells) {
6942
+ const header = cells.slice(0, 6).join(" ").toLowerCase();
6943
+ if (/\brev\b/.test(header) && /\bdate\b/.test(header) && /whom|what/.test(header)) {
6944
+ return 4;
6945
+ }
6946
+ for (const candidate of [5, 4, 3, 2]) {
6947
+ if (cells.length % candidate === 0) {
6948
+ return candidate;
6949
+ }
6950
+ }
6951
+ return 0;
6952
+ }
6953
+ function isCodeLikeParagraph(text) {
6954
+ return /^\d{24,}$/.test(text.replace(/\s+/g, "")) || /^GET\s+https?:\/\//i.test(text) || /^<other\s+HTTP\b/i.test(text) || /<\/?[A-Za-z][A-Za-z0-9:-]*(?:\s+[^>@]*)?>/.test(text) || /^\s*(?:<\?xml|function\b|const\b|let\b|var\b|if\s*\(|for\s*\(|while\s*\(|\{|\}|\/\/)/.test(text);
6955
+ }
6956
+ function cleanWordText(value) {
6957
+ return stripWordFieldCodes(value).replace(/[\u0001-\u0006\u0008\u000e-\u001f]/g, "").replace(/ {2,}/g, " ").trim();
6958
+ }
6959
+ function stripWordFieldCodes(value) {
6960
+ return value.replace(/\u0013\s*(?:HYPERLINK|PAGEREF|TOC)\b[^\u0014\u0015]*/gi, "").replace(/[\u0013-\u0015]/g, "").replace(/\bHYPERLINK\s+\\l\s+"[^"]*"\s*/gi, "").replace(/\bHYPERLINK\s+"[^"]*"\s*/gi, "").replace(/\bPAGEREF\s+\S+\s+\\h\s*/gi, "").replace(/\bTOC\s+\\o\s+"[^"]*"\s+\\h\s+\\z\s*/gi, "").replace(/\bREF\s+[_A-Za-z0-9-]+\s+(?:\\[A-Za-z]+\s*)+/gi, "");
6961
+ }
6962
+ function isDisplayableParagraph(value) {
6963
+ if (value.length < 2) {
6964
+ return false;
6965
+ }
6966
+ const letters = [...value].filter((char) => /[\p{L}\p{N}]/u.test(char)).length;
6967
+ return letters >= Math.min(2, value.length);
6968
+ }
6969
+ function inferDocumentTitle(paragraphs) {
6970
+ return paragraphs.find((paragraph) => paragraph.length <= 120) || "Word \u6587\u6863";
6971
+ }
6972
+ function appendMeta4(list, label, value) {
6973
+ const term = window.document.createElement("dt");
6974
+ term.textContent = label;
6975
+ const detail = window.document.createElement("dd");
6976
+ detail.textContent = value;
6977
+ list.append(term, detail);
6978
+ }
6979
+ function concatChunks(chunks, size) {
6980
+ const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
6981
+ const output = new Uint8Array(size === void 0 ? total : Math.min(total, size));
6982
+ let offset = 0;
6983
+ for (const chunk of chunks) {
6984
+ const slice = chunk.subarray(0, Math.min(chunk.length, output.length - offset));
6985
+ output.set(slice, offset);
6986
+ offset += slice.length;
6987
+ if (offset >= output.length) {
6988
+ break;
6989
+ }
6990
+ }
6991
+ return output;
6992
+ }
6993
+ function alignEven(value) {
6994
+ return value % 2 === 0 ? value : value + 1;
6995
+ }
6996
+ function isUsableSector(sector) {
6997
+ return sector !== FREE_SECTOR && sector !== END_OF_CHAIN && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR;
6998
+ }
6999
+ function sectorOffset(sector, sectorSize) {
7000
+ return (sector + 1) * sectorSize;
7001
+ }
7002
+ function normalizeStreamName(name) {
7003
+ return name.replace(/^\/+/, "").toLowerCase();
7004
+ }
7005
+ function decodeUtf16Le(bytes) {
7006
+ return new TextDecoder("utf-16le").decode(bytes);
7007
+ }
7008
+ function decodeWindows1252(bytes) {
7009
+ try {
7010
+ return new TextDecoder("windows-1252").decode(bytes);
7011
+ } catch {
7012
+ return Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
7013
+ }
7014
+ }
7015
+ function dataView2(bytes) {
7016
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
7017
+ }
7018
+
7019
+ // src/plugins/office.ts
5865
7020
  var wordExtensions = /* @__PURE__ */ new Set(["docx", "docm", "doc", "dotx", "dotm", "dot", "rtf", "odt", "fodt", "wps"]);
5866
7021
  var sheetExtensions = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "xlt", "xltx", "xltm", "csv", "tsv", "ods", "fods", "numbers", "et"]);
5867
7022
  var presentationExtensions = /* @__PURE__ */ new Set(["pptx", "pptm", "ppt", "pps", "ppsx", "ppsm", "potx", "potm", "odp", "fodp", "key", "dps"]);
@@ -5948,13 +7103,13 @@ function officePlugin(options = {}) {
5948
7103
  if (conversionContext && await shouldUseOfficeConversion(options, conversionContext)) {
5949
7104
  delegatedInstance = await renderConvertedOfficePreview(panel, ctx, options, conversionContext);
5950
7105
  } else if (packageFormat === "docx" && !fileIsDocx(extension)) {
5951
- disposeDocxFit = await renderDocx(panel, arrayBuffer);
7106
+ disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
5952
7107
  } else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
5953
7108
  await renderSheet(panel, arrayBuffer, "xlsx");
5954
7109
  } else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
5955
7110
  await renderPptx(panel, arrayBuffer);
5956
7111
  } else if (fileIsDocx(extension)) {
5957
- disposeDocxFit = await renderDocx(panel, arrayBuffer);
7112
+ disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
5958
7113
  } else if (extension === "rtf") {
5959
7114
  renderPlainDocument(panel, "RTF \u6587\u6863", rtfToText(await readTextFromBuffer(arrayBuffer)));
5960
7115
  } else if (extension === "odt") {
@@ -5963,7 +7118,7 @@ function officePlugin(options = {}) {
5963
7118
  renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
5964
7119
  } else if (extension === "fods") {
5965
7120
  renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
5966
- } else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension)) {
7121
+ } else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
5967
7122
  } else if (sheetExtensions.has(extension)) {
5968
7123
  await renderSheet(panel, arrayBuffer, extension);
5969
7124
  } else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
@@ -5972,6 +7127,8 @@ function officePlugin(options = {}) {
5972
7127
  await renderOdp(panel, arrayBuffer);
5973
7128
  } else if (extension === "fodp") {
5974
7129
  renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
7130
+ } else if (extension === "doc" || extension === "dot") {
7131
+ renderLegacyWordBinary(panel, extension, arrayBuffer);
5975
7132
  } else if (isLegacyOfficeBinary(extension)) {
5976
7133
  renderLegacyOfficeBinary(panel, extension, arrayBuffer);
5977
7134
  } else {
@@ -6165,7 +7322,7 @@ async function detectPackagedOfficeFormat(arrayBuffer) {
6165
7322
  }
6166
7323
  return void 0;
6167
7324
  }
6168
- async function renderDocx(panel, arrayBuffer) {
7325
+ async function renderDocx(panel, arrayBuffer, fit) {
6169
7326
  const content = document.createElement("div");
6170
7327
  content.className = "ofv-docx-document";
6171
7328
  const styleContainer = document.createElement("div");
@@ -6204,7 +7361,7 @@ async function renderDocx(panel, arrayBuffer) {
6204
7361
  return () => void 0;
6205
7362
  }
6206
7363
  panel.append(content);
6207
- disposeFit = fitDocxPages(content);
7364
+ disposeFit = fitDocxPages(content, fit);
6208
7365
  return () => {
6209
7366
  disposeFit?.();
6210
7367
  styleContainer.remove();
@@ -6802,7 +7959,8 @@ function looksLikeDocxTextboxHeading(value) {
6802
7959
  return text.length > 0 && text.length <= 12 && !/[0-9@.::]/.test(text);
6803
7960
  }
6804
7961
  async function normalizeDocxLayout(container, arrayBuffer) {
6805
- const hints = await readDocxLayoutHints(arrayBuffer);
7962
+ const [hints, charts] = await Promise.all([readDocxLayoutHints(arrayBuffer), readDocxCharts(arrayBuffer)]);
7963
+ repairDocxChartPlaceholders(container, charts);
6806
7964
  const pages = container.querySelectorAll("section.ofv-docx");
6807
7965
  for (const page of pages) {
6808
7966
  repairDocxShapeFills(page);
@@ -6817,6 +7975,75 @@ async function normalizeDocxLayout(container, arrayBuffer) {
6817
7975
  }
6818
7976
  }
6819
7977
  }
7978
+ async function readDocxCharts(arrayBuffer) {
7979
+ try {
7980
+ const zip = await import_jszip3.default.loadAsync(arrayBuffer);
7981
+ const documentXml = await zip.file("word/document.xml")?.async("text");
7982
+ const documentDoc = documentXml ? parseOfficeXml(documentXml) : void 0;
7983
+ if (!documentDoc) {
7984
+ return [];
7985
+ }
7986
+ const relationships = await readOfficeRelationships(zip, "word/document.xml");
7987
+ const chartDrawings = Array.from(documentDoc.getElementsByTagName("*")).filter((element) => element.localName === "inline" || element.localName === "anchor").map((element) => readDocxChartDrawing(element)).filter((item) => Boolean(item?.relationshipId));
7988
+ const charts = [];
7989
+ for (const [index, drawing] of chartDrawings.entries()) {
7990
+ const chartRel = relationships.find((rel) => rel.id === drawing.relationshipId && /\/chart$/i.test(rel.type));
7991
+ const chartPath = resolveOfficeRelationshipTarget("word/document.xml", chartRel?.target);
7992
+ const chartXml = chartPath ? await zip.file(chartPath)?.async("text") : void 0;
7993
+ const chart = chartXml ? parseChartXml(chartXml, chartPath?.split("/").pop() || `chart${index + 1}.xml`) : null;
7994
+ if (chart) {
7995
+ charts.push({ ...chart, widthPt: drawing.widthPt, heightPt: drawing.heightPt });
7996
+ }
7997
+ }
7998
+ return charts;
7999
+ } catch {
8000
+ return [];
8001
+ }
8002
+ }
8003
+ function readDocxChartDrawing(element) {
8004
+ const chart = Array.from(element.getElementsByTagName("*")).find((child) => child.localName === "chart");
8005
+ const relationshipId = chart ? getXmlAttribute3(chart, "id") : "";
8006
+ if (!relationshipId) {
8007
+ return void 0;
8008
+ }
8009
+ const extent = Array.from(element.children).find((child) => child.localName === "extent");
8010
+ return {
8011
+ relationshipId,
8012
+ widthPt: emuToPt(Number(extent?.getAttribute("cx") || 0)),
8013
+ heightPt: emuToPt(Number(extent?.getAttribute("cy") || 0))
8014
+ };
8015
+ }
8016
+ function repairDocxChartPlaceholders(container, charts) {
8017
+ if (charts.length === 0) {
8018
+ return;
8019
+ }
8020
+ const placeholders = Array.from(container.querySelectorAll("section.ofv-docx div")).filter(isDocxChartPlaceholder);
8021
+ if (placeholders.length !== charts.length) {
8022
+ return;
8023
+ }
8024
+ placeholders.forEach((placeholder, index) => {
8025
+ const chart = charts[index];
8026
+ placeholder.classList.add("ofv-docx-chart-preview");
8027
+ placeholder.dataset.ofvDocxChartPreview = "true";
8028
+ if (chart.widthPt > 0) {
8029
+ placeholder.style.width ||= `${formatCssNumber(chart.widthPt)}pt`;
8030
+ }
8031
+ if (chart.heightPt > 0) {
8032
+ placeholder.style.height ||= `${formatCssNumber(chart.heightPt)}pt`;
8033
+ }
8034
+ placeholder.replaceChildren(renderChartSvg(chart));
8035
+ });
8036
+ }
8037
+ function isDocxChartPlaceholder(element) {
8038
+ if (element.dataset.ofvDocxChartPreview === "true" || element.children.length > 0 || normalizePreviewText(element.textContent || "")) {
8039
+ return false;
8040
+ }
8041
+ const display = element.style.display;
8042
+ const position = element.style.position;
8043
+ const width = parseCssPixelValue(element.style.width);
8044
+ const height = parseCssPixelValue(element.style.height);
8045
+ return display === "inline-block" && position === "relative" && width >= 120 && height >= 80;
8046
+ }
6820
8047
  function repairDocxHeadingShapeAlignment(page) {
6821
8048
  for (const paragraph of page.querySelectorAll("p")) {
6822
8049
  const text = normalizePreviewText(paragraph.textContent || "");
@@ -6967,14 +8194,19 @@ function repairDocxShapeFills(page) {
6967
8194
  }
6968
8195
  }
6969
8196
  function repairDocxFloatingPictures(page, hints) {
6970
- const hint = hints.floatingPictures.find((item) => item.relativeFrom === "column" && item.wrap === "square");
6971
- if (!hint) {
8197
+ const pageHints = hints.floatingPictures.filter((item) => item.relativeFrom === "column" && item.wrap === "square");
8198
+ if (pageHints.length === 0) {
6972
8199
  return;
6973
8200
  }
6974
- const image = page.querySelector("img");
6975
- if (!image) {
8201
+ const images = Array.from(page.querySelectorAll("img")).filter(
8202
+ (image) => image.closest("[data-ofv-docx-float-repaired='true']") === null
8203
+ );
8204
+ if (images.length === 0 || images.length !== pageHints.length) {
6976
8205
  return;
6977
8206
  }
8207
+ images.forEach((image, index) => repairDocxFloatingPicture(page, image, pageHints[index]));
8208
+ }
8209
+ function repairDocxFloatingPicture(page, image, hint) {
6978
8210
  const wrapper = image.parentElement;
6979
8211
  if (!wrapper || wrapper.dataset.ofvDocxFloatRepaired === "true") {
6980
8212
  return;
@@ -7020,7 +8252,7 @@ function parseCssLineHeight(value) {
7020
8252
  const parsed = Number.parseFloat(trimmed);
7021
8253
  return Number.isFinite(parsed) ? parsed : 0;
7022
8254
  }
7023
- function fitDocxPages(container) {
8255
+ function fitDocxPages(container, fit) {
7024
8256
  const wrapper = container.querySelector(".ofv-docx-wrapper");
7025
8257
  if (!wrapper) {
7026
8258
  return () => void 0;
@@ -7033,6 +8265,7 @@ function fitDocxPages(container) {
7033
8265
  return;
7034
8266
  }
7035
8267
  const availableWidth = Math.max(1, container.clientWidth - 48);
8268
+ const availableHeight = container.clientHeight > 0 ? Math.max(1, container.clientHeight - 48) : void 0;
7036
8269
  const pageWidth = Math.max(
7037
8270
  1,
7038
8271
  ...frames.map(({ page }) => {
@@ -7040,14 +8273,24 @@ function fitDocxPages(container) {
7040
8273
  return page.offsetWidth || rectWidth || parseCssPixelValue(page.style.width) || 794;
7041
8274
  })
7042
8275
  );
7043
- const scale = Math.min(1, Math.max(0.35, availableWidth / pageWidth));
8276
+ const pageHeight = Math.max(
8277
+ 1,
8278
+ ...frames.map(({ page }) => page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height) || 1123)
8279
+ );
8280
+ const scale = getDocxFitScale(fit, availableWidth, availableHeight, pageWidth, pageHeight);
7044
8281
  const userZoom = parseCssPixelValue(panel?.style.getPropertyValue("--ofv-office-zoom") || "1") || 1;
7045
8282
  wrapper.style.setProperty("--ofv-docx-scale", formatCssNumber(scale));
7046
8283
  wrapper.style.setProperty("--ofv-docx-page-width", `${pageWidth}px`);
8284
+ wrapper.style.width = `${Math.ceil(pageWidth * scale * userZoom + 48)}px`;
8285
+ wrapper.style.maxWidth = "none";
8286
+ wrapper.style.overflow = "visible";
7047
8287
  for (const { frame, page } of frames) {
7048
- const pageHeight = page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height);
7049
- if (pageHeight > 0) {
7050
- frame.style.height = `${Math.ceil(pageHeight * scale * userZoom)}px`;
8288
+ const framePageHeight = page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height);
8289
+ const framePageWidth = page.offsetWidth || page.getBoundingClientRect().width || parseCssPixelValue(page.style.width) || pageWidth;
8290
+ frame.style.width = `${Math.ceil(framePageWidth * scale * userZoom)}px`;
8291
+ frame.style.maxWidth = "none";
8292
+ if (framePageHeight > 0) {
8293
+ frame.style.height = `${Math.ceil(framePageHeight * scale * userZoom)}px`;
7051
8294
  }
7052
8295
  }
7053
8296
  };
@@ -7072,6 +8315,26 @@ function fitDocxPages(container) {
7072
8315
  observer.disconnect();
7073
8316
  };
7074
8317
  }
8318
+ function getDocxFitScale(fit, availableWidth, availableHeight, pageWidth, pageHeight) {
8319
+ const widthScale = availableWidth / pageWidth;
8320
+ const heightScale = availableHeight ? availableHeight / pageHeight : void 0;
8321
+ if (fit === "actual") {
8322
+ return 1;
8323
+ }
8324
+ if (fit === "height") {
8325
+ return Math.max(0.1, heightScale ?? widthScale);
8326
+ }
8327
+ if (fit === "cover") {
8328
+ return Math.max(0.1, Math.max(widthScale, heightScale ?? widthScale));
8329
+ }
8330
+ if (fit === "scale-down") {
8331
+ return Math.min(1, Math.max(0.1, Math.min(widthScale, heightScale ?? widthScale)));
8332
+ }
8333
+ if (fit === "contain") {
8334
+ return Math.max(0.1, Math.min(widthScale, heightScale ?? widthScale));
8335
+ }
8336
+ return Math.max(0.1, widthScale);
8337
+ }
7075
8338
  function ensureDocxPageFrames(wrapper) {
7076
8339
  const pages = Array.from(wrapper.querySelectorAll("section.ofv-docx"));
7077
8340
  return pages.map((page) => {
@@ -7603,9 +8866,9 @@ function parseChartXml(xml, fallbackName) {
7603
8866
  return null;
7604
8867
  }
7605
8868
  const type = detectChartType(doc);
7606
- const title = textFromFirst(doc, "title") || fallbackName.replace(/\.xml$/i, "");
8869
+ const title = readChartTitle(doc, fallbackName);
7607
8870
  const seriesElements = Array.from(doc.getElementsByTagName("*")).filter((element) => element.localName === "ser");
7608
- const series = seriesElements.map((element, index) => parseChartSeries(element, index)).filter((item) => item.values.length > 0);
8871
+ const series = seriesElements.map((element, index) => ({ ...parseChartSeries(element, index), color: readChartSeriesColor(element) })).filter((item) => item.values.length > 0);
7609
8872
  if (series.length === 0) {
7610
8873
  return null;
7611
8874
  }
@@ -7614,9 +8877,21 @@ function parseChartXml(xml, fallbackName) {
7614
8877
  type,
7615
8878
  title,
7616
8879
  categories: series.find((item) => item.categories.length > 0)?.categories || [],
7617
- series: series.map((item) => ({ name: item.name, values: item.values }))
8880
+ series: series.map((item) => ({ name: item.name, values: item.values, color: item.color }))
7618
8881
  };
7619
8882
  }
8883
+ function readChartTitle(doc, fallbackName) {
8884
+ const titleElement = Array.from(doc.getElementsByTagName("*")).find((element) => element.localName === "title");
8885
+ if (!titleElement) {
8886
+ return fallbackName.replace(/\.xml$/i, "");
8887
+ }
8888
+ const explicitTitle = chartText(titleElement);
8889
+ if (explicitTitle) {
8890
+ return explicitTitle;
8891
+ }
8892
+ const language = Array.from(doc.getElementsByTagName("*")).find((element) => element.localName === "lang")?.getAttribute("val") || "";
8893
+ return /^zh\b/i.test(language) ? "\u56FE\u8868\u6807\u9898" : "Chart Title";
8894
+ }
7620
8895
  function detectChartType(doc) {
7621
8896
  const chartType = Array.from(doc.getElementsByTagName("*")).find(
7622
8897
  (element) => element.localName.endsWith("Chart") && element.localName !== "chart"
@@ -7633,6 +8908,31 @@ function parseChartSeries(element, index) {
7633
8908
  categories: stringsFromFirst(element, "cat")
7634
8909
  };
7635
8910
  }
8911
+ function readChartSeriesColor(element) {
8912
+ const shape = Array.from(element?.children || []).find((child) => child.localName === "spPr");
8913
+ const color = Array.from(shape?.getElementsByTagName("*") || []).find(
8914
+ (child) => child.localName === "srgbClr" || child.localName === "schemeClr"
8915
+ );
8916
+ if (!color) {
8917
+ return void 0;
8918
+ }
8919
+ if (color.localName === "srgbClr") {
8920
+ const value = color.getAttribute("val") || "";
8921
+ return /^[\da-f]{6}$/i.test(value) ? `#${value}` : void 0;
8922
+ }
8923
+ return chartSchemeColor(color.getAttribute("val") || "");
8924
+ }
8925
+ function chartSchemeColor(value) {
8926
+ const colors = {
8927
+ accent1: "#156082",
8928
+ accent2: "#e97132",
8929
+ accent3: "#196b24",
8930
+ accent4: "#0f9ed5",
8931
+ accent5: "#a02b93",
8932
+ accent6: "#4ea72e"
8933
+ };
8934
+ return colors[value];
8935
+ }
7636
8936
  function renderChartPreviewSection(charts) {
7637
8937
  const section = createSection("\u8868\u683C\u56FE\u8868\u9884\u89C8");
7638
8938
  const grid = document.createElement("div");
@@ -7670,17 +8970,39 @@ function renderChartCard(chart) {
7670
8970
  }
7671
8971
  function renderChartSvg(chart) {
7672
8972
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
7673
- svg.setAttribute("viewBox", "0 0 640 260");
8973
+ svg.setAttribute("viewBox", "0 0 640 380");
7674
8974
  svg.setAttribute("role", "img");
7675
8975
  svg.setAttribute("aria-label", chart.title);
7676
8976
  svg.classList.add("ofv-chart-svg");
7677
8977
  const allValues = chart.series.flatMap((item) => item.values).filter((value) => Number.isFinite(value));
7678
8978
  const max = Math.max(1, ...allValues);
7679
8979
  const min = Math.min(0, ...allValues);
8980
+ const axisScale = createChartAxisScale(max, min);
8981
+ const axisMax = axisScale.max;
8982
+ const axisMin = axisScale.min;
7680
8983
  const span = max - min || 1;
7681
- const colors = ["#2563eb", "#059669", "#d97706", "#dc2626", "#7c3aed"];
7682
- const plot = { x: 48, y: 24, width: 552, height: 178 };
7683
- appendSvg(svg, "line", { x1: plot.x, y1: plot.y, x2: plot.x, y2: plot.y + plot.height, class: "ofv-chart-axis" });
8984
+ const colors = ["#156082", "#e97132", "#196b24", "#0f9ed5", "#a02b93", "#4ea72e"];
8985
+ const plot = { x: 74, y: 74, width: 526, height: 214 };
8986
+ const categories = chart.categories.length > 0 ? chart.categories : chart.series[0]?.values.map((_, index) => String(index + 1)) || [];
8987
+ const title = appendSvg(svg, "text", { x: 320, y: 34, class: "ofv-chart-title", "text-anchor": "middle" });
8988
+ title.textContent = chart.title;
8989
+ for (const value of axisScale.ticks) {
8990
+ const y = plot.y + plot.height - (value - axisMin) / (axisMax - axisMin || 1) * plot.height;
8991
+ appendSvg(svg, "line", {
8992
+ x1: plot.x,
8993
+ y1: Number(y.toFixed(1)),
8994
+ x2: plot.x + plot.width,
8995
+ y2: Number(y.toFixed(1)),
8996
+ class: value === 0 ? "ofv-chart-axis" : "ofv-chart-gridline"
8997
+ });
8998
+ const label = appendSvg(svg, "text", {
8999
+ x: plot.x - 12,
9000
+ y: Number((y + 4).toFixed(1)),
9001
+ class: "ofv-chart-label",
9002
+ "text-anchor": "end"
9003
+ });
9004
+ label.textContent = formatChartTick(value);
9005
+ }
7684
9006
  appendSvg(svg, "line", {
7685
9007
  x1: plot.x,
7686
9008
  y1: plot.y + plot.height,
@@ -7688,28 +9010,47 @@ function renderChartSvg(chart) {
7688
9010
  y2: plot.y + plot.height,
7689
9011
  class: "ofv-chart-axis"
7690
9012
  });
7691
- chart.series.forEach((series, seriesIndex) => {
7692
- const color = colors[seriesIndex % colors.length];
7693
- const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
7694
- const points = series.values.map((value, index) => ({
7695
- x: plot.x + index * step,
7696
- y: plot.y + plot.height - (value - min) / span * plot.height
7697
- }));
7698
- if (chart.type.includes("bar") || chart.type.includes("col")) {
7699
- const barWidth = Math.max(4, Math.min(28, step * 0.6)) / Math.max(1, chart.series.length);
7700
- points.forEach((point, index) => {
7701
- const zeroY = plot.y + plot.height - (0 - min) / span * plot.height;
7702
- const x = point.x - barWidth * chart.series.length / 2 + seriesIndex * barWidth;
9013
+ if (chart.type.includes("bar") || chart.type.includes("col")) {
9014
+ const categoryCount = Math.max(1, categories.length, ...chart.series.map((series) => series.values.length));
9015
+ const groupWidth = plot.width / categoryCount;
9016
+ const clusterWidth = groupWidth * 0.58;
9017
+ const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
9018
+ const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
9019
+ categories.slice(0, categoryCount).forEach((category, index) => {
9020
+ const x = plot.x + groupWidth * (index + 0.5);
9021
+ const label = appendSvg(svg, "text", {
9022
+ x: Number(x.toFixed(1)),
9023
+ y: plot.y + plot.height + 22,
9024
+ class: "ofv-chart-label",
9025
+ "text-anchor": "middle"
9026
+ });
9027
+ label.textContent = truncateChartLabel(category);
9028
+ });
9029
+ chart.series.forEach((series, seriesIndex) => {
9030
+ const color = series.color || colors[seriesIndex % colors.length];
9031
+ series.values.forEach((value, index) => {
9032
+ const groupCenter = plot.x + groupWidth * (index + 0.5);
9033
+ const x = groupCenter - barWidth * chart.series.length / 2 + seriesIndex * barWidth + barWidth * 0.12;
9034
+ const y = plot.y + plot.height - (value - axisMin) / (axisMax - axisMin || 1) * plot.height;
7703
9035
  appendSvg(svg, "rect", {
7704
- x,
7705
- y: Math.min(point.y, zeroY),
7706
- width: barWidth,
7707
- height: Math.max(1, Math.abs(zeroY - point.y)),
9036
+ x: Number(x.toFixed(1)),
9037
+ y: Number(Math.min(y, zeroY).toFixed(1)),
9038
+ width: Number((barWidth * 0.76).toFixed(1)),
9039
+ height: Number(Math.max(1, Math.abs(zeroY - y)).toFixed(1)),
7708
9040
  fill: color,
7709
9041
  "data-index": index
7710
9042
  });
7711
9043
  });
7712
- } else {
9044
+ });
9045
+ } else {
9046
+ chart.series.forEach((series, seriesIndex) => {
9047
+ const color = series.color || colors[seriesIndex % colors.length];
9048
+ const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
9049
+ const lineSpan = axisMax - axisMin || span;
9050
+ const points = series.values.map((value, index) => ({
9051
+ x: plot.x + index * step,
9052
+ y: plot.y + plot.height - (value - axisMin) / lineSpan * plot.height
9053
+ }));
7713
9054
  appendSvg(svg, "polyline", {
7714
9055
  points: points.map((point) => `${point.x.toFixed(1)},${point.y.toFixed(1)}`).join(" "),
7715
9056
  fill: "none",
@@ -7721,11 +9062,49 @@ function renderChartSvg(chart) {
7721
9062
  for (const point of points.slice(0, 80)) {
7722
9063
  appendSvg(svg, "circle", { cx: point.x, cy: point.y, r: 3, fill: color });
7723
9064
  }
7724
- }
7725
- appendLegend(svg, series.name, color, 52 + seriesIndex * 118, 236);
7726
- });
9065
+ });
9066
+ }
9067
+ appendChartLegend(svg, chart, colors, 348);
7727
9068
  return svg;
7728
9069
  }
9070
+ function appendChartLegend(svg, chart, colors, y) {
9071
+ const itemWidth = 86;
9072
+ const startX = 320 - chart.series.length * itemWidth / 2;
9073
+ chart.series.forEach((series, seriesIndex) => {
9074
+ const color = series.color || colors[seriesIndex % colors.length];
9075
+ appendLegend(svg, series.name, color, startX + seriesIndex * itemWidth, y);
9076
+ });
9077
+ }
9078
+ function createChartAxisScale(max, min) {
9079
+ const axisMin = Math.min(0, min);
9080
+ const positiveMax = Math.max(1, max);
9081
+ const step = niceChartStep((positiveMax - axisMin) / 5);
9082
+ let axisMax = Math.ceil(positiveMax / step) * step;
9083
+ if (axisMax <= positiveMax) {
9084
+ axisMax += step;
9085
+ }
9086
+ const ticks = [];
9087
+ for (let value = axisMin; value <= axisMax + step / 2; value += step) {
9088
+ ticks.push(Number(value.toFixed(6)));
9089
+ }
9090
+ return { min: axisMin, max: axisMax, ticks };
9091
+ }
9092
+ function niceChartStep(rawStep) {
9093
+ if (rawStep <= 0) {
9094
+ return 1;
9095
+ }
9096
+ const magnitude = 10 ** Math.floor(Math.log10(rawStep));
9097
+ const normalized = rawStep / magnitude;
9098
+ const nice = normalized <= 1 ? 1 : normalized <= 2 ? 2 : normalized <= 5 ? 5 : 10;
9099
+ return nice * magnitude;
9100
+ }
9101
+ function formatChartTick(value) {
9102
+ const rounded = Math.abs(value) < 1 ? Number(value.toFixed(1)) : Number(value.toFixed(0));
9103
+ return String(rounded);
9104
+ }
9105
+ function truncateChartLabel(value) {
9106
+ return value.length > 10 ? `${value.slice(0, 10)}...` : value;
9107
+ }
7729
9108
  function appendLegend(svg, label, color, x, y) {
7730
9109
  appendSvg(svg, "rect", { x, y: y - 10, width: 12, height: 12, rx: 2, fill: color });
7731
9110
  const text = appendSvg(svg, "text", { x: x + 18, y, class: "ofv-chart-label" });
@@ -8459,7 +9838,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
8459
9838
  renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
8460
9839
  renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
8461
9840
  }
8462
- async function renderPackagedOfficePreview(panel, arrayBuffer, extension) {
9841
+ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
8463
9842
  let zip;
8464
9843
  try {
8465
9844
  zip = await import_jszip3.default.loadAsync(arrayBuffer);
@@ -8470,7 +9849,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension) {
8470
9849
  const hasEntry = (path) => entries.some((entry) => entry.name.toLowerCase() === path.toLowerCase());
8471
9850
  const contentXml = zip.file(/(^|\/)content\.xml$/i)[0];
8472
9851
  if (hasEntry("word/document.xml")) {
8473
- await renderDocx(panel, arrayBuffer);
9852
+ await renderDocx(panel, arrayBuffer, fit);
8474
9853
  return true;
8475
9854
  }
8476
9855
  if (hasEntry("xl/workbook.xml")) {
@@ -8905,6 +10284,13 @@ function legacyOfficeFormatLabel(extension) {
8905
10284
  }
8906
10285
  return "PowerPoint Binary File Format";
8907
10286
  }
10287
+ function renderLegacyWordBinary(panel, extension, arrayBuffer) {
10288
+ try {
10289
+ renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
10290
+ } catch (error) {
10291
+ renderLegacyOfficeBinary(panel, extension, arrayBuffer, `Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A${normalizeOfficeError(error)}`);
10292
+ }
10293
+ }
8908
10294
  function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
8909
10295
  const fragments = extractLegacyOfficeText(arrayBuffer);
8910
10296
  panel.replaceChildren();
@@ -13480,10 +14866,10 @@ function renderStep(panel, text, extension, ctx) {
13480
14866
  note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 STEP \u6587\u672C\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u5173\u952E\u51E0\u4F55\u53C2\u6570\u3002\u7CBE\u786E B-Rep/\u66F2\u9762\u6E32\u67D3\u5EFA\u8BAE\u540E\u7EED\u63A5\u5165 CAD \u5185\u6838\u6216\u670D\u52A1\u7AEF\u8F6C\u6362\u3002";
13481
14867
  const meta = document.createElement("div");
13482
14868
  meta.className = "ofv-cad-summary";
13483
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13484
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13485
- appendMeta5(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
13486
- appendMeta5(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
14869
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14870
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14871
+ appendMeta6(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
14872
+ appendMeta6(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
13487
14873
  const typeList = createCadTypeList(typeCounts);
13488
14874
  section.append(note, meta, typeList);
13489
14875
  let viewer;
@@ -13518,10 +14904,10 @@ function renderIges(panel, text, extension, ctx) {
13518
14904
  note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 IGES \u53C2\u6570\u533A\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u57FA\u7840\u53C2\u6570\u3002\u7CBE\u786E\u66F2\u7EBF/\u66F2\u9762\u6E32\u67D3\u5EFA\u8BAE\u540E\u7EED\u63A5\u5165 CAD \u5185\u6838\u6216\u670D\u52A1\u7AEF\u8F6C\u6362\u3002";
13519
14905
  const meta = document.createElement("div");
13520
14906
  meta.className = "ofv-cad-summary";
13521
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13522
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13523
- appendMeta5(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
13524
- appendMeta5(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
14907
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14908
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14909
+ appendMeta6(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
14910
+ appendMeta6(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
13525
14911
  const typeList = createCadTypeList(typeCounts, "\u7C7B\u578B\u53F7\u7EDF\u8BA1");
13526
14912
  section.append(note, meta, typeList);
13527
14913
  let viewer;
@@ -13555,13 +14941,13 @@ function renderIfc(panel, text) {
13555
14941
  note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 IFC STEP \u5B9E\u4F53\u3001BIM \u5C42\u7EA7\u548C\u5E38\u89C1\u6784\u4EF6\u7EDF\u8BA1\u3002\u51E0\u4F55\u7F51\u683C\u3001\u6750\u8D28\u548C\u5C5E\u6027\u96C6\u53EF\u540E\u7EED\u63A5\u5165 IfcOpenShell/IFC.js \u589E\u5F3A\u3002";
13556
14942
  const meta = document.createElement("div");
13557
14943
  meta.className = "ofv-cad-summary";
13558
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13559
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13560
- appendMeta5(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
13561
- appendMeta5(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
13562
- appendMeta5(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
13563
- appendMeta5(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
13564
- appendMeta5(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
14944
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14945
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14946
+ appendMeta6(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
14947
+ appendMeta6(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
14948
+ appendMeta6(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
14949
+ appendMeta6(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
14950
+ appendMeta6(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
13565
14951
  section.append(note, meta, createCadTypeList(typeCounts, "IFC \u5B9E\u4F53\u7EDF\u8BA1"));
13566
14952
  const hierarchy = createIfcHierarchy(records);
13567
14953
  if (hierarchy) {
@@ -13586,10 +14972,10 @@ function renderAcisSat(panel, text, extension, ctx) {
13586
14972
  note.textContent = "\u5F53\u524D\u7248\u672C\u4F1A\u5728\u524D\u7AEF\u89E3\u6790 ACIS SAT \u6587\u672C\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u5E38\u89C1 vertex/straight-curve \u51E0\u4F55\u7EBF\u7D22\uFF1B\u7CBE\u786E\u66F2\u9762\u3001\u62D3\u6251\u548C\u5E03\u5C14\u4F53\u4ECD\u5EFA\u8BAE\u63A5\u5165 CAD \u5185\u6838\u589E\u5F3A\u3002";
13587
14973
  const meta = document.createElement("div");
13588
14974
  meta.className = "ofv-cad-summary";
13589
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13590
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13591
- appendMeta5(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
13592
- appendMeta5(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
14975
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14976
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14977
+ appendMeta6(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
14978
+ appendMeta6(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
13593
14979
  const typeList = createCadTypeList(typeCounts);
13594
14980
  section.append(note, meta, typeList);
13595
14981
  let viewer;
@@ -13626,10 +15012,10 @@ function renderParasolidText(panel, text, extension, ctx) {
13626
15012
  note.textContent = "\u5F53\u524D\u7248\u672C\u4F1A\u5728\u524D\u7AEF\u89E3\u6790 Parasolid x_t \u6587\u672C\u7247\u6BB5\u3001\u5B9E\u4F53\u7C7B\u578B\u3001\u5750\u6807\u70B9\u548C\u57FA\u7840\u7EBF\u6BB5\u7EBF\u7D22\uFF1B\u5B8C\u6574 B-Rep\u3001\u66F2\u9762\u548C\u88C5\u914D\u5173\u7CFB\u5EFA\u8BAE\u63A5\u5165 Parasolid/HOOPS/ODA \u7B49\u4E13\u4E1A\u5185\u6838\u3002";
13627
15013
  const meta = document.createElement("div");
13628
15014
  meta.className = "ofv-cad-summary";
13629
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13630
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13631
- appendMeta5(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
13632
- appendMeta5(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
15015
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
15016
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
15017
+ appendMeta6(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
15018
+ appendMeta6(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
13633
15019
  const typeList = createCadTypeList(typeCounts);
13634
15020
  section.append(note, meta, typeList);
13635
15021
  let viewer;
@@ -13737,23 +15123,23 @@ function renderLayoutPreview(panel, data, ctx) {
13737
15123
  summary.setAttribute("aria-hidden", "true");
13738
15124
  summary.style.display = "none";
13739
15125
  }
13740
- appendMeta5(summary, "\u6587\u4EF6", data.fileName);
13741
- appendMeta5(summary, "\u683C\u5F0F", data.format);
15126
+ appendMeta6(summary, "\u6587\u4EF6", data.fileName);
15127
+ appendMeta6(summary, "\u683C\u5F0F", data.format);
13742
15128
  if (data.libraryName) {
13743
- appendMeta5(summary, "\u5E93", data.libraryName);
15129
+ appendMeta6(summary, "\u5E93", data.libraryName);
13744
15130
  }
13745
15131
  if (data.version) {
13746
- appendMeta5(summary, "\u7248\u672C", data.version);
15132
+ appendMeta6(summary, "\u7248\u672C", data.version);
13747
15133
  }
13748
15134
  if (data.unit) {
13749
- appendMeta5(summary, "\u5355\u4F4D", data.unit);
15135
+ appendMeta6(summary, "\u5355\u4F4D", data.unit);
13750
15136
  }
13751
- appendMeta5(summary, "Cell", data.cells.length);
13752
- appendMeta5(summary, "\u51E0\u4F55", data.shapes.length);
13753
- appendMeta5(summary, "\u5F15\u7528", data.references.length);
13754
- appendMeta5(summary, "\u6587\u5B57", data.labels.length);
15137
+ appendMeta6(summary, "Cell", data.cells.length);
15138
+ appendMeta6(summary, "\u51E0\u4F55", data.shapes.length);
15139
+ appendMeta6(summary, "\u5F15\u7528", data.references.length);
15140
+ appendMeta6(summary, "\u6587\u5B57", data.labels.length);
13755
15141
  for (const [label, value] of data.metadata) {
13756
- appendMeta5(summary, label, value);
15142
+ appendMeta6(summary, label, value);
13757
15143
  }
13758
15144
  section.append(summary);
13759
15145
  for (const noteText of [...data.notes, ...data.warnings]) {
@@ -14359,12 +15745,12 @@ function renderBinaryCad(panel, bytes, extension, fileName) {
14359
15745
  note.textContent = extension === "dwg" ? "\u5DF2\u8BC6\u522B DWG \u4E13\u6709\u4E8C\u8FDB\u5236\u56FE\u7EB8\u3002\u6838\u5FC3\u63D2\u4EF6\u9ED8\u8BA4\u63D0\u4F9B\u7248\u672C\u3001\u5BB9\u5668\u3001\u7ED3\u6784\u7EBF\u7D22\u548C\u63A5\u5165\u5EFA\u8BAE\uFF1B\u771F\u5B9E\u51E0\u4F55\u6E32\u67D3\u53EF\u901A\u8FC7 cadPlugin({ binaryRenderer }) \u63A5\u5165\u53EF\u9009\u524D\u7AEF\u5F15\u64CE\u6216\u8F6C\u6362\u670D\u52A1\u3002" : "\u5DF2\u8BC6\u522B DWF \u53D1\u5E03\u56FE\u7EB8\u3002\u6838\u5FC3\u63D2\u4EF6\u9ED8\u8BA4\u63D0\u4F9B\u5BB9\u5668\u7EBF\u7D22\u548C\u63A5\u5165\u5EFA\u8BAE\uFF1B\u9AD8\u4FDD\u771F\u9875\u9762\u6E32\u67D3\u53EF\u901A\u8FC7 cadPlugin({ binaryRenderer }) \u63A5\u5165\u4E13\u7528\u89E3\u6790\u5668\u6216\u8F6C\u6362\u670D\u52A1\u3002";
14360
15746
  const meta = document.createElement("div");
14361
15747
  meta.className = "ofv-cad-summary";
14362
- appendMeta5(meta, "\u6587\u4EF6", fileName);
14363
- appendMeta5(meta, "\u683C\u5F0F", extension.toUpperCase());
14364
- appendMeta5(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
14365
- appendMeta5(meta, "\u7B7E\u540D", byteSignature2(bytes));
14366
- appendMeta5(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
14367
- appendMeta5(meta, "\u5BB9\u5668", detectCadContainer(bytes));
15748
+ appendMeta6(meta, "\u6587\u4EF6", fileName);
15749
+ appendMeta6(meta, "\u683C\u5F0F", extension.toUpperCase());
15750
+ appendMeta6(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
15751
+ appendMeta6(meta, "\u7B7E\u540D", byteSignature2(bytes));
15752
+ appendMeta6(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
15753
+ appendMeta6(meta, "\u5BB9\u5668", detectCadContainer(bytes));
14368
15754
  const actions = document.createElement("div");
14369
15755
  actions.className = "ofv-cad-conversion";
14370
15756
  const actionTitle = document.createElement("h4");
@@ -14404,12 +15790,12 @@ function createBinaryCadProbe(bytes, extension) {
14404
15790
  summary.textContent = "\u4E8C\u8FDB\u5236\u7ED3\u6784\u63A2\u6D4B";
14405
15791
  const meta = document.createElement("div");
14406
15792
  meta.className = "ofv-archive-probe-meta";
14407
- appendMeta5(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
14408
- appendMeta5(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
14409
- appendMeta5(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
14410
- appendMeta5(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
14411
- appendMeta5(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
14412
- appendMeta5(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
15793
+ appendMeta6(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
15794
+ appendMeta6(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
15795
+ appendMeta6(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
15796
+ appendMeta6(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
15797
+ appendMeta6(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
15798
+ appendMeta6(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
14413
15799
  details.append(summary, meta);
14414
15800
  const hints = [...probe.layerHints, ...probe.blockHints, ...probe.externalRefs].slice(0, 18);
14415
15801
  if (hints.length > 0) {
@@ -14942,9 +16328,9 @@ function createUnsupportedCadSection(extension, fileName) {
14942
16328
  const section = createSection("CAD \u589E\u5F3A\u63A5\u5165\u63D0\u793A");
14943
16329
  const meta = document.createElement("div");
14944
16330
  meta.className = "ofv-cad-summary";
14945
- appendMeta5(meta, "\u6587\u4EF6", fileName);
14946
- appendMeta5(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
14947
- appendMeta5(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
16331
+ appendMeta6(meta, "\u6587\u4EF6", fileName);
16332
+ appendMeta6(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
16333
+ appendMeta6(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
14948
16334
  const note = document.createElement("p");
14949
16335
  note.textContent = unsupportedCadGuidance(extension);
14950
16336
  const actions = document.createElement("div");
@@ -15057,7 +16443,7 @@ function countBy(values) {
15057
16443
  }
15058
16444
  return counts;
15059
16445
  }
15060
- function appendMeta5(parent, label, value) {
16446
+ function appendMeta6(parent, label, value) {
15061
16447
  const row = document.createElement("div");
15062
16448
  row.className = "ofv-meta-row";
15063
16449
  const key = document.createElement("span");
@@ -17091,10 +18477,10 @@ function read255UInt16(bytes, offset) {
17091
18477
  return { value: code, offset };
17092
18478
  }
17093
18479
  function decodeEotString(bytes) {
17094
- const text = decodeUtf16Le(bytes).replace(/\0+$/g, "").trim();
18480
+ const text = decodeUtf16Le2(bytes).replace(/\0+$/g, "").trim();
17095
18481
  return text || new TextDecoder("latin1").decode(bytes).replace(/\0+$/g, "").trim();
17096
18482
  }
17097
- function decodeUtf16Le(bytes) {
18483
+ function decodeUtf16Le2(bytes) {
17098
18484
  let value = "";
17099
18485
  for (let index = 0; index + 1 < bytes.length; index += 2) {
17100
18486
  value += String.fromCharCode(bytes[index] | bytes[index + 1] << 8);