Compare commits
392 Commits
Author | SHA1 | Date | |
---|---|---|---|
1b758b73e6 | |||
65a0e97c97 | |||
3c33931d99 | |||
e475779ba5 | |||
9fb77d9cee | |||
f315909dc0 | |||
fa9ffec601 | |||
636d114d44 | |||
2140ed63cd | |||
8d0f7d58bf | |||
3c48822cec | |||
547c05b05d | |||
e5ba625820 | |||
45e644ac43 | |||
9b14b9c925 | |||
0bc55208ec | |||
285eb0a85d | |||
d521e20c0e | |||
439f8ff4bc | |||
18791c99f5 | |||
9991700701 | |||
01bc6093dd | |||
5c08b889b1 | |||
7944a7064e | |||
1713358f0c | |||
b6465e15de | |||
5ca97ce96f | |||
5609b11188 | |||
eec084767f | |||
3a795401d1 | |||
23fd3b483f | |||
a2566e92d2 | |||
bf884c8d13 | |||
dae2898496 | |||
9555ddd648 | |||
755895ebef | |||
4283a6c7d9 | |||
dd7439b45c | |||
b4c7ed2347 | |||
9354b99897 | |||
a1fbbde149 | |||
607087d256 | |||
7d50194cbf | |||
ab5c5c0fb7 | |||
bc1bca762e | |||
75290aeaf5 | |||
996594da9b | |||
5018134e35 | |||
da9ebbdb9a | |||
eb5a4f9620 | |||
64cec50b84 | |||
ce2a949176 | |||
ff7756f8c5 | |||
4221b9085a | |||
76e7f40bd2 | |||
dc2f9c3bdc | |||
8eb5d6281e | |||
6d09355174 | |||
4e3a2fd90f | |||
463c282568 | |||
8c0ff0422a | |||
0fe1765b7f | |||
4accf65802 | |||
c6eb11d535 | |||
58cfb427e9 | |||
90bb670de6 | |||
727e741b08 | |||
41f516d64b | |||
366cd2b4b1 | |||
243d73542f | |||
44520bc54b | |||
831ef9a98c | |||
bef9ea28f2 | |||
7fa94b6996 | |||
c1cc211c7f | |||
9efee181ba | |||
631f561441 | |||
94592de477 | |||
ac204a5189 | |||
e48ca53660 | |||
5c2d4f729a | |||
03d6636262 | |||
74b3267294 | |||
83af11aa1b | |||
8cf9b83068 | |||
5dab97241e | |||
3b7394fe74 | |||
31c6f0a8ca | |||
890983c1e1 | |||
e8db8ec669 | |||
dcbe542fb2 | |||
ca695ad122 | |||
60bd9a84dd | |||
ecc3b2ef3f | |||
3e8d816614 | |||
dde54082d5 | |||
6845cd433f | |||
046ef0330a | |||
fcd0427fe4 | |||
4c4e253883 | |||
3a9f09b578 | |||
e9aea8b8a9 | |||
5c9b5e4322 | |||
33d6544aba | |||
3f257bf5a4 | |||
1ff31a2a42 | |||
14013273af | |||
b34127665c | |||
0fcd02aea8 | |||
d773148218 | |||
d52bf7b57d | |||
f378c37b62 | |||
d773972877 | |||
738b36b6a9 | |||
ad7ef22b63 | |||
e73e1f98f9 | |||
738e374bf2 | |||
c5861129c9 | |||
5f4c595a1a | |||
238b8b9a8d | |||
a92f3a7ba1 | |||
2a1685ab82 | |||
0088d58fea | |||
cbf4f828ab | |||
2ccf27162e | |||
5dffda8c7c | |||
e1c777738b | |||
0f531b2a9b | |||
d523b2dae7 | |||
f50c7f20cb | |||
f21fb06467 | |||
2fd4f064ae | |||
36a18c5af3 | |||
75587df420 | |||
43ea0bd406 | |||
ec2ad99e95 | |||
46deaa5a4a | |||
697baa3fd6 | |||
15829b53a6 | |||
56f1e4408a | |||
689d4d07bc | |||
b0049d8221 | |||
152a11d7fc | |||
31171330a2 | |||
3c0032cf68 | |||
0e44af1c06 | |||
39893a984c | |||
b75e194993 | |||
9fb58a5852 | |||
5c578a6bea | |||
3ba197a289 | |||
bbf50c34a0 | |||
6b6f2214f6 | |||
836ffd683f | |||
6c94a1382c | |||
c13cac899a | |||
ec1f9d5ecf | |||
a8115ff964 | |||
da744cbdec | |||
439ab8441e | |||
15b14579e6 | |||
1cb666fd03 | |||
bde4aa4657 | |||
709876a02d | |||
a0b74f24e3 | |||
ed15614023 | |||
c3e97a0aab | |||
b69968a99c | |||
82b12a99b9 | |||
1486519a98 | |||
7e194350d8 | |||
855c47954e | |||
dd3300506b | |||
154c7cb54b | |||
cd75c2e860 | |||
1b0f19d570 | |||
45026eb30e | |||
aeddcc7478 | |||
f88b588b60 | |||
f00844ad1b | |||
8e87437272 | |||
49b011280c | |||
37b94eeedc | |||
4053b5bbc2 | |||
46972a861d | |||
528dab5c10 | |||
d1ffc0bffa | |||
3741dd7ef2 | |||
c6c4b0cbcd | |||
804380f70e | |||
118f60f704 | |||
d556f97dbe | |||
b116b0a268 | |||
99f0297c4f | |||
4543016869 | |||
2b9c15a638 | |||
4ca5ea6046 | |||
2de55a1eb3 | |||
db20efa95b | |||
3822d8139d | |||
3a65f383e4 | |||
d05fef6b93 | |||
f02b6211a3 | |||
4b4f67f9c7 | |||
9f38e33a48 | |||
69ca5d8b0c | |||
809474e9c5 | |||
e5b56c4214 | |||
568a27367a | |||
c6f99fcbe5 | |||
309abbcc47 | |||
de145e0623 | |||
7f24abd104 | |||
edafbdb1ff | |||
034cd187ab | |||
8f04e0da4a | |||
90b8b8140b | |||
0b28bf02c4 | |||
2b169fc63a | |||
e2bb50d6ad | |||
730e33b164 | |||
6603aafa38 | |||
05a6ab77cc | |||
5a52541136 | |||
e4709a7f8d | |||
60b7ce4785 | |||
fd4afea9aa | |||
04d88fa592 | |||
87000d8656 | |||
776132ede0 | |||
b845e4daee | |||
da61a30eb8 | |||
3a02bc087c | |||
b05748da25 | |||
63cea76eac | |||
e198f0752a | |||
22e62ed950 | |||
c3e92c0709 | |||
d0036e64b5 | |||
7bfe8f26f0 | |||
4274c7674c | |||
8505e04e58 | |||
4466145d00 | |||
ce2a0fb864 | |||
a56119e7cd | |||
56eecef1a8 | |||
097c6a5962 | |||
ee105cdb83 | |||
7891402c72 | |||
bde13193d5 | |||
449e1ed963 | |||
dd6d1bc039 | |||
528be93191 | |||
1ea6017483 | |||
08bd2744b6 | |||
54ab55b92c | |||
5155cdaf45 | |||
496fcb55fa | |||
fcc393aca2 | |||
2611e0c74f | |||
acc23be297 | |||
bdc0aa26ea | |||
ff14fcae3a | |||
37d099b457 | |||
0344eb8e27 | |||
403e7a4228 | |||
aa336dc652 | |||
d8fca42eb7 | |||
10d1d15f73 | |||
ac55e0fcb3 | |||
780682a8f7 | |||
b627f0982a | |||
798cbb8628 | |||
15f79abf5e | |||
f5e35603ef | |||
06da596ffb | |||
4593464a15 | |||
30912e7aaf | |||
56b18d3793 | |||
d0a675fde6 | |||
45130bed0b | |||
faefb0d2a8 | |||
c4b7a7094b | |||
d527013451 | |||
bb8ac8b9d8 | |||
cdc97adaeb | |||
72f0ad9fdb | |||
0f55d70a19 | |||
6ac0375400 | |||
9048f8f271 | |||
23eaff2dab | |||
df4a381135 | |||
41dcf363b4 | |||
f143c017cb | |||
7463c0301f | |||
bb24c50bf4 | |||
70538a8062 | |||
085db9350c | |||
eabdefdaf4 | |||
9fc8e50691 | |||
dfc01f2d5a | |||
4e8aec9a0e | |||
c7e0554817 | |||
d77d59836f | |||
a035f4f411 | |||
53b1bba103 | |||
605536ce68 | |||
a9e4c88804 | |||
79c1db9c91 | |||
3b757ad4c8 | |||
ee07ff8282 | |||
85583a3dbd | |||
46daacfbc8 | |||
7acd9e1fde | |||
97e3f8bc78 | |||
ff378d6667 | |||
9930476f64 | |||
3e5223dd5d | |||
e3bb8258e5 | |||
77301a401e | |||
a09882b566 | |||
e72453c19a | |||
bd159b280f | |||
4d3d971a12 | |||
def503c53e | |||
74afae1850 | |||
7db166b19c | |||
0271e4ad40 | |||
2b010dbfec | |||
a8f38a3d01 | |||
bd69779a12 | |||
571ba2e2c3 | |||
7a25165046 | |||
977fdbb9eb | |||
2f05186730 | |||
38695c3c4b | |||
f2152b3da1 | |||
51dc538cdd | |||
c76bb2859a | |||
0b6f040bba | |||
149908ea62 | |||
98f745a3f7 | |||
9b840c0d63 | |||
0085b1d128 | |||
c3ddd576e2 | |||
cf237bcc10 | |||
c6ce7fe3a3 | |||
712e612ab1 | |||
161038cc75 | |||
24aee70b67 | |||
b486bcf372 | |||
97147bc3d7 | |||
6a0b01e05c | |||
e60d9cbbce | |||
594045644b | |||
e36022d044 | |||
2b0acc2980 | |||
2058f72c2e | |||
0788b10106 | |||
7b431e50bc | |||
633487ca16 | |||
43d1f40baa | |||
aec7f09031 | |||
790dfa320e | |||
260482d9d4 | |||
b699481ae3 | |||
0f7260c152 | |||
d43d742875 | |||
fceefcf290 | |||
488711dae0 | |||
901847db3e | |||
dd7a83753b | |||
04d2b01e16 | |||
ca9f1c9af4 | |||
eed7cb9537 | |||
ec54c7f762 | |||
c7b69a3ff5 | |||
6892c7aa6c | |||
09ec3e682f | |||
e3ac9bc9bf | |||
958045e5c7 | |||
0f6f7b8a15 | |||
401e4851e1 | |||
abc7c8dc72 | |||
7a0cc2f2e7 | |||
b374dc0fac | |||
ed409ac1b7 | |||
4842630e09 | |||
d29286ab6d | |||
ebaf0dfbf0 | |||
72389e25a1 | |||
799bdcc2f0 |
40
.github/dependabot.yml
vendored
Normal file
40
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: npm
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
ignore:
|
||||||
|
- dependency-name: "@types/node"
|
||||||
|
versions:
|
||||||
|
- 14.14.22
|
||||||
|
- 14.14.24
|
||||||
|
- 14.14.25
|
||||||
|
- 14.14.26
|
||||||
|
- 14.14.28
|
||||||
|
- 14.14.29
|
||||||
|
- 14.14.30
|
||||||
|
- 15.0.0
|
||||||
|
- dependency-name: webpack
|
||||||
|
versions:
|
||||||
|
- 5.31.2
|
||||||
|
- 5.35.0
|
||||||
|
- dependency-name: ts-loader
|
||||||
|
versions:
|
||||||
|
- 9.1.0
|
||||||
|
- dependency-name: awesome-typescript-loader
|
||||||
|
versions:
|
||||||
|
- 5.2.1
|
||||||
|
- dependency-name: chai
|
||||||
|
versions:
|
||||||
|
- 4.2.0
|
||||||
|
- 4.3.0
|
||||||
|
- 4.3.1
|
||||||
|
- 4.3.3
|
||||||
|
- dependency-name: replace-in-file
|
||||||
|
versions:
|
||||||
|
- 6.1.0
|
||||||
|
- dependency-name: "@types/chai"
|
||||||
|
versions:
|
||||||
|
- 4.2.14
|
5
.github/workflows/default.yml
vendored
5
.github/workflows/default.yml
vendored
@ -33,6 +33,11 @@ jobs:
|
|||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test.coverage
|
run: npm run test.coverage
|
||||||
|
- name: Codecov
|
||||||
|
uses: codecov/codecov-action@v1
|
||||||
|
with:
|
||||||
|
fail_ci_if_error: true
|
||||||
|
verbose: true
|
||||||
lint:
|
lint:
|
||||||
name: Lint
|
name: Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
26
.github/workflows/remove-old-artifacts.yml
vendored
Normal file
26
.github/workflows/remove-old-artifacts.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: Remove old artifacts
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Every day at 1am
|
||||||
|
- cron: "0 1 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
logLevel:
|
||||||
|
description: "Log level"
|
||||||
|
required: true
|
||||||
|
default: "warning"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
remove-old-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Remove old artifacts
|
||||||
|
uses: c-hive/gha-remove-artifacts@v1
|
||||||
|
with:
|
||||||
|
age: "1 week"
|
||||||
|
# Optional inputs
|
||||||
|
# skip-tags: true
|
||||||
|
# skip-recent: 5
|
9
.nycrc
9
.nycrc
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"check-coverage": true,
|
"check-coverage": true,
|
||||||
"lines": 98.86,
|
"lines": 99.31,
|
||||||
"functions": 97.86,
|
"functions": 99.09,
|
||||||
"branches": 95.86,
|
"branches": 96.17,
|
||||||
"statements": 98.86,
|
"statements": 99.31,
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts"
|
"src/**/*.ts"
|
||||||
],
|
],
|
||||||
@ -21,6 +21,5 @@
|
|||||||
],
|
],
|
||||||
"cache": true,
|
"cache": true,
|
||||||
"all": true,
|
"all": true,
|
||||||
"instrument": false,
|
|
||||||
"sourceMap": true
|
"sourceMap": true
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
TabStopPosition,
|
TabStopPosition,
|
||||||
UnderlineType,
|
UnderlineType,
|
||||||
|
LevelFormat,
|
||||||
} from "../build";
|
} from "../build";
|
||||||
|
|
||||||
const table = new Table({
|
const table = new Table({
|
||||||
@ -51,6 +52,19 @@ const table = new Table({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
|
numbering:{
|
||||||
|
config:[{
|
||||||
|
reference: 'ref1',
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: LevelFormat.DECIMAL,
|
||||||
|
text: '%1)',
|
||||||
|
start: 50,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}]
|
||||||
|
},
|
||||||
styles: {
|
styles: {
|
||||||
default: {
|
default: {
|
||||||
heading1: {
|
heading1: {
|
||||||
@ -155,6 +169,28 @@ const doc = new Document({
|
|||||||
spacing: { line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 },
|
spacing: { line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "numberedPara",
|
||||||
|
name: "Numbered Para",
|
||||||
|
basedOn: "Normal",
|
||||||
|
next: "Normal",
|
||||||
|
quickFormat: true,
|
||||||
|
run: {
|
||||||
|
font: "Calibri",
|
||||||
|
size: 26,
|
||||||
|
bold: true,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
spacing: { line: 276, before: 20 * 72 * 0.1, after: 20 * 72 * 0.05 },
|
||||||
|
rightTabStop: TabStopPosition.MAX,
|
||||||
|
leftTabStop: 453.543307087,
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref1',
|
||||||
|
instance: 0,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
sections: [
|
sections: [
|
||||||
@ -260,6 +296,14 @@ const doc = new Document({
|
|||||||
text: "Test 2",
|
text: "Test 2",
|
||||||
style: "normalPara2",
|
style: "normalPara2",
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "Numbered paragraph that has numbering attached to custom styles",
|
||||||
|
style: "numberedPara",
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "Numbered para would show up in the styles pane at Word",
|
||||||
|
style: "numberedPara",
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Multiple sections and headers
|
// Multiple sections and headers
|
||||||
// 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, Footer, Header, Packer, PageNumber, PageNumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
|
import { Document, Footer, Header, Packer, PageNumber, NumberFormat, PageOrientation, Paragraph, TextRun } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [
|
sections: [
|
||||||
@ -13,7 +13,7 @@ const doc = new Document({
|
|||||||
page: {
|
page: {
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 1,
|
start: 1,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -38,7 +38,7 @@ const doc = new Document({
|
|||||||
},
|
},
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 1,
|
start: 1,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -85,7 +85,7 @@ const doc = new Document({
|
|||||||
orientation: PageOrientation.PORTRAIT,
|
orientation: PageOrientation.PORTRAIT,
|
||||||
},
|
},
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
formatType: PageNumberFormat.UPPER_ROMAN,
|
formatType: NumberFormat.UPPER_ROMAN,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -116,7 +116,7 @@ const doc = new Document({
|
|||||||
},
|
},
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 25,
|
start: 25,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -24,7 +24,7 @@ const doc = new Document({
|
|||||||
size: 28,
|
size: 28,
|
||||||
bold: true,
|
bold: true,
|
||||||
italics: true,
|
italics: true,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
paragraph: {
|
paragraph: {
|
||||||
spacing: {
|
spacing: {
|
||||||
|
@ -36,17 +36,17 @@ const doc = new Document({
|
|||||||
top: {
|
top: {
|
||||||
style: BorderStyle.DASH_DOT_STROKED,
|
style: BorderStyle.DASH_DOT_STROKED,
|
||||||
size: 3,
|
size: 3,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
style: BorderStyle.DOUBLE,
|
style: BorderStyle.DOUBLE,
|
||||||
size: 3,
|
size: 3,
|
||||||
color: "blue",
|
color: "0000FF",
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
style: BorderStyle.DASH_DOT_STROKED,
|
style: BorderStyle.DASH_DOT_STROKED,
|
||||||
size: 3,
|
size: 3,
|
||||||
color: "green",
|
color: "00FF00",
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
style: BorderStyle.DASH_DOT_STROKED,
|
style: BorderStyle.DASH_DOT_STROKED,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// This demo shows how to create bookmarks then link to them with internal hyperlinks
|
// This demo shows how to create bookmarks then link to them with internal hyperlinks
|
||||||
// Import from 'docx' rather than '../build' if you install from npm
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { Bookmark, Document, Footer, HeadingLevel, InternalHyperlink, Packer, PageBreak, Paragraph, TextRun } from "../build";
|
import { Bookmark, Document, Footer, HeadingLevel, InternalHyperlink, Packer, PageBreak, Paragraph, TextRun, PageReference } from "../build";
|
||||||
|
|
||||||
const LOREM_IPSUM =
|
const LOREM_IPSUM =
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante.";
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam mi velit, convallis convallis scelerisque nec, faucibus nec leo. Phasellus at posuere mauris, tempus dignissim velit. Integer et tortor dolor. Duis auctor efficitur mattis. Vivamus ut metus accumsan tellus auctor sollicitudin venenatis et nibh. Cras quis massa ac metus fringilla venenatis. Proin rutrum mauris purus, ut suscipit magna consectetur id. Integer consectetur sollicitudin ante, vitae faucibus neque efficitur in. Praesent ultricies nibh lectus. Mauris pharetra id odio eget iaculis. Duis dictum, risus id pellentesque rutrum, lorem quam malesuada massa, quis ullamcorper turpis urna a diam. Cras vulputate metus vel massa porta ullamcorper. Etiam porta condimentum nulla nec tristique. Sed nulla urna, pharetra non tortor sed, sollicitudin molestie diam. Maecenas enim leo, feugiat eget vehicula id, sollicitudin vitae ante.";
|
||||||
@ -18,10 +18,12 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new InternalHyperlink({
|
new InternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "Click here!",
|
text: "Click here!",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
anchor: "myAnchorId",
|
anchor: "myAnchorId",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -47,14 +49,24 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new InternalHyperlink({
|
new InternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
text: "Anchor Text",
|
new TextRun({
|
||||||
|
text: "Styled",
|
||||||
|
bold: true,
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: " Anchor Text",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
],
|
||||||
anchor: "myAnchorId",
|
anchor: "myAnchorId",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [new TextRun("The bookmark can be seen on page "), new PageReference("myAnchorId")],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Creates two paragraphs, one with a border and one without
|
// Creates two paragraphs, one with a border and one without
|
||||||
// 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 { BorderStyle, Document, Packer, Paragraph } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [
|
sections: [
|
||||||
@ -14,13 +14,13 @@ const doc = new Document({
|
|||||||
top: {
|
top: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,9 @@ import { File, HeadingLevel, Packer, Paragraph, StyleLevel, TableOfContents } fr
|
|||||||
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
|
// Let's define the properties for generate a TOC for heading 1-5 and MySpectacularStyle,
|
||||||
// making the entries be hyperlinks for the paragraph
|
// making the entries be hyperlinks for the paragraph
|
||||||
const doc = new File({
|
const doc = new File({
|
||||||
|
features: {
|
||||||
|
updateFields: true,
|
||||||
|
},
|
||||||
styles: {
|
styles: {
|
||||||
paragraphStyles: [
|
paragraphStyles: [
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ const table3 = new Table({
|
|||||||
children: [new Paragraph("Bar1")],
|
children: [new Paragraph("Bar1")],
|
||||||
shading: {
|
shading: {
|
||||||
fill: "b79c2f",
|
fill: "b79c2f",
|
||||||
val: ShadingType.REVERSE_DIAGONAL_STRIPE,
|
type: ShadingType.REVERSE_DIAGONAL_STRIPE,
|
||||||
color: "auto",
|
color: "auto",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -106,7 +106,7 @@ const table3 = new Table({
|
|||||||
children: [new Paragraph("Bar2")],
|
children: [new Paragraph("Bar2")],
|
||||||
shading: {
|
shading: {
|
||||||
fill: "42c5f4",
|
fill: "42c5f4",
|
||||||
val: ShadingType.PERCENT_95,
|
type: ShadingType.PERCENT_95,
|
||||||
color: "auto",
|
color: "auto",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -114,7 +114,7 @@ const table3 = new Table({
|
|||||||
children: [new Paragraph("Bar3")],
|
children: [new Paragraph("Bar3")],
|
||||||
shading: {
|
shading: {
|
||||||
fill: "880aa8",
|
fill: "880aa8",
|
||||||
val: ShadingType.PERCENT_10,
|
type: ShadingType.PERCENT_10,
|
||||||
color: "e2df0b",
|
color: "e2df0b",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -122,7 +122,7 @@ const table3 = new Table({
|
|||||||
children: [new Paragraph("Bar4")],
|
children: [new Paragraph("Bar4")],
|
||||||
shading: {
|
shading: {
|
||||||
fill: "FF0000",
|
fill: "FF0000",
|
||||||
val: ShadingType.CLEAR,
|
type: ShadingType.CLEAR,
|
||||||
color: "auto",
|
color: "auto",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -224,22 +224,22 @@ const borders = {
|
|||||||
top: {
|
top: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,10 +11,12 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun("Click here for the "),
|
new TextRun("Click here for the "),
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "Footnotes external hyperlink",
|
text: "Footnotes external hyperlink",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "http://www.example.com",
|
link: "http://www.example.com",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -31,10 +33,12 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun("Click here for the "),
|
new TextRun("Click here for the "),
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "Footer external hyperlink",
|
text: "Footer external hyperlink",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "http://www.example.com",
|
link: "http://www.example.com",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -49,10 +53,12 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun("Click here for the "),
|
new TextRun("Click here for the "),
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "Header external hyperlink",
|
text: "Header external hyperlink",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "http://www.google.com",
|
link: "http://www.google.com",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -64,10 +70,12 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "Anchor Text",
|
text: "Anchor Text",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "http://www.example.com",
|
link: "http://www.example.com",
|
||||||
}),
|
}),
|
||||||
new FootnoteReferenceRun(1),
|
new FootnoteReferenceRun(1),
|
||||||
@ -76,24 +84,63 @@ const doc = new Document({
|
|||||||
new Paragraph({
|
new Paragraph({
|
||||||
children: [
|
children: [
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new ImageRun({
|
children: [
|
||||||
|
new ImageRun({
|
||||||
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
data: fs.readFileSync("./demo/images/image1.jpeg"),
|
||||||
transformation: {
|
transformation: {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "http://www.google.com",
|
link: "http://www.google.com",
|
||||||
}),
|
}),
|
||||||
new ExternalHyperlink({
|
new ExternalHyperlink({
|
||||||
child: new TextRun({
|
children: [
|
||||||
|
new TextRun({
|
||||||
text: "BBC News Link",
|
text: "BBC News Link",
|
||||||
style: "Hyperlink",
|
style: "Hyperlink",
|
||||||
}),
|
}),
|
||||||
|
],
|
||||||
link: "https://www.bbc.co.uk/news",
|
link: "https://www.bbc.co.uk/news",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "This is a hyperlink with formatting: ",
|
||||||
|
}),
|
||||||
|
new ExternalHyperlink({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "A ",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: "single ",
|
||||||
|
bold: true,
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: "link",
|
||||||
|
doubleStrike: true,
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: "1",
|
||||||
|
superScript: true,
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: "!",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
link: "http://www.example.com",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Example how to display page numbers
|
// Example how to display page numbers
|
||||||
// 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 { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
|
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [
|
sections: [
|
||||||
@ -10,7 +10,7 @@ const doc = new Document({
|
|||||||
page: {
|
page: {
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 1,
|
start: 1,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun({
|
new TextRun({
|
||||||
text: "Hello World",
|
text: "Hello World",
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
bold: true,
|
bold: true,
|
||||||
size: 24,
|
size: 24,
|
||||||
font: {
|
font: {
|
||||||
|
@ -14,7 +14,7 @@ const doc = new Document({
|
|||||||
children: [
|
children: [
|
||||||
new TextRun({
|
new TextRun({
|
||||||
text: "Hello World",
|
text: "Hello World",
|
||||||
color: "red",
|
color: "FF0000",
|
||||||
bold: true,
|
bold: true,
|
||||||
size: 24,
|
size: 24,
|
||||||
font: {
|
font: {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Multiple sections with total number of pages in each section
|
// Multiple sections with total number of pages in each section
|
||||||
// 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 { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, PageNumberFormat, Paragraph, TextRun } from "../build";
|
import { AlignmentType, Document, Footer, Header, Packer, PageBreak, PageNumber, NumberFormat, Paragraph, TextRun } from "../build";
|
||||||
|
|
||||||
const header = new Header({
|
const header = new Header({
|
||||||
children: [
|
children: [
|
||||||
@ -31,7 +31,7 @@ const doc = new Document({
|
|||||||
page: {
|
page: {
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 1,
|
start: 1,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -52,7 +52,7 @@ const doc = new Document({
|
|||||||
page: {
|
page: {
|
||||||
pageNumbers: {
|
pageNumbers: {
|
||||||
start: 1,
|
start: 1,
|
||||||
formatType: PageNumberFormat.DECIMAL,
|
formatType: NumberFormat.DECIMAL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// Example of making content of section vertically aligned
|
// Example of making content of section vertically aligned
|
||||||
// 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, SectionVerticalAlignValue, TextRun } from "../build";
|
import { Document, Packer, Paragraph, VerticalAlign, TextRun } from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
properties: {
|
properties: {
|
||||||
verticalAlign: SectionVerticalAlignValue.CENTER,
|
verticalAlign: VerticalAlign.CENTER,
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
new Paragraph({
|
new Paragraph({
|
||||||
|
@ -24,22 +24,22 @@ const table = new Table({
|
|||||||
top: {
|
top: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
style: BorderStyle.DASH_SMALL_GAP,
|
style: BorderStyle.DASH_SMALL_GAP,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
children: [new Paragraph("Hello")],
|
children: [new Paragraph("Hello")],
|
||||||
|
@ -20,10 +20,12 @@ import {
|
|||||||
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.insertedrun
|
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.insertedrun
|
||||||
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.deletedrun
|
- https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.deletedrun
|
||||||
|
|
||||||
The method `addTrackRevisions()` adds an element `<w:trackRevisions />` to the `settings.xml` file. This specifies that the application shall track *new* revisions made to the existing document.
|
The setting `features: { trackRevisions: true }` adds an element `<w:trackRevisions />` to the `settings.xml` file.
|
||||||
|
This specifies that the application shall track *new* revisions made to the existing document.
|
||||||
See also https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.trackrevisions
|
See also https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.trackrevisions
|
||||||
|
|
||||||
Note that this setting enables to track *new changes* after teh file is generated, so this example will still show inserted and deleted text runs when you remove it.
|
Note that this setting enables to track *new changes* after teh file is generated, so this example will still
|
||||||
|
show inserted and deleted text runs when you remove it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
@ -85,7 +87,7 @@ const doc = new Document({
|
|||||||
new DeletedTextRun({
|
new DeletedTextRun({
|
||||||
break: 1,
|
break: 1,
|
||||||
text: "in order",
|
text: "in order",
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
bold: true,
|
bold: true,
|
||||||
size: 24,
|
size: 24,
|
||||||
font: {
|
font: {
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
// Text Frame (Text Box) example
|
// Text Frame (Text Box) example
|
||||||
// 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, FrameAnchorType, HorizontalPositionAlign, Packer, Paragraph, TextRun, VerticalPositionAlign } from "../build";
|
import {
|
||||||
|
BorderStyle,
|
||||||
|
Document,
|
||||||
|
FrameAnchorType,
|
||||||
|
HorizontalPositionAlign,
|
||||||
|
Packer,
|
||||||
|
Paragraph,
|
||||||
|
TextRun,
|
||||||
|
VerticalPositionAlign,
|
||||||
|
} from "../build";
|
||||||
|
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
sections: [
|
sections: [
|
||||||
@ -29,25 +38,25 @@ const doc = new Document({
|
|||||||
top: {
|
top: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
color: "auto",
|
color: "auto",
|
||||||
space: 1,
|
space: 1,
|
||||||
value: "single",
|
style: BorderStyle.SINGLE,
|
||||||
size: 6,
|
size: 6,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
111
demo/64-complex-numbering-text.ts
Normal file
111
demo/64-complex-numbering-text.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Numbered lists - With complex number text
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, LevelFormat } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
numbering: {
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
reference: "ref1",
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: LevelFormat.DECIMAL,
|
||||||
|
text: "%1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 1,
|
||||||
|
format: LevelFormat.DECIMAL,
|
||||||
|
text: "%1.%2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 2,
|
||||||
|
format: LevelFormat.DECIMAL,
|
||||||
|
text: "%1.%2.%3",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:1",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:2",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 2,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "Random text",
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:1 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
instance: 1,
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:0 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
instance: 0,
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:0 - lvl:0",
|
||||||
|
numbering: {
|
||||||
|
reference: "ref1",
|
||||||
|
instance: 0,
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Used to export the file into a .docx file
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("6-numbering.docx", buffer);
|
||||||
|
});
|
38
demo/65-page-sizes.ts
Normal file
38
demo/65-page-sizes.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Example of how to set the document page sizes
|
||||||
|
// Reference from https://papersizes.io/a/a3
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { convertMillimetersToTwip, Document, Packer, PageOrientation, Paragraph } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
page: {
|
||||||
|
size: {
|
||||||
|
orientation: PageOrientation.LANDSCAPE,
|
||||||
|
height: convertMillimetersToTwip(210),
|
||||||
|
width: convertMillimetersToTwip(148),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [new Paragraph("Hello World")],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
page: {
|
||||||
|
size: {
|
||||||
|
orientation: PageOrientation.PORTRAIT,
|
||||||
|
height: convertMillimetersToTwip(420),
|
||||||
|
width: convertMillimetersToTwip(297),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [new Paragraph("Hello World")],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
43
demo/66-fields.ts
Normal file
43
demo/66-fields.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Use fields to include dynamic text
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Bookmark, Document, Packer, Paragraph, SimpleField, TextRun } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
creator: 'Me',
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {},
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("This document is called "),
|
||||||
|
new SimpleField("FILENAME", "My Document.docx"),
|
||||||
|
new TextRun(", was created on "),
|
||||||
|
new SimpleField('CREATEDATE \\@ "d MMMM yyyy"'),
|
||||||
|
new TextRun(" by "),
|
||||||
|
new SimpleField("AUTHOR"),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("The document has "),
|
||||||
|
new SimpleField("NUMWORDS", "34"),
|
||||||
|
new TextRun(" words and if you'd print it "),
|
||||||
|
new Bookmark({
|
||||||
|
id: "TimesPrinted",
|
||||||
|
children: [new TextRun("42")],
|
||||||
|
}),
|
||||||
|
new TextRun(" times two-sided, you would need "),
|
||||||
|
new SimpleField("=INT((TimesPrinted+1)/2)"),
|
||||||
|
new TextRun(" sheets of paper."),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
28
demo/67-column-break.ts
Normal file
28
demo/67-column-break.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Section with 2 columns including a column break
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, ColumnBreak, TextRun } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
column: {
|
||||||
|
space: 708,
|
||||||
|
count: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new Paragraph({ children: [
|
||||||
|
new TextRun('This text will be in the first column.'),
|
||||||
|
new ColumnBreak(),
|
||||||
|
new TextRun('This text will be in the second column.'),
|
||||||
|
] }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
86
demo/68-numbering-instances-and-starting-number.ts
Normal file
86
demo/68-numbering-instances-and-starting-number.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import { Document, Packer, Paragraph, PageNumberFormat} from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
numbering:{
|
||||||
|
config:[
|
||||||
|
{
|
||||||
|
reference: 'ref1',
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: PageNumberFormat.DECIMAL,
|
||||||
|
text: '%1',
|
||||||
|
start: 10,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'ref2',
|
||||||
|
levels: [
|
||||||
|
{
|
||||||
|
level: 0,
|
||||||
|
format: PageNumberFormat.DECIMAL,
|
||||||
|
text: '%1'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
sections: [{
|
||||||
|
children: [
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:0 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref1',
|
||||||
|
instance: 0,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:0 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref1',
|
||||||
|
instance: 0,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:1 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref1',
|
||||||
|
instance: 1,
|
||||||
|
level: 0,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF1 - inst:1 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref1',
|
||||||
|
instance: 1,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF2 - inst:0 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref2',
|
||||||
|
instance: 1,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "REF2 - inst:0 - lvl:0",
|
||||||
|
numbering : {
|
||||||
|
reference: 'ref2',
|
||||||
|
instance: 1,
|
||||||
|
level: 0,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
31
demo/69-different-width-columns.ts
Normal file
31
demo/69-different-width-columns.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Sections with multiple columns
|
||||||
|
// Import from 'docx' rather than '../build' if you install from npm
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { Column, Document, Packer, Paragraph } from "../build";
|
||||||
|
|
||||||
|
const doc = new Document({
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
column: {
|
||||||
|
count: 2,
|
||||||
|
space: 720,
|
||||||
|
equalWidth: false,
|
||||||
|
children: [new Column({ width: 2880, space: 720 }), new Column({ width: 5760 })],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
new Paragraph(
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||||
|
),
|
||||||
|
new Paragraph(
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Packer.toBuffer(doc).then((buffer) => {
|
||||||
|
fs.writeFileSync("My Document.docx", buffer);
|
||||||
|
});
|
@ -12,9 +12,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
function generate() {
|
function generate() {
|
||||||
const doc = new docx.Document();
|
const doc = new docx.Document({
|
||||||
|
|
||||||
const doc = new Document({
|
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
children: [
|
children: [
|
||||||
|
@ -44,7 +44,7 @@ const doc = new Document({
|
|||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}];
|
}],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Used to export the file into a .docx file
|
// Used to export the file into a .docx file
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
- Simple, declarative API
|
- Simple, declarative API
|
||||||
- 60+ usage examples
|
- 60+ usage examples
|
||||||
- Battle tested, mature, 98%+ coverage
|
- Battle tested, mature, 99%+ coverage
|
||||||
|
|
||||||
[GitHub](https://github.com/dolanmiu/docx)
|
[GitHub](https://github.com/dolanmiu/docx)
|
||||||
[Get Started](#Welcome)
|
[Get Started](#Welcome)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* [Image](usage/images.md)
|
* [Image](usage/images.md)
|
||||||
* [Headers & Footers](usage/headers-and-footers.md)
|
* [Headers & Footers](usage/headers-and-footers.md)
|
||||||
* [Bullet Points](usage/bullet-points.md)
|
* [Bullet Points](usage/bullet-points.md)
|
||||||
|
* [Hyperlinks](usage/hyperlinks.md)
|
||||||
* [Numbering](usage/numbering.md)
|
* [Numbering](usage/numbering.md)
|
||||||
* [Tables](usage/tables.md)
|
* [Tables](usage/tables.md)
|
||||||
* [Tab Stops](usage/tab-stops.md)
|
* [Tab Stops](usage/tab-stops.md)
|
||||||
|
@ -27,7 +27,7 @@ const paragraph = new Paragraph({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that for a `InsertedTextRun` and `DeletedTextRun`, it is not possible to simply call it with only a text as in `new TextRun("some text")`, since the additonal fields for change tracking need to be provided. Similar to a normal `TextRun` you can add additional text properties.
|
Note that for a `InsertedTextRun` and `DeletedTextRun`, it is not possible to simply call it with only a text as in `new TextRun("some text")`, since the additional fields for change tracking need to be provided. Similar to a normal `TextRun` you can add additional text properties.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Paragraph, TextRun, InsertedTextRun, DeletedTextRun } from "docx";
|
import { Paragraph, TextRun, InsertedTextRun, DeletedTextRun } from "docx";
|
||||||
@ -37,7 +37,7 @@ const paragraph = new Paragraph({
|
|||||||
new TextRun("This is a simple demo"),
|
new TextRun("This is a simple demo"),
|
||||||
new DeletedTextRun({
|
new DeletedTextRun({
|
||||||
text: "with a deletion.",
|
text: "with a deletion.",
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
bold: true,
|
bold: true,
|
||||||
size: 24,
|
size: 24,
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -48,7 +48,7 @@ const paragraph = new Paragraph({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
In addtion to marking text as inserted or deleted, change tracking can also be added via the document settings. This will enable new changes to be tracked as well.
|
In addition to marking text as inserted or deleted, change tracking can also be added via the document settings. This will enable new changes to be tracked as well.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Document } from "docx";
|
import { Document } from "docx";
|
||||||
|
73
docs/usage/fields.md
Normal file
73
docs/usage/fields.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Fields
|
||||||
|
|
||||||
|
Fields are pieces of dynamic text that you can include in your document. Often used fields are page numbers or references, but you can also include document properties like the author name or last saved date.
|
||||||
|
|
||||||
|
## Simple fields
|
||||||
|
|
||||||
|
There are very complicated fields like the table of contents, but in many cases the whole field just has the same properties (like formatting). In those cases, you can use simple fields.
|
||||||
|
|
||||||
|
Word uses field codes to identify what the result of the field should be. You can find these field codes by adding a field in a document (`Insert -> Quick Parts -> Field...`) and clicking the 'Field codes'-button. Some examples include:
|
||||||
|
|
||||||
|
Field type | Example | Description
|
||||||
|
----------- | --------------- | ---------------------------------------------------------
|
||||||
|
= (Formula) | `=2*21` | Calculates the result of a formula. You can also use bookmarks as variables, see below.
|
||||||
|
Author | `AUTHOR` | Includes the author mentioned in the document properties.
|
||||||
|
CreateDate | `CREATEDATE` | Date the document was created.
|
||||||
|
Date | `DATE` | Today's date.
|
||||||
|
FileName | `FILENAME \p` | The name of the document. Add `\p` for the complete path.
|
||||||
|
Info | `INFO NumWords` | Data from the document properties, e.g. the number of words in the document.
|
||||||
|
NumPages | `NUMPAGES` | Number of pages in the document.
|
||||||
|
UserName | `USERNAME` | Your user name from the Office personalization settings.
|
||||||
|
|
||||||
|
Fields can be added as a child of a paragraph:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [new TextRun("This document was created by: "), new SimpleField("AUTHOR")],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Fields can contain a cached value that gives the word processor a text to show without having to calculate all fields. The cached value can be updated by selecting the field and pressing F9. A cached value can be passed in as the second argument to the constructor.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [new TextRun("This document was created by: "), new SimpleField("AUTHOR", "Richard Brodie")],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Formulas
|
||||||
|
|
||||||
|
One type of field is the formula that can be used to do some basic calculations. This can be done with static values, e.g. `12 + 34`, but a value from a bookmark can also be used in a calculation. This can be seen in the following example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("Value one is: "),
|
||||||
|
new Bookmark({ id: "One", children: [new TextRun("451")]}),
|
||||||
|
new TextRun(". The second value is: "),
|
||||||
|
new Bookmark({ id: "Two", children: [new TextRun("886")]}),
|
||||||
|
new TextRun(". The sum of these values is: "),
|
||||||
|
new SimpleField("=One+Two"),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mail merge fields
|
||||||
|
|
||||||
|
Fields are often used in a mail merge where a template document is created and data from another source (Excel or a database) is inserted in the document.
|
||||||
|
|
||||||
|
A convenience class was added to add these mail merge fields to the document easily. You can add these to a paragraph like any other field and only have to supply the name of the field in your data set:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [new TextRun("Your score was "), new SimpleMailMergeField("Score"), new TextRun(" of 100 points")],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
This code is equivalent to:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [new TextRun("Your score was "), new SimpleField("MERGEFIELD Score", "«Score»"), new TextRun(" of 100 points")],
|
||||||
|
});
|
||||||
|
```
|
@ -1,47 +1,98 @@
|
|||||||
# Hyperlinks
|
# Hyperlinks
|
||||||
|
|
||||||
|
!> Hyperlinks require an understanding of [Paragraphs](usage/paragraph.md) and [Text](usage/text.md).
|
||||||
|
|
||||||
There are two types of hyperlinks: internal (pointing to a bookmark inside the document) and external (pointing to an external url).
|
There are two types of hyperlinks: internal (pointing to a bookmark inside the document) and external (pointing to an external url).
|
||||||
|
|
||||||
## Internal
|
## Internal
|
||||||
|
|
||||||
To create an internal hyperlink you need first to create a bookmark (the paragraph that will be the destination of the hyperlink) with `doc.createBookmark(anchor, text)`.
|
To create an internal hyperlink you need first to create a `Bookmark`, which contains the content that will be the destination of the hyperlink.
|
||||||
|
|
||||||
A bookmark is composed of an anchor (an identifier) and the text displayed. After creating a bookmark just add it to a paragraph with `paragraph.addBookmark(bookmark)`
|
A bookmark is composed of an anchor (an identifier) and the text displayed. After creating a bookmark just add it to a paragraph. For example, creating a bookmarked heading:
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = this.doc.createParagraph();
|
const chapter1 = new Paragraph({
|
||||||
const bookmark = this.doc.createBookmark('anchorForChapter1', 'This is chapter1');
|
heading: HeadingLevel.HEADING_1,
|
||||||
paragraph.addBookmark(bookmark);
|
children: [
|
||||||
|
new Bookmark({
|
||||||
|
id: "anchorForChapter1",
|
||||||
|
children: [
|
||||||
|
new TextRun("Chapter 1"),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can create an hyperlink pointing to that bookmark with `doc.createInternalHyperLink(anchor,text)`:
|
Then you can create an hyperlink pointing to that bookmark with an `InternalHyperLink`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = this.doc.createParagraph();
|
const link = new InternalHyperlink({
|
||||||
const link = this.doc.createInternalHyperLink('anchorForChapter1', 'This is a link to chapter1');
|
children: [
|
||||||
paragraph.addHyperLink(link);
|
new TextRun({
|
||||||
|
text: "See Chapter 1",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
anchor: "anchorForChapter1",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also get the page number of the bookmark by creating a page reference to it:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const paragraph = new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun("Chapter 1 can be seen on page "),
|
||||||
|
new PageReference("anchorForChapter1"),
|
||||||
|
],
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## External
|
## External
|
||||||
|
|
||||||
To create an external hyperlink you just need to specify the url and the text of the link, then add it to a paragraph with `doc.createHyperlink(url, text)`:
|
To create an external hyperlink you just need to specify the url and the text of the link, then add it to a paragraph:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = this.doc.createParagraph();
|
const paragraph = new Paragraph({
|
||||||
const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link');
|
children: [
|
||||||
paragraph.addHyperLink(link);
|
new ExternalHyperlink({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "This is an external link!",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
link: "https://docx.js.org",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Styling an hyperlink
|
## Styling hyperlinks
|
||||||
|
|
||||||
It is possible to set the style of the text of an hyperlink. This can be done applying run formatting on `TextRun` property of the hyperlink.
|
It is possible to set the style of the text of both internal and external hyperlinks. This can be done applying run formatting on any of the `TextRun` children of the hyperlink. Use the `style: "Hyperlink"` property to show the default link styles, which can be combined with any other style.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const link = this.doc.createHyperlink('https://docx.js.org', 'This is an external link');
|
const styledLink = new ExternalHyperlink({
|
||||||
link.TextRun.bold().italics()
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
text: "This is a ",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: "bold",
|
||||||
|
bold: true,
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
new TextRun({
|
||||||
|
text: " link!",
|
||||||
|
style: "Hyperlink",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
link: "https://docx.js.org",
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
@ -78,7 +78,7 @@ const doc = new Document({
|
|||||||
|
|
||||||
> Positioning is the method on how to place the image on the document
|
> Positioning is the method on how to place the image on the document
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Three types of image positioning is supported:
|
Three types of image positioning is supported:
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ By default, images are exported as `Inline` elements.
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
Pass `options` into the `[POSITION_OPTIONS]` metioned in the [Intro above](#Intro).
|
Pass `options` into the `[POSITION_OPTIONS]` mentioned in the [Intro above](#Intro).
|
||||||
|
|
||||||
## Floating
|
## Floating
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
1. To add math, create a `Math` object
|
1. To add math, create a `Math` object
|
||||||
2. Add `MathComponents` inside `Math`
|
2. Add `MathComponents` inside `Math`
|
||||||
3. `MathComponents` can have nested `MathComponents` inside. e.g. A fraction where the numerator is a square root, and the demoninator as another fraction. More on `MathComponents` below
|
3. `MathComponents` can have nested `MathComponents` inside. e.g. A fraction where the numerator is a square root, and the denominator as another fraction. More on `MathComponents` below
|
||||||
4. Make sure to add the `Math` object inside a `Paragraph`
|
4. Make sure to add the `Math` object inside a `Paragraph`
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
@ -61,7 +61,7 @@ new Math({
|
|||||||
|
|
||||||
### Math Fraction
|
### Math Fraction
|
||||||
|
|
||||||
`MathFractions` require a `numerator` and a `demoninator`, which are both a list of `MathComponents`
|
`MathFractions` require a `numerator` and a `denominator`, which are both a list of `MathComponents`
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ those bullets/numbering. An abstract numbering system defines how
|
|||||||
bullets/numbers are to be shown for lists, including any sublists that
|
bullets/numbers are to be shown for lists, including any sublists that
|
||||||
may be used. Thus each abstract definition includes a series of
|
may be used. Thus each abstract definition includes a series of
|
||||||
_levels_ which form a sequence starting at 0 indicating the top-level
|
_levels_ which form a sequence starting at 0 indicating the top-level
|
||||||
list look and increasing from there to descibe the sublists, then
|
list look and increasing from there to describe the sublists, then
|
||||||
sub-sublists, etc. Each level includes the following properties:
|
sub-sublists, etc. Each level includes the following properties:
|
||||||
|
|
||||||
* **level**: This is its 0-based index in the definition stack
|
* **level**: This is its 0-based index in the definition stack
|
||||||
@ -39,10 +39,10 @@ sub-sublists, etc. Each level includes the following properties:
|
|||||||
the sequence "a)", "b)", ...
|
the sequence "a)", "b)", ...
|
||||||
* and a few others, which you can see in the OXML spec section 17.9.6
|
* and a few others, which you can see in the OXML spec section 17.9.6
|
||||||
|
|
||||||
## Document-level bullets/numbering defintions (concrete)
|
## Document-level bullets/numbering definitions (concrete)
|
||||||
|
|
||||||
Concrete definitions are sort of like concrete subclasses of the
|
Concrete definitions are sort of like concrete subclasses of the
|
||||||
abstract defintions. They indicate their parent and are allowed to
|
abstract definitions. They indicate their parent and are allowed to
|
||||||
override certain level definitions. Thus two lists that differ only in
|
override certain level definitions. Thus two lists that differ only in
|
||||||
how sub-sub-lists are to be displayed can share the same abstract
|
how sub-sub-lists are to be displayed can share the same abstract
|
||||||
numbering definition and have slightly different concrete definitions.
|
numbering definition and have slightly different concrete definitions.
|
||||||
|
@ -5,35 +5,49 @@
|
|||||||
?> **Note:** This feature only works on Headers and Footers
|
?> **Note:** This feature only works on Headers and Footers
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
doc.Header.createParagraph().addRun(new TextRun("Page Number: ").pageNumber()).addRun(new TextRun("to ").numberOfTotalPages());
|
new Paragraph({
|
||||||
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
children: ["Page #: ", PageNumber.CURRENT],
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Current page number
|
## 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
|
```ts
|
||||||
pageNumber();
|
PageNumber.CURRENT
|
||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const currentPageRun = new TextRun("Current Page Number: ").pageNumber();
|
new Paragraph({
|
||||||
paragraph.addRun(currentPageRun);
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
children: ["Page Number ", PageNumber.CURRENT],
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Total number of pages
|
## Total number of pages
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
numberOfTotalPages();
|
PageNumber.TOTAL_PAGES
|
||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const lastPage = new TextRun("Total Page Number: ").numberOfTotalPages();
|
new Paragraph({
|
||||||
paragraph.addRun(lastPage);
|
children: [
|
||||||
|
new TextRun({
|
||||||
|
children: ["Total Pages Number: ", PageNumber.TOTAL_PAGES],
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -42,17 +56,14 @@ paragraph.addRun(lastPage);
|
|||||||
You can combine the two to get "Page 2 of 10" effect:
|
You can combine the two to get "Page 2 of 10" effect:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const currentPageRun = new TextRun("Page ").pageNumber();
|
new Paragraph({
|
||||||
const lastPage = new TextRun("of ").numberOfTotalPages();
|
children: [
|
||||||
|
new TextRun("My awesome text here for my university dissertation. ")
|
||||||
paragraph.addRun(currentPageRun);
|
new TextRun({
|
||||||
paragraph.addRun(lastPage);
|
children: ["Page ", PageNumber.CURRENT, " of ", PageNumber.TOTAL_PAGES],
|
||||||
```
|
})
|
||||||
|
]
|
||||||
Or:
|
})
|
||||||
|
|
||||||
```ts
|
|
||||||
doc.Header.createParagraph().addRun(new TextRun("Page ").pageNumber()).addRun(new TextRun("of ").numberOfTotalPages());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Paragraph
|
# Paragraph
|
||||||
|
|
||||||
> Everything (text, images, graphs etc) in OpenXML is organised in paragraphs.
|
> Everything (text, images, graphs etc) in OpenXML is organized in paragraphs.
|
||||||
|
|
||||||
!> Paragraphs requires an understanding of [Sections](sections.md).
|
!> Paragraphs requires an understanding of [Sections](usage/sections.md).
|
||||||
|
|
||||||
You can create `Paragraphs` in the following ways:
|
You can create `Paragraphs` in the following ways:
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ const paragraph = new Paragraph("Short hand Hello World");
|
|||||||
|
|
||||||
### Children Method
|
### Children Method
|
||||||
|
|
||||||
This method is useful for adding different [text](text.md) with different styles, [symbols](symbols.md), or adding [images](images.md) inline.
|
This method is useful for adding different [text](usage/text.md) with different styles, [symbols](usage/symbols.md), or adding [images](usage/images.md) inline.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
@ -42,7 +42,7 @@ const doc = new Document({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Or the preferred convension, define the paragraph inside the section and remove the usage of variables:
|
Or the preferred convention, define the paragraph inside the section and remove the usage of variables:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const doc = new Document({
|
const doc = new Document({
|
||||||
@ -180,12 +180,12 @@ Adding spacing between paragraphs
|
|||||||
|
|
||||||
### ISpacingProperties
|
### ISpacingProperties
|
||||||
|
|
||||||
| Property | Type | Notes |
|
| Property | Type | Notes | Possible Values |
|
||||||
| -------- | -------------- | -------- |
|
| -------- | -------------- | -------- | ----------------------------- |
|
||||||
| after | `number` | Optional |
|
| after | `number` | Optional | |
|
||||||
| before | `number` | Optional |
|
| before | `number` | Optional | |
|
||||||
| line | `number` | Optional |
|
| line | `number` | Optional | |
|
||||||
| lineRule | `LineRuleType` | Optional |
|
| lineRule | `LineRuleType` | Optional | `AT_LEAST`, `EXACTLY`, `AUTO` |
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Create a new word document in Microsoft Word
|
1. Create a new word document in Microsoft Word
|
||||||
2. Customise the styles on the Ribbon Bar.
|
2. Customize the styles on the Ribbon Bar.
|
||||||
For example, modify the `Normal`, `Heading 1`, `Heading 2` like so:
|
For example, modify the `Normal`, `Heading 1`, `Heading 2` like so:
|
||||||
|
|
||||||

|

|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Symbol Runs
|
# Symbol Runs
|
||||||
|
|
||||||
!> SymbolRuns require an understanding of [Paragraphs](paragraph.md).
|
!> SymbolRuns require an understanding of [Paragraphs](usage/paragraph.md).
|
||||||
|
|
||||||
You can add multiple `symbol runs` in `Paragraphs` along with [text runs](text.md) using the Paragraph's `children` property.
|
You can add multiple `symbol runs` in `Paragraphs` along with [text runs](usage/text.md) using the Paragraph's `children` property.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Paragraph, TextRun, SymbolRun } from "docx";
|
import { Paragraph, TextRun, SymbolRun } from "docx";
|
||||||
@ -50,4 +50,4 @@ const symbol = new SymbolRun({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [text run](text.md) documentation for more info.
|
See the [text run](usage/text.md) documentation for more info.
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
|
|
||||||
!> **Note**: The unit of measurement for a tab stop is in [DXA](https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches)
|
!> **Note**: The unit of measurement for a tab stop is in [DXA](https://stackoverflow.com/questions/14360183/default-wordml-unit-measurement-pixel-or-point-or-inches)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Simply call the relevant methods on the paragraph listed below. Then just add a `tab()` method call to a text object. Adding multiple `tabStops` will mean you would have to chain `tab()` until the desired `tabStop` is selected. Example is shown below.
|
Simply declare the tab stops on the paragraph, as shown below. Use the tab character `\t` to indicate the tab position within the `text` property of a `TextRun`. Adding multiple `tabStops` will mean you can add additional `\t` characters until the desired `tabStop` is selected. Example is shown below.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
children: [new TextRun("Hey everyone").bold(), new TextRun(\t"11th November 1999")],
|
children: [new TextRun({ text: "Hey everyone", bold: true}), new TextRun("\t11th November 1999")],
|
||||||
tabStops: [
|
tabStops: [
|
||||||
{
|
{
|
||||||
type: TabStopType.RIGHT,
|
type: TabStopType.RIGHT,
|
||||||
@ -26,7 +26,7 @@ The example above will create a left aligned text, and a right aligned text on t
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
children: [new TextRun("Second tab stop here I come!")],
|
children: [new TextRun("\t\tSecond tab stop here I come!")],
|
||||||
tabStops: [
|
tabStops: [
|
||||||
{
|
{
|
||||||
type: TabStopType.RIGHT,
|
type: TabStopType.RIGHT,
|
||||||
@ -46,7 +46,7 @@ You can add multiple tab stops of the same `type` too.
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const paragraph = new Paragraph({
|
const paragraph = new Paragraph({
|
||||||
children: [new TextRun("Multiple tab stops!")],
|
children: [new TextRun("Multiple \ttab \tstops!")],
|
||||||
tabStops: [
|
tabStops: [
|
||||||
{
|
{
|
||||||
type: TabStopType.RIGHT,
|
type: TabStopType.RIGHT,
|
||||||
@ -103,7 +103,7 @@ const paragraph = new Paragraph({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
2268 is the distance fro0oum the left side.
|
2268 is the distance from the left side.
|
||||||
|
|
||||||
## Max Right Tab Stop
|
## Max Right Tab Stop
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
You can generate table of contents with `docx`. More information can be found [here](http://officeopenxml.com/WPtableOfContents.php).
|
You can generate table of contents with `docx`. More information can be found [here](http://officeopenxml.com/WPtableOfContents.php).
|
||||||
|
|
||||||
> Tables of Contents are fields and, by design, it's content is only generated or updated by Word. We can't do it programatically.
|
> Tables of Contents are fields and, by design, it's content is only generated or updated by Word. We can't do it programmatically.
|
||||||
> This is why, when you open a the file, Word you will prompt the message "This document contains fields that may refer to other files. Do you want to update the fields in this document?".
|
> This is why, when you open a the file, Word you will prompt the message "This document contains fields that may refer to other files. Do you want to update the fields in this document?".
|
||||||
> You have say yes to Word generate the content of all table of contents.
|
> You have say yes to Word generate the content of all table of contents.
|
||||||
|
|
||||||
@ -12,14 +12,29 @@ The complete documentation can be found [here](https://www.ecma-international.or
|
|||||||
|
|
||||||
All you need to do is create a `TableOfContents` object and assign it to the document.
|
All you need to do is create a `TableOfContents` object and assign it to the document.
|
||||||
|
|
||||||
|
**Note**: updateFields feature must be enabled for TableOfContents to update correctly.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const toc = new TableOfContents("Summary", {
|
const doc = new Document({
|
||||||
|
features: {
|
||||||
|
updateFields: true,
|
||||||
|
},
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
children: [
|
||||||
|
new TableOfContents("Summary", {
|
||||||
hyperlink: true,
|
hyperlink: true,
|
||||||
headingStyleRange: "1-5",
|
headingStyleRange: "1-5",
|
||||||
stylesWithLevels: [new StyleLevel("MySpectacularStyle", 1)],
|
}),
|
||||||
|
new Paragraph({
|
||||||
|
text: "Header #1",
|
||||||
|
heading: HeadingLevel.HEADING_1,
|
||||||
|
pageBreakBefore: true,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
doc.addTableOfContents(toc);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Table of Contents Options
|
## Table of Contents Options
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
- `Tables` contain a list of `Rows`
|
- `Tables` contain a list of `Rows`
|
||||||
- `Rows` contain a list of `TableCells`
|
- `Rows` contain a list of `TableCells`
|
||||||
- `TableCells` contain a list of `Parahraphs` and/or `Tables`. You can add `Tables` as tables can be nested inside each other
|
- `TableCells` contain a list of `Paragraphs` and/or `Tables`. You can add `Tables` as tables can be nested inside each other
|
||||||
|
|
||||||
Create a simple table like so:
|
Create a simple table like so:
|
||||||
|
|
||||||
@ -53,6 +53,18 @@ const table = new Table({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Set Indent
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const table = new Table({
|
||||||
|
...,
|
||||||
|
indent: {
|
||||||
|
size: 600,
|
||||||
|
type: WidthType.DXA,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Table Row
|
## Table Row
|
||||||
|
|
||||||
A table consists of multiple `table rows`. Table rows have a list of `children` which accepts a list of `table cells` explained below. You can create a simple `table row` like so:
|
A table consists of multiple `table rows`. Table rows have a list of `children` which accepts a list of `table cells` explained below. You can create a simple `table row` like so:
|
||||||
@ -145,7 +157,7 @@ const tableRow = new TableRow({
|
|||||||
| Property | Type | Notes |
|
| Property | Type | Notes |
|
||||||
| ------------- | ----------------------------------- | ----------------------------------------------------------- |
|
| ------------- | ----------------------------------- | ----------------------------------------------------------- |
|
||||||
| children | `Array<Paragraph or Table>` | Required. You can nest tables by adding a table into a cell |
|
| children | `Array<Paragraph or Table>` | Required. You can nest tables by adding a table into a cell |
|
||||||
| shading | `ITableShadingAttributesProperties` | Optional |
|
| shading | `IShadingAttributesProperties` | Optional |
|
||||||
| margins | `ITableCellMarginOptions` | Optional |
|
| margins | `ITableCellMarginOptions` | Optional |
|
||||||
| verticalAlign | `VerticalAlign` | Optional |
|
| verticalAlign | `VerticalAlign` | Optional |
|
||||||
| columnSpan | `number` | Optional |
|
| columnSpan | `number` | Optional |
|
||||||
@ -171,7 +183,7 @@ const cell = new TableCell({
|
|||||||
top: {
|
top: {
|
||||||
style: BorderStyle.DASH_DOT_STROKED,
|
style: BorderStyle.DASH_DOT_STROKED,
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "ff0000",
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
style: BorderStyle.THICK_THIN_MEDIUM_GAP,
|
style: BorderStyle.THICK_THIN_MEDIUM_GAP,
|
||||||
@ -190,12 +202,12 @@ Google DOCS does not support start and end borders, instead they use left and ri
|
|||||||
const cell = new TableCell({
|
const cell = new TableCell({
|
||||||
...,
|
...,
|
||||||
borders: {
|
borders: {
|
||||||
top: {
|
left: {
|
||||||
style: BorderStyle.DOT_DOT_DASH,
|
style: BorderStyle.DOT_DOT_DASH,
|
||||||
size: 3,
|
size: 3,
|
||||||
color: "green",
|
color: "00FF00",
|
||||||
},
|
},
|
||||||
bottom: {
|
right: {
|
||||||
style: BorderStyle.DOT_DOT_DASH,
|
style: BorderStyle.DOT_DOT_DASH,
|
||||||
size: 3,
|
size: 3,
|
||||||
color: "ff8000",
|
color: "ff8000",
|
||||||
@ -231,17 +243,11 @@ const cell = new TableCell({
|
|||||||
`WidthType` values can be:
|
`WidthType` values can be:
|
||||||
|
|
||||||
| Property | Notes |
|
| Property | Notes |
|
||||||
| -------- | --------------------------------- |
|
| ---------- | --------------------------------- |
|
||||||
| AUTO | |
|
| AUTO | |
|
||||||
| DXA | value is in twentieths of a point |
|
| DXA | Value is in twentieths of a point |
|
||||||
| NIL | is considered as zero |
|
| NIL | Is considered as zero |
|
||||||
| PCT | percent of table width |
|
| PERCENTAGE | Percent of table width |
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
```ts
|
|
||||||
cell.Properties.setWidth(100, WidthType.DXA);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nested Tables
|
### Nested Tables
|
||||||
|
|
||||||
@ -346,7 +352,7 @@ _Source: https://github.com/dolanmiu/docx/blob/master/demo/4-basic-table.ts_
|
|||||||
|
|
||||||
### Custom borders
|
### Custom borders
|
||||||
|
|
||||||
Example showing how to add colourful borders to tables
|
Example showing how to add colorful borders to tables
|
||||||
|
|
||||||
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/20-table-cell-borders.ts ':include')
|
[Example](https://raw.githubusercontent.com/dolanmiu/docx/master/demo/20-table-cell-borders.ts ':include')
|
||||||
|
|
||||||
|
5991
package-lock.json
generated
5991
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@ -1,26 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "docx",
|
"name": "docx",
|
||||||
"version": "6.0.1",
|
"version": "7.0.0",
|
||||||
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
"description": "Easily generate .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pretest": "rimraf ./build",
|
"pretest": "rimraf ./build",
|
||||||
"test": "mocha-webpack \"src/**/*.ts\"",
|
"test": "mocha -r ts-node/register -r tsconfig-paths/register \"src/**/*.ts\"",
|
||||||
"test.coverage": "nyc npm test",
|
"test.coverage": "nyc npm test",
|
||||||
"test.watch": "npm test -- --watch",
|
"test.watch": "npm test -- --watch",
|
||||||
"prepublishOnly": "npm run build --production",
|
"prepublishOnly": "npm run build --production",
|
||||||
"lint": "tslint --project .",
|
"lint": "tslint --project .",
|
||||||
"build": "npm run webpack && npm run fix-types",
|
"build": "npm run webpack",
|
||||||
"tsc": "rimraf ./build && tsc -p .",
|
"webpack": "rimraf ./build && webpack --config ./webpack.config.ts",
|
||||||
"webpack": "rimraf ./build && webpack",
|
"demo": "npm run build && npm run ts-node --skip-project ./demo",
|
||||||
"demo": "npm run build && npm run ts-node ./demo",
|
|
||||||
"typedoc": "rimraf ./build && typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
"typedoc": "rimraf ./build && typedoc src/index.ts --tsconfig tsconfig.typedoc.json",
|
||||||
"style": "prettier -l \"src/**/*.ts\"",
|
"style": "prettier -l \"src/**/*.ts\"",
|
||||||
"style.fix": "npm run style -- --write",
|
"style.fix": "npm run style -- --write",
|
||||||
"fix-types": "ts-node scripts/types-absolute-fixer.ts",
|
"fix-types": "ts-node scripts/types-absolute-fixer.ts",
|
||||||
"e2e": "ts-node scripts/e2e.ts",
|
"e2e": "ts-node scripts/e2e.ts",
|
||||||
"serve.docs": "cd docs && docsify serve",
|
"serve.docs": "cd docs && docsify serve",
|
||||||
"ts-node": "ts-node"
|
"ts-node": "ts-node --skip-project"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
"style",
|
"style",
|
||||||
@ -49,8 +48,7 @@
|
|||||||
],
|
],
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/jszip": "^3.1.4",
|
"@types/node": "^16.0.0",
|
||||||
"@types/node": "^14.0.5",
|
|
||||||
"jszip": "^3.1.5",
|
"jszip": "^3.1.5",
|
||||||
"nanoid": "^3.1.20",
|
"nanoid": "^3.1.20",
|
||||||
"xml": "^1.0.1",
|
"xml": "^1.0.1",
|
||||||
@ -64,34 +62,37 @@
|
|||||||
"homepage": "https://github.com/dolanmiu/docx#readme",
|
"homepage": "https://github.com/dolanmiu/docx#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.15",
|
"@types/chai": "^4.2.15",
|
||||||
"@types/mocha": "^8.0.0",
|
"@types/mocha": "^9.0.0",
|
||||||
"@types/request-promise": "^4.1.42",
|
"@types/request-promise": "^4.1.42",
|
||||||
"@types/sinon": "^9.0.4",
|
"@types/sinon": "^10.0.0",
|
||||||
"@types/webpack": "^4.4.24",
|
"@types/webpack": "^5.0.0",
|
||||||
"awesome-typescript-loader": "^3.4.1",
|
"buffer": "^6.0.3",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"docsify-cli": "^4.3.0",
|
"docsify-cli": "^4.3.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": "^9.0.2",
|
||||||
"mocha-webpack": "^1.0.1",
|
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"prettier": "^2.1.2",
|
"prettier": "^2.3.1",
|
||||||
|
"process": "^0.11.10",
|
||||||
"prompt": "^1.0.0",
|
"prompt": "^1.0.0",
|
||||||
"replace-in-file": "^3.1.0",
|
"replace-in-file": "^6.2.0",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"request-promise": "^4.2.2",
|
"request-promise": "^4.2.2",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
"sinon": "^9.0.2",
|
"sinon": "^11.0.0",
|
||||||
|
"stream-browserify": "^3.0.0",
|
||||||
|
"ts-loader": "^9.0.0",
|
||||||
"ts-node": "^9.0.0",
|
"ts-node": "^9.0.0",
|
||||||
|
"tsconfig-paths": "^3.9.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-immutable": "^6.0.1",
|
"tslint-immutable": "^6.0.1",
|
||||||
"typedoc": "^0.20.29",
|
"typedoc": "^0.22.3",
|
||||||
"typescript": "4.2.3",
|
"typescript": "4.4.3",
|
||||||
"webpack": "^3.10.0"
|
"webpack": "^5.28.0",
|
||||||
|
"webpack-cli": "^4.6.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
|
@ -18,14 +18,14 @@ describe("Utility", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("#uniqueNumericId", () => {
|
describe("#uniqueNumericId", () => {
|
||||||
it("should generate a unique ID", () => {
|
it("should generate a unique incrementing ID", () => {
|
||||||
// tslint:disable-next-line: no-unused-expression
|
// tslint:disable-next-line: no-unused-expression
|
||||||
expect(uniqueNumericId()).to.not.be.empty;
|
expect(uniqueNumericId()).to.not.be.undefined;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#uniqueId", () => {
|
describe("#uniqueId", () => {
|
||||||
it("should call the underlying header's addChildElement", () => {
|
it("should generate a unique pseudorandom ID", () => {
|
||||||
// tslint:disable-next-line: no-unused-expression
|
// tslint:disable-next-line: no-unused-expression
|
||||||
expect(uniqueId()).to.not.be.empty;
|
expect(uniqueId()).to.not.be.empty;
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { customAlphabet, nanoid } from "nanoid/non-secure";
|
import { nanoid } from "nanoid/non-secure";
|
||||||
|
|
||||||
const numericNanoId = customAlphabet("0123456789", 15);
|
let currentCount = 0;
|
||||||
|
|
||||||
// Twip - twentieths of a point
|
// Twip - twentieths of a point
|
||||||
export const convertMillimetersToTwip = (millimeters: number): number => {
|
export const convertMillimetersToTwip = (millimeters: number): number => {
|
||||||
@ -12,7 +12,7 @@ export const convertInchesToTwip = (inches: number): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const uniqueNumericId = (): number => {
|
export const uniqueNumericId = (): number => {
|
||||||
return parseFloat(numericNanoId());
|
return ++currentCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const uniqueId = (): string => {
|
export const uniqueId = (): string => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { assert, expect } from "chai";
|
import { assert, expect } from "chai";
|
||||||
import * as sinon from "sinon";
|
import * as sinon from "sinon";
|
||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "@export/formatter";
|
||||||
import { Paragraph, TextRun } from "file";
|
import { Paragraph, TextRun } from "file";
|
||||||
import { CoreProperties } from "file/core-properties";
|
import { CoreProperties } from "file/core-properties";
|
||||||
import { Attributes } from "file/xml-components";
|
import { Attributes } from "file/xml-components";
|
||||||
@ -45,18 +45,10 @@ describe("Formatter", () => {
|
|||||||
{
|
{
|
||||||
"w:rPr": [
|
"w:rPr": [
|
||||||
{
|
{
|
||||||
"w:b": {
|
"w:b": {},
|
||||||
_attr: {
|
|
||||||
"w:val": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"w:bCs": {
|
"w:bCs": {},
|
||||||
_attr: {
|
|
||||||
"w:val": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -36,7 +36,7 @@ describe("ImageReplacer", () => {
|
|||||||
describe("#getMediaData()", () => {
|
describe("#getMediaData()", () => {
|
||||||
it("should get media data", () => {
|
it("should get media data", () => {
|
||||||
const imageReplacer = new ImageReplacer();
|
const imageReplacer = new ImageReplacer();
|
||||||
const result = imageReplacer.getMediaData("test {test-image} test", ({
|
const result = imageReplacer.getMediaData("test {test-image} test", {
|
||||||
Array: [
|
Array: [
|
||||||
{
|
{
|
||||||
stream: Buffer.from(""),
|
stream: Buffer.from(""),
|
||||||
@ -53,7 +53,7 @@ describe("ImageReplacer", () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} as unknown) as Media);
|
} as unknown as Media);
|
||||||
|
|
||||||
expect(result).to.have.length(1);
|
expect(result).to.have.length(1);
|
||||||
});
|
});
|
||||||
|
@ -70,7 +70,6 @@ export class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping {
|
private xmlifyFile(file: File, prettify?: boolean): IXmlifyedFileMapping {
|
||||||
file.verifyUpdateFields();
|
|
||||||
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
const documentRelationshipCount = file.Document.Relationships.RelationshipCount + 1;
|
||||||
|
|
||||||
const documentXmlData = xml(
|
const documentXmlData = xml(
|
||||||
@ -78,7 +77,13 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
|
const documentMediaDatas = this.imageReplacer.getMediaData(documentXmlData, file.Media);
|
||||||
|
|
||||||
@ -98,7 +103,12 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
})(),
|
})(),
|
||||||
path: "word/_rels/document.xml.rels",
|
path: "word/_rels/document.xml.rels",
|
||||||
@ -113,13 +123,23 @@ export class Compiler {
|
|||||||
path: "word/document.xml",
|
path: "word/document.xml",
|
||||||
},
|
},
|
||||||
Styles: {
|
Styles: {
|
||||||
data: xml(
|
data: (() => {
|
||||||
|
const xmlStyles = xml(
|
||||||
this.formatter.format(file.Styles, {
|
this.formatter.format(file.Styles, {
|
||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
),
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const referencedXmlStyles = this.numberingReplacer.replace(xmlStyles, file.Numbering.ConcreteNumbering);
|
||||||
|
return referencedXmlStyles;
|
||||||
|
})(),
|
||||||
path: "word/styles.xml",
|
path: "word/styles.xml",
|
||||||
},
|
},
|
||||||
Properties: {
|
Properties: {
|
||||||
@ -129,6 +149,7 @@ export class Compiler {
|
|||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
indent: prettify,
|
||||||
declaration: {
|
declaration: {
|
||||||
standalone: "yes",
|
standalone: "yes",
|
||||||
encoding: "UTF-8",
|
encoding: "UTF-8",
|
||||||
@ -143,7 +164,13 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "word/numbering.xml",
|
path: "word/numbering.xml",
|
||||||
},
|
},
|
||||||
@ -153,7 +180,12 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "_rels/.rels",
|
path: "_rels/.rels",
|
||||||
},
|
},
|
||||||
@ -163,7 +195,12 @@ export class Compiler {
|
|||||||
viewWrapper: headerWrapper,
|
viewWrapper: headerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||||
|
|
||||||
@ -181,7 +218,12 @@ export class Compiler {
|
|||||||
viewWrapper: headerWrapper,
|
viewWrapper: headerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: `word/_rels/header${index + 1}.xml.rels`,
|
path: `word/_rels/header${index + 1}.xml.rels`,
|
||||||
};
|
};
|
||||||
@ -192,7 +234,12 @@ export class Compiler {
|
|||||||
viewWrapper: footerWrapper,
|
viewWrapper: footerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(xmlData, file.Media);
|
||||||
|
|
||||||
@ -210,7 +257,12 @@ export class Compiler {
|
|||||||
viewWrapper: footerWrapper,
|
viewWrapper: footerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: `word/_rels/footer${index + 1}.xml.rels`,
|
path: `word/_rels/footer${index + 1}.xml.rels`,
|
||||||
};
|
};
|
||||||
@ -221,7 +273,12 @@ export class Compiler {
|
|||||||
viewWrapper: headerWrapper,
|
viewWrapper: headerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
@ -238,7 +295,12 @@ export class Compiler {
|
|||||||
viewWrapper: footerWrapper,
|
viewWrapper: footerWrapper,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
const mediaDatas = this.imageReplacer.getMediaData(tempXmlData, file.Media);
|
||||||
// TODO: 0 needs to be changed when headers get relationships of their own
|
// TODO: 0 needs to be changed when headers get relationships of their own
|
||||||
@ -255,7 +317,12 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "[Content_Types].xml",
|
path: "[Content_Types].xml",
|
||||||
},
|
},
|
||||||
@ -265,7 +332,13 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "docProps/custom.xml",
|
path: "docProps/custom.xml",
|
||||||
},
|
},
|
||||||
@ -275,7 +348,13 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "docProps/app.xml",
|
path: "docProps/app.xml",
|
||||||
},
|
},
|
||||||
@ -285,7 +364,12 @@ export class Compiler {
|
|||||||
viewWrapper: file.FootNotes,
|
viewWrapper: file.FootNotes,
|
||||||
file: file,
|
file: file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "word/footnotes.xml",
|
path: "word/footnotes.xml",
|
||||||
},
|
},
|
||||||
@ -295,7 +379,12 @@ export class Compiler {
|
|||||||
viewWrapper: file.FootNotes,
|
viewWrapper: file.FootNotes,
|
||||||
file: file,
|
file: file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "word/_rels/footnotes.xml.rels",
|
path: "word/_rels/footnotes.xml.rels",
|
||||||
},
|
},
|
||||||
@ -305,7 +394,13 @@ export class Compiler {
|
|||||||
viewWrapper: file.Document,
|
viewWrapper: file.Document,
|
||||||
file,
|
file,
|
||||||
}),
|
}),
|
||||||
prettify,
|
{
|
||||||
|
indent: prettify,
|
||||||
|
declaration: {
|
||||||
|
standalone: "yes",
|
||||||
|
encoding: "UTF-8",
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
path: "word/settings.xml",
|
path: "word/settings.xml",
|
||||||
},
|
},
|
||||||
|
54
src/file/border/border.spec.ts
Normal file
54
src/file/border/border.spec.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
import { BorderStyle } from "file/border";
|
||||||
|
|
||||||
|
import { BorderElement } from "./border";
|
||||||
|
|
||||||
|
describe("BorderElement", () => {
|
||||||
|
describe("#constructor", () => {
|
||||||
|
it("should create a simple border element", () => {
|
||||||
|
const border = new BorderElement("w:top", {
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(border);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:top": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "single",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("should create a simple border element with a size", () => {
|
||||||
|
const border = new BorderElement("w:top", {
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
size: 22,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(border);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:top": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "single",
|
||||||
|
"w:sz": 22,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("should create a simple border element with space", () => {
|
||||||
|
const border = new BorderElement("w:top", {
|
||||||
|
style: BorderStyle.SINGLE,
|
||||||
|
space: 22,
|
||||||
|
});
|
||||||
|
const tree = new Formatter().format(border);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:top": {
|
||||||
|
_attr: {
|
||||||
|
"w:val": "single",
|
||||||
|
"w:space": 22,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
86
src/file/border/border.ts
Normal file
86
src/file/border/border.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// Note that the border type is identical in all places,
|
||||||
|
// regardless of where it's used like paragraph/table/etc.
|
||||||
|
// PageBorders are a superset, but we're not using any of those extras.
|
||||||
|
//
|
||||||
|
// http://officeopenxml.com/WPborders.php
|
||||||
|
// http://officeopenxml.com/WPtableBorders.php
|
||||||
|
// http://officeopenxml.com/WPtableCellProperties-Borders.php
|
||||||
|
// http://officeopenxml.com/WPsectionBorders.php
|
||||||
|
//
|
||||||
|
// This describes the CT_Border type.
|
||||||
|
// <xsd:complexType name="CT_Border">
|
||||||
|
// <xsd:attribute name="val" type="ST_Border" use="required"/>
|
||||||
|
// <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/>
|
||||||
|
// <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/>
|
||||||
|
// <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="sz" type="ST_EighthPointMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="space" type="ST_PointMeasure" use="optional" default="0"/>
|
||||||
|
// <xsd:attribute name="shadow" type="s:ST_OnOff" use="optional"/>
|
||||||
|
// <xsd:attribute name="frame" type="s:ST_OnOff" use="optional"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
import { eighthPointMeasureValue, hexColorValue, pointMeasureValue } from "../values";
|
||||||
|
|
||||||
|
export interface IBorderOptions {
|
||||||
|
readonly style: BorderStyle;
|
||||||
|
/** Border color, in hex (eg 'FF00AA') */
|
||||||
|
readonly color?: string;
|
||||||
|
/** Size of the border in 1/8 pt */
|
||||||
|
readonly size?: number;
|
||||||
|
/** Spacing offset. Values are specified in pt */
|
||||||
|
readonly space?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BorderElement extends XmlComponent {
|
||||||
|
constructor(elementName: string, { color, size, space, style }: IBorderOptions) {
|
||||||
|
super(elementName);
|
||||||
|
this.root.push(
|
||||||
|
new BordersAttributes({
|
||||||
|
style,
|
||||||
|
color: color === undefined ? undefined : hexColorValue(color),
|
||||||
|
size: size === undefined ? undefined : eighthPointMeasureValue(size),
|
||||||
|
space: space === undefined ? undefined : pointMeasureValue(space),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BordersAttributes extends XmlAttributeComponent<IBorderOptions> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
style: "w:val",
|
||||||
|
color: "w:color",
|
||||||
|
size: "w:sz",
|
||||||
|
space: "w:space",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BorderStyle {
|
||||||
|
SINGLE = "single",
|
||||||
|
DASH_DOT_STROKED = "dashDotStroked",
|
||||||
|
DASHED = "dashed",
|
||||||
|
DASH_SMALL_GAP = "dashSmallGap",
|
||||||
|
DOT_DASH = "dotDash",
|
||||||
|
DOT_DOT_DASH = "dotDotDash",
|
||||||
|
DOTTED = "dotted",
|
||||||
|
DOUBLE = "double",
|
||||||
|
DOUBLE_WAVE = "doubleWave",
|
||||||
|
INSET = "inset",
|
||||||
|
NIL = "nil",
|
||||||
|
NONE = "none",
|
||||||
|
OUTSET = "outset",
|
||||||
|
THICK = "thick",
|
||||||
|
THICK_THIN_LARGE_GAP = "thickThinLargeGap",
|
||||||
|
THICK_THIN_MEDIUM_GAP = "thickThinMediumGap",
|
||||||
|
THICK_THIN_SMALL_GAP = "thickThinSmallGap",
|
||||||
|
THIN_THICK_LARGE_GAP = "thinThickLargeGap",
|
||||||
|
THIN_THICK_MEDIUM_GAP = "thinThickMediumGap",
|
||||||
|
THIN_THICK_SMALL_GAP = "thinThickSmallGap",
|
||||||
|
THIN_THICK_THIN_LARGE_GAP = "thinThickThinLargeGap",
|
||||||
|
THIN_THICK_THIN_MEDIUM_GAP = "thinThickThinMediumGap",
|
||||||
|
THIN_THICK_THIN_SMALL_GAP = "thinThickThinSmallGap",
|
||||||
|
THREE_D_EMBOSS = "threeDEmboss",
|
||||||
|
THREE_D_ENGRAVE = "threeDEngrave",
|
||||||
|
TRIPLE = "triple",
|
||||||
|
WAVE = "wave",
|
||||||
|
}
|
1
src/file/border/index.ts
Normal file
1
src/file/border/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./border";
|
@ -1,89 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { DocumentAttributes } from "../document/document-attributes";
|
|
||||||
|
|
||||||
export class Title extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("dc:title");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Subject extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("dc:subject");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Creator extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("dc:creator");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Keywords extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("cp:keywords");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Description extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("dc:description");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LastModifiedBy extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("cp:lastModifiedBy");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Revision extends XmlComponent {
|
|
||||||
constructor(value: string) {
|
|
||||||
super("cp:revision");
|
|
||||||
this.root.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class DateComponent extends XmlComponent {
|
|
||||||
protected getCurrentDate(): string {
|
|
||||||
const date = new Date();
|
|
||||||
const year = date.getFullYear();
|
|
||||||
const month = ("0" + (date.getMonth() + 1)).slice(-2);
|
|
||||||
const day = ("0" + date.getDate()).slice(-2);
|
|
||||||
const hours = ("0" + date.getHours()).slice(-2);
|
|
||||||
const minutes = ("0" + date.getMinutes()).slice(-2);
|
|
||||||
const seconds = ("0" + date.getSeconds()).slice(-2);
|
|
||||||
|
|
||||||
return year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Created extends DateComponent {
|
|
||||||
constructor() {
|
|
||||||
super("dcterms:created");
|
|
||||||
this.root.push(
|
|
||||||
new DocumentAttributes({
|
|
||||||
type: "dcterms:W3CDTF",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
this.root.push(this.getCurrentDate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Modified extends DateComponent {
|
|
||||||
constructor() {
|
|
||||||
super("dcterms:modified");
|
|
||||||
this.root.push(
|
|
||||||
new DocumentAttributes({
|
|
||||||
type: "dcterms:W3CDTF",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
this.root.push(this.getCurrentDate());
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,8 +27,7 @@ describe("Properties", () => {
|
|||||||
const tree = new Formatter().format(properties);
|
const tree = new Formatter().format(properties);
|
||||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||||
expect(Object.keys(tree["cp:coreProperties"][0])).to.deep.equal(["_attr"]);
|
expect(tree["cp:coreProperties"]).to.deep.include({ "dc:title": ["test document"] });
|
||||||
expect(tree["cp:coreProperties"][1]).to.deep.equal({ "dc:title": ["test document"] });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create properties with all the attributes given", () => {
|
it("should create properties with all the attributes given", () => {
|
||||||
@ -44,9 +43,9 @@ describe("Properties", () => {
|
|||||||
const tree = new Formatter().format(properties);
|
const tree = new Formatter().format(properties);
|
||||||
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
expect(Object.keys(tree)).to.deep.equal(["cp:coreProperties"]);
|
||||||
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
expect(tree["cp:coreProperties"]).to.be.an.instanceof(Array);
|
||||||
|
|
||||||
const key = (obj) => Object.keys(obj)[0];
|
const key = (obj) => Object.keys(obj)[0];
|
||||||
const props = tree["cp:coreProperties"].map(key).sort();
|
expect(tree["cp:coreProperties"].map(key)).to.include.members([
|
||||||
expect(props).to.deep.equal([
|
|
||||||
"_attr",
|
"_attr",
|
||||||
"cp:keywords",
|
"cp:keywords",
|
||||||
"cp:lastModifiedBy",
|
"cp:lastModifiedBy",
|
||||||
@ -58,7 +57,7 @@ describe("Properties", () => {
|
|||||||
"dcterms:created",
|
"dcterms:created",
|
||||||
"dcterms:modified",
|
"dcterms:modified",
|
||||||
]);
|
]);
|
||||||
expect(tree["cp:coreProperties"].slice(1, -2).sort((a, b) => (key(a) < key(b) ? -1 : 1))).to.deep.equal([
|
expect(tree["cp:coreProperties"]).to.deep.include.members([
|
||||||
{ "cp:keywords": ["test docx"] },
|
{ "cp:keywords": ["test docx"] },
|
||||||
{ "cp:lastModifiedBy": ["the author"] },
|
{ "cp:lastModifiedBy": ["the author"] },
|
||||||
{ "cp:revision": ["123"] },
|
{ "cp:revision": ["123"] },
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
import { StringContainer, XmlComponent } from "file/xml-components";
|
||||||
import { ICustomPropertyOptions } from "../custom-properties";
|
import { ICustomPropertyOptions } from "../custom-properties";
|
||||||
import { IDocumentBackgroundOptions } from "../document";
|
import { IDocumentBackgroundOptions } from "../document";
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ import { ISectionOptions } from "../file";
|
|||||||
import { INumberingOptions } from "../numbering";
|
import { INumberingOptions } from "../numbering";
|
||||||
import { Paragraph } from "../paragraph";
|
import { Paragraph } from "../paragraph";
|
||||||
import { IStylesOptions } from "../styles";
|
import { IStylesOptions } from "../styles";
|
||||||
import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
|
import { dateTimeValue } from "../values";
|
||||||
|
|
||||||
export interface IPropertiesOptions {
|
export interface IPropertiesOptions {
|
||||||
readonly sections: ISectionOptions[];
|
readonly sections: ISectionOptions[];
|
||||||
@ -29,12 +29,35 @@ export interface IPropertiesOptions {
|
|||||||
readonly background?: IDocumentBackgroundOptions;
|
readonly background?: IDocumentBackgroundOptions;
|
||||||
readonly features?: {
|
readonly features?: {
|
||||||
readonly trackRevisions?: boolean;
|
readonly trackRevisions?: boolean;
|
||||||
|
readonly updateFields?: boolean;
|
||||||
};
|
};
|
||||||
readonly compatabilityModeVersion?: number;
|
readonly compatabilityModeVersion?: number;
|
||||||
readonly customProperties?: ICustomPropertyOptions[];
|
readonly customProperties?: ICustomPropertyOptions[];
|
||||||
readonly evenAndOddHeaderAndFooters?: boolean;
|
readonly evenAndOddHeaderAndFooters?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <xs:element name="coreProperties" type="CT_CoreProperties"/>
|
||||||
|
|
||||||
|
// <xs:complexType name="CT_CoreProperties">
|
||||||
|
// <xs:all>
|
||||||
|
// <xs:element name="category" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||||
|
// <xs:element name="contentStatus" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||||
|
// <xs:element ref="dcterms:created" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element ref="dc:creator" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element ref="dc:description" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element ref="dc:identifier" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element name="keywords" minOccurs="0" maxOccurs="1" type="CT_Keywords"/>
|
||||||
|
// <xs:element ref="dc:language" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element name="lastModifiedBy" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||||
|
// <xs:element name="lastPrinted" minOccurs="0" maxOccurs="1" type="xs:dateTime"/>
|
||||||
|
// <xs:element ref="dcterms:modified" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element name="revision" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||||
|
// <xs:element ref="dc:subject" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element ref="dc:title" minOccurs="0" maxOccurs="1"/>
|
||||||
|
// <xs:element name="version" minOccurs="0" maxOccurs="1" type="xs:string"/>
|
||||||
|
// </xs:all>
|
||||||
|
// </xs:complexType>
|
||||||
|
|
||||||
export class CoreProperties extends XmlComponent {
|
export class CoreProperties extends XmlComponent {
|
||||||
constructor(options: Omit<IPropertiesOptions, "sections">) {
|
constructor(options: Omit<IPropertiesOptions, "sections">) {
|
||||||
super("cp:coreProperties");
|
super("cp:coreProperties");
|
||||||
@ -48,27 +71,39 @@ export class CoreProperties extends XmlComponent {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if (options.title) {
|
if (options.title) {
|
||||||
this.root.push(new Title(options.title));
|
this.root.push(new StringContainer("dc:title", options.title));
|
||||||
}
|
}
|
||||||
if (options.subject) {
|
if (options.subject) {
|
||||||
this.root.push(new Subject(options.subject));
|
this.root.push(new StringContainer("dc:subject", options.subject));
|
||||||
}
|
}
|
||||||
if (options.creator) {
|
if (options.creator) {
|
||||||
this.root.push(new Creator(options.creator));
|
this.root.push(new StringContainer("dc:creator", options.creator));
|
||||||
}
|
}
|
||||||
if (options.keywords) {
|
if (options.keywords) {
|
||||||
this.root.push(new Keywords(options.keywords));
|
this.root.push(new StringContainer("cp:keywords", options.keywords));
|
||||||
}
|
}
|
||||||
if (options.description) {
|
if (options.description) {
|
||||||
this.root.push(new Description(options.description));
|
this.root.push(new StringContainer("dc:description", options.description));
|
||||||
}
|
}
|
||||||
if (options.lastModifiedBy) {
|
if (options.lastModifiedBy) {
|
||||||
this.root.push(new LastModifiedBy(options.lastModifiedBy));
|
this.root.push(new StringContainer("cp:lastModifiedBy", options.lastModifiedBy));
|
||||||
}
|
}
|
||||||
if (options.revision) {
|
if (options.revision) {
|
||||||
this.root.push(new Revision(options.revision));
|
this.root.push(new StringContainer("cp:revision", options.revision));
|
||||||
}
|
}
|
||||||
this.root.push(new Created());
|
this.root.push(new TimestampElement("dcterms:created"));
|
||||||
this.root.push(new Modified());
|
this.root.push(new TimestampElement("dcterms:modified"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimestampElement extends XmlComponent {
|
||||||
|
constructor(name: string) {
|
||||||
|
super(name);
|
||||||
|
this.root.push(
|
||||||
|
new DocumentAttributes({
|
||||||
|
type: "dcterms:W3CDTF",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.root.push(dateTimeValue(new Date()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Document, IDocumentOptions } from "./document";
|
import { Document, IDocumentOptions } from "./document";
|
||||||
import { Footer } from "./footer";
|
import { Footer } from "./footer/footer";
|
||||||
import { FootNotes } from "./footnotes";
|
import { FootNotes } from "./footnotes";
|
||||||
import { Header } from "./header/header";
|
import { Header } from "./header/header";
|
||||||
import { Relationships } from "./relationships";
|
import { Relationships } from "./relationships";
|
||||||
|
@ -3,6 +3,7 @@ import { expect } from "chai";
|
|||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { Body } from "./body";
|
import { Body } from "./body";
|
||||||
|
import { sectionMarginDefaults } from "./section-properties";
|
||||||
|
|
||||||
describe("Body", () => {
|
describe("Body", () => {
|
||||||
let body: Body;
|
let body: Body;
|
||||||
@ -32,24 +33,23 @@ describe("Body", () => {
|
|||||||
{
|
{
|
||||||
"w:pgMar": {
|
"w:pgMar": {
|
||||||
_attr: {
|
_attr: {
|
||||||
"w:top": 1440,
|
"w:top": sectionMarginDefaults.TOP,
|
||||||
"w:right": 1440,
|
"w:right": sectionMarginDefaults.RIGHT,
|
||||||
"w:bottom": 1440,
|
"w:bottom": sectionMarginDefaults.BOTTOM,
|
||||||
"w:left": 1440,
|
"w:left": sectionMarginDefaults.LEFT,
|
||||||
"w:header": 708,
|
"w:header": sectionMarginDefaults.HEADER,
|
||||||
"w:footer": 708,
|
"w:footer": sectionMarginDefaults.FOOTER,
|
||||||
"w:gutter": 0,
|
"w:gutter": sectionMarginDefaults.GUTTER,
|
||||||
"w:mirrorMargins": false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
|
|
||||||
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
|
|
||||||
{
|
{
|
||||||
"w:pgNumType": {
|
"w:pgNumType": {
|
||||||
_attr: {},
|
_attr: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// { "w:cols": { _attr: { "w:space": 708, "w:sep": false, "w:num": 1 } } },
|
||||||
|
{ "w:docGrid": { _attr: { "w:linePitch": 360 } } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
import { IContext, IXmlableObject, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
import { Paragraph, ParagraphProperties, TableOfContents } from "../..";
|
import { Paragraph, ParagraphProperties } from "../..";
|
||||||
import { ISectionPropertiesOptions, SectionProperties } from "./section-properties/section-properties";
|
import { ISectionPropertiesOptions, SectionProperties } from "./section-properties/section-properties";
|
||||||
|
|
||||||
export class Body extends XmlComponent {
|
export class Body extends XmlComponent {
|
||||||
@ -38,10 +38,6 @@ export class Body extends XmlComponent {
|
|||||||
this.root.push(component);
|
this.root.push(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTablesOfContents(): TableOfContents[] {
|
|
||||||
return this.root.filter((child) => child instanceof TableOfContents) as TableOfContents[];
|
|
||||||
}
|
|
||||||
|
|
||||||
private createSectionParagraph(section: SectionProperties): Paragraph {
|
private createSectionParagraph(section: SectionProperties): Paragraph {
|
||||||
const paragraph = new Paragraph({});
|
const paragraph = new Paragraph({});
|
||||||
const properties = new ParagraphProperties({});
|
const properties = new ParagraphProperties({});
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export class ColumnsAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly space?: number;
|
|
||||||
readonly num?: number;
|
|
||||||
readonly separate?: boolean;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
space: "w:space",
|
|
||||||
num: "w:num",
|
|
||||||
separate: "w:sep",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { ColumnsAttributes } from "./columns-attributes";
|
|
||||||
|
|
||||||
export class Columns extends XmlComponent {
|
|
||||||
constructor(space: number, num: number, separate: boolean) {
|
|
||||||
super("w:cols");
|
|
||||||
this.root.push(
|
|
||||||
new ColumnsAttributes({
|
|
||||||
space: space,
|
|
||||||
num: num,
|
|
||||||
separate: separate,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export interface IDocGridAttributesProperties {
|
|
||||||
readonly linePitch?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
linePitch: "w:linePitch",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { DocGridAttributes } from "./doc-grid-attributes";
|
|
||||||
|
|
||||||
export class DocumentGrid extends XmlComponent {
|
|
||||||
constructor(linePitch: number) {
|
|
||||||
super("w:docGrid");
|
|
||||||
this.root.push(
|
|
||||||
new DocGridAttributes({
|
|
||||||
linePitch: linePitch,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum FooterReferenceType {
|
|
||||||
DEFAULT = "default",
|
|
||||||
FIRST = "first",
|
|
||||||
EVEN = "even",
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FooterReferenceAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly type: string;
|
|
||||||
readonly id: string;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
type: "w:type",
|
|
||||||
id: "r:id",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
import { expect } from "chai";
|
|
||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
|
||||||
import { FooterReference } from "./footer-reference";
|
|
||||||
import { FooterReferenceType } from "./footer-reference-attributes";
|
|
||||||
|
|
||||||
describe("footerReference", () => {
|
|
||||||
it("should create", () => {
|
|
||||||
const footer = new FooterReference({
|
|
||||||
footerType: FooterReferenceType.DEFAULT,
|
|
||||||
footerId: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(footer);
|
|
||||||
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:footerReference": {
|
|
||||||
_attr: {
|
|
||||||
"r:id": "rId1",
|
|
||||||
"w:type": "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should create without a footer type", () => {
|
|
||||||
const footer = new FooterReference({
|
|
||||||
footerId: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(footer);
|
|
||||||
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:footerReference": {
|
|
||||||
_attr: {
|
|
||||||
"r:id": "rId1",
|
|
||||||
"w:type": "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,20 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { FooterReferenceAttributes, FooterReferenceType } from "./footer-reference-attributes";
|
|
||||||
|
|
||||||
export interface IFooterOptions {
|
|
||||||
readonly footerType?: FooterReferenceType;
|
|
||||||
readonly footerId?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FooterReference extends XmlComponent {
|
|
||||||
constructor(options: IFooterOptions) {
|
|
||||||
super("w:footerReference");
|
|
||||||
|
|
||||||
this.root.push(
|
|
||||||
new FooterReferenceAttributes({
|
|
||||||
type: options.footerType || FooterReferenceType.DEFAULT,
|
|
||||||
id: `rId${options.footerId}`,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from "./footer-reference";
|
|
||||||
export * from "./footer-reference-attributes";
|
|
@ -1,17 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum HeaderReferenceType {
|
|
||||||
DEFAULT = "default",
|
|
||||||
FIRST = "first",
|
|
||||||
EVEN = "even",
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HeaderReferenceAttributes extends XmlAttributeComponent<{
|
|
||||||
readonly type: string;
|
|
||||||
readonly id: string;
|
|
||||||
}> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
type: "w:type",
|
|
||||||
id: "r:id",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
import { expect } from "chai";
|
|
||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
|
||||||
import { HeaderReference } from "./header-reference";
|
|
||||||
import { HeaderReferenceType } from "./header-reference-attributes";
|
|
||||||
|
|
||||||
describe("HeaderReference", () => {
|
|
||||||
it("should create", () => {
|
|
||||||
const footer = new HeaderReference({
|
|
||||||
headerType: HeaderReferenceType.DEFAULT,
|
|
||||||
headerId: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(footer);
|
|
||||||
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:headerReference": {
|
|
||||||
_attr: {
|
|
||||||
"r:id": "rId1",
|
|
||||||
"w:type": "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should create without a header type", () => {
|
|
||||||
const footer = new HeaderReference({
|
|
||||||
headerId: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tree = new Formatter().format(footer);
|
|
||||||
|
|
||||||
expect(tree).to.deep.equal({
|
|
||||||
"w:headerReference": {
|
|
||||||
_attr: {
|
|
||||||
"r:id": "rId1",
|
|
||||||
"w:type": "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,19 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { HeaderReferenceAttributes, HeaderReferenceType } from "./header-reference-attributes";
|
|
||||||
|
|
||||||
export interface IHeaderReferenceOptions {
|
|
||||||
readonly headerType?: HeaderReferenceType;
|
|
||||||
readonly headerId?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HeaderReference extends XmlComponent {
|
|
||||||
constructor(options: IHeaderReferenceOptions) {
|
|
||||||
super("w:headerReference");
|
|
||||||
this.root.push(
|
|
||||||
new HeaderReferenceAttributes({
|
|
||||||
type: options.headerType || HeaderReferenceType.DEFAULT,
|
|
||||||
id: `rId${options.headerId}`,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from "./header-reference";
|
|
||||||
export * from "./header-reference-attributes";
|
|
@ -1,9 +1,2 @@
|
|||||||
export * from "./section-properties";
|
export * from "./section-properties";
|
||||||
export * from "./footer-reference";
|
export * from "./properties";
|
||||||
export * from "./header-reference";
|
|
||||||
export * from "./page-size";
|
|
||||||
export * from "./page-number";
|
|
||||||
export * from "./page-border";
|
|
||||||
export * from "./line-number";
|
|
||||||
export * from "./vertical-align";
|
|
||||||
export * from "./type";
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from "./line-number";
|
|
@ -1,38 +0,0 @@
|
|||||||
// http://officeopenxml.com/WPsectionLineNumbering.php
|
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum LineNumberRestartFormat {
|
|
||||||
CONTINUOUS = "continuous",
|
|
||||||
NEW_SECTION = "newSection",
|
|
||||||
NEW_PAGE = "newPage",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILineNumberAttributes {
|
|
||||||
readonly countBy?: number;
|
|
||||||
readonly start?: number;
|
|
||||||
readonly restart?: LineNumberRestartFormat;
|
|
||||||
readonly distance?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LineNumberAttributes extends XmlAttributeComponent<ILineNumberAttributes> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
countBy: "w:countBy",
|
|
||||||
start: "w:start",
|
|
||||||
restart: "w:restart",
|
|
||||||
distance: "w:distance",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LineNumberType extends XmlComponent {
|
|
||||||
constructor(countBy?: number, start?: number, restart?: LineNumberRestartFormat, dist?: number) {
|
|
||||||
super("w:lnNumType");
|
|
||||||
this.root.push(
|
|
||||||
new LineNumberAttributes({
|
|
||||||
countBy: countBy,
|
|
||||||
start: start,
|
|
||||||
restart: restart,
|
|
||||||
distance: dist,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from "./page-borders";
|
|
@ -1,100 +0,0 @@
|
|||||||
// http://officeopenxml.com/WPsectionBorders.php
|
|
||||||
import { BorderStyle } from "file/styles";
|
|
||||||
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum PageBorderDisplay {
|
|
||||||
ALL_PAGES = "allPages",
|
|
||||||
FIRST_PAGE = "firstPage",
|
|
||||||
NOT_FIRST_PAGE = "notFirstPage",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PageBorderOffsetFrom {
|
|
||||||
PAGE = "page",
|
|
||||||
TEXT = "text",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PageBorderZOrder {
|
|
||||||
BACK = "back",
|
|
||||||
FRONT = "front",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPageBorderAttributes {
|
|
||||||
readonly display?: PageBorderDisplay;
|
|
||||||
readonly offsetFrom?: PageBorderOffsetFrom;
|
|
||||||
readonly zOrder?: PageBorderZOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPageBorderConfiguration {
|
|
||||||
readonly style?: BorderStyle;
|
|
||||||
readonly size?: number;
|
|
||||||
readonly color?: string;
|
|
||||||
readonly space?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPageBordersOptions {
|
|
||||||
readonly pageBorders?: IPageBorderAttributes;
|
|
||||||
readonly pageBorderTop?: IPageBorderConfiguration;
|
|
||||||
readonly pageBorderRight?: IPageBorderConfiguration;
|
|
||||||
readonly pageBorderBottom?: IPageBorderConfiguration;
|
|
||||||
readonly pageBorderLeft?: IPageBorderConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PageBordeAttributes extends XmlAttributeComponent<IPageBorderConfiguration> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
style: "w:val",
|
|
||||||
size: "w:size",
|
|
||||||
color: "w:color",
|
|
||||||
space: "w:space",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class PageBorder extends XmlComponent {
|
|
||||||
constructor(key: string, options: IPageBorderConfiguration) {
|
|
||||||
super(key);
|
|
||||||
|
|
||||||
this.root.push(new PageBordeAttributes(options));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
display: "w:display",
|
|
||||||
offsetFrom: "w:offsetFrom",
|
|
||||||
zOrder: "w:zOrder",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PageBorders extends IgnoreIfEmptyXmlComponent {
|
|
||||||
constructor(options?: IPageBordersOptions) {
|
|
||||||
super("w:pgBorders");
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.pageBorders) {
|
|
||||||
this.root.push(
|
|
||||||
new PageBordersAttributes({
|
|
||||||
display: options.pageBorders.display,
|
|
||||||
offsetFrom: options.pageBorders.offsetFrom,
|
|
||||||
zOrder: options.pageBorders.zOrder,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.root.push(new PageBordersAttributes({}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.pageBorderTop) {
|
|
||||||
this.root.push(new PageBorder("w:top", options.pageBorderTop));
|
|
||||||
}
|
|
||||||
if (options.pageBorderRight) {
|
|
||||||
this.root.push(new PageBorder("w:right", options.pageBorderRight));
|
|
||||||
}
|
|
||||||
if (options.pageBorderBottom) {
|
|
||||||
this.root.push(new PageBorder("w:bottom", options.pageBorderBottom));
|
|
||||||
}
|
|
||||||
if (options.pageBorderLeft) {
|
|
||||||
this.root.push(new PageBorder("w:left", options.pageBorderLeft));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export interface IPageMarginAttributes {
|
|
||||||
readonly top?: number;
|
|
||||||
readonly right?: number;
|
|
||||||
readonly bottom?: number;
|
|
||||||
readonly left?: number;
|
|
||||||
readonly header?: number;
|
|
||||||
readonly footer?: number;
|
|
||||||
readonly gutter?: number;
|
|
||||||
readonly mirror?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
top: "w:top",
|
|
||||||
right: "w:right",
|
|
||||||
bottom: "w:bottom",
|
|
||||||
left: "w:left",
|
|
||||||
header: "w:header",
|
|
||||||
footer: "w:footer",
|
|
||||||
gutter: "w:gutter",
|
|
||||||
mirror: "w:mirrorMargins",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { PageMarginAttributes } from "./page-margin-attributes";
|
|
||||||
|
|
||||||
export class PageMargin extends XmlComponent {
|
|
||||||
constructor(top: number, right: number, bottom: number, left: number, header: number, footer: number, gutter: number, mirror: boolean) {
|
|
||||||
super("w:pgMar");
|
|
||||||
this.root.push(
|
|
||||||
new PageMarginAttributes({
|
|
||||||
top: top,
|
|
||||||
right: right,
|
|
||||||
bottom: bottom,
|
|
||||||
left: left,
|
|
||||||
header: header,
|
|
||||||
footer: footer,
|
|
||||||
gutter: gutter,
|
|
||||||
mirror: mirror,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from "./page-number";
|
|
@ -1,53 +0,0 @@
|
|||||||
// http://officeopenxml.com/WPSectionPgNumType.php
|
|
||||||
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum PageNumberFormat {
|
|
||||||
CARDINAL_TEXT = "cardinalText",
|
|
||||||
DECIMAL = "decimal",
|
|
||||||
DECIMAL_ENCLOSED_CIRCLE = "decimalEnclosedCircle",
|
|
||||||
DECIMAL_ENCLOSED_FULL_STOP = "decimalEnclosedFullstop",
|
|
||||||
DECIMAL_ENCLOSED_PAREN = "decimalEnclosedParen",
|
|
||||||
DECIMAL_ZERO = "decimalZero",
|
|
||||||
LOWER_LETTER = "lowerLetter",
|
|
||||||
LOWER_ROMAN = "lowerRoman",
|
|
||||||
NONE = "none",
|
|
||||||
ORDINAL_TEXT = "ordinalText",
|
|
||||||
UPPER_LETTER = "upperLetter",
|
|
||||||
UPPER_ROMAN = "upperRoman",
|
|
||||||
DECIMAL_FULL_WIDTH = "decimalFullWidth",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PageNumberSeparator {
|
|
||||||
COLON = "colon",
|
|
||||||
EM_DASH = "emDash",
|
|
||||||
EN_DASH = "endash",
|
|
||||||
HYPHEN = "hyphen",
|
|
||||||
PERIOD = "period",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPageNumberTypeAttributes {
|
|
||||||
readonly start?: number;
|
|
||||||
readonly formatType?: PageNumberFormat;
|
|
||||||
readonly separator?: PageNumberSeparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
start: "w:start",
|
|
||||||
formatType: "w:fmt",
|
|
||||||
separator: "w:chapSep",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PageNumberType extends XmlComponent {
|
|
||||||
constructor(start?: number, numberFormat?: PageNumberFormat, separator?: PageNumberSeparator) {
|
|
||||||
super("w:pgNumType");
|
|
||||||
this.root.push(
|
|
||||||
new PageNumberTypeAttributes({
|
|
||||||
start: start,
|
|
||||||
formatType: numberFormat,
|
|
||||||
separator: separator,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export * from "./page-size";
|
|
||||||
export * from "./page-size-attributes";
|
|
@ -1,20 +0,0 @@
|
|||||||
import { XmlAttributeComponent } from "file/xml-components";
|
|
||||||
|
|
||||||
export enum PageOrientation {
|
|
||||||
PORTRAIT = "portrait",
|
|
||||||
LANDSCAPE = "landscape",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPageSizeAttributes {
|
|
||||||
readonly width?: number;
|
|
||||||
readonly height?: number;
|
|
||||||
readonly orientation?: PageOrientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
|
||||||
protected readonly xmlKeys = {
|
|
||||||
width: "w:w",
|
|
||||||
height: "w:h",
|
|
||||||
orientation: "w:orient",
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
import { XmlComponent } from "file/xml-components";
|
|
||||||
import { PageOrientation, PageSizeAttributes } from "./page-size-attributes";
|
|
||||||
|
|
||||||
export class PageSize extends XmlComponent {
|
|
||||||
constructor(width: number, height: number, orientation: PageOrientation) {
|
|
||||||
super("w:pgSz");
|
|
||||||
|
|
||||||
const flip = orientation === PageOrientation.LANDSCAPE;
|
|
||||||
|
|
||||||
this.root.push(
|
|
||||||
new PageSizeAttributes({
|
|
||||||
width: flip ? height : width,
|
|
||||||
height: flip ? width : height,
|
|
||||||
orientation: orientation,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,26 @@
|
|||||||
|
import { twipsMeasureValue } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
export interface IColumnAttributes {
|
||||||
|
readonly width: number | string;
|
||||||
|
readonly space?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColumnAttributes extends XmlAttributeComponent<IColumnAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
width: "w:w",
|
||||||
|
space: "w:space",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Column extends XmlComponent {
|
||||||
|
constructor({ width, space }: IColumnAttributes) {
|
||||||
|
super("w:col");
|
||||||
|
this.root.push(
|
||||||
|
new ColumnAttributes({
|
||||||
|
width: twipsMeasureValue(width),
|
||||||
|
space: space === undefined ? undefined : twipsMeasureValue(space),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
|
import { Column, Columns } from ".";
|
||||||
|
|
||||||
|
describe("Columns", () => {
|
||||||
|
describe("#constructor()", () => {
|
||||||
|
it("should create columns of equal width if equalWidth is true", () => {
|
||||||
|
const columns = new Columns({ count: 3, space: 720 });
|
||||||
|
const tree = new Formatter().format(columns);
|
||||||
|
|
||||||
|
expect(tree["w:cols"]).to.deep.equal({ _attr: { "w:num": 3, "w:space": 720 } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should ignore individual column attributes if equalWidth is true", () => {
|
||||||
|
const unequalColumns = [new Column({ width: 1000, space: 400 }), new Column({ width: 2000 })];
|
||||||
|
const columns = new Columns({ count: 3, space: 720, equalWidth: true, children: unequalColumns });
|
||||||
|
const tree = new Formatter().format(columns);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({ "w:cols": { _attr: { "w:num": 3, "w:space": 720, "w:equalWidth": true } } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have column children if equalWidth is false and individual columns are provided", () => {
|
||||||
|
const unequalColumns = [new Column({ width: 1000, space: 400 }), new Column({ width: 2000 })];
|
||||||
|
const columns = new Columns({ count: 3, space: 720, equalWidth: false, children: unequalColumns });
|
||||||
|
const tree = new Formatter().format(columns);
|
||||||
|
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:cols": [
|
||||||
|
{ _attr: { "w:num": 3, "w:space": 720, "w:equalWidth": false } },
|
||||||
|
{ "w:col": { _attr: { "w:space": 400, "w:w": 1000 } } },
|
||||||
|
{ "w:col": { _attr: { "w:w": 2000 } } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,47 @@
|
|||||||
|
import { decimalNumber, twipsMeasureValue } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
import { Column } from "./column";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_Columns">
|
||||||
|
// <xsd:sequence minOccurs="0">
|
||||||
|
// <xsd:element name="col" type="CT_Column" maxOccurs="45"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="equalWidth" type="s:ST_OnOff" use="optional"/>
|
||||||
|
// <xsd:attribute name="space" type="s:ST_TwipsMeasure" use="optional" default="720"/>
|
||||||
|
// <xsd:attribute name="num" type="ST_DecimalNumber" use="optional" default="1"/>
|
||||||
|
// <xsd:attribute name="sep" type="s:ST_OnOff" use="optional"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export interface IColumnsAttributes {
|
||||||
|
readonly space?: number | string;
|
||||||
|
readonly count?: number;
|
||||||
|
readonly separate?: boolean;
|
||||||
|
readonly equalWidth?: boolean;
|
||||||
|
readonly children?: Column[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ColumnsAttributes extends XmlAttributeComponent<IColumnsAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
space: "w:space",
|
||||||
|
count: "w:num",
|
||||||
|
separate: "w:sep",
|
||||||
|
equalWidth: "w:equalWidth",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Columns extends XmlComponent {
|
||||||
|
constructor({ space, count, separate, equalWidth, children }: IColumnsAttributes) {
|
||||||
|
super("w:cols");
|
||||||
|
this.root.push(
|
||||||
|
new ColumnsAttributes({
|
||||||
|
space: space === undefined ? undefined : twipsMeasureValue(space),
|
||||||
|
count: count === undefined ? undefined : decimalNumber(count),
|
||||||
|
separate,
|
||||||
|
equalWidth,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!equalWidth && children) {
|
||||||
|
children.forEach((column) => this.addChildElement(column));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
import { decimalNumber } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// not implemented
|
||||||
|
// <xsd:simpleType name="ST_DocGrid">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="default"/>
|
||||||
|
// <xsd:enumeration value="lines"/>
|
||||||
|
// <xsd:enumeration value="linesAndChars"/>
|
||||||
|
// <xsd:enumeration value="snapToChars"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_DocGrid">
|
||||||
|
// <xsd:attribute name="type" type="ST_DocGrid"/>
|
||||||
|
// <xsd:attribute name="linePitch" type="ST_DecimalNumber"/>
|
||||||
|
// <xsd:attribute name="charSpace" type="ST_DecimalNumber"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export interface IDocGridAttributesProperties {
|
||||||
|
readonly linePitch?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DocGridAttributes extends XmlAttributeComponent<IDocGridAttributesProperties> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
linePitch: "w:linePitch",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DocumentGrid extends XmlComponent {
|
||||||
|
constructor(linePitch: number) {
|
||||||
|
super("w:docGrid");
|
||||||
|
this.root.push(
|
||||||
|
new DocGridAttributes({
|
||||||
|
linePitch: decimalNumber(linePitch),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
import { expect } from "chai";
|
||||||
|
|
||||||
|
import { Formatter } from "export/formatter";
|
||||||
|
import { HeaderFooterReference, HeaderFooterReferenceType, HeaderFooterType } from "./header-footer-reference";
|
||||||
|
|
||||||
|
describe("HeaderFooterReference", () => {
|
||||||
|
it("#constructor (footer)", () => {
|
||||||
|
const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
|
||||||
|
type: HeaderFooterReferenceType.DEFAULT,
|
||||||
|
id: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(footer);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:footerReference": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId1",
|
||||||
|
"w:type": "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("#constructor (header)", () => {
|
||||||
|
const header = new HeaderFooterReference(HeaderFooterType.HEADER, {
|
||||||
|
type: HeaderFooterReferenceType.DEFAULT,
|
||||||
|
id: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(header);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:headerReference": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId1",
|
||||||
|
"w:type": "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create without a type", () => {
|
||||||
|
const footer = new HeaderFooterReference(HeaderFooterType.FOOTER, {
|
||||||
|
id: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree = new Formatter().format(footer);
|
||||||
|
expect(tree).to.deep.equal({
|
||||||
|
"w:footerReference": {
|
||||||
|
_attr: {
|
||||||
|
"r:id": "rId1",
|
||||||
|
"w:type": "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,65 @@
|
|||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_HdrFtr">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="even"/>
|
||||||
|
// <xsd:enumeration value="default"/>
|
||||||
|
// <xsd:enumeration value="first"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum HeaderFooterReferenceType {
|
||||||
|
DEFAULT = "default",
|
||||||
|
FIRST = "first",
|
||||||
|
EVEN = "even",
|
||||||
|
}
|
||||||
|
|
||||||
|
// </xsd:complexType>
|
||||||
|
// <xsd:group name="EG_HdrFtrReferences">
|
||||||
|
// <xsd:choice>
|
||||||
|
// <xsd:element name="headerReference" type="CT_HdrFtrRef" minOccurs="0"/>
|
||||||
|
// <xsd:element name="footerReference" type="CT_HdrFtrRef" minOccurs="0"/>
|
||||||
|
// </xsd:choice>
|
||||||
|
// </xsd:group>
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_HdrFtrRef">
|
||||||
|
// <xsd:complexContent>
|
||||||
|
// <xsd:extension base="CT_Rel">
|
||||||
|
// <xsd:attribute name="type" type="ST_HdrFtr" use="required"/>
|
||||||
|
// </xsd:extension>
|
||||||
|
// </xsd:complexContent>
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_Rel">
|
||||||
|
// <xsd:attribute ref="r:id" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
export interface IHeaderFooterOptions {
|
||||||
|
readonly type?: HeaderFooterReferenceType;
|
||||||
|
readonly id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FooterReferenceAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly type: HeaderFooterReferenceType;
|
||||||
|
readonly id: string;
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
type: "w:type",
|
||||||
|
id: "r:id",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum HeaderFooterType {
|
||||||
|
HEADER = "w:headerReference",
|
||||||
|
FOOTER = "w:footerReference",
|
||||||
|
}
|
||||||
|
export class HeaderFooterReference extends XmlComponent {
|
||||||
|
constructor(type: HeaderFooterType, options: IHeaderFooterOptions) {
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new FooterReferenceAttributes({
|
||||||
|
type: options.type || HeaderFooterReferenceType.DEFAULT,
|
||||||
|
id: `rId${options.id}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
export * from "./column";
|
||||||
|
export * from "./columns";
|
||||||
|
export * from "./doc-grid";
|
||||||
|
// export * from "./header-reference";
|
||||||
|
export * from "./page-size";
|
||||||
|
export * from "./page-number";
|
||||||
|
export * from "./page-borders";
|
||||||
|
export * from "./page-margin";
|
||||||
|
export * from "./page-borders";
|
||||||
|
export * from "./line-number";
|
||||||
|
export * from "./section-type";
|
||||||
|
export * from "./header-footer-reference";
|
@ -0,0 +1,53 @@
|
|||||||
|
// http://officeopenxml.com/WPsectionLineNumbering.php
|
||||||
|
import { decimalNumber, twipsMeasureValue } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_LineNumberRestart">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="newPage"/>
|
||||||
|
// <xsd:enumeration value="newSection"/>
|
||||||
|
// <xsd:enumeration value="continuous"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum LineNumberRestartFormat {
|
||||||
|
NEW_PAGE = "newPage",
|
||||||
|
NEW_SECTION = "newSection",
|
||||||
|
CONTINUOUS = "continuous",
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_LineNumber">
|
||||||
|
// <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="start" type="ST_DecimalNumber" use="optional" default="1"/>
|
||||||
|
// <xsd:attribute name="distance" type="s:ST_TwipsMeasure" use="optional"/>
|
||||||
|
// <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
export interface ILineNumberAttributes {
|
||||||
|
readonly countBy?: number;
|
||||||
|
readonly start?: number;
|
||||||
|
readonly restart?: LineNumberRestartFormat;
|
||||||
|
readonly distance?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LineNumberAttributes extends XmlAttributeComponent<ILineNumberAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
countBy: "w:countBy",
|
||||||
|
start: "w:start",
|
||||||
|
restart: "w:restart",
|
||||||
|
distance: "w:distance",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LineNumberType extends XmlComponent {
|
||||||
|
constructor({ countBy, start, restart, distance }: ILineNumberAttributes) {
|
||||||
|
super("w:lnNumType");
|
||||||
|
this.root.push(
|
||||||
|
new LineNumberAttributes({
|
||||||
|
countBy: countBy === undefined ? undefined : decimalNumber(countBy),
|
||||||
|
start: start === undefined ? undefined : decimalNumber(start),
|
||||||
|
restart,
|
||||||
|
distance: distance === undefined ? undefined : twipsMeasureValue(distance),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
import { BorderStyle } from "file/styles";
|
import { BorderStyle } from "file/border";
|
||||||
|
|
||||||
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
|
import { PageBorderDisplay, PageBorders, PageBorderZOrder } from "./page-borders";
|
||||||
|
|
||||||
@ -70,22 +70,22 @@ describe("PageBorders", () => {
|
|||||||
expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage", "w:zOrder": "back" } });
|
expect(tree["w:pgBorders"][0]).to.deep.equal({ _attr: { "w:display": "firstPage", "w:zOrder": "back" } });
|
||||||
expect(tree["w:pgBorders"][1]).to.deep.equal({
|
expect(tree["w:pgBorders"][1]).to.deep.equal({
|
||||||
"w:top": {
|
"w:top": {
|
||||||
_attr: { "w:color": "001122", "w:size": 10, "w:val": "doubleWave" },
|
_attr: { "w:color": "001122", "w:sz": 10, "w:val": "doubleWave" },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["w:pgBorders"][2]).to.deep.equal({
|
expect(tree["w:pgBorders"][2]).to.deep.equal({
|
||||||
"w:right": {
|
"w:left": {
|
||||||
_attr: { "w:color": "223344", "w:size": 20, "w:val": "double" },
|
_attr: { "w:color": "889900", "w:sz": 40, "w:val": "dotted" },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["w:pgBorders"][3]).to.deep.equal({
|
expect(tree["w:pgBorders"][3]).to.deep.equal({
|
||||||
"w:bottom": {
|
"w:bottom": {
|
||||||
_attr: { "w:color": "556677", "w:size": 30, "w:val": "single" },
|
_attr: { "w:color": "556677", "w:sz": 30, "w:val": "single" },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(tree["w:pgBorders"][4]).to.deep.equal({
|
expect(tree["w:pgBorders"][4]).to.deep.equal({
|
||||||
"w:left": {
|
"w:right": {
|
||||||
_attr: { "w:color": "889900", "w:size": 40, "w:val": "dotted" },
|
_attr: { "w:color": "223344", "w:sz": 20, "w:val": "double" },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -0,0 +1,106 @@
|
|||||||
|
// http://officeopenxml.com/WPsectionBorders.php
|
||||||
|
import { BorderElement, IBorderOptions } from "file/border";
|
||||||
|
import { IgnoreIfEmptyXmlComponent, XmlAttributeComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PageBorderDisplay">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="allPages"/>
|
||||||
|
// <xsd:enumeration value="firstPage"/>
|
||||||
|
// <xsd:enumeration value="notFirstPage"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum PageBorderDisplay {
|
||||||
|
ALL_PAGES = "allPages",
|
||||||
|
FIRST_PAGE = "firstPage",
|
||||||
|
NOT_FIRST_PAGE = "notFirstPage",
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PageBorderOffset">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="page"/>
|
||||||
|
// <xsd:enumeration value="text"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum PageBorderOffsetFrom {
|
||||||
|
PAGE = "page",
|
||||||
|
TEXT = "text",
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PageBorderZOrder">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="front"/>
|
||||||
|
// <xsd:enumeration value="back"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum PageBorderZOrder {
|
||||||
|
BACK = "back",
|
||||||
|
FRONT = "front",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPageBorderAttributes {
|
||||||
|
readonly display?: PageBorderDisplay;
|
||||||
|
readonly offsetFrom?: PageBorderOffsetFrom;
|
||||||
|
readonly zOrder?: PageBorderZOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPageBordersOptions {
|
||||||
|
readonly pageBorders?: IPageBorderAttributes;
|
||||||
|
readonly pageBorderTop?: IBorderOptions;
|
||||||
|
readonly pageBorderRight?: IBorderOptions;
|
||||||
|
readonly pageBorderBottom?: IBorderOptions;
|
||||||
|
readonly pageBorderLeft?: IBorderOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PageBordersAttributes extends XmlAttributeComponent<IPageBorderAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
display: "w:display",
|
||||||
|
offsetFrom: "w:offsetFrom",
|
||||||
|
zOrder: "w:zOrder",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_PageBorders">
|
||||||
|
// <xsd:sequence>
|
||||||
|
// <xsd:element name="top" type="CT_TopPageBorder" minOccurs="0"/>
|
||||||
|
// <xsd:element name="left" type="CT_PageBorder" minOccurs="0"/>
|
||||||
|
// <xsd:element name="bottom" type="CT_BottomPageBorder" minOccurs="0"/>
|
||||||
|
// <xsd:element name="right" type="CT_PageBorder" minOccurs="0"/>
|
||||||
|
// </xsd:sequence>
|
||||||
|
// <xsd:attribute name="zOrder" type="ST_PageBorderZOrder" use="optional" default="front"/>
|
||||||
|
// <xsd:attribute name="display" type="ST_PageBorderDisplay" use="optional"/>
|
||||||
|
// <xsd:attribute name="offsetFrom" type="ST_PageBorderOffset" use="optional" default="text"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export class PageBorders extends IgnoreIfEmptyXmlComponent {
|
||||||
|
constructor(options?: IPageBordersOptions) {
|
||||||
|
super("w:pgBorders");
|
||||||
|
|
||||||
|
if (!options) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.pageBorders) {
|
||||||
|
this.root.push(
|
||||||
|
new PageBordersAttributes({
|
||||||
|
display: options.pageBorders.display,
|
||||||
|
offsetFrom: options.pageBorders.offsetFrom,
|
||||||
|
zOrder: options.pageBorders.zOrder,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.root.push(new PageBordersAttributes({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.pageBorderTop) {
|
||||||
|
this.root.push(new BorderElement("w:top", options.pageBorderTop));
|
||||||
|
}
|
||||||
|
if (options.pageBorderLeft) {
|
||||||
|
this.root.push(new BorderElement("w:left", options.pageBorderLeft));
|
||||||
|
}
|
||||||
|
if (options.pageBorderBottom) {
|
||||||
|
this.root.push(new BorderElement("w:bottom", options.pageBorderBottom));
|
||||||
|
}
|
||||||
|
if (options.pageBorderRight) {
|
||||||
|
this.root.push(new BorderElement("w:right", options.pageBorderRight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
import { signedTwipsMeasureValue, twipsMeasureValue } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_PageMar">
|
||||||
|
// <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="right" type="s:ST_TwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="bottom" type="ST_SignedTwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="left" type="s:ST_TwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="header" type="s:ST_TwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/>
|
||||||
|
// <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export interface IPageMarginAttributes {
|
||||||
|
readonly top?: number | string;
|
||||||
|
readonly right?: number | string;
|
||||||
|
readonly bottom?: number | string;
|
||||||
|
readonly left?: number | string;
|
||||||
|
readonly header?: number | string;
|
||||||
|
readonly footer?: number | string;
|
||||||
|
readonly gutter?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageMarginAttributes extends XmlAttributeComponent<IPageMarginAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
top: "w:top",
|
||||||
|
right: "w:right",
|
||||||
|
bottom: "w:bottom",
|
||||||
|
left: "w:left",
|
||||||
|
header: "w:header",
|
||||||
|
footer: "w:footer",
|
||||||
|
gutter: "w:gutter",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageMargin extends XmlComponent {
|
||||||
|
constructor(
|
||||||
|
top: number | string,
|
||||||
|
right: number | string,
|
||||||
|
bottom: number | string,
|
||||||
|
left: number | string,
|
||||||
|
header: number | string,
|
||||||
|
footer: number | string,
|
||||||
|
gutter: number | string,
|
||||||
|
) {
|
||||||
|
super("w:pgMar");
|
||||||
|
this.root.push(
|
||||||
|
new PageMarginAttributes({
|
||||||
|
top: signedTwipsMeasureValue(top),
|
||||||
|
right: twipsMeasureValue(right),
|
||||||
|
bottom: signedTwipsMeasureValue(bottom),
|
||||||
|
left: twipsMeasureValue(left),
|
||||||
|
header: twipsMeasureValue(header),
|
||||||
|
footer: twipsMeasureValue(footer),
|
||||||
|
gutter: twipsMeasureValue(gutter),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
// http://officeopenxml.com/WPSectionPgNumType.php
|
||||||
|
import { NumberFormat } from "file/shared/number-format";
|
||||||
|
import { decimalNumber } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_ChapterSep">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="hyphen"/>
|
||||||
|
// <xsd:enumeration value="period"/>
|
||||||
|
// <xsd:enumeration value="colon"/>
|
||||||
|
// <xsd:enumeration value="emDash"/>
|
||||||
|
// <xsd:enumeration value="enDash"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum PageNumberSeparator {
|
||||||
|
HYPHEN = "hyphen",
|
||||||
|
PERIOD = "period",
|
||||||
|
COLON = "colon",
|
||||||
|
EM_DASH = "emDash",
|
||||||
|
EN_DASH = "endash",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPageNumberTypeAttributes {
|
||||||
|
readonly start?: number;
|
||||||
|
readonly formatType?: NumberFormat;
|
||||||
|
readonly separator?: PageNumberSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_PageNumber">
|
||||||
|
// <xsd:attribute name="fmt" type="ST_NumberFormat" use="optional" default="decimal"/>
|
||||||
|
// <xsd:attribute name="start" type="ST_DecimalNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="chapStyle" type="ST_DecimalNumber" use="optional"/>
|
||||||
|
// <xsd:attribute name="chapSep" type="ST_ChapterSep" use="optional" default="hyphen"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
|
||||||
|
export class PageNumberTypeAttributes extends XmlAttributeComponent<IPageNumberTypeAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
start: "w:start",
|
||||||
|
formatType: "w:fmt",
|
||||||
|
separator: "w:chapSep",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export class PageNumberType extends XmlComponent {
|
||||||
|
constructor({ start, formatType, separator }: IPageNumberTypeAttributes) {
|
||||||
|
super("w:pgNumType");
|
||||||
|
this.root.push(
|
||||||
|
new PageNumberTypeAttributes({
|
||||||
|
start: start === undefined ? undefined : decimalNumber(start),
|
||||||
|
formatType,
|
||||||
|
separator,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,7 @@ import { expect } from "chai";
|
|||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
|
|
||||||
import { PageSize } from "./page-size";
|
import { PageOrientation, PageSize } from "./page-size";
|
||||||
import { PageOrientation } from "./page-size-attributes";
|
|
||||||
|
|
||||||
describe("PageSize", () => {
|
describe("PageSize", () => {
|
||||||
describe("#constructor()", () => {
|
describe("#constructor()", () => {
|
@ -0,0 +1,52 @@
|
|||||||
|
import { twipsMeasureValue } from "file/values";
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_PageOrientation">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="portrait"/>
|
||||||
|
// <xsd:enumeration value="landscape"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum PageOrientation {
|
||||||
|
PORTRAIT = "portrait",
|
||||||
|
LANDSCAPE = "landscape",
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_PageSz">
|
||||||
|
// <xsd:attribute name="w" type="s:ST_TwipsMeasure"/>
|
||||||
|
// <xsd:attribute name="h" type="s:ST_TwipsMeasure"/>
|
||||||
|
// <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/>
|
||||||
|
// <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export interface IPageSizeAttributes {
|
||||||
|
readonly width?: number | string;
|
||||||
|
readonly height?: number | string;
|
||||||
|
readonly orientation?: PageOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageSizeAttributes extends XmlAttributeComponent<IPageSizeAttributes> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
width: "w:w",
|
||||||
|
height: "w:h",
|
||||||
|
orientation: "w:orient",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PageSize extends XmlComponent {
|
||||||
|
constructor(width: number | string, height: number | string, orientation: PageOrientation) {
|
||||||
|
super("w:pgSz");
|
||||||
|
|
||||||
|
const flip = orientation === PageOrientation.LANDSCAPE;
|
||||||
|
|
||||||
|
const widthTwips = twipsMeasureValue(width);
|
||||||
|
const heightTwips = twipsMeasureValue(height);
|
||||||
|
|
||||||
|
this.root.push(
|
||||||
|
new PageSizeAttributes({
|
||||||
|
width: flip ? heightTwips : widthTwips,
|
||||||
|
height: flip ? widthTwips : heightTwips,
|
||||||
|
orientation: orientation,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { Formatter } from "export/formatter";
|
import { Formatter } from "export/formatter";
|
||||||
import { Type } from "./section-type";
|
import { SectionType, Type } from "./section-type";
|
||||||
import { SectionType } from "./section-type-attributes";
|
|
||||||
|
|
||||||
describe("Type", () => {
|
describe("Type", () => {
|
||||||
it("should create with even page section type", () => {
|
it("should create with even page section type", () => {
|
@ -0,0 +1,37 @@
|
|||||||
|
// http://officeopenxml.com/WPsection.php
|
||||||
|
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
|
||||||
|
|
||||||
|
// <xsd:simpleType name="ST_SectionMark">
|
||||||
|
// <xsd:restriction base="xsd:string">
|
||||||
|
// <xsd:enumeration value="nextPage"/>
|
||||||
|
// <xsd:enumeration value="nextColumn"/>
|
||||||
|
// <xsd:enumeration value="continuous"/>
|
||||||
|
// <xsd:enumeration value="evenPage"/>
|
||||||
|
// <xsd:enumeration value="oddPage"/>
|
||||||
|
// </xsd:restriction>
|
||||||
|
// </xsd:simpleType>
|
||||||
|
export enum SectionType {
|
||||||
|
NEXT_PAGE = "nextPage",
|
||||||
|
NEXT_COLUMN = "nextColumn",
|
||||||
|
CONTINUOUS = "continuous",
|
||||||
|
EVEN_PAGE = "evenPage",
|
||||||
|
ODD_PAGE = "oddPage",
|
||||||
|
}
|
||||||
|
|
||||||
|
// <xsd:complexType name="CT_SectType">
|
||||||
|
// <xsd:attribute name="val" type="ST_SectionMark"/>
|
||||||
|
// </xsd:complexType>
|
||||||
|
export class SectionTypeAttributes extends XmlAttributeComponent<{
|
||||||
|
readonly val: SectionType;
|
||||||
|
}> {
|
||||||
|
protected readonly xmlKeys = {
|
||||||
|
val: "w:val",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Type extends XmlComponent {
|
||||||
|
constructor(value: SectionType) {
|
||||||
|
super("w:type");
|
||||||
|
this.root.push(new SectionTypeAttributes({ val: value }));
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user