@open-file-viewer/core 0.1.16 → 0.1.18
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/README.md +6 -6
- package/dist/index.cjs +1176 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1176 -62
- package/dist/index.js.map +1 -1
- package/dist/style.css +313 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -331,7 +331,7 @@ function getFileNameFromUrl(source) {
|
|
|
331
331
|
function getExtension(name) {
|
|
332
332
|
const clean = name.split("?")[0]?.split("#")[0] || "";
|
|
333
333
|
const index = clean.lastIndexOf(".");
|
|
334
|
-
return index >= 0 ? clean.slice(index + 1).toLowerCase() : "";
|
|
334
|
+
return index >= 0 ? clean.slice(index + 1).split("!", 1)[0].toLowerCase() : "";
|
|
335
335
|
}
|
|
336
336
|
function isTextLike(file) {
|
|
337
337
|
const textFileName = normalizeFileName(file.name);
|
|
@@ -590,7 +590,7 @@ var defaultMessages = {
|
|
|
590
590
|
};
|
|
591
591
|
function resolveMessages(options) {
|
|
592
592
|
return {
|
|
593
|
-
...defaultMessages[options.locale || "
|
|
593
|
+
...defaultMessages[options.locale || "en-US"],
|
|
594
594
|
...options.messages
|
|
595
595
|
};
|
|
596
596
|
}
|
|
@@ -5870,6 +5870,1100 @@ function decodeXml(value) {
|
|
|
5870
5870
|
// src/plugins/office.ts
|
|
5871
5871
|
import JSZip3 from "jszip";
|
|
5872
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
|
|
5873
6967
|
var wordExtensions = /* @__PURE__ */ new Set(["docx", "docm", "doc", "dotx", "dotm", "dot", "rtf", "odt", "fodt", "wps"]);
|
|
5874
6968
|
var sheetExtensions = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "xlt", "xltx", "xltm", "csv", "tsv", "ods", "fods", "numbers", "et"]);
|
|
5875
6969
|
var presentationExtensions = /* @__PURE__ */ new Set(["pptx", "pptm", "ppt", "pps", "ppsx", "ppsm", "potx", "potm", "odp", "fodp", "key", "dps"]);
|
|
@@ -5980,6 +7074,8 @@ function officePlugin(options = {}) {
|
|
|
5980
7074
|
await renderOdp(panel, arrayBuffer);
|
|
5981
7075
|
} else if (extension === "fodp") {
|
|
5982
7076
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7077
|
+
} else if (extension === "doc" || extension === "dot") {
|
|
7078
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
5983
7079
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
5984
7080
|
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
5985
7081
|
} else {
|
|
@@ -7368,7 +8464,7 @@ async function renderSheet(panel, arrayBuffer, extension) {
|
|
|
7368
8464
|
heading.textContent = sheetName;
|
|
7369
8465
|
const sheet = workbook.Sheets[sheetName];
|
|
7370
8466
|
const sheetImages = workbookImages.get(sheetName) || [];
|
|
7371
|
-
const range = trimWorkbookSheetRange(sheet, xlsx.utils.decode_range(sheet["!ref"] || "A1:A1"), xlsx.utils.decode_cell);
|
|
8467
|
+
const range = trimWorkbookSheetRange(sheet, xlsx.utils.decode_range(sheet["!ref"] || "A1:A1"), xlsx.utils.decode_cell, sheetImages);
|
|
7372
8468
|
const rowCount = range.e.r - range.s.r + 1;
|
|
7373
8469
|
const columnCount = range.e.c - range.s.c + 1;
|
|
7374
8470
|
const formulaRows = collectFormulaRows(sheet, range, xlsx.utils.encode_cell);
|
|
@@ -7467,7 +8563,7 @@ function renderSheetFallback(panel, extension, detail) {
|
|
|
7467
8563
|
async function readWorkbookSheetImages(arrayBuffer) {
|
|
7468
8564
|
const zip = await JSZip3.loadAsync(arrayBuffer);
|
|
7469
8565
|
const fileNames = Object.keys(zip.files);
|
|
7470
|
-
if (!fileNames.some((name) => /^xl\/drawings\/.+\.xml$/i.test(name))
|
|
8566
|
+
if (!fileNames.some((name) => /^xl\/drawings\/.+\.xml$/i.test(name))) {
|
|
7471
8567
|
return /* @__PURE__ */ new Map();
|
|
7472
8568
|
}
|
|
7473
8569
|
const workbookXml = await zip.file("xl/workbook.xml")?.async("text");
|
|
@@ -7527,6 +8623,7 @@ async function readWorksheetDrawingImages(zip, drawingPath) {
|
|
|
7527
8623
|
const images = [];
|
|
7528
8624
|
for (const anchor of anchors) {
|
|
7529
8625
|
const from = Array.from(anchor.children).find((element) => element.localName === "from");
|
|
8626
|
+
const to = Array.from(anchor.children).find((element) => element.localName === "to");
|
|
7530
8627
|
const embedId = findDrawingImageRelationshipId(anchor);
|
|
7531
8628
|
const mediaRel = drawingRels.find((rel) => rel.id === embedId && /\/image$/i.test(rel.type));
|
|
7532
8629
|
const mediaPath = resolveOfficeRelationshipTarget(drawingPath, mediaRel?.target);
|
|
@@ -7538,6 +8635,8 @@ async function readWorksheetDrawingImages(zip, drawingPath) {
|
|
|
7538
8635
|
images.push({
|
|
7539
8636
|
row: readDrawingMarkerIndex(from, "row"),
|
|
7540
8637
|
column: readDrawingMarkerIndex(from, "col"),
|
|
8638
|
+
endRow: to ? readDrawingMarkerIndex(to, "row") : void 0,
|
|
8639
|
+
endColumn: to ? readDrawingMarkerIndex(to, "col") : void 0,
|
|
7541
8640
|
fileName: mediaPath.split("/").pop() || "image",
|
|
7542
8641
|
mimeType,
|
|
7543
8642
|
dataUrl: `data:${mimeType};base64,${await mediaFile.async("base64")}`,
|
|
@@ -7993,7 +9092,7 @@ function chartText(element) {
|
|
|
7993
9092
|
function chartStringValues(element) {
|
|
7994
9093
|
return Array.from(element.querySelectorAll("*")).filter((item) => item.localName === "v" || item.localName === "t").map((item) => item.textContent?.trim() || "").filter(Boolean);
|
|
7995
9094
|
}
|
|
7996
|
-
function trimWorkbookSheetRange(sheet, range, decodeCell) {
|
|
9095
|
+
function trimWorkbookSheetRange(sheet, range, decodeCell, images = []) {
|
|
7997
9096
|
let minRow = Number.POSITIVE_INFINITY;
|
|
7998
9097
|
let minColumn = Number.POSITIVE_INFINITY;
|
|
7999
9098
|
let maxRow = Number.NEGATIVE_INFINITY;
|
|
@@ -8018,17 +9117,21 @@ function trimWorkbookSheetRange(sheet, range, decodeCell) {
|
|
|
8018
9117
|
include(merge.s.r, merge.s.c);
|
|
8019
9118
|
include(merge.e.r, merge.e.c);
|
|
8020
9119
|
}
|
|
9120
|
+
for (const image of images) {
|
|
9121
|
+
include(image.row, image.column);
|
|
9122
|
+
include(image.endRow ?? image.row, image.endColumn ?? image.column);
|
|
9123
|
+
}
|
|
8021
9124
|
if (!Number.isFinite(minRow) || !Number.isFinite(minColumn) || !Number.isFinite(maxRow) || !Number.isFinite(maxColumn)) {
|
|
8022
9125
|
return range;
|
|
8023
9126
|
}
|
|
8024
9127
|
return {
|
|
8025
9128
|
s: {
|
|
8026
|
-
r:
|
|
8027
|
-
c:
|
|
9129
|
+
r: minRow,
|
|
9130
|
+
c: minColumn
|
|
8028
9131
|
},
|
|
8029
9132
|
e: {
|
|
8030
|
-
r:
|
|
8031
|
-
c:
|
|
9133
|
+
r: maxRow,
|
|
9134
|
+
c: maxColumn
|
|
8032
9135
|
}
|
|
8033
9136
|
};
|
|
8034
9137
|
}
|
|
@@ -8159,7 +9262,9 @@ function createWorkbookSheetTable(sheet, range, sheetIndex, viewport, encodeCell
|
|
|
8159
9262
|
cell.classList.add("ofv-cell-multiline");
|
|
8160
9263
|
}
|
|
8161
9264
|
appendWorkbookCellImages(cell, imagesByCell.get(`${rowIndex}:${columnIndex}`), text);
|
|
8162
|
-
|
|
9265
|
+
if (rowIndex === rowStart) {
|
|
9266
|
+
appendColumnResizeHandle(cell, columnIndex, columnSizing);
|
|
9267
|
+
}
|
|
8163
9268
|
row.append(cell);
|
|
8164
9269
|
}
|
|
8165
9270
|
table.append(row);
|
|
@@ -8385,7 +9490,9 @@ function createParsedSheetTable(sheet, sheetIndex, viewport, columnSizing, reren
|
|
|
8385
9490
|
if (value.includes("\n")) {
|
|
8386
9491
|
cell.classList.add("ofv-cell-multiline");
|
|
8387
9492
|
}
|
|
8388
|
-
|
|
9493
|
+
if (rowIndex === viewport.rowStart) {
|
|
9494
|
+
appendColumnResizeHandle(cell, columnIndex, columnSizing);
|
|
9495
|
+
}
|
|
8389
9496
|
row.append(cell);
|
|
8390
9497
|
}
|
|
8391
9498
|
table.append(row);
|
|
@@ -9135,6 +10242,13 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
9135
10242
|
}
|
|
9136
10243
|
return "PowerPoint Binary File Format";
|
|
9137
10244
|
}
|
|
10245
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10246
|
+
try {
|
|
10247
|
+
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10248
|
+
} catch (error) {
|
|
10249
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, `Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A${normalizeOfficeError(error)}`);
|
|
10250
|
+
}
|
|
10251
|
+
}
|
|
9138
10252
|
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
9139
10253
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
9140
10254
|
panel.replaceChildren();
|
|
@@ -13710,10 +14824,10 @@ function renderStep(panel, text, extension, ctx) {
|
|
|
13710
14824
|
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";
|
|
13711
14825
|
const meta = document.createElement("div");
|
|
13712
14826
|
meta.className = "ofv-cad-summary";
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
14827
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14828
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14829
|
+
appendMeta6(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
|
|
14830
|
+
appendMeta6(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
|
|
13717
14831
|
const typeList = createCadTypeList(typeCounts);
|
|
13718
14832
|
section.append(note, meta, typeList);
|
|
13719
14833
|
let viewer;
|
|
@@ -13748,10 +14862,10 @@ function renderIges(panel, text, extension, ctx) {
|
|
|
13748
14862
|
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";
|
|
13749
14863
|
const meta = document.createElement("div");
|
|
13750
14864
|
meta.className = "ofv-cad-summary";
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
14865
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14866
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14867
|
+
appendMeta6(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
|
|
14868
|
+
appendMeta6(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
|
|
13755
14869
|
const typeList = createCadTypeList(typeCounts, "\u7C7B\u578B\u53F7\u7EDF\u8BA1");
|
|
13756
14870
|
section.append(note, meta, typeList);
|
|
13757
14871
|
let viewer;
|
|
@@ -13785,13 +14899,13 @@ function renderIfc(panel, text) {
|
|
|
13785
14899
|
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";
|
|
13786
14900
|
const meta = document.createElement("div");
|
|
13787
14901
|
meta.className = "ofv-cad-summary";
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13791
|
-
|
|
13792
|
-
|
|
13793
|
-
|
|
13794
|
-
|
|
14902
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14903
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14904
|
+
appendMeta6(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
|
|
14905
|
+
appendMeta6(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
|
|
14906
|
+
appendMeta6(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
|
|
14907
|
+
appendMeta6(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
|
|
14908
|
+
appendMeta6(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
|
|
13795
14909
|
section.append(note, meta, createCadTypeList(typeCounts, "IFC \u5B9E\u4F53\u7EDF\u8BA1"));
|
|
13796
14910
|
const hierarchy = createIfcHierarchy(records);
|
|
13797
14911
|
if (hierarchy) {
|
|
@@ -13816,10 +14930,10 @@ function renderAcisSat(panel, text, extension, ctx) {
|
|
|
13816
14930
|
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";
|
|
13817
14931
|
const meta = document.createElement("div");
|
|
13818
14932
|
meta.className = "ofv-cad-summary";
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
14933
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14934
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14935
|
+
appendMeta6(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
|
|
14936
|
+
appendMeta6(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
|
|
13823
14937
|
const typeList = createCadTypeList(typeCounts);
|
|
13824
14938
|
section.append(note, meta, typeList);
|
|
13825
14939
|
let viewer;
|
|
@@ -13856,10 +14970,10 @@ function renderParasolidText(panel, text, extension, ctx) {
|
|
|
13856
14970
|
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";
|
|
13857
14971
|
const meta = document.createElement("div");
|
|
13858
14972
|
meta.className = "ofv-cad-summary";
|
|
13859
|
-
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
14973
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14974
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14975
|
+
appendMeta6(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
|
|
14976
|
+
appendMeta6(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
|
|
13863
14977
|
const typeList = createCadTypeList(typeCounts);
|
|
13864
14978
|
section.append(note, meta, typeList);
|
|
13865
14979
|
let viewer;
|
|
@@ -13967,23 +15081,23 @@ function renderLayoutPreview(panel, data, ctx) {
|
|
|
13967
15081
|
summary.setAttribute("aria-hidden", "true");
|
|
13968
15082
|
summary.style.display = "none";
|
|
13969
15083
|
}
|
|
13970
|
-
|
|
13971
|
-
|
|
15084
|
+
appendMeta6(summary, "\u6587\u4EF6", data.fileName);
|
|
15085
|
+
appendMeta6(summary, "\u683C\u5F0F", data.format);
|
|
13972
15086
|
if (data.libraryName) {
|
|
13973
|
-
|
|
15087
|
+
appendMeta6(summary, "\u5E93", data.libraryName);
|
|
13974
15088
|
}
|
|
13975
15089
|
if (data.version) {
|
|
13976
|
-
|
|
15090
|
+
appendMeta6(summary, "\u7248\u672C", data.version);
|
|
13977
15091
|
}
|
|
13978
15092
|
if (data.unit) {
|
|
13979
|
-
|
|
15093
|
+
appendMeta6(summary, "\u5355\u4F4D", data.unit);
|
|
13980
15094
|
}
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
15095
|
+
appendMeta6(summary, "Cell", data.cells.length);
|
|
15096
|
+
appendMeta6(summary, "\u51E0\u4F55", data.shapes.length);
|
|
15097
|
+
appendMeta6(summary, "\u5F15\u7528", data.references.length);
|
|
15098
|
+
appendMeta6(summary, "\u6587\u5B57", data.labels.length);
|
|
13985
15099
|
for (const [label, value] of data.metadata) {
|
|
13986
|
-
|
|
15100
|
+
appendMeta6(summary, label, value);
|
|
13987
15101
|
}
|
|
13988
15102
|
section.append(summary);
|
|
13989
15103
|
for (const noteText of [...data.notes, ...data.warnings]) {
|
|
@@ -14589,12 +15703,12 @@ function renderBinaryCad(panel, bytes, extension, fileName) {
|
|
|
14589
15703
|
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";
|
|
14590
15704
|
const meta = document.createElement("div");
|
|
14591
15705
|
meta.className = "ofv-cad-summary";
|
|
14592
|
-
|
|
14593
|
-
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
15706
|
+
appendMeta6(meta, "\u6587\u4EF6", fileName);
|
|
15707
|
+
appendMeta6(meta, "\u683C\u5F0F", extension.toUpperCase());
|
|
15708
|
+
appendMeta6(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
|
|
15709
|
+
appendMeta6(meta, "\u7B7E\u540D", byteSignature2(bytes));
|
|
15710
|
+
appendMeta6(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
|
|
15711
|
+
appendMeta6(meta, "\u5BB9\u5668", detectCadContainer(bytes));
|
|
14598
15712
|
const actions = document.createElement("div");
|
|
14599
15713
|
actions.className = "ofv-cad-conversion";
|
|
14600
15714
|
const actionTitle = document.createElement("h4");
|
|
@@ -14634,12 +15748,12 @@ function createBinaryCadProbe(bytes, extension) {
|
|
|
14634
15748
|
summary.textContent = "\u4E8C\u8FDB\u5236\u7ED3\u6784\u63A2\u6D4B";
|
|
14635
15749
|
const meta = document.createElement("div");
|
|
14636
15750
|
meta.className = "ofv-archive-probe-meta";
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
15751
|
+
appendMeta6(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
|
|
15752
|
+
appendMeta6(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
|
|
15753
|
+
appendMeta6(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
|
|
15754
|
+
appendMeta6(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
|
|
15755
|
+
appendMeta6(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
|
|
15756
|
+
appendMeta6(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
|
|
14643
15757
|
details.append(summary, meta);
|
|
14644
15758
|
const hints = [...probe.layerHints, ...probe.blockHints, ...probe.externalRefs].slice(0, 18);
|
|
14645
15759
|
if (hints.length > 0) {
|
|
@@ -15172,9 +16286,9 @@ function createUnsupportedCadSection(extension, fileName) {
|
|
|
15172
16286
|
const section = createSection("CAD \u589E\u5F3A\u63A5\u5165\u63D0\u793A");
|
|
15173
16287
|
const meta = document.createElement("div");
|
|
15174
16288
|
meta.className = "ofv-cad-summary";
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
16289
|
+
appendMeta6(meta, "\u6587\u4EF6", fileName);
|
|
16290
|
+
appendMeta6(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
|
|
16291
|
+
appendMeta6(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
|
|
15178
16292
|
const note = document.createElement("p");
|
|
15179
16293
|
note.textContent = unsupportedCadGuidance(extension);
|
|
15180
16294
|
const actions = document.createElement("div");
|
|
@@ -15287,7 +16401,7 @@ function countBy(values) {
|
|
|
15287
16401
|
}
|
|
15288
16402
|
return counts;
|
|
15289
16403
|
}
|
|
15290
|
-
function
|
|
16404
|
+
function appendMeta6(parent, label, value) {
|
|
15291
16405
|
const row = document.createElement("div");
|
|
15292
16406
|
row.className = "ofv-meta-row";
|
|
15293
16407
|
const key = document.createElement("span");
|
|
@@ -17321,10 +18435,10 @@ function read255UInt16(bytes, offset) {
|
|
|
17321
18435
|
return { value: code, offset };
|
|
17322
18436
|
}
|
|
17323
18437
|
function decodeEotString(bytes) {
|
|
17324
|
-
const text =
|
|
18438
|
+
const text = decodeUtf16Le2(bytes).replace(/\0+$/g, "").trim();
|
|
17325
18439
|
return text || new TextDecoder("latin1").decode(bytes).replace(/\0+$/g, "").trim();
|
|
17326
18440
|
}
|
|
17327
|
-
function
|
|
18441
|
+
function decodeUtf16Le2(bytes) {
|
|
17328
18442
|
let value = "";
|
|
17329
18443
|
for (let index = 0; index + 1 < bytes.length; index += 2) {
|
|
17330
18444
|
value += String.fromCharCode(bytes[index] | bytes[index + 1] << 8);
|