@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.js CHANGED
@@ -1877,12 +1877,12 @@ function imagePlugin() {
1877
1877
  let url = "";
1878
1878
  let convertedBlob = null;
1879
1879
  let isExternal = Boolean(ctx.file.url);
1880
- let canvasSource = null;
1880
+ let tiffSource = null;
1881
1881
  if (isTiff) {
1882
1882
  ctx.setLoading(true);
1883
1883
  try {
1884
1884
  const bytes = await sourceBytesPromise;
1885
- canvasSource = await createTiffCanvas(bytes);
1885
+ tiffSource = await createTiffPreview(bytes, ctx.file.name);
1886
1886
  } catch (err) {
1887
1887
  console.error("TIFF image conversion failed:", err);
1888
1888
  url = createObjectUrl(ctx.file);
@@ -1942,12 +1942,15 @@ function imagePlugin() {
1942
1942
  if (url) {
1943
1943
  image.src = url;
1944
1944
  }
1945
- const visual = canvasSource || image;
1946
- if (canvasSource) {
1947
- canvasSource.classList.add("ofv-media", "ofv-image-content", "ofv-tiff-canvas");
1948
- canvasSource.setAttribute("role", "img");
1949
- canvasSource.setAttribute("aria-label", ctx.file.name);
1945
+ const visual = tiffSource || image;
1946
+ if (tiffSource) {
1947
+ tiffSource.classList.add("ofv-image-content");
1948
+ if (tiffSource.classList.contains("ofv-tiff-pages")) {
1949
+ stage.classList.add("ofv-image-stage-pages");
1950
+ }
1950
1951
  }
1952
+ const visualBox = document.createElement("div");
1953
+ visualBox.className = "ofv-image-scrollbox";
1951
1954
  let scale = getInitialZoom(ctx);
1952
1955
  let rotation = 0;
1953
1956
  let offsetX = 0;
@@ -1961,7 +1964,23 @@ function imagePlugin() {
1961
1964
  let previewAvailable = true;
1962
1965
  const zoomLabel = document.createElement("span");
1963
1966
  zoomLabel.className = "ofv-image-zoom";
1967
+ const updateScrollBox = () => {
1968
+ if (visual.classList.contains("ofv-tiff-pages")) {
1969
+ visualBox.style.removeProperty("width");
1970
+ visualBox.style.removeProperty("height");
1971
+ return;
1972
+ }
1973
+ const baseWidth = visual.offsetWidth || visual.getBoundingClientRect().width || visual.naturalWidth || 0;
1974
+ const baseHeight = visual.offsetHeight || visual.getBoundingClientRect().height || visual.naturalHeight || 0;
1975
+ if (baseWidth > 0) {
1976
+ visualBox.style.width = `${Math.ceil(baseWidth * scale)}px`;
1977
+ }
1978
+ if (baseHeight > 0) {
1979
+ visualBox.style.height = `${Math.ceil(baseHeight * scale)}px`;
1980
+ }
1981
+ };
1964
1982
  const updateTransform = () => {
1983
+ updateScrollBox();
1965
1984
  visual.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale}) rotate(${rotation}deg)`;
1966
1985
  zoomLabel.textContent = `${Math.round(scale * 100)}%`;
1967
1986
  ctx.toolbar?.setZoom(previewAvailable ? scale : void 0);
@@ -2081,11 +2100,13 @@ function imagePlugin() {
2081
2100
  stage.addEventListener("lostpointercapture", onLostPointerCapture);
2082
2101
  stage.addEventListener("pointerleave", onPointerLeave);
2083
2102
  stage.addEventListener("wheel", onWheel, { passive: false });
2084
- if (!canvasSource) {
2103
+ if (!tiffSource) {
2085
2104
  image.addEventListener("error", showImageFallback);
2105
+ image.addEventListener("load", updateScrollBox);
2086
2106
  }
2087
2107
  window.addEventListener("blur", onWindowBlur);
2088
- stage.append(visual);
2108
+ visualBox.append(visual);
2109
+ stage.append(visualBox);
2089
2110
  wrapper.append(...showInlineControls ? [controls, stage, infoBar] : [stage, infoBar]);
2090
2111
  ctx.viewport.append(wrapper);
2091
2112
  updateTransform();
@@ -2123,7 +2144,12 @@ function imagePlugin() {
2123
2144
  },
2124
2145
  resize(size) {
2125
2146
  visual.style.maxWidth = `${size.width}px`;
2126
- visual.style.maxHeight = `${Math.max(0, size.height - controls.offsetHeight)}px`;
2147
+ if (visual.classList.contains("ofv-tiff-pages")) {
2148
+ visual.style.removeProperty("max-height");
2149
+ } else {
2150
+ visual.style.maxHeight = `${Math.max(0, size.height - controls.offsetHeight)}px`;
2151
+ }
2152
+ updateScrollBox();
2127
2153
  },
2128
2154
  destroy() {
2129
2155
  ctx.toolbar?.setZoom(void 0);
@@ -2138,6 +2164,7 @@ function imagePlugin() {
2138
2164
  stage.removeEventListener("pointerleave", onPointerLeave);
2139
2165
  stage.removeEventListener("wheel", onWheel);
2140
2166
  image.removeEventListener("error", showImageFallback);
2167
+ image.removeEventListener("load", updateScrollBox);
2141
2168
  window.removeEventListener("blur", onWindowBlur);
2142
2169
  finishDrag();
2143
2170
  wrapper.remove();
@@ -2151,33 +2178,64 @@ function imagePlugin() {
2151
2178
  }
2152
2179
  };
2153
2180
  }
2154
- async function createTiffCanvas(bytes) {
2181
+ async function createTiffPreview(bytes, fileName) {
2155
2182
  if (bytes.byteLength === 0) {
2156
2183
  throw new Error("\u65E0\u6CD5\u8BFB\u53D6 TIFF \u6587\u4EF6\u5185\u5BB9\u3002");
2157
2184
  }
2158
2185
  const UTIF = await import("utif");
2159
2186
  const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
2160
2187
  const ifds = UTIF.decode(buffer);
2161
- const ifd = ifds.find((item) => Number(item.width || 0) > 0 || Number(item.t256 || 0) > 0) || ifds[0];
2162
- if (!ifd) {
2188
+ const imageIfds = ifds.filter((item) => hasTiffDimensions(item));
2189
+ if (imageIfds.length === 0) {
2163
2190
  throw new Error("TIFF \u6587\u4EF6\u6CA1\u6709\u53EF\u89E3\u7801\u7684\u56FE\u50CF\u76EE\u5F55\u3002");
2164
2191
  }
2192
+ const pages = imageIfds.map((ifd, index) => createTiffPage(UTIF, buffer, ifd, index, imageIfds.length, fileName));
2193
+ if (pages.length === 1) {
2194
+ return pages[0].canvas;
2195
+ }
2196
+ const container = document.createElement("div");
2197
+ container.className = "ofv-tiff-pages";
2198
+ container.setAttribute("role", "group");
2199
+ container.setAttribute("aria-label", `${fileName}\uFF0C\u5171 ${pages.length} \u9875`);
2200
+ for (const page of pages) {
2201
+ const figure = document.createElement("figure");
2202
+ figure.className = "ofv-tiff-page";
2203
+ const caption = document.createElement("figcaption");
2204
+ caption.textContent = `\u7B2C ${page.index + 1} / ${pages.length} \u9875 \xB7 ${page.width} x ${page.height}px`;
2205
+ figure.append(page.canvas, caption);
2206
+ container.append(figure);
2207
+ }
2208
+ return container;
2209
+ }
2210
+ function createTiffPage(UTIF, buffer, ifd, index, total, fileName) {
2165
2211
  UTIF.decodeImage(buffer, ifd);
2166
2212
  const rgba = UTIF.toRGBA8(ifd);
2167
- const width = Number(ifd.width || ifd.t256 || 0);
2168
- const height = Number(ifd.height || ifd.t257 || 0);
2213
+ const { width, height } = getTiffDimensions(ifd);
2169
2214
  if (!width || !height || rgba.length < width * height * 4) {
2170
2215
  throw new Error("TIFF \u56FE\u50CF\u50CF\u7D20\u6570\u636E\u4E0D\u5B8C\u6574\u3002");
2171
2216
  }
2172
2217
  const canvas = document.createElement("canvas");
2218
+ canvas.className = "ofv-tiff-canvas";
2173
2219
  canvas.width = width;
2174
2220
  canvas.height = height;
2221
+ canvas.setAttribute("role", "img");
2222
+ canvas.setAttribute("aria-label", total > 1 ? `${fileName} \u7B2C ${index + 1} \u9875` : fileName);
2175
2223
  const context = canvas.getContext("2d");
2176
2224
  if (!context) {
2177
2225
  throw new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 Canvas 2D\uFF0C\u65E0\u6CD5\u5C55\u793A TIFF\u3002");
2178
2226
  }
2179
2227
  context.putImageData(new ImageData(new Uint8ClampedArray(rgba), width, height), 0, 0);
2180
- return canvas;
2228
+ return { canvas, width, height, index };
2229
+ }
2230
+ function hasTiffDimensions(ifd) {
2231
+ const { width, height } = getTiffDimensions(ifd);
2232
+ return width > 0 && height > 0;
2233
+ }
2234
+ function getTiffDimensions(ifd) {
2235
+ return {
2236
+ width: Number(ifd.width || ifd.t256 || 0),
2237
+ height: Number(ifd.height || ifd.t257 || 0)
2238
+ };
2181
2239
  }
2182
2240
  function createImageFallback(fileName, url) {
2183
2241
  const fallback = document.createElement("div");
@@ -2506,6 +2564,7 @@ function parseTiffInfo(bytes) {
2506
2564
  return { format: magic === 43 ? "BigTIFF" : "TIFF", note: "IFD \u504F\u79FB\u8D85\u51FA\u6587\u4EF6\u8303\u56F4" };
2507
2565
  }
2508
2566
  const count = magic === 43 ? readTiffUint64AsNumber(bytes, ifdOffset, littleEndian) : readTiffUint16(bytes, ifdOffset, littleEndian);
2567
+ const imageCount = countTiffIfds(bytes, ifdOffset, magic === 43, littleEndian);
2509
2568
  const entrySize = magic === 43 ? 20 : 12;
2510
2569
  const entriesStart = ifdOffset + (magic === 43 ? 8 : 2);
2511
2570
  let width;
@@ -2532,9 +2591,26 @@ function parseTiffInfo(bytes) {
2532
2591
  height,
2533
2592
  bitDepth: bitDepth ? `${bitDepth} bit` : void 0,
2534
2593
  color: compression ? tiffCompressionName(compression) : void 0,
2535
- count: Number.isFinite(count) ? count : void 0
2594
+ count: imageCount || void 0
2536
2595
  };
2537
2596
  }
2597
+ function countTiffIfds(bytes, firstOffset, bigTiff, littleEndian) {
2598
+ const seen = /* @__PURE__ */ new Set();
2599
+ let offset = firstOffset;
2600
+ let count = 0;
2601
+ while (Number.isFinite(offset) && offset > 0 && offset < bytes.length && !seen.has(offset) && count < 512) {
2602
+ seen.add(offset);
2603
+ const entryCount = bigTiff ? readTiffUint64AsNumber(bytes, offset, littleEndian) : readTiffUint16(bytes, offset, littleEndian);
2604
+ const entrySize = bigTiff ? 20 : 12;
2605
+ const nextOffsetPosition = offset + (bigTiff ? 8 : 2) + entryCount * entrySize;
2606
+ if (!Number.isFinite(entryCount) || nextOffsetPosition + (bigTiff ? 8 : 4) > bytes.length) {
2607
+ break;
2608
+ }
2609
+ count++;
2610
+ offset = bigTiff ? readTiffUint64AsNumber(bytes, nextOffsetPosition, littleEndian) : readTiffUint32(bytes, nextOffsetPosition, littleEndian);
2611
+ }
2612
+ return count;
2613
+ }
2538
2614
  function readTiffInlineValue(bytes, offset, type, littleEndian) {
2539
2615
  if (offset + 4 > bytes.length) {
2540
2616
  return void 0;
@@ -3933,26 +4009,6 @@ var mimeLangMap = {
3933
4009
  };
3934
4010
  var MAX_HIGHLIGHT_CHARS = 18e4;
3935
4011
  var MAX_RENDER_CHARS = 6e5;
3936
- function loadPrismCss(theme) {
3937
- const lightId = "ofv-prism-css-light";
3938
- const darkId = "ofv-prism-css-dark";
3939
- const activeId = theme === "dark" ? darkId : lightId;
3940
- const inactiveId = theme === "dark" ? lightId : darkId;
3941
- document.getElementById(inactiveId)?.remove();
3942
- if (document.getElementById(activeId)) {
3943
- return Promise.resolve();
3944
- }
3945
- 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";
3946
- return new Promise((resolve, reject) => {
3947
- const link = document.createElement("link");
3948
- link.id = activeId;
3949
- link.rel = "stylesheet";
3950
- link.href = href;
3951
- link.onload = () => resolve();
3952
- link.onerror = () => reject(new Error(`Failed to load Prism CSS: ${href}`));
3953
- document.head.appendChild(link);
3954
- });
3955
- }
3956
4012
  function textPlugin() {
3957
4013
  return {
3958
4014
  name: "text",
@@ -3976,7 +4032,6 @@ function textPlugin() {
3976
4032
  }
3977
4033
  };
3978
4034
  }
3979
- 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";
3980
4035
  if (isMarkdown) {
3981
4036
  const [markedModule, PrismModule2, DOMPurifyModule] = await Promise.all([
3982
4037
  import("marked"),
@@ -3997,7 +4052,6 @@ function textPlugin() {
3997
4052
  try {
3998
4053
  const codeBlocks = container.querySelectorAll("pre code");
3999
4054
  if (codeBlocks.length > 0) {
4000
- await loadPrismCss(isDark ? "dark" : "light");
4001
4055
  codeBlocks.forEach((block) => {
4002
4056
  const parent = block.parentElement;
4003
4057
  if (parent && !parent.className.includes("language-")) {
@@ -4121,9 +4175,6 @@ function textPlugin() {
4121
4175
  console.warn(`Prism failed to load language component for: ${lang}`, e);
4122
4176
  }
4123
4177
  }
4124
- await loadPrismCss(isDark ? "dark" : "light").catch((error) => {
4125
- console.warn("Prism CSS failed to load; rendering code without external theme:", error);
4126
- });
4127
4178
  const codeText = text.length > MAX_RENDER_CHARS ? text.slice(0, MAX_RENDER_CHARS) : text;
4128
4179
  const totalLines = countLines(text);
4129
4180
  const shownLines = countLines(codeText);
@@ -4651,10 +4702,11 @@ async function renderPdfDocumentPreview(options) {
4651
4702
  const baseViewport = page.getViewport({ scale: 1 });
4652
4703
  pagesMeta.push({
4653
4704
  width: baseViewport.width,
4654
- height: baseViewport.height
4705
+ height: baseViewport.height,
4706
+ rotation: getPdfPageRotation(page)
4655
4707
  });
4656
4708
  } catch {
4657
- pagesMeta.push({ width: 612, height: 792 });
4709
+ pagesMeta.push({ width: 612, height: 792, rotation: 0 });
4658
4710
  }
4659
4711
  }
4660
4712
  const pageStates = [];
@@ -4689,7 +4741,7 @@ async function renderPdfDocumentPreview(options) {
4689
4741
  const page = await pdfDocument.getPage(pageIdx + 1);
4690
4742
  const meta = pagesMeta[pageIdx];
4691
4743
  const scale = options.fit === "actual" ? zoomFactor : Math.max(0.05, Math.min(5, getPdfAvailableWidth(size.width) / rotatedPdfWidth(meta, rotation) * zoomFactor));
4692
- const viewport = page.getViewport({ scale, rotation });
4744
+ const viewport = page.getViewport({ scale, rotation: getPdfRenderRotation(meta, rotation) });
4693
4745
  const outputScale = getPdfOutputScale();
4694
4746
  const cssWidth = Math.floor(viewport.width);
4695
4747
  const cssHeight = Math.floor(viewport.height);
@@ -4728,6 +4780,8 @@ async function renderPdfDocumentPreview(options) {
4728
4780
  const span = document.createElement("span");
4729
4781
  span.textContent = str;
4730
4782
  span.style.fontSize = `${fontHeight}px`;
4783
+ span.style.lineHeight = "1";
4784
+ span.style.height = `${fontHeight}px`;
4731
4785
  span.style.fontFamily = item.fontName || "sans-serif";
4732
4786
  span.style.left = `${tx[4]}px`;
4733
4787
  span.style.top = `${tx[5] - fontHeight}px`;
@@ -4925,6 +4979,13 @@ function appendPdfSummary(parent, label, value) {
4925
4979
  function normalizePdfRotation(value) {
4926
4980
  return (value % 360 + 360) % 360;
4927
4981
  }
4982
+ function getPdfPageRotation(page) {
4983
+ const rotation = Number(page.rotate);
4984
+ return Number.isFinite(rotation) ? normalizePdfRotation(rotation) : 0;
4985
+ }
4986
+ function getPdfRenderRotation(meta, userRotation) {
4987
+ return normalizePdfRotation((meta.rotation || 0) + userRotation);
4988
+ }
4928
4989
  function isPdfRotatedSideways(rotation) {
4929
4990
  const normalized = normalizePdfRotation(rotation);
4930
4991
  return normalized === 90 || normalized === 270;
@@ -5809,6 +5870,1100 @@ function decodeXml(value) {
5809
5870
  // src/plugins/office.ts
5810
5871
  import JSZip3 from "jszip";
5811
5872
  import DOMPurify2 from "dompurify";
5873
+
5874
+ // src/plugins/msdoc.ts
5875
+ var CFB_SIGNATURE = [208, 207, 17, 224, 161, 177, 26, 225];
5876
+ var FREE_SECTOR = 4294967295;
5877
+ var END_OF_CHAIN = 4294967294;
5878
+ var FAT_SECTOR = 4294967293;
5879
+ var DIFAT_SECTOR = 4294967292;
5880
+ var MINI_STREAM_CUTOFF = 4096;
5881
+ var STSH_FC_LCB_INDEX = 1;
5882
+ var CLX_FC_LCB_INDEX = 33;
5883
+ var WORD_PAGE_BREAK = "\f";
5884
+ function parseLegacyWordDocument(input) {
5885
+ const cfb = parseCompoundFile(new Uint8Array(input));
5886
+ const wordDocument = cfb.getStream("WordDocument");
5887
+ if (!wordDocument) {
5888
+ throw new Error("\u672A\u627E\u5230 WordDocument \u6D41");
5889
+ }
5890
+ const fib = parseFib(wordDocument);
5891
+ if (fib.encrypted) {
5892
+ throw new Error("\u6682\u4E0D\u652F\u6301\u52A0\u5BC6\u7684 .doc \u6587\u4EF6");
5893
+ }
5894
+ const tableStreamName = fib.useOneTable ? "1Table" : "0Table";
5895
+ const tableStream = cfb.getStream(tableStreamName);
5896
+ if (!tableStream) {
5897
+ throw new Error(`\u672A\u627E\u5230 ${tableStreamName} \u8868\u6D41`);
5898
+ }
5899
+ const assets = extractImageAssets(cfb);
5900
+ const styles = parseStyleTable(tableStream, fib);
5901
+ const pieces = parseClxPieces(tableStream, fib.fcClx, fib.lcbClx);
5902
+ const text = pieces.length > 0 ? readPieceTableText(wordDocument, pieces, fib.ccpText) : readFibTextFallback(wordDocument, fib);
5903
+ const paragraphs = splitWordParagraphs(text);
5904
+ if (paragraphs.length === 0) {
5905
+ throw new Error("\u672A\u89E3\u6790\u5230\u53EF\u663E\u793A\u7684\u6B63\u6587\u6BB5\u843D");
5906
+ }
5907
+ const bodyParagraphs = removeTrailingFooterArtifacts(paragraphs);
5908
+ const blocks = buildWordBlocks(bodyParagraphs);
5909
+ const layout = inferLayoutHints(paragraphs, assets);
5910
+ return {
5911
+ title: inferDocumentTitle(paragraphs),
5912
+ paragraphs: bodyParagraphs,
5913
+ blocks,
5914
+ layout,
5915
+ assets,
5916
+ styles,
5917
+ stats: {
5918
+ streamCount: cfb.entries.length,
5919
+ pieceCount: pieces.length,
5920
+ characterCount: bodyParagraphs.join("\n").length,
5921
+ styleCount: styles.length,
5922
+ tableStream: tableStreamName
5923
+ },
5924
+ 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"] : []
5925
+ };
5926
+ }
5927
+ function renderLegacyWordDocument(panel, document2) {
5928
+ panel.replaceChildren();
5929
+ const article = window.document.createElement("article");
5930
+ article.className = "ofv-msdoc-document";
5931
+ const pages = paginateWordBlocks(document2.blocks.slice(0, 600), document2.layout);
5932
+ const pageCount = inferDisplayedPageCount(document2.blocks, pages.length);
5933
+ const page = window.document.createElement("section");
5934
+ page.className = "ofv-msdoc-page";
5935
+ appendPageChrome(page, document2, 1, pageCount);
5936
+ const meta = window.document.createElement("dl");
5937
+ meta.className = "ofv-msdoc-meta";
5938
+ appendMeta4(meta, "\u683C\u5F0F", "Word 97-2003 Binary");
5939
+ appendMeta4(meta, "\u6B63\u6587\u6BB5\u843D", `${document2.paragraphs.length}`);
5940
+ appendMeta4(meta, "Piece Table", `${document2.stats.pieceCount || 0} \u6BB5`);
5941
+ appendMeta4(meta, "\u6837\u5F0F\u8868", `${document2.stats.styleCount || 0} \u4E2A\u6837\u5F0F`);
5942
+ appendMeta4(meta, "\u8868\u6D41", document2.stats.tableStream);
5943
+ if (document2.styles.length > 0) {
5944
+ appendMeta4(meta, "\u6837\u5F0F\u540D\u79F0", document2.styles.slice(0, 30).map((style) => style.name).join("\u3001"));
5945
+ }
5946
+ meta.hidden = true;
5947
+ page.append(meta);
5948
+ appendBlocksToPage(page, pages[0] || [], document2.layout);
5949
+ appendWarnings(page, document2);
5950
+ article.append(page);
5951
+ for (const pageBlocks of pages.slice(1)) {
5952
+ const nextPage = window.document.createElement("section");
5953
+ nextPage.className = "ofv-msdoc-page";
5954
+ appendPageChrome(nextPage, document2, article.children.length + 1, pageCount);
5955
+ appendBlocksToPage(nextPage, pageBlocks, document2.layout);
5956
+ article.append(nextPage);
5957
+ }
5958
+ panel.append(article);
5959
+ }
5960
+ function inferDisplayedPageCount(blocks, renderedPageCount) {
5961
+ 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);
5962
+ if (tocPageNumbers.length === 0) {
5963
+ return renderedPageCount;
5964
+ }
5965
+ return Math.max(renderedPageCount, ...tocPageNumbers);
5966
+ }
5967
+ function appendPageChrome(page, document2, pageNumber, pageCount) {
5968
+ if (document2.layout.lineNumbers) {
5969
+ page.classList.add("ofv-msdoc-line-numbered");
5970
+ }
5971
+ page.setAttribute("aria-label", document2.title || "Word \u6587\u6863");
5972
+ if (document2.layout.headerBrand === "oasis") {
5973
+ page.append(createOasisHeader(document2.assets.find((asset) => asset.id === document2.layout.headerImageId)));
5974
+ }
5975
+ if (document2.layout.footer) {
5976
+ page.append(createPageFooter(document2.layout.footer, pageNumber, pageCount));
5977
+ }
5978
+ }
5979
+ function appendBlocksToPage(page, blocks, layout) {
5980
+ let lineNumber = 1;
5981
+ for (const block of blocks) {
5982
+ if (block.type === "pageBreak") {
5983
+ continue;
5984
+ }
5985
+ const element = renderWordBlock(block);
5986
+ if (layout.lineNumbers && element instanceof HTMLElement && !element.classList.contains("ofv-msdoc-page-header")) {
5987
+ element.dataset.line = String(lineNumber);
5988
+ lineNumber += estimatedLineCount(block);
5989
+ }
5990
+ page.append(element);
5991
+ }
5992
+ }
5993
+ function appendWarnings(page, document2) {
5994
+ if (document2.warnings.length === 0) {
5995
+ return;
5996
+ }
5997
+ const warning = window.document.createElement("p");
5998
+ warning.className = "ofv-msdoc-warning";
5999
+ warning.textContent = document2.warnings.join(" ");
6000
+ warning.hidden = true;
6001
+ page.append(warning);
6002
+ }
6003
+ function createOasisHeader(image) {
6004
+ const header = window.document.createElement("header");
6005
+ header.className = "ofv-msdoc-page-header ofv-msdoc-oasis-header";
6006
+ const logo = image ? createImageLogo(image) : createFallbackOasisLogo();
6007
+ header.append(logo);
6008
+ return header;
6009
+ }
6010
+ function createImageLogo(image) {
6011
+ const wrapper = window.document.createElement("div");
6012
+ wrapper.className = "ofv-msdoc-oasis-logo ofv-msdoc-oasis-logo-image";
6013
+ const img = window.document.createElement("img");
6014
+ img.src = image.dataUrl;
6015
+ img.alt = "OASIS";
6016
+ if (image.width) {
6017
+ img.width = image.width;
6018
+ }
6019
+ if (image.height) {
6020
+ img.height = image.height;
6021
+ }
6022
+ wrapper.append(img);
6023
+ return wrapper;
6024
+ }
6025
+ function createFallbackOasisLogo() {
6026
+ const logo = window.document.createElement("div");
6027
+ logo.className = "ofv-msdoc-oasis-logo";
6028
+ const word = window.document.createElement("span");
6029
+ word.textContent = "OASIS";
6030
+ const mark = window.document.createElement("span");
6031
+ mark.className = "ofv-msdoc-oasis-mark";
6032
+ mark.setAttribute("aria-hidden", "true");
6033
+ logo.append(word, mark);
6034
+ return logo;
6035
+ }
6036
+ function createPageFooter(footer, pageNumber, pageCount) {
6037
+ const element = window.document.createElement("footer");
6038
+ element.className = "ofv-msdoc-page-footer";
6039
+ const top = window.document.createElement("div");
6040
+ top.className = "ofv-msdoc-footer-row";
6041
+ const documentId = window.document.createElement("span");
6042
+ documentId.textContent = footer.documentId || "";
6043
+ const date = window.document.createElement("span");
6044
+ date.textContent = footer.date || "";
6045
+ top.append(documentId, date);
6046
+ const bottom = window.document.createElement("div");
6047
+ bottom.className = "ofv-msdoc-footer-row";
6048
+ const copyright = window.document.createElement("span");
6049
+ copyright.textContent = footer.copyright || "";
6050
+ const page = window.document.createElement("span");
6051
+ page.textContent = `Page ${pageNumber} of ${pageCount}`;
6052
+ bottom.append(copyright, page);
6053
+ element.append(top, bottom);
6054
+ return element;
6055
+ }
6056
+ function renderWordBlock(block) {
6057
+ if (block.type === "pageBreak") {
6058
+ const marker = window.document.createElement("span");
6059
+ marker.className = "ofv-msdoc-page-break";
6060
+ marker.hidden = true;
6061
+ return marker;
6062
+ }
6063
+ if (block.type === "table") {
6064
+ const table = window.document.createElement("table");
6065
+ table.className = "ofv-msdoc-table";
6066
+ const revisionColumnWidths = getRevisionTableColumnWidths(block.rows);
6067
+ if (revisionColumnWidths) {
6068
+ table.classList.add("ofv-msdoc-revision-table");
6069
+ const colgroup = window.document.createElement("colgroup");
6070
+ for (const width of revisionColumnWidths) {
6071
+ const col = window.document.createElement("col");
6072
+ col.style.width = `calc(${width}px * var(--ofv-office-zoom, 1))`;
6073
+ colgroup.append(col);
6074
+ }
6075
+ table.append(colgroup);
6076
+ }
6077
+ const tbody = window.document.createElement("tbody");
6078
+ for (const row of block.rows) {
6079
+ const tr = window.document.createElement("tr");
6080
+ const cellTag = row === block.rows[0] && block.rows.length > 1 ? "th" : "td";
6081
+ for (const cellText of row) {
6082
+ const cell = window.document.createElement(cellTag);
6083
+ cell.textContent = cellText;
6084
+ tr.append(cell);
6085
+ }
6086
+ tbody.append(tr);
6087
+ }
6088
+ table.append(tbody);
6089
+ return table;
6090
+ }
6091
+ if (block.type === "toc") {
6092
+ const paragraph2 = window.document.createElement("p");
6093
+ paragraph2.className = `ofv-msdoc-toc ofv-msdoc-toc-level-${block.level}`;
6094
+ const title = window.document.createElement("span");
6095
+ title.textContent = block.title;
6096
+ paragraph2.append(title);
6097
+ if (block.page) {
6098
+ const page = window.document.createElement("span");
6099
+ page.textContent = block.page;
6100
+ paragraph2.append(page);
6101
+ }
6102
+ return paragraph2;
6103
+ }
6104
+ const paragraph = window.document.createElement("p");
6105
+ const levelClass = block.type === "heading" ? ` ofv-msdoc-heading-level-${block.level}` : "";
6106
+ const listClass = block.type === "listItem" ? ` ofv-msdoc-list-level-${block.level}` : "";
6107
+ paragraph.className = `ofv-msdoc-${block.type}${levelClass}${listClass}${"indent" in block && block.indent ? " ofv-msdoc-indent" : ""}`;
6108
+ appendInlineRuns(paragraph, block.text, block.type === "code");
6109
+ return paragraph;
6110
+ }
6111
+ function appendInlineRuns(element, text, preserveTabs = false) {
6112
+ if (preserveTabs) {
6113
+ appendInlineText(element, text, true);
6114
+ return;
6115
+ }
6116
+ 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;
6117
+ let offset = 0;
6118
+ for (const match of text.matchAll(pattern)) {
6119
+ const value = match[0];
6120
+ const index = match.index || 0;
6121
+ if (index > offset) {
6122
+ appendInlineText(element, text.slice(offset, index), preserveTabs);
6123
+ }
6124
+ if (value.startsWith("[") && value.endsWith("]")) {
6125
+ appendBracketRun(element, value);
6126
+ } else if (isCodeStyleRun(value)) {
6127
+ const code = window.document.createElement("code");
6128
+ code.className = "ofv-msdoc-inline-code";
6129
+ code.textContent = value;
6130
+ element.append(code);
6131
+ } else if (isVariableStyleRun(value)) {
6132
+ const em = window.document.createElement("em");
6133
+ em.className = "ofv-msdoc-variable";
6134
+ em.textContent = value;
6135
+ element.append(em);
6136
+ } else if (isRequirementKeywordRun(value)) {
6137
+ const em = window.document.createElement("em");
6138
+ em.className = "ofv-msdoc-keyword";
6139
+ em.textContent = value;
6140
+ element.append(em);
6141
+ } else {
6142
+ const link = splitLinkRun(value);
6143
+ const anchor = window.document.createElement("a");
6144
+ anchor.className = "ofv-msdoc-link-text";
6145
+ anchor.href = link.href;
6146
+ anchor.target = "_blank";
6147
+ anchor.rel = "noreferrer noopener";
6148
+ anchor.textContent = link.text;
6149
+ element.append(anchor);
6150
+ if (link.trailing) {
6151
+ appendInlineText(element, link.trailing, preserveTabs);
6152
+ }
6153
+ }
6154
+ offset = index + value.length;
6155
+ }
6156
+ if (offset < text.length) {
6157
+ appendInlineText(element, text.slice(offset), preserveTabs);
6158
+ }
6159
+ }
6160
+ function appendBracketRun(element, value) {
6161
+ const tagName = isReferenceTerm(value) ? "strong" : "em";
6162
+ const run = window.document.createElement(tagName);
6163
+ run.className = isReferenceTerm(value) ? "ofv-msdoc-ref-term" : "ofv-msdoc-instruction-run";
6164
+ run.textContent = value;
6165
+ element.append(run);
6166
+ }
6167
+ function getRevisionTableColumnWidths(rows) {
6168
+ const header = rows[0]?.map((cell) => cell.toLowerCase());
6169
+ if (!header || header.length !== 4) {
6170
+ return void 0;
6171
+ }
6172
+ if (header[0] === "rev" && header[1] === "date" && /whom/.test(header[2]) && header[3] === "what") {
6173
+ return [59, 81, 106, 191];
6174
+ }
6175
+ return void 0;
6176
+ }
6177
+ function appendInlineText(element, text, preserveTabs) {
6178
+ element.append(window.document.createTextNode(preserveTabs ? text : text.replace(/\t+/g, " ")));
6179
+ }
6180
+ function isReferenceTerm(value) {
6181
+ return /^\[[A-Z0-9][A-Z0-9.-]{1,24}\]$/.test(value);
6182
+ }
6183
+ function isCodeStyleRun(value) {
6184
+ return /^<\/?[A-Za-z][A-Za-z0-9:-]*>$/.test(value) || /^(?:attributeNames|DataType|OtherKeyword)$/.test(value);
6185
+ }
6186
+ function isVariableStyleRun(value) {
6187
+ return value === "variable";
6188
+ }
6189
+ function isRequirementKeywordRun(value) {
6190
+ return /^(?:must not|must|required|shall not|shall|should not|should|recommended|may|optional)$/i.test(value);
6191
+ }
6192
+ function splitLinkRun(value) {
6193
+ let text = value;
6194
+ let trailing = "";
6195
+ while (/[),.;:]$/.test(text)) {
6196
+ trailing = text.slice(-1) + trailing;
6197
+ text = text.slice(0, -1);
6198
+ }
6199
+ const href = /^https?:\/\//i.test(text) ? text : `mailto:${text}`;
6200
+ return { text, href, trailing };
6201
+ }
6202
+ function extractImageAssets(cfb) {
6203
+ const assets = [];
6204
+ const seen = /* @__PURE__ */ new Set();
6205
+ for (const entry of cfb.entries) {
6206
+ if (entry.type !== 2) {
6207
+ continue;
6208
+ }
6209
+ const stream = cfb.getStream(entry.name);
6210
+ if (!stream || stream.length < 16) {
6211
+ continue;
6212
+ }
6213
+ for (const image of extractImagesFromBytes(stream, entry.name)) {
6214
+ const key = `${image.mimeType}:${image.bytes.length}:${image.bytes[0]}:${image.bytes[image.bytes.length - 1]}`;
6215
+ if (seen.has(key)) {
6216
+ continue;
6217
+ }
6218
+ seen.add(key);
6219
+ const id = `image-${assets.length + 1}`;
6220
+ assets.push({
6221
+ id,
6222
+ kind: "image",
6223
+ mimeType: image.mimeType,
6224
+ dataUrl: `data:${image.mimeType};base64,${bytesToBase64(image.bytes)}`,
6225
+ width: image.width,
6226
+ height: image.height
6227
+ });
6228
+ }
6229
+ }
6230
+ return assets;
6231
+ }
6232
+ function parseStyleTable(tableStream, fib) {
6233
+ if (fib.lcbStshf <= 0 || fib.fcStshf < 0 || fib.fcStshf >= tableStream.length) {
6234
+ return [];
6235
+ }
6236
+ const bytes = tableStream.subarray(fib.fcStshf, Math.min(tableStream.length, fib.fcStshf + fib.lcbStshf));
6237
+ if (bytes.length < 8) {
6238
+ return [];
6239
+ }
6240
+ const view3 = dataView2(bytes);
6241
+ const cbStshi = view3.getUint16(0, true);
6242
+ const stshiOffset = 2;
6243
+ const cstd = stshiOffset + 2 <= bytes.length ? view3.getUint16(stshiOffset, true) : 0;
6244
+ const cbSTDBaseInFile = stshiOffset + 4 <= bytes.length ? view3.getUint16(stshiOffset + 2, true) : 10;
6245
+ let offset = 2 + cbStshi;
6246
+ const styles = [];
6247
+ for (let id = 0; id < cstd && offset + 2 <= bytes.length; id += 1) {
6248
+ const cbStd = view3.getUint16(offset, true);
6249
+ const stdStart = offset + 2;
6250
+ const stdEnd = stdStart + cbStd;
6251
+ if (cbStd > 0 && stdStart < bytes.length) {
6252
+ const style = parseStyleDefinition(bytes.subarray(stdStart, Math.min(stdEnd, bytes.length)), Math.max(10, cbSTDBaseInFile), id);
6253
+ if (style.name) {
6254
+ styles.push(style);
6255
+ }
6256
+ }
6257
+ offset = alignEven(stdEnd);
6258
+ }
6259
+ return styles;
6260
+ }
6261
+ function parseStyleDefinition(bytes, baseSize, id) {
6262
+ const base = bytes.length >= 6 ? parseStyleBase(bytes) : void 0;
6263
+ const nameOffset = Math.min(bytes.length, Math.max(10, baseSize));
6264
+ const name = parseXstz(bytes, nameOffset);
6265
+ return {
6266
+ id,
6267
+ name,
6268
+ type: styleTypeFromStk(base?.stk),
6269
+ basedOn: base?.basedOn,
6270
+ next: base?.next
6271
+ };
6272
+ }
6273
+ function parseStyleBase(bytes) {
6274
+ const view3 = dataView2(bytes);
6275
+ const w2 = view3.getUint16(2, true);
6276
+ const w3 = view3.getUint16(4, true);
6277
+ return {
6278
+ stk: w2 & 15,
6279
+ basedOn: w2 >> 4 & 4095,
6280
+ next: w3 >> 4 & 4095
6281
+ };
6282
+ }
6283
+ function styleTypeFromStk(stk) {
6284
+ if (stk === 1) {
6285
+ return "paragraph";
6286
+ }
6287
+ if (stk === 2) {
6288
+ return "character";
6289
+ }
6290
+ if (stk === 3) {
6291
+ return "table";
6292
+ }
6293
+ if (stk === 4) {
6294
+ return "numbering";
6295
+ }
6296
+ return "unknown";
6297
+ }
6298
+ function parseXstz(bytes, offset) {
6299
+ if (offset + 2 > bytes.length) {
6300
+ return "";
6301
+ }
6302
+ const view3 = dataView2(bytes);
6303
+ const charCount = view3.getUint16(offset, true);
6304
+ const start = offset + 2;
6305
+ const end = Math.min(bytes.length, start + charCount * 2);
6306
+ if (end <= start) {
6307
+ return "";
6308
+ }
6309
+ return decodeUtf16Le(bytes.subarray(start, end)).replace(/\0+$/g, "");
6310
+ }
6311
+ function extractImagesFromBytes(bytes, sourceName) {
6312
+ const images = [];
6313
+ for (const start of findSignatureOffsets(bytes, PNG_SIGNATURE)) {
6314
+ const end = findPngEnd(bytes, start);
6315
+ if (end > start) {
6316
+ const imageBytes = bytes.slice(start, end);
6317
+ const dimensions = readPngDimensions(imageBytes);
6318
+ images.push({ bytes: imageBytes, mimeType: "image/png", width: dimensions?.width, height: dimensions?.height });
6319
+ }
6320
+ }
6321
+ for (const start of findSignatureOffsets(bytes, JPEG_SIGNATURE)) {
6322
+ const end = findJpegEnd(bytes, start);
6323
+ if (end > start) {
6324
+ images.push({ bytes: bytes.slice(start, end), mimeType: "image/jpeg" });
6325
+ }
6326
+ }
6327
+ if (/picture|image|data/i.test(sourceName)) {
6328
+ 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);
6329
+ if (gifStart >= 0) {
6330
+ images.push({ bytes: bytes.slice(gifStart), mimeType: "image/gif" });
6331
+ }
6332
+ }
6333
+ return images;
6334
+ }
6335
+ var PNG_SIGNATURE = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10]);
6336
+ var JPEG_SIGNATURE = Uint8Array.from([255, 216, 255]);
6337
+ function findSignatureOffsets(bytes, signature) {
6338
+ const offsets = [];
6339
+ for (let index = 0; index <= bytes.length - signature.length; index += 1) {
6340
+ let matches = true;
6341
+ for (let sigIndex = 0; sigIndex < signature.length; sigIndex += 1) {
6342
+ if (bytes[index + sigIndex] !== signature[sigIndex]) {
6343
+ matches = false;
6344
+ break;
6345
+ }
6346
+ }
6347
+ if (matches) {
6348
+ offsets.push(index);
6349
+ }
6350
+ }
6351
+ return offsets;
6352
+ }
6353
+ function findPngEnd(bytes, start) {
6354
+ for (let offset = start + PNG_SIGNATURE.length; offset + 12 <= bytes.length; ) {
6355
+ const length = readUint32Be4(bytes, offset);
6356
+ const typeOffset = offset + 4;
6357
+ const next = offset + 12 + length;
6358
+ if (next > bytes.length) {
6359
+ return 0;
6360
+ }
6361
+ if (bytes[typeOffset] === 73 && bytes[typeOffset + 1] === 69 && bytes[typeOffset + 2] === 78 && bytes[typeOffset + 3] === 68) {
6362
+ return next;
6363
+ }
6364
+ offset = next;
6365
+ }
6366
+ return 0;
6367
+ }
6368
+ function findJpegEnd(bytes, start) {
6369
+ for (let index = start + 2; index + 1 < bytes.length; index += 1) {
6370
+ if (bytes[index] === 255 && bytes[index + 1] === 217) {
6371
+ return index + 2;
6372
+ }
6373
+ }
6374
+ return 0;
6375
+ }
6376
+ function readPngDimensions(bytes) {
6377
+ if (bytes.length < 24 || !PNG_SIGNATURE.every((value, index) => bytes[index] === value)) {
6378
+ return void 0;
6379
+ }
6380
+ return {
6381
+ width: readUint32Be4(bytes, 16),
6382
+ height: readUint32Be4(bytes, 20)
6383
+ };
6384
+ }
6385
+ function readUint32Be4(bytes, offset) {
6386
+ return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
6387
+ }
6388
+ function bytesToBase64(bytes) {
6389
+ let binary = "";
6390
+ const chunkSize = 32768;
6391
+ for (let offset = 0; offset < bytes.length; offset += chunkSize) {
6392
+ binary += String.fromCharCode(...bytes.subarray(offset, Math.min(bytes.length, offset + chunkSize)));
6393
+ }
6394
+ return btoa(binary);
6395
+ }
6396
+ function parseCompoundFile(bytes) {
6397
+ if (!hasCompoundSignature(bytes)) {
6398
+ throw new Error("\u4E0D\u662F\u6807\u51C6 OLE Compound File");
6399
+ }
6400
+ const view3 = dataView2(bytes);
6401
+ const sectorSize = 1 << view3.getUint16(30, true);
6402
+ const miniSectorSize = 1 << view3.getUint16(32, true);
6403
+ const fatSectorCount = view3.getUint32(44, true);
6404
+ const firstDirectorySector = view3.getUint32(48, true);
6405
+ const miniStreamCutoff = view3.getUint32(56, true) || MINI_STREAM_CUTOFF;
6406
+ const firstMiniFatSector = view3.getUint32(60, true);
6407
+ const miniFatSectorCount = view3.getUint32(64, true);
6408
+ const firstDifatSector = view3.getUint32(68, true);
6409
+ const difatSectorCount = view3.getUint32(72, true);
6410
+ const difat = readDifat(view3, sectorSize, firstDifatSector, difatSectorCount);
6411
+ const fat = readFat(view3, sectorSize, difat.slice(0, fatSectorCount));
6412
+ const directoryBytes = readRegularStream(bytes, sectorSize, fat, firstDirectorySector);
6413
+ const entries = parseDirectoryEntries(directoryBytes);
6414
+ const root = entries.find((entry) => entry.type === 5);
6415
+ const miniStream = root ? readRegularStream(bytes, sectorSize, fat, root.startSector, root.size) : new Uint8Array();
6416
+ const miniFat = firstMiniFatSector < END_OF_CHAIN ? readFat(view3, sectorSize, sectorChain(fat, firstMiniFatSector).slice(0, miniFatSectorCount)) : [];
6417
+ return {
6418
+ entries,
6419
+ getStream(name) {
6420
+ const wanted = normalizeStreamName(name);
6421
+ const entry = entries.find((item) => item.type === 2 && normalizeStreamName(item.name) === wanted);
6422
+ if (!entry) {
6423
+ return void 0;
6424
+ }
6425
+ if (entry.size < miniStreamCutoff && miniFat.length > 0) {
6426
+ return readMiniStream(miniStream, miniSectorSize, miniFat, entry.startSector, entry.size);
6427
+ }
6428
+ return readRegularStream(bytes, sectorSize, fat, entry.startSector, entry.size);
6429
+ }
6430
+ };
6431
+ }
6432
+ function hasCompoundSignature(bytes) {
6433
+ return CFB_SIGNATURE.every((value, index) => bytes[index] === value);
6434
+ }
6435
+ function readDifat(view3, sectorSize, firstDifatSector, difatSectorCount) {
6436
+ const difat = [];
6437
+ for (let offset = 76; offset < 512; offset += 4) {
6438
+ const sector = view3.getUint32(offset, true);
6439
+ if (isUsableSector(sector)) {
6440
+ difat.push(sector);
6441
+ }
6442
+ }
6443
+ let next = firstDifatSector;
6444
+ for (let index = 0; index < difatSectorCount && isUsableSector(next); index += 1) {
6445
+ const offset = sectorOffset(next, sectorSize);
6446
+ const entriesPerSector = sectorSize / 4 - 1;
6447
+ for (let item = 0; item < entriesPerSector; item += 1) {
6448
+ const sector = view3.getUint32(offset + item * 4, true);
6449
+ if (isUsableSector(sector)) {
6450
+ difat.push(sector);
6451
+ }
6452
+ }
6453
+ next = view3.getUint32(offset + entriesPerSector * 4, true);
6454
+ }
6455
+ return difat;
6456
+ }
6457
+ function readFat(view3, sectorSize, sectors) {
6458
+ const fat = [];
6459
+ for (const sector of sectors) {
6460
+ if (!isUsableSector(sector) && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR) {
6461
+ continue;
6462
+ }
6463
+ const offset = sectorOffset(sector, sectorSize);
6464
+ for (let item = 0; item < sectorSize / 4; item += 1) {
6465
+ fat.push(view3.getUint32(offset + item * 4, true));
6466
+ }
6467
+ }
6468
+ return fat;
6469
+ }
6470
+ function parseDirectoryEntries(bytes) {
6471
+ const view3 = dataView2(bytes);
6472
+ const entries = [];
6473
+ for (let offset = 0; offset + 128 <= bytes.length; offset += 128) {
6474
+ const nameLength = view3.getUint16(offset + 64, true);
6475
+ const type = bytes[offset + 66] || 0;
6476
+ if (type === 0 || nameLength < 2) {
6477
+ continue;
6478
+ }
6479
+ const nameBytes = bytes.subarray(offset, offset + Math.max(0, nameLength - 2));
6480
+ const name = decodeUtf16Le(nameBytes).replace(/\0+$/g, "");
6481
+ const startSector = view3.getUint32(offset + 116, true);
6482
+ const lowSize = view3.getUint32(offset + 120, true);
6483
+ const highSize = view3.getUint32(offset + 124, true);
6484
+ const size = highSize > 0 ? Number(BigInt(highSize) << 32n) + lowSize : lowSize;
6485
+ entries.push({ name, type, startSector, size });
6486
+ }
6487
+ return entries;
6488
+ }
6489
+ function readRegularStream(bytes, sectorSize, fat, startSector, size) {
6490
+ const chunks = [];
6491
+ for (const sector of sectorChain(fat, startSector)) {
6492
+ const offset = sectorOffset(sector, sectorSize);
6493
+ chunks.push(bytes.subarray(offset, Math.min(bytes.length, offset + sectorSize)));
6494
+ }
6495
+ return concatChunks(chunks, size);
6496
+ }
6497
+ function readMiniStream(miniStream, miniSectorSize, miniFat, startSector, size) {
6498
+ const chunks = [];
6499
+ for (const sector of sectorChain(miniFat, startSector)) {
6500
+ const offset = sector * miniSectorSize;
6501
+ chunks.push(miniStream.subarray(offset, Math.min(miniStream.length, offset + miniSectorSize)));
6502
+ }
6503
+ return concatChunks(chunks, size);
6504
+ }
6505
+ function sectorChain(fat, startSector) {
6506
+ const chain = [];
6507
+ const seen = /* @__PURE__ */ new Set();
6508
+ let current = startSector;
6509
+ while (isUsableSector(current) && current < fat.length && !seen.has(current)) {
6510
+ seen.add(current);
6511
+ chain.push(current);
6512
+ current = fat[current];
6513
+ }
6514
+ return chain;
6515
+ }
6516
+ function parseFib(wordDocument) {
6517
+ const view3 = dataView2(wordDocument);
6518
+ if (view3.getUint16(0, true) !== 42476) {
6519
+ throw new Error("WordDocument FIB \u6807\u8BC6\u65E0\u6548");
6520
+ }
6521
+ const flags = view3.getUint16(10, true);
6522
+ const fcMin = view3.getUint32(24, true);
6523
+ const fcMac = view3.getUint32(28, true);
6524
+ let offset = 32;
6525
+ const csw = view3.getUint16(offset, true);
6526
+ offset += 2 + csw * 2;
6527
+ const fibRgLwOffset = offset + 2;
6528
+ const cslw = view3.getUint16(offset, true);
6529
+ const ccpText = fibRgLwOffset + 16 <= wordDocument.length ? Math.max(0, view3.getInt32(fibRgLwOffset + 12, true)) : 0;
6530
+ offset += 2 + cslw * 4;
6531
+ const cbRgFcLcb = view3.getUint16(offset, true);
6532
+ const fcLcbOffset = offset + 2;
6533
+ const stshOffset = fcLcbOffset + STSH_FC_LCB_INDEX * 8;
6534
+ const clxOffset = fcLcbOffset + CLX_FC_LCB_INDEX * 8;
6535
+ return {
6536
+ encrypted: (flags & 256) !== 0,
6537
+ useOneTable: (flags & 512) !== 0,
6538
+ textIsUnicode: (flags & 4096) !== 0,
6539
+ fcMin,
6540
+ fcMac,
6541
+ ccpText,
6542
+ fcStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset, true) : 0,
6543
+ lcbStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset + 4, true) : 0,
6544
+ fcClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset, true) : 0,
6545
+ lcbClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset + 4, true) : 0
6546
+ };
6547
+ }
6548
+ function parseClxPieces(tableStream, fcClx, lcbClx) {
6549
+ if (lcbClx <= 0 || fcClx < 0 || fcClx >= tableStream.length) {
6550
+ return [];
6551
+ }
6552
+ const end = Math.min(tableStream.length, fcClx + lcbClx);
6553
+ const view3 = dataView2(tableStream);
6554
+ let offset = fcClx;
6555
+ while (offset < end) {
6556
+ const marker = tableStream[offset];
6557
+ if (marker === 1) {
6558
+ const size = offset + 3 <= end ? view3.getUint16(offset + 1, true) : 0;
6559
+ offset += 3 + size;
6560
+ continue;
6561
+ }
6562
+ if (marker === 2) {
6563
+ if (offset + 5 > end) {
6564
+ break;
6565
+ }
6566
+ const plcSize = view3.getUint32(offset + 1, true);
6567
+ const plcOffset = offset + 5;
6568
+ return parsePlcPcd(tableStream, plcOffset, Math.min(end, plcOffset + plcSize));
6569
+ }
6570
+ offset += 1;
6571
+ }
6572
+ return [];
6573
+ }
6574
+ function parsePlcPcd(tableStream, offset, end) {
6575
+ const size = end - offset;
6576
+ if (size < 16 || (size - 4) % 12 !== 0) {
6577
+ return [];
6578
+ }
6579
+ const view3 = dataView2(tableStream);
6580
+ const pieceCount = Math.floor((size - 4) / 12);
6581
+ const pcdOffset = offset + (pieceCount + 1) * 4;
6582
+ const pieces = [];
6583
+ for (let index = 0; index < pieceCount; index += 1) {
6584
+ const cpStart = view3.getUint32(offset + index * 4, true);
6585
+ const cpEnd = view3.getUint32(offset + (index + 1) * 4, true);
6586
+ const descriptorOffset = pcdOffset + index * 8;
6587
+ const fcCompressed = view3.getUint32(descriptorOffset + 2, true);
6588
+ const compressed = (fcCompressed & 1073741824) !== 0;
6589
+ const fileOffset = compressed ? (fcCompressed & 1073741823) / 2 : fcCompressed;
6590
+ if (cpEnd > cpStart) {
6591
+ pieces.push({ cpStart, cpEnd, fileOffset, compressed });
6592
+ }
6593
+ }
6594
+ return pieces;
6595
+ }
6596
+ function readPieceTableText(wordDocument, pieces, ccpText) {
6597
+ let output = "";
6598
+ for (const piece of pieces) {
6599
+ const cpEnd = ccpText > 0 ? Math.min(piece.cpEnd, ccpText) : piece.cpEnd;
6600
+ const charCount = Math.max(0, cpEnd - piece.cpStart);
6601
+ if (charCount === 0) {
6602
+ continue;
6603
+ }
6604
+ const byteLength = charCount * (piece.compressed ? 1 : 2);
6605
+ const bytes = wordDocument.subarray(piece.fileOffset, Math.min(wordDocument.length, piece.fileOffset + byteLength));
6606
+ output += piece.compressed ? decodeWindows1252(bytes) : decodeUtf16Le(bytes);
6607
+ }
6608
+ return output;
6609
+ }
6610
+ function readFibTextFallback(wordDocument, fib) {
6611
+ const bytes = wordDocument.subarray(fib.fcMin, Math.min(wordDocument.length, fib.fcMac));
6612
+ return fib.textIsUnicode ? decodeUtf16Le(bytes) : decodeWindows1252(bytes);
6613
+ }
6614
+ function splitWordParagraphs(text) {
6615
+ const normalized = text.replace(/\u0000/g, "").replace(/\u0007/g, " ").replace(/\u000b/g, "\n");
6616
+ const paragraphs = [];
6617
+ for (const segment of normalized.split(/(\u000c)/)) {
6618
+ if (segment === "\f") {
6619
+ paragraphs.push(WORD_PAGE_BREAK);
6620
+ continue;
6621
+ }
6622
+ paragraphs.push(
6623
+ ...segment.split(/\r|\n{2,}/).map((paragraph) => cleanWordText(paragraph)).filter((paragraph) => paragraph.length > 0 && isDisplayableParagraph(paragraph))
6624
+ );
6625
+ }
6626
+ return paragraphs.slice(0, 1e3);
6627
+ }
6628
+ function removeTrailingFooterArtifacts(paragraphs) {
6629
+ const tailStart = Math.max(0, paragraphs.length - 32);
6630
+ const tail = paragraphs.slice(tailStart);
6631
+ const relativePageFieldIndex = tail.findIndex(isFooterPageField);
6632
+ if (relativePageFieldIndex < 0) {
6633
+ return paragraphs;
6634
+ }
6635
+ let start = tailStart + relativePageFieldIndex;
6636
+ for (let index = start - 1; index >= tailStart; index -= 1) {
6637
+ const paragraph = paragraphs[index];
6638
+ if (paragraph === WORD_PAGE_BREAK || isLikelyFooterArtifact(paragraph)) {
6639
+ start = index;
6640
+ continue;
6641
+ }
6642
+ break;
6643
+ }
6644
+ const artifactSlice = paragraphs.slice(start);
6645
+ const footerCueCount = artifactSlice.filter(isLikelyFooterArtifact).length;
6646
+ if (footerCueCount < 2) {
6647
+ return paragraphs;
6648
+ }
6649
+ return paragraphs.slice(0, start);
6650
+ }
6651
+ function isFooterPageField(paragraph) {
6652
+ return /^(?:PAGE|Page)(?:\s+(?:PAGE|\d+))?(?:\s+of\s+(?:NUMPAGES|\d+))?$/i.test(paragraph.trim()) || /\bNUMPAGES\b/i.test(paragraph);
6653
+ }
6654
+ function isLikelyFooterArtifact(paragraph) {
6655
+ const value = paragraph.trim();
6656
+ 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);
6657
+ }
6658
+ function buildWordBlocks(paragraphs) {
6659
+ const blocks = [];
6660
+ let index = 0;
6661
+ while (index < paragraphs.length) {
6662
+ const paragraph = paragraphs[index];
6663
+ if (paragraph === WORD_PAGE_BREAK) {
6664
+ blocks.push({ type: "pageBreak" });
6665
+ index += 1;
6666
+ continue;
6667
+ }
6668
+ const toc = parseTocEntry(paragraph);
6669
+ if (toc) {
6670
+ blocks.push(toc);
6671
+ index += 1;
6672
+ continue;
6673
+ }
6674
+ if (isTableRowCandidate(paragraph)) {
6675
+ const rows = [];
6676
+ while (index < paragraphs.length && isTableRowCandidate(paragraphs[index])) {
6677
+ rows.push(...normalizeTableRows(splitTableRow(paragraphs[index])));
6678
+ index += 1;
6679
+ }
6680
+ blocks.push({ type: "table", rows });
6681
+ continue;
6682
+ }
6683
+ blocks.push(classifyParagraphBlock(paragraph, blocks));
6684
+ index += 1;
6685
+ }
6686
+ return blocks;
6687
+ }
6688
+ function inferLayoutHints(paragraphs, assets) {
6689
+ const sample = paragraphs.slice(0, 40).join("\n");
6690
+ const isOasisSpec = /Word Specification Sample/.test(sample) && /\bOASIS\b/i.test(paragraphs.join("\n"));
6691
+ const oasisImage = isOasisSpec ? assets.find((asset) => asset.mimeType === "image/png" && asset.width && asset.height && asset.width / asset.height > 2.5) : void 0;
6692
+ return {
6693
+ lineNumbers: isOasisSpec,
6694
+ headerBrand: isOasisSpec ? "oasis" : void 0,
6695
+ headerImageId: oasisImage?.id,
6696
+ footer: isOasisSpec ? inferOasisFooter(paragraphs) : void 0
6697
+ };
6698
+ }
6699
+ function inferOasisFooter(paragraphs) {
6700
+ const documentId = findValueAfterLabel(paragraphs, "Document identifier:") || paragraphs.find((paragraph) => /^wd-[\w.-]+/i.test(paragraph));
6701
+ const subtitle = paragraphs.find((paragraph) => /\b(?:draft|version)\b/i.test(paragraph) && /\d{4}/.test(paragraph));
6702
+ const date = subtitle?.match(/\b\d{1,2}\s+[A-Za-z]+\s+\d{4}\b/)?.[0];
6703
+ const copyright = paragraphs.find((paragraph) => /Copyright.*OASIS.*All Rights Reserved/i.test(paragraph)) || "Copyright \xA9 OASIS Open 2002. All Rights Reserved.";
6704
+ return { documentId, date, copyright };
6705
+ }
6706
+ function findValueAfterLabel(paragraphs, label) {
6707
+ const index = paragraphs.findIndex((paragraph) => paragraph.toLowerCase() === label.toLowerCase());
6708
+ if (index < 0) {
6709
+ return void 0;
6710
+ }
6711
+ return paragraphs.slice(index + 1).find((paragraph) => paragraph !== WORD_PAGE_BREAK && paragraph.length > 0);
6712
+ }
6713
+ function paginateWordBlocks(blocks, layout) {
6714
+ const maxLines = layout.lineNumbers ? 33 : 46;
6715
+ const pages = [];
6716
+ let current = [];
6717
+ let usedLines = 0;
6718
+ for (const block of blocks) {
6719
+ if (block.type === "pageBreak") {
6720
+ if (current.length > 0) {
6721
+ pages.push(current);
6722
+ }
6723
+ current = [];
6724
+ usedLines = 0;
6725
+ continue;
6726
+ }
6727
+ const lines = estimatedLineCount(block);
6728
+ const shouldBreak = current.length > 0 && (usedLines + lines > maxLines || block.type === "heading" && usedLines > Math.floor(maxLines * 0.72));
6729
+ if (shouldBreak) {
6730
+ pages.push(current);
6731
+ current = [];
6732
+ usedLines = 0;
6733
+ }
6734
+ current.push(block);
6735
+ usedLines += lines;
6736
+ }
6737
+ if (current.length > 0 || pages.length === 0) {
6738
+ pages.push(current);
6739
+ }
6740
+ return pages;
6741
+ }
6742
+ function estimatedLineCount(block) {
6743
+ if (block.type === "pageBreak") {
6744
+ return 0;
6745
+ }
6746
+ if (block.type === "table") {
6747
+ return Math.max(1, block.rows.length);
6748
+ }
6749
+ if (block.type === "toc") {
6750
+ return 1;
6751
+ }
6752
+ const baseWidth = "indent" in block && block.indent ? 78 : 96;
6753
+ return Math.max(1, Math.ceil(block.text.length / baseWidth));
6754
+ }
6755
+ function classifyParagraphBlock(text, previousBlocks) {
6756
+ const visibleIndex = previousBlocks.filter((block) => block.type !== "toc").length;
6757
+ if (visibleIndex === 0 && text.length <= 140) {
6758
+ return { type: "title", text };
6759
+ }
6760
+ if (visibleIndex === 1 && /draft|version|20\d{2}|19\d{2}/i.test(text) && text.length <= 140) {
6761
+ return { type: "subtitle", text };
6762
+ }
6763
+ const headingLevel = inferHeadingLevel(text, previousBlocks);
6764
+ if (headingLevel) {
6765
+ return { type: "heading", text, level: headingLevel };
6766
+ }
6767
+ if (/^[\w\s/().-]{2,45}:$/.test(text)) {
6768
+ return { type: "label", text };
6769
+ }
6770
+ if (isInstructionParagraph(text)) {
6771
+ return { type: "instruction", text, indent: shouldIndentParagraph(previousBlocks) };
6772
+ }
6773
+ if (/^\[[-\w.]+\]\s+/.test(text)) {
6774
+ return { type: "reference", text };
6775
+ }
6776
+ const listLevel = inferListItemLevel(text);
6777
+ if (listLevel) {
6778
+ return { type: "listItem", text, level: listLevel };
6779
+ }
6780
+ if (isCodeLikeParagraph(text)) {
6781
+ return { type: "code", text, indent: shouldIndentParagraph(previousBlocks) };
6782
+ }
6783
+ return { type: "paragraph", text, indent: shouldIndentParagraph(previousBlocks) };
6784
+ }
6785
+ function isInstructionParagraph(text) {
6786
+ return /^\[[^\]]{8,}\]$/.test(text.trim());
6787
+ }
6788
+ function inferHeadingLevel(text, previousBlocks) {
6789
+ if (text.length > 120) {
6790
+ return void 0;
6791
+ }
6792
+ if (/^table of contents$/i.test(text)) {
6793
+ return 1;
6794
+ }
6795
+ if (/^(?:introduction|word styles|references|appendix\b.*|acknowledgments|revision history|notices)$/i.test(text)) {
6796
+ return 1;
6797
+ }
6798
+ const numbered = text.match(/^([1-9](?:\.\d+)*)\s+.+/);
6799
+ if (numbered) {
6800
+ return Math.min(3, numbered[1].split(".").length);
6801
+ }
6802
+ if (/^(?:terminology|overall style|title page|headings|paragraphs|lists|tables|code examples|character styles|normative)$/i.test(text)) {
6803
+ return 2;
6804
+ }
6805
+ const previousHeading = [...previousBlocks].reverse().find((block) => block.type === "heading");
6806
+ if (previousHeading?.type === "heading" && previousHeading.level === 1 && /^[A-Z][A-Za-z0-9 ()/-]{2,80}$/.test(text)) {
6807
+ return 2;
6808
+ }
6809
+ return void 0;
6810
+ }
6811
+ function shouldIndentParagraph(previousBlocks) {
6812
+ for (let index = previousBlocks.length - 1; index >= 0; index -= 1) {
6813
+ const block = previousBlocks[index];
6814
+ if (block.type === "toc" || block.type === "table") {
6815
+ continue;
6816
+ }
6817
+ if (block.type === "label") {
6818
+ return true;
6819
+ }
6820
+ if ((block.type === "paragraph" || block.type === "code") && block.indent) {
6821
+ return true;
6822
+ }
6823
+ return false;
6824
+ }
6825
+ return false;
6826
+ }
6827
+ function inferListItemLevel(text) {
6828
+ if (/^(?:list bullet|definition term)$/i.test(text)) {
6829
+ return 1;
6830
+ }
6831
+ if (/^(?:list bullet 2|list continue 2|definition for the term\.)$/i.test(text)) {
6832
+ return 2;
6833
+ }
6834
+ return void 0;
6835
+ }
6836
+ function parseTocEntry(text) {
6837
+ const tabCells = splitTableRow(text);
6838
+ if (tabCells.length >= 2 && /^\d{1,3}$/.test(tabCells[tabCells.length - 1] || "")) {
6839
+ const title2 = tabCells.slice(0, -1).join(" ").trim();
6840
+ if (isLikelyTocTitle(title2)) {
6841
+ const number2 = title2.match(/^(\d+(?:\.\d+)*)\b/)?.[1] || "";
6842
+ return { type: "toc", title: title2, page: tabCells[tabCells.length - 1], level: number2.includes(".") ? Math.min(3, number2.split(".").length) : 1 };
6843
+ }
6844
+ }
6845
+ const cleaned = text.replace(/\s+/g, " ").trim();
6846
+ const match = cleaned.match(/^(?:(\d+(?:\.\d+)*)\s+)?(.+?)\s+(\d{1,3})$/);
6847
+ if (!match || cleaned.length > 140) {
6848
+ return void 0;
6849
+ }
6850
+ const number = match[1] || "";
6851
+ const title = `${number ? `${number} ` : ""}${match[2] || ""}`.trim();
6852
+ const page = match[3];
6853
+ if (!title || !page || !/^(?:appendix\b|references\b|introduction\b|[A-Z0-9])/i.test(title)) {
6854
+ return void 0;
6855
+ }
6856
+ if (!isLikelyTocTitle(title)) {
6857
+ return void 0;
6858
+ }
6859
+ const level = number.includes(".") ? Math.min(3, number.split(".").length) : 1;
6860
+ return { type: "toc", title, page, level };
6861
+ }
6862
+ function isLikelyTocTitle(title) {
6863
+ return /^(?:appendix\b|references\b|introduction\b|[1-9](?:\.\d+)*\b|[A-Z][\w\s.-]{2,80}$)/i.test(title);
6864
+ }
6865
+ function isTableRowCandidate(text) {
6866
+ if (/^\[[-\w.]+\]\t+/.test(text)) {
6867
+ return false;
6868
+ }
6869
+ const cells = splitTableRow(text);
6870
+ return cells.length >= 2 && cells.some((cell) => cell.length > 0);
6871
+ }
6872
+ function splitTableRow(text) {
6873
+ return text.split(/\t+/).map((cell) => cell.trim()).filter(Boolean);
6874
+ }
6875
+ function normalizeTableRows(cells) {
6876
+ if (cells.length >= 8) {
6877
+ const columnCount = inferTableColumnCount(cells);
6878
+ if (columnCount > 1 && cells.length % columnCount === 0) {
6879
+ const rows = [];
6880
+ for (let offset = 0; offset < cells.length; offset += columnCount) {
6881
+ rows.push(cells.slice(offset, offset + columnCount));
6882
+ }
6883
+ return rows;
6884
+ }
6885
+ }
6886
+ return [cells];
6887
+ }
6888
+ function inferTableColumnCount(cells) {
6889
+ const header = cells.slice(0, 6).join(" ").toLowerCase();
6890
+ if (/\brev\b/.test(header) && /\bdate\b/.test(header) && /whom|what/.test(header)) {
6891
+ return 4;
6892
+ }
6893
+ for (const candidate of [5, 4, 3, 2]) {
6894
+ if (cells.length % candidate === 0) {
6895
+ return candidate;
6896
+ }
6897
+ }
6898
+ return 0;
6899
+ }
6900
+ function isCodeLikeParagraph(text) {
6901
+ 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);
6902
+ }
6903
+ function cleanWordText(value) {
6904
+ return stripWordFieldCodes(value).replace(/[\u0001-\u0006\u0008\u000e-\u001f]/g, "").replace(/ {2,}/g, " ").trim();
6905
+ }
6906
+ function stripWordFieldCodes(value) {
6907
+ 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, "");
6908
+ }
6909
+ function isDisplayableParagraph(value) {
6910
+ if (value.length < 2) {
6911
+ return false;
6912
+ }
6913
+ const letters = [...value].filter((char) => /[\p{L}\p{N}]/u.test(char)).length;
6914
+ return letters >= Math.min(2, value.length);
6915
+ }
6916
+ function inferDocumentTitle(paragraphs) {
6917
+ return paragraphs.find((paragraph) => paragraph.length <= 120) || "Word \u6587\u6863";
6918
+ }
6919
+ function appendMeta4(list, label, value) {
6920
+ const term = window.document.createElement("dt");
6921
+ term.textContent = label;
6922
+ const detail = window.document.createElement("dd");
6923
+ detail.textContent = value;
6924
+ list.append(term, detail);
6925
+ }
6926
+ function concatChunks(chunks, size) {
6927
+ const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
6928
+ const output = new Uint8Array(size === void 0 ? total : Math.min(total, size));
6929
+ let offset = 0;
6930
+ for (const chunk of chunks) {
6931
+ const slice = chunk.subarray(0, Math.min(chunk.length, output.length - offset));
6932
+ output.set(slice, offset);
6933
+ offset += slice.length;
6934
+ if (offset >= output.length) {
6935
+ break;
6936
+ }
6937
+ }
6938
+ return output;
6939
+ }
6940
+ function alignEven(value) {
6941
+ return value % 2 === 0 ? value : value + 1;
6942
+ }
6943
+ function isUsableSector(sector) {
6944
+ return sector !== FREE_SECTOR && sector !== END_OF_CHAIN && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR;
6945
+ }
6946
+ function sectorOffset(sector, sectorSize) {
6947
+ return (sector + 1) * sectorSize;
6948
+ }
6949
+ function normalizeStreamName(name) {
6950
+ return name.replace(/^\/+/, "").toLowerCase();
6951
+ }
6952
+ function decodeUtf16Le(bytes) {
6953
+ return new TextDecoder("utf-16le").decode(bytes);
6954
+ }
6955
+ function decodeWindows1252(bytes) {
6956
+ try {
6957
+ return new TextDecoder("windows-1252").decode(bytes);
6958
+ } catch {
6959
+ return Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
6960
+ }
6961
+ }
6962
+ function dataView2(bytes) {
6963
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
6964
+ }
6965
+
6966
+ // src/plugins/office.ts
5812
6967
  var wordExtensions = /* @__PURE__ */ new Set(["docx", "docm", "doc", "dotx", "dotm", "dot", "rtf", "odt", "fodt", "wps"]);
5813
6968
  var sheetExtensions = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "xlt", "xltx", "xltm", "csv", "tsv", "ods", "fods", "numbers", "et"]);
5814
6969
  var presentationExtensions = /* @__PURE__ */ new Set(["pptx", "pptm", "ppt", "pps", "ppsx", "ppsm", "potx", "potm", "odp", "fodp", "key", "dps"]);
@@ -5895,13 +7050,13 @@ function officePlugin(options = {}) {
5895
7050
  if (conversionContext && await shouldUseOfficeConversion(options, conversionContext)) {
5896
7051
  delegatedInstance = await renderConvertedOfficePreview(panel, ctx, options, conversionContext);
5897
7052
  } else if (packageFormat === "docx" && !fileIsDocx(extension)) {
5898
- disposeDocxFit = await renderDocx(panel, arrayBuffer);
7053
+ disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
5899
7054
  } else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
5900
7055
  await renderSheet(panel, arrayBuffer, "xlsx");
5901
7056
  } else if (packageFormat === "pptx" && !["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
5902
7057
  await renderPptx(panel, arrayBuffer);
5903
7058
  } else if (fileIsDocx(extension)) {
5904
- disposeDocxFit = await renderDocx(panel, arrayBuffer);
7059
+ disposeDocxFit = await renderDocx(panel, arrayBuffer, ctx.options.fit);
5905
7060
  } else if (extension === "rtf") {
5906
7061
  renderPlainDocument(panel, "RTF \u6587\u6863", rtfToText(await readTextFromBuffer(arrayBuffer)));
5907
7062
  } else if (extension === "odt") {
@@ -5910,7 +7065,7 @@ function officePlugin(options = {}) {
5910
7065
  renderOpenDocumentXml(panel, "FODT \u6587\u6863", await readTextFromBuffer(arrayBuffer));
5911
7066
  } else if (extension === "fods") {
5912
7067
  renderFlatOds(panel, await readTextFromBuffer(arrayBuffer));
5913
- } else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension)) {
7068
+ } else if (packagedOfficeCandidates.has(extension) && await renderPackagedOfficePreview(panel, arrayBuffer, extension, ctx.options.fit)) {
5914
7069
  } else if (sheetExtensions.has(extension)) {
5915
7070
  await renderSheet(panel, arrayBuffer, extension);
5916
7071
  } else if (["pptx", "pptm", "ppsx", "ppsm", "potx", "potm"].includes(extension)) {
@@ -5919,6 +7074,8 @@ function officePlugin(options = {}) {
5919
7074
  await renderOdp(panel, arrayBuffer);
5920
7075
  } else if (extension === "fodp") {
5921
7076
  renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
7077
+ } else if (extension === "doc" || extension === "dot") {
7078
+ renderLegacyWordBinary(panel, extension, arrayBuffer);
5922
7079
  } else if (isLegacyOfficeBinary(extension)) {
5923
7080
  renderLegacyOfficeBinary(panel, extension, arrayBuffer);
5924
7081
  } else {
@@ -6112,7 +7269,7 @@ async function detectPackagedOfficeFormat(arrayBuffer) {
6112
7269
  }
6113
7270
  return void 0;
6114
7271
  }
6115
- async function renderDocx(panel, arrayBuffer) {
7272
+ async function renderDocx(panel, arrayBuffer, fit) {
6116
7273
  const content = document.createElement("div");
6117
7274
  content.className = "ofv-docx-document";
6118
7275
  const styleContainer = document.createElement("div");
@@ -6151,7 +7308,7 @@ async function renderDocx(panel, arrayBuffer) {
6151
7308
  return () => void 0;
6152
7309
  }
6153
7310
  panel.append(content);
6154
- disposeFit = fitDocxPages(content);
7311
+ disposeFit = fitDocxPages(content, fit);
6155
7312
  return () => {
6156
7313
  disposeFit?.();
6157
7314
  styleContainer.remove();
@@ -6749,7 +7906,8 @@ function looksLikeDocxTextboxHeading(value) {
6749
7906
  return text.length > 0 && text.length <= 12 && !/[0-9@.::]/.test(text);
6750
7907
  }
6751
7908
  async function normalizeDocxLayout(container, arrayBuffer) {
6752
- const hints = await readDocxLayoutHints(arrayBuffer);
7909
+ const [hints, charts] = await Promise.all([readDocxLayoutHints(arrayBuffer), readDocxCharts(arrayBuffer)]);
7910
+ repairDocxChartPlaceholders(container, charts);
6753
7911
  const pages = container.querySelectorAll("section.ofv-docx");
6754
7912
  for (const page of pages) {
6755
7913
  repairDocxShapeFills(page);
@@ -6764,6 +7922,75 @@ async function normalizeDocxLayout(container, arrayBuffer) {
6764
7922
  }
6765
7923
  }
6766
7924
  }
7925
+ async function readDocxCharts(arrayBuffer) {
7926
+ try {
7927
+ const zip = await JSZip3.loadAsync(arrayBuffer);
7928
+ const documentXml = await zip.file("word/document.xml")?.async("text");
7929
+ const documentDoc = documentXml ? parseOfficeXml(documentXml) : void 0;
7930
+ if (!documentDoc) {
7931
+ return [];
7932
+ }
7933
+ const relationships = await readOfficeRelationships(zip, "word/document.xml");
7934
+ const chartDrawings = Array.from(documentDoc.getElementsByTagName("*")).filter((element) => element.localName === "inline" || element.localName === "anchor").map((element) => readDocxChartDrawing(element)).filter((item) => Boolean(item?.relationshipId));
7935
+ const charts = [];
7936
+ for (const [index, drawing] of chartDrawings.entries()) {
7937
+ const chartRel = relationships.find((rel) => rel.id === drawing.relationshipId && /\/chart$/i.test(rel.type));
7938
+ const chartPath = resolveOfficeRelationshipTarget("word/document.xml", chartRel?.target);
7939
+ const chartXml = chartPath ? await zip.file(chartPath)?.async("text") : void 0;
7940
+ const chart = chartXml ? parseChartXml(chartXml, chartPath?.split("/").pop() || `chart${index + 1}.xml`) : null;
7941
+ if (chart) {
7942
+ charts.push({ ...chart, widthPt: drawing.widthPt, heightPt: drawing.heightPt });
7943
+ }
7944
+ }
7945
+ return charts;
7946
+ } catch {
7947
+ return [];
7948
+ }
7949
+ }
7950
+ function readDocxChartDrawing(element) {
7951
+ const chart = Array.from(element.getElementsByTagName("*")).find((child) => child.localName === "chart");
7952
+ const relationshipId = chart ? getXmlAttribute3(chart, "id") : "";
7953
+ if (!relationshipId) {
7954
+ return void 0;
7955
+ }
7956
+ const extent = Array.from(element.children).find((child) => child.localName === "extent");
7957
+ return {
7958
+ relationshipId,
7959
+ widthPt: emuToPt(Number(extent?.getAttribute("cx") || 0)),
7960
+ heightPt: emuToPt(Number(extent?.getAttribute("cy") || 0))
7961
+ };
7962
+ }
7963
+ function repairDocxChartPlaceholders(container, charts) {
7964
+ if (charts.length === 0) {
7965
+ return;
7966
+ }
7967
+ const placeholders = Array.from(container.querySelectorAll("section.ofv-docx div")).filter(isDocxChartPlaceholder);
7968
+ if (placeholders.length !== charts.length) {
7969
+ return;
7970
+ }
7971
+ placeholders.forEach((placeholder, index) => {
7972
+ const chart = charts[index];
7973
+ placeholder.classList.add("ofv-docx-chart-preview");
7974
+ placeholder.dataset.ofvDocxChartPreview = "true";
7975
+ if (chart.widthPt > 0) {
7976
+ placeholder.style.width ||= `${formatCssNumber(chart.widthPt)}pt`;
7977
+ }
7978
+ if (chart.heightPt > 0) {
7979
+ placeholder.style.height ||= `${formatCssNumber(chart.heightPt)}pt`;
7980
+ }
7981
+ placeholder.replaceChildren(renderChartSvg(chart));
7982
+ });
7983
+ }
7984
+ function isDocxChartPlaceholder(element) {
7985
+ if (element.dataset.ofvDocxChartPreview === "true" || element.children.length > 0 || normalizePreviewText(element.textContent || "")) {
7986
+ return false;
7987
+ }
7988
+ const display = element.style.display;
7989
+ const position = element.style.position;
7990
+ const width = parseCssPixelValue(element.style.width);
7991
+ const height = parseCssPixelValue(element.style.height);
7992
+ return display === "inline-block" && position === "relative" && width >= 120 && height >= 80;
7993
+ }
6767
7994
  function repairDocxHeadingShapeAlignment(page) {
6768
7995
  for (const paragraph of page.querySelectorAll("p")) {
6769
7996
  const text = normalizePreviewText(paragraph.textContent || "");
@@ -6914,14 +8141,19 @@ function repairDocxShapeFills(page) {
6914
8141
  }
6915
8142
  }
6916
8143
  function repairDocxFloatingPictures(page, hints) {
6917
- const hint = hints.floatingPictures.find((item) => item.relativeFrom === "column" && item.wrap === "square");
6918
- if (!hint) {
8144
+ const pageHints = hints.floatingPictures.filter((item) => item.relativeFrom === "column" && item.wrap === "square");
8145
+ if (pageHints.length === 0) {
6919
8146
  return;
6920
8147
  }
6921
- const image = page.querySelector("img");
6922
- if (!image) {
8148
+ const images = Array.from(page.querySelectorAll("img")).filter(
8149
+ (image) => image.closest("[data-ofv-docx-float-repaired='true']") === null
8150
+ );
8151
+ if (images.length === 0 || images.length !== pageHints.length) {
6923
8152
  return;
6924
8153
  }
8154
+ images.forEach((image, index) => repairDocxFloatingPicture(page, image, pageHints[index]));
8155
+ }
8156
+ function repairDocxFloatingPicture(page, image, hint) {
6925
8157
  const wrapper = image.parentElement;
6926
8158
  if (!wrapper || wrapper.dataset.ofvDocxFloatRepaired === "true") {
6927
8159
  return;
@@ -6967,7 +8199,7 @@ function parseCssLineHeight(value) {
6967
8199
  const parsed = Number.parseFloat(trimmed);
6968
8200
  return Number.isFinite(parsed) ? parsed : 0;
6969
8201
  }
6970
- function fitDocxPages(container) {
8202
+ function fitDocxPages(container, fit) {
6971
8203
  const wrapper = container.querySelector(".ofv-docx-wrapper");
6972
8204
  if (!wrapper) {
6973
8205
  return () => void 0;
@@ -6980,6 +8212,7 @@ function fitDocxPages(container) {
6980
8212
  return;
6981
8213
  }
6982
8214
  const availableWidth = Math.max(1, container.clientWidth - 48);
8215
+ const availableHeight = container.clientHeight > 0 ? Math.max(1, container.clientHeight - 48) : void 0;
6983
8216
  const pageWidth = Math.max(
6984
8217
  1,
6985
8218
  ...frames.map(({ page }) => {
@@ -6987,14 +8220,24 @@ function fitDocxPages(container) {
6987
8220
  return page.offsetWidth || rectWidth || parseCssPixelValue(page.style.width) || 794;
6988
8221
  })
6989
8222
  );
6990
- const scale = Math.min(1, Math.max(0.35, availableWidth / pageWidth));
8223
+ const pageHeight = Math.max(
8224
+ 1,
8225
+ ...frames.map(({ page }) => page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height) || 1123)
8226
+ );
8227
+ const scale = getDocxFitScale(fit, availableWidth, availableHeight, pageWidth, pageHeight);
6991
8228
  const userZoom = parseCssPixelValue(panel?.style.getPropertyValue("--ofv-office-zoom") || "1") || 1;
6992
8229
  wrapper.style.setProperty("--ofv-docx-scale", formatCssNumber(scale));
6993
8230
  wrapper.style.setProperty("--ofv-docx-page-width", `${pageWidth}px`);
8231
+ wrapper.style.width = `${Math.ceil(pageWidth * scale * userZoom + 48)}px`;
8232
+ wrapper.style.maxWidth = "none";
8233
+ wrapper.style.overflow = "visible";
6994
8234
  for (const { frame, page } of frames) {
6995
- const pageHeight = page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height);
6996
- if (pageHeight > 0) {
6997
- frame.style.height = `${Math.ceil(pageHeight * scale * userZoom)}px`;
8235
+ const framePageHeight = page.offsetHeight || page.getBoundingClientRect().height || parseCssPixelValue(page.style.height);
8236
+ const framePageWidth = page.offsetWidth || page.getBoundingClientRect().width || parseCssPixelValue(page.style.width) || pageWidth;
8237
+ frame.style.width = `${Math.ceil(framePageWidth * scale * userZoom)}px`;
8238
+ frame.style.maxWidth = "none";
8239
+ if (framePageHeight > 0) {
8240
+ frame.style.height = `${Math.ceil(framePageHeight * scale * userZoom)}px`;
6998
8241
  }
6999
8242
  }
7000
8243
  };
@@ -7019,6 +8262,26 @@ function fitDocxPages(container) {
7019
8262
  observer.disconnect();
7020
8263
  };
7021
8264
  }
8265
+ function getDocxFitScale(fit, availableWidth, availableHeight, pageWidth, pageHeight) {
8266
+ const widthScale = availableWidth / pageWidth;
8267
+ const heightScale = availableHeight ? availableHeight / pageHeight : void 0;
8268
+ if (fit === "actual") {
8269
+ return 1;
8270
+ }
8271
+ if (fit === "height") {
8272
+ return Math.max(0.1, heightScale ?? widthScale);
8273
+ }
8274
+ if (fit === "cover") {
8275
+ return Math.max(0.1, Math.max(widthScale, heightScale ?? widthScale));
8276
+ }
8277
+ if (fit === "scale-down") {
8278
+ return Math.min(1, Math.max(0.1, Math.min(widthScale, heightScale ?? widthScale)));
8279
+ }
8280
+ if (fit === "contain") {
8281
+ return Math.max(0.1, Math.min(widthScale, heightScale ?? widthScale));
8282
+ }
8283
+ return Math.max(0.1, widthScale);
8284
+ }
7022
8285
  function ensureDocxPageFrames(wrapper) {
7023
8286
  const pages = Array.from(wrapper.querySelectorAll("section.ofv-docx"));
7024
8287
  return pages.map((page) => {
@@ -7550,9 +8813,9 @@ function parseChartXml(xml, fallbackName) {
7550
8813
  return null;
7551
8814
  }
7552
8815
  const type = detectChartType(doc);
7553
- const title = textFromFirst(doc, "title") || fallbackName.replace(/\.xml$/i, "");
8816
+ const title = readChartTitle(doc, fallbackName);
7554
8817
  const seriesElements = Array.from(doc.getElementsByTagName("*")).filter((element) => element.localName === "ser");
7555
- const series = seriesElements.map((element, index) => parseChartSeries(element, index)).filter((item) => item.values.length > 0);
8818
+ const series = seriesElements.map((element, index) => ({ ...parseChartSeries(element, index), color: readChartSeriesColor(element) })).filter((item) => item.values.length > 0);
7556
8819
  if (series.length === 0) {
7557
8820
  return null;
7558
8821
  }
@@ -7561,9 +8824,21 @@ function parseChartXml(xml, fallbackName) {
7561
8824
  type,
7562
8825
  title,
7563
8826
  categories: series.find((item) => item.categories.length > 0)?.categories || [],
7564
- series: series.map((item) => ({ name: item.name, values: item.values }))
8827
+ series: series.map((item) => ({ name: item.name, values: item.values, color: item.color }))
7565
8828
  };
7566
8829
  }
8830
+ function readChartTitle(doc, fallbackName) {
8831
+ const titleElement = Array.from(doc.getElementsByTagName("*")).find((element) => element.localName === "title");
8832
+ if (!titleElement) {
8833
+ return fallbackName.replace(/\.xml$/i, "");
8834
+ }
8835
+ const explicitTitle = chartText(titleElement);
8836
+ if (explicitTitle) {
8837
+ return explicitTitle;
8838
+ }
8839
+ const language = Array.from(doc.getElementsByTagName("*")).find((element) => element.localName === "lang")?.getAttribute("val") || "";
8840
+ return /^zh\b/i.test(language) ? "\u56FE\u8868\u6807\u9898" : "Chart Title";
8841
+ }
7567
8842
  function detectChartType(doc) {
7568
8843
  const chartType = Array.from(doc.getElementsByTagName("*")).find(
7569
8844
  (element) => element.localName.endsWith("Chart") && element.localName !== "chart"
@@ -7580,6 +8855,31 @@ function parseChartSeries(element, index) {
7580
8855
  categories: stringsFromFirst(element, "cat")
7581
8856
  };
7582
8857
  }
8858
+ function readChartSeriesColor(element) {
8859
+ const shape = Array.from(element?.children || []).find((child) => child.localName === "spPr");
8860
+ const color = Array.from(shape?.getElementsByTagName("*") || []).find(
8861
+ (child) => child.localName === "srgbClr" || child.localName === "schemeClr"
8862
+ );
8863
+ if (!color) {
8864
+ return void 0;
8865
+ }
8866
+ if (color.localName === "srgbClr") {
8867
+ const value = color.getAttribute("val") || "";
8868
+ return /^[\da-f]{6}$/i.test(value) ? `#${value}` : void 0;
8869
+ }
8870
+ return chartSchemeColor(color.getAttribute("val") || "");
8871
+ }
8872
+ function chartSchemeColor(value) {
8873
+ const colors = {
8874
+ accent1: "#156082",
8875
+ accent2: "#e97132",
8876
+ accent3: "#196b24",
8877
+ accent4: "#0f9ed5",
8878
+ accent5: "#a02b93",
8879
+ accent6: "#4ea72e"
8880
+ };
8881
+ return colors[value];
8882
+ }
7583
8883
  function renderChartPreviewSection(charts) {
7584
8884
  const section = createSection("\u8868\u683C\u56FE\u8868\u9884\u89C8");
7585
8885
  const grid = document.createElement("div");
@@ -7617,17 +8917,39 @@ function renderChartCard(chart) {
7617
8917
  }
7618
8918
  function renderChartSvg(chart) {
7619
8919
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
7620
- svg.setAttribute("viewBox", "0 0 640 260");
8920
+ svg.setAttribute("viewBox", "0 0 640 380");
7621
8921
  svg.setAttribute("role", "img");
7622
8922
  svg.setAttribute("aria-label", chart.title);
7623
8923
  svg.classList.add("ofv-chart-svg");
7624
8924
  const allValues = chart.series.flatMap((item) => item.values).filter((value) => Number.isFinite(value));
7625
8925
  const max = Math.max(1, ...allValues);
7626
8926
  const min = Math.min(0, ...allValues);
8927
+ const axisScale = createChartAxisScale(max, min);
8928
+ const axisMax = axisScale.max;
8929
+ const axisMin = axisScale.min;
7627
8930
  const span = max - min || 1;
7628
- const colors = ["#2563eb", "#059669", "#d97706", "#dc2626", "#7c3aed"];
7629
- const plot = { x: 48, y: 24, width: 552, height: 178 };
7630
- appendSvg(svg, "line", { x1: plot.x, y1: plot.y, x2: plot.x, y2: plot.y + plot.height, class: "ofv-chart-axis" });
8931
+ const colors = ["#156082", "#e97132", "#196b24", "#0f9ed5", "#a02b93", "#4ea72e"];
8932
+ const plot = { x: 74, y: 74, width: 526, height: 214 };
8933
+ const categories = chart.categories.length > 0 ? chart.categories : chart.series[0]?.values.map((_, index) => String(index + 1)) || [];
8934
+ const title = appendSvg(svg, "text", { x: 320, y: 34, class: "ofv-chart-title", "text-anchor": "middle" });
8935
+ title.textContent = chart.title;
8936
+ for (const value of axisScale.ticks) {
8937
+ const y = plot.y + plot.height - (value - axisMin) / (axisMax - axisMin || 1) * plot.height;
8938
+ appendSvg(svg, "line", {
8939
+ x1: plot.x,
8940
+ y1: Number(y.toFixed(1)),
8941
+ x2: plot.x + plot.width,
8942
+ y2: Number(y.toFixed(1)),
8943
+ class: value === 0 ? "ofv-chart-axis" : "ofv-chart-gridline"
8944
+ });
8945
+ const label = appendSvg(svg, "text", {
8946
+ x: plot.x - 12,
8947
+ y: Number((y + 4).toFixed(1)),
8948
+ class: "ofv-chart-label",
8949
+ "text-anchor": "end"
8950
+ });
8951
+ label.textContent = formatChartTick(value);
8952
+ }
7631
8953
  appendSvg(svg, "line", {
7632
8954
  x1: plot.x,
7633
8955
  y1: plot.y + plot.height,
@@ -7635,28 +8957,47 @@ function renderChartSvg(chart) {
7635
8957
  y2: plot.y + plot.height,
7636
8958
  class: "ofv-chart-axis"
7637
8959
  });
7638
- chart.series.forEach((series, seriesIndex) => {
7639
- const color = colors[seriesIndex % colors.length];
7640
- const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
7641
- const points = series.values.map((value, index) => ({
7642
- x: plot.x + index * step,
7643
- y: plot.y + plot.height - (value - min) / span * plot.height
7644
- }));
7645
- if (chart.type.includes("bar") || chart.type.includes("col")) {
7646
- const barWidth = Math.max(4, Math.min(28, step * 0.6)) / Math.max(1, chart.series.length);
7647
- points.forEach((point, index) => {
7648
- const zeroY = plot.y + plot.height - (0 - min) / span * plot.height;
7649
- const x = point.x - barWidth * chart.series.length / 2 + seriesIndex * barWidth;
8960
+ if (chart.type.includes("bar") || chart.type.includes("col")) {
8961
+ const categoryCount = Math.max(1, categories.length, ...chart.series.map((series) => series.values.length));
8962
+ const groupWidth = plot.width / categoryCount;
8963
+ const clusterWidth = groupWidth * 0.58;
8964
+ const barWidth = Math.max(5, Math.min(28, clusterWidth / Math.max(1, chart.series.length)));
8965
+ const zeroY = plot.y + plot.height - (0 - axisMin) / (axisMax - axisMin || 1) * plot.height;
8966
+ categories.slice(0, categoryCount).forEach((category, index) => {
8967
+ const x = plot.x + groupWidth * (index + 0.5);
8968
+ const label = appendSvg(svg, "text", {
8969
+ x: Number(x.toFixed(1)),
8970
+ y: plot.y + plot.height + 22,
8971
+ class: "ofv-chart-label",
8972
+ "text-anchor": "middle"
8973
+ });
8974
+ label.textContent = truncateChartLabel(category);
8975
+ });
8976
+ chart.series.forEach((series, seriesIndex) => {
8977
+ const color = series.color || colors[seriesIndex % colors.length];
8978
+ series.values.forEach((value, index) => {
8979
+ const groupCenter = plot.x + groupWidth * (index + 0.5);
8980
+ const x = groupCenter - barWidth * chart.series.length / 2 + seriesIndex * barWidth + barWidth * 0.12;
8981
+ const y = plot.y + plot.height - (value - axisMin) / (axisMax - axisMin || 1) * plot.height;
7650
8982
  appendSvg(svg, "rect", {
7651
- x,
7652
- y: Math.min(point.y, zeroY),
7653
- width: barWidth,
7654
- height: Math.max(1, Math.abs(zeroY - point.y)),
8983
+ x: Number(x.toFixed(1)),
8984
+ y: Number(Math.min(y, zeroY).toFixed(1)),
8985
+ width: Number((barWidth * 0.76).toFixed(1)),
8986
+ height: Number(Math.max(1, Math.abs(zeroY - y)).toFixed(1)),
7655
8987
  fill: color,
7656
8988
  "data-index": index
7657
8989
  });
7658
8990
  });
7659
- } else {
8991
+ });
8992
+ } else {
8993
+ chart.series.forEach((series, seriesIndex) => {
8994
+ const color = series.color || colors[seriesIndex % colors.length];
8995
+ const step = series.values.length > 1 ? plot.width / (series.values.length - 1) : plot.width;
8996
+ const lineSpan = axisMax - axisMin || span;
8997
+ const points = series.values.map((value, index) => ({
8998
+ x: plot.x + index * step,
8999
+ y: plot.y + plot.height - (value - axisMin) / lineSpan * plot.height
9000
+ }));
7660
9001
  appendSvg(svg, "polyline", {
7661
9002
  points: points.map((point) => `${point.x.toFixed(1)},${point.y.toFixed(1)}`).join(" "),
7662
9003
  fill: "none",
@@ -7668,11 +9009,49 @@ function renderChartSvg(chart) {
7668
9009
  for (const point of points.slice(0, 80)) {
7669
9010
  appendSvg(svg, "circle", { cx: point.x, cy: point.y, r: 3, fill: color });
7670
9011
  }
7671
- }
7672
- appendLegend(svg, series.name, color, 52 + seriesIndex * 118, 236);
7673
- });
9012
+ });
9013
+ }
9014
+ appendChartLegend(svg, chart, colors, 348);
7674
9015
  return svg;
7675
9016
  }
9017
+ function appendChartLegend(svg, chart, colors, y) {
9018
+ const itemWidth = 86;
9019
+ const startX = 320 - chart.series.length * itemWidth / 2;
9020
+ chart.series.forEach((series, seriesIndex) => {
9021
+ const color = series.color || colors[seriesIndex % colors.length];
9022
+ appendLegend(svg, series.name, color, startX + seriesIndex * itemWidth, y);
9023
+ });
9024
+ }
9025
+ function createChartAxisScale(max, min) {
9026
+ const axisMin = Math.min(0, min);
9027
+ const positiveMax = Math.max(1, max);
9028
+ const step = niceChartStep((positiveMax - axisMin) / 5);
9029
+ let axisMax = Math.ceil(positiveMax / step) * step;
9030
+ if (axisMax <= positiveMax) {
9031
+ axisMax += step;
9032
+ }
9033
+ const ticks = [];
9034
+ for (let value = axisMin; value <= axisMax + step / 2; value += step) {
9035
+ ticks.push(Number(value.toFixed(6)));
9036
+ }
9037
+ return { min: axisMin, max: axisMax, ticks };
9038
+ }
9039
+ function niceChartStep(rawStep) {
9040
+ if (rawStep <= 0) {
9041
+ return 1;
9042
+ }
9043
+ const magnitude = 10 ** Math.floor(Math.log10(rawStep));
9044
+ const normalized = rawStep / magnitude;
9045
+ const nice = normalized <= 1 ? 1 : normalized <= 2 ? 2 : normalized <= 5 ? 5 : 10;
9046
+ return nice * magnitude;
9047
+ }
9048
+ function formatChartTick(value) {
9049
+ const rounded = Math.abs(value) < 1 ? Number(value.toFixed(1)) : Number(value.toFixed(0));
9050
+ return String(rounded);
9051
+ }
9052
+ function truncateChartLabel(value) {
9053
+ return value.length > 10 ? `${value.slice(0, 10)}...` : value;
9054
+ }
7676
9055
  function appendLegend(svg, label, color, x, y) {
7677
9056
  appendSvg(svg, "rect", { x, y: y - 10, width: 12, height: 12, rx: 2, fill: color });
7678
9057
  const text = appendSvg(svg, "text", { x: x + 18, y, class: "ofv-chart-label" });
@@ -8406,7 +9785,7 @@ function renderOpenDocumentPresentationXml(panel, xml) {
8406
9785
  renderPresentationInsight(panel, inspectOpenDocumentPresentation("FODP \u6F14\u793A\u6587\u7A3F", xml, 0));
8407
9786
  renderOpenDocumentPresentation(panel, "FODP \u6F14\u793A\u6587\u7A3F", xml, []);
8408
9787
  }
8409
- async function renderPackagedOfficePreview(panel, arrayBuffer, extension) {
9788
+ async function renderPackagedOfficePreview(panel, arrayBuffer, extension, fit) {
8410
9789
  let zip;
8411
9790
  try {
8412
9791
  zip = await JSZip3.loadAsync(arrayBuffer);
@@ -8417,7 +9796,7 @@ async function renderPackagedOfficePreview(panel, arrayBuffer, extension) {
8417
9796
  const hasEntry = (path) => entries.some((entry) => entry.name.toLowerCase() === path.toLowerCase());
8418
9797
  const contentXml = zip.file(/(^|\/)content\.xml$/i)[0];
8419
9798
  if (hasEntry("word/document.xml")) {
8420
- await renderDocx(panel, arrayBuffer);
9799
+ await renderDocx(panel, arrayBuffer, fit);
8421
9800
  return true;
8422
9801
  }
8423
9802
  if (hasEntry("xl/workbook.xml")) {
@@ -8852,6 +10231,13 @@ function legacyOfficeFormatLabel(extension) {
8852
10231
  }
8853
10232
  return "PowerPoint Binary File Format";
8854
10233
  }
10234
+ function renderLegacyWordBinary(panel, extension, arrayBuffer) {
10235
+ try {
10236
+ renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
10237
+ } catch (error) {
10238
+ renderLegacyOfficeBinary(panel, extension, arrayBuffer, `Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A${normalizeOfficeError(error)}`);
10239
+ }
10240
+ }
8855
10241
  function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
8856
10242
  const fragments = extractLegacyOfficeText(arrayBuffer);
8857
10243
  panel.replaceChildren();
@@ -13427,10 +14813,10 @@ function renderStep(panel, text, extension, ctx) {
13427
14813
  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";
13428
14814
  const meta = document.createElement("div");
13429
14815
  meta.className = "ofv-cad-summary";
13430
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13431
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13432
- appendMeta5(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
13433
- appendMeta5(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
14816
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14817
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14818
+ appendMeta6(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
14819
+ appendMeta6(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
13434
14820
  const typeList = createCadTypeList(typeCounts);
13435
14821
  section.append(note, meta, typeList);
13436
14822
  let viewer;
@@ -13465,10 +14851,10 @@ function renderIges(panel, text, extension, ctx) {
13465
14851
  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";
13466
14852
  const meta = document.createElement("div");
13467
14853
  meta.className = "ofv-cad-summary";
13468
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13469
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13470
- appendMeta5(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
13471
- appendMeta5(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
14854
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14855
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14856
+ appendMeta6(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
14857
+ appendMeta6(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
13472
14858
  const typeList = createCadTypeList(typeCounts, "\u7C7B\u578B\u53F7\u7EDF\u8BA1");
13473
14859
  section.append(note, meta, typeList);
13474
14860
  let viewer;
@@ -13502,13 +14888,13 @@ function renderIfc(panel, text) {
13502
14888
  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";
13503
14889
  const meta = document.createElement("div");
13504
14890
  meta.className = "ofv-cad-summary";
13505
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13506
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13507
- appendMeta5(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
13508
- appendMeta5(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
13509
- appendMeta5(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
13510
- appendMeta5(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
13511
- appendMeta5(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
14891
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14892
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14893
+ appendMeta6(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
14894
+ appendMeta6(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
14895
+ appendMeta6(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
14896
+ appendMeta6(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
14897
+ appendMeta6(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
13512
14898
  section.append(note, meta, createCadTypeList(typeCounts, "IFC \u5B9E\u4F53\u7EDF\u8BA1"));
13513
14899
  const hierarchy = createIfcHierarchy(records);
13514
14900
  if (hierarchy) {
@@ -13533,10 +14919,10 @@ function renderAcisSat(panel, text, extension, ctx) {
13533
14919
  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";
13534
14920
  const meta = document.createElement("div");
13535
14921
  meta.className = "ofv-cad-summary";
13536
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13537
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13538
- appendMeta5(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
13539
- appendMeta5(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
14922
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14923
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14924
+ appendMeta6(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
14925
+ appendMeta6(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
13540
14926
  const typeList = createCadTypeList(typeCounts);
13541
14927
  section.append(note, meta, typeList);
13542
14928
  let viewer;
@@ -13573,10 +14959,10 @@ function renderParasolidText(panel, text, extension, ctx) {
13573
14959
  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";
13574
14960
  const meta = document.createElement("div");
13575
14961
  meta.className = "ofv-cad-summary";
13576
- appendMeta5(meta, "\u5B9E\u4F53", records.length);
13577
- appendMeta5(meta, "\u7C7B\u578B", typeCounts.size);
13578
- appendMeta5(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
13579
- appendMeta5(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
14962
+ appendMeta6(meta, "\u5B9E\u4F53", records.length);
14963
+ appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
14964
+ appendMeta6(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
14965
+ appendMeta6(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
13580
14966
  const typeList = createCadTypeList(typeCounts);
13581
14967
  section.append(note, meta, typeList);
13582
14968
  let viewer;
@@ -13684,23 +15070,23 @@ function renderLayoutPreview(panel, data, ctx) {
13684
15070
  summary.setAttribute("aria-hidden", "true");
13685
15071
  summary.style.display = "none";
13686
15072
  }
13687
- appendMeta5(summary, "\u6587\u4EF6", data.fileName);
13688
- appendMeta5(summary, "\u683C\u5F0F", data.format);
15073
+ appendMeta6(summary, "\u6587\u4EF6", data.fileName);
15074
+ appendMeta6(summary, "\u683C\u5F0F", data.format);
13689
15075
  if (data.libraryName) {
13690
- appendMeta5(summary, "\u5E93", data.libraryName);
15076
+ appendMeta6(summary, "\u5E93", data.libraryName);
13691
15077
  }
13692
15078
  if (data.version) {
13693
- appendMeta5(summary, "\u7248\u672C", data.version);
15079
+ appendMeta6(summary, "\u7248\u672C", data.version);
13694
15080
  }
13695
15081
  if (data.unit) {
13696
- appendMeta5(summary, "\u5355\u4F4D", data.unit);
15082
+ appendMeta6(summary, "\u5355\u4F4D", data.unit);
13697
15083
  }
13698
- appendMeta5(summary, "Cell", data.cells.length);
13699
- appendMeta5(summary, "\u51E0\u4F55", data.shapes.length);
13700
- appendMeta5(summary, "\u5F15\u7528", data.references.length);
13701
- appendMeta5(summary, "\u6587\u5B57", data.labels.length);
15084
+ appendMeta6(summary, "Cell", data.cells.length);
15085
+ appendMeta6(summary, "\u51E0\u4F55", data.shapes.length);
15086
+ appendMeta6(summary, "\u5F15\u7528", data.references.length);
15087
+ appendMeta6(summary, "\u6587\u5B57", data.labels.length);
13702
15088
  for (const [label, value] of data.metadata) {
13703
- appendMeta5(summary, label, value);
15089
+ appendMeta6(summary, label, value);
13704
15090
  }
13705
15091
  section.append(summary);
13706
15092
  for (const noteText of [...data.notes, ...data.warnings]) {
@@ -14306,12 +15692,12 @@ function renderBinaryCad(panel, bytes, extension, fileName) {
14306
15692
  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";
14307
15693
  const meta = document.createElement("div");
14308
15694
  meta.className = "ofv-cad-summary";
14309
- appendMeta5(meta, "\u6587\u4EF6", fileName);
14310
- appendMeta5(meta, "\u683C\u5F0F", extension.toUpperCase());
14311
- appendMeta5(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
14312
- appendMeta5(meta, "\u7B7E\u540D", byteSignature2(bytes));
14313
- appendMeta5(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
14314
- appendMeta5(meta, "\u5BB9\u5668", detectCadContainer(bytes));
15695
+ appendMeta6(meta, "\u6587\u4EF6", fileName);
15696
+ appendMeta6(meta, "\u683C\u5F0F", extension.toUpperCase());
15697
+ appendMeta6(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
15698
+ appendMeta6(meta, "\u7B7E\u540D", byteSignature2(bytes));
15699
+ appendMeta6(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
15700
+ appendMeta6(meta, "\u5BB9\u5668", detectCadContainer(bytes));
14315
15701
  const actions = document.createElement("div");
14316
15702
  actions.className = "ofv-cad-conversion";
14317
15703
  const actionTitle = document.createElement("h4");
@@ -14351,12 +15737,12 @@ function createBinaryCadProbe(bytes, extension) {
14351
15737
  summary.textContent = "\u4E8C\u8FDB\u5236\u7ED3\u6784\u63A2\u6D4B";
14352
15738
  const meta = document.createElement("div");
14353
15739
  meta.className = "ofv-archive-probe-meta";
14354
- appendMeta5(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
14355
- appendMeta5(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
14356
- appendMeta5(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
14357
- appendMeta5(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
14358
- appendMeta5(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
14359
- appendMeta5(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
15740
+ appendMeta6(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
15741
+ appendMeta6(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
15742
+ appendMeta6(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
15743
+ appendMeta6(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
15744
+ appendMeta6(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
15745
+ appendMeta6(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
14360
15746
  details.append(summary, meta);
14361
15747
  const hints = [...probe.layerHints, ...probe.blockHints, ...probe.externalRefs].slice(0, 18);
14362
15748
  if (hints.length > 0) {
@@ -14889,9 +16275,9 @@ function createUnsupportedCadSection(extension, fileName) {
14889
16275
  const section = createSection("CAD \u589E\u5F3A\u63A5\u5165\u63D0\u793A");
14890
16276
  const meta = document.createElement("div");
14891
16277
  meta.className = "ofv-cad-summary";
14892
- appendMeta5(meta, "\u6587\u4EF6", fileName);
14893
- appendMeta5(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
14894
- appendMeta5(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
16278
+ appendMeta6(meta, "\u6587\u4EF6", fileName);
16279
+ appendMeta6(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
16280
+ appendMeta6(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
14895
16281
  const note = document.createElement("p");
14896
16282
  note.textContent = unsupportedCadGuidance(extension);
14897
16283
  const actions = document.createElement("div");
@@ -15004,7 +16390,7 @@ function countBy(values) {
15004
16390
  }
15005
16391
  return counts;
15006
16392
  }
15007
- function appendMeta5(parent, label, value) {
16393
+ function appendMeta6(parent, label, value) {
15008
16394
  const row = document.createElement("div");
15009
16395
  row.className = "ofv-meta-row";
15010
16396
  const key = document.createElement("span");
@@ -17038,10 +18424,10 @@ function read255UInt16(bytes, offset) {
17038
18424
  return { value: code, offset };
17039
18425
  }
17040
18426
  function decodeEotString(bytes) {
17041
- const text = decodeUtf16Le(bytes).replace(/\0+$/g, "").trim();
18427
+ const text = decodeUtf16Le2(bytes).replace(/\0+$/g, "").trim();
17042
18428
  return text || new TextDecoder("latin1").decode(bytes).replace(/\0+$/g, "").trim();
17043
18429
  }
17044
- function decodeUtf16Le(bytes) {
18430
+ function decodeUtf16Le2(bytes) {
17045
18431
  let value = "";
17046
18432
  for (let index = 0; index + 1 < bytes.length; index += 2) {
17047
18433
  value += String.fromCharCode(bytes[index] | bytes[index + 1] << 8);