Consolidate TableWidth and TableCellMargins types; add Table indent (#954)
This commit is contained in:
@ -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",
|
||||
|
@ -2,3 +2,4 @@ export * from "./table";
|
||||
export * from "./table-cell";
|
||||
export * from "./table-properties";
|
||||
export * from "./table-row";
|
||||
export * from "./table-width";
|
||||
|
@ -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,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -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",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -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));
|
||||
}
|
||||
}
|
@ -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,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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 } } },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 }));
|
||||
}
|
||||
}
|
42
src/file/table/table-width.ts
Normal file
42
src/file/table/table-width.ts
Normal file
@ -0,0 +1,42 @@
|
||||
// http://officeopenxml.com/WPtableWidth.php
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
// <xsd:simpleType name="ST_TblWidth">
|
||||
// <xsd:restriction base="xsd:string">
|
||||
// <xsd:enumeration value="nil"/>
|
||||
// <xsd:enumeration value="pct"/>
|
||||
// <xsd:enumeration value="dxa"/>
|
||||
// <xsd:enumeration value="auto"/>
|
||||
// </xsd:restriction>
|
||||
// </xsd:simpleType>
|
||||
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",
|
||||
}
|
||||
|
||||
// <xsd:complexType name="CT_TblWidth">
|
||||
// <xsd:attribute name="w" type="ST_MeasurementOrPercent"/>
|
||||
// <xsd:attribute name="type" type="ST_TblWidth"/>
|
||||
// </xsd:complexType>
|
||||
export interface ITableWidthProperties {
|
||||
readonly size: string | number;
|
||||
readonly type?: WidthType;
|
||||
}
|
||||
|
||||
class TableWidthAttributes extends XmlAttributeComponent<ITableWidthProperties> {
|
||||
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 }));
|
||||
}
|
||||
}
|
@ -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,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
@ -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<number>(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,
|
||||
}),
|
||||
);
|
||||
|
Reference in New Issue
Block a user