diff --git a/demo/16-multiple-sections.ts b/demo/16-multiple-sections.ts
index 87c076cf66..db4bf4aac1 100644
--- a/demo/16-multiple-sections.ts
+++ b/demo/16-multiple-sections.ts
@@ -1,7 +1,7 @@
// Multiple sections and headers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { Document, Footer, Header, Packer, PageNumber, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
+import { Document, Footer, Header, Packer, PageNumber, NumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
const doc = new Document({
sections: [
@@ -13,7 +13,7 @@ const doc = new Document({
page: {
pageNumbers: {
start: 1,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
@@ -38,7 +38,7 @@ const doc = new Document({
},
pageNumbers: {
start: 1,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
@@ -85,7 +85,7 @@ const doc = new Document({
orientation: PageOrientation.PORTRAIT,
},
pageNumbers: {
- formatType: PageNumberFormat.UPPER_ROMAN,
+ formatType: NumberFormat.UPPER_ROMAN,
},
},
},
@@ -116,7 +116,7 @@ const doc = new Document({
},
pageNumbers: {
start: 25,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
diff --git a/demo/2-declaritive-styles.ts b/demo/2-declaritive-styles.ts
index 5795ebf6e1..6af4120574 100644
--- a/demo/2-declaritive-styles.ts
+++ b/demo/2-declaritive-styles.ts
@@ -24,7 +24,7 @@ const doc = new Document({
size: 28,
bold: true,
italics: true,
- color: "red",
+ color: "FF0000",
},
paragraph: {
spacing: {
diff --git a/demo/20-table-cell-borders.ts b/demo/20-table-cell-borders.ts
index 4dbc9192b9..9174fa28fa 100644
--- a/demo/20-table-cell-borders.ts
+++ b/demo/20-table-cell-borders.ts
@@ -36,17 +36,17 @@ const doc = new Document({
top: {
style: BorderStyle.DASH_DOT_STROKED,
size: 3,
- color: "red",
+ color: "FF0000",
},
bottom: {
style: BorderStyle.DOUBLE,
size: 3,
- color: "blue",
+ color: "0000FF",
},
left: {
style: BorderStyle.DASH_DOT_STROKED,
size: 3,
- color: "green",
+ color: "00FF00",
},
right: {
style: BorderStyle.DASH_DOT_STROKED,
diff --git a/demo/26-paragraph-borders.ts b/demo/26-paragraph-borders.ts
index c64be50429..788bbfafcf 100644
--- a/demo/26-paragraph-borders.ts
+++ b/demo/26-paragraph-borders.ts
@@ -1,7 +1,7 @@
// Creates two paragraphs, one with a border and one without
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { Document, Packer, Paragraph } from "../build";
+import { BorderStyle, Document, Packer, Paragraph } from "../build";
const doc = new Document({
sections: [
@@ -14,13 +14,13 @@ const doc = new Document({
top: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
bottom: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
},
diff --git a/demo/28-table-of-contents.ts b/demo/28-table-of-contents.ts
index 472ade8f67..aa5abd3986 100644
--- a/demo/28-table-of-contents.ts
+++ b/demo/28-table-of-contents.ts
@@ -9,6 +9,9 @@ import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } fr
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
// making the entries be hyperlinks for the paragraph
const doc = new File({
+ features: {
+ updateFields: true,
+ },
styles: {
paragraphStyles: [
{
diff --git a/demo/32-merge-and-shade-table-cells.ts b/demo/32-merge-and-shade-table-cells.ts
index 9ca432dc2d..a3e2451f12 100644
--- a/demo/32-merge-and-shade-table-cells.ts
+++ b/demo/32-merge-and-shade-table-cells.ts
@@ -98,7 +98,7 @@ const table3 = new Table({
children: [new Paragraph("Bar1")],
shading: {
fill: "b79c2f",
- val: ShadingType.REVERSE_DIAGONAL_STRIPE,
+ type: ShadingType.REVERSE_DIAGONAL_STRIPE,
color: "auto",
},
}),
@@ -106,7 +106,7 @@ const table3 = new Table({
children: [new Paragraph("Bar2")],
shading: {
fill: "42c5f4",
- val: ShadingType.PERCENT_95,
+ type: ShadingType.PERCENT_95,
color: "auto",
},
}),
@@ -114,7 +114,7 @@ const table3 = new Table({
children: [new Paragraph("Bar3")],
shading: {
fill: "880aa8",
- val: ShadingType.PERCENT_10,
+ type: ShadingType.PERCENT_10,
color: "e2df0b",
},
}),
@@ -122,7 +122,7 @@ const table3 = new Table({
children: [new Paragraph("Bar4")],
shading: {
fill: "FF0000",
- val: ShadingType.CLEAR,
+ type: ShadingType.CLEAR,
color: "auto",
},
}),
@@ -224,22 +224,22 @@ const borders = {
top: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "FF0000",
},
bottom: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "FF0000",
},
left: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "FF0000",
},
right: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "FF0000",
},
};
diff --git a/demo/39-page-numbers.ts b/demo/39-page-numbers.ts
index 44dd3719e4..4b526a5a74 100644
--- a/demo/39-page-numbers.ts
+++ b/demo/39-page-numbers.ts
@@ -1,7 +1,7 @@
// Example how to display page numbers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
+import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
const doc = new Document({
sections: [
@@ -10,7 +10,7 @@ const doc = new Document({
page: {
pageNumbers: {
start: 1,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
diff --git a/demo/45-highlighting-text.ts b/demo/45-highlighting-text.ts
index 373e9b4b17..bc48ebb342 100644
--- a/demo/45-highlighting-text.ts
+++ b/demo/45-highlighting-text.ts
@@ -14,7 +14,7 @@ const doc = new Document({
children: [
new TextRun({
text: "Hello World",
- color: "red",
+ color: "FF0000",
bold: true,
size: 24,
font: {
diff --git a/demo/46-shading-text.ts b/demo/46-shading-text.ts
index 39f4f461ac..289691bd25 100644
--- a/demo/46-shading-text.ts
+++ b/demo/46-shading-text.ts
@@ -14,7 +14,7 @@ const doc = new Document({
children: [
new TextRun({
text: "Hello World",
- color: "red",
+ color: "FF0000",
bold: true,
size: 24,
font: {
diff --git a/demo/47-number-of-total-pages-section.ts b/demo/47-number-of-total-pages-section.ts
index b19cc0b158..8d335337e4 100644
--- a/demo/47-number-of-total-pages-section.ts
+++ b/demo/47-number-of-total-pages-section.ts
@@ -1,7 +1,7 @@
// Multiple sections with total number of pages in each section
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
+import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
const header = new Header({
children: [
@@ -31,7 +31,7 @@ const doc = new Document({
page: {
pageNumbers: {
start: 1,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
@@ -52,7 +52,7 @@ const doc = new Document({
page: {
pageNumbers: {
start: 1,
- formatType: PageNumberFormat.DECIMAL,
+ formatType: NumberFormat.DECIMAL,
},
},
},
diff --git a/demo/48-vertical-align.ts b/demo/48-vertical-align.ts
index 123a784993..36400de154 100644
--- a/demo/48-vertical-align.ts
+++ b/demo/48-vertical-align.ts
@@ -1,13 +1,13 @@
// Example of making content of section vertically aligned
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { Document, Packer, Paragraph, SectionVerticalAlignValue, TextRun } from "../build";
+import { Document, Packer, Paragraph, VerticalAlign, TextRun } from "../build";
const doc = new Document({
sections: [
{
properties: {
- verticalAlign: SectionVerticalAlignValue.CENTER,
+ verticalAlign: VerticalAlign.CENTER,
},
children: [
new Paragraph({
diff --git a/demo/49-table-borders.ts b/demo/49-table-borders.ts
index aeccd73dd2..1a3943a947 100644
--- a/demo/49-table-borders.ts
+++ b/demo/49-table-borders.ts
@@ -24,22 +24,22 @@ const table = new Table({
top: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "ff0000",
},
bottom: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "ff0000",
},
left: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "ff0000",
},
right: {
style: BorderStyle.DASH_SMALL_GAP,
size: 1,
- color: "red",
+ color: "ff0000",
},
},
children: [new Paragraph("Hello")],
diff --git a/demo/60-track-revisions.ts b/demo/60-track-revisions.ts
index 81a68d4f7d..ced597806c 100644
--- a/demo/60-track-revisions.ts
+++ b/demo/60-track-revisions.ts
@@ -20,10 +20,12 @@ import {
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.insertedrun
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.deletedrun
- The method `addTrackRevisions()` adds an element `` to the `settings.xml` file. This specifies that the application shall track *new* revisions made to the existing document.
+ The setting `features: { trackRevisions: true }` adds an element `` to the `settings.xml` file.
+ This specifies that the application shall track *new* revisions made to the existing document.
See also https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.trackrevisions
- Note that this setting enables to track *new changes* after teh file is generated, so this example will still show inserted and deleted text runs when you remove it.
+ Note that this setting enables to track *new changes* after teh file is generated, so this example will still
+ show inserted and deleted text runs when you remove it.
*/
const paragraph = new Paragraph({
@@ -85,7 +87,7 @@ const doc = new Document({
new DeletedTextRun({
break: 1,
text: "in order",
- color: "red",
+ color: "ff0000",
bold: true,
size: 24,
font: {
diff --git a/demo/61-text-frame.ts b/demo/61-text-frame.ts
index e10e3b6f3c..d6563418cf 100644
--- a/demo/61-text-frame.ts
+++ b/demo/61-text-frame.ts
@@ -1,7 +1,16 @@
// Text Frame (Text Box) example
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
-import { Document, FrameAnchorType, HorizontalPositionAlign, Packer, Paragraph, TextRun, VerticalPositionAlign } from "../build";
+import {
+ BorderStyle,
+ Document,
+ FrameAnchorType,
+ HorizontalPositionAlign,
+ Packer,
+ Paragraph,
+ TextRun,
+ VerticalPositionAlign,
+} from "../build";
const doc = new Document({
sections: [
@@ -29,25 +38,25 @@ const doc = new Document({
top: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
bottom: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
left: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
right: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
},
diff --git a/docs/usage/change-tracking.md b/docs/usage/change-tracking.md
index f4c486eca2..96d10799ca 100644
--- a/docs/usage/change-tracking.md
+++ b/docs/usage/change-tracking.md
@@ -37,7 +37,7 @@ const paragraph = new Paragraph({
new TextRun("This is a simple demo"),
new DeletedTextRun({
text: "with a deletion.",
- color: "red",
+ color: "ff0000",
bold: true,
size: 24,
id: 0,
diff --git a/docs/usage/table-of-contents.md b/docs/usage/table-of-contents.md
index db2a6b321f..4a88508bc8 100644
--- a/docs/usage/table-of-contents.md
+++ b/docs/usage/table-of-contents.md
@@ -12,14 +12,29 @@ The complete documentation can be found [here](https://www.ecma-international.or
All you need to do is create a `TableOfContents` object and assign it to the document.
-```ts
-const toc = new TableOfContents("Summary", {
- hyperlink: true,
- headingStyleRange: "1-5",
- stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)],
-});
+**Note**: updateFields feature must be enabled for TableOfContents to update correctly.
-doc.addTableOfContents(toc);
+```ts
+const doc = new Document({
+ features: {
+ updateFields: true,
+ },
+ sections: [
+ {
+ children: [
+ new TableOfContents("Summary", {
+ hyperlink: true,
+ headingStyleRange: "1-5",
+ }),
+ new Paragraph({
+ text: "Header #1",
+ heading: HeadingLevel.HEADING_1,
+ pageBreakBefore: true,
+ }),
+ ]
+ }
+ ]
+});
```
## Table of Contents Options
diff --git a/docs/usage/tables.md b/docs/usage/tables.md
index 450d05e9b7..a13b7f5a02 100644
--- a/docs/usage/tables.md
+++ b/docs/usage/tables.md
@@ -53,6 +53,18 @@ const table = new Table({
});
```
+### Set Indent
+
+```ts
+const table = new Table({
+ ...,
+ indent: {
+ size: 600,
+ type: WidthType.DXA,
+ }
+});
+```
+
## Table Row
A table consists of multiple `table rows`. Table rows have a list of `children` which accepts a list of `table cells` explained below. You can create a simple `table row` like so:
@@ -145,7 +157,7 @@ const tableRow = new TableRow({
| Property | Type | Notes |
| ------------- | ----------------------------------- | ----------------------------------------------------------- |
| children | `Array` | Required. You can nest tables by adding a table into a cell |
-| shading | `ITableShadingAttributesProperties` | Optional |
+| shading | `IShadingAttributesProperties` | Optional |
| margins | `ITableCellMarginOptions` | Optional |
| verticalAlign | `VerticalAlign` | Optional |
| columnSpan | `number` | Optional |
@@ -171,7 +183,7 @@ const cell = new TableCell({
top: {
style: BorderStyle.DASH_DOT_STROKED,
size: 1,
- color: "red",
+ color: "ff0000",
},
bottom: {
style: BorderStyle.THICK_THIN_MEDIUM_GAP,
@@ -190,12 +202,12 @@ Google DOCS does not support start and end borders, instead they use left and ri
const cell = new TableCell({
...,
borders: {
- top: {
+ left: {
style: BorderStyle.DOT_DOT_DASH,
size: 3,
- color: "green",
+ color: "00FF00",
},
- bottom: {
+ right: {
style: BorderStyle.DOT_DOT_DASH,
size: 3,
color: "ff8000",
diff --git a/src/convenience-functions.spec.ts b/src/convenience-functions.spec.ts
index 29ea76736c..9a437adc73 100644
--- a/src/convenience-functions.spec.ts
+++ b/src/convenience-functions.spec.ts
@@ -18,14 +18,14 @@ describe("Utility", () => {
});
describe("#uniqueNumericId", () => {
- it("should generate a unique ID", () => {
+ it("should generate a unique incrementing ID", () => {
// tslint:disable-next-line: no-unused-expression
expect(uniqueNumericId()).to.not.be.undefined;
});
});
describe("#uniqueId", () => {
- it("should call the underlying header's addChildElement", () => {
+ it("should generate a unique pseudorandom ID", () => {
// tslint:disable-next-line: no-unused-expression
expect(uniqueId()).to.not.be.empty;
});
diff --git a/src/convenience-functions.ts b/src/convenience-functions.ts
index 4f1b9844ea..2443fb9f88 100644
--- a/src/convenience-functions.ts
+++ b/src/convenience-functions.ts
@@ -12,7 +12,7 @@ export const convertInchesToTwip = (inches: number): number => {
};
export const uniqueNumericId = (): number => {
- return currentCount++;
+ return ++currentCount;
};
export const uniqueId = (): string => {
diff --git a/src/export/formatter.spec.ts b/src/export/formatter.spec.ts
index e79cf7a9cc..463ec38c7f 100644
--- a/src/export/formatter.spec.ts
+++ b/src/export/formatter.spec.ts
@@ -45,18 +45,10 @@ describe("Formatter", () => {
{
"w:rPr": [
{
- "w:b": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:b": {},
},
{
- "w:bCs": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:bCs": {},
},
],
},
diff --git a/src/export/packer/next-compiler.ts b/src/export/packer/next-compiler.ts
index 3d99f93c64..3311301a61 100644
--- a/src/export/packer/next-compiler.ts
+++ b/src/export/packer/next-compiler.ts
@@ -70,7 +70,6 @@ export class Compiler {
}
private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping {
- file.verifyUpdateFields();
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
const documentXmlData = xml(
@@ -78,7 +77,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
);
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
@@ -98,7 +103,12 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
);
})(),
path: "word/_rels/document.xml.rels",
@@ -118,7 +128,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
),
path: "word/styles.xml",
},
@@ -129,6 +145,7 @@ export class Compiler {
file,
}),
{
+ indent: prettify,
declaration: {
standalone: "yes",
encoding: "UTF-8",
@@ -143,7 +160,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
),
path: "word/numbering.xml",
},
@@ -153,7 +176,12 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: "_rels/.rels",
},
@@ -163,7 +191,12 @@ export class Compiler {
viewWrapper: headerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
);
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
@@ -181,7 +214,12 @@ export class Compiler {
viewWrapper: headerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: `word/_rels/header${index + 1}.xml.rels`,
};
@@ -192,7 +230,12 @@ export class Compiler {
viewWrapper: footerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
);
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
@@ -210,7 +253,12 @@ export class Compiler {
viewWrapper: footerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: `word/_rels/footer${index + 1}.xml.rels`,
};
@@ -221,7 +269,12 @@ export class Compiler {
viewWrapper: headerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own
@@ -238,7 +291,12 @@ export class Compiler {
viewWrapper: footerWrapper,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own
@@ -255,7 +313,12 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: "[Content_Types].xml",
},
@@ -265,7 +328,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
),
path: "docProps/custom.xml",
},
@@ -275,7 +344,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
),
path: "docProps/app.xml",
},
@@ -285,7 +360,12 @@ export class Compiler {
viewWrapper: file.FootNotes,
file: file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: "word/footnotes.xml",
},
@@ -295,7 +375,12 @@ export class Compiler {
viewWrapper: file.FootNotes,
file: file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ encoding: "UTF-8",
+ },
+ },
),
path: "word/_rels/footnotes.xml.rels",
},
@@ -305,7 +390,13 @@ export class Compiler {
viewWrapper: file.Document,
file,
}),
- prettify,
+ {
+ indent: prettify,
+ declaration: {
+ standalone: "yes",
+ encoding: "UTF-8",
+ },
+ },
),
path: "word/settings.xml",
},
diff --git a/src/file/border/border.spec.ts b/src/file/border/border.spec.ts
new file mode 100644
index 0000000000..e652c50422
--- /dev/null
+++ b/src/file/border/border.spec.ts
@@ -0,0 +1,54 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { BorderStyle } from "file/border";
+
+import { BorderElement } from "./border";
+
+describe("BorderElement", () => {
+ describe("#constructor", () => {
+ it("should create a simple border element", () => {
+ const border = new BorderElement("w:top", {
+ style: BorderStyle.SINGLE,
+ });
+ const tree = new Formatter().format(border);
+ expect(tree).to.deep.equal({
+ "w:top": {
+ _attr: {
+ "w:val": "single",
+ },
+ },
+ });
+ });
+ it("should create a simple border element with a size", () => {
+ const border = new BorderElement("w:top", {
+ style: BorderStyle.SINGLE,
+ size: 22,
+ });
+ const tree = new Formatter().format(border);
+ expect(tree).to.deep.equal({
+ "w:top": {
+ _attr: {
+ "w:val": "single",
+ "w:sz": 22,
+ },
+ },
+ });
+ });
+ it("should create a simple border element with space", () => {
+ const border = new BorderElement("w:top", {
+ style: BorderStyle.SINGLE,
+ space: 22,
+ });
+ const tree = new Formatter().format(border);
+ expect(tree).to.deep.equal({
+ "w:top": {
+ _attr: {
+ "w:val": "single",
+ "w:space": 22,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/border/border.ts b/src/file/border/border.ts
new file mode 100644
index 0000000000..04e487ff61
--- /dev/null
+++ b/src/file/border/border.ts
@@ -0,0 +1,86 @@
+// Note that the border type is identical in all places,
+// regardless of where it's used like paragraph/table/etc.
+// PageBorders are a superset, but we're not using any of those extras.
+//
+// http://officeopenxml.com/WPborders.php
+// http://officeopenxml.com/WPtableBorders.php
+// http://officeopenxml.com/WPtableCellProperties-Borders.php
+// http://officeopenxml.com/WPsectionBorders.php
+//
+// This describes the CT_Border type.
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "../values";
+
+export interface IBorderOptions {
+ readonly style: BorderStyle;
+ /** Border color, in hex (eg 'FF00AA') */
+ readonly color?: string;
+ /** Size of the border in 1/8 pt */
+ readonly size?: number;
+ /** Spacing offset. Values are specified in pt */
+ readonly space?: number;
+}
+
+export class BorderElement extends XmlComponent {
+ constructor(elementName: string, { color, size, space, style }: IBorderOptions) {
+ super(elementName);
+ this.root.push(
+ new BordersAttributes({
+ style,
+ color: color === undefined ? undefined : hexColorValue(color),
+ size: size === undefined ? undefined : eighthPointMeasureValue(size),
+ space: space === undefined ? undefined : pointMeasureValue(space),
+ }),
+ );
+ }
+}
+
+class BordersAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ style: "w:val",
+ color: "w:color",
+ size: "w:sz",
+ space: "w:space",
+ };
+}
+
+export enum BorderStyle {
+ SINGLE = "single",
+ DASH_DOT_STROKED = "dashDotStroked",
+ DASHED = "dashed",
+ DASH_SMALL_GAP = "dashSmallGap",
+ DOT_DASH = "dotDash",
+ DOT_DOT_DASH = "dotDotDash",
+ DOTTED = "dotted",
+ DOUBLE = "double",
+ DOUBLE_WAVE = "doubleWave",
+ INSET = "inset",
+ NIL = "nil",
+ NONE = "none",
+ OUTSET = "outset",
+ THICK = "thick",
+ THICK_THIN_LARGE_GAP = "thickThinLargeGap",
+ THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
+ THICK_THIN_SMALL_GAP = "thickThinSmallGap",
+ THIN_THICK_LARGE_GAP = "thinThickLargeGap",
+ THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
+ THIN_THICK_SMALL_GAP = "thinThickSmallGap",
+ THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
+ THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
+ THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
+ THREE_D_EMBOSS = "threeDEmboss",
+ THREE_D_ENGRAVE = "threeDEngrave",
+ TRIPLE = "triple",
+ WAVE = "wave",
+}
diff --git a/src/file/border/index.ts b/src/file/border/index.ts
new file mode 100644
index 0000000000..cfae779c98
--- /dev/null
+++ b/src/file/border/index.ts
@@ -0,0 +1 @@
+export * from "./border";
diff --git a/src/file/core-properties/components.ts b/src/file/core-properties/components.ts
deleted file mode 100644
index 4a7d0a2795..0000000000
--- a/src/file/core-properties/components.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { DocumentAttributes } from "../document/document-attributes";
-
-export class Title extends XmlComponent {
- constructor(value: string) {
- super("dc:title");
- this.root.push(value);
- }
-}
-
-export class Subject extends XmlComponent {
- constructor(value: string) {
- super("dc:subject");
- this.root.push(value);
- }
-}
-
-export class Creator extends XmlComponent {
- constructor(value: string) {
- super("dc:creator");
- this.root.push(value);
- }
-}
-
-export class Keywords extends XmlComponent {
- constructor(value: string) {
- super("cp:keywords");
- this.root.push(value);
- }
-}
-
-export class Description extends XmlComponent {
- constructor(value: string) {
- super("dc:description");
- this.root.push(value);
- }
-}
-
-export class LastModifiedBy extends XmlComponent {
- constructor(value: string) {
- super("cp:lastModifiedBy");
- this.root.push(value);
- }
-}
-
-export class Revision extends XmlComponent {
- constructor(value: string) {
- super("cp:revision");
- this.root.push(value);
- }
-}
-
-export abstract class DateComponent extends XmlComponent {
- protected getCurrentDate(): string {
- const date = new Date();
- const year = date.getFullYear();
- const month = ("0" + (date.getMonth() + 1)).slice(-2);
- const day = ("0" + date.getDate()).slice(-2);
- const hours = ("0" + date.getHours()).slice(-2);
- const minutes = ("0" + date.getMinutes()).slice(-2);
- const seconds = ("0" + date.getSeconds()).slice(-2);
-
- return year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z";
- }
-}
-
-export class Created extends DateComponent {
- constructor() {
- super("dcterms:created");
- this.root.push(
- new DocumentAttributes({
- type: "dcterms:W3CDTF",
- }),
- );
- this.root.push(this.getCurrentDate());
- }
-}
-
-export class Modified extends DateComponent {
- constructor() {
- super("dcterms:modified");
- this.root.push(
- new DocumentAttributes({
- type: "dcterms:W3CDTF",
- }),
- );
- this.root.push(this.getCurrentDate());
- }
-}
diff --git a/src/file/core-properties/properties.spec.ts b/src/file/core-properties/properties.spec.ts
index 92b2cd6139..4d0b57f0f4 100644
--- a/src/file/core-properties/properties.spec.ts
+++ b/src/file/core-properties/properties.spec.ts
@@ -27,8 +27,7 @@ describe("Properties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
- expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
- expect(tree["cp:coreProperties"][1]).to.deep.equal({ "dc:title": ["test document"] });
+ expect(tree["cp:coreProperties"]).to.deep.include({ "dc:title": ["test document"] });
});
it("should create properties with all the attributes given", () => {
@@ -44,9 +43,9 @@ describe("Properties", () => {
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
+
const key = (obj) => Object.keys(obj)[0];
- const props = tree["cp:coreProperties"].map(key).sort();
- expect(props).to.deep.equal([
+ expect(tree["cp:coreProperties"].map(key)).to.include.members([
"_attr",
"cp:keywords",
"cp:lastModifiedBy",
@@ -58,7 +57,7 @@ describe("Properties", () => {
"dcterms:created",
"dcterms:modified",
]);
- expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => (key(a) < key(b) ? -1 : 1))).to.deep.equal([
+ expect(tree["cp:coreProperties"]).to.deep.include.members([
{ "cp:keywords": ["test docx"] },
{ "cp:lastModifiedBy": ["the author"] },
{ "cp:revision": ["123"] },
diff --git a/src/file/core-properties/properties.ts b/src/file/core-properties/properties.ts
index 3128b08517..57a869a167 100644
--- a/src/file/core-properties/properties.ts
+++ b/src/file/core-properties/properties.ts
@@ -1,4 +1,4 @@
-import { XmlComponent } from "file/xml-components";
+import { StringContainer, XmlComponent } from "file/xml-components";
import { ICustomPropertyOptions } from "../custom-properties";
import { IDocumentBackgroundOptions } from "../document";
@@ -7,7 +7,7 @@ import { ISectionOptions } from "../file";
import { INumberingOptions } from "../numbering";
import { Paragraph } from "../paragraph";
import { IStylesOptions } from "../styles";
-import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
+import { dateTimeValue } from "../values";
export interface IPropertiesOptions {
readonly sections: ISectionOptions[];
@@ -29,12 +29,35 @@ export interface IPropertiesOptions {
readonly background?: IDocumentBackgroundOptions;
readonly features?: {
readonly trackRevisions?: boolean;
+ readonly updateFields?: boolean;
};
readonly compatabilityModeVersion?: number;
readonly customProperties?: ICustomPropertyOptions[];
readonly evenAndOddHeaderAndFooters?: boolean;
}
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
export class CoreProperties extends XmlComponent {
constructor(options: Omit) {
super("cp:coreProperties");
@@ -48,27 +71,39 @@ export class CoreProperties extends XmlComponent {
}),
);
if (options.title) {
- this.root.push(new Title(options.title));
+ this.root.push(new StringContainer("dc:title", options.title));
}
if (options.subject) {
- this.root.push(new Subject(options.subject));
+ this.root.push(new StringContainer("dc:subject", options.subject));
}
if (options.creator) {
- this.root.push(new Creator(options.creator));
+ this.root.push(new StringContainer("dc:creator", options.creator));
}
if (options.keywords) {
- this.root.push(new Keywords(options.keywords));
+ this.root.push(new StringContainer("cp:keywords", options.keywords));
}
if (options.description) {
- this.root.push(new Description(options.description));
+ this.root.push(new StringContainer("dc:description", options.description));
}
if (options.lastModifiedBy) {
- this.root.push(new LastModifiedBy(options.lastModifiedBy));
+ this.root.push(new StringContainer("cp:lastModifiedBy", options.lastModifiedBy));
}
if (options.revision) {
- this.root.push(new Revision(options.revision));
+ this.root.push(new StringContainer("cp:revision", options.revision));
}
- this.root.push(new Created());
- this.root.push(new Modified());
+ this.root.push(new TimestampElement("dcterms:created"));
+ this.root.push(new TimestampElement("dcterms:modified"));
+ }
+}
+
+class TimestampElement extends XmlComponent {
+ constructor(name: string) {
+ super(name);
+ this.root.push(
+ new DocumentAttributes({
+ type: "dcterms:W3CDTF",
+ }),
+ );
+ this.root.push(dateTimeValue(new Date()));
}
}
diff --git a/src/file/document/body/body.spec.ts b/src/file/document/body/body.spec.ts
index bae759266c..a65f86b69e 100644
--- a/src/file/document/body/body.spec.ts
+++ b/src/file/document/body/body.spec.ts
@@ -3,6 +3,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import { Body } from "./body";
+import { sectionMarginDefaults } from "./section-properties";
describe("Body", () => {
let body: Body;
@@ -32,13 +33,13 @@ describe("Body", () => {
{
"w:pgMar": {
_attr: {
- "w:top": 1440,
- "w:right": 1440,
- "w:bottom": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:footer": 708,
- "w:gutter": 0,
+ "w:top": sectionMarginDefaults.TOP,
+ "w:right": sectionMarginDefaults.RIGHT,
+ "w:bottom": sectionMarginDefaults.BOTTOM,
+ "w:left": sectionMarginDefaults.LEFT,
+ "w:header": sectionMarginDefaults.HEADER,
+ "w:footer": sectionMarginDefaults.FOOTER,
+ "w:gutter": sectionMarginDefaults.GUTTER,
},
},
},
@@ -47,7 +48,7 @@ describe("Body", () => {
_attr: {},
},
},
- { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
+ // { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
],
},
diff --git a/src/file/document/body/body.ts b/src/file/document/body/body.ts
index ff56962d12..deb2e573cf 100644
--- a/src/file/document/body/body.ts
+++ b/src/file/document/body/body.ts
@@ -1,6 +1,6 @@
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
-import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
+import { Paragraph, ParagraphProperties } from "../..";
import { ISectionPropertiesOptions, SectionProperties } from "./section-properties/section-properties";
export class Body extends XmlComponent {
@@ -38,10 +38,6 @@ export class Body extends XmlComponent {
this.root.push(component);
}
- public getTablesOfContents(): TableOfContents[] {
- return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[];
- }
-
private createSectionParagraph(section: SectionProperties): Paragraph {
const paragraph = new Paragraph({});
const properties = new ParagraphProperties({});
diff --git a/src/file/document/body/section-properties/columns/columns-attributes.ts b/src/file/document/body/section-properties/columns/columns-attributes.ts
deleted file mode 100644
index 40140bd63f..0000000000
--- a/src/file/document/body/section-properties/columns/columns-attributes.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export class ColumnsAttributes extends XmlAttributeComponent<{
- readonly space?: number;
- readonly num?: number;
- readonly separate?: boolean;
-}> {
- protected readonly xmlKeys = {
- space: "w:space",
- num: "w:num",
- separate: "w:sep",
- };
-}
diff --git a/src/file/document/body/section-properties/columns/columns.ts b/src/file/document/body/section-properties/columns/columns.ts
deleted file mode 100644
index c074f189d9..0000000000
--- a/src/file/document/body/section-properties/columns/columns.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { ColumnsAttributes } from "./columns-attributes";
-
-export class Columns extends XmlComponent {
- constructor(space: number, num: number, separate: boolean) {
- super("w:cols");
- this.root.push(
- new ColumnsAttributes({
- space: space,
- num: num,
- separate: separate,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/doc-grid/doc-grid-attributes.ts b/src/file/document/body/section-properties/doc-grid/doc-grid-attributes.ts
deleted file mode 100644
index 3fb2a5030f..0000000000
--- a/src/file/document/body/section-properties/doc-grid/doc-grid-attributes.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export interface IDocGridAttributesProperties {
- readonly linePitch?: number;
-}
-
-export class DocGridAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- linePitch: "w:linePitch",
- };
-}
diff --git a/src/file/document/body/section-properties/doc-grid/doc-grid.ts b/src/file/document/body/section-properties/doc-grid/doc-grid.ts
deleted file mode 100644
index e4df527443..0000000000
--- a/src/file/document/body/section-properties/doc-grid/doc-grid.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { DocGridAttributes } from "./doc-grid-attributes";
-
-export class DocumentGrid extends XmlComponent {
- constructor(linePitch: number) {
- super("w:docGrid");
- this.root.push(
- new DocGridAttributes({
- linePitch: linePitch,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/footer-reference/footer-reference-attributes.ts b/src/file/document/body/section-properties/footer-reference/footer-reference-attributes.ts
deleted file mode 100644
index 861cc86a11..0000000000
--- a/src/file/document/body/section-properties/footer-reference/footer-reference-attributes.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export enum FooterReferenceType {
- DEFAULT = "default",
- FIRST = "first",
- EVEN = "even",
-}
-
-export class FooterReferenceAttributes extends XmlAttributeComponent<{
- readonly type: string;
- readonly id: string;
-}> {
- protected readonly xmlKeys = {
- type: "w:type",
- id: "r:id",
- };
-}
diff --git a/src/file/document/body/section-properties/footer-reference/footer-reference.spec.ts b/src/file/document/body/section-properties/footer-reference/footer-reference.spec.ts
deleted file mode 100644
index 50570b4b77..0000000000
--- a/src/file/document/body/section-properties/footer-reference/footer-reference.spec.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-import { FooterReference } from "./footer-reference";
-import { FooterReferenceType } from "./footer-reference-attributes";
-
-describe("footerReference", () => {
- it("should create", () => {
- const footer = new FooterReference({
- footerType: FooterReferenceType.DEFAULT,
- footerId: 1,
- });
-
- const tree = new Formatter().format(footer);
-
- expect(tree).to.deep.equal({
- "w:footerReference": {
- _attr: {
- "r:id": "rId1",
- "w:type": "default",
- },
- },
- });
- });
-
- it("should create without a footer type", () => {
- const footer = new FooterReference({
- footerId: 1,
- });
-
- const tree = new Formatter().format(footer);
-
- expect(tree).to.deep.equal({
- "w:footerReference": {
- _attr: {
- "r:id": "rId1",
- "w:type": "default",
- },
- },
- });
- });
-});
diff --git a/src/file/document/body/section-properties/footer-reference/footer-reference.ts b/src/file/document/body/section-properties/footer-reference/footer-reference.ts
deleted file mode 100644
index d23e99aba1..0000000000
--- a/src/file/document/body/section-properties/footer-reference/footer-reference.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
-
-export interface IFooterOptions {
- readonly footerType?: FooterReferenceType;
- readonly footerId?: number;
-}
-
-export class FooterReference extends XmlComponent {
- constructor(options: IFooterOptions) {
- super("w:footerReference");
-
- this.root.push(
- new FooterReferenceAttributes({
- type: options.footerType || FooterReferenceType.DEFAULT,
- id: `rId${options.footerId}`,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/footer-reference/index.ts b/src/file/document/body/section-properties/footer-reference/index.ts
deleted file mode 100644
index 9673319fba..0000000000
--- a/src/file/document/body/section-properties/footer-reference/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./footer-reference";
-export * from "./footer-reference-attributes";
diff --git a/src/file/document/body/section-properties/header-reference/header-reference-attributes.ts b/src/file/document/body/section-properties/header-reference/header-reference-attributes.ts
deleted file mode 100644
index b46c993999..0000000000
--- a/src/file/document/body/section-properties/header-reference/header-reference-attributes.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export enum HeaderReferenceType {
- DEFAULT = "default",
- FIRST = "first",
- EVEN = "even",
-}
-
-export class HeaderReferenceAttributes extends XmlAttributeComponent<{
- readonly type: string;
- readonly id: string;
-}> {
- protected readonly xmlKeys = {
- type: "w:type",
- id: "r:id",
- };
-}
diff --git a/src/file/document/body/section-properties/header-reference/header-reference.spec.ts b/src/file/document/body/section-properties/header-reference/header-reference.spec.ts
deleted file mode 100644
index 2d6b39e553..0000000000
--- a/src/file/document/body/section-properties/header-reference/header-reference.spec.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-import { HeaderReference } from "./header-reference";
-import { HeaderReferenceType } from "./header-reference-attributes";
-
-describe("HeaderReference", () => {
- it("should create", () => {
- const footer = new HeaderReference({
- headerType: HeaderReferenceType.DEFAULT,
- headerId: 1,
- });
-
- const tree = new Formatter().format(footer);
-
- expect(tree).to.deep.equal({
- "w:headerReference": {
- _attr: {
- "r:id": "rId1",
- "w:type": "default",
- },
- },
- });
- });
-
- it("should create without a header type", () => {
- const footer = new HeaderReference({
- headerId: 1,
- });
-
- const tree = new Formatter().format(footer);
-
- expect(tree).to.deep.equal({
- "w:headerReference": {
- _attr: {
- "r:id": "rId1",
- "w:type": "default",
- },
- },
- });
- });
-});
diff --git a/src/file/document/body/section-properties/header-reference/header-reference.ts b/src/file/document/body/section-properties/header-reference/header-reference.ts
deleted file mode 100644
index b1bc4ef4f4..0000000000
--- a/src/file/document/body/section-properties/header-reference/header-reference.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
-
-export interface IHeaderReferenceOptions {
- readonly headerType?: HeaderReferenceType;
- readonly headerId?: number;
-}
-
-export class HeaderReference extends XmlComponent {
- constructor(options: IHeaderReferenceOptions) {
- super("w:headerReference");
- this.root.push(
- new HeaderReferenceAttributes({
- type: options.headerType || HeaderReferenceType.DEFAULT,
- id: `rId${options.headerId}`,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/header-reference/index.ts b/src/file/document/body/section-properties/header-reference/index.ts
deleted file mode 100644
index 80239ad98e..0000000000
--- a/src/file/document/body/section-properties/header-reference/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./header-reference";
-export * from "./header-reference-attributes";
diff --git a/src/file/document/body/section-properties/index.ts b/src/file/document/body/section-properties/index.ts
index ee0820c640..bb4ce998e3 100644
--- a/src/file/document/body/section-properties/index.ts
+++ b/src/file/document/body/section-properties/index.ts
@@ -1,9 +1,2 @@
export * from "./section-properties";
-export * from "./footer-reference";
-export * from "./header-reference";
-export * from "./page-size";
-export * from "./page-number";
-export * from "./page-border";
-export * from "./line-number";
-export * from "./vertical-align";
-export * from "./type";
+export * from "./properties";
diff --git a/src/file/document/body/section-properties/line-number/index.ts b/src/file/document/body/section-properties/line-number/index.ts
deleted file mode 100644
index 5808fe7f7b..0000000000
--- a/src/file/document/body/section-properties/line-number/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./line-number";
diff --git a/src/file/document/body/section-properties/line-number/line-number.ts b/src/file/document/body/section-properties/line-number/line-number.ts
deleted file mode 100644
index fdc0515244..0000000000
--- a/src/file/document/body/section-properties/line-number/line-number.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-// http://officeopenxml.com/WPsectionLineNumbering.php
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export enum LineNumberRestartFormat {
- CONTINUOUS = "continuous",
- NEW_SECTION = "newSection",
- NEW_PAGE = "newPage",
-}
-
-export interface ILineNumberAttributes {
- readonly countBy?: number;
- readonly start?: number;
- readonly restart?: LineNumberRestartFormat;
- readonly distance?: number;
-}
-
-export class LineNumberAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- countBy: "w:countBy",
- start: "w:start",
- restart: "w:restart",
- distance: "w:distance",
- };
-}
-
-export class LineNumberType extends XmlComponent {
- constructor(countBy?: number, start?: number, restart?: LineNumberRestartFormat, dist?: number) {
- super("w:lnNumType");
- this.root.push(
- new LineNumberAttributes({
- countBy: countBy,
- start: start,
- restart: restart,
- distance: dist,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/page-border/index.ts b/src/file/document/body/section-properties/page-border/index.ts
deleted file mode 100644
index 53d8b8ce4b..0000000000
--- a/src/file/document/body/section-properties/page-border/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./page-borders";
diff --git a/src/file/document/body/section-properties/page-border/page-borders.ts b/src/file/document/body/section-properties/page-border/page-borders.ts
deleted file mode 100644
index 4a042ccf8a..0000000000
--- a/src/file/document/body/section-properties/page-border/page-borders.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-// http://officeopenxml.com/WPsectionBorders.php
-import { BorderStyle } from "file/styles";
-import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export enum PageBorderDisplay {
- ALL_PAGES = "allPages",
- FIRST_PAGE = "firstPage",
- NOT_FIRST_PAGE = "notFirstPage",
-}
-
-export enum PageBorderOffsetFrom {
- PAGE = "page",
- TEXT = "text",
-}
-
-export enum PageBorderZOrder {
- BACK = "back",
- FRONT = "front",
-}
-
-export interface IPageBorderAttributes {
- readonly display?: PageBorderDisplay;
- readonly offsetFrom?: PageBorderOffsetFrom;
- readonly zOrder?: PageBorderZOrder;
-}
-
-export interface IPageBorderConfiguration {
- readonly style?: BorderStyle;
- readonly size?: number;
- readonly color?: string;
- readonly space?: number;
-}
-
-export interface IPageBordersOptions {
- readonly pageBorders?: IPageBorderAttributes;
- readonly pageBorderTop?: IPageBorderConfiguration;
- readonly pageBorderRight?: IPageBorderConfiguration;
- readonly pageBorderBottom?: IPageBorderConfiguration;
- readonly pageBorderLeft?: IPageBorderConfiguration;
-}
-
-class PageBordeAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- style: "w:val",
- size: "w:size",
- color: "w:color",
- space: "w:space",
- };
-}
-
-class PageBorder extends XmlComponent {
- constructor(key: string, options: IPageBorderConfiguration) {
- super(key);
-
- this.root.push(new PageBordeAttributes(options));
- }
-}
-
-class PageBordersAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- display: "w:display",
- offsetFrom: "w:offsetFrom",
- zOrder: "w:zOrder",
- };
-}
-
-export class PageBorders extends IgnoreIfEmptyXmlComponent {
- constructor(options?: IPageBordersOptions) {
- super("w:pgBorders");
-
- if (!options) {
- return;
- }
-
- if (options.pageBorders) {
- this.root.push(
- new PageBordersAttributes({
- display: options.pageBorders.display,
- offsetFrom: options.pageBorders.offsetFrom,
- zOrder: options.pageBorders.zOrder,
- }),
- );
- } else {
- this.root.push(new PageBordersAttributes({}));
- }
-
- if (options.pageBorderTop) {
- this.root.push(new PageBorder("w:top", options.pageBorderTop));
- }
- if (options.pageBorderRight) {
- this.root.push(new PageBorder("w:right", options.pageBorderRight));
- }
- if (options.pageBorderBottom) {
- this.root.push(new PageBorder("w:bottom", options.pageBorderBottom));
- }
- if (options.pageBorderLeft) {
- this.root.push(new PageBorder("w:left", options.pageBorderLeft));
- }
- }
-}
diff --git a/src/file/document/body/section-properties/page-margin/page-margin-attributes.ts b/src/file/document/body/section-properties/page-margin/page-margin-attributes.ts
deleted file mode 100644
index 7d7df6565c..0000000000
--- a/src/file/document/body/section-properties/page-margin/page-margin-attributes.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export interface IPageMarginAttributes {
- readonly top?: number;
- readonly right?: number;
- readonly bottom?: number;
- readonly left?: number;
- readonly header?: number;
- readonly footer?: number;
- readonly gutter?: number;
-}
-
-export class PageMarginAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- top: "w:top",
- right: "w:right",
- bottom: "w:bottom",
- left: "w:left",
- header: "w:header",
- footer: "w:footer",
- gutter: "w:gutter",
- };
-}
diff --git a/src/file/document/body/section-properties/page-margin/page-margin.ts b/src/file/document/body/section-properties/page-margin/page-margin.ts
deleted file mode 100644
index bd9a8e5fa6..0000000000
--- a/src/file/document/body/section-properties/page-margin/page-margin.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { PageMarginAttributes } from "./page-margin-attributes";
-
-export class PageMargin extends XmlComponent {
- constructor(top: number, right: number, bottom: number, left: number, header: number, footer: number, gutter: number) {
- super("w:pgMar");
- this.root.push(
- new PageMarginAttributes({
- top: top,
- right: right,
- bottom: bottom,
- left: left,
- header: header,
- footer: footer,
- gutter: gutter,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/page-number/index.ts b/src/file/document/body/section-properties/page-number/index.ts
deleted file mode 100644
index 57e81d8724..0000000000
--- a/src/file/document/body/section-properties/page-number/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./page-number";
diff --git a/src/file/document/body/section-properties/page-number/page-number.ts b/src/file/document/body/section-properties/page-number/page-number.ts
deleted file mode 100644
index e6a12101a7..0000000000
--- a/src/file/document/body/section-properties/page-number/page-number.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// http://officeopenxml.com/WPSectionPgNumType.php
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export enum PageNumberFormat {
- CARDINAL_TEXT = "cardinalText",
- DECIMAL = "decimal",
- DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
- DECIMAL_ENCLOSED_FULL_STOP = "decimalEnclosedFullstop",
- DECIMAL_ENCLOSED_PAREN = "decimalEnclosedParen",
- DECIMAL_ZERO = "decimalZero",
- LOWER_LETTER = "lowerLetter",
- LOWER_ROMAN = "lowerRoman",
- NONE = "none",
- ORDINAL_TEXT = "ordinalText",
- UPPER_LETTER = "upperLetter",
- UPPER_ROMAN = "upperRoman",
- DECIMAL_FULL_WIDTH = "decimalFullWidth",
-}
-
-export enum PageNumberSeparator {
- COLON = "colon",
- EM_DASH = "emDash",
- EN_DASH = "endash",
- HYPHEN = "hyphen",
- PERIOD = "period",
-}
-
-export interface IPageNumberTypeAttributes {
- readonly start?: number;
- readonly formatType?: PageNumberFormat;
- readonly separator?: PageNumberSeparator;
-}
-
-export class PageNumberTypeAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- start: "w:start",
- formatType: "w:fmt",
- separator: "w:chapSep",
- };
-}
-
-export class PageNumberType extends XmlComponent {
- constructor(start?: number, numberFormat?: PageNumberFormat, separator?: PageNumberSeparator) {
- super("w:pgNumType");
- this.root.push(
- new PageNumberTypeAttributes({
- start: start,
- formatType: numberFormat,
- separator: separator,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/page-size/index.ts b/src/file/document/body/section-properties/page-size/index.ts
deleted file mode 100644
index 567f7c2d58..0000000000
--- a/src/file/document/body/section-properties/page-size/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./page-size";
-export * from "./page-size-attributes";
diff --git a/src/file/document/body/section-properties/page-size/page-size-attributes.ts b/src/file/document/body/section-properties/page-size/page-size-attributes.ts
deleted file mode 100644
index 9406de635a..0000000000
--- a/src/file/document/body/section-properties/page-size/page-size-attributes.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export enum PageOrientation {
- PORTRAIT = "portrait",
- LANDSCAPE = "landscape",
-}
-
-export interface IPageSizeAttributes {
- readonly width?: number;
- readonly height?: number;
- readonly orientation?: PageOrientation;
-}
-
-export class PageSizeAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- width: "w:w",
- height: "w:h",
- orientation: "w:orient",
- };
-}
diff --git a/src/file/document/body/section-properties/page-size/page-size.ts b/src/file/document/body/section-properties/page-size/page-size.ts
deleted file mode 100644
index 6aa400bea2..0000000000
--- a/src/file/document/body/section-properties/page-size/page-size.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { PageOrientation, PageSizeAttributes } from "./page-size-attributes";
-
-export class PageSize extends XmlComponent {
- constructor(width: number, height: number, orientation: PageOrientation) {
- super("w:pgSz");
-
- const flip = orientation === PageOrientation.LANDSCAPE;
-
- this.root.push(
- new PageSizeAttributes({
- width: flip ? height : width,
- height: flip ? width : height,
- orientation: orientation,
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/properties/columns.ts b/src/file/document/body/section-properties/properties/columns.ts
new file mode 100644
index 0000000000..395df4ecae
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/columns.ts
@@ -0,0 +1,41 @@
+import { decimalNumber, twipsMeasureValue } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+export interface IColumnsAttributes {
+ readonly space?: number | string;
+ readonly count?: number;
+ readonly separate?: boolean;
+ readonly equalWidth?: boolean;
+}
+
+export class ColumnsAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ space: "w:space",
+ count: "w:num",
+ separate: "w:sep",
+ equalWidth: "w:equalWidth",
+ };
+}
+
+export class Columns extends XmlComponent {
+ constructor({ space, count, separate, equalWidth }: IColumnsAttributes) {
+ super("w:cols");
+ this.root.push(
+ new ColumnsAttributes({
+ space: space === undefined ? undefined : twipsMeasureValue(space),
+ count: count === undefined ? undefined : decimalNumber(count),
+ separate,
+ equalWidth,
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/properties/doc-grid.ts b/src/file/document/body/section-properties/properties/doc-grid.ts
new file mode 100644
index 0000000000..c8048452b8
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/doc-grid.ts
@@ -0,0 +1,38 @@
+import { decimalNumber } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+// not implemented
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+export interface IDocGridAttributesProperties {
+ readonly linePitch?: number;
+}
+
+export class DocGridAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ linePitch: "w:linePitch",
+ };
+}
+
+export class DocumentGrid extends XmlComponent {
+ constructor(linePitch: number) {
+ super("w:docGrid");
+ this.root.push(
+ new DocGridAttributes({
+ linePitch: decimalNumber(linePitch),
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/properties/header-footer-reference.spec.ts b/src/file/document/body/section-properties/properties/header-footer-reference.spec.ts
new file mode 100644
index 0000000000..adb0bc70b6
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/header-footer-reference.spec.ts
@@ -0,0 +1,56 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./header-footer-reference";
+
+describe("HeaderFooterReference", () => {
+ it("#constructor (footer)", () => {
+ const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
+ type: HeaderFooterReferenceType.DEFAULT,
+ id: 1,
+ });
+
+ const tree = new Formatter().format(footer);
+ expect(tree).to.deep.equal({
+ "w:footerReference": {
+ _attr: {
+ "r:id": "rId1",
+ "w:type": "default",
+ },
+ },
+ });
+ });
+
+ it("#constructor (header)", () => {
+ const header = new HeaderFooterReference(HeaderFooterType.HEADER, {
+ type: HeaderFooterReferenceType.DEFAULT,
+ id: 1,
+ });
+
+ const tree = new Formatter().format(header);
+ expect(tree).to.deep.equal({
+ "w:headerReference": {
+ _attr: {
+ "r:id": "rId1",
+ "w:type": "default",
+ },
+ },
+ });
+ });
+
+ it("should create without a type", () => {
+ const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
+ id: 1,
+ });
+
+ const tree = new Formatter().format(footer);
+ expect(tree).to.deep.equal({
+ "w:footerReference": {
+ _attr: {
+ "r:id": "rId1",
+ "w:type": "default",
+ },
+ },
+ });
+ });
+});
diff --git a/src/file/document/body/section-properties/properties/header-footer-reference.ts b/src/file/document/body/section-properties/properties/header-footer-reference.ts
new file mode 100644
index 0000000000..1966790da9
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/header-footer-reference.ts
@@ -0,0 +1,65 @@
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+export enum HeaderFooterReferenceType {
+ DEFAULT = "default",
+ FIRST = "first",
+ EVEN = "even",
+}
+
+//
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+
+export interface IHeaderFooterOptions {
+ readonly type?: HeaderFooterReferenceType;
+ readonly id?: number;
+}
+
+class FooterReferenceAttributes extends XmlAttributeComponent<{
+ readonly type: HeaderFooterReferenceType;
+ readonly id: string;
+}> {
+ protected readonly xmlKeys = {
+ type: "w:type",
+ id: "r:id",
+ };
+}
+
+export enum HeaderFooterType {
+ HEADER = "w:headerReference",
+ FOOTER = "w:footerReference",
+}
+export class HeaderFooterReference extends XmlComponent {
+ constructor(type: HeaderFooterType, options: IHeaderFooterOptions) {
+ super(type);
+
+ this.root.push(
+ new FooterReferenceAttributes({
+ type: options.type || HeaderFooterReferenceType.DEFAULT,
+ id: `rId${options.id}`,
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/properties/index.ts b/src/file/document/body/section-properties/properties/index.ts
new file mode 100644
index 0000000000..089a005744
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/index.ts
@@ -0,0 +1,11 @@
+export * from "./columns";
+export * from "./doc-grid";
+// export * from "./header-reference";
+export * from "./page-size";
+export * from "./page-number";
+export * from "./page-borders";
+export * from "./page-margin";
+export * from "./page-borders";
+export * from "./line-number";
+export * from "./section-type";
+export * from "./header-footer-reference";
diff --git a/src/file/document/body/section-properties/properties/line-number.ts b/src/file/document/body/section-properties/properties/line-number.ts
new file mode 100644
index 0000000000..0ab1218568
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/line-number.ts
@@ -0,0 +1,53 @@
+// http://officeopenxml.com/WPsectionLineNumbering.php
+import { decimalNumber, twipsMeasureValue } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+export enum LineNumberRestartFormat {
+ NEW_PAGE = "newPage",
+ NEW_SECTION = "newSection",
+ CONTINUOUS = "continuous",
+}
+
+//
+//
+//
+//
+//
+//
+
+export interface ILineNumberAttributes {
+ readonly countBy?: number;
+ readonly start?: number;
+ readonly restart?: LineNumberRestartFormat;
+ readonly distance?: number | string;
+}
+
+export class LineNumberAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ countBy: "w:countBy",
+ start: "w:start",
+ restart: "w:restart",
+ distance: "w:distance",
+ };
+}
+
+export class LineNumberType extends XmlComponent {
+ constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
+ super("w:lnNumType");
+ this.root.push(
+ new LineNumberAttributes({
+ countBy: countBy === undefined ? undefined : decimalNumber(countBy),
+ start: start === undefined ? undefined : decimalNumber(start),
+ restart,
+ distance: distance === undefined ? undefined : twipsMeasureValue(distance),
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/page-border/page-borders.spec.ts b/src/file/document/body/section-properties/properties/page-borders.spec.ts
similarity index 89%
rename from src/file/document/body/section-properties/page-border/page-borders.spec.ts
rename to src/file/document/body/section-properties/properties/page-borders.spec.ts
index 3b6152013a..977bcbd1b7 100644
--- a/src/file/document/body/section-properties/page-border/page-borders.spec.ts
+++ b/src/file/document/body/section-properties/properties/page-borders.spec.ts
@@ -1,7 +1,7 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { BorderStyle } from "file/styles";
+import { BorderStyle } from "file/border";
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
@@ -70,22 +70,22 @@ describe("PageBorders", () => {
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": {
- _attr: { "w:color": "001122", "w:size": 10, "w:val": "doubleWave" },
+ _attr: { "w:color": "001122", "w:sz": 10, "w:val": "doubleWave" },
},
});
expect(tree["w:pgBorders"][2]).to.deep.equal({
- "w:right": {
- _attr: { "w:color": "223344", "w:size": 20, "w:val": "double" },
+ "w:left": {
+ _attr: { "w:color": "889900", "w:sz": 40, "w:val": "dotted" },
},
});
expect(tree["w:pgBorders"][3]).to.deep.equal({
"w:bottom": {
- _attr: { "w:color": "556677", "w:size": 30, "w:val": "single" },
+ _attr: { "w:color": "556677", "w:sz": 30, "w:val": "single" },
},
});
expect(tree["w:pgBorders"][4]).to.deep.equal({
- "w:left": {
- _attr: { "w:color": "889900", "w:size": 40, "w:val": "dotted" },
+ "w:right": {
+ _attr: { "w:color": "223344", "w:sz": 20, "w:val": "double" },
},
});
});
diff --git a/src/file/document/body/section-properties/properties/page-borders.ts b/src/file/document/body/section-properties/properties/page-borders.ts
new file mode 100644
index 0000000000..d3a8ecbb61
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/page-borders.ts
@@ -0,0 +1,106 @@
+// http://officeopenxml.com/WPsectionBorders.php
+import { BorderElement, IBorderOptions } from "file/border";
+import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+export enum PageBorderDisplay {
+ ALL_PAGES = "allPages",
+ FIRST_PAGE = "firstPage",
+ NOT_FIRST_PAGE = "notFirstPage",
+}
+
+//
+//
+//
+//
+//
+//
+export enum PageBorderOffsetFrom {
+ PAGE = "page",
+ TEXT = "text",
+}
+
+//
+//
+//
+//
+//
+//
+export enum PageBorderZOrder {
+ BACK = "back",
+ FRONT = "front",
+}
+
+export interface IPageBorderAttributes {
+ readonly display?: PageBorderDisplay;
+ readonly offsetFrom?: PageBorderOffsetFrom;
+ readonly zOrder?: PageBorderZOrder;
+}
+
+export interface IPageBordersOptions {
+ readonly pageBorders?: IPageBorderAttributes;
+ readonly pageBorderTop?: IBorderOptions;
+ readonly pageBorderRight?: IBorderOptions;
+ readonly pageBorderBottom?: IBorderOptions;
+ readonly pageBorderLeft?: IBorderOptions;
+}
+
+class PageBordersAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ display: "w:display",
+ offsetFrom: "w:offsetFrom",
+ zOrder: "w:zOrder",
+ };
+}
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+export class PageBorders extends IgnoreIfEmptyXmlComponent {
+ constructor(options?: IPageBordersOptions) {
+ super("w:pgBorders");
+
+ if (!options) {
+ return;
+ }
+
+ if (options.pageBorders) {
+ this.root.push(
+ new PageBordersAttributes({
+ display: options.pageBorders.display,
+ offsetFrom: options.pageBorders.offsetFrom,
+ zOrder: options.pageBorders.zOrder,
+ }),
+ );
+ } else {
+ this.root.push(new PageBordersAttributes({}));
+ }
+
+ if (options.pageBorderTop) {
+ this.root.push(new BorderElement("w:top", options.pageBorderTop));
+ }
+ if (options.pageBorderLeft) {
+ this.root.push(new BorderElement("w:left", options.pageBorderLeft));
+ }
+ if (options.pageBorderBottom) {
+ this.root.push(new BorderElement("w:bottom", options.pageBorderBottom));
+ }
+ if (options.pageBorderRight) {
+ this.root.push(new BorderElement("w:right", options.pageBorderRight));
+ }
+ }
+}
diff --git a/src/file/document/body/section-properties/properties/page-margin.ts b/src/file/document/body/section-properties/properties/page-margin.ts
new file mode 100644
index 0000000000..91df7db51a
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/page-margin.ts
@@ -0,0 +1,58 @@
+import { signedTwipsMeasureValue, twipsMeasureValue } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+export interface IPageMarginAttributes {
+ readonly top?: number | string;
+ readonly right?: number | string;
+ readonly bottom?: number | string;
+ readonly left?: number | string;
+ readonly header?: number | string;
+ readonly footer?: number | string;
+ readonly gutter?: number | string;
+}
+
+export class PageMarginAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ top: "w:top",
+ right: "w:right",
+ bottom: "w:bottom",
+ left: "w:left",
+ header: "w:header",
+ footer: "w:footer",
+ gutter: "w:gutter",
+ };
+}
+
+export class PageMargin extends XmlComponent {
+ constructor(
+ top: number | string,
+ right: number | string,
+ bottom: number | string,
+ left: number | string,
+ header: number | string,
+ footer: number | string,
+ gutter: number | string,
+ ) {
+ super("w:pgMar");
+ this.root.push(
+ new PageMarginAttributes({
+ top: signedTwipsMeasureValue(top),
+ right: twipsMeasureValue(right),
+ bottom: signedTwipsMeasureValue(bottom),
+ left: twipsMeasureValue(left),
+ header: twipsMeasureValue(header),
+ footer: twipsMeasureValue(footer),
+ gutter: twipsMeasureValue(gutter),
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/properties/page-number.ts b/src/file/document/body/section-properties/properties/page-number.ts
new file mode 100644
index 0000000000..0bca61ebba
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/page-number.ts
@@ -0,0 +1,54 @@
+// http://officeopenxml.com/WPSectionPgNumType.php
+import { NumberFormat } from "file/shared/number-format";
+import { decimalNumber } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+export enum PageNumberSeparator {
+ HYPHEN = "hyphen",
+ PERIOD = "period",
+ COLON = "colon",
+ EM_DASH = "emDash",
+ EN_DASH = "endash",
+}
+
+export interface IPageNumberTypeAttributes {
+ readonly start?: number;
+ readonly formatType?: NumberFormat;
+ readonly separator?: PageNumberSeparator;
+}
+
+//
+//
+//
+//
+//
+//
+
+export class PageNumberTypeAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ start: "w:start",
+ formatType: "w:fmt",
+ separator: "w:chapSep",
+ };
+}
+export class PageNumberType extends XmlComponent {
+ constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
+ super("w:pgNumType");
+ this.root.push(
+ new PageNumberTypeAttributes({
+ start: start === undefined ? undefined : decimalNumber(start),
+ formatType,
+ separator,
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/page-size/page-size.spec.ts b/src/file/document/body/section-properties/properties/page-size.spec.ts
similarity index 90%
rename from src/file/document/body/section-properties/page-size/page-size.spec.ts
rename to src/file/document/body/section-properties/properties/page-size.spec.ts
index 0921006e1e..aa7ca8ae1d 100644
--- a/src/file/document/body/section-properties/page-size/page-size.spec.ts
+++ b/src/file/document/body/section-properties/properties/page-size.spec.ts
@@ -2,8 +2,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { PageSize } from "./page-size";
-import { PageOrientation } from "./page-size-attributes";
+import { PageOrientation, PageSize } from "./page-size";
describe("PageSize", () => {
describe("#constructor()", () => {
diff --git a/src/file/document/body/section-properties/properties/page-size.ts b/src/file/document/body/section-properties/properties/page-size.ts
new file mode 100644
index 0000000000..ff99c52201
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/page-size.ts
@@ -0,0 +1,52 @@
+import { twipsMeasureValue } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+export enum PageOrientation {
+ PORTRAIT = "portrait",
+ LANDSCAPE = "landscape",
+}
+
+//
+//
+//
+//
+//
+//
+export interface IPageSizeAttributes {
+ readonly width?: number | string;
+ readonly height?: number | string;
+ readonly orientation?: PageOrientation;
+}
+
+export class PageSizeAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ width: "w:w",
+ height: "w:h",
+ orientation: "w:orient",
+ };
+}
+
+export class PageSize extends XmlComponent {
+ constructor(width: number | string, height: number | string, orientation: PageOrientation) {
+ super("w:pgSz");
+
+ const flip = orientation === PageOrientation.LANDSCAPE;
+
+ const widthTwips = twipsMeasureValue(width);
+ const heightTwips = twipsMeasureValue(height);
+
+ this.root.push(
+ new PageSizeAttributes({
+ width: flip ? heightTwips : widthTwips,
+ height: flip ? widthTwips : heightTwips,
+ orientation: orientation,
+ }),
+ );
+ }
+}
diff --git a/src/file/document/body/section-properties/type/section-type.spec.ts b/src/file/document/body/section-properties/properties/section-type.spec.ts
similarity index 89%
rename from src/file/document/body/section-properties/type/section-type.spec.ts
rename to src/file/document/body/section-properties/properties/section-type.spec.ts
index 7276825fab..bbf08799f3 100644
--- a/src/file/document/body/section-properties/type/section-type.spec.ts
+++ b/src/file/document/body/section-properties/properties/section-type.spec.ts
@@ -1,8 +1,7 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { Type } from "./section-type";
-import { SectionType } from "./section-type-attributes";
+import { SectionType, Type } from "./section-type";
describe("Type", () => {
it("should create with even page section type", () => {
diff --git a/src/file/document/body/section-properties/properties/section-type.ts b/src/file/document/body/section-properties/properties/section-type.ts
new file mode 100644
index 0000000000..e09d3c6508
--- /dev/null
+++ b/src/file/document/body/section-properties/properties/section-type.ts
@@ -0,0 +1,37 @@
+// http://officeopenxml.com/WPsection.php
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+export enum SectionType {
+ NEXT_PAGE = "nextPage",
+ NEXT_COLUMN = "nextColumn",
+ CONTINUOUS = "continuous",
+ EVEN_PAGE = "evenPage",
+ ODD_PAGE = "oddPage",
+}
+
+//
+//
+//
+export class SectionTypeAttributes extends XmlAttributeComponent<{
+ readonly val: SectionType;
+}> {
+ protected readonly xmlKeys = {
+ val: "w:val",
+ };
+}
+
+export class Type extends XmlComponent {
+ constructor(value: SectionType) {
+ super("w:type");
+ this.root.push(new SectionTypeAttributes({ val: value }));
+ }
+}
diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts
index 9483a4d47e..d0c7e7fc5a 100644
--- a/src/file/document/body/section-properties/section-properties.spec.ts
+++ b/src/file/document/body/section-properties/section-properties.spec.ts
@@ -5,13 +5,30 @@ import { Formatter } from "export/formatter";
import { FooterWrapper } from "file/footer-wrapper";
import { HeaderWrapper } from "file/header-wrapper";
import { Media } from "file/media";
-import { LineNumberRestartFormat } from "./line-number";
+import { NumberFormat } from "file/shared/number-format";
+import { VerticalAlign } from "file/vertical-align";
-import { PageBorderOffsetFrom } from "./page-border";
-import { PageNumberFormat } from "./page-number";
-import { SectionProperties } from "./section-properties";
-import { SectionType } from "./type/section-type-attributes";
-import { SectionVerticalAlignValue } from "./vertical-align";
+import { PageOrientation } from "./properties";
+import { LineNumberRestartFormat } from "./properties/line-number";
+import { PageBorderOffsetFrom } from "./properties/page-borders";
+import { SectionType } from "./properties/section-type";
+import { sectionMarginDefaults, sectionPageSizeDefaults, SectionProperties } from "./section-properties";
+
+const DEFAULT_MARGINS = {
+ "w:bottom": sectionMarginDefaults.BOTTOM,
+ "w:footer": sectionMarginDefaults.FOOTER,
+ "w:top": sectionMarginDefaults.TOP,
+ "w:right": sectionMarginDefaults.RIGHT,
+ "w:left": sectionMarginDefaults.LEFT,
+ "w:header": sectionMarginDefaults.HEADER,
+ "w:gutter": sectionMarginDefaults.GUTTER,
+};
+
+const PAGE_SIZE_DEFAULTS = {
+ "w:h": sectionPageSizeDefaults.HEIGHT,
+ "w:orient": sectionPageSizeDefaults.ORIENTATION,
+ "w:w": sectionPageSizeDefaults.WIDTH,
+};
describe("SectionProperties", () => {
describe("#constructor()", () => {
@@ -21,26 +38,27 @@ describe("SectionProperties", () => {
const properties = new SectionProperties({
page: {
size: {
- width: 11906,
- height: 16838,
+ width: 1190,
+ height: 1680,
+ orientation: PageOrientation.PORTRAIT,
},
margin: {
- top: convertInchesToTwip(1),
- right: convertInchesToTwip(1),
- bottom: convertInchesToTwip(1),
- left: convertInchesToTwip(1),
- header: 708,
- footer: 708,
- gutter: 0,
+ top: "2in",
+ right: "2in",
+ bottom: "2in",
+ left: "2in",
+ header: 808,
+ footer: 808,
+ gutter: 10,
},
pageNumbers: {
start: 10,
- formatType: PageNumberFormat.CARDINAL_TEXT,
+ formatType: NumberFormat.CARDINAL_TEXT,
},
},
column: {
- space: 708,
- count: 1,
+ space: 208,
+ count: 2,
separate: true,
},
grid: {
@@ -53,7 +71,7 @@ describe("SectionProperties", () => {
even: new FooterWrapper(media, 200),
},
titlePage: true,
- verticalAlign: SectionVerticalAlignValue.TOP,
+ verticalAlign: VerticalAlign.TOP,
});
const tree = new Formatter().format(properties);
@@ -62,25 +80,25 @@ describe("SectionProperties", () => {
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:headerReference": { _attr: { "r:id": "rId100", "w:type": "default" } } });
expect(tree["w:sectPr"][1]).to.deep.equal({ "w:footerReference": { _attr: { "r:id": "rId200", "w:type": "even" } } });
- expect(tree["w:sectPr"][2]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
+ expect(tree["w:sectPr"][2]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 1680, "w:w": 1190, "w:orient": "portrait" } } });
expect(tree["w:sectPr"][3]).to.deep.equal({
"w:pgMar": {
_attr: {
- "w:bottom": 1440,
- "w:footer": 708,
- "w:top": 1440,
- "w:right": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:gutter": 0,
+ "w:bottom": "2in",
+ "w:footer": 808,
+ "w:top": "2in",
+ "w:right": "2in",
+ "w:left": "2in",
+ "w:header": 808,
+ "w:gutter": 10,
},
},
});
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:pgNumType": { _attr: { "w:fmt": "cardinalText", "w:start": 10 } } });
- expect(tree["w:sectPr"][5]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": true, "w:num": 1 } } });
+ expect(tree["w:sectPr"][5]).to.deep.equal({ "w:cols": { _attr: { "w:space": 208, "w:sep": true, "w:num": 2 } } });
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:vAlign": { _attr: { "w:val": "top" } } });
- expect(tree["w:sectPr"][7]).to.deep.equal({ "w:titlePg": { _attr: { "w:val": "1" } } });
+ expect(tree["w:sectPr"][7]).to.deep.equal({ "w:titlePg": {} });
expect(tree["w:sectPr"][8]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
});
@@ -89,22 +107,12 @@ 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: PAGE_SIZE_DEFAULTS } });
expect(tree["w:sectPr"][1]).to.deep.equal({
- "w:pgMar": {
- _attr: {
- "w:bottom": 1440,
- "w:footer": 708,
- "w:top": 1440,
- "w:right": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:gutter": 0,
- },
- },
+ "w:pgMar": { _attr: DEFAULT_MARGINS },
});
- expect(tree["w:sectPr"][3]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } });
- expect(tree["w:sectPr"][4]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
+ // expect(tree["w:sectPr"][3]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } });
+ expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
});
it("should create section properties with changed options", () => {
@@ -118,17 +126,12 @@ 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: PAGE_SIZE_DEFAULTS } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": {
_attr: {
- "w:bottom": 1440,
- "w:footer": 708,
+ ...DEFAULT_MARGINS,
"w:top": 0,
- "w:right": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:gutter": 0,
},
},
});
@@ -145,17 +148,12 @@ 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: PAGE_SIZE_DEFAULTS } });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": {
_attr: {
+ ...DEFAULT_MARGINS,
"w:bottom": 0,
- "w:footer": 708,
- "w:top": 1440,
- "w:right": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:gutter": 0,
},
},
});
@@ -167,24 +165,25 @@ describe("SectionProperties", () => {
size: {
width: 0,
height: 0,
+ orientation: PageOrientation.LANDSCAPE,
},
},
});
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:orient": PageOrientation.LANDSCAPE,
+ "w:w": 0,
+ },
+ },
+ });
expect(tree["w:sectPr"][1]).to.deep.equal({
"w:pgMar": {
- _attr: {
- "w:bottom": 1440,
- "w:footer": 708,
- "w:top": 1440,
- "w:right": 1440,
- "w:left": 1440,
- "w:header": 708,
- "w:gutter": 0,
- },
+ _attr: DEFAULT_MARGINS,
},
});
});
@@ -211,7 +210,7 @@ describe("SectionProperties", () => {
const properties = new SectionProperties({
page: {
pageNumbers: {
- formatType: PageNumberFormat.UPPER_ROMAN,
+ formatType: NumberFormat.UPPER_ROMAN,
},
},
});
diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts
index 095928d022..ba155a61c4 100644
--- a/src/file/document/body/section-properties/section-properties.ts
+++ b/src/file/document/body/section-properties/section-properties.ts
@@ -1,29 +1,21 @@
// http://officeopenxml.com/WPsection.php
// tslint:disable: no-unnecessary-initializer
-import { convertInchesToTwip } from "convenience-functions";
import { FooterWrapper } from "file/footer-wrapper";
import { HeaderWrapper } from "file/header-wrapper";
-import { XmlComponent } from "file/xml-components";
+import { VerticalAlign, VerticalAlignElement } from "file/vertical-align";
+import { OnOffElement, XmlComponent } from "file/xml-components";
-import { Columns } from "./columns/columns";
-import { DocumentGrid } from "./doc-grid/doc-grid";
-import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
-import { FooterReferenceType } from "./footer-reference";
-import { FooterReference } from "./footer-reference/footer-reference";
-import { HeaderReferenceType } from "./header-reference";
-import { HeaderReference } from "./header-reference/header-reference";
-import { ILineNumberAttributes, LineNumberType } from "./line-number";
-import { IPageBordersOptions, PageBorders } from "./page-border";
-import { PageMargin } from "./page-margin/page-margin";
-import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
-import { IPageNumberTypeAttributes, PageNumberType } from "./page-number";
-import { PageSize } from "./page-size/page-size";
-import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
-import { TitlePage } from "./title-page/title-page";
-import { Type } from "./type/section-type";
-import { SectionType } from "./type/section-type-attributes";
-import { SectionVerticalAlign, SectionVerticalAlignValue } from "./vertical-align";
+import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./properties/header-footer-reference";
+
+import { Columns, IColumnsAttributes } from "./properties/columns";
+import { DocumentGrid, IDocGridAttributesProperties } from "./properties/doc-grid";
+import { ILineNumberAttributes, LineNumberType } from "./properties/line-number";
+import { IPageBordersOptions, PageBorders } from "./properties/page-borders";
+import { IPageMarginAttributes, PageMargin } from "./properties/page-margin";
+import { IPageNumberTypeAttributes, PageNumberType } from "./properties/page-number";
+import { IPageSizeAttributes, PageOrientation, PageSize } from "./properties/page-size";
+import { SectionType, Type } from "./properties/section-type";
export interface IHeaderFooterGroup {
readonly default?: T;
@@ -43,53 +35,93 @@ export interface ISectionPropertiesOptions {
readonly footerWrapperGroup?: IHeaderFooterGroup;
readonly lineNumbers?: ILineNumberAttributes;
readonly titlePage?: boolean;
- readonly verticalAlign?: SectionVerticalAlignValue;
- readonly column?: {
- readonly space?: number;
- readonly count?: number;
- readonly separate?: boolean;
- };
+ readonly verticalAlign?: VerticalAlign;
+ readonly column?: IColumnsAttributes;
readonly type?: SectionType;
}
+
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+export const sectionMarginDefaults = {
+ TOP: "1in",
+ RIGHT: "1in",
+ BOTTOM: "1in",
+ LEFT: "1in",
+ HEADER: 708,
+ FOOTER: 708,
+ GUTTER: 0,
+};
+
+export const sectionPageSizeDefaults = {
+ WIDTH: 11906,
+ HEIGHT: 16838,
+ ORIENTATION: PageOrientation.PORTRAIT,
+};
+
export class SectionProperties extends XmlComponent {
constructor({
page: {
- size: { width = 11906, height = 16838, orientation = PageOrientation.PORTRAIT } = {},
+ size: {
+ width = sectionPageSizeDefaults.WIDTH,
+ height = sectionPageSizeDefaults.HEIGHT,
+ orientation = sectionPageSizeDefaults.ORIENTATION,
+ } = {},
margin: {
- top = convertInchesToTwip(1),
- right = convertInchesToTwip(1),
- bottom = convertInchesToTwip(1),
- left = convertInchesToTwip(1),
- header = 708,
- footer = 708,
- gutter = 0,
- } = {},
- pageNumbers: {
- start: pageNumberStart = undefined,
- formatType: pageNumberFormatType = undefined,
- separator: pageNumberSeparator = undefined,
- } = {},
- borders: {
- pageBorders = undefined,
- pageBorderTop = undefined,
- pageBorderRight = undefined,
- pageBorderBottom = undefined,
- pageBorderLeft = undefined,
+ top = sectionMarginDefaults.TOP,
+ right = sectionMarginDefaults.RIGHT,
+ bottom = sectionMarginDefaults.BOTTOM,
+ left = sectionMarginDefaults.LEFT,
+ header = sectionMarginDefaults.HEADER,
+ footer = sectionMarginDefaults.FOOTER,
+ gutter = sectionMarginDefaults.GUTTER,
} = {},
+ pageNumbers = {},
+ borders,
} = {},
grid: { linePitch = 360 } = {},
headerWrapperGroup = {},
footerWrapperGroup = {},
- lineNumbers: { countBy: lineNumberCountBy, start: lineNumberStart, restart: lineNumberRestart, distance: lineNumberDistance } = {},
- titlePage = false,
+ lineNumbers,
+ titlePage,
verticalAlign,
- column: { space = 708, count = 1, separate = false } = {},
+ column,
type,
}: ISectionPropertiesOptions = {}) {
super("w:sectPr");
- this.addHeaders(headerWrapperGroup);
- this.addFooters(footerWrapperGroup);
+ this.addHeaderFooterGroup(HeaderFooterType.HEADER, headerWrapperGroup);
+ this.addHeaderFooterGroup(HeaderFooterType.FOOTER, footerWrapperGroup);
if (type) {
this.root.push(new Type(type));
@@ -98,90 +130,58 @@ export class SectionProperties extends XmlComponent {
this.root.push(new PageSize(width, height, orientation));
this.root.push(new PageMargin(top, right, bottom, left, header, footer, gutter));
- if (pageBorders || pageBorderTop || pageBorderRight || pageBorderBottom || pageBorderLeft) {
- this.root.push(
- new PageBorders({
- pageBorders: pageBorders,
- pageBorderTop: pageBorderTop,
- pageBorderRight: pageBorderRight,
- pageBorderBottom: pageBorderBottom,
- pageBorderLeft: pageBorderLeft,
- }),
- );
+ if (borders) {
+ this.root.push(new PageBorders(borders));
}
- if (lineNumberCountBy || lineNumberStart || lineNumberRestart || lineNumberDistance) {
- this.root.push(new LineNumberType(lineNumberCountBy, lineNumberStart, lineNumberRestart, lineNumberDistance));
+ if (lineNumbers) {
+ this.root.push(new LineNumberType(lineNumbers));
}
- this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType, pageNumberSeparator));
+ this.root.push(new PageNumberType(pageNumbers));
- this.root.push(new Columns(space, count, separate));
+ if (column) {
+ this.root.push(new Columns(column));
+ }
if (verticalAlign) {
- this.root.push(new SectionVerticalAlign(verticalAlign));
+ this.root.push(new VerticalAlignElement(verticalAlign));
}
- if (titlePage) {
- this.root.push(new TitlePage());
+ if (titlePage !== undefined) {
+ this.root.push(new OnOffElement("w:titlePg", titlePage));
}
this.root.push(new DocumentGrid(linePitch));
}
- private addHeaders(headers: IHeaderFooterGroup): void {
- if (headers.default) {
+ private addHeaderFooterGroup(
+ type: HeaderFooterType,
+ group: IHeaderFooterGroup | IHeaderFooterGroup,
+ ): void {
+ if (group.default) {
this.root.push(
- new HeaderReference({
- headerType: HeaderReferenceType.DEFAULT,
- headerId: headers.default.View.ReferenceId,
+ new HeaderFooterReference(type, {
+ type: HeaderFooterReferenceType.DEFAULT,
+ id: group.default.View.ReferenceId,
}),
);
}
- if (headers.first) {
+ if (group.first) {
this.root.push(
- new HeaderReference({
- headerType: HeaderReferenceType.FIRST,
- headerId: headers.first.View.ReferenceId,
+ new HeaderFooterReference(type, {
+ type: HeaderFooterReferenceType.FIRST,
+ id: group.first.View.ReferenceId,
}),
);
}
- if (headers.even) {
+ if (group.even) {
this.root.push(
- new HeaderReference({
- headerType: HeaderReferenceType.EVEN,
- headerId: headers.even.View.ReferenceId,
- }),
- );
- }
- }
-
- private addFooters(footers: IHeaderFooterGroup): void {
- if (footers.default) {
- this.root.push(
- new FooterReference({
- footerType: FooterReferenceType.DEFAULT,
- footerId: footers.default.View.ReferenceId,
- }),
- );
- }
-
- if (footers.first) {
- this.root.push(
- new FooterReference({
- footerType: FooterReferenceType.FIRST,
- footerId: footers.first.View.ReferenceId,
- }),
- );
- }
-
- if (footers.even) {
- this.root.push(
- new FooterReference({
- footerType: FooterReferenceType.EVEN,
- footerId: footers.even.View.ReferenceId,
+ new HeaderFooterReference(type, {
+ type: HeaderFooterReferenceType.EVEN,
+ id: group.even.View.ReferenceId,
}),
);
}
diff --git a/src/file/document/body/section-properties/title-page/title-page-attributes.ts b/src/file/document/body/section-properties/title-page/title-page-attributes.ts
deleted file mode 100644
index 078b6ed47f..0000000000
--- a/src/file/document/body/section-properties/title-page/title-page-attributes.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export class TitlePageAttributes extends XmlAttributeComponent<{
- readonly value: string;
-}> {
- protected readonly xmlKeys = {
- value: "w:val",
- };
-}
diff --git a/src/file/document/body/section-properties/title-page/title-page.spec.ts b/src/file/document/body/section-properties/title-page/title-page.spec.ts
deleted file mode 100644
index e5eed2a429..0000000000
--- a/src/file/document/body/section-properties/title-page/title-page.spec.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { TitlePage } from "./title-page";
-
-describe("PageSize", () => {
- describe("#constructor()", () => {
- it("should create title page property for different first page header", () => {
- const properties = new TitlePage();
- const tree = new Formatter().format(properties);
-
- expect(Object.keys(tree)).to.deep.equal(["w:titlePg"]);
- expect(tree["w:titlePg"]).to.deep.equal({ _attr: { "w:val": "1" } });
- });
- });
-});
diff --git a/src/file/document/body/section-properties/title-page/title-page.ts b/src/file/document/body/section-properties/title-page/title-page.ts
deleted file mode 100644
index 5b11d77581..0000000000
--- a/src/file/document/body/section-properties/title-page/title-page.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-import { TitlePageAttributes } from "./title-page-attributes";
-
-export class TitlePage extends XmlComponent {
- constructor() {
- super("w:titlePg");
- this.root.push(
- new TitlePageAttributes({
- value: "1",
- }),
- );
- }
-}
diff --git a/src/file/document/body/section-properties/type/index.ts b/src/file/document/body/section-properties/type/index.ts
deleted file mode 100644
index fd7a8abd9c..0000000000
--- a/src/file/document/body/section-properties/type/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./section-type";
-export * from "./section-type-attributes";
diff --git a/src/file/document/body/section-properties/type/section-type-attributes.ts b/src/file/document/body/section-properties/type/section-type-attributes.ts
deleted file mode 100644
index 4ac8dd60b4..0000000000
--- a/src/file/document/body/section-properties/type/section-type-attributes.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export enum SectionType {
- CONTINUOUS = "continuous",
- EVEN_PAGE = "evenPage",
- NEXT_COLUMN = "nextColumn",
- NEXT_PAGE = "nextPage",
- ODD_PAGE = "oddPage",
-}
-
-export class SectionTypeAttributes extends XmlAttributeComponent<{
- readonly val: SectionType;
-}> {
- protected readonly xmlKeys = {
- val: "w:val",
- };
-}
diff --git a/src/file/document/body/section-properties/type/section-type.ts b/src/file/document/body/section-properties/type/section-type.ts
deleted file mode 100644
index 3a11f2e041..0000000000
--- a/src/file/document/body/section-properties/type/section-type.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// http://officeopenxml.com/WPsection.php
-import { XmlComponent } from "file/xml-components";
-import { SectionType, SectionTypeAttributes } from "./section-type-attributes";
-
-export class Type extends XmlComponent {
- constructor(value: SectionType) {
- super("w:type");
- this.root.push(new SectionTypeAttributes({ val: value }));
- }
-}
diff --git a/src/file/document/body/section-properties/vertical-align/index.ts b/src/file/document/body/section-properties/vertical-align/index.ts
deleted file mode 100644
index 1f3fb76bb2..0000000000
--- a/src/file/document/body/section-properties/vertical-align/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./vertical-align";
-export * from "./vertical-align-attributes";
diff --git a/src/file/document/body/section-properties/vertical-align/vertical-align-attributes.ts b/src/file/document/body/section-properties/vertical-align/vertical-align-attributes.ts
deleted file mode 100644
index 477bb448b4..0000000000
--- a/src/file/document/body/section-properties/vertical-align/vertical-align-attributes.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-import { SectionVerticalAlignValue } from "./vertical-align";
-
-export class SectionVerticalAlignAttributes extends XmlAttributeComponent<{
- readonly verticalAlign?: SectionVerticalAlignValue;
-}> {
- protected readonly xmlKeys = {
- verticalAlign: "w:val",
- };
-}
diff --git a/src/file/document/body/section-properties/vertical-align/vertical-align.ts b/src/file/document/body/section-properties/vertical-align/vertical-align.ts
deleted file mode 100644
index b025059d16..0000000000
--- a/src/file/document/body/section-properties/vertical-align/vertical-align.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// http://officeopenxml.com/WPsection.php
-
-import { XmlComponent } from "file/xml-components";
-import { SectionVerticalAlignAttributes } from "./vertical-align-attributes";
-
-export enum SectionVerticalAlignValue {
- BOTH = "both",
- BOTTOM = "bottom",
- CENTER = "center",
- TOP = "top",
-}
-
-export class SectionVerticalAlign extends XmlComponent {
- constructor(value: SectionVerticalAlignValue) {
- super("w:vAlign");
- this.root.push(new SectionVerticalAlignAttributes({ verticalAlign: value }));
- }
-}
diff --git a/src/file/document/document-background/document-background.spec.ts b/src/file/document/document-background/document-background.spec.ts
index 83d1fb36b1..c7d947473d 100644
--- a/src/file/document/document-background/document-background.spec.ts
+++ b/src/file/document/document-background/document-background.spec.ts
@@ -34,8 +34,8 @@ describe("DocumentBackground", () => {
const documentBackground = new DocumentBackground({
color: "ffff00",
themeColor: "test",
- themeShade: "test",
- themeTint: "test",
+ themeShade: "0A",
+ themeTint: "0B",
});
const tree = new Formatter().format(documentBackground);
expect(tree).to.deep.equal({
@@ -43,8 +43,8 @@ describe("DocumentBackground", () => {
_attr: {
"w:color": "ffff00",
"w:themeColor": "test",
- "w:themeShade": "test",
- "w:themeTint": "test",
+ "w:themeShade": "0A",
+ "w:themeTint": "0B",
},
},
});
diff --git a/src/file/document/document-background/document-background.ts b/src/file/document/document-background/document-background.ts
index 44b04aabe6..bbda932882 100644
--- a/src/file/document/document-background/document-background.ts
+++ b/src/file/document/document-background/document-background.ts
@@ -1,7 +1,30 @@
// http://officeopenxml.com/WPdocument.php
// http://www.datypic.com/sc/ooxml/e-w_background-1.html
+import { hexColorValue, uCharHexNumber } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
export class DocumentBackgroundAttributes extends XmlAttributeComponent<{
readonly color: string;
readonly themeColor?: string;
@@ -23,16 +46,32 @@ export interface IDocumentBackgroundOptions {
readonly themeTint?: string;
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
export class DocumentBackground extends XmlComponent {
constructor(options: IDocumentBackgroundOptions) {
super("w:background");
this.root.push(
new DocumentBackgroundAttributes({
- color: options.color ? options.color : "FFFFFF",
+ color: hexColorValue(options.color ? options.color : "FFFFFF"),
themeColor: options.themeColor,
- themeShade: options.themeShade,
- themeTint: options.themeTint,
+ themeShade: options.themeShade === undefined ? undefined : uCharHexNumber(options.themeShade),
+ themeTint: options.themeTint === undefined ? undefined : uCharHexNumber(options.themeTint),
}),
);
}
diff --git a/src/file/document/document.ts b/src/file/document/document.ts
index cc33709076..4059eb5183 100644
--- a/src/file/document/document.ts
+++ b/src/file/document/document.ts
@@ -11,6 +11,25 @@ export interface IDocumentOptions {
readonly background: IDocumentBackgroundOptions;
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Document extends XmlComponent {
private readonly body: Body;
@@ -50,8 +69,4 @@ export class Document extends XmlComponent {
public get Body(): Body {
return this.body;
}
-
- public getTablesOfContents(): TableOfContents[] {
- return this.body.getTablesOfContents();
- }
}
diff --git a/src/file/drawing/anchor/anchor.ts b/src/file/drawing/anchor/anchor.ts
index 3d2d906500..5fe56d3305 100644
--- a/src/file/drawing/anchor/anchor.ts
+++ b/src/file/drawing/anchor/anchor.ts
@@ -11,6 +11,31 @@ import { Extent } from "./../extent/extent";
import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-properties";
import { AnchorAttributes } from "./anchor-attributes";
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Anchor extends XmlComponent {
constructor(mediaData: IMediaData, transform: IMediaDataTransformation, drawingOptions: IDrawingOptions) {
super("wp:anchor");
diff --git a/src/file/drawing/drawing.ts b/src/file/drawing/drawing.ts
index d42f403cf2..df20c8f5f0 100644
--- a/src/file/drawing/drawing.ts
+++ b/src/file/drawing/drawing.ts
@@ -15,6 +15,13 @@ export interface IDrawingOptions {
readonly floating?: IFloating;
}
+//
+//
+//
+//
+//
+//
+
export class Drawing extends XmlComponent {
private readonly inline: Inline;
@@ -28,8 +35,4 @@ export class Drawing extends XmlComponent {
this.root.push(new Anchor(imageData, imageData.transformation, drawingOptions));
}
}
-
- public scale(factorX: number, factorY: number): void {
- this.inline.scale(factorX, factorY);
- }
}
diff --git a/src/file/drawing/extent/extent.ts b/src/file/drawing/extent/extent.ts
index 500571425b..1945fd0eae 100644
--- a/src/file/drawing/extent/extent.ts
+++ b/src/file/drawing/extent/extent.ts
@@ -15,11 +15,4 @@ export class Extent extends XmlComponent {
this.root.push(this.attributes);
}
-
- public setXY(x: number, y: number): void {
- this.attributes.set({
- cx: x,
- cy: y,
- });
- }
}
diff --git a/src/file/drawing/floating/horizontal-position.spec.ts b/src/file/drawing/floating/horizontal-position.spec.ts
index 705e637dd5..7e9a6223d4 100644
--- a/src/file/drawing/floating/horizontal-position.spec.ts
+++ b/src/file/drawing/floating/horizontal-position.spec.ts
@@ -49,5 +49,9 @@ describe("HorizontalPosition", () => {
],
});
});
+
+ it("should require one of align or offset", () => {
+ expect(() => new HorizontalPosition({})).to.throw();
+ });
});
});
diff --git a/src/file/drawing/floating/vertical-position.spec.ts b/src/file/drawing/floating/vertical-position.spec.ts
index 20f4cbe62a..29c69b5bdc 100644
--- a/src/file/drawing/floating/vertical-position.spec.ts
+++ b/src/file/drawing/floating/vertical-position.spec.ts
@@ -49,5 +49,9 @@ describe("VerticalPosition", () => {
],
});
});
+
+ it("should require one of align or offset", () => {
+ expect(() => new VerticalPosition({})).to.throw();
+ });
});
});
diff --git a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
index 9a4c9a32de..b1a8337690 100644
--- a/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
+++ b/src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
@@ -20,8 +20,4 @@ export class GraphicData extends XmlComponent {
this.root.push(this.pic);
}
-
- public setXY(x: number, y: number): void {
- this.pic.setXY(x, y);
- }
}
diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
index 280dd8796e..df1254331e 100644
--- a/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
+++ b/src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
@@ -8,8 +8,6 @@ import { PicAttributes } from "./pic-attributes";
import { ShapeProperties } from "./shape-properties/shape-properties";
export class Pic extends XmlComponent {
- private readonly shapeProperties: ShapeProperties;
-
constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
super("pic:pic");
@@ -19,14 +17,8 @@ export class Pic extends XmlComponent {
}),
);
- this.shapeProperties = new ShapeProperties(transform);
-
this.root.push(new NonVisualPicProperties());
this.root.push(new BlipFill(mediaData));
this.root.push(new ShapeProperties(transform));
}
-
- public setXY(x: number, y: number): void {
- this.shapeProperties.setXY(x, y);
- }
}
diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts
index 55bf8bae0b..f17c8de426 100644
--- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts
+++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/extents/extents.ts
@@ -15,11 +15,4 @@ export class Extents extends XmlComponent {
this.root.push(this.attributes);
}
-
- public setXY(x: number, y: number): void {
- this.attributes.set({
- cx: x,
- cy: y,
- });
- }
}
diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts
index 163af208d6..541f862cd5 100644
--- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts
+++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/form/form.ts
@@ -37,8 +37,4 @@ export class Form extends XmlComponent {
this.root.push(new Offset());
this.root.push(this.extents);
}
-
- public setXY(x: number, y: number): void {
- this.extents.setXY(x, y);
- }
}
diff --git a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts
index 769e242205..2d22b00796 100644
--- a/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts
+++ b/src/file/drawing/inline/graphic/graphic-data/pic/shape-properties/shape-properties.ts
@@ -26,8 +26,4 @@ export class ShapeProperties extends XmlComponent {
// this.root.push(new NoFill());
// this.root.push(new Outline());
}
-
- public setXY(x: number, y: number): void {
- this.form.setXY(x, y);
- }
}
diff --git a/src/file/drawing/inline/graphic/graphic.ts b/src/file/drawing/inline/graphic/graphic.ts
index 3df31e3346..ca0d23a3a5 100644
--- a/src/file/drawing/inline/graphic/graphic.ts
+++ b/src/file/drawing/inline/graphic/graphic.ts
@@ -26,8 +26,4 @@ export class Graphic extends XmlComponent {
this.root.push(this.data);
}
-
- public setXY(x: number, y: number): void {
- this.data.setXY(x, y);
- }
}
diff --git a/src/file/drawing/inline/inline.ts b/src/file/drawing/inline/inline.ts
index 2b124fc524..ee37094b84 100644
--- a/src/file/drawing/inline/inline.ts
+++ b/src/file/drawing/inline/inline.ts
@@ -8,11 +8,25 @@ import { GraphicFrameProperties } from "./../graphic-frame/graphic-frame-propert
import { Graphic } from "./../inline/graphic";
import { InlineAttributes } from "./inline-attributes";
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Inline extends XmlComponent {
private readonly extent: Extent;
private readonly graphic: Graphic;
- constructor(mediaData: IMediaData, private readonly transform: IMediaDataTransformation) {
+ constructor(mediaData: IMediaData, transform: IMediaDataTransformation) {
super("wp:inline");
this.root.push(
@@ -33,12 +47,4 @@ export class Inline extends XmlComponent {
this.root.push(new GraphicFrameProperties());
this.root.push(this.graphic);
}
-
- public scale(factorX: number, factorY: number): void {
- const newX = Math.round(this.transform.emus.x * factorX);
- const newY = Math.round(this.transform.emus.y * factorY);
-
- this.extent.setXY(newX, newY);
- this.graphic.setXY(newX, newY);
- }
}
diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts
index a3cd9fbf65..321a03dc41 100644
--- a/src/file/file.spec.ts
+++ b/src/file/file.spec.ts
@@ -1,11 +1,18 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
+import { sectionMarginDefaults, sectionPageSizeDefaults } from "./document";
import { File } from "./file";
import { Footer, Header } from "./header";
import { Paragraph } from "./paragraph";
+const PAGE_SIZE_DEFAULTS = {
+ "w:h": sectionPageSizeDefaults.HEIGHT,
+ "w:orient": sectionPageSizeDefaults.ORIENTATION,
+ "w:w": sectionPageSizeDefaults.WIDTH,
+};
+
describe("File", () => {
describe("#constructor", () => {
it("should create with correct headers and footers", () => {
@@ -114,23 +121,19 @@ describe("File", () => {
"w:sectPr": [
{
"w:pgSz": {
- _attr: {
- "w:h": 16838,
- "w:orient": "portrait",
- "w:w": 11906,
- },
+ _attr: PAGE_SIZE_DEFAULTS,
},
},
{
"w:pgMar": {
_attr: {
- "w:bottom": 1440,
- "w:footer": 708,
- "w:gutter": 0,
- "w:header": 708,
- "w:left": 1440,
- "w:right": 1440,
- "w:top": 1440,
+ "w:bottom": sectionMarginDefaults.BOTTOM,
+ "w:footer": sectionMarginDefaults.FOOTER,
+ "w:gutter": sectionMarginDefaults.GUTTER,
+ "w:header": sectionMarginDefaults.HEADER,
+ "w:left": sectionMarginDefaults.LEFT,
+ "w:right": sectionMarginDefaults.RIGHT,
+ "w:top": sectionMarginDefaults.TOP,
},
},
},
@@ -139,15 +142,15 @@ describe("File", () => {
_attr: {},
},
},
- {
- "w:cols": {
- _attr: {
- "w:num": 1,
- "w:sep": false,
- "w:space": 708,
- },
- },
- },
+ // {
+ // "w:cols": {
+ // _attr: {
+ // "w:num": 1,
+ // "w:sep": false,
+ // "w:space": 708,
+ // },
+ // },
+ // },
{
"w:docGrid": {
_attr: {
@@ -162,20 +165,6 @@ describe("File", () => {
});
});
- describe("#addTrackRevisionsFeature", () => {
- it("should call the underlying document's add", () => {
- const file = new File({
- features: {
- trackRevisions: true,
- },
- sections: [],
- });
-
- // tslint:disable-next-line: no-unused-expression no-string-literal
- expect(file.Settings["trackRevisions"]).to.exist;
- });
- });
-
describe("#createFootnote", () => {
it("should create footnote", () => {
const wrapper = new File({
diff --git a/src/file/file.ts b/src/file/file.ts
index 66d4d84b51..0e6c9fc352 100644
--- a/src/file/file.ts
+++ b/src/file/file.ts
@@ -3,7 +3,7 @@ import { ContentTypes } from "./content-types/content-types";
import { CoreProperties, IPropertiesOptions } from "./core-properties";
import { CustomProperties } from "./custom-properties";
import { DocumentWrapper } from "./document-wrapper";
-import { FooterReferenceType, HeaderReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties";
+import { HeaderFooterReferenceType, ISectionPropertiesOptions } from "./document/body/section-properties";
import { IFileProperties } from "./file-properties";
import { FooterWrapper, IDocumentFooter } from "./footer-wrapper";
import { FootnotesWrapper } from "./footnotes-wrapper";
@@ -78,6 +78,8 @@ export class File {
this.settings = new Settings({
compatabilityModeVersion: options.compatabilityModeVersion,
evenAndOddHeaders: options.evenAndOddHeaderAndFooters ? true : false,
+ trackRevisions: options.features?.trackRevisions,
+ updateFields: options.features?.updateFields,
});
this.media = fileProperties.template && fileProperties.template.media ? fileProperties.template.media : new Media();
@@ -132,18 +134,6 @@ export class File {
this.footnotesWrapper.View.createFootNote(parseFloat(key), options.footnotes[key].children);
}
}
-
- if (options.features) {
- if (options.features.trackRevisions) {
- this.settings.addTrackRevisions();
- }
- }
- }
-
- public verifyUpdateFields(): void {
- if (this.documentWrapper.View.getTablesOfContents().length) {
- this.settings.addUpdateFields();
- }
}
private addSection({ headers = {}, footers = {}, children, properties }: ISectionOptions): void {
@@ -188,7 +178,7 @@ export class File {
return wrapper;
}
- private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void {
+ private addHeaderToDocument(header: HeaderWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
this.headers.push({ header, type });
this.documentWrapper.Relationships.createRelationship(
header.View.ReferenceId,
@@ -198,7 +188,7 @@ export class File {
this.contentTypes.addHeader(this.headers.length);
}
- private addFooterToDocument(footer: FooterWrapper, type: FooterReferenceType = FooterReferenceType.DEFAULT): void {
+ private addFooterToDocument(footer: FooterWrapper, type: HeaderFooterReferenceType = HeaderFooterReferenceType.DEFAULT): void {
this.footers.push({ footer, type });
this.documentWrapper.Relationships.createRelationship(
footer.View.ReferenceId,
diff --git a/src/file/footer-wrapper.ts b/src/file/footer-wrapper.ts
index e16a72e974..34162320c0 100644
--- a/src/file/footer-wrapper.ts
+++ b/src/file/footer-wrapper.ts
@@ -1,6 +1,6 @@
import { XmlComponent } from "file/xml-components";
-import { FooterReferenceType } from "./document";
+import { HeaderFooterReferenceType } from "./document";
import { IViewWrapper } from "./document-wrapper";
import { Footer } from "./footer/footer";
import { Media } from "./media";
@@ -10,7 +10,7 @@ import { Table } from "./table";
export interface IDocumentFooter {
readonly footer: FooterWrapper;
- readonly type: FooterReferenceType;
+ readonly type: HeaderFooterReferenceType;
}
export class FooterWrapper implements IViewWrapper {
diff --git a/src/file/footnotes/footnote/run/reference-run.ts b/src/file/footnotes/footnote/run/reference-run.ts
index 3bfd772f50..c355bb17a3 100644
--- a/src/file/footnotes/footnote/run/reference-run.ts
+++ b/src/file/footnotes/footnote/run/reference-run.ts
@@ -1,5 +1,4 @@
import { Run } from "file/paragraph/run";
-import { Style } from "file/paragraph/run/style";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export class FootNoteReferenceRunAttributes extends XmlAttributeComponent<{
@@ -24,9 +23,7 @@ export class FootnoteReference extends XmlComponent {
export class FootnoteReferenceRun extends Run {
constructor(id: number) {
- super({});
-
- this.properties.push(new Style("FootnoteReference"));
+ super({ style: "FootnoteReference" });
this.root.push(new FootnoteReference(id));
}
diff --git a/src/file/header-wrapper.ts b/src/file/header-wrapper.ts
index 945a9d674a..40fbd7bb1a 100644
--- a/src/file/header-wrapper.ts
+++ b/src/file/header-wrapper.ts
@@ -1,6 +1,6 @@
import { XmlComponent } from "file/xml-components";
-import { HeaderReferenceType } from "./document";
+import { HeaderFooterReferenceType } from "./document";
import { IViewWrapper } from "./document-wrapper";
import { Header } from "./header/header";
import { Media } from "./media";
@@ -10,7 +10,7 @@ import { Table } from "./table";
export interface IDocumentHeader {
readonly header: HeaderWrapper;
- readonly type: HeaderReferenceType;
+ readonly type: HeaderFooterReferenceType;
}
export class HeaderWrapper implements IViewWrapper {
diff --git a/src/file/index.ts b/src/file/index.ts
index 63761d4555..1ab2a79cfd 100644
--- a/src/file/index.ts
+++ b/src/file/index.ts
@@ -6,6 +6,7 @@ export * from "./numbering";
export * from "./media";
export * from "./drawing";
export * from "./document";
+export * from "./shading";
export * from "./styles";
export * from "./table-of-contents";
export * from "./xml-components";
@@ -15,3 +16,6 @@ export * from "./header";
export * from "./footnotes";
export * from "./track-revision";
export * from "./shared";
+export * from "./border";
+export * from "./values";
+export * from "./vertical-align";
diff --git a/src/file/numbering/abstract-numbering.spec.ts b/src/file/numbering/abstract-numbering.spec.ts
index b2d9f19bc1..8ab0845ed8 100644
--- a/src/file/numbering/abstract-numbering.spec.ts
+++ b/src/file/numbering/abstract-numbering.spec.ts
@@ -5,7 +5,7 @@ import { EMPTY_OBJECT } from "file/xml-components";
import { AlignmentType, EmphasisMarkType, TabStopPosition } from "../paragraph";
import { UnderlineType } from "../paragraph/run/underline";
-import { ShadingType } from "../table";
+import { ShadingType } from "../shading";
import { AbstractNumbering } from "./abstract-numbering";
import { LevelFormat, LevelSuffix } from "./level";
@@ -351,7 +351,7 @@ describe("AbstractNumbering", () => {
]);
const tree = new Formatter().format(abstractNumbering);
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
- "w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:smallCaps": {} }],
});
});
@@ -370,7 +370,7 @@ describe("AbstractNumbering", () => {
]);
const tree = new Formatter().format(abstractNumbering);
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
- "w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:caps": {} }],
});
});
@@ -390,7 +390,7 @@ describe("AbstractNumbering", () => {
const tree = new Formatter().format(abstractNumbering);
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
- "w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:strike": {} }],
});
});
@@ -409,7 +409,7 @@ describe("AbstractNumbering", () => {
]);
const tree = new Formatter().format(abstractNumbering);
expect(tree["w:abstractNum"][2]["w:lvl"]).to.include({
- "w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:dstrike": {} }],
});
});
@@ -515,17 +515,17 @@ describe("AbstractNumbering", () => {
const boldTests = [
{
bold: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: false,
- expected: [{ "w:b": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }],
},
];
boldTests.forEach(({ bold, boldComplexScript, expected }) => {
@@ -548,17 +548,17 @@ describe("AbstractNumbering", () => {
const italicsTests = [
{
italics: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: false,
- expected: [{ "w:i": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }],
},
];
italicsTests.forEach(({ italics, italicsComplexScript, expected }) => {
@@ -617,37 +617,13 @@ describe("AbstractNumbering", () => {
});
const shadingTests = [
- {
- shadow: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
{
shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
+ type: ShadingType.DIAGONAL_STRIPE,
+ fill: "006622",
+ color: "0000FF",
},
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
+ expected: [{ "w:shd": { _attr: { "w:val": "diagStripe", "w:fill": "006622", "w:color": "0000FF" } } }],
},
{
shading: {
@@ -658,15 +634,15 @@ describe("AbstractNumbering", () => {
expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
},
];
- shadingTests.forEach(({ shadow, shading, expected }) => {
- it("#shadow correctly", () => {
+ shadingTests.forEach(({ shading, expected }) => {
+ it("#shade correctly", () => {
const abstractNumbering = new AbstractNumbering(1, [
{
level: 0,
format: LevelFormat.LOWER_ROMAN,
text: "%0.",
style: {
- run: { shadow, shading },
+ run: { shading },
},
},
]);
diff --git a/src/file/numbering/abstract-numbering.ts b/src/file/numbering/abstract-numbering.ts
index 363d233ac9..6c4af129c3 100644
--- a/src/file/numbering/abstract-numbering.ts
+++ b/src/file/numbering/abstract-numbering.ts
@@ -1,8 +1,24 @@
+import { decimalNumber } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { ILevelsOptions, Level } from "./level";
import { MultiLevelType } from "./multi-level-type";
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-docx/cbddeff8-01aa-4486-a48e-6a83dede4f13
class AbstractNumberingAttributes extends XmlAttributeComponent<{
readonly abstractNumId: number;
readonly restartNumberingAfterBreak: number;
@@ -20,7 +36,7 @@ export class AbstractNumbering extends XmlComponent {
super("w:abstractNum");
this.root.push(
new AbstractNumberingAttributes({
- abstractNumId: id,
+ abstractNumId: decimalNumber(id),
restartNumberingAfterBreak: 0,
}),
);
diff --git a/src/file/numbering/level.ts b/src/file/numbering/level.ts
index d189e24e01..93fcbe6f67 100644
--- a/src/file/numbering/level.ts
+++ b/src/file/numbering/level.ts
@@ -1,5 +1,6 @@
// http://officeopenxml.com/WPnumbering-numFmt.php
-import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { decimalNumber } from "file/values";
+import { Attributes, NumberValueElement, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { AlignmentType } from "../paragraph/formatting";
import { IParagraphStylePropertiesOptions, ParagraphProperties } from "../paragraph/properties";
import { IRunStylePropertiesOptions, RunProperties } from "../paragraph/run/properties";
@@ -31,17 +32,10 @@ class LevelAttributes extends XmlAttributeComponent<{
};
}
-class Start extends XmlComponent {
- constructor(value: number) {
- super("w:start");
- this.root.push(
- new Attributes({
- val: value,
- }),
- );
- }
-}
-
+//
+//
+//
+//
class NumberFormat extends XmlComponent {
constructor(value: string) {
super("w:numFmt");
@@ -53,6 +47,10 @@ class NumberFormat extends XmlComponent {
}
}
+//
+//
+//
+//
class LevelText extends XmlComponent {
constructor(value: string) {
super("w:lvlText");
@@ -94,6 +92,16 @@ export interface ILevelsOptions {
};
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
class Suffix extends XmlComponent {
constructor(value: LevelSuffix) {
super("w:suff");
@@ -105,6 +113,25 @@ class Suffix extends XmlComponent {
}
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class LevelBase extends XmlComponent {
private readonly paragraphProperties: ParagraphProperties;
private readonly runProperties: RunProperties;
@@ -112,7 +139,7 @@ export class LevelBase extends XmlComponent {
constructor({ level, format, text, alignment = AlignmentType.START, start = 1, style, suffix }: ILevelsOptions) {
super("w:lvl");
- this.root.push(new Start(start));
+ this.root.push(new NumberValueElement("w:start", decimalNumber(start)));
if (format) {
this.root.push(new NumberFormat(format));
@@ -136,7 +163,7 @@ export class LevelBase extends XmlComponent {
this.root.push(
new LevelAttributes({
- ilvl: level,
+ ilvl: decimalNumber(level),
tentative: 1,
}),
);
diff --git a/src/file/numbering/multi-level-type.ts b/src/file/numbering/multi-level-type.ts
index c73ebec3cf..c2d53bb8cf 100644
--- a/src/file/numbering/multi-level-type.ts
+++ b/src/file/numbering/multi-level-type.ts
@@ -1,5 +1,19 @@
import { Attributes, XmlComponent } from "file/xml-components";
+//
+// ...
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class MultiLevelType extends XmlComponent {
constructor(value: string) {
super("w:multiLevelType");
diff --git a/src/file/numbering/num.ts b/src/file/numbering/num.ts
index 526d0f1b9f..87cd399a96 100644
--- a/src/file/numbering/num.ts
+++ b/src/file/numbering/num.ts
@@ -1,3 +1,4 @@
+import { decimalNumber } from "file/values";
import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-components";
class AbstractNumId extends XmlComponent {
@@ -28,6 +29,17 @@ export interface IConcreteNumberingOptions {
};
}
+//
+// ...
+//
+
+//
+//
+//
+//
+//
+//
+//
export class ConcreteNumbering extends XmlComponent {
public readonly numId: number;
public readonly reference: string;
@@ -42,11 +54,11 @@ export class ConcreteNumbering extends XmlComponent {
this.root.push(
new NumAttributes({
- numId: options.numId,
+ numId: decimalNumber(options.numId),
}),
);
- this.root.push(new AbstractNumId(options.abstractNumId));
+ this.root.push(new AbstractNumId(decimalNumber(options.abstractNumId)));
if (options.overrideLevel) {
this.root.push(new LevelOverride(options.overrideLevel.num, options.overrideLevel.start));
diff --git a/src/file/numbering/numbering.ts b/src/file/numbering/numbering.ts
index 7798d373d6..8f37b386c5 100644
--- a/src/file/numbering/numbering.ts
+++ b/src/file/numbering/numbering.ts
@@ -16,6 +16,16 @@ export interface INumberingOptions {
}[];
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Numbering extends XmlComponent {
private readonly abstractNumberingMap = new Map();
private readonly concreteNumberingMap = new Map();
@@ -149,7 +159,7 @@ export class Numbering extends XmlComponent {
this.concreteNumberingMap.set(
"default-bullet-numbering",
new ConcreteNumbering({
- numId: 0,
+ numId: 1,
abstractNumId: abstractNumbering.id,
reference: "default-bullet-numbering",
instance: 0,
diff --git a/src/file/paragraph/formatting/bidirectional.spec.ts b/src/file/paragraph/formatting/bidirectional.spec.ts
deleted file mode 100644
index a197ada54e..0000000000
--- a/src/file/paragraph/formatting/bidirectional.spec.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { Bidirectional } from "./bidirectional";
-
-describe("Bidirectional", () => {
- it("should create", () => {
- const bidirectional = new Bidirectional();
- const tree = new Formatter().format(bidirectional);
- expect(tree).to.deep.equal({
- "w:bidi": {},
- });
- });
-});
diff --git a/src/file/paragraph/formatting/bidirectional.ts b/src/file/paragraph/formatting/bidirectional.ts
deleted file mode 100644
index 4083247e78..0000000000
--- a/src/file/paragraph/formatting/bidirectional.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-
-export class Bidirectional extends XmlComponent {
- constructor() {
- super("w:bidi");
- }
-}
diff --git a/src/file/paragraph/formatting/border-attributes.ts b/src/file/paragraph/formatting/border-attributes.ts
deleted file mode 100644
index 304128426b..0000000000
--- a/src/file/paragraph/formatting/border-attributes.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { XmlAttributeComponent } from "file/xml-components";
-
-export class BorderAttributes extends XmlAttributeComponent<{
- readonly color: string;
- readonly space: number;
- readonly val: string;
- readonly sz: number;
-}> {
- protected readonly xmlKeys = {
- val: "w:val",
- color: "w:color",
- space: "w:space",
- sz: "w:sz",
- };
-}
diff --git a/src/file/paragraph/formatting/border.spec.ts b/src/file/paragraph/formatting/border.spec.ts
index 6e89ffcfc8..33e026f7c4 100644
--- a/src/file/paragraph/formatting/border.spec.ts
+++ b/src/file/paragraph/formatting/border.spec.ts
@@ -2,6 +2,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
+import { BorderStyle } from "file/border";
import { Border, ThematicBreak } from "./border";
describe("Border", () => {
@@ -9,27 +10,27 @@ describe("Border", () => {
it("should create", () => {
const border = new Border({
top: {
- color: "red",
+ color: "FF0000",
space: 1,
- value: "test",
+ style: BorderStyle.WAVE,
size: 2,
},
bottom: {
- color: "red",
+ color: "FF0000",
space: 3,
- value: "test",
+ style: BorderStyle.WAVE,
size: 4,
},
left: {
- color: "red",
+ color: "FF0000",
space: 5,
- value: "test",
+ style: BorderStyle.WAVE,
size: 6,
},
right: {
- color: "red",
+ color: "FF0000",
space: 7,
- value: "test",
+ style: BorderStyle.WAVE,
size: 8,
},
});
@@ -41,46 +42,51 @@ describe("Border", () => {
{
"w:top": {
_attr: {
- "w:color": "red",
+ "w:color": "FF0000",
"w:space": 1,
"w:sz": 2,
- "w:val": "test",
+ "w:val": "wave",
},
},
},
{
"w:bottom": {
_attr: {
- "w:color": "red",
+ "w:color": "FF0000",
"w:space": 3,
"w:sz": 4,
- "w:val": "test",
+ "w:val": "wave",
},
},
},
{
"w:left": {
_attr: {
- "w:color": "red",
+ "w:color": "FF0000",
"w:space": 5,
"w:sz": 6,
- "w:val": "test",
+ "w:val": "wave",
},
},
},
{
"w:right": {
_attr: {
- "w:color": "red",
+ "w:color": "FF0000",
"w:space": 7,
"w:sz": 8,
- "w:val": "test",
+ "w:val": "wave",
},
},
},
],
});
});
+
+ it("should not add empty borders element if there are no borders defined", () => {
+ const tb = new Border({});
+ expect(() => new Formatter().format(tb)).to.throw();
+ });
});
});
diff --git a/src/file/paragraph/formatting/border.ts b/src/file/paragraph/formatting/border.ts
index 9fdb9b65c3..b84b24df99 100644
--- a/src/file/paragraph/formatting/border.ts
+++ b/src/file/paragraph/formatting/border.ts
@@ -1,57 +1,32 @@
// http://officeopenxml.com/WPborders.php
-import { XmlComponent } from "file/xml-components";
-import { BorderAttributes } from "./border-attributes";
+import { BorderElement, BorderStyle, IBorderOptions } from "file/border";
+import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components";
-interface IBorderPropertyOptions {
- readonly color: string;
- readonly space: number;
- readonly value: string;
- readonly size: number;
+export interface IBordersOptions {
+ readonly top?: IBorderOptions;
+ readonly bottom?: IBorderOptions;
+ readonly left?: IBorderOptions;
+ readonly right?: IBorderOptions;
}
-export interface IBorderOptions {
- readonly top?: IBorderPropertyOptions;
- readonly bottom?: IBorderPropertyOptions;
- readonly left?: IBorderPropertyOptions;
- readonly right?: IBorderPropertyOptions;
-}
-
-class BorderProperty extends XmlComponent {
- constructor(rootKey: string, options: IBorderPropertyOptions = { color: "auto", space: 1, value: "single", size: 6 }) {
- super(rootKey);
-
- const attrs = new BorderAttributes({
- color: options.color,
- space: options.space,
- val: options.value,
- sz: options.size,
- });
- this.root.push(attrs);
- }
-}
-
-export class Border extends XmlComponent {
- constructor(options: IBorderOptions) {
+export class Border extends IgnoreIfEmptyXmlComponent {
+ constructor(options: IBordersOptions) {
super("w:pBdr");
- if (options.top !== undefined) {
- const borderProperty = new BorderProperty("w:top", options.top);
- this.root.push(borderProperty);
+ if (options.top) {
+ this.root.push(new BorderElement("w:top", options.top));
}
- if (options.bottom !== undefined) {
- const borderProperty = new BorderProperty("w:bottom", options.bottom);
- this.root.push(borderProperty);
+ if (options.bottom) {
+ this.root.push(new BorderElement("w:bottom", options.bottom));
}
- if (options.left !== undefined) {
- const borderProperty = new BorderProperty("w:left", options.left);
- this.root.push(borderProperty);
+ if (options.left) {
+ this.root.push(new BorderElement("w:left", options.left));
}
- if (options.right !== undefined) {
- const borderProperty = new BorderProperty("w:right", options.right);
- this.root.push(borderProperty);
+ if (options.right) {
+ this.root.push(new BorderElement("w:right", options.right));
}
}
}
@@ -59,10 +34,10 @@ export class Border extends XmlComponent {
export class ThematicBreak extends XmlComponent {
constructor() {
super("w:pBdr");
- const bottom = new BorderProperty("w:bottom", {
+ const bottom = new BorderElement("w:bottom", {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
});
this.root.push(bottom);
diff --git a/src/file/paragraph/formatting/indent.ts b/src/file/paragraph/formatting/indent.ts
index 3aad7d4e8a..aad272fa7c 100644
--- a/src/file/paragraph/formatting/indent.ts
+++ b/src/file/paragraph/formatting/indent.ts
@@ -1,29 +1,57 @@
// http://officeopenxml.com/WPindentation.php
+import { signedTwipsMeasureValue, twipsMeasureValue } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export interface IIndentAttributesProperties {
- readonly left?: number;
- readonly hanging?: number;
- readonly firstLine?: number;
- readonly start?: number;
- readonly end?: number;
- readonly right?: number;
+ readonly start?: number | string;
+ readonly end?: number | string;
+ readonly left?: number | string;
+ readonly right?: number | string;
+ readonly hanging?: number | string;
+ readonly firstLine?: number | string;
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
class IndentAttributes extends XmlAttributeComponent {
protected readonly xmlKeys = {
- left: "w:left",
- hanging: "w:hanging",
- firstLine: "w:firstLine",
start: "w:start",
end: "w:end",
- right: "w:end", // alias
+ left: "w:left",
+ right: "w:right",
+ hanging: "w:hanging",
+ firstLine: "w:firstLine",
};
}
+//
+//
+// ...
+//
export class Indent extends XmlComponent {
- constructor(attrs: IIndentAttributesProperties) {
+ constructor({ start, end, left, right, hanging, firstLine }: IIndentAttributesProperties) {
super("w:ind");
- this.root.push(new IndentAttributes(attrs));
+ this.root.push(
+ new IndentAttributes({
+ start: start === undefined ? undefined : signedTwipsMeasureValue(start),
+ end: end === undefined ? undefined : signedTwipsMeasureValue(end),
+ left: left === undefined ? undefined : signedTwipsMeasureValue(left),
+ right: right === undefined ? undefined : signedTwipsMeasureValue(right),
+ hanging: hanging === undefined ? undefined : twipsMeasureValue(hanging),
+ firstLine: firstLine === undefined ? undefined : twipsMeasureValue(firstLine),
+ }),
+ );
}
}
diff --git a/src/file/paragraph/formatting/index.ts b/src/file/paragraph/formatting/index.ts
index 2c8829ee9d..0d83804dc6 100644
--- a/src/file/paragraph/formatting/index.ts
+++ b/src/file/paragraph/formatting/index.ts
@@ -1,7 +1,6 @@
export * from "./alignment";
export * from "./border";
export * from "./indent";
-export * from "./keep";
export * from "./page-break";
export * from "./spacing";
export * from "./style";
diff --git a/src/file/paragraph/formatting/keep.ts b/src/file/paragraph/formatting/keep.ts
deleted file mode 100644
index 5f1abb53f8..0000000000
--- a/src/file/paragraph/formatting/keep.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-
-export class KeepLines extends XmlComponent {
- constructor() {
- super("w:keepLines");
- }
-}
-
-export class KeepNext extends XmlComponent {
- constructor() {
- super("w:keepNext");
- }
-}
diff --git a/src/file/paragraph/formatting/spacing.spec.ts b/src/file/paragraph/formatting/spacing.spec.ts
index 8241fb282c..09d88dc31c 100644
--- a/src/file/paragraph/formatting/spacing.spec.ts
+++ b/src/file/paragraph/formatting/spacing.spec.ts
@@ -2,7 +2,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { ContextualSpacing, Spacing } from "./spacing";
+import { Spacing } from "./spacing";
describe("Spacing", () => {
describe("#constructor", () => {
@@ -23,23 +23,3 @@ describe("Spacing", () => {
});
});
});
-
-describe("ContextualSpacing", () => {
- describe("#constructor", () => {
- it("should create", () => {
- const spacing = new ContextualSpacing(true);
- const tree = new Formatter().format(spacing);
- expect(tree).to.deep.equal({
- "w:contextualSpacing": { _attr: { "w:val": 1 } },
- });
- });
-
- it("should create with value of 0 if param is false", () => {
- const spacing = new ContextualSpacing(false);
- const tree = new Formatter().format(spacing);
- expect(tree).to.deep.equal({
- "w:contextualSpacing": { _attr: { "w:val": 0 } },
- });
- });
- });
-});
diff --git a/src/file/paragraph/formatting/spacing.ts b/src/file/paragraph/formatting/spacing.ts
index 7eac5cea72..bac1a17049 100644
--- a/src/file/paragraph/formatting/spacing.ts
+++ b/src/file/paragraph/formatting/spacing.ts
@@ -1,5 +1,5 @@
// http://officeopenxml.com/WPspacing.php
-import { Attributes, XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export enum LineRuleType {
AT_LEAST = "atLeast",
@@ -30,14 +30,3 @@ export class Spacing extends XmlComponent {
this.root.push(new SpacingAttributes(options));
}
}
-
-export class ContextualSpacing extends XmlComponent {
- constructor(value: boolean) {
- super("w:contextualSpacing");
- this.root.push(
- new Attributes({
- val: value === false ? 0 : 1,
- }),
- );
- }
-}
diff --git a/src/file/paragraph/formatting/widow-control.spec.ts b/src/file/paragraph/formatting/widow-control.spec.ts
deleted file mode 100644
index e6e50fb13c..0000000000
--- a/src/file/paragraph/formatting/widow-control.spec.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { WidowControl } from "./widow-control";
-
-describe("WidowControl", () => {
- it("should create", () => {
- const widowControl = new WidowControl(true);
- const tree = new Formatter().format(widowControl);
-
- expect(tree).to.deep.equal({
- "w:widowControl": {
- _attr: {
- "w:val": true,
- },
- },
- });
- });
-});
diff --git a/src/file/paragraph/formatting/widow-control.ts b/src/file/paragraph/formatting/widow-control.ts
deleted file mode 100644
index cbfc125564..0000000000
--- a/src/file/paragraph/formatting/widow-control.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// http://www.datypic.com/sc/ooxml/e-w_widowControl-1.html
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export class WidowControlAttributes extends XmlAttributeComponent<{ readonly val: boolean }> {
- protected readonly xmlKeys = { val: "w:val" };
-}
-
-export class WidowControl extends XmlComponent {
- constructor(value: boolean) {
- super("w:widowControl");
- this.root.push(new WidowControlAttributes({ val: value }));
- }
-}
diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts
index 5b2f95ed58..d898777b12 100644
--- a/src/file/paragraph/paragraph.spec.ts
+++ b/src/file/paragraph/paragraph.spec.ts
@@ -2,13 +2,15 @@ import { assert, expect } from "chai";
import { SinonStub, stub } from "sinon";
import * as convenienceFunctions from "convenience-functions";
+
import { Formatter } from "export/formatter";
+import { BorderStyle } from "file/border";
import { EMPTY_OBJECT } from "file/xml-components";
import { IViewWrapper } from "../document-wrapper";
import { File } from "../file";
+import { ShadingType } from "../shading";
import { HorizontalPositionAlign, VerticalPositionAlign } from "../shared";
-import { ShadingType } from "../table/shading";
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
import { FrameAnchorType } from "./frame";
import { Bookmark, ExternalHyperlink } from "./links";
@@ -414,7 +416,7 @@ describe("Paragraph", () => {
});
describe("#contextualSpacing()", () => {
- it("should add contextualSpacing to JSON, and set 1 if true", () => {
+ it("should add contextualSpacing", () => {
const paragraph = new Paragraph({
contextualSpacing: true,
});
@@ -422,7 +424,20 @@ describe("Paragraph", () => {
expect(tree).to.deep.equal({
"w:p": [
{
- "w:pPr": [{ "w:contextualSpacing": { _attr: { "w:val": 1 } } }],
+ "w:pPr": [{ "w:contextualSpacing": {} }],
+ },
+ ],
+ });
+ });
+ it("should remove contextualSpacing", () => {
+ const paragraph = new Paragraph({
+ contextualSpacing: false,
+ });
+ const tree = new Formatter().format(paragraph);
+ expect(tree).to.deep.equal({
+ "w:p": [
+ {
+ "w:pPr": [{ "w:contextualSpacing": { _attr: { "w:val": false } } }],
},
],
});
@@ -467,13 +482,13 @@ describe("Paragraph", () => {
left: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
right: {
color: "auto",
space: 1,
- value: "single",
+ style: BorderStyle.SINGLE,
size: 6,
},
},
diff --git a/src/file/paragraph/properties.spec.ts b/src/file/paragraph/properties.spec.ts
index deb7f416c2..e8961ceea6 100644
--- a/src/file/paragraph/properties.spec.ts
+++ b/src/file/paragraph/properties.spec.ts
@@ -86,11 +86,7 @@ describe("ParagraphProperties", () => {
expect(tree).to.deep.equal({
"w:pPr": [
{
- "w:widowControl": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:widowControl": {},
},
],
});
diff --git a/src/file/paragraph/properties.ts b/src/file/paragraph/properties.ts
index 6a7fe283fd..d3cb2081e9 100644
--- a/src/file/paragraph/properties.ts
+++ b/src/file/paragraph/properties.ts
@@ -1,21 +1,17 @@
// http://officeopenxml.com/WPparagraphProperties.php
-import { IContext, IgnoreIfEmptyXmlComponent, IXmlableObject, XmlComponent } from "file/xml-components";
+import { IContext, IgnoreIfEmptyXmlComponent, IXmlableObject, OnOffElement, XmlComponent } from "file/xml-components";
import { DocumentWrapper } from "../document-wrapper";
-import { ShadingType } from "../table/shading";
+import { IShadingAttributesProperties, Shading } from "../shading";
import { Alignment, AlignmentType } from "./formatting/alignment";
-import { Bidirectional } from "./formatting/bidirectional";
-import { Border, IBorderOptions, ThematicBreak } from "./formatting/border";
+import { Border, IBordersOptions, ThematicBreak } from "./formatting/border";
import { IIndentAttributesProperties, Indent } from "./formatting/indent";
-import { KeepLines, KeepNext } from "./formatting/keep";
import { PageBreakBefore } from "./formatting/page-break";
-import { ContextualSpacing, ISpacingProperties, Spacing } from "./formatting/spacing";
+import { ISpacingProperties, Spacing } from "./formatting/spacing";
import { HeadingLevel, Style } from "./formatting/style";
import { LeaderType, TabStop, TabStopPosition, TabStopType } from "./formatting/tab-stop";
import { NumberProperties } from "./formatting/unordered-list";
-import { WidowControl } from "./formatting/widow-control";
import { FrameProperties, IFrameOptions } from "./frame/frame-properties";
import { OutlineLevel } from "./links";
-import { Shading } from "./run/formatting";
export interface IParagraphStylePropertiesOptions {
readonly alignment?: AlignmentType;
@@ -31,7 +27,7 @@ export interface IParagraphStylePropertiesOptions {
}
export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions {
- readonly border?: IBorderOptions;
+ readonly border?: IBordersOptions;
readonly heading?: HeadingLevel;
readonly bidirectional?: boolean;
readonly pageBreakBefore?: boolean;
@@ -50,11 +46,7 @@ export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOp
readonly instance?: number;
readonly custom?: boolean;
};
- readonly shading?: {
- readonly type: ShadingType;
- readonly fill: string;
- readonly color: string;
- };
+ readonly shading?: IShadingAttributesProperties;
readonly widowControl?: boolean;
readonly frame?: IFrameOptions;
}
@@ -89,12 +81,12 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
this.push(new Style(options.style));
}
- if (options.keepNext) {
- this.push(new KeepNext());
+ if (options.keepNext !== undefined) {
+ this.push(new OnOffElement("w:keepNext", options.keepNext));
}
- if (options.keepLines) {
- this.push(new KeepLines());
+ if (options.keepLines !== undefined) {
+ this.push(new OnOffElement("w:keepLines", options.keepLines));
}
if (options.pageBreakBefore) {
@@ -105,8 +97,8 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
this.push(new FrameProperties(options.frame));
}
- if (options.widowControl) {
- this.push(new WidowControl(options.widowControl));
+ if (options.widowControl !== undefined) {
+ this.push(new OnOffElement("w:widowControl", options.widowControl));
}
if (options.bullet) {
@@ -131,7 +123,7 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
}
if (options.shading) {
- this.push(new Shading(options.shading.type, options.shading.fill, options.shading.color));
+ this.push(new Shading(options.shading));
}
if (options.rightTabStop) {
@@ -148,8 +140,8 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
this.push(new TabStop(TabStopType.LEFT, options.leftTabStop));
}
- if (options.bidirectional) {
- this.push(new Bidirectional());
+ if (options.bidirectional !== undefined) {
+ this.push(new OnOffElement("w:bidi", options.contextualSpacing));
}
if (options.spacing) {
@@ -160,8 +152,8 @@ export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
this.push(new Indent(options.indent));
}
- if (options.contextualSpacing) {
- this.push(new ContextualSpacing(options.contextualSpacing));
+ if (options.contextualSpacing !== undefined) {
+ this.push(new OnOffElement("w:contextualSpacing", options.contextualSpacing));
}
if (options.alignment) {
diff --git a/src/file/paragraph/run/break.ts b/src/file/paragraph/run/break.ts
index 293071773b..0d0eac8c8c 100644
--- a/src/file/paragraph/run/break.ts
+++ b/src/file/paragraph/run/break.ts
@@ -1,6 +1,30 @@
// http://officeopenxml.com/WPtextSpecialContent-break.php
import { XmlComponent } from "file/xml-components";
+//
+// ...
+//
+
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Break extends XmlComponent {
constructor() {
super("w:br");
diff --git a/src/file/paragraph/run/formatting.spec.ts b/src/file/paragraph/run/formatting.spec.ts
index 43a1de1fd0..cf590d8cf6 100644
--- a/src/file/paragraph/run/formatting.spec.ts
+++ b/src/file/paragraph/run/formatting.spec.ts
@@ -2,18 +2,35 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { Bold } from "./formatting";
+import { CharacterSpacing, Color } from "./formatting";
-describe("Bold", () => {
+describe("CharacterSpacing", () => {
describe("#constructor()", () => {
it("should create", () => {
- const currentBold = new Bold();
+ const element = new CharacterSpacing(32);
- const tree = new Formatter().format(currentBold);
+ const tree = new Formatter().format(element);
expect(tree).to.deep.equal({
- "w:b": {
+ "w:spacing": {
_attr: {
- "w:val": true,
+ "w:val": 32,
+ },
+ },
+ });
+ });
+ });
+});
+
+describe("Color", () => {
+ describe("#constructor()", () => {
+ it("should create", () => {
+ const element = new Color("#FFFFFF");
+
+ const tree = new Formatter().format(element);
+ expect(tree).to.deep.equal({
+ "w:color": {
+ _attr: {
+ "w:val": "FFFFFF",
},
},
});
diff --git a/src/file/paragraph/run/formatting.ts b/src/file/paragraph/run/formatting.ts
index 07e401a91e..5f735fdfbb 100644
--- a/src/file/paragraph/run/formatting.ts
+++ b/src/file/paragraph/run/formatting.ts
@@ -1,170 +1,55 @@
+import { hexColorValue, signedTwipsMeasureValue } from "file/values";
import { Attributes, XmlComponent } from "file/xml-components";
-export class Bold extends XmlComponent {
- constructor() {
- super("w:b");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class BoldComplexScript extends XmlComponent {
- constructor() {
- super("w:bCs");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
export class CharacterSpacing extends XmlComponent {
- constructor(value: number) {
+ constructor(value: number | string) {
super("w:spacing");
this.root.push(
new Attributes({
- val: value,
- }),
- );
- }
-}
-
-export class Italics extends XmlComponent {
- constructor() {
- super("w:i");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class ItalicsComplexScript extends XmlComponent {
- constructor() {
- super("w:iCs");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class Caps extends XmlComponent {
- constructor() {
- super("w:caps");
- this.root.push(
- new Attributes({
- val: true,
+ val: signedTwipsMeasureValue(value),
}),
);
}
}
+//
+//
+//
+//
+//
+//
export class Color extends XmlComponent {
constructor(color: string) {
super("w:color");
this.root.push(
new Attributes({
- val: color,
- }),
- );
- }
-}
-
-export class DoubleStrike extends XmlComponent {
- constructor() {
- super("w:dstrike");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class Emboss extends XmlComponent {
- constructor() {
- super("w:emboss");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class Imprint extends XmlComponent {
- constructor() {
- super("w:imprint");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class SmallCaps extends XmlComponent {
- constructor() {
- super("w:smallCaps");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class Strike extends XmlComponent {
- constructor() {
- super("w:strike");
- this.root.push(
- new Attributes({
- val: true,
- }),
- );
- }
-}
-
-export class Size extends XmlComponent {
- constructor(size: number) {
- super("w:sz");
- this.root.push(
- new Attributes({
- val: size,
- }),
- );
- }
-}
-
-export class SizeComplexScript extends XmlComponent {
- constructor(size: number) {
- super("w:szCs");
- this.root.push(
- new Attributes({
- val: size,
- }),
- );
- }
-}
-
-export class RightToLeft extends XmlComponent {
- constructor() {
- super("w:rtl");
- this.root.push(
- new Attributes({
- val: true,
+ val: hexColorValue(color),
}),
);
}
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class Highlight extends XmlComponent {
constructor(color: string) {
super("w:highlight");
@@ -186,16 +71,3 @@ export class HighlightComplexScript extends XmlComponent {
);
}
}
-
-export class Shading extends XmlComponent {
- constructor(value: string, fill: string, color: string) {
- super("w:shd");
- this.root.push(
- new Attributes({
- val: value,
- fill: fill,
- color: color,
- }),
- );
- }
-}
diff --git a/src/file/paragraph/run/properties.ts b/src/file/paragraph/run/properties.ts
index fa61e4d9d7..3c47099b85 100644
--- a/src/file/paragraph/run/properties.ts
+++ b/src/file/paragraph/run/properties.ts
@@ -1,29 +1,9 @@
-import { ShadingType } from "file/table";
-import { IgnoreIfEmptyXmlComponent, XmlComponent } from "file/xml-components";
+import { IShadingAttributesProperties, Shading } from "file/shading";
+import { HpsMeasureElement, IgnoreIfEmptyXmlComponent, OnOffElement, StringValueElement, XmlComponent } from "file/xml-components";
import { EmphasisMark, EmphasisMarkType } from "./emphasis-mark";
-import {
- Bold,
- BoldComplexScript,
- Caps,
- CharacterSpacing,
- Color,
- DoubleStrike,
- Emboss,
- Highlight,
- HighlightComplexScript,
- Imprint,
- Italics,
- ItalicsComplexScript,
- RightToLeft,
- Shading,
- Size,
- SizeComplexScript,
- SmallCaps,
- Strike,
-} from "./formatting";
+import { CharacterSpacing, Color, Highlight, HighlightComplexScript } from "./formatting";
import { IFontAttributesProperties, RunFonts } from "./run-fonts";
import { SubScript, SuperScript } from "./script";
-import { Style } from "./style";
import { Underline, UnderlineType } from "./underline";
interface IFontOptions {
@@ -44,8 +24,8 @@ export interface IRunStylePropertiesOptions {
readonly type?: EmphasisMarkType;
};
readonly color?: string;
- readonly size?: number;
- readonly sizeComplexScript?: boolean | number;
+ readonly size?: number | string;
+ readonly sizeComplexScript?: boolean | number | string;
readonly rightToLeft?: boolean;
readonly smallCaps?: boolean;
readonly allCaps?: boolean;
@@ -57,12 +37,7 @@ export interface IRunStylePropertiesOptions {
readonly highlight?: string;
readonly highlightComplexScript?: boolean | string;
readonly characterSpacing?: number;
- readonly shading?: {
- readonly type: ShadingType;
- readonly fill: string;
- readonly color: string;
- };
- readonly shadow?: IRunStylePropertiesOptions["shading"];
+ readonly shading?: IShadingAttributesProperties;
readonly emboss?: boolean;
readonly imprint?: boolean;
}
@@ -71,6 +46,49 @@ export interface IRunPropertiesOptions extends IRunStylePropertiesOptions {
readonly style?: string;
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export class RunProperties extends IgnoreIfEmptyXmlComponent {
constructor(options?: IRunPropertiesOptions) {
super("w:rPr");
@@ -79,18 +97,19 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
return;
}
- if (options.bold) {
- this.push(new Bold());
+ if (options.bold !== undefined) {
+ this.push(new OnOffElement("w:b", options.bold));
}
- if ((options.boldComplexScript === undefined && options.bold) || options.boldComplexScript) {
- this.push(new BoldComplexScript());
+ if ((options.boldComplexScript === undefined && options.bold !== undefined) || options.boldComplexScript) {
+ this.push(new OnOffElement("w:bCs", options.boldComplexScript ?? options.bold));
}
- if (options.italics) {
- this.push(new Italics());
+ if (options.italics !== undefined) {
+ this.push(new OnOffElement("w:i", options.italics));
}
- if ((options.italicsComplexScript === undefined && options.italics) || options.italicsComplexScript) {
- this.push(new ItalicsComplexScript());
+
+ if ((options.italicsComplexScript === undefined && options.italics !== undefined) || options.italicsComplexScript) {
+ this.push(new OnOffElement("w:iCs", options.italicsComplexScript ?? options.italics));
}
if (options.underline) {
@@ -105,33 +124,32 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
this.push(new Color(options.color));
}
- if (options.size) {
- this.push(new Size(options.size));
+ if (options.size !== undefined) {
+ this.push(new HpsMeasureElement("w:sz", options.size));
}
const szCs =
options.sizeComplexScript === undefined || options.sizeComplexScript === true ? options.size : options.sizeComplexScript;
if (szCs) {
- this.push(new SizeComplexScript(szCs));
+ this.push(new HpsMeasureElement("w:szCs", szCs));
}
- if (options.rightToLeft) {
- this.push(new RightToLeft());
+ if (options.rightToLeft !== undefined) {
+ this.push(new OnOffElement("w:rtl", options.rightToLeft));
}
- if (options.smallCaps) {
- this.push(new SmallCaps());
+ // These two are mutually exclusive
+ if (options.smallCaps !== undefined) {
+ this.push(new OnOffElement("w:smallCaps", options.smallCaps));
+ } else if (options.allCaps !== undefined) {
+ this.push(new OnOffElement("w:caps", options.allCaps));
}
- if (options.allCaps) {
- this.push(new Caps());
+ if (options.strike !== undefined) {
+ this.push(new OnOffElement("w:strike", options.strike));
}
- if (options.strike) {
- this.push(new Strike());
- }
-
- if (options.doubleStrike) {
- this.push(new DoubleStrike());
+ if (options.doubleStrike !== undefined) {
+ this.push(new OnOffElement("w:dstrike", options.doubleStrike));
}
if (options.subScript) {
@@ -143,7 +161,7 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
}
if (options.style) {
- this.push(new Style(options.style));
+ this.push(new StringValueElement("w:rStyle", options.style));
}
if (options.font) {
@@ -171,17 +189,16 @@ export class RunProperties extends IgnoreIfEmptyXmlComponent {
this.push(new CharacterSpacing(options.characterSpacing));
}
- if (options.emboss) {
- this.push(new Emboss());
+ if (options.emboss !== undefined) {
+ this.push(new OnOffElement("w:emboss", options.emboss));
}
- if (options.imprint) {
- this.push(new Imprint());
+ if (options.imprint !== undefined) {
+ this.push(new OnOffElement("w:imprint", options.imprint));
}
- const shading = options.shading || options.shadow;
- if (shading) {
- this.push(new Shading(shading.type, shading.fill, shading.color));
+ if (options.shading) {
+ this.push(new Shading(options.shading));
}
}
diff --git a/src/file/paragraph/run/run.spec.ts b/src/file/paragraph/run/run.spec.ts
index a001699a7b..aaa2a640de 100644
--- a/src/file/paragraph/run/run.spec.ts
+++ b/src/file/paragraph/run/run.spec.ts
@@ -2,7 +2,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
// import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run";
-import { ShadingType } from "file/table";
+import { ShadingType } from "file/shading";
import { Run } from "./";
import { EmphasisMarkType } from "./emphasis-mark";
@@ -20,13 +20,9 @@ describe("Run", () => {
"w:r": [
{
"w:rPr": [
- { "w:b": { _attr: { "w:val": true } } },
+ { "w:b": {} },
{
- "w:bCs": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:bCs": {},
},
],
},
@@ -45,13 +41,9 @@ describe("Run", () => {
"w:r": [
{
"w:rPr": [
- { "w:i": { _attr: { "w:val": true } } },
+ { "w:i": {} },
{
- "w:iCs": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:iCs": {},
},
],
},
@@ -116,7 +108,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:smallCaps": {} }] }],
});
});
});
@@ -128,7 +120,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:caps": {} }] }],
});
});
});
@@ -140,7 +132,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:strike": {} }] }],
});
});
});
@@ -152,7 +144,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:dstrike": {} }] }],
});
});
});
@@ -164,7 +156,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:emboss": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:emboss": {} }] }],
});
});
});
@@ -176,7 +168,7 @@ describe("Run", () => {
});
const tree = new Formatter().format(run);
expect(tree).to.deep.equal({
- "w:r": [{ "w:rPr": [{ "w:imprint": { _attr: { "w:val": true } } }] }],
+ "w:r": [{ "w:rPr": [{ "w:imprint": {} }] }],
});
});
});
@@ -367,7 +359,7 @@ describe("Run", () => {
});
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": {} }] }],
});
});
});
diff --git a/src/file/paragraph/run/run.ts b/src/file/paragraph/run/run.ts
index 461fd9da29..02b97ec47f 100644
--- a/src/file/paragraph/run/run.ts
+++ b/src/file/paragraph/run/run.ts
@@ -29,6 +29,12 @@ export class Run extends XmlComponent {
this.properties = new RunProperties(options);
this.root.push(this.properties);
+ if (options.break) {
+ for (let i = 0; i < options.break; i++) {
+ this.root.push(new Break());
+ }
+ }
+
if (options.children) {
for (const child of options.children) {
if (typeof child === "string") {
@@ -63,11 +69,5 @@ export class Run extends XmlComponent {
} else if (options.text) {
this.root.push(new Text(options.text));
}
-
- if (options.break) {
- for (let i = 0; i < options.break; i++) {
- this.root.splice(1, 0, new Break());
- }
- }
}
}
diff --git a/src/file/paragraph/run/strike.spec.ts b/src/file/paragraph/run/strike.spec.ts
deleted file mode 100644
index 73c7e853c8..0000000000
--- a/src/file/paragraph/run/strike.spec.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { DoubleStrike, Strike } from "./formatting";
-
-describe("Strike", () => {
- let strike: Strike;
-
- beforeEach(() => {
- strike = new Strike();
- });
-
- describe("#constructor()", () => {
- it("should create a Strike with correct root key", () => {
- const tree = new Formatter().format(strike);
- expect(tree).to.deep.equal({
- "w:strike": {
- _attr: {
- "w:val": true,
- },
- },
- });
- });
- });
-});
-
-describe("DoubleStrike", () => {
- let strike: DoubleStrike;
-
- beforeEach(() => {
- strike = new DoubleStrike();
- });
-
- describe("#constructor()", () => {
- it("should create a Double Strike with correct root key", () => {
- const tree = new Formatter().format(strike);
- expect(tree).to.deep.equal({
- "w:dstrike": {
- _attr: {
- "w:val": true,
- },
- },
- });
- });
- });
-});
diff --git a/src/file/paragraph/run/style.ts b/src/file/paragraph/run/style.ts
deleted file mode 100644
index 2472c1d406..0000000000
--- a/src/file/paragraph/run/style.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-class StyleAttributes extends XmlAttributeComponent<{ readonly val: string }> {
- protected readonly xmlKeys = { val: "w:val" };
-}
-
-export class Style extends XmlComponent {
- constructor(styleId: string) {
- super("w:rStyle");
- this.root.push(new StyleAttributes({ val: styleId }));
- }
-}
diff --git a/src/file/paragraph/run/symbol-run.spec.ts b/src/file/paragraph/run/symbol-run.spec.ts
index c41e6e1d51..06e98a4373 100644
--- a/src/file/paragraph/run/symbol-run.spec.ts
+++ b/src/file/paragraph/run/symbol-run.spec.ts
@@ -43,13 +43,13 @@ describe("SymbolRun", () => {
italics: true,
bold: true,
underline: {
- color: "red",
+ color: "ff0000",
type: UnderlineType.DOUBLE,
},
emphasisMark: {
type: EmphasisMarkType.DOT,
},
- color: "green",
+ color: "00FF00",
size: 40,
highlight: "yellow",
});
@@ -59,13 +59,13 @@ describe("SymbolRun", () => {
"w:r": [
{
"w:rPr": [
- { "w:b": { _attr: { "w:val": true } } },
- { "w:bCs": { _attr: { "w:val": true } } },
- { "w:i": { _attr: { "w:val": true } } },
- { "w:iCs": { _attr: { "w:val": true } } },
- { "w:u": { _attr: { "w:val": "double", "w:color": "red" } } },
+ { "w:b": {} },
+ { "w:bCs": {} },
+ { "w:i": {} },
+ { "w:iCs": {} },
+ { "w:u": { _attr: { "w:val": "double", "w:color": "ff0000" } } },
{ "w:em": { _attr: { "w:val": "dot" } } },
- { "w:color": { _attr: { "w:val": "green" } } },
+ { "w:color": { _attr: { "w:val": "00FF00" } } },
{ "w:sz": { _attr: { "w:val": 40 } } },
{ "w:szCs": { _attr: { "w:val": 40 } } },
{ "w:highlight": { _attr: { "w:val": "yellow" } } },
diff --git a/src/file/paragraph/run/tab.ts b/src/file/paragraph/run/tab.ts
index 55893862af..33f2b09427 100644
--- a/src/file/paragraph/run/tab.ts
+++ b/src/file/paragraph/run/tab.ts
@@ -1,5 +1,11 @@
import { XmlComponent } from "file/xml-components";
+//
+// ...
+//
+//
+// TODO: this is unused and undocumented currently.
+// I think the intended use was for users to import, and insert as a child of `Run`.
export class Tab extends XmlComponent {
constructor() {
super("w:tab");
diff --git a/src/file/paragraph/run/underline.spec.ts b/src/file/paragraph/run/underline.spec.ts
index 77f7819e7b..bc406a1da4 100644
--- a/src/file/paragraph/run/underline.spec.ts
+++ b/src/file/paragraph/run/underline.spec.ts
@@ -2,12 +2,12 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import * as u from "./underline";
+import { Underline, UnderlineType } from "./underline";
describe("Underline", () => {
describe("#constructor()", () => {
it("should create a new Underline object with u:u as the rootKey", () => {
- const underline = new u.Underline();
+ const underline = new Underline();
const tree = new Formatter().format(underline);
expect(tree).to.deep.equal({
"w:u": {
@@ -19,7 +19,7 @@ describe("Underline", () => {
});
it("should default to 'single' and no color", () => {
- const underline = new u.Underline();
+ const underline = new Underline();
const tree = new Formatter().format(underline);
expect(tree).to.deep.equal({
"w:u": { _attr: { "w:val": "single" } },
@@ -27,7 +27,7 @@ describe("Underline", () => {
});
it("should use the given style type and color", () => {
- const underline = new u.Underline(u.UnderlineType.DOUBLE, "FF00CC");
+ const underline = new Underline(UnderlineType.DOUBLE, "FF00CC");
const tree = new Formatter().format(underline);
expect(tree).to.deep.equal({
"w:u": { _attr: { "w:val": "double", "w:color": "FF00CC" } },
@@ -35,259 +35,3 @@ describe("Underline", () => {
});
});
});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DashDotDotHeavyUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dashDotDotHeavy",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DashDotHeavyUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dashDotHeavy",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DashLongHeavyUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dashLongHeavy",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DashLongUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dashLong",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DashUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dash",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DotDashUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dotDash",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DotDotDashUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dotDotDash",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DottedHeavyUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dottedHeavy",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DottedUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "dotted",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.DoubleUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "double",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.SingleUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "single",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.ThickUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "thick",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.WaveUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "wave",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.WavyDoubleUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "wavyDouble",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.WavyHeavyUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "wavyHeavy",
- },
- },
- });
- });
- });
-});
-
-describe("DashDotDotHeavyUnderline", () => {
- describe("#constructor()", () => {
- it("should put value in attribute", () => {
- const underline = new u.WordsUnderline();
- const tree = new Formatter().format(underline);
- expect(tree).to.deep.equal({
- "w:u": {
- _attr: {
- "w:val": "words",
- },
- },
- });
- });
- });
-});
diff --git a/src/file/paragraph/run/underline.ts b/src/file/paragraph/run/underline.ts
index 9cdb7b25a1..a94c37e1f5 100644
--- a/src/file/paragraph/run/underline.ts
+++ b/src/file/paragraph/run/underline.ts
@@ -1,3 +1,4 @@
+import { hexColorValue } from "file/values";
import { Attributes, XmlComponent } from "file/xml-components";
export enum UnderlineType {
@@ -20,116 +21,14 @@ export enum UnderlineType {
WAVYDOUBLE = "wavyDouble",
}
-export abstract class BaseUnderline extends XmlComponent {
- constructor(underlineType: string, color?: string) {
+export class Underline extends XmlComponent {
+ constructor(underlineType: UnderlineType = UnderlineType.SINGLE, color?: string) {
super("w:u");
this.root.push(
new Attributes({
val: underlineType,
- color: color,
+ color: color === undefined ? undefined : hexColorValue(color),
}),
);
}
}
-
-export class Underline extends BaseUnderline {
- constructor(underlineType: UnderlineType = UnderlineType.SINGLE, color?: string) {
- super(underlineType, color);
- }
-}
-
-export class DashUnderline extends BaseUnderline {
- constructor() {
- super("dash");
- }
-}
-
-export class DashDotDotHeavyUnderline extends BaseUnderline {
- constructor() {
- super("dashDotDotHeavy");
- }
-}
-
-export class DashDotHeavyUnderline extends BaseUnderline {
- constructor() {
- super("dashDotHeavy");
- }
-}
-
-export class DashLongUnderline extends BaseUnderline {
- constructor() {
- super("dashLong");
- }
-}
-
-export class DashLongHeavyUnderline extends BaseUnderline {
- constructor() {
- super("dashLongHeavy");
- }
-}
-
-export class DotDashUnderline extends BaseUnderline {
- constructor() {
- super("dotDash");
- }
-}
-
-export class DotDotDashUnderline extends BaseUnderline {
- constructor() {
- super("dotDotDash");
- }
-}
-
-export class DottedUnderline extends BaseUnderline {
- constructor() {
- super("dotted");
- }
-}
-
-export class DottedHeavyUnderline extends BaseUnderline {
- constructor() {
- super("dottedHeavy");
- }
-}
-
-export class DoubleUnderline extends BaseUnderline {
- constructor() {
- super("double");
- }
-}
-
-export class SingleUnderline extends BaseUnderline {
- constructor() {
- super("single");
- }
-}
-
-export class ThickUnderline extends BaseUnderline {
- constructor() {
- super("thick");
- }
-}
-
-export class WaveUnderline extends BaseUnderline {
- constructor() {
- super("wave");
- }
-}
-
-export class WavyDoubleUnderline extends BaseUnderline {
- constructor() {
- super("wavyDouble");
- }
-}
-
-export class WavyHeavyUnderline extends BaseUnderline {
- constructor() {
- super("wavyHeavy");
- }
-}
-
-export class WordsUnderline extends BaseUnderline {
- constructor() {
- super("words");
- }
-}
diff --git a/src/file/settings/compatibility-setting/compatibility-setting.ts b/src/file/settings/compatibility-setting/compatibility-setting.ts
index 9f2a0b4982..43a7c5d71a 100644
--- a/src/file/settings/compatibility-setting/compatibility-setting.ts
+++ b/src/file/settings/compatibility-setting/compatibility-setting.ts
@@ -1,5 +1,15 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+// Currently, this is hard-coded for Microsoft word compatSettings.
+// Theoretically, we could add compatSettings for other programs, but
+// currently there isn't a need.
+
+//
+//
+//
+//
+//
+
export class CompatibilitySettingAttributes extends XmlAttributeComponent<{
readonly version: number;
readonly name: string;
@@ -12,6 +22,8 @@ export class CompatibilitySettingAttributes extends XmlAttributeComponent<{
};
}
+// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-docx/90138c4d-eb18-4edc-aa6c-dfb799cb1d0d
+
export class CompatibilitySetting extends XmlComponent {
constructor(version: number) {
super("w:compatSetting");
diff --git a/src/file/settings/compatibility.ts b/src/file/settings/compatibility.ts
index fe63da92c5..1405697bca 100644
--- a/src/file/settings/compatibility.ts
+++ b/src/file/settings/compatibility.ts
@@ -1,11 +1,77 @@
-import { XmlComponent } from "file/xml-components";
+import { OnOffElement, XmlComponent } from "file/xml-components";
import { CompatibilitySetting } from "./compatibility-setting/compatibility-setting";
-class DoNotExpandShiftReturn extends XmlComponent {
- constructor() {
- super("w:doNotExpandShiftReturn");
- }
-}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export interface ICompatibilityOptions {
readonly doNotExpandShiftReturn?: boolean;
@@ -16,8 +82,9 @@ export class Compatibility extends XmlComponent {
constructor(options: ICompatibilityOptions) {
super("w:compat");
- if (options.doNotExpandShiftReturn) {
- this.root.push(new DoNotExpandShiftReturn());
+ // Don't justify lines ending in soft line break setting
+ if (options.doNotExpandShiftReturn !== undefined) {
+ this.root.push(new OnOffElement("w:doNotExpandShiftReturn", options.doNotExpandShiftReturn));
}
if (options.version) {
diff --git a/src/file/settings/display-background-shape.spec.ts b/src/file/settings/display-background-shape.spec.ts
deleted file mode 100644
index 34c23b65db..0000000000
--- a/src/file/settings/display-background-shape.spec.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { DisplayBackgroundShape } from "./display-background-shape";
-
-describe("DisplayBackgroundShape", () => {
- describe("#constructor()", () => {
- it("should create", () => {
- const displayBackgroundShape = new DisplayBackgroundShape();
- const tree = new Formatter().format(displayBackgroundShape);
- expect(tree).to.deep.equal({
- "w:displayBackgroundShape": {},
- });
- });
- });
-});
diff --git a/src/file/settings/display-background-shape.ts b/src/file/settings/display-background-shape.ts
deleted file mode 100644
index bd0cd15675..0000000000
--- a/src/file/settings/display-background-shape.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// http://officeopenxml.com/WPdocument.php
-// http://www.datypic.com/sc/ooxml/e-w_background-1.html
-import { XmlComponent } from "file/xml-components";
-
-export class DisplayBackgroundShape extends XmlComponent {
- constructor() {
- super("w:displayBackgroundShape");
- }
-}
diff --git a/src/file/settings/even-odd-headers.ts b/src/file/settings/even-odd-headers.ts
deleted file mode 100644
index c6f85a7aca..0000000000
--- a/src/file/settings/even-odd-headers.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// http://officeopenxml.com/WPSectionFooterReference.php
-// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_evenAndOddHeaders_topic_ID0ET1WU.html
-import { XmlComponent } from "file/xml-components";
-
-export class EvenAndOddHeadersAndFooters extends XmlComponent {
- constructor() {
- super("w:evenAndOddHeaders");
- }
-}
diff --git a/src/file/settings/index.ts b/src/file/settings/index.ts
index d750485a16..dcf101b0c6 100644
--- a/src/file/settings/index.ts
+++ b/src/file/settings/index.ts
@@ -1,2 +1 @@
export * from "./settings";
-export * from "./update-fields";
diff --git a/src/file/settings/settings.spec.ts b/src/file/settings/settings.spec.ts
index 03a3612a0b..b12f340f43 100644
--- a/src/file/settings/settings.spec.ts
+++ b/src/file/settings/settings.spec.ts
@@ -7,83 +7,37 @@ import { Settings } from "./settings";
describe("Settings", () => {
describe("#constructor", () => {
it("should create a empty Settings with correct rootKey", () => {
- const settings = new Settings({
- evenAndOddHeaders: false,
- });
+ const settings = new Settings({});
const tree = new Formatter().format(settings);
- let keys = Object.keys(tree);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:settings");
- keys = Object.keys(tree["w:settings"]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(3);
+
+ expect(Object.keys(tree)).has.length(1);
+ expect(tree["w:settings"]).to.be.an("array");
});
- });
- describe("#addUpdateFields", () => {
- const assertSettingsWithUpdateFields = (settings: Settings) => {
- const tree = new Formatter().format(settings);
- let keys = Object.keys(tree);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:settings");
- const rootArray = tree["w:settings"];
- expect(rootArray).is.an.instanceof(Array);
- expect(rootArray).has.length(4);
- keys = Object.keys(rootArray[0]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("_attr");
- keys = Object.keys(rootArray[3]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:updateFields");
- const updateFields = rootArray[3]["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 = updateFields._attr;
- expect(updateFieldsAttr["w:val"]).to.be.equal(true);
- };
- it("should add a UpdateFields with value true", () => {
+
+ it("should add updateFields setting", () => {
const settings = new Settings({
- evenAndOddHeaders: false,
- });
- settings.addUpdateFields();
- assertSettingsWithUpdateFields(settings);
- });
- it("should add a UpdateFields with value true only once", () => {
- const settings = new Settings({
- evenAndOddHeaders: false,
- });
- settings.addUpdateFields();
- assertSettingsWithUpdateFields(settings);
- settings.addUpdateFields();
- assertSettingsWithUpdateFields(settings);
- });
- });
- describe("#addCompatibility", () => {
- it("should add an empty Compatibility by default", () => {
- const settings = new Settings({
- evenAndOddHeaders: false,
+ updateFields: true,
});
const tree = new Formatter().format(settings);
- let keys: string[] = Object.keys(tree);
- expect(keys[0]).to.be.equal("w:settings");
- const rootArray = tree["w:settings"];
- expect(rootArray).is.an.instanceof(Array);
- expect(rootArray).has.length(3);
- keys = Object.keys(rootArray[0]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("_attr");
- keys = Object.keys(rootArray[1]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:compat");
- expect(rootArray[1]["w:compat"][0]).to.deep.equal({
+ expect(Object.keys(tree)).has.length(1);
+ expect(tree["w:settings"]).to.be.an("array");
+
+ expect(tree["w:settings"]).to.deep.include({
+ "w:updateFields": {},
+ });
+ });
+
+ it("should indicate modern word compatibility by default", () => {
+ const settings = new Settings({});
+
+ const tree = new Formatter().format(settings);
+ expect(Object.keys(tree)).has.length(1);
+ expect(tree["w:settings"]).to.be.an("array");
+
+ const compat = tree["w:settings"][2];
+ expect(compat).to.be.an("object").with.keys("w:compat");
+ expect(compat["w:compat"]).to.deep.include({
"w:compatSetting": {
_attr: {
"w:val": 15,
@@ -93,81 +47,19 @@ describe("Settings", () => {
},
});
});
- });
- describe("#addTrackRevisions", () => {
- it("should add an empty Track Revisions", () => {
+
+ it("should add trackRevisions setting", () => {
const settings = new Settings({
- evenAndOddHeaders: false,
+ trackRevisions: true,
});
- settings.addTrackRevisions();
const tree = new Formatter().format(settings);
- let keys: string[] = Object.keys(tree);
- expect(keys[0]).to.be.equal("w:settings");
- const rootArray = tree["w:settings"];
- expect(rootArray).is.an.instanceof(Array);
- expect(rootArray).has.length(4);
- keys = Object.keys(rootArray[0]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("_attr");
- keys = Object.keys(rootArray[3]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:trackRevisions");
- });
- });
- describe("#addTrackRevisionsTwice", () => {
- it("should add an empty Track Revisions if called twice", () => {
- const settings = new Settings({
- evenAndOddHeaders: false,
+ expect(Object.keys(tree)).has.length(1);
+ expect(tree["w:settings"]).to.be.an("array");
+
+ expect(tree["w:settings"]).to.deep.include({
+ "w:trackRevisions": {},
});
- settings.addTrackRevisions();
- settings.addTrackRevisions();
-
- const tree = new Formatter().format(settings);
- let keys: string[] = Object.keys(tree);
- expect(keys[0]).to.be.equal("w:settings");
- const rootArray = tree["w:settings"];
- expect(rootArray).is.an.instanceof(Array);
- expect(rootArray).has.length(4);
- keys = Object.keys(rootArray[0]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("_attr");
- keys = Object.keys(rootArray[3]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:trackRevisions");
- });
- });
-
- describe("#addTrackRevisionsTwice", () => {
- it("should add an empty Track Revisions if called twice", () => {
- const settings = new Settings({
- evenAndOddHeaders: true,
- });
- settings.addTrackRevisions();
- settings.addTrackRevisions();
-
- const tree = new Formatter().format(settings);
- let keys: string[] = Object.keys(tree);
- expect(keys[0]).to.be.equal("w:settings");
- const rootArray = tree["w:settings"];
- expect(rootArray).is.an.instanceof(Array);
- expect(rootArray).has.length(5);
- keys = Object.keys(rootArray[0]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("_attr");
- keys = Object.keys(rootArray[4]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:trackRevisions");
- keys = Object.keys(rootArray[2]);
- expect(keys).is.an.instanceof(Array);
- expect(keys).has.length(1);
- expect(keys[0]).to.be.equal("w:evenAndOddHeaders");
});
});
});
diff --git a/src/file/settings/settings.ts b/src/file/settings/settings.ts
index 30b26d8f04..4c57532a41 100644
--- a/src/file/settings/settings.ts
+++ b/src/file/settings/settings.ts
@@ -1,10 +1,6 @@
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { OnOffElement, XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { Compatibility } from "./compatibility";
-import { DisplayBackgroundShape } from "./display-background-shape";
-import { EvenAndOddHeadersAndFooters } from "./even-odd-headers";
-import { TrackRevisions } from "./track-revisions";
-import { UpdateFields } from "./update-fields";
export class SettingsAttributes extends XmlAttributeComponent<{
readonly wpc?: string;
@@ -46,14 +42,118 @@ export class SettingsAttributes extends XmlAttributeComponent<{
};
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
export interface ISettingsOptions {
readonly compatabilityModeVersion?: number;
- readonly evenAndOddHeaders: boolean;
+ readonly evenAndOddHeaders?: boolean;
+ readonly trackRevisions?: boolean;
+ readonly updateFields?: boolean;
}
export class Settings extends XmlComponent {
- private readonly trackRevisions: TrackRevisions;
-
constructor(options: ISettingsOptions) {
super("w:settings");
this.root.push(
@@ -78,32 +178,29 @@ export class Settings extends XmlComponent {
}),
);
+ // http://officeopenxml.com/WPdocument.php
+ // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_displayBackgroundSha_topic_ID0ET4SX.html
+ this.root.push(new OnOffElement("w:displayBackgroundShape", true));
+
+ // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_trackRevisions_topic_ID0EKXKY.html
+ if (options.trackRevisions !== undefined) {
+ this.root.push(new OnOffElement("w:trackRevisions", options.trackRevisions));
+ }
+
+ // http://officeopenxml.com/WPSectionFooterReference.php
+ // https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_evenAndOddHeaders_topic_ID0ET1WU.html
+ if (options.evenAndOddHeaders !== undefined) {
+ this.root.push(new OnOffElement("w:evenAndOddHeaders", options.evenAndOddHeaders));
+ }
+
+ if (options.updateFields !== undefined) {
+ this.root.push(new OnOffElement("w:updateFields", options.updateFields));
+ }
+
this.root.push(
new Compatibility({
version: options.compatabilityModeVersion || 15,
}),
);
-
- if (options.evenAndOddHeaders) {
- this.root.push(new EvenAndOddHeadersAndFooters());
- }
-
- this.trackRevisions = new TrackRevisions();
-
- this.root.push(new DisplayBackgroundShape());
- }
-
- public addUpdateFields(): void {
- if (!this.root.find((child) => child instanceof UpdateFields)) {
- this.addChildElement(new UpdateFields());
- }
- }
-
- public addTrackRevisions(): TrackRevisions {
- if (!this.root.find((child) => child instanceof TrackRevisions)) {
- this.addChildElement(this.trackRevisions);
- }
-
- return this.trackRevisions;
}
}
diff --git a/src/file/settings/track-revisions.spec.ts b/src/file/settings/track-revisions.spec.ts
deleted file mode 100644
index 3875d51f0a..0000000000
--- a/src/file/settings/track-revisions.spec.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { expect } from "chai";
-import { Formatter } from "export/formatter";
-import { TrackRevisions } from "file/settings/track-revisions";
-
-import { EMPTY_OBJECT } from "file/xml-components";
-
-describe("TrackRevisions", () => {
- describe("#constructor", () => {
- it("creates an initially empty property object", () => {
- const trackRevisions = new TrackRevisions();
-
- const tree = new Formatter().format(trackRevisions);
- expect(tree).to.deep.equal({ "w:trackRevisions": EMPTY_OBJECT });
- });
- });
-});
diff --git a/src/file/settings/track-revisions.ts b/src/file/settings/track-revisions.ts
deleted file mode 100644
index 2da692827e..0000000000
--- a/src/file/settings/track-revisions.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { XmlComponent } from "file/xml-components";
-
-export class TrackRevisions extends XmlComponent {
- constructor() {
- super("w:trackRevisions");
- }
-}
diff --git a/src/file/settings/update-fields.spec.ts b/src/file/settings/update-fields.spec.ts
deleted file mode 100644
index 2ccc9df8c4..0000000000
--- a/src/file/settings/update-fields.spec.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { UpdateFields } from "./update-fields";
-
-const UF_TRUE = {
- "w:updateFields": {
- _attr: {
- "w:val": true,
- },
- },
-};
-const UF_FALSE = {
- "w:updateFields": {
- _attr: {
- "w:val": false,
- },
- },
-};
-describe("Update Fields", () => {
- describe("#constructor", () => {
- it("should construct a Update Fields with TRUE value by default", () => {
- const uf = new UpdateFields();
- const tree = new Formatter().format(uf);
- expect(tree).to.be.deep.equal(UF_TRUE);
- });
- it("should construct a Update Fields with TRUE value", () => {
- const uf = new UpdateFields(true);
- const tree = new Formatter().format(uf);
- expect(tree).to.be.deep.equal(UF_TRUE);
- });
- it("should construct a Update Fields with FALSE value", () => {
- const uf = new UpdateFields(false);
- const tree = new Formatter().format(uf);
- expect(tree).to.be.deep.equal(UF_FALSE);
- });
- });
-});
diff --git a/src/file/settings/update-fields.ts b/src/file/settings/update-fields.ts
deleted file mode 100644
index 47a2ec6e18..0000000000
--- a/src/file/settings/update-fields.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export class UpdateFieldsAttributes extends XmlAttributeComponent<{
- readonly enabled: boolean;
-}> {
- protected readonly xmlKeys = {
- enabled: "w:val",
- };
-}
-export class UpdateFields extends XmlComponent {
- constructor(enabled: boolean = true) {
- super("w:updateFields");
- this.root.push(
- new UpdateFieldsAttributes({
- enabled,
- }),
- );
- }
-}
diff --git a/src/file/table/shading/index.ts b/src/file/shading/index.ts
similarity index 100%
rename from src/file/table/shading/index.ts
rename to src/file/shading/index.ts
diff --git a/src/file/table/shading/shading.spec.ts b/src/file/shading/shading.spec.ts
similarity index 75%
rename from src/file/table/shading/shading.spec.ts
rename to src/file/shading/shading.spec.ts
index ce28fcca92..7b808aa829 100644
--- a/src/file/table/shading/shading.spec.ts
+++ b/src/file/shading/shading.spec.ts
@@ -2,12 +2,12 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { ShadingType, TableShading } from "./shading";
+import { Shading, ShadingType } from "./shading";
-describe("TableShading", () => {
+describe("Shading", () => {
describe("#constructor", () => {
it("should create", () => {
- const shading = new TableShading({});
+ const shading = new Shading({});
const tree = new Formatter().format(shading);
expect(tree).to.deep.equal({
"w:shd": {
@@ -17,7 +17,7 @@ describe("TableShading", () => {
});
it("should create with params", () => {
- const shading = new TableShading({ val: ShadingType.PERCENT_40, color: "FF0000", fill: "555555" });
+ const shading = new Shading({ type: ShadingType.PERCENT_40, color: "FF0000", fill: "555555" });
const tree = new Formatter().format(shading);
expect(tree).to.deep.equal({
"w:shd": {
diff --git a/src/file/shading/shading.ts b/src/file/shading/shading.ts
new file mode 100644
index 0000000000..9199122c78
--- /dev/null
+++ b/src/file/shading/shading.ts
@@ -0,0 +1,88 @@
+// Note that the shading type is identical in all places,
+// regardless of where it's used like paragraph/table/etc.
+//
+// http://officeopenxml.com/WPshading.php
+// http://officeopenxml.com/WPtableShading.php
+// http://officeopenxml.com/WPtableCellProperties-Shading.php
+//
+// This describes the CT_Shd type.
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { hexColorValue } from "../values";
+
+export interface IShadingAttributesProperties {
+ readonly fill?: string;
+ readonly color?: string;
+ readonly type?: ShadingType;
+}
+
+class ShadingAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = {
+ fill: "w:fill",
+ color: "w:color",
+ type: "w:val",
+ };
+}
+
+export class Shading extends XmlComponent {
+ constructor({ fill, color, type }: IShadingAttributesProperties) {
+ super("w:shd");
+ this.root.push(
+ new ShadingAttributes({
+ fill: fill === undefined ? undefined : hexColorValue(fill),
+ color: color === undefined ? undefined : hexColorValue(color),
+ type,
+ }),
+ );
+ }
+}
+
+export enum ShadingType {
+ CLEAR = "clear",
+ DIAGONAL_CROSS = "diagCross",
+ DIAGONAL_STRIPE = "diagStripe",
+ HORIZONTAL_CROSS = "horzCross",
+ HORIZONTAL_STRIPE = "horzStripe",
+ NIL = "nil",
+ PERCENT_5 = "pct5",
+ PERCENT_10 = "pct10",
+ PERCENT_12 = "pct12",
+ PERCENT_15 = "pct15",
+ PERCENT_20 = "pct20",
+ PERCENT_25 = "pct25",
+ PERCENT_30 = "pct30",
+ PERCENT_35 = "pct35",
+ PERCENT_37 = "pct37",
+ PERCENT_40 = "pct40",
+ PERCENT_45 = "pct45",
+ PERCENT_50 = "pct50",
+ PERCENT_55 = "pct55",
+ PERCENT_60 = "pct60",
+ PERCENT_62 = "pct62",
+ PERCENT_65 = "pct65",
+ PERCENT_70 = "pct70",
+ PERCENT_75 = "pct75",
+ PERCENT_80 = "pct80",
+ PERCENT_85 = "pct85",
+ PERCENT_87 = "pct87",
+ PERCENT_90 = "pct90",
+ PERCENT_95 = "pct95",
+ REVERSE_DIAGONAL_STRIPE = "reverseDiagStripe",
+ SOLID = "solid",
+ THIN_DIAGONAL_CROSS = "thinDiagCross",
+ THIN_DIAGONAL_STRIPE = "thinDiagStripe",
+ THIN_HORIZONTAL_CROSS = "thinHorzCross",
+ THIN_REVERSE_DIAGONAL_STRIPE = "thinReverseDiagStripe",
+ THIN_VERTICAL_STRIPE = "thinVertStripe",
+ VERTICAL_STRIPE = "vertStripe",
+}
diff --git a/src/file/shared/index.ts b/src/file/shared/index.ts
index bc61bbe9ca..6abfbc0a8e 100644
--- a/src/file/shared/index.ts
+++ b/src/file/shared/index.ts
@@ -1 +1,2 @@
export * from "./alignment";
+export * from "./number-format";
diff --git a/src/file/shared/number-format.ts b/src/file/shared/number-format.ts
new file mode 100644
index 0000000000..8ee5ad10fc
--- /dev/null
+++ b/src/file/shared/number-format.ts
@@ -0,0 +1,133 @@
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+export enum NumberFormat {
+ DECIMAL = "decimal",
+ UPPER_ROMAN = "upperRoman",
+ LOWER_ROMAN = "lowerRoman",
+ UPPER_LETTER = "upperLetter",
+ LOWER_LETTER = "lowerLetter",
+ ORDINAL = "ordinal",
+ CARDINAL_TEXT = "cardinalText",
+ ORDINAL_TEXT = "ordinalText",
+ HEX = "hex",
+ CHICAGO = "chicago",
+ IDEOGRAPH_DIGITAL = "ideographDigital",
+ JAPANESE_COUNTING = "japaneseCounting",
+ AIUEO = "aiueo",
+ IROHA = "iroha",
+ DECIMAL_FULL_WIDTH = "decimalFullWidth",
+ DECIMAL_HALF_WIDTH = "decimalHalfWidth",
+ JAPANESE_LEGAL = "japaneseLegal",
+ JAPANESE_DIGITAL_TEN_THOUSAND = "japaneseDigitalTenThousand",
+ DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
+ DECIMAL_FULL_WIDTH_2 = "decimalFullWidth2",
+ AIUEO_FULL_WIDTH = "aiueoFullWidth",
+ IROHA_FULL_WIDTH = "irohaFullWidth",
+ DECIMAL_ZERO = "decimalZero",
+ BULLET = "bullet",
+ GANADA = "ganada",
+ CHOSUNG = "chosung",
+ DECIMAL_ENCLOSED_FULL_STOP = "decimalEnclosedFullstop",
+ DECIMAL_ENCLOSED_PAREN = "decimalEnclosedParen",
+ DECIMAL_ENCLOSED_CIRCLE_CHINESE = "decimalEnclosedCircleChinese",
+ IDEOGRAPH_ENCLOSED_CIRCLE = "ideographEnclosedCircle",
+ IDEOGRAPH_TRADITIONAL = "ideographTraditional",
+ IDEOGRAPH_ZODIAC = "ideographZodiac",
+ IDEOGRAPH_ZODIAC_TRADITIONAL = "ideographZodiacTraditional",
+ TAIWANESE_COUNTING = "taiwaneseCounting",
+ IDEOGRAPH_LEGAL_TRADITIONAL = "ideographLegalTraditional",
+ TAIWANESE_COUNTING_THOUSAND = "taiwaneseCountingThousand",
+ TAIWANESE_DIGITAL = "taiwaneseDigital",
+ CHINESE_COUNTING = "chineseCounting",
+ CHINESE_LEGAL_SIMPLIFIED = "chineseLegalSimplified",
+ CHINESE_COUNTING_TEN_THOUSAND = "chineseCountingThousand",
+ KOREAN_DIGITAL = "koreanDigital",
+ KOREAN_COUNTING = "koreanCounting",
+ KOREAN_LEGAL = "koreanLegal",
+ KOREAN_DIGITAL_2 = "koreanDigital2",
+ VIETNAMESE_COUNTING = "vietnameseCounting",
+ RUSSIAN_LOWER = "russianLower",
+ RUSSIAN_UPPER = "russianUpper",
+ NONE = "none",
+ NUMBER_IN_DASH = "numberInDash",
+ HEBREW_1 = "hebrew1",
+ HEBREW_2 = "hebrew2",
+ ARABIC_ALPHA = "arabicAlpha",
+ ARABIC_ABJAD = "arabicAbjad",
+ HINDI_VOWELS = "hindiVowels",
+ HINDI_CONSONANTS = "hindiConsonants",
+ HINDI_NUMBERS = "hindiNumbers",
+ HINDI_COUNTING = "hindiCounting",
+ THAI_LETTERS = "thaiLetters",
+ THAI_NUMBERS = "thaiNumbers",
+ THAI_COUNTING = "thaiCounting",
+ BAHT_TEXT = "bahtText",
+ DOLLAR_TEXT = "dollarText",
+ //
+}
diff --git a/src/file/styles/border/border-style.ts b/src/file/styles/border/border-style.ts
deleted file mode 100644
index 00f4117d31..0000000000
--- a/src/file/styles/border/border-style.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export enum BorderStyle {
- SINGLE = "single",
- DASH_DOT_STROKED = "dashDotStroked",
- DASHED = "dashed",
- DASH_SMALL_GAP = "dashSmallGap",
- DOT_DASH = "dotDash",
- DOT_DOT_DASH = "dotDotDash",
- DOTTED = "dotted",
- DOUBLE = "double",
- DOUBLE_WAVE = "doubleWave",
- INSET = "inset",
- NIL = "nil",
- NONE = "none",
- OUTSET = "outset",
- THICK = "thick",
- THICK_THIN_LARGE_GAP = "thickThinLargeGap",
- THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
- THICK_THIN_SMALL_GAP = "thickThinSmallGap",
- THIN_THICK_LARGE_GAP = "thinThickLargeGap",
- THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
- THIN_THICK_SMALL_GAP = "thinThickSmallGap",
- THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
- THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
- THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
- THREE_D_EMBOSS = "threeDEmboss",
- THREE_D_ENGRAVE = "threeDEngrave",
- TRIPLE = "triple",
- WAVE = "wave",
-}
diff --git a/src/file/styles/border/index.ts b/src/file/styles/border/index.ts
deleted file mode 100644
index e62e5f7dcc..0000000000
--- a/src/file/styles/border/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./border-style";
diff --git a/src/file/styles/external-styles-factory.spec.ts b/src/file/styles/external-styles-factory.spec.ts
index 2ddc849ae8..9db766008b 100644
--- a/src/file/styles/external-styles-factory.spec.ts
+++ b/src/file/styles/external-styles-factory.spec.ts
@@ -62,19 +62,14 @@ describe("External styles factory", () => {
// tslint:disable-next-line:no-any
const importedStyle = new ExternalStylesFactory().newInstance(externalStyles) as any;
expect(importedStyle.root[1]).to.deep.equal({
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:ascii": "Arial",
"w:cstheme": "minorHAnsi",
@@ -87,10 +82,8 @@ describe("External styles factory", () => {
rootKey: "w:rFonts",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:bidi": "ar-SA",
"w:eastAsia": "en-US",
@@ -108,16 +101,12 @@ describe("External styles factory", () => {
rootKey: "w:rPrDefault",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:after": "160",
"w:line": "259",
@@ -138,10 +127,8 @@ describe("External styles factory", () => {
rootKey: "w:docDefaults",
});
expect(importedStyle.root[2]).to.deep.equal({
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:defLockedState": "1",
"w:defUIPriority": "99",
@@ -165,10 +152,8 @@ describe("External styles factory", () => {
expect(importedStyle.root.length).to.equal(5);
expect(importedStyle.root[3]).to.deep.equal({
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:default": "1",
"w:styleId": "Normal",
@@ -177,10 +162,8 @@ describe("External styles factory", () => {
rootKey: "_attr",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:val": "Normal",
},
@@ -190,7 +173,6 @@ describe("External styles factory", () => {
rootKey: "w:name",
},
{
- deleted: false,
root: [],
rootKey: "w:qFormat",
},
@@ -199,10 +181,8 @@ describe("External styles factory", () => {
});
expect(importedStyle.root[4]).to.deep.equal({
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:styleId": "Heading1",
"w:type": "paragraph",
@@ -210,10 +190,8 @@ describe("External styles factory", () => {
rootKey: "_attr",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:val": "heading 1",
},
@@ -223,10 +201,8 @@ describe("External styles factory", () => {
rootKey: "w:name",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:val": "Normal",
},
@@ -236,26 +212,20 @@ describe("External styles factory", () => {
rootKey: "w:basedOn",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: [],
rootKey: "w:keepNext",
},
{
- deleted: false,
root: [],
rootKey: "w:keepLines",
},
{
- deleted: false,
root: [
{
- deleted: false,
root: [
{
- deleted: false,
root: {
"w:color": "auto",
"w:space": "1",
diff --git a/src/file/styles/style/character-style.spec.ts b/src/file/styles/style/character-style.spec.ts
index 65dcdc26ee..4ddf087f2d 100644
--- a/src/file/styles/style/character-style.spec.ts
+++ b/src/file/styles/style/character-style.spec.ts
@@ -3,7 +3,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import { EmphasisMarkType } from "file/paragraph/run/emphasis-mark";
import { UnderlineType } from "file/paragraph/run/underline";
-import { ShadingType } from "file/table";
+import { ShadingType } from "file/shading";
import { EMPTY_OBJECT } from "file/xml-components";
import { StyleForCharacter } from "./character-style";
@@ -65,9 +65,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -78,6 +75,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:smallCaps": {} }],
+ },
],
});
});
@@ -93,9 +93,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -106,6 +103,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:caps": {} }],
+ },
],
});
});
@@ -121,9 +121,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -134,6 +131,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:strike": {} }],
+ },
],
});
});
@@ -149,9 +149,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -162,6 +159,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:dstrike": {} }],
+ },
],
});
});
@@ -177,6 +177,16 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -188,16 +198,6 @@ describe("CharacterStyle", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
],
});
});
@@ -213,6 +213,16 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -227,16 +237,6 @@ describe("CharacterStyle", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
],
});
});
@@ -255,6 +255,16 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -267,16 +277,6 @@ describe("CharacterStyle", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
],
});
});
@@ -292,9 +292,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:spacing": { _attr: { "w:val": 100 } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -305,6 +302,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:spacing": { _attr: { "w:val": 100 } } }],
+ },
],
});
});
@@ -317,6 +317,7 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ { "w:basedOn": { _attr: { "w:val": "otherId" } } },
{
"w:uiPriority": {
_attr: {
@@ -327,7 +328,6 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
- { "w:basedOn": { _attr: { "w:val": "otherId" } } },
],
});
});
@@ -365,9 +365,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": expected,
- },
{
"w:uiPriority": {
_attr: {
@@ -378,6 +375,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": expected,
+ },
],
});
});
@@ -395,9 +395,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -408,6 +405,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:u": { _attr: { "w:val": "single" } } }],
+ },
],
});
});
@@ -425,9 +425,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:u": { _attr: { "w:val": "double" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -438,6 +435,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:u": { _attr: { "w:val": "double" } } }],
+ },
],
});
});
@@ -456,9 +456,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "005599" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -469,6 +466,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:u": { _attr: { "w:val": "double", "w:color": "005599" } } }],
+ },
],
});
});
@@ -486,9 +486,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:em": { _attr: { "w:val": "dot" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -499,6 +496,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:em": { _attr: { "w:val": "dot" } } }],
+ },
],
});
});
@@ -516,9 +516,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:em": { _attr: { "w:val": "dot" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -529,6 +526,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:em": { _attr: { "w:val": "dot" } } }],
+ },
],
});
});
@@ -545,6 +545,16 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -556,16 +566,6 @@ describe("CharacterStyle", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
],
});
});
@@ -581,9 +581,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": [{ "w:color": { _attr: { "w:val": "123456" } } }],
- },
{
"w:uiPriority": {
_attr: {
@@ -594,6 +591,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": [{ "w:color": { _attr: { "w:val": "123456" } } }],
+ },
],
});
});
@@ -601,17 +601,17 @@ describe("CharacterStyle", () => {
const boldTests = [
{
bold: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: false,
- expected: [{ "w:b": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }],
},
];
boldTests.forEach(({ bold, boldComplexScript, expected }) => {
@@ -624,9 +624,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": expected,
- },
{
"w:uiPriority": {
_attr: {
@@ -637,6 +634,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": expected,
+ },
],
});
});
@@ -645,17 +645,17 @@ describe("CharacterStyle", () => {
const italicsTests = [
{
italics: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: false,
- expected: [{ "w:i": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }],
},
];
italicsTests.forEach(({ italics, italicsComplexScript, expected }) => {
@@ -668,9 +668,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": expected,
- },
{
"w:uiPriority": {
_attr: {
@@ -681,6 +678,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": expected,
+ },
],
});
});
@@ -692,6 +692,7 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
+ { "w:link": { _attr: { "w:val": "MyLink" } } },
{
"w:uiPriority": {
_attr: {
@@ -702,7 +703,6 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
- { "w:link": { _attr: { "w:val": "MyLink" } } },
],
});
});
@@ -720,8 +720,8 @@ describe("CharacterStyle", () => {
},
},
},
- { "w:unhideWhenUsed": EMPTY_OBJECT },
{ "w:semiHidden": EMPTY_OBJECT },
+ { "w:unhideWhenUsed": EMPTY_OBJECT },
],
});
});
@@ -757,9 +757,6 @@ describe("CharacterStyle", () => {
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": expected,
- },
{
"w:uiPriority": {
_attr: {
@@ -770,20 +767,15 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": expected,
+ },
],
});
});
});
const shadingTests = [
- {
- shadow: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
{
shading: {
type: ShadingType.PERCENT_10,
@@ -794,42 +786,23 @@ describe("CharacterStyle", () => {
},
{
shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
+ type: ShadingType.SOLID,
+ fill: "AA0000",
+ color: "DD0000",
},
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
+ expected: [{ "w:shd": { _attr: { "w:val": "solid", "w:fill": "AA0000", "w:color": "DD0000" } } }],
},
];
- shadingTests.forEach(({ shadow, shading, expected }) => {
+ shadingTests.forEach(({ shading, expected }) => {
it("#shadow correctly", () => {
const style = new StyleForCharacter({
id: "myStyleId",
- run: { shadow, shading },
+ run: { shading },
});
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "myStyleId" } },
- {
- "w:rPr": expected,
- },
{
"w:uiPriority": {
_attr: {
@@ -840,6 +813,9 @@ describe("CharacterStyle", () => {
{
"w:unhideWhenUsed": EMPTY_OBJECT,
},
+ {
+ "w:rPr": expected,
+ },
],
});
});
diff --git a/src/file/styles/style/character-style.ts b/src/file/styles/style/character-style.ts
index 63252bddd5..229c8e54c6 100644
--- a/src/file/styles/style/character-style.ts
+++ b/src/file/styles/style/character-style.ts
@@ -1,12 +1,8 @@
import { IRunStylePropertiesOptions, RunProperties } from "file/paragraph/run/properties";
-import { BasedOn, Link, SemiHidden, UiPriority, UnhideWhenUsed } from "./components";
-import { Style } from "./style";
+import { IStyleOptions, Style } from "./style";
-export interface IBaseCharacterStyleOptions {
- readonly basedOn?: string;
- readonly link?: string;
- readonly semiHidden?: boolean;
+export interface IBaseCharacterStyleOptions extends IStyleOptions {
readonly run?: IRunStylePropertiesOptions;
}
@@ -19,24 +15,16 @@ export class StyleForCharacter extends Style {
private readonly runProperties: RunProperties;
constructor(options: ICharacterStyleOptions) {
- super({ type: "character", styleId: options.id }, options.name);
+ super(
+ { type: "character", styleId: options.id },
+ {
+ uiPriority: 99,
+ unhideWhenUsed: true,
+ ...options,
+ },
+ );
this.runProperties = new RunProperties(options.run);
-
this.root.push(this.runProperties);
- this.root.push(new UiPriority(99));
- this.root.push(new UnhideWhenUsed());
-
- if (options.basedOn) {
- this.root.push(new BasedOn(options.basedOn));
- }
-
- if (options.link) {
- this.root.push(new Link(options.link));
- }
-
- if (options.semiHidden) {
- this.root.push(new SemiHidden());
- }
}
}
diff --git a/src/file/styles/style/components.spec.ts b/src/file/styles/style/components.spec.ts
index b1720ef4b4..7ce7df62ab 100644
--- a/src/file/styles/style/components.spec.ts
+++ b/src/file/styles/style/components.spec.ts
@@ -2,8 +2,6 @@ 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");
@@ -11,45 +9,9 @@ describe("Style components", () => {
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" } } });
- });
-
- 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" } } });
- });
-
- 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" } } });
- });
-
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 } } });
});
-
- it("UnhideWhenUsed#constructor", () => {
- const style = new components.UnhideWhenUsed();
- const tree = new Formatter().format(style);
- 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": EMPTY_OBJECT });
- });
-
- it("SemiHidden#constructor", () => {
- const style = new components.SemiHidden();
- const tree = new Formatter().format(style);
- expect(tree).to.deep.equal({ "w:semiHidden": EMPTY_OBJECT });
- });
});
diff --git a/src/file/styles/style/components.ts b/src/file/styles/style/components.ts
index e8a217c638..4b35ba38b3 100644
--- a/src/file/styles/style/components.ts
+++ b/src/file/styles/style/components.ts
@@ -1,4 +1,5 @@
// http://officeopenxml.com/WPstyleGenProps.php
+import { decimalNumber } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
class ComponentAttributes extends XmlAttributeComponent<{
@@ -14,53 +15,13 @@ export class Name extends XmlComponent {
}
}
-export class BasedOn extends XmlComponent {
- constructor(value: string) {
- super("w:basedOn");
- this.root.push(new ComponentAttributes({ val: value }));
- }
-}
-
-export class Next extends XmlComponent {
- constructor(value: string) {
- super("w:next");
- this.root.push(new ComponentAttributes({ val: value }));
- }
-}
-
-export class Link extends XmlComponent {
- constructor(value: string) {
- super("w:link");
- this.root.push(new ComponentAttributes({ val: value }));
- }
-}
-
export class UiPriority extends XmlComponent {
constructor(value: number) {
super("w:uiPriority");
- // TODO: this value should be a ST_DecimalNumber
- this.root.push(new ComponentAttributes({ val: value }));
- }
-}
-
-export class UnhideWhenUsed extends XmlComponent {
- constructor() {
- super("w:unhideWhenUsed");
- }
-}
-
-export class QuickFormat extends XmlComponent {
- constructor() {
- super("w:qFormat");
+ this.root.push(new ComponentAttributes({ val: decimalNumber(value) }));
}
}
export class TableProperties extends XmlComponent {}
export class RsId extends XmlComponent {}
-
-export class SemiHidden extends XmlComponent {
- constructor() {
- super("w:semiHidden");
- }
-}
diff --git a/src/file/styles/style/default-styles.spec.ts b/src/file/styles/style/default-styles.spec.ts
index 962f47d9c0..dda921a110 100644
--- a/src/file/styles/style/default-styles.spec.ts
+++ b/src/file/styles/style/default-styles.spec.ts
@@ -154,6 +154,21 @@ describe("Default Styles", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "FootnoteText" } },
{ "w:name": { _attr: { "w:val": "footnote text" } } },
+ { "w:basedOn": { _attr: { "w:val": "Normal" } } },
+ { "w:link": { _attr: { "w:val": "FootnoteTextChar" } } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:semiHidden": EMPTY_OBJECT,
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:pPr": [
{
@@ -185,21 +200,6 @@ describe("Default Styles", () => {
},
],
},
- { "w:basedOn": { _attr: { "w:val": "Normal" } } },
- { "w:link": { _attr: { "w:val": "FootnoteTextChar" } } },
- {
- "w:semiHidden": EMPTY_OBJECT,
- },
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
],
});
});
@@ -211,6 +211,20 @@ describe("Default Styles", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "FootnoteReference" } },
{ "w:name": { _attr: { "w:val": "footnote reference" } } },
+ { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:semiHidden": EMPTY_OBJECT,
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -222,21 +236,6 @@ describe("Default Styles", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
- { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
-
- {
- "w:semiHidden": EMPTY_OBJECT,
- },
],
});
});
@@ -248,6 +247,21 @@ describe("Default Styles", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "FootnoteTextChar" } },
{ "w:name": { _attr: { "w:val": "Footnote Text Char" } } },
+ { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
+ { "w:link": { _attr: { "w:val": "FootnoteText" } } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:semiHidden": EMPTY_OBJECT,
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{
@@ -266,21 +280,6 @@ describe("Default Styles", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
- { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
- { "w:link": { _attr: { "w:val": "FootnoteText" } } },
- {
- "w:semiHidden": EMPTY_OBJECT,
- },
],
});
});
@@ -292,6 +291,17 @@ describe("Default Styles", () => {
"w:style": [
{ _attr: { "w:type": "character", "w:styleId": "Hyperlink" } },
{ "w:name": { _attr: { "w:val": "Hyperlink" } } },
+ { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
+ {
+ "w:uiPriority": {
+ _attr: {
+ "w:val": 99,
+ },
+ },
+ },
+ {
+ "w:unhideWhenUsed": EMPTY_OBJECT,
+ },
{
"w:rPr": [
{ "w:u": { _attr: { "w:val": "single" } } },
@@ -304,17 +314,6 @@ describe("Default Styles", () => {
},
],
},
- {
- "w:uiPriority": {
- _attr: {
- "w:val": 99,
- },
- },
- },
- {
- "w:unhideWhenUsed": EMPTY_OBJECT,
- },
- { "w:basedOn": { _attr: { "w:val": "DefaultParagraphFont" } } },
],
});
});
diff --git a/src/file/styles/style/paragraph-style.spec.ts b/src/file/styles/style/paragraph-style.spec.ts
index 0885181c0c..28f229677b 100644
--- a/src/file/styles/style/paragraph-style.spec.ts
+++ b/src/file/styles/style/paragraph-style.spec.ts
@@ -3,7 +3,7 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
import { AlignmentType, EmphasisMarkType, TabStopPosition } from "file/paragraph";
import { UnderlineType } from "file/paragraph/run/underline";
-import { ShadingType } from "file/table";
+import { ShadingType } from "file/shading";
import { EMPTY_OBJECT } from "file/xml-components";
import { StyleForParagraph } from "./paragraph-style";
@@ -78,7 +78,7 @@ describe("ParagraphStyle", () => {
const style = new StyleForParagraph({
id: "myStyleId",
paragraph: {
- indent: { left: 720 },
+ indent: { left: 720, right: 500 },
},
});
const tree = new Formatter().format(style);
@@ -86,7 +86,7 @@ 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:right": 500 } } }],
},
],
});
@@ -242,11 +242,7 @@ describe("ParagraphStyle", () => {
{
"w:pPr": [
{
- "w:contextualSpacing": {
- _attr: {
- "w:val": 1,
- },
- },
+ "w:contextualSpacing": {},
},
],
},
@@ -404,7 +400,7 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
- "w:rPr": [{ "w:smallCaps": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:smallCaps": {} }],
},
],
});
@@ -422,7 +418,7 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
- "w:rPr": [{ "w:caps": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:caps": {} }],
},
],
});
@@ -440,7 +436,7 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
- "w:rPr": [{ "w:strike": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:strike": {} }],
},
],
});
@@ -458,7 +454,7 @@ describe("ParagraphStyle", () => {
"w:style": [
{ _attr: { "w:type": "paragraph", "w:styleId": "myStyleId" } },
{
- "w:rPr": [{ "w:dstrike": { _attr: { "w:val": true } } }],
+ "w:rPr": [{ "w:dstrike": {} }],
},
],
});
@@ -562,17 +558,17 @@ describe("ParagraphStyle", () => {
const boldTests = [
{
bold: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: true,
- expected: [{ "w:b": { _attr: { "w:val": true } } }, { "w:bCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }, { "w:bCs": {} }],
},
{
bold: true,
boldComplexScript: false,
- expected: [{ "w:b": { _attr: { "w:val": true } } }],
+ expected: [{ "w:b": {} }],
},
];
boldTests.forEach(({ bold, boldComplexScript, expected }) => {
@@ -591,17 +587,17 @@ describe("ParagraphStyle", () => {
const italicsTests = [
{
italics: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: true,
- expected: [{ "w:i": { _attr: { "w:val": true } } }, { "w:iCs": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }, { "w:iCs": {} }],
},
{
italics: true,
italicsComplexScript: false,
- expected: [{ "w:i": { _attr: { "w:val": true } } }],
+ expected: [{ "w:i": {} }],
},
];
italicsTests.forEach(({ italics, italicsComplexScript, expected }) => {
@@ -652,14 +648,6 @@ describe("ParagraphStyle", () => {
});
const shadingTests = [
- {
- shadow: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
{
shading: {
type: ShadingType.PERCENT_10,
@@ -670,34 +658,18 @@ describe("ParagraphStyle", () => {
},
{
shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
+ type: ShadingType.DIAGONAL_CROSS,
+ fill: "0066FF",
+ color: "0000FF",
},
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
- },
- {
- shading: {
- type: ShadingType.PERCENT_10,
- fill: "00FFFF",
- color: "FF0000",
- },
- expected: [{ "w:shd": { _attr: { "w:val": "pct10", "w:fill": "00FFFF", "w:color": "FF0000" } } }],
+ expected: [{ "w:shd": { _attr: { "w:val": "diagCross", "w:fill": "0066FF", "w:color": "0000FF" } } }],
},
];
- shadingTests.forEach(({ shadow, shading, expected }) => {
- it("#shadow correctly", () => {
+ shadingTests.forEach(({ shading, expected }) => {
+ it("#shade correctly", () => {
const style = new StyleForParagraph({
id: "myStyleId",
- run: { shadow, shading },
+ run: { shading },
});
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
diff --git a/src/file/styles/style/paragraph-style.ts b/src/file/styles/style/paragraph-style.ts
index 25c035e514..5f90a87fe2 100644
--- a/src/file/styles/style/paragraph-style.ts
+++ b/src/file/styles/style/paragraph-style.ts
@@ -1,17 +1,8 @@
import { IParagraphStylePropertiesOptions, IRunStylePropertiesOptions, ParagraphProperties } from "file/paragraph";
import { RunProperties } from "file/paragraph/run/properties";
+import { IStyleOptions, Style } from "./style";
-import { BasedOn, Link, Next, QuickFormat, SemiHidden, UiPriority, UnhideWhenUsed } from "./components";
-import { Style } from "./style";
-
-export interface IBaseParagraphStyleOptions {
- readonly basedOn?: string;
- readonly next?: string;
- readonly quickFormat?: boolean;
- readonly link?: string;
- readonly semiHidden?: boolean;
- readonly uiPriority?: number;
- readonly unhideWhenUsed?: boolean;
+export interface IBaseParagraphStyleOptions extends IStyleOptions {
readonly paragraph?: IParagraphStylePropertiesOptions;
readonly run?: IRunStylePropertiesOptions;
}
@@ -26,40 +17,12 @@ export class StyleForParagraph extends Style {
private readonly runProperties: RunProperties;
constructor(options: IParagraphStyleOptions) {
- super({ type: "paragraph", styleId: options.id }, options.name);
+ super({ type: "paragraph", styleId: options.id }, options);
this.paragraphProperties = new ParagraphProperties(options.paragraph);
this.runProperties = new RunProperties(options.run);
this.root.push(this.paragraphProperties);
this.root.push(this.runProperties);
-
- if (options.basedOn) {
- this.root.push(new BasedOn(options.basedOn));
- }
-
- if (options.next) {
- this.root.push(new Next(options.next));
- }
-
- if (options.quickFormat) {
- this.root.push(new QuickFormat());
- }
-
- if (options.link) {
- this.root.push(new Link(options.link));
- }
-
- if (options.semiHidden) {
- this.root.push(new SemiHidden());
- }
-
- if (options.uiPriority) {
- this.root.push(new UiPriority(options.uiPriority));
- }
-
- if (options.unhideWhenUsed) {
- this.root.push(new UnhideWhenUsed());
- }
}
}
diff --git a/src/file/styles/style/style.spec.ts b/src/file/styles/style/style.spec.ts
index 55f55bd398..4135272e5d 100644
--- a/src/file/styles/style/style.spec.ts
+++ b/src/file/styles/style/style.spec.ts
@@ -5,11 +5,14 @@ import { Style } from "./style";
describe("Style", () => {
describe("#constructor()", () => {
it("should set the given properties", () => {
- const style = new Style({
- type: "paragraph",
- styleId: "myStyleId",
- default: true,
- });
+ const style = new Style(
+ {
+ type: "paragraph",
+ styleId: "myStyleId",
+ default: true,
+ },
+ {},
+ );
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
"w:style": { _attr: { "w:type": "paragraph", "w:styleId": "myStyleId", "w:default": true } },
@@ -22,7 +25,7 @@ describe("Style", () => {
type: "paragraph",
styleId: "myStyleId",
},
- "Style Name",
+ { name: "Style Name" },
);
const tree = new Formatter().format(style);
expect(tree).to.deep.equal({
diff --git a/src/file/styles/style/style.ts b/src/file/styles/style/style.ts
index d0d69f17ed..767539503b 100644
--- a/src/file/styles/style/style.ts
+++ b/src/file/styles/style/style.ts
@@ -1,5 +1,36 @@
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-import { Name } from "./components";
+import { OnOffElement, StringValueElement, XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { Name, UiPriority } from "./components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
export interface IStyleAttributes {
readonly type?: string;
@@ -8,6 +39,17 @@ export interface IStyleAttributes {
readonly customStyle?: string;
}
+export interface IStyleOptions {
+ readonly name?: string;
+ readonly basedOn?: string;
+ readonly next?: string;
+ readonly link?: string;
+ readonly uiPriority?: number;
+ readonly semiHidden?: boolean;
+ readonly unhideWhenUsed?: boolean;
+ readonly quickFormat?: boolean;
+}
+
class StyleAttributes extends XmlAttributeComponent {
protected readonly xmlKeys = {
type: "w:type",
@@ -18,11 +60,39 @@ class StyleAttributes extends XmlAttributeComponent {
}
export class Style extends XmlComponent {
- constructor(attributes: IStyleAttributes, name?: string) {
+ constructor(attributes: IStyleAttributes, options: IStyleOptions) {
super("w:style");
this.root.push(new StyleAttributes(attributes));
- if (name) {
- this.root.push(new Name(name));
+ if (options.name) {
+ this.root.push(new Name(options.name));
+ }
+
+ if (options.basedOn) {
+ this.root.push(new StringValueElement("w:basedOn", options.basedOn));
+ }
+
+ if (options.next) {
+ this.root.push(new StringValueElement("w:next", options.next));
+ }
+
+ if (options.link) {
+ this.root.push(new StringValueElement("w:link", options.link));
+ }
+
+ if (options.uiPriority !== undefined) {
+ this.root.push(new UiPriority(options.uiPriority));
+ }
+
+ if (options.semiHidden !== undefined) {
+ this.root.push(new OnOffElement("w:semiHidden", options.semiHidden));
+ }
+
+ if (options.unhideWhenUsed !== undefined) {
+ this.root.push(new OnOffElement("w:unhideWhenUsed", options.unhideWhenUsed));
+ }
+
+ if (options.quickFormat !== undefined) {
+ this.root.push(new OnOffElement("w:qFormat", options.quickFormat));
}
}
}
diff --git a/src/file/styles/styles.ts b/src/file/styles/styles.ts
index 1906b45ba0..e37fe8c263 100644
--- a/src/file/styles/styles.ts
+++ b/src/file/styles/styles.ts
@@ -3,7 +3,6 @@ import { BaseXmlComponent, ImportedXmlComponent, XmlComponent } from "file/xml-c
import { StyleForCharacter, StyleForParagraph } from "./style";
import { ICharacterStyleOptions } from "./style/character-style";
import { IParagraphStyleOptions } from "./style/paragraph-style";
-export * from "./border";
export interface IStylesOptions {
readonly default?: IDefaultStylesOptions;
@@ -13,6 +12,13 @@ export interface IStylesOptions {
readonly importedStyles?: (XmlComponent | StyleForParagraph | StyleForCharacter | ImportedXmlComponent)[];
}
+//
+//
+//
+//
+//
+//
+//
export class Styles extends XmlComponent {
constructor(options: IStylesOptions) {
super("w:styles");
diff --git a/src/file/table/grid.ts b/src/file/table/grid.ts
index 5ce6486fcc..b8a683f255 100644
--- a/src/file/table/grid.ts
+++ b/src/file/table/grid.ts
@@ -1,8 +1,19 @@
// http://officeopenxml.com/WPtableGrid.php
+
+//
+//
+//
+//
+//
+//
+//
+//
+
+import { twipsMeasureValue } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
export class TableGrid extends XmlComponent {
- constructor(widths: number[]) {
+ constructor(widths: number[] | string[]) {
super("w:tblGrid");
for (const width of widths) {
this.root.push(new GridCol(width));
@@ -10,15 +21,15 @@ export class TableGrid extends XmlComponent {
}
}
-class GridColAttributes extends XmlAttributeComponent<{ readonly w: number }> {
+class GridColAttributes extends XmlAttributeComponent<{ readonly w: number | string }> {
protected readonly xmlKeys = { w: "w:w" };
}
export class GridCol extends XmlComponent {
- constructor(width?: number) {
+ constructor(width?: number | string) {
super("w:gridCol");
if (width !== undefined) {
- this.root.push(new GridColAttributes({ w: width }));
+ this.root.push(new GridColAttributes({ w: twipsMeasureValue(width) }));
}
}
}
diff --git a/src/file/table/index.ts b/src/file/table/index.ts
index cec3788f8e..81ceac8b1a 100644
--- a/src/file/table/index.ts
+++ b/src/file/table/index.ts
@@ -1,5 +1,5 @@
export * from "./table";
export * from "./table-cell";
export * from "./table-properties";
-export * from "./shading";
export * from "./table-row";
+export * from "./table-width";
diff --git a/src/file/table/shading/shading.ts b/src/file/table/shading/shading.ts
deleted file mode 100644
index baeb426e22..0000000000
--- a/src/file/table/shading/shading.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-// http://officeopenxml.com/WPtableShading.php
-// http://officeopenxml.com/WPtableCellProperties-Shading.php
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-export interface ITableShadingAttributesProperties {
- readonly fill?: string;
- readonly color?: string;
- readonly val?: ShadingType;
-}
-
-class TableShadingAttributes extends XmlAttributeComponent {
- protected readonly xmlKeys = {
- fill: "w:fill",
- color: "w:color",
- val: "w:val",
- };
-}
-
-export class TableShading extends XmlComponent {
- constructor(attrs: ITableShadingAttributesProperties) {
- super("w:shd");
- this.root.push(new TableShadingAttributes(attrs));
- }
-}
-
-export enum ShadingType {
- CLEAR = "clear",
- DIAGONAL_CROSS = "diagCross",
- DIAGONAL_STRIPE = "diagStripe",
- HORIZONTAL_CROSS = "horzCross",
- HORIZONTAL_STRIPE = "horzStripe",
- NIL = "nil",
- PERCENT_5 = "pct5",
- PERCENT_10 = "pct10",
- PERCENT_12 = "pct12",
- PERCENT_15 = "pct15",
- PERCENT_20 = "pct20",
- PERCENT_25 = "pct25",
- PERCENT_30 = "pct30",
- PERCENT_35 = "pct35",
- PERCENT_37 = "pct37",
- PERCENT_40 = "pct40",
- PERCENT_45 = "pct45",
- PERCENT_50 = "pct50",
- PERCENT_55 = "pct55",
- PERCENT_60 = "pct60",
- PERCENT_62 = "pct62",
- PERCENT_65 = "pct65",
- PERCENT_70 = "pct70",
- PERCENT_75 = "pct75",
- PERCENT_80 = "pct80",
- PERCENT_85 = "pct85",
- PERCENT_87 = "pct87",
- PERCENT_90 = "pct90",
- PERCENT_95 = "pct95",
- REVERSE_DIAGONAL_STRIPE = "reverseDiagStripe",
- SOLID = "solid",
- THIN_DIAGONAL_CROSS = "thinDiagCross",
- THIN_DIAGONAL_STRIPE = "thinDiagStripe",
- THIN_HORIZONTAL_CROSS = "thinHorzCross",
- THIN_REVERSE_DIAGONAL_STRIPE = "thinReverseDiagStripe",
- THIN_VERTICAL_STRIPE = "thinVertStripe",
- VERTICAL_STRIPE = "vertStripe",
-}
diff --git a/src/file/table/table-cell/cell-margin/cell-margin.spec.ts b/src/file/table/table-cell/cell-margin/cell-margin.spec.ts
deleted file mode 100644
index 399020a2d2..0000000000
--- a/src/file/table/table-cell/cell-margin/cell-margin.spec.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-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,
- },
- },
- });
- });
- });
-});
diff --git a/src/file/table/table-cell/cell-margin/cell-margin.ts b/src/file/table/table-cell/cell-margin/cell-margin.ts
deleted file mode 100644
index 090f83367a..0000000000
--- a/src/file/table/table-cell/cell-margin/cell-margin.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-// http://officeopenxml.com/WPtableCellProperties-Margins.php
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-class CellMarginAttributes extends XmlAttributeComponent<{
- readonly type: string;
- readonly width: number;
-}> {
- protected readonly xmlKeys = { width: "w:w", type: "w:type" };
-}
-
-export class TopCellMargin extends XmlComponent {
- constructor(value: number) {
- super("w:top");
-
- this.root.push(
- new CellMarginAttributes({
- width: value,
- type: "dxa",
- }),
- );
- }
-}
-
-export class BottomCellMargin extends XmlComponent {
- constructor(value: number) {
- super("w:bottom");
-
- this.root.push(
- new CellMarginAttributes({
- width: value,
- type: "dxa",
- }),
- );
- }
-}
-
-export class LeftCellMargin extends XmlComponent {
- constructor(value: number) {
- super("w:start");
-
- this.root.push(
- new CellMarginAttributes({
- width: value,
- type: "dxa",
- }),
- );
- }
-}
-
-export class RightCellMargin extends XmlComponent {
- constructor(value: number) {
- super("w:end");
-
- this.root.push(
- new CellMarginAttributes({
- width: value,
- type: "dxa",
- }),
- );
- }
-}
diff --git a/src/file/table/table-cell/cell-margin/table-cell-margins.spec.ts b/src/file/table/table-cell/cell-margin/table-cell-margins.spec.ts
deleted file mode 100644
index 8777ec5a9b..0000000000
--- a/src/file/table/table-cell/cell-margin/table-cell-margins.spec.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-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:start": {
- _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,
- },
- },
- },
- ],
- });
- });
-
- 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:start": {
- _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,
- },
- },
- },
- ],
- });
- });
- });
-});
diff --git a/src/file/table/table-cell/cell-margin/table-cell-margins.ts b/src/file/table/table-cell/cell-margin/table-cell-margins.ts
deleted file mode 100644
index efb2beb5bd..0000000000
--- a/src/file/table/table-cell/cell-margin/table-cell-margins.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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 LeftCellMargin(left));
- this.root.push(new BottomCellMargin(bottom));
- this.root.push(new RightCellMargin(right));
- }
-}
diff --git a/src/file/table/table-cell/table-cell-components.ts b/src/file/table/table-cell/table-cell-components.ts
index 41858d4e17..e57785a19f 100644
--- a/src/file/table/table-cell/table-cell-components.ts
+++ b/src/file/table/table-cell/table-cell-components.ts
@@ -1,78 +1,53 @@
-import { BorderStyle } from "file/styles";
+import { BorderElement, IBorderOptions } from "file/border";
+import { decimalNumber } from "file/values";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
-class CellBorderAttributes extends XmlAttributeComponent<{
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
-}> {
- protected readonly xmlKeys = { style: "w:val", size: "w:sz", color: "w:color" };
-}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
-class BaseTableCellBorder extends XmlComponent {
- public setProperties(style: BorderStyle, size: number, color: string): BaseTableCellBorder {
- const attrs = new CellBorderAttributes({
- style: style,
- size: size,
- color: color,
- });
- this.root.push(attrs);
-
- return this;
- }
+export interface ITableCellBorders {
+ readonly top?: IBorderOptions;
+ readonly start?: IBorderOptions;
+ readonly left?: IBorderOptions;
+ readonly bottom?: IBorderOptions;
+ readonly end?: IBorderOptions;
+ readonly right?: IBorderOptions;
}
export class TableCellBorders extends IgnoreIfEmptyXmlComponent {
- constructor() {
+ constructor(options: ITableCellBorders) {
super("w:tcBorders");
- }
- public addTopBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const top = new BaseTableCellBorder("w:top");
- top.setProperties(style, size, color);
- this.root.push(top);
-
- return this;
- }
-
- public addStartBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const start = new BaseTableCellBorder("w:start");
- start.setProperties(style, size, color);
- this.root.push(start);
-
- return this;
- }
-
- public addBottomBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const bottom = new BaseTableCellBorder("w:bottom");
- bottom.setProperties(style, size, color);
- this.root.push(bottom);
-
- return this;
- }
-
- public addEndBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const end = new BaseTableCellBorder("w:end");
- end.setProperties(style, size, color);
- this.root.push(end);
-
- return this;
- }
-
- public addLeftBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const left = new BaseTableCellBorder("w:left");
- left.setProperties(style, size, color);
- this.root.push(left);
-
- return this;
- }
-
- public addRightBorder(style: BorderStyle, size: number, color: string): TableCellBorders {
- const right = new BaseTableCellBorder("w:right");
- right.setProperties(style, size, color);
- this.root.push(right);
-
- return this;
+ if (options.top) {
+ this.root.push(new BorderElement("w:top", options.top));
+ }
+ if (options.start) {
+ this.root.push(new BorderElement("w:start", options.start));
+ }
+ if (options.left) {
+ this.root.push(new BorderElement("w:left", options.left));
+ }
+ if (options.bottom) {
+ this.root.push(new BorderElement("w:bottom", options.bottom));
+ }
+ if (options.end) {
+ this.root.push(new BorderElement("w:end", options.end));
+ }
+ if (options.right) {
+ this.root.push(new BorderElement("w:right", options.right));
+ }
}
}
@@ -83,6 +58,10 @@ class GridSpanAttributes extends XmlAttributeComponent<{ readonly val: number }>
protected readonly xmlKeys = { val: "w:val" };
}
+//
+// ...
+//
+//
/**
* GridSpan element. Should be used in a table cell. Pass the number of columns that this cell need to span.
*/
@@ -92,7 +71,7 @@ export class GridSpan extends XmlComponent {
this.root.push(
new GridSpanAttributes({
- val: value,
+ val: decimalNumber(value),
}),
);
}
@@ -131,31 +110,6 @@ export class VerticalMerge extends XmlComponent {
}
}
-export enum VerticalAlign {
- BOTTOM = "bottom",
- CENTER = "center",
- TOP = "top",
-}
-
-class VAlignAttributes extends XmlAttributeComponent<{ readonly val: VerticalAlign }> {
- protected readonly xmlKeys = { val: "w:val" };
-}
-
-/**
- * Vertical align element.
- */
-export class VAlign extends XmlComponent {
- constructor(value: VerticalAlign) {
- super("w:vAlign");
-
- this.root.push(
- new VAlignAttributes({
- val: value,
- }),
- );
- }
-}
-
export enum TextDirection {
BOTTOM_TO_TOP_LEFT_TO_RIGHT = "btLr",
LEFT_TO_RIGHT_TOP_TO_BOTTOM = "lrTb",
@@ -180,34 +134,3 @@ export class TDirection extends XmlComponent {
);
}
}
-
-export enum WidthType {
- /** Auto. */
- AUTO = "auto",
- /** Value is in twentieths of a point */
- DXA = "dxa",
- /** No (empty) value. */
- NIL = "nil",
- /** Value is in percentage. */
- PERCENTAGE = "pct",
-}
-
-class TableCellWidthAttributes extends XmlAttributeComponent<{ readonly type: WidthType; readonly width: string | number }> {
- protected readonly xmlKeys = { width: "w:w", type: "w:type" };
-}
-
-/**
- * Table cell width element.
- */
-export class TableCellWidth extends XmlComponent {
- constructor(value: string | number, type: WidthType) {
- super("w:tcW");
-
- this.root.push(
- new TableCellWidthAttributes({
- width: value,
- type: type,
- }),
- );
- }
-}
diff --git a/src/file/table/table-cell/table-cell-properties.spec.ts b/src/file/table/table-cell/table-cell-properties.spec.ts
index 24c17b674c..03bd2adc3b 100644
--- a/src/file/table/table-cell/table-cell-properties.spec.ts
+++ b/src/file/table/table-cell/table-cell-properties.spec.ts
@@ -1,137 +1,114 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { BorderStyle } from "file/styles";
+import { BorderStyle } from "file/border";
+import { VerticalAlign } from "file/vertical-align";
-import { VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components";
+import { WidthType } from "../table-width";
+
+import { VerticalMergeType } from "./table-cell-components";
import { TableCellProperties } from "./table-cell-properties";
describe("TableCellProperties", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
- const properties = new TableCellProperties();
+ 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 properties = new TableCellProperties();
- properties.addGridSpan(1);
+ const properties = new TableCellProperties({ columnSpan: 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 properties = new TableCellProperties();
- properties.addVerticalMerge(VerticalMergeType.CONTINUE);
+ const properties = new TableCellProperties({ verticalMerge: VerticalMergeType.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 properties = new TableCellProperties();
- properties.setVerticalAlign(VerticalAlign.BOTTOM);
+ const properties = new TableCellProperties({ verticalAlign: 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 properties = new TableCellProperties();
- properties.setWidth(1, WidthType.DXA);
+ const properties = new TableCellProperties({
+ width: {
+ size: 1,
+ type: 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 properties = new TableCellProperties();
- properties.setWidth(1);
+ const properties = new TableCellProperties({
+ width: {
+ size: 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 properties = new TableCellProperties();
- properties.setShading({
- fill: "test",
- color: "000",
+ const properties = new TableCellProperties({
+ shading: {
+ fill: "ffffff",
+ color: "000000",
+ },
});
const tree = new Formatter().format(properties);
- expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": { _attr: { "w:fill": "test", "w:color": "000" } } }] });
+ expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": { _attr: { "w:fill": "ffffff", "w:color": "000000" } } }] });
});
- });
- describe("#addMargins", () => {
- it("sets shading", () => {
- const properties = new TableCellProperties();
- properties.addMargins({});
- const tree = new Formatter().format(properties);
- expect(tree).to.deep.equal({
- "w:tcPr": [
- {
- "w:tcMar": [
- {
- "w:top": {
- _attr: {
- "w:type": "dxa",
- "w:w": 0,
- },
- },
- },
- {
- "w:start": {
- _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,
- },
- },
- },
- ],
+ it("should set the TableCellBorders", () => {
+ const properties = new TableCellProperties({
+ borders: {
+ top: {
+ style: BorderStyle.DASH_DOT_STROKED,
+ color: "ff0000",
+ size: 3,
},
+ },
+ });
+
+ const tree = new Formatter().format(properties);
+
+ expect(tree["w:tcPr"][0]).to.deep.equal({
+ "w:tcBorders": [{ "w:top": { _attr: { "w:val": "dashDotStroked", "w:sz": 3, "w:color": "ff0000" } } }],
+ });
+ });
+
+ it("should set the margins", () => {
+ const properties = new TableCellProperties({
+ margins: {
+ marginUnitType: WidthType.DXA,
+ top: 5,
+ left: 10,
+ bottom: 15,
+ right: 20,
+ },
+ });
+
+ const tree = new Formatter().format(properties);
+
+ expect(tree["w:tcPr"][0]).to.deep.equal({
+ "w:tcMar": [
+ { "w:top": { _attr: { "w:type": "dxa", "w:w": 5 } } },
+ { "w:left": { _attr: { "w:type": "dxa", "w:w": 10 } } },
+ { "w:bottom": { _attr: { "w:type": "dxa", "w:w": 15 } } },
+ { "w:right": { _attr: { "w:type": "dxa", "w:w": 20 } } },
],
});
});
});
-
- describe("#Borders", () => {
- it("should return the TableCellBorders if Border has 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" } } }],
- });
- });
- });
});
diff --git a/src/file/table/table-cell/table-cell-properties.ts b/src/file/table/table-cell/table-cell-properties.ts
index 68f21e22dc..a10808ef7c 100644
--- a/src/file/table/table-cell/table-cell-properties.ts
+++ b/src/file/table/table-cell/table-cell-properties.ts
@@ -1,77 +1,68 @@
+import { VerticalAlign, VerticalAlignElement } from "file/vertical-align";
import { IgnoreIfEmptyXmlComponent } from "file/xml-components";
-import { ITableShadingAttributesProperties, TableShading } from "../shading";
-import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins";
+import { IShadingAttributesProperties, Shading } from "../../shading";
+import { ITableCellMarginOptions, TableCellMargin, TableCellMarginElementType } from "../table-properties/table-cell-margin";
+import { ITableWidthProperties, TableWidthElement } from "../table-width";
import {
GridSpan,
+ ITableCellBorders,
TableCellBorders,
- TableCellWidth,
TDirection,
TextDirection,
- VAlign,
- VerticalAlign,
VerticalMerge,
VerticalMergeType,
- WidthType,
} from "./table-cell-components";
+export interface ITableCellPropertiesOptions {
+ readonly shading?: IShadingAttributesProperties;
+ readonly margins?: ITableCellMarginOptions;
+ readonly verticalAlign?: VerticalAlign;
+ readonly textDirection?: TextDirection;
+ readonly verticalMerge?: VerticalMergeType;
+ readonly width?: ITableWidthProperties;
+ readonly columnSpan?: number;
+ readonly rowSpan?: number;
+ readonly borders?: ITableCellBorders;
+}
+
export class TableCellProperties extends IgnoreIfEmptyXmlComponent {
- private readonly cellBorder: TableCellBorders;
-
- constructor() {
+ constructor(options: ITableCellPropertiesOptions) {
super("w:tcPr");
- this.cellBorder = new TableCellBorders();
- }
- public get Borders(): TableCellBorders {
- return this.cellBorder;
- }
+ if (options.width) {
+ this.root.push(new TableWidthElement("w:tcW", options.width));
+ }
- public addGridSpan(cellSpan: number): TableCellProperties {
- this.root.push(new GridSpan(cellSpan));
+ if (options.columnSpan) {
+ this.root.push(new GridSpan(options.columnSpan));
+ }
- return this;
- }
+ if (options.verticalMerge) {
+ this.root.push(new VerticalMerge(options.verticalMerge));
+ } else if (options.rowSpan && options.rowSpan > 1) {
+ // if cell already have a `verticalMerge`, don't handle `rowSpan`
+ this.root.push(new VerticalMerge(VerticalMergeType.RESTART));
+ }
- public addVerticalMerge(type: VerticalMergeType): TableCellProperties {
- this.root.push(new VerticalMerge(type));
+ if (options.borders) {
+ this.root.push(new TableCellBorders(options.borders));
+ }
- return this;
- }
+ if (options.shading) {
+ this.root.push(new Shading(options.shading));
+ }
- public setVerticalAlign(type: VerticalAlign): TableCellProperties {
- this.root.push(new VAlign(type));
+ if (options.margins) {
+ this.root.push(new TableCellMargin(TableCellMarginElementType.TABLE_CELL, options.margins));
+ }
- return this;
- }
+ if (options.textDirection) {
+ this.root.push(new TDirection(options.textDirection));
+ }
- public setWidth(width: string | number, type: WidthType = WidthType.AUTO): TableCellProperties {
- this.root.push(new TableCellWidth(width, type));
-
- return this;
- }
-
- public setShading(attrs: ITableShadingAttributesProperties): TableCellProperties {
- this.root.push(new TableShading(attrs));
-
- return this;
- }
-
- public addMargins(options: ITableCellMarginOptions): TableCellProperties {
- this.root.push(new TableCellMargin(options));
-
- return this;
- }
-
- public setTextDirection(type: TextDirection): TableCellProperties {
- this.root.push(new TDirection(type));
-
- return this;
- }
-
- public addBorders(): TableCellProperties {
- this.root.push(this.cellBorder);
-
- return this;
+ if (options.verticalAlign) {
+ this.root.push(new VerticalAlignElement(options.verticalAlign));
+ }
}
}
diff --git a/src/file/table/table-cell/table-cell.spec.ts b/src/file/table/table-cell/table-cell.spec.ts
index 3ea123fb5b..b4fa5e7429 100644
--- a/src/file/table/table-cell/table-cell.spec.ts
+++ b/src/file/table/table-cell/table-cell.spec.ts
@@ -1,24 +1,31 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { BorderStyle } from "file/styles";
+import { BorderStyle } from "file/border";
+import { ShadingType } from "file/shading";
+import { VerticalAlign } from "file/vertical-align";
-import { ShadingType } from "../shading";
+import { WidthType } from "../table-width";
import { TableCell } from "./table-cell";
-import { TableCellBorders, TableCellWidth, TextDirection, VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components";
+import { TableCellBorders, TextDirection, VerticalMergeType } from "./table-cell-components";
describe("TableCellBorders", () => {
describe("#prepForXml", () => {
it("should not add empty borders element if there are no borders defined", () => {
- const tb = new TableCellBorders();
+ const tb = new TableCellBorders({});
expect(() => new Formatter().format(tb)).to.throw();
});
});
describe("#addingBorders", () => {
it("should add top border", () => {
- const tb = new TableCellBorders();
- tb.addTopBorder(BorderStyle.DOTTED, 1, "FF00FF");
+ const tb = new TableCellBorders({
+ top: {
+ style: BorderStyle.DOTTED,
+ size: 1,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -37,8 +44,13 @@ describe("TableCellBorders", () => {
});
it("should add start(left) border", () => {
- const tb = new TableCellBorders();
- tb.addStartBorder(BorderStyle.SINGLE, 2, "FF00FF");
+ const tb = new TableCellBorders({
+ start: {
+ style: BorderStyle.SINGLE,
+ size: 2,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -57,8 +69,13 @@ describe("TableCellBorders", () => {
});
it("should add bottom border", () => {
- const tb = new TableCellBorders();
- tb.addBottomBorder(BorderStyle.DOUBLE, 1, "FF00FF");
+ const tb = new TableCellBorders({
+ bottom: {
+ style: BorderStyle.DOUBLE,
+ size: 1,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -77,8 +94,13 @@ describe("TableCellBorders", () => {
});
it("should add end(right) border", () => {
- const tb = new TableCellBorders();
- tb.addEndBorder(BorderStyle.THICK, 3, "FF00FF");
+ const tb = new TableCellBorders({
+ end: {
+ style: BorderStyle.THICK,
+ size: 3,
+ color: "FF0000",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -86,7 +108,7 @@ describe("TableCellBorders", () => {
{
"w:end": {
_attr: {
- "w:color": "FF00FF",
+ "w:color": "FF0000",
"w:sz": 3,
"w:val": "thick",
},
@@ -97,8 +119,13 @@ describe("TableCellBorders", () => {
});
it("should add left border", () => {
- const tb = new TableCellBorders();
- tb.addLeftBorder(BorderStyle.THICK, 3, "FF00FF");
+ const tb = new TableCellBorders({
+ left: {
+ style: BorderStyle.THICK,
+ size: 3,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -117,8 +144,13 @@ describe("TableCellBorders", () => {
});
it("should add right border", () => {
- const tb = new TableCellBorders();
- tb.addRightBorder(BorderStyle.THICK, 3, "FF00FF");
+ const tb = new TableCellBorders({
+ right: {
+ style: BorderStyle.THICK,
+ size: 3,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -137,13 +169,38 @@ describe("TableCellBorders", () => {
});
it("should add multiple borders", () => {
- const tb = new TableCellBorders();
- tb.addTopBorder(BorderStyle.DOTTED, 1, "FF00FF");
- tb.addEndBorder(BorderStyle.THICK, 3, "FF00FF");
- tb.addBottomBorder(BorderStyle.DOUBLE, 1, "FF00FF");
- tb.addStartBorder(BorderStyle.SINGLE, 2, "FF00FF");
- tb.addLeftBorder(BorderStyle.SINGLE, 2, "FF00FF");
- tb.addRightBorder(BorderStyle.SINGLE, 2, "FF00FF");
+ const tb = new TableCellBorders({
+ top: {
+ style: BorderStyle.DOTTED,
+ size: 1,
+ color: "FF00FF",
+ },
+ end: {
+ style: BorderStyle.THICK,
+ size: 3,
+ color: "FF00FF",
+ },
+ bottom: {
+ style: BorderStyle.DOUBLE,
+ size: 1,
+ color: "FF00FF",
+ },
+ start: {
+ style: BorderStyle.SINGLE,
+ size: 2,
+ color: "FF00FF",
+ },
+ left: {
+ style: BorderStyle.SINGLE,
+ size: 2,
+ color: "FF00FF",
+ },
+ right: {
+ style: BorderStyle.SINGLE,
+ size: 2,
+ color: "FF00FF",
+ },
+ });
const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({
@@ -157,24 +214,6 @@ describe("TableCellBorders", () => {
},
},
},
- {
- "w:end": {
- _attr: {
- "w:color": "FF00FF",
- "w:sz": 3,
- "w:val": "thick",
- },
- },
- },
- {
- "w:bottom": {
- _attr: {
- "w:color": "FF00FF",
- "w:sz": 1,
- "w:val": "double",
- },
- },
- },
{
"w:start": {
_attr: {
@@ -193,6 +232,24 @@ describe("TableCellBorders", () => {
},
},
},
+ {
+ "w:bottom": {
+ _attr: {
+ "w:color": "FF00FF",
+ "w:sz": 1,
+ "w:val": "double",
+ },
+ },
+ },
+ {
+ "w:end": {
+ _attr: {
+ "w:color": "FF00FF",
+ "w:sz": 3,
+ "w:val": "thick",
+ },
+ },
+ },
{
"w:right": {
_attr: {
@@ -208,23 +265,6 @@ describe("TableCellBorders", () => {
});
});
-describe("TableCellWidth", () => {
- describe("#constructor", () => {
- it("should create object", () => {
- const tcWidth = new TableCellWidth(100, WidthType.DXA);
- const tree = new Formatter().format(tcWidth);
- expect(tree).to.deep.equal({
- "w:tcW": {
- _attr: {
- "w:type": "dxa",
- "w:w": 100,
- },
- },
- });
- });
- });
-});
-
describe("TableCell", () => {
describe("#constructor", () => {
it("should create", () => {
@@ -355,7 +395,7 @@ describe("TableCell", () => {
},
},
{
- "w:start": {
+ "w:left": {
_attr: {
"w:type": "dxa",
"w:w": 1,
@@ -371,7 +411,7 @@ describe("TableCell", () => {
},
},
{
- "w:end": {
+ "w:right": {
_attr: {
"w:type": "dxa",
"w:w": 1,
@@ -393,9 +433,9 @@ describe("TableCell", () => {
const cell = new TableCell({
children: [],
shading: {
- fill: "red",
- color: "blue",
- val: ShadingType.PERCENT_10,
+ fill: "FF0000",
+ color: "0000ff",
+ type: ShadingType.PERCENT_10,
},
});
@@ -408,8 +448,8 @@ describe("TableCell", () => {
{
"w:shd": {
_attr: {
- "w:color": "blue",
- "w:fill": "red",
+ "w:color": "0000ff",
+ "w:fill": "FF0000",
"w:val": "pct10",
},
},
@@ -531,17 +571,17 @@ describe("TableCell", () => {
top: {
style: BorderStyle.DASH_DOT_STROKED,
size: 3,
- color: "red",
+ color: "FF0000",
},
bottom: {
style: BorderStyle.DOUBLE,
size: 3,
- color: "blue",
+ color: "0000ff",
},
left: {
style: BorderStyle.DASH_DOT_STROKED,
size: 3,
- color: "green",
+ color: "00ff00",
},
right: {
style: BorderStyle.DASH_DOT_STROKED,
@@ -562,7 +602,7 @@ describe("TableCell", () => {
{
"w:top": {
_attr: {
- "w:color": "red",
+ "w:color": "FF0000",
"w:sz": 3,
"w:val": "dashDotStroked",
},
@@ -571,7 +611,7 @@ describe("TableCell", () => {
{
"w:left": {
_attr: {
- "w:color": "green",
+ "w:color": "00ff00",
"w:sz": 3,
"w:val": "dashDotStroked",
},
@@ -580,7 +620,7 @@ describe("TableCell", () => {
{
"w:bottom": {
_attr: {
- "w:color": "blue",
+ "w:color": "0000ff",
"w:sz": 3,
"w:val": "double",
},
@@ -589,7 +629,7 @@ describe("TableCell", () => {
{
"w:right": {
_attr: {
- "w:color": "#ff8000",
+ "w:color": "ff8000",
"w:sz": 3,
"w:val": "dashDotStroked",
},
diff --git a/src/file/table/table-cell/table-cell.ts b/src/file/table/table-cell/table-cell.ts
index 672b5d2f94..565d389c6d 100644
--- a/src/file/table/table-cell/table-cell.ts
+++ b/src/file/table/table-cell/table-cell.ts
@@ -1,48 +1,11 @@
// http://officeopenxml.com/WPtableGrid.php
import { Paragraph } from "file/paragraph";
-import { BorderStyle } from "file/styles";
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
-import { ITableShadingAttributesProperties } from "../shading";
import { Table } from "../table";
-import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins";
-import { TextDirection, VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components";
-import { TableCellProperties } from "./table-cell-properties";
+import { ITableCellPropertiesOptions, TableCellProperties } from "./table-cell-properties";
-export interface ITableCellOptions {
- readonly shading?: ITableShadingAttributesProperties;
- readonly margins?: ITableCellMarginOptions;
- readonly verticalAlign?: VerticalAlign;
- readonly textDirection?: TextDirection;
- readonly verticalMerge?: VerticalMergeType;
- readonly width?: {
- readonly size: number | string;
- readonly type?: WidthType;
- };
- readonly columnSpan?: number;
- readonly rowSpan?: number;
- readonly borders?: {
- readonly top?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly bottom?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly left?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly right?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- };
+export interface ITableCellOptions extends ITableCellPropertiesOptions {
readonly children: (Paragraph | Table)[];
}
@@ -50,59 +13,11 @@ export class TableCell extends XmlComponent {
constructor(readonly options: ITableCellOptions) {
super("w:tc");
- const properties = new TableCellProperties();
- this.root.push(properties);
+ this.root.push(new TableCellProperties(options));
for (const child of options.children) {
this.root.push(child);
}
-
- if (options.width) {
- properties.setWidth(options.width.size, options.width.type);
- }
-
- if (options.columnSpan) {
- properties.addGridSpan(options.columnSpan);
- }
-
- if (options.verticalMerge) {
- properties.addVerticalMerge(options.verticalMerge);
- } else if (options.rowSpan && options.rowSpan > 1) {
- // if cell already have a `verticalMerge`, don't handle `rowSpan`
- properties.addVerticalMerge(VerticalMergeType.RESTART);
- }
-
- if (options.borders) {
- properties.addBorders();
- if (options.borders.top) {
- properties.Borders.addTopBorder(options.borders.top.style, options.borders.top.size, options.borders.top.color);
- }
- if (options.borders.left) {
- properties.Borders.addLeftBorder(options.borders.left.style, options.borders.left.size, options.borders.left.color);
- }
- if (options.borders.bottom) {
- properties.Borders.addBottomBorder(options.borders.bottom.style, options.borders.bottom.size, options.borders.bottom.color);
- }
- if (options.borders.right) {
- properties.Borders.addRightBorder(options.borders.right.style, options.borders.right.size, options.borders.right.color);
- }
- }
-
- if (options.shading) {
- properties.setShading(options.shading);
- }
-
- if (options.margins) {
- properties.addMargins(options.margins);
- }
-
- if (options.textDirection) {
- properties.setTextDirection(options.textDirection);
- }
-
- if (options.verticalAlign) {
- properties.setVerticalAlign(options.verticalAlign);
- }
}
public prepForXml(context: IContext): IXmlableObject | undefined {
diff --git a/src/file/table/table-properties/table-borders.spec.ts b/src/file/table/table-properties/table-borders.spec.ts
index 4a3212feb1..a13482f349 100644
--- a/src/file/table/table-properties/table-borders.spec.ts
+++ b/src/file/table/table-properties/table-borders.spec.ts
@@ -1,7 +1,7 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { BorderStyle } from "file/styles";
+import { BorderStyle } from "file/border";
import { TableBorders } from "./table-borders";
@@ -18,7 +18,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -28,7 +27,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -38,7 +36,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -48,7 +45,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -58,7 +54,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -68,7 +63,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -85,7 +79,7 @@ describe("TableBorders", () => {
top: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "FF0000",
},
});
@@ -95,8 +89,7 @@ describe("TableBorders", () => {
{
"w:top": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "FF0000",
"w:sz": 1,
"w:val": "double",
},
@@ -106,7 +99,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -116,7 +108,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -126,7 +117,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -136,7 +126,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -146,7 +135,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -163,7 +151,7 @@ describe("TableBorders", () => {
left: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "ff0000",
},
});
const tree = new Formatter().format(tableBorders);
@@ -174,7 +162,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -183,8 +170,7 @@ describe("TableBorders", () => {
{
"w:left": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "ff0000",
"w:sz": 1,
"w:val": "double",
},
@@ -194,7 +180,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -204,7 +189,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -214,7 +198,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -224,7 +207,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -241,7 +223,7 @@ describe("TableBorders", () => {
bottom: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "ff0000",
},
});
const tree = new Formatter().format(tableBorders);
@@ -252,7 +234,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -262,7 +243,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -271,8 +251,7 @@ describe("TableBorders", () => {
{
"w:bottom": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "ff0000",
"w:sz": 1,
"w:val": "double",
},
@@ -282,7 +261,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -292,7 +270,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -302,7 +279,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -319,7 +295,7 @@ describe("TableBorders", () => {
right: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "ff0000",
},
});
const tree = new Formatter().format(tableBorders);
@@ -330,7 +306,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -340,7 +315,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -350,7 +324,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -359,8 +332,7 @@ describe("TableBorders", () => {
{
"w:right": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "ff0000",
"w:sz": 1,
"w:val": "double",
},
@@ -370,7 +342,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -380,7 +351,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -397,7 +367,7 @@ describe("TableBorders", () => {
insideHorizontal: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "ff0000",
},
});
const tree = new Formatter().format(tableBorders);
@@ -408,7 +378,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -418,7 +387,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -428,7 +396,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -438,7 +405,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -447,8 +413,7 @@ describe("TableBorders", () => {
{
"w:insideH": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "ff0000",
"w:sz": 1,
"w:val": "double",
},
@@ -458,7 +423,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -475,7 +439,7 @@ describe("TableBorders", () => {
insideVertical: {
style: BorderStyle.DOUBLE,
size: 1,
- color: "red",
+ color: "ff0000",
},
});
const tree = new Formatter().format(tableBorders);
@@ -486,7 +450,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -496,7 +459,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -506,7 +468,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -516,7 +477,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -526,7 +486,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 4,
"w:val": "single",
},
@@ -535,8 +494,7 @@ describe("TableBorders", () => {
{
"w:insideV": {
_attr: {
- "w:color": "red",
- "w:space": 0,
+ "w:color": "ff0000",
"w:sz": 1,
"w:val": "double",
},
@@ -558,7 +516,6 @@ describe("TableBorders", () => {
"w:top": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
@@ -568,7 +525,6 @@ describe("TableBorders", () => {
"w:left": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
@@ -578,7 +534,6 @@ describe("TableBorders", () => {
"w:bottom": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
@@ -588,7 +543,6 @@ describe("TableBorders", () => {
"w:right": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
@@ -598,7 +552,6 @@ describe("TableBorders", () => {
"w:insideH": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
@@ -608,7 +561,6 @@ describe("TableBorders", () => {
"w:insideV": {
_attr: {
"w:color": "auto",
- "w:space": 0,
"w:sz": 0,
"w:val": "none",
},
diff --git a/src/file/table/table-properties/table-borders.ts b/src/file/table/table-properties/table-borders.ts
index 8de354fc36..923a7bb019 100644
--- a/src/file/table/table-properties/table-borders.ts
+++ b/src/file/table/table-properties/table-borders.ts
@@ -1,155 +1,75 @@
// http://officeopenxml.com/WPtableBorders.php
-import { BorderStyle } from "file/styles";
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+import { BorderElement, BorderStyle, IBorderOptions } from "file/border";
+import { XmlComponent } from "file/xml-components";
export interface ITableBordersOptions {
- readonly top?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly bottom?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly left?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly right?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly insideHorizontal?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
- readonly insideVertical?: {
- readonly style: BorderStyle;
- readonly size: number;
- readonly color: string;
- };
+ readonly top?: IBorderOptions;
+ readonly bottom?: IBorderOptions;
+ readonly left?: IBorderOptions;
+ readonly right?: IBorderOptions;
+ readonly insideHorizontal?: IBorderOptions;
+ readonly insideVertical?: IBorderOptions;
}
+const NONE_BORDER = {
+ style: BorderStyle.NONE,
+ size: 0,
+ color: "auto",
+};
+
+const DEFAULT_BORDER = {
+ style: BorderStyle.SINGLE,
+ size: 4,
+ color: "auto",
+};
+
export class TableBorders extends XmlComponent {
public static readonly NONE = {
- top: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
- bottom: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
- left: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
- right: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
- insideHorizontal: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
- insideVertical: {
- style: BorderStyle.NONE,
- size: 0,
- color: "auto",
- },
+ top: NONE_BORDER,
+ bottom: NONE_BORDER,
+ left: NONE_BORDER,
+ right: NONE_BORDER,
+ insideHorizontal: NONE_BORDER,
+ insideVertical: NONE_BORDER,
};
constructor(options: ITableBordersOptions) {
super("w:tblBorders");
if (options.top) {
- this.root.push(new TableBordersElement("w:top", options.top.style, options.top.size, 0, options.top.color));
+ this.root.push(new BorderElement("w:top", options.top));
} else {
- this.root.push(new TableBordersElement("w:top", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:top", DEFAULT_BORDER));
}
if (options.left) {
- this.root.push(new TableBordersElement("w:left", options.left.style, options.left.size, 0, options.left.color));
+ this.root.push(new BorderElement("w:left", options.left));
} else {
- this.root.push(new TableBordersElement("w:left", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:left", DEFAULT_BORDER));
}
if (options.bottom) {
- this.root.push(new TableBordersElement("w:bottom", options.bottom.style, options.bottom.size, 0, options.bottom.color));
+ this.root.push(new BorderElement("w:bottom", options.bottom));
} else {
- this.root.push(new TableBordersElement("w:bottom", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:bottom", DEFAULT_BORDER));
}
if (options.right) {
- this.root.push(new TableBordersElement("w:right", options.right.style, options.right.size, 0, options.right.color));
+ this.root.push(new BorderElement("w:right", options.right));
} else {
- this.root.push(new TableBordersElement("w:right", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:right", DEFAULT_BORDER));
}
if (options.insideHorizontal) {
- this.root.push(
- new TableBordersElement(
- "w:insideH",
- options.insideHorizontal.style,
- options.insideHorizontal.size,
- 0,
- options.insideHorizontal.color,
- ),
- );
+ this.root.push(new BorderElement("w:insideH", options.insideHorizontal));
} else {
- this.root.push(new TableBordersElement("w:insideH", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:insideH", DEFAULT_BORDER));
}
if (options.insideVertical) {
- this.root.push(
- new TableBordersElement(
- "w:insideV",
- options.insideVertical.style,
- options.insideVertical.size,
- 0,
- options.insideVertical.color,
- ),
- );
+ this.root.push(new BorderElement("w:insideV", options.insideVertical));
} else {
- this.root.push(new TableBordersElement("w:insideV", BorderStyle.SINGLE, 4, 0, "auto"));
+ this.root.push(new BorderElement("w:insideV", DEFAULT_BORDER));
}
}
}
-
-class TableBordersElement extends XmlComponent {
- constructor(elementName: string, value: string, size: number, space: number, color: string) {
- super(elementName);
- this.root.push(
- new TableBordersAttributes({
- value,
- size,
- space,
- color,
- }),
- );
- }
-}
-
-class TableBordersAttributes extends XmlAttributeComponent<{
- readonly value: string;
- readonly size: number;
- readonly space: number;
- readonly color: string;
-}> {
- protected readonly xmlKeys = {
- value: "w:val",
- size: "w:sz",
- space: "w:space",
- color: "w:color",
- };
-}
diff --git a/src/file/table/table-properties/table-cell-margin.spec.ts b/src/file/table/table-properties/table-cell-margin.spec.ts
index 814888adc0..0361b37f27 100644
--- a/src/file/table/table-properties/table-cell-margin.spec.ts
+++ b/src/file/table/table-properties/table-cell-margin.spec.ts
@@ -1,25 +1,23 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
+import { WidthType } from "../table-width";
-import { WidthType } from "../table-cell";
-import { TableCellMargin } from "./table-cell-margin";
+import { TableCellMargin, TableCellMarginElementType } from "./table-cell-margin";
describe("TableCellMargin", () => {
describe("#constructor", () => {
it("should throw an error if theres no child elements", () => {
- const cellMargin = new TableCellMargin({});
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {});
expect(() => new Formatter().format(cellMargin)).to.throw();
});
});
describe("#addTopMargin", () => {
it("should add a table cell top margin", () => {
- const cellMargin = new TableCellMargin({
- top: {
- value: 1234,
- type: WidthType.DXA,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ marginUnitType: WidthType.DXA,
+ top: 1234,
});
const tree = new Formatter().format(cellMargin);
@@ -27,10 +25,8 @@ describe("TableCellMargin", () => {
});
it("should add a table cell top margin using default width type", () => {
- const cellMargin = new TableCellMargin({
- top: {
- value: 1234,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ top: 1234,
});
const tree = new Formatter().format(cellMargin);
@@ -40,21 +36,17 @@ describe("TableCellMargin", () => {
describe("#addLeftMargin", () => {
it("should add a table cell left margin", () => {
- const cellMargin = new TableCellMargin({
- left: {
- value: 1234,
- type: WidthType.DXA,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ marginUnitType: WidthType.DXA,
+ left: 1234,
});
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:left": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
});
it("should add a table cell left margin using default width type", () => {
- const cellMargin = new TableCellMargin({
- left: {
- value: 1234,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ left: 1234,
});
const tree = new Formatter().format(cellMargin);
expect(tree).to.deep.equal({ "w:tblCellMar": [{ "w:left": { _attr: { "w:type": "dxa", "w:w": 1234 } } }] });
@@ -63,11 +55,9 @@ describe("TableCellMargin", () => {
describe("#addBottomMargin", () => {
it("should add a table cell bottom margin", () => {
- const cellMargin = new TableCellMargin({
- bottom: {
- value: 1234,
- type: WidthType.DXA,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ marginUnitType: WidthType.DXA,
+ bottom: 1234,
});
const tree = new Formatter().format(cellMargin);
@@ -75,10 +65,8 @@ describe("TableCellMargin", () => {
});
it("should add a table cell bottom margin using default width type", () => {
- const cellMargin = new TableCellMargin({
- bottom: {
- value: 1234,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ bottom: 1234,
});
const tree = new Formatter().format(cellMargin);
@@ -88,11 +76,9 @@ describe("TableCellMargin", () => {
describe("#addRightMargin", () => {
it("should add a table cell right margin", () => {
- const cellMargin = new TableCellMargin({
- right: {
- value: 1234,
- type: WidthType.DXA,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ marginUnitType: WidthType.DXA,
+ right: 1234,
});
const tree = new Formatter().format(cellMargin);
@@ -100,10 +86,8 @@ describe("TableCellMargin", () => {
});
it("should add a table cell right margin using default width type", () => {
- const cellMargin = new TableCellMargin({
- right: {
- value: 1234,
- },
+ const cellMargin = new TableCellMargin(TableCellMarginElementType.TABLE, {
+ right: 1234,
});
const tree = new Formatter().format(cellMargin);
diff --git a/src/file/table/table-properties/table-cell-margin.ts b/src/file/table/table-properties/table-cell-margin.ts
index ffa554a8de..c01cf84f6e 100644
--- a/src/file/table/table-properties/table-cell-margin.ts
+++ b/src/file/table/table-properties/table-cell-margin.ts
@@ -1,54 +1,61 @@
-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:type" };
-}
-
-interface IBaseTableCellMarginOptions {
- readonly value: number;
- readonly type?: WidthType;
-}
-
-class BaseTableCellMargin extends XmlComponent {
- constructor(rootKey: string, options: IBaseTableCellMarginOptions) {
- super(rootKey);
-
- this.root.push(
- new TableCellMarginAttributes({
- type: options.type ?? WidthType.DXA,
- value: options.value,
- }),
- );
- }
-}
+import { IgnoreIfEmptyXmlComponent } from "file/xml-components";
+import { TableWidthElement, WidthType } from "../table-width";
export interface ITableCellMarginOptions {
- readonly top?: IBaseTableCellMarginOptions;
- readonly bottom?: IBaseTableCellMarginOptions;
- readonly left?: IBaseTableCellMarginOptions;
- readonly right?: IBaseTableCellMarginOptions;
+ readonly marginUnitType?: WidthType;
+ readonly top?: number;
+ readonly bottom?: number;
+ readonly left?: number;
+ readonly right?: number;
+}
+
+// Technically two different types, but they're identical
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+export enum TableCellMarginElementType {
+ TABLE = "w:tblCellMar",
+ TABLE_CELL = "w:tcMar",
}
export class TableCellMargin extends IgnoreIfEmptyXmlComponent {
- constructor(options: ITableCellMarginOptions) {
- super("w:tblCellMar");
+ constructor(type: TableCellMarginElementType, { marginUnitType = WidthType.DXA, top, left, bottom, right }: ITableCellMarginOptions) {
+ super(type);
- if (options.top) {
- this.root.push(new BaseTableCellMargin("w:top", options.top));
+ if (top !== undefined) {
+ this.root.push(new TableWidthElement("w:top", { type: marginUnitType, size: top }));
}
- if (options.left) {
- this.root.push(new BaseTableCellMargin("w:left", options.left));
+ if (left !== undefined) {
+ this.root.push(new TableWidthElement("w:left", { type: marginUnitType, size: left }));
}
- if (options.bottom) {
- this.root.push(new BaseTableCellMargin("w:bottom", options.bottom));
+ if (bottom !== undefined) {
+ this.root.push(new TableWidthElement("w:bottom", { type: marginUnitType, size: bottom }));
}
- if (options.right) {
- this.root.push(new BaseTableCellMargin("w:right", options.right));
+ if (right !== undefined) {
+ this.root.push(new TableWidthElement("w:right", { type: marginUnitType, size: right }));
}
}
}
diff --git a/src/file/table/table-properties/table-float-properties.ts b/src/file/table/table-properties/table-float-properties.ts
index 2b97d86c1c..8e365fc93d 100644
--- a/src/file/table/table-properties/table-float-properties.ts
+++ b/src/file/table/table-properties/table-float-properties.ts
@@ -1,3 +1,4 @@
+import { signedTwipsMeasureValue, twipsMeasureValue } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { OverlapType, TableOverlap } from "./table-overlap";
@@ -43,7 +44,7 @@ export interface ITableFloatOptions {
* If relativeHorizontalPosition is also specified, then the absoluteHorizontalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero.
*/
- readonly absoluteHorizontalPosition?: number;
+ readonly absoluteHorizontalPosition?: number | string;
/**
* Specifies a relative horizontal position for the table, relative to the horizontalAnchor attribute.
@@ -74,7 +75,7 @@ export interface ITableFloatOptions {
* If relativeVerticalPosition is also specified, then the absoluteVerticalPosition attribute is ignored.
* If the attribute is omitted, the value is assumed to be zero.
*/
- readonly absoluteVerticalPosition?: number;
+ readonly absoluteVerticalPosition?: number | string;
/**
* Specifies a relative vertical position for the table, relative to the verticalAnchor attribute.
@@ -92,28 +93,41 @@ export interface ITableFloatOptions {
* Specifies the minimun distance to be maintained between the table and the top of text in the paragraph
* below the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
- readonly bottomFromText?: number;
+ readonly bottomFromText?: number | string;
/**
* Specifies the minimun distance to be maintained between the table and the bottom edge of text in the paragraph
* above the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
- readonly topFromText?: number;
+ readonly topFromText?: number | string;
/**
* Specifies the minimun distance to be maintained between the table and the edge of text in the paragraph
* to the left of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
- readonly leftFromText?: number;
+ readonly leftFromText?: number | string;
/**
* Specifies the minimun distance to be maintained between the table and the edge of text in the paragraph
* to the right of the table. The value is in twentieths of a point. If omitted, the value is assumed to be zero.
*/
- readonly rightFromText?: number;
+ readonly rightFromText?: number | string;
readonly overlap?: OverlapType;
}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
export class TableFloatOptionsAttributes extends XmlAttributeComponent {
protected readonly xmlKeys = {
horizontalAnchor: "w:horzAnchor",
@@ -130,9 +144,29 @@ export class TableFloatOptionsAttributes extends XmlAttributeComponent
+//
+//
+//
+//
+//
export enum TableLayoutType {
AUTOFIT = "autofit",
FIXED = "fixed",
@@ -9,6 +15,9 @@ class TableLayoutAttributes extends XmlAttributeComponent<{ readonly type: Table
protected readonly xmlKeys = { type: "w:type" };
}
+//
+//
+//
export class TableLayout extends XmlComponent {
constructor(type: TableLayoutType) {
super("w:tblLayout");
diff --git a/src/file/table/table-properties/table-overlap.ts b/src/file/table/table-properties/table-overlap.ts
index 387cf27943..102d2afa5d 100644
--- a/src/file/table/table-properties/table-overlap.ts
+++ b/src/file/table/table-properties/table-overlap.ts
@@ -1,10 +1,19 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+//
+//
+//
+//
+//
+//
export enum OverlapType {
NEVER = "never",
OVERLAP = "overlap",
}
+//
+//
+//
class TableOverlapAttributes extends XmlAttributeComponent<{ readonly val: OverlapType }> {
protected readonly xmlKeys = { val: "w:val" };
}
diff --git a/src/file/table/table-properties/table-properties.spec.ts b/src/file/table/table-properties/table-properties.spec.ts
index a6a9b5879f..ceadb5c3a8 100644
--- a/src/file/table/table-properties/table-properties.spec.ts
+++ b/src/file/table/table-properties/table-properties.spec.ts
@@ -2,9 +2,10 @@ import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { AlignmentType } from "../../paragraph";
-import { ShadingType } from "../shading";
-import { WidthType } from "../table-cell";
+import { AlignmentType } from "file/paragraph";
+import { ShadingType } from "file/shading";
+
+import { WidthType } from "../table-width";
import { TableLayoutType } from "./table-layout";
import { TableProperties } from "./table-properties";
@@ -18,9 +19,7 @@ describe("TableProperties", () => {
// has been asked to format.
expect(() => new Formatter().format(tp)).to.throw("XMLComponent did not format correctly");
});
- });
- describe("#setStyle", () => {
it("should add a table style property", () => {
const tp = new TableProperties({
style: "TableNormal",
@@ -30,9 +29,7 @@ describe("TableProperties", () => {
"w:tblPr": [{ "w:tblStyle": { _attr: { "w:val": "TableNormal" } } }],
});
});
- });
- describe("#setWidth", () => {
it("should add a table width property", () => {
const tp = new TableProperties({
width: {
@@ -58,9 +55,33 @@ describe("TableProperties", () => {
"w:tblPr": [{ "w:tblW": { _attr: { "w:type": "auto", "w:w": 1234 } } }],
});
});
- });
- describe("#setLayout", () => {
+ it("should add a table indent property", () => {
+ const tp = new TableProperties({
+ indent: {
+ size: 1234,
+ type: WidthType.DXA,
+ },
+ });
+ const tree = new Formatter().format(tp);
+ expect(tree).to.deep.equal({
+ "w:tblPr": [{ "w:tblInd": { _attr: { "w:type": "dxa", "w:w": 1234 } } }],
+ });
+ });
+
+ it("should add a table indent property with default of AUTO", () => {
+ const tp = new TableProperties({
+ indent: {
+ size: 1234,
+ },
+ });
+
+ const tree = new Formatter().format(tp);
+ expect(tree).to.deep.equal({
+ "w:tblPr": [{ "w:tblInd": { _attr: { "w:type": "auto", "w:w": 1234 } } }],
+ });
+ });
+
it("sets the table to fixed width layout", () => {
const tp = new TableProperties({
layout: TableLayoutType.FIXED,
@@ -77,10 +98,8 @@ describe("TableProperties", () => {
it("adds a table cell top margin", () => {
const tp = new TableProperties({
cellMargin: {
- top: {
- value: 1234,
- type: WidthType.DXA,
- },
+ marginUnitType: WidthType.DXA,
+ top: 1234,
},
});
@@ -93,10 +112,8 @@ describe("TableProperties", () => {
it("adds a table cell left margin", () => {
const tp = new TableProperties({
cellMargin: {
- left: {
- value: 1234,
- type: WidthType.DXA,
- },
+ marginUnitType: WidthType.DXA,
+ left: 1234,
},
});
@@ -112,7 +129,7 @@ describe("TableProperties", () => {
const tp = new TableProperties({
shading: {
fill: "b79c2f",
- val: ShadingType.REVERSE_DIAGONAL_STRIPE,
+ type: ShadingType.REVERSE_DIAGONAL_STRIPE,
color: "auto",
},
});
diff --git a/src/file/table/table-properties/table-properties.ts b/src/file/table/table-properties/table-properties.ts
index 5d1aa048e1..5e46cfa92a 100644
--- a/src/file/table/table-properties/table-properties.ts
+++ b/src/file/table/table-properties/table-properties.ts
@@ -1,26 +1,43 @@
// http://officeopenxml.com/WPtableProperties.php
-import { IgnoreIfEmptyXmlComponent } from "file/xml-components";
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+import { IgnoreIfEmptyXmlComponent, OnOffElement, StringValueElement } from "file/xml-components";
import { Alignment, AlignmentType } from "../../paragraph";
-import { ITableShadingAttributesProperties, TableShading } from "../shading";
-import { WidthType } from "../table-cell";
+import { IShadingAttributesProperties, Shading } from "../../shading";
+import { ITableWidthProperties, TableWidthElement } from "../table-width";
import { ITableBordersOptions, TableBorders } from "./table-borders";
-import { ITableCellMarginOptions, TableCellMargin } from "./table-cell-margin";
+import { ITableCellMarginOptions, TableCellMargin, TableCellMarginElementType } from "./table-cell-margin";
import { ITableFloatOptions, TableFloatProperties } from "./table-float-properties";
import { TableLayout, TableLayoutType } from "./table-layout";
-import { TableStyle } from "./table-style";
-import { PreferredTableWidth } from "./table-width";
-import { VisuallyRightToLeft } from "./visually-right-to-left";
export interface ITablePropertiesOptions {
- readonly width?: {
- readonly size: number;
- readonly type?: WidthType;
- };
+ readonly width?: ITableWidthProperties;
+ readonly indent?: ITableWidthProperties;
readonly layout?: TableLayoutType;
readonly borders?: ITableBordersOptions;
readonly float?: ITableFloatOptions;
- readonly shading?: ITableShadingAttributesProperties;
+ readonly shading?: IShadingAttributesProperties;
readonly style?: string;
readonly alignment?: AlignmentType;
readonly cellMargin?: ITableCellMarginOptions;
@@ -32,37 +49,43 @@ export class TableProperties extends IgnoreIfEmptyXmlComponent {
super("w:tblPr");
if (options.style) {
- this.root.push(new TableStyle(options.style));
+ this.root.push(new StringValueElement("w:tblStyle", options.style));
}
if (options.float) {
this.root.push(new TableFloatProperties(options.float));
}
- if (options.visuallyRightToLeft) {
- this.root.push(new VisuallyRightToLeft());
+ if (options.visuallyRightToLeft !== undefined) {
+ this.root.push(new OnOffElement("w:bidiVisual", options.visuallyRightToLeft));
}
if (options.width) {
- this.root.push(new PreferredTableWidth(options.width.type, options.width.size));
+ this.root.push(new TableWidthElement("w:tblW", options.width));
}
if (options.alignment) {
this.root.push(new Alignment(options.alignment));
}
+ if (options.indent) {
+ this.root.push(new TableWidthElement("w:tblInd", options.indent));
+ }
+
if (options.borders) {
this.root.push(new TableBorders(options.borders));
}
if (options.shading) {
- this.root.push(new TableShading(options.shading));
+ this.root.push(new Shading(options.shading));
}
if (options.layout) {
this.root.push(new TableLayout(options.layout));
}
- this.root.push(new TableCellMargin(options.cellMargin || {}));
+ if (options.cellMargin) {
+ this.root.push(new TableCellMargin(TableCellMarginElementType.TABLE, options.cellMargin));
+ }
}
}
diff --git a/src/file/table/table-properties/table-style.spec.ts b/src/file/table/table-properties/table-style.spec.ts
deleted file mode 100644
index 1b9b0e9748..0000000000
--- a/src/file/table/table-properties/table-style.spec.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-
-import { TableStyle } from "./table-style";
-
-describe("TableStyle", () => {
- describe("#constructor", () => {
- it("should create", () => {
- const tableStyle = new TableStyle("test-id");
- const tree = new Formatter().format(tableStyle);
-
- expect(tree).to.deep.equal({
- "w:tblStyle": {
- _attr: {
- "w:val": "test-id",
- },
- },
- });
- });
- });
-});
diff --git a/src/file/table/table-properties/table-style.ts b/src/file/table/table-properties/table-style.ts
deleted file mode 100644
index 22b4dc5e89..0000000000
--- a/src/file/table/table-properties/table-style.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Attributes, XmlComponent } from "file/xml-components";
-
-export class TableStyle extends XmlComponent {
- constructor(styleId: string) {
- super("w:tblStyle");
-
- this.root.push(
- new Attributes({
- val: styleId,
- }),
- );
- }
-}
diff --git a/src/file/table/table-properties/table-width.ts b/src/file/table/table-properties/table-width.ts
deleted file mode 100644
index 1b86125e90..0000000000
--- a/src/file/table/table-properties/table-width.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// http://officeopenxml.com/WPtableWidth.php
-import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
-
-import { WidthType } from "../table-cell";
-
-class TableWidthAttributes extends XmlAttributeComponent<{
- readonly type: WidthType;
- readonly w: number | string;
-}> {
- protected readonly xmlKeys = { type: "w:type", w: "w:w" };
-}
-
-export class PreferredTableWidth extends XmlComponent {
- constructor(type: WidthType = WidthType.AUTO, w: number) {
- super("w:tblW");
- const width: number | string = type === WidthType.PERCENTAGE ? `${w}%` : w;
- this.root.push(new TableWidthAttributes({ type: type, w: width }));
- }
-}
diff --git a/src/file/table/table-properties/visually-right-to-left.spec.ts b/src/file/table/table-properties/visually-right-to-left.spec.ts
deleted file mode 100644
index 792c90194b..0000000000
--- a/src/file/table/table-properties/visually-right-to-left.spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { expect } from "chai";
-
-import { Formatter } from "export/formatter";
-import { VisuallyRightToLeft } from "./visually-right-to-left";
-
-describe("VisuallyRightToLeft", () => {
- it("should create", () => {
- const visuallyRightToLeft = new VisuallyRightToLeft();
- const tree = new Formatter().format(visuallyRightToLeft);
- expect(tree).to.deep.equal({
- "w:bidiVisual": {},
- });
- });
-});
diff --git a/src/file/table/table-properties/visually-right-to-left.ts b/src/file/table/table-properties/visually-right-to-left.ts
deleted file mode 100644
index c0598a5a26..0000000000
--- a/src/file/table/table-properties/visually-right-to-left.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_bidiVisual_topic_ID0EOXIQ.html
-import { XmlComponent } from "file/xml-components";
-
-export class VisuallyRightToLeft extends XmlComponent {
- constructor() {
- super("w:bidiVisual");
- }
-}
diff --git a/src/file/table/table-row/table-row-height.ts b/src/file/table/table-row/table-row-height.ts
index 6803d9b17e..84d696b63b 100644
--- a/src/file/table/table-row/table-row-height.ts
+++ b/src/file/table/table-row/table-row-height.ts
@@ -1,5 +1,18 @@
+import { twipsMeasureValue } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+//
export enum HeightRule {
/** Height is determined based on the content, so value is ignored. */
AUTO = "auto",
@@ -10,19 +23,19 @@ export enum HeightRule {
}
export class TableRowHeightAttributes extends XmlAttributeComponent<{
- readonly value: number;
+ readonly value: number | string;
readonly rule: HeightRule;
}> {
protected readonly xmlKeys = { value: "w:val", rule: "w:hRule" };
}
export class TableRowHeight extends XmlComponent {
- constructor(value: number, rule: HeightRule) {
+ constructor(value: number | string, rule: HeightRule) {
super("w:trHeight");
this.root.push(
new TableRowHeightAttributes({
- value: value,
+ value: twipsMeasureValue(value),
rule: rule,
}),
);
diff --git a/src/file/table/table-row/table-row-properties.spec.ts b/src/file/table/table-row/table-row-properties.spec.ts
index 05092d4178..3f008ce77e 100644
--- a/src/file/table/table-row/table-row-properties.spec.ts
+++ b/src/file/table/table-row/table-row-properties.spec.ts
@@ -6,49 +6,55 @@ import { TableRowProperties } from "./table-row-properties";
describe("TableRowProperties", () => {
describe("#constructor", () => {
it("creates an initially empty property object", () => {
- const rowProperties = new TableRowProperties();
+ const rowProperties = new TableRowProperties({});
// 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");
});
- });
- describe("#setCantSplit", () => {
it("sets cantSplit to avoid row been paginated", () => {
- const rowProperties = new TableRowProperties();
- rowProperties.setCantSplit();
+ const rowProperties = new TableRowProperties({ cantSplit: true });
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": {} }] });
});
- });
- describe("#setTableHeader", () => {
it("sets row as table header (repeat row on each page of table)", () => {
- const rowProperties = new TableRowProperties();
- rowProperties.setTableHeader();
+ const rowProperties = new TableRowProperties({ tableHeader: true });
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": {} }] });
});
- });
- describe("#setHeight", () => {
it("sets row height exact", () => {
- const rowProperties = new TableRowProperties();
- rowProperties.setHeight(100, HeightRule.EXACT);
+ const rowProperties = new TableRowProperties({
+ height: {
+ value: 100,
+ rule: HeightRule.EXACT,
+ },
+ });
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "exact" } } }] });
});
+
it("sets row height auto", () => {
- const rowProperties = new TableRowProperties();
- rowProperties.setHeight(100, HeightRule.AUTO);
+ const rowProperties = new TableRowProperties({
+ height: {
+ value: 100,
+ rule: HeightRule.AUTO,
+ },
+ });
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "auto" } } }] });
});
+
it("sets row height at least", () => {
- const rowProperties = new TableRowProperties();
- rowProperties.setHeight(100, HeightRule.ATLEAST);
+ const rowProperties = new TableRowProperties({
+ height: {
+ value: 100,
+ rule: HeightRule.ATLEAST,
+ },
+ });
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "atLeast" } } }] });
});
diff --git a/src/file/table/table-row/table-row-properties.ts b/src/file/table/table-row/table-row-properties.ts
index 1b4c9784cd..2168d0774a 100644
--- a/src/file/table/table-row/table-row-properties.ts
+++ b/src/file/table/table-row/table-row-properties.ts
@@ -1,50 +1,59 @@
// http://officeopenxml.com/WPtableRowProperties.php
-import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+import { IgnoreIfEmptyXmlComponent, OnOffElement } from "file/xml-components";
import { HeightRule, TableRowHeight } from "./table-row-height";
+export interface ITableRowPropertiesOptions {
+ readonly cantSplit?: boolean;
+ readonly tableHeader?: boolean;
+ readonly height?: {
+ readonly value: number | string;
+ readonly rule: HeightRule;
+ };
+}
+
export class TableRowProperties extends IgnoreIfEmptyXmlComponent {
- constructor() {
+ constructor(options: ITableRowPropertiesOptions) {
super("w:trPr");
- }
- public setCantSplit(): TableRowProperties {
- this.root.push(new CantSplit());
+ if (options.cantSplit !== undefined) {
+ this.root.push(new OnOffElement("w:cantSplit", options.cantSplit));
+ }
- return this;
- }
+ if (options.tableHeader !== undefined) {
+ this.root.push(new OnOffElement("w:tblHeader", options.tableHeader));
+ }
- public setTableHeader(): TableRowProperties {
- this.root.push(new TableHeader());
-
- return this;
- }
-
- public setHeight(value: number, rule: HeightRule): TableRowProperties {
- this.root.push(new TableRowHeight(value, rule));
-
- return this;
- }
-}
-
-class CantSplitAttributes extends XmlAttributeComponent<{ readonly val: boolean }> {
- protected readonly xmlKeys = { val: "w:val" };
-}
-
-export class CantSplit extends XmlComponent {
- constructor() {
- super("w:cantSplit");
- this.root.push(new CantSplitAttributes({ val: true }));
- }
-}
-
-class TableHeaderAttributes extends XmlAttributeComponent<{ readonly val: boolean }> {
- protected readonly xmlKeys = { val: "w:val" };
-}
-
-export class TableHeader extends XmlComponent {
- constructor() {
- super("w:tblHeader");
- this.root.push(new TableHeaderAttributes({ val: true }));
+ if (options.height) {
+ this.root.push(new TableRowHeight(options.height.value, options.height.rule));
+ }
}
}
diff --git a/src/file/table/table-row/table-row.spec.ts b/src/file/table/table-row/table-row.spec.ts
index 16a08e10ae..f1bcbb1aaf 100644
--- a/src/file/table/table-row/table-row.spec.ts
+++ b/src/file/table/table-row/table-row.spec.ts
@@ -53,11 +53,7 @@ describe("TableRow", () => {
{
"w:trPr": [
{
- "w:cantSplit": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:cantSplit": {},
},
],
},
@@ -76,11 +72,7 @@ describe("TableRow", () => {
{
"w:trPr": [
{
- "w:tblHeader": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:tblHeader": {},
},
],
},
@@ -141,11 +133,7 @@ describe("TableRow", () => {
{
"w:trPr": [
{
- "w:tblHeader": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:tblHeader": {},
},
],
},
diff --git a/src/file/table/table-row/table-row.ts b/src/file/table/table-row/table-row.ts
index 92a8614511..11dc9c776a 100644
--- a/src/file/table/table-row/table-row.ts
+++ b/src/file/table/table-row/table-row.ts
@@ -1,41 +1,19 @@
-import { HeightRule } from "file/table/table-row/table-row-height";
import { XmlComponent } from "file/xml-components";
import { TableCell } from "../table-cell";
-import { TableRowProperties } from "./table-row-properties";
+import { ITableRowPropertiesOptions, TableRowProperties } from "./table-row-properties";
-export interface ITableRowOptions {
- readonly cantSplit?: boolean;
- readonly tableHeader?: boolean;
- readonly height?: {
- readonly value: number;
- readonly rule: HeightRule;
- };
+export interface ITableRowOptions extends ITableRowPropertiesOptions {
readonly children: TableCell[];
}
export class TableRow extends XmlComponent {
- private readonly properties: TableRowProperties;
-
constructor(private readonly options: ITableRowOptions) {
super("w:tr");
- this.properties = new TableRowProperties();
- this.root.push(this.properties);
+ this.root.push(new TableRowProperties(options));
for (const child of options.children) {
this.root.push(child);
}
-
- if (options.cantSplit) {
- this.properties.setCantSplit();
- }
-
- if (options.tableHeader) {
- this.properties.setTableHeader();
- }
-
- if (options.height) {
- this.properties.setHeight(options.height.value, options.height.rule);
- }
}
public get CellCount(): number {
diff --git a/src/file/table/table-width.ts b/src/file/table/table-width.ts
new file mode 100644
index 0000000000..ff203506eb
--- /dev/null
+++ b/src/file/table/table-width.ts
@@ -0,0 +1,43 @@
+// http://officeopenxml.com/WPtableWidth.php
+import { measurementOrPercentValue } from "file/values";
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+//
+//
+//
+//
+//
+export enum WidthType {
+ /** Auto. */
+ AUTO = "auto",
+ /** Value is in twentieths of a point */
+ DXA = "dxa",
+ /** No (empty) value. */
+ NIL = "nil",
+ /** Value is in percentage. */
+ PERCENTAGE = "pct",
+}
+
+//
+//
+//
+//
+export interface ITableWidthProperties {
+ readonly size: string | number;
+ readonly type?: WidthType;
+}
+
+class TableWidthAttributes extends XmlAttributeComponent {
+ protected readonly xmlKeys = { type: "w:type", size: "w:w" };
+}
+
+export class TableWidthElement extends XmlComponent {
+ constructor(name: string, { type = WidthType.AUTO, size }: ITableWidthProperties) {
+ super(name);
+ // super("w:tblW");
+ this.root.push(new TableWidthAttributes({ type: type, size: measurementOrPercentValue(size) }));
+ }
+}
diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts
index 623540985f..d3e703decd 100644
--- a/src/file/table/table.spec.ts
+++ b/src/file/table/table.spec.ts
@@ -5,58 +5,21 @@ import { Formatter } from "export/formatter";
import { AlignmentType, Paragraph } from "../paragraph";
import { Table } from "./table";
-// import { WidthType } from "./table-cell";
import { RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType } from "./table-properties";
-import { TableCell, WidthType } from "./table-cell";
+import { TableCell } from "./table-cell";
import { TableLayoutType } from "./table-properties/table-layout";
import { TableRow } from "./table-row";
-
-const DEFAULT_TABLE_PROPERTIES = {
- "w:tblCellMar": [
- {
- "w:top": {
- _attr: {
- "w:type": "auto",
- "w:w": 0,
- },
- },
- },
- {
- "w:left": {
- _attr: {
- "w:type": "auto",
- "w:w": 0,
- },
- },
- },
- {
- "w:bottom": {
- _attr: {
- "w:type": "auto",
- "w:w": 0,
- },
- },
- },
- {
- "w:right": {
- _attr: {
- "w:type": "auto",
- "w:w": 0,
- },
- },
- },
- ],
-};
+import { WidthType } from "./table-width";
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:color": "auto" } } },
+ { "w:left": { _attr: { "w:val": "single", "w:sz": 4, "w:color": "auto" } } },
+ { "w:bottom": { _attr: { "w:val": "single", "w:sz": 4, "w:color": "auto" } } },
+ { "w:right": { _attr: { "w:val": "single", "w:sz": 4, "w:color": "auto" } } },
+ { "w:insideH": { _attr: { "w:val": "single", "w:sz": 4, "w:color": "auto" } } },
+ { "w:insideV": { _attr: { "w:val": "single", "w:sz": 4, "w:color": "auto" } } },
],
};
@@ -177,7 +140,7 @@ describe("Table", () => {
};
expect(tree).to.deep.equal({
"w:tbl": [
- { "w:tblPr": [WIDTHS, BORDERS, DEFAULT_TABLE_PROPERTIES] },
+ { "w:tblPr": [WIDTHS, BORDERS] },
{
"w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }, { "w:gridCol": { _attr: { "w:w": 100 } } }],
},
@@ -223,7 +186,7 @@ describe("Table", () => {
const cellP = { "w:p": [{ "w:r": [{ "w:t": [{ _attr: { "xml:space": "preserve" } }, "hello"] }] }] };
expect(tree).to.deep.equal({
"w:tbl": [
- { "w:tblPr": [WIDTHS, BORDERS, DEFAULT_TABLE_PROPERTIES] },
+ { "w:tblPr": [WIDTHS, BORDERS] },
{
"w:tblGrid": [{ "w:gridCol": { _attr: { "w:w": 100 } } }, { "w:gridCol": { _attr: { "w:w": 100 } } }],
},
@@ -270,7 +233,7 @@ describe("Table", () => {
const tree = new Formatter().format(table);
expect(tree).to.have.property("w:tbl").which.is.an("array").with.has.length.at.least(1);
expect(tree["w:tbl"][0]).to.deep.equal({
- "w:tblPr": [WIDTHS, BORDERS, { "w:tblLayout": { _attr: { "w:type": "fixed" } } }, DEFAULT_TABLE_PROPERTIES],
+ "w:tblPr": [WIDTHS, BORDERS, { "w:tblLayout": { _attr: { "w:type": "fixed" } } }],
});
});
@@ -290,7 +253,7 @@ describe("Table", () => {
const tree = new Formatter().format(table);
expect(tree).to.have.property("w:tbl").which.is.an("array").with.has.length.at.least(1);
expect(tree["w:tbl"][0]).to.deep.equal({
- "w:tblPr": [WIDTHS, { "w:jc": { _attr: { "w:val": "center" } } }, BORDERS, DEFAULT_TABLE_PROPERTIES],
+ "w:tblPr": [WIDTHS, { "w:jc": { _attr: { "w:val": "center" } } }, BORDERS],
});
});
@@ -319,13 +282,12 @@ describe("Table", () => {
"w:tblW": {
_attr: {
"w:type": "pct",
- "w:w": "100%",
+ "w:w": 100,
},
},
},
BORDERS,
{ "w:tblLayout": { _attr: { "w:type": "fixed" } } },
- DEFAULT_TABLE_PROPERTIES,
],
});
});
@@ -495,7 +457,6 @@ describe("Table", () => {
},
WIDTHS,
BORDERS,
- DEFAULT_TABLE_PROPERTIES,
],
});
});
diff --git a/src/file/table/table.ts b/src/file/table/table.ts
index ea4acd93d5..5751207ba9 100644
--- a/src/file/table/table.ts
+++ b/src/file/table/table.ts
@@ -3,10 +3,12 @@ import { XmlComponent } from "file/xml-components";
import { AlignmentType } from "../paragraph";
import { TableGrid } from "./grid";
-import { TableCell, VerticalMergeType, WidthType } from "./table-cell";
+import { TableCell, VerticalMergeType } from "./table-cell";
import { ITableBordersOptions, ITableFloatOptions, TableProperties } from "./table-properties";
+import { ITableCellMarginOptions } from "./table-properties/table-cell-margin";
import { TableLayoutType } from "./table-properties/table-layout";
import { TableRow } from "./table-row";
+import { ITableWidthProperties } from "./table-width";
/*
0-width columns don't get rendered correctly, so we need
@@ -20,18 +22,10 @@ import { TableRow } from "./table-row";
*/
export interface ITableOptions {
readonly rows: TableRow[];
- readonly width?: {
- readonly size: number;
- readonly type?: WidthType;
- };
+ readonly width?: ITableWidthProperties;
readonly columnWidths?: number[];
- readonly margins?: {
- readonly marginUnitType?: WidthType;
- readonly top?: number;
- readonly bottom?: number;
- readonly right?: number;
- readonly left?: number;
- };
+ readonly margins?: ITableCellMarginOptions;
+ readonly indent?: ITableWidthProperties;
readonly float?: ITableFloatOptions;
readonly layout?: TableLayoutType;
readonly style?: string;
@@ -45,7 +39,8 @@ export class Table extends XmlComponent {
rows,
width,
columnWidths = Array(Math.max(...rows.map((row) => row.CellCount))).fill(100),
- margins: { marginUnitType, top, bottom, right, left } = { marginUnitType: WidthType.AUTO, top: 0, bottom: 0, right: 0, left: 0 },
+ margins,
+ indent,
float,
layout,
style,
@@ -59,28 +54,12 @@ export class Table extends XmlComponent {
new TableProperties({
borders: borders ?? {},
width: width ?? { size: 100 },
+ indent,
float,
layout,
style,
alignment,
- cellMargin: {
- bottom: {
- value: bottom || 0,
- type: marginUnitType,
- },
- top: {
- value: top || 0,
- type: marginUnitType,
- },
- left: {
- value: left || 0,
- type: marginUnitType,
- },
- right: {
- value: right || 0,
- type: marginUnitType,
- },
- },
+ cellMargin: margins,
visuallyRightToLeft,
}),
);
diff --git a/src/file/track-revision/track-revision-components/deleted-text-run.spec.ts b/src/file/track-revision/track-revision-components/deleted-text-run.spec.ts
index 6bd11c24d7..9eacb7c23c 100644
--- a/src/file/track-revision/track-revision-components/deleted-text-run.spec.ts
+++ b/src/file/track-revision/track-revision-components/deleted-text-run.spec.ts
@@ -54,18 +54,10 @@ describe("DeletedTextRun", () => {
{
"w:rPr": [
{
- "w:b": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:b": {},
},
{
- "w:bCs": {
- _attr: {
- "w:val": true,
- },
- },
+ "w:bCs": {},
},
],
},
diff --git a/src/file/values.spec.ts b/src/file/values.spec.ts
new file mode 100644
index 0000000000..3ef06a6abc
--- /dev/null
+++ b/src/file/values.spec.ts
@@ -0,0 +1,193 @@
+import { expect } from "chai";
+import {
+ dateTimeValue,
+ hexColorValue,
+ hpsMeasureValue,
+ longHexNumber,
+ measurementOrPercentValue,
+ percentageValue,
+ positiveUniversalMeasureValue,
+ shortHexNumber,
+ signedHpsMeasureValue,
+ signedTwipsMeasureValue,
+ twipsMeasureValue,
+ universalMeasureValue,
+ unsignedDecimalNumber,
+} from "./values";
+
+describe("values", () => {
+ describe("universalMeasureValue", () => {
+ it("should allow valid values", () => {
+ // "-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
+ expect(universalMeasureValue("-9mm")).to.eq("-9mm");
+ expect(universalMeasureValue("-0.5in")).to.eq("-0.5in");
+ expect(universalMeasureValue("20.pt")).to.eq("20pt");
+ expect(universalMeasureValue("5.22pc")).to.eq("5.22pc");
+ expect(universalMeasureValue("100 pi")).to.eq("100pi");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => universalMeasureValue("100pp")).to.throw();
+ expect(() => universalMeasureValue("foo")).to.throw();
+ expect(() => universalMeasureValue("--in")).to.throw();
+ expect(() => universalMeasureValue("NaNpc")).to.throw();
+ expect(() => universalMeasureValue("50")).to.throw();
+ });
+ });
+
+ describe("positiveUniversalMeasureValue", () => {
+ it("should allow valid values", () => {
+ // "[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
+ expect(positiveUniversalMeasureValue("9mm")).to.eq("9mm");
+ expect(positiveUniversalMeasureValue("0.5in")).to.eq("0.5in");
+ expect(positiveUniversalMeasureValue("20.pt")).to.eq("20pt");
+ expect(positiveUniversalMeasureValue("5.22pc")).to.eq("5.22pc");
+ expect(positiveUniversalMeasureValue("100 pi")).to.eq("100pi");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => positiveUniversalMeasureValue("-9mm")).to.throw();
+ expect(() => positiveUniversalMeasureValue("-0.5in")).to.throw();
+ expect(() => positiveUniversalMeasureValue("100pp")).to.throw();
+ expect(() => positiveUniversalMeasureValue("foo")).to.throw();
+ expect(() => positiveUniversalMeasureValue("--in")).to.throw();
+ expect(() => positiveUniversalMeasureValue("NaNpc")).to.throw();
+ expect(() => positiveUniversalMeasureValue("50")).to.throw();
+ });
+ });
+
+ describe("longHexNumber", () => {
+ it("should allow valid values", () => {
+ expect(longHexNumber("112233FF")).to.eq("112233FF");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => longHexNumber("112233GG")).to.throw();
+ expect(() => longHexNumber("112233F")).to.throw();
+ expect(() => longHexNumber("112233FFF")).to.throw();
+ });
+ });
+
+ describe("shortHexNumber", () => {
+ it("should allow valid values", () => {
+ expect(shortHexNumber("1122")).to.eq("1122");
+ expect(shortHexNumber("FFFF")).to.eq("FFFF");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => shortHexNumber("11")).to.throw();
+ expect(() => shortHexNumber("112233")).to.throw();
+ expect(() => shortHexNumber("FFFG")).to.throw();
+ });
+ });
+
+ describe("hexColorValue", () => {
+ it("should allow valid values", () => {
+ expect(hexColorValue("auto")).to.eq("auto");
+ expect(hexColorValue("FF0000")).to.eq("FF0000");
+ expect(hexColorValue("aabbcc")).to.eq("aabbcc");
+ expect(hexColorValue("#BEEFEE")).to.eq("BEEFEE");
+ expect(hexColorValue("abcdef")).to.eq("abcdef");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => hexColorValue("foo")).to.throw();
+ expect(() => hexColorValue("fff")).to.throw();
+ expect(() => hexColorValue("a")).to.throw();
+ expect(() => hexColorValue("abcde")).to.throw();
+ expect(() => hexColorValue("---")).to.throw();
+ expect(() => hexColorValue("brown")).to.throw();
+ });
+ });
+
+ describe("unsignedDecimalNumber", () => {
+ it("should allow valid values", () => {
+ expect(unsignedDecimalNumber(1243)).to.eq(1243);
+ expect(unsignedDecimalNumber(12.43)).to.eq(12);
+ expect(unsignedDecimalNumber(1e10)).to.eq(1e10);
+ });
+ it("should throw on invalid values", () => {
+ expect(() => unsignedDecimalNumber(NaN)).to.throw();
+ expect(() => unsignedDecimalNumber(-10)).to.throw();
+ });
+ });
+
+ describe("signedTwipsMeasureValue", () => {
+ it("should allow valid values", () => {
+ expect(signedTwipsMeasureValue(1243)).to.eq(1243);
+ expect(signedTwipsMeasureValue("-5mm")).to.eq("-5mm");
+ expect(signedTwipsMeasureValue("10.in")).to.eq("10in");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => signedTwipsMeasureValue(NaN)).to.throw();
+ expect(() => signedTwipsMeasureValue("foo")).to.throw();
+ });
+ });
+
+ describe("twipsMeasureValue", () => {
+ it("should allow valid values", () => {
+ expect(twipsMeasureValue(1243)).to.eq(1243);
+ expect(twipsMeasureValue("5mm")).to.eq("5mm");
+ expect(twipsMeasureValue("10.in")).to.eq("10in");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => twipsMeasureValue(-12)).to.throw();
+ expect(() => twipsMeasureValue(NaN)).to.throw();
+ expect(() => twipsMeasureValue("foo")).to.throw();
+ expect(() => twipsMeasureValue("-5mm")).to.throw();
+ });
+ });
+
+ describe("hpsMeasureValue", () => {
+ it("should allow valid values", () => {
+ expect(hpsMeasureValue(1243)).to.eq(1243);
+ expect(hpsMeasureValue("5mm")).to.eq("5mm");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => hpsMeasureValue(NaN)).to.throw();
+ expect(() => hpsMeasureValue("-5mm")).to.throw();
+ });
+ });
+
+ describe("signedHpsMeasureValue", () => {
+ it("should allow valid values", () => {
+ expect(signedHpsMeasureValue(1243)).to.eq(1243);
+ expect(signedHpsMeasureValue(-1243)).to.eq(-1243);
+ expect(signedHpsMeasureValue("5mm")).to.eq("5mm");
+ expect(signedHpsMeasureValue("-5mm")).to.eq("-5mm");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => hpsMeasureValue(NaN)).to.throw();
+ expect(() => hpsMeasureValue("5FF")).to.throw();
+ });
+ });
+
+ describe("percentageValue", () => {
+ it("should allow valid values", () => {
+ expect(percentageValue("0%")).to.eq("0%");
+ expect(percentageValue("-20%")).to.eq("-20%");
+ expect(percentageValue("100%")).to.eq("100%");
+ expect(percentageValue("1000%")).to.eq("1000%");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => percentageValue("0%%")).to.throw();
+ expect(() => percentageValue("20")).to.throw();
+ expect(() => percentageValue("FF%")).to.throw();
+ });
+ });
+
+ describe("measurementOrPercentValue", () => {
+ it("should allow valid values", () => {
+ expect(measurementOrPercentValue(1243)).to.eq(1243);
+ expect(measurementOrPercentValue(-1243)).to.eq(-1243);
+ expect(measurementOrPercentValue("10%")).to.eq("10%");
+ expect(measurementOrPercentValue("5mm")).to.eq("5mm");
+ });
+ it("should throw on invalid values", () => {
+ expect(() => measurementOrPercentValue(NaN)).to.throw();
+ expect(() => measurementOrPercentValue("10%%")).to.throw();
+ expect(() => measurementOrPercentValue("10F")).to.throw();
+ });
+ });
+
+ describe("dateTimeValue", () => {
+ it("should allow valid values", () => {
+ expect(dateTimeValue(new Date())).to.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d+)?Z/);
+ });
+ });
+});
diff --git a/src/file/values.ts b/src/file/values.ts
new file mode 100644
index 0000000000..8634d47de4
--- /dev/null
+++ b/src/file/values.ts
@@ -0,0 +1,226 @@
+// Runtime checks and cleanup for value types in the spec that aren't easily expressed through our type system.
+// These will help us to prevent silent failures and corrupted documents.
+//
+// Most of the rest of the types not defined here are either aliases of existing types or enumerations.
+// Enumerations should probably just be implemented as enums, with instructions to end-users, without a runtime check.
+
+//
+//
+//
+export function decimalNumber(val: number): number {
+ if (isNaN(val)) {
+ throw new Error(`Invalid value '${val}' specified. Must be an integer.`);
+ }
+ return Math.floor(val);
+}
+
+//
+//
+//
+export function unsignedDecimalNumber(val: number): number {
+ const value = decimalNumber(val);
+ if (value < 0) {
+ throw new Error(`Invalid value '${val}' specified. Must be a positive integer.`);
+ }
+ return value;
+}
+
+// The xsd:hexBinary type represents binary data as a sequence of binary octets.
+// It uses hexadecimal encoding, where each binary octet is a two-character hexadecimal number.
+// Lowercase and uppercase letters A through F are permitted. For example, 0FB8 and 0fb8 are two
+// equal xsd:hexBinary representations consisting of two octets.
+// http://www.datypic.com/sc/xsd/t-xsd_hexBinary.html
+function hexBinary(val: string, length: number): string {
+ const expectedLength = length * 2;
+ if (val.length !== expectedLength || isNaN(Number("0x" + val))) {
+ throw new Error(`Invalid hex value '${val}'. Expected ${expectedLength} digit hex value`);
+ }
+ return val;
+}
+
+//
+//
+//
+//
+//
+export function longHexNumber(val: string): string {
+ return hexBinary(val, 4);
+}
+
+//
+//
+//
+//
+//
+export function shortHexNumber(val: string): string {
+ return hexBinary(val, 2);
+}
+
+//
+//
+//
+//
+//
+export function uCharHexNumber(val: string): string {
+ return hexBinary(val, 1);
+}
+
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+export function universalMeasureValue(val: string): string {
+ const unit = val.slice(-2);
+ if (!universalMeasureUnits.includes(unit)) {
+ throw new Error(`Invalid unit '${unit}' specified. Valid units are ${universalMeasureUnits.join(", ")}`);
+ }
+ const amount = val.substring(0, val.length - 2);
+ if (isNaN(Number(amount))) {
+ throw new Error(`Invalid value '${amount}' specified. Expected a valid number.`);
+ }
+ return `${Number(amount)}${unit}`;
+}
+const universalMeasureUnits = ["mm", "cm", "in", "pt", "pc", "pi"];
+
+//
+//
+//
+//
+//
+export function positiveUniversalMeasureValue(val: string): string {
+ const value = universalMeasureValue(val);
+ if (parseFloat(value) < 0) {
+ throw new Error(`Invalid value '${value}' specified. Expected a positive number.`);
+ }
+ return value;
+}
+
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+//
+//
+//
+//
+export function hexColorValue(val: string): string {
+ if (val === "auto") {
+ return val;
+ }
+ // It's super common to see colors prefixed with a pound, but technically invalid here.
+ // Most clients work with it, but strip it off anyway for strict compliance.
+ const color = val.charAt(0) === "#" ? val.substring(1) : val;
+ return hexBinary(color, 3);
+}
+
+//
+//
+//
+export function signedTwipsMeasureValue(val: string | number): string | number {
+ return typeof val === "string" ? universalMeasureValue(val) : decimalNumber(val);
+}
+
+//
+//
+//
+export function hpsMeasureValue(val: string | number): string | number {
+ return typeof val === "string" ? positiveUniversalMeasureValue(val) : unsignedDecimalNumber(val);
+}
+
+//
+//
+//
+export function signedHpsMeasureValue(val: string | number): string | number {
+ return typeof val === "string" ? universalMeasureValue(val) : decimalNumber(val);
+}
+
+//
+//
+//
+export function twipsMeasureValue(val: string | number): string | number {
+ return typeof val === "string" ? positiveUniversalMeasureValue(val) : unsignedDecimalNumber(val);
+}
+
+//
+//
+//
+//
+//
+export function percentageValue(val: string): string {
+ if (val.slice(-1) !== "%") {
+ throw new Error(`Invalid value '${val}'. Expected percentage value (eg '55%')`);
+ }
+ const percent = val.substring(0, val.length - 1);
+ if (isNaN(Number(percent))) {
+ throw new Error(`Invalid value '${percent}' specified. Expected a valid number.`);
+ }
+ return `${Number(percent)}%`;
+}
+
+//
+//
+//
+
+//
+//
+//
+
+//
+//
+//
+
+export function measurementOrPercentValue(val: number | string): number | string {
+ if (typeof val === "number") {
+ return decimalNumber(val);
+ }
+ if (val.slice(-1) === "%") {
+ return percentageValue(val);
+ }
+ return universalMeasureValue(val);
+}
+
+//
+//
+//
+export const eighthPointMeasureValue = unsignedDecimalNumber;
+
+//
+//
+//
+export const pointMeasureValue = unsignedDecimalNumber;
+
+//
+//
+//
+//
+// http://www.datypic.com/sc/xsd/t-xsd_dateTime.html
+// The type xsd:dateTime represents a specific date and time in the format
+// CCYY-MM-DDThh:mm:ss.sss, which is a concatenation of the date and time forms,
+// separated by a literal letter "T". All of the same rules that apply to the date
+// and time types are applicable to xsd:dateTime as well.
+//
+// An optional time zone expression may be added at the end of the value.
+// The letter Z is used to indicate Coordinated Universal Time (UTC). All other time
+// zones are represented by their difference from Coordinated Universal Time in the
+// format +hh:mm, or -hh:mm. These values may range from -14:00 to 14:00. For example,
+// US Eastern Standard Time, which is five hours behind UTC, is represented as -05:00.
+// If no time zone value is present, it is considered unknown; it is not assumed to be UTC.
+//
+// Luckily, js has this format built in already. See:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
+export function dateTimeValue(val: Date): string {
+ return val.toISOString();
+}
diff --git a/src/file/vertical-align/index.ts b/src/file/vertical-align/index.ts
new file mode 100644
index 0000000000..29714c88b6
--- /dev/null
+++ b/src/file/vertical-align/index.ts
@@ -0,0 +1 @@
+export * from "./vertical-align";
diff --git a/src/file/vertical-align/vertical-align.ts b/src/file/vertical-align/vertical-align.ts
new file mode 100644
index 0000000000..a031eb674d
--- /dev/null
+++ b/src/file/vertical-align/vertical-align.ts
@@ -0,0 +1,34 @@
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+//
+//
+//
+
+//
+//
+//
+//
+//
+//
+//
+//
+export enum VerticalAlign {
+ BOTH = "both",
+ BOTTOM = "bottom",
+ CENTER = "center",
+ TOP = "top",
+}
+export class VerticalAlignAttributes extends XmlAttributeComponent<{
+ readonly verticalAlign?: VerticalAlign;
+}> {
+ protected readonly xmlKeys = {
+ verticalAlign: "w:val",
+ };
+}
+
+export class VerticalAlignElement extends XmlComponent {
+ constructor(value: VerticalAlign) {
+ super("w:vAlign");
+ this.root.push(new VerticalAlignAttributes({ verticalAlign: value }));
+ }
+}
diff --git a/src/file/xml-components/base.ts b/src/file/xml-components/base.ts
index 375e30d910..7a0d5a758b 100644
--- a/src/file/xml-components/base.ts
+++ b/src/file/xml-components/base.ts
@@ -9,16 +9,10 @@ export interface IContext {
export abstract class BaseXmlComponent {
protected readonly rootKey: string;
- // tslint:disable-next-line:readonly-keyword
- protected deleted: boolean = false;
constructor(rootKey: string) {
this.rootKey = rootKey;
}
public abstract prepForXml(context: IContext): IXmlableObject | undefined;
-
- public get IsDeleted(): boolean {
- return this.deleted;
- }
}
diff --git a/src/file/xml-components/imported-xml-component.spec.ts b/src/file/xml-components/imported-xml-component.spec.ts
index 0f590b1286..58c07d09ca 100644
--- a/src/file/xml-components/imported-xml-component.spec.ts
+++ b/src/file/xml-components/imported-xml-component.spec.ts
@@ -20,28 +20,24 @@ const xmlString = `
`;
const convertedXmlElement = {
- deleted: false,
root: [
{
- 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"] }] },
+ { rootKey: "_attr", root: { "w:one": "value 1", "w:two": "value 2" } },
+ { rootKey: "w:rPr", root: [{ rootKey: "w:noProof", root: ["some value"] }] },
{
- deleted: false,
rootKey: "w:r",
root: [
- { deleted: false, rootKey: "_attr", root: { active: "true" } },
- { deleted: false, rootKey: "w:t", root: ["Text 1"] },
+ { rootKey: "_attr", root: { active: "true" } },
+ { 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"] },
+ { rootKey: "_attr", root: { active: "true" } },
+ { rootKey: "w:t", root: ["Text 2"] },
],
},
],
diff --git a/src/file/xml-components/index.ts b/src/file/xml-components/index.ts
index 295161b395..9ad7572069 100644
--- a/src/file/xml-components/index.ts
+++ b/src/file/xml-components/index.ts
@@ -4,4 +4,5 @@ export * from "./default-attributes";
export * from "./imported-xml-component";
export * from "./xmlable-object";
export * from "./initializable-xml-component";
+export * from "./simple-elements";
export * from "./base";
diff --git a/src/file/xml-components/simple-elements.ts b/src/file/xml-components/simple-elements.ts
new file mode 100644
index 0000000000..02562e4c58
--- /dev/null
+++ b/src/file/xml-components/simple-elements.ts
@@ -0,0 +1,65 @@
+import { Attributes, XmlComponent } from "file/xml-components";
+
+import { hpsMeasureValue } from "../values";
+
+// This represents element type CT_OnOff, which indicate a boolean value.
+//
+// A value of 1 or true specifies that the property shall be explicitly applied.
+// This is the default value for this attribute, and is implied when the parent
+// element is present, but this attribute is omitted.
+// A value of 0 or false specifies that the property shall be explicitly turned off.
+//
+//
+//
+//
+export class OnOffElement extends XmlComponent {
+ constructor(name: string, val: boolean | undefined = true) {
+ super(name);
+ if (val !== true) {
+ this.root.push(new Attributes({ val }));
+ }
+ }
+}
+
+// This represents element type CT_HpsMeasure, which indicate an unsigned int or a measurement with unit.
+//
+//
+//
+//
+export class HpsMeasureElement extends XmlComponent {
+ constructor(name: string, val: number | string) {
+ super(name);
+ this.root.push(new Attributes({ val: hpsMeasureValue(val) }));
+ }
+}
+
+// This represents element type CT_String, which indicate a string value.
+//
+//
+//
+//
+export class StringValueElement extends XmlComponent {
+ constructor(name: string, val: string) {
+ super(name);
+ this.root.push(new Attributes({ val }));
+ }
+}
+
+// This represents various number element types.
+export class NumberValueElement extends XmlComponent {
+ constructor(name: string, val: number) {
+ super(name);
+ this.root.push(new Attributes({ val }));
+ }
+}
+
+// Simple nodes containing text.
+//
+// new StringContainer("hello", "world")
+// world
+export class StringContainer extends XmlComponent {
+ constructor(name: string, val: string) {
+ super(name);
+ this.root.push(val);
+ }
+}
diff --git a/src/file/xml-components/xml-component.spec.ts b/src/file/xml-components/xml-component.spec.ts
index 4fa5bfc515..497f14eab2 100644
--- a/src/file/xml-components/xml-component.spec.ts
+++ b/src/file/xml-components/xml-component.spec.ts
@@ -1,41 +1,62 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
-import { EMPTY_OBJECT, XmlComponent } from "./";
-import { IContext } from "./base";
+import { Attributes, BaseXmlComponent, XmlComponent } from "./";
-class TestComponent extends XmlComponent {}
+class TestComponent extends XmlComponent {
+ public push(el: BaseXmlComponent): void {
+ this.root.push(el);
+ }
+}
describe("XmlComponent", () => {
- let xmlComponent: TestComponent;
-
- beforeEach(() => {
- xmlComponent = new TestComponent("w:test");
- });
-
describe("#constructor()", () => {
it("should create an Xml Component which has the correct rootKey", () => {
+ const xmlComponent = new TestComponent("w:test");
const tree = new Formatter().format(xmlComponent);
expect(tree).to.deep.equal({
"w:test": {},
});
});
- });
+ it("should handle children elements", () => {
+ const xmlComponent = new TestComponent("w:test");
+ xmlComponent.push(
+ new Attributes({
+ val: "test",
+ }),
+ );
+ xmlComponent.push(new TestComponent("innerTest"));
- describe("#prepForXml()", () => {
- it("should skip deleted elements", () => {
- const child = new TestComponent("w:test1");
- child.delete();
- xmlComponent.addChildElement(child);
+ const tree = new Formatter().format(xmlComponent);
+ expect(tree).to.deep.equal({
+ "w:test": [
+ {
+ _attr: {
+ "w:val": "test",
+ },
+ },
+ {
+ innerTest: {},
+ },
+ ],
+ });
+ });
+ it("should hoist attrs if only attrs are present", () => {
+ const xmlComponent = new TestComponent("w:test");
+ xmlComponent.push(
+ new Attributes({
+ val: "test",
+ }),
+ );
- // tslint:disable-next-line: no-object-literal-type-assertion
- const xml = xmlComponent.prepForXml({} as IContext);
-
- if (!xml) {
- return;
- }
-
- expect(xml["w:test"]).to.deep.equal(EMPTY_OBJECT);
+ const tree = new Formatter().format(xmlComponent);
+ expect(tree).to.deep.equal({
+ "w:test": {
+ _attr: {
+ "w:val": "test",
+ },
+ },
+ });
});
});
});
diff --git a/src/file/xml-components/xml-component.ts b/src/file/xml-components/xml-component.ts
index a4e77b30a6..f1e76aa797 100644
--- a/src/file/xml-components/xml-component.ts
+++ b/src/file/xml-components/xml-component.ts
@@ -14,12 +14,6 @@ export abstract class XmlComponent extends BaseXmlComponent {
public prepForXml(context: IContext): IXmlableObject | undefined {
const children = this.root
- .filter((c) => {
- if (c instanceof BaseXmlComponent) {
- return !c.IsDeleted;
- }
- return c !== undefined;
- })
.map((comp) => {
if (comp instanceof BaseXmlComponent) {
return comp.prepForXml(context);
@@ -29,13 +23,11 @@ export abstract class XmlComponent extends BaseXmlComponent {
.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.)
+ // avoid an unneeded XML close element.
// 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.length ? (children.length === 1 && onlyAttrs(children[0]) ? children[0] : children) : EMPTY_OBJECT,
+ [this.rootKey]: children.length ? (children.length === 1 && children[0]?._attr ? children[0] : children) : EMPTY_OBJECT,
};
}
@@ -44,10 +36,6 @@ export abstract class XmlComponent extends BaseXmlComponent {
return this;
}
-
- public delete(): void {
- this.deleted = true;
- }
}
export abstract class IgnoreIfEmptyXmlComponent extends XmlComponent {
diff --git a/src/import-dotx/import-dotx.ts b/src/import-dotx/import-dotx.ts
index 69a1ff0bcc..61340bf79e 100644
--- a/src/import-dotx/import-dotx.ts
+++ b/src/import-dotx/import-dotx.ts
@@ -1,8 +1,7 @@
import * as JSZip from "jszip";
import { Element as XMLElement, ElementCompact as XMLElementCompact, xml2js } from "xml-js";
-import { FooterReferenceType } from "file/document/body/section-properties/footer-reference";
-import { HeaderReferenceType } from "file/document/body/section-properties/header-reference";
+import { HeaderFooterReferenceType } from "file/document/body/section-properties";
import { FooterWrapper, IDocumentFooter } from "file/footer-wrapper";
import { HeaderWrapper, IDocumentHeader } from "file/header-wrapper";
import { Media } from "file/media";
@@ -17,8 +16,8 @@ const schemeToType = {
};
interface IDocumentRefs {
- readonly headers: { readonly id: number; readonly type: HeaderReferenceType }[];
- readonly footers: { readonly id: number; readonly type: FooterReferenceType }[];
+ readonly headers: { readonly id: number; readonly type: HeaderFooterReferenceType }[];
+ readonly footers: { readonly id: number; readonly type: HeaderFooterReferenceType }[];
}
enum RelationshipType {
@@ -219,7 +218,7 @@ export class ImportDotx {
throw Error("header referecne element has no attributes");
}
return {
- type: item._attributes["w:type"] as HeaderReferenceType,
+ type: item._attributes["w:type"] as HeaderFooterReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});
@@ -239,7 +238,7 @@ export class ImportDotx {
throw Error("footer referecne element has no attributes");
}
return {
- type: item._attributes["w:type"] as FooterReferenceType,
+ type: item._attributes["w:type"] as HeaderFooterReferenceType,
id: this.parseRefId(item._attributes["r:id"] as string),
};
});