diff --git a/demo/58-section-types.ts b/demo/58-section-types.ts new file mode 100644 index 0000000000..6c16b44600 --- /dev/null +++ b/demo/58-section-types.ts @@ -0,0 +1,93 @@ +// Usage of different Section Types +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun, SectionType } from "../build"; + +const doc = new Document(); + +doc.addSection({ + properties: {}, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + ], + }), + ], +}); + +doc.addSection({ + properties: { + type: SectionType.CONTINUOUS, + }, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + ], + }), + ], +}); + +doc.addSection({ + properties: { + type: SectionType.ODD_PAGE, + }, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + ], + }), + ], +}); + +doc.addSection({ + properties: { + type: SectionType.EVEN_PAGE, + }, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + ], + }), + ], +}); + +doc.addSection({ + properties: { + type: SectionType.NEXT_PAGE, + }, + children: [ + new Paragraph({ + children: [ + new TextRun("Hello World"), + new TextRun({ + text: "Foo Bar", + bold: true, + }), + ], + }), + ], +}); + +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/docs/usage/sections.md b/docs/usage/sections.md index 5b6d4e9c74..daabb02294 100644 --- a/docs/usage/sections.md +++ b/docs/usage/sections.md @@ -19,3 +19,30 @@ doc.addSection({ ], }); ``` + +## Properties + +You can specify additional properties to the section, by providing a `properties` attribute. + +### Section Type + +Setting the section type determines how the contents of the section will be placed relative to the previous section. E.g., There are five different types: + +- `CONTINUOUS` +- `EVEN_PAGE` +- `NEXT_COLUMN` +- `NEXT_PAGE` +- `ODD_PAGE` + +```ts +doc.addSection({ + properties: { + type: SectionType.CONTINUOUS, + } + children: [ + new Paragraph({ + children: [new TextRun("Hello World")], + }), + ], +}); +``` diff --git a/src/file/document/body/section-properties/index.ts b/src/file/document/body/section-properties/index.ts index 47e56ec172..ee0820c640 100644 --- a/src/file/document/body/section-properties/index.ts +++ b/src/file/document/body/section-properties/index.ts @@ -6,3 +6,4 @@ export * from "./page-number"; export * from "./page-border"; export * from "./line-number"; export * from "./vertical-align"; +export * from "./type"; diff --git a/src/file/document/body/section-properties/section-properties.spec.ts b/src/file/document/body/section-properties/section-properties.spec.ts index 8a55699eb5..7fca1ae265 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -9,6 +9,7 @@ import { Media } from "file/media"; import { PageBorderOffsetFrom } from "./page-border"; import { PageNumberFormat } from "./page-number"; import { SectionProperties } from "./section-properties"; +import { SectionType } from "./type/section-type-attributes"; import { SectionVerticalAlignValue } from "./vertical-align"; describe("SectionProperties", () => { @@ -199,5 +200,17 @@ describe("SectionProperties", () => { const pgNumType = tree["w:sectPr"].find((item) => item["w:pgNumType"] !== undefined); expect(pgNumType).to.equal(undefined); }); + + it("should create section properties with section type", () => { + const properties = new SectionProperties({ + type: SectionType.CONTINUOUS, + }); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]); + const type = tree["w:sectPr"].find((item) => item["w:type"] !== undefined); + expect(type).to.deep.equal({ + "w:type": { _attr: { "w:val": "continuous" } }, + }); + }); }); }); diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index d497bb9131..4b6df3252e 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -18,6 +18,8 @@ import { IPageMarginAttributes } from "./page-margin/page-margin-attributes"; import { IPageNumberTypeAttributes, PageNumberType } from "./page-number"; import { PageSize } from "./page-size/page-size"; import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes"; +import { Type } from "./type/section-type"; +import { SectionType } from "./type/section-type-attributes"; import { TitlePage } from "./title-page/title-page"; import { ISectionVerticalAlignAttributes, SectionVerticalAlign } from "./vertical-align"; @@ -53,6 +55,7 @@ export type SectionPropertiesOptions = IPageSizeAttributes & readonly space?: number; readonly count?: number; }; + readonly type?: SectionType; }; // Need to decouple this from the attributes @@ -91,6 +94,7 @@ export class SectionProperties extends XmlComponent { pageBorderLeft, titlePage = false, verticalAlign, + type, } = options; this.options = options; @@ -129,6 +133,10 @@ export class SectionProperties extends XmlComponent { if (verticalAlign) { this.root.push(new SectionVerticalAlign(verticalAlign)); } + + if (type) { + this.root.push(new Type(type)); + } } private addHeaders(headers?: IHeaderFooterGroup): void { diff --git a/src/file/document/body/section-properties/type/index.ts b/src/file/document/body/section-properties/type/index.ts new file mode 100644 index 0000000000..fd7a8abd9c --- /dev/null +++ b/src/file/document/body/section-properties/type/index.ts @@ -0,0 +1,2 @@ +export * from "./section-type"; +export * from "./section-type-attributes"; diff --git a/src/file/document/body/section-properties/type/section-type-attributes.ts b/src/file/document/body/section-properties/type/section-type-attributes.ts new file mode 100644 index 0000000000..4ac8dd60b4 --- /dev/null +++ b/src/file/document/body/section-properties/type/section-type-attributes.ts @@ -0,0 +1,17 @@ +import { XmlAttributeComponent } from "file/xml-components"; + +export enum SectionType { + CONTINUOUS = "continuous", + EVEN_PAGE = "evenPage", + NEXT_COLUMN = "nextColumn", + NEXT_PAGE = "nextPage", + ODD_PAGE = "oddPage", +} + +export class SectionTypeAttributes extends XmlAttributeComponent<{ + readonly val: SectionType; +}> { + protected readonly xmlKeys = { + val: "w:val", + }; +} diff --git a/src/file/document/body/section-properties/type/section-type.spec.ts b/src/file/document/body/section-properties/type/section-type.spec.ts new file mode 100644 index 0000000000..7276825fab --- /dev/null +++ b/src/file/document/body/section-properties/type/section-type.spec.ts @@ -0,0 +1,35 @@ +import { expect } from "chai"; + +import { Formatter } from "export/formatter"; +import { Type } from "./section-type"; +import { SectionType } from "./section-type-attributes"; + +describe("Type", () => { + it("should create with even page section type", () => { + const sectionType = new Type(SectionType.EVEN_PAGE); + + const tree = new Formatter().format(sectionType); + + expect(tree).to.deep.equal({ + "w:type": { + _attr: { + "w:val": "evenPage", + }, + }, + }); + }); + + it("should create with continuous section type", () => { + const sectionType = new Type(SectionType.CONTINUOUS); + + const tree = new Formatter().format(sectionType); + + expect(tree).to.deep.equal({ + "w:type": { + _attr: { + "w:val": "continuous", + }, + }, + }); + }); +}); diff --git a/src/file/document/body/section-properties/type/section-type.ts b/src/file/document/body/section-properties/type/section-type.ts new file mode 100644 index 0000000000..3a11f2e041 --- /dev/null +++ b/src/file/document/body/section-properties/type/section-type.ts @@ -0,0 +1,10 @@ +// http://officeopenxml.com/WPsection.php +import { XmlComponent } from "file/xml-components"; +import { SectionType, SectionTypeAttributes } from "./section-type-attributes"; + +export class Type extends XmlComponent { + constructor(value: SectionType) { + super("w:type"); + this.root.push(new SectionTypeAttributes({ val: value })); + } +}