211 lines
7.9 KiB
TypeScript
211 lines
7.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { exportDocxBlob, htmlToWordBlocks, importDocxFile } from "./wordOffice";
|
|
|
|
const tinyPngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=";
|
|
const tinyPngDataUri = `data:image/png;base64,${tinyPngBase64}`;
|
|
|
|
describe("wordOffice DOCX import", () => {
|
|
it("imports DOCX text color and highlight from OOXML", async () => {
|
|
const blob = await exportDocxBlob(
|
|
"Color.docx",
|
|
'<p><span style="color: #0f5fae; background-color: #fff2cc;">Color fragment</span></p>'
|
|
);
|
|
const file = new File([blob], "Color.docx", { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("color: #0F5FAE;");
|
|
expect(imported.html).toContain("background-color: #FFF2CC;");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Color fragment",
|
|
runs: [{ text: "Color fragment", color: "0F5FAE", highlightColor: "FFF2CC" }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX paragraph alignment from OOXML", async () => {
|
|
const blob = await exportDocxBlob(
|
|
"Alignment.docx",
|
|
'<p style="text-align: center;">Centered</p><p align="right">Right</p><p style="text-align: justify;">Justified</p>'
|
|
);
|
|
const file = new File([blob], "Alignment.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain('style="text-align: center;"');
|
|
expect(imported.html).toContain('style="text-align: right;"');
|
|
expect(imported.html).toContain('style="text-align: justify;"');
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{ type: "paragraph", text: "Centered", runs: [{ text: "Centered" }], alignment: "center" },
|
|
{ type: "paragraph", text: "Right", runs: [{ text: "Right" }], alignment: "right" },
|
|
{ type: "paragraph", text: "Justified", runs: [{ text: "Justified" }], alignment: "both" }
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX font size from OOXML", async () => {
|
|
const blob = await exportDocxBlob("FontSize.docx", '<p><span style="font-size: 18pt;">Large text</span></p>');
|
|
const file = new File([blob], "FontSize.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("font-size: 18pt;");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Large text",
|
|
runs: [{ text: "Large text", fontSize: 18 }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX font family from OOXML", async () => {
|
|
const blob = await exportDocxBlob("FontFamily.docx", '<p><span style="font-family: Arial;">Arial text</span></p>');
|
|
const file = new File([blob], "FontFamily.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("font-family: 'Arial';");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Arial text",
|
|
runs: [{ text: "Arial text", fontFamily: "Arial" }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX strikethrough from OOXML", async () => {
|
|
const blob = await exportDocxBlob("Strike.docx", "<p><s>Deleted text</s></p>");
|
|
const file = new File([blob], "Strike.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("<s>Deleted text</s>");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Deleted text",
|
|
runs: [{ text: "Deleted text", strike: true }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX line breaks from OOXML", async () => {
|
|
const blob = await exportDocxBlob("LineBreak.docx", "<p>Line 1<br>Line 2</p>");
|
|
const file = new File([blob], "LineBreak.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("Line 1<br>Line 2");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Line 1 Line 2",
|
|
runs: [{ text: "Line 1\nLine 2" }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX tabs from OOXML", async () => {
|
|
const blob = await exportDocxBlob("Tab.docx", '<p>Before<span data-qoffice-tab="true" style="white-space: pre;">\t</span>After</p>');
|
|
const file = new File([blob], "Tab.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain('data-qoffice-tab="true"');
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Before After",
|
|
runs: [{ text: "Before\tAfter" }]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports DOCX external hyperlinks from OOXML relationships", async () => {
|
|
const blob = await exportDocxBlob("Hyperlink.docx", '<p>Open <a href="https://example.com/report"><strong>report</strong></a>.</p>');
|
|
const file = new File([blob], "Hyperlink.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain('<a href="https://example.com/report">');
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{
|
|
type: "paragraph",
|
|
text: "Open report.",
|
|
runs: [
|
|
{ text: "Open " },
|
|
{ text: "report", bold: true, href: "https://example.com/report" },
|
|
{ text: "." }
|
|
]
|
|
}
|
|
]);
|
|
});
|
|
|
|
it("imports simple DOCX tables from OOXML", async () => {
|
|
const blob = await exportDocxBlob(
|
|
"Table.docx",
|
|
"<p>Before table</p><table><tr><th>Stage</th><th>Owner</th></tr><tr><td>Plan</td><td>Anna</td></tr></table><p>After table</p>"
|
|
);
|
|
const file = new File([blob], "Table.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
|
|
expect(imported.html).toContain("<table>");
|
|
expect(imported.html).toContain("<td><p>Stage</p></td>");
|
|
expect(imported.html).toContain("<td><p>Anna</p></td>");
|
|
expect(htmlToWordBlocks(imported.html)).toEqual([
|
|
{ type: "paragraph", text: "Before table", runs: [{ text: "Before table" }] },
|
|
{
|
|
type: "table",
|
|
rows: [
|
|
["Stage", "Owner"],
|
|
["Plan", "Anna"]
|
|
]
|
|
},
|
|
{ type: "paragraph", text: "After table", runs: [{ text: "After table" }] }
|
|
]);
|
|
});
|
|
|
|
it("imports styled DOCX content when the document also contains images", async () => {
|
|
const blob = await exportDocxBlob(
|
|
"Mixed.docx",
|
|
`<p><span style="color: #0f5fae;">Color fragment</span></p><img src="${tinyPngDataUri}" alt="Logo" width="32" height="32"><table><tr><td>Stage</td><td>Done</td></tr></table>`
|
|
);
|
|
const file = new File([blob], "Mixed.docx", {
|
|
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
});
|
|
const imported = await importDocxFile(file);
|
|
const blocks = htmlToWordBlocks(imported.html);
|
|
|
|
expect(imported.html).toContain("color: #0F5FAE;");
|
|
expect(imported.html).toContain("<table>");
|
|
expect(imported.html).toContain(`src="${tinyPngDataUri}"`);
|
|
expect(blocks[0]).toEqual({
|
|
type: "paragraph",
|
|
text: "Color fragment",
|
|
runs: [{ text: "Color fragment", color: "0F5FAE" }]
|
|
});
|
|
expect(blocks[1]).toMatchObject({
|
|
type: "image",
|
|
src: tinyPngDataUri,
|
|
alt: "Logo",
|
|
width: 32,
|
|
height: 32
|
|
});
|
|
expect(blocks[2]).toEqual({
|
|
type: "table",
|
|
rows: [["Stage", "Done"]]
|
|
});
|
|
});
|
|
});
|