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