Compare commits
111 Commits
Author | SHA1 | Date | |
---|---|---|---|
8dc590746b | |||
de5f5c9a77 | |||
ca5f6a56a5 | |||
8f6984580a | |||
da0fa86345 | |||
78b310e1dd | |||
4541d7c977 | |||
a37ff90bd7 | |||
9998ddfcc9 | |||
12ed54c9fd | |||
3a1a21e498 | |||
e5bfa99b92 | |||
f640f17fa6 | |||
494a32d45d | |||
8040a455be | |||
f091cff7c9 | |||
401ef7336b | |||
18134519be | |||
7980f14efb | |||
40d6a41305 | |||
9cfd835171 | |||
95a9f592eb | |||
61411fd0f3 | |||
a84eb16392 | |||
3355a6f472 | |||
071a8ea9f7 | |||
ea3777d28b | |||
3346b97ee7 | |||
2b834a75a8 | |||
21df53d547 | |||
9143c1c2c1 | |||
83cab7563d | |||
b05fbe7f6e | |||
e6a57738f4 | |||
cc6e35165a | |||
7791ddf76e | |||
4742cf0f3f | |||
8858970491 | |||
f7d18bfead | |||
0ce1b7fa15 | |||
4633592711 | |||
54697ab6b1 | |||
1eed844b9a | |||
dd89fe2463 | |||
9c66db97ff | |||
fea6afdfe4 | |||
6ec2e742ef | |||
3f80b054fc | |||
96d81873d8 | |||
c429ae9920 | |||
6b4e769f48 | |||
b67a9de0e9 | |||
ac9f65a068 | |||
7e8ebb2af2 | |||
f53fe2f881 | |||
6fdd88527a | |||
b6f431e14d | |||
23dee01f06 | |||
5532f91423 | |||
c849d5f3e5 | |||
3f3fd05cb1 | |||
a5bedf9a5b | |||
9d9dd62f00 | |||
97f76fb62c | |||
3508fd97ec | |||
90f6f68693 | |||
733775d3b9 | |||
f3aa6a9203 | |||
ffdcc7baca | |||
a1e20f4c9a | |||
048ae6a58c | |||
fafa54e4c9 | |||
60dbb32e9e | |||
52b07fd9cb | |||
8ec5bc05e0 | |||
6e0c12afb3 | |||
466e880bfc | |||
0a8feca6ab | |||
f2b50478bf | |||
fc71ebdfef | |||
10114bb12d | |||
e6d4741955 | |||
4d7387524c | |||
5fe4405d76 | |||
79dffc873a | |||
26ee12759c | |||
2e00634bc4 | |||
d63e6bf6b1 | |||
a95366e54e | |||
1c376abeb6 | |||
353d888abd | |||
b6bd532295 | |||
c5b004166d | |||
2f43600daf | |||
b39c7ce323 | |||
5b00279996 | |||
d1d1e01aff | |||
980bc597e2 | |||
a05c5edd49 | |||
985452f5f4 | |||
482674b3b3 | |||
fcbfed9068 | |||
385ad92331 | |||
571f8b526b | |||
7688aa99f6 | |||
4994bca34c | |||
1a3603dbfb | |||
e382dbff84 | |||
e08be3d7a4 | |||
03c4190c2c | |||
010fde6258 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -58,5 +58,8 @@ yarn.lock
|
|||||||
# Documents
|
# Documents
|
||||||
My Document.docx
|
My Document.docx
|
||||||
|
|
||||||
# Temporary folder
|
# Temporary folder
|
||||||
tmp
|
tmp
|
||||||
|
|
||||||
|
# nyc
|
||||||
|
.nyc_output
|
||||||
|
25
.nycrc
Normal file
25
.nycrc
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"check-coverage": true,
|
||||||
|
"lines": 87.54,
|
||||||
|
"functions": 83.61,
|
||||||
|
"branches": 72.57,
|
||||||
|
"statements": 87.32,
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"src/**/*.spec.ts"
|
||||||
|
],
|
||||||
|
"reporter": [
|
||||||
|
"lcov",
|
||||||
|
"text",
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"extension": [
|
||||||
|
".ts"
|
||||||
|
],
|
||||||
|
"cache": true,
|
||||||
|
"all": true,
|
||||||
|
"instrument": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
14
.travis.yml
14
.travis.yml
@ -3,9 +3,10 @@ node_js:
|
|||||||
- 9
|
- 9
|
||||||
install:
|
install:
|
||||||
- npm install
|
- npm install
|
||||||
|
- npm install -g codecov
|
||||||
script:
|
script:
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm test
|
- npm run test.coverage
|
||||||
- npm run style
|
- npm run style
|
||||||
- npm run build
|
- npm run build
|
||||||
- npm run ts-node -- ./demo/demo1.ts
|
- npm run ts-node -- ./demo/demo1.ts
|
||||||
@ -32,12 +33,23 @@ script:
|
|||||||
- npm run ts-node -- ./demo/demo22.ts
|
- npm run ts-node -- ./demo/demo22.ts
|
||||||
- npm run ts-node -- ./demo/demo23.ts
|
- npm run ts-node -- ./demo/demo23.ts
|
||||||
- npm run ts-node -- ./demo/demo24.ts
|
- npm run ts-node -- ./demo/demo24.ts
|
||||||
|
# - npm run ts-node -- ./demo/demo25.ts
|
||||||
|
- npm run ts-node -- ./demo/demo26.ts
|
||||||
|
- npm run ts-node -- ./demo/demo27.ts
|
||||||
|
- npm run ts-node -- ./demo/demo28.ts
|
||||||
|
- npm run ts-node -- ./demo/demo29.ts
|
||||||
|
- npm run ts-node -- ./demo/demo30.ts
|
||||||
|
- npm run ts-node -- ./demo/demo31.ts
|
||||||
|
- npm run ts-node -- ./demo/demo32.ts
|
||||||
|
- npm run ts-node -- ./demo/demo33.ts
|
||||||
|
- npm run ts-node -- ./demo/demo34.ts
|
||||||
after_failure:
|
after_failure:
|
||||||
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
|
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
|
||||||
after_success:
|
after_success:
|
||||||
- npm run typedoc
|
- npm run typedoc
|
||||||
- echo "docx.js.org" > docs/.nojekyll
|
- echo "docx.js.org" > docs/.nojekyll
|
||||||
- echo "docx.js.org" > docs/CNAME
|
- echo "docx.js.org" > docs/CNAME
|
||||||
|
- codecov
|
||||||
deploy:
|
deploy:
|
||||||
provider: pages
|
provider: pages
|
||||||
skip-cleanup: true
|
skip-cleanup: true
|
||||||
|
24
.vscode/tasks.json
vendored
Normal file
24
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "typescript",
|
||||||
|
"tsconfig": "tsconfig.json",
|
||||||
|
"option": "watch",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$tsc-watch"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "ts-node",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
[![Known Vulnerabilities][snky-image]][snky-url]
|
[![Known Vulnerabilities][snky-image]][snky-url]
|
||||||
[![Chat on Gitter][gitter-image]][gitter-url]
|
[![Chat on Gitter][gitter-image]][gitter-url]
|
||||||
[![PRs Welcome][pr-image]][pr-url]
|
[![PRs Welcome][pr-image]][pr-url]
|
||||||
|
[![codecov][codecov-image]][codecov-url]
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://i.imgur.com/H5FA1Qy.gif" alt="drawing" width="800"/>
|
<img src="https://i.imgur.com/H5FA1Qy.gif" alt="drawing" width="800"/>
|
||||||
@ -29,6 +30,10 @@ Here are examples of `docx` being used with basic `HTML/JS` in a browser environ
|
|||||||
* https://codepen.io/anon/pen/dqoVgQ
|
* https://codepen.io/anon/pen/dqoVgQ
|
||||||
* https://jsfiddle.net/3xhezb5w/2
|
* https://jsfiddle.net/3xhezb5w/2
|
||||||
|
|
||||||
|
Here is an example of `docx` working in `Angular`:
|
||||||
|
|
||||||
|
* https://stackblitz.com/edit/angular-afvxtz
|
||||||
|
|
||||||
## Node
|
## Node
|
||||||
|
|
||||||
Press `endpoint` on the `RunKit` website:
|
Press `endpoint` on the `RunKit` website:
|
||||||
@ -77,3 +82,5 @@ Made with 💖
|
|||||||
[gitter-url]: https://gitter.im/docx-lib/Lobby
|
[gitter-url]: https://gitter.im/docx-lib/Lobby
|
||||||
[pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
|
[pr-image]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
|
||||||
[pr-url]: http://makeapullrequest.com
|
[pr-url]: http://makeapullrequest.com
|
||||||
|
[codecov-image]: https://codecov.io/gh/dolanmiu/docx/branch/master/graph/badge.svg
|
||||||
|
[codecov-url]: https://codecov.io/gh/dolanmiu/docx
|
||||||
|
@ -15,8 +15,12 @@ const footer = doc.createFooter();
|
|||||||
footer.createParagraph("Footer on another page");
|
footer.createParagraph("Footer on another page");
|
||||||
|
|
||||||
doc.addSection({
|
doc.addSection({
|
||||||
headerId: header.Header.ReferenceId,
|
headers: {
|
||||||
footerId: footer.Footer.ReferenceId,
|
default: header,
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: footer,
|
||||||
|
},
|
||||||
pageNumberStart: 1,
|
pageNumberStart: 1,
|
||||||
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
||||||
});
|
});
|
||||||
@ -24,8 +28,12 @@ doc.addSection({
|
|||||||
doc.createParagraph("hello");
|
doc.createParagraph("hello");
|
||||||
|
|
||||||
doc.addSection({
|
doc.addSection({
|
||||||
headerId: header.Header.ReferenceId,
|
headers: {
|
||||||
footerId: footer.Footer.ReferenceId,
|
default: header,
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: footer,
|
||||||
|
},
|
||||||
pageNumberStart: 1,
|
pageNumberStart: 1,
|
||||||
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
||||||
orientation: PageOrientation.LANDSCAPE,
|
orientation: PageOrientation.LANDSCAPE,
|
||||||
|
@ -8,11 +8,11 @@ const doc = new Document();
|
|||||||
const paragraph = new Paragraph("Hello World");
|
const paragraph = new Paragraph("Hello World");
|
||||||
doc.addParagraph(paragraph);
|
doc.addParagraph(paragraph);
|
||||||
|
|
||||||
const image = Media.addImage(doc, "./demo/images/image1.jpeg");
|
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
|
||||||
const image2 = Media.addImage(doc, "./demo/images/dog.png");
|
const image2 = Media.addImage(doc, fs.readFileSync("./demo/images/dog.png"));
|
||||||
const image3 = Media.addImage(doc, "./demo/images/cat.jpg");
|
const image3 = Media.addImage(doc, fs.readFileSync("./demo/images/cat.jpg"));
|
||||||
const image4 = Media.addImage(doc, "./demo/images/parrots.bmp");
|
const image4 = Media.addImage(doc, fs.readFileSync("./demo/images/parrots.bmp"));
|
||||||
const image5 = Media.addImage(doc, "./demo/images/pizza.gif");
|
const image5 = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
|
||||||
|
|
||||||
const imageBase64Data = `iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAACzVBMVEUAAAAAAAAAAAAAAAA/AD8zMzMqKiokJCQfHx8cHBwZGRkuFxcqFSonJyckJCQiIiIfHx8eHh4cHBwoGhomGSYkJCQhISEfHx8eHh4nHR0lHBwkGyQjIyMiIiIgICAfHx8mHh4lHh4kHR0jHCMiGyIhISEgICAfHx8lHx8kHh4jHR0hHCEhISEgICAlHx8kHx8jHh4jHh4iHSIhHCEhISElICAkHx8jHx8jHh4iHh4iHSIhHSElICAkICAjHx8jHx8iHh4iHh4hHiEhHSEkICAjHx8iHx8iHx8hHh4hHiEkHSEjHSAjHx8iHx8iHx8hHh4kHiEkHiEjHSAiHx8hHx8hHh4kHiEjHiAjHSAiHx8iHx8hHx8kHh4jHiEjHiAjHiAiICAiHx8kHx8jHh4jHiEjHiAiHiAiHSAiHx8jHx8jHx8jHiAiHiAiHiAiHSAiHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8jHx8iHiAiHiAiHiAjHx8jHx8jHx8iHx8iHSAiHiAjHiAjHx8jHx8hHx8iHx8iHyAiHiAjHiAjHiAjHh4hHx8iHx8iHx8iHyAjHSAjHiAjHiAjHh4hHx8iHx8iHx8jHyAjHiAhHh4iHx8iHx8jHyAjHSAjHSAhHiAhHh4iHx8iHx8jHx8jHyAjHSAjHSAiHh4iHh4jHx8jHx8jHyAjHyAhHSAhHSAiHh4iHh4jHx8jHx8jHyAhHyAhHSAiHSAiHh4jHh4jHx8jHx8jHyAhHyAhHSAiHSAjHR4jHh4jHx8jHx8hHyAhHyAiHSAjHSAjHR4jHh4jHx8hHx8hHyAhHyAiHyAjHSAjHR4jHR4hHh4hHx8hHyAiHyAjHyAjHSAjHR4jHR4hHh4hHx8hHyAjHyAjHyAjHSAjHR4hHR4hHR4hHx8iHyAjHyAjHyAjHSAhHR4hHR4hHR4hHx8jHyAjHyAjHyAjHyC9S2xeAAAA7nRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFxgZGhscHR4fICEiIyQlJicoKSorLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZISUpLTE1OUFFSU1RVVllaW1xdXmBhYmNkZWZnaGprbG1ub3Byc3R1dnd4eXp8fn+AgYKDhIWGiImKi4yNj5CRkpOUlZaXmJmam5ydnp+goaKjpKaoqqusra6vsLGys7S1tri5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+fkZpVQAABcBJREFUGBntwftjlQMcBvDnnLNL22qzJjWlKLHFVogyty3SiFq6EZliqZGyhnSxsLlMRahYoZKRFcul5dKFCatYqWZaNKvWtrPz/A2+7/b27qRzec/lPfvl/XxgMplMJpPJZDKZAtA9HJ3ppnIez0KnSdtC0RCNznHdJrbrh85wdSlVVRaEXuoGamYi5K5430HNiTiEWHKJg05eRWgNfKeV7RxbqUhGKPV/207VupQ8is0IoX5vtFC18SqEHaK4GyHTZ2kzVR8PBTCO4oANIZL4ShNVZcOhKKeYg9DoWdhI1ec3os2VFI0JCIUez5+i6st0qJZRrEAIJCw+QdW223BG/EmKwTBc/IJ/qfp2FDrkUnwFo8U9dZyqnaPhxLqfYjyM1S3vb6p+GGOBszsojoTDSDFz6qj66R4LzvYJxVMwUNRjf1H1ywQr/megg2RzLximy8waqvbda8M5iijegVEiHjlM1W/3h+FcXesphsMY4dMOUnUgOxyuPEzxPQwRNvV3qg5Nj4BreyimwADWe/dRVTMjEm6MoGLzGwtystL6RyOY3qSqdlYU3FpLZw1VW0sK5943MvUCKwJ1noNtjs6Ohge76Zq9ZkfpigU5WWkDYuCfbs1U5HWFR8/Qq4a9W0uK5k4ZmdrTCl8spGIePLPlbqqsc1Afe83O0hULc8alDYiBd7ZyitYMeBfR55rR2fOKP6ioPk2dGvZ+UVI0d8rtqT2tcCexlqK2F3wRn5Q+YVbBqrLKOupkr9lZujAOrmS0UpTb4JeIPkNHZ+cXr6uoPk2vyuBSPhWLEKj45PQJuQWryyqP0Z14uGLdROHIRNBEXDR09EP5r62rOHCazhrD4VKPwxTH+sIA3ZPTJ+YuWV22n+IruHFDC8X2CBjnPoolcGc2FYUwzmsUWXDHsoGKLBhmN0VvuBVfTVE/AAbpaid5CB4MbaLY1QXGuIViLTyZQcVyGGMuxWPwaA0Vk2GI9RRp8Ci2iuLkIBjhT5LNUfAspZFiTwyC72KK7+DNg1SsRvCNp3gZXq2k4iEEXSHFJHgVXUlxejCCbTvFAHiXdIJiXxyCK7KJ5FHoMZGK9xBcwyg2QpdlVMxEUM2iyIMuXXZQNF+HswxMsSAAJRQjoE//eoqDCXBSTO6f1xd+O0iyNRY6jaWi1ALNYCocZROj4JdEikroVkjFk9DcStXxpdfCD2MoXodu4RUU9ptxxmXssOfxnvDVcxRTod9FxyhqLoAqis5aPhwTDp9spRgEH2Q6KLbYoKqlaKTm6Isp0C/sJMnjFvhiERXPQvUNRe9p29lhR04CdBpC8Sl8YiuncIxEuzUUg4Dkgj+paVozygY9plPMh28SaymO9kabAopREGF3vt9MzeFFl8G7lRSZ8FFGK8XX4VA8QjEd7XrM3M0OXz8YCy+qKBLgq3wqnofiTorF0Ax56Rg1J1elW+BBAsVe+My6iYq7IK6keBdOIseV2qn5Pb8f3MqkWAXf9ThM8c8lAOIotuFsF875lRrH5klRcG0+xcPwQ1oLxfeRAP4heQTnGL78X2rqlw2DK59SXAV/zKaiGMAuko5InCt68mcOan5+ohf+z1pP8lQY/GHZQMV4YD3FpXDp4qerqbF/lBWBswyi+AL+ia+maLgcRRQj4IYlY/UpauqKBsPJAxQF8NM1TRQ/RudSPAD34rK3scOuR8/HGcspxsJfOVS8NZbiGXiUtPgINU3v3WFDmx8pEuG3EiqKKVbCC1vm2iZqap5LAtCtleQf8F9sFYWDohzeJczYyQ4V2bEZFGsQgJRGqqqhS2phHTWn9lDkIhBTqWqxQZ+IsRvtdHY9AvI2VX2hW68nfqGmuQsCEl3JdjfCF8OW1bPdtwhQ0gm2mQzfRE3a7KCYj0BNZJs8+Kxf/r6WtTEI2FIqlsMfFgRB5A6KUnSe/vUkX0AnuvUIt8SjM1m6wWQymUwmk8lkMgXRf5vi8rLQxtUhAAAAAElFTkSuQmCC`;
|
const imageBase64Data = `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`;
|
||||||
const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100);
|
const image6 = Media.addImage(doc, Buffer.from(imageBase64Data, "base64"), 100, 100);
|
||||||
|
@ -8,7 +8,7 @@ const doc = new Document();
|
|||||||
const table = doc.createTable(4, 4);
|
const table = doc.createTable(4, 4);
|
||||||
table.getCell(2, 2).addContent(new Paragraph("Hello"));
|
table.getCell(2, 2).addContent(new Paragraph("Hello"));
|
||||||
|
|
||||||
const image = Media.addImage(doc, "./demo/images/image1.jpeg");
|
const image = Media.addImage(doc, fs.readFileSync("./demo/images/image1.jpeg"));
|
||||||
table.getCell(1, 1).addContent(image.Paragraph);
|
table.getCell(1, 1).addContent(image.Paragraph);
|
||||||
|
|
||||||
const packer = new Packer();
|
const packer = new Packer();
|
||||||
|
@ -30,5 +30,4 @@ const packer = new Packer();
|
|||||||
|
|
||||||
packer.toBuffer(doc).then((buffer) => {
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
fs.writeFileSync("My Document.docx", buffer);
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
console.log("Document created successfully at project root!");
|
|
||||||
});
|
});
|
||||||
|
29
demo/demo30.ts
Normal file
29
demo/demo30.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, ImportDotx, Packer, Paragraph } from "../build";
|
||||||
|
|
||||||
|
const importDotx = new ImportDotx();
|
||||||
|
const filePath = "./demo/dotx/template.dotx";
|
||||||
|
|
||||||
|
fs.readFile(filePath, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(`Failed to read file ${filePath}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
importDotx.extract(data).then((templateDocument) => {
|
||||||
|
// This any needs fixing
|
||||||
|
const sectionProps = {
|
||||||
|
titlePage: templateDocument.titlePageIsDefined,
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
const doc = new Document(undefined, sectionProps, {
|
||||||
|
template: templateDocument,
|
||||||
|
});
|
||||||
|
const paragraph = new Paragraph("Hello World");
|
||||||
|
doc.addParagraph(paragraph);
|
||||||
|
|
||||||
|
const packer = new Packer();
|
||||||
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
22
demo/demo33.ts
Normal file
22
demo/demo33.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Sequential Captions
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, TextRun } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document();
|
||||||
|
|
||||||
|
const paragraph = new Paragraph("Hello World 1->").addSequentialIdentifier("Caption").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Caption");
|
||||||
|
const paragraph2 = new Paragraph("Hello World 1->").addSequentialIdentifier("Label").addRun(new TextRun(" text after sequencial caption 2->")).addSequentialIdentifier("Label");
|
||||||
|
const paragraph3 = new Paragraph("Hello World 1->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 3->")).addSequentialIdentifier("Label");
|
||||||
|
const paragraph4 = new Paragraph("Hello World 2->").addSequentialIdentifier("Another").addRun(new TextRun(" text after sequencial caption 4->")).addSequentialIdentifier("Label");
|
||||||
|
|
||||||
|
doc.addParagraph(paragraph);
|
||||||
|
doc.addParagraph(paragraph2);
|
||||||
|
doc.addParagraph(paragraph3);
|
||||||
|
doc.addParagraph(paragraph4);
|
||||||
|
|
||||||
|
const packer = new Packer();
|
||||||
|
|
||||||
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
32
demo/demo34.ts
Normal file
32
demo/demo34.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Example of how you would create a table with float positions
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import {
|
||||||
|
Document,
|
||||||
|
Packer,
|
||||||
|
Paragraph,
|
||||||
|
RelativeHorizontalPosition,
|
||||||
|
RelativeVerticalPosition,
|
||||||
|
TableAnchorType,
|
||||||
|
WidthType,
|
||||||
|
} from "../build";
|
||||||
|
|
||||||
|
const doc = new Document();
|
||||||
|
|
||||||
|
const table = doc.createTable(2, 2).float({
|
||||||
|
horizontalAnchor: TableAnchorType.MARGIN,
|
||||||
|
verticalAnchor: TableAnchorType.MARGIN,
|
||||||
|
relativeHorizontalPosition: RelativeHorizontalPosition.RIGHT,
|
||||||
|
relativeVerticalPosition: RelativeVerticalPosition.BOTTOM,
|
||||||
|
});
|
||||||
|
table.setFixedWidthLayout();
|
||||||
|
table.setWidth(WidthType.DXA, 4535);
|
||||||
|
|
||||||
|
table.getCell(0, 0).addContent(new Paragraph("Hello"));
|
||||||
|
table.getRow(0).mergeCells(0, 1);
|
||||||
|
|
||||||
|
const packer = new Packer();
|
||||||
|
|
||||||
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
44
demo/demo38.ts
Normal file
44
demo/demo38.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
// import { Document, Packer, Paragraph } from "../build";
|
||||||
|
import { Document, Packer, TextWrappingSide, TextWrappingType } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document();
|
||||||
|
|
||||||
|
doc.createParagraph(
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vehicula nec nulla vitae efficitur. Ut interdum mauris eu ipsum rhoncus, nec pharetra velit placerat. Sed vehicula libero ac urna molestie, id pharetra est pellentesque. Praesent iaculis vehicula fringilla. Duis pretium gravida orci eu vestibulum. Mauris tincidunt ipsum dolor, ut ornare dolor pellentesque id. Integer in nulla gravida, lacinia ante non, commodo ex. Vivamus vulputate nisl id lectus finibus vulputate. Ut et nisl mi. Cras fermentum augue arcu, ac accumsan elit euismod id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed ac posuere nisi. Pellentesque tincidunt vehicula bibendum. Phasellus eleifend viverra nisl.",
|
||||||
|
);
|
||||||
|
|
||||||
|
doc.createParagraph(
|
||||||
|
"Proin ac purus faucibus, porttitor magna ut, cursus nisl. Vivamus ante purus, porta accumsan nibh eget, eleifend dignissim odio. Integer sed dictum est, aliquam lacinia justo. Donec ultrices auctor venenatis. Etiam interdum et elit nec elementum. Pellentesque nec viverra mauris. Etiam suscipit leo nec velit fringilla mattis. Pellentesque justo lacus, sodales eu condimentum in, dapibus finibus lacus. Morbi vitae nibh sit amet sem molestie feugiat. In non porttitor enim.",
|
||||||
|
);
|
||||||
|
|
||||||
|
doc.createParagraph(
|
||||||
|
"Ut eget diam cursus quam accumsan interdum at id ante. Ut mollis mollis arcu, eu scelerisque dui tempus in. Quisque aliquam, augue quis ornare aliquam, ex purus ultrices mauris, ut porta dolor dolor nec justo. Nunc a tempus odio, eu viverra arcu. Suspendisse vitae nibh nec mi pharetra tempus. Mauris ut ullamcorper sapien, et sagittis sapien. Vestibulum in urna metus. In scelerisque, massa id bibendum tempus, quam orci rutrum turpis, a feugiat nisi ligula id metus. Praesent id dictum purus. Proin interdum ipsum nulla.",
|
||||||
|
);
|
||||||
|
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.SQUARE,
|
||||||
|
side: TextWrappingSide.BOTH_SIDES,
|
||||||
|
},
|
||||||
|
margins: {
|
||||||
|
top: 201440,
|
||||||
|
bottom: 201440,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const packer = new Packer();
|
||||||
|
|
||||||
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
33
demo/demo39.ts
Normal file
33
demo/demo39.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Scaling images
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, PageNumberFormat, TextRun } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
pageNumberStart: 1,
|
||||||
|
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
doc.Header.createParagraph("Foo Bar corp. ")
|
||||||
|
.addRun(new TextRun("Page Number ").pageNumber())
|
||||||
|
.addRun(new TextRun(" to ").numberOfTotalPages());
|
||||||
|
|
||||||
|
doc.Footer.createParagraph("Foo Bar corp. ")
|
||||||
|
.center()
|
||||||
|
.addRun(new TextRun("Page Number: ").pageNumber())
|
||||||
|
.addRun(new TextRun(" to ").numberOfTotalPages());
|
||||||
|
|
||||||
|
doc.createParagraph("Hello World 1").pageBreak();
|
||||||
|
doc.createParagraph("Hello World 2").pageBreak();
|
||||||
|
doc.createParagraph("Hello World 3").pageBreak();
|
||||||
|
doc.createParagraph("Hello World 4").pageBreak();
|
||||||
|
doc.createParagraph("Hello World 5").pageBreak();
|
||||||
|
|
||||||
|
const packer = new Packer();
|
||||||
|
|
||||||
|
packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
@ -1,7 +1,8 @@
|
|||||||
// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings
|
// Example of how to add images to the document - You can use Buffers, UInt8Arrays or Base64 strings
|
||||||
// Import from 'docx' rather than '../build' if you install from npm
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { Document, Packer, Paragraph } from "../build";
|
// import { Document, Packer, Paragraph } from "../build";
|
||||||
|
import { Document, HorizontalPositionAlign, HorizontalPositionRelativeFrom, Packer, Paragraph, VerticalPositionAlign, VerticalPositionRelativeFrom} from "../build";
|
||||||
|
|
||||||
const doc = new Document();
|
const doc = new Document();
|
||||||
|
|
||||||
@ -13,6 +14,29 @@ doc.createImage(fs.readFileSync("./demo/images/dog.png").toString("base64"));
|
|||||||
doc.createImage(fs.readFileSync("./demo/images/cat.jpg"));
|
doc.createImage(fs.readFileSync("./demo/images/cat.jpg"));
|
||||||
doc.createImage(fs.readFileSync("./demo/images/parrots.bmp"));
|
doc.createImage(fs.readFileSync("./demo/images/parrots.bmp"));
|
||||||
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"));
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 1014400,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 1014400,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/cat.jpg"), 200, 200, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
relative: HorizontalPositionRelativeFrom.PAGE,
|
||||||
|
align: HorizontalPositionAlign.RIGHT,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
relative: VerticalPositionRelativeFrom.PAGE,
|
||||||
|
align: VerticalPositionAlign.BOTTOM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const packer = new Packer();
|
const packer = new Packer();
|
||||||
|
|
||||||
|
BIN
demo/dotx/template.dotx
Normal file
BIN
demo/dotx/template.dotx
Normal file
Binary file not shown.
@ -17,6 +17,7 @@
|
|||||||
* [Numbering](usage/numbering.md)
|
* [Numbering](usage/numbering.md)
|
||||||
* [Tab Stops](usage/tab-stops.md)
|
* [Tab Stops](usage/tab-stops.md)
|
||||||
* [Table of Contents](usage/table-of-contents.md)
|
* [Table of Contents](usage/table-of-contents.md)
|
||||||
|
* [Page Numbers](usage/page-numbers.md)
|
||||||
* Styling
|
* Styling
|
||||||
* [Styling with JS](usage/styling-with-js.md)
|
* [Styling with JS](usage/styling-with-js.md)
|
||||||
* [Styling with XML](usage/styling-with-xml.md)
|
* [Styling with XML](usage/styling-with-xml.md)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
# Contribution Guidelines
|
# Contribution Guidelines
|
||||||
|
|
||||||
## Writing Code
|
|
||||||
|
|
||||||
* Include documentation reference(s) at the top of each file:
|
* Include documentation reference(s) at the top of each file:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -12,6 +10,59 @@
|
|||||||
|
|
||||||
* Follow the `TSLint` rules
|
* Follow the `TSLint` rules
|
||||||
|
|
||||||
|
## Always think about the user
|
||||||
|
|
||||||
|
The number one pillar for contribution is to **ALWAYS** think about how the user will use the library.
|
||||||
|
|
||||||
|
Put yourself in their position, and imagine how they would feel about your feature you wrote.
|
||||||
|
|
||||||
|
1. Is it easy to use?
|
||||||
|
2. Has it been documented well?
|
||||||
|
3. Is it intuative?
|
||||||
|
4. Is it consistent with the rest of the API?
|
||||||
|
5. Is it fun to use?
|
||||||
|
|
||||||
|
## Good Commit Names
|
||||||
|
|
||||||
|
Please write good commit messages when making a commit: https://chris.beams.io/posts/git-commit/
|
||||||
|
|
||||||
|
**Do not:**
|
||||||
|
```
|
||||||
|
c // What?
|
||||||
|
rtl // Adding acryonyms without explaining anything else is not helpful
|
||||||
|
works! // Glad its working, but the message is not helpful
|
||||||
|
demo updated // Getting better, but capitalize the first letter
|
||||||
|
Unesesary coment removed // Make sure to use correct spelling
|
||||||
|
```
|
||||||
|
|
||||||
|
## No leaky components in API interface
|
||||||
|
|
||||||
|
This mainly applies to the API the end user will consume.
|
||||||
|
|
||||||
|
Try to make method parameters accept primatives, or `json` objects, so that child components are created **inside** the component, rather than being **injected** in.
|
||||||
|
|
||||||
|
This is so that:
|
||||||
|
|
||||||
|
1. Imports are much cleaner, no need for:
|
||||||
|
```js
|
||||||
|
import { ChildComponent } from "./my-feature/sub-component/deeper/.../my-deep.component";
|
||||||
|
```
|
||||||
|
|
||||||
|
2. This is what I consider "leakage". The code is aware of the underlying implementation of the component.
|
||||||
|
3. It means the end user does not need to import and create the child component to be injected.
|
||||||
|
|
||||||
|
**Do not**
|
||||||
|
`TableFloatProperties` is a class. The outside world would have to construct the object, and inject it in
|
||||||
|
```js
|
||||||
|
public float(tableFloatProperties: TableFloatProperties): Table
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do**
|
||||||
|
`ITableFloatOptions` is an interface for a JSON of primatives.
|
||||||
|
```js
|
||||||
|
public float(tableFloatOptions: ITableFloatOptions): Table
|
||||||
|
```
|
||||||
|
|
||||||
## Add vs Create
|
## Add vs Create
|
||||||
|
|
||||||
This is just a guideline, and the rules can sometimes be broken.
|
This is just a guideline, and the rules can sometimes be broken.
|
||||||
@ -39,24 +90,104 @@ Getters and Setters are done with a capital letter like so:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
public get Level() {
|
public get Level() {
|
||||||
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There is no performance advantage by doing this. It means we don't need to prefix all private variables with the ugly `_`:
|
There is no performance advantage by doing this. It means we don't need to prefix all private variables with the ugly `_`:
|
||||||
|
|
||||||
**Do not:**
|
**Do not:**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
private get _level: string;
|
private get _level: string;
|
||||||
```
|
```
|
||||||
|
|
||||||
**Do**
|
**Do**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
private get level: string;
|
private get level: string;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Interfaces over type alias
|
||||||
|
|
||||||
|
Do not use `type`, but rather use `Interfaces`. `type` cannot be extended, and a class cannot implement it.
|
||||||
|
|
||||||
|
> "In general, use what you want ( type alias / interface ) just be consistent"
|
||||||
|
> "always use interface for public API's definition when authoring a library or 3rd party ambient type definitions"
|
||||||
|
>
|
||||||
|
> * https://medium.com/@martin_hotell/interface-vs-type-alias-in-typescript-2-7-2a8f1777af4c
|
||||||
|
|
||||||
|
`Interface` is generally preferred over `type`: https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types
|
||||||
|
|
||||||
|
**Do not:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
type RelationshipFileInfo = { id: number, target: string };
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
interface IRelationshipFileInfo {
|
||||||
|
id: number;
|
||||||
|
target: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## String enums vs type
|
||||||
|
|
||||||
|
To take full advantage of TypeScript's typing system, its best to use `string enums`:
|
||||||
|
|
||||||
|
**Do not:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
type WeaponType = "bow" | "sword" | "wand";
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do:**
|
||||||
|
|
||||||
|
```js
|
||||||
|
enum WeaponType = {
|
||||||
|
BOW = "bow",
|
||||||
|
SWORD = "sword",
|
||||||
|
WAND = "wand",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Spell correctly, full and in American English
|
||||||
|
|
||||||
|
I am not sure where these habits in software development come from, but I do not believe it is beneficial:
|
||||||
|
|
||||||
|
**Do not:**
|
||||||
|
```js
|
||||||
|
readdy // misspelling
|
||||||
|
perm // abbreviation
|
||||||
|
conf // abbreviation
|
||||||
|
cnty // abbreviation
|
||||||
|
relationFile // abbreviation
|
||||||
|
colour // U.K. English
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do:**
|
||||||
|
```js
|
||||||
|
ready
|
||||||
|
permission
|
||||||
|
config
|
||||||
|
country
|
||||||
|
relationshipFile
|
||||||
|
color
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keep files small (within reason)
|
||||||
|
|
||||||
|
To minimize merge conflicts, reduce complexity, and improve readability, keep the files small.
|
||||||
|
|
||||||
|
## Name files and folders with `/foo-bar/kebab-case.ts`
|
||||||
|
|
||||||
|
To be consistent and in-line with the project, name files `like-this.ts`.
|
||||||
|
|
||||||
|
https://stackoverflow.com/questions/7273316/what-is-the-javascript-filename-naming-convention
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Please write a test of every file you make and suffix it with `.spec.ts`.
|
Please write a test of every file you make and suffix it with `.spec.ts`.
|
||||||
@ -78,3 +209,5 @@ describe("ClassName", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Try not to use the `tests/utility.ts` file as this is being deprecated.
|
||||||
|
@ -1,156 +1,231 @@
|
|||||||
# Images
|
# Images
|
||||||
|
|
||||||
## Intro
|
To create a `floating` image on top of text:
|
||||||
|
|
||||||
Adding images is very simple
|
```ts
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
|
||||||
Simply call the `createImage` method:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const image = doc.createImage([BUFFER_OF_YOUR_IMAGE]);
|
|
||||||
```
|
|
||||||
|
|
||||||
`docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png`
|
|
||||||
|
|
||||||
Check `demo5.js` for an example
|
|
||||||
|
|
||||||
## Positioning
|
|
||||||
|
|
||||||
Images can be:
|
|
||||||
|
|
||||||
* floating position of images
|
|
||||||
* Wrapped around the text
|
|
||||||
* Inline
|
|
||||||
|
|
||||||
By default, picture are exported as `INLINE` elements.
|
|
||||||
|
|
||||||
In Word this is found in:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
The `PictureRun` element support various options to define the positioning of the element in the document.
|
|
||||||
|
|
||||||
```js
|
|
||||||
interface DrawingOptions {
|
|
||||||
position?: PlacementPosition;
|
|
||||||
textWrapping?: TextWrapping;
|
|
||||||
floating?: Floating;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
can be passed when creating `PictureRun()` for example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
const imageData = document.createImage(buffer, 903, 1149);
|
|
||||||
|
|
||||||
new docx.PictureRun(imageData, {
|
|
||||||
position: docx.PlacementPosition.FLOATING,
|
|
||||||
floating: {
|
floating: {
|
||||||
horizontalPosition: {
|
horizontalPosition: {
|
||||||
relative: HorizontalPositionRelativeFrom.PAGE,
|
offset: 1014400,
|
||||||
align: HorizontalPositionAlign.LEFT,
|
|
||||||
},
|
},
|
||||||
verticalPosition: {
|
verticalPosition: {
|
||||||
relative: VerticalPositionRelativeFrom.PAGE,
|
offset: 1014400,
|
||||||
align: VerticalPositionAlign.TOP,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
So, the first thing is to define the placement position: `INLINE` or `FLOATING`. Inline is the default one so there is no need to pass drawing options for inline.
|
By default with no arguments, its an `inline` image:
|
||||||
|
|
||||||
When placement position is FLOATING then we can use two options:
|
```ts
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/parrots.bmp"));
|
||||||
### Wrap text
|
|
||||||
|
|
||||||
for `drawingOptions.textWrapping` we can define various options. `textWrapping` has the following properties:
|
|
||||||
|
|
||||||
```js
|
|
||||||
interface TextWrapping {
|
|
||||||
textWrapStyle: TextWrapStyle;
|
|
||||||
wrapTextOption?: WrapTextOption;
|
|
||||||
distanceFromText?: Distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TextWrapStyle {
|
|
||||||
NONE,
|
|
||||||
SQUARE,
|
|
||||||
TIGHT,
|
|
||||||
TOP_AND_BOTTOM,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum WrapTextOption {
|
|
||||||
BOTH_SIDES = "bothSides",
|
|
||||||
LEFT = "left",
|
|
||||||
RIGHT = "right",
|
|
||||||
LARGEST = "largest",
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Floating position
|
You can also create images manually and add them later:
|
||||||
|
|
||||||
When we want to position the image relative or absolute then we need to use option `drawingOptions.floating`:
|
```ts
|
||||||
|
const image = Media.addImage(doc, fs.readFileSync("./demo/images/pizza.gif"));
|
||||||
```js
|
doc.addImage(image);
|
||||||
export interface Floating {
|
|
||||||
horizontalPosition: HorizontalPositionOptions;
|
|
||||||
verticalPosition: VerticalPositionOptions;
|
|
||||||
allowOverlap?: boolean;
|
|
||||||
lockAnchor?: boolean;
|
|
||||||
behindDocument?: boolean;
|
|
||||||
layoutInCell?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HorizontalPositionOptions {
|
|
||||||
relative: HorizontalPositionRelativeFrom;
|
|
||||||
align?: HorizontalPositionAlign;
|
|
||||||
offset?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VerticalPositionOptions {
|
|
||||||
relative: VerticalPositionRelativeFrom;
|
|
||||||
align?: VerticalPositionAlign;
|
|
||||||
offset?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum HorizontalPositionRelativeFrom {
|
|
||||||
CHARACTER = "character",
|
|
||||||
COLUMN = "column",
|
|
||||||
INSIDE_MARGIN = "insideMargin",
|
|
||||||
LEFT_MARGIN = "leftMargin",
|
|
||||||
MARGIN = "margin",
|
|
||||||
OUTSIDE_MARGIN = "outsideMargin",
|
|
||||||
PAGE = "page",
|
|
||||||
RIGHT_MARGIN = "rightMargin",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum VerticalPositionRelativeFrom {
|
|
||||||
BOTTOM_MARGIN = "bottomMargin",
|
|
||||||
INSIDE_MARGIN = "insideMargin",
|
|
||||||
LINE = "line",
|
|
||||||
MARGIN = "margin",
|
|
||||||
OUTSIDE_MARGIN = "outsideMargin",
|
|
||||||
PAGE = "page",
|
|
||||||
PARAGRAPH = "paragraph",
|
|
||||||
TOP_MARGIN = "topMargin",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum HorizontalPositionAlign {
|
|
||||||
CENTER = "center",
|
|
||||||
INSIDE = "inside",
|
|
||||||
LEFT = "left",
|
|
||||||
OUTSIDE = "outside",
|
|
||||||
RIGHT = "right",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum VerticalPositionAlign {
|
|
||||||
BOTTOM = "bottom",
|
|
||||||
CENTER = "center",
|
|
||||||
INSIDE = "inside",
|
|
||||||
OUTSIDE = "outside",
|
|
||||||
TOP = "top",
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
Adding images can be done in two ways:
|
||||||
|
|
||||||
|
1. Call the `createImage` method to add the image directly into the `document`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
doc.createImage([IMAGE_BUFFER], [WIDTH], [HEIGHT], [POSITION_OPTIONS]);
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create an `image` first, then add it into the `document`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const image = Media.addImage(doc, [IMAGE_BUFFER]);
|
||||||
|
doc.addImage(image);
|
||||||
|
```
|
||||||
|
|
||||||
|
`docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png`
|
||||||
|
|
||||||
|
## Positioning
|
||||||
|
|
||||||
|
> Positioning is the method on how to place the image on the document
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Three types of image positioning is supported:
|
||||||
|
|
||||||
|
- Floating
|
||||||
|
- Inline
|
||||||
|
|
||||||
|
By default, picture are exported as `Inline` elements.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Pass `options` into the `[POSITION_OPTIONS]` metioned in the [Intro above](#Intro).
|
||||||
|
|
||||||
|
## Floating
|
||||||
|
|
||||||
|
To change the position the image to be on top of the text, simply add the `floating` property to the last argument. By default, the offsets are relative to the top left corner of the `page`. Offset units are in [emus](https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const imageData = document.createImage(buffer, 903, 1149, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 1014400, // relative: HorizontalPositionRelativeFrom.PAGE by default
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 1014400, // relative: VerticalPositionRelativeFrom.PAGE by default
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const imageData = document.createImage(buffer, 903, 1149, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
relative: HorizontalPositionRelativeFrom.RIGHT_MARGIN,
|
||||||
|
offset: 1014400,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
relative: VerticalPositionRelativeFrom.BOTTOM_MARGIN,
|
||||||
|
offset: 1014400,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
Full options you can pass into `floating` are:
|
||||||
|
|
||||||
|
| Property | Type | Notes |
|
||||||
|
| ------------------ | --------------------------- | -------- |
|
||||||
|
| horizontalPosition | `HorizontalPositionOptions` | Required |
|
||||||
|
| verticalPosition | `VerticalPositionOptions` | Required |
|
||||||
|
| allowOverlap | `boolean` | Optional |
|
||||||
|
| lockAnchor | `boolean` | Optional |
|
||||||
|
| behindDocument | `boolean` | Optional |
|
||||||
|
| layoutInCell | `boolean` | Optional |
|
||||||
|
|
||||||
|
`HorizontalPositionOptions` are:
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| -------- | -------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||||
|
| relative | `HorizontalPositionRelativeFrom` | Required | `CHARACTER`, `COLUMN`, `INSIDE_MARGIN`, `LEFT_MARGIN`, `MARGIN`, `OUTSIDE_MARGIN`, `PAGE`, `RIGHT_MARGIN` |
|
||||||
|
| align | `HorizontalPositionAlign` | You can either have `align` or `offset`, not both | `CENTER`, `INSIDE`, `LEFT`, `OUTSIDE`, `RIGHT` |
|
||||||
|
| offset | `number` | You can either have `align` or `offset`, not both | `0` to `Infinity` |
|
||||||
|
|
||||||
|
`VerticalPositionOptions` are:
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| -------- | ------------------------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||||
|
| relative | `VerticalPositionRelativeFrom` | Required | `BOTTOM_MARGIN`, `INSIDE_MARGIN`, `LINE`, `MARGIN`, `OUTSIDE_MARGIN`, `PAGE`, `PARAGRAPH`, `TOP_MARGIN` |
|
||||||
|
| align | `VerticalPositionAlign` | You can either have `align` or `offset`, not both | `BOTTOM`, `CENTER`, `INSIDE`, `OUTSIDE`, `TOP` |
|
||||||
|
| offset | `number` | You can either have `align` or `offset`, not both | `0` to `Infinity` |
|
||||||
|
|
||||||
|
## Wrap text
|
||||||
|
|
||||||
|
Wrapping only works for floating elements. Text will "wrap" around the floating `image`.
|
||||||
|
|
||||||
|
Add `wrap` options inside the `floating` options:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
wrap: {
|
||||||
|
type: [TextWrappingType],
|
||||||
|
side: [TextWrappingSide],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.SQUARE,
|
||||||
|
side: TextWrappingSide.BOTH_SIDES,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrap options have the following properties are:
|
||||||
|
|
||||||
|
| Property | Type | Notes | Possible Values |
|
||||||
|
| -------- | ------------------ | -------- | ------------------------------------------- |
|
||||||
|
| type | `TextWrappingType` | Optional | `NONE`, `SQUARE`, `TIGHT`, `TOP_AND_BOTTOM` |
|
||||||
|
| side | `TextWrappingSide` | Optional | `BOTH_SIDES`, `LEFT`, `RIGHT`, `LARGEST` |
|
||||||
|
|
||||||
|
## Margins
|
||||||
|
|
||||||
|
Margins give some space between the text and the image. Margins [only work for floating elements](http://officeopenxml.com/drwPicInline.php). Additionally, the image must also be in wrap mode (see above).
|
||||||
|
|
||||||
|
?> Be sure to also set `wrap` in your options!
|
||||||
|
|
||||||
|
To use, add the `margins` options inside the `floating` options:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
margins: {
|
||||||
|
top: number,
|
||||||
|
bottom: number,
|
||||||
|
left: number,
|
||||||
|
right: number
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
doc.createImage(fs.readFileSync("./demo/images/pizza.gif"), 200, 200, {
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 2014400,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.SQUARE,
|
||||||
|
side: TextWrappingSide.BOTH_SIDES,
|
||||||
|
},
|
||||||
|
margins: {
|
||||||
|
top: 201440,
|
||||||
|
bottom: 201440,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Add image to the document
|
||||||
|
|
||||||
|
Importing Images from file system path
|
||||||
|
|
||||||
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo5.ts ":include")
|
||||||
|
|
||||||
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo5.ts_
|
||||||
|
|
||||||
|
### Add images to header and footer
|
||||||
|
|
||||||
|
Example showing how to add image to headers and footers
|
||||||
|
|
||||||
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo9.ts ":include")
|
||||||
|
|
||||||
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo9.ts_
|
||||||
|
|
||||||
|
### Floating images
|
||||||
|
|
||||||
|
Example showing how to float images on top of text and optimally give a `margin`
|
||||||
|
|
||||||
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo38.ts ":include")
|
||||||
|
|
||||||
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo38.ts_
|
||||||
|
@ -75,7 +75,7 @@ abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new
|
|||||||
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980));
|
abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980));
|
||||||
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700));
|
abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700));
|
||||||
|
|
||||||
const concrete = numbering.createConcreteNumbering(numberedAbstract);
|
const concrete = numbering.createConcreteNumbering(abstractNum);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then apply your concrete style to paragraphs using their
|
You can then apply your concrete style to paragraphs using their
|
||||||
|
66
docs/usage/page-numbers.md
Normal file
66
docs/usage/page-numbers.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Page Numbers
|
||||||
|
|
||||||
|
> This feature allows you to set page numbers on each page
|
||||||
|
|
||||||
|
?> **Note:** This feature only works on Headers and Footers
|
||||||
|
|
||||||
|
```ts
|
||||||
|
doc.Header.createParagraph().addRun(new TextRun("Page Number: ").pageNumber()).addRun(new TextRun("to ").numberOfTotalPages());
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current page number
|
||||||
|
|
||||||
|
To get the current page number, call the `.pageNumber()` method on a `TextRun`. Then add the newly created `TextRun` into a paragraph
|
||||||
|
|
||||||
|
```ts
|
||||||
|
pageNumber();
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const currentPageRun = new TextRun("Current Page Number: ").pageNumber();
|
||||||
|
paragraph.addRun(currentPageRun);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Total number of pages
|
||||||
|
|
||||||
|
```ts
|
||||||
|
numberOfTotalPages();
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const lastPage = new TextRun("Total Page Number: ").numberOfTotalPages();
|
||||||
|
paragraph.addRun(lastPage);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Both
|
||||||
|
|
||||||
|
You can combine the two to get "Page 2 of 10" effect:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const currentPageRun = new TextRun("Page ").pageNumber();
|
||||||
|
const lastPage = new TextRun("of ").numberOfTotalPages();
|
||||||
|
|
||||||
|
paragraph.addRun(currentPageRun);
|
||||||
|
paragraph.addRun(lastPage);
|
||||||
|
```
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
doc.Header.createParagraph().addRun(new TextRun("Page ").pageNumber()).addRun(new TextRun("of ").numberOfTotalPages());
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Simple Example
|
||||||
|
|
||||||
|
Adding page numbers to Header and Footer
|
||||||
|
|
||||||
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/demo39.ts ":include")
|
||||||
|
|
||||||
|
_Source: https://github.com/dolanmiu/docx/blob/master/demo/demo39.ts_
|
17
package.json
17
package.json
@ -1,22 +1,22 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "4.3.0",
|
"version": "4.7.0",
|
||||||
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
|
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pretest": "rimraf ./build",
|
"pretest": "rimraf ./build",
|
||||||
"test": "mocha-webpack \"src/**/*.ts\"",
|
"test": "mocha-webpack \"src/**/*.ts\"",
|
||||||
"test-watch": "mocha-webpack \"src/**/*.ts\" --watch",
|
"test.coverage": "nyc npm test",
|
||||||
|
"test.watch": "npm test -- --watch",
|
||||||
"prepublishOnly": "npm run build",
|
"prepublishOnly": "npm run build",
|
||||||
"lint": "tslint --project .",
|
"lint": "tslint --project .",
|
||||||
"build": "npm run webpack && npm run fix-types",
|
"build": "npm run webpack && npm run fix-types",
|
||||||
"tsc": "rimraf ./build && tsc -p .",
|
"tsc": "rimraf ./build && tsc -p .",
|
||||||
"webpack": "rimraf ./build && webpack",
|
"webpack": "rimraf ./build && webpack",
|
||||||
"build.web": "webpack --config webpack.web.config.js",
|
|
||||||
"demo": "npm run build && npm run ts-node ./demo",
|
"demo": "npm run build && npm run ts-node ./demo",
|
||||||
"typedoc": "typedoc src/index.ts",
|
"typedoc": "typedoc src/index.ts",
|
||||||
"style": "prettier -l \"src/**/*.ts\"",
|
"style": "prettier -l \"src/**/*.ts\"",
|
||||||
"style.fix": "prettier \"src/**/*.ts\" --write",
|
"style.fix": "npm run style -- --write",
|
||||||
"fix-types": "node types-absolute-fixer.js",
|
"fix-types": "node types-absolute-fixer.js",
|
||||||
"ts-node": "ts-node"
|
"ts-node": "ts-node"
|
||||||
},
|
},
|
||||||
@ -48,11 +48,11 @@
|
|||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/image-size": "0.0.29",
|
"@types/image-size": "0.0.29",
|
||||||
"@types/jszip": "^3.1.3",
|
"@types/jszip": "^3.1.4",
|
||||||
"fast-xml-parser": "^3.3.6",
|
|
||||||
"image-size": "^0.6.2",
|
"image-size": "^0.6.2",
|
||||||
"jszip": "^3.1.5",
|
"jszip": "^3.1.5",
|
||||||
"xml": "^1.0.1"
|
"xml": "^1.0.1",
|
||||||
|
"xml-js": "^1.6.8"
|
||||||
},
|
},
|
||||||
"author": "Dolan Miu",
|
"author": "Dolan Miu",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -67,9 +67,11 @@
|
|||||||
"awesome-typescript-loader": "^3.4.1",
|
"awesome-typescript-loader": "^3.4.1",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
|
"istanbul-instrumenter-loader": "^3.0.1",
|
||||||
"jszip": "^3.1.5",
|
"jszip": "^3.1.5",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"mocha-webpack": "^1.0.1",
|
"mocha-webpack": "^1.0.1",
|
||||||
|
"nyc": "^13.1.0",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^1.12.1",
|
"prettier": "^1.12.1",
|
||||||
"prompt": "^1.0.0",
|
"prompt": "^1.0.0",
|
||||||
@ -79,6 +81,7 @@
|
|||||||
"sinon": "^5.0.7",
|
"sinon": "^5.0.7",
|
||||||
"ts-node": "^7.0.1",
|
"ts-node": "^7.0.1",
|
||||||
"tslint": "^5.11.0",
|
"tslint": "^5.11.0",
|
||||||
|
"tslint-immutable": "^4.9.0",
|
||||||
"typedoc": "^0.11.1",
|
"typedoc": "^0.11.1",
|
||||||
"typescript": "2.9.2",
|
"typescript": "2.9.2",
|
||||||
"webpack": "^3.10.0"
|
"webpack": "^3.10.0"
|
||||||
|
@ -2,6 +2,12 @@ import { BaseXmlComponent, IXmlableObject } from "file/xml-components";
|
|||||||
|
|
||||||
export class Formatter {
|
export class Formatter {
|
||||||
public format(input: BaseXmlComponent): IXmlableObject {
|
public format(input: BaseXmlComponent): IXmlableObject {
|
||||||
return input.prepForXml();
|
const output = input.prepForXml();
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
return output;
|
||||||
|
} else {
|
||||||
|
throw Error("XMLComponent did not format correctly");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/* tslint:disable:typedef space-before-function-paren */
|
/* tslint:disable:typedef space-before-function-paren */
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { File } from "../../file";
|
|
||||||
|
import { File } from "file";
|
||||||
|
|
||||||
import { Compiler } from "./next-compiler";
|
import { Compiler } from "./next-compiler";
|
||||||
|
|
||||||
describe("Compiler", () => {
|
describe("Compiler", () => {
|
||||||
|
@ -5,25 +5,25 @@ import { File } from "file";
|
|||||||
import { Formatter } from "../formatter";
|
import { Formatter } from "../formatter";
|
||||||
|
|
||||||
interface IXmlifyedFile {
|
interface IXmlifyedFile {
|
||||||
data: string;
|
readonly data: string;
|
||||||
path: string;
|
readonly path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IXmlifyedFileMapping {
|
interface IXmlifyedFileMapping {
|
||||||
Document: IXmlifyedFile;
|
readonly Document: IXmlifyedFile;
|
||||||
Styles: IXmlifyedFile;
|
readonly Styles: IXmlifyedFile;
|
||||||
Properties: IXmlifyedFile;
|
readonly Properties: IXmlifyedFile;
|
||||||
Numbering: IXmlifyedFile;
|
readonly Numbering: IXmlifyedFile;
|
||||||
Relationships: IXmlifyedFile;
|
readonly Relationships: IXmlifyedFile;
|
||||||
FileRelationships: IXmlifyedFile;
|
readonly FileRelationships: IXmlifyedFile;
|
||||||
Headers: IXmlifyedFile[];
|
readonly Headers: IXmlifyedFile[];
|
||||||
Footers: IXmlifyedFile[];
|
readonly Footers: IXmlifyedFile[];
|
||||||
HeaderRelationships: IXmlifyedFile[];
|
readonly HeaderRelationships: IXmlifyedFile[];
|
||||||
FooterRelationships: IXmlifyedFile[];
|
readonly FooterRelationships: IXmlifyedFile[];
|
||||||
ContentTypes: IXmlifyedFile;
|
readonly ContentTypes: IXmlifyedFile;
|
||||||
AppProperties: IXmlifyedFile;
|
readonly AppProperties: IXmlifyedFile;
|
||||||
FootNotes: IXmlifyedFile;
|
readonly FootNotes: IXmlifyedFile;
|
||||||
Settings: IXmlifyedFile;
|
readonly Settings: IXmlifyedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
@ -59,6 +59,18 @@ export class Compiler {
|
|||||||
zip.file(`word/media/${data.fileName}`, mediaData);
|
zip.file(`word/media/${data.fileName}`, mediaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const header of file.Headers) {
|
||||||
|
for (const data of header.Media.Array) {
|
||||||
|
zip.file(`word/media/${data.fileName}`, data.stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const footer of file.Footers) {
|
||||||
|
for (const data of footer.Media.Array) {
|
||||||
|
zip.file(`word/media/${data.fileName}`, data.stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return zip;
|
return zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,4 +140,13 @@ export class Compiler {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* By default docx collapse empty tags. <a></a> -> <a/>. this function mimic it
|
||||||
|
so comparing (diff) original docx file and the library output is easier
|
||||||
|
Currently not used, so commenting out */
|
||||||
|
// private collapseEmptyTags(xmlData: string): string {
|
||||||
|
// const regEx = /<(([^ <>]+)[^<>]*)><\/\2>/g;
|
||||||
|
// const collapsed = xmlData.replace(regEx, "<$1/>");
|
||||||
|
// return collapsed;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
import { stub } from "sinon";
|
import { stub } from "sinon";
|
||||||
|
|
||||||
import { File, Paragraph } from "../../file";
|
import { File, Paragraph } from "file";
|
||||||
|
|
||||||
import { Packer } from "./packer";
|
import { Packer } from "./packer";
|
||||||
|
|
||||||
describe("Packer", () => {
|
describe("Packer", () => {
|
||||||
|
@ -10,21 +10,30 @@ export class Packer {
|
|||||||
|
|
||||||
public async toBuffer(file: File): Promise<Buffer> {
|
public async toBuffer(file: File): Promise<Buffer> {
|
||||||
const zip = await this.compiler.compile(file);
|
const zip = await this.compiler.compile(file);
|
||||||
const zipData = (await zip.generateAsync({ type: "nodebuffer" })) as Buffer;
|
const zipData = (await zip.generateAsync({
|
||||||
|
type: "nodebuffer",
|
||||||
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
})) as Buffer;
|
||||||
|
|
||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toBase64String(file: File): Promise<string> {
|
public async toBase64String(file: File): Promise<string> {
|
||||||
const zip = await this.compiler.compile(file);
|
const zip = await this.compiler.compile(file);
|
||||||
const zipData = (await zip.generateAsync({ type: "base64" })) as string;
|
const zipData = (await zip.generateAsync({
|
||||||
|
type: "base64",
|
||||||
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
})) as string;
|
||||||
|
|
||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toBlob(file: File): Promise<Blob> {
|
public async toBlob(file: File): Promise<Blob> {
|
||||||
const zip = await this.compiler.compile(file);
|
const zip = await this.compiler.compile(file);
|
||||||
const zipData = (await zip.generateAsync({ type: "blob" })) as Blob;
|
const zipData = (await zip.generateAsync({
|
||||||
|
type: "blob",
|
||||||
|
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
})) as Blob;
|
||||||
|
|
||||||
return zipData;
|
return zipData;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IAppPropertiesAttributes {
|
export interface IAppPropertiesAttributes {
|
||||||
xmlns: string;
|
readonly xmlns: string;
|
||||||
vt: string;
|
readonly vt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AppPropertiesAttributes extends XmlAttributeComponent<IAppPropertiesAttributes> {
|
export class AppPropertiesAttributes extends XmlAttributeComponent<IAppPropertiesAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
xmlns: "xmlns",
|
xmlns: "xmlns",
|
||||||
vt: "xmlns:vt",
|
vt: "xmlns:vt",
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IContentTypeAttributes {
|
export interface IContentTypeAttributes {
|
||||||
xmlns?: string;
|
readonly xmlns?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContentTypeAttributes extends XmlAttributeComponent<IContentTypeAttributes> {
|
export class ContentTypeAttributes extends XmlAttributeComponent<IContentTypeAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
xmlns: "xmlns",
|
xmlns: "xmlns",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// tslint:disable:no-string-literal
|
// tslint:disable:no-string-literal
|
||||||
|
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { Formatter } from "../../export/formatter";
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { ContentTypes } from "./content-types";
|
import { ContentTypes } from "./content-types";
|
||||||
|
|
||||||
describe("ContentTypes", () => {
|
describe("ContentTypes", () => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IDefaultAttributes {
|
export interface IDefaultAttributes {
|
||||||
contentType: string;
|
readonly contentType: string;
|
||||||
extension?: string;
|
readonly extension?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DefaultAttributes extends XmlAttributeComponent<IDefaultAttributes> {
|
export class DefaultAttributes extends XmlAttributeComponent<IDefaultAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
contentType: "ContentType",
|
contentType: "ContentType",
|
||||||
extension: "Extension",
|
extension: "Extension",
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IOverrideAttributes {
|
export interface IOverrideAttributes {
|
||||||
contentType: string;
|
readonly contentType: string;
|
||||||
partName?: string;
|
readonly partName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OverrideAttributes extends XmlAttributeComponent<IOverrideAttributes> {
|
export class OverrideAttributes extends XmlAttributeComponent<IOverrideAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
contentType: "ContentType",
|
contentType: "ContentType",
|
||||||
partName: "PartName",
|
partName: "PartName",
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { CoreProperties } from "./properties";
|
import { CoreProperties } from "./properties";
|
||||||
|
|
||||||
describe("Properties", () => {
|
describe("Properties", () => {
|
||||||
|
@ -3,14 +3,14 @@ import { DocumentAttributes } from "../document/document-attributes";
|
|||||||
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
||||||
|
|
||||||
export interface IPropertiesOptions {
|
export interface IPropertiesOptions {
|
||||||
title?: string;
|
readonly title?: string;
|
||||||
subject?: string;
|
readonly subject?: string;
|
||||||
creator?: string;
|
readonly creator?: string;
|
||||||
keywords?: string;
|
readonly keywords?: string;
|
||||||
description?: string;
|
readonly description?: string;
|
||||||
lastModifiedBy?: string;
|
readonly lastModifiedBy?: string;
|
||||||
revision?: string;
|
readonly revision?: string;
|
||||||
externalStyles?: string;
|
readonly externalStyles?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CoreProperties extends XmlComponent {
|
export class CoreProperties extends XmlComponent {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { Body } from "./body";
|
import { Body } from "./body";
|
||||||
|
|
||||||
describe("Body", () => {
|
describe("Body", () => {
|
||||||
@ -16,11 +17,11 @@ describe("Body", () => {
|
|||||||
expect(formatted)
|
expect(formatted)
|
||||||
.to.have.property("w:sectPr")
|
.to.have.property("w:sectPr")
|
||||||
.and.to.be.an.instanceof(Array);
|
.and.to.be.an.instanceof(Array);
|
||||||
expect(formatted["w:sectPr"]).to.have.length(7);
|
expect(formatted["w:sectPr"]).to.have.length(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("addSection", () => {
|
describe("#addSection", () => {
|
||||||
it("should add section with options", () => {
|
it("should add section with options", () => {
|
||||||
body.addSection({
|
body.addSection({
|
||||||
width: 10000,
|
width: 10000,
|
||||||
@ -38,5 +39,93 @@ describe("Body", () => {
|
|||||||
const newSection = formatted[1]["w:sectPr"];
|
const newSection = formatted[1]["w:sectPr"];
|
||||||
expect(newSection[0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } }] });
|
expect(newSection[0]).to.deep.equal({ "w:pgSz": [{ _attr: { "w:h": 10000, "w:w": 10000, "w:orient": "portrait" } }] });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should add section with default parameters", () => {
|
||||||
|
body.addSection({
|
||||||
|
width: 10000,
|
||||||
|
height: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(body);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:body": [
|
||||||
|
{
|
||||||
|
"w:p": [
|
||||||
|
{ "w:pPr": [] },
|
||||||
|
{
|
||||||
|
"w:pPr": [
|
||||||
|
{
|
||||||
|
"w:sectPr": [
|
||||||
|
{ "w:pgSz": [{ _attr: { "w:w": 11906, "w:h": 16838, "w:orient": "portrait" } }] },
|
||||||
|
{
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
"w:mirrorMargins": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ "w:cols": [{ _attr: { "w:space": 708 } }] },
|
||||||
|
{ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] },
|
||||||
|
{ "w:pgNumType": [{ _attr: { "w:fmt": "decimal" } }] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"w:sectPr": [
|
||||||
|
{ "w:pgSz": [{ _attr: { "w:w": 10000, "w:h": 10000, "w:orient": "portrait" } }] },
|
||||||
|
{
|
||||||
|
"w:pgMar": [
|
||||||
|
{
|
||||||
|
_attr: {
|
||||||
|
"w:top": 1440,
|
||||||
|
"w:right": 1440,
|
||||||
|
"w:bottom": 1440,
|
||||||
|
"w:left": 1440,
|
||||||
|
"w:header": 708,
|
||||||
|
"w:footer": 708,
|
||||||
|
"w:gutter": 0,
|
||||||
|
"w:mirrorMargins": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ "w:cols": [{ _attr: { "w:space": 708 } }] },
|
||||||
|
{ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] },
|
||||||
|
{ "w:pgNumType": [{ _attr: { "w:fmt": "decimal" } }] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#getParagraphs", () => {
|
||||||
|
it("should get no paragraphs", () => {
|
||||||
|
const paragraphs = body.getParagraphs();
|
||||||
|
|
||||||
|
expect(paragraphs).to.be.an.instanceof(Array);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#DefaultSection", () => {
|
||||||
|
it("should get section", () => {
|
||||||
|
const section = body.DefaultSection;
|
||||||
|
|
||||||
|
const tree = new Formatter().format(section);
|
||||||
|
expect(tree["w:sectPr"]).to.be.an.instanceof(Array);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -35,11 +35,9 @@ export class Body extends XmlComponent {
|
|||||||
this.sections.push(new SectionProperties(params));
|
this.sections.push(new SectionProperties(params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public prepForXml(): IXmlableObject {
|
public prepForXml(): IXmlableObject | undefined {
|
||||||
if (this.sections.length === 1) {
|
if (this.sections.length === 1) {
|
||||||
this.root.push(this.sections[0]);
|
this.root.push(this.sections[0]);
|
||||||
} else if (this.sections.length > 1) {
|
|
||||||
throw new Error("Invalid usage of sections. At the end of the body element there must be ONE section.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.prepForXml();
|
return super.prepForXml();
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IColumnsAttributes {
|
export interface IColumnsAttributes {
|
||||||
space?: number;
|
readonly space?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
space: "w:space",
|
space: "w:space",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IDocGridAttributesProperties {
|
export interface IDocGridAttributesProperties {
|
||||||
linePitch?: number;
|
readonly linePitch?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
linePitch: "w:linePitch",
|
linePitch: "w:linePitch",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,12 @@ export enum FooterReferenceType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IFooterReferenceAttributes {
|
export interface IFooterReferenceAttributes {
|
||||||
type: string;
|
readonly type: string;
|
||||||
id: string;
|
readonly id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FooterReferenceAttributes extends XmlAttributeComponent<IFooterReferenceAttributes> {
|
export class FooterReferenceAttributes extends XmlAttributeComponent<IFooterReferenceAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
type: "w:type",
|
type: "w:type",
|
||||||
id: "r:id",
|
id: "r:id",
|
||||||
};
|
};
|
||||||
|
@ -2,8 +2,8 @@ import { XmlComponent } from "file/xml-components";
|
|||||||
import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
|
import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
|
||||||
|
|
||||||
export interface IFooterOptions {
|
export interface IFooterOptions {
|
||||||
footerType?: FooterReferenceType;
|
readonly footerType?: FooterReferenceType;
|
||||||
footerId?: number;
|
readonly footerId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FooterReference extends XmlComponent {
|
export class FooterReference extends XmlComponent {
|
||||||
|
@ -7,12 +7,12 @@ export enum HeaderReferenceType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IHeaderReferenceAttributes {
|
export interface IHeaderReferenceAttributes {
|
||||||
type: string;
|
readonly type: string;
|
||||||
id: string;
|
readonly id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HeaderReferenceAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
export class HeaderReferenceAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
type: "w:type",
|
type: "w:type",
|
||||||
id: "r:id",
|
id: "r:id",
|
||||||
};
|
};
|
||||||
|
@ -2,8 +2,8 @@ import { XmlComponent } from "file/xml-components";
|
|||||||
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
|
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
|
||||||
|
|
||||||
export interface IHeaderOptions {
|
export interface IHeaderOptions {
|
||||||
headerType?: HeaderReferenceType;
|
readonly headerType?: HeaderReferenceType;
|
||||||
headerId?: number;
|
readonly headerId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HeaderReference extends XmlComponent {
|
export class HeaderReference extends XmlComponent {
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../../../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
import { BorderStyle } from "../../../../styles";
|
import { BorderStyle } from "file/styles";
|
||||||
|
|
||||||
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
|
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
|
||||||
|
|
||||||
describe("PageBorders", () => {
|
describe("PageBorders", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create empty element when no options are passed", () => {
|
it("should create empty element when no options are passed", () => {
|
||||||
const properties = new PageBorders();
|
const properties = new PageBorders();
|
||||||
const tree = new Formatter().format(properties);
|
expect(() => new Formatter().format(properties)).to.throw();
|
||||||
|
|
||||||
expect(tree).to.equal("");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create page borders with some configuration", () => {
|
it("should create page borders with some configuration", () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// http://officeopenxml.com/WPsectionBorders.php
|
// http://officeopenxml.com/WPsectionBorders.php
|
||||||
|
import { BorderStyle } from "file/styles";
|
||||||
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { IXmlableObject, XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
import { BorderStyle } from "../../../../styles";
|
|
||||||
|
|
||||||
export enum PageBorderDisplay {
|
export enum PageBorderDisplay {
|
||||||
ALL_PAGES = "allPages",
|
ALL_PAGES = "allPages",
|
||||||
@ -19,28 +19,28 @@ export enum PageBorderZOrder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageBorderAttributes {
|
export interface IPageBorderAttributes {
|
||||||
display?: PageBorderDisplay;
|
readonly display?: PageBorderDisplay;
|
||||||
offsetFrom?: PageBorderOffsetFrom;
|
readonly offsetFrom?: PageBorderOffsetFrom;
|
||||||
zOrder?: PageBorderZOrder;
|
readonly zOrder?: PageBorderZOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageBorderConfiguration {
|
export interface IPageBorderConfiguration {
|
||||||
style?: BorderStyle;
|
readonly style?: BorderStyle;
|
||||||
size?: number;
|
readonly size?: number;
|
||||||
color?: string;
|
readonly color?: string;
|
||||||
space?: number;
|
readonly space?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageBordersOptions {
|
export interface IPageBordersOptions {
|
||||||
pageBorders?: IPageBorderAttributes;
|
readonly pageBorders?: IPageBorderAttributes;
|
||||||
pageBorderTop?: IPageBorderConfiguration;
|
readonly pageBorderTop?: IPageBorderConfiguration;
|
||||||
pageBorderRight?: IPageBorderConfiguration;
|
readonly pageBorderRight?: IPageBorderConfiguration;
|
||||||
pageBorderBottom?: IPageBorderConfiguration;
|
readonly pageBorderBottom?: IPageBorderConfiguration;
|
||||||
pageBorderLeft?: IPageBorderConfiguration;
|
readonly pageBorderLeft?: IPageBorderConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PageBordeAttributes extends XmlAttributeComponent<IPageBorderConfiguration> {
|
class PageBordeAttributes extends XmlAttributeComponent<IPageBorderConfiguration> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
style: "w:val",
|
style: "w:val",
|
||||||
size: "w:size",
|
size: "w:size",
|
||||||
color: "w:color",
|
color: "w:color",
|
||||||
@ -57,7 +57,7 @@ class PageBorder extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
display: "w:display",
|
display: "w:display",
|
||||||
offsetFrom: "w:offsetFrom",
|
offsetFrom: "w:offsetFrom",
|
||||||
zOrder: "w:zOrder",
|
zOrder: "w:zOrder",
|
||||||
@ -98,7 +98,9 @@ export class PageBorders extends XmlComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public prepForXml(): IXmlableObject {
|
public prepForXml(): IXmlableObject | undefined {
|
||||||
return this.root.length > 0 ? super.prepForXml() : "";
|
if (this.root.length > 0) {
|
||||||
|
return super.prepForXml();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IPageMarginAttributes {
|
export interface IPageMarginAttributes {
|
||||||
top?: number;
|
readonly top?: number;
|
||||||
right?: number;
|
readonly right?: number;
|
||||||
bottom?: number;
|
readonly bottom?: number;
|
||||||
left?: number;
|
readonly left?: number;
|
||||||
header?: number;
|
readonly header?: number;
|
||||||
footer?: number;
|
readonly footer?: number;
|
||||||
gutter?: number;
|
readonly gutter?: number;
|
||||||
mirror?: boolean;
|
readonly mirror?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
top: "w:top",
|
top: "w:top",
|
||||||
right: "w:right",
|
right: "w:right",
|
||||||
bottom: "w:bottom",
|
bottom: "w:bottom",
|
||||||
|
@ -17,12 +17,12 @@ export enum PageNumberFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageNumberTypeAttributes {
|
export interface IPageNumberTypeAttributes {
|
||||||
pageNumberStart?: number;
|
readonly pageNumberStart?: number;
|
||||||
pageNumberFormatType?: PageNumberFormat;
|
readonly pageNumberFormatType?: PageNumberFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
pageNumberStart: "w:start",
|
pageNumberStart: "w:start",
|
||||||
pageNumberFormatType: "w:fmt",
|
pageNumberFormatType: "w:fmt",
|
||||||
};
|
};
|
||||||
|
@ -6,13 +6,13 @@ export enum PageOrientation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IPageSizeAttributes {
|
export interface IPageSizeAttributes {
|
||||||
width?: number;
|
readonly width?: number;
|
||||||
height?: number;
|
readonly height?: number;
|
||||||
orientation?: PageOrientation;
|
readonly orientation?: PageOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
width: "w:w",
|
width: "w:w",
|
||||||
height: "w:h",
|
height: "w:h",
|
||||||
orientation: "w:orient",
|
orientation: "w:orient",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../../../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { PageSize } from "./page-size";
|
import { PageSize } from "./page-size";
|
||||||
import { PageOrientation } from "./page-size-attributes";
|
import { PageOrientation } from "./page-size-attributes";
|
||||||
|
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
import { FooterReferenceType, PageBorderOffsetFrom, PageNumberFormat } from "./";
|
import { FooterWrapper } from "file/footer-wrapper";
|
||||||
|
import { HeaderWrapper } from "file/header-wrapper";
|
||||||
|
import { Media } from "file/media";
|
||||||
|
|
||||||
|
import { PageBorderOffsetFrom } from "./page-border";
|
||||||
|
import { PageNumberFormat } from "./page-number";
|
||||||
import { SectionProperties } from "./section-properties";
|
import { SectionProperties } from "./section-properties";
|
||||||
|
|
||||||
describe("SectionProperties", () => {
|
describe("SectionProperties", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create section properties with options", () => {
|
it("should create section properties with options", () => {
|
||||||
|
const media = new Media();
|
||||||
|
|
||||||
const properties = new SectionProperties({
|
const properties = new SectionProperties({
|
||||||
width: 11906,
|
width: 11906,
|
||||||
height: 16838,
|
height: 16838,
|
||||||
@ -20,9 +27,12 @@ describe("SectionProperties", () => {
|
|||||||
mirror: false,
|
mirror: false,
|
||||||
space: 708,
|
space: 708,
|
||||||
linePitch: 360,
|
linePitch: 360,
|
||||||
headerId: 100,
|
headers: {
|
||||||
footerId: 200,
|
default: new HeaderWrapper(media, 100),
|
||||||
footerType: FooterReferenceType.EVEN,
|
},
|
||||||
|
footers: {
|
||||||
|
even: new FooterWrapper(media, 200),
|
||||||
|
},
|
||||||
pageNumberStart: 10,
|
pageNumberStart: 10,
|
||||||
pageNumberFormatType: PageNumberFormat.CARDINAL_TEXT,
|
pageNumberFormatType: PageNumberFormat.CARDINAL_TEXT,
|
||||||
});
|
});
|
||||||
@ -78,9 +88,7 @@ describe("SectionProperties", () => {
|
|||||||
});
|
});
|
||||||
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
|
expect(tree["w:sectPr"][2]).to.deep.equal({ "w:cols": [{ _attr: { "w:space": 708 } }] });
|
||||||
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
|
expect(tree["w:sectPr"][3]).to.deep.equal({ "w:docGrid": [{ _attr: { "w:linePitch": 360 } }] });
|
||||||
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:headerReference": [{ _attr: { "r:id": "rId0", "w:type": "default" } }] });
|
expect(tree["w:sectPr"][4]).to.deep.equal({ "w:pgNumType": [{ _attr: { "w:fmt": "decimal" } }] });
|
||||||
expect(tree["w:sectPr"][5]).to.deep.equal({ "w:footerReference": [{ _attr: { "r:id": "rId0", "w:type": "default" } }] });
|
|
||||||
expect(tree["w:sectPr"][6]).to.deep.equal({ "w:pgNumType": [{ _attr: { "w:fmt": "decimal" } }] });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create section properties with changed options", () => {
|
it("should create section properties with changed options", () => {
|
||||||
@ -170,7 +178,8 @@ describe("SectionProperties", () => {
|
|||||||
});
|
});
|
||||||
const tree = new Formatter().format(properties);
|
const tree = new Formatter().format(properties);
|
||||||
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
expect(Object.keys(tree)).to.deep.equal(["w:sectPr"]);
|
||||||
expect(tree["w:sectPr"][7]).to.deep.equal({
|
const pgBorders = tree["w:sectPr"].find((item) => item["w:pgBorders"] !== undefined);
|
||||||
|
expect(pgBorders).to.deep.equal({
|
||||||
"w:pgBorders": [{ _attr: { "w:offsetFrom": "page" } }],
|
"w:pgBorders": [{ _attr: { "w:offsetFrom": "page" } }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,115 +1,172 @@
|
|||||||
// http://officeopenxml.com/WPsection.php
|
// http://officeopenxml.com/WPsection.php
|
||||||
|
import { FooterWrapper } from "file/footer-wrapper";
|
||||||
|
import { HeaderWrapper } from "file/header-wrapper";
|
||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { FooterReferenceType, IPageBordersOptions, IPageNumberTypeAttributes, PageBorders, PageNumberFormat, PageNumberType } from "./";
|
|
||||||
import { Columns } from "./columns/columns";
|
import { Columns } from "./columns/columns";
|
||||||
import { IColumnsAttributes } from "./columns/columns-attributes";
|
import { IColumnsAttributes } from "./columns/columns-attributes";
|
||||||
import { DocumentGrid } from "./doc-grid/doc-grid";
|
import { DocumentGrid } from "./doc-grid/doc-grid";
|
||||||
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
|
import { IDocGridAttributesProperties } from "./doc-grid/doc-grid-attributes";
|
||||||
import { FooterReference, IFooterOptions } from "./footer-reference/footer-reference";
|
import { FooterReferenceType } from "./footer-reference";
|
||||||
import { HeaderReference, IHeaderOptions } from "./header-reference/header-reference";
|
import { FooterReference } from "./footer-reference/footer-reference";
|
||||||
import { HeaderReferenceType } from "./header-reference/header-reference-attributes";
|
import { HeaderReferenceType } from "./header-reference";
|
||||||
|
import { HeaderReference } from "./header-reference/header-reference";
|
||||||
|
import { IPageBordersOptions, PageBorders } from "./page-border";
|
||||||
import { PageMargin } from "./page-margin/page-margin";
|
import { PageMargin } from "./page-margin/page-margin";
|
||||||
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
|
import { IPageMarginAttributes } from "./page-margin/page-margin-attributes";
|
||||||
|
import { IPageNumberTypeAttributes, PageNumberFormat, PageNumberType } from "./page-number";
|
||||||
import { PageSize } from "./page-size/page-size";
|
import { PageSize } from "./page-size/page-size";
|
||||||
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
|
import { IPageSizeAttributes, PageOrientation } from "./page-size/page-size-attributes";
|
||||||
|
import { TitlePage } from "./title-page/title-page";
|
||||||
|
|
||||||
|
export interface IHeaderFooterGroup<T> {
|
||||||
|
readonly default?: T;
|
||||||
|
readonly first?: T;
|
||||||
|
readonly even?: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IHeadersOptions {
|
||||||
|
readonly headers?: IHeaderFooterGroup<HeaderWrapper>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IFootersOptions {
|
||||||
|
readonly footers?: IHeaderFooterGroup<FooterWrapper>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ITitlePageOptions {
|
||||||
|
readonly titlePage?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type SectionPropertiesOptions = IPageSizeAttributes &
|
export type SectionPropertiesOptions = IPageSizeAttributes &
|
||||||
IPageMarginAttributes &
|
IPageMarginAttributes &
|
||||||
IColumnsAttributes &
|
IColumnsAttributes &
|
||||||
IDocGridAttributesProperties &
|
IDocGridAttributesProperties &
|
||||||
IHeaderOptions &
|
IHeadersOptions &
|
||||||
IFooterOptions &
|
IFootersOptions &
|
||||||
IPageNumberTypeAttributes &
|
IPageNumberTypeAttributes &
|
||||||
IPageBordersOptions;
|
IPageBordersOptions &
|
||||||
|
ITitlePageOptions;
|
||||||
|
|
||||||
export class SectionProperties extends XmlComponent {
|
export class SectionProperties extends XmlComponent {
|
||||||
private readonly options: SectionPropertiesOptions;
|
private readonly options: SectionPropertiesOptions;
|
||||||
|
|
||||||
constructor(options?: SectionPropertiesOptions) {
|
constructor(options: SectionPropertiesOptions = {}) {
|
||||||
super("w:sectPr");
|
super("w:sectPr");
|
||||||
|
|
||||||
const defaultOptions = {
|
const {
|
||||||
width: 11906,
|
width = 11906,
|
||||||
height: 16838,
|
height = 16838,
|
||||||
top: 1440,
|
top = 1440,
|
||||||
right: 1440,
|
right = 1440,
|
||||||
bottom: 1440,
|
bottom = 1440,
|
||||||
left: 1440,
|
left = 1440,
|
||||||
header: 708,
|
header = 708,
|
||||||
footer: 708,
|
footer = 708,
|
||||||
gutter: 0,
|
gutter = 0,
|
||||||
mirror: false,
|
mirror = false,
|
||||||
space: 708,
|
space = 708,
|
||||||
linePitch: 360,
|
linePitch = 360,
|
||||||
orientation: PageOrientation.PORTRAIT,
|
orientation = PageOrientation.PORTRAIT,
|
||||||
headerType: HeaderReferenceType.DEFAULT,
|
headers,
|
||||||
headerId: 0,
|
footers,
|
||||||
footerType: FooterReferenceType.DEFAULT,
|
pageNumberFormatType = PageNumberFormat.DECIMAL,
|
||||||
footerId: 0,
|
pageNumberStart,
|
||||||
pageNumberStart: undefined,
|
pageBorders,
|
||||||
pageNumberFormatType: PageNumberFormat.DECIMAL,
|
pageBorderTop,
|
||||||
pageBorders: undefined,
|
pageBorderRight,
|
||||||
pageBorderTop: undefined,
|
pageBorderBottom,
|
||||||
pageBorderRight: undefined,
|
pageBorderLeft,
|
||||||
pageBorderBottom: undefined,
|
titlePage = false,
|
||||||
pageBorderLeft: undefined,
|
} = options;
|
||||||
};
|
|
||||||
|
|
||||||
const mergedOptions = {
|
this.options = options;
|
||||||
...defaultOptions,
|
this.root.push(new PageSize(width, height, orientation));
|
||||||
...options,
|
this.root.push(new PageMargin(top, right, bottom, left, header, footer, gutter, mirror));
|
||||||
};
|
this.root.push(new Columns(space));
|
||||||
|
this.root.push(new DocumentGrid(linePitch));
|
||||||
|
|
||||||
this.root.push(new PageSize(mergedOptions.width, mergedOptions.height, mergedOptions.orientation));
|
this.addHeaders(headers);
|
||||||
this.root.push(
|
this.addFooters(footers);
|
||||||
new PageMargin(
|
|
||||||
mergedOptions.top,
|
|
||||||
mergedOptions.right,
|
|
||||||
mergedOptions.bottom,
|
|
||||||
mergedOptions.left,
|
|
||||||
mergedOptions.header,
|
|
||||||
mergedOptions.footer,
|
|
||||||
mergedOptions.gutter,
|
|
||||||
mergedOptions.mirror,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
this.root.push(new Columns(mergedOptions.space));
|
|
||||||
this.root.push(new DocumentGrid(mergedOptions.linePitch));
|
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(new PageNumberType(pageNumberStart, pageNumberFormatType));
|
||||||
new HeaderReference({
|
|
||||||
headerType: mergedOptions.headerType,
|
|
||||||
headerId: mergedOptions.headerId,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
this.root.push(
|
|
||||||
new FooterReference({
|
|
||||||
footerType: mergedOptions.footerType,
|
|
||||||
footerId: mergedOptions.footerId,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.root.push(new PageNumberType(mergedOptions.pageNumberStart, mergedOptions.pageNumberFormatType));
|
if (pageBorders || pageBorderTop || pageBorderRight || pageBorderBottom || pageBorderLeft) {
|
||||||
|
|
||||||
if (
|
|
||||||
mergedOptions.pageBorders ||
|
|
||||||
mergedOptions.pageBorderTop ||
|
|
||||||
mergedOptions.pageBorderRight ||
|
|
||||||
mergedOptions.pageBorderBottom ||
|
|
||||||
mergedOptions.pageBorderLeft
|
|
||||||
) {
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new PageBorders({
|
new PageBorders({
|
||||||
pageBorders: mergedOptions.pageBorders,
|
pageBorders: pageBorders,
|
||||||
pageBorderTop: mergedOptions.pageBorderTop,
|
pageBorderTop: pageBorderTop,
|
||||||
pageBorderRight: mergedOptions.pageBorderRight,
|
pageBorderRight: pageBorderRight,
|
||||||
pageBorderBottom: mergedOptions.pageBorderBottom,
|
pageBorderBottom: pageBorderBottom,
|
||||||
pageBorderLeft: mergedOptions.pageBorderLeft,
|
pageBorderLeft: pageBorderLeft,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.options = mergedOptions;
|
if (titlePage) {
|
||||||
|
this.root.push(new TitlePage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addHeaders(headers?: IHeaderFooterGroup<HeaderWrapper>): void {
|
||||||
|
if (headers) {
|
||||||
|
if (headers.default) {
|
||||||
|
this.root.push(
|
||||||
|
new HeaderReference({
|
||||||
|
headerType: HeaderReferenceType.DEFAULT,
|
||||||
|
headerId: headers.default.Header.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.first) {
|
||||||
|
this.root.push(
|
||||||
|
new HeaderReference({
|
||||||
|
headerType: HeaderReferenceType.FIRST,
|
||||||
|
headerId: headers.first.Header.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.even) {
|
||||||
|
this.root.push(
|
||||||
|
new HeaderReference({
|
||||||
|
headerType: HeaderReferenceType.EVEN,
|
||||||
|
headerId: headers.even.Header.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFooters(footers?: IHeaderFooterGroup<FooterWrapper>): void {
|
||||||
|
if (footers) {
|
||||||
|
if (footers.default) {
|
||||||
|
this.root.push(
|
||||||
|
new FooterReference({
|
||||||
|
footerType: FooterReferenceType.DEFAULT,
|
||||||
|
footerId: footers.default.Footer.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footers.first) {
|
||||||
|
this.root.push(
|
||||||
|
new FooterReference({
|
||||||
|
footerType: FooterReferenceType.FIRST,
|
||||||
|
footerId: footers.first.Footer.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footers.even) {
|
||||||
|
this.root.push(
|
||||||
|
new FooterReference({
|
||||||
|
footerType: FooterReferenceType.EVEN,
|
||||||
|
footerId: footers.even.Footer.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get Options(): SectionPropertiesOptions {
|
public get Options(): SectionPropertiesOptions {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IHeaderReferenceAttributes {
|
export interface IHeaderReferenceAttributes {
|
||||||
value: string;
|
readonly value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TitlePageAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
export class TitlePageAttributes extends XmlAttributeComponent<IHeaderReferenceAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
value: "w:val",
|
value: "w:val",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../../../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { TitlePage } from "./title-page";
|
import { TitlePage } from "./title-page";
|
||||||
|
|
||||||
describe("PageSize", () => {
|
describe("PageSize", () => {
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IDocumentAttributesProperties {
|
export interface IDocumentAttributesProperties {
|
||||||
wpc?: string;
|
readonly wpc?: string;
|
||||||
mc?: string;
|
readonly mc?: string;
|
||||||
o?: string;
|
readonly o?: string;
|
||||||
r?: string;
|
readonly r?: string;
|
||||||
m?: string;
|
readonly m?: string;
|
||||||
v?: string;
|
readonly v?: string;
|
||||||
wp14?: string;
|
readonly wp14?: string;
|
||||||
wp?: string;
|
readonly wp?: string;
|
||||||
w10?: string;
|
readonly w10?: string;
|
||||||
w?: string;
|
readonly w?: string;
|
||||||
w14?: string;
|
readonly w14?: string;
|
||||||
w15?: string;
|
readonly w15?: string;
|
||||||
wpg?: string;
|
readonly wpg?: string;
|
||||||
wpi?: string;
|
readonly wpi?: string;
|
||||||
wne?: string;
|
readonly wne?: string;
|
||||||
wps?: string;
|
readonly wps?: string;
|
||||||
Ignorable?: string;
|
readonly Ignorable?: string;
|
||||||
cp?: string;
|
readonly cp?: string;
|
||||||
dc?: string;
|
readonly dc?: string;
|
||||||
dcterms?: string;
|
readonly dcterms?: string;
|
||||||
dcmitype?: string;
|
readonly dcmitype?: string;
|
||||||
xsi?: string;
|
readonly xsi?: string;
|
||||||
type?: string;
|
readonly type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DocumentAttributes extends XmlAttributeComponent<IDocumentAttributesProperties> {
|
export class DocumentAttributes extends XmlAttributeComponent<IDocumentAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
wpc: "xmlns:wpc",
|
wpc: "xmlns:wpc",
|
||||||
mc: "xmlns:mc",
|
mc: "xmlns:mc",
|
||||||
o: "xmlns:o",
|
o: "xmlns:o",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { assert, expect } from "chai";
|
import { assert, expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "../../export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { Paragraph } from "../paragraph";
|
import { Paragraph } from "../paragraph";
|
||||||
import { Table } from "../table";
|
import { Table } from "../table";
|
||||||
import { Document } from "./document";
|
import { Document } from "./document";
|
||||||
|
@ -2,16 +2,16 @@ import { XmlAttributeComponent } from "file/xml-components";
|
|||||||
import { IDistance } from "../drawing";
|
import { IDistance } from "../drawing";
|
||||||
|
|
||||||
export interface IAnchorAttributes extends IDistance {
|
export interface IAnchorAttributes extends IDistance {
|
||||||
allowOverlap?: "0" | "1";
|
readonly allowOverlap?: "0" | "1";
|
||||||
behindDoc?: "0" | "1";
|
readonly behindDoc?: "0" | "1";
|
||||||
layoutInCell?: "0" | "1";
|
readonly layoutInCell?: "0" | "1";
|
||||||
locked?: "0" | "1";
|
readonly locked?: "0" | "1";
|
||||||
relativeHeight?: number;
|
readonly relativeHeight?: number;
|
||||||
simplePos?: "0" | "1";
|
readonly simplePos?: "0" | "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AnchorAttributes extends XmlAttributeComponent<IAnchorAttributes> {
|
export class AnchorAttributes extends XmlAttributeComponent<IAnchorAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
distT: "distT",
|
distT: "distT",
|
||||||
distB: "distB",
|
distB: "distB",
|
||||||
distL: "distL",
|
distL: "distL",
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { Utility } from "../../../tests/utility";
|
import { Utility } from "tests/utility";
|
||||||
import { IDrawingOptions, TextWrapStyle } from ".././";
|
|
||||||
import { Anchor } from "./";
|
|
||||||
|
|
||||||
function createDrawing(drawingOptions: IDrawingOptions): Anchor {
|
import { IDrawingOptions } from "../drawing";
|
||||||
|
import { TextWrappingType } from "../text-wrap";
|
||||||
|
import { Anchor } from "./anchor";
|
||||||
|
|
||||||
|
function createAnchor(drawingOptions: IDrawingOptions): Anchor {
|
||||||
return new Anchor(
|
return new Anchor(
|
||||||
1,
|
1,
|
||||||
{
|
{
|
||||||
@ -26,14 +28,32 @@ describe("Anchor", () => {
|
|||||||
|
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
it("should create a Drawing with correct root key", () => {
|
it("should create a Drawing with correct root key", () => {
|
||||||
anchor = createDrawing({});
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
const newJson = Utility.jsonify(anchor);
|
const newJson = Utility.jsonify(anchor);
|
||||||
assert.equal(newJson.rootKey, "wp:anchor");
|
assert.equal(newJson.rootKey, "wp:anchor");
|
||||||
assert.equal(newJson.root.length, 10);
|
assert.equal(newJson.root.length, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create a Drawing with all default options", () => {
|
it("should create a Drawing with all default options", () => {
|
||||||
anchor = createDrawing({});
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
const newJson = Utility.jsonify(anchor);
|
const newJson = Utility.jsonify(anchor);
|
||||||
assert.equal(newJson.root.length, 10);
|
assert.equal(newJson.root.length, 10);
|
||||||
|
|
||||||
@ -58,7 +78,7 @@ describe("Anchor", () => {
|
|||||||
const horizontalPosition = newJson.root[2];
|
const horizontalPosition = newJson.root[2];
|
||||||
assert.equal(horizontalPosition.rootKey, "wp:positionH");
|
assert.equal(horizontalPosition.rootKey, "wp:positionH");
|
||||||
assert.include(horizontalPosition.root[0].root, {
|
assert.include(horizontalPosition.root[0].root, {
|
||||||
relativeFrom: "column",
|
relativeFrom: "page",
|
||||||
});
|
});
|
||||||
assert.equal(horizontalPosition.root[1].rootKey, "wp:posOffset");
|
assert.equal(horizontalPosition.root[1].rootKey, "wp:posOffset");
|
||||||
assert.include(horizontalPosition.root[1].root[0], 0);
|
assert.include(horizontalPosition.root[1].root[0], 0);
|
||||||
@ -67,7 +87,7 @@ describe("Anchor", () => {
|
|||||||
const verticalPosition = newJson.root[3];
|
const verticalPosition = newJson.root[3];
|
||||||
assert.equal(verticalPosition.rootKey, "wp:positionV");
|
assert.equal(verticalPosition.rootKey, "wp:positionV");
|
||||||
assert.include(verticalPosition.root[0].root, {
|
assert.include(verticalPosition.root[0].root, {
|
||||||
relativeFrom: "paragraph",
|
relativeFrom: "page",
|
||||||
});
|
});
|
||||||
assert.equal(verticalPosition.root[1].rootKey, "wp:posOffset");
|
assert.equal(verticalPosition.root[1].rootKey, "wp:posOffset");
|
||||||
assert.include(verticalPosition.root[1].root[0], 0);
|
assert.include(verticalPosition.root[1].root[0], 0);
|
||||||
@ -101,10 +121,18 @@ describe("Anchor", () => {
|
|||||||
assert.equal(graphic.rootKey, "a:graphic");
|
assert.equal(graphic.rootKey, "a:graphic");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create a Drawing with text wrapping", () => {
|
it("should create a Drawing with square text wrapping", () => {
|
||||||
anchor = createDrawing({
|
anchor = createAnchor({
|
||||||
textWrapping: {
|
floating: {
|
||||||
textWrapStyle: TextWrapStyle.SQUARE,
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.SQUARE,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const newJson = Utility.jsonify(anchor);
|
const newJson = Utility.jsonify(anchor);
|
||||||
@ -114,5 +142,68 @@ describe("Anchor", () => {
|
|||||||
const textWrap = newJson.root[6];
|
const textWrap = newJson.root[6];
|
||||||
assert.equal(textWrap.rootKey, "wp:wrapSquare");
|
assert.equal(textWrap.rootKey, "wp:wrapSquare");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create a Drawing with no text wrapping", () => {
|
||||||
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.NONE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const newJson = Utility.jsonify(anchor);
|
||||||
|
assert.equal(newJson.root.length, 10);
|
||||||
|
|
||||||
|
const textWrap = newJson.root[6];
|
||||||
|
assert.equal(textWrap.rootKey, "wp:wrapNone");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a Drawing with tight text wrapping", () => {
|
||||||
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.TIGHT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const newJson = Utility.jsonify(anchor);
|
||||||
|
assert.equal(newJson.root.length, 10);
|
||||||
|
|
||||||
|
const textWrap = newJson.root[6];
|
||||||
|
assert.equal(textWrap.rootKey, "wp:wrapTight");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a Drawing with tight text wrapping", () => {
|
||||||
|
anchor = createAnchor({
|
||||||
|
floating: {
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
type: TextWrappingType.TOP_AND_BOTTOM,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const newJson = Utility.jsonify(anchor);
|
||||||
|
assert.equal(newJson.root.length, 10);
|
||||||
|
|
||||||
|
const textWrap = newJson.root[6];
|
||||||
|
assert.equal(textWrap.rootKey, "wp:wrapTopAndBottom");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,16 +2,9 @@
|
|||||||
import { IMediaDataDimensions } from "file/media";
|
import { IMediaDataDimensions } from "file/media";
|
||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { IDrawingOptions } from "../drawing";
|
import { IDrawingOptions } from "../drawing";
|
||||||
import {
|
import { HorizontalPosition, IFloating, SimplePos, VerticalPosition } from "../floating";
|
||||||
HorizontalPosition,
|
|
||||||
HorizontalPositionRelativeFrom,
|
|
||||||
IFloating,
|
|
||||||
SimplePos,
|
|
||||||
VerticalPosition,
|
|
||||||
VerticalPositionRelativeFrom,
|
|
||||||
} from "../floating";
|
|
||||||
import { Graphic } from "../inline/graphic";
|
import { Graphic } from "../inline/graphic";
|
||||||
import { TextWrapStyle, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
import { TextWrappingType, WrapNone, WrapSquare, WrapTight, WrapTopAndBottom } from "../text-wrap";
|
||||||
import { DocProperties } from "./../doc-properties/doc-properties";
|
import { DocProperties } from "./../doc-properties/doc-properties";
|
||||||
import { EffectExtent } from "./../effect-extent/effect-extent";
|
import { EffectExtent } from "./../effect-extent/effect-extent";
|
||||||
import { Extent } from "./../extent/extent";
|
import { Extent } from "./../extent/extent";
|
||||||
@ -23,14 +16,8 @@ const defaultOptions: IFloating = {
|
|||||||
behindDocument: false,
|
behindDocument: false,
|
||||||
lockAnchor: false,
|
lockAnchor: false,
|
||||||
layoutInCell: true,
|
layoutInCell: true,
|
||||||
verticalPosition: {
|
verticalPosition: {},
|
||||||
relative: VerticalPositionRelativeFrom.PARAGRAPH,
|
horizontalPosition: {},
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.COLUMN,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Anchor extends XmlComponent {
|
export class Anchor extends XmlComponent {
|
||||||
@ -38,15 +25,22 @@ export class Anchor extends XmlComponent {
|
|||||||
super("wp:anchor");
|
super("wp:anchor");
|
||||||
|
|
||||||
const floating = {
|
const floating = {
|
||||||
|
margins: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
...drawingOptions.floating,
|
...drawingOptions.floating,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new AnchorAttributes({
|
new AnchorAttributes({
|
||||||
distT: 0,
|
distT: floating.margins.top || 0,
|
||||||
distB: 0,
|
distB: floating.margins.bottom || 0,
|
||||||
distL: 0,
|
distL: floating.margins.left || 0,
|
||||||
distR: 0,
|
distR: floating.margins.right || 0,
|
||||||
simplePos: "0", // note: word doesn't fully support - so we use 0
|
simplePos: "0", // note: word doesn't fully support - so we use 0
|
||||||
allowOverlap: floating.allowOverlap === true ? "1" : "0",
|
allowOverlap: floating.allowOverlap === true ? "1" : "0",
|
||||||
behindDoc: floating.behindDocument === true ? "1" : "0",
|
behindDoc: floating.behindDocument === true ? "1" : "0",
|
||||||
@ -62,18 +56,18 @@ export class Anchor extends XmlComponent {
|
|||||||
this.root.push(new Extent(dimensions.emus.x, dimensions.emus.y));
|
this.root.push(new Extent(dimensions.emus.x, dimensions.emus.y));
|
||||||
this.root.push(new EffectExtent());
|
this.root.push(new EffectExtent());
|
||||||
|
|
||||||
if (drawingOptions.textWrapping !== undefined) {
|
if (drawingOptions.floating !== undefined && drawingOptions.floating.wrap !== undefined) {
|
||||||
switch (drawingOptions.textWrapping.textWrapStyle) {
|
switch (drawingOptions.floating.wrap.type) {
|
||||||
case TextWrapStyle.SQUARE:
|
case TextWrappingType.SQUARE:
|
||||||
this.root.push(new WrapSquare(drawingOptions.textWrapping));
|
this.root.push(new WrapSquare(drawingOptions.floating.wrap, drawingOptions.floating.margins));
|
||||||
break;
|
break;
|
||||||
case TextWrapStyle.TIGHT:
|
case TextWrappingType.TIGHT:
|
||||||
this.root.push(new WrapTight(drawingOptions.textWrapping.distanceFromText));
|
this.root.push(new WrapTight(drawingOptions.floating.margins));
|
||||||
break;
|
break;
|
||||||
case TextWrapStyle.TOP_AND_BOTTOM:
|
case TextWrappingType.TOP_AND_BOTTOM:
|
||||||
this.root.push(new WrapTopAndBottom(drawingOptions.textWrapping.distanceFromText));
|
this.root.push(new WrapTopAndBottom(drawingOptions.floating.margins));
|
||||||
break;
|
break;
|
||||||
case TextWrapStyle.NONE:
|
case TextWrappingType.NONE:
|
||||||
default:
|
default:
|
||||||
this.root.push(new WrapNone());
|
this.root.push(new WrapNone());
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IDocPropertiesAttributes {
|
export interface IDocPropertiesAttributes {
|
||||||
id?: number;
|
readonly id?: number;
|
||||||
name?: string;
|
readonly name?: string;
|
||||||
descr?: string;
|
readonly descr?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DocPropertiesAttributes extends XmlAttributeComponent<IDocPropertiesAttributes> {
|
export class DocPropertiesAttributes extends XmlAttributeComponent<IDocPropertiesAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
id: "id",
|
id: "id",
|
||||||
name: "name",
|
name: "name",
|
||||||
descr: "descr",
|
descr: "descr",
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { Utility } from "../../tests/utility";
|
import { Utility } from "tests/utility";
|
||||||
import { Drawing, IDrawingOptions, PlacementPosition } from "./";
|
|
||||||
|
import { Drawing, IDrawingOptions } from "./drawing";
|
||||||
|
|
||||||
const imageBase64Data = `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`;
|
const imageBase64Data = `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`;
|
||||||
|
|
||||||
@ -46,7 +47,14 @@ describe("Drawing", () => {
|
|||||||
|
|
||||||
it("should create a drawing with anchor element when there options are passed", () => {
|
it("should create a drawing with anchor element when there options are passed", () => {
|
||||||
currentBreak = createDrawing({
|
currentBreak = createDrawing({
|
||||||
position: PlacementPosition.FLOATING,
|
floating: {
|
||||||
|
horizontalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
verticalPosition: {
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const newJson = Utility.jsonify(currentBreak);
|
const newJson = Utility.jsonify(currentBreak);
|
||||||
assert.equal(newJson.root[0].rootKey, "wp:anchor");
|
assert.equal(newJson.root[0].rootKey, "wp:anchor");
|
||||||
|
@ -3,50 +3,33 @@ import { XmlComponent } from "file/xml-components";
|
|||||||
import { Anchor } from "./anchor";
|
import { Anchor } from "./anchor";
|
||||||
import { IFloating } from "./floating";
|
import { IFloating } from "./floating";
|
||||||
import { Inline } from "./inline";
|
import { Inline } from "./inline";
|
||||||
import { ITextWrapping } from "./text-wrap";
|
|
||||||
|
|
||||||
export enum PlacementPosition {
|
|
||||||
INLINE,
|
|
||||||
FLOATING,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDistance {
|
export interface IDistance {
|
||||||
distT?: number;
|
readonly distT?: number;
|
||||||
distB?: number;
|
readonly distB?: number;
|
||||||
distL?: number;
|
readonly distL?: number;
|
||||||
distR?: number;
|
readonly distR?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDrawingOptions {
|
export interface IDrawingOptions {
|
||||||
position?: PlacementPosition;
|
readonly floating?: IFloating;
|
||||||
textWrapping?: ITextWrapping;
|
|
||||||
floating?: IFloating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultDrawingOptions: IDrawingOptions = {
|
|
||||||
position: PlacementPosition.INLINE,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Drawing extends XmlComponent {
|
export class Drawing extends XmlComponent {
|
||||||
private readonly inline: Inline;
|
private readonly inline: Inline;
|
||||||
|
|
||||||
constructor(imageData: IMediaData, drawingOptions?: IDrawingOptions) {
|
constructor(imageData: IMediaData, drawingOptions: IDrawingOptions = {}) {
|
||||||
super("w:drawing");
|
super("w:drawing");
|
||||||
|
|
||||||
if (imageData === undefined) {
|
if (imageData === undefined) {
|
||||||
throw new Error("imageData cannot be undefined");
|
throw new Error("imageData cannot be undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const mergedOptions = {
|
if (!drawingOptions.floating) {
|
||||||
...defaultDrawingOptions,
|
|
||||||
...drawingOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mergedOptions.position === PlacementPosition.INLINE) {
|
|
||||||
this.inline = new Inline(imageData.referenceId, imageData.dimensions);
|
this.inline = new Inline(imageData.referenceId, imageData.dimensions);
|
||||||
this.root.push(this.inline);
|
this.root.push(this.inline);
|
||||||
} else if (mergedOptions.position === PlacementPosition.FLOATING) {
|
} else {
|
||||||
this.root.push(new Anchor(imageData.referenceId, imageData.dimensions, mergedOptions));
|
this.root.push(new Anchor(imageData.referenceId, imageData.dimensions, drawingOptions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IEffectExtentAttributes {
|
export interface IEffectExtentAttributes {
|
||||||
b?: number;
|
readonly b?: number;
|
||||||
l?: number;
|
readonly l?: number;
|
||||||
r?: number;
|
readonly r?: number;
|
||||||
t?: number;
|
readonly t?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EffectExtentAttributes extends XmlAttributeComponent<IEffectExtentAttributes> {
|
export class EffectExtentAttributes extends XmlAttributeComponent<IEffectExtentAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
b: "b",
|
b: "b",
|
||||||
l: "l",
|
l: "l",
|
||||||
r: "r",
|
r: "r",
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IExtentAttributes {
|
export interface IExtentAttributes {
|
||||||
cx?: number;
|
readonly cx?: number;
|
||||||
cy?: number;
|
readonly cy?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExtentAttributes extends XmlAttributeComponent<IExtentAttributes> {
|
export class ExtentAttributes extends XmlAttributeComponent<IExtentAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
cx: "cx",
|
cx: "cx",
|
||||||
cy: "cy",
|
cy: "cy",
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { ExtentAttributes } from "./extent-attributes";
|
import { ExtentAttributes } from "./extent-attributes";
|
||||||
|
|
||||||
export class Extent extends XmlComponent {
|
export class Extent extends XmlComponent {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { VerticalPositionAlign } from ".";
|
import { Utility } from "tests/utility";
|
||||||
import { Utility } from "../../../tests/utility";
|
|
||||||
import { Align } from "./align";
|
import { Align } from "./align";
|
||||||
|
import { VerticalPositionAlign } from "./floating-position";
|
||||||
|
|
||||||
describe("Align", () => {
|
describe("Align", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-position.php
|
// http://officeopenxml.com/drwPicFloating-position.php
|
||||||
|
import { ITextWrapping } from "../text-wrap";
|
||||||
|
|
||||||
export enum HorizontalPositionRelativeFrom {
|
export enum HorizontalPositionRelativeFrom {
|
||||||
CHARACTER = "character",
|
CHARACTER = "character",
|
||||||
@ -39,22 +40,31 @@ export enum VerticalPositionAlign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IHorizontalPositionOptions {
|
export interface IHorizontalPositionOptions {
|
||||||
relative: HorizontalPositionRelativeFrom;
|
readonly relative?: HorizontalPositionRelativeFrom;
|
||||||
align?: HorizontalPositionAlign;
|
readonly align?: HorizontalPositionAlign;
|
||||||
offset?: number;
|
readonly offset?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IVerticalPositionOptions {
|
export interface IVerticalPositionOptions {
|
||||||
relative: VerticalPositionRelativeFrom;
|
readonly relative?: VerticalPositionRelativeFrom;
|
||||||
align?: VerticalPositionAlign;
|
readonly align?: VerticalPositionAlign;
|
||||||
offset?: number;
|
readonly offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMargins {
|
||||||
|
readonly left?: number;
|
||||||
|
readonly bottom?: number;
|
||||||
|
readonly top?: number;
|
||||||
|
readonly right?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFloating {
|
export interface IFloating {
|
||||||
horizontalPosition: IHorizontalPositionOptions;
|
readonly horizontalPosition: IHorizontalPositionOptions;
|
||||||
verticalPosition: IVerticalPositionOptions;
|
readonly verticalPosition: IVerticalPositionOptions;
|
||||||
allowOverlap?: boolean;
|
readonly allowOverlap?: boolean;
|
||||||
lockAnchor?: boolean;
|
readonly lockAnchor?: boolean;
|
||||||
behindDocument?: boolean;
|
readonly behindDocument?: boolean;
|
||||||
layoutInCell?: boolean;
|
readonly layoutInCell?: boolean;
|
||||||
|
readonly margins?: IMargins;
|
||||||
|
readonly wrap?: ITextWrapping;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from ".";
|
import { Utility } from "tests/utility";
|
||||||
import { Utility } from "../../../tests/utility";
|
|
||||||
|
import { HorizontalPositionAlign, HorizontalPositionRelativeFrom } from "./floating-position";
|
||||||
import { HorizontalPosition } from "./horizontal-position";
|
import { HorizontalPosition } from "./horizontal-position";
|
||||||
|
|
||||||
describe("HorizontalPosition", () => {
|
describe("HorizontalPosition", () => {
|
||||||
|
@ -5,11 +5,11 @@ import { HorizontalPositionRelativeFrom, IHorizontalPositionOptions } from "./fl
|
|||||||
import { PositionOffset } from "./position-offset";
|
import { PositionOffset } from "./position-offset";
|
||||||
|
|
||||||
interface IHorizontalPositionAttributes {
|
interface IHorizontalPositionAttributes {
|
||||||
relativeFrom: HorizontalPositionRelativeFrom;
|
readonly relativeFrom: HorizontalPositionRelativeFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HorizontalPositionAttributes extends XmlAttributeComponent<IHorizontalPositionAttributes> {
|
class HorizontalPositionAttributes extends XmlAttributeComponent<IHorizontalPositionAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
relativeFrom: "relativeFrom",
|
relativeFrom: "relativeFrom",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ export class HorizontalPosition extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new HorizontalPositionAttributes({
|
new HorizontalPositionAttributes({
|
||||||
relativeFrom: horizontalPosition.relative,
|
relativeFrom: horizontalPosition.relative || HorizontalPositionRelativeFrom.PAGE,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { Utility } from "../../../tests/utility";
|
import { Utility } from "tests/utility";
|
||||||
|
|
||||||
import { PositionOffset } from "./position-offset";
|
import { PositionOffset } from "./position-offset";
|
||||||
|
|
||||||
describe("PositionOffset", () => {
|
describe("PositionOffset", () => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { Utility } from "../../../tests/utility";
|
import { Utility } from "tests/utility";
|
||||||
|
|
||||||
import { SimplePos } from "./simple-pos";
|
import { SimplePos } from "./simple-pos";
|
||||||
|
|
||||||
describe("SimplePos", () => {
|
describe("SimplePos", () => {
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
interface ISimplePosAttributes {
|
interface ISimplePosAttributes {
|
||||||
x: number;
|
readonly x: number;
|
||||||
y: number;
|
readonly y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimplePosAttributes extends XmlAttributeComponent<ISimplePosAttributes> {
|
class SimplePosAttributes extends XmlAttributeComponent<ISimplePosAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
x: "x",
|
x: "x",
|
||||||
y: "y",
|
y: "y",
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { assert } from "chai";
|
import { assert } from "chai";
|
||||||
|
|
||||||
import { VerticalPositionAlign, VerticalPositionRelativeFrom } from ".";
|
import { Utility } from "tests/utility";
|
||||||
import { Utility } from "../../../tests/utility";
|
|
||||||
|
import { VerticalPositionAlign, VerticalPositionRelativeFrom } from "./floating-position";
|
||||||
import { VerticalPosition } from "./vertical-position";
|
import { VerticalPosition } from "./vertical-position";
|
||||||
|
|
||||||
describe("VerticalPosition", () => {
|
describe("VerticalPosition", () => {
|
||||||
|
@ -5,11 +5,11 @@ import { IVerticalPositionOptions, VerticalPositionRelativeFrom } from "./floati
|
|||||||
import { PositionOffset } from "./position-offset";
|
import { PositionOffset } from "./position-offset";
|
||||||
|
|
||||||
interface IVerticalPositionAttributes {
|
interface IVerticalPositionAttributes {
|
||||||
relativeFrom: VerticalPositionRelativeFrom;
|
readonly relativeFrom: VerticalPositionRelativeFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
class VerticalPositionAttributes extends XmlAttributeComponent<IVerticalPositionAttributes> {
|
class VerticalPositionAttributes extends XmlAttributeComponent<IVerticalPositionAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
relativeFrom: "relativeFrom",
|
relativeFrom: "relativeFrom",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ export class VerticalPosition extends XmlComponent {
|
|||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new VerticalPositionAttributes({
|
new VerticalPositionAttributes({
|
||||||
relativeFrom: verticalPosition.relative,
|
relativeFrom: verticalPosition.relative || VerticalPositionRelativeFrom.PAGE,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IGraphicFrameLockAttributes {
|
export interface IGraphicFrameLockAttributes {
|
||||||
xmlns?: string;
|
readonly xmlns?: string;
|
||||||
noChangeAspect?: number;
|
readonly noChangeAspect?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GraphicFrameLockAttributes extends XmlAttributeComponent<IGraphicFrameLockAttributes> {
|
export class GraphicFrameLockAttributes extends XmlAttributeComponent<IGraphicFrameLockAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
xmlns: "xmlns:a",
|
xmlns: "xmlns:a",
|
||||||
noChangeAspect: "noChangeAspect",
|
noChangeAspect: "noChangeAspect",
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IGraphicDataAttributes {
|
export interface IGraphicDataAttributes {
|
||||||
uri?: string;
|
readonly uri?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GraphicDataAttributes extends XmlAttributeComponent<IGraphicDataAttributes> {
|
export class GraphicDataAttributes extends XmlAttributeComponent<IGraphicDataAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
uri: "uri",
|
uri: "uri",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
interface IBlipProperties {
|
interface IBlipProperties {
|
||||||
embed: string;
|
readonly embed: string;
|
||||||
cstate: string;
|
readonly cstate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
|
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
embed: "r:embed",
|
embed: "r:embed",
|
||||||
cstate: "cstate",
|
cstate: "cstate",
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IPicLocksAttributes {
|
export interface IPicLocksAttributes {
|
||||||
noChangeAspect?: number;
|
readonly noChangeAspect?: number;
|
||||||
noChangeArrowheads?: number;
|
readonly noChangeArrowheads?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PicLocksAttributes extends XmlAttributeComponent<IPicLocksAttributes> {
|
export class PicLocksAttributes extends XmlAttributeComponent<IPicLocksAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
noChangeAspect: "noChangeAspect",
|
noChangeAspect: "noChangeAspect",
|
||||||
noChangeArrowheads: "noChangeArrowheads",
|
noChangeArrowheads: "noChangeArrowheads",
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface INonVisualPropertiesAttributes {
|
export interface INonVisualPropertiesAttributes {
|
||||||
id?: number;
|
readonly id?: number;
|
||||||
name?: string;
|
readonly name?: string;
|
||||||
descr?: string;
|
readonly descr?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NonVisualPropertiesAttributes extends XmlAttributeComponent<INonVisualPropertiesAttributes> {
|
export class NonVisualPropertiesAttributes extends XmlAttributeComponent<INonVisualPropertiesAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
id: "id",
|
id: "id",
|
||||||
name: "name",
|
name: "name",
|
||||||
descr: "desc",
|
descr: "desc",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IPicAttributes {
|
export interface IPicAttributes {
|
||||||
xmlns?: string;
|
readonly xmlns?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PicAttributes extends XmlAttributeComponent<IPicAttributes> {
|
export class PicAttributes extends XmlAttributeComponent<IPicAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
xmlns: "xmlns:pic",
|
xmlns: "xmlns:pic",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IExtentsAttributes {
|
export interface IExtentsAttributes {
|
||||||
cx?: number;
|
readonly cx?: number;
|
||||||
cy?: number;
|
readonly cy?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExtentsAttributes extends XmlAttributeComponent<IExtentsAttributes> {
|
export class ExtentsAttributes extends XmlAttributeComponent<IExtentsAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
cx: "cx",
|
cx: "cx",
|
||||||
cy: "cy",
|
cy: "cy",
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IOffsetAttributes {
|
export interface IOffsetAttributes {
|
||||||
x?: number;
|
readonly x?: number;
|
||||||
y?: number;
|
readonly y?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OffsetAttributes extends XmlAttributeComponent<IOffsetAttributes> {
|
export class OffsetAttributes extends XmlAttributeComponent<IOffsetAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
x: "x",
|
x: "x",
|
||||||
y: "y",
|
y: "y",
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IPresetGeometryAttributes {
|
export interface IPresetGeometryAttributes {
|
||||||
prst?: string;
|
readonly prst?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PresetGeometryAttributes extends XmlAttributeComponent<IPresetGeometryAttributes> {
|
export class PresetGeometryAttributes extends XmlAttributeComponent<IPresetGeometryAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
prst: "prst",
|
prst: "prst",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IShapePropertiesAttributes {
|
export interface IShapePropertiesAttributes {
|
||||||
bwMode?: string;
|
readonly bwMode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ShapePropertiesAttributes extends XmlAttributeComponent<IShapePropertiesAttributes> {
|
export class ShapePropertiesAttributes extends XmlAttributeComponent<IShapePropertiesAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
bwMode: "bwMode",
|
bwMode: "bwMode",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
|||||||
import { GraphicData } from "./graphic-data";
|
import { GraphicData } from "./graphic-data";
|
||||||
|
|
||||||
interface IGraphicProperties {
|
interface IGraphicProperties {
|
||||||
a: string;
|
readonly a: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GraphicAttributes extends XmlAttributeComponent<IGraphicProperties> {
|
class GraphicAttributes extends XmlAttributeComponent<IGraphicProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
a: "xmlns:a",
|
a: "xmlns:a",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
import { IDistance } from "../drawing";
|
import { IDistance } from "../drawing";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// distT, distB etc have no effect on inline images, only floating
|
||||||
export interface IInlineAttributes extends IDistance {}
|
export interface IInlineAttributes extends IDistance {
|
||||||
|
readonly distT?: number;
|
||||||
|
readonly distB?: number;
|
||||||
|
readonly distL?: number;
|
||||||
|
readonly distR?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class InlineAttributes extends XmlAttributeComponent<IInlineAttributes> {
|
export class InlineAttributes extends XmlAttributeComponent<IInlineAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
distT: "distT",
|
distT: "distT",
|
||||||
distB: "distB",
|
distB: "distB",
|
||||||
distL: "distL",
|
distL: "distL",
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
||||||
import { IDistance } from "../drawing";
|
import { IDistance } from "../drawing";
|
||||||
|
|
||||||
export enum TextWrapStyle {
|
export enum TextWrappingType {
|
||||||
NONE,
|
NONE,
|
||||||
SQUARE,
|
SQUARE,
|
||||||
TIGHT,
|
TIGHT,
|
||||||
TOP_AND_BOTTOM,
|
TOP_AND_BOTTOM,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum WrapTextOption {
|
export enum TextWrappingSide {
|
||||||
BOTH_SIDES = "bothSides",
|
BOTH_SIDES = "bothSides",
|
||||||
LEFT = "left",
|
LEFT = "left",
|
||||||
RIGHT = "right",
|
RIGHT = "right",
|
||||||
@ -16,7 +16,7 @@ export enum WrapTextOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ITextWrapping {
|
export interface ITextWrapping {
|
||||||
textWrapStyle: TextWrapStyle;
|
readonly type: TextWrappingType;
|
||||||
wrapTextOption?: WrapTextOption;
|
readonly side?: TextWrappingSide;
|
||||||
distanceFromText?: IDistance;
|
readonly margins?: IDistance;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
import { ITextWrapping, WrapTextOption } from ".";
|
import { ITextWrapping, TextWrappingSide } from ".";
|
||||||
import { IDistance } from "../drawing";
|
import { IDistance } from "../drawing";
|
||||||
|
import { IMargins } from "../floating";
|
||||||
|
|
||||||
interface IWrapSquareAttributes extends IDistance {
|
interface IWrapSquareAttributes extends IDistance {
|
||||||
wrapText?: WrapTextOption;
|
readonly wrapText?: TextWrappingSide;
|
||||||
|
readonly distT?: number;
|
||||||
|
readonly distB?: number;
|
||||||
|
readonly distL?: number;
|
||||||
|
readonly distR?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {
|
class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
distT: "distT",
|
distT: "distT",
|
||||||
distB: "distB",
|
distB: "distB",
|
||||||
distL: "distL",
|
distL: "distL",
|
||||||
@ -18,13 +23,24 @@ class WrapSquareAttributes extends XmlAttributeComponent<IWrapSquareAttributes>
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class WrapSquare extends XmlComponent {
|
export class WrapSquare extends XmlComponent {
|
||||||
constructor(textWrapping: ITextWrapping) {
|
constructor(
|
||||||
|
textWrapping: ITextWrapping,
|
||||||
|
margins: IMargins = {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
) {
|
||||||
super("wp:wrapSquare");
|
super("wp:wrapSquare");
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new WrapSquareAttributes({
|
new WrapSquareAttributes({
|
||||||
wrapText: textWrapping.wrapTextOption || WrapTextOption.BOTH_SIDES,
|
wrapText: textWrapping.side || TextWrappingSide.BOTH_SIDES,
|
||||||
...textWrapping.distanceFromText,
|
distT: margins.top,
|
||||||
|
distB: margins.bottom,
|
||||||
|
distL: margins.left,
|
||||||
|
distR: margins.right,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
import { IDistance } from "../drawing";
|
|
||||||
|
import { IMargins } from "../floating";
|
||||||
|
|
||||||
interface IWrapTightAttributes {
|
interface IWrapTightAttributes {
|
||||||
distT?: number;
|
readonly distT?: number;
|
||||||
distB?: number;
|
readonly distB?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrapTightAttributes extends XmlAttributeComponent<IWrapTightAttributes> {
|
class WrapTightAttributes extends XmlAttributeComponent<IWrapTightAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
distT: "distT",
|
distT: "distT",
|
||||||
distB: "distB",
|
distB: "distB",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WrapTight extends XmlComponent {
|
export class WrapTight extends XmlComponent {
|
||||||
constructor(distanceFromText?: IDistance) {
|
constructor(
|
||||||
|
margins: IMargins = {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
) {
|
||||||
super("wp:wrapTight");
|
super("wp:wrapTight");
|
||||||
|
|
||||||
distanceFromText = distanceFromText || {
|
|
||||||
distT: 0,
|
|
||||||
distB: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new WrapTightAttributes({
|
new WrapTightAttributes({
|
||||||
distT: distanceFromText.distT,
|
distT: margins.top,
|
||||||
distB: distanceFromText.distB,
|
distB: margins.bottom,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
// http://officeopenxml.com/drwPicFloating-textWrap.php
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
import { IDistance } from "../drawing";
|
|
||||||
|
import { IMargins } from "../floating";
|
||||||
|
|
||||||
interface IWrapTopAndBottomAttributes {
|
interface IWrapTopAndBottomAttributes {
|
||||||
distT?: number;
|
readonly distT?: number;
|
||||||
distB?: number;
|
readonly distB?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrapTopAndBottomAttributes extends XmlAttributeComponent<IWrapTopAndBottomAttributes> {
|
class WrapTopAndBottomAttributes extends XmlAttributeComponent<IWrapTopAndBottomAttributes> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
distT: "distT",
|
distT: "distT",
|
||||||
distB: "distB",
|
distB: "distB",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WrapTopAndBottom extends XmlComponent {
|
export class WrapTopAndBottom extends XmlComponent {
|
||||||
constructor(distanceFromText?: IDistance) {
|
constructor(
|
||||||
|
margins: IMargins = {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
) {
|
||||||
super("wp:wrapTopAndBottom");
|
super("wp:wrapTopAndBottom");
|
||||||
|
|
||||||
distanceFromText = distanceFromText || {
|
|
||||||
distT: 0,
|
|
||||||
distB: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new WrapTopAndBottomAttributes({
|
new WrapTopAndBottomAttributes({
|
||||||
distT: distanceFromText.distT,
|
distT: margins.top,
|
||||||
distB: distanceFromText.distB,
|
distB: margins.bottom,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
11
src/file/file-properties.ts
Normal file
11
src/file/file-properties.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { IDocumentTemplate } from "../import-dotx";
|
||||||
|
|
||||||
|
export interface IFileProperties {
|
||||||
|
readonly template?: IDocumentTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed because of: https://github.com/s-panferov/awesome-typescript-loader/issues/432
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
export const WORKAROUND = "";
|
58
src/file/file.spec.ts
Normal file
58
src/file/file.spec.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
|
import { File } from "./file";
|
||||||
|
|
||||||
|
describe("File", () => {
|
||||||
|
describe("#constructor", () => {
|
||||||
|
it("should create with correct headers", () => {
|
||||||
|
const doc = new File();
|
||||||
|
const header = doc.createHeader();
|
||||||
|
const footer = doc.createFooter();
|
||||||
|
|
||||||
|
doc.addSection({
|
||||||
|
headers: {
|
||||||
|
default: header,
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: footer,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(doc.Document.Body);
|
||||||
|
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("default");
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][5]["w:footerReference"][0]._attr["w:type"]).to.equal("default");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create with correct headers", () => {
|
||||||
|
const doc = new File();
|
||||||
|
const header = doc.createHeader();
|
||||||
|
const footer = doc.createFooter();
|
||||||
|
|
||||||
|
doc.addSection({
|
||||||
|
headers: {
|
||||||
|
default: header,
|
||||||
|
first: header,
|
||||||
|
even: header,
|
||||||
|
},
|
||||||
|
footers: {
|
||||||
|
default: footer,
|
||||||
|
first: footer,
|
||||||
|
even: footer,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(doc.Document.Body);
|
||||||
|
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][4]["w:headerReference"][0]._attr["w:type"]).to.equal("default");
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][5]["w:headerReference"][0]._attr["w:type"]).to.equal("first");
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][6]["w:headerReference"][0]._attr["w:type"]).to.equal("even");
|
||||||
|
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][7]["w:footerReference"][0]._attr["w:type"]).to.equal("default");
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][8]["w:footerReference"][0]._attr["w:type"]).to.equal("first");
|
||||||
|
expect(tree["w:body"][1]["w:sectPr"][9]["w:footerReference"][0]._attr["w:type"]).to.equal("even");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
393
src/file/file.ts
393
src/file/file.ts
@ -2,10 +2,19 @@ import { AppProperties } from "./app-properties/app-properties";
|
|||||||
import { ContentTypes } from "./content-types/content-types";
|
import { ContentTypes } from "./content-types/content-types";
|
||||||
import { CoreProperties, IPropertiesOptions } from "./core-properties";
|
import { CoreProperties, IPropertiesOptions } from "./core-properties";
|
||||||
import { Document } from "./document";
|
import { Document } from "./document";
|
||||||
import { FooterReferenceType, HeaderReference, HeaderReferenceType, SectionPropertiesOptions } from "./document/body/section-properties";
|
import {
|
||||||
import { FooterWrapper } from "./footer-wrapper";
|
FooterReference,
|
||||||
|
FooterReferenceType,
|
||||||
|
HeaderReference,
|
||||||
|
HeaderReferenceType,
|
||||||
|
IHeaderFooterGroup,
|
||||||
|
SectionPropertiesOptions,
|
||||||
|
} from "./document/body/section-properties";
|
||||||
|
import { IDrawingOptions } from "./drawing";
|
||||||
|
import { IFileProperties } from "./file-properties";
|
||||||
|
import { FooterWrapper, IDocumentFooter } from "./footer-wrapper";
|
||||||
import { FootNotes } from "./footnotes";
|
import { FootNotes } from "./footnotes";
|
||||||
import { HeaderWrapper } from "./header-wrapper";
|
import { HeaderWrapper, IDocumentHeader } from "./header-wrapper";
|
||||||
import { Image, Media } from "./media";
|
import { Image, Media } from "./media";
|
||||||
import { Numbering } from "./numbering";
|
import { Numbering } from "./numbering";
|
||||||
import { Bookmark, Hyperlink, Paragraph } from "./paragraph";
|
import { Bookmark, Hyperlink, Paragraph } from "./paragraph";
|
||||||
@ -18,33 +27,53 @@ import { Table } from "./table";
|
|||||||
import { TableOfContents } from "./table-of-contents";
|
import { TableOfContents } from "./table-of-contents";
|
||||||
|
|
||||||
export class File {
|
export class File {
|
||||||
|
// tslint:disable-next-line:readonly-keyword
|
||||||
|
private currentRelationshipId: number = 1;
|
||||||
|
|
||||||
private readonly document: Document;
|
private readonly document: Document;
|
||||||
private styles: Styles;
|
private readonly headers: IDocumentHeader[] = [];
|
||||||
|
private readonly footers: IDocumentFooter[] = [];
|
||||||
|
private readonly docRelationships: Relationships;
|
||||||
private readonly coreProperties: CoreProperties;
|
private readonly coreProperties: CoreProperties;
|
||||||
private readonly numbering: Numbering;
|
private readonly numbering: Numbering;
|
||||||
private readonly media: Media;
|
private readonly media: Media;
|
||||||
private readonly docRelationships: Relationships;
|
|
||||||
private readonly fileRelationships: Relationships;
|
private readonly fileRelationships: Relationships;
|
||||||
private readonly headerWrapper: HeaderWrapper[] = [];
|
|
||||||
private readonly footerWrapper: FooterWrapper[] = [];
|
|
||||||
private readonly footNotes: FootNotes;
|
private readonly footNotes: FootNotes;
|
||||||
private readonly settings: Settings;
|
private readonly settings: Settings;
|
||||||
|
|
||||||
private readonly contentTypes: ContentTypes;
|
private readonly contentTypes: ContentTypes;
|
||||||
private readonly appProperties: AppProperties;
|
private readonly appProperties: AppProperties;
|
||||||
|
// tslint:disable-next-line:readonly-keyword
|
||||||
|
private styles: Styles;
|
||||||
|
|
||||||
private currentRelationshipId: number = 1;
|
constructor(
|
||||||
|
options: IPropertiesOptions = {
|
||||||
|
creator: "Un-named",
|
||||||
|
revision: "1",
|
||||||
|
lastModifiedBy: "Un-named",
|
||||||
|
},
|
||||||
|
sectionPropertiesOptions: SectionPropertiesOptions = {},
|
||||||
|
fileProperties: IFileProperties = {},
|
||||||
|
) {
|
||||||
|
this.coreProperties = new CoreProperties(options);
|
||||||
|
this.numbering = new Numbering();
|
||||||
|
this.docRelationships = new Relationships();
|
||||||
|
this.media = new Media();
|
||||||
|
this.fileRelationships = new Relationships();
|
||||||
|
this.appProperties = new AppProperties();
|
||||||
|
this.footNotes = new FootNotes();
|
||||||
|
this.contentTypes = new ContentTypes();
|
||||||
|
|
||||||
constructor(options?: IPropertiesOptions, sectionPropertiesOptions?: SectionPropertiesOptions) {
|
if (fileProperties.template) {
|
||||||
if (!options) {
|
this.currentRelationshipId = fileProperties.template.currentRelationshipId + 1;
|
||||||
options = {
|
|
||||||
creator: "Un-named",
|
|
||||||
revision: "1",
|
|
||||||
lastModifiedBy: "Un-named",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.externalStyles) {
|
// set up styles
|
||||||
|
if (fileProperties.template && options.externalStyles) {
|
||||||
|
throw Error("can not use both template and external styles");
|
||||||
|
}
|
||||||
|
if (fileProperties.template) {
|
||||||
|
this.styles = fileProperties.template.styles;
|
||||||
|
} else if (options.externalStyles) {
|
||||||
const stylesFactory = new ExternalStylesFactory();
|
const stylesFactory = new ExternalStylesFactory();
|
||||||
this.styles = stylesFactory.newInstance(options.externalStyles);
|
this.styles = stylesFactory.newInstance(options.externalStyles);
|
||||||
} else {
|
} else {
|
||||||
@ -52,62 +81,31 @@ export class File {
|
|||||||
this.styles = stylesFactory.newInstance();
|
this.styles = stylesFactory.newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.coreProperties = new CoreProperties(options);
|
this.addDefaultRelationships();
|
||||||
this.numbering = new Numbering();
|
|
||||||
this.docRelationships = new Relationships();
|
|
||||||
this.docRelationships.createRelationship(
|
|
||||||
this.currentRelationshipId++,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
|
|
||||||
"styles.xml",
|
|
||||||
);
|
|
||||||
this.docRelationships.createRelationship(
|
|
||||||
this.currentRelationshipId++,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
|
|
||||||
"numbering.xml",
|
|
||||||
);
|
|
||||||
this.contentTypes = new ContentTypes();
|
|
||||||
|
|
||||||
this.docRelationships.createRelationship(
|
if (fileProperties.template && fileProperties.template.headers) {
|
||||||
this.currentRelationshipId++,
|
for (const templateHeader of fileProperties.template.headers) {
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
|
this.addHeaderToDocument(templateHeader.header, templateHeader.type);
|
||||||
"footnotes.xml",
|
}
|
||||||
);
|
|
||||||
this.media = new Media();
|
|
||||||
|
|
||||||
const header = this.createHeader();
|
|
||||||
const footer = this.createFooter();
|
|
||||||
|
|
||||||
this.fileRelationships = new Relationships();
|
|
||||||
this.fileRelationships.createRelationship(
|
|
||||||
1,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
|
||||||
"word/document.xml",
|
|
||||||
);
|
|
||||||
this.fileRelationships.createRelationship(
|
|
||||||
2,
|
|
||||||
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
|
|
||||||
"docProps/core.xml",
|
|
||||||
);
|
|
||||||
this.fileRelationships.createRelationship(
|
|
||||||
3,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
|
|
||||||
"docProps/app.xml",
|
|
||||||
);
|
|
||||||
this.appProperties = new AppProperties();
|
|
||||||
|
|
||||||
this.footNotes = new FootNotes();
|
|
||||||
if (!sectionPropertiesOptions) {
|
|
||||||
sectionPropertiesOptions = {
|
|
||||||
footerType: FooterReferenceType.DEFAULT,
|
|
||||||
headerType: HeaderReferenceType.DEFAULT,
|
|
||||||
headerId: header.Header.ReferenceId,
|
|
||||||
footerId: footer.Footer.ReferenceId,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
sectionPropertiesOptions.headerId = header.Header.ReferenceId;
|
this.createHeader();
|
||||||
sectionPropertiesOptions.footerId = footer.Footer.ReferenceId;
|
|
||||||
}
|
}
|
||||||
this.document = new Document(sectionPropertiesOptions);
|
|
||||||
|
if (fileProperties.template && fileProperties.template.footers) {
|
||||||
|
for (const templateFooter of fileProperties.template.footers) {
|
||||||
|
this.addFooterToDocument(templateFooter.footer, templateFooter.type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.createFooter();
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSectionPropertiesOptions = {
|
||||||
|
...sectionPropertiesOptions,
|
||||||
|
headers: this.groupHeaders(this.headers, sectionPropertiesOptions.headers),
|
||||||
|
footers: this.groupFooters(this.footers, sectionPropertiesOptions.footers),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.document = new Document(newSectionPropertiesOptions);
|
||||||
this.settings = new Settings();
|
this.settings = new Settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,8 +113,9 @@ export class File {
|
|||||||
this.document.addTableOfContents(toc);
|
this.document.addTableOfContents(toc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addParagraph(paragraph: Paragraph): void {
|
public addParagraph(paragraph: Paragraph): File {
|
||||||
this.document.addParagraph(paragraph);
|
this.document.addParagraph(paragraph);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createParagraph(text?: string): Paragraph {
|
public createParagraph(text?: string): Paragraph {
|
||||||
@ -136,16 +135,21 @@ export class File {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createImage(buffer: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): Image {
|
public createImage(
|
||||||
const image = Media.addImage(this, buffer, width, height);
|
buffer: Buffer | string | Uint8Array | ArrayBuffer,
|
||||||
|
width?: number,
|
||||||
|
height?: number,
|
||||||
|
drawingOptions?: IDrawingOptions,
|
||||||
|
): Image {
|
||||||
|
const image = Media.addImage(this, buffer, width, height, drawingOptions);
|
||||||
this.document.addParagraph(image.Paragraph);
|
this.document.addParagraph(image.Paragraph);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createHyperlink(link: string, text?: string): Hyperlink {
|
public createHyperlink(link: string, text?: string): Hyperlink {
|
||||||
text = text === undefined ? link : text;
|
const newText = text === undefined ? link : text;
|
||||||
const hyperlink = new Hyperlink(text, this.docRelationships.RelationshipCount);
|
const hyperlink = new Hyperlink(newText, this.docRelationships.RelationshipCount);
|
||||||
this.docRelationships.createRelationship(
|
this.docRelationships.createRelationship(
|
||||||
hyperlink.linkId,
|
hyperlink.linkId,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
||||||
@ -156,16 +160,16 @@ export class File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createInternalHyperLink(anchor: string, text?: string): Hyperlink {
|
public createInternalHyperLink(anchor: string, text?: string): Hyperlink {
|
||||||
text = text === undefined ? anchor : text;
|
const newText = text === undefined ? anchor : text;
|
||||||
const hyperlink = new Hyperlink(text, this.docRelationships.RelationshipCount, anchor);
|
const hyperlink = new Hyperlink(newText, this.docRelationships.RelationshipCount, anchor);
|
||||||
// NOTE: unlike File#createHyperlink(), since the link is to an internal bookmark
|
// NOTE: unlike File#createHyperlink(), since the link is to an internal bookmark
|
||||||
// we don't need to create a new relationship.
|
// we don't need to create a new relationship.
|
||||||
return hyperlink;
|
return hyperlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createBookmark(name: string, text?: string): Bookmark {
|
public createBookmark(name: string, text?: string): Bookmark {
|
||||||
text = text === undefined ? name : text;
|
const newText = text === undefined ? name : text;
|
||||||
const bookmark = new Bookmark(name, text, this.docRelationships.RelationshipCount);
|
const bookmark = new Bookmark(name, newText, this.docRelationships.RelationshipCount);
|
||||||
return bookmark;
|
return bookmark;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,25 +183,13 @@ export class File {
|
|||||||
|
|
||||||
public createHeader(): HeaderWrapper {
|
public createHeader(): HeaderWrapper {
|
||||||
const header = new HeaderWrapper(this.media, this.currentRelationshipId++);
|
const header = new HeaderWrapper(this.media, this.currentRelationshipId++);
|
||||||
this.headerWrapper.push(header);
|
this.addHeaderToDocument(header);
|
||||||
this.docRelationships.createRelationship(
|
|
||||||
header.Header.ReferenceId,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
|
|
||||||
`header${this.headerWrapper.length}.xml`,
|
|
||||||
);
|
|
||||||
this.contentTypes.addHeader(this.headerWrapper.length);
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createFooter(): FooterWrapper {
|
public createFooter(): FooterWrapper {
|
||||||
const footer = new FooterWrapper(this.media, this.currentRelationshipId++);
|
const footer = new FooterWrapper(this.media, this.currentRelationshipId++);
|
||||||
this.footerWrapper.push(footer);
|
this.addFooterToDocument(footer);
|
||||||
this.docRelationships.createRelationship(
|
|
||||||
footer.Footer.ReferenceId,
|
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
|
|
||||||
`footer${this.footerWrapper.length}.xml`,
|
|
||||||
);
|
|
||||||
this.contentTypes.addFooter(this.footerWrapper.length);
|
|
||||||
return footer;
|
return footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +206,191 @@ export class File {
|
|||||||
return headerWrapper;
|
return headerWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createEvenPageHeader(): HeaderWrapper {
|
||||||
|
const headerWrapper = this.createHeader();
|
||||||
|
|
||||||
|
this.document.Body.DefaultSection.addChildElement(
|
||||||
|
new HeaderReference({
|
||||||
|
headerType: HeaderReferenceType.EVEN,
|
||||||
|
headerId: headerWrapper.Header.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return headerWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createFirstPageFooter(): FooterWrapper {
|
||||||
|
const footerWrapper = this.createFooter();
|
||||||
|
|
||||||
|
this.document.Body.DefaultSection.addChildElement(
|
||||||
|
new FooterReference({
|
||||||
|
footerType: FooterReferenceType.FIRST,
|
||||||
|
footerId: footerWrapper.Footer.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return footerWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEvenPageFooter(): FooterWrapper {
|
||||||
|
const footerWrapper = this.createFooter();
|
||||||
|
|
||||||
|
this.document.Body.DefaultSection.addChildElement(
|
||||||
|
new FooterReference({
|
||||||
|
footerType: FooterReferenceType.EVEN,
|
||||||
|
footerId: footerWrapper.Footer.ReferenceId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return footerWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFooterByReferenceNumber(refId: number): FooterWrapper {
|
||||||
|
const entry = this.footers.map((item) => item.footer).find((h) => h.Footer.ReferenceId === refId);
|
||||||
|
if (entry) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
throw new Error(`There is no footer with given reference id ${refId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeaderByReferenceNumber(refId: number): HeaderWrapper {
|
||||||
|
const entry = this.headers.map((item) => item.header).find((h) => h.Header.ReferenceId === refId);
|
||||||
|
if (entry) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
throw new Error(`There is no header with given reference id ${refId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public verifyUpdateFields(): void {
|
||||||
|
if (this.document.getTablesOfContents().length) {
|
||||||
|
this.settings.addUpdateFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addHeaderToDocument(header: HeaderWrapper, type: HeaderReferenceType = HeaderReferenceType.DEFAULT): void {
|
||||||
|
this.headers.push({ header, type });
|
||||||
|
this.docRelationships.createRelationship(
|
||||||
|
header.Header.ReferenceId,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
|
||||||
|
`header${this.headers.length}.xml`,
|
||||||
|
);
|
||||||
|
this.contentTypes.addHeader(this.headers.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFooterToDocument(footer: FooterWrapper, type: FooterReferenceType = FooterReferenceType.DEFAULT): void {
|
||||||
|
this.footers.push({ footer, type });
|
||||||
|
this.docRelationships.createRelationship(
|
||||||
|
footer.Footer.ReferenceId,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
|
||||||
|
`footer${this.footers.length}.xml`,
|
||||||
|
);
|
||||||
|
this.contentTypes.addFooter(this.footers.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addDefaultRelationships(): void {
|
||||||
|
this.fileRelationships.createRelationship(
|
||||||
|
1,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
||||||
|
"word/document.xml",
|
||||||
|
);
|
||||||
|
this.fileRelationships.createRelationship(
|
||||||
|
2,
|
||||||
|
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
|
||||||
|
"docProps/core.xml",
|
||||||
|
);
|
||||||
|
this.fileRelationships.createRelationship(
|
||||||
|
3,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
|
||||||
|
"docProps/app.xml",
|
||||||
|
);
|
||||||
|
|
||||||
|
this.docRelationships.createRelationship(
|
||||||
|
this.currentRelationshipId++,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
|
||||||
|
"styles.xml",
|
||||||
|
);
|
||||||
|
this.docRelationships.createRelationship(
|
||||||
|
this.currentRelationshipId++,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
|
||||||
|
"numbering.xml",
|
||||||
|
);
|
||||||
|
this.docRelationships.createRelationship(
|
||||||
|
this.currentRelationshipId++,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
|
||||||
|
"footnotes.xml",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private groupHeaders(headers: IDocumentHeader[], group: IHeaderFooterGroup<HeaderWrapper> = {}): IHeaderFooterGroup<HeaderWrapper> {
|
||||||
|
let newGroup = group;
|
||||||
|
|
||||||
|
for (const header of headers) {
|
||||||
|
switch (header.type) {
|
||||||
|
case HeaderReferenceType.DEFAULT:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
default: header.header,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case HeaderReferenceType.FIRST:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
first: header.header,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case HeaderReferenceType.EVEN:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
even: header.header,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
default: header.header,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private groupFooters(footers: IDocumentFooter[], group: IHeaderFooterGroup<FooterWrapper> = {}): IHeaderFooterGroup<FooterWrapper> {
|
||||||
|
let newGroup = group;
|
||||||
|
|
||||||
|
for (const footer of footers) {
|
||||||
|
switch (footer.type) {
|
||||||
|
case FooterReferenceType.DEFAULT:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
default: footer.footer,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case FooterReferenceType.FIRST:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
first: footer.footer,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case FooterReferenceType.EVEN:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
even: footer.footer,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newGroup = {
|
||||||
|
...newGroup,
|
||||||
|
default: footer.footer,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newGroup;
|
||||||
|
}
|
||||||
|
|
||||||
public get Document(): Document {
|
public get Document(): Document {
|
||||||
return this.document;
|
return this.document;
|
||||||
}
|
}
|
||||||
@ -247,35 +424,19 @@ export class File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get Header(): HeaderWrapper {
|
public get Header(): HeaderWrapper {
|
||||||
return this.headerWrapper[0];
|
return this.headers[0].header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get Headers(): HeaderWrapper[] {
|
public get Headers(): HeaderWrapper[] {
|
||||||
return this.headerWrapper;
|
return this.headers.map((item) => item.header);
|
||||||
}
|
|
||||||
|
|
||||||
public HeaderByRefNumber(refId: number): HeaderWrapper {
|
|
||||||
const entry = this.headerWrapper.find((h) => h.Header.ReferenceId === refId);
|
|
||||||
if (entry) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
throw new Error(`There is no header with given reference id ${refId}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get Footer(): FooterWrapper {
|
public get Footer(): FooterWrapper {
|
||||||
return this.footerWrapper[0];
|
return this.footers[0].footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get Footers(): FooterWrapper[] {
|
public get Footers(): FooterWrapper[] {
|
||||||
return this.footerWrapper;
|
return this.footers.map((item) => item.footer);
|
||||||
}
|
|
||||||
|
|
||||||
public FooterByRefNumber(refId: number): FooterWrapper {
|
|
||||||
const entry = this.footerWrapper.find((h) => h.Footer.ReferenceId === refId);
|
|
||||||
if (entry) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
throw new Error(`There is no footer with given reference id ${refId}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get ContentTypes(): ContentTypes {
|
public get ContentTypes(): ContentTypes {
|
||||||
@ -293,10 +454,4 @@ export class File {
|
|||||||
public get Settings(): Settings {
|
public get Settings(): Settings {
|
||||||
return this.settings;
|
return this.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public verifyUpdateFields(): void {
|
|
||||||
if (this.document.getTablesOfContents().length) {
|
|
||||||
this.settings.addUpdateFields();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
import { FooterReferenceType } from "./document";
|
||||||
import { Footer } from "./footer/footer";
|
import { Footer } from "./footer/footer";
|
||||||
import { Image, Media } from "./media";
|
import { Image, IMediaData, Media } from "./media";
|
||||||
import { ImageParagraph, Paragraph } from "./paragraph";
|
import { ImageParagraph, Paragraph } from "./paragraph";
|
||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
import { Table } from "./table";
|
import { Table } from "./table";
|
||||||
|
|
||||||
|
export interface IDocumentFooter {
|
||||||
|
readonly footer: FooterWrapper;
|
||||||
|
readonly type: FooterReferenceType;
|
||||||
|
}
|
||||||
|
|
||||||
export class FooterWrapper {
|
export class FooterWrapper {
|
||||||
private readonly footer: Footer;
|
private readonly footer: Footer;
|
||||||
private readonly relationships: Relationships;
|
private readonly relationships: Relationships;
|
||||||
|
|
||||||
constructor(private readonly media: Media, referenceId: number) {
|
constructor(private readonly media: Media, referenceId: number, initContent?: XmlComponent) {
|
||||||
this.footer = new Footer(referenceId);
|
this.footer = new Footer(referenceId, initContent);
|
||||||
this.relationships = new Relationships();
|
this.relationships = new Relationships();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,17 +39,33 @@ export class FooterWrapper {
|
|||||||
return this.footer.createTable(rows, cols);
|
return this.footer.createTable(rows, cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addChildElement(childElement: XmlComponent | string): void {
|
public addChildElement(childElement: XmlComponent): void {
|
||||||
this.footer.addChildElement(childElement);
|
this.footer.addChildElement(childElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public createImage(image: Buffer, width?: number, height?: number): void {
|
public addImageRelationship(image: Buffer, refId: number, width?: number, height?: number): IMediaData {
|
||||||
const mediaData = this.media.addMedia(image, this.relationships.RelationshipCount, width, height);
|
const mediaData = this.media.addMedia(image, refId, width, height);
|
||||||
this.relationships.createRelationship(
|
this.relationships.createRelationship(
|
||||||
mediaData.referenceId,
|
mediaData.referenceId,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
||||||
`media/${mediaData.fileName}`,
|
`media/${mediaData.fileName}`,
|
||||||
);
|
);
|
||||||
|
return mediaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addHyperlinkRelationship(target: string, refId: number, targetMode?: "External" | undefined): void {
|
||||||
|
this.relationships.createRelationship(
|
||||||
|
refId,
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
||||||
|
target,
|
||||||
|
targetMode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createImage(image: Buffer | string | Uint8Array | ArrayBuffer, width?: number, height?: number): void {
|
||||||
|
// TODO
|
||||||
|
// tslint:disable-next-line:no-any
|
||||||
|
const mediaData = this.addImageRelationship(image as any, this.relationships.RelationshipCount, width, height);
|
||||||
this.addImage(new Image(new ImageParagraph(mediaData)));
|
this.addImage(new Image(new ImageParagraph(mediaData)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +81,8 @@ export class FooterWrapper {
|
|||||||
public get Relationships(): Relationships {
|
public get Relationships(): Relationships {
|
||||||
return this.relationships;
|
return this.relationships;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get Media(): Media {
|
||||||
|
return this.media;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IFooterAttributesProperties {
|
export interface IFooterAttributesProperties {
|
||||||
wpc?: string;
|
readonly wpc?: string;
|
||||||
mc?: string;
|
readonly mc?: string;
|
||||||
o?: string;
|
readonly o?: string;
|
||||||
r?: string;
|
readonly r?: string;
|
||||||
m?: string;
|
readonly m?: string;
|
||||||
v?: string;
|
readonly v?: string;
|
||||||
wp14?: string;
|
readonly wp14?: string;
|
||||||
wp?: string;
|
readonly wp?: string;
|
||||||
w10?: string;
|
readonly w10?: string;
|
||||||
w?: string;
|
readonly w?: string;
|
||||||
w14?: string;
|
readonly w14?: string;
|
||||||
w15?: string;
|
readonly w15?: string;
|
||||||
wpg?: string;
|
readonly wpg?: string;
|
||||||
wpi?: string;
|
readonly wpi?: string;
|
||||||
wne?: string;
|
readonly wne?: string;
|
||||||
wps?: string;
|
readonly wps?: string;
|
||||||
cp?: string;
|
readonly cp?: string;
|
||||||
dc?: string;
|
readonly dc?: string;
|
||||||
dcterms?: string;
|
readonly dcterms?: string;
|
||||||
dcmitype?: string;
|
readonly dcmitype?: string;
|
||||||
xsi?: string;
|
readonly xsi?: string;
|
||||||
type?: string;
|
readonly type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FooterAttributes extends XmlAttributeComponent<IFooterAttributesProperties> {
|
export class FooterAttributes extends XmlAttributeComponent<IFooterAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
wpc: "xmlns:wpc",
|
wpc: "xmlns:wpc",
|
||||||
mc: "xmlns:mc",
|
mc: "xmlns:mc",
|
||||||
o: "xmlns:o",
|
o: "xmlns:o",
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// http://officeopenxml.com/WPfooters.php
|
// http://officeopenxml.com/WPfooters.php
|
||||||
import { XmlComponent } from "file/xml-components";
|
import { InitializableXmlComponent, XmlComponent } from "file/xml-components";
|
||||||
import { Paragraph } from "../paragraph";
|
import { Paragraph } from "../paragraph";
|
||||||
import { Table } from "../table";
|
import { Table } from "../table";
|
||||||
import { FooterAttributes } from "./footer-attributes";
|
import { FooterAttributes } from "./footer-attributes";
|
||||||
|
|
||||||
export class Footer extends XmlComponent {
|
export class Footer extends InitializableXmlComponent {
|
||||||
private readonly refId: number;
|
private readonly refId: number;
|
||||||
|
|
||||||
constructor(referenceNumber: number) {
|
constructor(referenceNumber: number, initContent?: XmlComponent) {
|
||||||
super("w:ftr");
|
super("w:ftr", initContent);
|
||||||
this.refId = referenceNumber;
|
this.refId = referenceNumber;
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new FooterAttributes({
|
new FooterAttributes({
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IFootnoteAttributesProperties {
|
export interface IFootnoteAttributesProperties {
|
||||||
type?: string;
|
readonly type?: string;
|
||||||
id: number;
|
readonly id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FootnoteAttributes extends XmlAttributeComponent<IFootnoteAttributesProperties> {
|
export class FootnoteAttributes extends XmlAttributeComponent<IFootnoteAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
type: "w:type",
|
type: "w:type",
|
||||||
id: "w:id",
|
id: "w:id",
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import { Formatter } from "../../../export/formatter";
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { Footnote, FootnoteType } from "./footnote";
|
import { Footnote, FootnoteType } from "./footnote";
|
||||||
|
|
||||||
describe("Footnote", () => {
|
describe("Footnote", () => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import { Paragraph } from "file/paragraph";
|
||||||
import { XmlComponent } from "file/xml-components";
|
import { XmlComponent } from "file/xml-components";
|
||||||
import { Paragraph } from "../../paragraph";
|
|
||||||
import { FootnoteAttributes } from "./footnote-attributes";
|
import { FootnoteAttributes } from "./footnote-attributes";
|
||||||
import { FootnoteRefRun } from "./run/footnote-ref-run";
|
import { FootnoteRefRun } from "./run/footnote-ref-run";
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ import { Style } from "file/paragraph/run/style";
|
|||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IFootNoteReferenceRunAttributesProperties {
|
export interface IFootNoteReferenceRunAttributesProperties {
|
||||||
id: number;
|
readonly id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FootNoteReferenceRunAttributes extends XmlAttributeComponent<IFootNoteReferenceRunAttributesProperties> {
|
export class FootNoteReferenceRunAttributes extends XmlAttributeComponent<IFootNoteReferenceRunAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
id: "w:id",
|
id: "w:id",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
import { XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
export interface IFootnotesAttributesProperties {
|
export interface IFootnotesAttributesProperties {
|
||||||
wpc?: string;
|
readonly wpc?: string;
|
||||||
mc?: string;
|
readonly mc?: string;
|
||||||
o?: string;
|
readonly o?: string;
|
||||||
r?: string;
|
readonly r?: string;
|
||||||
m?: string;
|
readonly m?: string;
|
||||||
v?: string;
|
readonly v?: string;
|
||||||
wp14?: string;
|
readonly wp14?: string;
|
||||||
wp?: string;
|
readonly wp?: string;
|
||||||
w10?: string;
|
readonly w10?: string;
|
||||||
w?: string;
|
readonly w?: string;
|
||||||
w14?: string;
|
readonly w14?: string;
|
||||||
w15?: string;
|
readonly w15?: string;
|
||||||
wpg?: string;
|
readonly wpg?: string;
|
||||||
wpi?: string;
|
readonly wpi?: string;
|
||||||
wne?: string;
|
readonly wne?: string;
|
||||||
wps?: string;
|
readonly wps?: string;
|
||||||
Ignorable?: string;
|
readonly Ignorable?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FootnotesAttributes extends XmlAttributeComponent<IFootnotesAttributesProperties> {
|
export class FootnotesAttributes extends XmlAttributeComponent<IFootnotesAttributesProperties> {
|
||||||
protected xmlKeys = {
|
protected readonly xmlKeys = {
|
||||||
wpc: "xmlns:wpc",
|
wpc: "xmlns:wpc",
|
||||||
mc: "xmlns:mc",
|
mc: "xmlns:mc",
|
||||||
o: "xmlns:o",
|
o: "xmlns:o",
|
||||||
|
@ -6,12 +6,13 @@ import { SeperatorRun } from "./footnote/run/seperator-run";
|
|||||||
import { FootnotesAttributes } from "./footnotes-attributes";
|
import { FootnotesAttributes } from "./footnotes-attributes";
|
||||||
|
|
||||||
export class FootNotes extends XmlComponent {
|
export class FootNotes extends XmlComponent {
|
||||||
private counter: number;
|
// tslint:disable-next-line:readonly-keyword
|
||||||
|
private currentId: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super("w:footnotes");
|
super("w:footnotes");
|
||||||
|
|
||||||
this.counter = 1;
|
this.currentId = 1;
|
||||||
|
|
||||||
this.root.push(
|
this.root.push(
|
||||||
new FootnotesAttributes({
|
new FootnotesAttributes({
|
||||||
@ -61,10 +62,10 @@ export class FootNotes extends XmlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createFootNote(paragraph: Paragraph): void {
|
public createFootNote(paragraph: Paragraph): void {
|
||||||
const footnote = new Footnote(this.counter);
|
const footnote = new Footnote(this.currentId);
|
||||||
footnote.addParagraph(paragraph);
|
footnote.addParagraph(paragraph);
|
||||||
this.root.push(footnote);
|
this.root.push(footnote);
|
||||||
|
|
||||||
this.counter++;
|
this.currentId++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user