Skip to content

Commit

Permalink
fix(list): text content of a list item cannot be styled (#120)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `addListItem` method on a `List` no longer accepts a string and it doesn't automagically create a "hidden" paragraph. Instead an empty `ListItem` is being created. On the `ListItem` instance it is now possible to add headings or paragraphs.

Fixes: #67
  • Loading branch information
connium authored Oct 8, 2019
1 parent ee9c1fb commit 453a96b
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 86 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.


## [Unreleased] (2019-??-??)
### Changed
- **list:** text content of a list item cannot be styled, closes [#67](https://github.com/connium/simple-odf/issues/67)

## [0.10.1] (2019-07-11)
### Changed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ body.addHeading('Credits', 2);
body.addParagraph('This was quite easy. Do you want to know why?');

const list = body.addList();
list.addItem('one-liner setup');
list.addItem('just write like you would do in a full-blown editor');
list.addItem().addParagraph('one-liner setup');
list.addItem().addParagraph('just write like you would do in a full-blown editor');

document.saveFlat('/home/homer/My_first_document.fodf');
```
Expand Down
13 changes: 7 additions & 6 deletions examples/homer-resume/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobTitleStyle.setTypeface(Typeface.Bold);

const companyNameStyle = new ParagraphStyle();
companyNameStyle.setFontName(fontName);
companyNameStyle.setFontSize(10)
companyNameStyle.setFontSize(10);
companyNameStyle.setTypeface(Typeface.Italic);

const defaultStyle = new ParagraphStyle();
Expand Down Expand Up @@ -93,8 +93,9 @@ body.addHeading('Nuclear Safety Inspector', 3)
body.addParagraph('Springfield Nuclear Power Plant, Springfield, USA')
.setStyle(companyNameStyle);
const list1 = body.addList();
list1.addItem('Strengthened safety procedures that resulted in 75% fewer accidents on days I was absent');
list1.addItem('Pioneered workplace stress-reduction methods that worked for at least one employee');
// tslint:disable-next-line:max-line-length
list1.addItem().addParagraph('Strengthened safety procedures that resulted in 75% fewer accidents on days I was absent');
list1.addItem().addParagraph('Pioneered workplace stress-reduction methods that worked for at least one employee');

body.addParagraph();

Expand All @@ -105,8 +106,8 @@ body.addHeading('Owner and Chief Driver for Snow-Plowing Business', 3)
body.addParagraph('Mr. Plow, Springfield, USA')
.setStyle(companyNameStyle);
const list2 = body.addList();
list2.addItem('Boosted business 15% by executing late-night TV marketing campaign');
list2.addItem('Received key to the city in recognition of the achievements');
list2.addItem().addParagraph('Boosted business 15% by executing late-night TV marketing campaign');
list2.addItem().addParagraph('Received key to the city in recognition of the achievements');

body.addParagraph();
body.addParagraph();
Expand All @@ -127,7 +128,7 @@ body.addParagraph('1969-10 - 1973-06')
body.addHeading('Springfield High School', 3)
.setStyle(jobTitleStyle);
const list3 = body.addList();
list3.addItem('Graduated 4-');
list3.addItem().addParagraph('Graduated 4-');

body.addParagraph();
body.addParagraph();
Expand Down
4 changes: 4 additions & 0 deletions src/api/office/TextBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export class TextBody extends OdfElement {
/**
* Adds an empty list at the end of the document.
*
* @example
* new TextBody()
* .addList();
*
* @returns {List} The newly added list
* @since 0.7.0
*/
Expand Down
27 changes: 15 additions & 12 deletions src/api/text/List.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,31 @@ describe(List.name, () => {
beforeEach(() => {
list = new List();

testItem1 = new ListItem('first');
testItem2 = new ListItem('second');
testItem3 = new ListItem('third');
testItem1 = new ListItem();
testItem2 = new ListItem();
testItem3 = new ListItem();
});

describe('#addItem', () => {
beforeEach(() => {
list.addItem('first');
list.addItem();
});

it('create new item at the end of the list and return the added item', () => {
const addedItem = list.addItem('second');
const addedItem = list.addItem();

expect(addedItem).toEqual(testItem2);
expect(list.getItems()).toEqual([testItem1, testItem2]);
expect(addedItem).toBeInstanceOf(ListItem);
expect(list.getItems().length).toBe(2);
});

it('add new item to the end of the list and return the added item', () => {
const addedItem = list.addItem(testItem2);
const testItem = new ListItem();

expect(addedItem).toBe(testItem2);
expect(list.getItems()).toEqual([testItem1, testItem2]);
const addedItem = list.addItem(testItem);

expect(addedItem).toBe(testItem);
expect(list.getItems().length).toBe(2);
expect(list.getItem(1)).toBe(testItem);
});
});

Expand All @@ -43,11 +46,11 @@ describe(List.name, () => {
list.addItem(testItem2);
list.addItem(testItem3);

itemToAdd = new ListItem('new');
itemToAdd = new ListItem();
});

it('insert item at the specified position and return the added item', () => {
const insertedItem = list.insertItem(2, 'new');
const insertedItem = list.insertItem(2, itemToAdd);

expect(insertedItem).toEqual(itemToAdd);
expect(list.getItems()).toEqual([testItem1, testItem2, itemToAdd, testItem3]);
Expand Down
89 changes: 38 additions & 51 deletions src/api/text/List.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { ListItem } from './ListItem';
*
* @example
* const list = document.getBody().addList();
* list.addItem('First item');
* list.addItem('Second item');
* list.insertItem(1, 'After first item');
* list.addItem();
* list.addItem();
* list.insertItem(1, new ListItem());
* list.removeItemAt(2);
*
* @since 0.2.0
Expand All @@ -27,58 +27,44 @@ export class List extends OdfElement {
}

/**
* The `addItem()` method adds a new list item with the specified text or adds the specified item to the list.
* The `addItem()` method adds a new list item or adds the specified item to the list.
*
* @example
* const list = new List();
* list.addItem('First item');
* list.addItem(new ListItem('Second item'));
* list.addItem();
* list.addItem(new ListItem());
*
* @param {string | ListItem} [item] The text content of the new item or the item to add
* @param {ListItem} [item] The item to add
* @returns {ListItem} The added `ListItem` object
* @since 0.2.0
*/
public addItem (item?: string | ListItem): ListItem {
if (item instanceof ListItem) {
this.append(item);
return item;
}

const listItem = new ListItem(item);
public addItem (item?: ListItem): ListItem {
const listItem = item || new ListItem();
this.append(listItem);

return listItem;
}

/**
* The `insertItem` method inserts a new list item with the specified text
* or inserts the specified item at the specified position.
* The `insertItem` method inserts the specified item at the specified position.
* The item is inserted before the item at the specified position.
*
* If the position is greater than the current number items, the new item is appended at the end of the list.
* If the position is greater than the current number of items, the new item is appended at the end of the list.
* If the position is negative, the new item is inserted as first element.
*
* @example
* const list = new List();
* list.addItem('First item'); // 'First item'
* list.addItem('Second item'); // 'First item', 'Second item'
* list.insertItem(1, 'After first item'); // 'First item', 'After first item', 'Second item'
* list.addItem();
* list.insertItem(0, new ListItem()); // insert before existing item
*
* @param {number} position The index at which to insert the list item (starting from 0).
* @param {string | ListItem} item The text content of the new item or the item to insert
* @param {ListItem} item The item to insert
* @returns {ListItem} The inserted `ListItem` object
* @since 0.2.0
*/
public insertItem (position: number, item: string | ListItem): ListItem {
if (item instanceof ListItem) {
this.insert(position, item);
return item;
}

const listItem = new ListItem(item);
this.insert(position, listItem);

return listItem;
public insertItem (position: number, item: ListItem): ListItem {
this.insert(position, item);
return item;
}

/**
Expand All @@ -87,10 +73,10 @@ export class List extends OdfElement {
*
* @example
* const list = new List();
* list.addItem('First item');
* list.addItem('Second item');
* list.getItem(1); // 'Second item'
* list.getItem(2); // undefined
* list.addItem();
* list.addItem();
* list.getItem(1); // second item
* list.getItem(2); // undefined
*
* @param {number} position The index of the requested list item (starting from 0).
* @returns {ListItem | undefined} The `ListItem` object at the specified position
Expand All @@ -106,10 +92,10 @@ export class List extends OdfElement {
*
* @example
* const list = new List();
* list.getItems(); // []
* list.addItem('First item');
* list.addItem('Second item');
* list.getItems(); // ['First item', 'Second item']
* list.getItems(); // []
* list.addItem();
* list.addItem();
* list.getItems(); // [first item, second item]
*
* @returns {ListItem[]} A copy of the list of `ListItem` objects
* @since 0.2.0
Expand All @@ -123,11 +109,11 @@ export class List extends OdfElement {
*
* @example
* const list = new List();
* list.addItem('First item');
* list.addItem('Second item');
* list.removeItemAt(0); // 'First item'
* list.getItems(); // ['Second item']
* list.removeItemAt(2); // undefined
* list.addItem();
* list.addItem();
* list.removeItemAt(0); // first item
* list.getItems(); // [second item]
* list.removeItemAt(2); // undefined
*
* @param {number} position The index of the list item to remove (starting from 0).
* @returns {ListItem | undefined} The removed `ListItem` object
Expand All @@ -143,9 +129,10 @@ export class List extends OdfElement {
*
* @example
* const list = new List();
* list.addItem('First item'); // 'First item'
* list.addItem('Second item'); // 'First item', 'Second item'
* list.clear(); // -
* list.addItem();
* list.addItem();
* list.clear();
* list.getItems(); // []
*
* @returns {List} The `List` object
* @since 0.2.0
Expand All @@ -165,10 +152,10 @@ export class List extends OdfElement {
*
* @example
* const list = new List();
* list.size(); // 0
* list.addItem('First item');
* list.addItem('Second item');
* list.size(); // 2
* list.size(); // 0
* list.addItem();
* list.addItem();
* list.size(); // 2
*
* @returns {number} The number of items in this list
* @since 0.2.0
Expand Down
27 changes: 27 additions & 0 deletions src/api/text/ListItem.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Heading } from './Heading';
import { ListItem } from './ListItem';
import { Paragraph } from './Paragraph';

describe(ListItem.name, () => {
let listItem: ListItem;

beforeEach(() => {
listItem = new ListItem();
});

describe('#addHeading', () => {
it('return a heading', () => {
const heading = listItem.addHeading();

expect(heading).toBeInstanceOf(Heading);
});
});

describe('#addParagraph', () => {
it('return a paragraph', () => {
const paragraph = listItem.addParagraph();

expect(paragraph).toBeInstanceOf(Paragraph);
});
});
});
46 changes: 36 additions & 10 deletions src/api/text/ListItem.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,58 @@
import { OdfElement } from '../OdfElement';
import { Heading } from './Heading';
import { Paragraph } from './Paragraph';

/**
* This class represents an item in a list.
*
* @example
* const list = document.getBody()
* .addList()
* .addItem('First item');
* const listItem = new ListItem();
* listItem.addHeading('headline');
* listItem.addParagraph('paragraph');
*
* @since 0.2.0
*/
export class ListItem extends OdfElement {
private paragraph: Paragraph;

/**
* Creates a `ListItem` instance that represents an item in a list.
*
* @example
* new ListItem('First item');
* new ListItem();
*
* @param {string} [text=''] The text content of the list item; defaults to an empty string if omitted
* @since 0.2.0
*/
public constructor (text?: string) {
public constructor () {
super();
}

/**
* Adds a heading at the end of the list item.
* If a text is given, this will be set as text content of the heading.
*
* @param {string} [text] The text content of the heading
* @param {number} [level=1] The heading level; defaults to 1 if omitted
* @returns {Heading} The newly added heading
* @since 0.11.0
*/
public addHeading (text?: string, level = 1): Heading {
const heading = new Heading(text, level);
this.append(heading);

return heading;
}

/**
* Adds a paragraph at the end of the list item.
* If a text is given, this will be set as text content of the paragraph.
*
* @param {string} [text] The text content of the paragraph
* @returns {Paragraph} The newly added paragraph
* @since 0.11.0
*/
public addParagraph (text?: string): Paragraph {
const paragraph = new Paragraph(text);
this.append(paragraph);

this.paragraph = new Paragraph(text);
this.append(this.paragraph);
return paragraph;
}
}
Loading

0 comments on commit 453a96b

Please sign in to comment.