From dd6d1bc039606791d1aa959ff07296d0e81fdc04 Mon Sep 17 00:00:00 2001 From: Tom Hunkapiller Date: Sun, 23 May 2021 21:17:20 +0300 Subject: [PATCH] Consolidate TableWidth and TableCellMargins types; add Table indent (#954) --- docs/usage/tables.md | 16 +++- src/file/table/index.ts | 1 + .../cell-margin/cell-margin.spec.ts | 73 -------------- .../table-cell/cell-margin/cell-margin.ts | 61 ------------ .../cell-margin/table-cell-margins.spec.ts | 96 ------------------- .../cell-margin/table-cell-margins.ts | 21 ---- .../table/table-cell/table-cell-components.ts | 31 ------ .../table-cell/table-cell-properties.spec.ts | 73 +++++--------- .../table/table-cell/table-cell-properties.ts | 14 +-- src/file/table/table-cell/table-cell.spec.ts | 24 +---- .../table-cell-margin.spec.ts | 62 +++++------- .../table-properties/table-cell-margin.ts | 85 ++++++++-------- .../table-properties/table-properties.spec.ts | 14 +-- .../table-properties/table-properties.ts | 43 +++++++-- .../table/table-properties/table-width.ts | 19 ---- src/file/table/table-width.ts | 42 ++++++++ src/file/table/table.spec.ts | 51 ++-------- src/file/table/table.ts | 41 ++------ 18 files changed, 215 insertions(+), 552 deletions(-) delete mode 100644 src/file/table/table-cell/cell-margin/cell-margin.spec.ts delete mode 100644 src/file/table/table-cell/cell-margin/cell-margin.ts delete mode 100644 src/file/table/table-cell/cell-margin/table-cell-margins.spec.ts delete mode 100644 src/file/table/table-cell/cell-margin/table-cell-margins.ts delete mode 100644 src/file/table/table-properties/table-width.ts create mode 100644 src/file/table/table-width.ts diff --git a/docs/usage/tables.md b/docs/usage/tables.md index a7b0ff9979..7b140bb55c 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: @@ -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", }, - bottom: { + right: { style: BorderStyle.DOT_DOT_DASH, size: 3, color: "ff8000", diff --git a/src/file/table/index.ts b/src/file/table/index.ts index a9d2968920..81ceac8b1a 100644 --- a/src/file/table/index.ts +++ b/src/file/table/index.ts @@ -2,3 +2,4 @@ export * from "./table"; export * from "./table-cell"; export * from "./table-properties"; export * from "./table-row"; +export * from "./table-width"; 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 615aae78e9..9b31f3f29d 100644 --- a/src/file/table/table-cell/table-cell-components.ts +++ b/src/file/table/table-cell/table-cell-components.ts @@ -139,34 +139,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 = WidthType.AUTO) { - 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 5e48b1684f..8b5e8cbb94 100644 --- a/src/file/table/table-cell/table-cell-properties.spec.ts +++ b/src/file/table/table-cell/table-cell-properties.spec.ts @@ -2,8 +2,9 @@ import { expect } from "chai"; import { Formatter } from "export/formatter"; import { BorderStyle } from "file/border"; +import { WidthType } from "../table-width"; -import { VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components"; +import { VerticalAlign, VerticalMergeType } from "./table-cell-components"; import { TableCellProperties } from "./table-cell-properties"; describe("TableCellProperties", () => { @@ -67,53 +68,6 @@ describe("TableCellProperties", () => { expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": { _attr: { "w:fill": "test", "w:color": "000" } } }] }); }); - it("sets shading", () => { - const properties = new TableCellProperties({ - margins: {}, - }); - 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: { @@ -131,5 +85,28 @@ describe("TableCellProperties", () => { "w:tcBorders": [{ "w:top": { _attr: { "w:val": "dashDotStroked", "w:sz": 3, "w:color": "red" } } }], }); }); + + 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 } } }, + ], + }); + }); }); }); diff --git a/src/file/table/table-cell/table-cell-properties.ts b/src/file/table/table-cell/table-cell-properties.ts index 1eae98768c..ebbf44bd55 100644 --- a/src/file/table/table-cell/table-cell-properties.ts +++ b/src/file/table/table-cell/table-cell-properties.ts @@ -1,19 +1,18 @@ import { IgnoreIfEmptyXmlComponent } from "file/xml-components"; import { IShadingAttributesProperties, Shading } from "../../shading"; -import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins"; +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 { @@ -22,10 +21,7 @@ export interface ITableCellPropertiesOptions { readonly verticalAlign?: VerticalAlign; readonly textDirection?: TextDirection; readonly verticalMerge?: VerticalMergeType; - readonly width?: { - readonly size: number | string; - readonly type?: WidthType; - }; + readonly width?: ITableWidthProperties; readonly columnSpan?: number; readonly rowSpan?: number; readonly borders?: ITableCellBorders; @@ -36,7 +32,7 @@ export class TableCellProperties extends IgnoreIfEmptyXmlComponent { super("w:tcPr"); if (options.width) { - this.root.push(new TableCellWidth(options.width.size, options.width.type)); + this.root.push(new TableWidthElement("w:tcW", options.width)); } if (options.columnSpan) { @@ -59,7 +55,7 @@ export class TableCellProperties extends IgnoreIfEmptyXmlComponent { } if (options.margins) { - this.root.push(new TableCellMargin(options.margins)); + this.root.push(new TableCellMargin(TableCellMarginElementType.TABLE_CELL, options.margins)); } if (options.textDirection) { diff --git a/src/file/table/table-cell/table-cell.spec.ts b/src/file/table/table-cell/table-cell.spec.ts index 3abca3009d..51b452f347 100644 --- a/src/file/table/table-cell/table-cell.spec.ts +++ b/src/file/table/table-cell/table-cell.spec.ts @@ -4,8 +4,9 @@ import { Formatter } from "export/formatter"; import { BorderStyle } from "file/border"; import { ShadingType } from "file/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, VerticalAlign, VerticalMergeType } from "./table-cell-components"; describe("TableCellBorders", () => { describe("#prepForXml", () => { @@ -263,23 +264,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", () => { @@ -410,7 +394,7 @@ describe("TableCell", () => { }, }, { - "w:start": { + "w:left": { _attr: { "w:type": "dxa", "w:w": 1, @@ -426,7 +410,7 @@ describe("TableCell", () => { }, }, { - "w:end": { + "w:right": { _attr: { "w:type": "dxa", "w:w": 1, 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-properties.spec.ts b/src/file/table/table-properties/table-properties.spec.ts index 74042d386a..0059f0e219 100644 --- a/src/file/table/table-properties/table-properties.spec.ts +++ b/src/file/table/table-properties/table-properties.spec.ts @@ -5,7 +5,7 @@ import { Formatter } from "export/formatter"; import { AlignmentType } from "file/paragraph"; import { ShadingType } from "file/shading"; -import { WidthType } from "../table-cell"; +import { WidthType } from "../table-width"; import { TableLayoutType } from "./table-layout"; import { TableProperties } from "./table-properties"; @@ -78,10 +78,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, }, }); @@ -94,10 +92,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, }, }); diff --git a/src/file/table/table-properties/table-properties.ts b/src/file/table/table-properties/table-properties.ts index 368c52fc3b..a615584ce2 100644 --- a/src/file/table/table-properties/table-properties.ts +++ b/src/file/table/table-properties/table-properties.ts @@ -1,22 +1,41 @@ // http://officeopenxml.com/WPtableProperties.php +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// import { IgnoreIfEmptyXmlComponent } from "file/xml-components"; import { Alignment, AlignmentType } from "../../paragraph"; import { IShadingAttributesProperties, Shading } from "../../shading"; -import { WidthType } from "../table-cell"; +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; @@ -44,13 +63,17 @@ export class TableProperties extends IgnoreIfEmptyXmlComponent { } 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)); } @@ -63,6 +86,8 @@ export class TableProperties extends IgnoreIfEmptyXmlComponent { 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-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-width.ts b/src/file/table/table-width.ts new file mode 100644 index 0000000000..d25fa69276 --- /dev/null +++ b/src/file/table/table-width.ts @@ -0,0 +1,42 @@ +// http://officeopenxml.com/WPtableWidth.php +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: type === WidthType.PERCENTAGE ? `${size}%` : size })); + } +} diff --git a/src/file/table/table.spec.ts b/src/file/table/table.spec.ts index f01703b0e7..04020833b4 100644 --- a/src/file/table/table.spec.ts +++ b/src/file/table/table.spec.ts @@ -5,49 +5,12 @@ 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": [ @@ -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], }); }); @@ -325,7 +288,6 @@ describe("Table", () => { }, 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, }), );