Compare commits

..

62 Commits

Author SHA1 Message Date
a54c2714db Version bump 2019-08-08 02:01:22 +01:00
ad4a843a1e Update README.md 2019-08-08 01:56:31 +01:00
183062a977 Update README.md 2019-08-08 01:55:48 +01:00
e685da8cc2 Add more Used by logos 2019-08-08 01:52:20 +01:00
eea38a6709 Merge pull request #373 from dolanmiu/feat/declaritive
Static Packer
2019-08-08 01:06:00 +01:00
9fdd07e7fe Fix tests 2019-08-07 22:27:44 +01:00
d8b60d82f3 Turn Packer static 2019-08-07 22:12:14 +01:00
629e6a5095 Merge pull request #336 from dolanmiu/feat/declaritive
New declaritive API
2019-08-06 23:34:40 +01:00
65c5177daf Fix demo paths 2019-08-06 23:28:12 +01:00
b741db3050 Using a better demo naming system 2019-08-06 23:08:21 +01:00
82fef4c2b1 Fix tests 2019-08-06 22:27:16 +01:00
e45e7ffe06 Consolidate highlight and shadow API 2019-08-06 21:37:33 +01:00
099eb1d202 Merge branch 'master' of github.com:dolanmiu/docx into feat/declaritive
# Conflicts:
#	src/file/paragraph/run/run.ts
2019-08-06 21:06:06 +01:00
9da9f31c77 Change text documentation 2019-08-06 18:27:00 +01:00
820e5edc1e Using const rather than var and let, and using ts rather than js examples 2019-08-06 17:51:13 +01:00
0f1f398e6d Amended images documentation 2019-08-06 17:48:07 +01:00
b5503e7b9b Add documentation for AlignmentType 2019-08-06 17:36:05 +01:00
5a005365b2 Add more documentation 2019-08-06 17:15:45 +01:00
2a5e3729e0 Merge pull request #371 from mforman1/Highlighting
Add Highlight and Shading to the properties
2019-08-06 12:47:34 +01:00
ebc7dca949 Fix tests 2019-08-06 13:39:05 +03:00
fa710d1ba6 Highlighting 2019-08-06 11:13:43 +03:00
4b19131dbd Add description about sections 2019-08-06 00:52:50 +01:00
cb699e17b3 Paragraph documentation 2019-08-05 23:24:43 +01:00
c2c05b0140 Adding some documentation 2019-08-03 13:42:24 +01:00
3263984f03 Merge pull request #370 from wainstead/master
Removed artifact left over from (likely) the patch program
2019-08-03 13:41:38 +01:00
6f6f1e249c Removed artifact left over from (likely) the patch program 2019-08-01 11:12:07 -04:00
6380b2d8f3 Merge pull request #363 from moritz-tr/fix/create-document-from-template
fix: docx generation from template
2019-08-01 14:26:41 +01:00
9938a8bcc0 Fix linting 2019-07-31 08:48:25 +01:00
ac5b15d0e3 Mandatory Sections 2019-07-31 08:48:02 +01:00
ec5a678f05 fix: multiple def of header/footer attributes 2019-07-22 17:36:13 +02:00
bf80311ef7 Add new section method 2019-07-07 20:23:42 +01:00
58346a8937 Section WIP 2019-07-07 03:54:29 +01:00
f33d6da65a Merge branch 'master' into feat/declaritive
# Conflicts:
#	src/file/paragraph/formatting/border.spec.ts
#	src/file/paragraph/links/outline-level.spec.ts
#	src/file/paragraph/run/run.spec.ts
2019-07-02 01:33:41 +01:00
9e8d67c4a9 Version bump 2019-06-28 01:59:18 +01:00
cbbc4a80e7 FIx up API for column count 2019-06-28 01:57:43 +01:00
1f51fd7a31 Remove usage of Utility 2019-06-27 01:35:58 +01:00
120d97bc64 Remove Utility 2019-06-27 01:10:39 +01:00
a531713214 Remove usage of Utility class 2019-06-26 22:12:18 +01:00
564a055316 Remove jsonify method 2019-06-26 02:11:43 +01:00
6c29c4fb1f Merge pull request #343 from markcharyk/no-pretty-xml
Make prettified XML a Packer-wide configurable option
2019-06-26 00:44:33 +01:00
edbb4ce9f2 Merge branch 'master' into feat/declaritive 2019-06-26 00:38:21 +01:00
e2574ec23b Turn methods into "add()" 2019-06-25 23:17:56 +01:00
3ef8f5311d Make fixed layout declaritive 2019-06-25 20:57:46 +01:00
552580bc47 Merge pull request #340 from filippomuscolino/feat/row-height
Add table row height
2019-06-25 20:18:17 +01:00
0998d43b8f Merge pull request #341 from filippomuscolino/fix/missing-exports
Fix: add missing exports
2019-06-25 15:38:13 +01:00
b08354494c Improve tests 2019-06-25 14:48:45 +02:00
f54b9a197d Fix: add missing exports 2019-06-25 14:35:35 +02:00
2d4412ce51 Add table row height 2019-06-25 12:02:53 +02:00
b566b0f765 Simplify multiple addXXX methods into a single add method for Footer 2019-06-25 01:58:09 +01:00
384d144a85 Simplify multiple addXXX methods into a single add method 2019-06-25 01:52:02 +01:00
c97d15cb9f Remove create table helper function 2019-06-25 01:21:28 +01:00
dfe986331d Make media return a picture run instead 2019-06-23 22:36:01 +01:00
72c32378c5 Make prettified XML a Packer-wide configurable option
The xml() function was being passed a flag for pretty printing the XML in word/document.xml. This was causing some parsers (not Word itself) to break when they didn't expect whitepsace. It was also causing some files to be prettified and others to be ugly. This ensures consistent prettification.
2019-06-21 13:53:01 -07:00
0c79c0ac83 Merge pull request #337 from zahrafali/multiple-columns
Multiple columns in a section
2019-06-21 15:36:33 +01:00
1dfc27ba08 Multiple columns in a section 2019-06-21 01:22:27 +05:30
427dc86915 Fix demos 2019-06-17 01:54:48 +01:00
7bc00926eb Merge branch 'master' of github.com:dolanmiu/docx into feat/declaritive 2019-06-17 01:52:46 +01:00
fb65bb4207 Turn Run into a declaritive API 2019-06-17 01:51:57 +01:00
a1cd5e9573 Use new Paragraph API 2019-06-13 22:36:42 +01:00
5497dabaf9 Deprecate createParagraph in all demos 2019-06-13 01:07:00 +01:00
58dc6fe389 Format demo 2019-06-12 01:12:32 +01:00
cb42c74a8d Make Paragraph declaritive 2019-06-12 01:03:36 +01:00
183 changed files with 4413 additions and 3481 deletions

View File

@ -9,43 +9,43 @@ script:
- npm run test.coverage - npm run test.coverage
- npm run style - npm run style
- npm run build - npm run build
- npm run ts-node -- ./demo/demo1.ts - npm run ts-node -- ./demo/1-basic.ts
- npm run e2e "My Document.docx" - npm run e2e "My Document.docx"
- npm run ts-node -- ./demo/demo2.ts - npm run ts-node -- ./demo/2-declaritive-styles.ts
- npm run ts-node -- ./demo/demo3.ts - npm run ts-node -- ./demo/3-numbering-and-bullet-points.ts
- npm run ts-node -- ./demo/demo4.ts - npm run ts-node -- ./demo/4-basic-table.ts
- npm run ts-node -- ./demo/demo5.ts - npm run ts-node -- ./demo/5-images.ts
- npm run ts-node -- ./demo/demo6.ts - npm run ts-node -- ./demo/6-page-borders.ts
- npm run ts-node -- ./demo/demo7.ts - npm run ts-node -- ./demo/7-landscape.ts
- npm run ts-node -- ./demo/demo8.ts - npm run ts-node -- ./demo/8-header-footer.ts
- npm run ts-node -- ./demo/demo9.ts - npm run ts-node -- ./demo/9-images-in-header-and-footer.ts
- npm run ts-node -- ./demo/demo10.ts - npm run ts-node -- ./demo/10-my-cv.ts
- npm run e2e "My Document.docx" - npm run e2e "My Document.docx"
- npm run ts-node -- ./demo/demo11.ts - npm run ts-node -- ./demo/11-declaritive-styles-2.ts
- npm run ts-node -- ./demo/demo12.ts - npm run ts-node -- ./demo/12-scaling-images.ts
- npm run ts-node -- ./demo/demo13.ts - npm run ts-node -- ./demo/13-xml-styles.ts
- npm run ts-node -- ./demo/demo14.ts - npm run ts-node -- ./demo/14-page-numbers.ts
- npm run ts-node -- ./demo/demo15.ts - npm run ts-node -- ./demo/15-page-break-before.ts
- npm run ts-node -- ./demo/demo16.ts - npm run ts-node -- ./demo/16-multiple-sections.ts
- npm run ts-node -- ./demo/demo17.ts - npm run ts-node -- ./demo/17-footnotes.ts
- npm run ts-node -- ./demo/demo18.ts - npm run ts-node -- ./demo/18-image-from-buffer.ts
- npm run ts-node -- ./demo/demo19.ts - npm run ts-node -- ./demo/19-export-to-base64.ts
- npm run ts-node -- ./demo/demo20.ts - npm run ts-node -- ./demo/20-table-cell-borders.ts
- npm run ts-node -- ./demo/demo21.ts - npm run ts-node -- ./demo/21-bookmarks.ts
- npm run ts-node -- ./demo/demo22.ts - npm run ts-node -- ./demo/22-right-to-left-text.ts
- npm run ts-node -- ./demo/demo23.ts - npm run ts-node -- ./demo/23-base64-images.ts
- npm run ts-node -- ./demo/demo24.ts - npm run ts-node -- ./demo/24-images-to-table-cell.ts
# - npm run ts-node -- ./demo/demo25.ts # - npm run ts-node -- ./demo/demo25.ts
- npm run ts-node -- ./demo/demo26.ts - npm run ts-node -- ./demo/26-paragraph-borders.ts
- npm run ts-node -- ./demo/demo27.ts - npm run ts-node -- ./demo/27-declaritive-styles-3.ts
- npm run ts-node -- ./demo/demo28.ts - npm run ts-node -- ./demo/28-table-of-contents.ts
- npm run ts-node -- ./demo/demo29.ts - npm run ts-node -- ./demo/29-numbered-lists.ts
- npm run ts-node -- ./demo/demo30.ts - npm run ts-node -- ./demo/30-template-document.ts
- npm run ts-node -- ./demo/demo31.ts - npm run ts-node -- ./demo/31-tables.ts
- npm run ts-node -- ./demo/demo32.ts - npm run ts-node -- ./demo/32-merge-table-cells.ts
# - npm run e2e "My Document.docx" // Need to fix # - npm run e2e "My Document.docx" // Need to fix
- npm run ts-node -- ./demo/demo33.ts - npm run ts-node -- ./demo/33-sequential-captions.ts
- npm run ts-node -- ./demo/demo34.ts - npm run ts-node -- ./demo/34-floating-tables.ts
after_failure: after_failure:
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log" - "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
after_success: after_success:

View File

