@open-file-viewer/core 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1154 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1154 -51
- package/dist/index.js.map +1 -1
- package/dist/style.css +311 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5923,6 +5923,1100 @@ function decodeXml(value) {
|
|
|
5923
5923
|
// src/plugins/office.ts
|
|
5924
5924
|
var import_jszip3 = __toESM(require("jszip"), 1);
|
|
5925
5925
|
var import_dompurify2 = __toESM(require("dompurify"), 1);
|
|
5926
|
+
|
|
5927
|
+
// src/plugins/msdoc.ts
|
|
5928
|
+
var CFB_SIGNATURE = [208, 207, 17, 224, 161, 177, 26, 225];
|
|
5929
|
+
var FREE_SECTOR = 4294967295;
|
|
5930
|
+
var END_OF_CHAIN = 4294967294;
|
|
5931
|
+
var FAT_SECTOR = 4294967293;
|
|
5932
|
+
var DIFAT_SECTOR = 4294967292;
|
|
5933
|
+
var MINI_STREAM_CUTOFF = 4096;
|
|
5934
|
+
var STSH_FC_LCB_INDEX = 1;
|
|
5935
|
+
var CLX_FC_LCB_INDEX = 33;
|
|
5936
|
+
var WORD_PAGE_BREAK = "\f";
|
|
5937
|
+
function parseLegacyWordDocument(input) {
|
|
5938
|
+
const cfb = parseCompoundFile(new Uint8Array(input));
|
|
5939
|
+
const wordDocument = cfb.getStream("WordDocument");
|
|
5940
|
+
if (!wordDocument) {
|
|
5941
|
+
throw new Error("\u672A\u627E\u5230 WordDocument \u6D41");
|
|
5942
|
+
}
|
|
5943
|
+
const fib = parseFib(wordDocument);
|
|
5944
|
+
if (fib.encrypted) {
|
|
5945
|
+
throw new Error("\u6682\u4E0D\u652F\u6301\u52A0\u5BC6\u7684 .doc \u6587\u4EF6");
|
|
5946
|
+
}
|
|
5947
|
+
const tableStreamName = fib.useOneTable ? "1Table" : "0Table";
|
|
5948
|
+
const tableStream = cfb.getStream(tableStreamName);
|
|
5949
|
+
if (!tableStream) {
|
|
5950
|
+
throw new Error(`\u672A\u627E\u5230 ${tableStreamName} \u8868\u6D41`);
|
|
5951
|
+
}
|
|
5952
|
+
const assets = extractImageAssets(cfb);
|
|
5953
|
+
const styles = parseStyleTable(tableStream, fib);
|
|
5954
|
+
const pieces = parseClxPieces(tableStream, fib.fcClx, fib.lcbClx);
|
|
5955
|
+
const text = pieces.length > 0 ? readPieceTableText(wordDocument, pieces, fib.ccpText) : readFibTextFallback(wordDocument, fib);
|
|
5956
|
+
const paragraphs = splitWordParagraphs(text);
|
|
5957
|
+
if (paragraphs.length === 0) {
|
|
5958
|
+
throw new Error("\u672A\u89E3\u6790\u5230\u53EF\u663E\u793A\u7684\u6B63\u6587\u6BB5\u843D");
|
|
5959
|
+
}
|
|
5960
|
+
const bodyParagraphs = removeTrailingFooterArtifacts(paragraphs);
|
|
5961
|
+
const blocks = buildWordBlocks(bodyParagraphs);
|
|
5962
|
+
const layout = inferLayoutHints(paragraphs, assets);
|
|
5963
|
+
return {
|
|
5964
|
+
title: inferDocumentTitle(paragraphs),
|
|
5965
|
+
paragraphs: bodyParagraphs,
|
|
5966
|
+
blocks,
|
|
5967
|
+
layout,
|
|
5968
|
+
assets,
|
|
5969
|
+
styles,
|
|
5970
|
+
stats: {
|
|
5971
|
+
streamCount: cfb.entries.length,
|
|
5972
|
+
pieceCount: pieces.length,
|
|
5973
|
+
characterCount: bodyParagraphs.join("\n").length,
|
|
5974
|
+
styleCount: styles.length,
|
|
5975
|
+
tableStream: tableStreamName
|
|
5976
|
+
},
|
|
5977
|
+
warnings: pieces.length === 0 ? ["\u672A\u627E\u5230 CLX piece table\uFF0C\u5DF2\u6309 FIB \u6587\u672C\u533A\u95F4\u5C1D\u8BD5\u6062\u590D\u6B63\u6587\u3002"] : []
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
function renderLegacyWordDocument(panel, document2) {
|
|
5981
|
+
panel.replaceChildren();
|
|
5982
|
+
const article = window.document.createElement("article");
|
|
5983
|
+
article.className = "ofv-msdoc-document";
|
|
5984
|
+
const pages = paginateWordBlocks(document2.blocks.slice(0, 600), document2.layout);
|
|
5985
|
+
const pageCount = inferDisplayedPageCount(document2.blocks, pages.length);
|
|
5986
|
+
const page = window.document.createElement("section");
|
|
5987
|
+
page.className = "ofv-msdoc-page";
|
|
5988
|
+
appendPageChrome(page, document2, 1, pageCount);
|
|
5989
|
+
const meta = window.document.createElement("dl");
|
|
5990
|
+
meta.className = "ofv-msdoc-meta";
|
|
5991
|
+
appendMeta4(meta, "\u683C\u5F0F", "Word 97-2003 Binary");
|
|
5992
|
+
appendMeta4(meta, "\u6B63\u6587\u6BB5\u843D", `${document2.paragraphs.length}`);
|
|
5993
|
+
appendMeta4(meta, "Piece Table", `${document2.stats.pieceCount || 0} \u6BB5`);
|
|
5994
|
+
appendMeta4(meta, "\u6837\u5F0F\u8868", `${document2.stats.styleCount || 0} \u4E2A\u6837\u5F0F`);
|
|
5995
|
+
appendMeta4(meta, "\u8868\u6D41", document2.stats.tableStream);
|
|
5996
|
+
if (document2.styles.length > 0) {
|
|
5997
|
+
appendMeta4(meta, "\u6837\u5F0F\u540D\u79F0", document2.styles.slice(0, 30).map((style) => style.name).join("\u3001"));
|
|
5998
|
+
}
|
|
5999
|
+
meta.hidden = true;
|
|
6000
|
+
page.append(meta);
|
|
6001
|
+
appendBlocksToPage(page, pages[0] || [], document2.layout);
|
|
6002
|
+
appendWarnings(page, document2);
|
|
6003
|
+
article.append(page);
|
|
6004
|
+
for (const pageBlocks of pages.slice(1)) {
|
|
6005
|
+
const nextPage = window.document.createElement("section");
|
|
6006
|
+
nextPage.className = "ofv-msdoc-page";
|
|
6007
|
+
appendPageChrome(nextPage, document2, article.children.length + 1, pageCount);
|
|
6008
|
+
appendBlocksToPage(nextPage, pageBlocks, document2.layout);
|
|
6009
|
+
article.append(nextPage);
|
|
6010
|
+
}
|
|
6011
|
+
panel.append(article);
|
|
6012
|
+
}
|
|
6013
|
+
function inferDisplayedPageCount(blocks, renderedPageCount) {
|
|
6014
|
+
const tocPageNumbers = blocks.filter((block) => block.type === "toc" && Boolean(block.page)).map((block) => Number.parseInt(block.page || "", 10)).filter((page) => Number.isFinite(page) && page > 0);
|
|
6015
|
+
if (tocPageNumbers.length === 0) {
|
|
6016
|
+
return renderedPageCount;
|
|
6017
|
+
}
|
|
6018
|
+
return Math.max(renderedPageCount, ...tocPageNumbers);
|
|
6019
|
+
}
|
|
6020
|
+
function appendPageChrome(page, document2, pageNumber, pageCount) {
|
|
6021
|
+
if (document2.layout.lineNumbers) {
|
|
6022
|
+
page.classList.add("ofv-msdoc-line-numbered");
|
|
6023
|
+
}
|
|
6024
|
+
page.setAttribute("aria-label", document2.title || "Word \u6587\u6863");
|
|
6025
|
+
if (document2.layout.headerBrand === "oasis") {
|
|
6026
|
+
page.append(createOasisHeader(document2.assets.find((asset) => asset.id === document2.layout.headerImageId)));
|
|
6027
|
+
}
|
|
6028
|
+
if (document2.layout.footer) {
|
|
6029
|
+
page.append(createPageFooter(document2.layout.footer, pageNumber, pageCount));
|
|
6030
|
+
}
|
|
6031
|
+
}
|
|
6032
|
+
function appendBlocksToPage(page, blocks, layout) {
|
|
6033
|
+
let lineNumber = 1;
|
|
6034
|
+
for (const block of blocks) {
|
|
6035
|
+
if (block.type === "pageBreak") {
|
|
6036
|
+
continue;
|
|
6037
|
+
}
|
|
6038
|
+
const element = renderWordBlock(block);
|
|
6039
|
+
if (layout.lineNumbers && element instanceof HTMLElement && !element.classList.contains("ofv-msdoc-page-header")) {
|
|
6040
|
+
element.dataset.line = String(lineNumber);
|
|
6041
|
+
lineNumber += estimatedLineCount(block);
|
|
6042
|
+
}
|
|
6043
|
+
page.append(element);
|
|
6044
|
+
}
|
|
6045
|
+
}
|
|
6046
|
+
function appendWarnings(page, document2) {
|
|
6047
|
+
if (document2.warnings.length === 0) {
|
|
6048
|
+
return;
|
|
6049
|
+
}
|
|
6050
|
+
const warning = window.document.createElement("p");
|
|
6051
|
+
warning.className = "ofv-msdoc-warning";
|
|
6052
|
+
warning.textContent = document2.warnings.join(" ");
|
|
6053
|
+
warning.hidden = true;
|
|
6054
|
+
page.append(warning);
|
|
6055
|
+
}
|
|
6056
|
+
function createOasisHeader(image) {
|
|
6057
|
+
const header = window.document.createElement("header");
|
|
6058
|
+
header.className = "ofv-msdoc-page-header ofv-msdoc-oasis-header";
|
|
6059
|
+
const logo = image ? createImageLogo(image) : createFallbackOasisLogo();
|
|
6060
|
+
header.append(logo);
|
|
6061
|
+
return header;
|
|
6062
|
+
}
|
|
6063
|
+
function createImageLogo(image) {
|
|
6064
|
+
const wrapper = window.document.createElement("div");
|
|
6065
|
+
wrapper.className = "ofv-msdoc-oasis-logo ofv-msdoc-oasis-logo-image";
|
|
6066
|
+
const img = window.document.createElement("img");
|
|
6067
|
+
img.src = image.dataUrl;
|
|
6068
|
+
img.alt = "OASIS";
|
|
6069
|
+
if (image.width) {
|
|
6070
|
+
img.width = image.width;
|
|
6071
|
+
}
|
|
6072
|
+
if (image.height) {
|
|
6073
|
+
img.height = image.height;
|
|
6074
|
+
}
|
|
6075
|
+
wrapper.append(img);
|
|
6076
|
+
return wrapper;
|
|
6077
|
+
}
|
|
6078
|
+
function createFallbackOasisLogo() {
|
|
6079
|
+
const logo = window.document.createElement("div");
|
|
6080
|
+
logo.className = "ofv-msdoc-oasis-logo";
|
|
6081
|
+
const word = window.document.createElement("span");
|
|
6082
|
+
word.textContent = "OASIS";
|
|
6083
|
+
const mark = window.document.createElement("span");
|
|
6084
|
+
mark.className = "ofv-msdoc-oasis-mark";
|
|
6085
|
+
mark.setAttribute("aria-hidden", "true");
|
|
6086
|
+
logo.append(word, mark);
|
|
6087
|
+
return logo;
|
|
6088
|
+
}
|
|
6089
|
+
function createPageFooter(footer, pageNumber, pageCount) {
|
|
6090
|
+
const element = window.document.createElement("footer");
|
|
6091
|
+
element.className = "ofv-msdoc-page-footer";
|
|
6092
|
+
const top = window.document.createElement("div");
|
|
6093
|
+
top.className = "ofv-msdoc-footer-row";
|
|
6094
|
+
const documentId = window.document.createElement("span");
|
|
6095
|
+
documentId.textContent = footer.documentId || "";
|
|
6096
|
+
const date = window.document.createElement("span");
|
|
6097
|
+
date.textContent = footer.date || "";
|
|
6098
|
+
top.append(documentId, date);
|
|
6099
|
+
const bottom = window.document.createElement("div");
|
|
6100
|
+
bottom.className = "ofv-msdoc-footer-row";
|
|
6101
|
+
const copyright = window.document.createElement("span");
|
|
6102
|
+
copyright.textContent = footer.copyright || "";
|
|
6103
|
+
const page = window.document.createElement("span");
|
|
6104
|
+
page.textContent = `Page ${pageNumber} of ${pageCount}`;
|
|
6105
|
+
bottom.append(copyright, page);
|
|
6106
|
+
element.append(top, bottom);
|
|
6107
|
+
return element;
|
|
6108
|
+
}
|
|
6109
|
+
function renderWordBlock(block) {
|
|
6110
|
+
if (block.type === "pageBreak") {
|
|
6111
|
+
const marker = window.document.createElement("span");
|
|
6112
|
+
marker.className = "ofv-msdoc-page-break";
|
|
6113
|
+
marker.hidden = true;
|
|
6114
|
+
return marker;
|
|
6115
|
+
}
|
|
6116
|
+
if (block.type === "table") {
|
|
6117
|
+
const table = window.document.createElement("table");
|
|
6118
|
+
table.className = "ofv-msdoc-table";
|
|
6119
|
+
const revisionColumnWidths = getRevisionTableColumnWidths(block.rows);
|
|
6120
|
+
if (revisionColumnWidths) {
|
|
6121
|
+
table.classList.add("ofv-msdoc-revision-table");
|
|
6122
|
+
const colgroup = window.document.createElement("colgroup");
|
|
6123
|
+
for (const width of revisionColumnWidths) {
|
|
6124
|
+
const col = window.document.createElement("col");
|
|
6125
|
+
col.style.width = `calc(${width}px * var(--ofv-office-zoom, 1))`;
|
|
6126
|
+
colgroup.append(col);
|
|
6127
|
+
}
|
|
6128
|
+
table.append(colgroup);
|
|
6129
|
+
}
|
|
6130
|
+
const tbody = window.document.createElement("tbody");
|
|
6131
|
+
for (const row of block.rows) {
|
|
6132
|
+
const tr = window.document.createElement("tr");
|
|
6133
|
+
const cellTag = row === block.rows[0] && block.rows.length > 1 ? "th" : "td";
|
|
6134
|
+
for (const cellText of row) {
|
|
6135
|
+
const cell = window.document.createElement(cellTag);
|
|
6136
|
+
cell.textContent = cellText;
|
|
6137
|
+
tr.append(cell);
|
|
6138
|
+
}
|
|
6139
|
+
tbody.append(tr);
|
|
6140
|
+
}
|
|
6141
|
+
table.append(tbody);
|
|
6142
|
+
return table;
|
|
6143
|
+
}
|
|
6144
|
+
if (block.type === "toc") {
|
|
6145
|
+
const paragraph2 = window.document.createElement("p");
|
|
6146
|
+
paragraph2.className = `ofv-msdoc-toc ofv-msdoc-toc-level-${block.level}`;
|
|
6147
|
+
const title = window.document.createElement("span");
|
|
6148
|
+
title.textContent = block.title;
|
|
6149
|
+
paragraph2.append(title);
|
|
6150
|
+
if (block.page) {
|
|
6151
|
+
const page = window.document.createElement("span");
|
|
6152
|
+
page.textContent = block.page;
|
|
6153
|
+
paragraph2.append(page);
|
|
6154
|
+
}
|
|
6155
|
+
return paragraph2;
|
|
6156
|
+
}
|
|
6157
|
+
const paragraph = window.document.createElement("p");
|
|
6158
|
+
const levelClass = block.type === "heading" ? ` ofv-msdoc-heading-level-${block.level}` : "";
|
|
6159
|
+
const listClass = block.type === "listItem" ? ` ofv-msdoc-list-level-${block.level}` : "";
|
|
6160
|
+
paragraph.className = `ofv-msdoc-${block.type}${levelClass}${listClass}${"indent" in block && block.indent ? " ofv-msdoc-indent" : ""}`;
|
|
6161
|
+
appendInlineRuns(paragraph, block.text, block.type === "code");
|
|
6162
|
+
return paragraph;
|
|
6163
|
+
}
|
|
6164
|
+
function appendInlineRuns(element, text, preserveTabs = false) {
|
|
6165
|
+
if (preserveTabs) {
|
|
6166
|
+
appendInlineText(element, text, true);
|
|
6167
|
+
return;
|
|
6168
|
+
}
|
|
6169
|
+
const pattern = /(https?:\/\/\S+|[\w.+-]+@[\w.-]+\.[A-Za-z]{2,}|\[[^\]]+\]|<\/?[A-Za-z][A-Za-z0-9:-]*>|(?:\b(?:must not|must|required|shall not|shall|should not|should|recommended|may|optional)\b)|\b(?:attributeNames|DataType|OtherKeyword|variable)\b)/gi;
|
|
6170
|
+
let offset = 0;
|
|
6171
|
+
for (const match of text.matchAll(pattern)) {
|
|
6172
|
+
const value = match[0];
|
|
6173
|
+
const index = match.index || 0;
|
|
6174
|
+
if (index > offset) {
|
|
6175
|
+
appendInlineText(element, text.slice(offset, index), preserveTabs);
|
|
6176
|
+
}
|
|
6177
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
6178
|
+
appendBracketRun(element, value);
|
|
6179
|
+
} else if (isCodeStyleRun(value)) {
|
|
6180
|
+
const code = window.document.createElement("code");
|
|
6181
|
+
code.className = "ofv-msdoc-inline-code";
|
|
6182
|
+
code.textContent = value;
|
|
6183
|
+
element.append(code);
|
|
6184
|
+
} else if (isVariableStyleRun(value)) {
|
|
6185
|
+
const em = window.document.createElement("em");
|
|
6186
|
+
em.className = "ofv-msdoc-variable";
|
|
6187
|
+
em.textContent = value;
|
|
6188
|
+
element.append(em);
|
|
6189
|
+
} else if (isRequirementKeywordRun(value)) {
|
|
6190
|
+
const em = window.document.createElement("em");
|
|
6191
|
+
em.className = "ofv-msdoc-keyword";
|
|
6192
|
+
em.textContent = value;
|
|
6193
|
+
element.append(em);
|
|
6194
|
+
} else {
|
|
6195
|
+
const link = splitLinkRun(value);
|
|
6196
|
+
const anchor = window.document.createElement("a");
|
|
6197
|
+
anchor.className = "ofv-msdoc-link-text";
|
|
6198
|
+
anchor.href = link.href;
|
|
6199
|
+
anchor.target = "_blank";
|
|
6200
|
+
anchor.rel = "noreferrer noopener";
|
|
6201
|
+
anchor.textContent = link.text;
|
|
6202
|
+
element.append(anchor);
|
|
6203
|
+
if (link.trailing) {
|
|
6204
|
+
appendInlineText(element, link.trailing, preserveTabs);
|
|
6205
|
+
}
|
|
6206
|
+
}
|
|
6207
|
+
offset = index + value.length;
|
|
6208
|
+
}
|
|
6209
|
+
if (offset < text.length) {
|
|
6210
|
+
appendInlineText(element, text.slice(offset), preserveTabs);
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
function appendBracketRun(element, value) {
|
|
6214
|
+
const tagName = isReferenceTerm(value) ? "strong" : "em";
|
|
6215
|
+
const run = window.document.createElement(tagName);
|
|
6216
|
+
run.className = isReferenceTerm(value) ? "ofv-msdoc-ref-term" : "ofv-msdoc-instruction-run";
|
|
6217
|
+
run.textContent = value;
|
|
6218
|
+
element.append(run);
|
|
6219
|
+
}
|
|
6220
|
+
function getRevisionTableColumnWidths(rows) {
|
|
6221
|
+
const header = rows[0]?.map((cell) => cell.toLowerCase());
|
|
6222
|
+
if (!header || header.length !== 4) {
|
|
6223
|
+
return void 0;
|
|
6224
|
+
}
|
|
6225
|
+
if (header[0] === "rev" && header[1] === "date" && /whom/.test(header[2]) && header[3] === "what") {
|
|
6226
|
+
return [59, 81, 106, 191];
|
|
6227
|
+
}
|
|
6228
|
+
return void 0;
|
|
6229
|
+
}
|
|
6230
|
+
function appendInlineText(element, text, preserveTabs) {
|
|
6231
|
+
element.append(window.document.createTextNode(preserveTabs ? text : text.replace(/\t+/g, " ")));
|
|
6232
|
+
}
|
|
6233
|
+
function isReferenceTerm(value) {
|
|
6234
|
+
return /^\[[A-Z0-9][A-Z0-9.-]{1,24}\]$/.test(value);
|
|
6235
|
+
}
|
|
6236
|
+
function isCodeStyleRun(value) {
|
|
6237
|
+
return /^<\/?[A-Za-z][A-Za-z0-9:-]*>$/.test(value) || /^(?:attributeNames|DataType|OtherKeyword)$/.test(value);
|
|
6238
|
+
}
|
|
6239
|
+
function isVariableStyleRun(value) {
|
|
6240
|
+
return value === "variable";
|
|
6241
|
+
}
|
|
6242
|
+
function isRequirementKeywordRun(value) {
|
|
6243
|
+
return /^(?:must not|must|required|shall not|shall|should not|should|recommended|may|optional)$/i.test(value);
|
|
6244
|
+
}
|
|
6245
|
+
function splitLinkRun(value) {
|
|
6246
|
+
let text = value;
|
|
6247
|
+
let trailing = "";
|
|
6248
|
+
while (/[),.;:]$/.test(text)) {
|
|
6249
|
+
trailing = text.slice(-1) + trailing;
|
|
6250
|
+
text = text.slice(0, -1);
|
|
6251
|
+
}
|
|
6252
|
+
const href = /^https?:\/\//i.test(text) ? text : `mailto:${text}`;
|
|
6253
|
+
return { text, href, trailing };
|
|
6254
|
+
}
|
|
6255
|
+
function extractImageAssets(cfb) {
|
|
6256
|
+
const assets = [];
|
|
6257
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6258
|
+
for (const entry of cfb.entries) {
|
|
6259
|
+
if (entry.type !== 2) {
|
|
6260
|
+
continue;
|
|
6261
|
+
}
|
|
6262
|
+
const stream = cfb.getStream(entry.name);
|
|
6263
|
+
if (!stream || stream.length < 16) {
|
|
6264
|
+
continue;
|
|
6265
|
+
}
|
|
6266
|
+
for (const image of extractImagesFromBytes(stream, entry.name)) {
|
|
6267
|
+
const key = `${image.mimeType}:${image.bytes.length}:${image.bytes[0]}:${image.bytes[image.bytes.length - 1]}`;
|
|
6268
|
+
if (seen.has(key)) {
|
|
6269
|
+
continue;
|
|
6270
|
+
}
|
|
6271
|
+
seen.add(key);
|
|
6272
|
+
const id = `image-${assets.length + 1}`;
|
|
6273
|
+
assets.push({
|
|
6274
|
+
id,
|
|
6275
|
+
kind: "image",
|
|
6276
|
+
mimeType: image.mimeType,
|
|
6277
|
+
dataUrl: `data:${image.mimeType};base64,${bytesToBase64(image.bytes)}`,
|
|
6278
|
+
width: image.width,
|
|
6279
|
+
height: image.height
|
|
6280
|
+
});
|
|
6281
|
+
}
|
|
6282
|
+
}
|
|
6283
|
+
return assets;
|
|
6284
|
+
}
|
|
6285
|
+
function parseStyleTable(tableStream, fib) {
|
|
6286
|
+
if (fib.lcbStshf <= 0 || fib.fcStshf < 0 || fib.fcStshf >= tableStream.length) {
|
|
6287
|
+
return [];
|
|
6288
|
+
}
|
|
6289
|
+
const bytes = tableStream.subarray(fib.fcStshf, Math.min(tableStream.length, fib.fcStshf + fib.lcbStshf));
|
|
6290
|
+
if (bytes.length < 8) {
|
|
6291
|
+
return [];
|
|
6292
|
+
}
|
|
6293
|
+
const view3 = dataView2(bytes);
|
|
6294
|
+
const cbStshi = view3.getUint16(0, true);
|
|
6295
|
+
const stshiOffset = 2;
|
|
6296
|
+
const cstd = stshiOffset + 2 <= bytes.length ? view3.getUint16(stshiOffset, true) : 0;
|
|
6297
|
+
const cbSTDBaseInFile = stshiOffset + 4 <= bytes.length ? view3.getUint16(stshiOffset + 2, true) : 10;
|
|
6298
|
+
let offset = 2 + cbStshi;
|
|
6299
|
+
const styles = [];
|
|
6300
|
+
for (let id = 0; id < cstd && offset + 2 <= bytes.length; id += 1) {
|
|
6301
|
+
const cbStd = view3.getUint16(offset, true);
|
|
6302
|
+
const stdStart = offset + 2;
|
|
6303
|
+
const stdEnd = stdStart + cbStd;
|
|
6304
|
+
if (cbStd > 0 && stdStart < bytes.length) {
|
|
6305
|
+
const style = parseStyleDefinition(bytes.subarray(stdStart, Math.min(stdEnd, bytes.length)), Math.max(10, cbSTDBaseInFile), id);
|
|
6306
|
+
if (style.name) {
|
|
6307
|
+
styles.push(style);
|
|
6308
|
+
}
|
|
6309
|
+
}
|
|
6310
|
+
offset = alignEven(stdEnd);
|
|
6311
|
+
}
|
|
6312
|
+
return styles;
|
|
6313
|
+
}
|
|
6314
|
+
function parseStyleDefinition(bytes, baseSize, id) {
|
|
6315
|
+
const base = bytes.length >= 6 ? parseStyleBase(bytes) : void 0;
|
|
6316
|
+
const nameOffset = Math.min(bytes.length, Math.max(10, baseSize));
|
|
6317
|
+
const name = parseXstz(bytes, nameOffset);
|
|
6318
|
+
return {
|
|
6319
|
+
id,
|
|
6320
|
+
name,
|
|
6321
|
+
type: styleTypeFromStk(base?.stk),
|
|
6322
|
+
basedOn: base?.basedOn,
|
|
6323
|
+
next: base?.next
|
|
6324
|
+
};
|
|
6325
|
+
}
|
|
6326
|
+
function parseStyleBase(bytes) {
|
|
6327
|
+
const view3 = dataView2(bytes);
|
|
6328
|
+
const w2 = view3.getUint16(2, true);
|
|
6329
|
+
const w3 = view3.getUint16(4, true);
|
|
6330
|
+
return {
|
|
6331
|
+
stk: w2 & 15,
|
|
6332
|
+
basedOn: w2 >> 4 & 4095,
|
|
6333
|
+
next: w3 >> 4 & 4095
|
|
6334
|
+
};
|
|
6335
|
+
}
|
|
6336
|
+
function styleTypeFromStk(stk) {
|
|
6337
|
+
if (stk === 1) {
|
|
6338
|
+
return "paragraph";
|
|
6339
|
+
}
|
|
6340
|
+
if (stk === 2) {
|
|
6341
|
+
return "character";
|
|
6342
|
+
}
|
|
6343
|
+
if (stk === 3) {
|
|
6344
|
+
return "table";
|
|
6345
|
+
}
|
|
6346
|
+
if (stk === 4) {
|
|
6347
|
+
return "numbering";
|
|
6348
|
+
}
|
|
6349
|
+
return "unknown";
|
|
6350
|
+
}
|
|
6351
|
+
function parseXstz(bytes, offset) {
|
|
6352
|
+
if (offset + 2 > bytes.length) {
|
|
6353
|
+
return "";
|
|
6354
|
+
}
|
|
6355
|
+
const view3 = dataView2(bytes);
|
|
6356
|
+
const charCount = view3.getUint16(offset, true);
|
|
6357
|
+
const start = offset + 2;
|
|
6358
|
+
const end = Math.min(bytes.length, start + charCount * 2);
|
|
6359
|
+
if (end <= start) {
|
|
6360
|
+
return "";
|
|
6361
|
+
}
|
|
6362
|
+
return decodeUtf16Le(bytes.subarray(start, end)).replace(/\0+$/g, "");
|
|
6363
|
+
}
|
|
6364
|
+
function extractImagesFromBytes(bytes, sourceName) {
|
|
6365
|
+
const images = [];
|
|
6366
|
+
for (const start of findSignatureOffsets(bytes, PNG_SIGNATURE)) {
|
|
6367
|
+
const end = findPngEnd(bytes, start);
|
|
6368
|
+
if (end > start) {
|
|
6369
|
+
const imageBytes = bytes.slice(start, end);
|
|
6370
|
+
const dimensions = readPngDimensions(imageBytes);
|
|
6371
|
+
images.push({ bytes: imageBytes, mimeType: "image/png", width: dimensions?.width, height: dimensions?.height });
|
|
6372
|
+
}
|
|
6373
|
+
}
|
|
6374
|
+
for (const start of findSignatureOffsets(bytes, JPEG_SIGNATURE)) {
|
|
6375
|
+
const end = findJpegEnd(bytes, start);
|
|
6376
|
+
if (end > start) {
|
|
6377
|
+
images.push({ bytes: bytes.slice(start, end), mimeType: "image/jpeg" });
|
|
6378
|
+
}
|
|
6379
|
+
}
|
|
6380
|
+
if (/picture|image|data/i.test(sourceName)) {
|
|
6381
|
+
const gifStart = bytes.findIndex((byte, index) => index + 4 <= bytes.length && bytes[index] === 71 && bytes[index + 1] === 73 && bytes[index + 2] === 70 && bytes[index + 3] === 56);
|
|
6382
|
+
if (gifStart >= 0) {
|
|
6383
|
+
images.push({ bytes: bytes.slice(gifStart), mimeType: "image/gif" });
|
|
6384
|
+
}
|
|
6385
|
+
}
|
|
6386
|
+
return images;
|
|
6387
|
+
}
|
|
6388
|
+
var PNG_SIGNATURE = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
6389
|
+
var JPEG_SIGNATURE = Uint8Array.from([255, 216, 255]);
|
|
6390
|
+
function findSignatureOffsets(bytes, signature) {
|
|
6391
|
+
const offsets = [];
|
|
6392
|
+
for (let index = 0; index <= bytes.length - signature.length; index += 1) {
|
|
6393
|
+
let matches = true;
|
|
6394
|
+
for (let sigIndex = 0; sigIndex < signature.length; sigIndex += 1) {
|
|
6395
|
+
if (bytes[index + sigIndex] !== signature[sigIndex]) {
|
|
6396
|
+
matches = false;
|
|
6397
|
+
break;
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
if (matches) {
|
|
6401
|
+
offsets.push(index);
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
return offsets;
|
|
6405
|
+
}
|
|
6406
|
+
function findPngEnd(bytes, start) {
|
|
6407
|
+
for (let offset = start + PNG_SIGNATURE.length; offset + 12 <= bytes.length; ) {
|
|
6408
|
+
const length = readUint32Be4(bytes, offset);
|
|
6409
|
+
const typeOffset = offset + 4;
|
|
6410
|
+
const next = offset + 12 + length;
|
|
6411
|
+
if (next > bytes.length) {
|
|
6412
|
+
return 0;
|
|
6413
|
+
}
|
|
6414
|
+
if (bytes[typeOffset] === 73 && bytes[typeOffset + 1] === 69 && bytes[typeOffset + 2] === 78 && bytes[typeOffset + 3] === 68) {
|
|
6415
|
+
return next;
|
|
6416
|
+
}
|
|
6417
|
+
offset = next;
|
|
6418
|
+
}
|
|
6419
|
+
return 0;
|
|
6420
|
+
}
|
|
6421
|
+
function findJpegEnd(bytes, start) {
|
|
6422
|
+
for (let index = start + 2; index + 1 < bytes.length; index += 1) {
|
|
6423
|
+
if (bytes[index] === 255 && bytes[index + 1] === 217) {
|
|
6424
|
+
return index + 2;
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
return 0;
|
|
6428
|
+
}
|
|
6429
|
+
function readPngDimensions(bytes) {
|
|
6430
|
+
if (bytes.length < 24 || !PNG_SIGNATURE.every((value, index) => bytes[index] === value)) {
|
|
6431
|
+
return void 0;
|
|
6432
|
+
}
|
|
6433
|
+
return {
|
|
6434
|
+
width: readUint32Be4(bytes, 16),
|
|
6435
|
+
height: readUint32Be4(bytes, 20)
|
|
6436
|
+
};
|
|
6437
|
+
}
|
|
6438
|
+
function readUint32Be4(bytes, offset) {
|
|
6439
|
+
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
6440
|
+
}
|
|
6441
|
+
function bytesToBase64(bytes) {
|
|
6442
|
+
let binary = "";
|
|
6443
|
+
const chunkSize = 32768;
|
|
6444
|
+
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
|
|
6445
|
+
binary += String.fromCharCode(...bytes.subarray(offset, Math.min(bytes.length, offset + chunkSize)));
|
|
6446
|
+
}
|
|
6447
|
+
return btoa(binary);
|
|
6448
|
+
}
|
|
6449
|
+
function parseCompoundFile(bytes) {
|
|
6450
|
+
if (!hasCompoundSignature(bytes)) {
|
|
6451
|
+
throw new Error("\u4E0D\u662F\u6807\u51C6 OLE Compound File");
|
|
6452
|
+
}
|
|
6453
|
+
const view3 = dataView2(bytes);
|
|
6454
|
+
const sectorSize = 1 << view3.getUint16(30, true);
|
|
6455
|
+
const miniSectorSize = 1 << view3.getUint16(32, true);
|
|
6456
|
+
const fatSectorCount = view3.getUint32(44, true);
|
|
6457
|
+
const firstDirectorySector = view3.getUint32(48, true);
|
|
6458
|
+
const miniStreamCutoff = view3.getUint32(56, true) || MINI_STREAM_CUTOFF;
|
|
6459
|
+
const firstMiniFatSector = view3.getUint32(60, true);
|
|
6460
|
+
const miniFatSectorCount = view3.getUint32(64, true);
|
|
6461
|
+
const firstDifatSector = view3.getUint32(68, true);
|
|
6462
|
+
const difatSectorCount = view3.getUint32(72, true);
|
|
6463
|
+
const difat = readDifat(view3, sectorSize, firstDifatSector, difatSectorCount);
|
|
6464
|
+
const fat = readFat(view3, sectorSize, difat.slice(0, fatSectorCount));
|
|
6465
|
+
const directoryBytes = readRegularStream(bytes, sectorSize, fat, firstDirectorySector);
|
|
6466
|
+
const entries = parseDirectoryEntries(directoryBytes);
|
|
6467
|
+
const root = entries.find((entry) => entry.type === 5);
|
|
6468
|
+
const miniStream = root ? readRegularStream(bytes, sectorSize, fat, root.startSector, root.size) : new Uint8Array();
|
|
6469
|
+
const miniFat = firstMiniFatSector < END_OF_CHAIN ? readFat(view3, sectorSize, sectorChain(fat, firstMiniFatSector).slice(0, miniFatSectorCount)) : [];
|
|
6470
|
+
return {
|
|
6471
|
+
entries,
|
|
6472
|
+
getStream(name) {
|
|
6473
|
+
const wanted = normalizeStreamName(name);
|
|
6474
|
+
const entry = entries.find((item) => item.type === 2 && normalizeStreamName(item.name) === wanted);
|
|
6475
|
+
if (!entry) {
|
|
6476
|
+
return void 0;
|
|
6477
|
+
}
|
|
6478
|
+
if (entry.size < miniStreamCutoff && miniFat.length > 0) {
|
|
6479
|
+
return readMiniStream(miniStream, miniSectorSize, miniFat, entry.startSector, entry.size);
|
|
6480
|
+
}
|
|
6481
|
+
return readRegularStream(bytes, sectorSize, fat, entry.startSector, entry.size);
|
|
6482
|
+
}
|
|
6483
|
+
};
|
|
6484
|
+
}
|
|
6485
|
+
function hasCompoundSignature(bytes) {
|
|
6486
|
+
return CFB_SIGNATURE.every((value, index) => bytes[index] === value);
|
|
6487
|
+
}
|
|
6488
|
+
function readDifat(view3, sectorSize, firstDifatSector, difatSectorCount) {
|
|
6489
|
+
const difat = [];
|
|
6490
|
+
for (let offset = 76; offset < 512; offset += 4) {
|
|
6491
|
+
const sector = view3.getUint32(offset, true);
|
|
6492
|
+
if (isUsableSector(sector)) {
|
|
6493
|
+
difat.push(sector);
|
|
6494
|
+
}
|
|
6495
|
+
}
|
|
6496
|
+
let next = firstDifatSector;
|
|
6497
|
+
for (let index = 0; index < difatSectorCount && isUsableSector(next); index += 1) {
|
|
6498
|
+
const offset = sectorOffset(next, sectorSize);
|
|
6499
|
+
const entriesPerSector = sectorSize / 4 - 1;
|
|
6500
|
+
for (let item = 0; item < entriesPerSector; item += 1) {
|
|
6501
|
+
const sector = view3.getUint32(offset + item * 4, true);
|
|
6502
|
+
if (isUsableSector(sector)) {
|
|
6503
|
+
difat.push(sector);
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
next = view3.getUint32(offset + entriesPerSector * 4, true);
|
|
6507
|
+
}
|
|
6508
|
+
return difat;
|
|
6509
|
+
}
|
|
6510
|
+
function readFat(view3, sectorSize, sectors) {
|
|
6511
|
+
const fat = [];
|
|
6512
|
+
for (const sector of sectors) {
|
|
6513
|
+
if (!isUsableSector(sector) && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR) {
|
|
6514
|
+
continue;
|
|
6515
|
+
}
|
|
6516
|
+
const offset = sectorOffset(sector, sectorSize);
|
|
6517
|
+
for (let item = 0; item < sectorSize / 4; item += 1) {
|
|
6518
|
+
fat.push(view3.getUint32(offset + item * 4, true));
|
|
6519
|
+
}
|
|
6520
|
+
}
|
|
6521
|
+
return fat;
|
|
6522
|
+
}
|
|
6523
|
+
function parseDirectoryEntries(bytes) {
|
|
6524
|
+
const view3 = dataView2(bytes);
|
|
6525
|
+
const entries = [];
|
|
6526
|
+
for (let offset = 0; offset + 128 <= bytes.length; offset += 128) {
|
|
6527
|
+
const nameLength = view3.getUint16(offset + 64, true);
|
|
6528
|
+
const type = bytes[offset + 66] || 0;
|
|
6529
|
+
if (type === 0 || nameLength < 2) {
|
|
6530
|
+
continue;
|
|
6531
|
+
}
|
|
6532
|
+
const nameBytes = bytes.subarray(offset, offset + Math.max(0, nameLength - 2));
|
|
6533
|
+
const name = decodeUtf16Le(nameBytes).replace(/\0+$/g, "");
|
|
6534
|
+
const startSector = view3.getUint32(offset + 116, true);
|
|
6535
|
+
const lowSize = view3.getUint32(offset + 120, true);
|
|
6536
|
+
const highSize = view3.getUint32(offset + 124, true);
|
|
6537
|
+
const size = highSize > 0 ? Number(BigInt(highSize) << 32n) + lowSize : lowSize;
|
|
6538
|
+
entries.push({ name, type, startSector, size });
|
|
6539
|
+
}
|
|
6540
|
+
return entries;
|
|
6541
|
+
}
|
|
6542
|
+
function readRegularStream(bytes, sectorSize, fat, startSector, size) {
|
|
6543
|
+
const chunks = [];
|
|
6544
|
+
for (const sector of sectorChain(fat, startSector)) {
|
|
6545
|
+
const offset = sectorOffset(sector, sectorSize);
|
|
6546
|
+
chunks.push(bytes.subarray(offset, Math.min(bytes.length, offset + sectorSize)));
|
|
6547
|
+
}
|
|
6548
|
+
return concatChunks(chunks, size);
|
|
6549
|
+
}
|
|
6550
|
+
function readMiniStream(miniStream, miniSectorSize, miniFat, startSector, size) {
|
|
6551
|
+
const chunks = [];
|
|
6552
|
+
for (const sector of sectorChain(miniFat, startSector)) {
|
|
6553
|
+
const offset = sector * miniSectorSize;
|
|
6554
|
+
chunks.push(miniStream.subarray(offset, Math.min(miniStream.length, offset + miniSectorSize)));
|
|
6555
|
+
}
|
|
6556
|
+
return concatChunks(chunks, size);
|
|
6557
|
+
}
|
|
6558
|
+
function sectorChain(fat, startSector) {
|
|
6559
|
+
const chain = [];
|
|
6560
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6561
|
+
let current = startSector;
|
|
6562
|
+
while (isUsableSector(current) && current < fat.length && !seen.has(current)) {
|
|
6563
|
+
seen.add(current);
|
|
6564
|
+
chain.push(current);
|
|
6565
|
+
current = fat[current];
|
|
6566
|
+
}
|
|
6567
|
+
return chain;
|
|
6568
|
+
}
|
|
6569
|
+
function parseFib(wordDocument) {
|
|
6570
|
+
const view3 = dataView2(wordDocument);
|
|
6571
|
+
if (view3.getUint16(0, true) !== 42476) {
|
|
6572
|
+
throw new Error("WordDocument FIB \u6807\u8BC6\u65E0\u6548");
|
|
6573
|
+
}
|
|
6574
|
+
const flags = view3.getUint16(10, true);
|
|
6575
|
+
const fcMin = view3.getUint32(24, true);
|
|
6576
|
+
const fcMac = view3.getUint32(28, true);
|
|
6577
|
+
let offset = 32;
|
|
6578
|
+
const csw = view3.getUint16(offset, true);
|
|
6579
|
+
offset += 2 + csw * 2;
|
|
6580
|
+
const fibRgLwOffset = offset + 2;
|
|
6581
|
+
const cslw = view3.getUint16(offset, true);
|
|
6582
|
+
const ccpText = fibRgLwOffset + 16 <= wordDocument.length ? Math.max(0, view3.getInt32(fibRgLwOffset + 12, true)) : 0;
|
|
6583
|
+
offset += 2 + cslw * 4;
|
|
6584
|
+
const cbRgFcLcb = view3.getUint16(offset, true);
|
|
6585
|
+
const fcLcbOffset = offset + 2;
|
|
6586
|
+
const stshOffset = fcLcbOffset + STSH_FC_LCB_INDEX * 8;
|
|
6587
|
+
const clxOffset = fcLcbOffset + CLX_FC_LCB_INDEX * 8;
|
|
6588
|
+
return {
|
|
6589
|
+
encrypted: (flags & 256) !== 0,
|
|
6590
|
+
useOneTable: (flags & 512) !== 0,
|
|
6591
|
+
textIsUnicode: (flags & 4096) !== 0,
|
|
6592
|
+
fcMin,
|
|
6593
|
+
fcMac,
|
|
6594
|
+
ccpText,
|
|
6595
|
+
fcStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset, true) : 0,
|
|
6596
|
+
lcbStshf: STSH_FC_LCB_INDEX < cbRgFcLcb && stshOffset + 8 <= wordDocument.length ? view3.getUint32(stshOffset + 4, true) : 0,
|
|
6597
|
+
fcClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset, true) : 0,
|
|
6598
|
+
lcbClx: CLX_FC_LCB_INDEX < cbRgFcLcb && clxOffset + 8 <= wordDocument.length ? view3.getUint32(clxOffset + 4, true) : 0
|
|
6599
|
+
};
|
|
6600
|
+
}
|
|
6601
|
+
function parseClxPieces(tableStream, fcClx, lcbClx) {
|
|
6602
|
+
if (lcbClx <= 0 || fcClx < 0 || fcClx >= tableStream.length) {
|
|
6603
|
+
return [];
|
|
6604
|
+
}
|
|
6605
|
+
const end = Math.min(tableStream.length, fcClx + lcbClx);
|
|
6606
|
+
const view3 = dataView2(tableStream);
|
|
6607
|
+
let offset = fcClx;
|
|
6608
|
+
while (offset < end) {
|
|
6609
|
+
const marker = tableStream[offset];
|
|
6610
|
+
if (marker === 1) {
|
|
6611
|
+
const size = offset + 3 <= end ? view3.getUint16(offset + 1, true) : 0;
|
|
6612
|
+
offset += 3 + size;
|
|
6613
|
+
continue;
|
|
6614
|
+
}
|
|
6615
|
+
if (marker === 2) {
|
|
6616
|
+
if (offset + 5 > end) {
|
|
6617
|
+
break;
|
|
6618
|
+
}
|
|
6619
|
+
const plcSize = view3.getUint32(offset + 1, true);
|
|
6620
|
+
const plcOffset = offset + 5;
|
|
6621
|
+
return parsePlcPcd(tableStream, plcOffset, Math.min(end, plcOffset + plcSize));
|
|
6622
|
+
}
|
|
6623
|
+
offset += 1;
|
|
6624
|
+
}
|
|
6625
|
+
return [];
|
|
6626
|
+
}
|
|
6627
|
+
function parsePlcPcd(tableStream, offset, end) {
|
|
6628
|
+
const size = end - offset;
|
|
6629
|
+
if (size < 16 || (size - 4) % 12 !== 0) {
|
|
6630
|
+
return [];
|
|
6631
|
+
}
|
|
6632
|
+
const view3 = dataView2(tableStream);
|
|
6633
|
+
const pieceCount = Math.floor((size - 4) / 12);
|
|
6634
|
+
const pcdOffset = offset + (pieceCount + 1) * 4;
|
|
6635
|
+
const pieces = [];
|
|
6636
|
+
for (let index = 0; index < pieceCount; index += 1) {
|
|
6637
|
+
const cpStart = view3.getUint32(offset + index * 4, true);
|
|
6638
|
+
const cpEnd = view3.getUint32(offset + (index + 1) * 4, true);
|
|
6639
|
+
const descriptorOffset = pcdOffset + index * 8;
|
|
6640
|
+
const fcCompressed = view3.getUint32(descriptorOffset + 2, true);
|
|
6641
|
+
const compressed = (fcCompressed & 1073741824) !== 0;
|
|
6642
|
+
const fileOffset = compressed ? (fcCompressed & 1073741823) / 2 : fcCompressed;
|
|
6643
|
+
if (cpEnd > cpStart) {
|
|
6644
|
+
pieces.push({ cpStart, cpEnd, fileOffset, compressed });
|
|
6645
|
+
}
|
|
6646
|
+
}
|
|
6647
|
+
return pieces;
|
|
6648
|
+
}
|
|
6649
|
+
function readPieceTableText(wordDocument, pieces, ccpText) {
|
|
6650
|
+
let output = "";
|
|
6651
|
+
for (const piece of pieces) {
|
|
6652
|
+
const cpEnd = ccpText > 0 ? Math.min(piece.cpEnd, ccpText) : piece.cpEnd;
|
|
6653
|
+
const charCount = Math.max(0, cpEnd - piece.cpStart);
|
|
6654
|
+
if (charCount === 0) {
|
|
6655
|
+
continue;
|
|
6656
|
+
}
|
|
6657
|
+
const byteLength = charCount * (piece.compressed ? 1 : 2);
|
|
6658
|
+
const bytes = wordDocument.subarray(piece.fileOffset, Math.min(wordDocument.length, piece.fileOffset + byteLength));
|
|
6659
|
+
output += piece.compressed ? decodeWindows1252(bytes) : decodeUtf16Le(bytes);
|
|
6660
|
+
}
|
|
6661
|
+
return output;
|
|
6662
|
+
}
|
|
6663
|
+
function readFibTextFallback(wordDocument, fib) {
|
|
6664
|
+
const bytes = wordDocument.subarray(fib.fcMin, Math.min(wordDocument.length, fib.fcMac));
|
|
6665
|
+
return fib.textIsUnicode ? decodeUtf16Le(bytes) : decodeWindows1252(bytes);
|
|
6666
|
+
}
|
|
6667
|
+
function splitWordParagraphs(text) {
|
|
6668
|
+
const normalized = text.replace(/\u0000/g, "").replace(/\u0007/g, " ").replace(/\u000b/g, "\n");
|
|
6669
|
+
const paragraphs = [];
|
|
6670
|
+
for (const segment of normalized.split(/(\u000c)/)) {
|
|
6671
|
+
if (segment === "\f") {
|
|
6672
|
+
paragraphs.push(WORD_PAGE_BREAK);
|
|
6673
|
+
continue;
|
|
6674
|
+
}
|
|
6675
|
+
paragraphs.push(
|
|
6676
|
+
...segment.split(/\r|\n{2,}/).map((paragraph) => cleanWordText(paragraph)).filter((paragraph) => paragraph.length > 0 && isDisplayableParagraph(paragraph))
|
|
6677
|
+
);
|
|
6678
|
+
}
|
|
6679
|
+
return paragraphs.slice(0, 1e3);
|
|
6680
|
+
}
|
|
6681
|
+
function removeTrailingFooterArtifacts(paragraphs) {
|
|
6682
|
+
const tailStart = Math.max(0, paragraphs.length - 32);
|
|
6683
|
+
const tail = paragraphs.slice(tailStart);
|
|
6684
|
+
const relativePageFieldIndex = tail.findIndex(isFooterPageField);
|
|
6685
|
+
if (relativePageFieldIndex < 0) {
|
|
6686
|
+
return paragraphs;
|
|
6687
|
+
}
|
|
6688
|
+
let start = tailStart + relativePageFieldIndex;
|
|
6689
|
+
for (let index = start - 1; index >= tailStart; index -= 1) {
|
|
6690
|
+
const paragraph = paragraphs[index];
|
|
6691
|
+
if (paragraph === WORD_PAGE_BREAK || isLikelyFooterArtifact(paragraph)) {
|
|
6692
|
+
start = index;
|
|
6693
|
+
continue;
|
|
6694
|
+
}
|
|
6695
|
+
break;
|
|
6696
|
+
}
|
|
6697
|
+
const artifactSlice = paragraphs.slice(start);
|
|
6698
|
+
const footerCueCount = artifactSlice.filter(isLikelyFooterArtifact).length;
|
|
6699
|
+
if (footerCueCount < 2) {
|
|
6700
|
+
return paragraphs;
|
|
6701
|
+
}
|
|
6702
|
+
return paragraphs.slice(0, start);
|
|
6703
|
+
}
|
|
6704
|
+
function isFooterPageField(paragraph) {
|
|
6705
|
+
return /^(?:PAGE|Page)(?:\s+(?:PAGE|\d+))?(?:\s+of\s+(?:NUMPAGES|\d+))?$/i.test(paragraph.trim()) || /\bNUMPAGES\b/i.test(paragraph);
|
|
6706
|
+
}
|
|
6707
|
+
function isLikelyFooterArtifact(paragraph) {
|
|
6708
|
+
const value = paragraph.trim();
|
|
6709
|
+
return value === WORD_PAGE_BREAK || isFooterPageField(value) || /^wd-[\w.-]+$/i.test(value) || /^\d{1,2}\s+[A-Za-z]+\s+\d{4}$/.test(value) || /^Copyright\s+©?\s*(?:OASIS|2002 OASIS)/i.test(value);
|
|
6710
|
+
}
|
|
6711
|
+
function buildWordBlocks(paragraphs) {
|
|
6712
|
+
const blocks = [];
|
|
6713
|
+
let index = 0;
|
|
6714
|
+
while (index < paragraphs.length) {
|
|
6715
|
+
const paragraph = paragraphs[index];
|
|
6716
|
+
if (paragraph === WORD_PAGE_BREAK) {
|
|
6717
|
+
blocks.push({ type: "pageBreak" });
|
|
6718
|
+
index += 1;
|
|
6719
|
+
continue;
|
|
6720
|
+
}
|
|
6721
|
+
const toc = parseTocEntry(paragraph);
|
|
6722
|
+
if (toc) {
|
|
6723
|
+
blocks.push(toc);
|
|
6724
|
+
index += 1;
|
|
6725
|
+
continue;
|
|
6726
|
+
}
|
|
6727
|
+
if (isTableRowCandidate(paragraph)) {
|
|
6728
|
+
const rows = [];
|
|
6729
|
+
while (index < paragraphs.length && isTableRowCandidate(paragraphs[index])) {
|
|
6730
|
+
rows.push(...normalizeTableRows(splitTableRow(paragraphs[index])));
|
|
6731
|
+
index += 1;
|
|
6732
|
+
}
|
|
6733
|
+
blocks.push({ type: "table", rows });
|
|
6734
|
+
continue;
|
|
6735
|
+
}
|
|
6736
|
+
blocks.push(classifyParagraphBlock(paragraph, blocks));
|
|
6737
|
+
index += 1;
|
|
6738
|
+
}
|
|
6739
|
+
return blocks;
|
|
6740
|
+
}
|
|
6741
|
+
function inferLayoutHints(paragraphs, assets) {
|
|
6742
|
+
const sample = paragraphs.slice(0, 40).join("\n");
|
|
6743
|
+
const isOasisSpec = /Word Specification Sample/.test(sample) && /\bOASIS\b/i.test(paragraphs.join("\n"));
|
|
6744
|
+
const oasisImage = isOasisSpec ? assets.find((asset) => asset.mimeType === "image/png" && asset.width && asset.height && asset.width / asset.height > 2.5) : void 0;
|
|
6745
|
+
return {
|
|
6746
|
+
lineNumbers: isOasisSpec,
|
|
6747
|
+
headerBrand: isOasisSpec ? "oasis" : void 0,
|
|
6748
|
+
headerImageId: oasisImage?.id,
|
|
6749
|
+
footer: isOasisSpec ? inferOasisFooter(paragraphs) : void 0
|
|
6750
|
+
};
|
|
6751
|
+
}
|
|
6752
|
+
function inferOasisFooter(paragraphs) {
|
|
6753
|
+
const documentId = findValueAfterLabel(paragraphs, "Document identifier:") || paragraphs.find((paragraph) => /^wd-[\w.-]+/i.test(paragraph));
|
|
6754
|
+
const subtitle = paragraphs.find((paragraph) => /\b(?:draft|version)\b/i.test(paragraph) && /\d{4}/.test(paragraph));
|
|
6755
|
+
const date = subtitle?.match(/\b\d{1,2}\s+[A-Za-z]+\s+\d{4}\b/)?.[0];
|
|
6756
|
+
const copyright = paragraphs.find((paragraph) => /Copyright.*OASIS.*All Rights Reserved/i.test(paragraph)) || "Copyright \xA9 OASIS Open 2002. All Rights Reserved.";
|
|
6757
|
+
return { documentId, date, copyright };
|
|
6758
|
+
}
|
|
6759
|
+
function findValueAfterLabel(paragraphs, label) {
|
|
6760
|
+
const index = paragraphs.findIndex((paragraph) => paragraph.toLowerCase() === label.toLowerCase());
|
|
6761
|
+
if (index < 0) {
|
|
6762
|
+
return void 0;
|
|
6763
|
+
}
|
|
6764
|
+
return paragraphs.slice(index + 1).find((paragraph) => paragraph !== WORD_PAGE_BREAK && paragraph.length > 0);
|
|
6765
|
+
}
|
|
6766
|
+
function paginateWordBlocks(blocks, layout) {
|
|
6767
|
+
const maxLines = layout.lineNumbers ? 33 : 46;
|
|
6768
|
+
const pages = [];
|
|
6769
|
+
let current = [];
|
|
6770
|
+
let usedLines = 0;
|
|
6771
|
+
for (const block of blocks) {
|
|
6772
|
+
if (block.type === "pageBreak") {
|
|
6773
|
+
if (current.length > 0) {
|
|
6774
|
+
pages.push(current);
|
|
6775
|
+
}
|
|
6776
|
+
current = [];
|
|
6777
|
+
usedLines = 0;
|
|
6778
|
+
continue;
|
|
6779
|
+
}
|
|
6780
|
+
const lines = estimatedLineCount(block);
|
|
6781
|
+
const shouldBreak = current.length > 0 && (usedLines + lines > maxLines || block.type === "heading" && usedLines > Math.floor(maxLines * 0.72));
|
|
6782
|
+
if (shouldBreak) {
|
|
6783
|
+
pages.push(current);
|
|
6784
|
+
current = [];
|
|
6785
|
+
usedLines = 0;
|
|
6786
|
+
}
|
|
6787
|
+
current.push(block);
|
|
6788
|
+
usedLines += lines;
|
|
6789
|
+
}
|
|
6790
|
+
if (current.length > 0 || pages.length === 0) {
|
|
6791
|
+
pages.push(current);
|
|
6792
|
+
}
|
|
6793
|
+
return pages;
|
|
6794
|
+
}
|
|
6795
|
+
function estimatedLineCount(block) {
|
|
6796
|
+
if (block.type === "pageBreak") {
|
|
6797
|
+
return 0;
|
|
6798
|
+
}
|
|
6799
|
+
if (block.type === "table") {
|
|
6800
|
+
return Math.max(1, block.rows.length);
|
|
6801
|
+
}
|
|
6802
|
+
if (block.type === "toc") {
|
|
6803
|
+
return 1;
|
|
6804
|
+
}
|
|
6805
|
+
const baseWidth = "indent" in block && block.indent ? 78 : 96;
|
|
6806
|
+
return Math.max(1, Math.ceil(block.text.length / baseWidth));
|
|
6807
|
+
}
|
|
6808
|
+
function classifyParagraphBlock(text, previousBlocks) {
|
|
6809
|
+
const visibleIndex = previousBlocks.filter((block) => block.type !== "toc").length;
|
|
6810
|
+
if (visibleIndex === 0 && text.length <= 140) {
|
|
6811
|
+
return { type: "title", text };
|
|
6812
|
+
}
|
|
6813
|
+
if (visibleIndex === 1 && /draft|version|20\d{2}|19\d{2}/i.test(text) && text.length <= 140) {
|
|
6814
|
+
return { type: "subtitle", text };
|
|
6815
|
+
}
|
|
6816
|
+
const headingLevel = inferHeadingLevel(text, previousBlocks);
|
|
6817
|
+
if (headingLevel) {
|
|
6818
|
+
return { type: "heading", text, level: headingLevel };
|
|
6819
|
+
}
|
|
6820
|
+
if (/^[\w\s/().-]{2,45}:$/.test(text)) {
|
|
6821
|
+
return { type: "label", text };
|
|
6822
|
+
}
|
|
6823
|
+
if (isInstructionParagraph(text)) {
|
|
6824
|
+
return { type: "instruction", text, indent: shouldIndentParagraph(previousBlocks) };
|
|
6825
|
+
}
|
|
6826
|
+
if (/^\[[-\w.]+\]\s+/.test(text)) {
|
|
6827
|
+
return { type: "reference", text };
|
|
6828
|
+
}
|
|
6829
|
+
const listLevel = inferListItemLevel(text);
|
|
6830
|
+
if (listLevel) {
|
|
6831
|
+
return { type: "listItem", text, level: listLevel };
|
|
6832
|
+
}
|
|
6833
|
+
if (isCodeLikeParagraph(text)) {
|
|
6834
|
+
return { type: "code", text, indent: shouldIndentParagraph(previousBlocks) };
|
|
6835
|
+
}
|
|
6836
|
+
return { type: "paragraph", text, indent: shouldIndentParagraph(previousBlocks) };
|
|
6837
|
+
}
|
|
6838
|
+
function isInstructionParagraph(text) {
|
|
6839
|
+
return /^\[[^\]]{8,}\]$/.test(text.trim());
|
|
6840
|
+
}
|
|
6841
|
+
function inferHeadingLevel(text, previousBlocks) {
|
|
6842
|
+
if (text.length > 120) {
|
|
6843
|
+
return void 0;
|
|
6844
|
+
}
|
|
6845
|
+
if (/^table of contents$/i.test(text)) {
|
|
6846
|
+
return 1;
|
|
6847
|
+
}
|
|
6848
|
+
if (/^(?:introduction|word styles|references|appendix\b.*|acknowledgments|revision history|notices)$/i.test(text)) {
|
|
6849
|
+
return 1;
|
|
6850
|
+
}
|
|
6851
|
+
const numbered = text.match(/^([1-9](?:\.\d+)*)\s+.+/);
|
|
6852
|
+
if (numbered) {
|
|
6853
|
+
return Math.min(3, numbered[1].split(".").length);
|
|
6854
|
+
}
|
|
6855
|
+
if (/^(?:terminology|overall style|title page|headings|paragraphs|lists|tables|code examples|character styles|normative)$/i.test(text)) {
|
|
6856
|
+
return 2;
|
|
6857
|
+
}
|
|
6858
|
+
const previousHeading = [...previousBlocks].reverse().find((block) => block.type === "heading");
|
|
6859
|
+
if (previousHeading?.type === "heading" && previousHeading.level === 1 && /^[A-Z][A-Za-z0-9 ()/-]{2,80}$/.test(text)) {
|
|
6860
|
+
return 2;
|
|
6861
|
+
}
|
|
6862
|
+
return void 0;
|
|
6863
|
+
}
|
|
6864
|
+
function shouldIndentParagraph(previousBlocks) {
|
|
6865
|
+
for (let index = previousBlocks.length - 1; index >= 0; index -= 1) {
|
|
6866
|
+
const block = previousBlocks[index];
|
|
6867
|
+
if (block.type === "toc" || block.type === "table") {
|
|
6868
|
+
continue;
|
|
6869
|
+
}
|
|
6870
|
+
if (block.type === "label") {
|
|
6871
|
+
return true;
|
|
6872
|
+
}
|
|
6873
|
+
if ((block.type === "paragraph" || block.type === "code") && block.indent) {
|
|
6874
|
+
return true;
|
|
6875
|
+
}
|
|
6876
|
+
return false;
|
|
6877
|
+
}
|
|
6878
|
+
return false;
|
|
6879
|
+
}
|
|
6880
|
+
function inferListItemLevel(text) {
|
|
6881
|
+
if (/^(?:list bullet|definition term)$/i.test(text)) {
|
|
6882
|
+
return 1;
|
|
6883
|
+
}
|
|
6884
|
+
if (/^(?:list bullet 2|list continue 2|definition for the term\.)$/i.test(text)) {
|
|
6885
|
+
return 2;
|
|
6886
|
+
}
|
|
6887
|
+
return void 0;
|
|
6888
|
+
}
|
|
6889
|
+
function parseTocEntry(text) {
|
|
6890
|
+
const tabCells = splitTableRow(text);
|
|
6891
|
+
if (tabCells.length >= 2 && /^\d{1,3}$/.test(tabCells[tabCells.length - 1] || "")) {
|
|
6892
|
+
const title2 = tabCells.slice(0, -1).join(" ").trim();
|
|
6893
|
+
if (isLikelyTocTitle(title2)) {
|
|
6894
|
+
const number2 = title2.match(/^(\d+(?:\.\d+)*)\b/)?.[1] || "";
|
|
6895
|
+
return { type: "toc", title: title2, page: tabCells[tabCells.length - 1], level: number2.includes(".") ? Math.min(3, number2.split(".").length) : 1 };
|
|
6896
|
+
}
|
|
6897
|
+
}
|
|
6898
|
+
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
6899
|
+
const match = cleaned.match(/^(?:(\d+(?:\.\d+)*)\s+)?(.+?)\s+(\d{1,3})$/);
|
|
6900
|
+
if (!match || cleaned.length > 140) {
|
|
6901
|
+
return void 0;
|
|
6902
|
+
}
|
|
6903
|
+
const number = match[1] || "";
|
|
6904
|
+
const title = `${number ? `${number} ` : ""}${match[2] || ""}`.trim();
|
|
6905
|
+
const page = match[3];
|
|
6906
|
+
if (!title || !page || !/^(?:appendix\b|references\b|introduction\b|[A-Z0-9])/i.test(title)) {
|
|
6907
|
+
return void 0;
|
|
6908
|
+
}
|
|
6909
|
+
if (!isLikelyTocTitle(title)) {
|
|
6910
|
+
return void 0;
|
|
6911
|
+
}
|
|
6912
|
+
const level = number.includes(".") ? Math.min(3, number.split(".").length) : 1;
|
|
6913
|
+
return { type: "toc", title, page, level };
|
|
6914
|
+
}
|
|
6915
|
+
function isLikelyTocTitle(title) {
|
|
6916
|
+
return /^(?:appendix\b|references\b|introduction\b|[1-9](?:\.\d+)*\b|[A-Z][\w\s.-]{2,80}$)/i.test(title);
|
|
6917
|
+
}
|
|
6918
|
+
function isTableRowCandidate(text) {
|
|
6919
|
+
if (/^\[[-\w.]+\]\t+/.test(text)) {
|
|
6920
|
+
return false;
|
|
6921
|
+
}
|
|
6922
|
+
const cells = splitTableRow(text);
|
|
6923
|
+
return cells.length >= 2 && cells.some((cell) => cell.length > 0);
|
|
6924
|
+
}
|
|
6925
|
+
function splitTableRow(text) {
|
|
6926
|
+
return text.split(/\t+/).map((cell) => cell.trim()).filter(Boolean);
|
|
6927
|
+
}
|
|
6928
|
+
function normalizeTableRows(cells) {
|
|
6929
|
+
if (cells.length >= 8) {
|
|
6930
|
+
const columnCount = inferTableColumnCount(cells);
|
|
6931
|
+
if (columnCount > 1 && cells.length % columnCount === 0) {
|
|
6932
|
+
const rows = [];
|
|
6933
|
+
for (let offset = 0; offset < cells.length; offset += columnCount) {
|
|
6934
|
+
rows.push(cells.slice(offset, offset + columnCount));
|
|
6935
|
+
}
|
|
6936
|
+
return rows;
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
return [cells];
|
|
6940
|
+
}
|
|
6941
|
+
function inferTableColumnCount(cells) {
|
|
6942
|
+
const header = cells.slice(0, 6).join(" ").toLowerCase();
|
|
6943
|
+
if (/\brev\b/.test(header) && /\bdate\b/.test(header) && /whom|what/.test(header)) {
|
|
6944
|
+
return 4;
|
|
6945
|
+
}
|
|
6946
|
+
for (const candidate of [5, 4, 3, 2]) {
|
|
6947
|
+
if (cells.length % candidate === 0) {
|
|
6948
|
+
return candidate;
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
return 0;
|
|
6952
|
+
}
|
|
6953
|
+
function isCodeLikeParagraph(text) {
|
|
6954
|
+
return /^\d{24,}$/.test(text.replace(/\s+/g, "")) || /^GET\s+https?:\/\//i.test(text) || /^<other\s+HTTP\b/i.test(text) || /<\/?[A-Za-z][A-Za-z0-9:-]*(?:\s+[^>@]*)?>/.test(text) || /^\s*(?:<\?xml|function\b|const\b|let\b|var\b|if\s*\(|for\s*\(|while\s*\(|\{|\}|\/\/)/.test(text);
|
|
6955
|
+
}
|
|
6956
|
+
function cleanWordText(value) {
|
|
6957
|
+
return stripWordFieldCodes(value).replace(/[\u0001-\u0006\u0008\u000e-\u001f]/g, "").replace(/ {2,}/g, " ").trim();
|
|
6958
|
+
}
|
|
6959
|
+
function stripWordFieldCodes(value) {
|
|
6960
|
+
return value.replace(/\u0013\s*(?:HYPERLINK|PAGEREF|TOC)\b[^\u0014\u0015]*/gi, "").replace(/[\u0013-\u0015]/g, "").replace(/\bHYPERLINK\s+\\l\s+"[^"]*"\s*/gi, "").replace(/\bHYPERLINK\s+"[^"]*"\s*/gi, "").replace(/\bPAGEREF\s+\S+\s+\\h\s*/gi, "").replace(/\bTOC\s+\\o\s+"[^"]*"\s+\\h\s+\\z\s*/gi, "").replace(/\bREF\s+[_A-Za-z0-9-]+\s+(?:\\[A-Za-z]+\s*)+/gi, "");
|
|
6961
|
+
}
|
|
6962
|
+
function isDisplayableParagraph(value) {
|
|
6963
|
+
if (value.length < 2) {
|
|
6964
|
+
return false;
|
|
6965
|
+
}
|
|
6966
|
+
const letters = [...value].filter((char) => /[\p{L}\p{N}]/u.test(char)).length;
|
|
6967
|
+
return letters >= Math.min(2, value.length);
|
|
6968
|
+
}
|
|
6969
|
+
function inferDocumentTitle(paragraphs) {
|
|
6970
|
+
return paragraphs.find((paragraph) => paragraph.length <= 120) || "Word \u6587\u6863";
|
|
6971
|
+
}
|
|
6972
|
+
function appendMeta4(list, label, value) {
|
|
6973
|
+
const term = window.document.createElement("dt");
|
|
6974
|
+
term.textContent = label;
|
|
6975
|
+
const detail = window.document.createElement("dd");
|
|
6976
|
+
detail.textContent = value;
|
|
6977
|
+
list.append(term, detail);
|
|
6978
|
+
}
|
|
6979
|
+
function concatChunks(chunks, size) {
|
|
6980
|
+
const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
6981
|
+
const output = new Uint8Array(size === void 0 ? total : Math.min(total, size));
|
|
6982
|
+
let offset = 0;
|
|
6983
|
+
for (const chunk of chunks) {
|
|
6984
|
+
const slice = chunk.subarray(0, Math.min(chunk.length, output.length - offset));
|
|
6985
|
+
output.set(slice, offset);
|
|
6986
|
+
offset += slice.length;
|
|
6987
|
+
if (offset >= output.length) {
|
|
6988
|
+
break;
|
|
6989
|
+
}
|
|
6990
|
+
}
|
|
6991
|
+
return output;
|
|
6992
|
+
}
|
|
6993
|
+
function alignEven(value) {
|
|
6994
|
+
return value % 2 === 0 ? value : value + 1;
|
|
6995
|
+
}
|
|
6996
|
+
function isUsableSector(sector) {
|
|
6997
|
+
return sector !== FREE_SECTOR && sector !== END_OF_CHAIN && sector !== FAT_SECTOR && sector !== DIFAT_SECTOR;
|
|
6998
|
+
}
|
|
6999
|
+
function sectorOffset(sector, sectorSize) {
|
|
7000
|
+
return (sector + 1) * sectorSize;
|
|
7001
|
+
}
|
|
7002
|
+
function normalizeStreamName(name) {
|
|
7003
|
+
return name.replace(/^\/+/, "").toLowerCase();
|
|
7004
|
+
}
|
|
7005
|
+
function decodeUtf16Le(bytes) {
|
|
7006
|
+
return new TextDecoder("utf-16le").decode(bytes);
|
|
7007
|
+
}
|
|
7008
|
+
function decodeWindows1252(bytes) {
|
|
7009
|
+
try {
|
|
7010
|
+
return new TextDecoder("windows-1252").decode(bytes);
|
|
7011
|
+
} catch {
|
|
7012
|
+
return Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
|
|
7013
|
+
}
|
|
7014
|
+
}
|
|
7015
|
+
function dataView2(bytes) {
|
|
7016
|
+
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
7017
|
+
}
|
|
7018
|
+
|
|
7019
|
+
// src/plugins/office.ts
|
|
5926
7020
|
var wordExtensions = /* @__PURE__ */ new Set(["docx", "docm", "doc", "dotx", "dotm", "dot", "rtf", "odt", "fodt", "wps"]);
|
|
5927
7021
|
var sheetExtensions = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "xlt", "xltx", "xltm", "csv", "tsv", "ods", "fods", "numbers", "et"]);
|
|
5928
7022
|
var presentationExtensions = /* @__PURE__ */ new Set(["pptx", "pptm", "ppt", "pps", "ppsx", "ppsm", "potx", "potm", "odp", "fodp", "key", "dps"]);
|
|
@@ -6033,6 +7127,8 @@ function officePlugin(options = {}) {
|
|
|
6033
7127
|
await renderOdp(panel, arrayBuffer);
|
|
6034
7128
|
} else if (extension === "fodp") {
|
|
6035
7129
|
renderOpenDocumentPresentationXml(panel, await readTextFromBuffer(arrayBuffer));
|
|
7130
|
+
} else if (extension === "doc" || extension === "dot") {
|
|
7131
|
+
renderLegacyWordBinary(panel, extension, arrayBuffer);
|
|
6036
7132
|
} else if (isLegacyOfficeBinary(extension)) {
|
|
6037
7133
|
renderLegacyOfficeBinary(panel, extension, arrayBuffer);
|
|
6038
7134
|
} else {
|
|
@@ -9188,6 +10284,13 @@ function legacyOfficeFormatLabel(extension) {
|
|
|
9188
10284
|
}
|
|
9189
10285
|
return "PowerPoint Binary File Format";
|
|
9190
10286
|
}
|
|
10287
|
+
function renderLegacyWordBinary(panel, extension, arrayBuffer) {
|
|
10288
|
+
try {
|
|
10289
|
+
renderLegacyWordDocument(panel, parseLegacyWordDocument(arrayBuffer));
|
|
10290
|
+
} catch (error) {
|
|
10291
|
+
renderLegacyOfficeBinary(panel, extension, arrayBuffer, `Word \u4E8C\u8FDB\u5236\u89E3\u6790\u5931\u8D25\uFF1A${normalizeOfficeError(error)}`);
|
|
10292
|
+
}
|
|
10293
|
+
}
|
|
9191
10294
|
function renderLegacyOfficeBinary(panel, extension, arrayBuffer, parseError) {
|
|
9192
10295
|
const fragments = extractLegacyOfficeText(arrayBuffer);
|
|
9193
10296
|
panel.replaceChildren();
|
|
@@ -13763,10 +14866,10 @@ function renderStep(panel, text, extension, ctx) {
|
|
|
13763
14866
|
note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 STEP \u6587\u672C\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u5173\u952E\u51E0\u4F55\u53C2\u6570\u3002\u7CBE\u786E B-Rep/\u66F2\u9762\u6E32\u67D3\u5EFA\u8BAE\u540E\u7EED\u63A5\u5165 CAD \u5185\u6838\u6216\u670D\u52A1\u7AEF\u8F6C\u6362\u3002";
|
|
13764
14867
|
const meta = document.createElement("div");
|
|
13765
14868
|
meta.className = "ofv-cad-summary";
|
|
13766
|
-
|
|
13767
|
-
|
|
13768
|
-
|
|
13769
|
-
|
|
14869
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14870
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14871
|
+
appendMeta6(meta, "\u70B9", typeCounts.get("CARTESIAN_POINT") || 0);
|
|
14872
|
+
appendMeta6(meta, "\u65B9\u5411", typeCounts.get("DIRECTION") || 0);
|
|
13770
14873
|
const typeList = createCadTypeList(typeCounts);
|
|
13771
14874
|
section.append(note, meta, typeList);
|
|
13772
14875
|
let viewer;
|
|
@@ -13801,10 +14904,10 @@ function renderIges(panel, text, extension, ctx) {
|
|
|
13801
14904
|
note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 IGES \u53C2\u6570\u533A\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u57FA\u7840\u53C2\u6570\u3002\u7CBE\u786E\u66F2\u7EBF/\u66F2\u9762\u6E32\u67D3\u5EFA\u8BAE\u540E\u7EED\u63A5\u5165 CAD \u5185\u6838\u6216\u670D\u52A1\u7AEF\u8F6C\u6362\u3002";
|
|
13802
14905
|
const meta = document.createElement("div");
|
|
13803
14906
|
meta.className = "ofv-cad-summary";
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
14907
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14908
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14909
|
+
appendMeta6(meta, "\u70B9\u5B9E\u4F53", typeCounts.get("116") || 0);
|
|
14910
|
+
appendMeta6(meta, "\u7EBF\u5B9E\u4F53", typeCounts.get("110") || 0);
|
|
13808
14911
|
const typeList = createCadTypeList(typeCounts, "\u7C7B\u578B\u53F7\u7EDF\u8BA1");
|
|
13809
14912
|
section.append(note, meta, typeList);
|
|
13810
14913
|
let viewer;
|
|
@@ -13838,13 +14941,13 @@ function renderIfc(panel, text) {
|
|
|
13838
14941
|
note.textContent = "\u5F53\u524D\u7248\u672C\u63D0\u53D6 IFC STEP \u5B9E\u4F53\u3001BIM \u5C42\u7EA7\u548C\u5E38\u89C1\u6784\u4EF6\u7EDF\u8BA1\u3002\u51E0\u4F55\u7F51\u683C\u3001\u6750\u8D28\u548C\u5C5E\u6027\u96C6\u53EF\u540E\u7EED\u63A5\u5165 IfcOpenShell/IFC.js \u589E\u5F3A\u3002";
|
|
13839
14942
|
const meta = document.createElement("div");
|
|
13840
14943
|
meta.className = "ofv-cad-summary";
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
14944
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14945
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14946
|
+
appendMeta6(meta, "\u9879\u76EE", typeCounts.get("IFCPROJECT") || 0);
|
|
14947
|
+
appendMeta6(meta, "\u5EFA\u7B51", typeCounts.get("IFCBUILDING") || 0);
|
|
14948
|
+
appendMeta6(meta, "\u697C\u5C42", typeCounts.get("IFCBUILDINGSTOREY") || 0);
|
|
14949
|
+
appendMeta6(meta, "\u7A7A\u95F4", typeCounts.get("IFCSPACE") || 0);
|
|
14950
|
+
appendMeta6(meta, "\u6784\u4EF6", countIfcElements(typeCounts));
|
|
13848
14951
|
section.append(note, meta, createCadTypeList(typeCounts, "IFC \u5B9E\u4F53\u7EDF\u8BA1"));
|
|
13849
14952
|
const hierarchy = createIfcHierarchy(records);
|
|
13850
14953
|
if (hierarchy) {
|
|
@@ -13869,10 +14972,10 @@ function renderAcisSat(panel, text, extension, ctx) {
|
|
|
13869
14972
|
note.textContent = "\u5F53\u524D\u7248\u672C\u4F1A\u5728\u524D\u7AEF\u89E3\u6790 ACIS SAT \u6587\u672C\u5B9E\u4F53\u3001\u7C7B\u578B\u7EDF\u8BA1\u548C\u5E38\u89C1 vertex/straight-curve \u51E0\u4F55\u7EBF\u7D22\uFF1B\u7CBE\u786E\u66F2\u9762\u3001\u62D3\u6251\u548C\u5E03\u5C14\u4F53\u4ECD\u5EFA\u8BAE\u63A5\u5165 CAD \u5185\u6838\u589E\u5F3A\u3002";
|
|
13870
14973
|
const meta = document.createElement("div");
|
|
13871
14974
|
meta.className = "ofv-cad-summary";
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
14975
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
14976
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
14977
|
+
appendMeta6(meta, "\u9876\u70B9", typeCounts.get("vertex") || 0);
|
|
14978
|
+
appendMeta6(meta, "\u76F4\u7EBF", typeCounts.get("straight-curve") || 0);
|
|
13876
14979
|
const typeList = createCadTypeList(typeCounts);
|
|
13877
14980
|
section.append(note, meta, typeList);
|
|
13878
14981
|
let viewer;
|
|
@@ -13909,10 +15012,10 @@ function renderParasolidText(panel, text, extension, ctx) {
|
|
|
13909
15012
|
note.textContent = "\u5F53\u524D\u7248\u672C\u4F1A\u5728\u524D\u7AEF\u89E3\u6790 Parasolid x_t \u6587\u672C\u7247\u6BB5\u3001\u5B9E\u4F53\u7C7B\u578B\u3001\u5750\u6807\u70B9\u548C\u57FA\u7840\u7EBF\u6BB5\u7EBF\u7D22\uFF1B\u5B8C\u6574 B-Rep\u3001\u66F2\u9762\u548C\u88C5\u914D\u5173\u7CFB\u5EFA\u8BAE\u63A5\u5165 Parasolid/HOOPS/ODA \u7B49\u4E13\u4E1A\u5185\u6838\u3002";
|
|
13910
15013
|
const meta = document.createElement("div");
|
|
13911
15014
|
meta.className = "ofv-cad-summary";
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
15015
|
+
appendMeta6(meta, "\u5B9E\u4F53", records.length);
|
|
15016
|
+
appendMeta6(meta, "\u7C7B\u578B", typeCounts.size);
|
|
15017
|
+
appendMeta6(meta, "\u70B9", typeCounts.get("point") || typeCounts.get("vertex") || 0);
|
|
15018
|
+
appendMeta6(meta, "\u66F2\u7EBF", (typeCounts.get("line") || 0) + (typeCounts.get("curve") || 0));
|
|
13916
15019
|
const typeList = createCadTypeList(typeCounts);
|
|
13917
15020
|
section.append(note, meta, typeList);
|
|
13918
15021
|
let viewer;
|
|
@@ -14020,23 +15123,23 @@ function renderLayoutPreview(panel, data, ctx) {
|
|
|
14020
15123
|
summary.setAttribute("aria-hidden", "true");
|
|
14021
15124
|
summary.style.display = "none";
|
|
14022
15125
|
}
|
|
14023
|
-
|
|
14024
|
-
|
|
15126
|
+
appendMeta6(summary, "\u6587\u4EF6", data.fileName);
|
|
15127
|
+
appendMeta6(summary, "\u683C\u5F0F", data.format);
|
|
14025
15128
|
if (data.libraryName) {
|
|
14026
|
-
|
|
15129
|
+
appendMeta6(summary, "\u5E93", data.libraryName);
|
|
14027
15130
|
}
|
|
14028
15131
|
if (data.version) {
|
|
14029
|
-
|
|
15132
|
+
appendMeta6(summary, "\u7248\u672C", data.version);
|
|
14030
15133
|
}
|
|
14031
15134
|
if (data.unit) {
|
|
14032
|
-
|
|
15135
|
+
appendMeta6(summary, "\u5355\u4F4D", data.unit);
|
|
14033
15136
|
}
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
15137
|
+
appendMeta6(summary, "Cell", data.cells.length);
|
|
15138
|
+
appendMeta6(summary, "\u51E0\u4F55", data.shapes.length);
|
|
15139
|
+
appendMeta6(summary, "\u5F15\u7528", data.references.length);
|
|
15140
|
+
appendMeta6(summary, "\u6587\u5B57", data.labels.length);
|
|
14038
15141
|
for (const [label, value] of data.metadata) {
|
|
14039
|
-
|
|
15142
|
+
appendMeta6(summary, label, value);
|
|
14040
15143
|
}
|
|
14041
15144
|
section.append(summary);
|
|
14042
15145
|
for (const noteText of [...data.notes, ...data.warnings]) {
|
|
@@ -14642,12 +15745,12 @@ function renderBinaryCad(panel, bytes, extension, fileName) {
|
|
|
14642
15745
|
note.textContent = extension === "dwg" ? "\u5DF2\u8BC6\u522B DWG \u4E13\u6709\u4E8C\u8FDB\u5236\u56FE\u7EB8\u3002\u6838\u5FC3\u63D2\u4EF6\u9ED8\u8BA4\u63D0\u4F9B\u7248\u672C\u3001\u5BB9\u5668\u3001\u7ED3\u6784\u7EBF\u7D22\u548C\u63A5\u5165\u5EFA\u8BAE\uFF1B\u771F\u5B9E\u51E0\u4F55\u6E32\u67D3\u53EF\u901A\u8FC7 cadPlugin({ binaryRenderer }) \u63A5\u5165\u53EF\u9009\u524D\u7AEF\u5F15\u64CE\u6216\u8F6C\u6362\u670D\u52A1\u3002" : "\u5DF2\u8BC6\u522B DWF \u53D1\u5E03\u56FE\u7EB8\u3002\u6838\u5FC3\u63D2\u4EF6\u9ED8\u8BA4\u63D0\u4F9B\u5BB9\u5668\u7EBF\u7D22\u548C\u63A5\u5165\u5EFA\u8BAE\uFF1B\u9AD8\u4FDD\u771F\u9875\u9762\u6E32\u67D3\u53EF\u901A\u8FC7 cadPlugin({ binaryRenderer }) \u63A5\u5165\u4E13\u7528\u89E3\u6790\u5668\u6216\u8F6C\u6362\u670D\u52A1\u3002";
|
|
14643
15746
|
const meta = document.createElement("div");
|
|
14644
15747
|
meta.className = "ofv-cad-summary";
|
|
14645
|
-
|
|
14646
|
-
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
|
|
15748
|
+
appendMeta6(meta, "\u6587\u4EF6", fileName);
|
|
15749
|
+
appendMeta6(meta, "\u683C\u5F0F", extension.toUpperCase());
|
|
15750
|
+
appendMeta6(meta, "\u5927\u5C0F", formatBytes3(bytes.byteLength));
|
|
15751
|
+
appendMeta6(meta, "\u7B7E\u540D", byteSignature2(bytes));
|
|
15752
|
+
appendMeta6(meta, "\u7248\u672C", detectCadVersion(bytes, extension));
|
|
15753
|
+
appendMeta6(meta, "\u5BB9\u5668", detectCadContainer(bytes));
|
|
14651
15754
|
const actions = document.createElement("div");
|
|
14652
15755
|
actions.className = "ofv-cad-conversion";
|
|
14653
15756
|
const actionTitle = document.createElement("h4");
|
|
@@ -14687,12 +15790,12 @@ function createBinaryCadProbe(bytes, extension) {
|
|
|
14687
15790
|
summary.textContent = "\u4E8C\u8FDB\u5236\u7ED3\u6784\u63A2\u6D4B";
|
|
14688
15791
|
const meta = document.createElement("div");
|
|
14689
15792
|
meta.className = "ofv-archive-probe-meta";
|
|
14690
|
-
|
|
14691
|
-
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
15793
|
+
appendMeta6(meta, "\u53EF\u8BFB\u7247\u6BB5", probe.tokens.length);
|
|
15794
|
+
appendMeta6(meta, "\u5B9E\u4F53\u5173\u952E\u8BCD", formatCadKeywordCounts(probe.entityCounts));
|
|
15795
|
+
appendMeta6(meta, "\u56FE\u5C42\u7EBF\u7D22", String(probe.layerHints.length));
|
|
15796
|
+
appendMeta6(meta, "\u5757/\u5F15\u7528\u7EBF\u7D22", String(probe.blockHints.length));
|
|
15797
|
+
appendMeta6(meta, "\u5916\u90E8\u5F15\u7528", String(probe.externalRefs.length));
|
|
15798
|
+
appendMeta6(meta, "\u89E3\u6790\u7EA7\u522B", extension === "dwg" ? "\u542F\u53D1\u5F0F\u626B\u63CF" : "\u5BB9\u5668/\u6587\u672C\u626B\u63CF");
|
|
14696
15799
|
details.append(summary, meta);
|
|
14697
15800
|
const hints = [...probe.layerHints, ...probe.blockHints, ...probe.externalRefs].slice(0, 18);
|
|
14698
15801
|
if (hints.length > 0) {
|
|
@@ -15225,9 +16328,9 @@ function createUnsupportedCadSection(extension, fileName) {
|
|
|
15225
16328
|
const section = createSection("CAD \u589E\u5F3A\u63A5\u5165\u63D0\u793A");
|
|
15226
16329
|
const meta = document.createElement("div");
|
|
15227
16330
|
meta.className = "ofv-cad-summary";
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
16331
|
+
appendMeta6(meta, "\u6587\u4EF6", fileName);
|
|
16332
|
+
appendMeta6(meta, "\u683C\u5F0F", `.${extension || "cad"}`);
|
|
16333
|
+
appendMeta6(meta, "\u5185\u7F6E\u80FD\u529B", unsupportedCadBuiltInLevel(extension));
|
|
15231
16334
|
const note = document.createElement("p");
|
|
15232
16335
|
note.textContent = unsupportedCadGuidance(extension);
|
|
15233
16336
|
const actions = document.createElement("div");
|
|
@@ -15340,7 +16443,7 @@ function countBy(values) {
|
|
|
15340
16443
|
}
|
|
15341
16444
|
return counts;
|
|
15342
16445
|
}
|
|
15343
|
-
function
|
|
16446
|
+
function appendMeta6(parent, label, value) {
|
|
15344
16447
|
const row = document.createElement("div");
|
|
15345
16448
|
row.className = "ofv-meta-row";
|
|
15346
16449
|
const key = document.createElement("span");
|
|
@@ -17374,10 +18477,10 @@ function read255UInt16(bytes, offset) {
|
|
|
17374
18477
|
return { value: code, offset };
|
|
17375
18478
|
}
|
|
17376
18479
|
function decodeEotString(bytes) {
|
|
17377
|
-
const text =
|
|
18480
|
+
const text = decodeUtf16Le2(bytes).replace(/\0+$/g, "").trim();
|
|
17378
18481
|
return text || new TextDecoder("latin1").decode(bytes).replace(/\0+$/g, "").trim();
|
|
17379
18482
|
}
|
|
17380
|
-
function
|
|
18483
|
+
function decodeUtf16Le2(bytes) {
|
|
17381
18484
|
let value = "";
|
|
17382
18485
|
for (let index = 0; index + 1 < bytes.length; index += 2) {
|
|
17383
18486
|
value += String.fromCharCode(bytes[index] | bytes[index + 1] << 8);
|