Files
docx-js/src/patcher/replacer.spec.ts
SebKranz dece0f58e1 Fix duplicated br tags (#2717)
* Adjust test to demo duplicated br tags

* Fix patchDocument duplicating br tags

* Only include w:Pr

* Fix tag condition

---------

Co-authored-by: Dolan <dolan_miu@hotmail.com>
2024-11-20 11:19:25 +00:00

662 lines
39 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it, vi } from "vitest";
import { IViewWrapper } from "@file/document-wrapper";
import { File } from "@file/file";
import { Paragraph, TextRun } from "@file/paragraph";
import { IContext } from "@file/xml-components";
import { PatchType } from "./from-docx";
import { replacer } from "./replacer";
export const MOCK_JSON = {
elements: [
{
type: "element",
name: "w:hdr",
elements: [
{
type: "element",
name: "w:p",
attributes: { "w14:paraId": "3BE1A671", "w14:textId": "74E856C4", "w:rsidR": "000D38A7", "w:rsidRDefault": "000D38A7" },
elements: [
{
type: "element",
name: "w:pPr",
elements: [{ type: "element", name: "w:pStyle", attributes: { "w:val": "Header" } }],
},
{
type: "element",
name: "w:r",
elements: [{ type: "element", name: "w:t", elements: [{ type: "text", text: "This is a {{head" }] }],
},
{
type: "element",
name: "w:r",
attributes: { "w:rsidR": "004A3A99" },
elements: [{ type: "element", name: "w:t", elements: [{ type: "text", text: "er" }] }],
},
{
type: "element",
name: "w:r",
elements: [
{ type: "element", name: "w:t", elements: [{ type: "text", text: "_adjective}} dont you think?" }] },
],
},
],
},
{
type: "element",
name: "w:p",
elements: [
{
type: "element",
name: "w:r",
elements: [
{
type: "element",
name: "w:rPr",
elements: [{ type: "element", name: "w:b", attributes: { "w:val": "1" } }],
},
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "What a {{bold}} text!" }],
},
{
type: "element",
name: "w:br",
},
],
},
],
},
],
},
],
};
describe("replacer", () => {
describe("replacer", () => {
it("should throw an error if nothing is added", () => {
expect(() =>
replacer({
json: {
elements: [],
},
patch: {
type: PatchType.PARAGRAPH,
children: [],
},
patchText: "hello",
// eslint-disable-next-line functional/prefer-readonly-type
context: vi.fn<[], IContext>()(),
}),
).toThrow();
});
it("should replace paragraph type", () => {
const output = replacer({
json: JSON.parse(JSON.stringify(MOCK_JSON)),
patch: {
type: PatchType.PARAGRAPH,
children: [new TextRun("Delightful Header")],
},
patchText: "{{header_adjective}}",
context: {
file: {} as unknown as File,
viewWrapper: {
Relationships: {},
} as unknown as IViewWrapper,
stack: [],
},
});
expect(JSON.stringify(output)).to.contain("Delightful Header");
});
it("should replace paragraph type keeping original styling if keepOriginalStyles is true", () => {
const output = replacer({
json: JSON.parse(JSON.stringify(MOCK_JSON)),
patch: {
type: PatchType.PARAGRAPH,
children: [new TextRun("sweet")],
},
patchText: "{{bold}}",
context: {
file: {} as unknown as File,
viewWrapper: {
Relationships: {},
} as unknown as IViewWrapper,
stack: [],
},
keepOriginalStyles: true,
});
expect(JSON.stringify(output)).to.contain("sweet");
expect(output.elements![0].elements![1].elements).toMatchObject([
{
type: "element",
name: "w:r",
elements: [
{
type: "element",
name: "w:rPr",
elements: [{ type: "element", name: "w:b", attributes: { "w:val": "1" } }],
},
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "What a " }],
},
],
},
{
type: "element",
name: "w:r",
elements: [
{
type: "element",
name: "w:rPr",
elements: [{ type: "element", name: "w:b", attributes: { "w:val": "1" } }],
},
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "sweet" }],
},
],
},
{
type: "element",
name: "w:r",
elements: [
{
type: "element",
name: "w:rPr",
elements: [{ type: "element", name: "w:b", attributes: { "w:val": "1" } }],
},
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: " text!" }],
},
{
name: "w:br",
type: "element",
},
],
},
]);
});
it("should replace document type", () => {
const output = replacer({
json: JSON.parse(JSON.stringify(MOCK_JSON)),
patch: {
type: PatchType.DOCUMENT,
children: [new Paragraph("Lorem ipsum paragraph")],
},
patchText: "{{header_adjective}}",
context: {
file: {} as unknown as File,
viewWrapper: {
Relationships: {},
} as unknown as IViewWrapper,
stack: [],
},
});
expect(JSON.stringify(output)).to.contain("Lorem ipsum paragraph");
});
it("should replace", () => {
// cspell:disable
const output = replacer({
json: {
elements: [
{
type: "element",
name: "w:hdr",
elements: [
{
type: "element",
name: "w:p",
elements: [
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "{{" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "s" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "chool_" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "n" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "{{" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "a" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "ddr" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "ess" }],
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:r",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rPr",
elements: [
{ type: "text", text: "\n " },
{
type: "element",
name: "w:rFonts",
attributes: { "w:eastAsia": "Times New Roman" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:kern",
attributes: { "w:val": "0" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:sz",
attributes: { "w:val": "20" },
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:lang",
attributes: {
"w:val": "en-US",
"w:eastAsia": "en-US",
"w:bidi": "ar-SA",
},
},
{ type: "text", text: "\n " },
],
},
{ type: "text", text: "\n " },
{
type: "element",
name: "w:t",
elements: [{ type: "text", text: "}}" }],
},
],
},
],
},
],
},
],
},
// cspell:enable
patch: {
type: PatchType.PARAGRAPH,
children: [new Paragraph("Lorem ipsum paragraph")],
},
patchText: "{{address}}",
context: {
file: {} as unknown as File,
viewWrapper: {
Relationships: {},
} as unknown as IViewWrapper,
stack: [],
},
});
expect(JSON.stringify(output)).to.contain("Lorem ipsum paragraph");
});
});
});