@ -66,9 +66,15 @@ Read the contribution guidelines [here](https://docx.js.org/#/contribution-guide
# Used by # Used by
[<img src="https://i.imgur.com/zy5qWmI.png" alt="drawing" height="200"/>](https://hfour.com/) [<img src="https://i.imgur.com/zy5qWmI.png" alt="drawing" height="50"/>](https://hfour.com/)
[<img src="https://i.imgur.com/OYP5tgS.png" alt="drawing" height="200"/>](https://fuzzproductions.com/) [<img src="https://i.imgur.com/OYP5tgS.png" alt="drawing" height="50"/>](https://fuzzproductions.com/)
[<img src="https://i.imgur.com/zUDMfZ3.png" alt="drawing" height="200"/>](https://www.mettzer.com/) [<img src="https://i.imgur.com/zUDMfZ3.png" alt="drawing" height="50"/>](https://www.mettzer.com/)
[<img src="https://i.imgur.com/wtNB1uq.png" alt="drawing" height="50"/>](https://www.wisedoc.net/)
[<img src="https://i.imgur.com/suiH2zc.png" alt="drawing" height="50"/>](https://www.dabblewriter.com/)
[<img src="https://i.imgur.com/1LjuK2M.png" alt="drawing" height="50"/>](https://turbopatent.com/)
[<img src="https://i.imgur.com/dHMg0wF.gif" alt="drawing" height="50"/>](http://www.madisoncres.com/)
...and many more!
--- ---

29
demo/1-basic.ts Normal file
View File

@ -0,0 +1,29 @@
// Simple example to add text to a document
// 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();
doc.addSection({
properties: {},
children: [
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
text: "Foo Bar",
bold: true,
}),
new TextRun({
text: "Github is the best",
bold: true,
}).tab(),
],
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,7 +1,7 @@
// Generate a CV // Generate a CV
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, TextRun } from "../build"; import { AlignmentType, Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build";
// tslint:disable:no-shadowed-variable // tslint:disable:no-shadowed-variable
@ -127,150 +127,165 @@ const achievements = [
]; ];
class DocumentCreator { class DocumentCreator {
public create(data: object[]): Document { // tslint:disable-next-line: typedef
// tslint:disable-next-line:no-any public create([experiences, educations, skills, achivements]): Document {
const experiences = data[0] as any[];
// tslint:disable-next-line:no-any
const educations = data[1] as any[];
const skills = data[2] as object[];
const achivements = data[3] as object[];
const document = new Document(); const document = new Document();
document.addParagraph(new Paragraph("Dolan Miu").title());
document.addParagraph(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL)); document.addSection({
document.addParagraph(this.createHeading("Education")); children: [
new Paragraph({
text: "Dolan Miu",
heading: HeadingLevel.TITLE,
}),
this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL),
this.createHeading("Education"),
...educations
.map((education) => {
const arr: Paragraph[] = [];
arr.push(
this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`),
);
arr.push(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`));
for (const education of educations) { const bulletPoints = this.splitParagraphIntoBullets(education.notes);
document.addParagraph( bulletPoints.forEach((bulletPoint) => {
this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`), arr.push(this.createBullet(bulletPoint));
); });
document.addParagraph(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`));
const bulletPoints = this.splitParagraphIntoBullets(education.notes); return arr;
bulletPoints.forEach((bulletPoint) => { })
document.addParagraph(this.createBullet(bulletPoint)); .reduce((prev, curr) => prev.concat(curr), []),
}); this.createHeading("Experience"),
} ...experiences
.map((position) => {
const arr: Paragraph[] = [];
document.addParagraph(this.createHeading("Experience")); arr.push(
this.createInstitutionHeader(
position.company.name,
this.createPositionDateText(position.startDate, position.endDate, position.isCurrent),
),
);
arr.push(this.createRoleText(position.title));
for (const position of experiences) { const bulletPoints = this.splitParagraphIntoBullets(position.summary);
document.addParagraph(
this.createInstitutionHeader( bulletPoints.forEach((bulletPoint) => {
position.company.name, arr.push(this.createBullet(bulletPoint));
this.createPositionDateText(position.startDate, position.endDate, position.isCurrent), });
return arr;
})
.reduce((prev, curr) => prev.concat(curr), []),
this.createHeading("Skills, Achievements and Interests"),
this.createSubHeading("Skills"),
this.createSkillList(skills),
this.createSubHeading("Achievements"),
...this.createAchivementsList(achivements),
this.createSubHeading("Interests"),
this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing."),
this.createHeading("References"),
new Paragraph(
"Dr. Dean Mohamedally Director of Postgraduate Studies Department of Computer Science, University College London Malet Place, Bloomsbury, London WC1E d.mohamedally@ucl.ac.uk",
), ),
); new Paragraph("More references upon request"),
document.addParagraph(this.createRoleText(position.title)); new Paragraph({
text: "This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.",
alignment: AlignmentType.CENTER,
}),
],
});
const bulletPoints = this.splitParagraphIntoBullets(position.summary);
bulletPoints.forEach((bulletPoint) => {
document.addParagraph(this.createBullet(bulletPoint));
});
}
document.addParagraph(this.createHeading("Skills, Achievements and Interests"));
document.addParagraph(this.createSubHeading("Skills"));
document.addParagraph(this.createSkillList(skills));
document.addParagraph(this.createSubHeading("Achievements"));
for (const achievementParagraph of this.createAchivementsList(achivements)) {
document.addParagraph(achievementParagraph);
}
document.addParagraph(this.createSubHeading("Interests"));
document.addParagraph(this.createInterests("Programming, Technology, Music Production, Web Design, 3D Modelling, Dancing."));
document.addParagraph(this.createHeading("References"));
document.addParagraph(
new Paragraph(
"Dr. Dean Mohamedally Director of Postgraduate Studies Department of Computer Science, University College London Malet Place, Bloomsbury, London WC1E d.mohamedally@ucl.ac.uk",
),
);
document.addParagraph(new Paragraph("More references upon request"));
document.addParagraph(
new Paragraph(
"This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.",
).center(),
);
return document; return document;
} }
public createContactInfo(phoneNumber: string, profileUrl: string, email: string): Paragraph { public createContactInfo(phoneNumber: string, profileUrl: string, email: string): Paragraph {
const paragraph = new Paragraph().center(); return new Paragraph({
const contactInfo = new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`); alignment: AlignmentType.CENTER,
const address = new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(); children: [
new TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`),
paragraph.addRun(contactInfo); new TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break(),
paragraph.addRun(address); ],
});
return paragraph;
} }
public createHeading(text: string): Paragraph { public createHeading(text: string): Paragraph {
return new Paragraph(text).heading1().thematicBreak(); return new Paragraph({
text: text,
heading: HeadingLevel.HEADING_1,
thematicBreak: true,
});
} }
public createSubHeading(text: string): Paragraph { public createSubHeading(text: string): Paragraph {
return new Paragraph(text).heading2(); return new Paragraph({
text: text,
heading: HeadingLevel.HEADING_2,
});
} }
public createInstitutionHeader(institutionName: string, dateText: string): Paragraph { public createInstitutionHeader(institutionName: string, dateText: string): Paragraph {
const paragraph = new Paragraph().maxRightTabStop(); return new Paragraph({
const institution = new TextRun(institutionName).bold(); tabStop: {
const date = new TextRun(dateText).tab().bold(); maxRight: {},
},
paragraph.addRun(institution); children: [
paragraph.addRun(date); new TextRun({
text: institutionName,
return paragraph; bold: true,
}),
new TextRun({
text: dateText,
bold: true,
}).tab(),
],
});
} }
public createRoleText(roleText: string): Paragraph { public createRoleText(roleText: string): Paragraph {
const paragraph = new Paragraph(); return new Paragraph({
const role = new TextRun(roleText).italics(); children: [
new TextRun({
paragraph.addRun(role); text: roleText,
italics: true,
return paragraph; }),
],
});
} }
public createBullet(text: string): Paragraph { public createBullet(text: string): Paragraph {
return new Paragraph(text).bullet(); return new Paragraph({
text: text,
bullet: {
level: 0,
},
});
} }
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
public createSkillList(skills: any[]): Paragraph { public createSkillList(skills: any[]): Paragraph {
const paragraph = new Paragraph(); return new Paragraph({
const skillConcat = skills.map((skill) => skill.name).join(", ") + "."; children: [new TextRun(skills.map((skill) => skill.name).join(", ") + ".")],
});
paragraph.addRun(new TextRun(skillConcat));
return paragraph;
} }
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
public createAchivementsList(achivements: any[]): Paragraph[] { public createAchivementsList(achivements: any[]): Paragraph[] {
const arr: Paragraph[] = []; return achivements.map(
(achievement) =>
for (const achievement of achivements) { new Paragraph({
const paragraph = new Paragraph(achievement.name).bullet(); text: achievement.name,
arr.push(paragraph); bullet: {
} level: 0,
},
return arr; }),
);
} }
public createInterests(interests: string): Paragraph { public createInterests(interests: string): Paragraph {
const paragraph = new Paragraph(); return new Paragraph({
children: [new TextRun(interests)],
paragraph.addRun(new TextRun(interests)); });
return paragraph;
} }
public splitParagraphIntoBullets(text: string): string[] { public splitParagraphIntoBullets(text: string): string[] {
@ -321,8 +336,6 @@ const documentCreator = new DocumentCreator();
const doc = documentCreator.create([experiences, education, skills, achievements]); const doc = documentCreator.create([experiences, education, skills, achievements]);
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -1,14 +1,9 @@
// Setting styles with JavaScript configuration // Setting styles with JavaScript configuration
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, Table } from "../build"; import { AlignmentType, Document, Footer, HeadingLevel, Media, Packer, Paragraph, Table } from "../build";
const doc = new Document(undefined, { const doc = new Document();
top: 700,
right: 700,
bottom: 700,
left: 700,
});
doc.Styles.createParagraphStyle("Heading1", "Heading 1") doc.Styles.createParagraphStyle("Heading1", "Heading 1")
.basedOn("Normal") .basedOn("Normal")
@ -83,28 +78,7 @@ doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph")
.quickFormat() .quickFormat()
.basedOn("Normal"); .basedOn("Normal");
doc.createImage(fs.readFileSync("./demo/images/pizza.gif")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
doc.createParagraph("HEADING")
.heading1()
.center();
doc.Footer.createParagraph("1")
.style("normalPara")
.right();
doc.createParagraph("Ref. :").style("normalPara");
doc.createParagraph("Date :").style("normalPara");
doc.createParagraph("To,").style("normalPara");
doc.createParagraph("The Superindenting Engineer,(O &M)").style("normalPara");
doc.createParagraph("Sub : ").style("normalPara");
doc.createParagraph("Ref. : ").style("normalPara");
doc.createParagraph("Sir,").style("normalPara");
doc.createParagraph("BRIEF DESCRIPTION").style("normalPara");
const table = new Table({ const table = new Table({
rows: 4, rows: 4,
@ -113,28 +87,82 @@ const table = new Table({
table table
.getRow(0) .getRow(0)
.getCell(0) .getCell(0)
.addParagraph(new Paragraph("Pole No.")); .add(new Paragraph("Pole No."));
doc.addTable(table); const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const arrboth = [ doc.addSection({
{ properties: {
image: "./demo/images/pizza.gif", top: 700,
comment: "Test", right: 700,
bottom: 700,
left: 700,
}, },
{ footers: {
image: "./demo/images/pizza.gif", default: new Footer({
comment: "Test 2", children: [
new Paragraph({
text: "1",
style: "normalPara",
alignment: AlignmentType.RIGHT,
}),
],
}),
}, },
]; children: [
new Paragraph(image),
arrboth.forEach((item) => { new Paragraph({
doc.createImage(fs.readFileSync(item.image)); text: "HEADING",
doc.createParagraph(item.comment).style("normalPara2"); heading: HeadingLevel.HEADING_1,
alignment: AlignmentType.CENTER,
}),
new Paragraph({
text: "Ref. :",
style: "normalPara",
}),
new Paragraph({
text: "Date :",
style: "normalPara",
}),
new Paragraph({
text: "To,",
style: "normalPara",
}),
new Paragraph({
text: "The Superindenting Engineer,(O &M)",
style: "normalPara",
}),
new Paragraph({
text: "Sub : ",
style: "normalPara",
}),
new Paragraph({
text: "Ref. : ",
style: "normalPara",
}),
new Paragraph({
text: "Sir,",
style: "normalPara",
}),
new Paragraph({
text: "BRIEF DESCRIPTION",
style: "normalPara",
}),
table,
new Paragraph(image1),
new Paragraph({
text: "Test",
style: "normalPara2",
}),
new Paragraph(image2),
new Paragraph({
text: "Test 2",
style: "normalPara2",
}),
],
}); });
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

19
demo/12-scaling-images.ts Normal file
View File

@ -0,0 +1,19 @@
// Scaling images
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Media, Packer, Paragraph } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 50, 50);
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 100, 100);
const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 250, 250);
const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 400, 400);
doc.addSection({
children: [new Paragraph("Hello World"), new Paragraph(image), new Paragraph(image2), new Paragraph(image3), new Paragraph(image4)],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

32
demo/13-xml-styles.ts Normal file
View File

@ -0,0 +1,32 @@
// This example shows 3 styles using XML styles
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph } from "../build";
const styles = fs.readFileSync("./demo/assets/custom-styles.xml", "utf-8");
const doc = new Document({
title: "Title",
externalStyles: styles,
});
doc.addSection({
children: [
new Paragraph({
text: "Cool Heading Text",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph({
text: 'This is a custom named style from the template "MyFancyStyle"',
style: "MyFancyStyle",
}),
new Paragraph("Some normal text"),
new Paragraph({
text: "MyFancyStyle again",
style: "MyFancyStyle",
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

37
demo/14-page-numbers.ts Normal file
View File

@ -0,0 +1,37 @@
// Page numbers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, Document, Header, Packer, 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("Page ").pageNumber()],
}),
],
}),
first: new Header({
children: [
new Paragraph({
alignment: AlignmentType.RIGHT,
children: [new TextRun("First Page Header "), new TextRun("Page ").pageNumber()],
}),
],
}),
},
children: [
new Paragraph({
text: "First Page",
}).pageBreak(),
new Paragraph("Second Page"),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -5,14 +5,16 @@ import { Document, Packer, Paragraph } from "../build";
const doc = new Document(); const doc = new Document();
const paragraph = new Paragraph("Hello World"); doc.addSection({
const paragraph2 = new Paragraph("Hello World on another page").pageBreakBefore(); children: [
new Paragraph("Hello World"),
new Paragraph({
text: "Hello World on another page",
pageBreakBefore: true,
}),
],
});
doc.addParagraph(paragraph); Packer.toBuffer(doc).then((buffer) => {
doc.addParagraph(paragraph2);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,112 @@
// Multiple sections and headers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Footer, Header, Packer, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
const doc = new Document();
doc.addSection({
children: [new Paragraph("Hello World").pageBreak()],
});
doc.addSection({
headers: {
default: new Header({
children: [new Paragraph("First Default Header on another page")],
}),
},
footers: {
default: new Footer({
children: [new Paragraph("Footer on another page")],
}),
},
properties: {
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
},
children: [new Paragraph("hello")],
});
doc.addSection({
headers: {
default: new Header({
children: [new Paragraph("Second Default Header on another page")],
}),
},
footers: {
default: new Footer({
children: [new Paragraph("Footer on another page")],
}),
},
size: {
orientation: PageOrientation.LANDSCAPE,
},
properties: {
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
},
children: [new Paragraph("hello in landscape")],
});
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
children: [new TextRun("Page number: ").pageNumber()],
}),
],
}),
},
size: {
orientation: PageOrientation.PORTRAIT,
},
children: [new Paragraph("Page number in the header must be 2, because it continues from the previous section.")],
});
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
children: [new TextRun("Page number: ").pageNumber()],
}),
],
}),
},
properties: {
pageNumberFormatType: PageNumberFormat.UPPER_ROMAN,
orientation: PageOrientation.PORTRAIT,
},
children: [
new Paragraph(
"Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.",
),
],
});
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
children: [new TextRun("Page number: ").pageNumber()],
}),
],
}),
},
size: {
orientation: PageOrientation.PORTRAIT,
},
properties: {
pageNumberFormatType: PageNumberFormat.DECIMAL,
pageNumberStart: 25,
},
children: [
new Paragraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section."),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -5,17 +5,13 @@ import { Document, Packer, Paragraph } from "../build";
const doc = new Document(); const doc = new Document();
const paragraph = new Paragraph("Hello World").referenceFootnote(1); doc.addSection({
const paragraph2 = new Paragraph("Hello World").referenceFootnote(2); children: [new Paragraph("Hello World").referenceFootnote(1), new Paragraph("Hello World").referenceFootnote(2)],
});
doc.addParagraph(paragraph);
doc.addParagraph(paragraph2);
doc.createFootnote(new Paragraph("Test")); doc.createFootnote(new Paragraph("Test"));
doc.createFootnote(new Paragraph("My amazing reference")); doc.createFootnote(new Paragraph("My amazing reference"));
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -1,17 +1,22 @@
// Insert image from a buffer // Insert image from a buffer
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer } from "../build"; import { Document, Media, Packer, Paragraph } from "../build";
const doc = new Document(); const doc = new Document();
const imageBase64Data = `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`; const imageBase64Data = `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`;
// doc.createImage(Buffer.from(imageBase64Data, 'base64')); const image = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100);
doc.createImage(Buffer.from(imageBase64Data, "base64"), 100, 100);
const packer = new Packer(); doc.addSection({
children: [
new Paragraph({
children: [image],
}),
],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,28 @@
// Export to base64 string - Useful in a browser environment.
// 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();
doc.addSection({
children: [
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
text: "Foo",
bold: true,
}),
new TextRun({
text: "Bar",
bold: true,
}).tab(),
],
}),
],
});
Packer.toBase64String(doc).then((str) => {
fs.writeFileSync("My Document.docx", str);
});

View File

