feature: add support to add mutiple sections to the document inc. headers and footers

- write missing tests
This commit is contained in:
Igor Bulovski
2018-06-21 12:03:34 +02:00
parent b8b5d18662
commit 0b963ec3b8
33 changed files with 611 additions and 102 deletions

View File

@ -1,5 +1,11 @@
import { XmlAttributeComponent } from "file/xml-components";
export enum FooterReferenceType {
DEFAULT = "default",
FIRST = "first",
EVEN = "even",
}
export interface IFooterReferenceAttributes {
type: string;
id: string;

View File

@ -1,13 +1,19 @@
import { XmlComponent } from "file/xml-components";
import { FooterReferenceAttributes } from "./footer-reference-attributes";
import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
export interface FooterOptions {
footerType?: FooterReferenceType;
footerId?: number;
}
export class FooterReference extends XmlComponent {
constructor() {
constructor(options: FooterOptions) {
super("w:footerReference");
this.root.push(
new FooterReferenceAttributes({
type: "default",
id: `rId${4}`,
type: options.footerType || FooterReferenceType.DEFAULT,
id: `rId${options.footerId}`,
}),
);
}

View File

@ -0,0 +1,2 @@
export * from "./footer-reference";
export * from "./footer-reference-attributes";

View File

@ -1,5 +1,11 @@
import { XmlAttributeComponent } from "file/xml-components";
export enum HeaderReferenceType {
DEFAULT = "default",
FIRST = "first",
EVEN = "even",
}
export interface IHeaderReferenceAttributes {
type: string;
id: string;

View File

@ -1,13 +1,18 @@
import { XmlComponent } from "file/xml-components";
import { HeaderReferenceAttributes } from "./header-reference-attributes";
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
export interface HeaderOptions {
headerType?: HeaderReferenceType;
headerId?: number;
}
export class HeaderReference extends XmlComponent {
constructor() {
constructor(options: HeaderOptions) {
super("w:headerReference");
this.root.push(
new HeaderReferenceAttributes({
type: "default",
id: `rId${3}`,
type: options.headerType || HeaderReferenceType.DEFAULT,
id: `rId${options.headerId}`,
}),
);
}

View File

@ -0,0 +1,2 @@
export * from "./header-reference";
export * from "./header-reference-attributes";

View File

@ -0,0 +1,5 @@
export * from "./section-properties";
export * from "./footer-reference";
export * from "./header-reference";
export * from "./page-size";
export * from "./page-number";

View File

@ -0,0 +1 @@
export * from "./page-number";

View File

@ -0,0 +1,41 @@
// http://officeopenxml.com/WPSectionPgNumType.php
import { XmlComponent, XmlAttributeComponent } from "file/xml-components";
export enum PageNumberFormat {
CARDINAL_TEXT = "cardinalText",
DECIMAL = "decimal",
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
DECIMAL_ENCLOSED_FULL_STOP = "decimalEnclosedFullstop",
DECIMAL_ENCLOSED_PAREN = "decimalEnclosedParen",
DECIMAL_ZERO = "decimalZero",
LOWER_LETTER = "lowerLetter",
LOWER_ROMAN = "lowerRoman",
NONE = "none",
ORDINAL_TEXT = "ordinalText",
UPPER_LETTER = "upperLetter",
UPPER_ROMAN = "upperRoman",
}
export interface IPageNumberTypeAttributes {
pageNumberStart?: number;
pageNumberFormatType?: PageNumberFormat;
}
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
protected xmlKeys = {
pageNumberStart: "w:start",
pageNumberFormatType: "w:fmt",
};
}
export class PageNumberType extends XmlComponent {
constructor(start?: number, numberFormat?: PageNumberFormat) {
super("w:pgNumType");
this.root.push(
new PageNumberTypeAttributes({
pageNumberStart: start,
pageNumberFormatType: numberFormat,
}),
);
}
}

View File

@ -0,0 +1,2 @@
export * from "./page-size";
export * from "./page-size-attributes";

View File

@ -1,9 +1,14 @@
import { XmlAttributeComponent } from "file/xml-components";
export enum PageOrientation {
PORTRAIT = "portrait",
LANDSCAPE = "landscape",
}
export interface IPageSizeAttributes {
width?: number;
height?: number;
orientation?: string;
orientation?: PageOrientation;
}
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {

View File

@ -2,11 +2,12 @@ import { expect } from "chai";
import { Formatter } from "../../../../../export/formatter";
import { PageSize } from "./page-size";
import { PageOrientation } from "./page-size-attributes";
describe("PageSize", () => {
describe("#constructor()", () => {
it("should create page size with portrait", () => {
const properties = new PageSize(100, 200, "portrait");
const properties = new PageSize(100, 200, PageOrientation.PORTRAIT);
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
@ -15,7 +16,7 @@ describe("PageSize", () => {
});
it("should create page size with horizontal and invert the lengths", () => {
const properties = new PageSize(100, 200, "landscape");
const properties = new PageSize(100, 200, PageOrientation.LANDSCAPE);
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);

View File

@ -1,11 +1,11 @@
import { XmlComponent } from "file/xml-components";
import { PageSizeAttributes } from "./page-size-attributes";
import { PageSizeAttributes, PageOrientation } from "./page-size-attributes";
export class PageSize extends XmlComponent {
constructor(width: number, height: number, orientation: string) {
constructor(width: number, height: number, orientation: PageOrientation) {
super("w:pgSz");
const flip = orientation === "landscape";
const flip = orientation === PageOrientation.LANDSCAPE;
this.root.push(
new PageSizeAttributes({

View File

@ -2,6 +2,7 @@ import { expect } from "chai";
import { Formatter } from "../../../../export/formatter";
import { SectionProperties } from "./section-properties";
import { FooterReferenceType, PageNumberFormat } from ".";
describe("SectionProperties", () => {
describe("#constructor()", () => {
@ -18,6 +19,11 @@ describe("SectionProperties", () => {
gutter: 0,
space: 708,
linePitch: 360,
headerId: 100,
footerId: 200,
footerType: FooterReferenceType.EVEN,
pageNumberStart: 10,
pageNumberFormatType: PageNumberFormat.CARDINAL_TEXT,
});
const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
@ -38,6 +44,12 @@ describe("SectionProperties", () => {
},
],
});
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:headerReference": [{ _attr: { "r:id": "rId100", "w:type": "default" } }] });
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:footerReference": [{ _attr: { "r:id": "rId200", "w:type": "even" } }] });
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:pgNumType": [{ _attr: { "w:fmt": "cardinalText", "w:start": 10 } }] });
});
it("should create section properties with no options", () => {
@ -61,6 +73,11 @@ describe("SectionProperties", () => {
},
],
});
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:headerReference": [{ _attr: { "r:id": "rId0", "w:type": "default" } }] });
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:footerReference": [{ _attr: { "r:id": "rId0", "w:type": "default" } }] });
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:pgNumType": [{ _attr: { "w:fmt": "decimal" } }] });
});
it("should create section properties with changed options", () => {

View File

@ -4,16 +4,25 @@ import { Columns } from "./columns/columns";
import { IColumnsAttributes } from "./columns/columns-attributes";
import { DocumentGrid } from "./doc-grid/doc-grid";
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
import { FooterReference } from "./footer-reference/footer-reference";
import { HeaderReference } from "./header-reference/header-reference";
import { FooterReference, FooterOptions } from "./footer-reference/footer-reference";
import { HeaderReference, HeaderOptions } from "./header-reference/header-reference";
import { PageMargin } from "./page-margin/page-margin";
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
import { PageSize } from "./page-size/page-size";
import { IPageSizeAttributes } from "./page-size/page-size-attributes";
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
import { FooterReferenceType, IPageNumberTypeAttributes, PageNumberType, PageNumberFormat } from ".";
import { HeaderReferenceType } from "./header-reference/header-reference-attributes";
export type SectionPropertiesOptions = IPageSizeAttributes & IPageMarginAttributes & IColumnsAttributes & IDocGridAttributesProperties;
export type SectionPropertiesOptions = IPageSizeAttributes &
IPageMarginAttributes &
IColumnsAttributes &
IDocGridAttributesProperties &
HeaderOptions &
FooterOptions &
IPageNumberTypeAttributes;
export class SectionProperties extends XmlComponent {
private options: SectionPropertiesOptions;
constructor(options?: SectionPropertiesOptions) {
super("w:sectPr");
@ -29,7 +38,13 @@ export class SectionProperties extends XmlComponent {
gutter: 0,
space: 708,
linePitch: 360,
orientation: "portrait",
orientation: PageOrientation.PORTRAIT,
headerType: HeaderReferenceType.DEFAULT,
headerId: 0,
footerType: FooterReferenceType.DEFAULT,
footerId: 0,
pageNumberStart: undefined,
pageNumberFormatType: PageNumberFormat.DECIMAL,
};
const mergedOptions = {
@ -51,7 +66,25 @@ export class SectionProperties extends XmlComponent {
);
this.root.push(new Columns(mergedOptions.space));
this.root.push(new DocumentGrid(mergedOptions.linePitch));
this.root.push(new HeaderReference());
this.root.push(new FooterReference());
this.root.push(
new HeaderReference({
headerType: mergedOptions.headerType,
headerId: mergedOptions.headerId,
}),
);
this.root.push(
new FooterReference({
footerType: mergedOptions.footerType,
footerId: mergedOptions.footerId,
}),
);
this.root.push(new PageNumberType(mergedOptions.pageNumberStart, mergedOptions.pageNumberFormatType));
this.options = mergedOptions;
}
get Options() {
return this.options;
}
}