feat: add support for custom patch delimiters in PatchDocumentOptions (#3036)
* feat: add support for custom patch delimiters in PatchDocumentOptions * chore: add validation for placeholder delimiters
This commit is contained in:
committed by
GitHub
parent
4d1a351649
commit
5af1045a59
@ -288,6 +288,101 @@ describe("from-docx", () => {
|
||||
});
|
||||
expect(output).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it("should patch the document", async () => {
|
||||
const output = await patchDocument({
|
||||
outputType: "uint8array",
|
||||
data: Buffer.from(""),
|
||||
placeholderDelimiters: { start: "{{", end: "}}" },
|
||||
patches: {
|
||||
name: {
|
||||
type: PatchType.PARAGRAPH,
|
||||
children: [new TextRun("Sir. "), new TextRun("John Doe"), new TextRun("(The Conqueror)")],
|
||||
},
|
||||
item_1: {
|
||||
type: PatchType.PARAGRAPH,
|
||||
children: [
|
||||
new TextRun("#657"),
|
||||
new ExternalHyperlink({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: "BBC News Link",
|
||||
}),
|
||||
],
|
||||
link: "https://www.bbc.co.uk/news",
|
||||
}),
|
||||
],
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
paragraph_replace: {
|
||||
type: PatchType.DOCUMENT,
|
||||
children: [
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun("This is a "),
|
||||
new ExternalHyperlink({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: "Google Link",
|
||||
}),
|
||||
],
|
||||
link: "https://www.google.co.uk",
|
||||
}),
|
||||
new ImageRun({
|
||||
type: "png",
|
||||
data: Buffer.from(""),
|
||||
transformation: { width: 100, height: 100 },
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
image_test: {
|
||||
type: PatchType.PARAGRAPH,
|
||||
children: [
|
||||
new ImageRun({
|
||||
type: "png",
|
||||
data: Buffer.from(""),
|
||||
transformation: { width: 100, height: 100 },
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(output).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it("should patch the document", async () => {
|
||||
const output = await patchDocument({
|
||||
outputType: "uint8array",
|
||||
data: Buffer.from(""),
|
||||
patches: {},
|
||||
});
|
||||
expect(output).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it("throws error with empty delimiters", async () => {
|
||||
await expect(() =>
|
||||
patchDocument({
|
||||
outputType: "uint8array",
|
||||
data: Buffer.from(""),
|
||||
patches: {},
|
||||
placeholderDelimiters: { start: "", end: "" },
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("throws error with whitespace-only delimiters", async () => {
|
||||
await expect(() =>
|
||||
patchDocument({
|
||||
outputType: "uint8array",
|
||||
data: Buffer.from(""),
|
||||
patches: {},
|
||||
placeholderDelimiters: { start: " ", end: " " },
|
||||
}),
|
||||
).rejects.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe("document.xml and [Content_Types].xml with relationships", () => {
|
||||
|
@ -55,6 +55,10 @@ export type PatchDocumentOptions<T extends PatchDocumentOutputType = PatchDocume
|
||||
readonly data: InputDataType;
|
||||
readonly patches: Readonly<Record<string, IPatch>>;
|
||||
readonly keepOriginalStyles?: boolean;
|
||||
readonly placeholderDelimiters?: Readonly<{
|
||||
readonly start: string;
|
||||
readonly end: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
const imageReplacer = new ImageReplacer();
|
||||
@ -64,6 +68,7 @@ export const patchDocument = async <T extends PatchDocumentOutputType = PatchDoc
|
||||
data,
|
||||
patches,
|
||||
keepOriginalStyles,
|
||||
placeholderDelimiters = { start: "{{", end: "}}" } as const,
|
||||
}: PatchDocumentOptions<T>): Promise<OutputByType[T]> => {
|
||||
const zipContent = await JSZip.loadAsync(data);
|
||||
const contexts = new Map<string, IContext>();
|
||||
@ -132,8 +137,14 @@ export const patchDocument = async <T extends PatchDocumentOutputType = PatchDoc
|
||||
};
|
||||
contexts.set(key, context);
|
||||
|
||||
if (!placeholderDelimiters?.start.trim() || !placeholderDelimiters?.end.trim()) {
|
||||
throw new Error("Both start and end delimiters must be non-empty strings.");
|
||||
}
|
||||
|
||||
const { start, end } = placeholderDelimiters;
|
||||
|
||||
for (const [patchKey, patchValue] of Object.entries(patches)) {
|
||||
const patchText = `{{${patchKey}}}`;
|
||||
const patchText = `${start}${patchKey}${end}`;
|
||||
// TODO: mutates json. Make it immutable
|
||||
// We need to loop through to catch every occurrence of the patch text
|
||||
// It is possible that the patch text is in the same run
|
||||
|
Reference in New Issue
Block a user