Merge pull request #511 from dolanmiu/feature/separator

Restart page numbering
This commit is contained in:
Dolan
2021-03-09 23:11:15 +00:00
committed by GitHub
8 changed files with 135 additions and 11 deletions

View File

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

View File

@ -41,6 +41,11 @@ describe("Body", () => {
}, },
{ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } }, { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } }, { "w:docGrid": { _attr: { "w:linePitch": 360 } } },
{
"w:pgNumType": {
_attr: {},
},
},
], ],
}, },
], ],

View File

@ -17,25 +17,36 @@ export enum PageNumberFormat {
DECIMAL_FULL_WIDTH = "decimalFullWidth", DECIMAL_FULL_WIDTH = "decimalFullWidth",
} }
export enum PageNumberSeparator {
COLON = "colon",
EM_DASH = "emDash",
EN_DASH = "endash",
HYPHEN = "hyphen",
PERIOD = "period",
}
export interface IPageNumberTypeAttributes { export interface IPageNumberTypeAttributes {
readonly pageNumberStart?: number; readonly pageNumberStart?: number;
readonly pageNumberFormatType?: PageNumberFormat; readonly pageNumberFormatType?: PageNumberFormat;
readonly pageNumberSeparator?: PageNumberSeparator;
} }
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> { export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
pageNumberStart: "w:start", pageNumberStart: "w:start",
pageNumberFormatType: "w:fmt", pageNumberFormatType: "w:fmt",
pageNumberSeparator: "w:chapSep",
}; };
} }
export class PageNumberType extends XmlComponent { export class PageNumberType extends XmlComponent {
constructor(start?: number, numberFormat?: PageNumberFormat) { constructor(start?: number, numberFormat?: PageNumberFormat, separator?: PageNumberSeparator) {
super("w:pgNumType"); super("w:pgNumType");
this.root.push( this.root.push(
new PageNumberTypeAttributes({ new PageNumberTypeAttributes({
pageNumberStart: start, pageNumberStart: start,
pageNumberFormatType: numberFormat, pageNumberFormatType: numberFormat,
pageNumberSeparator: separator,
}), }),
); );
} }

View File

@ -5,6 +5,7 @@ import { Formatter } from "export/formatter";
import { FooterWrapper } from "file/footer-wrapper"; import { FooterWrapper } from "file/footer-wrapper";
import { HeaderWrapper } from "file/header-wrapper"; import { HeaderWrapper } from "file/header-wrapper";
import { Media } from "file/media"; import { Media } from "file/media";
import { LineNumberRestartFormat } from "./line-number";
import { PageBorderOffsetFrom } from "./page-border"; import { PageBorderOffsetFrom } from "./page-border";
import { PageNumberFormat } from "./page-number"; 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 properties = new SectionProperties({});
const tree = new Formatter().format(properties); const tree = new Formatter().format(properties);
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]); expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
const pgNumType = tree["w:sectPr"].find((item) => item["w:pgNumType"] !== undefined); 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", () => { it("should create section properties with section type", () => {
@ -213,5 +214,20 @@ describe("SectionProperties", () => {
"w:type": { _attr: { "w:val": "continuous" } }, "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 } },
});
});
}); });
}); });

View File

@ -65,10 +65,8 @@ export class SectionProperties extends XmlComponent {
public readonly rightMargin: number; public readonly rightMargin: number;
public readonly leftMargin: number; public readonly leftMargin: number;
constructor(options: SectionPropertiesOptions = { column: {} }) { constructor(
super("w:sectPr"); {
const {
width = 11906, width = 11906,
height = 16838, height = 16838,
top = convertInchesToTwip(1), top = convertInchesToTwip(1),
@ -86,6 +84,7 @@ export class SectionProperties extends XmlComponent {
footers, footers,
pageNumberFormatType, pageNumberFormatType,
pageNumberStart, pageNumberStart,
pageNumberSeparator,
lineNumberCountBy, lineNumberCountBy,
lineNumberStart, lineNumberStart,
lineNumberRestart, lineNumberRestart,
@ -98,7 +97,9 @@ export class SectionProperties extends XmlComponent {
titlePage = false, titlePage = false,
verticalAlign, verticalAlign,
type, type,
} = options; }: SectionPropertiesOptions = { column: {} },
) {
super("w:sectPr");
this.leftMargin = left; this.leftMargin = left;
this.rightMargin = right; this.rightMargin = right;
@ -112,9 +113,7 @@ export class SectionProperties extends XmlComponent {
this.addHeaders(headers); this.addHeaders(headers);
this.addFooters(footers); this.addFooters(footers);
if (pageNumberStart || pageNumberFormatType) { this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType, pageNumberSeparator));
this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType));
}
if (lineNumberCountBy || lineNumberStart || lineNumberRestart || lineNumberDistance) { if (lineNumberCountBy || lineNumberStart || lineNumberRestart || lineNumberDistance) {
this.root.push(new LineNumberType(lineNumberCountBy, lineNumberStart, lineNumberRestart, lineNumberDistance)); this.root.push(new LineNumberType(lineNumberCountBy, lineNumberStart, lineNumberRestart, lineNumberDistance));

View File

@ -160,6 +160,11 @@ describe("File", () => {
}, },
}, },
}, },
{
"w:pgNumType": {
_attr: {},
},
},
], ],
}, },
], ],