Compare commits

...

21 Commits

Author SHA1 Message Date
5c1a731314 Version bump 2019-05-16 22:15:50 +01:00
622331ad24 Merge pull request #324 from Scarface2013/master
Fix merging of 3+ cells vertically
2019-05-16 21:06:20 +01:00
3a593a53d3 Fix tests 2019-05-16 11:15:20 -04:00
31a9111667 Fix merging of 3+ cells vertically 2019-05-15 18:14:39 -04:00
373c890354 Add docsify serve 2019-04-30 00:30:18 +01:00
723d76d06f Merge pull request #314 from efx/fix-doc-links
fix broken documentation links
2019-04-29 12:08:27 +01:00
a24d745d75 fix broken documentation links 2019-04-25 09:49:44 -04:00
90891cfafd Merge pull request #310 from nickgeorgiou/feat/margin-spelling-fix
Fix spelling of "margin"
2019-04-18 17:10:00 +01:00
29f890918c Fix spelling of "margin" 2019-04-18 13:55:18 +10:00
b0f8f8ddbd Merge pull request #308 from filippomuscolino/master
Update documentation
2019-04-12 14:43:32 +01:00
9c89c1ab59 Update docs 2019-04-12 13:46:05 +02:00
7a9cb92955 Merge pull request #307 from brucehappy/features/xml_optimization
Optimize XML output
2019-04-11 22:50:10 +01:00
77edf8862b Added constant EMPTY_OBJECT (an empty sealed object) that is used to indicate to the xml library that an empty XML element should be generated, and use it in the JSON hardcoded into the tests. 2019-04-10 13:47:38 -04:00
bb1604cd8f Turn back on no-null-keyword. Use empty object instead of null to signal to the xml library that an empty element should be produced. Update the related tests.
Related to #306
2019-04-10 01:28:37 -04:00
816cb54b14 Optimize XML output by properly constructing objects to send to the xml library so that it can produce proper empty elements.
Rework the way attributes are stored in ImportedXmlComponent to match elsewhere (required allowing for a null xmlKeys in the XmlAttributeComponent interface).
Rework the way paragraphs get added to the end of table cells if needed.
The goal in both reworks is to not mess around with the objects output from `prepForXml` if we can avoid it.
Made the output of RunProperties, ParagraphProperties, TableCellProperties, TableRowProperties, and TableProperties all optional based on whether they contain any attributes or children.  Changed code in PageBorders, TableCellMargin, and TableCellBorders that implemented this same thing by overriding `prepForXml` so that it uses the new XmlComponent subclass instead.
Removed commented out code that attempted to fix-up XML output and make proper empty elements.
Fixed all affected tests.
Turn off `no-null-keyword` in the linter as we need to use null to signal to the `xml` library to create an empty element with no attributes (`undefined` will not work in its place).

Fixes #306
2019-04-09 05:27:18 -04:00
920bd3c175 Merge pull request #304 from brucehappy/issues/issue_303
Fix table cell margin type XML attribute
2019-04-08 20:30:54 +01:00
a2a01edc24 Change table cell margin type attribute form w:sz to w:type as per http://officeopenxml.com/WPtableCellMargins.php
Fixes #303
2019-04-08 13:50:40 -04:00
193d0c4239 Merge pull request #299 from filippomuscolino/fix-duplicated-section
Fix: duplicated generation of last section properties
2019-04-05 01:07:10 +01:00
d8cc11c5ab Merge pull request #300 from efx/fix-typo
fix minor typos
2019-04-05 01:03:39 +01:00
b874051f32 fix minor typos 2019-04-04 15:35:41 -04:00
272e2496f4 Fix duplicated generation of last section properties 2019-04-04 17:43:54 +02:00
79 changed files with 1549 additions and 1795 deletions

View File

@ -25,7 +25,7 @@ table = doc.createTable({
table
.getCell(0, 0)
.addParagraph(new Paragraph("World"))
.setMargains({
.setMargins({
top: 1000,
bottom: 1000,
left: 1000,
@ -40,7 +40,7 @@ table = doc.createTable({
columns: 4,
width: 7000,
widthUnitType: WidthType.DXA,
margains: {
margins: {
top: 400,
bottom: 400,
right: 400,

View File

@ -18,7 +18,7 @@ Put yourself in their position, and imagine how they would feel about your featu
1. Is it easy to use?
2. Has it been documented well?
3. Is it intuative?
3. Is it intuitive?
4. Is it consistent with the rest of the API?
5. Is it fun to use?
@ -39,7 +39,7 @@ Unesesary coment removed // Make sure to use correct spelling
> This mainly applies to the API the end user will consume.
Try to make method parameters of the outside API accept primatives, or `json` objects, so that child components are created **inside** the component, rather than being **injected** in.
Try to make method parameters of the outside API accept primitives, or `json` objects, so that child components are created **inside** the component, rather than being **injected** in.
This is so that:
@ -65,7 +65,7 @@ This is so that:
**Do**
`ITableFloatOptions` is an interface for a JSON of primatives. The end user would need to pass in a json object and not need to worry about the internals:
`ITableFloatOptions` is an interface for a JSON of primitives. The end user would need to pass in a json object and not need to worry about the internals:
```js
public float(tableFloatOptions: ITableFloatOptions): Table

View File

@ -112,7 +112,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo18.ts_
## Margins
Example showing how to set custom margains
Example showing how to set custom margins
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo6.ts ':include')

View File

@ -23,7 +23,7 @@ doc.Header.createImage([BUFFER_OF_YOUR_IMAGE]);
doc.Footer.createImage([BUFFER_OF_YOUR_IMAGE]);
```
Refer to `demo8.js` for more information
Refer to [`demo8.ts`](https://github.com/dolanmiu/docx/blob/master/demo/demo8.ts) for more information.
## Multiple Headers and Footers

47
docs/usage/hyperlinks.md Normal file
View File

@ -0,0 +1,47 @@
# Hyperlinks
There are two types of hyperlinks: internal (pointing to a bookmark inside the document) and external (pointing to an external url).
## Internal
To create an internal hyperlink you need first to create a bookmark (the paragraph that will be the destination of the hyperlink) with `doc.createBookmark(anchor, text)`.
A bookmark is composed of an anchor (an identifier) and the text displayed. After creating a bookmark just add it to a paragraph with `paragraph.addBookmark(bookmark)`
For example:
```ts
const paragraph = this.doc.createParagraph();
const bookmark = this.doc.createBookmark('anchorForChapter1', 'This is chapter1');
paragraph.addBookmark(bookmark);
```
Then you can create an hyperlink pointing to that bookmark with `doc.createInternalHyperLink(anchor,text)`:
```ts
const paragraph = this.doc.createParagraph();
const link = this.doc.createInternalHyperLink('anchorForChapter1', 'This is a link to chapter1');
paragraph.addHyperLink(link);
```
## External
To create an external hyperlink you just need to specify the url and the text of the link, then add it to a paragraph with `doc.createHyperlink(url, text)`:
```ts
const paragraph = this.doc.createParagraph();
const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link');
paragraph.addHyperLink(link);
```
## Styling an hyperlink
It is possible to set the style of the text of an hyperlink. This can be done applying run formatting on `TextRun` property of the hyperlink.
Example:
```ts
const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link');
link.TextRun.bold().italics()
```

View File

@ -76,6 +76,22 @@ paragraph.heading1().center();
The above will create a `heading 1` which is `centered`.
### Justified text with breaks
When a paragraph is justified, you may want to not justify the contents of incomplete lines, which end in a soft line break.
![Justified line before](https://user-images.githubusercontent.com/7989576/53820338-e060c680-3f6b-11e9-817c-ecb43271951e.png)
This is possible to achieve using:
```ts
this.doc.Settings.addCompatibility().doNotExpandShiftReturn();
```
The result is:
![Justified line after](https://user-images.githubusercontent.com/7989576/53820344-e2c32080-3f6b-11e9-9afe-24a2ed6e0d78.png)
## Thematic Break
To add a break in the page, simply add `.thematicBreak()` on a paragraph:
@ -106,7 +122,7 @@ var paragraph = new docx.Paragraph("Hello World on another page").pageBreakBefor
![Page Break Before in Word](https://user-images.githubusercontent.com/34742290/40176503-df3a8398-59db-11e8-8b9c-d719f13aa8b4.png)
Example: https://github.com/dolanmiu/docx/blob/master/demo/demo15.js
Example: https://github.com/dolanmiu/docx/blob/master/demo/demo15.ts
## Page break control

View File

@ -44,4 +44,4 @@ doc.addParagraph(paragraph);
doc.createParagraph("Some normal text");
```
Example: https://github.com/dolanmiu/docx/blob/master/demo/demo13.js
Example: https://github.com/dolanmiu/docx/blob/master/demo/demo13.ts

View File

@ -96,6 +96,28 @@ Once you have got the cell, you can add data to it with the `addParagraph()` met
cell.addParagraph(new Paragraph("Hello"));
```
### Set width of a cell
You can specify the width of a cell using:
`cell.Properties.setWidth(width, format)`
format can be:
* WidthType.AUTO
* WidthType.DXA: value is in twentieths of a point
* WidthType.NIL: is considered as zero
* WidthType.PCT: percent of table width
### Example
```ts
cell.Properties.setWidth(100, WidthType.DXA);
```
```ts
cell.Properties.setWidth('50%', WidthType.PCT);
```
## Borders
BorderStyle can be imported from `docx`. Size determines the thickness. HTML color can be a hex code or alias such as `red`.
@ -122,7 +144,18 @@ cell.Borders.addEndBorder([BorderStyle], [SIZE], [HTML COLOR]);
import { BorderStyle } from "docx";
cell.Borders.addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green");
cell.Borders.addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000");
cell.Borders.addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000");
```
### Google DOCS
Google DOCS does not support start and end borders, instead they use left and right borders. So to set left and right borders for Google DOCS you should use:
```ts
import { BorderStyle } from "docx";
cell.Borders.addLeftBorder(BorderStyle.DOT_DOT_DASH, 3, "green");
cell.Borders.addRightBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000");
```
## Set Width
@ -193,6 +226,23 @@ To have a table within a table
cell.addTable(new Table(1, 1));
```
## Pagination
###Prevent row pagination
To prevent breaking contents of a row across multiple pages, call `cantSplit()`:
```ts
table.getRow(0).setCantSplit();
```
###Repeat row
If a table is paginated on multiple pages, it is possible to repeat a row at the top of each new page calling `setTableHeader()`:
```ts
table.getRow(0).setTableHeader();
```
## Examples
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ':include')

View File

@ -1,6 +1,6 @@
{
"name": "docx",
"version": "5.0.0-rc1",
"version": "5.0.0-rc2",
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
"main": "build/index.js",
"scripts": {
@ -19,6 +19,7 @@
"style.fix": "npm run style -- --write",
"fix-types": "ts-node scripts/types-absolute-fixer.ts",
"e2e": "ts-node scripts/e2e.ts",
"serve.docs": "cd docs && docsify serve",
"ts-node": "ts-node"
},
"pre-commit": [
@ -67,6 +68,7 @@
"@types/webpack": "^4.4.24",
"awesome-typescript-loader": "^3.4.1",
"chai": "^3.5.0",
"docsify": "^4.9.1",
"glob": "^7.1.2",
"istanbul-instrumenter-loader": "^3.0.1",
"jszip": "^3.1.5",

View File

@ -31,7 +31,7 @@ describe("Formatter", () => {
const paragraph = new file.Paragraph();
paragraph.addRun(new file.TextRun("test").bold());
const newJson = formatter.format(paragraph);
assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]._attr["w:val"]);
assert.isDefined(newJson["w:p"][0]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]);
});
it("should format attributes (rsidSect)", () => {

View File

@ -191,13 +191,4 @@ export class Compiler {
},
};
}
/* By default docx collapse empty tags. <a></a> -> <a/>. this function mimic it
so comparing (diff) original docx file and the library output is easier
Currently not used, so commenting out */
// private collapseEmptyTags(xmlData: string): string {
// const regEx = /<(([^ <>]+)[^<>]*)><\/\2>/g;
// const collapsed = xmlData.replace(regEx, "<$1/>");
// return collapsed;
// }
}

View File

@ -20,84 +20,70 @@ describe("ContentTypes", () => {
expect(tree["Types"]).to.be.an.instanceof(Array);
expect(tree["Types"][0]).to.deep.equal({ _attr: { xmlns: "http://schemas.openxmlformats.org/package/2006/content-types" } });
expect(tree["Types"][1]).to.deep.equal({ Default: [{ _attr: { ContentType: "image/png", Extension: "png" } }] });
expect(tree["Types"][2]).to.deep.equal({ Default: [{ _attr: { ContentType: "image/jpeg", Extension: "jpeg" } }] });
expect(tree["Types"][3]).to.deep.equal({ Default: [{ _attr: { ContentType: "image/jpeg", Extension: "jpg" } }] });
expect(tree["Types"][4]).to.deep.equal({ Default: [{ _attr: { ContentType: "image/bmp", Extension: "bmp" } }] });
expect(tree["Types"][5]).to.deep.equal({ Default: [{ _attr: { ContentType: "image/gif", Extension: "gif" } }] });
expect(tree["Types"][1]).to.deep.equal({ Default: { _attr: { ContentType: "image/png", Extension: "png" } } });
expect(tree["Types"][2]).to.deep.equal({ Default: { _attr: { ContentType: "image/jpeg", Extension: "jpeg" } } });
expect(tree["Types"][3]).to.deep.equal({ Default: { _attr: { ContentType: "image/jpeg", Extension: "jpg" } } });
expect(tree["Types"][4]).to.deep.equal({ Default: { _attr: { ContentType: "image/bmp", Extension: "bmp" } } });
expect(tree["Types"][5]).to.deep.equal({ Default: { _attr: { ContentType: "image/gif", Extension: "gif" } } });
expect(tree["Types"][6]).to.deep.equal({
Default: [{ _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } }],
Default: { _attr: { ContentType: "application/vnd.openxmlformats-package.relationships+xml", Extension: "rels" } },
});
expect(tree["Types"][7]).to.deep.equal({ Default: [{ _attr: { ContentType: "application/xml", Extension: "xml" } }] });
expect(tree["Types"][7]).to.deep.equal({ Default: { _attr: { ContentType: "application/xml", Extension: "xml" } } });
expect(tree["Types"][8]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
PartName: "/word/document.xml",
},
},
],
});
expect(tree["Types"][9]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
PartName: "/word/styles.xml",
},
},
],
});
expect(tree["Types"][10]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-package.core-properties+xml",
PartName: "/docProps/core.xml",
},
},
],
});
expect(tree["Types"][11]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.extended-properties+xml",
PartName: "/docProps/app.xml",
},
},
],
});
expect(tree["Types"][12]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
PartName: "/word/numbering.xml",
},
},
],
});
expect(tree["Types"][13]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
PartName: "/word/footnotes.xml",
},
},
],
});
expect(tree["Types"][14]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
PartName: "/word/settings.xml",
},
},
],
});
});
});
@ -109,25 +95,21 @@ describe("ContentTypes", () => {
const tree = new Formatter().format(contentTypes);
expect(tree["Types"][15]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
PartName: "/word/footer101.xml",
},
},
],
});
expect(tree["Types"][16]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
PartName: "/word/footer102.xml",
},
},
],
});
});
});
@ -139,25 +121,21 @@ describe("ContentTypes", () => {
const tree = new Formatter().format(contentTypes);
expect(tree["Types"][15]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
PartName: "/word/header201.xml",
},
},
],
});
expect(tree["Types"][16]).to.deep.equal({
Override: [
{
Override: {
_attr: {
ContentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
PartName: "/word/header202.xml",
},
},
],
});
});
});

View File

