diff --git a/demo/35-hyperlinks.ts b/demo/35-hyperlinks.ts index 85fa5fc1f3..c9ef863aa4 100644 --- a/demo/35-hyperlinks.ts +++ b/demo/35-hyperlinks.ts @@ -1,7 +1,7 @@ // Example on how to add hyperlinks to websites // Import from 'docx' rather than '../build' if you install from npm import * as fs from "fs"; -import { ExternalHyperlink, Document, Packer, Paragraph, Media, TextRun, Footer } from "../build"; +import { Document, ExternalHyperlink, Footer, Media, Packer, Paragraph, TextRun } from "../build"; const doc = new Document({}); @@ -26,6 +26,24 @@ doc.addSection({ ], }), }, + headers: { + default: new Footer({ + children: [ + new Paragraph({ + children: [ + new TextRun("Click here for the "), + new ExternalHyperlink({ + child: new TextRun({ + text: "Header external hyperlink", + style: "Hyperlink", + }), + link: "http://www.google.com", + }), + ], + }), + ], + }), + }, children: [ new Paragraph({ children: [ diff --git a/src/export/formatter.ts b/src/export/formatter.ts index b863ea4b97..a91702212e 100644 --- a/src/export/formatter.ts +++ b/src/export/formatter.ts @@ -1,8 +1,8 @@ +import { IViewWrapper } from "file/document-wrapper"; import { BaseXmlComponent, IXmlableObject } from "file/xml-components"; -import { File } from "../file"; export class Formatter { - public format(input: BaseXmlComponent, file?: File): IXmlableObject { + public format(input: BaseXmlComponent, file?: IViewWrapper): IXmlableObject { const output = input.prepForXml(file); if (output) { diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts index a0c73090fc..aed3951ab5 100644 --- a/src/export/packer/next-compiler.ts +++ b/src/export/packer/next-compiler.ts @@ -71,7 +71,7 @@ export class Compiler { file.verifyUpdateFields(); const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1; - const documentXmlData = xml(this.formatter.format(file.Document.View, file), prettify); + const documentXmlData = xml(this.formatter.format(file.Document.View, file.Document), prettify); const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media); return { @@ -85,7 +85,7 @@ export class Compiler { ); }); - return xml(this.formatter.format(file.Document.Relationships, file), prettify); + return xml(this.formatter.format(file.Document.Relationships, file.Document), prettify); })(), path: "word/_rels/document.xml.rels", }, @@ -99,11 +99,11 @@ export class Compiler { path: "word/document.xml", }, Styles: { - data: xml(this.formatter.format(file.Styles, file), prettify), + data: xml(this.formatter.format(file.Styles, file.Document), prettify), path: "word/styles.xml", }, Properties: { - data: xml(this.formatter.format(file.CoreProperties, file), { + data: xml(this.formatter.format(file.CoreProperties, file.Document), { declaration: { standalone: "yes", encoding: "UTF-8", @@ -112,15 +112,15 @@ export class Compiler { path: "docProps/core.xml", }, Numbering: { - data: xml(this.formatter.format(file.Numbering, file), prettify), + data: xml(this.formatter.format(file.Numbering, file.Document), prettify), path: "word/numbering.xml", }, FileRelationships: { - data: xml(this.formatter.format(file.FileRelationships, file), prettify), + data: xml(this.formatter.format(file.FileRelationships, file.Document), prettify), path: "_rels/.rels", }, HeaderRelationships: file.Headers.map((headerWrapper, index) => { - const xmlData = xml(this.formatter.format(headerWrapper.View, file), prettify); + const xmlData = xml(this.formatter.format(headerWrapper.View, headerWrapper), prettify); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -132,12 +132,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(headerWrapper.Relationships, file), prettify), + data: xml(this.formatter.format(headerWrapper.Relationships, headerWrapper), prettify), path: `word/_rels/header${index + 1}.xml.rels`, }; }), FooterRelationships: file.Footers.map((footerWrapper, index) => { - const xmlData = xml(this.formatter.format(footerWrapper.View, file), prettify); + const xmlData = xml(this.formatter.format(footerWrapper.View, footerWrapper), prettify); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); mediaDatas.forEach((mediaData, i) => { @@ -149,12 +149,12 @@ export class Compiler { }); return { - data: xml(this.formatter.format(footerWrapper.Relationships, file), prettify), + data: xml(this.formatter.format(footerWrapper.Relationships, footerWrapper), prettify), path: `word/_rels/footer${index + 1}.xml.rels`, }; }), Headers: file.Headers.map((headerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(headerWrapper.View, file), prettify); + const tempXmlData = xml(this.formatter.format(headerWrapper.View, headerWrapper), prettify); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -165,7 +165,7 @@ export class Compiler { }; }), Footers: file.Footers.map((footerWrapper, index) => { - const tempXmlData = xml(this.formatter.format(footerWrapper.View, file), prettify); + const tempXmlData = xml(this.formatter.format(footerWrapper.View, footerWrapper), prettify); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); // TODO: 0 needs to be changed when headers get relationships of their own const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); @@ -176,19 +176,19 @@ export class Compiler { }; }), ContentTypes: { - data: xml(this.formatter.format(file.ContentTypes, file), prettify), + data: xml(this.formatter.format(file.ContentTypes, file.Document), prettify), path: "[Content_Types].xml", }, AppProperties: { - data: xml(this.formatter.format(file.AppProperties, file), prettify), + data: xml(this.formatter.format(file.AppProperties, file.Document), prettify), path: "docProps/app.xml", }, FootNotes: { - data: xml(this.formatter.format(file.FootNotes, file), prettify), + data: xml(this.formatter.format(file.FootNotes, file.Document), prettify), path: "word/footnotes.xml", }, Settings: { - data: xml(this.formatter.format(file.Settings, file), prettify), + data: xml(this.formatter.format(file.Settings, file.Document), prettify), path: "word/settings.xml", }, }; diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts index ea0d24a448..4b0e588809 100644 --- a/src/file/document/body/body.ts +++ b/src/file/document/body/body.ts @@ -1,6 +1,7 @@ +import { IViewWrapper } from "file/document-wrapper"; import { IXmlableObject, XmlComponent } from "file/xml-components"; + import { Paragraph, ParagraphProperties, TableOfContents } from "../.."; -import { File } from "../../../file"; import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; export class Body extends XmlComponent { @@ -25,7 +26,7 @@ export class Body extends XmlComponent { this.sections.push(new SectionProperties(options)); } - public prepForXml(file?: File): IXmlableObject | undefined { + public prepForXml(file?: IViewWrapper): IXmlableObject | undefined { if (this.sections.length === 1) { this.root.splice(0, 1); this.root.push(this.sections.pop() as SectionProperties); diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts index 211697b850..4302801a01 100644 --- a/src/file/paragraph/paragraph.spec.ts +++ b/src/file/paragraph/paragraph.spec.ts @@ -5,7 +5,7 @@ import { stub } from "sinon"; import { Formatter } from "export/formatter"; import { EMPTY_OBJECT } from "file/xml-components"; -import { File } from "../file"; +import { IViewWrapper } from "../document-wrapper"; import { ShadingType } from "../table/shading"; import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting"; import { Bookmark, ExternalHyperlink } from "./links"; @@ -804,12 +804,10 @@ describe("Paragraph", () => { ], }); const fileMock = ({ - Document: { - Relationships: { - createRelationship: () => ({}), - }, + Relationships: { + createRelationship: () => ({}), }, - } as unknown) as File; + } as unknown) as IViewWrapper; paragraph.prepForXml(fileMock); const tree = new Formatter().format(paragraph); expect(tree).to.deep.equal({ diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 2e75c77f4e..7c05ee711c 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -4,7 +4,7 @@ import * as shortid from "shortid"; import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"; import { IXmlableObject, XmlComponent } from "file/xml-components"; -import { File } from "../file"; +import { IViewWrapper } from "../document-wrapper"; import { TargetModeType } from "../relationships/relationship/relationship"; import { DeletedTextRun, InsertedTextRun } from "../track-revision"; import { PageBreak } from "./formatting/page-break"; @@ -74,12 +74,12 @@ export class Paragraph extends XmlComponent { } } - public prepForXml(file: File): IXmlableObject | undefined { + public prepForXml(file: IViewWrapper): IXmlableObject | undefined { for (const element of this.root) { if (element instanceof ExternalHyperlink) { const index = this.root.indexOf(element); const concreteHyperlink = new ConcreteHyperlink(element.options.child, shortid.generate().toLowerCase()); - file.Document.Relationships.createRelationship( + file.Relationships.createRelationship( concreteHyperlink.linkId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", element.options.link, diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts index 6fbd748cf5..e598888f83 100644 --- a/src/file/table/table-cell/table-cell.ts +++ b/src/file/table/table-cell/table-cell.ts @@ -1,9 +1,9 @@ // http://officeopenxml.com/WPtableGrid.php +import { IViewWrapper } from "file/document-wrapper"; import { Paragraph } from "file/paragraph"; import { BorderStyle } from "file/styles"; import { IXmlableObject, XmlComponent } from "file/xml-components"; -import { File } from "../../file"; import { ITableShadingAttributesProperties } from "../shading"; import { Table } from "../table"; import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins"; @@ -115,7 +115,7 @@ export class TableCell extends XmlComponent { } } - public prepForXml(file?: File): IXmlableObject | undefined { + public prepForXml(file?: IViewWrapper): IXmlableObject | undefined { // Cells must end with a paragraph if (!(this.root[this.root.length - 1] instanceof Paragraph)) { this.root.push(new Paragraph({})); diff --git a/src/file/xml-components/base.ts b/src/file/xml-components/base.ts index 782dfdba12..4bb37c8ad9 100644 --- a/src/file/xml-components/base.ts +++ b/src/file/xml-components/base.ts @@ -1,4 +1,4 @@ -import { File } from "../file"; +import { IViewWrapper } from "../document-wrapper"; import { IXmlableObject } from "./xmlable-object"; export abstract class BaseXmlComponent { @@ -10,7 +10,7 @@ export abstract class BaseXmlComponent { this.rootKey = rootKey; } - public abstract prepForXml(file?: File): IXmlableObject | undefined; + public abstract prepForXml(file?: IViewWrapper): IXmlableObject | undefined; public get IsDeleted(): boolean { return this.deleted; diff --git a/src/file/xml-components/xml-component.ts b/src/file/xml-components/xml-component.ts index b06f73b930..84fd5f98e4 100644 --- a/src/file/xml-components/xml-component.ts +++ b/src/file/xml-components/xml-component.ts @@ -1,4 +1,4 @@ -import { File } from "../file"; +import { IViewWrapper } from "../document-wrapper"; import { BaseXmlComponent } from "./base"; import { IXmlableObject } from "./xmlable-object"; @@ -13,7 +13,7 @@ export abstract class XmlComponent extends BaseXmlComponent { this.root = new Array(); } - public prepForXml(file?: File): IXmlableObject | undefined { + public prepForXml(file?: IViewWrapper): IXmlableObject | undefined { const children = this.root .filter((c) => { if (c instanceof BaseXmlComponent) {