Merge branch 'master' of github.com:dolanmiu/docx into feature/separator
# Conflicts: # src/file/document/body/section-properties/section-properties.ts
This commit is contained in:
@ -39,8 +39,13 @@ describe("Body", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
{ "w:cols": { _attr: { "w:space": 708, "w:num": 1 } } },
|
||||
{ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
|
||||
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
|
||||
{
|
||||
"w:pgNumType": {
|
||||
_attr: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { IViewWrapper } from "file/document-wrapper";
|
||||
import { IXmlableObject, XmlComponent } from "file/xml-components";
|
||||
|
||||
import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
|
||||
import { File } from "../../../file";
|
||||
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
|
||||
|
||||
export class Body extends XmlComponent {
|
||||
@ -25,7 +26,7 @@ export class Body extends XmlComponent {
|
||||
this.sections.push(new SectionProperties(options));
|
||||
}
|
||||
|
||||
public prepForXml(file?: File): IXmlableObject | undefined {
|
||||
public prepForXml(file?: IViewWrapper): IXmlableObject | undefined {
|
||||
if (this.sections.length === 1) {
|
||||
this.root.splice(0, 1);
|
||||
this.root.push(this.sections.pop() as SectionProperties);
|
||||
@ -45,7 +46,7 @@ export class Body extends XmlComponent {
|
||||
private createSectionParagraph(section: SectionProperties): Paragraph {
|
||||
const paragraph = new Paragraph({});
|
||||
const properties = new ParagraphProperties({});
|
||||
properties.addChildElement(section);
|
||||
properties.push(section);
|
||||
paragraph.addChildElement(properties);
|
||||
return paragraph;
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IColumnsAttributes {
|
||||
export class ColumnsAttributes extends XmlAttributeComponent<{
|
||||
readonly space?: number;
|
||||
readonly num?: number;
|
||||
}
|
||||
|
||||
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||
readonly separate?: boolean;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
space: "w:space",
|
||||
num: "w:num",
|
||||
separate: "w:sep",
|
||||
};
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ import { XmlComponent } from "file/xml-components";
|
||||
import { ColumnsAttributes } from "./columns-attributes";
|
||||
|
||||
export class Columns extends XmlComponent {
|
||||
constructor(space: number, num: number) {
|
||||
constructor(space: number, num: number, separate: boolean) {
|
||||
super("w:cols");
|
||||
this.root.push(
|
||||
new ColumnsAttributes({
|
||||
space: space,
|
||||
num: num,
|
||||
separate: separate,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -6,3 +6,4 @@ export * from "./page-number";
|
||||
export * from "./page-border";
|
||||
export * from "./line-number";
|
||||
export * from "./vertical-align";
|
||||
export * from "./type";
|
||||
|
@ -14,6 +14,7 @@ export enum PageNumberFormat {
|
||||
ORDINAL_TEXT = "ordinalText",
|
||||
UPPER_LETTER = "upperLetter",
|
||||
UPPER_ROMAN = "upperRoman",
|
||||
DECIMAL_FULL_WIDTH = "decimalFullWidth",
|
||||
}
|
||||
|
||||
export enum PageNumberSeparator {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { convertInchesToTwip } from "convenience-functions";
|
||||
import { Formatter } from "export/formatter";
|
||||
import { FooterWrapper } from "file/footer-wrapper";
|
||||
import { HeaderWrapper } from "file/header-wrapper";
|
||||
@ -8,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", () => {
|
||||
@ -18,10 +20,10 @@ describe("SectionProperties", () => {
|
||||
const properties = new SectionProperties({
|
||||
width: 11906,
|
||||
height: 16838,
|
||||
top: 1440,
|
||||
right: 1440,
|
||||
bottom: 1440,
|
||||
left: 1440,
|
||||
top: convertInchesToTwip(1),
|
||||
right: convertInchesToTwip(1),
|
||||
bottom: convertInchesToTwip(1),
|
||||
left: convertInchesToTwip(1),
|
||||
header: 708,
|
||||
footer: 708,
|
||||
gutter: 0,
|
||||
@ -29,8 +31,9 @@ describe("SectionProperties", () => {
|
||||
column: {
|
||||
space: 708,
|
||||
count: 1,
|
||||
separate: true,
|
||||
},
|
||||
linePitch: 360,
|
||||
linePitch: convertInchesToTwip(0.25),
|
||||
headers: {
|
||||
default: new HeaderWrapper(media, 100),
|
||||
},
|
||||
@ -61,7 +64,7 @@ describe("SectionProperties", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": true, "w:num": 1 } } });
|
||||
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" } } });
|
||||
@ -88,7 +91,7 @@ describe("SectionProperties", () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } });
|
||||
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": { _attr: { "w:linePitch": 360 } } });
|
||||
});
|
||||
|
||||
@ -191,12 +194,24 @@ describe("SectionProperties", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should create section properties without page number type", () => {
|
||||
it("should create section properties with a page number type by default", () => {
|
||||
const properties = new SectionProperties({});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
const pgNumType = tree["w:sectPr"].find((item) => item["w:pgNumType"] !== undefined);
|
||||
expect(pgNumType).to.equal(undefined);
|
||||
expect(pgNumType).to.deep.equal({ "w:pgNumType": { _attr: {} } });
|
||||
});
|
||||
|
||||
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" } },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
import { convertInchesToTwip } from "convenience-functions";
|
||||
import { FooterWrapper } from "file/footer-wrapper";
|
||||
import { HeaderWrapper } from "file/header-wrapper";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
@ -18,6 +19,8 @@ import { IPageNumberTypeAttributes, PageNumberType } from "./page-number";
|
||||
import { PageSize } from "./page-size/page-size";
|
||||
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
|
||||
import { TitlePage } from "./title-page/title-page";
|
||||
import { Type } from "./type/section-type";
|
||||
import { SectionType } from "./type/section-type-attributes";
|
||||
import { ISectionVerticalAlignAttributes, SectionVerticalAlign } from "./vertical-align";
|
||||
|
||||
export interface IHeaderFooterGroup<T> {
|
||||
@ -51,19 +54,25 @@ export type SectionPropertiesOptions = IPageSizeAttributes &
|
||||
readonly column?: {
|
||||
readonly space?: number;
|
||||
readonly count?: number;
|
||||
readonly separate?: boolean;
|
||||
};
|
||||
readonly type?: SectionType;
|
||||
};
|
||||
// Need to decouple this from the attributes
|
||||
|
||||
export class SectionProperties extends XmlComponent {
|
||||
public readonly width: number;
|
||||
public readonly rightMargin: number;
|
||||
public readonly leftMargin: number;
|
||||
|
||||
constructor(
|
||||
{
|
||||
width = 11906,
|
||||
height = 16838,
|
||||
top = 1440,
|
||||
right = 1440,
|
||||
bottom = 1440,
|
||||
left = 1440,
|
||||
top = convertInchesToTwip(1),
|
||||
right = convertInchesToTwip(1),
|
||||
bottom = convertInchesToTwip(1),
|
||||
left = convertInchesToTwip(1),
|
||||
header = 708,
|
||||
footer = 708,
|
||||
gutter = 0,
|
||||
@ -87,13 +96,18 @@ export class SectionProperties extends XmlComponent {
|
||||
pageBorderLeft,
|
||||
titlePage = false,
|
||||
verticalAlign,
|
||||
type,
|
||||
}: SectionPropertiesOptions = { column: {} },
|
||||
) {
|
||||
super("w:sectPr");
|
||||
|
||||
this.leftMargin = left;
|
||||
this.rightMargin = right;
|
||||
this.width = width;
|
||||
|
||||
this.root.push(new PageSize(width, height, orientation));
|
||||
this.root.push(new PageMargin(top, right, bottom, left, header, footer, gutter, mirror));
|
||||
this.root.push(new Columns(column.space ? column.space : 708, column.count ? column.count : 1));
|
||||
this.root.push(new Columns(column.space ? column.space : 708, column.count ? column.count : 1, column.separate ?? false));
|
||||
this.root.push(new DocumentGrid(linePitch));
|
||||
|
||||
this.addHeaders(headers);
|
||||
@ -124,6 +138,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<HeaderWrapper>): void {
|
||||
@ -132,7 +150,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.DEFAULT,
|
||||
headerId: headers.default.Header.ReferenceId,
|
||||
headerId: headers.default.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -141,7 +159,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.FIRST,
|
||||
headerId: headers.first.Header.ReferenceId,
|
||||
headerId: headers.first.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -150,7 +168,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new HeaderReference({
|
||||
headerType: HeaderReferenceType.EVEN,
|
||||
headerId: headers.even.Header.ReferenceId,
|
||||
headerId: headers.even.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -163,7 +181,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.DEFAULT,
|
||||
footerId: footers.default.Footer.ReferenceId,
|
||||
footerId: footers.default.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -172,7 +190,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.FIRST,
|
||||
footerId: footers.first.Footer.ReferenceId,
|
||||
footerId: footers.first.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -181,7 +199,7 @@ export class SectionProperties extends XmlComponent {
|
||||
this.root.push(
|
||||
new FooterReference({
|
||||
footerType: FooterReferenceType.EVEN,
|
||||
footerId: footers.even.Footer.ReferenceId,
|
||||
footerId: footers.even.View.ReferenceId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
2
src/file/document/body/section-properties/type/index.ts
Normal file
2
src/file/document/body/section-properties/type/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from "./section-type";
|
||||
export * from "./section-type-attributes";
|
@ -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",
|
||||
};
|
||||
}
|
@ -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",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
@ -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 }));
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "export/formatter";
|
||||
|
||||
import { DocumentBackground } from "./document-background";
|
||||
|
||||
describe("DocumentBackground", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create a DocumentBackground with no options and set color to auto", () => {
|
||||
const documentBackground = new DocumentBackground({});
|
||||
const tree = new Formatter().format(documentBackground);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:background": {
|
||||
_attr: {
|
||||
"w:color": "FFFFFF",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a DocumentBackground with no options and set color to value", () => {
|
||||
const documentBackground = new DocumentBackground({ color: "ffff00" });
|
||||
const tree = new Formatter().format(documentBackground);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:background": {
|
||||
_attr: {
|
||||
"w:color": "ffff00",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a DocumentBackground with no options and set other values", () => {
|
||||
const documentBackground = new DocumentBackground({
|
||||
color: "ffff00",
|
||||
themeColor: "test",
|
||||
themeShade: "test",
|
||||
themeTint: "test",
|
||||
});
|
||||
const tree = new Formatter().format(documentBackground);
|
||||
expect(tree).to.deep.equal({
|
||||
"w:background": {
|
||||
_attr: {
|
||||
"w:color": "ffff00",
|
||||
"w:themeColor": "test",
|
||||
"w:themeShade": "test",
|
||||
"w:themeTint": "test",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
39
src/file/document/document-background/document-background.ts
Normal file
39
src/file/document/document-background/document-background.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// http://officeopenxml.com/WPdocument.php
|
||||
// http://www.datypic.com/sc/ooxml/e-w_background-1.html
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
export class DocumentBackgroundAttributes extends XmlAttributeComponent<{
|
||||
readonly color: string;
|
||||
readonly themeColor?: string;
|
||||
readonly themeShade?: string;
|
||||
readonly themeTint?: string;
|
||||
}> {
|
||||
protected readonly xmlKeys = {
|
||||
color: "w:color",
|
||||
themeColor: "w:themeColor",
|
||||
themeShade: "w:themeShade",
|
||||
themeTint: "w:themeTint",
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDocumentBackgroundOptions {
|
||||
readonly color?: string;
|
||||
readonly themeColor?: string;
|
||||
readonly themeShade?: string;
|
||||
readonly themeTint?: string;
|
||||
}
|
||||
|
||||
export class DocumentBackground extends XmlComponent {
|
||||
constructor(options: IDocumentBackgroundOptions) {
|
||||
super("w:background");
|
||||
|
||||
this.root.push(
|
||||
new DocumentBackgroundAttributes({
|
||||
color: options.color ? options.color : "FFFFFF",
|
||||
themeColor: options.themeColor,
|
||||
themeShade: options.themeShade,
|
||||
themeTint: options.themeTint,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
1
src/file/document/document-background/index.ts
Normal file
1
src/file/document/document-background/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./document-background";
|
@ -8,7 +8,7 @@ describe("Document", () => {
|
||||
let document: Document;
|
||||
|
||||
beforeEach(() => {
|
||||
document = new Document();
|
||||
document = new Document({ background: {} });
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
@ -38,6 +38,13 @@ describe("Document", () => {
|
||||
"mc:Ignorable": "w14 w15 wp14",
|
||||
},
|
||||
},
|
||||
{
|
||||
"w:background": {
|
||||
_attr: {
|
||||
"w:color": "FFFFFF",
|
||||
},
|
||||
},
|
||||
},
|
||||
{ "w:body": {} },
|
||||
],
|
||||
});
|
||||
|
@ -1,15 +1,20 @@
|
||||
// http://officeopenxml.com/WPdocument.php
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Hyperlink, Paragraph } from "../paragraph";
|
||||
import { ConcreteHyperlink, Paragraph } from "../paragraph";
|
||||
import { Table } from "../table";
|
||||
import { TableOfContents } from "../table-of-contents";
|
||||
import { Body } from "./body";
|
||||
import { DocumentAttributes } from "./document-attributes";
|
||||
import { DocumentBackground, IDocumentBackgroundOptions } from "./document-background";
|
||||
|
||||
export interface IDocumentOptions {
|
||||
readonly background: IDocumentBackgroundOptions;
|
||||
}
|
||||
|
||||
export class Document extends XmlComponent {
|
||||
private readonly body: Body;
|
||||
|
||||
constructor() {
|
||||
constructor(options: IDocumentOptions) {
|
||||
super("w:document");
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
@ -33,10 +38,11 @@ export class Document extends XmlComponent {
|
||||
}),
|
||||
);
|
||||
this.body = new Body();
|
||||
this.root.push(new DocumentBackground(options.background));
|
||||
this.root.push(this.body);
|
||||
}
|
||||
|
||||
public add(item: Paragraph | Table | TableOfContents | Hyperlink): Document {
|
||||
public add(item: Paragraph | Table | TableOfContents | ConcreteHyperlink): Document {
|
||||
this.body.push(item);
|
||||
return this;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
export * from "./document";
|
||||
export * from "./document-attributes";
|
||||
export * from "./body";
|
||||
export * from "./document-background";
|
||||
|
Reference in New Issue
Block a user