Consolidate TableWidth and TableCellMargins types; add Table indent (#954)

This commit is contained in:
Tom Hunkapiller
2021-05-23 21:17:20 +03:00
parent 528be93191
commit dd6d1bc039
18 changed files with 215 additions and 552 deletions

View File

@ -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);

View File

@ -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
//
// <xsd:complexType name="CT_TcMar">
// <xsd:sequence>
// <xsd:element name="top" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="start" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="left" type="CT_TblWidth" minOccurs="0"/>
// <xsd:element name="bottom" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="end" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="right" type="CT_TblWidth" minOccurs="0"/>
// </xsd:sequence>
// </xsd:complexType>
// <xsd:complexType name="CT_TblCellMar">
// <xsd:sequence>
// <xsd:element name="top" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="start" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="left" type="CT_TblWidth" minOccurs="0"/>
// <xsd:element name="bottom" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="end" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="right" type="CT_TblWidth" minOccurs="0"/>
// </xsd:sequence>
// </xsd:complexType>
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 }));
}
}
}

View File

@ -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,
},
});

View File

@ -1,22 +1,41 @@
// http://officeopenxml.com/WPtableProperties.php
//
// <xsd:complexType name="CT_TblPrBase">
// <xsd:sequence>
// <xsd:element name="tblStyle" type="CT_String" minOccurs="0"/>
// <xsd:element name="tblpPr" type="CT_TblPPr" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblOverlap" type="CT_TblOverlap" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="bidiVisual" type="CT_OnOff" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblStyleRowBandSize" type="CT_DecimalNumber" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblStyleColBandSize" type="CT_DecimalNumber" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblW" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="jc" type="CT_JcTable" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblCellSpacing" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblInd" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblBorders" type="CT_TblBorders" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="shd" type="CT_Shd" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblLayout" type="CT_TblLayoutType" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblCellMar" type="CT_TblCellMar" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblLook" type="CT_TblLook" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblCaption" type="CT_String" minOccurs="0" maxOccurs="1"/>
// <xsd:element name="tblDescription" type="CT_String" minOccurs="0" maxOccurs="1"/>
// </xsd:sequence>
// </xsd:complexType>
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));
}
}
}

View File

@ -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 }));
}
}