update table-row-properties, table-cell-properties, table-cell-borders to declarative style

This commit is contained in:
Tom Hunkapiller
2021-05-22 04:03:40 +03:00
parent acc23be297
commit 2611e0c74f
8 changed files with 259 additions and 328 deletions

View File

@ -1,6 +1,12 @@
import { BorderStyle } from "file/styles"; import { BorderStyle } from "file/styles";
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components"; import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
interface ITableCellBorderPropertyOptions {
readonly style: BorderStyle;
readonly size: number;
readonly color: string;
}
class CellBorderAttributes extends XmlAttributeComponent<{ class CellBorderAttributes extends XmlAttributeComponent<{
readonly style: BorderStyle; readonly style: BorderStyle;
readonly size: number; readonly size: number;
@ -10,69 +16,43 @@ class CellBorderAttributes extends XmlAttributeComponent<{
} }
class BaseTableCellBorder extends XmlComponent { class BaseTableCellBorder extends XmlComponent {
public setProperties(style: BorderStyle, size: number, color: string): BaseTableCellBorder { constructor(key: string, options: ITableCellBorderPropertyOptions) {
const attrs = new CellBorderAttributes({ super(key);
style: style, this.root.push(new CellBorderAttributes(options));
size: size,
color: color,
});
this.root.push(attrs);
return this;
} }
} }
export interface ITableCellBorders {
readonly top?: ITableCellBorderPropertyOptions;
readonly start?: ITableCellBorderPropertyOptions;
readonly left?: ITableCellBorderPropertyOptions;
readonly bottom?: ITableCellBorderPropertyOptions;
readonly end?: ITableCellBorderPropertyOptions;
readonly right?: ITableCellBorderPropertyOptions;
}
export class TableCellBorders extends IgnoreIfEmptyXmlComponent { export class TableCellBorders extends IgnoreIfEmptyXmlComponent {
constructor() { constructor(options: ITableCellBorders) {
super("w:tcBorders"); super("w:tcBorders");
}
public addTopBorder(style: BorderStyle, size: number, color: string): TableCellBorders { if (options.top) {
const top = new BaseTableCellBorder("w:top"); this.root.push(new BaseTableCellBorder("w:top", options.top));
top.setProperties(style, size, color); }
this.root.push(top); if (options.start) {
this.root.push(new BaseTableCellBorder("w:start", options.start));
return this; }
} if (options.left) {
this.root.push(new BaseTableCellBorder("w:left", options.left));
public addStartBorder(style: BorderStyle, size: number, color: string): TableCellBorders { }
const start = new BaseTableCellBorder("w:start"); if (options.bottom) {
start.setProperties(style, size, color); this.root.push(new BaseTableCellBorder("w:bottom", options.bottom));
this.root.push(start); }
if (options.end) {
return this; this.root.push(new BaseTableCellBorder("w:end", options.end));
} }
if (options.right) {
public addBottomBorder(style: BorderStyle, size: number, color: string): TableCellBorders { this.root.push(new BaseTableCellBorder("w:right", options.right));
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;
} }
} }
@ -200,7 +180,7 @@ class TableCellWidthAttributes extends XmlAttributeComponent<{ readonly type: Wi
* Table cell width element. * Table cell width element.
*/ */
export class TableCellWidth extends XmlComponent { export class TableCellWidth extends XmlComponent {
constructor(value: string | number, type: WidthType) { constructor(value: string | number, type: WidthType = WidthType.AUTO) {
super("w:tcW"); super("w:tcW");
this.root.push( this.root.push(

View File

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

View File

@ -4,6 +4,7 @@ import { ITableShadingAttributesProperties, TableShading } from "../shading";
import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins"; import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins";
import { import {
GridSpan, GridSpan,
ITableCellBorders,
TableCellBorders, TableCellBorders,
TableCellWidth, TableCellWidth,
TDirection, TDirection,
@ -15,63 +16,58 @@ import {
WidthType, WidthType,
} from "./table-cell-components"; } from "./table-cell-components";
export interface ITableCellPropertiesOptions {
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?: ITableCellBorders;
}
export class TableCellProperties extends IgnoreIfEmptyXmlComponent { export class TableCellProperties extends IgnoreIfEmptyXmlComponent {
private readonly cellBorder: TableCellBorders; constructor(options: ITableCellPropertiesOptions) {
constructor() {
super("w:tcPr"); super("w:tcPr");
this.cellBorder = new TableCellBorders();
}
public get Borders(): TableCellBorders { if (options.width) {
return this.cellBorder; this.root.push(new TableCellWidth(options.width.size, options.width.type));
} }
public addGridSpan(cellSpan: number): TableCellProperties { if (options.columnSpan) {
this.root.push(new GridSpan(cellSpan)); 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 { if (options.borders) {
this.root.push(new VerticalMerge(type)); this.root.push(new TableCellBorders(options.borders));
}
return this; if (options.shading) {
} this.root.push(new TableShading(options.shading));
}
public setVerticalAlign(type: VerticalAlign): TableCellProperties { if (options.margins) {
this.root.push(new VAlign(type)); this.root.push(new TableCellMargin(options.margins));
}
return this; if (options.textDirection) {
} this.root.push(new TDirection(options.textDirection));
}
public setWidth(width: string | number, type: WidthType = WidthType.AUTO): TableCellProperties { if (options.verticalAlign) {
this.root.push(new TableCellWidth(width, type)); this.root.push(new VAlign(options.verticalAlign));
}
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;
} }
} }

View File

@ -10,15 +10,20 @@ import { TableCellBorders, TableCellWidth, TextDirection, VerticalAlign, Vertica
describe("TableCellBorders", () => { describe("TableCellBorders", () => {
describe("#prepForXml", () => { describe("#prepForXml", () => {
it("should not add empty borders element if there are no borders defined", () => { 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(); expect(() => new Formatter().format(tb)).to.throw();
}); });
}); });
describe("#addingBorders", () => { describe("#addingBorders", () => {
it("should add top border", () => { it("should add top border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addTopBorder(BorderStyle.DOTTED, 1, "FF00FF"); top: {
style: BorderStyle.DOTTED,
size: 1,
color: "FF00FF",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -37,8 +42,13 @@ describe("TableCellBorders", () => {
}); });
it("should add start(left) border", () => { it("should add start(left) border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addStartBorder(BorderStyle.SINGLE, 2, "FF00FF"); start: {
style: BorderStyle.SINGLE,
size: 2,
color: "FF00FF",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -57,8 +67,13 @@ describe("TableCellBorders", () => {
}); });
it("should add bottom border", () => { it("should add bottom border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addBottomBorder(BorderStyle.DOUBLE, 1, "FF00FF"); bottom: {
style: BorderStyle.DOUBLE,
size: 1,
color: "FF00FF",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -77,8 +92,13 @@ describe("TableCellBorders", () => {
}); });
it("should add end(right) border", () => { it("should add end(right) border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addEndBorder(BorderStyle.THICK, 3, "FF00FF"); end: {
style: BorderStyle.THICK,
size: 3,
color: "FF0000",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -86,7 +106,7 @@ describe("TableCellBorders", () => {
{ {
"w:end": { "w:end": {
_attr: { _attr: {
"w:color": "FF00FF", "w:color": "FF0000",
"w:sz": 3, "w:sz": 3,
"w:val": "thick", "w:val": "thick",
}, },
@ -97,8 +117,13 @@ describe("TableCellBorders", () => {
}); });
it("should add left border", () => { it("should add left border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addLeftBorder(BorderStyle.THICK, 3, "FF00FF"); left: {
style: BorderStyle.THICK,
size: 3,
color: "FF00FF",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -117,8 +142,13 @@ describe("TableCellBorders", () => {
}); });
it("should add right border", () => { it("should add right border", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addRightBorder(BorderStyle.THICK, 3, "FF00FF"); right: {
style: BorderStyle.THICK,
size: 3,
color: "FF00FF",
},
});
const tree = new Formatter().format(tb); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -137,13 +167,38 @@ describe("TableCellBorders", () => {
}); });
it("should add multiple borders", () => { it("should add multiple borders", () => {
const tb = new TableCellBorders(); const tb = new TableCellBorders({
tb.addTopBorder(BorderStyle.DOTTED, 1, "FF00FF"); top: {
tb.addEndBorder(BorderStyle.THICK, 3, "FF00FF"); style: BorderStyle.DOTTED,
tb.addBottomBorder(BorderStyle.DOUBLE, 1, "FF00FF"); size: 1,
tb.addStartBorder(BorderStyle.SINGLE, 2, "FF00FF"); color: "FF00FF",
tb.addLeftBorder(BorderStyle.SINGLE, 2, "FF00FF"); },
tb.addRightBorder(BorderStyle.SINGLE, 2, "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); const tree = new Formatter().format(tb);
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
@ -157,24 +212,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": { "w:start": {
_attr: { _attr: {
@ -193,6 +230,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": { "w:right": {
_attr: { _attr: {

View File

@ -1,48 +1,11 @@
// http://officeopenxml.com/WPtableGrid.php // http://officeopenxml.com/WPtableGrid.php
import { Paragraph } from "file/paragraph"; import { Paragraph } from "file/paragraph";
import { BorderStyle } from "file/styles";
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components"; import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
import { ITableShadingAttributesProperties } from "../shading";
import { Table } from "../table"; import { Table } from "../table";
import { ITableCellMarginOptions } from "./cell-margin/table-cell-margins"; import { ITableCellPropertiesOptions, TableCellProperties } from "./table-cell-properties";
import { TextDirection, VerticalAlign, VerticalMergeType, WidthType } from "./table-cell-components";
import { TableCellProperties } from "./table-cell-properties";
export interface ITableCellOptions { export interface ITableCellOptions extends ITableCellPropertiesOptions {
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;
};
};
readonly children: (Paragraph | Table)[]; readonly children: (Paragraph | Table)[];
} }
@ -50,59 +13,11 @@ export class TableCell extends XmlComponent {
constructor(readonly options: ITableCellOptions) { constructor(readonly options: ITableCellOptions) {
super("w:tc"); super("w:tc");
const properties = new TableCellProperties(); this.root.push(new TableCellProperties(options));
this.root.push(properties);
for (const child of options.children) { for (const child of options.children) {
this.root.push(child); 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 { public prepForXml(context: IContext): IXmlableObject | undefined {

View File

@ -6,49 +6,55 @@ import { TableRowProperties } from "./table-row-properties";
describe("TableRowProperties", () => { describe("TableRowProperties", () => {
describe("#constructor", () => { describe("#constructor", () => {
it("creates an initially empty property object", () => { it("creates an initially empty property object", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({});
// The TableRowProperties is ignorable if there are no attributes, // The TableRowProperties is ignorable if there are no attributes,
// which results in prepForXml returning undefined, which causes // which results in prepForXml returning undefined, which causes
// the formatter to throw an error if that is the only object it // the formatter to throw an error if that is the only object it
// has been asked to format. // has been asked to format.
expect(() => new Formatter().format(rowProperties)).to.throw("XMLComponent did not format correctly"); expect(() => new Formatter().format(rowProperties)).to.throw("XMLComponent did not format correctly");
}); });
});
describe("#setCantSplit", () => {
it("sets cantSplit to avoid row been paginated", () => { it("sets cantSplit to avoid row been paginated", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({ cantSplit: true });
rowProperties.setCantSplit();
const tree = new Formatter().format(rowProperties); const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:cantSplit": { _attr: { "w:val": true } } }] }); expect(tree).to.deep.equal({ "w:trPr": [{ "w:cantSplit": { _attr: { "w:val": true } } }] });
}); });
});
describe("#setTableHeader", () => {
it("sets row as table header (repeat row on each page of table)", () => { it("sets row as table header (repeat row on each page of table)", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({ tableHeader: true });
rowProperties.setTableHeader();
const tree = new Formatter().format(rowProperties); const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:tblHeader": { _attr: { "w:val": true } } }] }); expect(tree).to.deep.equal({ "w:trPr": [{ "w:tblHeader": { _attr: { "w:val": true } } }] });
}); });
});
describe("#setHeight", () => {
it("sets row height exact", () => { it("sets row height exact", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({
rowProperties.setHeight(100, HeightRule.EXACT); height: {
value: 100,
rule: HeightRule.EXACT,
},
});
const tree = new Formatter().format(rowProperties); const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "exact" } } }] }); expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "exact" } } }] });
}); });
it("sets row height auto", () => { it("sets row height auto", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({
rowProperties.setHeight(100, HeightRule.AUTO); height: {
value: 100,
rule: HeightRule.AUTO,
},
});
const tree = new Formatter().format(rowProperties); const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "auto" } } }] }); expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "auto" } } }] });
}); });
it("sets row height at least", () => { it("sets row height at least", () => {
const rowProperties = new TableRowProperties(); const rowProperties = new TableRowProperties({
rowProperties.setHeight(100, HeightRule.ATLEAST); height: {
value: 100,
rule: HeightRule.ATLEAST,
},
});
const tree = new Formatter().format(rowProperties); const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "atLeast" } } }] }); expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "atLeast" } } }] });
}); });

View File

@ -3,27 +3,30 @@ import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "
import { HeightRule, TableRowHeight } from "./table-row-height"; import { HeightRule, TableRowHeight } from "./table-row-height";
export interface ITableRowPropertiesOptions {
readonly cantSplit?: boolean;
readonly tableHeader?: boolean;
readonly height?: {
readonly value: number;
readonly rule: HeightRule;
};
}
export class TableRowProperties extends IgnoreIfEmptyXmlComponent { export class TableRowProperties extends IgnoreIfEmptyXmlComponent {
constructor() { constructor(options: ITableRowPropertiesOptions) {
super("w:trPr"); super("w:trPr");
}
public setCantSplit(): TableRowProperties { if (options.cantSplit) {
this.root.push(new CantSplit()); this.root.push(new CantSplit());
}
return this; if (options.tableHeader) {
} this.root.push(new TableHeader());
}
public setTableHeader(): TableRowProperties { if (options.height) {
this.root.push(new TableHeader()); this.root.push(new TableRowHeight(options.height.value, options.height.rule));
}
return this;
}
public setHeight(value: number, rule: HeightRule): TableRowProperties {
this.root.push(new TableRowHeight(value, rule));
return this;
} }
} }

View File

@ -1,41 +1,19 @@
import { HeightRule } from "file/table/table-row/table-row-height";
import { XmlComponent } from "file/xml-components"; import { XmlComponent } from "file/xml-components";
import { TableCell } from "../table-cell"; import { TableCell } from "../table-cell";
import { TableRowProperties } from "./table-row-properties"; import { ITableRowPropertiesOptions, TableRowProperties } from "./table-row-properties";
export interface ITableRowOptions { export interface ITableRowOptions extends ITableRowPropertiesOptions {
readonly cantSplit?: boolean;
readonly tableHeader?: boolean;
readonly height?: {
readonly value: number;
readonly rule: HeightRule;
};
readonly children: TableCell[]; readonly children: TableCell[];
} }
export class TableRow extends XmlComponent { export class TableRow extends XmlComponent {
private readonly properties: TableRowProperties;
constructor(private readonly options: ITableRowOptions) { constructor(private readonly options: ITableRowOptions) {
super("w:tr"); super("w:tr");
this.properties = new TableRowProperties(); this.root.push(new TableRowProperties(options));
this.root.push(this.properties);
for (const child of options.children) { for (const child of options.children) {
this.root.push(child); 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 { public get CellCount(): number {