Respect DOCX underline none on import
This commit is contained in:
+10
-1
@@ -1493,7 +1493,7 @@ function docxRunToHtml(run: unknown, imageDataByRelationshipId: DocxImageDataByR
|
|||||||
if (hasDocxBoolean(properties, "w:i")) {
|
if (hasDocxBoolean(properties, "w:i")) {
|
||||||
html = `<em>${html}</em>`;
|
html = `<em>${html}</em>`;
|
||||||
}
|
}
|
||||||
if (hasDocxBoolean(properties, "w:u")) {
|
if (hasDocxUnderline(properties)) {
|
||||||
html = `<u>${html}</u>`;
|
html = `<u>${html}</u>`;
|
||||||
}
|
}
|
||||||
if (hasStrike) {
|
if (hasStrike) {
|
||||||
@@ -1707,6 +1707,15 @@ function hasDocxBoolean(properties: XmlRecord, key: string) {
|
|||||||
return !["0", "false", "off"].includes(value.toLowerCase());
|
return !["0", "false", "off"].includes(value.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasDocxUnderline(properties: XmlRecord) {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(properties, "w:u")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (docxAttribute(childRecord(properties, "w:u"), "w:val") || docxAttribute(childRecord(properties, "w:u"), "val")).trim().toLowerCase();
|
||||||
|
return !["0", "false", "off", "none"].includes(value);
|
||||||
|
}
|
||||||
|
|
||||||
function childRecord(value: unknown, key: string): XmlRecord {
|
function childRecord(value: unknown, key: string): XmlRecord {
|
||||||
const child = asRecord(value)[key];
|
const child = asRecord(value)[key];
|
||||||
if (Array.isArray(child)) {
|
if (Array.isArray(child)) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import JSZip from "jszip";
|
||||||
import { exportDocxBlob, htmlToWordBlocks, importDocxFile } from "./wordOffice";
|
import { exportDocxBlob, htmlToWordBlocks, importDocxFile } from "./wordOffice";
|
||||||
|
|
||||||
const tinyPngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=";
|
const tinyPngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=";
|
||||||
@@ -128,6 +129,36 @@ describe("wordOffice DOCX import", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not import DOCX underline when w:u val is none", async () => {
|
||||||
|
const sourceBlob = await exportDocxBlob("UnderlineNone.docx", '<p><span style="color: #0f5fae;">Not underlined</span></p>');
|
||||||
|
const zip = await JSZip.loadAsync(await sourceBlob.arrayBuffer());
|
||||||
|
const documentXml = (await zip.file("word/document.xml")?.async("string")) ?? "";
|
||||||
|
const patchedDocumentXml = documentXml.replace(/(<w:rPr\b[^>]*>[\s\S]*?)(<\/w:rPr>)/, '$1<w:u w:val="none"/>$2');
|
||||||
|
expect(patchedDocumentXml).toContain('<w:u w:val="none"/>');
|
||||||
|
zip.file("word/document.xml", patchedDocumentXml);
|
||||||
|
const patchedBlob = await zip.generateAsync({
|
||||||
|
type: "blob",
|
||||||
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||||
|
});
|
||||||
|
|
||||||
|
const imported = await importDocxFile(
|
||||||
|
new File([patchedBlob], "UnderlineNone.docx", {
|
||||||
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(imported.html).not.toContain("<u>Not underlined</u>");
|
||||||
|
expect(imported.html).not.toContain("<u>");
|
||||||
|
expect(imported.html).toContain("color: #0F5FAE;");
|
||||||
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
text: "Not underlined",
|
||||||
|
runs: [{ text: "Not underlined", color: "0F5FAE" }]
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("imports DOCX subscript and superscript from OOXML", async () => {
|
it("imports DOCX subscript and superscript from OOXML", async () => {
|
||||||
const blob = await exportDocxBlob("Indexes.docx", "<p>H<sub>2</sub>O m<sup>2</sup></p>");
|
const blob = await exportDocxBlob("Indexes.docx", "<p>H<sub>2</sub>O m<sup>2</sup></p>");
|
||||||
const file = new File([blob], "Indexes.docx", {
|
const file = new File([blob], "Indexes.docx", {
|
||||||
|
|||||||
Reference in New Issue
Block a user