Compare commits
158 Commits
Author | SHA1 | Date | |
---|---|---|---|
4d7bdc2ed9 | |||
d10c707f12 | |||
49cc8a267c | |||
68cb57aea6 | |||
9d7fd55e4c | |||
195c62f80b | |||
1fd222abea | |||
ac40e13e33 | |||
52e8fe576e | |||
b389ac6347 | |||
8108eca2fa | |||
8c613195f3 | |||
41f941728e | |||
ecf1542d95 | |||
06b2bbba25 | |||
0494fdeabd | |||
226206b100 | |||
02f80bc616 | |||
3189c9251a | |||
ae43137906 | |||
50bee30799 | |||
38484a3063 | |||
919327ed08 | |||
c00c5fa02d | |||
80f09ac10b | |||
ee721ffbec | |||
1dd1c65341 | |||
e593327fea | |||
64e0aeeb18 | |||
05816abc12 | |||
a954c69458 | |||
a0e034bd55 | |||
1a1c1f26d9 | |||
a102b479e6 | |||
5b5f5ea203 | |||
40a8e581f1 | |||
1b988e7135 | |||
9433c7aedc | |||
479dfed987 | |||
1866033128 | |||
844b9ab2ec | |||
e6713d6ce2 | |||
069ce73c07 | |||
6dda6a5513 | |||
329def42ac | |||
c5137b5fad | |||
ab05ccb846 | |||
cb8e9fdd36 | |||
53ce3c1526 | |||
a78f06b41b | |||
ce7ef30806 | |||
fd93c0776a | |||
6a762c6c0e | |||
23c5aef276 | |||
69707a7207 | |||
cfd3505414 | |||
ee958dc351 | |||
680f2325a3 | |||
2f0ad3eeb2 | |||
c895a9c7d9 | |||
388a8404f5 | |||
320cb1c418 | |||
8a6b73915f | |||
774355d608 | |||
35dbce3a68 | |||
6d0a267ba4 | |||
df701be572 | |||
1edad47e6e | |||
c873abfe18 | |||
989446ef36 | |||
fc6daed620 | |||
5e921f1dfc | |||
45bbf1b693 | |||
8b8c664f0f | |||
079334f71b | |||
3fe0c76d54 | |||
1e55a3e6a8 | |||
950a2f8b53 | |||
bbe2e1e46e | |||
635c58c131 | |||
ba39d806b7 | |||
355e97cb5e | |||
4339f8cfc0 | |||
448572d7a1 | |||
2132c7b6da | |||
d0bd83d6c5 | |||
1037b7c23d | |||
df197f73ea | |||
ea08f603f5 | |||
fa2f1235f7 | |||
ff5d02c964 | |||
e93d6799fd | |||
f2027230a0 | |||
cb47d4f772 | |||
eebc9fbcfa | |||
0e698491f3 | |||
ae52e8fabb | |||
ccd655ef8b | |||
3dc6e71aaf | |||
e6d3577f74 | |||
ef05024f2f | |||
d3bc784248 | |||
979701331e | |||
76b1682296 | |||
7c31b72f99 | |||
f7c2072cff | |||
392db1cd11 | |||
ca244bcfe1 | |||
2d02f51f25 | |||
592fb5ca9f | |||
a3945bc7f1 | |||
2adde9830c | |||
0355afe11c | |||
998fe3f370 | |||
eb71fc20e6 | |||
ab348bd5f9 | |||
c518d1c6c7 | |||
d8d16b4a7d | |||
928e4b9bc2 | |||
4f900d6566 | |||
362a997187 | |||
89c658746d | |||
75d699f7ef | |||
f7412690b6 | |||
ece2b23407 | |||
f84af9a44b | |||
90dc1103f6 | |||
c469fb24db | |||
32be6e36da | |||
b34ad22ad6 | |||
2358139a6b | |||
43ebfe7a2f | |||
0b8094dea8 | |||
f1d1570b10 | |||
e9e68bc802 | |||
4c369510ce | |||
96413d6c47 | |||
df6c7cf19f | |||
49fc28d86c | |||
cc67a83ce8 | |||
742e2b5089 | |||
d19ff1e300 | |||
01950ed443 | |||
cf1689a3c2 | |||
66d0bab0a5 | |||
5889f20f1e | |||
ebec10e312 | |||
ae8a0c7fd0 | |||
bb49200fad | |||
a6bba0bc6c | |||
fb08f79344 | |||
741c74825e | |||
28539cd47b | |||
8ca7c5a343 | |||
32b56e7071 | |||
7dad717952 | |||
34e928755f | |||
51e0f311fe |
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -36,5 +36,16 @@ node_modules
|
||||
build
|
||||
build-tests
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
# VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
|
||||
# Documents
|
||||
My Document.docx
|
||||
|
5
.prettierrc.yml
Normal file
5
.prettierrc.yml
Normal file
@ -0,0 +1,5 @@
|
||||
trailingComma: all
|
||||
printWidth: 140
|
||||
tabWidth: 4
|
||||
arrowParens: always
|
||||
bracketSpacing: true
|
31
.travis.yml
31
.travis.yml
@ -6,11 +6,30 @@ install:
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
after_failure:
|
||||
- npm run style
|
||||
- npm run build
|
||||
- node ./demo/demo1.js
|
||||
- node ./demo/demo2.js
|
||||
- node ./demo/demo3.js
|
||||
- node ./demo/demo4.js
|
||||
- node ./demo/demo5.js
|
||||
- node ./demo/demo6.js
|
||||
- node ./demo/demo7.js
|
||||
- node ./demo/demo8.js
|
||||
- node ./demo/demo9.js
|
||||
- node ./demo/demo10.js
|
||||
- node ./demo/demo11.js
|
||||
- node ./demo/demo12.js
|
||||
after_failure:
|
||||
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
|
||||
after_success:
|
||||
- bash ./deploy-docs.sh
|
||||
env:
|
||||
global:
|
||||
- ENCRYPTION_LABEL: "ad385fa3b525"
|
||||
|
||||
- npm run typedoc
|
||||
- echo "janchi.co.uk" > docs/.nojekyll
|
||||
deploy:
|
||||
provider: pages
|
||||
skip-cleanup: true
|
||||
github-token: $GITHUB_TOKEN
|
||||
keep-history: true
|
||||
local-dir: docs
|
||||
on:
|
||||
branch: master
|
||||
|
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"cSpell.words": ["clippy", "docx", "dolan", "miu", "officegen", "typedoc"],
|
||||
"prettier.trailingComma": "all",
|
||||
"prettier.printWidth": 140,
|
||||
"editor.formatOnSave": false,
|
||||
"prettier.tabWidth": 4,
|
||||
"prettier.arrowParens": "always",
|
||||
"prettier.bracketSpacing": true
|
||||
}
|
46
README.md
46
README.md
@ -6,9 +6,15 @@
|
||||
Generate .docx files with JS/TS very easily, written in TS.
|
||||
</p>
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][gemnasium-image]][gemnasium-url] [![Known Vulnerabilities][snky-image]][snky-url] [![Chat on Gitter][gitter-image]][gitter-url]
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Dependency Status][gemnasium-image]][gemnasium-url]
|
||||
[![Known Vulnerabilities][snky-image]][snky-url]
|
||||
[![Chat on Gitter][gitter-image]][gitter-url]
|
||||
[![code style: prettier][prettier-image]][prettier-url]
|
||||
[![PRs Welcome][pr-image]][pr-url]
|
||||
|
||||
[](https://nodei.co/npm/docx/)
|
||||
|
||||
@ -22,23 +28,39 @@ $ npm install --save docx
|
||||
|
||||
## Demo
|
||||
|
||||
Press `endpoint` on the `RunKit` website:
|
||||
|
||||

|
||||
|
||||
* https://runkit.com/dolanmiu/docx-demo1 - Simple paragraph and text
|
||||
* https://runkit.com/dolanmiu/docx-demo2 - Advanced Paragraphs and text
|
||||
* https://runkit.com/dolanmiu/docx-demo3 - Bullet points
|
||||
* https://runkit.com/dolanmiu/docx-demo4 - Simple table
|
||||
* https://runkit.com/dolanmiu/docx-demo5 - Images
|
||||
* https://runkit.com/dolanmiu/docx-demo6 - Margins
|
||||
* https://runkit.com/dolanmiu/docx-demo7 - Landscape
|
||||
* https://runkit.com/dolanmiu/docx-demo8/1.0.1 - Header and Footer
|
||||
* https://runkit.com/dolanmiu/docx-demo10 - **My CV generated with docx**
|
||||
|
||||
#### Run demos locally:
|
||||
|
||||
```sh
|
||||
$ npm run demo
|
||||
```
|
||||
|
||||
will run the demo selector app in the `demo` folder. It will prompt you to select a demo number, which will run a demo from that folder.
|
||||
This command will run the demo selector app in the `demo` folder. It will prompt you to select a demo number, which will run a demo from that folder.
|
||||
|
||||
## Guide
|
||||
|
||||
Please refer to [the Wiki](https://github.com/dolanmiu/docx/wiki) for details on how to use this library, examples and much more!
|
||||
|
||||
Full documentation can be found here: [http://dolanmiu.github.io/docx](http://dolanmiu.github.io/docx)
|
||||
Full documentation can be found here: [http://dolanmiu.github.io/docx/index.html](http://dolanmiu.github.io/docx/index.html)
|
||||
|
||||
## Simple Usage
|
||||
|
||||
```js
|
||||
// Used to create docx files
|
||||
var docx = require('docx');
|
||||
var docx = require("docx");
|
||||
|
||||
// Create document
|
||||
var doc = new docx.Document();
|
||||
@ -46,7 +68,7 @@ var doc = new docx.Document();
|
||||
// Add some content in the document
|
||||
var paragraph = new docx.Paragraph("Some cool text here.");
|
||||
// Add more text into the paragraph if you wish
|
||||
paragraph.addRun(new docx.TextRun('Lorem Ipsum Foo Bar'));
|
||||
paragraph.addRun(new docx.TextRun("Lorem Ipsum Foo Bar"));
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
// Used to export the file into a .docx file
|
||||
@ -56,7 +78,9 @@ var exporter = new docx.LocalPacker(doc);
|
||||
// res is express' Response object
|
||||
var exporter = new docx.ExpressPacker(doc, res);
|
||||
|
||||
exporter.pack('My First Document');
|
||||
exporter.pack("My First Document");
|
||||
// If you want to export it as a .pdf file instead
|
||||
exporter.packPdf("My First Document");
|
||||
|
||||
// done! A file called 'My First Document.docx'
|
||||
// will be in your file system if you used LocalPacker
|
||||
@ -64,13 +88,14 @@ exporter.pack('My First Document');
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Check [the Wiki](https://github.com/dolanmiu/docx/wiki/Examples) for examples.
|
||||
|
||||
# Contributing
|
||||
|
||||
Read the contribution guidelines [here](https://github.com/dolanmiu/docx/wiki/Contributing-Guidelines).
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
Made with 💖
|
||||
|
||||
@ -88,4 +113,7 @@ Huge thanks to [@felipeochoa](https://github.com/felipeochoa) for awesome contri
|
||||
[gitter-url]: https://gitter.im/docx-lib/Lobby
|
||||
[gemnasium-image]: https://gemnasium.com/badges/github.com/dolanmiu/docx.svg
|
||||
[gemnasium-url]: https://gemnasium.com/github.com/dolanmiu/docx
|
||||
|
||||
[prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg
|
||||
[prettier-url]: https://github.com/prettier/prettier
|
||||
[pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
|
||||
[pr-url]: http://makeapullrequest.com
|
||||
|
@ -10,13 +10,7 @@ paragraph.addRun(dateText);
|
||||
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
// Feature coming soon
|
||||
// var media = new docx.Media();
|
||||
// media.addMedia("happy-penguins", "./demo/penguins.jpg");
|
||||
// var pictureRun = new docx.PictureRun(media.getMedia("happy-penguins"));
|
||||
|
||||
// var exporter = new docx.LocalPacker(doc);
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created succesfully at project root!');
|
||||
console.log('Document created successfully at project root!');
|
||||
|
314
demo/demo10.js
Normal file
314
demo/demo10.js
Normal file
@ -0,0 +1,314 @@
|
||||
const docx = require("../build");
|
||||
|
||||
const PHONE_NUMBER = "07534563401";
|
||||
const PROFILE_URL = "https://www.linkedin.com/in/dolan1";
|
||||
const EMAIL = "docx@docx.com";
|
||||
|
||||
const experiences = [
|
||||
{
|
||||
isCurrent: true,
|
||||
summary: "Full-stack developer working with Angular and Java. Working for the iShares platform",
|
||||
title: "Associate Software Developer",
|
||||
startDate: {
|
||||
month: 11,
|
||||
year: 2017,
|
||||
},
|
||||
company: {
|
||||
name: "BlackRock",
|
||||
},
|
||||
},
|
||||
{
|
||||
isCurrent: false,
|
||||
summary:
|
||||
"Full-stack developer working with Angular, Node and TypeScript. Working for the iShares platform. Emphasis on Dev-ops and developing the continous integration pipeline.",
|
||||
title: "Software Developer",
|
||||
endDate: {
|
||||
month: 11,
|
||||
year: 2017,
|
||||
},
|
||||
startDate: {
|
||||
month: 10,
|
||||
year: 2016,
|
||||
},
|
||||
company: {
|
||||
name: "Torch Markets",
|
||||
},
|
||||
},
|
||||
{
|
||||
isCurrent: false,
|
||||
summary:
|
||||
"Used ASP.NET MVC 5 to produce a diversity data collection tool for the future of British television.\n\nUsed AngularJS and C# best practices. Technologies used include JavaScript, ASP.NET MVC 5, SQL, Oracle, SASS, Bootstrap, Grunt.",
|
||||
title: "Software Developer",
|
||||
endDate: {
|
||||
month: 10,
|
||||
year: 2016,
|
||||
},
|
||||
startDate: {
|
||||
month: 3,
|
||||
year: 2015,
|
||||
},
|
||||
company: {
|
||||
name: "Soundmouse",
|
||||
},
|
||||
},
|
||||
{
|
||||
isCurrent: false,
|
||||
summary:
|
||||
"Develop web commerce platforms for various high profile clients.\n\nCreated a log analysis web application with the Play Framework in Java, incorporating Test Driven Development. It asynchronously uploads and processes large (2 GB) log files, and outputs meaningful results in context with the problem. \n\nAnalysis and development of the payment system infrastructure and user accounts section to be used by several clients of the company such as Waitrose, Tally Weijl, DJ Sports, Debenhams, Ann Summers, John Lewis and others.\n\nTechnologies used include WebSphere Commerce, Java, JavaScript and JSP.",
|
||||
title: "Java Developer",
|
||||
endDate: {
|
||||
month: 10,
|
||||
year: 2014,
|
||||
},
|
||||
startDate: {
|
||||
month: 3,
|
||||
year: 2013,
|
||||
},
|
||||
company: {
|
||||
name: "Soundmouse",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const education = [
|
||||
{
|
||||
degree: "Master of Science (MSc)",
|
||||
fieldOfStudy: "Computer Science",
|
||||
notes:
|
||||
"Exam Results: 1st Class with Distinction, Dissertation: 1st Class with Distinction\n\nRelevant Courses: Java and C# Programming, Software Engineering, Artificial Intelligence, \nComputational Photography, Algorithmics, Architecture and Hardware.\n\nCreated a Windows 8 game in JavaScript for the dissertation. \n\nCreated an award-winning 3D stereoscopic game in C# using XNA.",
|
||||
schoolName: "University College London",
|
||||
startDate: {
|
||||
year: 2012,
|
||||
},
|
||||
endDate: {
|
||||
year: 2013,
|
||||
},
|
||||
},
|
||||
{
|
||||
degree: "Bachelor of Engineering (BEng)",
|
||||
fieldOfStudy: "Material Science and Engineering",
|
||||
notes:
|
||||
"Exam Results: 2:1, Dissertation: 1st Class with Distinction\n\nRelevant courses: C Programming, Mathematics and Business for Engineers.",
|
||||
schoolName: "Imperial College London",
|
||||
startDate: {
|
||||
year: 2009,
|
||||
},
|
||||
endDate: {
|
||||
year: 2012,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const skills = [
|
||||
{
|
||||
name: "Angular",
|
||||
},
|
||||
{
|
||||
name: "TypeScript",
|
||||
},
|
||||
{
|
||||
name: "JavaScript",
|
||||
},
|
||||
{
|
||||
name: "NodeJS",
|
||||
},
|
||||
];
|
||||
|
||||
const achievements = [
|
||||
{
|
||||
issuer: "Oracle",
|
||||
name: "Oracle Certified Expert",
|
||||
},
|
||||
];
|
||||
|
||||
class DocumentCreator {
|
||||
create(data) {
|
||||
const experiences = data[0];
|
||||
const educations = data[1];
|
||||
const skills = data[2];
|
||||
const achivements = data[3];
|
||||
const document = new docx.Document();
|
||||
document.addParagraph(new docx.Paragraph("Dolan Miu").title());
|
||||
|
||||
document.addParagraph(this.createContactInfo(PHONE_NUMBER, PROFILE_URL, EMAIL));
|
||||
document.addParagraph(this.createHeading("Education"));
|
||||
|
||||
for (const education of educations) {
|
||||
document.addParagraph(
|
||||
this.createInstitutionHeader(education.schoolName, `${education.startDate.year} - ${education.endDate.year}`),
|
||||
);
|
||||
document.addParagraph(this.createRoleText(`${education.fieldOfStudy} - ${education.degree}`));
|
||||
|
||||
const bulletPoints = this.splitParagraphIntoBullets(education.notes);
|
||||
bulletPoints.forEach((bulletPoint) => {
|
||||
document.addParagraph(this.createBullet(bulletPoint));
|
||||
});
|
||||
}
|
||||
|
||||
document.addParagraph(this.createHeading("Experience"));
|
||||
|
||||
for (const position of experiences) {
|
||||
document.addParagraph(
|
||||
this.createInstitutionHeader(
|
||||
position.company.name,
|
||||
this.createPositionDateText(position.startDate, position.endDate, position.isCurrent),
|
||||
),
|
||||
);
|
||||
document.addParagraph(this.createRoleText(position.title));
|
||||
|
||||
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 docx.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 docx.Paragraph("More references upon request"));
|
||||
document.addParagraph(
|
||||
new docx.Paragraph(
|
||||
"This CV was generated in real-time based on my Linked-In profile from my personal website www.dolan.bio.",
|
||||
).center(),
|
||||
);
|
||||
return document;
|
||||
}
|
||||
|
||||
createContactInfo(phoneNumber, profileUrl, email) {
|
||||
const paragraph = new docx.Paragraph().center();
|
||||
const contactInfo = new docx.TextRun(`Mobile: ${phoneNumber} | LinkedIn: ${profileUrl} | Email: ${email}`);
|
||||
const address = new docx.TextRun("Address: 58 Elm Avenue, Kent ME4 6ER, UK").break();
|
||||
|
||||
paragraph.addRun(contactInfo);
|
||||
paragraph.addRun(address);
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
createHeading(text) {
|
||||
return new docx.Paragraph(text).heading1().thematicBreak();
|
||||
}
|
||||
|
||||
createSubHeading(text) {
|
||||
return new docx.Paragraph(text).heading2();
|
||||
}
|
||||
|
||||
createInstitutionHeader(institutionName, dateText) {
|
||||
const paragraph = new docx.Paragraph().maxRightTabStop();
|
||||
const institution = new docx.TextRun(institutionName).bold();
|
||||
const date = new docx.TextRun(dateText).tab().bold();
|
||||
|
||||
paragraph.addRun(institution);
|
||||
paragraph.addRun(date);
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
createRoleText(roleText) {
|
||||
const paragraph = new docx.Paragraph();
|
||||
const role = new docx.TextRun(roleText).italic();
|
||||
|
||||
paragraph.addRun(role);
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
createBullet(text) {
|
||||
return new docx.Paragraph(text).bullet();
|
||||
}
|
||||
|
||||
createSkillList(skills) {
|
||||
const paragraph = new docx.Paragraph();
|
||||
const skillConcat = skills.map((skill) => skill.name).join(", ") + ".";
|
||||
|
||||
paragraph.addRun(new docx.TextRun(skillConcat));
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
createAchivementsList(achivements) {
|
||||
const arr = [];
|
||||
|
||||
for (const achievement of achivements) {
|
||||
arr.push(new docx.Paragraph(achievement.name).bullet());
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
createInterests(interests) {
|
||||
const paragraph = new docx.Paragraph();
|
||||
|
||||
paragraph.addRun(new docx.TextRun(interests));
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
splitParagraphIntoBullets(text) {
|
||||
return text.split("\n\n");
|
||||
}
|
||||
|
||||
createPositionDateText(startDate, endDate, isCurrent) {
|
||||
const startDateText = this.getMonthFromInt(startDate.month) + ". " + startDate.year;
|
||||
const endDateText = isCurrent ? "Present" : `${this.getMonthFromInt(endDate.month)}. ${endDate.year}`;
|
||||
|
||||
return `${startDateText} - ${endDateText}`;
|
||||
}
|
||||
|
||||
getMonthFromInt(value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return "Jan";
|
||||
case 2:
|
||||
return "Feb";
|
||||
case 3:
|
||||
return "Mar";
|
||||
case 4:
|
||||
return "Apr";
|
||||
case 5:
|
||||
return "May";
|
||||
case 6:
|
||||
return "Jun";
|
||||
case 7:
|
||||
return "Jul";
|
||||
case 8:
|
||||
return "Aug";
|
||||
case 9:
|
||||
return "Sept";
|
||||
case 10:
|
||||
return "Oct";
|
||||
case 11:
|
||||
return "Nov";
|
||||
case 12:
|
||||
return "Dec";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const documentCreator = new DocumentCreator();
|
||||
|
||||
const doc = documentCreator.create([experiences, education, skills, achievements]);
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack("Dolan Miu CV");
|
||||
|
||||
console.log("Document created successfully at project root!");
|
132
demo/demo11.js
Normal file
132
demo/demo11.js
Normal file
@ -0,0 +1,132 @@
|
||||
const docx = require("../build");
|
||||
|
||||
const doc = new docx.Document(undefined, {
|
||||
top: 700,
|
||||
right: 700,
|
||||
bottom: 700,
|
||||
left: 700,
|
||||
});
|
||||
|
||||
doc.Styles.createParagraphStyle("Heading1", "Heading 1")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.quickFormat()
|
||||
.font("Calibri")
|
||||
.size(52)
|
||||
.center()
|
||||
.bold()
|
||||
.color(000000)
|
||||
.spacing({ line: 340 })
|
||||
.underline("single", "000000");
|
||||
|
||||
doc.Styles.createParagraphStyle("Heading2", "Heading 2")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.font("Calibri")
|
||||
.quickFormat()
|
||||
.size(26)
|
||||
.bold()
|
||||
.spacing({ line: 340 });
|
||||
|
||||
doc.Styles.createParagraphStyle("Heading3", "Heading 3")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.font("Calibri")
|
||||
.quickFormat()
|
||||
.size(26)
|
||||
.bold()
|
||||
.spacing({ line: 276 });
|
||||
|
||||
doc.Styles.createParagraphStyle("Heading4", "Heading 4")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.justified()
|
||||
.font("Calibri")
|
||||
.size(26)
|
||||
.bold();
|
||||
|
||||
doc.Styles.createParagraphStyle("normalPara", "Normal Para")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.font("Calibri")
|
||||
.quickFormat()
|
||||
.leftTabStop(453.543307087)
|
||||
.maxRightTabStop(453.543307087)
|
||||
.size(26)
|
||||
.spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 });
|
||||
|
||||
doc.Styles.createParagraphStyle("normalPara2", "Normal Para2")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.quickFormat()
|
||||
.font("Calibri")
|
||||
.size(26)
|
||||
.justified()
|
||||
.spacing({ line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 });
|
||||
|
||||
doc.Styles.createParagraphStyle("aside", "Aside")
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.color("999999")
|
||||
.italics()
|
||||
.indent(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");
|
||||
|
||||
doc.createImage("./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");
|
||||
|
||||
var table = new docx.Table(4, 4);
|
||||
var contentParagraph = table
|
||||
.getRow(0)
|
||||
.getCell(0)
|
||||
.addContent(new docx.Paragraph("Pole No."));
|
||||
table.properties.width = 10000;
|
||||
doc.addTable(table);
|
||||
|
||||
var arrboth = [{
|
||||
image: "./demo/images/pizza.gif",
|
||||
comment: "Test"
|
||||
}, {
|
||||
image: "./demo/images/pizza.gif",
|
||||
comment: "Test 2"
|
||||
}];
|
||||
|
||||
arrboth.forEach(function(item) {
|
||||
const para = doc.createParagraph();
|
||||
para.createTextRun(doc.createImage(item.image));
|
||||
para.properties.width = 60;
|
||||
para.properties.height = 90;
|
||||
doc.createParagraph(item.comment).style("normalPara2");
|
||||
});
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack("My Document");
|
21
demo/demo12.js
Normal file
21
demo/demo12.js
Normal file
@ -0,0 +1,21 @@
|
||||
const docx = require("../build");
|
||||
|
||||
var doc = new docx.Document();
|
||||
|
||||
var paragraph = new docx.Paragraph("Hello World");
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
const image = doc.createImage("./demo/images/pizza.gif");
|
||||
const image2 = doc.createImage("./demo/images/pizza.gif");
|
||||
const image3 = doc.createImage("./demo/images/pizza.gif");
|
||||
const image4 = doc.createImage("./demo/images/pizza.gif");
|
||||
|
||||
image.scale(0.5);
|
||||
image2.scale(1)
|
||||
image3.scale(2.5);
|
||||
image4.scale(4);
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack("My Document");
|
||||
|
||||
console.log("Document created successfully at project root!");
|
@ -1,7 +1,12 @@
|
||||
const docx = require('../build');
|
||||
|
||||
const styles = new docx.Styles();
|
||||
styles.createParagraphStyle('Heading1', 'Heading 1')
|
||||
const doc = new docx.Document({
|
||||
creator: 'Clippy',
|
||||
title: 'Sample Document',
|
||||
description: 'A brief example of using docx',
|
||||
});
|
||||
|
||||
doc.Styles.createParagraphStyle('Heading1', 'Heading 1')
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.quickFormat()
|
||||
@ -10,7 +15,7 @@ styles.createParagraphStyle('Heading1', 'Heading 1')
|
||||
.italics()
|
||||
.spacing({after: 120});
|
||||
|
||||
styles.createParagraphStyle('Heading2', 'Heading 2')
|
||||
doc.Styles.createParagraphStyle('Heading2', 'Heading 2')
|
||||
.basedOn("Normal")
|
||||
.next("Normal")
|
||||
.quickFormat()
|
||||
@ -19,7 +24,7 @@ styles.createParagraphStyle('Heading2', 'Heading 2')
|
||||
.underline('double', 'FF0000')
|
||||
.spacing({before: 240, after: 120});
|
||||
|
||||
styles.createParagraphStyle('aside', 'Aside')
|
||||
doc.Styles.createParagraphStyle('aside', 'Aside')
|
||||
.basedOn('Normal')
|
||||
.next('Normal')
|
||||
.color('999999')
|
||||
@ -27,31 +32,24 @@ styles.createParagraphStyle('aside', 'Aside')
|
||||
.indent(720)
|
||||
.spacing({line: 276});
|
||||
|
||||
styles.createParagraphStyle('wellSpaced', 'Well Spaced')
|
||||
doc.Styles.createParagraphStyle('wellSpaced', 'Well Spaced')
|
||||
.basedOn('Normal')
|
||||
.spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05});
|
||||
|
||||
styles.createParagraphStyle('ListParagraph', 'List Paragraph')
|
||||
doc.Styles.createParagraphStyle('ListParagraph', 'List Paragraph')
|
||||
.quickFormat()
|
||||
.basedOn('Normal');
|
||||
|
||||
|
||||
const numbering = new docx.Numbering();
|
||||
const numberedAbstract = numbering.createAbstractNumbering();
|
||||
const numberedAbstract = doc.Numbering.createAbstractNumbering();
|
||||
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
|
||||
|
||||
const doc = new docx.Document({
|
||||
creator: 'Clippy',
|
||||
title: 'Sample Document',
|
||||
description: 'A brief example of using docx',
|
||||
});
|
||||
|
||||
doc.createParagraph('Test heading1, bold and italicized').heading1();
|
||||
doc.createParagraph('Some simple content');
|
||||
doc.createParagraph('Test heading2 with double red underline').heading2();
|
||||
|
||||
const letterNumbering = numbering.createConcreteNumbering(numberedAbstract);
|
||||
const letterNumbering5 = numbering.createConcreteNumbering(numberedAbstract);
|
||||
const letterNumbering = doc.Numbering.createConcreteNumbering(numberedAbstract);
|
||||
const letterNumbering5 = doc.Numbering.createConcreteNumbering(numberedAbstract);
|
||||
letterNumbering5.overrideLevel(0, 5);
|
||||
|
||||
doc.createParagraph('Option1').setNumbering(letterNumbering, 0);
|
||||
@ -70,5 +68,7 @@ para.createTextRun(' switching to normal ');
|
||||
para.createTextRun('and then underlined ').underline();
|
||||
para.createTextRun('and back to normal.');
|
||||
|
||||
const exporter = new docx.LocalPacker(doc, styles, undefined, numbering);
|
||||
exporter.pack('test.docx');
|
||||
const exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created successfully at project root!');
|
||||
|
@ -29,7 +29,17 @@ doc.addParagraph(subP);
|
||||
doc.addParagraph(secondSubP);
|
||||
doc.addParagraph(subSubP);
|
||||
|
||||
var bullet1 = new docx.Paragraph("Hey you").bullet();
|
||||
var bullet2 = new docx.Paragraph("What's up fam").bullet(1);
|
||||
var bullet3 = new docx.Paragraph("Hello World 2").bullet(2);
|
||||
var bullet4 = new docx.Paragraph("Yeah boi").bullet(3);
|
||||
|
||||
doc.addParagraph(bullet1);
|
||||
doc.addParagraph(bullet2);
|
||||
doc.addParagraph(bullet3);
|
||||
doc.addParagraph(bullet4);
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created succesfully at project root!');
|
||||
console.log('Document created successfully at project root!');
|
||||
|
@ -9,4 +9,4 @@ table.getCell(2, 2).addContent(new docx.Paragraph('Hello'));
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created succesfully at project root!');
|
||||
console.log('Document created successfully at project root!');
|
||||
|
17
demo/demo5.js
Normal file
17
demo/demo5.js
Normal file
@ -0,0 +1,17 @@
|
||||
const docx = require('../build');
|
||||
|
||||
var doc = new docx.Document();
|
||||
|
||||
var paragraph = new docx.Paragraph("Hello World");
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
const image = doc.createImage("./demo/images/image1.jpeg");
|
||||
const image2 = doc.createImage("./demo/images/dog.png");
|
||||
const image3 = doc.createImage("./demo/images/cat.jpg");
|
||||
const image4 = doc.createImage("./demo/images/parrots.bmp");
|
||||
const image5 = doc.createImage("./demo/images/pizza.gif");
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created successfully at project root!');
|
25
demo/demo6.js
Normal file
25
demo/demo6.js
Normal file
@ -0,0 +1,25 @@
|
||||
const docx = require("../build");
|
||||
|
||||
var doc = new docx.Document(undefined, {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
});
|
||||
|
||||
var paragraph = new docx.Paragraph("Hello World");
|
||||
var institutionText = new docx.TextRun("University College London").bold();
|
||||
var dateText = new docx.TextRun("5th Dec 2015").tab().bold();
|
||||
paragraph.addRun(institutionText);
|
||||
paragraph.addRun(dateText);
|
||||
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
doc.createParagraph("Hello World").heading1();
|
||||
doc.createParagraph("University College London");
|
||||
doc.createParagraph("5th Dec 2015");
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack("My Document");
|
||||
|
||||
console.log("Document created successfully at project root!");
|
14
demo/demo7.js
Normal file
14
demo/demo7.js
Normal file
@ -0,0 +1,14 @@
|
||||
const docx = require("../build");
|
||||
|
||||
var doc = new docx.Document(undefined, {
|
||||
orientation: "landscape",
|
||||
});
|
||||
|
||||
var paragraph = new docx.Paragraph("Hello World");
|
||||
|
||||
doc.addParagraph(paragraph);
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack("My Document");
|
||||
|
||||
console.log("Document created successfully at project root!");
|
13
demo/demo8.js
Normal file
13
demo/demo8.js
Normal file
@ -0,0 +1,13 @@
|
||||
const docx = require('../build');
|
||||
|
||||
var doc = new docx.Document();
|
||||
|
||||
doc.createParagraph("Hello World");
|
||||
|
||||
doc.Header.createParagraph("Header text");
|
||||
doc.Footer.createParagraph("Footer text");
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created successfully at project root!');
|
13
demo/demo9.js
Normal file
13
demo/demo9.js
Normal file
@ -0,0 +1,13 @@
|
||||
const docx = require('../build');
|
||||
|
||||
var doc = new docx.Document();
|
||||
|
||||
doc.createParagraph("Hello World");
|
||||
|
||||
doc.Header.createImage("./demo/images/pizza.gif");
|
||||
doc.Footer.createImage("./demo/images/pizza.gif");
|
||||
|
||||
var exporter = new docx.LocalPacker(doc);
|
||||
exporter.pack('My Document');
|
||||
|
||||
console.log('Document created successfully at project root!');
|
BIN
demo/images/cat.jpg
Normal file
BIN
demo/images/cat.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
BIN
demo/images/dog.png
Normal file
BIN
demo/images/dog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
BIN
demo/images/parrots.bmp
Normal file
BIN
demo/images/parrots.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 818 KiB |
BIN
demo/images/pizza.gif
Normal file
BIN
demo/images/pizza.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 310 KiB |
@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e # Exit with nonzero exit code if anything fails
|
||||
|
||||
SOURCE_BRANCH="master"
|
||||
TARGET_BRANCH="gh-pages"
|
||||
|
||||
function doCompile {
|
||||
npm run typedoc
|
||||
}
|
||||
|
||||
# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
|
||||
echo "Skipping deploy; just doing a build."
|
||||
doCompile
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Save some useful information
|
||||
REPO=`git config remote.origin.url`
|
||||
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
|
||||
SHA=`git rev-parse --verify HEAD`
|
||||
|
||||
# Clone the existing gh-pages for this repo into docs/
|
||||
# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
|
||||
git clone $REPO docs
|
||||
cd docs
|
||||
git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
|
||||
cd ..
|
||||
|
||||
# Clean out existing contents
|
||||
# echo "Cleaning out existing contents."
|
||||
# rm -rf docs/*
|
||||
|
||||
# Run our compile script
|
||||
doCompile
|
||||
|
||||
# Now let's go have some fun with the cloned repo
|
||||
cd docs
|
||||
git config user.name "Travis CI"
|
||||
git config user.email "dolan_miu@hotmail.com"
|
||||
ls
|
||||
|
||||
# add .nojekyll file
|
||||
touch .nojekyll
|
||||
|
||||
# If there are no changes to the compiled out (e.g. this is a README update) then just bail.
|
||||
if [ -z `git diff --exit-code` ]; then
|
||||
echo "No changes to the output on this push; exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Commit the "changes", i.e. the new version.
|
||||
# The delta will show diffs between new and old versions.
|
||||
git add .
|
||||
git commit -m "Deploy to GitHub Pages: ${SHA}"
|
||||
|
||||
# Get the deploy key by using Travis's stored variables to decrypt deploy-key.enc
|
||||
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
|
||||
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
|
||||
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
|
||||
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
|
||||
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy-key.enc -out deploy-key -d
|
||||
chmod 600 deploy-key
|
||||
eval `ssh-agent -s`
|
||||
ssh-add deploy-key
|
||||
|
||||
# Now that we're all set up, we can push.
|
||||
git push $SSH_REPO $TARGET_BRANCH
|
BIN
deploy-key.enc
BIN
deploy-key.enc
Binary file not shown.
41
package.json
41
package.json
@ -1,19 +1,25 @@
|
||||
{
|
||||
"name": "docx",
|
||||
"version": "3.0.1",
|
||||
"version": "3.5.0",
|
||||
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
"pretest": "rimraf ./build-tests && tsc -p ts/test-tsconfig.json",
|
||||
"test": "mocha ./build-tests --recursive",
|
||||
"pretest": "rimraf ./build",
|
||||
"test": "mocha-webpack \"src/**/*.ts\"",
|
||||
"test-watch": "mocha-webpack \"src/**/*.ts\" --watch",
|
||||
"prepublishOnly": "npm run build",
|
||||
"lint": "tslint --project ./ts",
|
||||
"build": "rimraf ./build && tsc -p ts",
|
||||
"lint": "tslint --project .",
|
||||
"build": "npm run webpack && npm run fix-types",
|
||||
"tsc": "rimraf ./build && tsc -p .",
|
||||
"webpack": "rimraf ./build && webpack",
|
||||
"demo": "npm run build && node ./demo",
|
||||
"typedoc": "typedoc --out docs/ ts/ --module commonjs --target ES6 --disableOutputCheck"
|
||||
"typedoc": "typedoc --out docs/ src/ --module commonjs --target ES6 --disableOutputCheck --excludePrivate --externalPattern \"**/*.spec.ts\"",
|
||||
"style": "prettier -l \"src/**/*.ts\"",
|
||||
"style.fix": "prettier \"src/**/*.ts\" --write",
|
||||
"fix-types": "node types-absolute-fixer.js"
|
||||
},
|
||||
"files": [
|
||||
"ts",
|
||||
"src",
|
||||
"build",
|
||||
"template"
|
||||
],
|
||||
@ -35,9 +41,14 @@
|
||||
],
|
||||
"types": "./build/index.d.ts",
|
||||
"dependencies": {
|
||||
"@types/archiver": "^1.3.4",
|
||||
"@types/archiver": "^2.1.0",
|
||||
"@types/express": "^4.0.35",
|
||||
"archiver": "^1.3.0",
|
||||
"@types/image-size": "0.0.29",
|
||||
"@types/request-promise": "^4.1.41",
|
||||
"archiver": "^2.1.1",
|
||||
"image-size": "^0.6.2",
|
||||
"request": "^2.83.0",
|
||||
"request-promise": "^4.2.2",
|
||||
"xml": "^1.0.1"
|
||||
},
|
||||
"author": "Dolan Miu",
|
||||
@ -49,13 +60,21 @@
|
||||
"devDependencies": {
|
||||
"@types/chai": "^3.4.35",
|
||||
"@types/mocha": "^2.2.39",
|
||||
"@types/sinon": "^4.3.1",
|
||||
"awesome-typescript-loader": "^3.4.1",
|
||||
"chai": "^3.5.0",
|
||||
"glob": "^7.1.2",
|
||||
"mocha": "^3.2.0",
|
||||
"mocha-webpack": "^1.0.1",
|
||||
"prettier": "^1.12.1",
|
||||
"prompt": "^1.0.0",
|
||||
"replace-in-file": "^3.1.0",
|
||||
"rimraf": "^2.5.2",
|
||||
"shelljs": "^0.7.7",
|
||||
"sinon": "^5.0.7",
|
||||
"tslint": "^5.1.0",
|
||||
"typedoc": "^0.5.10",
|
||||
"typescript": "2.4.1"
|
||||
"typedoc": "^0.9.0",
|
||||
"typescript": "2.6.2",
|
||||
"webpack": "^3.10.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { assert } from "chai";
|
||||
|
||||
import * as docx from "../docx";
|
||||
import { Attributes } from "../docx/xml-components";
|
||||
import { Formatter } from "../export/formatter";
|
||||
import { Properties } from "../properties";
|
||||
import * as file from "../file";
|
||||
import { CoreProperties } from "../file/core-properties";
|
||||
import { Attributes } from "../file/xml-components";
|
||||
import { Utility } from "../tests/utility";
|
||||
|
||||
describe("Formatter", () => {
|
||||
@ -15,21 +15,21 @@ describe("Formatter", () => {
|
||||
|
||||
describe("#format()", () => {
|
||||
it("should format simple paragraph", () => {
|
||||
const paragraph = new docx.Paragraph();
|
||||
const paragraph = new file.Paragraph();
|
||||
const newJson = formatter.format(paragraph);
|
||||
assert.isDefined(newJson["w:p"]);
|
||||
});
|
||||
|
||||
it("should remove xmlKeys", () => {
|
||||
const paragraph = new docx.Paragraph();
|
||||
const paragraph = new file.Paragraph();
|
||||
const newJson = formatter.format(paragraph);
|
||||
const stringifiedJson = JSON.stringify(newJson);
|
||||
assert(stringifiedJson.indexOf("xmlKeys") < 0);
|
||||
});
|
||||
|
||||
it("should format simple paragraph with bold text", () => {
|
||||
const paragraph = new docx.Paragraph();
|
||||
paragraph.addRun(new docx.TextRun("test").bold());
|
||||
const paragraph = new file.Paragraph();
|
||||
paragraph.addRun(new file.TextRun("test").bold());
|
||||
const newJson = formatter.format(paragraph);
|
||||
assert.isDefined(newJson["w:p"][1]["w:r"][0]["w:rPr"][0]["w:b"][0]._attr["w:val"]);
|
||||
});
|
||||
@ -61,13 +61,13 @@ describe("Formatter", () => {
|
||||
});
|
||||
|
||||
it("should should change 'p' tag into 'w:p' tag", () => {
|
||||
const paragraph = new docx.Paragraph();
|
||||
const paragraph = new file.Paragraph();
|
||||
const newJson = formatter.format(paragraph);
|
||||
assert.isDefined(newJson["w:p"]);
|
||||
});
|
||||
|
||||
it("should format Properties object correctly", () => {
|
||||
const properties = new Properties({
|
||||
const properties = new CoreProperties({
|
||||
title: "test document",
|
||||
creator: "Dolan",
|
||||
});
|
7
src/export/formatter.ts
Normal file
7
src/export/formatter.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { BaseXmlComponent, IXmlableObject } from "file/xml-components";
|
||||
|
||||
export class Formatter {
|
||||
public format(input: BaseXmlComponent): IXmlableObject {
|
||||
return input.prepForXml();
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export * from "./packer/local";
|
||||
export * from "./packer/express";
|
||||
export * from "./packer/packer";
|
||||
export * from "./packer/stream";
|
105
src/export/packer/compiler.ts
Normal file
105
src/export/packer/compiler.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import * as archiver from "archiver";
|
||||
import * as express from "express";
|
||||
import { Writable } from "stream";
|
||||
import * as xml from "xml";
|
||||
|
||||
import { File } from "file";
|
||||
import { Formatter } from "../formatter";
|
||||
|
||||
export class Compiler {
|
||||
protected archive: archiver.Archiver;
|
||||
private formatter: Formatter;
|
||||
|
||||
constructor(private file: File) {
|
||||
this.formatter = new Formatter();
|
||||
this.archive = archiver.create("zip", {});
|
||||
|
||||
this.archive.on("error", (err) => {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
public async compile(output: Writable | express.Response): Promise<void> {
|
||||
this.archive.pipe(output);
|
||||
|
||||
const xmlDocument = xml(this.formatter.format(this.file.Document), true);
|
||||
const xmlStyles = xml(this.formatter.format(this.file.Styles));
|
||||
const xmlProperties = xml(this.formatter.format(this.file.CoreProperties), {
|
||||
declaration: {
|
||||
standalone: "yes",
|
||||
encoding: "UTF-8",
|
||||
},
|
||||
});
|
||||
const xmlNumbering = xml(this.formatter.format(this.file.Numbering));
|
||||
const xmlRelationships = xml(this.formatter.format(this.file.DocumentRelationships));
|
||||
const xmlFileRelationships = xml(this.formatter.format(this.file.FileRelationships));
|
||||
const xmlHeader = xml(this.formatter.format(this.file.Header.Header));
|
||||
const xmlFooter = xml(this.formatter.format(this.file.Footer.Footer));
|
||||
const xmlHeaderRelationships = xml(this.formatter.format(this.file.Header.Relationships));
|
||||
const xmlFooterRelationships = xml(this.formatter.format(this.file.Footer.Relationships));
|
||||
const xmlContentTypes = xml(this.formatter.format(this.file.ContentTypes));
|
||||
const xmlAppProperties = xml(this.formatter.format(this.file.AppProperties));
|
||||
|
||||
this.archive.append(xmlDocument, {
|
||||
name: "word/document.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlStyles, {
|
||||
name: "word/styles.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlProperties, {
|
||||
name: "docProps/core.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlAppProperties, {
|
||||
name: "docProps/app.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlNumbering, {
|
||||
name: "word/numbering.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlHeader, {
|
||||
name: "word/header1.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlFooter, {
|
||||
name: "word/footer1.xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlRelationships, {
|
||||
name: "word/_rels/document.xml.rels",
|
||||
});
|
||||
|
||||
this.archive.append(xmlHeaderRelationships, {
|
||||
name: "word/_rels/header1.xml.rels",
|
||||
});
|
||||
|
||||
this.archive.append(xmlFooterRelationships, {
|
||||
name: "word/_rels/footer1.xml.rels",
|
||||
});
|
||||
|
||||
this.archive.append(xmlContentTypes, {
|
||||
name: "[Content_Types].xml",
|
||||
});
|
||||
|
||||
this.archive.append(xmlFileRelationships, {
|
||||
name: "_rels/.rels",
|
||||
});
|
||||
|
||||
for (const data of this.file.Media.array) {
|
||||
this.archive.append(data.stream, {
|
||||
name: `word/media/${data.fileName}`,
|
||||
});
|
||||
}
|
||||
|
||||
this.archive.finalize();
|
||||
|
||||
return new Promise<void>((resolve) => {
|
||||
output.on("close", () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
43
src/export/packer/express.spec.ts
Normal file
43
src/export/packer/express.spec.ts
Normal file
@ -0,0 +1,43 @@
|
||||
// tslint:disable:typedef space-before-function-paren
|
||||
// tslint:disable:no-empty
|
||||
// tslint:disable:no-any
|
||||
import { assert } from "chai";
|
||||
import { stub } from "sinon";
|
||||
|
||||
import { ExpressPacker } from "../../export/packer/express";
|
||||
import { File, Paragraph } from "../../file";
|
||||
|
||||
describe("LocalPacker", () => {
|
||||
let packer: ExpressPacker;
|
||||
|
||||
beforeEach(() => {
|
||||
const file = new File({
|
||||
creator: "Dolan Miu",
|
||||
revision: "1",
|
||||
lastModifiedBy: "Dolan Miu",
|
||||
});
|
||||
const paragraph = new Paragraph("test text");
|
||||
const heading = new Paragraph("Hello world").heading1();
|
||||
file.addParagraph(new Paragraph("title").title());
|
||||
file.addParagraph(heading);
|
||||
file.addParagraph(new Paragraph("heading 2").heading2());
|
||||
file.addParagraph(paragraph);
|
||||
|
||||
const expressResMock = {
|
||||
on: () => {},
|
||||
attachment: () => {},
|
||||
};
|
||||
|
||||
packer = new ExpressPacker(file, expressResMock as any);
|
||||
});
|
||||
|
||||
describe("#pack()", () => {
|
||||
it("should handle exception if it throws any", () => {
|
||||
const compiler = stub((packer as any).packer, "compile");
|
||||
compiler.throwsException();
|
||||
return packer.pack("build/tests/test").catch((error) => {
|
||||
assert.isDefined(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
29
src/export/packer/express.ts
Normal file
29
src/export/packer/express.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import * as express from "express";
|
||||
|
||||
import { File } from "file";
|
||||
import { Compiler } from "./compiler";
|
||||
import { IPacker } from "./packer";
|
||||
|
||||
export class ExpressPacker implements IPacker {
|
||||
private readonly packer: Compiler;
|
||||
|
||||
constructor(file: File, private readonly res: express.Response) {
|
||||
this.packer = new Compiler(file);
|
||||
|
||||
this.res = res;
|
||||
|
||||
this.res.on("close", () => {
|
||||
return res
|
||||
.status(200)
|
||||
.send("OK")
|
||||
.end();
|
||||
});
|
||||
}
|
||||
|
||||
public async pack(name: string): Promise<void> {
|
||||
name = name.replace(/.docx$/, "");
|
||||
|
||||
this.res.attachment(`${name}.docx`);
|
||||
await this.packer.compile(this.res);
|
||||
}
|
||||
}
|
66
src/export/packer/local.spec.ts
Normal file
66
src/export/packer/local.spec.ts
Normal file
@ -0,0 +1,66 @@
|
||||
/* tslint:disable:typedef space-before-function-paren */
|
||||
import { assert } from "chai";
|
||||
import * as fs from "fs";
|
||||
import { stub } from "sinon";
|
||||
|
||||
import { LocalPacker } from "../../export/packer/local";
|
||||
import { File, Paragraph } from "../../file";
|
||||
|
||||
describe("LocalPacker", () => {
|
||||
let packer: LocalPacker;
|
||||
|
||||
beforeEach(() => {
|
||||
const file = new File({
|
||||
creator: "Dolan Miu",
|
||||
revision: "1",
|
||||
lastModifiedBy: "Dolan Miu",
|
||||
});
|
||||
const paragraph = new Paragraph("test text");
|
||||
const heading = new Paragraph("Hello world").heading1();
|
||||
file.addParagraph(new Paragraph("title").title());
|
||||
file.addParagraph(heading);
|
||||
file.addParagraph(new Paragraph("heading 2").heading2());
|
||||
file.addParagraph(paragraph);
|
||||
|
||||
packer = new LocalPacker(file);
|
||||
});
|
||||
|
||||
describe("#pack()", () => {
|
||||
it("should create a standard docx file", async function() {
|
||||
this.timeout(99999999);
|
||||
await packer.pack("build/tests/test");
|
||||
fs.statSync("build/tests/test.docx");
|
||||
});
|
||||
|
||||
it("should handle exception if it throws any", () => {
|
||||
// tslint:disable-next-line:no-any
|
||||
const compiler = stub((packer as any).packer, "compile");
|
||||
compiler.throwsException();
|
||||
return packer.pack("build/tests/test").catch((error) => {
|
||||
assert.isDefined(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#packPdf", () => {
|
||||
it("should create a standard PDF file", async function() {
|
||||
this.timeout(99999999);
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
const pdfConverterConvert = stub((packer as any).pdfConverter, "convert");
|
||||
pdfConverterConvert.returns("Test PDF Contents");
|
||||
|
||||
await packer.packPdf("build/tests/pdf-test");
|
||||
fs.statSync("build/tests/pdf-test.pdf");
|
||||
});
|
||||
|
||||
it("should handle exception if it throws any", () => {
|
||||
// tslint:disable-next-line:no-any
|
||||
const compiler = stub((packer as any).packer, "compile");
|
||||
compiler.throwsException();
|
||||
return packer.packPdf("build/tests/pdf-test").catch((error) => {
|
||||
assert.isDefined(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
47
src/export/packer/local.ts
Normal file
47
src/export/packer/local.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
|
||||
import { File } from "../../file";
|
||||
import { Compiler } from "./compiler";
|
||||
import { IPacker } from "./packer";
|
||||
import { PdfConvertWrapper } from "./pdf-convert-wrapper";
|
||||
|
||||
export class LocalPacker implements IPacker {
|
||||
private stream: fs.WriteStream;
|
||||
private readonly pdfConverter: PdfConvertWrapper;
|
||||
private readonly packer: Compiler;
|
||||
|
||||
constructor(file: File) {
|
||||
this.pdfConverter = new PdfConvertWrapper();
|
||||
this.packer = new Compiler(file);
|
||||
}
|
||||
|
||||
public async pack(filePath: string): Promise<void> {
|
||||
filePath = filePath.replace(/.docx$/, "");
|
||||
|
||||
this.stream = fs.createWriteStream(`${filePath}.docx`);
|
||||
await this.packer.compile(this.stream);
|
||||
}
|
||||
|
||||
public async packPdf(filePath: string): Promise<void> {
|
||||
filePath = filePath.replace(/.pdf$/, "");
|
||||
|
||||
const fileName = path.basename(filePath, path.extname(filePath));
|
||||
const tempPath = path.join(os.tmpdir(), `${fileName}.docx`);
|
||||
this.stream = fs.createWriteStream(tempPath);
|
||||
await this.packer.compile(this.stream);
|
||||
const text = await this.pdfConverter.convert(tempPath);
|
||||
// const writeFile = util.promisify(fs.writeFile); --use this in future, in 3 years time. Only in node 8
|
||||
// return writeFile(`${filePath}.pdf`, text);
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
fs.writeFile(`${filePath}.pdf`, text, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
6
src/export/packer/packer.ts
Normal file
6
src/export/packer/packer.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface IPacker {
|
||||
pack(path: string): void;
|
||||
}
|
||||
|
||||
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
|
||||
export const WORKAROUND = "";
|
35
src/export/packer/pdf-convert-wrapper.ts
Normal file
35
src/export/packer/pdf-convert-wrapper.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/* tslint:disable:object-literal-key-quotes */
|
||||
// This tslint disable is needed, or it simply won't work
|
||||
import * as fs from "fs";
|
||||
import * as request from "request-promise";
|
||||
|
||||
export interface IConvertOutput {
|
||||
data: string;
|
||||
}
|
||||
|
||||
export class PdfConvertWrapper {
|
||||
public convert(filePath: string): request.RequestPromise {
|
||||
return request.post({
|
||||
url: "http://mirror1.convertonlinefree.com",
|
||||
encoding: null,
|
||||
headers: {
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36",
|
||||
},
|
||||
formData: {
|
||||
__EVENTTARGET: "",
|
||||
__EVENTARGUMENT: "",
|
||||
__VIEWSTATE: "",
|
||||
ctl00$MainContent$fu: {
|
||||
value: fs.readFileSync(filePath),
|
||||
options: {
|
||||
filename: "output.docx",
|
||||
contentType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
},
|
||||
},
|
||||
ctl00$MainContent$btnConvert: "Convert",
|
||||
ctl00$MainContent$fuZip: "",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
25
src/export/packer/stream.ts
Normal file
25
src/export/packer/stream.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Readable, Transform } from "stream";
|
||||
import { File } from "../../file";
|
||||
import { Compiler } from "./compiler";
|
||||
import { IPacker } from "./packer";
|
||||
|
||||
class Pipe extends Transform {
|
||||
public _transform(chunk: Buffer | string, encoding: string, callback: () => void): void {
|
||||
this.push(chunk, encoding);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
export class StreamPacker implements IPacker {
|
||||
private readonly compiler: Compiler;
|
||||
|
||||
constructor(file: File) {
|
||||
this.compiler = new Compiler(file);
|
||||
}
|
||||
|
||||
public pack(): Readable {
|
||||
const pipe = new Pipe();
|
||||
this.compiler.compile(pipe);
|
||||
return pipe;
|
||||
}
|
||||
}
|
13
src/file/app-properties/app-properties-attributes.ts
Normal file
13
src/file/app-properties/app-properties-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IAppPropertiesAttributes {
|
||||
xmlns: string;
|
||||
vt: string;
|
||||
}
|
||||
|
||||
export class AppPropertiesAttributes extends XmlAttributeComponent<IAppPropertiesAttributes> {
|
||||
protected xmlKeys = {
|
||||
xmlns: "xmlns",
|
||||
vt: "xmlns:vt",
|
||||
};
|
||||
}
|
15
src/file/app-properties/app-properties.ts
Normal file
15
src/file/app-properties/app-properties.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { AppPropertiesAttributes } from "./app-properties-attributes";
|
||||
|
||||
export class AppProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("Properties");
|
||||
|
||||
this.root.push(
|
||||
new AppPropertiesAttributes({
|
||||
xmlns: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
|
||||
vt: "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
11
src/file/content-types/content-types-attributes.ts
Normal file
11
src/file/content-types/content-types-attributes.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IContentTypeAttributes {
|
||||
xmlns?: string;
|
||||
}
|
||||
|
||||
export class ContentTypeAttributes extends XmlAttributeComponent<IContentTypeAttributes> {
|
||||
protected xmlKeys = {
|
||||
xmlns: "xmlns",
|
||||
};
|
||||
}
|
34
src/file/content-types/content-types.ts
Normal file
34
src/file/content-types/content-types.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { ContentTypeAttributes } from "./content-types-attributes";
|
||||
import { Default } from "./default/default";
|
||||
import { Override } from "./override/override";
|
||||
|
||||
export class ContentTypes extends XmlComponent {
|
||||
constructor() {
|
||||
super("Types");
|
||||
|
||||
this.root.push(
|
||||
new ContentTypeAttributes({
|
||||
xmlns: "http://schemas.openxmlformats.org/package/2006/content-types",
|
||||
}),
|
||||
);
|
||||
|
||||
this.root.push(new Default("image/png", "png"));
|
||||
this.root.push(new Default("image/jpeg", "jpeg"));
|
||||
this.root.push(new Default("image/jpeg", "jpg"));
|
||||
this.root.push(new Default("image/bmp", "bmp"));
|
||||
this.root.push(new Default("image/gif", "gif"));
|
||||
this.root.push(new Default("application/vnd.openxmlformats-package.relationships+xml", "rels"));
|
||||
this.root.push(new Default("application/xml", "xml"));
|
||||
|
||||
this.root.push(
|
||||
new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml"),
|
||||
);
|
||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", "/word/header1.xml"));
|
||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", "/word/footer1.xml"));
|
||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", "/word/styles.xml"));
|
||||
this.root.push(new Override("application/vnd.openxmlformats-package.core-properties+xml", "/docProps/core.xml"));
|
||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.extended-properties+xml", "/docProps/app.xml"));
|
||||
this.root.push(new Override("application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", "/word/numbering.xml"));
|
||||
}
|
||||
}
|
13
src/file/content-types/default/default-attributes.ts
Normal file
13
src/file/content-types/default/default-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IDefaultAttributes {
|
||||
contentType: string;
|
||||
extension?: string;
|
||||
}
|
||||
|
||||
export class DefaultAttributes extends XmlAttributeComponent<IDefaultAttributes> {
|
||||
protected xmlKeys = {
|
||||
contentType: "ContentType",
|
||||
extension: "Extension",
|
||||
};
|
||||
}
|
15
src/file/content-types/default/default.ts
Normal file
15
src/file/content-types/default/default.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DefaultAttributes } from "./default-attributes";
|
||||
|
||||
export class Default extends XmlComponent {
|
||||
constructor(contentType: string, extension?: string) {
|
||||
super("Default");
|
||||
|
||||
this.root.push(
|
||||
new DefaultAttributes({
|
||||
contentType: contentType,
|
||||
extension: extension,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
13
src/file/content-types/override/override-attributes.ts
Normal file
13
src/file/content-types/override/override-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IOverrideAttributes {
|
||||
contentType: string;
|
||||
partName?: string;
|
||||
}
|
||||
|
||||
export class OverrideAttributes extends XmlAttributeComponent<IOverrideAttributes> {
|
||||
protected xmlKeys = {
|
||||
contentType: "ContentType",
|
||||
partName: "PartName",
|
||||
};
|
||||
}
|
15
src/file/content-types/override/override.ts
Normal file
15
src/file/content-types/override/override.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { OverrideAttributes } from "./override-attributes";
|
||||
|
||||
export class Override extends XmlComponent {
|
||||
constructor(contentType: string, partName?: string) {
|
||||
super("Override");
|
||||
|
||||
this.root.push(
|
||||
new OverrideAttributes({
|
||||
contentType: contentType,
|
||||
partName: partName,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
import { DocumentAttributes } from "../docx/document/document-attributes";
|
||||
import { XmlComponent } from "../docx/xml-components";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocumentAttributes } from "../document/document-attributes";
|
||||
|
||||
export class Title extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("dc:title");
|
||||
this.root.push(value);
|
||||
@ -10,7 +9,6 @@ export class Title extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Subject extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("dc:subject");
|
||||
this.root.push(value);
|
||||
@ -18,7 +16,6 @@ export class Subject extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Creator extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("dc:creator");
|
||||
this.root.push(value);
|
||||
@ -26,7 +23,6 @@ export class Creator extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Keywords extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("cp:keywords");
|
||||
this.root.push(value);
|
||||
@ -34,7 +30,6 @@ export class Keywords extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Description extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("dc:description");
|
||||
this.root.push(value);
|
||||
@ -42,7 +37,6 @@ export class Description extends XmlComponent {
|
||||
}
|
||||
|
||||
export class LastModifiedBy extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("cp:lastModifiedBy");
|
||||
this.root.push(value);
|
||||
@ -50,7 +44,6 @@ export class LastModifiedBy extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Revision extends XmlComponent {
|
||||
|
||||
constructor(value: string) {
|
||||
super("cp:revision");
|
||||
this.root.push(value);
|
||||
@ -72,23 +65,25 @@ export abstract class DateComponent extends XmlComponent {
|
||||
}
|
||||
|
||||
export class Created extends DateComponent {
|
||||
|
||||
constructor() {
|
||||
super("dcterms:created");
|
||||
this.root.push(new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}));
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}),
|
||||
);
|
||||
this.root.push(this.getCurrentDate());
|
||||
}
|
||||
}
|
||||
|
||||
export class Modified extends DateComponent {
|
||||
|
||||
constructor() {
|
||||
super("dcterms:modified");
|
||||
this.root.push(new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}));
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
type: "dcterms:W3CDTF",
|
||||
}),
|
||||
);
|
||||
this.root.push(this.getCurrentDate());
|
||||
}
|
||||
}
|
1
src/file/core-properties/index.ts
Normal file
1
src/file/core-properties/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./properties";
|
@ -1,13 +1,12 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "../export/formatter";
|
||||
import { Properties } from "./";
|
||||
import { Formatter } from "../../export/formatter";
|
||||
import { CoreProperties } from "./properties";
|
||||
|
||||
describe("Properties", () => {
|
||||
|
||||
describe("#constructor()", () => {
|
||||
it("sets the appropriate attributes on the top-level", () => {
|
||||
const properties = new Properties({});
|
||||
const properties = new CoreProperties({});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||
@ -23,18 +22,16 @@ describe("Properties", () => {
|
||||
});
|
||||
|
||||
it("should create properties with a title", () => {
|
||||
const properties = new Properties({title: "test document"});
|
||||
const properties = new CoreProperties({ title: "test document" });
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||
expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
|
||||
expect(tree["cp:coreProperties"][1]).to.deep.equal(
|
||||
{"dc:title": ["test document"]},
|
||||
);
|
||||
expect(tree["cp:coreProperties"][1]).to.deep.equal({ "dc:title": ["test document"] });
|
||||
});
|
||||
|
||||
it("should create properties with all the attributes given", () => {
|
||||
const properties = new Properties({
|
||||
const properties = new CoreProperties({
|
||||
title: "test document",
|
||||
subject: "test subject",
|
||||
creator: "me",
|
||||
@ -60,14 +57,14 @@ describe("Properties", () => {
|
||||
"dcterms:created",
|
||||
"dcterms:modified",
|
||||
]);
|
||||
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => key(a) < key(b) ? -1 : 1)).to.deep.equal([
|
||||
{"cp:keywords": ["test docx"]},
|
||||
{"cp:lastModifiedBy": ["the author"]},
|
||||
{"cp:revision": ["123"]},
|
||||
{"dc:creator": ["me"]},
|
||||
{"dc:description": ["testing document"]},
|
||||
{"dc:subject": ["test subject"]},
|
||||
{"dc:title": ["test document"]},
|
||||
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => (key(a) < key(b) ? -1 : 1))).to.deep.equal([
|
||||
{ "cp:keywords": ["test docx"] },
|
||||
{ "cp:lastModifiedBy": ["the author"] },
|
||||
{ "cp:revision": ["123"] },
|
||||
{ "dc:creator": ["me"] },
|
||||
{ "dc:description": ["testing document"] },
|
||||
{ "dc:subject": ["test subject"] },
|
||||
{ "dc:title": ["test document"] },
|
||||
]);
|
||||
});
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import { DocumentAttributes } from "../docx/document/document-attributes";
|
||||
import { XmlComponent } from "../docx/xml-components";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocumentAttributes } from "../document/document-attributes";
|
||||
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
||||
|
||||
export interface IPropertiesOptions {
|
||||
@ -12,17 +12,18 @@ export interface IPropertiesOptions {
|
||||
revision?: string;
|
||||
}
|
||||
|
||||
export class Properties extends XmlComponent {
|
||||
|
||||
export class CoreProperties extends XmlComponent {
|
||||
constructor(options: IPropertiesOptions) {
|
||||
super("cp:coreProperties");
|
||||
this.root.push(new DocumentAttributes({
|
||||
cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
|
||||
dc: "http://purl.org/dc/elements/1.1/",
|
||||
dcterms: "http://purl.org/dc/terms/",
|
||||
dcmitype: "http://purl.org/dc/dcmitype/",
|
||||
xsi: "http://www.w3.org/2001/XMLSchema-instance",
|
||||
}));
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
|
||||
dc: "http://purl.org/dc/elements/1.1/",
|
||||
dcterms: "http://purl.org/dc/terms/",
|
||||
dcmitype: "http://purl.org/dc/dcmitype/",
|
||||
xsi: "http://www.w3.org/2001/XMLSchema-instance",
|
||||
}),
|
||||
);
|
||||
if (options.title) {
|
||||
this.root.push(new Title(options.title));
|
||||
}
|
39
src/file/document/body/body.spec.ts
Normal file
39
src/file/document/body/body.spec.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// import { assert } from "chai";
|
||||
|
||||
// import { Utility } from "../../../tests/utility";
|
||||
// import { Body } from "./";
|
||||
|
||||
describe("Body", () => {
|
||||
// let body: Body;
|
||||
|
||||
beforeEach(() => {
|
||||
// body = new Body();
|
||||
});
|
||||
|
||||
// describe("#constructor()", () => {
|
||||
// it("should create the Section Properties", () => {
|
||||
// const newJson = Utility.jsonify(body);
|
||||
// assert.equal(newJson.root[0].rootKey, "w:sectPr");
|
||||
// });
|
||||
|
||||
// it("should create the Page Size", () => {
|
||||
// const newJson = Utility.jsonify(body);
|
||||
// assert.equal(newJson.root[1].rootKey, "w:pgSz");
|
||||
// });
|
||||
|
||||
// it("should create the Page Margin", () => {
|
||||
// const newJson = Utility.jsonify(body);
|
||||
// assert.equal(newJson.root[2].rootKey, "w:pgMar");
|
||||
// });
|
||||
|
||||
// it("should create the Columns", () => {
|
||||
// const newJson = Utility.jsonify(body);
|
||||
// assert.equal(newJson.root[3].rootKey, "w:cols");
|
||||
// });
|
||||
|
||||
// it("should create the Document Grid", () => {
|
||||
// const newJson = Utility.jsonify(body);
|
||||
// assert.equal(newJson.root[4].rootKey, "w:docGrid");
|
||||
// });
|
||||
// });
|
||||
});
|
14
src/file/document/body/body.ts
Normal file
14
src/file/document/body/body.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { SectionProperties, SectionPropertiesOptions } from "./section-properties/section-properties";
|
||||
|
||||
export class Body extends XmlComponent {
|
||||
constructor(sectionPropertiesOptions?: SectionPropertiesOptions) {
|
||||
super("w:body");
|
||||
|
||||
this.root.push(new SectionProperties(sectionPropertiesOptions));
|
||||
}
|
||||
|
||||
public push(component: XmlComponent): void {
|
||||
this.root.push(component);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IColumnsAttributes {
|
||||
space?: number;
|
||||
}
|
||||
|
||||
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||
protected xmlKeys = {
|
||||
space: "w:space",
|
||||
};
|
||||
}
|
13
src/file/document/body/section-properties/columns/columns.ts
Normal file
13
src/file/document/body/section-properties/columns/columns.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { ColumnsAttributes } from "./columns-attributes";
|
||||
|
||||
export class Columns extends XmlComponent {
|
||||
constructor(space: number) {
|
||||
super("w:cols");
|
||||
this.root.push(
|
||||
new ColumnsAttributes({
|
||||
space: space,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IDocGridAttributesProperties {
|
||||
linePitch?: number;
|
||||
}
|
||||
|
||||
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||
protected xmlKeys = {
|
||||
linePitch: "w:linePitch",
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocGridAttributes } from "./doc-grid-attributes";
|
||||
|
||||
export class DocumentGrid extends XmlComponent {
|
||||
constructor(linePitch: number) {
|
||||
super("w:docGrid");
|
||||
this.root.push(
|
||||
new DocGridAttributes({
|
||||
linePitch: linePitch,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IFooterReferenceAttributes {
|
||||
type: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class FooterReferenceAttributes extends XmlAttributeComponent<IFooterReferenceAttributes> {
|
||||
protected xmlKeys = {
|
||||
type: "w:type",
|
||||
id: "r:id",
|
||||
};
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { FooterReferenceAttributes } from "./footer-reference-attributes";
|
||||
|
||||
export class FooterReference extends XmlComponent {
|
||||
constructor() {
|
||||
super("w:footerReference");
|
||||
this.root.push(
|
||||
new FooterReferenceAttributes({
|
||||
type: "default",
|
||||
id: `rId${4}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IHeaderReferenceAttributes {
|
||||
type: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class HeaderReferenceAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
||||
protected xmlKeys = {
|
||||
type: "w:type",
|
||||
id: "r:id",
|
||||
};
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { HeaderReferenceAttributes } from "./header-reference-attributes";
|
||||
|
||||
export class HeaderReference extends XmlComponent {
|
||||
constructor() {
|
||||
super("w:headerReference");
|
||||
this.root.push(
|
||||
new HeaderReferenceAttributes({
|
||||
type: "default",
|
||||
id: `rId${3}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IPageMarginAttributes {
|
||||
top?: number;
|
||||
right?: number;
|
||||
bottom?: number;
|
||||
left?: number;
|
||||
header?: number;
|
||||
footer?: number;
|
||||
gutter?: number;
|
||||
}
|
||||
|
||||
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||
protected xmlKeys = {
|
||||
top: "w:top",
|
||||
right: "w:right",
|
||||
bottom: "w:bottom",
|
||||
left: "w:left",
|
||||
header: "w:header",
|
||||
footer: "w:footer",
|
||||
gutter: "w:gutter",
|
||||
};
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PageMarginAttributes } from "./page-margin-attributes";
|
||||
|
||||
export class PageMargin extends XmlComponent {
|
||||
constructor(top: number, right: number, bottom: number, left: number, header: number, footer: number, gutter: number) {
|
||||
super("w:pgMar");
|
||||
this.root.push(
|
||||
new PageMarginAttributes({
|
||||
top: top,
|
||||
right: right,
|
||||
bottom: bottom,
|
||||
left: left,
|
||||
header: header,
|
||||
footer: footer,
|
||||
gutter: gutter,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IPageSizeAttributes {
|
||||
width?: number;
|
||||
height?: number;
|
||||
orientation?: string;
|
||||
}
|
||||
|
||||
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||
protected xmlKeys = {
|
||||
width: "w:w",
|
||||
height: "w:h",
|
||||
orientation: "w:orient",
|
||||
};
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "../../../../../export/formatter";
|
||||
import { PageSize } from "./page-size";
|
||||
|
||||
describe("PageSize", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create page size with portrait", () => {
|
||||
const properties = new PageSize(100, 200, "portrait");
|
||||
const tree = new Formatter().format(properties);
|
||||
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
|
||||
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 200, "w:w": 100, "w:orient": "portrait" } });
|
||||
});
|
||||
|
||||
it("should create page size with horizontal and invert the lengths", () => {
|
||||
const properties = new PageSize(100, 200, "landscape");
|
||||
const tree = new Formatter().format(properties);
|
||||
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:pgSz"]);
|
||||
expect(tree["w:pgSz"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:pgSz"][0]).to.deep.equal({ _attr: { "w:h": 100, "w:w": 200, "w:orient": "landscape" } });
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,18 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PageSizeAttributes } from "./page-size-attributes";
|
||||
|
||||
export class PageSize extends XmlComponent {
|
||||
constructor(width: number, height: number, orientation: string) {
|
||||
super("w:pgSz");
|
||||
|
||||
const flip = orientation === "landscape";
|
||||
|
||||
this.root.push(
|
||||
new PageSizeAttributes({
|
||||
width: flip ? height : width,
|
||||
height: flip ? width : height,
|
||||
orientation: orientation,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
import { expect } from "chai";
|
||||
|
||||
import { Formatter } from "../../../../export/formatter";
|
||||
import { SectionProperties } from "./section-properties";
|
||||
|
||||
describe("SectionProperties", () => {
|
||||
describe("#constructor()", () => {
|
||||
it("should create section properties with options", () => {
|
||||
const properties = new SectionProperties({
|
||||
width: 11906,
|
||||
height: 16838,
|
||||
top: 1440,
|
||||
right: 1440,
|
||||
bottom: 1440,
|
||||
left: 1440,
|
||||
header: 708,
|
||||
footer: 708,
|
||||
gutter: 0,
|
||||
space: 708,
|
||||
linePitch: 360,
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": [
|
||||
{
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create section properties with no options", () => {
|
||||
const properties = new SectionProperties();
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": [
|
||||
{
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create section properties with changed options", () => {
|
||||
const properties = new SectionProperties({
|
||||
top: 0,
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": [
|
||||
{
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 0,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create section properties with changed options", () => {
|
||||
const properties = new SectionProperties({
|
||||
bottom: 0,
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 16838, "w:w": 11906, "w:orient": "portrait" } }] });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": [
|
||||
{
|
||||
_attr: {
|
||||
"w:bottom": 0,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should create section properties with changed options", () => {
|
||||
const properties = new SectionProperties({
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
const tree = new Formatter().format(properties);
|
||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||
expect(tree["w:sectPr"][0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 0, "w:w": 0, "w:orient": "portrait" } }] });
|
||||
expect(tree["w:sectPr"][1]).to.deep.equal({
|
||||
"w:pgMar": [
|
||||
{
|
||||
_attr: {
|
||||
"w:bottom": 1440,
|
||||
"w:footer": 708,
|
||||
"w:top": 1440,
|
||||
"w:right": 1440,
|
||||
"w:left": 1440,
|
||||
"w:header": 708,
|
||||
"w:gutter": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,57 @@
|
||||
// http://officeopenxml.com/WPsection.php
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Columns } from "./columns/columns";
|
||||
import { IColumnsAttributes } from "./columns/columns-attributes";
|
||||
import { DocumentGrid } from "./doc-grid/doc-grid";
|
||||
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
|
||||
import { FooterReference } from "./footer-reference/footer-reference";
|
||||
import { HeaderReference } from "./header-reference/header-reference";
|
||||
import { PageMargin } from "./page-margin/page-margin";
|
||||
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
|
||||
import { PageSize } from "./page-size/page-size";
|
||||
import { IPageSizeAttributes } from "./page-size/page-size-attributes";
|
||||
|
||||
export type SectionPropertiesOptions = IPageSizeAttributes & IPageMarginAttributes & IColumnsAttributes & IDocGridAttributesProperties;
|
||||
|
||||
export class SectionProperties extends XmlComponent {
|
||||
constructor(options?: SectionPropertiesOptions) {
|
||||
super("w:sectPr");
|
||||
|
||||
const defaultOptions = {
|
||||
width: 11906,
|
||||
height: 16838,
|
||||
top: 1440,
|
||||
right: 1440,
|
||||
bottom: 1440,
|
||||
left: 1440,
|
||||
header: 708,
|
||||
footer: 708,
|
||||
gutter: 0,
|
||||
space: 708,
|
||||
linePitch: 360,
|
||||
orientation: "portrait",
|
||||
};
|
||||
|
||||
const mergedOptions = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
};
|
||||
|
||||
this.root.push(new PageSize(mergedOptions.width, mergedOptions.height, mergedOptions.orientation));
|
||||
this.root.push(
|
||||
new PageMargin(
|
||||
mergedOptions.top,
|
||||
mergedOptions.right,
|
||||
mergedOptions.bottom,
|
||||
mergedOptions.left,
|
||||
mergedOptions.header,
|
||||
mergedOptions.footer,
|
||||
mergedOptions.gutter,
|
||||
),
|
||||
);
|
||||
this.root.push(new Columns(mergedOptions.space));
|
||||
this.root.push(new DocumentGrid(mergedOptions.linePitch));
|
||||
this.root.push(new HeaderReference());
|
||||
this.root.push(new FooterReference());
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { XmlAttributeComponent } from "../xml-components";
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IDocumentAttributesProperties {
|
||||
wpc?: string;
|
83
src/file/document/document.spec.ts
Normal file
83
src/file/document/document.spec.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { assert, expect } from "chai";
|
||||
|
||||
import { Formatter } from "../../export/formatter";
|
||||
import { Paragraph } from "../paragraph";
|
||||
import { Table } from "../table";
|
||||
import { Document } from "./document";
|
||||
|
||||
describe("Document", () => {
|
||||
let document: Document;
|
||||
|
||||
beforeEach(() => {
|
||||
document = new Document();
|
||||
});
|
||||
|
||||
describe("#constructor()", () => {
|
||||
it("should create valid JSON", () => {
|
||||
const stringifiedJson = JSON.stringify(document);
|
||||
|
||||
try {
|
||||
JSON.parse(stringifiedJson);
|
||||
} catch (e) {
|
||||
assert.isTrue(false);
|
||||
}
|
||||
assert.isTrue(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#createParagraph", () => {
|
||||
it("should create a new paragraph and append it to body", () => {
|
||||
const para = document.createParagraph();
|
||||
expect(para).to.be.an.instanceof(Paragraph);
|
||||
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||
expect(body)
|
||||
.to.be.an("array")
|
||||
.which.has.length.at.least(1);
|
||||
expect(body[1]).to.have.property("w:p");
|
||||
});
|
||||
|
||||
it("should use the text given to create a run in the paragraph", () => {
|
||||
const para = document.createParagraph("sample paragraph text");
|
||||
expect(para).to.be.an.instanceof(Paragraph);
|
||||
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||
expect(body)
|
||||
.to.be.an("array")
|
||||
.which.has.length.at.least(1);
|
||||
expect(body[1])
|
||||
.to.have.property("w:p")
|
||||
.which.includes({
|
||||
"w:r": [{ "w:rPr": [] }, { "w:t": [{ _attr: { "xml:space": "preserve" } }, "sample paragraph text"] }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#createTable", () => {
|
||||
it("should create a new table and append it to body", () => {
|
||||
const table = document.createTable(2, 3);
|
||||
expect(table).to.be.an.instanceof(Table);
|
||||
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||
expect(body)
|
||||
.to.be.an("array")
|
||||
.which.has.length.at.least(1);
|
||||
expect(body[1]).to.have.property("w:tbl");
|
||||
});
|
||||
|
||||
it("should create a table with the correct dimensions", () => {
|
||||
document.createTable(2, 3);
|
||||
const body = new Formatter().format(document)["w:document"][1]["w:body"];
|
||||
expect(body)
|
||||
.to.be.an("array")
|
||||
.which.has.length.at.least(1);
|
||||
expect(body[1])
|
||||
.to.have.property("w:tbl")
|
||||
.which.includes({
|
||||
"w:tblGrid": [
|
||||
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||
{ "w:gridCol": [{ _attr: { "w:w": 1 } }] },
|
||||
],
|
||||
});
|
||||
expect(body[1]["w:tbl"].filter((x) => x["w:tr"])).to.have.length(2);
|
||||
});
|
||||
});
|
||||
});
|
73
src/file/document/document.ts
Normal file
73
src/file/document/document.ts
Normal file
@ -0,0 +1,73 @@
|
||||
// http://officeopenxml.com/WPdocument.php
|
||||
import { IMediaData } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Paragraph, PictureRun } from "../paragraph";
|
||||
import { Table } from "../table";
|
||||
import { Body } from "./body";
|
||||
import { SectionPropertiesOptions } from "./body/section-properties/section-properties";
|
||||
import { DocumentAttributes } from "./document-attributes";
|
||||
|
||||
export class Document extends XmlComponent {
|
||||
private readonly body: Body;
|
||||
|
||||
constructor(sectionPropertiesOptions?: SectionPropertiesOptions) {
|
||||
super("w:document");
|
||||
this.root.push(
|
||||
new DocumentAttributes({
|
||||
wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
|
||||
mc: "http://schemas.openxmlformats.org/markup-compatibility/2006",
|
||||
o: "urn:schemas-microsoft-com:office:office",
|
||||
r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
||||
m: "http://schemas.openxmlformats.org/officeDocument/2006/math",
|
||||
v: "urn:schemas-microsoft-com:vml",
|
||||
wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
|
||||
wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
|
||||
w10: "urn:schemas-microsoft-com:office:word",
|
||||
w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
||||
w14: "http://schemas.microsoft.com/office/word/2010/wordml",
|
||||
w15: "http://schemas.microsoft.com/office/word/2012/wordml",
|
||||
wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
|
||||
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
|
||||
wne: "http://schemas.microsoft.com/office/word/2006/wordml",
|
||||
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
|
||||
Ignorable: "w14 w15 wp14",
|
||||
}),
|
||||
);
|
||||
this.body = new Body(sectionPropertiesOptions);
|
||||
this.root.push(this.body);
|
||||
}
|
||||
|
||||
public addParagraph(paragraph: Paragraph): void {
|
||||
this.body.push(paragraph);
|
||||
}
|
||||
|
||||
public createParagraph(text?: string): Paragraph {
|
||||
const para = new Paragraph(text);
|
||||
this.addParagraph(para);
|
||||
return para;
|
||||
}
|
||||
|
||||
public addTable(table: Table): void {
|
||||
this.body.push(table);
|
||||
}
|
||||
|
||||
public createTable(rows: number, cols: number): Table {
|
||||
const table = new Table(rows, cols);
|
||||
this.addTable(table);
|
||||
return table;
|
||||
}
|
||||
|
||||
public addDrawing(pictureParagraph: Paragraph): void {
|
||||
this.body.push(pictureParagraph);
|
||||
}
|
||||
|
||||
public createDrawing(imageData: IMediaData): PictureRun {
|
||||
const paragraph = new Paragraph();
|
||||
const run = new PictureRun(imageData);
|
||||
|
||||
paragraph.addRun(run);
|
||||
this.addDrawing(paragraph);
|
||||
|
||||
return run;
|
||||
}
|
||||
}
|
@ -1,19 +1,29 @@
|
||||
import { assert } from "chai";
|
||||
import * as fs from "fs";
|
||||
|
||||
import { Utility } from "../../../../tests/utility";
|
||||
import { Utility } from "../../tests/utility";
|
||||
import { Drawing } from "./";
|
||||
|
||||
describe("Drawing", () => {
|
||||
let currentBreak: Drawing;
|
||||
|
||||
beforeEach(() => {
|
||||
const path = "./demo/penguins.jpg";
|
||||
const path = "./demo/images/image1.jpeg";
|
||||
currentBreak = new Drawing({
|
||||
fileName: "test.jpg",
|
||||
referenceId: 1,
|
||||
stream: fs.createReadStream(path),
|
||||
path: path,
|
||||
dimensions: {
|
||||
pixels: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
emus: {
|
||||
x: 100 * 9525,
|
||||
y: 100 * 9525,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
23
src/file/drawing/drawing.ts
Normal file
23
src/file/drawing/drawing.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { IMediaData } from "file/media";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Inline } from "./inline";
|
||||
|
||||
export class Drawing extends XmlComponent {
|
||||
private inline: Inline;
|
||||
|
||||
constructor(imageData: IMediaData) {
|
||||
super("w:drawing");
|
||||
|
||||
if (imageData === undefined) {
|
||||
throw new Error("imageData cannot be undefined");
|
||||
}
|
||||
|
||||
this.inline = new Inline(imageData.referenceId, imageData.dimensions);
|
||||
|
||||
this.root.push(this.inline);
|
||||
}
|
||||
|
||||
public scale(factorX: number, factorY: number): void {
|
||||
this.inline.scale(factorX, factorY);
|
||||
}
|
||||
}
|
1
src/file/drawing/index.ts
Normal file
1
src/file/drawing/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { Drawing } from "./drawing";
|
@ -0,0 +1,15 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IDocPropertiesAttributes {
|
||||
id?: number;
|
||||
name?: string;
|
||||
descr?: string;
|
||||
}
|
||||
|
||||
export class DocPropertiesAttributes extends XmlAttributeComponent<IDocPropertiesAttributes> {
|
||||
protected xmlKeys = {
|
||||
id: "id",
|
||||
name: "name",
|
||||
descr: "descr",
|
||||
};
|
||||
}
|
16
src/file/drawing/inline/doc-properties/doc-properties.ts
Normal file
16
src/file/drawing/inline/doc-properties/doc-properties.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { DocPropertiesAttributes } from "./doc-properties-attributes";
|
||||
|
||||
export class DocProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("wp:docPr");
|
||||
|
||||
this.root.push(
|
||||
new DocPropertiesAttributes({
|
||||
id: 0,
|
||||
name: "",
|
||||
descr: "",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IEffectExtentAttributes {
|
||||
b?: number;
|
||||
l?: number;
|
||||
r?: number;
|
||||
t?: number;
|
||||
}
|
||||
|
||||
export class EffectExtentAttributes extends XmlAttributeComponent<IEffectExtentAttributes> {
|
||||
protected xmlKeys = {
|
||||
b: "b",
|
||||
l: "l",
|
||||
r: "r",
|
||||
t: "t",
|
||||
};
|
||||
}
|
17
src/file/drawing/inline/effect-extent/effect-extent.ts
Normal file
17
src/file/drawing/inline/effect-extent/effect-extent.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { EffectExtentAttributes } from "./effect-extent-attributes";
|
||||
|
||||
export class EffectExtent extends XmlComponent {
|
||||
constructor() {
|
||||
super("wp:effectExtent");
|
||||
|
||||
this.root.push(
|
||||
new EffectExtentAttributes({
|
||||
b: 0,
|
||||
l: 0,
|
||||
r: 0,
|
||||
t: 0,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
13
src/file/drawing/inline/extent/extent-attributes.ts
Normal file
13
src/file/drawing/inline/extent/extent-attributes.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IExtentAttributes {
|
||||
cx?: number;
|
||||
cy?: number;
|
||||
}
|
||||
|
||||
export class ExtentAttributes extends XmlAttributeComponent<IExtentAttributes> {
|
||||
protected xmlKeys = {
|
||||
cx: "cx",
|
||||
cy: "cy",
|
||||
};
|
||||
}
|
24
src/file/drawing/inline/extent/extent.ts
Normal file
24
src/file/drawing/inline/extent/extent.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { ExtentAttributes } from "./extent-attributes";
|
||||
|
||||
export class Extent extends XmlComponent {
|
||||
private attributes: ExtentAttributes;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
super("wp:extent");
|
||||
|
||||
this.attributes = new ExtentAttributes({
|
||||
cx: x,
|
||||
cy: y,
|
||||
});
|
||||
|
||||
this.root.push(this.attributes);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.attributes.set({
|
||||
cx: x,
|
||||
cy: y,
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IGraphicFrameLockAttributes {
|
||||
xmlns?: string;
|
||||
noChangeAspect?: number;
|
||||
}
|
||||
|
||||
export class GraphicFrameLockAttributes extends XmlAttributeComponent<IGraphicFrameLockAttributes> {
|
||||
protected xmlKeys = {
|
||||
xmlns: "xmlns:a",
|
||||
noChangeAspect: "noChangeAspect",
|
||||
};
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { GraphicFrameLockAttributes } from "./graphic-frame-lock-attributes";
|
||||
|
||||
export class GraphicFrameLocks extends XmlComponent {
|
||||
constructor() {
|
||||
super("a:graphicFrameLocks");
|
||||
|
||||
this.root.push(
|
||||
new GraphicFrameLockAttributes({
|
||||
xmlns: "http://schemas.openxmlformats.org/drawingml/2006/main",
|
||||
noChangeAspect: 1,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { GraphicFrameLocks } from "./graphic-frame-locks/graphic-frame-locks";
|
||||
|
||||
export class GraphicFrameProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("wp:cNvGraphicFramePr");
|
||||
|
||||
this.root.push(new GraphicFrameLocks());
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IGraphicDataAttributes {
|
||||
uri?: string;
|
||||
}
|
||||
|
||||
export class GraphicDataAttributes extends XmlAttributeComponent<IGraphicDataAttributes> {
|
||||
protected xmlKeys = {
|
||||
uri: "uri",
|
||||
};
|
||||
}
|
25
src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
Normal file
25
src/file/drawing/inline/graphic/graphic-data/graphic-data.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { GraphicDataAttributes } from "./graphic-data-attribute";
|
||||
import { Pic } from "./pic";
|
||||
|
||||
export class GraphicData extends XmlComponent {
|
||||
private pic: Pic;
|
||||
|
||||
constructor(referenceId: number, x: number, y: number) {
|
||||
super("a:graphicData");
|
||||
|
||||
this.root.push(
|
||||
new GraphicDataAttributes({
|
||||
uri: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||
}),
|
||||
);
|
||||
|
||||
this.pic = new Pic(referenceId, x, y);
|
||||
|
||||
this.root.push(this.pic);
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.pic.setXY(x, y);
|
||||
}
|
||||
}
|
1
src/file/drawing/inline/graphic/graphic-data/index.ts
Normal file
1
src/file/drawing/inline/graphic/graphic-data/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./graphic-data";
|
@ -1,10 +1,9 @@
|
||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { Blip } from "./blip";
|
||||
import { SourceRectangle } from "./source-rectangle";
|
||||
import { Stretch } from "./stretch";
|
||||
|
||||
export class BlipFill extends XmlComponent {
|
||||
|
||||
constructor(referenceId: number) {
|
||||
super("pic:blipFill");
|
||||
this.root.push(new Blip(referenceId));
|
@ -1,21 +1,25 @@
|
||||
import { XmlAttributeComponent, XmlComponent } from "../../../../../../../../xml-components";
|
||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||
|
||||
interface IBlipProperties {
|
||||
embed: string;
|
||||
cstate: string;
|
||||
}
|
||||
|
||||
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
|
||||
protected xmlKeys = {
|
||||
embed: "r:embed",
|
||||
cstate: "cstate",
|
||||
};
|
||||
}
|
||||
|
||||
export class Blip extends XmlComponent {
|
||||
|
||||
constructor(referenceId: number) {
|
||||
super("a:blip");
|
||||
this.root.push(new BlipAttributes({
|
||||
embed: `rId${referenceId}`,
|
||||
}));
|
||||
this.root.push(
|
||||
new BlipAttributes({
|
||||
embed: `rId${referenceId}`,
|
||||
cstate: "none",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
export class SourceRectangle extends XmlComponent {
|
||||
|
||||
constructor() {
|
||||
super("a:srcRect");
|
||||
}
|
@ -1,14 +1,12 @@
|
||||
import { XmlComponent } from "../../../../../../../../xml-components";
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
|
||||
class FillRectangle extends XmlComponent {
|
||||
|
||||
constructor() {
|
||||
super("a:fillRect");
|
||||
}
|
||||
}
|
||||
|
||||
export class Stretch extends XmlComponent {
|
||||
|
||||
constructor() {
|
||||
super("a:stretch");
|
||||
this.root.push(new FillRectangle());
|
@ -0,0 +1 @@
|
||||
export * from "./pic";
|
@ -0,0 +1,10 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PicLocks } from "./pic-locks/pic-locks";
|
||||
|
||||
export class ChildNonVisualProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("pic:cNvPicPr");
|
||||
|
||||
this.root.push(new PicLocks());
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IPicLocksAttributes {
|
||||
noChangeAspect?: number;
|
||||
noChangeArrowheads?: number;
|
||||
}
|
||||
|
||||
export class PicLocksAttributes extends XmlAttributeComponent<IPicLocksAttributes> {
|
||||
protected xmlKeys = {
|
||||
noChangeAspect: "noChangeAspect",
|
||||
noChangeArrowheads: "noChangeArrowheads",
|
||||
};
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { PicLocksAttributes } from "./pic-locks-attributes";
|
||||
|
||||
export class PicLocks extends XmlComponent {
|
||||
constructor() {
|
||||
super("a:picLocks");
|
||||
this.root.push(
|
||||
new PicLocksAttributes({
|
||||
noChangeAspect: 1,
|
||||
noChangeArrowheads: 1,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { ChildNonVisualProperties } from "./child-non-visual-pic-properties/child-non-visual-pic-properties";
|
||||
import { NonVisualProperties } from "./non-visual-properties/non-visual-properties";
|
||||
|
||||
export class NonVisualPicProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("pic:nvPicPr");
|
||||
|
||||
this.root.push(new NonVisualProperties());
|
||||
this.root.push(new ChildNonVisualProperties());
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface INonVisualPropertiesAttributes {
|
||||
id?: number;
|
||||
name?: string;
|
||||
descr?: string;
|
||||
}
|
||||
|
||||
export class NonVisualPropertiesAttributes extends XmlAttributeComponent<INonVisualPropertiesAttributes> {
|
||||
protected xmlKeys = {
|
||||
id: "id",
|
||||
name: "name",
|
||||
descr: "desc",
|
||||
};
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { NonVisualPropertiesAttributes } from "./non-visual-properties-attributes";
|
||||
|
||||
export class NonVisualProperties extends XmlComponent {
|
||||
constructor() {
|
||||
super("pic:cNvPr");
|
||||
|
||||
this.root.push(
|
||||
new NonVisualPropertiesAttributes({
|
||||
id: 0,
|
||||
name: "",
|
||||
descr: "",
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IPicAttributes {
|
||||
xmlns?: string;
|
||||
}
|
||||
|
||||
export class PicAttributes extends XmlAttributeComponent<IPicAttributes> {
|
||||
protected xmlKeys = {
|
||||
xmlns: "xmlns:pic",
|
||||
};
|
||||
}
|
30
src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
Normal file
30
src/file/drawing/inline/graphic/graphic-data/pic/pic.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// http://officeopenxml.com/drwPic.php
|
||||
import { XmlComponent } from "file/xml-components";
|
||||
import { BlipFill } from "./blip/blip-fill";
|
||||
import { NonVisualPicProperties } from "./non-visual-pic-properties/non-visual-pic-properties";
|
||||
import { PicAttributes } from "./pic-attributes";
|
||||
import { ShapeProperties } from "./shape-properties/shape-properties";
|
||||
|
||||
export class Pic extends XmlComponent {
|
||||
private shapeProperties: ShapeProperties;
|
||||
|
||||
constructor(referenceId: number, x: number, y: number) {
|
||||
super("pic:pic");
|
||||
|
||||
this.root.push(
|
||||
new PicAttributes({
|
||||
xmlns: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
||||
}),
|
||||
);
|
||||
|
||||
this.shapeProperties = new ShapeProperties(x, y);
|
||||
|
||||
this.root.push(new NonVisualPicProperties());
|
||||
this.root.push(new BlipFill(referenceId));
|
||||
this.root.push(new ShapeProperties(x, y));
|
||||
}
|
||||
|
||||
public setXY(x: number, y: number): void {
|
||||
this.shapeProperties.setXY(x, y);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { XmlAttributeComponent } from "file/xml-components";
|
||||
|
||||
export interface IExtentsAttributes {
|
||||
cx?: number;
|
||||
cy?: number;
|
||||
}
|
||||
|
||||
export class ExtentsAttributes extends XmlAttributeComponent<IExtentsAttributes> {
|
||||
protected xmlKeys = {
|
||||
cx: "cx",
|
||||
cy: "cy",
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user