@ -30,14 +30,14 @@ describe("Body", () => {
const formatted = new Formatter().format(body)["w:body"];
expect(formatted).to.be.an.instanceof(Array);
const defaultSectionPr = formatted[0]["w:p"][1]["w:pPr"][0]["w:sectPr"];
const defaultSectionPr = formatted[0]["w:p"][0]["w:pPr"][0]["w:sectPr"];
// check that this is the default section and added first in paragraph
expect(defaultSectionPr[0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
expect(defaultSectionPr[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
// check for new section (since it's the last one, it's direct child of body)
const newSection = formatted[1]["w:sectPr"];
expect(newSection[0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } }] });
expect(newSection[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } } });
});
it("should add section with default parameters", () => {
@ -52,15 +52,13 @@ describe("Body", () => {
"w:body": [
{
"w:p": [
{ "w:pPr": [] },
{
"w:pPr": [
{
"w:sectPr": [
{ "w:pgSz": [{ _attr: { "w:w": 11906, "w:h": 16838, "w:orient": "portrait" } }] },
{
"w:pgMar": [
{ "w:pgSz": { _attr: { "w:w": 11906, "w:h": 16838, "w:orient": "portrait" } } },
{
"w:pgMar": {
_attr: {
"w:top": 1440,
"w:right": 1440,
@ -72,10 +70,9 @@ describe("Body", () => {
"w:mirrorMargins": false,
},
},
],
},
{ "w:cols": [{ _attr: { "w:space": 708 } }] },
{ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] },
{ "w:cols": { _attr: { "w:space": 708 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
],
},
],
@ -84,10 +81,9 @@ describe("Body", () => {
},
{
"w:sectPr": [
{ "w:pgSz": [{ _attr: { "w:w": 10000, "w:h": 10000, "w:orient": "portrait" } }] },
{
"w:pgMar": [
{ "w:pgSz": { _attr: { "w:w": 10000, "w:h": 10000, "w:orient": "portrait" } } },
{
"w:pgMar": {
_attr: {
"w:top": 1440,
"w:right": 1440,
@ -99,10 +95,9 @@ describe("Body", () => {
"w:mirrorMargins": false,
},
},
],
},
{ "w:cols": [{ _attr: { "w:space": 708 } }] },
{ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] },
{ "w:cols": { _attr: { "w:space": 708 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
],
},
],

View File

@ -37,7 +37,7 @@ export class Body extends XmlComponent {
}
public prepForXml(): IXmlableObject | undefined {
if (this.sections.length === 1) {
this.root.push(this.sections[0]);
this.root.push(this.sections.pop() as SectionProperties);
}
return super.prepForXml();

View File

@ -21,8 +21,7 @@ describe("PageBorders", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:pgBorders"]);
expect(tree["w:pgBorders"]).to.be.an.instanceof(Array);
expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage" } });
expect(tree["w:pgBorders"]).to.deep.equal({ _attr: { "w:display": "firstPage" } });
});
it("should create page borders with full configuration", () => {
@ -58,32 +57,24 @@ describe("PageBorders", () => {
expect(tree["w:pgBorders"]).to.be.an.instanceof(Array);
expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage", "w:zOrder": "back" } });
expect(tree["w:pgBorders"][1]).to.deep.equal({
"w:top": [
{
"w:top": {
_attr: { "w:color": "001122", "w:size": 10, "w:val": "doubleWave" },
},
],
});
expect(tree["w:pgBorders"][2]).to.deep.equal({
"w:right": [
{
"w:right": {
_attr: { "w:color": "223344", "w:size": 20, "w:val": "double" },
},
],
});
expect(tree["w:pgBorders"][3]).to.deep.equal({
"w:bottom": [
{
"w:bottom": {
_attr: { "w:color": "556677", "w:size": 30, "w:val": "single" },
},
],
});
expect(tree["w:pgBorders"][4]).to.deep.equal({
"w:left": [
{
"w:left": {
_attr: { "w:color": "889900", "w:size": 40, "w:val": "dotted" },
},
],
});
});
});

View File

@ -1,6 +1,6 @@
// http://officeopenxml.com/WPsectionBorders.php
import { BorderStyle } from "file/styles";
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
export enum PageBorderDisplay {
ALL_PAGES = "allPages",
@ -64,7 +64,7 @@ class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes>
};
}
export class PageBorders extends XmlComponent {
export class PageBorders extends IgnoreIfEmptyXmlComponent {
constructor(options?: IPageBordersOptions) {
super("w:pgBorders");
@ -97,10 +97,4 @@ export class PageBorders extends XmlComponent {
this.root.push(new PageBorder("w:left", options.pageBorderLeft));
}
}
public prepForXml(): IXmlableObject | undefined {
if (this.root.length > 0) {
return super.prepForXml();
}
}
}

View File

@ -12,8 +12,7 @@ describe("PageSize", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 200, "w:w": 100, "w:orient": "portrait" } });
expect(tree["w:pgSz"]).to.deep.equal({ _attr: { "w:h": 200, "w:w": 100, "w:orient": "portrait" } });
});
it("should create page size with horizontal and invert the lengths", () => {
@ -21,8 +20,7 @@ describe("PageSize", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 100, "w:w": 200, "w:orient": "landscape" } });
expect(tree["w:pgSz"]).to.deep.equal({ _attr: { "w:h": 100, "w:w": 200, "w:orient": "landscape" } });
});
});
});

View File

@ -39,10 +39,9 @@ describe("SectionProperties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": [
{
"w:pgMar": {
_attr: {
"w:bottom": 1440,
"w:footer": 708,
@ -54,14 +53,13 @@ describe("SectionProperties", () => {
"w:mirrorMargins": false,
},
},
],
});
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:headerReference": [{ _attr: { "r:id": "rId100", "w:type": "default" } }] });
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:footerReference": [{ _attr: { "r:id": "rId200", "w:type": "even" } }] });
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:pgNumType": [{ _attr: { "w:fmt": "cardinalText", "w:start": 10 } }] });
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708 } } });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:headerReference": { _attr: { "r:id": "rId100", "w:type": "default" } } });
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:footerReference": { _attr: { "r:id": "rId200", "w:type": "even" } } });
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:pgNumType": { _attr: { "w:fmt": "cardinalText", "w:start": 10 } } });
});
it("should create section properties with no options", () => {
@ -69,10 +67,9 @@ describe("SectionProperties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": [
{
"w:pgMar": {
_attr: {
"w:bottom": 1440,
"w:footer": 708,
@ -84,10 +81,9 @@ describe("SectionProperties", () => {
"w:mirrorMargins": false,
},
},
],
});
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708 } } });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
});
it("should create section properties with changed options", () => {
@ -97,10 +93,9 @@ describe("SectionProperties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": [
{
"w:pgMar": {
_attr: {
"w:bottom": 1440,
"w:footer": 708,
@ -112,7 +107,6 @@ describe("SectionProperties", () => {
"w:mirrorMargins": false,
},
},
],
});
});
@ -123,10 +117,9 @@ describe("SectionProperties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": [
{
"w:pgMar": {
_attr: {
"w:bottom": 0,
"w:footer": 708,
@ -138,7 +131,6 @@ describe("SectionProperties", () => {
"w:mirrorMargins": false,
},
},
],
});
});
@ -150,10 +142,9 @@ describe("SectionProperties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 0, "w:w": 0, "w:orient": "portrait" } }] });
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 0, "w:w": 0, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": [
{
"w:pgMar": {
_attr: {
"w:bottom": 1440,
"w:footer": 708,
@ -165,7 +156,6 @@ describe("SectionProperties", () => {
"w:mirrorMargins": false,
},
},
],
});
});
@ -179,7 +169,7 @@ describe("SectionProperties", () => {
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
const pgBorders = tree["w:sectPr"].find((item) => item["w:pgBorders"] !== undefined);
expect(pgBorders).to.deep.equal({
"w:pgBorders": [{ _attr: { "w:offsetFrom": "page" } }],
"w:pgBorders": { _attr: { "w:offsetFrom": "page" } },
});
});
@ -191,7 +181,7 @@ describe("SectionProperties", () => {
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
const pgNumType = tree["w:sectPr"].find((item) => item["w:pgNumType"] !== undefined);
expect(pgNumType).to.deep.equal({
"w:pgNumType": [{ _attr: { "w:fmt": "upperRoman" } }],
"w:pgNumType": { _attr: { "w:fmt": "upperRoman" } },
});
});

View File

@ -11,8 +11,7 @@ describe("PageSize", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:titlePg"]);
expect(tree["w:titlePg"]).to.be.an.instanceof(Array);
expect(tree["w:titlePg"][0]).to.deep.equal({ _attr: { "w:val": "1" } });
expect(tree["w:titlePg"]).to.deep.equal({ _attr: { "w:val": "1" } });
});
});
});

View File

@ -52,7 +52,7 @@ describe("Document", () => {
expect(body[0])
.to.have.property("w:p")
.which.includes({
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "sample paragraph text"] }],
"w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "sample paragraph text"] }],
});
});
});
@ -84,9 +84,9 @@ describe("Document", () => {
.to.have.property("w:tbl")
.which.includes({
"w:tblGrid": [
{ "w:gridCol": [{ _attr: { "w:w": 100 } }] },
{ "w:gridCol": [{ _attr: { "w:w": 100 } }] },
{ "w:gridCol": [{ _attr: { "w:w": 100 } }] },
{ "w:gridCol": { _attr: { "w:w": 100 } } },
{ "w:gridCol": { _attr: { "w:w": 100 } } },
{ "w:gridCol": { _attr: { "w:w": 100 } } },
],
});
expect(body[0]["w:tbl"].filter((x) => x["w:tr"])).to.have.length(2);

View File

@ -25,8 +25,8 @@ describe("File", () => {
const tree = new Formatter().format(doc.Document.Body);
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"][0]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"]._attr["w:type"]).to.equal("default");
});
it("should create with first headers and footers", () => {
@ -45,8 +45,8 @@ describe("File", () => {
const tree = new Formatter().format(doc.Document.Body);
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"][0]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"]._attr["w:type"]).to.equal("first");
});
it("should create with correct headers", () => {
@ -69,13 +69,13 @@ describe("File", () => {
const tree = new Formatter().format(doc.Document.Body);
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][5]["w:headerReference"][0]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][6]["w:headerReference"][0]._attr["w:type"]).to.equal("even");
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][5]["w:headerReference"]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][6]["w:headerReference"]._attr["w:type"]).to.equal("even");
expect(tree["w:body"][1]["w:sectPr"][7]["w:footerReference"][0]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][8]["w:footerReference"][0]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][9]["w:footerReference"][0]._attr["w:type"]).to.equal("even");
expect(tree["w:body"][1]["w:sectPr"][7]["w:footerReference"]._attr["w:type"]).to.equal("default");
expect(tree["w:body"][1]["w:sectPr"][8]["w:footerReference"]._attr["w:type"]).to.equal("first");
expect(tree["w:body"][1]["w:sectPr"][9]["w:footerReference"]._attr["w:type"]).to.equal("even");
});
});

View File

@ -11,8 +11,7 @@ describe("Footnote", () => {
const tree = new Formatter().format(footnote);
expect(Object.keys(tree)).to.deep.equal(["w:footnote"]);
expect(tree["w:footnote"]).to.be.an.instanceof(Array);
expect(tree["w:footnote"][0]).to.deep.equal({ _attr: { "w:type": "separator", "w:id": 1 } });
expect(tree["w:footnote"]).to.deep.equal({ _attr: { "w:type": "separator", "w:id": 1 } });
});
it("should create a footnote without a footnote type", () => {
@ -20,8 +19,7 @@ describe("Footnote", () => {
const tree = new Formatter().format(footnote);
expect(Object.keys(tree)).to.deep.equal(["w:footnote"]);
expect(tree["w:footnote"]).to.be.an.instanceof(Array);
expect(tree["w:footnote"][0]).to.deep.equal({ _attr: { "w:id": 1 } });
expect(tree["w:footnote"]).to.deep.equal({ _attr: { "w:id": 1 } });
});
});
});

View File

