diff --git a/src/file/file.ts b/src/file/file.ts index 328598b4da..2ab3f159fc 100644 --- a/src/file/file.ts +++ b/src/file/file.ts @@ -8,7 +8,7 @@ import { FooterWrapper } from "./footer-wrapper"; import { HeaderWrapper } from "./header-wrapper"; import { Media } from "./media"; import { Numbering } from "./numbering"; -import { Paragraph, PictureRun } from "./paragraph"; +import { Hyperlink, Paragraph, PictureRun } from "./paragraph"; import { Relationships } from "./relationships"; import { Styles } from "./styles"; import { ExternalStylesFactory } from "./styles/external-styles-factory"; @@ -129,6 +129,18 @@ export class File { return mediaData; } + public createHyperlink(link: string, text?: string): Hyperlink { + text = text === undefined ? link : text; + const hyperlink = new Hyperlink(text, this.docRelationships.RelationshipCount); + this.docRelationships.createRelationship( + hyperlink.linkId, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", + link, + "External", + ); + return hyperlink; + } + public get Document(): Document { return this.document; } diff --git a/src/file/paragraph/index.ts b/src/file/paragraph/index.ts index 08d4e487cf..68a1b0b800 100644 --- a/src/file/paragraph/index.ts +++ b/src/file/paragraph/index.ts @@ -2,3 +2,4 @@ export * from "./formatting"; export * from "./paragraph"; export * from "./properties"; export * from "./run"; +export * from "./links"; diff --git a/src/file/paragraph/links/hyperlink-attributes.ts b/src/file/paragraph/links/hyperlink-attributes.ts new file mode 100644 index 0000000000..d51f5a8b65 --- /dev/null +++ b/src/file/paragraph/links/hyperlink-attributes.ts @@ -0,0 +1,13 @@ +import { XmlAttributeComponent } from "file/xml-components"; + +export interface IHyperlinkAttributesProperties { + id?: string; + history: number; +} + +export class HyperlinkAttributes extends XmlAttributeComponent { + protected xmlKeys = { + id: "r:id", + history: "w:history", + }; +} diff --git a/src/file/paragraph/links/hyperlink.spec.ts b/src/file/paragraph/links/hyperlink.spec.ts new file mode 100644 index 0000000000..e3f0b58c49 --- /dev/null +++ b/src/file/paragraph/links/hyperlink.spec.ts @@ -0,0 +1,40 @@ +import { assert, expect } from "chai"; + +import { Formatter } from "../../../export/formatter"; +import { Utility } from "../../../tests/utility"; +import { Hyperlink } from "./"; + +describe("Hyperlink", () => { + let hyperlink: Hyperlink; + + beforeEach(() => { + hyperlink = new Hyperlink("https://example.com", 0); + }); + + describe("#constructor()", () => { + it("should create a hyperlink with correct root key", () => { + const newJson = Utility.jsonify(hyperlink); + assert.equal(newJson.rootKey, "w:hyperlink"); + }); + + it("should create a hyperlink with right attributes", () => { + const newJson = Utility.jsonify(hyperlink); + const attributes = { + id: "rId1", + history: 1, + }; + assert.equal(JSON.stringify(newJson.root[0].root), JSON.stringify(attributes)); + }); + + it("should create a hyperlink with a run component", () => { + const tree = new Formatter().format(hyperlink); + const runJson = { + "w:r": [ + { "w:rPr": [{ "w:rStyle": [{ _attr: { "w:val": "Hyperlink" } }] }] }, + { "w:t": [{ _attr: { "xml:space": "preserve" } }, "https://example.com"] }, + ], + }; + expect(tree["w:hyperlink"][1]).to.deep.equal(runJson); + }); + }); +}); diff --git a/src/file/paragraph/links/hyperlink.ts b/src/file/paragraph/links/hyperlink.ts new file mode 100644 index 0000000000..53f72e72bd --- /dev/null +++ b/src/file/paragraph/links/hyperlink.ts @@ -0,0 +1,21 @@ +// http://officeopenxml.com/WPhyperlink.php + +import { XmlComponent } from "file/xml-components"; +import { TextRun } from "../run"; +import { HyperlinkAttributes } from "./hyperlink-attributes"; + +export class Hyperlink extends XmlComponent { + public linkId: number; + + constructor(text: string, relationshipsCount: number) { + super("w:hyperlink"); + + this.linkId = relationshipsCount + 1; + const attributes = new HyperlinkAttributes({ + id: `rId${this.linkId}`, + history: 1, + }); + this.root.push(attributes); + this.root.push(new TextRun(text).style("Hyperlink")); + } +} diff --git a/src/file/paragraph/links/index.ts b/src/file/paragraph/links/index.ts new file mode 100644 index 0000000000..619d1bee30 --- /dev/null +++ b/src/file/paragraph/links/index.ts @@ -0,0 +1 @@ +export * from "./hyperlink"; diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index b9274a4d7a..2f75422077 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -13,6 +13,7 @@ import { ISpacingProperties, Spacing } from "./formatting/spacing"; import { Style } from "./formatting/style"; import { CenterTabStop, LeftTabStop, MaxRightTabStop, RightTabStop } from "./formatting/tab-stop"; import { NumberProperties } from "./formatting/unordered-list"; +import { Hyperlink } from "./links"; import { ParagraphProperties } from "./properties"; export class Paragraph extends XmlComponent { @@ -32,6 +33,11 @@ export class Paragraph extends XmlComponent { return this; } + public addHyperLink(hyperlink: Hyperlink): Paragraph { + this.root.push(hyperlink); + return this; + } + public createTextRun(text: string): TextRun { const run = new TextRun(text); this.addRun(run); diff --git a/src/file/relationships/relationship/relationship-attributes.ts b/src/file/relationships/relationship/relationship-attributes.ts index 1b23e26977..1cb3e116c0 100644 --- a/src/file/relationships/relationship/relationship-attributes.ts +++ b/src/file/relationships/relationship/relationship-attributes.ts @@ -4,6 +4,7 @@ export interface IRelationshipAttributesProperties { id: string; type: string; target: string; + targetMode?: string; } export class RelationshipAttributes extends XmlAttributeComponent { @@ -11,5 +12,6 @@ export class RelationshipAttributes extends XmlAttributeComponent