@open-file-viewer/core 0.1.11 → 0.1.12
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 +38 -0
- package/dist/index.cjs +201 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +201 -7
- package/dist/index.js.map +1 -1
- package/dist/style.css +56 -23
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -152,7 +152,26 @@ declare function epubPlugin(): PreviewPlugin;
|
|
|
152
152
|
|
|
153
153
|
declare function xpsPlugin(): PreviewPlugin;
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
interface OfficeConversionContext {
|
|
156
|
+
file: PreviewContext["file"];
|
|
157
|
+
arrayBuffer: ArrayBuffer;
|
|
158
|
+
extension: string;
|
|
159
|
+
detectedFormat?: "docx" | "xlsx" | "pptx";
|
|
160
|
+
reason: "complex-docx" | "legacy-office" | "manual";
|
|
161
|
+
}
|
|
162
|
+
type OfficeConversionResult = Blob | ArrayBuffer | string | {
|
|
163
|
+
blob?: Blob;
|
|
164
|
+
data?: Blob | ArrayBuffer;
|
|
165
|
+
url?: string;
|
|
166
|
+
fileName?: string;
|
|
167
|
+
mimeType?: string;
|
|
168
|
+
};
|
|
169
|
+
interface OfficePluginOptions {
|
|
170
|
+
convert?: (ctx: OfficeConversionContext) => Promise<OfficeConversionResult | null | undefined> | OfficeConversionResult | null | undefined;
|
|
171
|
+
preferConversion?: boolean | ((ctx: OfficeConversionContext) => boolean | Promise<boolean>);
|
|
172
|
+
pdf?: PdfPluginOptions;
|
|
173
|
+
}
|
|
174
|
+
declare function officePlugin(options?: OfficePluginOptions): PreviewPlugin;
|
|
156
175
|
|
|
157
176
|
declare function ofdPlugin(): PreviewPlugin;
|
|
158
177
|
|
|
@@ -211,4 +230,4 @@ declare function assetPlugin(): PreviewPlugin;
|
|
|
211
230
|
|
|
212
231
|
declare function fallbackPlugin(): PreviewPlugin;
|
|
213
232
|
|
|
214
|
-
export { type CadBinaryPreviewContext, type CadPluginOptions, type FileViewer, type LibreDwgPreviewOptions, type PreviewCommand, type PreviewContext, type PreviewFallback, type PreviewFile, type PreviewFit, type PreviewInstance, type PreviewItem, type PreviewOptions, type PreviewPlugin, type PreviewSize, type PreviewSource, type PreviewTheme, type PreviewToolbarActionId, type PreviewToolbarBuiltInAction, type PreviewToolbarCustomAction, type PreviewToolbarOptions, type PreviewToolbarRenderContext, archivePlugin, assetPlugin, audioPlugin, cadPlugin, createViewer, drawingPlugin, emailPlugin, epubPlugin, fallbackPlugin, gisPlugin, imagePlugin, model3dPlugin, ofdPlugin, officePlugin, pdfPlugin, textPlugin, videoPlugin, xpsPlugin };
|
|
233
|
+
export { type CadBinaryPreviewContext, type CadPluginOptions, type FileViewer, type LibreDwgPreviewOptions, type OfficeConversionContext, type OfficeConversionResult, type OfficePluginOptions, type PreviewCommand, type PreviewContext, type PreviewFallback, type PreviewFile, type PreviewFit, type PreviewInstance, type PreviewItem, type PreviewOptions, type PreviewPlugin, type PreviewSize, type PreviewSource, type PreviewTheme, type PreviewToolbarActionId, type PreviewToolbarBuiltInAction, type PreviewToolbarCustomAction, type PreviewToolbarOptions, type PreviewToolbarRenderContext, archivePlugin, assetPlugin, audioPlugin, cadPlugin, createViewer, drawingPlugin, emailPlugin, epubPlugin, fallbackPlugin, gisPlugin, imagePlugin, model3dPlugin, ofdPlugin, officePlugin, pdfPlugin, textPlugin, videoPlugin, xpsPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -152,7 +152,26 @@ declare function epubPlugin(): PreviewPlugin;
|
|
|
152
152
|
|
|
153
153
|
declare function xpsPlugin(): PreviewPlugin;
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
interface OfficeConversionContext {
|
|
156
|
+
file: PreviewContext["file"];
|
|
157
|
+
arrayBuffer: ArrayBuffer;
|
|
158
|
+
extension: string;
|
|
159
|
+
detectedFormat?: "docx" | "xlsx" | "pptx";
|
|
160
|
+
reason: "complex-docx" | "legacy-office" | "manual";
|
|
161
|
+
}
|
|
162
|
+
type OfficeConversionResult = Blob | ArrayBuffer | string | {
|
|
163
|
+
blob?: Blob;
|
|
164
|
+
data?: Blob | ArrayBuffer;
|
|
165
|
+
url?: string;
|
|
166
|
+
fileName?: string;
|
|
167
|
+
mimeType?: string;
|
|
168
|
+
};
|
|
169
|
+
interface OfficePluginOptions {
|
|
170
|
+
convert?: (ctx: OfficeConversionContext) => Promise<OfficeConversionResult | null | undefined> | OfficeConversionResult | null | undefined;
|
|
171
|
+
preferConversion?: boolean | ((ctx: OfficeConversionContext) => boolean | Promise<boolean>);
|
|
172
|
+
pdf?: PdfPluginOptions;
|
|
173
|
+
}
|
|
174
|
+
declare function officePlugin(options?: OfficePluginOptions): PreviewPlugin;
|
|
156
175
|
|
|
157
176
|
declare function ofdPlugin(): PreviewPlugin;
|
|
158
177
|
|
|
@@ -211,4 +230,4 @@ declare function assetPlugin(): PreviewPlugin;
|
|
|
211
230
|
|
|
212
231
|
declare function fallbackPlugin(): PreviewPlugin;
|
|
213
232
|
|
|
214
|
-
export { type CadBinaryPreviewContext, type CadPluginOptions, type FileViewer, type LibreDwgPreviewOptions, type PreviewCommand, type PreviewContext, type PreviewFallback, type PreviewFile, type PreviewFit, type PreviewInstance, type PreviewItem, type PreviewOptions, type PreviewPlugin, type PreviewSize, type PreviewSource, type PreviewTheme, type PreviewToolbarActionId, type PreviewToolbarBuiltInAction, type PreviewToolbarCustomAction, type PreviewToolbarOptions, type PreviewToolbarRenderContext, archivePlugin, assetPlugin, audioPlugin, cadPlugin, createViewer, drawingPlugin, emailPlugin, epubPlugin, fallbackPlugin, gisPlugin, imagePlugin, model3dPlugin, ofdPlugin, officePlugin, pdfPlugin, textPlugin, videoPlugin, xpsPlugin };
|
|
233
|
+
export { type CadBinaryPreviewContext, type CadPluginOptions, type FileViewer, type LibreDwgPreviewOptions, type OfficeConversionContext, type OfficeConversionResult, type OfficePluginOptions, type PreviewCommand, type PreviewContext, type PreviewFallback, type PreviewFile, type PreviewFit, type PreviewInstance, type PreviewItem, type PreviewOptions, type PreviewPlugin, type PreviewSize, type PreviewSource, type PreviewTheme, type PreviewToolbarActionId, type PreviewToolbarBuiltInAction, type PreviewToolbarCustomAction, type PreviewToolbarOptions, type PreviewToolbarRenderContext, archivePlugin, assetPlugin, audioPlugin, cadPlugin, createViewer, drawingPlugin, emailPlugin, epubPlugin, fallbackPlugin, gisPlugin, imagePlugin, model3dPlugin, ofdPlugin, officePlugin, pdfPlugin, textPlugin, videoPlugin, xpsPlugin };
|
package/dist/index.js
CHANGED
|
@@ -5802,7 +5802,7 @@ var officeMimeFormatMap = {
|
|
|
5802
5802
|
"application/vnd.oasis.opendocument.presentation-flat-xml": "fodp",
|
|
5803
5803
|
"application/vnd.apple.keynote": "key"
|
|
5804
5804
|
};
|
|
5805
|
-
function officePlugin() {
|
|
5805
|
+
function officePlugin(options = {}) {
|
|
5806
5806
|
return {
|
|
5807
5807
|
name: "office",
|
|
5808
5808
|
match(file) {
|
|
@@ -5815,7 +5815,11 @@ function officePlugin() {
|
|
|
5815
5815
|
const arrayBuffer = await readArrayBuffer(ctx.file);
|
|
5816
5816
|
const packageFormat = shouldSniffPackagedOffice(extension) ? await detectPackagedOfficeFormat(arrayBuffer) : void 0;
|
|
5817
5817
|
let disposeDocxFit;
|
|
5818
|
-
|
|
5818
|
+
let delegatedInstance;
|
|
5819
|
+
const conversionContext = await createOfficeConversionContext(ctx, arrayBuffer, extension, packageFormat);
|
|
5820
|
+
if (conversionContext && await shouldUseOfficeConversion(options, conversionContext)) {
|
|
5821
|
+
delegatedInstance = await renderConvertedOfficePreview(panel, ctx, options, conversionContext);
|
|
5822
|
+
} else if (packageFormat === "docx" && !fileIsDocx(extension)) {
|
|
5819
5823
|
disposeDocxFit = await renderDocx(panel, arrayBuffer);
|
|
5820
5824
|
} else if (packageFormat === "xlsx" && !sheetExtensions.has(extension)) {
|
|
5821
5825
|
await renderSheet(panel, arrayBuffer, "xlsx");
|
|
@@ -5849,12 +5853,13 @@ function officePlugin() {
|
|
|
5849
5853
|
ctx.toolbar?.refreshCommandSupport();
|
|
5850
5854
|
return {
|
|
5851
5855
|
canCommand(command) {
|
|
5852
|
-
return controller?.canCommand(command)
|
|
5856
|
+
return delegatedInstance?.canCommand?.(command) || controller?.canCommand(command) || false;
|
|
5853
5857
|
},
|
|
5854
5858
|
command(command) {
|
|
5855
|
-
return controller?.command(command)
|
|
5859
|
+
return delegatedInstance?.command?.(command) || controller?.command(command) || false;
|
|
5856
5860
|
},
|
|
5857
5861
|
destroy() {
|
|
5862
|
+
delegatedInstance?.destroy();
|
|
5858
5863
|
controller?.destroy();
|
|
5859
5864
|
disposeDocxFit?.();
|
|
5860
5865
|
panel.remove();
|
|
@@ -5863,6 +5868,104 @@ function officePlugin() {
|
|
|
5863
5868
|
}
|
|
5864
5869
|
};
|
|
5865
5870
|
}
|
|
5871
|
+
async function createOfficeConversionContext(ctx, arrayBuffer, extension, detectedFormat) {
|
|
5872
|
+
const effectiveFormat = detectedFormat || extension;
|
|
5873
|
+
if ((effectiveFormat === "docx" || fileIsDocx(extension)) && await docxShouldPreferTextboxLayoutFallback(arrayBuffer)) {
|
|
5874
|
+
return { file: ctx.file, arrayBuffer, extension, detectedFormat, reason: "complex-docx" };
|
|
5875
|
+
}
|
|
5876
|
+
if (isLegacyOfficeBinary(extension)) {
|
|
5877
|
+
return { file: ctx.file, arrayBuffer, extension, detectedFormat, reason: "legacy-office" };
|
|
5878
|
+
}
|
|
5879
|
+
return void 0;
|
|
5880
|
+
}
|
|
5881
|
+
async function shouldUseOfficeConversion(options, context) {
|
|
5882
|
+
if (!options.convert) {
|
|
5883
|
+
return false;
|
|
5884
|
+
}
|
|
5885
|
+
if (typeof options.preferConversion === "function") {
|
|
5886
|
+
return Boolean(await options.preferConversion(context));
|
|
5887
|
+
}
|
|
5888
|
+
if (options.preferConversion !== void 0) {
|
|
5889
|
+
return options.preferConversion;
|
|
5890
|
+
}
|
|
5891
|
+
return context.reason === "complex-docx" || context.reason === "legacy-office";
|
|
5892
|
+
}
|
|
5893
|
+
async function renderConvertedOfficePreview(panel, ctx, options, conversionContext) {
|
|
5894
|
+
if (!options.convert) {
|
|
5895
|
+
throw new Error("Office conversion handler is not configured.");
|
|
5896
|
+
}
|
|
5897
|
+
const converted = normalizeOfficeConversionResult(await options.convert(conversionContext), ctx.file.name);
|
|
5898
|
+
if (!converted) {
|
|
5899
|
+
throw new Error("Office conversion handler did not return a previewable file.");
|
|
5900
|
+
}
|
|
5901
|
+
if (converted.mimeType !== "application/pdf" && !converted.fileName.toLowerCase().endsWith(".pdf")) {
|
|
5902
|
+
throw new Error("Office conversion handler must return a PDF Blob, ArrayBuffer or URL.");
|
|
5903
|
+
}
|
|
5904
|
+
return renderPdfDocumentPreview({
|
|
5905
|
+
...options.pdf || {},
|
|
5906
|
+
fileName: converted.fileName,
|
|
5907
|
+
fileUrl: converted.fileUrl,
|
|
5908
|
+
fileSize: converted.fileSize,
|
|
5909
|
+
isExternal: !converted.revokeUrlOnDestroy,
|
|
5910
|
+
viewport: panel,
|
|
5911
|
+
size: ctx.size,
|
|
5912
|
+
fit: ctx.options.fit,
|
|
5913
|
+
toolbar: ctx.toolbar,
|
|
5914
|
+
title: "Office \u9AD8\u4FDD\u771F\u8F6C\u6362\u9884\u89C8",
|
|
5915
|
+
fallbackTitle: "Office \u8F6C\u6362\u540E\u7684 PDF \u65E0\u6CD5\u9884\u89C8",
|
|
5916
|
+
revokeUrlOnDestroy: converted.revokeUrlOnDestroy
|
|
5917
|
+
});
|
|
5918
|
+
}
|
|
5919
|
+
function normalizeOfficeConversionResult(result, sourceFileName) {
|
|
5920
|
+
if (!result) {
|
|
5921
|
+
return void 0;
|
|
5922
|
+
}
|
|
5923
|
+
const fallbackFileName = `${stripFileExtension(sourceFileName) || "office-preview"}.pdf`;
|
|
5924
|
+
if (typeof result === "string") {
|
|
5925
|
+
return {
|
|
5926
|
+
fileName: fallbackFileName,
|
|
5927
|
+
fileUrl: result,
|
|
5928
|
+
mimeType: "application/pdf",
|
|
5929
|
+
revokeUrlOnDestroy: false
|
|
5930
|
+
};
|
|
5931
|
+
}
|
|
5932
|
+
if (result instanceof ArrayBuffer) {
|
|
5933
|
+
const blob = new Blob([result], { type: "application/pdf" });
|
|
5934
|
+
return createConvertedOfficeBlobPreview(blob, fallbackFileName);
|
|
5935
|
+
}
|
|
5936
|
+
if (result instanceof Blob) {
|
|
5937
|
+
return createConvertedOfficeBlobPreview(result, fallbackFileName);
|
|
5938
|
+
}
|
|
5939
|
+
if (result.url) {
|
|
5940
|
+
return {
|
|
5941
|
+
fileName: result.fileName || fallbackFileName,
|
|
5942
|
+
fileUrl: result.url,
|
|
5943
|
+
mimeType: result.mimeType || "application/pdf",
|
|
5944
|
+
revokeUrlOnDestroy: false
|
|
5945
|
+
};
|
|
5946
|
+
}
|
|
5947
|
+
const data = result.blob || result.data;
|
|
5948
|
+
if (data instanceof ArrayBuffer) {
|
|
5949
|
+
const blob = new Blob([data], { type: result.mimeType || "application/pdf" });
|
|
5950
|
+
return createConvertedOfficeBlobPreview(blob, result.fileName || fallbackFileName);
|
|
5951
|
+
}
|
|
5952
|
+
if (data instanceof Blob) {
|
|
5953
|
+
return createConvertedOfficeBlobPreview(data, result.fileName || fallbackFileName);
|
|
5954
|
+
}
|
|
5955
|
+
return void 0;
|
|
5956
|
+
}
|
|
5957
|
+
function createConvertedOfficeBlobPreview(blob, fileName) {
|
|
5958
|
+
return {
|
|
5959
|
+
fileName,
|
|
5960
|
+
fileUrl: URL.createObjectURL(blob),
|
|
5961
|
+
fileSize: blob.size,
|
|
5962
|
+
mimeType: blob.type || "application/pdf",
|
|
5963
|
+
revokeUrlOnDestroy: true
|
|
5964
|
+
};
|
|
5965
|
+
}
|
|
5966
|
+
function stripFileExtension(fileName) {
|
|
5967
|
+
return fileName.replace(/\.[^.]+$/, "");
|
|
5968
|
+
}
|
|
5866
5969
|
function createOfficeZoomController(panel, ctx) {
|
|
5867
5970
|
const canZoom = Boolean(
|
|
5868
5971
|
panel.querySelector(".ofv-docx-document, .ofv-sheet, .ofv-pptx-viewer > div, .ofv-document, .ofv-text-block, .ofv-slide")
|
|
@@ -5959,7 +6062,7 @@ async function renderDocx(panel, arrayBuffer) {
|
|
|
5959
6062
|
useBase64URL: true
|
|
5960
6063
|
});
|
|
5961
6064
|
await normalizeDocxLayout(content, arrayBuffer);
|
|
5962
|
-
const shouldUseTextboxFallback = await docxPreviewLooksBlank(content, arrayBuffer) || await docxPreviewMissesRichTextboxContent(content, arrayBuffer);
|
|
6065
|
+
const shouldUseTextboxFallback = await docxPreviewLooksBlank(content, arrayBuffer) || await docxPreviewMissesRichTextboxContent(content, arrayBuffer) || await docxShouldPreferTextboxLayoutFallback(arrayBuffer);
|
|
5963
6066
|
if (shouldUseTextboxFallback) {
|
|
5964
6067
|
disposeFit?.();
|
|
5965
6068
|
styleContainer.remove();
|
|
@@ -6042,6 +6145,27 @@ async function docxHasRichTextboxContent(arrayBuffer) {
|
|
|
6042
6145
|
return false;
|
|
6043
6146
|
}
|
|
6044
6147
|
}
|
|
6148
|
+
async function docxShouldPreferTextboxLayoutFallback(arrayBuffer) {
|
|
6149
|
+
try {
|
|
6150
|
+
const zip = await JSZip3.loadAsync(arrayBuffer);
|
|
6151
|
+
const documentXml = await zip.file("word/document.xml")?.async("text");
|
|
6152
|
+
if (!documentXml || !/\btxbxContent\b/.test(documentXml)) {
|
|
6153
|
+
return false;
|
|
6154
|
+
}
|
|
6155
|
+
const blocks = extractDocxTextboxBlocks(documentXml);
|
|
6156
|
+
const meaningfulBlocks = blocks.filter((block) => block.paragraphs.length > 0);
|
|
6157
|
+
const sidebarBackgrounds = blocks.filter(
|
|
6158
|
+
(block) => block.paragraphs.length === 0 && block.fill && block.relativeV === "page" && block.x < 0 && block.width >= 120 && block.height >= 500
|
|
6159
|
+
);
|
|
6160
|
+
const pageAnchoredTextboxes = meaningfulBlocks.filter((block) => block.relativeV === "page");
|
|
6161
|
+
const paragraphAnchoredTextboxes = meaningfulBlocks.filter((block) => block.relativeV !== "page");
|
|
6162
|
+
const leftTextboxes = meaningfulBlocks.filter((block) => block.x < 0);
|
|
6163
|
+
const rightTextboxes = meaningfulBlocks.filter((block) => block.x >= 80);
|
|
6164
|
+
return sidebarBackgrounds.length >= 2 && meaningfulBlocks.length >= 8 && pageAnchoredTextboxes.length >= 4 && paragraphAnchoredTextboxes.length >= 2 && leftTextboxes.length >= 3 && rightTextboxes.length >= 3;
|
|
6165
|
+
} catch {
|
|
6166
|
+
return false;
|
|
6167
|
+
}
|
|
6168
|
+
}
|
|
6045
6169
|
async function renderDocxContentFallback(container, arrayBuffer, options = {}) {
|
|
6046
6170
|
if (options.showNote !== false) {
|
|
6047
6171
|
const fallbackNote = document.createElement("div");
|
|
@@ -6493,6 +6617,10 @@ function createDocxTextboxBlockElement(block) {
|
|
|
6493
6617
|
const paragraphs = normalizeDocxTextboxParagraphOrder(block);
|
|
6494
6618
|
const [first, ...rest] = paragraphs;
|
|
6495
6619
|
if (first) {
|
|
6620
|
+
const sectionKind = getDocxTextboxSectionKind(first);
|
|
6621
|
+
if (sectionKind) {
|
|
6622
|
+
section.classList.add(`ofv-docx-textbox-section-${sectionKind}`);
|
|
6623
|
+
}
|
|
6496
6624
|
const heading = document.createElement("h3");
|
|
6497
6625
|
heading.textContent = first;
|
|
6498
6626
|
section.append(heading);
|
|
@@ -6505,6 +6633,28 @@ function createDocxTextboxBlockElement(block) {
|
|
|
6505
6633
|
}
|
|
6506
6634
|
return section;
|
|
6507
6635
|
}
|
|
6636
|
+
function getDocxTextboxSectionKind(heading) {
|
|
6637
|
+
const text = normalizePreviewText(heading);
|
|
6638
|
+
if (text.includes("\u6559\u80B2\u80CC\u666F")) {
|
|
6639
|
+
return "education";
|
|
6640
|
+
}
|
|
6641
|
+
if (text.includes("\u4E13\u4E1A\u6280\u80FD")) {
|
|
6642
|
+
return "skills";
|
|
6643
|
+
}
|
|
6644
|
+
if (text.includes("\u5DE5\u4F5C\u7ECF\u5386")) {
|
|
6645
|
+
return "work";
|
|
6646
|
+
}
|
|
6647
|
+
if (text.includes("\u9879\u76EE\u7ECF\u9A8C")) {
|
|
6648
|
+
return "projects";
|
|
6649
|
+
}
|
|
6650
|
+
if (text.includes("\u81EA\u6211\u8BC4\u4EF7")) {
|
|
6651
|
+
return "summary";
|
|
6652
|
+
}
|
|
6653
|
+
if (text.includes("\u57FA\u672C\u4FE1\u606F")) {
|
|
6654
|
+
return "profile";
|
|
6655
|
+
}
|
|
6656
|
+
return "";
|
|
6657
|
+
}
|
|
6508
6658
|
function estimateDocxTextboxBlockHeight(block) {
|
|
6509
6659
|
return Math.max(block.height, 18 + block.paragraphs.length * 14);
|
|
6510
6660
|
}
|
|
@@ -6548,13 +6698,57 @@ function repairDocxHeadingShapeAlignment(page) {
|
|
|
6548
6698
|
if (!svg) {
|
|
6549
6699
|
continue;
|
|
6550
6700
|
}
|
|
6551
|
-
const width = parseCssPixelValue(svg.getAttribute("width") ||
|
|
6701
|
+
const width = parseCssPixelValue(svg.style.width) || parseCssPixelValue(svg.getAttribute("width") || "");
|
|
6552
6702
|
const marginLeft = parseCssPixelValue(svg.style.marginLeft);
|
|
6553
6703
|
if (width < 300 || marginLeft < 28 || marginLeft > 44) {
|
|
6554
6704
|
continue;
|
|
6555
6705
|
}
|
|
6556
|
-
|
|
6706
|
+
const textWidth = getDocxParagraphVisibleTextWidth(paragraph);
|
|
6707
|
+
svg.style.marginLeft = `${formatCssNumber(Math.max(48, marginLeft + textWidth * 0.68))}pt`;
|
|
6708
|
+
svg.style.marginTop = `${formatCssNumber(parseCssPixelValue(svg.style.marginTop) - 4)}pt`;
|
|
6709
|
+
normalizeDocxHeadingShapeFill(svg);
|
|
6710
|
+
repairDocxHeadingTextBackground(paragraph);
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
function normalizeDocxHeadingShapeFill(svg) {
|
|
6714
|
+
const headingFill = "#3f4aa3";
|
|
6715
|
+
const fillNodes = svg.querySelectorAll("image[fill], rect[data-ofv-docx-shape-fill]");
|
|
6716
|
+
for (const node of fillNodes) {
|
|
6717
|
+
const fill = node.getAttribute("fill") || "";
|
|
6718
|
+
if (fill.toLowerCase() === "#38449a") {
|
|
6719
|
+
node.setAttribute("fill", headingFill);
|
|
6720
|
+
}
|
|
6721
|
+
}
|
|
6722
|
+
}
|
|
6723
|
+
function repairDocxHeadingTextBackground(paragraph) {
|
|
6724
|
+
const textSpans = Array.from(paragraph.querySelectorAll("span")).filter(
|
|
6725
|
+
(element) => normalizePreviewText(element.textContent || "")
|
|
6726
|
+
);
|
|
6727
|
+
const lastTextSpan = textSpans.at(-1);
|
|
6728
|
+
if (!lastTextSpan || !hasWhiteBackground(lastTextSpan)) {
|
|
6729
|
+
return;
|
|
6730
|
+
}
|
|
6731
|
+
lastTextSpan.style.paddingRight = "3pt";
|
|
6732
|
+
lastTextSpan.style.paddingTop = "2pt";
|
|
6733
|
+
lastTextSpan.style.paddingBottom = "2pt";
|
|
6734
|
+
lastTextSpan.style.boxDecorationBreak = "clone";
|
|
6735
|
+
}
|
|
6736
|
+
function hasWhiteBackground(element) {
|
|
6737
|
+
const background = element.style.backgroundColor.replace(/\s+/g, "").toLowerCase();
|
|
6738
|
+
return background === "white" || background === "#fff" || background === "#ffffff" || background === "rgb(255,255,255)";
|
|
6739
|
+
}
|
|
6740
|
+
function getDocxParagraphVisibleTextWidth(paragraph) {
|
|
6741
|
+
let textWidth = 0;
|
|
6742
|
+
for (const element of paragraph.querySelectorAll("span")) {
|
|
6743
|
+
if (!normalizePreviewText(element.textContent || "")) {
|
|
6744
|
+
continue;
|
|
6745
|
+
}
|
|
6746
|
+
textWidth += pxToPt(element.getBoundingClientRect().width);
|
|
6557
6747
|
}
|
|
6748
|
+
return textWidth;
|
|
6749
|
+
}
|
|
6750
|
+
function pxToPt(value) {
|
|
6751
|
+
return value * 0.75;
|
|
6558
6752
|
}
|
|
6559
6753
|
function repairDocxListIndentAlignment(page) {
|
|
6560
6754
|
for (const paragraph of page.querySelectorAll("p[class*='ofv-docx-num-']")) {
|