@ -27,10 +27,10 @@ describe("Media", () => {
const file = new File();
const image1 = Media.addImage(file, "test");
const tree = new Formatter().format(image1.Paragraph);
const inlineElements = tree["w:p"][1]["w:r"][1]["w:drawing"][0]["wp:inline"];
const inlineElements = tree["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"];
const graphicData = inlineElements.find((x) => x["a:graphic"]);
expect(graphicData["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({
expect(graphicData["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"]).to.deep.equal({
_attr: {
"r:embed": `rId{testId.png}`,
cstate: "none",
@ -39,10 +39,10 @@ describe("Media", () => {
const image2 = Media.addImage(file, "test");
const tree2 = new Formatter().format(image2.Paragraph);
const inlineElements2 = tree2["w:p"][1]["w:r"][1]["w:drawing"][0]["wp:inline"];
const inlineElements2 = tree2["w:p"][0]["w:r"][0]["w:drawing"][0]["wp:inline"];
const graphicData2 = inlineElements2.find((x) => x["a:graphic"]);
expect(graphicData2["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"][0]).to.deep.equal({
expect(graphicData2["a:graphic"][1]["a:graphicData"][1]["pic:pic"][2]["pic:blipFill"][0]["a:blip"]).to.deep.equal({
_attr: {
"r:embed": `rId{testId.png}`,
cstate: "none",

View File

@ -7,6 +7,8 @@ import { LevelForOverride } from "./level";
import { Num } from "./num";
import { Numbering } from "./numbering";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Numbering", () => {
let numbering: Numbering;
@ -22,7 +24,7 @@ describe("Numbering", () => {
expect(abstractNums).to.have.lengthOf(1);
expect(abstractNums[0]["w:abstractNum"]).to.deep.include.members([
{ _attr: { "w:abstractNumId": 0, "w15:restartNumberingAfterBreak": 0 } },
{ "w:multiLevelType": [{ _attr: { "w:val": "hybridMultilevel" } }] },
{ "w:multiLevelType": { _attr: { "w:val": "hybridMultilevel" } } },
]);
abstractNums
@ -37,9 +39,9 @@ describe("Numbering", () => {
{ "w:numFmt": [{ _attr: { "w:val": "bullet" } }] },
]);
// Once chai 4.0.0 lands and #644 is resolved, we can add the following to the test:
// {"w:lvlText": [{"_attr": {"w:val": "•"}}]},
// {"w:rPr": [{"w:rFonts": [{"_attr": {"w:ascii": "Symbol", "w:cs": "Symbol", "w:eastAsia": "Symbol", "w:hAnsi": "Symbol", "w:hint": "default"}}]}]},
// {"w:pPr": [{"_attr": {}},
// {"w:lvlText": {"_attr": {"w:val": "•"}}},
// {"w:rPr": [{"w:rFonts": {"_attr": {"w:ascii": "Symbol", "w:cs": "Symbol", "w:eastAsia": "Symbol", "w:hAnsi": "Symbol", "w:hint": "default"}}}]},
// {"w:pPr": [
// {"w:ind": [{"_attr": {"w:left": 720, "w:hanging": 360}}]}]},
});
});
@ -65,7 +67,7 @@ describe("Numbering", () => {
expect(n).to.be.instanceof(Num);
const tree = new Formatter().format(numbering);
const serializedN = tree["w:numbering"].find((obj) => obj["w:num"] && obj["w:num"][0]._attr["w:numId"] === n.id);
expect(serializedN["w:num"][1]["w:abstractNumId"][0]._attr["w:val"]).to.equal(a2.id);
expect(serializedN["w:num"][1]["w:abstractNumId"]._attr["w:val"]).to.equal(a2.id);
});
it("assigns a unique ID to each concrete numbering it creates", () => {
@ -89,10 +91,10 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(3, "lowerLetter", "%1)", "end");
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({ _attr: { "w:ilvl": 3, "w15:tentative": 1 } });
expect(tree["w:lvl"]).to.include({ "w:start": [{ _attr: { "w:val": 1 } }] });
expect(tree["w:lvl"]).to.include({ "w:lvlJc": [{ _attr: { "w:val": "end" } }] });
expect(tree["w:lvl"]).to.include({ "w:numFmt": [{ _attr: { "w:val": "lowerLetter" } }] });
expect(tree["w:lvl"]).to.include({ "w:lvlText": [{ _attr: { "w:val": "%1)" } }] });
expect(tree["w:lvl"]).to.include({ "w:start": { _attr: { "w:val": 1 } } });
expect(tree["w:lvl"]).to.include({ "w:lvlJc": { _attr: { "w:val": "end" } } });
expect(tree["w:lvl"]).to.include({ "w:numFmt": { _attr: { "w:val": "lowerLetter" } } });
expect(tree["w:lvl"]).to.include({ "w:lvlText": { _attr: { "w:val": "%1)" } } });
});
it("uses 'start' as the default alignment", () => {
@ -100,10 +102,10 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(3, "lowerLetter", "%1)");
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({ _attr: { "w:ilvl": 3, "w15:tentative": 1 } });
expect(tree["w:lvl"]).to.include({ "w:start": [{ _attr: { "w:val": 1 } }] });
expect(tree["w:lvl"]).to.include({ "w:lvlJc": [{ _attr: { "w:val": "start" } }] });
expect(tree["w:lvl"]).to.include({ "w:numFmt": [{ _attr: { "w:val": "lowerLetter" } }] });
expect(tree["w:lvl"]).to.include({ "w:lvlText": [{ _attr: { "w:val": "%1)" } }] });
expect(tree["w:lvl"]).to.include({ "w:start": { _attr: { "w:val": 1 } } });
expect(tree["w:lvl"]).to.include({ "w:lvlJc": { _attr: { "w:val": "start" } } });
expect(tree["w:lvl"]).to.include({ "w:numFmt": { _attr: { "w:val": "lowerLetter" } } });
expect(tree["w:lvl"]).to.include({ "w:lvlText": { _attr: { "w:val": "%1)" } } });
});
describe("formatting methods: paragraph properties", () => {
@ -112,7 +114,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.").indent({ left: 720 });
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:ind": [{ _attr: { "w:left": 720 } }] }],
"w:pPr": [{ "w:ind": { _attr: { "w:left": 720 } } }],
});
});
@ -121,7 +123,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.").spacing({ before: 50, after: 150 });
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:spacing": [{ _attr: { "w:before": 50, "w:after": 150 } }] }],
"w:pPr": [{ "w:spacing": { _attr: { "w:before": 50, "w:after": 150 } } }],
});
});
@ -130,7 +132,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerLetter", "%0.").center();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "center" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "center" } } }],
});
});
@ -139,7 +141,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.", "left").left();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "left" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "left" } } }],
});
});
@ -148,7 +150,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").right();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "right" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "right" } } }],
});
});
@ -157,7 +159,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").justified();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "both" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "both" } } }],
});
});
@ -170,8 +172,7 @@ describe("AbstractNumbering", () => {
{
"w:pBdr": [
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:color": "auto",
"w:space": "1",
@ -179,7 +180,6 @@ describe("AbstractNumbering", () => {
"w:sz": "6",
},
},
],
},
],
},
@ -194,7 +194,7 @@ describe("AbstractNumbering", () => {
expect(tree["w:lvl"]).to.include({
"w:pPr": [
{
"w:tabs": [{ "w:tab": [{ _attr: { "w:val": "left", "w:pos": 1200 } }] }],
"w:tabs": [{ "w:tab": { _attr: { "w:val": "left", "w:pos": 1200 } } }],
},
],
});
@ -207,7 +207,7 @@ describe("AbstractNumbering", () => {
expect(tree["w:lvl"]).to.include({
"w:pPr": [
{
"w:tabs": [{ "w:tab": [{ _attr: { "w:val": "right", "w:pos": 9026 } }] }],
"w:tabs": [{ "w:tab": { _attr: { "w:val": "right", "w:pos": 9026 } } }],
},
],
});
@ -218,7 +218,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").keepLines();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:keepLines": [] }],
"w:pPr": [{ "w:keepLines": EMPTY_OBJECT }],
});
});
@ -227,7 +227,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").keepNext();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:pPr": [{ "w:keepNext": [] }],
"w:pPr": [{ "w:keepNext": EMPTY_OBJECT }],
});
});
});
@ -238,7 +238,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").size(24);
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:sz": [{ _attr: { "w:val": 24 } }] }],
"w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }],
});
});
@ -247,7 +247,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").smallCaps();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:smallCaps": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
});
});
@ -256,7 +256,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").allCaps();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:caps": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
});
});
@ -265,7 +265,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").strike();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:strike": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
});
});
@ -274,7 +274,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").doubleStrike();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:dstrike": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
});
});
@ -283,7 +283,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").subScript();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:vertAlign": [{ _attr: { "w:val": "subscript" } }] }],
"w:rPr": [{ "w:vertAlign": { _attr: { "w:val": "subscript" } } }],
});
});
@ -292,7 +292,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").superScript();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:vertAlign": [{ _attr: { "w:val": "superscript" } }] }],
"w:rPr": [{ "w:vertAlign": { _attr: { "w:val": "superscript" } } }],
});
});
@ -302,7 +302,7 @@ describe("AbstractNumbering", () => {
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [
{ "w:rFonts": [{ _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } }] },
{ "w:rFonts": { _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } } },
],
});
});
@ -312,7 +312,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").bold();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:b": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:b": { _attr: { "w:val": true } } }],
});
});
@ -321,7 +321,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").italics();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:i": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:i": { _attr: { "w:val": true } } }],
});
});
@ -331,7 +331,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").underline();
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "single" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }],
});
});
@ -340,7 +340,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").underline("double");
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double" } } }],
});
});
@ -349,7 +349,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").underline("double", "005599");
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double", "w:color": "005599" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "005599" } } }],
});
});
});
@ -359,7 +359,7 @@ describe("AbstractNumbering", () => {
const level = abstractNumbering.createLevel(0, "lowerRoman", "%0.").color("123456");
const tree = new Formatter().format(level);
expect(tree["w:lvl"]).to.include({
"w:rPr": [{ "w:color": [{ _attr: { "w:val": "123456" } }] }],
"w:rPr": [{ "w:color": { _attr: { "w:val": "123456" } } }],
});
});
});
@ -388,20 +388,12 @@ describe("concrete numbering", () => {
},
},
{
"w:lvl": [
{
"w:lvl": {
_attr: {
"w:ilvl": 3,
"w15:tentative": 1,
},
},
{
"w:pPr": [],
},
{
"w:rPr": [],
},
],
},
],
});
@ -418,29 +410,19 @@ describe("concrete numbering", () => {
},
},
{
"w:startOverride": [
{
"w:startOverride": {
_attr: {
"w:val": 9,
},
},
],
},
{
"w:lvl": [
{
"w:lvl": {
_attr: {
"w:ilvl": 1,
"w15:tentative": 1,
},
},
{
"w:pPr": [],
},
{
"w:rPr": [],
},
],
},
],
});
@ -454,7 +436,7 @@ describe("concrete numbering", () => {
"w:lvlOverride": [
{ _attr: { "w:ilvl": 1 } },
{
"w:lvl": [{ _attr: { "w15:tentative": 1, "w:ilvl": 1 } }, { "w:pPr": [] }, { "w:rPr": [] }],
"w:lvl": { _attr: { "w15:tentative": 1, "w:ilvl": 1 } },
},
],
});

View File

@ -10,7 +10,7 @@ describe("Spacing", () => {
const spacing = new Spacing({ before: 100, after: 120, line: 150 });
const tree = new Formatter().format(spacing);
expect(tree).to.deep.equal({
"w:spacing": [{ _attr: { "w:after": 120, "w:before": 100, "w:line": 150 } }],
"w:spacing": { _attr: { "w:after": 120, "w:before": 100, "w:line": 150 } },
});
});
@ -18,7 +18,7 @@ describe("Spacing", () => {
const spacing = new Spacing({ before: 100 });
const tree = new Formatter().format(spacing);
expect(tree).to.deep.equal({
"w:spacing": [{ _attr: { "w:before": 100 } }],
"w:spacing": { _attr: { "w:before": 100 } },
});
});
});
@ -30,7 +30,7 @@ describe("ContextualSpacing", () => {
const spacing = new ContextualSpacing(true);
const tree = new Formatter().format(spacing);
expect(tree).to.deep.equal({
"w:contextualSpacing": [{ _attr: { "w:val": 1 } }],
"w:contextualSpacing": { _attr: { "w:val": 1 } },
});
});
@ -38,7 +38,7 @@ describe("ContextualSpacing", () => {
const spacing = new ContextualSpacing(false);
const tree = new Formatter().format(spacing);
expect(tree).to.deep.equal({
"w:contextualSpacing": [{ _attr: { "w:val": 0 } }],
"w:contextualSpacing": { _attr: { "w:val": 0 } },
});
});
});

View File

@ -5,6 +5,8 @@ import { Formatter } from "export/formatter";
import { ImageParagraph } from "./image";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Image", () => {
let image: ImageParagraph;
@ -45,14 +47,8 @@ describe("Image", () => {
const tree = new Formatter().format(image);
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:drawing": [
{
@ -66,18 +62,15 @@ describe("Image", () => {
},
},
{
"wp:extent": [
{
"wp:extent": {
_attr: {
cx: 20,
cy: 20,
},
},
],
},
{
"wp:effectExtent": [
{
"wp:effectExtent": {
_attr: {
b: 0,
l: 0,
@ -85,30 +78,25 @@ describe("Image", () => {
t: 0,
},
},
],
},
{
"wp:docPr": [
{
"wp:docPr": {
_attr: {
descr: "",
id: 0,
name: "",
},
},
],
},
{
"wp:cNvGraphicFramePr": [
{
"a:graphicFrameLocks": [
{
"a:graphicFrameLocks": {
_attr: {
noChangeAspect: 1,
"xmlns:a": "http://schemas.openxmlformats.org/drawingml/2006/main",
},
},
],
},
],
},
@ -137,27 +125,23 @@ describe("Image", () => {
{
"pic:nvPicPr": [
{
"pic:cNvPr": [
{
"pic:cNvPr": {
_attr: {
desc: "",
id: 0,
name: "",
},
},
],
},
{
"pic:cNvPicPr": [
{
"a:picLocks": [
{
"a:picLocks": {
_attr: {
noChangeArrowheads: 1,
noChangeAspect: 1,
},
},
],
},
],
},
@ -166,22 +150,20 @@ describe("Image", () => {
{
"pic:blipFill": [
{
"a:blip": [
{
"a:blip": {
_attr: {
cstate: "none",
"r:embed": "rId{test.png}",
},
},
],
},
{
"a:srcRect": [],
"a:srcRect": EMPTY_OBJECT,
},
{
"a:stretch": [
{
"a:fillRect": [],
"a:fillRect": EMPTY_OBJECT,
},
],
},
@ -197,24 +179,20 @@ describe("Image", () => {
{
"a:xfrm": [
{
"a:ext": [
{
"a:ext": {
_attr: {
cx: 10,
cy: 10,
},
},
],
},
{
"a:off": [
{
"a:off": {
_attr: {
x: 0,
y: 0,
},
},
],
},
],
},
@ -226,7 +204,7 @@ describe("Image", () => {
},
},
{
"a:avLst": [],
"a:avLst": EMPTY_OBJECT,
},
],
},

View File

@ -31,7 +31,7 @@ describe("Hyperlink", () => {
const tree = new Formatter().format(hyperlink);
const runJson = {
"w:r": [
{ "w:rPr": [{ "w:rStyle": [{ _attr: { "w:val": "Hyperlink" } }] }] },
{ "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "Hyperlink" } } }] },
{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "https://example.com"] },
],
};

View File

@ -6,6 +6,8 @@ import * as file from "file";
import { Numbering } from "../numbering";
import { LeaderType } from "./formatting";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Paragraph", () => {
let paragraph: file.Paragraph;
@ -40,7 +42,7 @@ describe("Paragraph", () => {
expect(tree)
.to.be.an("array")
.which.includes({
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "this is a test run"] }],
"w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "this is a test run"] }],
});
});
});
@ -52,7 +54,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading1" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading1" } } }],
},
],
});
@ -66,7 +68,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading2" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading2" } } }],
},
],
});
@ -80,7 +82,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading3" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading3" } } }],
},
],
});
@ -94,7 +96,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading4" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading4" } } }],
},
],
});
@ -108,7 +110,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading5" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading5" } } }],
},
],
});
@ -122,7 +124,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Heading6" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Heading6" } } }],
},
],
});
@ -136,7 +138,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "Title" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "Title" } } }],
},
],
});
@ -150,7 +152,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "center" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "center" } } }],
},
],
});
@ -164,7 +166,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "left" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "left" } } }],
},
],
});
@ -178,7 +180,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "right" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "right" } } }],
},
],
});
@ -192,7 +194,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "start" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "start" } } }],
},
],
});
@ -206,7 +208,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "end" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "end" } } }],
},
],
});
@ -220,7 +222,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "distribute" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "distribute" } } }],
},
],
});
@ -234,7 +236,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "both" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "both" } } }],
},
],
});
@ -252,14 +254,12 @@ describe("Paragraph", () => {
{
"w:tabs": [
{
"w:tab": [
{
"w:tab": {
_attr: {
"w:pos": 9026,
"w:val": "right",
},
},
],
},
],
},
@ -281,15 +281,13 @@ describe("Paragraph", () => {
{
"w:tabs": [
{
"w:tab": [
{
"w:tab": {
_attr: {
"w:pos": 100,
"w:val": "left",
"w:leader": "hyphen",
},
},
],
},
],
},
@ -311,15 +309,13 @@ describe("Paragraph", () => {
{
"w:tabs": [
{
"w:tab": [
{
"w:tab": {
_attr: {
"w:pos": 100,
"w:val": "right",
"w:leader": "dot",
},
},
],
},
],
},
@ -341,15 +337,13 @@ describe("Paragraph", () => {
{
"w:tabs": [
{
"w:tab": [
{
"w:tab": {
_attr: {
"w:pos": 100,
"w:val": "center",
"w:leader": "middleDot",
},
},
],
},
],
},
@ -367,7 +361,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:contextualSpacing": [{ _attr: { "w:val": 1 } }] }],
"w:pPr": [{ "w:contextualSpacing": { _attr: { "w:val": 1 } } }],
},
],
});
@ -379,7 +373,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:contextualSpacing": [{ _attr: { "w:val": 0 } }] }],
"w:pPr": [{ "w:contextualSpacing": { _attr: { "w:val": 0 } } }],
},
],
});
@ -397,8 +391,7 @@ describe("Paragraph", () => {
{
"w:pBdr": [
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:val": "single",
"w:color": "auto",
@ -406,7 +399,6 @@ describe("Paragraph", () => {
"w:sz": "6",
},
},
],
},
],
},
@ -430,8 +422,7 @@ describe("Paragraph", () => {
{
"w:pBdr": [
{
"w:left": [
{
"w:left": {
_attr: {
"w:color": "auto",
"w:space": "1",
@ -439,11 +430,9 @@ describe("Paragraph", () => {
"w:val": "single",
},
},
],
},
{
"w:right": [
{
"w:right": {
_attr: {
"w:color": "auto",
"w:space": "1",
@ -451,7 +440,6 @@ describe("Paragraph", () => {
"w:val": "single",
},
},
],
},
],
},
@ -469,10 +457,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [{ "w:rPr": [] }, { "w:br": [{ _attr: { "w:type": "page" } }] }],
"w:r": [{ "w:br": { _attr: { "w:type": "page" } } }],
},
],
});
@ -488,7 +473,7 @@ describe("Paragraph", () => {
{
"w:pPr": [
{
"w:pageBreakBefore": [],
"w:pageBreakBefore": EMPTY_OBJECT,
},
],
},
@ -510,7 +495,7 @@ describe("Paragraph", () => {
.which.is.an("array")
.which.has.length.at.least(1);
expect(tree["w:p"][0]["w:pPr"][0]).to.deep.equal({
"w:pStyle": [{ _attr: { "w:val": "ListParagraph" } }],
"w:pStyle": { _attr: { "w:val": "ListParagraph" } },
});
});
@ -526,7 +511,7 @@ describe("Paragraph", () => {
.which.is.an("array")
.which.has.length.at.least(1);
expect(tree["w:p"][0]["w:pPr"][0]).to.deep.equal({
"w:pStyle": [{ _attr: { "w:val": "ListParagraph" } }],
"w:pStyle": { _attr: { "w:val": "ListParagraph" } },
});
});
@ -542,7 +527,7 @@ describe("Paragraph", () => {
.which.is.an("array")
.which.has.length.at.least(2);
expect(tree["w:p"][0]["w:pPr"][1]).to.deep.equal({
"w:numPr": [{ "w:ilvl": [{ _attr: { "w:val": 1 } }] }, { "w:numId": [{ _attr: { "w:val": 1 } }] }],
"w:numPr": [{ "w:ilvl": { _attr: { "w:val": 1 } } }, { "w:numId": { _attr: { "w:val": 1 } } }],
});
});
});
@ -565,7 +550,7 @@ describe("Paragraph", () => {
.which.is.an("array")
.which.has.length.at.least(1);
expect(tree["w:p"][0]["w:pPr"][0]).to.deep.equal({
"w:pStyle": [{ _attr: { "w:val": "ListParagraph" } }],
"w:pStyle": { _attr: { "w:val": "ListParagraph" } },
});
});
@ -581,11 +566,11 @@ describe("Paragraph", () => {
"w:p": [
{
"w:pPr": [
{ "w:pStyle": [{ _attr: { "w:val": "ListParagraph" } }] },
{ "w:pStyle": { _attr: { "w:val": "ListParagraph" } } },
{
"w:numPr": [
{ "w:ilvl": [{ _attr: { "w:val": 0 } }] },
{ "w:numId": [{ _attr: { "w:val": letterNumbering.id } }] },
{ "w:ilvl": { _attr: { "w:val": 0 } } },
{ "w:numId": { _attr: { "w:val": letterNumbering.id } } },
],
},
],
@ -602,7 +587,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:pStyle": [{ _attr: { "w:val": "myFancyStyle" } }] }],
"w:pPr": [{ "w:pStyle": { _attr: { "w:val": "myFancyStyle" } } }],
},
],
});
@ -616,7 +601,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:ind": [{ _attr: { "w:left": 720 } }] }],
"w:pPr": [{ "w:ind": { _attr: { "w:left": 720 } } }],
},
],
});
@ -630,7 +615,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:spacing": [{ _attr: { "w:before": 90, "w:line": 50 } }] }],
"w:pPr": [{ "w:spacing": { _attr: { "w:before": 90, "w:line": 50 } } }],
},
],
});
@ -642,7 +627,7 @@ describe("Paragraph", () => {
paragraph.keepLines();
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"w:p": [{ "w:pPr": [{ "w:keepLines": [] }] }],
"w:p": [{ "w:pPr": [{ "w:keepLines": EMPTY_OBJECT }] }],
});
});
});
@ -652,7 +637,7 @@ describe("Paragraph", () => {
paragraph.keepNext();
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"w:p": [{ "w:pPr": [{ "w:keepNext": [] }] }],
"w:p": [{ "w:pPr": [{ "w:keepNext": EMPTY_OBJECT }] }],
});
});
});
@ -662,7 +647,7 @@ describe("Paragraph", () => {
paragraph.bidirectional();
const tree = new Formatter().format(paragraph);
expect(tree).to.deep.equal({
"w:p": [{ "w:pPr": [{ "w:bidi": [] }] }],
"w:p": [{ "w:pPr": [{ "w:bidi": EMPTY_OBJECT }] }],
});
});
});
@ -674,7 +659,7 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
"w:pPr": [{ "w:outlineLvl": [{ _attr: { "w:val": "0" } }] }],
"w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": "0" } } }],
},
],
});

