diff --git a/demo/48-table-xml-styles.ts b/demo/25-table-xml-styles.ts similarity index 100% rename from demo/48-table-xml-styles.ts rename to demo/25-table-xml-styles.ts diff --git a/demo/42-restart-page-numbers.ts b/demo/42-restart-page-numbers.ts new file mode 100644 index 0000000000..0ecfcee6cc --- /dev/null +++ b/demo/42-restart-page-numbers.ts @@ -0,0 +1,88 @@ +// Page numbers - Start from 0 on a new section +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { AlignmentType, Document, Header, Packer, PageBreak, PageNumber, PageNumberSeparator, Paragraph, TextRun } from "../build"; + +const doc = new Document(); + +doc.addSection({ + headers: { + default: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun("My Title "), + new TextRun({ + children: ["Page ", PageNumber.CURRENT], + }), + ], + }), + ], + }), + first: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun("First Page Header "), + new TextRun({ + children: ["Page ", PageNumber.CURRENT], + }), + ], + }), + ], + }), + }, + children: [ + new Paragraph({ + children: [new TextRun("First Page"), new PageBreak()], + }), + new Paragraph("Second Page"), + ], +}); + +doc.addSection({ + properties: { + pageNumberStart: 1, + pageNumberSeparator: PageNumberSeparator.EM_DASH + }, + headers: { + default: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun("My Title "), + new TextRun({ + children: ["Page ", PageNumber.CURRENT], + }), + ], + }), + ], + }), + first: new Header({ + children: [ + new Paragraph({ + alignment: AlignmentType.RIGHT, + children: [ + new TextRun("First Page Header of Second section"), + new TextRun({ + children: ["Page ", PageNumber.CURRENT], + }), + ], + }), + ], + }), + }, + children: [ + new Paragraph({ + children: [new TextRun("Third Page"), new PageBreak()], + }), + new Paragraph("Fourth Page"), + ], +}); + +Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/demo/54-track-revisions.ts b/demo/60-track-revisions.ts similarity index 100% rename from demo/54-track-revisions.ts rename to demo/60-track-revisions.ts diff --git a/src/file/document/body/body.spec.ts b/src/file/document/body/body.spec.ts index 3e2a3155eb..d9e536242b 100644 --- a/src/file/document/body/body.spec.ts +++ b/src/file/document/body/body.spec.ts @@ -41,6 +41,11 @@ describe("Body", () => { }, { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } }, { "w:docGrid": { _attr: { "w:linePitch": 360 } } }, + { + "w:pgNumType": { + _attr: {}, + }, + }, ], }, ], diff --git a/src/file/document/body/section-properties/page-number/page-number.ts b/src/file/document/body/section-properties/page-number/page-number.ts index b6bd5a6e86..f536a6a935 100644 --- a/src/file/document/body/section-properties/page-number/page-number.ts +++ b/src/file/document/body/section-properties/page-number/page-number.ts @@ -17,25 +17,36 @@ export enum PageNumberFormat { DECIMAL_FULL_WIDTH = "decimalFullWidth", } +export enum PageNumberSeparator { + COLON = "colon", + EM_DASH = "emDash", + EN_DASH = "endash", + HYPHEN = "hyphen", + PERIOD = "period", +} + export interface IPageNumberTypeAttributes { readonly pageNumberStart?: number; readonly pageNumberFormatType?: PageNumberFormat; + readonly pageNumberSeparator?: PageNumberSeparator; } export class PageNumberTypeAttributes extends XmlAttributeComponent { protected readonly xmlKeys = { pageNumberStart: "w:start", pageNumberFormatType: "w:fmt", + pageNumberSeparator: "w:chapSep", }; } export class PageNumberType extends XmlComponent { - constructor(start?: number, numberFormat?: PageNumberFormat) { + constructor(start?: number, numberFormat?: PageNumberFormat, separator?: PageNumberSeparator) { super("w:pgNumType"); this.root.push( new PageNumberTypeAttributes({ pageNumberStart: start, pageNumberFormatType: numberFormat, + pageNumberSeparator: separator, }), ); } 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 dea16f5ac3..9bd13aa078 100644 --- a/src/file/document/body/section-properties/section-properties.spec.ts +++ b/src/file/document/body/section-properties/section-properties.spec.ts @@ -5,6 +5,7 @@ import { Formatter } from "export/formatter"; import { FooterWrapper } from "file/footer-wrapper"; import { HeaderWrapper } from "file/header-wrapper"; import { Media } from "file/media"; +import { LineNumberRestartFormat } from "./line-number"; import { PageBorderOffsetFrom } from "./page-border"; import { PageNumberFormat } from "./page-number"; @@ -194,12 +195,12 @@ 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", () => { @@ -213,5 +214,20 @@ describe("SectionProperties", () => { "w:type": { _attr: { "w:val": "continuous" } }, }); }); + + it("should create section properties line number type", () => { + const properties = new SectionProperties({ + lineNumberCountBy: 2, + lineNumberStart: 2, + lineNumberRestart: LineNumberRestartFormat.CONTINUOUS, + lineNumberDistance: 4, + }); + const tree = new Formatter().format(properties); + expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]); + const type = tree["w:sectPr"].find((item) => item["w:lnNumType"] !== undefined); + expect(type).to.deep.equal({ + "w:lnNumType": { _attr: { "w:countBy": 2, "w:distance": 4, "w:restart": "continuous", "w:start": 2 } }, + }); + }); }); }); diff --git a/src/file/document/body/section-properties/section-properties.ts b/src/file/document/body/section-properties/section-properties.ts index 83bb93e580..1e0af54191 100644 --- a/src/file/document/body/section-properties/section-properties.ts +++ b/src/file/document/body/section-properties/section-properties.ts @@ -65,10 +65,8 @@ export class SectionProperties extends XmlComponent { public readonly rightMargin: number; public readonly leftMargin: number; - constructor(options: SectionPropertiesOptions = { column: {} }) { - super("w:sectPr"); - - const { + constructor( + { width = 11906, height = 16838, top = convertInchesToTwip(1), @@ -86,6 +84,7 @@ export class SectionProperties extends XmlComponent { footers, pageNumberFormatType, pageNumberStart, + pageNumberSeparator, lineNumberCountBy, lineNumberStart, lineNumberRestart, @@ -98,7 +97,9 @@ export class SectionProperties extends XmlComponent { titlePage = false, verticalAlign, type, - } = options; + }: SectionPropertiesOptions = { column: {} }, + ) { + super("w:sectPr"); this.leftMargin = left; this.rightMargin = right; @@ -112,9 +113,7 @@ export class SectionProperties extends XmlComponent { this.addHeaders(headers); this.addFooters(footers); - if (pageNumberStart || pageNumberFormatType) { - this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType)); - } + this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType, pageNumberSeparator)); if (lineNumberCountBy || lineNumberStart || lineNumberRestart || lineNumberDistance) { this.root.push(new LineNumberType(lineNumberCountBy, lineNumberStart, lineNumberRestart, lineNumberDistance)); diff --git a/src/file/file.spec.ts b/src/file/file.spec.ts index c266b1d3b9..b2195f439f 100644 --- a/src/file/file.spec.ts +++ b/src/file/file.spec.ts @@ -160,6 +160,11 @@ describe("File", () => { }, }, }, + { + "w:pgNumType": { + _attr: {}, + }, + }, ], }, ],