@ -0,0 +1,122 @@
// Example on how to customise the look at feel using Styles
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build";
const doc = new Document({
creator: "Clippy",
title: "Sample Document",
description: "A brief example of using docx",
});
doc.Styles.createParagraphStyle("Heading1", "Heading 1")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(28)
.bold()
.italics()
.spacing({ after: 120 });
doc.Styles.createParagraphStyle("Heading2", "Heading 2")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26)
.bold()
.underline("double", "FF0000")
.spacing({ before: 240, after: 120 });
doc.Styles.createParagraphStyle("aside", "Aside")
.basedOn("Normal")
.next("Normal")
.color("999999")
.italics()
.indent({ left: 720 })
.spacing({ line: 276 });
doc.Styles.createParagraphStyle("wellSpaced", "Well Spaced")
.basedOn("Normal")
.spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 });
doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph")
.quickFormat()
.basedOn("Normal");
const numberedAbstract = doc.Numbering.createAbstractNumbering();
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract);
const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract);
letterNumbering5.overrideLevel(0, 5);
doc.addSection({
children: [
new Paragraph({
text: "Test heading1, bold and italicized",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph("Some simple content"),
new Paragraph({
text: "Test heading2 with double red underline",
heading: HeadingLevel.HEADING_2,
}),
new Paragraph({
text: "Option1",
numbering: {
num: letterNumbering,
level: 0,
},
}),
new Paragraph({
text: "Option5 -- override 2 to 5",
numbering: {
num: letterNumbering,
level: 0,
},
}),
new Paragraph({
text: "Option3",
numbering: {
num: letterNumbering,
level: 0,
},
}),
new Paragraph({}).addRun(
new TextRun({
text: "Some monospaced content",
font: {
name: "Monospace",
},
}),
),
new Paragraph({
text: "An aside, in light gray italics and indented",
style: "aside",
}),
new Paragraph({
text: "This is normal, but well-spaced text",
style: "wellSpaced",
}),
new Paragraph({
children: [
new TextRun({
text: "This is a bold run,",
bold: true,
}),
new TextRun(" switching to normal "),
new TextRun({
text: "and then underlined ",
underline: {},
}),
new TextRun({
text: "and back to normal.",
}),
],
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,24 +1,24 @@
// Add custom borders to table cell // Add custom borders to table cell
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { BorderStyle, Document, Packer, Paragraph } from "../build"; import { BorderStyle, Document, Packer, Paragraph, Table } from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 4, rows: 4,
columns: 4, columns: 4,
}); });
doc.addSection({ children: [table] });
table table
.getCell(2, 2) .getCell(2, 2)
.addParagraph(new Paragraph("Hello")) .add(new Paragraph("Hello"))
.Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red") .Borders.addTopBorder(BorderStyle.DASH_DOT_STROKED, 3, "red")
.addBottomBorder(BorderStyle.DOUBLE, 3, "blue") .addBottomBorder(BorderStyle.DOUBLE, 3, "blue")
.addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green") .addStartBorder(BorderStyle.DOT_DOT_DASH, 3, "green")
.addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000"); .addEndBorder(BorderStyle.DOT_DOT_DASH, 3, "#ff8000");
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -1,9 +1,9 @@
// This demo shows how to create bookmarks then link to them with internal hyperlinks // This demo shows how to create bookmarks then link to them with internal hyperlinks
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer } from "../build"; import { Document, HeadingLevel, Packer, Paragraph } from "../build";
const loremIpsum = const LOREM_IPSUM =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante."; "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante.";
const doc = new Document({ const doc = new Document({
@ -16,22 +16,20 @@ const anchorId = "anchorID";
// First create the bookmark // First create the bookmark
const bookmark = doc.createBookmark(anchorId, "Lorem Ipsum"); const bookmark = doc.createBookmark(anchorId, "Lorem Ipsum");
// That has header styling
doc
.createParagraph()
.addBookmark(bookmark)
.heading1();
doc.createParagraph("\n");
doc.createParagraph(loremIpsum);
doc.createParagraph().pageBreak();
// Now the link back up to the bookmark
const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`); const hyperlink = doc.createInternalHyperLink(anchorId, `Click me!`);
doc.createParagraph().addHyperLink(hyperlink);
const packer = new Packer(); doc.addSection({
children: [
new Paragraph({
heading: HeadingLevel.HEADING_1,
}).addBookmark(bookmark),
new Paragraph("\n"),
new Paragraph(LOREM_IPSUM),
new Paragraph({}).pageBreak(),
new Paragraph({}).addHyperLink(hyperlink),
],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,44 @@
// This demo shows right to left for special languages
// 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();
doc.addSection({
children: [
new Paragraph({
bidirectional: true,
children: [
new TextRun({
text: "שלום עולם",
rightToLeft: true,
}),
],
}),
new Paragraph({
bidirectional: true,
children: [
new TextRun({
text: "שלום עולם",
bold: true,
rightToLeft: true,
}),
],
}),
new Paragraph({
bidirectional: true,
children: [
new TextRun({
text: "שלום עולם",
italics: true,
rightToLeft: true,
}),
],
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,13 +1,10 @@
// This demo adds an image to the Media cache, and then insert to the document afterwards // This demo adds an image to the Media cache, and then insert to the document afterwards
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Media, Packer, Paragraph } from "../build"; import { Document, Media, Packer, Paragraph, TextRun } from "../build";
const doc = new Document(); const doc = new Document();
const paragraph = new Paragraph("Hello World");
doc.addParagraph(paragraph);
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png")); const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png"));
const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg")); const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"));
@ -17,18 +14,19 @@ const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const imageBase64Data = `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`; const imageBase64Data = `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`;
const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100); const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100);
// I am adding an image to the paragraph rather than the document to make the image inline doc.addSection({
paragraph.addImage(image5); children: [
new Paragraph({
children: [new TextRun("Hello World"), image5],
}),
new Paragraph(image),
new Paragraph(image2),
new Paragraph(image3),
new Paragraph(image4),
new Paragraph(image6),
],
});
doc.addImage(image); Packer.toBuffer(doc).then((buffer) => {
doc.addImage(image2);
doc.addImage(image3);
doc.addImage(image4);
doc.addImage(image5);
doc.addImage(image6);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -1,21 +1,24 @@
// Add image to table cell // Add image to table cell
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Media, Packer, Paragraph } from "../build"; import { Document, Media, Packer, Paragraph, Table } from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 4, rows: 4,
columns: 4, columns: 4,
}); });
table.getCell(2, 2).addParagraph(new Paragraph("Hello"));
doc.addSection({
children: [table],
});
table.getCell(2, 2).add(new Paragraph("Hello"));
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
table.getCell(1, 1).addParagraph(image.Paragraph); table.getCell(1, 1).add(new Paragraph(image));
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,33 @@
// Creates two paragraphs, one with a border and one without
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
doc.addSection({
children: [
new Paragraph("No border!"),
new Paragraph({
text: "I have borders on my top and bottom sides!",
border: {
top: {
color: "auto",
space: 1,
value: "single",
size: 6,
},
bottom: {
color: "auto",
space: 1,
value: "single",
size: 6,
},
},
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,42 @@
// Custom styles using JavaScript configuration
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph } from "../build";
const doc = new Document();
// The first argument is an ID you use to apply the style to paragraphs
// The second argument is a human-friendly name to show in the UI
doc.Styles.createParagraphStyle("myWonkyStyle", "My Wonky Style")
.basedOn("Normal")
.next("Normal")
.color("990000")
.italics()
.indent({ left: 720 }) // 720 TWIP === 720 / 20 pt === .5 in
.spacing({ line: 276 }); // 276 / 240 = 1.15x line spacing
doc.Styles.createParagraphStyle("Heading2", "Heading 2")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26) // 26 half-points === 13pt font
.bold()
.underline("double", "FF0000")
.spacing({ before: 240, after: 120 }); // TWIP for both
doc.addSection({
children: [
new Paragraph({
text: "Hello",
style: "myWonkyStyle",
}),
new Paragraph({
text: "World",
heading: HeadingLevel.HEADING_2,
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,56 @@
// Table of contents
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } from "../build";
const doc = new File();
// The first argument is an ID you use to apply the style to paragraphs
// The second argument is a human-friendly name to show in the UI
doc.Styles.createParagraphStyle("MySpectacularStyle", "My Spectacular Style")
.basedOn("Heading1")
.next("Heading1")
.color("990000")
.italics();
// WordprocessingML docs for TableOfContents can be found here:
// http://officeopenxml.com/WPtableOfContents.php
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
// making the entries be hyperlinks for the paragraph
doc.addSection({
children: [
new TableOfContents("Summary", {
hyperlink: true,
headingStyleRange: "1-5",
stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)],
}),
new Paragraph({
text: "Header #1",
heading: HeadingLevel.HEADING_1,
pageBreakBefore: true,
}),
new Paragraph("I'm a little text very nicely written.'"),
new Paragraph({
text: "Header #2",
heading: HeadingLevel.HEADING_1,
pageBreakBefore: true,
}),
new Paragraph("I'm a other text very nicely written.'"),
new Paragraph({
text: "Header #2.1",
heading: HeadingLevel.HEADING_2,
}),
new Paragraph("I'm a another text very nicely written.'"),
new Paragraph({
text: "My Spectacular Style #1",
style: "MySpectacularStyle",
pageBreakBefore: true,
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

66
demo/29-numbered-lists.ts Normal file
View File

@ -0,0 +1,66 @@
// Numbered lists
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Numbering, Packer, Paragraph } from "../build";
const doc = new Document();
const numbering = new Numbering();
const abstractNum = numbering.createAbstractNumbering();
abstractNum.createLevel(0, "upperRoman", "%1", "start").indent({ left: 720, hanging: 260 });
const concrete = numbering.createConcreteNumbering(abstractNum);
doc.addSection({
children: [
new Paragraph({
text: "line with contextual spacing",
numbering: {
num: concrete,
level: 0,
},
contextualSpacing: true,
spacing: {
before: 200,
},
}),
new Paragraph({
text: "line with contextual spacing",
numbering: {
num: concrete,
level: 0,
},
contextualSpacing: true,
spacing: {
before: 200,
},
}),
new Paragraph({
text: "line without contextual spacing",
numbering: {
num: concrete,
level: 0,
},
contextualSpacing: false,
spacing: {
before: 200,
},
}),
new Paragraph({
text: "line without contextual spacing",
numbering: {
num: concrete,
level: 0,
},
contextualSpacing: false,
spacing: {
before: 200,
},
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,76 @@
// Numbering and bullet points example
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Numbering, Packer, Paragraph } from "../build";
const doc = new Document();
const numbering = new Numbering();
const abstractNum = numbering.createAbstractNumbering();
abstractNum.createLevel(0, "upperRoman", "%1", "start").indent({ left: 720, hanging: 260 });
abstractNum.createLevel(1, "decimal", "%2.", "start").indent({ left: 1440, hanging: 980 });
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").indent({ left: 14402160, hanging: 1700 });
const concrete = numbering.createConcreteNumbering(abstractNum);
doc.addSection({
children: [
new Paragraph({
text: "Hey you",
numbering: {
num: concrete,
level: 0,
},
}),
new Paragraph({
text: "What's up fam",
numbering: {
num: concrete,
level: 1,
},
}),
new Paragraph({
text: "Hello World 2",
numbering: {
num: concrete,
level: 1,
},
}),
new Paragraph({
text: "Yeah boi",
numbering: {
num: concrete,
level: 2,
},
}),
new Paragraph({
text: "Hey you",
bullet: {
level: 0,
},
}),
new Paragraph({
text: "What's up fam",
bullet: {
level: 1,
},
}),
new Paragraph({
text: "Hello World 2",
bullet: {
level: 2,
},
}),
new Paragraph({
text: "Yeah boi",
bullet: {
level: 3,
},
}),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -12,19 +12,18 @@ fs.readFile(filePath, (err, data) => {
} }
importDotx.extract(data).then((templateDocument) => { importDotx.extract(data).then((templateDocument) => {
// This any needs fixing const doc = new Document(undefined, {
const sectionProps = {
titlePage: templateDocument.titlePageIsDefined,
} as any;
const doc = new Document(undefined, sectionProps, {
template: templateDocument, template: templateDocument,
}); });
const paragraph = new Paragraph("Hello World");
doc.addParagraph(paragraph);
const packer = new Packer(); doc.addSection({
packer.toBuffer(doc).then((buffer) => { properties: {
titlePage: templateDocument.titlePageIsDefined,
},
children: [new Paragraph("Hello World")],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });
}); });

View File

@ -1,29 +1,32 @@
// Example of how you would create a table and add data to it // Example of how you would create a table and add data to it
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, VerticalAlign } from "../build"; import { Document, HeadingLevel, Packer, Paragraph, Table, VerticalAlign } from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 2, rows: 2,
columns: 2, columns: 2,
}); });
table table
.getCell(1, 1) .getCell(1, 1)
.addParagraph(new Paragraph("This text should be in the middle of the cell")) .add(new Paragraph("This text should be in the middle of the cell"))
.setVerticalAlign(VerticalAlign.CENTER); .setVerticalAlign(VerticalAlign.CENTER);
table table.getCell(1, 0).add(
.getCell(1, 0) new Paragraph({
.addParagraph( text:
new Paragraph(
"Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah", "Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah",
).heading1(), heading: HeadingLevel.HEADING_1,
); }),
);
const packer = new Packer(); doc.addSection({
children: [table],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -1,30 +1,29 @@
// Example of how you would merge cells together // Example of how you would merge cells together
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, ShadingType, WidthType } from "../build"; import { Document, HeadingLevel, Packer, Paragraph, ShadingType, Table, WidthType } from "../build";
const doc = new Document(); const doc = new Document();
let table = doc.createTable({ const table = new Table({
rows: 2, rows: 2,
columns: 2, columns: 2,
}); });
table.getCell(0, 0).addParagraph(new Paragraph("Hello")); table.getCell(0, 0).add(new Paragraph("Hello"));
table.getRow(0).mergeCells(0, 1); table.getRow(0).mergeCells(0, 1);
doc.createParagraph("Another table").heading2(); const table2 = new Table({
table = doc.createTable({
rows: 2, rows: 2,
columns: 3, columns: 3,
width: 100, width: 100,
widthUnitType: WidthType.AUTO, widthUnitType: WidthType.AUTO,
columnWidths: [1000, 1000, 1000], columnWidths: [1000, 1000, 1000],
}); });
table
table2
.getCell(0, 0) .getCell(0, 0)
.addParagraph(new Paragraph("World")) .add(new Paragraph("World"))
.setMargins({ .setMargins({
top: 1000, top: 1000,
bottom: 1000, bottom: 1000,
@ -33,9 +32,7 @@ table
}); });
table.getRow(0).mergeCells(0, 2); table.getRow(0).mergeCells(0, 2);
doc.createParagraph("Another table").heading2(); const table3 = new Table({
table = doc.createTable({
rows: 2, rows: 2,
columns: 4, columns: 4,
width: 7000, width: 7000,
@ -47,55 +44,70 @@ table = doc.createTable({
left: 400, left: 400,
}, },
}); });
table.getCell(0, 0).addParagraph(new Paragraph("Foo"));
table.getCell(0, 1).addParagraph(new Paragraph("v"));
table table3.getCell(0, 0).add(new Paragraph("Foo"));
table3.getCell(0, 1).add(new Paragraph("v"));
table3
.getCell(1, 0) .getCell(1, 0)
.addParagraph(new Paragraph("Bar1")) .add(new Paragraph("Bar1"))
.setShading({ .setShading({
fill: "b79c2f", fill: "b79c2f",
val: ShadingType.REVERSE_DIAGONAL_STRIPE, val: ShadingType.REVERSE_DIAGONAL_STRIPE,
color: "auto", color: "auto",
}); });
table table3
.getCell(1, 1) .getCell(1, 1)
.addParagraph(new Paragraph("Bar2")) .add(new Paragraph("Bar2"))
.setShading({ .setShading({
fill: "42c5f4", fill: "42c5f4",
val: ShadingType.PERCENT_95, val: ShadingType.PERCENT_95,
color: "auto", color: "auto",
}); });
table table3
.getCell(1, 2) .getCell(1, 2)
.addParagraph(new Paragraph("Bar3")) .add(new Paragraph("Bar3"))
.setShading({ .setShading({
fill: "880aa8", fill: "880aa8",
val: ShadingType.PERCENT_10, val: ShadingType.PERCENT_10,
color: "e2df0b", color: "e2df0b",
}); });
table table3
.getCell(1, 3) .getCell(1, 3)
.addParagraph(new Paragraph("Bar4")) .add(new Paragraph("Bar4"))
.setShading({ .setShading({
fill: "FF0000", fill: "FF0000",
val: ShadingType.CLEAR, val: ShadingType.CLEAR,
color: "auto", color: "auto",
}); });
table.getRow(0).mergeCells(0, 3); table3.getRow(0).mergeCells(0, 3);
doc.createParagraph("hi"); const table4 = new Table({
doc.createTable({
rows: 2, rows: 2,
columns: 2, columns: 2,
width: 100, width: 100,
widthUnitType: WidthType.PERCENTAGE, widthUnitType: WidthType.PERCENTAGE,
}); });
const packer = new Packer(); doc.addSection({
children: [
table,
new Paragraph({
text: "Another table",
heading: HeadingLevel.HEADING_2,
}),
table2,
new Paragraph({
text: "Another table",
heading: HeadingLevel.HEADING_2,
}),
table3,
new Paragraph("hi"),
table4,
],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,31 @@
// 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();
doc.addSection({
children: [
new Paragraph("Hello World 1->")
.addSequentialIdentifier("Caption")
.addRun(new TextRun(" text after sequencial caption 2->"))
.addSequentialIdentifier("Caption"),
new Paragraph("Hello World 1->")
.addSequentialIdentifier("Label")
.addRun(new TextRun(" text after sequencial caption 2->"))
.addSequentialIdentifier("Label"),
new Paragraph("Hello World 1->")
.addSequentialIdentifier("Another")
.addRun(new TextRun(" text after sequencial caption 3->"))
.addSequentialIdentifier("Label"),
new Paragraph("Hello World 2->")
.addSequentialIdentifier("Another")
.addRun(new TextRun(" text after sequencial caption 4->"))
.addSequentialIdentifier("Label"),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,11 +1,21 @@
// Example of how you would create a table with float positions // Example of how you would create a table with float positions
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph, RelativeHorizontalPosition, RelativeVerticalPosition, TableAnchorType, WidthType } from "../build"; import {
Document,
Packer,
Paragraph,
RelativeHorizontalPosition,
RelativeVerticalPosition,
Table,
TableAnchorType,
TableLayoutType,
WidthType,
} from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 2, rows: 2,
columns: 2, columns: 2,
float: { float: {
@ -16,14 +26,16 @@ const table = doc.createTable({
}, },
width: 4535, width: 4535,
widthUnitType: WidthType.DXA, widthUnitType: WidthType.DXA,
layout: TableLayoutType.FIXED,
}); });
table.setFixedWidthLayout();
table.getCell(0, 0).addParagraph(new Paragraph("Hello")); table.getCell(0, 0).add(new Paragraph("Hello"));
table.getRow(0).mergeCells(0, 1); table.getRow(0).mergeCells(0, 1);
const packer = new Packer(); doc.addSection({
children: [table],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -4,15 +4,14 @@ import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build"; import { Document, Packer, Paragraph } from "../build";
const doc = new Document(); const doc = new Document();
const paragraph = new Paragraph(); const paragraph = new Paragraph({});
const link = doc.createHyperlink("http://www.example.com", "Hyperlink"); const link = doc.createHyperlink("http://www.example.com", "Hyperlink");
link.bold();
paragraph.addHyperLink(link); paragraph.addHyperLink(link);
doc.addParagraph(paragraph); doc.addSection({
children: [paragraph],
});
const packer = new Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,27 @@
// Add image to table cell
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Header, Media, Packer, Paragraph, Table } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const table = new Table({
rows: 2,
columns: 2,
});
table.getCell(1, 1).add(new Paragraph(image));
// Adding same table in the body and in the header
doc.addSection({
headers: {
default: new Header({
children: [table],
}),
},
children: [table],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,22 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Header, Media, Packer, Paragraph } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
doc.addSection({
headers: {
default: new Header({
children: [new Paragraph(image), new Paragraph(image1), new Paragraph(image2)],
}),
},
children: [new Paragraph("Hello World")],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

45
demo/38-text-wrapping.ts Normal file
View File

@ -0,0 +1,45 @@
// Example of how to "wrap" text around an image
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
// import { Document, Packer, Paragraph } from "../build";
import { Document, Media, Packer, Paragraph, TextWrappingSide, TextWrappingType } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: {
horizontalPosition: {
offset: 2014400,
},
verticalPosition: {
offset: 2014400,
},
wrap: {
type: TextWrappingType.SQUARE,
side: TextWrappingSide.BOTH_SIDES,
},
margins: {
top: 201440,
bottom: 201440,
},
},
});
doc.addSection({
children: [
new Paragraph(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.",
),
new Paragraph(
"Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.",
),
new Paragraph(
"Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.",
),
new Paragraph(image),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

45
demo/39-page-numbers.ts Normal file
View File

@ -0,0 +1,45 @@
// Example how to display page numbers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, Document, Footer, Header, Packer, PageNumberFormat, Paragraph, TextRun } from "../build";
const doc = new Document({});
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph("Foo Bar corp. ")
.addRun(new TextRun("Page Number ").pageNumber())
.addRun(new TextRun(" to ").numberOfTotalPages()),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
text: "Foo Bar corp. ",
alignment: AlignmentType.CENTER,
})
.addRun(new TextRun("Page Number: ").pageNumber())
.addRun(new TextRun(" to ").numberOfTotalPages()),
],
}),
},
properties: {
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
},
children: [
new Paragraph("Hello World 1").pageBreak(),
new Paragraph("Hello World 2").pageBreak(),
new Paragraph("Hello World 3").pageBreak(),
new Paragraph("Hello World 4").pageBreak(),
new Paragraph("Hello World 5").pageBreak(),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,18 +1,21 @@
// Example of how you would create a table and add data to it // Example of how you would create a table and add data to it
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build"; import { Document, Packer, Paragraph, Table } from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 4, rows: 4,
columns: 4, columns: 4,
}); });
table.getCell(2, 2).addParagraph(new Paragraph("Hello"));
const packer = new Packer(); table.getCell(2, 2).add(new Paragraph("Hello"));
packer.toBuffer(doc).then((buffer) => { doc.addSection({
children: [table],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

29
demo/40-line-numbers.ts Normal file
View File

@ -0,0 +1,29 @@
// Example demonstrating line numbers.
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, HeadingLevel, LineNumberRestartFormat, Packer, Paragraph } from "../build";
const doc = new Document();
doc.addSection({
properties: {
lineNumberCountBy: 1,
lineNumberRestart: LineNumberRestartFormat.CONTINUOUS,
},
children: [
new Paragraph({
text: "Hello",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph(
"Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.",
),
new Paragraph(
"Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.",
),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,54 @@
// Multiple cells merging in the same table
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph, Table } from "../build";
const doc = new Document();
const table = new Table({
rows: 13,
columns: 6,
});
let row = 0;
table.getCell(row, 0).add(new Paragraph("0,0"));
table.getCell(row, 1).add(new Paragraph("0,1"));
table.getCell(row, 3).add(new Paragraph("0,3"));
table.getCell(row, 4).add(new Paragraph("0,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(1, 2);
row = 1;
table.getCell(row, 0).add(new Paragraph("1,0"));
table.getCell(row, 2).add(new Paragraph("1,2"));
table.getCell(row, 4).add(new Paragraph("1,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(2, 3);
table.getRow(row).mergeCells(0, 1);
row = 2;
table.getCell(row, 0).add(new Paragraph("2,0"));
table.getCell(row, 1).add(new Paragraph("2,1"));
table.getCell(row, 2).add(new Paragraph("2,2"));
table.getCell(row, 3).add(new Paragraph("2,3"));
table.getCell(row, 4).add(new Paragraph("2,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(1, 2);
row = 3;
table.getCell(row, 0).add(new Paragraph("3,0"));
table.getCell(row, 1).add(new Paragraph("3,1"));
table.getCell(row, 2).add(new Paragraph("3,2"));
table.getCell(row, 3).add(new Paragraph("3,3"));
table.getCell(row, 4).add(new Paragraph("3,4"));
table.getCell(row, 5).add(new Paragraph("3,5"));
row = 4;
table.getCell(row, 0).add(new Paragraph("4,0"));
table.getCell(row, 5).add(new Paragraph("4,5"));
table.getRow(row).mergeCells(0, 4);
doc.addSection({
children: [table],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,20 +1,22 @@
// Add image to table cell // Add image to table cell
// Import from 'docx' rather than '../build' if you install from npm // Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build"; import { Document, Packer, Paragraph, Table } from "../build";
const doc = new Document(); const doc = new Document();
const table = doc.createTable({ const table = new Table({
rows: 4, rows: 4,
columns: 4, columns: 4,
}); });
table.getCell(2, 2).addParagraph(new Paragraph("Hello"));
table.getCell(2, 2).add(new Paragraph("Hello"));
table.getColumn(3).mergeCells(1, 2); table.getColumn(3).mergeCells(1, 2);
// table.getCell(3, 2).addParagraph(new Paragraph("Hello"));
const packer = new Packer(); doc.addSection({
children: [table],
});
packer.toBuffer(doc).then((buffer) => { Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

View File

@ -0,0 +1,40 @@
// Sections with multiple columns
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
doc.addSection({
properties: {
column: {
width: 708,
count: 2,
},
},
children: [
new Paragraph("This text will be split into 2 columns on a page."),
new Paragraph(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
),
],
});
doc.addSection({
properties: {
column: {
width: 708,
count: 3,
},
},
children: [
new Paragraph("This text will be split into 3 columns on a page."),
new Paragraph(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,35 @@
// Highlighting text
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, Document, Header, Packer, Paragraph, TextRun } from "../build";
const doc = new Document();
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
alignment: AlignmentType.RIGHT,
children: [
new TextRun({
text: "Hello World",
color: "red",
bold: true,
size: 24,
font: {
name: "Garamond",
},
highlight: "yellow",
}),
],
}),
],
}),
},
children: [],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

39
demo/46-shading-text.ts Normal file
View File

@ -0,0 +1,39 @@
// Shading text
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { AlignmentType, Document, Header, Packer, Paragraph, ShadingType, TextRun } from "../build";
const doc = new Document();
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
alignment: AlignmentType.RIGHT,
children: [
new TextRun({
text: "Hello World",
color: "red",
bold: true,
size: 24,
font: {
name: "Garamond",
},
shading: {
type: ShadingType.REVERSE_DIAGONAL_STRIPE,
color: "00FFFF",
fill: "FF0000",
},
}),
],
}),
],
}),
},
children: [],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

62
demo/5-images.ts Normal file
View File

@ -0,0 +1,62 @@
// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
// import { Document, Packer, Paragraph } from "../build";
import {
Document,
HorizontalPositionAlign,
HorizontalPositionRelativeFrom,
Media,
Packer,
Paragraph,
VerticalPositionAlign,
VerticalPositionRelativeFrom,
} from "../build";
const doc = new Document();
const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png").toString("base64"));
const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"));
const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp"));
const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const image6 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: {
horizontalPosition: {
offset: 1014400,
},
verticalPosition: {
offset: 1014400,
},
},
});
const image7 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"), 200, 200, {
floating: {
horizontalPosition: {
relative: HorizontalPositionRelativeFrom.PAGE,
align: HorizontalPositionAlign.RIGHT,
},
verticalPosition: {
relative: VerticalPositionRelativeFrom.PAGE,
align: VerticalPositionAlign.BOTTOM,
},
},
});
doc.addSection({
children: [
new Paragraph("Hello World"),
new Paragraph(image1),
new Paragraph(image2),
new Paragraph(image3),
new Paragraph(image4),
new Paragraph(image5),
new Paragraph(image6),
new Paragraph(image7),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

40
demo/6-page-borders.ts Normal file
View File

@ -0,0 +1,40 @@
// Example of how to change page borders
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "../build";
const doc = new Document();
doc.addSection({
margins: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
children: [
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
text: "Foo bar",
bold: true,
}),
new TextRun({
text: "Github is the best",
bold: true,
}).tab(),
],
}),
new Paragraph({
text: "Hello World",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph("Foo bar"),
new Paragraph("Github is the best"),
],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -3,16 +3,15 @@
import * as fs from "fs"; import * as fs from "fs";
import { Document, Packer, PageOrientation, Paragraph } from "../build"; import { Document, Packer, PageOrientation, Paragraph } from "../build";
const doc = new Document(undefined, { const doc = new Document();
orientation: PageOrientation.LANDSCAPE,
doc.addSection({
size: {
orientation: PageOrientation.LANDSCAPE,
},
children: [new Paragraph("Hello World")],
}); });
const paragraph = new Paragraph("Hello World"); Packer.toBuffer(doc).then((buffer) => {
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer); fs.writeFileSync("My Document.docx", buffer);
}); });

24
demo/8-header-footer.ts Normal file
View File

@ -0,0 +1,24 @@
// Add text to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Footer, Header, Packer, Paragraph } from "../build";
const doc = new Document();
doc.addSection({
headers: {
default: new Header({
children: [new Paragraph("Header text")],
}),
},
footers: {
default: new Footer({
children: [new Paragraph("Footer text")],
}),
},
children: [new Paragraph("Hello World")],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -0,0 +1,35 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Footer, Header, Media, Packer, Paragraph } from "../build";
const doc = new Document();
const image1 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
doc.addSection({
headers: {
default: new Header({
children: [
new Paragraph({
children: [image1],
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
children: [image2],
}),
],
}),
},
children: [new Paragraph("Hello World")],
});
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,39 +1,45 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<script src="../build/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
</head>
<head> <body>
<script src="../build/index.js"></script> <h1>DOCX browser Word document generation</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
</head>
<body> <button type="button" onclick="generate()">Click to generate document</button>
<h1>DOCX browser Word document generation</h1> <script>
function generate() {
const doc = new Document();
<button type="button" onclick="generate()">Click to generate document</button> doc.addSection({
children: [
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
text: "Foo Bar",
bold: true,
}),
new TextRun({
text: "Github is the best",
bold: true,
}).tab(),
],
}),
],
});
<script>
function generate() {
const doc = new Document();
const paragraph = new Paragraph("Hello World");
const institutionText = new TextRun("Foo Bar").bold();
const dateText = new TextRun("Github is the best").tab().bold();
paragraph.addRun(institutionText);
paragraph.addRun(dateText);
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBlob(doc).then(blob => {
console.log(blob);
saveAs(blob, "example.docx");
console.log("Document created successfully");
});
}
</script>
</body>
Packer.toBlob(doc).then((blob) => {
console.log(blob);
saveAs(blob, "example.docx");
console.log("Document created successfully");
});
}
</script>
</body>
</html> </html>

View File

@ -1,20 +0,0 @@
// Simple example to add text to a document
// 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");
const institutionText = new TextRun("Foo Bar").bold();
const dateText = new TextRun("Github is the best").tab().bold();
paragraph.addRun(institutionText);
paragraph.addRun(dateText);
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,25 +0,0 @@
// Scaling images
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
const paragraph = new Paragraph("Hello World");
doc.addParagraph(paragraph);
const image = doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const image2 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const image3 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const image4 = doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
image.scale(0.5);
image2.scale(1);
image3.scale(2.5);
image4.scale(4);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,28 +0,0 @@
// This example shows 3 styles using XML styles
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const styles = fs.readFileSync("./demo/assets/custom-styles.xml", "utf-8");
const doc = new Document({
title: "Title",
externalStyles: styles,
});
doc.createParagraph("Cool Heading Text").heading1();
const paragraph = new Paragraph('This is a custom named style from the template "MyFancyStyle"');
paragraph.style("MyFancyStyle");
doc.addParagraph(paragraph);
doc.createParagraph("Some normal text");
doc.createParagraph("MyFancyStyle again").style("MyFancyStyle");
paragraph.style("MyFancyStyle");
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,28 +0,0 @@
// Page numbers
// 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();
doc.createParagraph("First Page").pageBreak();
doc.createParagraph("Second Page");
const pageNumber = new TextRun("Page ").pageNumber();
const pageoneheader = new Paragraph("First Page Header ").right();
pageoneheader.addRun(pageNumber);
const firstPageHeader = doc.createFirstPageHeader();
firstPageHeader.addParagraph(pageoneheader);
const pagetwoheader = new Paragraph("My Title ").right();
pagetwoheader.addRun(pageNumber);
doc.Header.addParagraph(pagetwoheader);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,84 +0,0 @@
// Multiple sections and headers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
const doc = new Document();
const paragraph = new Paragraph("Hello World").pageBreak();
doc.addParagraph(paragraph);
const header = doc.createHeader();
header.createParagraph("Header on another page");
const footer = doc.createFooter();
footer.createParagraph("Footer on another page");
doc.addSection({
headers: {
default: header,
},
footers: {
default: footer,
},
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
});
doc.createParagraph("hello");
doc.addSection({
headers: {
default: header,
},
footers: {
default: footer,
},
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
orientation: PageOrientation.LANDSCAPE,
});
doc.createParagraph("hello in landscape");
const header2 = doc.createHeader();
const pageNumber = new TextRun("Page number: ").pageNumber();
header2.createParagraph().addRun(pageNumber);
doc.addSection({
headers: {
default: header2,
},
orientation: PageOrientation.PORTRAIT,
});
doc.createParagraph("Page number in the header must be 2, because it continues from the previous section.");
doc.addSection({
headers: {
default: header2,
},
pageNumberFormatType: PageNumberFormat.UPPER_ROMAN,
orientation: PageOrientation.PORTRAIT,
});
doc.createParagraph(
"Page number in the header must be III, because it continues from the previous section, but is defined as upper roman.",
);
doc.addSection({
headers: {
default: header2,
},
pageNumberFormatType: PageNumberFormat.DECIMAL,
pageNumberStart: 25,
orientation: PageOrientation.PORTRAIT,
});
doc.createParagraph("Page number in the header must be 25, because it is defined to start at 25 and to be decimal in this section.");
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,20 +0,0 @@
// Export to base64 string - Useful in a browser environment.
// 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");
const institutionText = new TextRun("Foo").bold();
const dateText = new TextRun("Bar").tab().bold();
paragraph.addRun(institutionText);
paragraph.addRun(dateText);
doc.addParagraph(paragraph);
const packer = new Packer();
packer.toBase64String(doc).then((str) => {
fs.writeFileSync("My Document.docx", str);
});

View File

@ -1,78 +0,0 @@
// Example on how to customise the look at feel using Styles
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer } from "../build";
const doc = new Document({
creator: "Clippy",
title: "Sample Document",
description: "A brief example of using docx",
});
doc.Styles.createParagraphStyle("Heading1", "Heading 1")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(28)
.bold()
.italics()
.spacing({ after: 120 });
doc.Styles.createParagraphStyle("Heading2", "Heading 2")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26)
.bold()
.underline("double", "FF0000")
.spacing({ before: 240, after: 120 });
doc.Styles.createParagraphStyle("aside", "Aside")
.basedOn("Normal")
.next("Normal")
.color("999999")
.italics()
.indent({ left: 720 })
.spacing({ line: 276 });
doc.Styles.createParagraphStyle("wellSpaced", "Well Spaced")
.basedOn("Normal")
.spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 });
doc.Styles.createParagraphStyle("ListParagraph", "List Paragraph")
.quickFormat()
.basedOn("Normal");
const numberedAbstract = doc.Numbering.createAbstractNumbering();
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
doc.createParagraph("Test heading1, bold and italicized").heading1();
doc.createParagraph("Some simple content");
doc.createParagraph("Test heading2 with double red underline").heading2();
const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract);
const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract);
letterNumbering5.overrideLevel(0, 5);
doc.createParagraph("Option1").setNumbering(letterNumbering, 0);
doc.createParagraph("Option5 -- override 2 to 5").setNumbering(letterNumbering5, 0);
doc.createParagraph("Option3").setNumbering(letterNumbering, 0);
doc
.createParagraph()
.createTextRun("Some monospaced content")
.font("Monospace");
doc.createParagraph("An aside, in light gray italics and indented").style("aside");
doc.createParagraph("This is normal, but well-spaced text").style("wellSpaced");
const para = doc.createParagraph();
para.createTextRun("This is a bold run,").bold();
para.createTextRun(" switching to normal ");
para.createTextRun("and then underlined ").underline();
para.createTextRun("and back to normal.");
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,27 +0,0 @@
// This demo shows right to left for special languages
// 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 paragraph1 = new Paragraph().bidirectional();
const textRun1 = new TextRun("שלום עולם").rightToLeft();
paragraph1.addRun(textRun1);
doc.addParagraph(paragraph1);
const paragraph2 = new Paragraph().bidirectional();
const textRun2 = new TextRun("שלום עולם").bold().rightToLeft();
paragraph2.addRun(textRun2);
doc.addParagraph(paragraph2);
const paragraph3 = new Paragraph().bidirectional();
const textRun3 = new TextRun("שלום עולם").italics().rightToLeft();
paragraph3.addRun(textRun3);
doc.addParagraph(paragraph3);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,22 +0,0 @@
// Creates two paragraphs, one with a border and one without
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
const paragraph = new Paragraph("No border!");
doc.addParagraph(paragraph);
const borderParagraph = new Paragraph("I have borders on my top and bottom sides!").createBorder();
borderParagraph.Borders.addTopBorder();
borderParagraph.Borders.addBottomBorder();
doc.addParagraph(borderParagraph);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,35 +0,0 @@
// Custom styles using JavaScript configuration
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer } from "../build";
const doc = new Document();
const myStyles = doc.Styles;
// The first argument is an ID you use to apply the style to paragraphs
// The second argument is a human-friendly name to show in the UI
myStyles.createParagraphStyle("myWonkyStyle", "My Wonky Style")
.basedOn("Normal")
.next("Normal")
.color("990000")
.italics()
.indent({left: 720}) // 720 TWIP === 720 / 20 pt === .5 in
.spacing({line: 276}); // 276 / 240 = 1.15x line spacing
myStyles.createParagraphStyle("Heading2", "Heading 2")
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26) // 26 half-points === 13pt font
.bold()
.underline("double", "FF0000")
.spacing({before: 240, after: 120}); // TWIP for both
doc.createParagraph("Hello").style("myWonkyStyle");
doc.createParagraph("World").heading2(); // Uses the Heading2 style
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,43 +0,0 @@
// Table of contents
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { File, Packer, Paragraph, StyleLevel, TableOfContents } from "../build";
const doc = new File();
// The first argument is an ID you use to apply the style to paragraphs
// The second argument is a human-friendly name to show in the UI
doc.Styles.createParagraphStyle("MySpectacularStyle", "My Spectacular Style")
.basedOn("Heading1")
.next("Heading1")
.color("990000")
.italics();
// WordprocessingML docs for TableOfContents can be found here:
// http://officeopenxml.com/WPtableOfContents.php
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
// making the entries be hyperlinks for the paragraph
const toc = new TableOfContents("Summary", {
hyperlink: true,
headingStyleRange: "1-5",
stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)],
});
doc.addTableOfContents(toc);
doc.addParagraph(new Paragraph("Header #1").heading1().pageBreakBefore());
doc.addParagraph(new Paragraph("I'm a little text very nicely written.'"));
doc.addParagraph(new Paragraph("Header #2").heading1().pageBreakBefore());
doc.addParagraph(new Paragraph("I'm a other text very nicely written.'"));
doc.addParagraph(new Paragraph("Header #2.1").heading2());
doc.addParagraph(new Paragraph("I'm a another text very nicely written.'"));
doc.addParagraph(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore());
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,46 +0,0 @@
// Numbered lists
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Indent, Numbering, Packer, Paragraph } from "../build";
const doc = new Document();
const numbering = new Numbering();
const abstractNum = numbering.createAbstractNumbering();
abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent({ left: 720, hanging: 260 }));
const concrete = numbering.createConcreteNumbering(abstractNum);
const item1 = new Paragraph("line with contextual spacing");
const item2 = new Paragraph("line with contextual spacing");
const item3 = new Paragraph("line without contextual spacing");
const item4 = new Paragraph("line without contextual spacing");
item1
.setNumbering(concrete, 0)
.spacing({ before: 200 })
.contextualSpacing(true);
item2
.setNumbering(concrete, 0)
.spacing({ before: 200 })
.contextualSpacing(true);
item3
.setNumbering(concrete, 0)
.spacing({ before: 200 })
.contextualSpacing(false);
item4
.setNumbering(concrete, 0)
.spacing({ before: 200 })
.contextualSpacing(false);
doc.addParagraph(item1);
doc.addParagraph(item2);
doc.addParagraph(item3);
doc.addParagraph(item4);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,46 +0,0 @@
// Numbering and bullet points example
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Indent, Numbering, Packer, Paragraph } from "../build";
const doc = new Document();
const numbering = new Numbering();
const abstractNum = numbering.createAbstractNumbering();
abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent({ left: 720, hanging: 260 }));
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent({ left: 1440, hanging: 980 }));
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent({ left: 14402160, hanging: 1700 }));
const concrete = numbering.createConcreteNumbering(abstractNum);
const topLevelP = new Paragraph("Hey you");
const subP = new Paragraph("What's up fam");
const secondSubP = new Paragraph("Hello World 2");
const subSubP = new Paragraph("Yeah boi");
topLevelP.setNumbering(concrete, 0);
subP.setNumbering(concrete, 1);
secondSubP.setNumbering(concrete, 1);
subSubP.setNumbering(concrete, 2);
doc.addParagraph(topLevelP);
doc.addParagraph(subP);
doc.addParagraph(secondSubP);
doc.addParagraph(subSubP);
const bullet1 = new Paragraph("Hey you").bullet();
const bullet2 = new Paragraph("What's up fam").bullet(1);
const bullet3 = new Paragraph("Hello World 2").bullet(2);
const bullet4 = new Paragraph("Yeah boi").bullet(3);
doc.addParagraph(bullet1);
doc.addParagraph(bullet2);
doc.addParagraph(bullet3);
doc.addParagraph(bullet4);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,22 +0,0 @@
// 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);
});

View File

@ -1,26 +0,0 @@
// Add image to table cell
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Media, Packer, Table } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
const table = new Table({
rows: 2,
columns: 2,
});
table.getCell(1, 1).addParagraph(image.Paragraph);
// doc.createParagraph("Hello World");
doc.addTable(table);
// doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.Header.addTable(table);
// doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,18 +0,0 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Media, Packer } from "../build";
const doc = new Document();
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
doc.createParagraph("Hello World");
doc.Header.addImage(image);
doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.Header.createImage(fs.readFileSync("./demo/images/image1.jpeg"));
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,44 +0,0 @@
// Example of how to "wrap" text around an image
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
// import { Document, Packer, Paragraph } from "../build";
import { Document, Packer, TextWrappingSide, TextWrappingType } from "../build";
const doc = new Document();
doc.createParagraph(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.",
);
doc.createParagraph(
"Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.",
);
doc.createParagraph(
"Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.",
);
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: {
horizontalPosition: {
offset: 2014400,
},
verticalPosition: {
offset: 2014400,
},
wrap: {
type: TextWrappingType.SQUARE,
side: TextWrappingSide.BOTH_SIDES,
},
margins: {
top: 201440,
bottom: 201440,
},
},
});
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,33 +0,0 @@
// Example how to display page numbers
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, PageNumberFormat, TextRun } from "../build";
const doc = new Document(
{},
{
pageNumberStart: 1,
pageNumberFormatType: PageNumberFormat.DECIMAL,
},
);
doc.Header.createParagraph("Foo Bar corp. ")
.addRun(new TextRun("Page Number ").pageNumber())
.addRun(new TextRun(" to ").numberOfTotalPages());
doc.Footer.createParagraph("Foo Bar corp. ")
.center()
.addRun(new TextRun("Page Number: ").pageNumber())
.addRun(new TextRun(" to ").numberOfTotalPages());
doc.createParagraph("Hello World 1").pageBreak();
doc.createParagraph("Hello World 2").pageBreak();
doc.createParagraph("Hello World 3").pageBreak();
doc.createParagraph("Hello World 4").pageBreak();
doc.createParagraph("Hello World 5").pageBreak();
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,25 +0,0 @@
// Example demonstrating line numbers.
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Paragraph, Packer, LineNumberRestartFormat } from "../build";
const doc = new Document(
{},
{
lineNumberCountBy: 1,
lineNumberRestart: LineNumberRestartFormat.CONTINUOUS,
},
);
doc.addParagraph(new Paragraph('Hello').heading1());
doc.createParagraph("Himenaeos duis luctus nullam fermentum lobortis potenti vivamus non dis, sed facilisis ultricies scelerisque aenean risus hac senectus. Adipiscing id venenatis justo ante gravida placerat, ac curabitur dis pellentesque proin bibendum risus, aliquam porta taciti vulputate primis. Tortor ipsum fermentum quam vel convallis primis nisl praesent tincidunt, lobortis quisque felis vitae condimentum class ut sem nam, aenean potenti pretium ac amet lacinia himenaeos mi. Aliquam nisl turpis hendrerit est morbi malesuada, augue interdum mus inceptos curabitur tristique, parturient feugiat sodales nulla facilisi. Aliquam non pulvinar purus nulla ex integer, velit faucibus vitae at bibendum quam, risus elit aenean adipiscing posuere.");
doc.createParagraph("Sed laoreet id mattis egestas nam mollis elit lacinia convallis dui tincidunt ultricies habitant, pharetra per maximus interdum neque tempor risus efficitur morbi imperdiet senectus. Lectus laoreet senectus finibus inceptos donec potenti fermentum, ultrices eleifend odio suscipit magnis tellus maximus nibh, ac sit nullam eget felis himenaeos. Diam class sem magnis aenean commodo faucibus id proin mi, nullam sodales nec mus parturient ornare ad inceptos velit hendrerit, bibendum placerat eleifend integer facilisis urna dictumst suspendisse.");
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,51 +0,0 @@
// Multiple cells merging in the same table
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer, Paragraph } from "../build";
const doc = new Document();
const table = doc.createTable({
rows: 13,
columns: 6,
});
let row = 0;
table.getCell(row, 0).addContent(new Paragraph("0,0"));
table.getCell(row, 1).addContent(new Paragraph("0,1"));
table.getCell(row, 3).addContent(new Paragraph("0,3"));
table.getCell(row, 4).addContent(new Paragraph("0,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(1, 2);
row = 1;
table.getCell(row, 0).addContent(new Paragraph("1,0"));
table.getCell(row, 2).addContent(new Paragraph("1,2"));
table.getCell(row, 4).addContent(new Paragraph("1,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(2, 3);
table.getRow(row).mergeCells(0, 1);
row = 2;
table.getCell(row, 0).addContent(new Paragraph("2,0"));
table.getCell(row, 1).addContent(new Paragraph("2,1"));
table.getCell(row, 2).addContent(new Paragraph("2,2"));
table.getCell(row, 3).addContent(new Paragraph("2,3"));
table.getCell(row, 4).addContent(new Paragraph("2,4"));
table.getRow(row).mergeCells(4, 5);
table.getRow(row).mergeCells(1, 2);
row = 3;
table.getCell(row, 0).addContent(new Paragraph("3,0"));
table.getCell(row, 1).addContent(new Paragraph("3,1"));
table.getCell(row, 2).addContent(new Paragraph("3,2"));
table.getCell(row, 3).addContent(new Paragraph("3,3"));
table.getCell(row, 4).addContent(new Paragraph("3,4"));
table.getCell(row, 5).addContent(new Paragraph("3,5"));
row = 4;
table.getCell(row, 0).addContent(new Paragraph("4,0"));
table.getCell(row, 5).addContent(new Paragraph("4,5"));
table.getRow(row).mergeCells(0, 4);
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,45 +0,0 @@
// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
// import { Document, Packer, Paragraph } from "../build";
import { Document, HorizontalPositionAlign, HorizontalPositionRelativeFrom, Packer, Paragraph, VerticalPositionAlign, VerticalPositionRelativeFrom} from "../build";
const doc = new Document();
const paragraph = new Paragraph("Hello World");
doc.addParagraph(paragraph);
doc.createImage(fs.readFileSync("./demo/images/image1.jpeg"));
doc.createImage(fs.readFileSync("./demo/images/dog.png").toString("base64"));
doc.createImage(fs.readFileSync("./demo/images/cat.jpg"));
doc.createImage(fs.readFileSync("./demo/images/parrots.bmp"));
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: {
horizontalPosition: {
offset: 1014400,
},
verticalPosition: {
offset: 1014400,
},
},
});
doc.createImage(fs.readFileSync("./demo/images/cat.jpg"), 200, 200, {
floating: {
horizontalPosition: {
relative: HorizontalPositionRelativeFrom.PAGE,
align: HorizontalPositionAlign.RIGHT,
},
verticalPosition: {
relative: VerticalPositionRelativeFrom.PAGE,
align: VerticalPositionAlign.BOTTOM,
},
},
});
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,29 +0,0 @@
// Example of how to change page borders
// 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(undefined, {
top: 0,
right: 0,
bottom: 0,
left: 0,
});
const paragraph = new Paragraph("Hello World");
const institutionText = new TextRun("Foo bar").bold();
const dateText = new TextRun("Github is the best").tab().bold();
paragraph.addRun(institutionText);
paragraph.addRun(dateText);
doc.addParagraph(paragraph);
doc.createParagraph("Hello World").heading1();
doc.createParagraph("Foo bar");
doc.createParagraph("Github is the best");
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,17 +0,0 @@
// Add text to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer } from "../build";
const doc = new Document();
doc.createParagraph("Hello World");
doc.Header.createParagraph("Header text");
doc.Footer.createParagraph("Footer text");
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -1,17 +0,0 @@
// Add images to header and footer
// Import from 'docx' rather than '../build' if you install from npm
import * as fs from "fs";
import { Document, Packer } from "../build";
const doc = new Document();
doc.createParagraph("Hello World");
doc.Header.createImage(fs.readFileSync("./demo/images/pizza.gif"));
doc.Footer.createImage(fs.readFileSync("./demo/images/pizza.gif"));
const packer = new Packer();
packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});

View File

@ -19,13 +19,16 @@ prompt.start();
prompt.get(schema, (_, result) => { prompt.get(schema, (_, result) => {
const demoNumber = result.number; const demoNumber = result.number;
const filePath = `./demo/demo${demoNumber}.ts`; const files = fs.readdirSync("./demo").filter((fn) => fn.startsWith(demoNumber));
if (!fs.existsSync(filePath)) { if (files.length === 0) {
console.error(`demo${demoNumber} does not exist: ${filePath}`); console.error(`demo number ${demoNumber} does not exist`);
return; return;
} }
console.log(`Running demo ${demoNumber}`);
const filePath = `./demo/${files[0]}`;
console.log(`Running demo ${demoNumber}: ${files[0]}`);
if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) { if (shelljs.exec(`npm run ts-node -- ${filePath}`).code === 0) {
console.log("Document created successfully"); console.log("Document created successfully");
} else { } else {

View File

@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<img alt="clippy the assistant" src="https://i.imgur.com/pwCV6L8.png"> <img alt="clippy the assistant" src="https://i.imgur.com/37uBGhO.gif">
</p> </p>
<p align="center"> <p align="center">
@ -18,33 +18,49 @@ npm install --save docx
Then you can `require` or `import` as usual: Then you can `require` or `import` as usual:
```js ```ts
let docx = require("docx"); const docx = require("docx");
``` ```
```js ```ts
import * as docx from "docx"; import * as docx from "docx";
// or
import { ... } from "docx";
``` ```
## Basic Usage ## Basic Usage
```js ```ts
var fs = require("fs"); import * as fs from "fs";
var docx = require("docx"); import { Document, Packer, Paragraph, TextRun } from "docx";
// Create document // Create document
var doc = new docx.Document(); const doc = new Document();
// Add some content in the document // Documents contain sections, you can have multiple sections per document, go here to learn more about sections
var paragraph = new docx.Paragraph("Some cool text here."); // This simple example will only contain one section
// Add more text into the paragraph if you wish doc.addSection({
paragraph.addRun(new docx.TextRun("Lorem Ipsum Foo Bar")); properties: {},
doc.addParagraph(paragraph); children: [
new Paragraph({
children: [
new TextRun("Hello World"),
new TextRun({
text: "Foo Bar",
bold: true,
}),
new TextRun({
text: "Github is the best",
bold: true,
}).tab(),
],
}),
],
});
// Used to export the file into a .docx file // Used to export the file into a .docx file
var packer = new docx.Packer(); Packer.toBuffer(doc).then((buffer) => {
packer.toBuffer(doc).then((buffer) => { fs.writeFileSync("My Document.docx", buffer);
fs.writeFileSync("My First Document.docx", buffer);
}); });
// Done! A file called 'My First Document.docx' will be in your file system. // Done! A file called 'My First Document.docx' will be in your file system.

View File

@ -9,6 +9,7 @@
* Usage * Usage
* [Document](usage/document.md) * [Document](usage/document.md)
* [Sections](usage/sections.md)
* [Paragraph](usage/paragraph.md) * [Paragraph](usage/paragraph.md)
* [Text](usage/text.md) * [Text](usage/text.md)
* [Image](usage/images.md) * [Image](usage/images.md)

View File

@ -2,7 +2,7 @@
* Include documentation reference(s) at the top of each file: * Include documentation reference(s) at the top of each file:
```js ```ts
// http://officeopenxml.com/WPdocument.php // http://officeopenxml.com/WPdocument.php
``` ```
@ -44,7 +44,7 @@ Try to make method parameters of the outside API accept primitives, or `json` ob
This is so that: This is so that:
1. Imports are much cleaner for the end user, no need for: 1. Imports are much cleaner for the end user, no need for:
```js ```ts
import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component"; import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component";
``` ```
@ -55,7 +55,7 @@ This is so that:
`TableFloatProperties` is a class. The outside world would have to `new` up the object, and inject it in like so: `TableFloatProperties` is a class. The outside world would have to `new` up the object, and inject it in like so:
```js ```ts
public float(tableFloatProperties: TableFloatProperties): Table public float(tableFloatProperties: TableFloatProperties): Table
``` ```
@ -67,7 +67,7 @@ This is so that:
`ITableFloatOptions` is an interface for a JSON of primitives. The end user would need to pass in a json object and not need to worry about the internals: `ITableFloatOptions` is an interface for a JSON of primitives. The end user would need to pass in a json object and not need to worry about the internals:
```js ```ts
public float(tableFloatOptions: ITableFloatOptions): Table public float(tableFloatOptions: ITableFloatOptions): Table
``` ```
@ -81,7 +81,7 @@ This is just a guideline, and the rules can sometimes be broken.
* Use `create` if the method `new`'s up an element inside: * Use `create` if the method `new`'s up an element inside:
```js ```ts
public createParagraph() { public createParagraph() {
const paragraph = new Paragraph(); const paragraph = new Paragraph();
this.root.push(paragraph); this.root.push(paragraph);
@ -91,8 +91,8 @@ This is just a guideline, and the rules can sometimes be broken.
* Use `add` if you add the element into the method as a parameter. * Use `add` if you add the element into the method as a parameter.
*Note:* This may look like its breaking the previous guideline, but it has semantically different meanings. The previous one is using data to construct an object, whereas this one is simply adding elements into the document: *Note:* This may look like its breaking the previous guideline, but it has semantically different meanings. The previous one is using data to construct an object, whereas this one is simply adding elements into the document:
```js ```ts
public addParagraph(paragraph: Paragraph) { public add(paragraph: Paragraph) {
this.root.push(paragraph); this.root.push(paragraph);
} }
``` ```
@ -101,7 +101,7 @@ This is just a guideline, and the rules can sometimes be broken.
Getters and Setters are done with a capital letter like so: Getters and Setters are done with a capital letter like so:
```js ```ts
public get Level() { public get Level() {
... ...
} }
@ -111,13 +111,13 @@ There is no performance advantage by doing this. It means we don't need to prefi
**Do not:** **Do not:**
```js ```ts
private get _level: string; private get _level: string;
``` ```
**Do** **Do**
```js ```ts
private get level: string; private get level: string;
``` ```
@ -158,13 +158,13 @@ Do not use `type`, but rather use `Interfaces`. `type` cannot be extended, and a
**Do not:** **Do not:**
```js ```ts
type RelationshipFileInfo = { id: number, target: string }; type RelationshipFileInfo = { id: number, target: string };
``` ```
**Do:** **Do:**
```js ```ts
interface IRelationshipFileInfo { interface IRelationshipFileInfo {
id: number; id: number;
target: string; target: string;
@ -177,13 +177,13 @@ To take full advantage of TypeScript's typing system, its best to use `string en
**Do not:** **Do not:**
```js ```ts
type WeaponType = "bow" | "sword" | "wand"; type WeaponType = "bow" | "sword" | "wand";
``` ```
**Do:** **Do:**
```js ```ts
enum WeaponType = { enum WeaponType = {
BOW = "bow", BOW = "bow",
SWORD = "sword", SWORD = "sword",
@ -196,7 +196,7 @@ enum WeaponType = {
I am not sure where these habits in software development come from, but I do not believe it is beneficial: I am not sure where these habits in software development come from, but I do not believe it is beneficial:
**Do not:** **Do not:**
```js ```ts
readdy // misspelling readdy // misspelling
perm // abbreviation perm // abbreviation
conf // abbreviation conf // abbreviation
@ -206,7 +206,7 @@ colour // U.K. English
``` ```
**Do:** **Do:**
```js ```ts
ready ready
permission permission
config config
@ -231,7 +231,7 @@ Please write a test of every file you make and suffix it with `.spec.ts`.
Here is a template of a test: Here is a template of a test:
```js ```ts
import { assert } from "chai"; import { assert } from "chai";
describe("ClassName", () => { describe("ClassName", () => {

View File

@ -4,15 +4,15 @@
To make a bullet point, simply make a paragraph into a bullet point: To make a bullet point, simply make a paragraph into a bullet point:
```js ```ts
var text = new docx.TextRun("Bullet points"); const text = new docx.TextRun("Bullet points");
var paragraph = new docx.Paragraph(text).bullet(); const paragraph = new docx.Paragraph(text).bullet();
var text2 = new docx.TextRun("Are awesome"); const text2 = new docx.TextRun("Are awesome");
var paragraph2 = new docx.Paragraph(text2).bullet(); const paragraph2 = new docx.Paragraph(text2).bullet();
doc.addParagraph(paragraph); doc.add(paragraph);
doc.addParagraph(paragraph2); doc.add(paragraph2);
``` ```
### This will produce: ### This will produce:

View File

@ -4,7 +4,7 @@
To create a new document, it is very easy: To create a new document, it is very easy:
```js ```ts
const doc = new docx.Document(); const doc = new docx.Document();
``` ```
@ -12,7 +12,7 @@ const doc = new docx.Document();
You can add properties to the Word document by specifying options, for example: You can add properties to the Word document by specifying options, for example:
```js ```ts
const doc = new docx.Document({ const doc = new docx.Document({
creator: "Dolan Miu", creator: "Dolan Miu",
description: "My extremely interesting document", description: "My extremely interesting document",
@ -33,7 +33,7 @@ const doc = new docx.Document({
You can mix and match whatever properties you want, or provide no properties. You can mix and match whatever properties you want, or provide no properties.
### units for positioning ### Units for positioning
Various parts of the API require positioning arguments. The units are "20ths of a point" from the [OOXML](http://officeopenxml.com/index.php) specification. Various parts of the API require positioning arguments. The units are "20ths of a point" from the [OOXML](http://officeopenxml.com/index.php) specification.
See [Lars Corneliussen's blog post](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/) for more information and how to convert units. See [Lars Corneliussen's blog post](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/) for more information and how to convert units.

View File

@ -1,24 +1,26 @@
# Headers and Footers # Headers and Footers
!> Headers and Footers requires an understanding of [Sections](usage/sections.md).
## Example ## Example
Creating Headers and footers is simple. Access the `Header` and `Footer` by doing so like this: Creating Headers and footers is simple. Access the `Header` and `Footer` by doing so like this:
```js ```ts
doc.Header; doc.Header;
doc.Footer; doc.Footer;
``` ```
You can call the same methods as you would with a `File`: You can call the same methods as you would with a `File`:
```js ```ts
doc.Header.createParagraph("Header text"); doc.Header.createParagraph("Header text");
doc.Footer.createParagraph("Footer text"); doc.Footer.createParagraph("Footer text");
``` ```
Even add images: Even add images:
```js ```ts
doc.Header.createImage([BUFFER_OF_YOUR_IMAGE]); doc.Header.createImage([BUFFER_OF_YOUR_IMAGE]);
doc.Footer.createImage([BUFFER_OF_YOUR_IMAGE]); doc.Footer.createImage([BUFFER_OF_YOUR_IMAGE]);
``` ```
@ -31,7 +33,7 @@ Also all the supported section properties are implemented according to: http://o
### Example ### Example
```js ```ts
const header = this.document.createHeader(); const header = this.document.createHeader();
const footer = this.document.createFooter(); const footer = this.document.createFooter();

View File

@ -1,9 +1,11 @@
# Images # Images
!> Images requires an understanding of [Sections](usage/sections.md) and [Paragraphs](usage/paragraph.md).
To create a `floating` image on top of text: To create a `floating` image on top of text:
```ts ```ts
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: { floating: {
horizontalPosition: { horizontalPosition: {
offset: 1014400, offset: 1014400,
@ -18,14 +20,27 @@ doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
By default with no arguments, its an `inline` image: By default with no arguments, its an `inline` image:
```ts ```ts
doc.createImage(fs.readFileSync("./demo/images/parrots.bmp")); const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
``` ```
You can also create images manually and add them later: Add it into the document by adding the image into a paragraph:
```ts ```ts
const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif")); doc.addSection({
doc.addImage(image); children: [new Paragraph(image)],
});
```
Or:
```ts
doc.addSection({
children: [
new Paragraph({
children: [image],
}),
],
});
``` ```
## Intro ## Intro
@ -34,15 +49,17 @@ Adding images can be done in two ways:
1. Call the `createImage` method to add the image directly into the `document`: 1. Call the `createImage` method to add the image directly into the `document`:
```js ```ts
doc.createImage([IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]); Media.addImage(doc, [IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]);
``` ```
2. Create an `image` first, then add it into the `document`: 2. Create an `image` first, then add it into the `document`:
```ts ```ts
const image = Media.addImage(doc, [IMAGE_BUFFER]); const image = Media.addImage(doc, [IMAGE_BUFFER]);
doc.addImage(image); doc.addSection({
children: [new Paragraph(image)],
});
``` ```
`docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png` `docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png`
@ -141,7 +158,7 @@ wrap: {
For example: For example:
```ts ```ts
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: { floating: {
horizontalPosition: { horizontalPosition: {
offset: 2014400, offset: 2014400,
@ -184,7 +201,7 @@ margins: {
For example: For example:
```ts ```ts
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, { Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
floating: { floating: {
horizontalPosition: { horizontalPosition: {
offset: 2014400, offset: 2014400,
@ -210,7 +227,7 @@ doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
Importing Images from file system path Importing Images from file system path
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_
@ -218,7 +235,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_
Example showing how to add image to headers and footers Example showing how to add image to headers and footers
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_
@ -226,6 +243,6 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_
Example showing how to float images on top of text and optimally give a `margin` Example showing how to float images on top of text and optimally give a `margin`
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo38.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo38.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo38.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo38.ts_

View File

@ -67,7 +67,7 @@ First you need to create a new numbering container class and use it to
create your abstract numbering style, define your levels, and create create your abstract numbering style, define your levels, and create
your concrete numbering style: your concrete numbering style:
```js ```ts
const numbering = new docx.Numbering(); const numbering = new docx.Numbering();
const abstractNum = numbering.createAbstractNumbering(); const abstractNum = numbering.createAbstractNumbering();
@ -81,7 +81,7 @@ const concrete = numbering.createConcreteNumbering(abstractNum);
You can then apply your concrete style to paragraphs using the You can then apply your concrete style to paragraphs using the
`setNumbering` method: `setNumbering` method:
```js ```ts
topLevelP.setNumbering(concrete, 0); topLevelP.setNumbering(concrete, 0);
subP.setNumbering(concrete, 1); subP.setNumbering(concrete, 1);
subSubP.setNumbering(concrete, 2); subSubP.setNumbering(concrete, 2);
@ -90,7 +90,7 @@ subSubP.setNumbering(concrete, 2);
Finally, you need to let your exporter know about your numbering Finally, you need to let your exporter know about your numbering
styles when you're ready to render the document: styles when you're ready to render the document:
```js ```ts
const packer = new Packer(doc, undefined, undefined, numbering); const packer = new Packer(doc, undefined, undefined, numbering);
packer.pack(myOutput); packer.pack(myOutput);
``` ```

View File

@ -2,15 +2,50 @@
> Packers are the way in which `docx` turns your code into `.docx` format. It is completely decoupled from the `docx.Document`. > Packers are the way in which `docx` turns your code into `.docx` format. It is completely decoupled from the `docx.Document`.
## Version 4
Packers in `version 4` and above are now one single `Packer`. It works in both a node and browser environment (Angular etc). Now, the packer returns a `Buffer`, `Blob` or `base64 string`. It is up to you to take that and persist it with node's `fs`, send it down as a downloadable file, or anything else you wish. As of version 4, this library will not have options to export to PDF. Packers in `version 4` and above are now one single `Packer`. It works in both a node and browser environment (Angular etc). Now, the packer returns a `Buffer`, `Blob` or `base64 string`. It is up to you to take that and persist it with node's `fs`, send it down as a downloadable file, or anything else you wish. As of version 4, this library will not have options to export to PDF.
## Version 5
Packers in `version 5` and above are now static methods on `Packer`.
### Export as Buffer ### Export as Buffer
This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead. This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead.
```js ```ts
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync("My Document.docx", buffer);
});
```
### Export as a `base64` string
```ts
Packer.toBase64String(doc).then((string) => {
console.log(string);
});
```
### Export as Blob
This is useful if you want to send it as an downloadable in a browser environment.
```ts
Packer.toBlob(doc).then((blob) => {
// saveAs from FileSaver will download the file
saveAs(blob, "example.docx");
});
```
## Version 4
The `Packer` in `version 4` requires an instance of `Packer`, so be sure to `new` it.
### Export as Buffer
This will return a NodeJS `Buffer`. If this is used in the browser, it will return a `UInt8Array` instead.
```ts
const packer = new docx.Packer(); const packer = new docx.Packer();
packer.toBuffer(doc).then((buffer) => { packer.toBuffer(doc).then((buffer) => {
@ -20,7 +55,7 @@ packer.toBuffer(doc).then((buffer) => {
### Export as a `base64` string ### Export as a `base64` string
```js ```ts
const packer = new docx.Packer(); const packer = new docx.Packer();
packer.toBase64String(doc).then((string) => { packer.toBase64String(doc).then((string) => {
@ -32,7 +67,7 @@ packer.toBase64String(doc).then((string) => {
This is useful if you want to send it as an downloadable in a browser environment. This is useful if you want to send it as an downloadable in a browser environment.
```js ```ts
const packer = new docx.Packer(); const packer = new docx.Packer();
packer.toBlob(doc).then((blob) => { packer.toBlob(doc).then((blob) => {
@ -45,7 +80,7 @@ packer.toBlob(doc).then((blob) => {
### File System Packer ### File System Packer
```js ```ts
const docx = require("docx"); const docx = require("docx");
const doc = new docx.Document(); const doc = new docx.Document();
@ -56,7 +91,7 @@ exporter.pack("My Document");
### Buffer Packer ### Buffer Packer
```js ```ts
const docx = require("docx"); const docx = require("docx");
const doc = new docx.Document(); const doc = new docx.Document();
@ -68,7 +103,7 @@ const buffer = exporter.pack();
Creates a `node` `Readable` stream Creates a `node` `Readable` stream
```js ```ts
const docx = require("docx"); const docx = require("docx");
const doc = new docx.Document(); const doc = new docx.Document();
@ -88,7 +123,7 @@ I used the express exporter in my [website](http://www.dolan.bio).
The recommended way is to use the `StreamPacker` and handle the `express` magic outside of the library: The recommended way is to use the `StreamPacker` and handle the `express` magic outside of the library:
```js ```ts
const docx = require("docx"); const docx = require("docx");
const doc = new docx.Document(); const doc = new docx.Document();
@ -107,7 +142,7 @@ where `res` is the response object obtained through the Express router. It is th
You can export your word document as a PDF file like so: You can export your word document as a PDF file like so:
```js ```ts
const exporter = new docx.LocalPacker(doc); const exporter = new docx.LocalPacker(doc);
exporter.packPdf("My Document"); exporter.packPdf("My Document");

View File

@ -2,28 +2,180 @@
> Everything (text, images, graphs etc) in OpenXML is organised in paragraphs. > Everything (text, images, graphs etc) in OpenXML is organised in paragraphs.
## Example !> Paragraphs requires an understanding of [Sections](usage/sections.md).
You can add more text to the paragraph by doing this: You can create `Paragraphs` in the following ways:
```js ### Shorthand
var paragraph = new docx.Paragraph(),
```ts
import { Paragraph } from "docx";
const paragraph = new Paragraph("Short hand Hello World");
``` ```
```js ### Children Method
var text = new docx.TextRun("Lorem Ipsum Foo Bar");
var paragraph = new docx.Paragraph(); This method is useful for adding different `text` with different styles or adding `images` inline.
paragraph.addRun(text);
```ts
const paragraph = new Paragraph({
children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")],
});
``` ```
```js ### Explicit
var paragraph = new docx.Paragraph("Short hand notation for adding text.");
```ts
const paragraph = new Paragraph({
text: "Short hand notation for adding text.",
});
``` ```
After you create the paragraph, you must add the paragraph into the `document`: After you create the paragraph, you must add the paragraph into the `document's section`. Learn more about `sections` here:
```js ```ts
doc.addParagraph(paragraph); doc.addSection({
children: [paragraph],
});
```
Or the preferred convension, define the paragraph inside the section and remove the usage of variables:
```ts
doc.addSection({
children: [
new Paragraph({
children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")],
}),
],
});
```
## Options
This is the list of options for a paragraph. A detailed explanation is below:
| Property | Type | Mandatory? | Possible Values |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- |
| [text](#text) | `string` | Optional | |
| [heading](#heading) | `HeadingLevel` | Optional | `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`, `TITLE` |
| [border](#border) | `IBorderOptions` | Optional | `top`, `bottom`, `left`, `right`. Each of these are of type IBorderPropertyOptions. Click here for Example |
| [spacing](#spacing) | `ISpacingProperties` | Optional | See below for ISpacingProperties |
| [outlineLevel](#outline-level) | `number` | Optional | |
| alignment | `AlignmentType` | Optional | |
| heading | `HeadingLevel` | Optional | |
| bidirectional | `boolean` | Optional | |
| thematicBreak | `boolean` | Optional | |
| pageBreakBefore | `boolean` | Optional | |
| contextualSpacing | `boolean` | Optional | |
| indent | `IIndentAttributesProperties` | Optional | |
| keepLines | `boolean` | Optional | |
| keepNext | `boolean` | Optional | |
| children | `(TextRun or PictureRun or Hyperlink)[]` | Optional | |
| style | `string` | Optional | |
| tabStop | `{ left?: ITabStopOptions; right?: ITabStopOptions; maxRight?: { leader: LeaderType; }; center?: ITabStopOptions }` | Optional | |
| bullet | `{ level: number }` | Optional | |
| numbering | `{ num: Num; level: number; custom?: boolean }` | Optional | |
## Text
This is the text in a paragraph. You can also add text by using the `Paragraph` shorthand (mentioned above) or adding `children`.
**Example:**
```ts
const paragraph = new Paragraph({
text: "Hello World",
});
```
## Heading
**Example:**
Setting a Heading 1 paragraph with "Hello World" as it's text:
```ts
const paragraph = new Paragraph({
text: "Hello World",
heading: HeadingLevel.HEADING_1,
});
```
## Border
Add borders to a `Paragraph`. Good for making the `Paragraph` stand out
#### IBorderPropertyOptions
`top`, `bottom`, `left`, `right` of the border
| Property | Type | Notes |
| -------- | -------- | -------- |
| color | `string` | Required |
| space | `number` | Required |
| value | `string` | Required |
| size | `number` | Required |
**Example:**
Add border on the top and the bottom of the paragraph
```ts
const paragraph = new Paragraph({
text: "I have borders on my top and bottom sides!",
border: {
top: {
color: "auto",
space: 1,
value: "single",
size: 6,
},
bottom: {
color: "auto",
space: 1,
value: "single",
size: 6,
},
},
});
```
## Spacing
Adding spacing between paragraphs
### ISpacingProperties
| Property | Type | Notes |
| -------- | -------- | -------- |
| after | `number` | Optional |
| before | `number` | Optional |
| line | `number` | Optional |
| lineRule | `string` | Optional |
**Example:**
Add spacing before the paragraph:
```ts
const paragraph = new Paragraph({
text: "Paragraph with spacing before",
spacing: {
before: 200,
},
});
```
## Outline Level
**Example:**
```ts
const paragraph = new Paragraph({
outlineLevel: 0,
});
``` ```
## Styles ## Styles
@ -32,46 +184,29 @@ To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/
![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu") ![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu")
### Heading1 - Heading5 ### Headings and titles
```js ```ts
paragraph.heading1(); import { HeadingLevel, Paragraph } from "docx";
paragraph.heading2();
paragraph.heading3();
paragraph.heading4();
paragraph.heading5();
```
### Title const paragraph = new Paragraph({
text: "Hello World",
```js heading: HeadingLevel.TITLE,
paragraph.title(); });
``` ```
## Text Alignment ## Text Alignment
To change the text alignment of a paragraph, for center, left, right or justified: To change the text alignment of a paragraph, add an `AlignmentType` option on the paragraph.for center, left, right or justified:
```js **Example:**
paragraph.center();
```
```js ```ts
paragraph.left(); const paragraph = new Paragraph({
``` text: "Hello World",
heading: HeadingLevel.HEADING_1,
```js alignment: AlignmentType.CENTER,
paragraph.right(); });
```
```js
paragraph.justified();
```
### Example
```js
paragraph.heading1().center();
``` ```
The above will create a `heading 1` which is `centered`. The above will create a `heading 1` which is `centered`.
@ -94,10 +229,15 @@ The result is:
## Thematic Break ## Thematic Break
To add a break in the page, simply add `.thematicBreak()` on a paragraph: To add a thematic break in the `Paragraph`:
```js ```ts
var paragraph = new docx.Paragraph("Amazing Heading").heading1().thematicBreak(); const paragraph = new docx.Paragraph("Amazing Heading");
const paragraph = new Paragraph({
text: "Amazing Heading",
heading: HeadingLevel.HEADING_1,
thematicBreak: true,
});
``` ```
The above example will create a heading with a page break directly under it. The above example will create a heading with a page break directly under it.
@ -106,8 +246,8 @@ The above example will create a heading with a page break directly under it.
To move to a new page (insert a page break), simply add `.pageBreak()` on a paragraph: To move to a new page (insert a page break), simply add `.pageBreak()` on a paragraph:
```js ```ts
var paragraph = new docx.Paragraph("Amazing Heading").heading1().pageBreak(); const paragraph = new docx.Paragraph("Amazing Heading").pageBreak();
``` ```
The above example will create a heading and start a new page immediately afterwards. The above example will create a heading and start a new page immediately afterwards.
@ -116,8 +256,11 @@ The above example will create a heading and start a new page immediately afterwa
This option (available in word) will make sure that the paragraph will start on a new page (if it's not already on a new page). This option (available in word) will make sure that the paragraph will start on a new page (if it's not already on a new page).
```js ```ts
var paragraph = new docx.Paragraph("Hello World on another page").pageBreakBefore(); const paragraph = new Paragraph({
text: "Hello World on another page",
pageBreakBefore: true,
});
``` ```
![Page Break Before in Word](https://user-images.githubusercontent.com/34742290/40176503-df3a8398-59db-11e8-8b9c-d719f13aa8b4.png) ![Page Break Before in Word](https://user-images.githubusercontent.com/34742290/40176503-df3a8398-59db-11e8-8b9c-d719f13aa8b4.png)

21
docs/usage/sections.md Normal file
View File

@ -0,0 +1,21 @@
# Sections
> Every document is made up of one or more sections
A section is a grouping of paragraphs that have a specific set of properties used to define the pages on which the text will appear. Properties include page size, page numbers, page orientation, headers, borders and margins.
For example, you could have one section which is portrait with a header and footer, and another section in landscape with no footer, and a header showing the current page number.
## Example
This creates a simple section in a document with one paragraph inside:
```ts
doc.addSection({
children: [
new Paragraph({
children: [new TextRun("Hello World")],
}),
],
});
```

View File

@ -2,7 +2,7 @@
## Example ## Example
```js ```ts
const para = new Paragraph("To whom it may concern:").heading2().center(); const para = new Paragraph("To whom it may concern:").heading2().center();
const name = new TextRun("Name:") const name = new TextRun("Name:")
@ -56,7 +56,7 @@ Unlike CSS, less specific rules don't _necessarily_ override parent rules. The r
This is the type of formatting that your uncle uses when he types out documents: _N ... a ... m ... e ... :_ Then he grabs the mouse, highlights _Name:_ and moves over to the **B** for bold. This manner of formatting results in markup that is similar to writing `<span style="bold: true">Name:</span>` if you were typing out HTML. DOCX (the format) allows you to specify this for any of the four types of items. `docx` (the library) only supports this type of formatting for paragraphs and characters, using a _fluent_ api. Thus you could do: This is the type of formatting that your uncle uses when he types out documents: _N ... a ... m ... e ... :_ Then he grabs the mouse, highlights _Name:_ and moves over to the **B** for bold. This manner of formatting results in markup that is similar to writing `<span style="bold: true">Name:</span>` if you were typing out HTML. DOCX (the format) allows you to specify this for any of the four types of items. `docx` (the library) only supports this type of formatting for paragraphs and characters, using a _fluent_ api. Thus you could do:
```js ```ts
const name = new TextRun("Name:") const name = new TextRun("Name:")
.bold() .bold()
.font("Calibri") .font("Calibri")
@ -65,7 +65,7 @@ const name = new TextRun("Name:")
Or for paragraph formatting: Or for paragraph formatting:
```js ```ts
const para = new Paragraph("To whom it may concern:").heading2().center(); const para = new Paragraph("To whom it may concern:").heading2().center();
``` ```
@ -76,12 +76,12 @@ DOCX files contain a styles section separate from the main content, much like ho
There are three parts to using custom styles with `docx`: There are three parts to using custom styles with `docx`:
1. Create a container object for the style definitions: 1. Create a container object for the style definitions:
```js ```ts
const myStyles = new docx.Styles(); const myStyles = new docx.Styles();
``` ```
2. Define your custom styles, similar to the way you would format a paragraph or run 2. Define your custom styles, similar to the way you would format a paragraph or run
```js ```ts
// The first argument is an ID you use to apply the style to paragraphs // The first argument is an ID you use to apply the style to paragraphs
// The second argument is a human-friendly name to show in the UI // The second argument is a human-friendly name to show in the UI
myStyles myStyles
@ -106,9 +106,8 @@ There are three parts to using custom styles with `docx`:
3. When you generate your document, make sure to pass the `styles` container to the `Packer`: 3. When you generate your document, make sure to pass the `styles` container to the `Packer`:
```js ```ts
const packer = new Packer(doc, myStyles); Packer.pack(myOutStream);
packer.pack(myOutStream);
``` ```
**Note**: If you are using the `.headingX` or `.title` methods of paragraphs, you must make sure to define `HeadingX` or `Title` styles for these. Otherwise they'll show up unstyled :(. If you are using the `.bullet` or `.setNumbering` methods, you need to define a `ListParagraph` style or the numbers may not show up. **Note**: If you are using the `.headingX` or `.title` methods of paragraphs, you must make sure to define `HeadingX` or `Title` styles for these. Otherwise they'll show up unstyled :(. If you are using the `.bullet` or `.setNumbering` methods, you need to define a `ListParagraph` style or the numbers may not show up.

View File

@ -24,7 +24,7 @@
Read the styles using `fs`, and put it into the `Document` object in the constructor: Read the styles using `fs`, and put it into the `Document` object in the constructor:
```js ```ts
const styles = fs.readFileSync("./styles.xml", "utf-8"); const styles = fs.readFileSync("./styles.xml", "utf-8");
const doc = new docx.Document({ const doc = new docx.Document({
title: "Title", title: "Title",
@ -34,12 +34,12 @@ const doc = new docx.Document({
You can use paragraphs, `heading1()`, `heading2()` etc and it will be styled according to your `styles.xml` created earlier. You can even use your new style you made by calling the `style` method: You can use paragraphs, `heading1()`, `heading2()` etc and it will be styled according to your `styles.xml` created earlier. You can even use your new style you made by calling the `style` method:
```js ```ts
doc.createParagraph("Cool Heading Text").heading1(); doc.createParagraph("Cool Heading Text").heading1();
let paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"'); const paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"');
paragraph.style("Cool New Style"); paragraph.style("Cool New Style");
doc.addParagraph(paragraph); doc.add(paragraph);
doc.createParagraph("Some normal text"); doc.createParagraph("Some normal text");
``` ```

View File

@ -10,45 +10,45 @@ Simply call the relevant methods on the paragraph listed below. Then just add a
## Example ## Example
```js ```ts
var paragraph = new docx.Paragraph().maxRightTabStop(); const paragraph = new docx.Paragraph().maxRightTabStop();
var leftText = new docx.TextRun("Hey everyone").bold(); const leftText = new docx.TextRun("Hey everyone").bold();
var rightText = new docx.TextRun("11th November 2015").tab(); const rightText = new docx.TextRun("11th November 2015").tab();
paragraph.addRun(leftText); paragraph.addRun(leftText);
paragraph.addRun(rightText); paragraph.addRun(rightText);
``` ```
The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. YUK! The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. YUK!
```js ```ts
var paragraph = new docx.Paragraph(); const paragraph = new docx.Paragraph();
paragraph.maxRightTabStop(); paragraph.maxRightTabStop();
paragraph.leftTabStop(1000); paragraph.leftTabStop(1000);
var text = new docx.TextRun("Second tab stop here I come!").tab().tab(); const text = new docx.TextRun("Second tab stop here I come!").tab().tab();
paragraph.addRun(text); paragraph.addRun(text);
``` ```
The above shows the use of two tab stops, and how to select/use it. The above shows the use of two tab stops, and how to select/use it.
## Left Tab Stop ## Left Tab Stop
```js ```ts
paragraph.leftTabStop(2268); paragraph.leftTabStop(2268);
``` ```
2268 is the distance from the left side. 2268 is the distance from the left side.
## Center Tab Stop ## Center Tab Stop
```js ```ts
paragraph.centerTabStop(2268); paragraph.centerTabStop(2268);
``` ```
2268 is the distance from the left side. 2268 is the distance from the left side.
## Right Tab Stop ## Right Tab Stop
```js ```ts
paragraph.rightTabStop(2268); paragraph.rightTabStop(2268);
``` ```
2268 is the distance from the left side. 2268 is the distance from the left side.
## Max Right Tab Stop ## Max Right Tab Stop
```js ```ts
paragraph.maxRightTabStop(); paragraph.maxRightTabStop();
``` ```
This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line. This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line.

View File

@ -12,7 +12,7 @@ The complete documentation can be found [here](https://www.ecma-international.or
All you need to do is create a `TableOfContents` object and assign it to the document. All you need to do is create a `TableOfContents` object and assign it to the document.
```js ```ts
const toc = new TableOfContents("Summary", { const toc = new TableOfContents("Summary", {
hyperlink: true, hyperlink: true,
headingStyleRange: "1-5", headingStyleRange: "1-5",
@ -47,7 +47,7 @@ Here is the list of all options that you can use to generate your tables of cont
## Examples ## Examples
```js ```ts
// Let's define the options for generate a TOC for heading 1-5 and MySpectacularStyle, // Let's define the options for generate a TOC for heading 1-5 and MySpectacularStyle,
// making the entries be hyperlinks for the paragraph // making the entries be hyperlinks for the paragraph
const toc = new TableOfContents("Summary", { const toc = new TableOfContents("Summary", {
@ -58,15 +58,15 @@ const toc = new TableOfContents("Summary", {
doc.addTableOfContents(toc); doc.addTableOfContents(toc);
doc.addParagraph(new Paragraph("Header #1").heading1().pageBreakBefore()); doc.add(new Paragraph("Header #1").heading1().pageBreakBefore());
doc.addParagraph(new Paragraph("I'm a little text, very nicely written.'")); doc.add(new Paragraph("I'm a little text, very nicely written.'"));
doc.addParagraph(new Paragraph("Header #2").heading1().pageBreakBefore()); doc.add(new Paragraph("Header #2").heading1().pageBreakBefore());
doc.addParagraph(new Paragraph("I'm another text very nicely written.'")); doc.add(new Paragraph("I'm another text very nicely written.'"));
doc.addParagraph(new Paragraph("Header #2.1").heading2()); doc.add(new Paragraph("Header #2.1").heading2());
doc.addParagraph(new Paragraph("I'm another text very nicely written.'")); doc.add(new Paragraph("I'm another text very nicely written.'"));
doc.addParagraph(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore()); doc.add(new Paragraph("My Spectacular Style #1").style("MySpectacularStyle").pageBreakBefore());
``` ```
### Complete example ### Complete example

View File

@ -4,28 +4,30 @@ You can create tables with `docx`. More information can be found [here](http://o
## Create Table ## Create Table
To create a table, simply use the `createTable()` method on a `document`. To create a table, simply create one with `new Table()`, then add it to the document: `doc.add()`.
```ts ```ts
const table = doc.createTable([NUMBER OF ROWS], [NUMBER OF COLUMNS]); const table = doc.add(new Table({
rows: [NUMBER OF ROWS],
columns: [NUMBER OF COLUMNS]
});
``` ```
Alternatively, you can create a table object directly, and then add it in the `document` Alternatively, you can create a table object directly, and then add it in the `document`
```ts ```ts
const table = new Table(4, 4); const table = new Table(4, 4);
doc.addTable(table); doc.add(table);
``` ```
The snippet below creates a table of 2 rows and 4 columns. The snippet below creates a table of 2 rows and 4 columns.
```ts ```ts
const table = doc.createTable(2, 4); const table = new Table({
rows: 2,
// Or columns: 4,
});
const table = new Table(2, 4); doc.add(table);
doc.addTable(table);
``` ```
## Rows and Columns ## Rows and Columns
@ -70,7 +72,7 @@ column.getCell(index);
## Cells ## Cells
The `createTable()` method created a table with cells. To access the cell, use the `getCell()` method. To access the cell, use the `getCell()` method.
```ts ```ts
const cell = table.getCell([ROW INDEX], [COLUMN INDEX]); const cell = table.getCell([ROW INDEX], [COLUMN INDEX]);
@ -90,10 +92,10 @@ const cell = column.getCell(2);
### Add paragraph to a cell ### Add paragraph to a cell
Once you have got the cell, you can add data to it with the `addParagraph()` method. Once you have got the cell, you can add data to it with the `add()` method.
```ts ```ts
cell.addParagraph(new Paragraph("Hello")); cell.add(new Paragraph("Hello"));
``` ```
### Set width of a cell ### Set width of a cell
@ -103,10 +105,11 @@ You can specify the width of a cell using:
`cell.Properties.setWidth(width, format)` `cell.Properties.setWidth(width, format)`
format can be: format can be:
* WidthType.AUTO
* WidthType.DXA: value is in twentieths of a point - WidthType.AUTO
* WidthType.NIL: is considered as zero - WidthType.DXA: value is in twentieths of a point
* WidthType.PCT: percent of table width - WidthType.NIL: is considered as zero
- WidthType.PCT: percent of table width
### Example ### Example
@ -115,7 +118,7 @@ cell.Properties.setWidth(100, WidthType.DXA);
``` ```
```ts ```ts
cell.Properties.setWidth('50%', WidthType.PCT); cell.Properties.setWidth("50%", WidthType.PCT);
``` ```
## Borders ## Borders
@ -223,7 +226,7 @@ It has not been implemented yet, but it will follow a similar structure as mergi
To have a table within a table To have a table within a table
```ts ```ts
cell.addTable(new Table(1, 1)); cell.add(new Table(1, 1));
``` ```
## Pagination ## Pagination
@ -241,11 +244,10 @@ If a table is paginated on multiple pages, it is possible to repeat a row at the
```ts ```ts
table.getRow(0).setTableHeader(); table.getRow(0).setTableHeader();
``` ```
## Examples ## Examples
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo4.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_
@ -253,7 +255,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo4.ts_
Example showing how to add colourful borders to tables Example showing how to add colourful borders to tables
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo20.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_
@ -261,11 +263,11 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo20.ts_
Example showing how to add images to tables Example showing how to add images to tables
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo24.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo24.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo24.ts_
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo36.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo36.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo36.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo36.ts_
@ -273,7 +275,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo36.ts_
Example showing how align text in a table cell Example showing how align text in a table cell
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo31.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo31.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo31.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo31.ts_
@ -281,11 +283,11 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo31.ts_
Example showing merging of `rows` Example showing merging of `rows`
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo32.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo32.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo32.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo32.ts_
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo41.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo41.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo41.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo41.ts_
@ -293,13 +295,12 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo41.ts_
Example showing merging of `columns` Example showing merging of `columns`
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo43.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo43.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo43.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo43.ts_
### Floating tables ### Floating tables
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo34.ts ':include') [Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo34.ts ":include")
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo34.ts_ _Source: https://github.com/dolanmiu/docx/blob/master/demo/demo34.ts_

View File

@ -1,10 +1,15 @@
# Text # Text Runs
Paragraphs need `text run` objects. To create text: !> TextRuns requires an understanding of [Paragraphs](usage/paragraph.md).
```js You can add multiple `text runs` in `Paragraphs`. This is the most verbose way of writing a `Paragraph` but it is also the most flexible:
var text = new docx.TextRun("My awesome text here for my university dissertation");
paragraph.addRun(text); ```ts
import { Paragraph, TextRun } from "docx";
const paragraph = new Paragraph({
children: [new TextRun("My awesome text here for my university dissertation"), new TextRun("Foo Bar")],
});
``` ```
Text objects have methods inside which changes the way the text is displayed. Text objects have methods inside which changes the way the text is displayed.
@ -15,55 +20,87 @@ More info [here](https://english.stackexchange.com/questions/97081/what-is-the-t
### Bold ### Bold
```js ```ts
text.bold(); const text = new TextRun({
text: "Foo Bar",
bold: true,
});
``` ```
### Italics ### Italics
```js ```ts
text.italics(); const text = new TextRun({
text: "Foo Bar",
italics: true,
});
``` ```
### Underline ### Underline
```js Underline has a few options
text.underline();
#### Options
| Property | Type | Notes | Possible Values |
| -------- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type | `UnderlineType` | Optional | SINGLE, WORD, DOUBLE, THICK, DOTTED, DOTTEDHEAV, DASH, DASHEDHEAV, DASHLONG, DASHLONGHEAV, DOTDASH, DASHDOTHEAVY, DOTDOTDAS, DASHDOTDOTHEAVY, WAVE, WAVYHEAVY, WAVYDOUBLE |
| color | `string` | Optional | Color Hex values |
**Example:**
```ts
const text = new TextRun({
text: "and then underlined ",
underline: {
type: UnderlineType.DOUBLE,
color: "990011",
},
});
```
To do a simple vanilla underline:
```ts
const text = new TextRun({
text: "and then underlined ",
underline: {},
});
``` ```
### Strike through ### Strike through
```js ```ts
text.strike(); text.strike();
``` ```
### Double strike through ### Double strike through
```js ```ts
text.doubleStrike(); text.doubleStrike();
``` ```
### Superscript ### Superscript
```js ```ts
text.superScript(); text.superScript();
``` ```
### Subscript ### Subscript
```js ```ts
text.subScript(); text.subScript();
``` ```
### All Capitals ### All Capitals
```js ```ts
text.allCaps(); text.allCaps();
``` ```
### Small Capitals ### Small Capitals
```js ```ts
text.smallCaps(); text.smallCaps();
``` ```
@ -71,7 +108,7 @@ text.smallCaps();
Sometimes you would want to put text underneath another line of text but inside the same paragraph. Sometimes you would want to put text underneath another line of text but inside the same paragraph.
```js ```ts
text.break(); text.break();
``` ```
@ -79,6 +116,6 @@ text.break();
What if you want to create a paragraph which is **_bold_** and **_italic_**? What if you want to create a paragraph which is **_bold_** and **_italic_**?
```js ```ts
paragraph.bold().italics(); paragraph.bold().italics();
``` ```

View File

@ -1,6 +1,6 @@
{ {
"name": "docx", "name": "docx",
"version": "5.0.0-rc3", "version": "5.0.0-rc5",
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {
@ -68,7 +68,7 @@
"@types/webpack": "^4.4.24", "@types/webpack": "^4.4.24",
"awesome-typescript-loader": "^3.4.1", "awesome-typescript-loader": "^3.4.1",
"chai": "^3.5.0", "chai": "^3.5.0",
"docsify": "^4.9.1", "docsify-cli": "^4.3.0",
"glob": "^7.1.2", "glob": "^7.1.2",
"istanbul-instrumenter-loader": "^3.0.1", "istanbul-instrumenter-loader": "^3.0.1",
"jszip": "^3.1.5", "jszip": "^3.1.5",

View File

@ -1,10 +1,9 @@
import { assert } from "chai"; import { assert, expect } from "chai";
import { Formatter } from "../export/formatter"; import { Formatter } from "export/formatter";
import * as file from "../file"; import * as file from "file";
import { CoreProperties } from "../file/core-properties"; import { CoreProperties } from "file/core-properties";
import { Attributes } from "../file/xml-components"; import { Attributes } from "file/xml-components";
import { Utility } from "../tests/utility";
describe("Formatter", () => { describe("Formatter", () => {
let formatter: Formatter; let formatter: Formatter;
@ -15,53 +14,56 @@ describe("Formatter", () => {
describe("#format()", () => { describe("#format()", () => {
it("should format simple paragraph", () => { it("should format simple paragraph", () => {
const paragraph = new file.Paragraph(); const paragraph = new file.Paragraph("");
const newJson = formatter.format(paragraph); const newJson = formatter.format(paragraph);
assert.isDefined(newJson["w:p"]); assert.isDefined(newJson["w:p"]);
}); });
it("should remove xmlKeys", () => { it("should remove xmlKeys", () => {
const paragraph = new file.Paragraph(); const paragraph = new file.Paragraph("");
const newJson = formatter.format(paragraph); const newJson = formatter.format(paragraph);
const stringifiedJson = JSON.stringify(newJson); const stringifiedJson = JSON.stringify(newJson);
assert(stringifiedJson.indexOf("xmlKeys") < 0); assert(stringifiedJson.indexOf("xmlKeys") < 0);
}); });
it("should format simple paragraph with bold text", () => { it("should format simple paragraph with bold text", () => {
const paragraph = new file.Paragraph(); const paragraph = new file.Paragraph("");
paragraph.addRun(new file.TextRun("test").bold()); paragraph.addRun(
new file.TextRun({
text: "test",
bold: true,
}),
);
const newJson = formatter.format(paragraph); const newJson = formatter.format(paragraph);
assert.isDefined(newJson["w:p"][0]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]); assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"]._attr["w:val"]);
}); });
it("should format attributes (rsidSect)", () => { it("should format attributes (rsidSect)", () => {
const attributes = new Attributes({ const attributes = new Attributes({
rsidSect: "test2", rsidSect: "test2",
}); });
let newJson = formatter.format(attributes); const tree = formatter.format(attributes);
newJson = Utility.jsonify(newJson); expect(tree).to.deep.equal({
if (newJson._attr === undefined) { _attr: {
assert.fail(); "w:rsidSect": "test2",
return; },
} });
assert.isDefined(newJson._attr["w:rsidSect"]);
}); });
it("should format attributes (val)", () => { it("should format attributes (val)", () => {
const attributes = new Attributes({ const attributes = new Attributes({
val: "test", val: "test",
}); });
let newJson = formatter.format(attributes); const tree = formatter.format(attributes);
newJson = Utility.jsonify(newJson); expect(tree).to.deep.equal({
if (newJson._attr === undefined) { _attr: {
assert.fail(); "w:val": "test",
return; },
} });
assert.isDefined(newJson._attr["w:val"]);
}); });
it("should should change 'p' tag into 'w:p' tag", () => { it("should should change 'p' tag into 'w:p' tag", () => {
const paragraph = new file.Paragraph(); const paragraph = new file.Paragraph("");
const newJson = formatter.format(paragraph); const newJson = formatter.format(paragraph);
assert.isDefined(newJson["w:p"]); assert.isDefined(newJson["w:p"]);
}); });

View File

@ -1,7 +1,7 @@
/* tslint:disable:typedef space-before-function-paren */ /* tslint:disable:typedef space-before-function-paren */
import { expect } from "chai"; import { expect } from "chai";
import { File } from "file"; import { File, Footer, Header } from "file";
import { Compiler } from "./next-compiler"; import { Compiler } from "./next-compiler";
@ -21,28 +21,39 @@ describe("Compiler", () => {
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
expect(fileNames).is.an.instanceof(Array); expect(fileNames).is.an.instanceof(Array);
expect(fileNames).has.length(18); expect(fileNames).has.length(14);
expect(fileNames).to.include("word/document.xml"); expect(fileNames).to.include("word/document.xml");
expect(fileNames).to.include("word/styles.xml"); expect(fileNames).to.include("word/styles.xml");
expect(fileNames).to.include("docProps/core.xml"); expect(fileNames).to.include("docProps/core.xml");
expect(fileNames).to.include("docProps/app.xml"); expect(fileNames).to.include("docProps/app.xml");
expect(fileNames).to.include("word/numbering.xml"); expect(fileNames).to.include("word/numbering.xml");
expect(fileNames).to.include("word/header1.xml");
expect(fileNames).to.include("word/_rels/header1.xml.rels");
expect(fileNames).to.include("word/footer1.xml");
expect(fileNames).to.include("word/footnotes.xml"); expect(fileNames).to.include("word/footnotes.xml");
expect(fileNames).to.include("word/settings.xml"); expect(fileNames).to.include("word/settings.xml");
expect(fileNames).to.include("word/_rels/footer1.xml.rels");
expect(fileNames).to.include("word/_rels/document.xml.rels"); expect(fileNames).to.include("word/_rels/document.xml.rels");
expect(fileNames).to.include("[Content_Types].xml"); expect(fileNames).to.include("[Content_Types].xml");
expect(fileNames).to.include("_rels/.rels"); expect(fileNames).to.include("_rels/.rels");
}); });
it("should pack all additional headers and footers", async function() { it("should pack all additional headers and footers", async function() {
file.createFooter(); file.addSection({
file.createFooter(); headers: {
file.createHeader(); default: new Header(),
file.createHeader(); },
footers: {
default: new Footer(),
},
children: [],
});
file.addSection({
headers: {
default: new Header(),
},
footers: {
default: new Footer(),
},
children: [],
});
this.timeout(99999999); this.timeout(99999999);
@ -50,20 +61,16 @@ describe("Compiler", () => {
const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name); const fileNames = Object.keys(zipFile.files).map((f) => zipFile.files[f].name);
expect(fileNames).is.an.instanceof(Array); expect(fileNames).is.an.instanceof(Array);
expect(fileNames).has.length(26); expect(fileNames).has.length(22);
expect(fileNames).to.include("word/header1.xml"); expect(fileNames).to.include("word/header1.xml");
expect(fileNames).to.include("word/_rels/header1.xml.rels"); expect(fileNames).to.include("word/_rels/header1.xml.rels");
expect(fileNames).to.include("word/header2.xml"); expect(fileNames).to.include("word/header2.xml");
expect(fileNames).to.include("word/_rels/header2.xml.rels"); expect(fileNames).to.include("word/_rels/header2.xml.rels");
expect(fileNames).to.include("word/header3.xml");
expect(fileNames).to.include("word/_rels/header3.xml.rels");
expect(fileNames).to.include("word/footer1.xml"); expect(fileNames).to.include("word/footer1.xml");
expect(fileNames).to.include("word/_rels/footer1.xml.rels"); expect(fileNames).to.include("word/_rels/footer1.xml.rels");
expect(fileNames).to.include("word/footer2.xml"); expect(fileNames).to.include("word/footer2.xml");
expect(fileNames).to.include("word/_rels/footer2.xml.rels"); expect(fileNames).to.include("word/_rels/footer2.xml.rels");
expect(fileNames).to.include("word/footer3.xml");
expect(fileNames).to.include("word/_rels/footer3.xml.rels");
}); });
}); });
}); });

View File

@ -36,9 +36,9 @@ export class Compiler {
this.imageReplacer = new ImageReplacer(); this.imageReplacer = new ImageReplacer();
} }
public compile(file: File): JSZip { public compile(file: File, prettifyXml?: boolean): JSZip {
const zip = new JSZip(); const zip = new JSZip();
const xmlifiedFileMapping = this.xmlifyFile(file); const xmlifiedFileMapping = this.xmlifyFile(file, prettifyXml);
for (const key in xmlifiedFileMapping) { for (const key in xmlifiedFileMapping) {
if (!xmlifiedFileMapping[key]) { if (!xmlifiedFileMapping[key]) {
@ -64,14 +64,14 @@ export class Compiler {
return zip; return zip;
} }
private xmlifyFile(file: File): IXmlifyedFileMapping { private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping {
file.verifyUpdateFields(); file.verifyUpdateFields();
const documentRelationshipCount = file.DocumentRelationships.RelationshipCount + 1; const documentRelationshipCount = file.DocumentRelationships.RelationshipCount + 1;
return { return {
Relationships: { Relationships: {
data: (() => { data: (() => {
const xmlData = xml(this.formatter.format(file.Document)); const xmlData = xml(this.formatter.format(file.Document), prettify);
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
mediaDatas.forEach((mediaData, i) => { mediaDatas.forEach((mediaData, i) => {
@ -82,13 +82,13 @@ export class Compiler {
); );
}); });
return xml(this.formatter.format(file.DocumentRelationships)); return xml(this.formatter.format(file.DocumentRelationships), prettify);
})(), })(),
path: "word/_rels/document.xml.rels", path: "word/_rels/document.xml.rels",
}, },
Document: { Document: {
data: (() => { data: (() => {
const tempXmlData = xml(this.formatter.format(file.Document), true); const tempXmlData = xml(this.formatter.format(file.Document), prettify);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, documentRelationshipCount); const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, documentRelationshipCount);
@ -97,7 +97,7 @@ export class Compiler {
path: "word/document.xml", path: "word/document.xml",
}, },
Styles: { Styles: {
data: xml(this.formatter.format(file.Styles)), data: xml(this.formatter.format(file.Styles), prettify),
path: "word/styles.xml", path: "word/styles.xml",
}, },
Properties: { Properties: {
@ -110,15 +110,15 @@ export class Compiler {
path: "docProps/core.xml", path: "docProps/core.xml",
}, },
Numbering: { Numbering: {
data: xml(this.formatter.format(file.Numbering)), data: xml(this.formatter.format(file.Numbering), prettify),
path: "word/numbering.xml", path: "word/numbering.xml",
}, },
FileRelationships: { FileRelationships: {
data: xml(this.formatter.format(file.FileRelationships)), data: xml(this.formatter.format(file.FileRelationships), prettify),
path: "_rels/.rels", path: "_rels/.rels",
}, },
HeaderRelationships: file.Headers.map((headerWrapper, index) => { HeaderRelationships: file.Headers.map((headerWrapper, index) => {
const xmlData = xml(this.formatter.format(headerWrapper.Header)); const xmlData = xml(this.formatter.format(headerWrapper.Header), prettify);
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
mediaDatas.forEach((mediaData, i) => { mediaDatas.forEach((mediaData, i) => {
@ -130,12 +130,12 @@ export class Compiler {
}); });
return { return {
data: xml(this.formatter.format(headerWrapper.Relationships)), data: xml(this.formatter.format(headerWrapper.Relationships), prettify),
path: `word/_rels/header${index + 1}.xml.rels`, path: `word/_rels/header${index + 1}.xml.rels`,
}; };
}), }),
FooterRelationships: file.Footers.map((footerWrapper, index) => { FooterRelationships: file.Footers.map((footerWrapper, index) => {
const xmlData = xml(this.formatter.format(footerWrapper.Footer)); const xmlData = xml(this.formatter.format(footerWrapper.Footer), prettify);
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
mediaDatas.forEach((mediaData, i) => { mediaDatas.forEach((mediaData, i) => {
@ -147,12 +147,12 @@ export class Compiler {
}); });
return { return {
data: xml(this.formatter.format(footerWrapper.Relationships)), data: xml(this.formatter.format(footerWrapper.Relationships), prettify),
path: `word/_rels/footer${index + 1}.xml.rels`, path: `word/_rels/footer${index + 1}.xml.rels`,
}; };
}), }),
Headers: file.Headers.map((headerWrapper, index) => { Headers: file.Headers.map((headerWrapper, index) => {
const tempXmlData = xml(this.formatter.format(headerWrapper.Header)); const tempXmlData = xml(this.formatter.format(headerWrapper.Header), prettify);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own // TODO: 0 needs to be changed when headers get relationships of their own
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
@ -163,7 +163,7 @@ export class Compiler {
}; };
}), }),
Footers: file.Footers.map((footerWrapper, index) => { Footers: file.Footers.map((footerWrapper, index) => {
const tempXmlData = xml(this.formatter.format(footerWrapper.Footer)); const tempXmlData = xml(this.formatter.format(footerWrapper.Footer), prettify);
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media); const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
// TODO: 0 needs to be changed when headers get relationships of their own // TODO: 0 needs to be changed when headers get relationships of their own
const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0); const xmlData = this.imageReplacer.replace(tempXmlData, mediaDatas, 0);
@ -174,19 +174,19 @@ export class Compiler {
}; };
}), }),
ContentTypes: { ContentTypes: {
data: xml(this.formatter.format(file.ContentTypes)), data: xml(this.formatter.format(file.ContentTypes), prettify),
path: "[Content_Types].xml", path: "[Content_Types].xml",
}, },
AppProperties: { AppProperties: {
data: xml(this.formatter.format(file.AppProperties)), data: xml(this.formatter.format(file.AppProperties), prettify),
path: "docProps/app.xml", path: "docProps/app.xml",
}, },
FootNotes: { FootNotes: {
data: xml(this.formatter.format(file.FootNotes)), data: xml(this.formatter.format(file.FootNotes), prettify),
path: "word/footnotes.xml", path: "word/footnotes.xml",
}, },
Settings: { Settings: {
data: xml(this.formatter.format(file.Settings)), data: xml(this.formatter.format(file.Settings), prettify),
path: "word/settings.xml", path: "word/settings.xml",
}, },
}; };

View File

@ -2,12 +2,11 @@
import { assert } from "chai"; import { assert } from "chai";
import { stub } from "sinon"; import { stub } from "sinon";
import { File, Paragraph } from "file"; import { File, HeadingLevel, Paragraph } from "file";
import { Packer } from "./packer"; import { Packer } from "./packer";
describe("Packer", () => { describe("Packer", () => {
let packer: Packer;
let file: File; let file: File;
beforeEach(() => { beforeEach(() => {
@ -16,21 +15,30 @@ describe("Packer", () => {
revision: "1", revision: "1",
lastModifiedBy: "Dolan Miu", lastModifiedBy: "Dolan Miu",
}); });
const paragraph = new Paragraph("test text");
const heading = new Paragraph("Hello world").heading1();
file.addParagraph(new Paragraph("title").title()); file.addSection({
file.addParagraph(heading); children: [
file.addParagraph(new Paragraph("heading 2").heading2()); new Paragraph({
file.addParagraph(paragraph); text: "title",
heading: HeadingLevel.TITLE,
packer = new Packer(); }),
new Paragraph({
text: "Hello world",
heading: HeadingLevel.HEADING_1,
}),
new Paragraph({
text: "heading 2",
heading: HeadingLevel.HEADING_2,
}),
new Paragraph("test text"),
],
});
}); });
describe("#toBuffer()", () => { describe("#toBuffer()", () => {
it("should create a standard docx file", async function() { it("should create a standard docx file", async function() {
this.timeout(99999999); this.timeout(99999999);
const buffer = await packer.toBuffer(file); const buffer = await Packer.toBuffer(file);
assert.isDefined(buffer); assert.isDefined(buffer);
assert.isTrue(buffer.byteLength > 0); assert.isTrue(buffer.byteLength > 0);
@ -38,19 +46,24 @@ describe("Packer", () => {
it("should handle exception if it throws any", () => { it("should handle exception if it throws any", () => {
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
const compiler = stub((packer as any).compiler, "compile"); const compiler = stub((Packer as any).compiler, "compile");
compiler.throwsException(); compiler.throwsException();
return packer.toBuffer(file).catch((error) => { return Packer.toBuffer(file).catch((error) => {
assert.isDefined(error); assert.isDefined(error);
}); });
}); });
after(() => {
// tslint:disable-next-line:no-any
(Packer as any).compiler.compile.restore();
});
}); });
describe("#toBase64String()", () => { describe("#toBase64String()", () => {
it("should create a standard docx file", async function() { it("should create a standard docx file", async function() {
this.timeout(99999999); this.timeout(99999999);
const str = await packer.toBase64String(file); const str = await Packer.toBase64String(file);
assert.isDefined(str); assert.isDefined(str);
assert.isTrue(str.length > 0); assert.isTrue(str.length > 0);
@ -58,12 +71,17 @@ describe("Packer", () => {
it("should handle exception if it throws any", () => { it("should handle exception if it throws any", () => {
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
const compiler = stub((packer as any).compiler, "compile"); const compiler = stub((Packer as any).compiler, "compile");
compiler.throwsException(); compiler.throwsException();
return packer.toBase64String(file).catch((error) => { return Packer.toBase64String(file).catch((error) => {
assert.isDefined(error); assert.isDefined(error);
}); });
}); });
after(() => {
// tslint:disable-next-line:no-any
(Packer as any).compiler.compile.restore();
});
}); });
}); });

View File

@ -2,14 +2,8 @@ import { File } from "file";
import { Compiler } from "./next-compiler"; import { Compiler } from "./next-compiler";
export class Packer { export class Packer {
private readonly compiler: Compiler; public static async toBuffer(file: File, prettify?: boolean): Promise<Buffer> {
const zip = this.compiler.compile(file, prettify);
constructor() {
this.compiler = new Compiler();
}
public async toBuffer(file: File): Promise<Buffer> {
const zip = this.compiler.compile(file);
const zipData = (await zip.generateAsync({ const zipData = (await zip.generateAsync({
type: "nodebuffer", type: "nodebuffer",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@ -18,8 +12,8 @@ export class Packer {
return zipData; return zipData;
} }
public async toBase64String(file: File): Promise<string> { public static async toBase64String(file: File, prettify?: boolean): Promise<string> {
const zip = this.compiler.compile(file); const zip = this.compiler.compile(file, prettify);
const zipData = (await zip.generateAsync({ const zipData = (await zip.generateAsync({
type: "base64", type: "base64",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@ -28,8 +22,8 @@ export class Packer {
return zipData; return zipData;
} }
public async toBlob(file: File): Promise<Blob> { public static async toBlob(file: File, prettify?: boolean): Promise<Blob> {
const zip = this.compiler.compile(file); const zip = this.compiler.compile(file, prettify);
const zipData = (await zip.generateAsync({ const zipData = (await zip.generateAsync({
type: "blob", type: "blob",
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@ -37,4 +31,6 @@ export class Packer {
return zipData; return zipData;
} }
private static readonly compiler = new Compiler();
} }

View File

@ -11,35 +11,7 @@ describe("Body", () => {
body = new Body(); body = new Body();
}); });
describe("#constructor()", () => {
it("should create default section", () => {
const formatted = new Formatter().format(body)["w:body"][0];
expect(formatted)
.to.have.property("w:sectPr")
.and.to.be.an.instanceof(Array);
expect(formatted["w:sectPr"]).to.have.length(4);
});
});
describe("#addSection", () => { describe("#addSection", () => {
it("should add section with options", () => {
body.addSection({
width: 10000,
height: 10000,
});
const formatted = new Formatter().format(body)["w:body"];
expect(formatted).to.be.an.instanceof(Array);
const defaultSectionPr = formatted[0]["w:p"][0]["w:pPr"][0]["w:sectPr"];
// check that this is the default section and added first in paragraph
expect(defaultSectionPr[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } } });
// check for new section (since it's the last one, it's direct child of body)
const newSection = formatted[1]["w:sectPr"];
expect(newSection[0]).to.deep.equal({ "w:pgSz": { _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } } });
});
it("should add section with default parameters", () => { it("should add section with default parameters", () => {
body.addSection({ body.addSection({
width: 10000, width: 10000,
@ -51,33 +23,7 @@ describe("Body", () => {
expect(tree).to.deep.equal({ expect(tree).to.deep.equal({
"w:body": [ "w:body": [
{ {
"w:p": [ "w:p": {},
{
"w:pPr": [
{
"w:sectPr": [
{ "w:pgSz": { _attr: { "w:w": 11906, "w:h": 16838, "w:orient": "portrait" } } },
{
"w:pgMar": {
_attr: {
"w:top": 1440,
"w:right": 1440,
"w:bottom": 1440,
"w:left": 1440,
"w:header": 708,
"w:footer": 708,
"w:gutter": 0,
"w:mirrorMargins": false,
},
},
},
{ "w:cols": { _attr: { "w:space": 708 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
],
},
],
},
],
}, },
{ {
"w:sectPr": [ "w:sectPr": [
@ -96,7 +42,7 @@ describe("Body", () => {
}, },
}, },
}, },
{ "w:cols": { _attr: { "w:space": 708 } } }, { "w:cols": { _attr: { "w:space": 708, "w:num": 1 } } },
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } }, { "w:docGrid": { _attr: { "w:linePitch": 360 } } },
], ],
}, },
@ -104,21 +50,4 @@ describe("Body", () => {
}); });
}); });
}); });
describe("#getParagraphs", () => {
it("should get no paragraphs", () => {
const paragraphs = body.getParagraphs();
expect(paragraphs).to.be.an.instanceof(Array);
});
});
describe("#DefaultSection", () => {
it("should get section", () => {
const section = body.DefaultSection;
const tree = new Formatter().format(section);
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
});
});
}); });

View File

@ -3,15 +3,10 @@ import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties"; import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
export class Body extends XmlComponent { export class Body extends XmlComponent {
private readonly defaultSection: SectionProperties;
private readonly sections: SectionProperties[] = []; private readonly sections: SectionProperties[] = [];
constructor(sectionPropertiesOptions?: SectionPropertiesOptions) { constructor() {
super("w:body"); super("w:body");
this.defaultSection = new SectionProperties(sectionPropertiesOptions);
this.sections.push(this.defaultSection);
} }
/** /**
@ -20,21 +15,15 @@ export class Body extends XmlComponent {
* The spec says: * The spec says:
* - section element should be in the last paragraph of the section * - section element should be in the last paragraph of the section
* - last section should be direct child of body * - last section should be direct child of body
* @param section new section * @param options new section options
*/ */
public addSection(section: SectionPropertiesOptions | SectionProperties): void { public addSection(options: SectionPropertiesOptions): void {
const currentSection = this.sections.pop() as SectionProperties; const currentSection = this.sections.pop() as SectionProperties;
this.root.push(this.createSectionParagraph(currentSection)); this.root.push(this.createSectionParagraph(currentSection));
if (section instanceof SectionProperties) {
this.sections.push(section); this.sections.push(new SectionProperties(options));
} else {
const params = {
...this.defaultSection.Options,
...section,
};
this.sections.push(new SectionProperties(params));
}
} }
public prepForXml(): IXmlableObject | undefined { public prepForXml(): IXmlableObject | undefined {
if (this.sections.length === 1) { if (this.sections.length === 1) {
this.root.push(this.sections.pop() as SectionProperties); this.root.push(this.sections.pop() as SectionProperties);
@ -47,21 +36,13 @@ export class Body extends XmlComponent {
this.root.push(component); this.root.push(component);
} }
public get DefaultSection(): SectionProperties {
return this.defaultSection;
}
public getTablesOfContents(): TableOfContents[] { public getTablesOfContents(): TableOfContents[] {
return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[]; return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[];
} }
public getParagraphs(): Paragraph[] {
return this.root.filter((child) => child instanceof Paragraph) as Paragraph[];
}
private createSectionParagraph(section: SectionProperties): Paragraph { private createSectionParagraph(section: SectionProperties): Paragraph {
const paragraph = new Paragraph(); const paragraph = new Paragraph({});
const properties = new ParagraphProperties(); const properties = new ParagraphProperties({});
properties.addChildElement(section); properties.addChildElement(section);
paragraph.addChildElement(properties); paragraph.addChildElement(properties);
return paragraph; return paragraph;

View File

@ -2,10 +2,12 @@ import { XmlAttributeComponent } from "file/xml-components";
export interface IColumnsAttributes { export interface IColumnsAttributes {
readonly space?: number; readonly space?: number;
readonly num?: number;
} }
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> { export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
protected readonly xmlKeys = { protected readonly xmlKeys = {
space: "w:space", space: "w:space",
num: "w:num",
}; };
} }

View File

@ -2,11 +2,12 @@ import { XmlComponent } from "file/xml-components";
import { ColumnsAttributes } from "./columns-attributes"; import { ColumnsAttributes } from "./columns-attributes";
export class Columns extends XmlComponent { export class Columns extends XmlComponent {
constructor(space: number) { constructor(space: number, num: number) {
super("w:cols"); super("w:cols");
this.root.push( this.root.push(
new ColumnsAttributes({ new ColumnsAttributes({
space: space, space: space,
num: num,
}), }),
); );
} }

View File

@ -1,13 +1,13 @@
import { XmlComponent } from "file/xml-components"; import { XmlComponent } from "file/xml-components";
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes"; import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
export interface IHeaderOptions { export interface IHeaderReferenceOptions {
readonly headerType?: HeaderReferenceType; readonly headerType?: HeaderReferenceType;
readonly headerId?: number; readonly headerId?: number;
} }
export class HeaderReference extends XmlComponent { export class HeaderReference extends XmlComponent {
constructor(options: IHeaderOptions) { constructor(options: IHeaderReferenceOptions) {
super("w:headerReference"); super("w:headerReference");
this.root.push( this.root.push(
new HeaderReferenceAttributes({ new HeaderReferenceAttributes({

Some files were not shown because too many files have changed in this diff Show More