Fix: separate vertical alignment enums for ITableCellOptions and ISectionPropertiesOptions (#3079)

* fix: separate vertical alignment enums for table and section properties

- Introduced `VerticalAlignTable` for table-cell vertical alignment with valid values: `top`, `center`, and `bottom`.
- Added `VerticalAlignSection` for section properties, extending `VerticalAlignTable` with an additional value `both`.
- Marked the original `VerticalAlign` as deprecated for backward compatibility, directing users to the new enums.
- Updated type definitions for better clarity on valid vertical alignments.

* refactor: update vertical alignment imports and types for section and table properties

- Renamed `VerticalAlign` to `VerticalAlignSection` in section properties and `VerticalAlignTable` in table-cell properties for clarity.
- Updated type definitions to reflect the new enum names, ensuring better organization and understanding of vertical alignment options.
- Adjusted related test cases to utilize the new imports and types.

* refactor: update demos to use new enums for table and section properties for vertical alignment
This commit is contained in:
Firat Ciftci
2025-05-02 13:58:10 -05:00
committed by GitHub
parent 1e6c9e1772
commit 7d1129900f
14 changed files with 81 additions and 52 deletions

View File

@ -1,7 +1,7 @@
// Example of how you would create a table and add data to it // Example of how you would create a table and add data to it
import * as fs from "fs"; import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph, Table, TableCell, TableRow, VerticalAlign, TextDirection } from "docx"; import { Document, HeadingLevel, Packer, Paragraph, Table, TableCell, TableRow, VerticalAlignTable, TextDirection } from "docx";
const doc = new Document({ const doc = new Document({
sections: [ sections: [
@ -13,11 +13,11 @@ const doc = new Document({
children: [ children: [
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})], children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})],
@ -45,7 +45,7 @@ const doc = new Document({
text: "This text should be in the middle of the cell", text: "This text should be in the middle of the cell",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -53,7 +53,7 @@ const doc = new Document({
text: "Text above should be vertical from bottom to top", text: "Text above should be vertical from bottom to top",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -61,7 +61,7 @@ const doc = new Document({
text: "Text above should be vertical from top to bottom", text: "Text above should be vertical from top to bottom",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
], ],
}), }),

View File

@ -1,13 +1,13 @@
// Example of making content of section vertically aligned // Example of making content of section vertically aligned
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, VerticalAlign, TextRun, Tab } from "docx"; import { Document, Packer, Paragraph, VerticalAlignSection, TextRun, Tab } from "docx";
const doc = new Document({ const doc = new Document({
sections: [ sections: [
{ {
properties: { properties: {
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignSection.CENTER,
}, },
children: [ children: [
new Paragraph({ new Paragraph({

View File

@ -12,7 +12,7 @@ import {
TableCell, TableCell,
TableRow, TableRow,
TextDirection, TextDirection,
VerticalAlign, VerticalAlignTable,
} from "docx"; } from "docx";
const table = new Table({ const table = new Table({
@ -102,11 +102,11 @@ const noBorderTable = new Table({
children: [ children: [
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})], children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})],
@ -134,7 +134,7 @@ const noBorderTable = new Table({
text: "This text should be in the middle of the cell", text: "This text should be in the middle of the cell",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -142,7 +142,7 @@ const noBorderTable = new Table({
text: "Text above should be vertical from bottom to top", text: "Text above should be vertical from bottom to top",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -150,7 +150,7 @@ const noBorderTable = new Table({
text: "Text above should be vertical from top to bottom", text: "Text above should be vertical from top to bottom",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
], ],
}), }),

View File

@ -1,7 +1,7 @@
// The demo on the README.md // The demo on the README.md
import * as fs from "fs"; import * as fs from "fs";
import { Document, HeadingLevel, ImageRun, Packer, Paragraph, Table, TableCell, TableRow, VerticalAlign } from "docx"; import { Document, HeadingLevel, ImageRun, Packer, Paragraph, Table, TableCell, TableRow, VerticalAlignTable } from "docx";
const table = new Table({ const table = new Table({
rows: [ rows: [
@ -13,6 +13,7 @@ const table = new Table({
children: [ children: [
new ImageRun({ new ImageRun({
data: fs.readFileSync("./demo/images/image1.jpeg"), data: fs.readFileSync("./demo/images/image1.jpeg"),
type: "jpg",
transformation: { transformation: {
width: 100, width: 100,
height: 100, height: 100,
@ -21,7 +22,7 @@ const table = new Table({
], ],
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -30,7 +31,7 @@ const table = new Table({
heading: HeadingLevel.HEADING_1, heading: HeadingLevel.HEADING_1,
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
], ],
}), }),
@ -50,6 +51,7 @@ const table = new Table({
children: [ children: [
new ImageRun({ new ImageRun({
data: fs.readFileSync("./demo/images/image1.jpeg"), data: fs.readFileSync("./demo/images/image1.jpeg"),
type: "jpg",
transformation: { transformation: {
width: 100, width: 100,
height: 100, height: 100,
@ -77,6 +79,7 @@ const doc = new Document({
children: [ children: [
new ImageRun({ new ImageRun({
data: fs.readFileSync("./demo/images/pizza.gif"), data: fs.readFileSync("./demo/images/pizza.gif"),
type: "gif",
transformation: { transformation: {
width: 100, width: 100,
height: 100, height: 100,

View File

@ -9,7 +9,7 @@ import {
Table, Table,
TableCell, TableCell,
TableRow, TableRow,
VerticalAlign, VerticalAlignTable,
TextDirection, TextDirection,
TextRun, TextRun,
WidthType, WidthType,
@ -101,17 +101,17 @@ const generateRows = (prices: StockPrice[]): TableRow[] =>
children: [ children: [
new TableCell({ new TableCell({
children: [new Paragraph(date.toString())], children: [new Paragraph(date.toString())],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM, textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph(ticker)], children: [new Paragraph(ticker)],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM, textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph(price.toString())], children: [new Paragraph(price.toString())],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT, textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT,
}), }),
], ],
@ -143,7 +143,7 @@ const doc = new Document({
], ],
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM, textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}), }),
new TableCell({ new TableCell({
@ -159,7 +159,7 @@ const doc = new Document({
], ],
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM, textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM,
}), }),
new TableCell({ new TableCell({
@ -175,7 +175,7 @@ const doc = new Document({
], ],
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT, textDirection: TextDirection.TOP_TO_BOTTOM_RIGHT_TO_LEFT,
}), }),
], ],

View File

@ -13,7 +13,7 @@ import {
TableRow, TableRow,
TextDirection, TextDirection,
TextRun, TextRun,
VerticalAlign, VerticalAlignTable,
} from "docx"; } from "docx";
patchDocument({ patchDocument({
@ -105,11 +105,11 @@ patchDocument({
children: [ children: [
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})], children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})],
@ -137,7 +137,7 @@ patchDocument({
text: "This text should be in the middle of the cell", text: "This text should be in the middle of the cell",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -145,7 +145,7 @@ patchDocument({
text: "Text above should be vertical from bottom to top", text: "Text above should be vertical from bottom to top",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -153,7 +153,7 @@ patchDocument({
text: "Text above should be vertical from top to bottom", text: "Text above should be vertical from top to bottom",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
], ],
}), }),

View File

@ -13,7 +13,7 @@ import {
TableRow, TableRow,
TextDirection, TextDirection,
TextRun, TextRun,
VerticalAlign, VerticalAlignTable,
} from "docx"; } from "docx";
patchDocument({ patchDocument({
@ -105,11 +105,11 @@ patchDocument({
children: [ children: [
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({}), new Paragraph({})], children: [new Paragraph({}), new Paragraph({})],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})], children: [new Paragraph({ text: "bottom to top" }), new Paragraph({})],
@ -137,7 +137,7 @@ patchDocument({
text: "This text should be in the middle of the cell", text: "This text should be in the middle of the cell",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -145,7 +145,7 @@ patchDocument({
text: "Text above should be vertical from bottom to top", text: "Text above should be vertical from bottom to top",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
new TableCell({ new TableCell({
children: [ children: [
@ -153,7 +153,7 @@ patchDocument({
text: "Text above should be vertical from top to bottom", text: "Text above should be vertical from top to bottom",
}), }),
], ],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}), }),
], ],
}), }),

View File

@ -159,7 +159,7 @@ const tableRow = new TableRow({
| children | `Array<Paragraph or Table>` | Required. You can nest tables by adding a table into a cell | | children | `Array<Paragraph or Table>` | Required. You can nest tables by adding a table into a cell |
| shading | `IShadingAttributesProperties` | Optional | | shading | `IShadingAttributesProperties` | Optional |
| margins | `ITableCellMarginOptions` | Optional | | margins | `ITableCellMarginOptions` | Optional |
| verticalAlign | `VerticalAlign` | Optional | | verticalAlign | `VerticalAlignTable` | Optional |
| columnSpan | `number` | Optional | | columnSpan | `number` | Optional |
| rowSpan | `number` | Optional | | rowSpan | `number` | Optional |
| borders | `BorderOptions` | Optional | | borders | `BorderOptions` | Optional |
@ -266,7 +266,7 @@ Sets the vertical alignment of the contents of the cell
```ts ```ts
const cell = new TableCell({ const cell = new TableCell({
..., ...,
verticalAlign: VerticalAlign, verticalAlign: VerticalAlignTable,
}); });
``` ```
@ -282,7 +282,7 @@ For example, to center align a cell:
```ts ```ts
const cell = new TableCell({ const cell = new TableCell({
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}); });
``` ```

View File

@ -6,7 +6,7 @@ import { FooterWrapper } from "@file/footer-wrapper";
import { HeaderWrapper } from "@file/header-wrapper"; import { HeaderWrapper } from "@file/header-wrapper";
import { Media } from "@file/media"; import { Media } from "@file/media";
import { NumberFormat } from "@file/shared/number-format"; import { NumberFormat } from "@file/shared/number-format";
import { VerticalAlign } from "@file/vertical-align"; import { VerticalAlignSection } from "@file/vertical-align";
import { convertInchesToTwip } from "@util/convenience-functions"; import { convertInchesToTwip } from "@util/convenience-functions";
import { PageOrientation } from "./properties"; import { PageOrientation } from "./properties";
@ -75,7 +75,7 @@ describe("SectionProperties", () => {
even: new FooterWrapper(media, 200), even: new FooterWrapper(media, 200),
}, },
titlePage: true, titlePage: true,
verticalAlign: VerticalAlign.TOP, verticalAlign: VerticalAlignSection.TOP,
}); });
const tree = new Formatter().format(properties); const tree = new Formatter().format(properties);

View File

@ -2,7 +2,7 @@
import { FooterWrapper } from "@file/footer-wrapper"; import { FooterWrapper } from "@file/footer-wrapper";
import { HeaderWrapper } from "@file/header-wrapper"; import { HeaderWrapper } from "@file/header-wrapper";
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align"; import { SectionVerticalAlign, VerticalAlignElement } from "@file/vertical-align";
import { OnOffElement, XmlComponent } from "@file/xml-components"; import { OnOffElement, XmlComponent } from "@file/xml-components";
import { Columns, IColumnsAttributes } from "./properties/columns"; import { Columns, IColumnsAttributes } from "./properties/columns";
@ -35,7 +35,7 @@ export type ISectionPropertiesOptions = {
readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>; readonly footerWrapperGroup?: IHeaderFooterGroup<FooterWrapper>;
readonly lineNumbers?: ILineNumberAttributes; readonly lineNumbers?: ILineNumberAttributes;
readonly titlePage?: boolean; readonly titlePage?: boolean;
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign]; readonly verticalAlign?: SectionVerticalAlign;
readonly column?: IColumnsAttributes; readonly column?: IColumnsAttributes;
readonly type?: (typeof SectionType)[keyof typeof SectionType]; readonly type?: (typeof SectionType)[keyof typeof SectionType];
}; };

View File

@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import { Formatter } from "@export/formatter"; import { Formatter } from "@export/formatter";
import { BorderStyle } from "@file/border"; import { BorderStyle } from "@file/border";
import { VerticalAlign } from "@file/vertical-align"; import { VerticalAlignTable } from "@file/vertical-align";
import { WidthType } from "../table-width"; import { WidthType } from "../table-width";
import { VerticalMergeType } from "./table-cell-components"; import { VerticalMergeType } from "./table-cell-components";
@ -32,7 +32,7 @@ describe("TableCellProperties", () => {
}); });
it("sets vertical align", () => { it("sets vertical align", () => {
const properties = new TableCellProperties({ verticalAlign: VerticalAlign.BOTTOM }); const properties = new TableCellProperties({ verticalAlign: VerticalAlignTable.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" } } }] });
}); });

View File

@ -1,4 +1,4 @@
import { VerticalAlign, VerticalAlignElement } from "@file/vertical-align"; import { TableVerticalAlign, VerticalAlignElement } from "@file/vertical-align";
import { IgnoreIfEmptyXmlComponent } from "@file/xml-components"; import { IgnoreIfEmptyXmlComponent } from "@file/xml-components";
import { IShadingAttributesProperties, Shading } from "../../shading"; import { IShadingAttributesProperties, Shading } from "../../shading";
@ -17,7 +17,7 @@ import {
export type ITableCellPropertiesOptions = { export type ITableCellPropertiesOptions = {
readonly shading?: IShadingAttributesProperties; readonly shading?: IShadingAttributesProperties;
readonly margins?: ITableCellMarginOptions; readonly margins?: ITableCellMarginOptions;
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign]; readonly verticalAlign?: TableVerticalAlign;
readonly textDirection?: (typeof TextDirection)[keyof typeof TextDirection]; readonly textDirection?: (typeof TextDirection)[keyof typeof TextDirection];
readonly verticalMerge?: (typeof VerticalMergeType)[keyof typeof VerticalMergeType]; readonly verticalMerge?: (typeof VerticalMergeType)[keyof typeof VerticalMergeType];
readonly width?: ITableWidthProperties; readonly width?: ITableWidthProperties;

View File

@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest";
import { Formatter } from "@export/formatter"; import { Formatter } from "@export/formatter";
import { BorderStyle } from "@file/border"; import { BorderStyle } from "@file/border";
import { ShadingType } from "@file/shading"; import { ShadingType } from "@file/shading";
import { VerticalAlign } from "@file/vertical-align"; import { VerticalAlignTable } from "@file/vertical-align";
import { WidthType } from "../table-width"; import { WidthType } from "../table-width";
import { TableCell } from "./table-cell"; import { TableCell } from "./table-cell";
@ -286,7 +286,7 @@ describe("TableCell", () => {
it("should create with vertical align", () => { it("should create with vertical align", () => {
const cell = new TableCell({ const cell = new TableCell({
children: [], children: [],
verticalAlign: VerticalAlign.CENTER, verticalAlign: VerticalAlignTable.CENTER,
}); });
const tree = new Formatter().format(cell); const tree = new Formatter().format(cell);

View File

@ -6,17 +6,43 @@ import { XmlAttributeComponent, XmlComponent } from "@file/xml-components";
// <xsd:simpleType name="ST_VerticalJc"> // <xsd:simpleType name="ST_VerticalJc">
// <xsd:restriction base="xsd:string"> // <xsd:restriction base="xsd:string">
// <xsd:enumeration value="both"/>
// <xsd:enumeration value="top"/> // <xsd:enumeration value="top"/>
// <xsd:enumeration value="center"/> // <xsd:enumeration value="center"/>
// <xsd:enumeration value="bottom"/> // <xsd:enumeration value="bottom"/>
// </xsd:restriction> // </xsd:restriction>
// </xsd:simpleType> // </xsd:simpleType>
export const VerticalAlign = {
BOTTOM: "bottom", /**
CENTER: "center", * Enumeration for table-cell vertical alignment. Only `top`, `center`, `bottom`
* are valid according to ECMA-376 (§17.18.87 ST_VerticalJc within <w:tcPr>).
*/
export const VerticalAlignTable = {
TOP: "top", TOP: "top",
CENTER: "center",
BOTTOM: "bottom",
} as const; } as const;
/**
* Enumeration for section (<w:sectPr>) vertical alignment. Adds `both` on top of
* the table-cell set (§17.18.87 ST_VerticalJc within <w:sectPr>).
*/
export const VerticalAlignSection = {
...VerticalAlignTable,
BOTH: "both",
} as const;
/**
* @deprecated Use {@link VerticalAlignTable} for table cells or
* {@link VerticalAlignSection} for section properties. This alias remains for
* backward-compatibility and will be removed in the next major release.
*/
export const VerticalAlign = VerticalAlignSection;
export type TableVerticalAlign = (typeof VerticalAlignTable)[keyof typeof VerticalAlignTable];
export type SectionVerticalAlign = (typeof VerticalAlignSection)[keyof typeof VerticalAlignSection];
export class VerticalAlignAttributes extends XmlAttributeComponent<{ export class VerticalAlignAttributes extends XmlAttributeComponent<{
readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign]; readonly verticalAlign?: (typeof VerticalAlign)[keyof typeof VerticalAlign];
}> { }> {