From 3997ce538dd2131634594154c455f651b31b6e74 Mon Sep 17 00:00:00 2001 From: SebKranz <33868262+SebKranz@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:35:11 +0100 Subject: [PATCH] fix(replacer): errors suppressed by catch statement (#2856) --- src/patcher/from-docx.ts | 59 ++++++++++++++++++------------------ src/patcher/replacer.spec.ts | 49 ++++++++++++++++-------------- src/patcher/replacer.ts | 11 +++++-- 3 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/patcher/from-docx.ts b/src/patcher/from-docx.ts index fd472bdacc..f7f5570cc8 100644 --- a/src/patcher/from-docx.ts +++ b/src/patcher/from-docx.ts @@ -132,38 +132,37 @@ export const patchDocument = async { - // We need to replace external hyperlinks with concrete hyperlinks - if (element instanceof ExternalHyperlink) { - const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId()); - // eslint-disable-next-line functional/immutable-data - hyperlinkRelationshipAdditions.push({ - key, - hyperlink: { - id: concreteHyperlink.linkId, - link: element.options.link, - }, - }); - return concreteHyperlink; - } else { - return element; - } - }), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any, - patchText, - context, - keepOriginalStyles, - }); - } catch { + const { didFindOccurrence } = replacer({ + json, + patch: { + ...patchValue, + children: patchValue.children.map((element) => { + // We need to replace external hyperlinks with concrete hyperlinks + if (element instanceof ExternalHyperlink) { + const concreteHyperlink = new ConcreteHyperlink(element.options.children, uniqueId()); + // eslint-disable-next-line functional/immutable-data + hyperlinkRelationshipAdditions.push({ + key, + hyperlink: { + id: concreteHyperlink.linkId, + link: element.options.link, + }, + }); + return concreteHyperlink; + } else { + return element; + } + }), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + patchText, + context, + keepOriginalStyles, + }); + if (!didFindOccurrence) { break; } } diff --git a/src/patcher/replacer.spec.ts b/src/patcher/replacer.spec.ts index 5b56cace6e..314a83c7e2 100644 --- a/src/patcher/replacer.spec.ts +++ b/src/patcher/replacer.spec.ts @@ -78,24 +78,23 @@ export const MOCK_JSON = { 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(); + const { didFindOccurrence } = replacer({ + json: { + elements: [], + }, + patch: { + type: PatchType.PARAGRAPH, + children: [], + }, + patchText: "hello", + // eslint-disable-next-line functional/prefer-readonly-type + context: vi.fn<[], IContext>()(), + }); + expect(didFindOccurrence).toBe(false); }); it("should replace paragraph type", () => { - const output = replacer({ + const { element, didFindOccurrence } = replacer({ json: JSON.parse(JSON.stringify(MOCK_JSON)), patch: { type: PatchType.PARAGRAPH, @@ -111,11 +110,12 @@ describe("replacer", () => { }, }); - expect(JSON.stringify(output)).to.contain("Delightful Header"); + expect(JSON.stringify(element)).to.contain("Delightful Header"); + expect(didFindOccurrence).toBe(true); }); it("should replace paragraph type keeping original styling if keepOriginalStyles is true", () => { - const output = replacer({ + const { element, didFindOccurrence } = replacer({ json: JSON.parse(JSON.stringify(MOCK_JSON)), patch: { type: PatchType.PARAGRAPH, @@ -132,8 +132,8 @@ describe("replacer", () => { keepOriginalStyles: true, }); - expect(JSON.stringify(output)).to.contain("sweet"); - expect(output.elements![0].elements![1].elements).toMatchObject([ + expect(JSON.stringify(element)).to.contain("sweet"); + expect(element.elements![0].elements![1].elements).toMatchObject([ { type: "element", name: "w:r", @@ -187,10 +187,11 @@ describe("replacer", () => { ], }, ]); + expect(didFindOccurrence).toBe(true); }); it("should replace document type", () => { - const output = replacer({ + const { element, didFindOccurrence } = replacer({ json: JSON.parse(JSON.stringify(MOCK_JSON)), patch: { type: PatchType.DOCUMENT, @@ -206,12 +207,13 @@ describe("replacer", () => { }, }); - expect(JSON.stringify(output)).to.contain("Lorem ipsum paragraph"); + expect(JSON.stringify(element)).to.contain("Lorem ipsum paragraph"); + expect(didFindOccurrence).toBe(true); }); it("should replace", () => { // cspell:disable - const output = replacer({ + const { element, didFindOccurrence } = replacer({ json: { elements: [ { @@ -655,7 +657,8 @@ describe("replacer", () => { }, }); - expect(JSON.stringify(output)).to.contain("Lorem ipsum paragraph"); + expect(JSON.stringify(element)).to.contain("Lorem ipsum paragraph"); + expect(didFindOccurrence).toBe(true); }); }); }); diff --git a/src/patcher/replacer.ts b/src/patcher/replacer.ts index 49b206db3d..7d47f4eb76 100644 --- a/src/patcher/replacer.ts +++ b/src/patcher/replacer.ts @@ -14,6 +14,11 @@ const formatter = new Formatter(); const SPLIT_TOKEN = "ɵ"; +type IReplacerResult = { + readonly element: Element; + readonly didFindOccurrence: boolean; +}; + export const replacer = ({ json, patch, @@ -26,11 +31,11 @@ export const replacer = ({ readonly patchText: string; readonly context: IContext; readonly keepOriginalStyles?: boolean; -}): Element => { +}): IReplacerResult => { const renderedParagraphs = findLocationOfText(json, patchText); if (renderedParagraphs.length === 0) { - throw new Error(`Could not find text ${patchText}`); + return { element: json, didFindOccurrence: false }; } for (const renderedParagraph of renderedParagraphs) { @@ -85,7 +90,7 @@ export const replacer = ({ } } - return json; + return { element: json, didFindOccurrence: true }; }; const goToElementFromPath = (json: Element, path: readonly number[]): Element => {