From 44d4b93d064ab03561f2980a82373c9a4f953160 Mon Sep 17 00:00:00 2001
From: Philip <32778021+CodingTimeDEV@users.noreply.github.com>
Date: Wed, 16 Apr 2025 23:38:28 +0200
Subject: [PATCH] feat: Added TableCellSpacing (#3052)
* feat: Added TableCellSpacingElement
* feat: Added cellSpacing (Table-constructor, TableProperties-constructor and ITableOptions)
* feat: Added cellSpacing (ITablePropertiesOptions and constructor implementation)
* feat: Added cellSpacing (ITableRowPropertiesOptions and constructor implementation)
* feat: Added cellSpacing (Implementation Test)
---------
Co-authored-by: Philip <1760073-philip.asx@users.noreply.gitlab.com>
---
src/file/table/table-cell-spacing.ts | 39 +++++++++++++++++++
.../table-properties/table-properties.spec.ts | 14 +++++++
.../table-properties/table-properties.ts | 6 +++
.../table-row/table-row-properties.spec.ts | 14 +++++++
.../table/table-row/table-row-properties.ts | 6 +++
src/file/table/table.ts | 4 ++
6 files changed, 83 insertions(+)
create mode 100644 src/file/table/table-cell-spacing.ts
diff --git a/src/file/table/table-cell-spacing.ts b/src/file/table/table-cell-spacing.ts
new file mode 100644
index 0000000000..73fd9fee96
--- /dev/null
+++ b/src/file/table/table-cell-spacing.ts
@@ -0,0 +1,39 @@
+// http://officeopenxml.com/WPtableCellSpacing.php
+import { NextAttributeComponent, XmlComponent } from "@file/xml-components";
+import { Percentage, UniversalMeasure, measurementOrPercentValue } from "@util/values";
+
+//
+//
+//
+//
+//
+//
+
+export const CellSpacingType = {
+ /** Value is in twentieths of a point */
+ DXA: "dxa",
+ /** No (empty) value. */
+ NIL: "nil",
+} as const;
+
+//
+//
+//
+//
+export type ITableCellSpacingProperties = {
+ readonly value: number | Percentage | UniversalMeasure;
+ readonly type?: (typeof CellSpacingType)[keyof typeof CellSpacingType];
+};
+
+export class TableCellSpacingElement extends XmlComponent {
+ public constructor({ type = CellSpacingType.DXA, value }: ITableCellSpacingProperties) {
+ super("w:tblCellSpacing");
+
+ this.root.push(
+ new NextAttributeComponent({
+ type: { key: "w:type", value: type },
+ value: { key: "w:w", value: measurementOrPercentValue(value) },
+ }),
+ );
+ }
+}
diff --git a/src/file/table/table-properties/table-properties.spec.ts b/src/file/table/table-properties/table-properties.spec.ts
index cebe7153b6..02da55821e 100644
--- a/src/file/table/table-properties/table-properties.spec.ts
+++ b/src/file/table/table-properties/table-properties.spec.ts
@@ -7,6 +7,7 @@ import { ShadingType } from "@file/shading";
import { WidthType } from "../table-width";
import { TableLayoutType } from "./table-layout";
import { TableProperties } from "./table-properties";
+import { CellSpacingType } from "../table-cell-spacing";
describe("TableProperties", () => {
describe("#constructor", () => {
@@ -91,6 +92,19 @@ describe("TableProperties", () => {
"w:tblPr": [{ "w:tblLayout": { _attr: { "w:type": "fixed" } } }],
});
});
+
+ it("should add a table cell spacing property", () => {
+ const tp = new TableProperties({
+ cellSpacing: {
+ value: 1234,
+ type: CellSpacingType.DXA,
+ },
+ });
+ const tree = new Formatter().format(tp);
+ expect(tree).to.deep.equal({
+ "w:tblPr": [{ "w:tblCellSpacing": { _attr: { "w:type": "dxa", "w:w": 1234 } } }],
+ });
+ });
});
describe("#cellMargin", () => {
diff --git a/src/file/table/table-properties/table-properties.ts b/src/file/table/table-properties/table-properties.ts
index 08cfe80b68..b0946a1d60 100644
--- a/src/file/table/table-properties/table-properties.ts
+++ b/src/file/table/table-properties/table-properties.ts
@@ -30,6 +30,7 @@ import { ITableBordersOptions, TableBorders } from "./table-borders";
import { ITableCellMarginOptions, TableCellMargin, TableCellMarginElementType } from "./table-cell-margin";
import { ITableFloatOptions, TableFloatProperties } from "./table-float-properties";
import { TableLayout, TableLayoutType } from "./table-layout";
+import { ITableCellSpacingProperties, TableCellSpacingElement } from "../table-cell-spacing";
export type ITablePropertiesOptions = {
readonly width?: ITableWidthProperties;
@@ -42,6 +43,7 @@ export type ITablePropertiesOptions = {
readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
readonly cellMargin?: ITableCellMarginOptions;
readonly visuallyRightToLeft?: boolean;
+ readonly cellSpacing?: ITableCellSpacingProperties;
};
export class TableProperties extends IgnoreIfEmptyXmlComponent {
@@ -87,5 +89,9 @@ export class TableProperties extends IgnoreIfEmptyXmlComponent {
if (options.cellMargin) {
this.root.push(new TableCellMargin(TableCellMarginElementType.TABLE, options.cellMargin));
}
+
+ if (options.cellSpacing) {
+ this.root.push(new TableCellSpacingElement(options.cellSpacing));
+ }
}
}
diff --git a/src/file/table/table-row/table-row-properties.spec.ts b/src/file/table/table-row/table-row-properties.spec.ts
index f96d39dca8..dd7cb419d2 100644
--- a/src/file/table/table-row/table-row-properties.spec.ts
+++ b/src/file/table/table-row/table-row-properties.spec.ts
@@ -4,6 +4,7 @@ import { Formatter } from "@export/formatter";
import { HeightRule } from "@file/table/table-row/table-row-height";
import { TableRowProperties } from "./table-row-properties";
+import { CellSpacingType } from "../table-cell-spacing";
describe("TableRowProperties", () => {
describe("#constructor", () => {
@@ -60,5 +61,18 @@ describe("TableRowProperties", () => {
const tree = new Formatter().format(rowProperties);
expect(tree).to.deep.equal({ "w:trPr": [{ "w:trHeight": { _attr: { "w:val": 100, "w:hRule": "atLeast" } } }] });
});
+
+ it("should add a table cell spacing property", () => {
+ const rowProperties = new TableRowProperties({
+ cellSpacing: {
+ value: 1234,
+ type: CellSpacingType.DXA,
+ },
+ });
+ const tree = new Formatter().format(rowProperties);
+ expect(tree).to.deep.equal({
+ "w:trPr": [{ "w:tblCellSpacing": { _attr: { "w:type": "dxa", "w:w": 1234 } } }],
+ });
+ });
});
});
diff --git a/src/file/table/table-row/table-row-properties.ts b/src/file/table/table-row/table-row-properties.ts
index 40605869cd..28d1b509fd 100644
--- a/src/file/table/table-row/table-row-properties.ts
+++ b/src/file/table/table-row/table-row-properties.ts
@@ -31,6 +31,7 @@ import { IgnoreIfEmptyXmlComponent, OnOffElement } from "@file/xml-components";
import { PositiveUniversalMeasure } from "@util/values";
import { HeightRule, TableRowHeight } from "./table-row-height";
+import { ITableCellSpacingProperties, TableCellSpacingElement } from "../table-cell-spacing";
export type ITableRowPropertiesOptions = {
readonly cantSplit?: boolean;
@@ -39,6 +40,7 @@ export type ITableRowPropertiesOptions = {
readonly value: number | PositiveUniversalMeasure;
readonly rule: (typeof HeightRule)[keyof typeof HeightRule];
};
+ readonly cellSpacing?: ITableCellSpacingProperties;
};
export class TableRowProperties extends IgnoreIfEmptyXmlComponent {
@@ -56,5 +58,9 @@ export class TableRowProperties extends IgnoreIfEmptyXmlComponent {
if (options.height) {
this.root.push(new TableRowHeight(options.height.value, options.height.rule));
}
+
+ if (options.cellSpacing) {
+ this.root.push(new TableCellSpacingElement(options.cellSpacing));
+ }
}
}
diff --git a/src/file/table/table.ts b/src/file/table/table.ts
index 0cf2e6e6ee..37d4bcfbca 100644
--- a/src/file/table/table.ts
+++ b/src/file/table/table.ts
@@ -4,6 +4,7 @@ import { FileChild } from "@file/file-child";
import { AlignmentType } from "../paragraph";
import { TableGrid } from "./grid";
import { TableCell, VerticalMergeType } from "./table-cell";
+import { ITableCellSpacingProperties } from "./table-cell-spacing";
import { ITableBordersOptions, ITableFloatOptions, TableProperties } from "./table-properties";
import { ITableCellMarginOptions } from "./table-properties/table-cell-margin";
import { TableLayoutType } from "./table-properties/table-layout";
@@ -32,6 +33,7 @@ export type ITableOptions = {
readonly borders?: ITableBordersOptions;
readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
readonly visuallyRightToLeft?: boolean;
+ readonly cellSpacing?: ITableCellSpacingProperties;
};
export class Table extends FileChild {
@@ -48,6 +50,7 @@ export class Table extends FileChild {
borders,
alignment,
visuallyRightToLeft,
+ cellSpacing,
}: ITableOptions) {
super("w:tbl");
@@ -62,6 +65,7 @@ export class Table extends FileChild {
alignment,
cellMargin: margins,
visuallyRightToLeft,
+ cellSpacing,
}),
);