View File

@ -1,8 +1,8 @@
// http://officeopenxml.com/WPparagraphProperties.php
import { XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components";
import { Border } from "./formatting/border";
export class ParagraphProperties extends XmlComponent {
export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
public readonly paragraphBorder: Border;
constructor() {

View File

@ -1,6 +1,6 @@
import { XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components";
export class RunProperties extends XmlComponent {
export class RunProperties extends IgnoreIfEmptyXmlComponent {
constructor() {
super("w:rPr");
}

View File

@ -9,7 +9,7 @@ describe("Text", () => {
it("creates an empty text run if no text is given", () => {
const t = new Text("");
const f = new Formatter().format(t);
expect(f).to.deep.equal({ "w:t": [{ _attr: { "xml:space": "preserve" } }] });
expect(f).to.deep.equal({ "w:t": { _attr: { "xml:space": "preserve" } } });
});
it("adds the passed in text to the component", () => {

View File

@ -9,16 +9,16 @@ describe("RunFonts", () => {
it("uses the font name for both ascii and hAnsi", () => {
const tree = new Formatter().format(new RunFonts("Times"));
expect(tree).to.deep.equal({
"w:rFonts": [{ _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } }],
"w:rFonts": { _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } },
});
});
it("uses hint if given", () => {
const tree = new Formatter().format(new RunFonts("Times", "default"));
expect(tree).to.deep.equal({
"w:rFonts": [
{ _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times", "w:hint": "default" } },
],
"w:rFonts": {
_attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times", "w:hint": "default" },
},
});
});
});

View File

@ -41,7 +41,7 @@ describe("Run", () => {
run.underline();
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [{ "w:rPr": [{ "w:u": [{ _attr: { "w:val": "single" } }] }] }],
"w:r": [{ "w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }] }],
});
});
@ -49,7 +49,7 @@ describe("Run", () => {
run.underline("double", "990011");
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [{ "w:rPr": [{ "w:u": [{ _attr: { "w:val": "double", "w:color": "990011" } }] }] }],
"w:r": [{ "w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "990011" } } }] }],
});
});
});
@ -114,7 +114,7 @@ describe("Run", () => {
"w:r": [
{
"w:rPr": [
{ "w:rFonts": [{ _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } }] },
{ "w:rFonts": { _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } } },
],
},
],
@ -127,7 +127,7 @@ describe("Run", () => {
run.color("001122");
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [{ "w:rPr": [{ "w:color": [{ _attr: { "w:val": "001122" } }] }] }],
"w:r": [{ "w:rPr": [{ "w:color": { _attr: { "w:val": "001122" } } }] }],
});
});
});
@ -139,7 +139,7 @@ describe("Run", () => {
expect(tree).to.deep.equal({
"w:r": [
{
"w:rPr": [{ "w:sz": [{ _attr: { "w:val": 24 } }] }, { "w:szCs": [{ _attr: { "w:val": 24 } }] }],
"w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }],
},
],
});
@ -151,7 +151,7 @@ describe("Run", () => {
run.rightToLeft();
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [{ "w:rPr": [{ "w:rtl": [{ _attr: { "w:val": true } }] }] }],
"w:r": [{ "w:rPr": [{ "w:rtl": { _attr: { "w:val": true } } }] }],
});
});
});
@ -162,11 +162,10 @@ describe("Run", () => {
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{ "w:rPr": [] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "begin" } }] },
{ "w:fldChar": { _attr: { "w:fldCharType": "begin" } } },
{ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "NUMPAGES"] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "separate" } }] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "end" } }] },
{ "w:fldChar": { _attr: { "w:fldCharType": "separate" } } },
{ "w:fldChar": { _attr: { "w:fldCharType": "end" } } },
],
});
});
@ -178,11 +177,10 @@ describe("Run", () => {
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [
{ "w:rPr": [] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "begin" } }] },
{ "w:fldChar": { _attr: { "w:fldCharType": "begin" } } },
{ "w:instrText": [{ _attr: { "xml:space": "preserve" } }, "PAGE"] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "separate" } }] },
{ "w:fldChar": [{ _attr: { "w:fldCharType": "end" } }] },
{ "w:fldChar": { _attr: { "w:fldCharType": "separate" } } },
{ "w:fldChar": { _attr: { "w:fldCharType": "end" } } },
],
});
});
@ -193,7 +191,7 @@ describe("Run", () => {
run.style("myRunStyle");
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
"w:r": [{ "w:rPr": [{ "w:rStyle": [{ _attr: { "w:val": "myRunStyle" } }] }] }],
"w:r": [{ "w:rPr": [{ "w:rStyle": { _attr: { "w:val": "myRunStyle" } } }] }],
});
});
});

View File

@ -17,17 +17,12 @@ describe("Sequential Identifier", () => {
const DEFAULT_SEQ = {
"w:r": [
{
"w:rPr": [],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "begin",
"w:dirty": true,
},
},
],
},
{
"w:instrText": [
@ -40,22 +35,18 @@ const DEFAULT_SEQ = {
],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "separate",
},
},
],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "end",
},
},
],
},
],
};

View File

@ -12,7 +12,7 @@ describe("TextRun", () => {
run = new TextRun("test");
const f = new Formatter().format(run);
expect(f).to.deep.equal({
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "test"] }],
"w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "test"] }],
});
});
});

View File

@ -17,7 +17,7 @@ describe("Underline", () => {
const underline = new u.Underline();
const tree = new Formatter().format(underline);
expect(tree).to.deep.equal({
"w:u": [{ _attr: { "w:val": "single" } }],
"w:u": { _attr: { "w:val": "single" } },
});
});
@ -25,7 +25,7 @@ describe("Underline", () => {
const underline = new u.Underline("double", "FF00CC");
const tree = new Formatter().format(underline);
expect(tree).to.deep.equal({
"w:u": [{ _attr: { "w:val": "double", "w:color": "FF00CC" } }],
"w:u": { _attr: { "w:val": "double", "w:color": "FF00CC" } },
});
});
});

View File

@ -11,8 +11,7 @@ describe("Relationships", () => {
const properties = new Relationships();
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["Relationships"]);
expect(tree["Relationships"]).to.be.an.instanceof(Array);
expect(tree["Relationships"][0]).to.deep.equal({
expect(tree["Relationships"]).to.deep.equal({
_attr: { xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" },
});
});

View File

@ -2,13 +2,15 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import { Compatibility } from "file/settings/compatibility";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Compatibility", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
const compatibility = new Compatibility();
const tree = new Formatter().format(compatibility);
expect(tree).to.deep.equal({ "w:compat": [] });
expect(tree).to.deep.equal({ "w:compat": EMPTY_OBJECT });
});
});
@ -18,7 +20,7 @@ describe("Compatibility", () => {
compatibility.doNotExpandShiftReturn();
const tree = new Formatter().format(compatibility);
expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotExpandShiftReturn": [] }] });
expect(tree).to.deep.equal({ "w:compat": [{ "w:doNotExpandShiftReturn": EMPTY_OBJECT }] });
});
});
});

View File

