update table-row-properties, table-cell-properties, table-cell-borders to declarative style
This commit is contained in:
@ -1,6 +1,12 @@
|
||||
import { BorderStyle } from "file/styles";
|
||||
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
interface ITableCellBorderPropertyOptions {
|
||||
readonly style: BorderStyle;
|
||||
readonly size: number;
|
||||
readonly color: string;
|
||||
}
|
||||
|
||||
class CellBorderAttributes extends XmlAttributeComponent<{
|
||||
readonly style: BorderStyle;
|
||||
readonly size: number;
|
||||
@ -10,69 +16,43 @@ class CellBorderAttributes extends XmlAttributeComponent<{
|
||||
}
|
||||
|
||||
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;
|
||||
constructor(key: string, options: ITableCellBorderPropertyOptions) {
|
||||
super(key);
|
||||
this.root.push(new CellBorderAttributes(options));
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 BaseTableCellBorder("w:top", options.top));
|
||||
}
|
||||
if (options.start) {
|
||||
this.root.push(new BaseTableCellBorder("w:start", options.start));
|
||||
}
|
||||
if (options.left) {
|
||||
this.root.push(new BaseTableCellBorder("w:left", options.left));
|
||||
}
|
||||
if (options.bottom) {
|
||||
this.root.push(new BaseTableCellBorder("w:bottom", options.bottom));
|
||||
}
|
||||
if (options.end) {
|
||||
this.root.push(new BaseTableCellBorder("w:end", options.end));
|
||||
}
|
||||
if (options.right) {
|
||||
this.root.push(new BaseTableCellBorder("w:right", options.right));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,7 +180,7 @@ class TableCellWidthAttributes extends XmlAttributeComponent<{ readonly type: Wi
|
||||
* Table cell width element.
|
||||
*/
|
||||
export class TableCellWidth extends XmlComponent {
|
||||
constructor(value: string | number, type: WidthType) {
|
||||
constructor(value: string | number, type: WidthType = WidthType.AUTO) {
|
||||
super("w:tcW");
|
||||
|
||||
this.root.push(
|
||||
|
@ -9,74 +9,68 @@ 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: "test",
|
||||
color: "000",
|
||||
},
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(tree).to.deep.equal({ "w:tcPr": [{ "w:shd": { _attr: { "w:fill": "test", "w:color": "000" } } }] });
|
||||
});
|
||||
});
|
||||
|
||||
describe("#addMargins", () => {
|
||||
it("sets shading", () => {
|
||||
const properties = new TableCellProperties();
|
||||
properties.addMargins({});
|
||||
const properties = new TableCellProperties({
|
||||
margins: {},
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:tcPr": [
|
||||
@ -119,17 +113,21 @@ describe("TableCellProperties", () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
it("should set the TableCellBorders", () => {
|
||||
const properties = new TableCellProperties({
|
||||
borders: {
|
||||
top: {
|
||||
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" } } }],
|
||||
});
|
||||
});
|
||||
|
@ -4,6 +4,7 @@ import { ITableShadingAttributesProperties, TableShading } from "../shading";
|
||||
import { ITableCellMarginOptions, TableCellMargin } from "./cell-margin/table-cell-margins";
|
||||
import {
|
||||
GridSpan,
|
||||
ITableCellBorders,
|
||||
TableCellBorders,
|
||||
TableCellWidth,
|
||||
TDirection,
|
||||
@ -15,63 +16,58 @@ import {
|
||||
WidthType,
|
||||
} 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 {
|
||||
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 TableCellWidth(options.width.size, options.width.type));
|
||||
}
|
||||
|
||||
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 TableShading(options.shading));
|
||||
}
|
||||
|
||||
public setVerticalAlign(type: VerticalAlign): TableCellProperties {
|
||||
this.root.push(new VAlign(type));
|
||||
if (options.margins) {
|
||||
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 {
|
||||
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 VAlign(options.verticalAlign));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,20 @@ import { TableCellBorders, TableCellWidth, TextDirection, VerticalAlign, Vertica
|
||||
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 +42,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 +67,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 +92,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 +106,7 @@ describe("TableCellBorders", () => {
|
||||
{
|
||||
"w:end": {
|
||||
_attr: {
|
||||
"w:color": "FF00FF",
|
||||
"w:color": "FF0000",
|
||||
"w:sz": 3,
|
||||
"w:val": "thick",
|
||||
},
|
||||
@ -97,8 +117,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 +142,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 +167,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 +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": {
|
||||
_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": {
|
||||
_attr: {
|
||||
|
@ -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 {
|
||||
|
@ -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 } } }] });
|
||||
});
|
||||
});
|
||||
|
||||
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 } } }] });
|
||||
});
|
||||
});
|
||||
|
||||
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" } } }] });
|
||||
});
|
||||
|
@ -3,27 +3,30 @@ import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "
|
||||
|
||||
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 {
|
||||
constructor() {
|
||||
constructor(options: ITableRowPropertiesOptions) {
|
||||
super("w:trPr");
|
||||
}
|
||||
|
||||
public setCantSplit(): TableRowProperties {
|
||||
this.root.push(new CantSplit());
|
||||
if (options.cantSplit) {
|
||||
this.root.push(new CantSplit());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
if (options.tableHeader) {
|
||||
this.root.push(new 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;
|
||||
if (options.height) {
|
||||
this.root.push(new TableRowHeight(options.height.value, options.height.rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user