Merge pull request #1168 from askoufis/unequal-columns

Extend `Columns` API to allow specifying individual column widths/spacing
This commit is contained in:
Dolan
2021-09-20 10:00:20 +01:00
committed by GitHub
6 changed files with 105 additions and 3 deletions

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
import { decimalNumber, twipsMeasureValue } from "file/values";
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { Column } from "./column";
// <xsd:complexType name="CT_Columns">
// <xsd:sequence minOccurs="0">
@ -15,6 +16,7 @@ export interface IColumnsAttributes {
readonly count?: number;
readonly separate?: boolean;
readonly equalWidth?: boolean;
readonly children?: Column[];
}
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
@ -27,7 +29,7 @@ export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes>
}
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));
}
}
}

View File

@ -1,3 +1,4 @@
export * from "./column";
export * from "./columns";
export * from "./doc-grid";
// export * from "./header-reference";

View File

@ -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,