diff --git a/package.json b/package.json index e10bd3b7ba..e63dd166bf 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "fast-xml-parser": "^3.3.6", "image-size": "^0.6.2", "jszip": "^3.1.5", - "lodash.clonedeep": "^4.5.0", "xml": "^1.0.1" }, "author": "Dolan Miu", diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index af00b2bc92..1ee02bf589 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -34,8 +34,6 @@ export class Compiler { } public async compile(file: File): Promise { - file.generateTablesOfContents(); - const zip = new JSZip(); const xmlifiedFileMapping = this.xmlifyFile(file); @@ -65,6 +63,7 @@ export class Compiler { } private xmlifyFile(file: File): IXmlifyedFileMapping { + file.verifyUpdateFields(); return { Document: { data: xml(this.formatter.format(file.Document), true), diff --git a/src/file/file.ts b/src/file/file.ts index 63d5fa1656..afa268a5a7 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -8,16 +8,14 @@ import { FootNotes } from "./footnotes"; import { HeaderWrapper } from "./header-wrapper"; import { Image, Media } from "./media"; import { Numbering } from "./numbering"; -import { Bookmark, Hyperlink, Paragraph, Run, TextRun } from "./paragraph"; -import { Begin, End, Separate } from "./paragraph/run/field"; -import { Tab } from "./paragraph/run/tab"; +import { Bookmark, Hyperlink, Paragraph } from "./paragraph"; import { Relationships } from "./relationships"; import { Settings } from "./settings"; import { Styles } from "./styles"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; import { DefaultStylesFactory } from "./styles/factory"; import { Table } from "./table"; -import { PageReferenceInstruction, TableOfContents } from "./table-of-contents"; +import { TableOfContents } from "./table-of-contents"; export class File { private readonly document: Document; @@ -36,7 +34,6 @@ export class File { private readonly appProperties: AppProperties; private currentRelationshipId: number = 1; - private currentTocBookmarkId: number = 1; constructor(options?: IPropertiesOptions, sectionPropertiesOptions?: SectionPropertiesOptions) { if (!options) { @@ -297,76 +294,9 @@ export class File { return this.settings; } - public generateTablesOfContents(): void { - // console.log("generateTablesOfContents"); - const TOCs = this.document.getTablesOfContents(); - if (TOCs && TOCs.length) { + public verifyUpdateFields(): void { + if (this.document.getTablesOfContents().length) { this.settings.addUpdateFields(); - TOCs.forEach((child) => this.generateContent(child)); } } - - private generateContent(toc: TableOfContents): void { - // console.log("TOC", JSON.stringify(toc)); - if (toc.getHeaderRange()) { - this.generateContentForHeaderRange(toc); - } - } - - private generateContentForHeaderRange(toc: TableOfContents): void { - const headerRange = toc.getHeaderRange(); - const hyphenIndex = headerRange.indexOf("-"); - // console.log("Hyphen Index: ", hyphenIndex); - if (hyphenIndex !== -1) { - const rangeBegin = parseInt(headerRange.substring(0, hyphenIndex), 10); - const rangeEnd = parseInt(headerRange.substring(hyphenIndex + 1), 10); - const styles = new Array(); - for (let i = rangeBegin; i <= rangeEnd; i++) { - styles.push(`Heading${i}`); - } - // console.log("Find Headers for range ", rangeBegin, " - ", rangeEnd, styles.join(",")); - this.document - .getParagraphs() - .filter((paragraph) => this.paragraphContainAnyStyle(paragraph, styles)) - .forEach((paragraph) => this.generateContentForParagraph(paragraph, toc)); - } else { - throw new Error(`Invalid headerRange: '${headerRange}'`); - } - } - - private paragraphContainAnyStyle(paragraph: Paragraph, styles: string[]): boolean { - return paragraph.getStyles().some((style) => styles.indexOf(style.styleId) !== -1); - } - - private generateContentForParagraph(paragraph: Paragraph, toc: TableOfContents): void { - const bookmarkId = `_TOC_${this.currentTocBookmarkId}`; - // console.log("Generating content for paragraph: ", bookmarkId); - - // deep clone the original paragraph - const generatedParagraph = paragraph.clone() as Paragraph; - - generatedParagraph.clearPageBreaks().maxRightTabStop("dot"); - - const tabRun = new Run(); - tabRun.addChildElement(new Tab()); - generatedParagraph.addChildElement(tabRun); - - const beginRun = new Run(); - beginRun.addChildElement(new Begin(true)); - beginRun.addChildElement(new PageReferenceInstruction(bookmarkId)); - beginRun.addChildElement(new Separate()); - generatedParagraph.addRun(beginRun); - - generatedParagraph.addRun(new TextRun("?")); - - const endRun = new Run(); - endRun.addChildElement(new End()); - generatedParagraph.addRun(endRun); - - toc.addGeneratedContent(generatedParagraph); - - paragraph.addBookmark(this.createBookmark(bookmarkId, "")); - // console.log("Paragraph after content generation", JSON.stringify(paragraph, null, 2)); - this.currentTocBookmarkId++; - } } diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 2ab8836f96..2413769b1e 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -393,43 +393,4 @@ describe("Paragraph", () => { }); }); }); - - describe("#clone", () => { - it("changes in a cloned paragraph must not affect the original paragraph", () => { - paragraph.pageBreakBefore(); - - const tree = new Formatter().format(paragraph); - expect(tree).to.deep.equal({ "w:p": [{ "w:pPr": [{ "w:pageBreakBefore": [] }] }] }, "Paragraph with a page break before"); - - const clonedParagraph = paragraph.clone(); - expect(clonedParagraph).to.be.instanceof(file.Paragraph); - expect(clonedParagraph.paragraphProperties).to.be.instanceof(file.ParagraphProperties); - - const clonedTree = new Formatter().format(clonedParagraph); - expect(clonedTree).to.deep.equal( - { - "w:p": [{ "w:pPr": [{ "w:pageBreakBefore": [] }] }], - }, - "Cloned Paragraph with page break before", - ); - - clonedParagraph.clearPageBreaks(); - - const clonedTreeAfter = new Formatter().format(clonedParagraph); - expect(clonedTreeAfter).to.deep.equal( - { - "w:p": [{ "w:pPr": [] }], - }, - "Cloned Paragraph after clearPageBreaks must have no properties", - ); - - const treeAfter = new Formatter().format(paragraph); - expect(treeAfter).to.deep.equal( - { - "w:p": [{ "w:pPr": [{ "w:pageBreakBefore": [] }] }], - }, - "Paragraph after clearPageBreaks in Cloned Paragraph must keep the properties.", - ); - }); - }); }); diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 16f6ef0cd1..a047ef1fa6 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -1,6 +1,4 @@ // http://officeopenxml.com/WPparagraph.php -import * as cloneDeep from "lodash.clonedeep"; - import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"; import { Image } from "file/media"; import { Num } from "file/numbering/num"; @@ -252,8 +250,4 @@ export class Paragraph extends XmlComponent { this.properties.clearPageBreaks(); return this; } - - public clone(): Paragraph { - return cloneDeep(this, false); - } } diff --git a/src/file/table-of-contents/index.ts b/src/file/table-of-contents/index.ts index 0f593a9652..13700e9bfb 100644 --- a/src/file/table-of-contents/index.ts +++ b/src/file/table-of-contents/index.ts @@ -1,2 +1 @@ export * from "./table-of-contents"; -export * from "./page-reference-instruction"; diff --git a/src/file/table-of-contents/page-reference-instruction.ts b/src/file/table-of-contents/page-reference-instruction.ts deleted file mode 100644 index e630e164b4..0000000000 --- a/src/file/table-of-contents/page-reference-instruction.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; - -class TextAttributes extends XmlAttributeComponent<{ space: "default" | "preserve" }> { - protected xmlKeys = { space: "xml:space" }; -} - -export class PageReferenceInstruction extends XmlComponent { - constructor(bookmarkId: string) { - super("w:instrText"); - this.root.push(new TextAttributes({ space: "preserve" })); - this.root.push(`PAGEREF ${bookmarkId} \h`); - } -} diff --git a/src/file/table-of-contents/sdt-content.ts b/src/file/table-of-contents/sdt-content.ts index a059886b42..e668da6052 100644 --- a/src/file/table-of-contents/sdt-content.ts +++ b/src/file/table-of-contents/sdt-content.ts @@ -1,12 +1,7 @@ -import { Paragraph } from "file/paragraph"; import { XmlComponent } from "file/xml-components"; export class SdtContent extends XmlComponent { constructor() { super("w:sdtContent"); } - - public addGeneratedContent(paragraph: Paragraph): void { - this.root.splice(this.root.length - 1, 0, paragraph); - } } diff --git a/src/file/table-of-contents/table-of-contents.ts b/src/file/table-of-contents/table-of-contents.ts index ded1be62cc..d4a93b57e1 100644 --- a/src/file/table-of-contents/table-of-contents.ts +++ b/src/file/table-of-contents/table-of-contents.ts @@ -8,41 +8,26 @@ import { SdtProperties } from "./sdt-properties"; import { TableOfContentsInstruction } from "./table-of-contents-instruction"; export class TableOfContents extends XmlComponent { - // private readonly tocProperties: TableOfContentsProperties; - private readonly properties: SdtProperties; - - private readonly content: SdtContent; - - private readonly instruction: TableOfContentsInstruction; - - constructor(/*tocProperties?: TableOfContentsProperties*/) { + constructor() { super("w:sdt"); - this.properties = new SdtProperties("Table of Contents"); - this.content = new SdtContent(); - this.instruction = new TableOfContentsInstruction(); - this.root.push(this.properties); - this.root.push(this.content); - // this.tocProperties = tocProperties || new TableOfContentsProperties(); + this.root.push(new SdtProperties("Table of Contents")); + + const content = new SdtContent(); + const beginParagraph = new Paragraph(); const beginRun = new Run(); beginRun.addChildElement(new Begin(true)); - beginRun.addChildElement(this.instruction); + beginRun.addChildElement(new TableOfContentsInstruction()); beginRun.addChildElement(new Separate()); beginParagraph.addRun(beginRun); - this.content.addChildElement(beginParagraph); + content.addChildElement(beginParagraph); const endParagraph = new Paragraph(); const endRun = new Run(); endRun.addChildElement(new End()); endParagraph.addRun(endRun); - this.content.addChildElement(endParagraph); - } + content.addChildElement(endParagraph); - public getHeaderRange(): string { - return this.instruction.getHeaderRange(); - } - - public addGeneratedContent(paragraph: Paragraph): void { - this.content.addGeneratedContent(paragraph); + this.root.push(content); } }