@ -13,9 +13,7 @@ describe("Settings", () => {
expect(keys).is.an.instanceof(Array);
expect(keys).has.length(1);
expect(keys[0]).to.be.equal("w:settings");
expect(tree["w:settings"]).is.an.instanceof(Array);
expect(tree["w:settings"]).has.length(1);
keys = Object.keys(tree["w:settings"][0]);
keys = Object.keys(tree["w:settings"]);
expect(keys).is.an.instanceof(Array);
expect(keys).has.length(1);
expect(keys[0]).to.be.equal("_attr");
@ -39,12 +37,12 @@ describe("Settings", () => {
expect(keys).is.an.instanceof(Array);
expect(keys).has.length(1);
expect(keys[0]).to.be.equal("w:updateFields");
const updateFieldsArray = rootArray[1]["w:updateFields"];
keys = Object.keys(updateFieldsArray[0]);
const updateFields = rootArray[1]["w:updateFields"];
keys = Object.keys(updateFields);
expect(keys).is.an.instanceof(Array);
expect(keys).has.length(1);
expect(keys[0]).to.be.equal("_attr");
const updateFieldsAttr = updateFieldsArray[0]._attr;
const updateFieldsAttr = updateFields._attr;
expect(updateFieldsAttr["w:val"]).to.be.equal(true);
};
it("should add a UpdateFields with value true", () => {

View File

@ -5,22 +5,18 @@ import { Formatter } from "export/formatter";
import { UpdateFields } from "./update-fields";
const UF_TRUE = {
"w:updateFields": [
{
"w:updateFields": {
_attr: {
"w:val": true,
},
},
],
};
const UF_FALSE = {
"w:updateFields": [
{
"w:updateFields": {
_attr: {
"w:val": false,
},
},
],
};
describe("Update Fields", () => {
describe("#constructor", () => {

View File

@ -71,24 +71,34 @@ describe("External styles factory", () => {
deleted: false,
root: [
{
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:ascii": "Arial",
"w:cstheme": "minorHAnsi",
"w:eastAsiaTheme": "minorHAnsi",
"w:hAnsi": "Arial",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:rFonts",
},
{
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:bidi": "ar-SA",
"w:eastAsia": "en-US",
"w:val": "en-US",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:lang",
},
],
@ -104,13 +114,18 @@ describe("External styles factory", () => {
deleted: false,
root: [
{
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:after": "160",
"w:line": "259",
"w:lineRule": "auto",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:spacing",
},
],
@ -123,12 +138,17 @@ describe("External styles factory", () => {
rootKey: "w:docDefaults",
});
expect(importedStyle.root[2]).to.deep.equal({
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:defLockedState": "1",
"w:defUIPriority": "99",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:latentStyles",
});
});
@ -139,19 +159,28 @@ describe("External styles factory", () => {
expect(importedStyle.root.length).to.equal(5);
expect(importedStyle.root[3]).to.deep.equal({
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:default": "1",
"w:styleId": "Normal",
"w:type": "paragraph",
},
rootKey: "_attr",
},
{
deleted: false,
root: [
{
_attr: {
deleted: false,
root: {
"w:val": "Normal",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:name",
},
{
@ -164,26 +193,40 @@ describe("External styles factory", () => {
});
expect(importedStyle.root[4]).to.deep.equal({
_attr: {
"w:styleId": "Heading1",
"w:type": "paragraph",
},
deleted: false,
root: [
{
_attr: {
deleted: false,
root: {
"w:styleId": "Heading1",
"w:type": "paragraph",
},
rootKey: "_attr",
},
{
deleted: false,
root: [
{
deleted: false,
root: {
"w:val": "heading 1",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:name",
},
{
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:val": "Normal",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:basedOn",
},
{
@ -203,14 +246,19 @@ describe("External styles factory", () => {
deleted: false,
root: [
{
_attr: {
deleted: false,
root: [
{
deleted: false,
root: {
"w:color": "auto",
"w:space": "1",
"w:sz": "4",
"w:val": "single",
},
deleted: false,
root: [],
rootKey: "_attr",
},
],
rootKey: "w:bottom",
},
],

View File

@ -4,6 +4,8 @@ import { Formatter } from "export/formatter";
import { CharacterStyle } from "./character-style";
import { EMPTY_OBJECT } from "file/xml-components";
describe("CharacterStyle", () => {
describe("#constructor", () => {
it("should set the style type to character and use the given style id", () => {
@ -12,18 +14,15 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{ "w:rPr": [] },
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -35,19 +34,16 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{ "w:name": [{ _attr: { "w:val": "Style Name" } }] },
{ "w:rPr": [] },
{
"w:uiPriority": [
{ "w:name": { _attr: { "w:val": "Style Name" } } },
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -61,20 +57,17 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{ "w:rPr": [] },
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
{ "w:basedOn": [{ _attr: { "w:val": "otherId" } }] },
{ "w:basedOn": { _attr: { "w:val": "otherId" } } },
],
});
});
@ -88,19 +81,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:sz": [{ _attr: { "w:val": 24 } }] }, { "w:szCs": [{ _attr: { "w:val": 24 } }] }],
"w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -114,19 +105,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "single" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -139,19 +128,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double" } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -164,19 +151,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double", "w:color": "005599" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "005599" } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -192,27 +177,23 @@ describe("CharacterStyle", () => {
{
"w:rPr": [
{
"w:vertAlign": [
{
"w:vertAlign": {
_attr: {
"w:val": "superscript",
},
},
],
},
],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -225,19 +206,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:color": [{ _attr: { "w:val": "123456" } }] }],
"w:rPr": [{ "w:color": { _attr: { "w:val": "123456" } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -250,19 +229,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:b": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:b": { _attr: { "w:val": true } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -275,19 +252,17 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [{ "w:i": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:i": { _attr: { "w:val": true } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -300,21 +275,16 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
{ "w:link": [{ _attr: { "w:val": "MyLink" } }] },
{ "w:link": { _attr: { "w:val": "MyLink" } } },
],
});
});
@ -326,19 +296,14 @@ describe("CharacterStyle", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
{
"w:rPr": [],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{ "w:unhideWhenUsed": [] },
{ "w:semiHidden": [] },
{ "w:unhideWhenUsed": EMPTY_OBJECT },
{ "w:semiHidden": EMPTY_OBJECT },
],
});
});

View File

@ -2,52 +2,54 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import * as components from "./components";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Style components", () => {
it("Name#constructor", () => {
const style = new components.Name("Style Name");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:name": [{ _attr: { "w:val": "Style Name" } }] });
expect(tree).to.deep.equal({ "w:name": { _attr: { "w:val": "Style Name" } } });
});
it("BasedOn#constructor", () => {
const style = new components.BasedOn("otherId");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:basedOn": [{ _attr: { "w:val": "otherId" } }] });
expect(tree).to.deep.equal({ "w:basedOn": { _attr: { "w:val": "otherId" } } });
});
it("Next#constructor", () => {
const style = new components.Next("otherId");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:next": [{ _attr: { "w:val": "otherId" } }] });
expect(tree).to.deep.equal({ "w:next": { _attr: { "w:val": "otherId" } } });
});
it("Link#constructor", () => {
const style = new components.Link("otherId");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:link": [{ _attr: { "w:val": "otherId" } }] });
expect(tree).to.deep.equal({ "w:link": { _attr: { "w:val": "otherId" } } });
});
it("UiPriority#constructor", () => {
const style = new components.UiPriority("123");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:uiPriority": [{ _attr: { "w:val": "123" } }] });
expect(tree).to.deep.equal({ "w:uiPriority": { _attr: { "w:val": "123" } } });
});
it("UnhideWhenUsed#constructor", () => {
const style = new components.UnhideWhenUsed();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:unhideWhenUsed": [] });
expect(tree).to.deep.equal({ "w:unhideWhenUsed": EMPTY_OBJECT });
});
it("QuickFormat#constructor", () => {
const style = new components.QuickFormat();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:qFormat": [] });
expect(tree).to.deep.equal({ "w:qFormat": EMPTY_OBJECT });
});
it("SemiHidden#constructor", () => {
const style = new components.SemiHidden();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({ "w:semiHidden": [] });
expect(tree).to.deep.equal({ "w:semiHidden": EMPTY_OBJECT });
});
});

View File

@ -2,6 +2,8 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import * as defaultStyels from "./default-styles";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Default Styles", () => {
it("HeadingStyle#constructor", () => {
const style = new defaultStyels.HeadingStyle("Heading1", "Heading 1");
@ -9,12 +11,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading1" } },
{ "w:name": [{ _attr: { "w:val": "Heading 1" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 1" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -25,12 +25,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Title" } },
{ "w:name": [{ _attr: { "w:val": "Title" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Title" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -41,12 +39,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading1" } },
{ "w:name": [{ _attr: { "w:val": "Heading 1" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 1" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -57,12 +53,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading2" } },
{ "w:name": [{ _attr: { "w:val": "Heading 2" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 2" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -73,12 +67,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading3" } },
{ "w:name": [{ _attr: { "w:val": "Heading 3" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 3" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -89,12 +81,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading4" } },
{ "w:name": [{ _attr: { "w:val": "Heading 4" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 4" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -105,12 +95,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading5" } },
{ "w:name": [{ _attr: { "w:val": "Heading 5" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 5" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -121,12 +109,10 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "Heading6" } },
{ "w:name": [{ _attr: { "w:val": "Heading 6" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:next": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "Heading 6" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:next": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -137,11 +123,9 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "ListParagraph" } },
{ "w:name": [{ _attr: { "w:val": "List Paragraph" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:qFormat": [] },
{ "w:name": { _attr: { "w:val": "List Paragraph" } } },
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:qFormat": EMPTY_OBJECT },
],
});
});
@ -152,60 +136,52 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "FootnoteText" } },
{ "w:name": [{ _attr: { "w:val": "footnote text" } }] },
{ "w:name": { _attr: { "w:val": "footnote text" } } },
{
"w:pPr": [
{
"w:spacing": [
{
"w:spacing": {
_attr: {
"w:after": 0,
"w:line": 240,
"w:lineRule": "auto",
},
},
],
},
],
},
{
"w:rPr": [
{
"w:sz": [
{
"w:sz": {
_attr: {
"w:val": 20,
},
},
],
},
{
"w:szCs": [
{
"w:szCs": {
_attr: {
"w:val": 20,
},
},
],
},
],
},
{ "w:basedOn": [{ _attr: { "w:val": "Normal" } }] },
{ "w:link": [{ _attr: { "w:val": "FootnoteTextChar" } }] },
{
"w:uiPriority": [
{ "w:basedOn": { _attr: { "w:val": "Normal" } } },
{ "w:link": { _attr: { "w:val": "FootnoteTextChar" } } },
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:semiHidden": [],
"w:semiHidden": EMPTY_OBJECT,
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
});
@ -217,36 +193,32 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "FootnoteReference" } },
{ "w:name": [{ _attr: { "w:val": "footnote reference" } }] },
{ "w:name": { _attr: { "w:val": "footnote reference" } } },
{
"w:rPr": [
{
"w:vertAlign": [
{
"w:vertAlign": {
_attr: {
"w:val": "superscript",
},
},
],
},
],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
{ "w:basedOn": [{ _attr: { "w:val": "DefaultParagraphFont" } }] },
{ "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
{
"w:semiHidden": [],
"w:semiHidden": EMPTY_OBJECT,
},
],
});
@ -258,45 +230,39 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "FootnoteTextChar" } },
{ "w:name": [{ _attr: { "w:val": "Footnote Text Char" } }] },
{ "w:name": { _attr: { "w:val": "Footnote Text Char" } } },
{
"w:rPr": [
{
"w:sz": [
{
"w:sz": {
_attr: {
"w:val": 20,
},
},
],
},
{
"w:szCs": [
{
"w:szCs": {
_attr: {
"w:val": 20,
},
},
],
},
],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
{ "w:basedOn": [{ _attr: { "w:val": "DefaultParagraphFont" } }] },
{ "w:link": [{ _attr: { "w:val": "FootnoteText" } }] },
{ "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
{ "w:link": { _attr: { "w:val": "FootnoteText" } } },
{
"w:semiHidden": [],
"w:semiHidden": EMPTY_OBJECT,
},
],
});
@ -308,23 +274,21 @@ describe("Default Styles", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "Hyperlink" } },
{ "w:name": [{ _attr: { "w:val": "Hyperlink" } }] },
{ "w:name": { _attr: { "w:val": "Hyperlink" } } },
{
"w:rPr": [{ "w:color": [{ _attr: { "w:val": "0563C1" } }] }, { "w:u": [{ _attr: { "w:val": "single" } }] }],
"w:rPr": [{ "w:color": { _attr: { "w:val": "0563C1" } } }, { "w:u": { _attr: { "w:val": "single" } } }],
},
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
{ "w:basedOn": [{ _attr: { "w:val": "DefaultParagraphFont" } }] },
{ "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
],
});
});

View File

@ -4,13 +4,15 @@ import { Formatter } from "export/formatter";
import { ParagraphStyle } from "./paragraph-style";
import { EMPTY_OBJECT } from "file/xml-components";
describe("ParagraphStyle", () => {
describe("#constructor", () => {
it("should set the style type to paragraph and use the given style id", () => {
const style = new ParagraphStyle("myStyleId");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:pPr": [] }, { "w:rPr": [] }],
"w:style": { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
});
});
@ -20,9 +22,7 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:name": [{ _attr: { "w:val": "Style Name" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:name": { _attr: { "w:val": "Style Name" } } },
],
});
});
@ -35,9 +35,7 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:basedOn": [{ _attr: { "w:val": "otherId" } }] },
{ "w:basedOn": { _attr: { "w:val": "otherId" } } },
],
});
});
@ -46,12 +44,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").quickFormat();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:qFormat": [] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:qFormat": EMPTY_OBJECT }],
});
});
@ -61,9 +54,7 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:next": [{ _attr: { "w:val": "otherId" } }] },
{ "w:next": { _attr: { "w:val": "otherId" } } },
],
});
});
@ -77,9 +68,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:ind": [{ _attr: { "w:left": 720 } }] }],
"w:pPr": [{ "w:ind": { _attr: { "w:left": 720 } } }],
},
{ "w:rPr": [] },
],
});
});
@ -91,9 +81,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:spacing": [{ _attr: { "w:before": 50, "w:after": 150 } }] }],
"w:pPr": [{ "w:spacing": { _attr: { "w:before": 50, "w:after": 150 } } }],
},
{ "w:rPr": [] },
],
});
});
@ -105,9 +94,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "center" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "center" } } }],
},
{ "w:rPr": [] },
],
});
});
@ -118,9 +106,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:spacing": [{ _attr: { "w:val": 24 } }] }],
"w:rPr": [{ "w:spacing": { _attr: { "w:val": 24 } } }],
},
],
});
@ -133,9 +120,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "left" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "left" } } }],
},
{ "w:rPr": [] },
],
});
});
@ -147,9 +133,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "right" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "right" } } }],
},
{ "w:rPr": [] },
],
});
});
@ -161,9 +146,8 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
"w:pPr": [{ "w:jc": [{ _attr: { "w:val": "both" } }] }],
"w:pPr": [{ "w:jc": { _attr: { "w:val": "both" } } }],
},
{ "w:rPr": [] },
],
});
});
@ -179,8 +163,7 @@ describe("ParagraphStyle", () => {
{
"w:pBdr": [
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:color": "auto",
"w:space": "1",
@ -188,13 +171,11 @@ describe("ParagraphStyle", () => {
"w:sz": "6",
},
},
],
},
],
},
],
},
{ "w:rPr": [] },
],
});
});
@ -208,11 +189,10 @@ describe("ParagraphStyle", () => {
{
"w:pPr": [
{
"w:tabs": [{ "w:tab": [{ _attr: { "w:val": "left", "w:pos": 1200 } }] }],
"w:tabs": [{ "w:tab": { _attr: { "w:val": "left", "w:pos": 1200 } } }],
},
],
},
{ "w:rPr": [] },
],
});
});
@ -226,11 +206,10 @@ describe("ParagraphStyle", () => {
{
"w:pPr": [
{
"w:tabs": [{ "w:tab": [{ _attr: { "w:val": "right", "w:pos": 9026 } }] }],
"w:tabs": [{ "w:tab": { _attr: { "w:val": "right", "w:pos": 9026 } } }],
},
],
},
{ "w:rPr": [] },
],
});
});
@ -239,11 +218,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").keepLines();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [{ "w:keepLines": [] }] },
{ "w:rPr": [] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:pPr": [{ "w:keepLines": EMPTY_OBJECT }] }],
});
});
@ -251,11 +226,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").keepNext();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [{ "w:keepNext": [] }] },
{ "w:rPr": [] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:pPr": [{ "w:keepNext": EMPTY_OBJECT }] }],
});
});
@ -265,8 +236,7 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [{ "w:outlineLvl": [{ _attr: { "w:val": "1" } }] }] },
{ "w:rPr": [] },
{ "w:pPr": [{ "w:outlineLvl": { _attr: { "w:val": "1" } } }] },
],
});
});
@ -279,9 +249,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:sz": [{ _attr: { "w:val": 24 } }] }, { "w:szCs": [{ _attr: { "w:val": 24 } }] }],
"w:rPr": [{ "w:sz": { _attr: { "w:val": 24 } } }, { "w:szCs": { _attr: { "w:val": 24 } } }],
},
],
});
@ -293,9 +262,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:smallCaps": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
},
],
});
@ -307,9 +275,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:caps": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
},
],
});
@ -321,9 +288,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:strike": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
},
],
});
@ -335,9 +301,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:dstrike": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
},
],
});
@ -349,9 +314,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:vertAlign": [{ _attr: { "w:val": "subscript" } }] }],
"w:rPr": [{ "w:vertAlign": { _attr: { "w:val": "subscript" } } }],
},
],
});
@ -363,9 +327,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:vertAlign": [{ _attr: { "w:val": "superscript" } }] }],
"w:rPr": [{ "w:vertAlign": { _attr: { "w:val": "superscript" } } }],
},
],
});
@ -377,10 +340,9 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [
{ "w:rFonts": [{ _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } }] },
{ "w:rFonts": { _attr: { "w:ascii": "Times", "w:cs": "Times", "w:eastAsia": "Times", "w:hAnsi": "Times" } } },
],
},
],
@ -393,9 +355,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:b": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:b": { _attr: { "w:val": true } } }],
},
],
});
@ -407,9 +368,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:i": [{ _attr: { "w:val": true } }] }],
"w:rPr": [{ "w:i": { _attr: { "w:val": true } } }],
},
],
});
@ -422,9 +382,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "single" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }],
},
],
});
@ -436,9 +395,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double" } } }],
},
],
});
@ -450,9 +408,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:u": [{ _attr: { "w:val": "double", "w:color": "005599" } }] }],
"w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "005599" } } }],
},
],
});
@ -465,9 +422,8 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{
"w:rPr": [{ "w:color": [{ _attr: { "w:val": "123456" } }] }],
"w:rPr": [{ "w:color": { _attr: { "w:val": "123456" } } }],
},
],
});
@ -477,12 +433,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").link("MyLink");
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:link": [{ _attr: { "w:val": "MyLink" } }] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:link": { _attr: { "w:val": "MyLink" } } }],
});
});
@ -490,12 +441,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").semiHidden();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:semiHidden": [] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:semiHidden": EMPTY_OBJECT }],
});
});
@ -505,16 +451,12 @@ describe("ParagraphStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
],
});
@ -524,12 +466,7 @@ describe("ParagraphStyle", () => {
const style = new ParagraphStyle("myStyleId").unhideWhenUsed();
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:unhideWhenUsed": [] },
],
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } }, { "w:unhideWhenUsed": EMPTY_OBJECT }],
});
});
});

View File

@ -12,7 +12,7 @@ describe("Style", () => {
});
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId", "w:default": true } }],
"w:style": { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId", "w:default": true } },
});
});
@ -28,7 +28,7 @@ describe("Style", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{ "w:name": [{ _attr: { "w:val": "Style Name" } }] },
{ "w:name": { _attr: { "w:val": "Style Name" } } },
],
});
});

View File

