Work on replacer logic
This commit is contained in:
@ -9,6 +9,18 @@ patchDocument(fs.readFileSync("demo/assets/simple-template.docx"), {
|
||||
children: [new TextRun("John Doe")],
|
||||
text: "{{ name }}",
|
||||
},
|
||||
{
|
||||
children: [new TextRun("Heading wow!")],
|
||||
text: "{{ table_heading_1 }}",
|
||||
},
|
||||
{
|
||||
children: [new TextRun("#657")],
|
||||
text: "{{ item_1 }}",
|
||||
},
|
||||
{
|
||||
children: [new TextRun("Lorem ipsum paragraph")],
|
||||
text: "{{ paragraph_replace }}",
|
||||
},
|
||||
],
|
||||
}).then((doc) => {
|
||||
fs.writeFileSync("My Document.docx", doc);
|
||||
|
56
src/templater/paragraph-split-inject.ts
Normal file
56
src/templater/paragraph-split-inject.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { Element } from "xml-js";
|
||||
import { createTextElementContents } from "./util";
|
||||
|
||||
export const findRunElementIndexWithToken = (paragraphElement: Element, token: string): number => {
|
||||
for (let i = 0; i < (paragraphElement.elements ?? []).length; i++) {
|
||||
const element = paragraphElement.elements![i];
|
||||
if (element.type === "element" && element.name === "w:r") {
|
||||
const textElement = (element.elements ?? []).filter((e) => e.type === "element" && e.name === "w:t");
|
||||
|
||||
for (const text of textElement) {
|
||||
if ((text.elements?.[0].text as string)?.includes(token)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// return -1;
|
||||
throw new Error("Token not found");
|
||||
};
|
||||
|
||||
export const splitRunElement = (runElement: Element, token: string): { readonly left: Element; readonly right: Element } => {
|
||||
let splitIndex = 0;
|
||||
|
||||
const splitElements =
|
||||
runElement.elements
|
||||
?.map((e, i) => {
|
||||
if (e.type === "element" && e.name === "w:t") {
|
||||
const text = e.elements?.[0].text as string;
|
||||
const splitText = text.split(token);
|
||||
const newElements = splitText.map((t) => ({
|
||||
...e,
|
||||
attributes: {
|
||||
"xml:space": "preserve",
|
||||
},
|
||||
elements: createTextElementContents(t),
|
||||
}));
|
||||
splitIndex = i;
|
||||
return newElements;
|
||||
} else {
|
||||
return e;
|
||||
}
|
||||
})
|
||||
.flat() ?? [];
|
||||
|
||||
const leftRunElement: Element = {
|
||||
...JSON.parse(JSON.stringify(runElement)),
|
||||
elements: splitElements.slice(0, splitIndex + 1),
|
||||
};
|
||||
|
||||
const rightRunElement: Element = {
|
||||
...JSON.parse(JSON.stringify(runElement)),
|
||||
elements: splitElements.slice(splitIndex + 1),
|
||||
};
|
||||
|
||||
return { left: leftRunElement, right: rightRunElement };
|
||||
};
|
@ -1,10 +1,6 @@
|
||||
import { Element } from "xml-js";
|
||||
import * as xml from "xml";
|
||||
|
||||
import { Formatter } from "@export/formatter";
|
||||
import { Text } from "@file/paragraph/run/run-components/text";
|
||||
|
||||
import { toJson } from "./util";
|
||||
import { createTextElementContents } from "./util";
|
||||
import { IRenderedParagraphNode } from "./run-renderer";
|
||||
|
||||
enum ReplaceMode {
|
||||
@ -13,8 +9,6 @@ enum ReplaceMode {
|
||||
END,
|
||||
}
|
||||
|
||||
const formatter = new Formatter();
|
||||
|
||||
export const replaceTokenInParagraphElement = ({
|
||||
paragraphElement,
|
||||
renderedParagraph,
|
||||
@ -63,10 +57,8 @@ export const replaceTokenInParagraphElement = ({
|
||||
};
|
||||
|
||||
const patchTextElement = (element: Element, text: string): Element => {
|
||||
const textJson = toJson(xml(formatter.format(new Text({ text }))));
|
||||
|
||||
// eslint-disable-next-line functional/immutable-data
|
||||
element.elements = textJson.elements;
|
||||
element.elements = createTextElementContents(text);
|
||||
|
||||
return element;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ import { IPatch } from "./from-docx";
|
||||
import { toJson } from "./util";
|
||||
import { IRenderedParagraphNode } from "./run-renderer";
|
||||
import { replaceTokenInParagraphElement } from "./paragraph-token-replacer";
|
||||
import { findRunElementIndexWithToken, splitRunElement } from "./paragraph-split-inject";
|
||||
|
||||
const formatter = new Formatter();
|
||||
|
||||
@ -18,7 +19,6 @@ export const replacer = (json: Element, options: IPatch, renderedParagraphs: rea
|
||||
if (child instanceof Paragraph) {
|
||||
console.log("is para");
|
||||
} else if (child instanceof TextRun) {
|
||||
console.log("paragrapghs", JSON.stringify(renderedParagraphs, null, 2));
|
||||
for (const renderedParagraph of renderedParagraphs) {
|
||||
const textJson = toJson(xml(formatter.format(child)));
|
||||
const paragraphElement = goToElementFromPath(json, renderedParagraph.path);
|
||||
@ -33,9 +33,6 @@ export const replacer = (json: Element, options: IPatch, renderedParagraphs: rea
|
||||
} else {
|
||||
// Hard case where the text is only part of the paragraph
|
||||
|
||||
console.log("hard case");
|
||||
console.log("paragraphElement", JSON.stringify(paragraphElement, null, 2));
|
||||
|
||||
replaceTokenInParagraphElement({
|
||||
paragraphElement,
|
||||
renderedParagraph,
|
||||
@ -43,6 +40,12 @@ export const replacer = (json: Element, options: IPatch, renderedParagraphs: rea
|
||||
replacementText: SPLIT_TOKEN,
|
||||
});
|
||||
|
||||
const index = findRunElementIndexWithToken(paragraphElement, SPLIT_TOKEN);
|
||||
|
||||
const { left, right } = splitRunElement(paragraphElement.elements![index], SPLIT_TOKEN);
|
||||
// eslint-disable-next-line functional/immutable-data
|
||||
paragraphElement.elements!.splice(index, 1, left, ...textJson.elements!, right);
|
||||
console.log(index, JSON.stringify(paragraphElement.elements![index], null, 2));
|
||||
console.log("paragraphElement after", JSON.stringify(paragraphElement, null, 2));
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ const renderRunNode = (node: Element, index: number, currentRunStringIndex: numb
|
||||
|
||||
const parts = node.elements
|
||||
.map((element, i: number) =>
|
||||
element.name === "w:t" && element.elements
|
||||
element.name === "w:t" && element.elements && element.elements.length > 0
|
||||
? {
|
||||
text: element.elements[0].text?.toString() ?? "",
|
||||
index: i,
|
||||
|
@ -1,6 +1,19 @@
|
||||
import { xml2js, Element } from "xml-js";
|
||||
import * as xml from "xml";
|
||||
|
||||
import { Formatter } from "@export/formatter";
|
||||
import { Text } from "@file/paragraph/run/run-components/text";
|
||||
|
||||
const formatter = new Formatter();
|
||||
|
||||
export const toJson = (xmlData: string): Element => {
|
||||
const xmlObj = xml2js(xmlData, { compact: false }) as Element;
|
||||
return xmlObj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line functional/prefer-readonly-type
|
||||
export const createTextElementContents = (text: string): Element[] => {
|
||||
const textJson = toJson(xml(formatter.format(new Text({ text }))));
|
||||
|
||||
return textJson.elements![0].elements ?? [];
|
||||
};
|
||||
|
Reference in New Issue
Block a user