diff --git a/demo/69-different-width-columns.ts b/demo/69-different-width-columns.ts new file mode 100644 index 0000000000..883391c195 --- /dev/null +++ b/demo/69-different-width-columns.ts @@ -0,0 +1,31 @@ +// Sections with multiple columns +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Column, Document, Packer, Paragraph } from "../build"; + +const doc = new Document({ + sections: [ + { + properties: { + column: { + count: 2, + space: 720, + equalWidth: false, + children: [new Column({ width: 2880, space: 720 }), new Column({ width: 5760 })], + }, + }, + children: [ + new Paragraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + ), + new Paragraph( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + ), + ], + }, + ], +}); + +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/src/file/document/body/section-properties/properties/column.ts b/src/file/document/body/section-properties/properties/column.ts new file mode 100644 index 0000000000..d1f48a7aa5 --- /dev/null +++ b/src/file/document/body/section-properties/properties/column.ts @@ -0,0 +1,26 @@ +import { twipsMeasureValue } from "file/values"; +import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; + +export interface IColumnAttributes { + readonly width: number | string; + readonly space?: number | string; +} + +export class ColumnAttributes extends XmlAttributeComponent { + protected readonly xmlKeys = { + width: "w:w", + space: "w:space", + }; +} + +export class Column extends XmlComponent { + constructor({ width, space }: IColumnAttributes) { + super("w:col"); + this.root.push( + new ColumnAttributes({ + width: twipsMeasureValue(width), + space: space === undefined ? undefined : twipsMeasureValue(space), + }), + ); + } +} diff --git a/src/file/document/body/section-properties/properties/columns.spec.ts b/src/file/document/body/section-properties/properties/columns.spec.ts new file mode 100644 index 0000000000..596b30bdb1 --- /dev/null +++ b/src/file/document/body/section-properties/properties/columns.spec.ts @@ -0,0 +1,38 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; + +import { Column, Columns } from "."; + +describe("Columns", () => { + describe("#constructor()", () => { + it("should create columns of equal width if equalWidth is true", () => { + const columns = new Columns({ count: 3, space: 720 }); + const tree = new Formatter().format(columns); + + expect(tree["w:cols"]).to.deep.equal({ _attr: { "w:num": 3, "w:space": 720 } }); + }); + + it("should ignore individual column attributes if equalWidth is true", () => { + const unequalColumns = [new Column({ width: 1000, space: 400 }), new Column({ width: 2000 })]; + const columns = new Columns({ count: 3, space: 720, equalWidth: true, children: unequalColumns }); + const tree = new Formatter().format(columns); + + expect(tree).to.deep.equal({ "w:cols": { _attr: { "w:num": 3, "w:space": 720, "w:equalWidth": true } } }); + }); + + it("should have column children if equalWidth is false and individual columns are provided", () => { + const unequalColumns = [new Column({ width: 1000, space: 400 }), new Column({ width: 2000 })]; + const columns = new Columns({ count: 3, space: 720, equalWidth: false, children: unequalColumns }); + const tree = new Formatter().format(columns); + + expect(tree).to.deep.equal({ + "w:cols": [ + { _attr: { "w:num": 3, "w:space": 720, "w:equalWidth": false } }, + { "w:col": { _attr: { "w:space": 400, "w:w": 1000 } } }, + { "w:col": { _attr: { "w:w": 2000 } } }, + ], + }); + }); + }); +}); diff --git a/src/file/document/body/section-properties/properties/columns.ts b/src/file/document/body/section-properties/properties/columns.ts index 395df4ecae..e418b0ff1f 100644 --- a/src/file/document/body/section-properties/properties/columns.ts +++ b/src/file/document/body/section-properties/properties/columns.ts @@ -1,5 +1,6 @@ import { decimalNumber, twipsMeasureValue } from "file/values"; import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; +import { Column } from "./column"; // // @@ -15,6 +16,7 @@ export interface IColumnsAttributes { readonly count?: number; readonly separate?: boolean; readonly equalWidth?: boolean; + readonly children?: Column[]; } export class ColumnsAttributes extends XmlAttributeComponent { @@ -27,7 +29,7 @@ export class ColumnsAttributes extends XmlAttributeComponent } export class Columns extends XmlComponent { - constructor({ space, count, separate, equalWidth }: IColumnsAttributes) { + constructor({ space, count, separate, equalWidth, children }: IColumnsAttributes) { super("w:cols"); this.root.push( new ColumnsAttributes({ @@ -37,5 +39,9 @@ export class Columns extends XmlComponent { equalWidth, }), ); + + if (!equalWidth && children) { + children.forEach((column) => this.addChildElement(column)); + } } } diff --git a/src/file/document/body/section-properties/properties/index.ts b/src/file/document/body/section-properties/properties/index.ts index 089a005744..3349b2595f 100644 --- a/src/file/document/body/section-properties/properties/index.ts +++ b/src/file/document/body/section-properties/properties/index.ts @@ -1,3 +1,4 @@ +export * from "./column"; export * from "./columns"; export * from "./doc-grid"; // export * from "./header-reference"; diff --git a/src/import-dotx/import-dotx.ts b/src/import-dotx/import-dotx.ts index 61340bf79e..74a63b8ea4 100644 --- a/src/import-dotx/import-dotx.ts +++ b/src/import-dotx/import-dotx.ts @@ -215,7 +215,7 @@ export class ImportDotx { } const headers = headersXmlArray.map((item) => { if (item._attributes === undefined) { - throw Error("header referecne element has no attributes"); + throw Error("header reference element has no attributes"); } return { type: item._attributes["w:type"] as HeaderFooterReferenceType, @@ -235,7 +235,7 @@ export class ImportDotx { const footers = footersXmlArray.map((item) => { if (item._attributes === undefined) { - throw Error("footer referecne element has no attributes"); + throw Error("footer reference element has no attributes"); } return { type: item._attributes["w:type"] as HeaderFooterReferenceType,