@ -6,6 +6,8 @@ import { CharacterStyle, ParagraphStyle } from "./style";
import { Styles } from "./styles";
import { EMPTY_OBJECT } from "file/xml-components";
describe("Styles", () => {
let styles: Styles;
@ -27,7 +29,7 @@ describe("Styles", () => {
const tree = new Formatter().format(styles)["w:styles"].filter((x) => !x._attr);
expect(tree).to.deep.equal([
{
"w:style": [{ _attr: { "w:type": "paragraph", "w:styleId": "pStyleId" } }, { "w:pPr": [] }, { "w:rPr": [] }],
"w:style": { _attr: { "w:type": "paragraph", "w:styleId": "pStyleId" } },
},
]);
});
@ -40,9 +42,7 @@ describe("Styles", () => {
{
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "pStyleId" } },
{ "w:name": [{ _attr: { "w:val": "Paragraph Style" } }] },
{ "w:pPr": [] },
{ "w:rPr": [] },
{ "w:name": { _attr: { "w:val": "Paragraph Style" } } },
],
},
]);
@ -58,18 +58,15 @@ describe("Styles", () => {
{
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "pStyleId" } },
{ "w:rPr": [] },
{
"w:uiPriority": [
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
},
@ -84,19 +81,16 @@ describe("Styles", () => {
{
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "pStyleId" } },
{ "w:name": [{ _attr: { "w:val": "Character Style" } }] },
{ "w:rPr": [] },
{
"w:uiPriority": [
{ "w:name": { _attr: { "w:val": "Character Style" } } },
{
"w:uiPriority": {
_attr: {
"w:val": "99",
},
},
],
},
{
"w:unhideWhenUsed": [],
"w:unhideWhenUsed": EMPTY_OBJECT,
},
],
},

View File

@ -49,13 +49,11 @@ const DEFAULT_TOC = {
{
"w:sdtPr": [
{
"w:alias": [
{
"w:alias": {
_attr: {
"w:val": "Table of Contents",
},
},
],
},
],
},
@ -63,23 +61,15 @@ const DEFAULT_TOC = {
"w:sdtContent": [
{
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "begin",
"w:dirty": true,
},
},
],
},
{
"w:instrText": [
@ -92,13 +82,11 @@ const DEFAULT_TOC = {
],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "separate",
},
},
],
},
],
},
@ -106,22 +94,14 @@ const DEFAULT_TOC = {
},
{
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "end",
},
},
],
},
],
},
@ -137,13 +117,11 @@ const COMPLETE_TOC = {
{
"w:sdtPr": [
{
"w:alias": [
{
"w:alias": {
_attr: {
"w:val": "Summary",
},
},
],
},
],
},
@ -151,23 +129,15 @@ const COMPLETE_TOC = {
"w:sdtContent": [
{
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "begin",
"w:dirty": true,
},
},
],
},
{
"w:instrText": [
@ -180,13 +150,11 @@ const COMPLETE_TOC = {
],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "separate",
},
},
],
},
],
},
@ -194,22 +162,14 @@ const COMPLETE_TOC = {
},
{
"w:p": [
{
"w:pPr": [],
},
{
"w:r": [
{
"w:rPr": [],
},
{
"w:fldChar": [
{
"w:fldChar": {
_attr: {
"w:fldCharType": "end",
},
},
],
},
],
},

View File

@ -4,20 +4,22 @@ import { Formatter } from "export/formatter";
import { GridCol, TableGrid } from "./grid";
import { EMPTY_OBJECT } from "file/xml-components";
describe("GridCol", () => {
describe("#constructor", () => {
it("sets the width attribute to the value given", () => {
const grid = new GridCol(1234);
const tree = new Formatter().format(grid);
expect(tree).to.deep.equal({
"w:gridCol": [{ _attr: { "w:w": 1234 } }],
"w:gridCol": { _attr: { "w:w": 1234 } },
});
});
it("does not set a width attribute if not given", () => {
const grid = new GridCol();
const tree = new Formatter().format(grid);
expect(tree).to.deep.equal({ "w:gridCol": [] });
expect(tree).to.deep.equal({ "w:gridCol": EMPTY_OBJECT });
});
});
});
@ -29,9 +31,9 @@ describe("TableGrid", () => {
const tree = new Formatter().format(grid);
expect(tree).to.deep.equal({
"w:tblGrid": [
{ "w:gridCol": [{ _attr: { "w:w": 1234 } }] },
{ "w:gridCol": [{ _attr: { "w:w": 321 } }] },
{ "w:gridCol": [{ _attr: { "w:w": 123 } }] },
{ "w:gridCol": { _attr: { "w:w": 1234 } } },
{ "w:gridCol": { _attr: { "w:w": 321 } } },
{ "w:gridCol": { _attr: { "w:w": 123 } } },
],
});
});

View File

@ -7,30 +7,26 @@ import { ShadingType, TableShading } from "./shading";
describe("TableShading", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargain = new TableShading({});
const tree = new Formatter().format(cellMargain);
const shading = new TableShading({});
const tree = new Formatter().format(shading);
expect(tree).to.deep.equal({
"w:shd": [
{
"w:shd": {
_attr: {},
},
],
});
});
it("should create with params", () => {
const cellMargain = new TableShading({ val: ShadingType.PERCENT_40, color: "FF0000", fill: "555555" });
const tree = new Formatter().format(cellMargain);
const shading = new TableShading({ val: ShadingType.PERCENT_40, color: "FF0000", fill: "555555" });
const tree = new Formatter().format(shading);
expect(tree).to.deep.equal({
"w:shd": [
{
"w:shd": {
_attr: {
"w:color": "FF0000",
"w:fill": "555555",
"w:val": "pct40",
},
},
],
});
});
});

View File

@ -1,81 +0,0 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { BottomCellMargain, LeftCellMargain, RightCellMargain, TopCellMargain } from "./cell-margain";
describe("TopCellMargain", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargain = new TopCellMargain(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:top": [
{
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
],
});
});
});
});
describe("BottomCellMargain", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargain = new BottomCellMargain(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:bottom": [
{
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
],
});
});
});
});
describe("LeftCellMargain", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargain = new LeftCellMargain(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:start": [
{
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
],
});
});
});
});
describe("RightCellMargain", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargain = new RightCellMargain(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:end": [
{
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
],
});
});
});
});

View File

@ -1,112 +0,0 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { TableCellMargain } from "./table-cell-margains";
describe("TableCellMargain", () => {
describe("#constructor", () => {
it("should create with default values", () => {
const cellMargain = new TableCellMargain({});
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:tcMar": [
{
"w:top": [
{
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
],
},
{
"w:bottom": [
{
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
],
},
{
"w:end": [
{
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
],
},
{
"w:start": [
{
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
],
},
],
});
});
it("should create with values", () => {
const cellMargain = new TableCellMargain({
top: 5,
bottom: 5,
left: 5,
right: 5,
});
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({
"w:tcMar": [
{
"w:top": [
{
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
],
},
{
"w:bottom": [
{
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
],
},
{
"w:end": [
{
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
],
},
{
"w:start": [
{
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
],
},
],
});
});
});
});

View File

@ -1,21 +0,0 @@
// http://officeopenxml.com/WPtableCellProperties-Margins.php
import { XmlComponent } from "file/xml-components";
import { BottomCellMargain, LeftCellMargain, RightCellMargain, TopCellMargain } from "./cell-margain";
export interface ITableCellMargainOptions {
readonly top?: number;
readonly left?: number;
readonly bottom?: number;
readonly right?: number;
}
export class TableCellMargain extends XmlComponent {
constructor({ top = 0, left = 0, right = 0, bottom = 0 }: ITableCellMargainOptions) {
super("w:tcMar");
this.root.push(new TopCellMargain(top));
this.root.push(new BottomCellMargain(bottom));
this.root.push(new RightCellMargain(right));
this.root.push(new LeftCellMargain(left));
}
}

View File

@ -0,0 +1,73 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { BottomCellMargin, LeftCellMargin, RightCellMargin, TopCellMargin } from "./cell-margin";
describe("TopCellMargin", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargin = new TopCellMargin(1);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:top": {
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
});
});
});
});
describe("BottomCellMargin", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargin = new BottomCellMargin(1);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:bottom": {
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
});
});
});
});
describe("LeftCellMargin", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargin = new LeftCellMargin(1);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:start": {
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
});
});
});
});
describe("RightCellMargin", () => {
describe("#constructor", () => {
it("should create", () => {
const cellMargin = new RightCellMargin(1);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:end": {
_attr: {
"w:type": "dxa",
"w:w": 1,
},
},
});
});
});
});

View File

