Files
docx-js/src/patcher/traverser.ts

63 lines
2.0 KiB
TypeScript
Raw Normal View History

2023-02-17 10:38:03 +00:00
import { Element } from "xml-js";
2023-02-18 20:36:24 +00:00
2023-02-17 10:38:03 +00:00
import { IRenderedParagraphNode, renderParagraphNode } from "./run-renderer";
2023-02-18 20:36:24 +00:00
export interface ElementWrapper {
readonly element: Element;
readonly index: number;
readonly parent: ElementWrapper | undefined;
}
2023-02-17 10:38:03 +00:00
export interface ILocationOfText {
readonly parent: Element;
readonly startIndex: number;
readonly endIndex: number;
readonly currentText: string;
// This is optional because the text could start in the middle of a tag
readonly startElement?: Element;
// This is optional because the text could end in the middle of a tag
readonly endElement?: Element;
}
2023-02-18 20:36:24 +00:00
const elementsToWrapper = (wrapper: ElementWrapper): readonly ElementWrapper[] =>
wrapper.element.elements?.map((e, i) => ({
element: e,
index: i,
parent: wrapper,
})) ?? [];
export const findLocationOfText = (node: Element, text: string): readonly IRenderedParagraphNode[] => {
2023-02-17 10:38:03 +00:00
let renderedParagraphs: readonly IRenderedParagraphNode[] = [];
// eslint-disable-next-line functional/prefer-readonly-type
2023-02-18 20:36:24 +00:00
const queue: ElementWrapper[] = [
...(elementsToWrapper({
element: node,
index: 0,
parent: undefined,
}) ?? []),
];
2023-02-17 10:38:03 +00:00
// eslint-disable-next-line functional/immutable-data
2023-02-18 20:36:24 +00:00
let currentNode: ElementWrapper | undefined;
2023-02-17 10:38:03 +00:00
while (queue.length > 0) {
// eslint-disable-next-line functional/immutable-data
currentNode = queue.shift();
if (!currentNode) {
break;
}
2023-02-18 20:36:24 +00:00
if (currentNode.element.name === "w:p") {
2023-02-17 10:38:03 +00:00
renderedParagraphs = [...renderedParagraphs, renderParagraphNode(currentNode)];
} else {
// eslint-disable-next-line functional/immutable-data
2023-02-18 20:36:24 +00:00
queue.push(...(elementsToWrapper(currentNode) ?? []));
2023-02-17 10:38:03 +00:00
}
}
const filteredParagraphs = renderedParagraphs.filter((p) => p.text.includes(text));
2023-02-18 20:36:24 +00:00
return filteredParagraphs;
2023-02-17 10:38:03 +00:00
};