Skip to content

Commit

Permalink
Add hyperlink to a paragraph, set text and uri of a hyperlink (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
connium authored Apr 19, 2018
1 parent 7df44a5 commit b6bed4c
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 55 deletions.
34 changes: 28 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,33 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).


## 0.1.0 (2017-06-20)
## [Unreleased] (2018-??-??)
### Added
- **paragraph:** Add hyperlinks to a paragraph (), closes [#5](https://github.com/connium/simple-odf/issues/5)

## [0.2.0] (2018-01-12)
### Added
* **heading:** add headings to a document and modify their outline level
* **paragraph:** add paragraphs to a document and modify their text content
* **paragraph:** set page break before paragraph
* **paragraph:** set horizontal alignment
* **text-document:** create text documents and save them as flat XML ODF document
- **docs:** Add CHANGELOG
- **docs:** Improve and extend README
- **docs:** Add badges (dependencies, known vulnerabilities, version) to README
- **list:** Add basic list support (add/insert/get/set/remove item)
- **paragraph:** Overwrite text content
- **style:** Get horizontal alignment
- **test:** Add integration test

### Changed
- **general:** Export public API from / (no namespaces)
- **paragraph:** Rename text related functions in paragraph
- **heading:** Rename headline to heading

## 0.1.0 (2018-01-08)
### Added
- **heading:** Add headings to a document and modify their outline level
- **paragraph:** Add paragraphs to a document and modify their text content
- **paragraph:** Set page break before paragraph
- **paragraph:** Set horizontal alignment
- **text-document:** Create text documents and save them as flat XML ODF document

[Unreleased]: https://github.com/connium/simple-odf/compare/v0.2.0...HEAD
[0.3.0]: https://github.com/connium/simple-odf/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/connium/simple-odf/compare/v0.1.0...v0.2.0
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const document = new simpleOdf.TextDocument();
document.addHeadline("My First Document");

const p1 = document.addParagraph("The quick, brown fox jumps over a lazy dog.");
p1.appendTextContent("\nThe five boxing wizards jump quickly");
p1.appendTextContent("\nThe five boxing wizards jump quickly\n\n");
p1.appendHyperlink("Visit me", "http://example.org/");

document.addHeadline("Credits", 2);

Expand Down
5 changes: 4 additions & 1 deletion src/OdfAttributeName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export enum OdfAttributeName {
StyleFamily = "style:family",
StyleName = "style:name",

TextStyleName = "text:style-name",
TextOutlineLevel = "text:outline-level",
TextStyleName = "text:style-name",

XlinkHref = "xlink:href",
XlinkType = "xlink:type",
}
1 change: 1 addition & 0 deletions src/OdfElementName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum OdfElementName {
StyleTextProperties = "style:text-properties",
StyleParagraphProperties = "style:paragraph-properties",

TextHyperlink = "text:a",
TextHeading = "text:h",
TextLineBreak = "text:line-break",
TextList = "text:list",
Expand Down
61 changes: 61 additions & 0 deletions src/text/HyperLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { OdfAttributeName } from "../OdfAttributeName";
import { OdfElementName } from "../OdfElementName";
import { Text } from "./Text";

/**
* This class represents a hyperlink in a paragraph.
*
* @since 0.3.0
*/
export class Hyperlink extends Text {
/**
* Creates a hyperlink
*
* @param {string} text The text content of the hyperlink
* @param {string} uri The URI of the hyperlink
* @since 0.3.0
*/
public constructor(text: string, private uri: string) {
super(text);
}

/**
* Returns the URI of this hyperlink.
*
* @returns {string} The URI of this hyperlink
* @since 0.3.0
*/
public getURI(): string {
return this.uri;
}

/**
* Sets the URI for this hyperlink.
*
* @param {string} uri The new URI of this hyperlink
* @since 0.3.0
*/
public setURI(uri: string): void {
this.uri = uri;
}

/** @inheritDoc */
protected toXML(document: Document, parent: Element): void {
const text = this.getText();

if (text === undefined || text === "") {
return;
}

(document.firstChild as Element).setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");

const hyperlink = document.createElement(OdfElementName.TextHyperlink);
hyperlink.setAttribute(OdfAttributeName.XlinkType, "simple");
hyperlink.setAttribute(OdfAttributeName.XlinkHref, this.uri);

const textNode = document.createTextNode(text);
hyperlink.appendChild(textNode);

parent.appendChild(hyperlink);
}
}
77 changes: 39 additions & 38 deletions src/text/Paragraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { OdfElement } from "../OdfElement";
import { OdfElementName } from "../OdfElementName";
import { HorizontalAlignment } from "../style/HorizontalAlignment";
import { Style } from "../style/Style";
import { Hyperlink } from "./HyperLink";
import { Text } from "./Text";

/**
* This class represents a paragraph.
Expand All @@ -11,7 +13,6 @@ import { Style } from "../style/Style";
* @since 0.1.0
*/
export class Paragraph extends OdfElement {
private text: string | undefined;
private style: Style;

/**
Expand All @@ -23,18 +24,24 @@ export class Paragraph extends OdfElement {
public constructor(text?: string) {
super();

this.text = text;
this.appendText(text || "");

this.style = new Style();
}

/**
* Returns the text content of this paragraph.
* Note: This will only return the text; other elements and markup will be omitted.
*
* @returns {string | undefined} The text content of this paragraph
* @returns {string} The text content of this paragraph
* @since 0.1.0
*/
public getText(): string | undefined {
return this.text;
public getText(): string {
return this.getElements()
.map((value: OdfElement) => {
return value instanceof Text ? value.getText() : "";
})
.join("");
}

/**
Expand All @@ -44,22 +51,27 @@ export class Paragraph extends OdfElement {
* @since 0.1.0
*/
public appendText(text: string): void {
if (this.text === undefined) {
this.text = text;
const elements = this.getElements();

if (elements.length > 0 && elements[elements.length - 1].constructor.name === Text.name) {
const lastElement = elements[elements.length - 1] as Text;
lastElement.setText(lastElement.getText() + text);
return;
}

this.text += text;
this.appendElement(new Text(text));
}

/**
* Sets the text content of this paragraph.
* Note: This will replace any existing content of the paragraph.
*
* @param {string} text The text content
* @since 0.1.0
*/
public setText(text: string): void {
this.text = text;
this.removeText();
this.appendText(text || "");
}

/**
Expand All @@ -68,7 +80,22 @@ export class Paragraph extends OdfElement {
* @since 0.1.0
*/
public removeText(): void {
this.text = undefined;
const elements = this.getElements();

for (let i = elements.length - 1; i >= 0; i--) {
this.removeElement(i);
}
}

/**
* Appends the specified text as hyperlink to the end of this paragraph.
*
* @param {string} text The text content of the hyperlink
* @param {string} uri The URI of the hyperlink
* @since 0.3.0
*/
public appendHyperlink(text: string, uri: string): void {
this.appendElement(new Hyperlink(text, uri));
}

/**
Expand Down Expand Up @@ -112,10 +139,11 @@ export class Paragraph extends OdfElement {

/** @inheritDoc */
protected toXML(document: Document, parent: Element): void {
(document.firstChild as Element).setAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");

const paragraph = this.createElement(document);

this.appendStyle(document, paragraph);
this.appendTextContent(document, paragraph);

parent.appendChild(paragraph);

Expand All @@ -135,31 +163,4 @@ export class Paragraph extends OdfElement {
paragraph.setAttribute(OdfAttributeName.TextStyleName, this.style.getName());
}
}

/**
* Appends the text of the paragraph to the paragraph element.
* Newlines will be replaced with line breaks.
*
* @param {Document} document The XML document
* @param {Element} paragraph The paragraph the text belongs to
*/
private appendTextContent(document: Document, paragraph: Element): void {
if (this.text === undefined) {
return;
}

(document.firstChild as Element).setAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");

const lines = this.text.split("\n");

for (let i = 0; i < lines.length; i++) {
if (i > 0) {
const lineBreak = document.createElement(OdfElementName.TextLineBreak);
paragraph.appendChild(lineBreak);
}

const textNode = document.createTextNode(lines[i]);
paragraph.appendChild(textNode);
}
}
}
58 changes: 58 additions & 0 deletions src/text/Text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { OdfElement } from "../OdfElement";
import { OdfElementName } from "../OdfElementName";

/**
* This class represents text in a paragraph.
*
* @since 0.3.0
*/
export class Text extends OdfElement {
/**
* Creates a text
*
* @param {string} text The text content
* @since 0.3.0
*/
public constructor(private text: string) {
super();
}

/**
* Returns the text content.
*
* @returns {string} The text content
* @since 0.3.0
*/
public getText(): string {
return this.text;
}

/**
* Sets the new text content.
*
* @param {string} text The new text content
* @since 0.3.0
*/
public setText(text: string): void {
this.text = text;
}

/** @inheritDoc */
protected toXML(document: Document, parent: Element): void {
if (this.text === undefined || this.text === "") {
return;
}

const lines = this.text.split("\n");

for (let i = 0; i < lines.length; i++) {
if (i > 0) {
const lineBreak = document.createElement(OdfElementName.TextLineBreak);
parent.appendChild(lineBreak);
}

const textNode = document.createTextNode(lines[i]);
parent.appendChild(textNode);
}
}
}
4 changes: 4 additions & 0 deletions test/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ describe(TextDocument.name, () => {
const heading30 = document.addHeading("Another chapter");
heading30.setPageBreak();

const para2 = document.addParagraph("This is just an ");
para2.appendHyperlink("example", "http://example.org");
para2.appendText(".");

await document.saveFlat(FILEPATH);
done();
});
Expand Down
9 changes: 7 additions & 2 deletions test/text/Heading.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ describe(Heading.name, () => {
document = new TextDocument();
});

it("add text namespace", () => {
document.addHeading();

const documentAsString = document.toString();
expect(documentAsString).toMatch(/xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"/);
});

it("insert an empty heading with default level 1", () => {
document.addHeading();

const documentAsString = document.toString();
expect(documentAsString).toMatch(/<text:h text:outline-level="1"\/>/);
expect(documentAsString).not.toMatch(/xmlns:text/);
});

it("insert a heading with given text and default level 1", () => {
document.addHeading("heading");

const documentAsString = document.toString();
expect(documentAsString).toMatch(/<text:h text:outline-level="1">heading<\/text:h>/);
expect(documentAsString).toMatch(/xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"/);
});

it("insert a heading with given text and given level", () => {
Expand Down
Loading

0 comments on commit b6bed4c

Please sign in to comment.