@ -1,21 +1,21 @@
// http://officeopenxml.com/WPtableCellProperties-Margins.php
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export interface ICellMargainProperties {
export interface ICellMarginProperties {
readonly type: string;
readonly width: number;
}
class CellMargainAttributes extends XmlAttributeComponent<ICellMargainProperties> {
class CellMarginAttributes extends XmlAttributeComponent<ICellMarginProperties> {
protected readonly xmlKeys = { width: "w:w", type: "w:type" };
}
export class TopCellMargain extends XmlComponent {
export class TopCellMargin extends XmlComponent {
constructor(value: number) {
super("w:top");
this.root.push(
new CellMargainAttributes({
new CellMarginAttributes({
width: value,
type: "dxa",
}),
@ -23,12 +23,12 @@ export class TopCellMargain extends XmlComponent {
}
}
export class BottomCellMargain extends XmlComponent {
export class BottomCellMargin extends XmlComponent {
constructor(value: number) {
super("w:bottom");
this.root.push(
new CellMargainAttributes({
new CellMarginAttributes({
width: value,
type: "dxa",
}),
@ -36,12 +36,12 @@ export class BottomCellMargain extends XmlComponent {
}
}
export class LeftCellMargain extends XmlComponent {
export class LeftCellMargin extends XmlComponent {
constructor(value: number) {
super("w:start");
this.root.push(
new CellMargainAttributes({
new CellMarginAttributes({
width: value,
type: "dxa",
}),
@ -49,12 +49,12 @@ export class LeftCellMargain extends XmlComponent {
}
}
export class RightCellMargain extends XmlComponent {
export class RightCellMargin extends XmlComponent {
constructor(value: number) {
super("w:end");
this.root.push(
new CellMargainAttributes({
new CellMarginAttributes({
width: value,
type: "dxa",
}),

View File

@ -0,0 +1,96 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { TableCellMargin } from "./table-cell-margins";
describe("TableCellMargin", () => {
describe("#constructor", () => {
it("should create with default values", () => {
const cellMargin = new TableCellMargin({});
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:tcMar": [
{
"w:top": {
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
},
{
"w:bottom": {
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
},
{
"w:end": {
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
},
{
"w:start": {
_attr: {
"w:type": "dxa",
"w:w": 0,
},
},
},
],
});
});
it("should create with values", () => {
const cellMargin = new TableCellMargin({
top: 5,
bottom: 5,
left: 5,
right: 5,
});
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({
"w:tcMar": [
{
"w:top": {
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
},
{
"w:bottom": {
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
},
{
"w:end": {
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
},
{
"w:start": {
_attr: {
"w:type": "dxa",
"w:w": 5,
},
},
},
],
});
});
});
});

View File

@ -0,0 +1,21 @@
// http://officeopenxml.com/WPtableCellProperties-Margins.php
import { XmlComponent } from "file/xml-components";
import { BottomCellMargin, LeftCellMargin, RightCellMargin, TopCellMargin } from "./cell-margin";
export interface ITableCellMarginOptions {
readonly top?: number;
readonly left?: number;
readonly bottom?: number;
readonly right?: number;
}
export class TableCellMargin extends XmlComponent {
constructor({ top = 0, left = 0, right = 0, bottom = 0 }: ITableCellMarginOptions) {
super("w:tcMar");
this.root.push(new TopCellMargin(top));
this.root.push(new BottomCellMargin(bottom));
this.root.push(new RightCellMargin(right));
this.root.push(new LeftCellMargin(left));
}
}

View File

@ -1,5 +1,5 @@
import { BorderStyle } from "file/styles";
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
interface ICellBorder {
readonly style: BorderStyle;
@ -24,17 +24,11 @@ class BaseTableCellBorder extends XmlComponent {
}
}
export class TableCellBorders extends XmlComponent {
export class TableCellBorders extends IgnoreIfEmptyXmlComponent {
constructor() {
super("w:tcBorders");
}
public prepForXml(): IXmlableObject | undefined {
if (this.root.length > 0) {
return super.prepForXml();
}
}
public addTopBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
const top = new BaseTableCellBorder("w:top");
top.setProperties(style, size, color);

View File

@ -9,77 +9,80 @@ import { TableCellProperties } from "./table-cell-properties";
describe("TableCellProperties", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
const cellMargain = new TableCellProperties();
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [] });
const properties = new TableCellProperties();
// The TableCellProperties is ignorable if there are no attributes,
// which results in prepForXml returning undefined, which causes
// the formatter to throw an error if that is the only object it
// has been asked to format.
expect(() => new Formatter().format(properties)).to.throw("XMLComponent did not format correctly");
});
});
describe("#addGridSpan", () => {
it("adds grid span", () => {
const cellMargain = new TableCellProperties();
cellMargain.addGridSpan(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:gridSpan": [{ _attr: { "w:val": 1 } }] }] });
const properties = new TableCellProperties();
properties.addGridSpan(1);
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:gridSpan": { _attr: { "w:val": 1 } } }] });
});
});
describe("#addVerticalMerge", () => {
it("adds vertical merge", () => {
const cellMargain = new TableCellProperties();
cellMargain.addVerticalMerge(VMergeType.CONTINUE);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:vMerge": [{ _attr: { "w:val": "continue" } }] }] });
const properties = new TableCellProperties();
properties.addVerticalMerge(VMergeType.CONTINUE);
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:vMerge": { _attr: { "w:val": "continue" } } }] });
});
});
describe("#setVerticalAlign", () => {
it("sets vertical align", () => {
const cellMargain = new TableCellProperties();
cellMargain.setVerticalAlign(VerticalAlign.BOTTOM);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:vAlign": [{ _attr: { "w:val": "bottom" } }] }] });
const properties = new TableCellProperties();
properties.setVerticalAlign(VerticalAlign.BOTTOM);
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:vAlign": { _attr: { "w:val": "bottom" } } }] });
});
});
describe("#setWidth", () => {
it("should set width", () => {
const cellMargain = new TableCellProperties();
cellMargain.setWidth(1, WidthType.DXA);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:tcW": [{ _attr: { "w:type": "dxa", "w:w": 1 } }] }] });
const properties = new TableCellProperties();
properties.setWidth(1, WidthType.DXA);
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:tcW": { _attr: { "w:type": "dxa", "w:w": 1 } } }] });
});
it("should set width using default of AUTO", () => {
const cellMargain = new TableCellProperties();
cellMargain.setWidth(1);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:tcW": [{ _attr: { "w:type": "auto", "w:w": 1 } }] }] });
const properties = new TableCellProperties();
properties.setWidth(1);
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:tcW": { _attr: { "w:type": "auto", "w:w": 1 } } }] });
});
});
describe("#setShading", () => {
it("sets shading", () => {
const cellMargain = new TableCellProperties();
cellMargain.setShading({
const properties = new TableCellProperties();
properties.setShading({
fill: "test",
color: "000",
});
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": [{ _attr: { "w:fill": "test", "w:color": "000" } }] }] });
const tree = new Formatter().format(properties);
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": { _attr: { "w:fill": "test", "w:color": "000" } } }] });
});
});
describe("#Borders", () => {
it("should return the TableCellBorders if Border has borders", () => {
const cellMargain = new TableCellProperties();
cellMargain.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red");
const borders = cellMargain.Borders;
const properties = new TableCellProperties();
properties.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red");
const borders = properties.Borders;
const tree = new Formatter().format(borders);
expect(tree).to.deep.equal({
"w:tcBorders": [{ "w:top": [{ _attr: { "w:val": "dashDotStroked", "w:sz": 3, "w:color": "red" } }] }],
"w:tcBorders": [{ "w:top": { _attr: { "w:val": "dashDotStroked", "w:sz": 3, "w:color": "red" } } }],
});
});
});

View File

@ -1,10 +1,10 @@
import { XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent } from "file/xml-components";
import { ITableShadingAttributesProperties, TableShading } from "../shading";
import { ITableCellMargainOptions, TableCellMargain } from "./cell-margain/table-cell-margains";
import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins";
import { GridSpan, TableCellBorders, TableCellWidth, VAlign, VerticalAlign, VMerge, VMergeType, WidthType } from "./table-cell-components";
export class TableCellProperties extends XmlComponent {
export class TableCellProperties extends IgnoreIfEmptyXmlComponent {
private readonly cellBorder: TableCellBorders;
constructor() {
@ -47,8 +47,8 @@ export class TableCellProperties extends XmlComponent {
return this;
}
public addMargains(options: ITableCellMargainOptions): TableCellProperties {
this.root.push(new TableCellMargain(options));
public addMargins(options: ITableCellMarginOptions): TableCellProperties {
this.root.push(new TableCellMargin(options));
return this;
}

View File

@ -22,15 +22,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:top": [
{
"w:top": {
_attr: {
"w:color": "FF00FF",
"w:sz": 1,
"w:val": "dotted",
},
},
],
},
],
});
@ -44,15 +42,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:start": [
{
"w:start": {
_attr: {
"w:color": "FF00FF",
"w:sz": 2,
"w:val": "single",
},
},
],
},
],
});
@ -66,15 +62,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:color": "FF00FF",
"w:sz": 1,
"w:val": "double",
},
},
],
},
],
});
@ -88,15 +82,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:end": [
{
"w:end": {
_attr: {
"w:color": "FF00FF",
"w:sz": 3,
"w:val": "thick",
},
},
],
},
],
});
@ -110,15 +102,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:left": [
{
"w:left": {
_attr: {
"w:color": "FF00FF",
"w:sz": 3,
"w:val": "thick",
},
},
],
},
],
});
@ -132,15 +122,13 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:right": [
{
"w:right": {
_attr: {
"w:color": "FF00FF",
"w:sz": 3,
"w:val": "thick",
},
},
],
},
],
});
@ -159,70 +147,58 @@ describe("TableCellBorders", () => {
expect(tree).to.deep.equal({
"w:tcBorders": [
{
"w:top": [
{
"w:top": {
_attr: {
"w:color": "FF00FF",
"w:sz": 1,
"w:val": "dotted",
},
},
],
},
{
"w:end": [
{
"w:end": {
_attr: {
"w:color": "FF00FF",
"w:sz": 3,
"w:val": "thick",
},
},
],
},
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:color": "FF00FF",
"w:sz": 1,
"w:val": "double",
},
},
],
},
{
"w:start": [
{
"w:start": {
_attr: {
"w:color": "FF00FF",
"w:sz": 2,
"w:val": "single",
},
},
],
},
{
"w:left": [
{
"w:left": {
_attr: {
"w:color": "FF00FF",
"w:sz": 2,
"w:val": "single",
},
},
],
},
{
"w:right": [
{
"w:right": {
_attr: {
"w:color": "FF00FF",
"w:sz": 2,
"w:val": "single",
},
},
],
},
],
});
@ -236,14 +212,12 @@ describe("TableCellWidth", () => {
const tcWidth = new TableCellWidth(100, WidthType.DXA);
const tree = new Formatter().format(tcWidth);
expect(tree).to.deep.equal({
"w:tcW": [
{
"w:tcW": {
_attr: {
"w:type": "dxa",
"w:w": 100,
},
},
],
});
});
});

View File

@ -4,7 +4,7 @@ import { IXmlableObject, XmlComponent } from "file/xml-components";
import { ITableShadingAttributesProperties } from "../shading";
import { Table } from "../table";
import { ITableCellMargainOptions } from "./cell-margain/table-cell-margains";
import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins";
import { TableCellBorders, VerticalAlign, VMergeType } from "./table-cell-components";
import { TableCellProperties } from "./table-cell-properties";
@ -30,16 +30,10 @@ export class TableCell extends XmlComponent {
public prepForXml(): IXmlableObject | undefined {
// Cells must end with a paragraph
const retval = super.prepForXml();
if (!retval) {
return undefined;
if (!(this.root[this.root.length - 1] instanceof Paragraph)) {
this.createParagraph();
}
const content = retval["w:tc"];
if (!content[content.length - 1]["w:p"]) {
content.push(new Paragraph().prepForXml());
}
return retval;
return super.prepForXml();
}
public createParagraph(text?: string): Paragraph {
@ -67,8 +61,8 @@ export class TableCell extends XmlComponent {
return this;
}
public setMargains(margains: ITableCellMargainOptions): TableCell {
this.properties.addMargains(margains);
public setMargins(margins: ITableCellMarginOptions): TableCell {
this.properties.addMargins(margins);
return this;
}

View File

@ -5,6 +5,8 @@ import { Formatter } from "export/formatter";
import { TableCell } from "./table-cell";
import { TableColumn } from "./table-column";
import { EMPTY_OBJECT } from "file/xml-components";
describe("TableColumn", () => {
let cells: TableCell[];
beforeEach(() => {
@ -37,15 +39,17 @@ describe("TableColumn", () => {
const tree = new Formatter().format(cells[0]);
expect(tree).to.deep.equal({
"w:tc": [{ "w:tcPr": [{ "w:vMerge": [{ _attr: { "w:val": "restart" } }] }] }, { "w:p": [{ "w:pPr": [] }] }],
"w:tc": [{ "w:tcPr": [{ "w:vMerge": { _attr: { "w:val": "restart" } } }] }, { "w:p": EMPTY_OBJECT }],
});
const tree2 = new Formatter().format(cells[1]);
expect(tree2).to.deep.equal({ "w:tc": [{ "w:tcPr": [] }, { "w:p": [{ "w:pPr": [] }] }] });
expect(tree2).to.deep.equal({
"w:tc": [{ "w:tcPr": [{ "w:vMerge": { _attr: { "w:val": "continue" } } }] }, { "w:p": EMPTY_OBJECT }],
});
const tree3 = new Formatter().format(cells[2]);
expect(tree3).to.deep.equal({
"w:tc": [{ "w:tcPr": [{ "w:vMerge": [{ _attr: { "w:val": "continue" } }] }] }, { "w:p": [{ "w:pPr": [] }] }],
"w:tc": [{ "w:tcPr": [{ "w:vMerge": { _attr: { "w:val": "continue" } } }] }, { "w:p": EMPTY_OBJECT }],
});
});
});

View File

@ -15,7 +15,10 @@ export class TableColumn {
public mergeCells(startIndex: number, endIndex: number): TableCell {
this.cells[startIndex].addVerticalMerge(VMergeType.RESTART);
this.cells[endIndex].addVerticalMerge(VMergeType.CONTINUE);
for (let i = startIndex + 1; i <= endIndex; i++) {
this.cells[i].addVerticalMerge(VMergeType.CONTINUE);
}
return this.cells[startIndex];
}

View File

@ -8,44 +8,44 @@ import { TableCellMargin } from "./table-cell-margin";
describe("TableCellMargin", () => {
describe("#constructor", () => {
it("should throw an error if theres no child elements", () => {
const cellMargain = new TableCellMargin();
expect(() => new Formatter().format(cellMargain)).to.throw();
const cellMargin = new TableCellMargin();
expect(() => new Formatter().format(cellMargin)).to.throw();
});
});
describe("#addTopMargin", () => {
it("adds a table cell top margin", () => {
const cellMargain = new TableCellMargin();
cellMargain.addTopMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:top": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] });
const cellMargin = new TableCellMargin();
cellMargin.addTopMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:top": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
});
});
describe("#addLeftMargin", () => {
it("adds a table cell left margin", () => {
const cellMargain = new TableCellMargin();
cellMargain.addLeftMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:left": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] });
const cellMargin = new TableCellMargin();
cellMargin.addLeftMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:left": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
});
});
describe("#addBottomMargin", () => {
it("adds a table cell bottom margin", () => {
const cellMargain = new TableCellMargin();
cellMargain.addBottomMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:bottom": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] });
const cellMargin = new TableCellMargin();
cellMargin.addBottomMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:bottom": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
});
});
describe("#addRightMargin", () => {
it("adds a table cell right margin", () => {
const cellMargain = new TableCellMargin();
cellMargain.addRightMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargain);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:right": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] });
const cellMargin = new TableCellMargin();
cellMargin.addRightMargin(1234, WidthType.DXA);
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:right": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
});
});
});

View File

@ -1,9 +1,9 @@
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { WidthType } from "../table-cell";
class TableCellMarginAttributes extends XmlAttributeComponent<{ readonly type: WidthType; readonly value: number }> {
protected readonly xmlKeys = { value: "w:w", type: "w:sz" };
protected readonly xmlKeys = { value: "w:w", type: "w:type" };
}
class BaseTableCellMargin extends XmlComponent {
@ -17,17 +17,11 @@ class BaseTableCellMargin extends XmlComponent {
}
}
export class TableCellMargin extends XmlComponent {
export class TableCellMargin extends IgnoreIfEmptyXmlComponent {
constructor() {
super("w:tblCellMar");
}
public prepForXml(): IXmlableObject | undefined {
if (this.root.length > 0) {
return super.prepForXml();
}
}
public addTopMargin(value: number, type: WidthType = WidthType.DXA): void {
const top = new BaseTableCellMargin("w:top");

View File

@ -26,8 +26,7 @@ describe("Table Float Properties", () => {
});
const DEFAULT_TFP = {
"w:tblpPr": [
{
"w:tblpPr": {
_attr: {
"w:horzAnchor": "margin",
"w:vertAnchor": "page",
@ -41,5 +40,4 @@ const DEFAULT_TFP = {
"w:rightFromText": 60,
},
},
],
};

View File

@ -9,8 +9,11 @@ describe("TableProperties", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
const tp = new TableProperties();
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({ "w:tblPr": [] });
// The TableProperties is ignorable if there are no attributes,
// which results in prepForXml returning undefined, which causes
// the formatter to throw an error if that is the only object it
// has been asked to format.
expect(() => new Formatter().format(tp)).to.throw("XMLComponent did not format correctly");
});
});
@ -19,7 +22,7 @@ describe("TableProperties", () => {
const tp = new TableProperties().setWidth(1234, WidthType.DXA);
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({
"w:tblPr": [{ "w:tblW": [{ _attr: { "w:type": "dxa", "w:w": 1234 } }] }],
"w:tblPr": [{ "w:tblW": { _attr: { "w:type": "dxa", "w:w": 1234 } } }],
});
});
@ -27,7 +30,7 @@ describe("TableProperties", () => {
const tp = new TableProperties().setWidth(1234);
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({
"w:tblPr": [{ "w:tblW": [{ _attr: { "w:type": "auto", "w:w": 1234 } }] }],
"w:tblPr": [{ "w:tblW": { _attr: { "w:type": "auto", "w:w": 1234 } } }],
});
});
});
@ -37,7 +40,7 @@ describe("TableProperties", () => {
const tp = new TableProperties().setFixedWidthLayout();
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({
"w:tblPr": [{ "w:tblLayout": [{ _attr: { "w:type": "fixed" } }] }],
"w:tblPr": [{ "w:tblLayout": { _attr: { "w:type": "fixed" } } }],
});
});
});
@ -48,7 +51,7 @@ describe("TableProperties", () => {
tp.CellMargin.addTopMargin(1234, WidthType.DXA);
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({
"w:tblPr": [{ "w:tblCellMar": [{ "w:top": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] }],
"w:tblPr": [{ "w:tblCellMar": [{ "w:top": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] }],
});
});
@ -57,7 +60,7 @@ describe("TableProperties", () => {
tp.CellMargin.addLeftMargin(1234, WidthType.DXA);
const tree = new Formatter().format(tp);
expect(tree).to.deep.equal({
"w:tblPr": [{ "w:tblCellMar": [{ "w:left": [{ _attr: { "w:sz": "dxa", "w:w": 1234 } }] }] }],
"w:tblPr": [{ "w:tblCellMar": [{ "w:left": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] }],
});
});
});

View File

@ -1,4 +1,4 @@
import { XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent } from "file/xml-components";
import { ITableShadingAttributesProperties, TableShading } from "../shading";
import { WidthType } from "../table-cell";
@ -8,7 +8,7 @@ import { ITableFloatOptions, TableFloatProperties } from "./table-float-properti
import { TableLayout, TableLayoutType } from "./table-layout";
import { PreferredTableWidth } from "./table-width";
export class TableProperties extends XmlComponent {
export class TableProperties extends IgnoreIfEmptyXmlComponent {
private readonly cellMargin: TableCellMargin;
constructor() {

View File

@ -6,8 +6,11 @@ describe("TableRowProperties", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
const rowProperties = new TableRowProperties();
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [] });
// The TableRowProperties is ignorable if there are no attributes,
// which results in prepForXml returning undefined, which causes
// the formatter to throw an error if that is the only object it
// has been asked to format.
expect(() => new Formatter().format(rowProperties)).to.throw("XMLComponent did not format correctly");
});
});
@ -16,7 +19,7 @@ describe("TableRowProperties", () => {
const rowProperties = new TableRowProperties();
rowProperties.setCantSplit();
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:cantSplit": [{ _attr: { "w:val": true } }] }] });
expect(tree).to.deep.equal({ "w:trPr": [{ "w:cantSplit": { _attr: { "w:val": true } } }] });
});
});
@ -25,7 +28,7 @@ describe("TableRowProperties", () => {
const rowProperties = new TableRowProperties();
rowProperties.setTableHeader();
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:tblHeader": [{ _attr: { "w:val": true } }] }] });
expect(tree).to.deep.equal({ "w:trPr": [{ "w:tblHeader": { _attr: { "w:val": true } } }] });
});
});
});

View File

@ -1,6 +1,6 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
export class TableRowProperties extends XmlComponent {
export class TableRowProperties extends IgnoreIfEmptyXmlComponent {
constructor() {
super("w:trPr");
}

View File

@ -5,17 +5,15 @@ import { Formatter } from "export/formatter";
import { TableCell } from "../table-cell";
import { TableRow } from "./table-row";
import { EMPTY_OBJECT } from "file/xml-components";
describe("TableRow", () => {
describe("#constructor", () => {
it("should create with no cells", () => {
const tableRow = new TableRow([]);
const tree = new Formatter().format(tableRow);
expect(tree).to.deep.equal({
"w:tr": [
{
"w:trPr": [],
},
],
"w:tr": EMPTY_OBJECT,
});
});
@ -24,20 +22,10 @@ describe("TableRow", () => {
const tree = new Formatter().format(tableRow);
expect(tree).to.deep.equal({
"w:tr": [
{
"w:trPr": [],
},
{
"w:tc": [
{
"w:tcPr": [],
},
{
"w:p": [
{
"w:pPr": [],
},
],
"w:p": EMPTY_OBJECT,
},
],
},

View File

@ -8,71 +8,63 @@ import { Table } from "./table";
// import { WidthType } from "./table-cell";
import { RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType } from "./table-properties";
import { EMPTY_OBJECT } from "file/xml-components";
const DEFAULT_TABLE_PROPERTIES = {
"w:tblCellMar": [
{
"w:bottom": [
{
"w:bottom": {
_attr: {
"w:sz": "auto",
"w:type": "auto",
"w:w": 0,
},
},
],
},
{
"w:top": [
{
"w:top": {
_attr: {
"w:sz": "auto",
"w:type": "auto",
"w:w": 0,
},
},
],
},
{
"w:left": [
{
"w:left": {
_attr: {
"w:sz": "auto",
"w:type": "auto",
"w:w": 0,
},
},
],
},
{
"w:right": [
{
"w:right": {
_attr: {
"w:sz": "auto",
"w:type": "auto",
"w:w": 0,
},
},
],
},
],
};
const BORDERS = {
"w:tblBorders": [
{ "w:top": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:left": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:bottom": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:right": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:insideH": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:insideV": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
{ "w:top": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
{ "w:left": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
{ "w:bottom": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
{ "w:right": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
{ "w:insideH": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
{ "w:insideV": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
],
};
const WIDTHS = {
"w:tblW": [
{
"w:tblW": {
_attr: {
"w:type": "auto",
"w:w": 100,
},
},
],
};
// const f = {
@ -81,26 +73,25 @@ const WIDTHS = {
// "w:tblPr": [
// {
// "w:tblCellMar": [
// { "w:bottom": [{ _attr: { "w:sz": "auto", "w:w": 0 } }] },
// { "w:top": [{ _attr: { "w:sz": "auto", "w:w": 0 } }] },
// { "w:left": [{ _attr: { "w:sz": "auto", "w:w": 0 } }] },
// { "w:right": [{ _attr: { "w:sz": "auto", "w:w": 0 } }] },
// { "w:bottom": { _attr: { "w:type": "auto", "w:w": 0 } } },
// { "w:top": { _attr: { "w:type": "auto", "w:w": 0 } } },
// { "w:left": { _attr: { "w:type": "auto", "w:w": 0 } } },
// { "w:right": { _attr: { "w:type": "auto", "w:w": 0 } } },
// ],
// },
// {
// "w:tblBorders": [
// { "w:top": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:left": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:bottom": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:right": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:insideH": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:insideV": [{ _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } }] },
// { "w:top": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// { "w:left": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// { "w:bottom": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// { "w:right": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// { "w:insideH": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// { "w:insideV": { _attr: { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" } } },
// ],
// },
// { "w:tblW": [{ _attr: { "w:type": "auto", "w:w": 100 } }] },
// {
// "w:tblpPr": [
// { "w:tblW": { _attr: { "w:type": "auto", "w:w": 100 } } },
// {
// "w:tblpPr": {
// _attr: {
// "w:horzAnchor": "margin",
// "w:vertAnchor": "page",
@ -114,12 +105,11 @@ const WIDTHS = {
// "w:rightFromText": 60,
// },
// },
// ],
// },
// ],
// },
// { "w:tblGrid": [{ "w:gridCol": [{ _attr: { "w:w": 100 } }] }] },
// { "w:tr": [{ "w:trPr": [] }, { "w:tc": [{ "w:tcPr": [] }, { "w:p": [{ "w:pPr": [] }] }] }] },
// { "w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }] },
// { "w:tr": [{ "w:tc": [{ "w:p": EMPTY_OBJECT }] }] },
// ],
// };
@ -131,16 +121,16 @@ describe("Table", () => {
columns: 2,
});
const tree = new Formatter().format(table);
const cell = { "w:tc": [{ "w:tcPr": [] }, { "w:p": [{ "w:pPr": [] }] }] };
const cell = { "w:tc": [{ "w:p": EMPTY_OBJECT }] };
expect(tree).to.deep.equal({
"w:tbl": [
{ "w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS] },
{
"w:tblGrid": [{ "w:gridCol": [{ _attr: { "w:w": 100 } }] }, { "w:gridCol": [{ _attr: { "w:w": 100 } }] }],
"w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }, { "w:gridCol": { _attr: { "w:w": 100 } } }],
},
{ "w:tr": [{ "w:trPr": [] }, cell, cell] },
{ "w:tr": [{ "w:trPr": [] }, cell, cell] },
{ "w:tr": [{ "w:trPr": [] }, cell, cell] },
{ "w:tr": [cell, cell] },
{ "w:tr": [cell, cell] },
{ "w:tr": [cell, cell] },
],
});
});
@ -172,9 +162,8 @@ describe("Table", () => {
const tree = new Formatter().format(table);
const cell = (c) => ({
"w:tc": [
{ "w:tcPr": [] },
{
"w:p": [{ "w:pPr": [] }, { "w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, c] }] }],
"w:p": [{ "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, c] }] }],
},
],
});
@ -182,10 +171,10 @@ describe("Table", () => {
"w:tbl": [
{ "w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS] },
{
"w:tblGrid": [{ "w:gridCol": [{ _attr: { "w:w": 100 } }] }, { "w:gridCol": [{ _attr: { "w:w": 100 } }] }],
"w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }, { "w:gridCol": { _attr: { "w:w": 100 } } }],
},
{ "w:tr": [{ "w:trPr": [] }, cell("A1"), cell("B1")] },
{ "w:tr": [{ "w:trPr": [] }, cell("A2"), cell("B2")] },
{ "w:tr": [cell("A1"), cell("B1")] },
{ "w:tr": [cell("A2"), cell("B2")] },
],
});
});
@ -222,9 +211,8 @@ describe("Table", () => {
const tree = new Formatter().format(table);
const cell = (c) => ({
"w:tc": [
{ "w:tcPr": [] },
{
"w:p": [{ "w:pPr": [] }, { "w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, c] }] }],
"w:p": [{ "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, c] }] }],
},
],
});
@ -232,10 +220,10 @@ describe("Table", () => {
"w:tbl": [
{ "w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS] },
{
"w:tblGrid": [{ "w:gridCol": [{ _attr: { "w:w": 100 } }] }, { "w:gridCol": [{ _attr: { "w:w": 100 } }] }],
"w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }, { "w:gridCol": { _attr: { "w:w": 100 } } }],
},
{ "w:tr": [{ "w:trPr": [] }, cell("A1"), cell("B1")] },
{ "w:tr": [{ "w:trPr": [] }, cell("A2"), cell("B2")] },
{ "w:tr": [cell("A1"), cell("B1")] },
{ "w:tr": [cell("A2"), cell("B2")] },
],
});
});
@ -250,7 +238,7 @@ describe("Table", () => {
// .which.is.an("array")
// .with.has.length.at.least(1);
// expect(tree["w:tbl"][0]).to.deep.equal({
// "w:tblPr": [DEFAULT_TABLE_PROPERTIES, { "w:tblW": [{ _attr: { "w:type": "pct", "w:w": "1000%" } }] }],
// "w:tblPr": [DEFAULT_TABLE_PROPERTIES, { "w:tblW": { _attr: { "w:type": "pct", "w:w": "1000%" } } }],
// });
// });
@ -259,7 +247,7 @@ describe("Table", () => {
// const tree = new Formatter().format(table);
// expect(tree["w:tbl"][0]).to.deep.equal({
// "w:tblPr": [DEFAULT_TABLE_PROPERTIES, { "w:tblW": [{ _attr: { "w:type": "auto", "w:w": 1000 } }] }],
// "w:tblPr": [DEFAULT_TABLE_PROPERTIES, { "w:tblW": { _attr: { "w:type": "auto", "w:w": 1000 } } }],
// });
// });
// });
@ -276,7 +264,7 @@ describe("Table", () => {
.which.is.an("array")
.with.has.length.at.least(1);
expect(tree["w:tbl"][0]).to.deep.equal({
"w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS, { "w:tblLayout": [{ _attr: { "w:type": "fixed" } }] }],
"w:tblPr": [DEFAULT_TABLE_PROPERTIES, BORDERS, WIDTHS, { "w:tblLayout": { _attr: { "w:type": "fixed" } } }],
});
});
});
@ -298,7 +286,7 @@ describe("Table", () => {
.to.be.an("array")
.which.has.length.at.least(1);
expect(row["w:tr"].find((x) => x["w:tc"])).to.deep.equal({
"w:tc": [{ "w:tcPr": [] }, { "w:p": [{ "w:pPr": [] }] }],
"w:tc": [{ "w:p": EMPTY_OBJECT }],
});
});
@ -325,7 +313,7 @@ describe("Table", () => {
const cell = row["w:tr"].find((x) => x["w:tc"]);
expect(cell).not.to.be.undefined;
expect(cell["w:tc"][cell["w:tc"].length - 1]).to.deep.equal({
"w:p": [{ "w:pPr": [] }],
"w:p": EMPTY_OBJECT,
});
});
@ -346,12 +334,8 @@ describe("Table", () => {
.which.has.length.at.least(1);
expect(row["w:tr"].find((x) => x["w:tc"])).to.deep.equal({
"w:tc": [
{ "w:tcPr": [] },
{
"w:p": [
{ "w:pPr": [] },
{ "w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "Hello"] }] },
],
"w:p": [{ "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "Hello"] }] }],
},
],
});
@ -377,12 +361,10 @@ describe("Table", () => {
.which.has.length.at.least(1);
expect(row["w:tr"].find((x) => x["w:tc"])).to.deep.equal({
"w:tc": [
{ "w:tcPr": [] },
{
"w:p": [
{ "w:pPr": [] },
{
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "Test paragraph"] }],
"w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "Test paragraph"] }],
},
],
},
@ -421,8 +403,7 @@ describe("Table", () => {
BORDERS,
WIDTHS,
{
"w:tblpPr": [
{
"w:tblpPr": {
_attr: {
"w:horzAnchor": "margin",
"w:vertAnchor": "page",
@ -436,7 +417,6 @@ describe("Table", () => {
"w:rightFromText": 60,
},
},
],
},
],
});

View File

@ -22,8 +22,8 @@ export interface ITableOptions {
readonly width?: number;
readonly widthUnitType?: WidthType;
readonly columnWidths?: number[];
readonly margains?: {
readonly margainUnitType?: WidthType;
readonly margins?: {
readonly marginUnitType?: WidthType;
readonly top?: number;
readonly bottom?: number;
readonly right?: number;
@ -42,7 +42,7 @@ export class Table extends XmlComponent {
width = 100,
widthUnitType = WidthType.AUTO,
columnWidths = Array<number>(columns).fill(100),
margains: { margainUnitType, top, bottom, right, left } = { margainUnitType: WidthType.AUTO, top: 0, bottom: 0, right: 0, left: 0 },
margins: { marginUnitType, top, bottom, right, left } = { marginUnitType: WidthType.AUTO, top: 0, bottom: 0, right: 0, left: 0 },
float,
}: ITableOptions) {
super("w:tbl");
@ -50,10 +50,10 @@ export class Table extends XmlComponent {
this.root.push(this.properties);
this.properties.setBorder();
this.properties.setWidth(width, widthUnitType);
this.properties.CellMargin.addBottomMargin(bottom || 0, margainUnitType);
this.properties.CellMargin.addTopMargin(top || 0, margainUnitType);
this.properties.CellMargin.addLeftMargin(left || 0, margainUnitType);
this.properties.CellMargin.addRightMargin(right || 0, margainUnitType);
this.properties.CellMargin.addBottomMargin(bottom || 0, marginUnitType);
this.properties.CellMargin.addTopMargin(top || 0, marginUnitType);
this.properties.CellMargin.addLeftMargin(left || 0, marginUnitType);
this.properties.CellMargin.addRightMargin(right || 0, marginUnitType);
const grid = new TableGrid(columnWidths);
this.root.push(grid);

View File

@ -6,7 +6,7 @@ export type AttributeMap<T> = { [P in keyof T]: string };
export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
// tslint:disable-next-line:readonly-keyword
protected root: T;
protected readonly xmlKeys: AttributeMap<T>;
protected readonly xmlKeys?: AttributeMap<T>;
constructor(properties: T) {
super("_attr");
@ -18,7 +18,7 @@ export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
Object.keys(this.root).forEach((key) => {
const value = this.root[key];
if (value !== undefined) {
const newKey = this.xmlKeys[key];
const newKey = (this.xmlKeys && this.xmlKeys[key]) || key;
attrs[newKey] = value;
}
});

View File

@ -1,7 +1,7 @@
import { expect } from "chai";
import { Element, xml2js } from "xml-js";
import { ImportedXmlComponent } from "./";
import { EMPTY_OBJECT, ImportedXmlComponent } from "./";
import { convertToXmlComponent } from "./imported-xml-component";
const xmlString = `
@ -25,11 +25,25 @@ const convertedXmlElement = {
deleted: false,
rootKey: "w:p",
root: [
{ deleted: false, rootKey: "_attr", root: { "w:one": "value 1", "w:two": "value 2" } },
{ deleted: false, rootKey: "w:rPr", root: [{ deleted: false, rootKey: "w:noProof", root: ["some value"] }] },
{ deleted: false, rootKey: "w:r", root: [{ deleted: false, rootKey: "w:t", root: ["Text 1"] }], _attr: { active: "true" } },
{ deleted: false, rootKey: "w:r", root: [{ deleted: false, rootKey: "w:t", root: ["Text 2"] }], _attr: { active: "true" } },
{
deleted: false,
rootKey: "w:r",
root: [
{ deleted: false, rootKey: "_attr", root: { active: "true" } },
{ deleted: false, rootKey: "w:t", root: ["Text 1"] },
],
},
{
deleted: false,
rootKey: "w:r",
root: [
{ deleted: false, rootKey: "_attr", root: { active: "true" } },
{ deleted: false, rootKey: "w:t", root: ["Text 2"] },
],
},
],
_attr: { "w:one": "value 1", "w:two": "value 2" },
},
],
rootKey: undefined,
@ -59,7 +73,7 @@ describe("ImportedXmlComponent", () => {
},
},
{
"w:child": [],
"w:child": EMPTY_OBJECT,
},
],
});

View File

@ -1,6 +1,6 @@
// tslint:disable:no-any
import { Element as XmlElement, xml2js } from "xml-js";
import { IXmlableObject, XmlComponent } from ".";
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from ".";
/**
* Converts the given xml element (in json format) into XmlComponent.
@ -27,6 +27,10 @@ export function convertToXmlComponent(element: XmlElement): ImportedXmlComponent
}
}
class ImportedXmlComponentAttributes extends XmlAttributeComponent<any> {
// noop
}
/**
* Represents imported xml component from xml file.
*/
@ -46,58 +50,14 @@ export class ImportedXmlComponent extends XmlComponent {
* @param importedContent xml content of the imported component
*/
// tslint:disable-next-line:variable-name
private readonly _attr: any;
// tslint:disable-next-line:variable-name
constructor(rootKey: string, _attr?: any) {
super(rootKey);
if (_attr) {
this._attr = _attr;
this.root.push(new ImportedXmlComponentAttributes(_attr));
}
}
/**
* Transforms the object so it can be converted to xml. Example:
* <w:someKey someAttr="1" otherAttr="11">
* <w:child childAttr="2">
* </w:child>
* </w:someKey>
* {
* 'w:someKey': [
* {
* _attr: {
* someAttr: "1",
* otherAttr: "11"
* }
* },
* {
* 'w:child': [
* {
* _attr: {
* childAttr: "2"
* }
* }
* ]
* }
* ]
* }
*/
public prepForXml(): IXmlableObject | undefined {
const result = super.prepForXml();
if (!result) {
return undefined;
}
if (!!this._attr) {
if (!Array.isArray(result[this.rootKey])) {
result[this.rootKey] = [result[this.rootKey]];
}
result[this.rootKey].unshift({ _attr: this._attr });
}
return result;
}
public push(xmlComponent: XmlComponent | string): void {
this.root.push(xmlComponent);
}

View File

@ -1,7 +1,7 @@
import { assert } from "chai";
import { expect } from "chai";
import { Utility } from "tests/utility";
import { XmlComponent } from "./";
import { EMPTY_OBJECT, XmlComponent } from "./";
class TestComponent extends XmlComponent {}
@ -15,7 +15,7 @@ describe("XmlComponent", () => {
describe("#constructor()", () => {
it("should create an Xml Component which has the correct rootKey", () => {
const newJson = Utility.jsonify(xmlComponent);
assert.equal(newJson.rootKey, "w:test");
expect(newJson.rootKey).to.equal("w:test");
});
});
@ -31,7 +31,7 @@ describe("XmlComponent", () => {
return;
}
assert.equal(xml["w:test"].length, 0);
expect(xml["w:test"]).to.deep.equal(EMPTY_OBJECT);
});
});
});

View File

@ -2,6 +2,8 @@ import { BaseXmlComponent } from "./base";
import { IXmlableObject } from "./xmlable-object";
export { BaseXmlComponent };
export const EMPTY_OBJECT = Object.seal({});
export abstract class XmlComponent extends BaseXmlComponent {
// tslint:disable-next-line:readonly-keyword
protected root: Array<BaseXmlComponent | string>;
@ -17,7 +19,7 @@ export abstract class XmlComponent extends BaseXmlComponent {
if (c instanceof BaseXmlComponent) {
return !c.IsDeleted;
}
return true;
return c !== undefined;
})
.map((comp) => {
if (comp instanceof BaseXmlComponent) {
@ -26,8 +28,15 @@ export abstract class XmlComponent extends BaseXmlComponent {
return comp;
})
.filter((comp) => comp !== undefined); // Exclude undefined
// If we only have a single IXmlableObject in our children array and it
// represents our attributes, use the object itself as our children to
// avoid an unneeded XML close element. (Note: We have to use this
// function to get typescript to allow our check.)
// Additionally, if the array is empty, use an empty object as our
// children in order to get an empty XML element generated.
const onlyAttrs = (c) => typeof c === "object" && c._attr;
return {
[this.rootKey]: children,
[this.rootKey]: children.length ? (children.length === 1 && onlyAttrs(children[0]) ? children[0] : children) : EMPTY_OBJECT,
};
}
@ -41,3 +50,14 @@ export abstract class XmlComponent extends BaseXmlComponent {
this.deleted = true;
}
}
export abstract class IgnoreIfEmptyXmlComponent extends XmlComponent {
public prepForXml(): IXmlableObject | undefined {
const result = super.prepForXml();
// Ignore the object if its falsey or is an empty object (would produce
// an empty XML element if allowed to be included in the output).
if (result && (typeof result[this.rootKey] !== "object" || Object.keys(result[this.rootKey]).length)) {
return result;
}
}
}