diff --git a/demo/demo33.ts b/demo/demo33.ts new file mode 100644 index 0000000000..c6efe2ed0f --- /dev/null +++ b/demo/demo33.ts @@ -0,0 +1,22 @@ +// Sequential Captions +// Import from 'docx' rather than '../build' if you install from npm +import * as fs from "fs"; +import { Document, Packer, Paragraph, TextRun } from "../build"; + +const doc = new Document(); + +const paragraph = new Paragraph("Hello World 1->").addSequentialIdentifier("Caption").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Caption"); +const paragraph2 = new Paragraph("Hello World 1->").addSequentialIdentifier("Label").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Label"); +const paragraph3 = new Paragraph("Hello World 1->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 3->")).addSequentialIdentifier("Label"); +const paragraph4 = new Paragraph("Hello World 2->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 4->")).addSequentialIdentifier("Label"); + +doc.addParagraph(paragraph); +doc.addParagraph(paragraph2); +doc.addParagraph(paragraph3); +doc.addParagraph(paragraph4); + +const packer = new Packer(); + +packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); +}); diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts index 8fdfbe2fff..263064d2fa 100644 --- a/src/file/paragraph/paragraph.ts +++ b/src/file/paragraph/paragraph.ts @@ -16,7 +16,7 @@ import { CenterTabStop, LeaderType, LeftTabStop, MaxRightTabStop, RightTabStop } import { NumberProperties } from "./formatting/unordered-list"; import { Bookmark, Hyperlink } from "./links"; import { ParagraphProperties } from "./properties"; -import { PictureRun, Run, TextRun } from "./run"; +import { PictureRun, Run, SequentialIdentifier, TextRun } from "./run"; export class Paragraph extends XmlComponent { private readonly properties: ParagraphProperties; @@ -245,4 +245,9 @@ export class Paragraph extends XmlComponent { this.root.splice(1, 0, run); return this; } + + public addSequentialIdentifier(identifier: string): Paragraph { + this.root.push(new SequentialIdentifier(identifier)); + return this; + } } diff --git a/src/file/paragraph/run/index.ts b/src/file/paragraph/run/index.ts index 6ac823e9bb..a30a1d6037 100644 --- a/src/file/paragraph/run/index.ts +++ b/src/file/paragraph/run/index.ts @@ -1,3 +1,4 @@ export * from "./run"; export * from "./text-run"; export * from "./picture-run"; +export * from "./sequential-identifier"; diff --git a/src/file/paragraph/run/sequential-identifier-instruction.ts b/src/file/paragraph/run/sequential-identifier-instruction.ts new file mode 100644 index 0000000000..6f48738db7 --- /dev/null +++ b/src/file/paragraph/run/sequential-identifier-instruction.ts @@ -0,0 +1,19 @@ +// http://officeopenxml.com/WPfieldInstructions.php +import { XmlAttributeComponent, XmlComponent } from "file/xml-components"; + +enum SpaceType { + DEFAULT = "default", + PRESERVE = "preserve", +} + +class TextAttributes extends XmlAttributeComponent<{ space: SpaceType }> { + protected xmlKeys = { space: "xml:space" }; +} + +export class SequentialIdentifierInstruction extends XmlComponent { + constructor(identifier: string) { + super("w:instrText"); + this.root.push(new TextAttributes({ space: SpaceType.PRESERVE })); + this.root.push(`SEQ ${identifier}`); + } +} diff --git a/src/file/paragraph/run/sequential-identifier.spec.ts b/src/file/paragraph/run/sequential-identifier.spec.ts new file mode 100644 index 0000000000..1b34997b9c --- /dev/null +++ b/src/file/paragraph/run/sequential-identifier.spec.ts @@ -0,0 +1,60 @@ +import { expect } from "chai"; + +import { Formatter } from "../../../export/formatter"; +import { SequentialIdentifier } from "./sequential-identifier"; + +describe("Sequential Identifier", () => { + describe("#constructor", () => { + it("should construct a SEQ without options", () => { + const seq = new SequentialIdentifier("Figure"); + const tree = new Formatter().format(seq); + expect(tree).to.be.deep.equal(DEFAULT_SEQ); + }); + }); +}); + +const DEFAULT_SEQ = { + "w:r": [ + { + "w:rPr": [], + }, + { + "w:fldChar": [ + { + _attr: { + "w:fldCharType": "begin", + "w:dirty": true, + }, + }, + ], + }, + { + "w:instrText": [ + { + _attr: { + "xml:space": "preserve", + }, + }, + "SEQ Figure", + ], + }, + { + "w:fldChar": [ + { + _attr: { + "w:fldCharType": "separate", + }, + }, + ], + }, + { + "w:fldChar": [ + { + _attr: { + "w:fldCharType": "end", + }, + }, + ], + }, + ], +}; diff --git a/src/file/paragraph/run/sequential-identifier.ts b/src/file/paragraph/run/sequential-identifier.ts new file mode 100644 index 0000000000..5536eca4ae --- /dev/null +++ b/src/file/paragraph/run/sequential-identifier.ts @@ -0,0 +1,13 @@ +import { Run } from "file/paragraph/run"; +import { Begin, End, Separate } from "file/paragraph/run/field"; +import { SequentialIdentifierInstruction } from "./sequential-identifier-instruction"; + +export class SequentialIdentifier extends Run { + constructor(identifier: string) { + super(); + this.root.push(new Begin(true)); + this.root.push(new SequentialIdentifierInstruction(identifier)); + this.root.push(new Separate()); + this.root.push(new End()); + } +}