Compare commits

..

232 Commits
1.0.1 ... 2.1.0

Author SHA1 Message Date
b0a29e26c9 Version bump 2017-07-07 14:36:34 +01:00
8826fb010d Added types to package json 2017-07-07 14:34:03 +01:00
97101adb10 Enabled declarations in tsconfig to be true 2017-07-07 14:31:08 +01:00
2ec171d4a8 Used my updated typings for archiver 1.3 2017-05-09 18:03:31 +01:00
8876bb1fea updated readme about demos 2017-04-17 19:53:53 +01:00
96ca9d9c23 commented out the rm 2017-04-17 16:36:56 +01:00
74a65f02fa remove exit code 2017-04-17 16:07:28 +01:00
339c017940 edited rm function 2017-04-17 15:41:03 +01:00
969b52ae05 added nojekyll to gh-pages 2017-04-17 13:24:43 +01:00
eb8f0f4033 added debugging to deployment 2017-04-17 13:05:02 +01:00
d7229eb049 removed rimraf 2017-04-16 12:41:24 +01:00
644819ed81 added deployment keys and scripts 2017-04-16 12:22:50 +01:00
96fd61d3e4 using stable version of node 2017-04-16 02:25:44 +01:00
b96cfe7b19 git fetch added 2017-04-16 01:29:29 +01:00
d0e7c97a88 added commit message with merge with gh pages 2017-04-16 01:18:22 +01:00
0ede54cfdc added travis doc deployment solution 2017-04-16 01:12:42 +01:00
5be1163549 remove docs in gitignore 2017-04-16 01:07:11 +01:00
580f6eb633 fixed tests 2017-04-16 00:44:35 +01:00
321be35918 added docs in gitignore 2017-04-16 00:30:27 +01:00
45a18742d7 moved documentation to gh-pages branch 2017-04-16 00:22:29 +01:00
7e81da404a updated readme 2017-04-16 00:09:07 +01:00
6c2abb4abc added typedoc generated docs 2017-04-16 00:07:16 +01:00
e8b0dbf93b added docs ignore to npmignore file 2017-04-16 00:04:29 +01:00
e59c255d85 added type to pack param 2017-04-15 23:45:27 +01:00
17b28cb724 fixed more linting issues 2017-04-15 20:11:54 +01:00
410152441b fixed tslinting issues 2017-04-15 17:54:47 +01:00
dfff4b96bd updated tslint to 5.1.0 2017-04-15 17:47:29 +01:00
72cb75a486 added comma 2017-04-15 17:46:56 +01:00
53fe1dd988 added typedoc support for generating documentation 2017-04-15 17:46:11 +01:00
043219f005 Merge pull request #32 from felipeochoa/keep-lines
add keepLines and keepNext support for paragraph formatting
2017-04-15 17:41:11 +01:00
0453f28951 add keepLines and keepNext support for paragraph formatting
This commit adds it to the three places where paragraph formatting can
be applied right now (directly on the paragraph, paragraph styles, and
bullets/numbering styles). I'm separately adding an entry to the wiki
regarding what these methods do (widow/orphan control)
2017-04-14 21:13:11 +02:00
94716e081b Merge pull request #31 from felipeochoa/spacing-bugfix
Spacing bugfix
2017-04-14 17:30:54 +01:00
30f826fd3d made a mini app which you can select the demo you want from a list with an interactive prompt. 2017-04-14 15:48:12 +01:00
99b7a03b8a update demo2 to test space preservation 2017-04-14 11:09:08 +02:00
b1c8b2beb8 add xml:space="preserve" to text runs
In MS Word 2015 (and possibly others), leading and trailing spaces are
ignored in text runs. This means that calling TextRun with
leading/trailing space would result in a document that didn't include
those spaces. The fix here (per http://officeopenxml.com/WPtext.php)
is to include an extra attribute on the "w:t" element that forces word
to recognize those spaces.
2017-04-14 11:08:19 +02:00
a706455a7c Merge pull request #30 from felipeochoa/overrides
Add support for numbering level overrides
2017-04-12 18:34:07 +01:00
8c388a95c4 bump patch version 2017-04-12 16:01:26 +02:00
9a41d78ecb add an additional demo 2017-04-12 16:00:16 +02:00
6fc4ad782a add #overrideLevel method to concrete numberings 2017-04-12 16:00:16 +02:00
16b9057ac6 prepare Level to be extended for overrides 2017-04-12 15:57:26 +02:00
28c62c1ee4 version 2.0.0 2017-04-01 13:31:24 +01:00
91a757619e fixed unit tests 2017-04-01 12:30:27 +01:00
f89049e4c1 version bump 2017-04-01 12:23:01 +01:00
086f5f5d03 Merge branch 'image-support' 2017-04-01 12:22:23 +01:00
a2694f1d7d edited demo code 2017-04-01 12:21:59 +01:00
fd350d53db fixed some typescript compile issues 2017-04-01 12:18:23 +01:00
af48af2854 added error checking and updated demo 2017-03-29 22:57:52 +01:00
15009884e3 made image take in IData instead of image path 2017-03-29 22:47:34 +01:00
ad462dfe10 added relationships 2017-03-27 01:28:52 +01:00
68fe380575 renamed template constant 2017-03-27 01:28:31 +01:00
5b2a311ad4 media now adds object into docx /media folder 2017-03-26 20:57:43 +01:00
5db2503e7b added media class and packer to handle it 2017-03-25 21:50:33 +00:00
55a1d23f29 fixed missing comma 2017-03-14 11:33:46 +00:00
0bfd753a0d fixed json, missing comma 2017-03-14 11:28:05 +00:00
22adabd2d9 updated keywords 2017-03-14 10:51:05 +00:00
6d5c89ff47 corrected underline 2017-03-14 10:48:24 +00:00
96a9bb1a1e corrected underline 2017-03-14 10:47:50 +00:00
2be00d3f1e corrected example 2017-03-14 10:38:05 +00:00
30b21217a9 added create picture run method 2017-03-13 23:41:14 +00:00
260a680f56 Merge branch 'master' into image-support 2017-03-13 23:37:09 +00:00
486777b108 named this addRun because I realised Text can be a Run, but also a Picture can be a run 2017-03-13 23:35:24 +00:00
3730e2b60e clean up of packer 2017-03-13 23:30:26 +00:00
e7e6d02cc5 Merge pull request #28 from felipeochoa/npm-fixes
NPM fixes
2017-03-13 22:38:13 +00:00
c7b7b585be fix path to template when installed via npm
I'm not sure why, buy app-root-path was not picking up the correct
path for this module when installed via NPM. Since we're already using
relative paths for imports, I don't think we gain much from using it
anyway, so I've changed to using path.resolve instead
2017-03-13 20:40:16 +01:00
0c128ae4a5 add template to npm bundle 2017-03-13 20:40:16 +01:00
d7a70ffe03 use gemnasium rather than david-dm 2017-03-13 16:14:03 +00:00
e1c699ec41 Merge pull request #27 from felipeochoa/styles
More styles harmony
2017-03-13 12:31:25 +00:00
245f0ae2ea added gitter integration 2017-03-13 12:30:22 +00:00
762fc0ca9d added run formatting methods to levels 2017-03-13 12:38:16 +01:00
457d074a59 added paragraph formatting methods to numbering Level 2017-03-13 12:38:16 +01:00
ba80440faf formatting and correct heading values 2017-03-13 01:21:26 +00:00
ae41e22df5 moved Documents section to Wiki.
Cleaned up Wiki
Added felipeochoa mention
removed TOC
2017-03-13 01:19:39 +00:00
bf2e5201c8 made usage much more clear 2017-03-13 01:11:11 +00:00
2662bcc60b removed Paragraph from readme, and put it in the Wiki 2017-03-13 01:03:57 +00:00
efa4f1933a moved Text section to Wiki 2017-03-13 00:57:57 +00:00
8c58ec2ba4 moved bullet points to Wiki 2017-03-13 00:54:05 +00:00
e6ed3a55ff updated contents 2017-03-13 00:51:01 +00:00
69abf509c9 removed tab stops and placed it in the Wiki 2017-03-13 00:50:29 +00:00
66eace4a33 added a attribute to graphic 2017-03-13 00:40:39 +00:00
eeb2187db4 added source rectangle and stretch in the blip fill 2017-03-13 00:33:59 +00:00
fa44acca1b added the remaining classes required 2017-03-13 00:02:56 +00:00
34ce662f70 added basic test for drawing 2017-03-12 23:32:02 +00:00
8d72fa5542 added more boilerplate files to drawing 2017-03-12 23:31:43 +00:00
64d642b593 Merge branch 'master' into image-support 2017-03-12 21:44:17 +00:00
d9e533156f fixed the build :P removed .docx extension if one is already present 2017-03-12 21:43:52 +00:00
90e5cc3ad5 Revert "fixed the build :P removed .docx extension if one is already present"
This reverts commit 9f61ca7abe.
2017-03-12 21:43:15 +00:00
9f61ca7abe fixed the build :P removed .docx extension if one is already present 2017-03-12 21:42:45 +00:00
6af79a884c Merge branch 'master' into image-support 2017-03-12 21:38:38 +00:00
353401d148 updated readme to add demo folder 2017-03-12 21:37:36 +00:00
f17360d45a add simple demo page 2017-03-12 21:34:49 +00:00
4bc6ed0eda added more files to drawing 2017-03-12 21:30:46 +00:00
bf22866a8d Merge pull request #26 from felipeochoa/styles
Standardizing formatting methods
2017-03-12 21:26:47 +00:00
a6e40d9d92 tightened type checking for tab stops 2017-03-12 22:06:43 +01:00
0b78e33444 added #leftTabStop and #maxRightTabStop methods to paragraph styles 2017-03-12 22:05:54 +01:00
6689f76c28 added #thematicBreak method to paragraph styles 2017-03-12 21:58:12 +01:00
df8ba1e8b8 added alignment methods to paragraph style 2017-03-12 21:40:01 +01:00
b3524971ac clean up imports into paragraph and paragraph style
(this prep for importing it from styles)
2017-03-12 21:39:29 +01:00
1cd681bc2d added #font method to paragraph styles 2017-03-12 17:53:32 +01:00
7f4d1bf3e7 added #SubScript and #SuperScript methods to ParagraphStyle 2017-03-12 17:52:03 +01:00
8c6cd012e7 eliminated duplicate implementation of strikethrough 2017-03-12 17:51:52 +01:00
371398bc2c added #strike and #doubleStrike methods to paragraphStyle 2017-03-12 17:44:42 +01:00
9a90818729 added #smallCaps and #allCaps methods to ParagraphStyle 2017-03-12 17:43:00 +01:00
90049a31ee added #style method to runs 2017-03-12 17:35:15 +01:00
3dbd917667 added #color and #size methods to Run 2017-03-12 17:31:36 +01:00
d85c6ce56a allow Run#underline to take style and color arguments 2017-03-12 17:28:52 +01:00
db24f67e34 Merge pull request #21 from felipeochoa/tables
Tables!
2017-03-11 20:31:57 +00:00
fb6a4383ff renamed cell#push to cell#addContent 2017-03-11 21:15:45 +01:00
c33cdb450c added initial constructor 2017-03-11 18:21:31 +00:00
62b6b33254 created drawing file and refactored run components in components folder 2017-03-11 16:56:35 +00:00
64ab91765a edited contents 2017-03-11 16:06:09 +00:00
c0ba937c3a simplified readme 2017-03-11 16:05:20 +00:00
70f4613e1b appease the linter 2017-03-11 10:30:25 +01:00
bd9d6b74f5 added Cell#createParagraph method 2017-03-11 10:30:08 +01:00
bd3eb3e214 move the cell-paragraph validation into prepForXml
Instead of forcing table cells to only have a single paragraph as
their content, we now check whether they end in a paragraph (and
insert one if necessary) during #prepForXml
2017-03-11 10:22:30 +01:00
c10b576a3a added fixedWidthLayout option and method 2017-03-11 09:59:29 +01:00
210b97d00b added document#createTable 2017-03-11 09:02:36 +01:00
62a238de84 more sane width management 2017-03-11 09:02:22 +01:00
7b6f5bbaef forgot to test #getCell 2017-03-10 17:48:05 +01:00
a45048a464 fix a handful of strict null errors; make test config also be strict
These errors only arose because I didn't run `npm build`, only `npm
test`. Then, when I tried building the null checks failed. Keeping the
two config fiels in sync will help prevent this issue in the future
2017-03-10 17:45:37 +01:00
c0b0649f37 added tests for table v1 2017-03-10 17:39:37 +01:00
e7e5c61a90 clean up initial table attempt (linter, interfaces, etc.) 2017-03-10 17:11:08 +01:00
f1fb0c4f22 initial attempt at Table 2017-03-10 16:55:39 +01:00
0de30f6c59 Merge pull request #19 from felipeochoa/cleanup
fix unused imports linter warnings
2017-03-10 15:43:19 +00:00
599be5bf2b got a little carried away with the purge! fixed failing errors 2017-03-10 16:35:48 +01:00
9d7573ed9c fix unused imports linter warnings 2017-03-10 16:09:21 +01:00
738cac0253 Merge pull request #17 from felipeochoa/cleanup
More cleanup
2017-03-10 14:53:42 +00:00
35ddda444a rename paragraph#createRun to paragraph#createTextRun 2017-03-10 14:44:25 +01:00
8d11ec3422 add paragraph.createRun method 2017-03-10 14:36:16 +01:00
ea647d84df add document.createParagraph method 2017-03-10 14:31:21 +01:00
8c91c04afa clean up latentstyles to use modern attribute implementation 2017-03-10 14:31:21 +01:00
a89718ea83 fix a couple of compiler null warnings 2017-03-10 14:31:21 +01:00
62911d6e44 make XmlAttributeComponent into a generic class
This change brings increased type safety to uses of
XmlAttributeComponent. Now the compiler is checkign for us that the
properties that get passed in to every subclass match the intended
interface, and also that the xmlKeys property -> xml attribute mapping
has all the right keys
2017-03-10 14:19:45 +01:00
766069c7cc make packers a top-level export 2017-03-10 13:54:49 +01:00
09f1d473c3 remove lodash from dependencies as it's no longer used 2017-03-10 13:54:44 +01:00
74ea0f699f remove npm and install from dependencies
These aren't actually needed at run time or build time
2017-03-10 13:54:37 +01:00
b00e4fa5b5 moved exporting to the wiki 2017-03-10 11:35:43 +00:00
7ffa59d7fa formatting 2017-03-10 11:27:48 +00:00
d662391a64 removed LICENCE in readme.
It is already in the repository as the LICENCE file. No need to repeat
2017-03-10 11:26:04 +00:00
7a9661c55a moved examples to Wiki 2017-03-10 11:24:41 +00:00
f80a5654b4 adding unused variable checking 2017-03-10 10:33:42 +00:00
001b756866 Merge pull request #16 from felipeochoa/cleanup
Cleanup
2017-03-10 10:32:05 +00:00
fd1aab48f7 removed some dead code causing tslint problems 2017-03-10 10:35:38 +01:00
7ff838357a removed empty Attributes from ParagraphProperties
I checked the spec, and "w:pPr" does not take any attributes. I also
converted the paragraph tests to use the deep.equal style to get rid
of some more jsonify!
2017-03-10 10:32:40 +01:00
958b5ea307 improved type annotation for Attributes#prepForXml 2017-03-10 08:58:29 +01:00
3a6cf81c60 use strict null checks for added type safety
From the TypeScript manual "In strict null checking mode, the null and
undefined values are not in the domain of every type and are only
assignable to themselves and any (the one exception being that
undefined is also assignable to void)."

In other words, this setting means the compiler will complain if you
try to use a variable, but it might be null or undefined. Since the
project builds and tests pass with it, I think it's good to turn it
on. If it becomes annoying, you can always turn it off later
2017-03-10 08:54:55 +01:00
10684b34aa clean up unused imports and a linter warning 2017-03-10 08:52:47 +01:00
2fc9156e93 remove console.log statements 2017-03-10 08:25:11 +01:00
c521d0ce63 rename toXml -> prepForXml 2017-03-10 08:23:27 +01:00
50ca71087e reverted back as they’re both buggy 2017-03-10 00:52:43 +00:00
72eff21027 used html as markdown version is buggy 2017-03-10 00:51:42 +00:00
11bbb5e285 linting 2017-03-09 23:32:52 +00:00
18bba1870e added types for app-root-path 2017-03-09 23:20:37 +00:00
c6eef3fd79 tslint fixes 2017-03-09 23:20:28 +00:00
06353a6977 linting 2017-03-09 22:57:37 +00:00
2b28dd42ee unclear variable name. please improve 2017-03-09 22:57:30 +00:00
7022b39d2e linting 2017-03-09 22:56:08 +00:00
5fac776dca listing stuff 2017-03-09 22:31:55 +00:00
0e8d92f8bb Merge pull request #14 from felipeochoa/formatting
Clean up xml formatting (clearVariables) and introduced toXml()
2017-03-09 22:17:04 +00:00
30fef5238e fix some linter warnings 2017-03-09 21:06:54 +01:00
0fe6ff95a2 fix an incorrect test 2017-03-09 20:49:34 +01:00
11e918114d clear out clearVariables! In comes toXml 2017-03-09 20:49:14 +01:00
879b9163a3 Allow XmlComponent to take strings and remove XmlUnit 2017-03-09 20:21:49 +01:00
4a2b8a1e04 remove unused XmlProperty code 2017-03-09 19:04:17 +01:00
d6f5fe0ae8 Remove extraneous multi-property from base numbering object 2017-03-09 17:59:17 +01:00
dd4ff944d7 Merge pull request #12 from felipeochoa/styles
Styles cleanup
2017-03-09 15:25:19 +00:00
aac81ffa12 add Styles to top-level exports 2017-03-09 13:27:53 +01:00
d93432678b added #createParagraphStyle method to Styles 2017-03-09 13:27:40 +01:00
ac7799a875 add an #underline method to ParagraphStyle 2017-03-09 13:19:50 +01:00
766bcabcb8 allow Underline to be called with type and color; fix default 2017-03-09 12:42:19 +01:00
f06094c91d clean up underlineTests linter warnings 2017-03-09 12:36:33 +01:00
3b18b8267a fix paragraphTests.ts linter warnings 2017-03-09 12:25:59 +01:00
20ec9b679e added Spacing for paragraphs and ParagraphStyle 2017-03-09 12:16:49 +01:00
449d1bc2c3 added fluent formatting methods to ParagraphStyle 2017-03-09 11:27:47 +01:00
b4dca79d72 added optional name parameter to style constructor 2017-03-09 11:11:07 +01:00
e6e0658812 clean up style & components attributes 2017-03-09 11:11:07 +01:00
18ca93e50a add paragraph#style method to quickly set the style 2017-03-09 11:11:07 +01:00
f5144e6d72 ts/styles linter warnings 2017-03-09 11:11:07 +01:00
2684f16579 move indent.ts over to paragraph and add a #indent method 2017-03-09 09:59:48 +01:00
77255c9d5e modified build script and version bump 2017-03-08 23:35:22 +00:00
e10b8889f7 version bump 2017-03-08 23:27:55 +00:00
744b16b753 tslinting 2017-03-08 21:59:27 +00:00
77824ce1d2 tslinting fixes 2017-03-08 21:56:19 +00:00
d2f777c4e5 more listing 2017-03-08 21:54:52 +00:00
946a222d37 linting fixes 2017-03-08 21:49:41 +00:00
279a5a93f1 fixed failing test 2017-03-08 21:40:21 +00:00
0e89606ec9 lots of tslinting 2017-03-08 21:36:09 +00:00
72683ea990 fixed bug where snky badge wasn’t displaying 2017-03-08 20:42:56 +00:00
88cf5f5065 added vulnerability checker 2017-03-08 20:37:21 +00:00
540518bd54 more tslinting 2017-03-08 20:35:26 +00:00
03b34915c6 tslinting 2017-03-08 20:32:30 +00:00
f6eb412357 removed numbering.md in favour of Wiki 2017-03-08 20:26:08 +00:00
ca769cc849 Merge pull request #11 from felipeochoa/fonts
Fonts cleanup
2017-03-08 20:16:17 +00:00
727471b7e3 fix linter warnings in docx/run/index.ts 2017-03-08 20:52:37 +01:00
1a37242a3d add #font method to Run 2017-03-08 20:47:36 +01:00
81e0d56918 fix linter warnings in runTest.ts 2017-03-08 20:47:35 +01:00
237be76d33 move run-fonts to docx/run and add a test 2017-03-08 20:47:35 +01:00
a454ff9643 Merge pull request #10 from felipeochoa/numbering
Numbering
2017-03-08 19:30:21 +00:00
f7b90d4ff3 add default argument "start" to createLevel 2017-03-08 19:18:24 +01:00
cee515e43f added Numbering to top-level exports and added docs on usage 2017-03-08 19:07:44 +01:00
0e9532d835 added #setNumbering method to paragraph 2017-03-08 18:23:00 +01:00
4b300e4def add fluent interface for defining abstract numbering levels 2017-03-08 18:03:39 +01:00
1fe7ab90f2 add createLevel method to AbstractNumbering 2017-03-08 18:03:24 +01:00
a3d2323254 rename methods from addXXX to createXXX
addXXX sounds like the argument should be XXX
2017-03-08 17:49:41 +01:00
0b2de737de fix linter warnings in numbering/index.ts 2017-03-08 17:45:29 +01:00
0a70d932a0 fix numberingTest linter warnings 2017-03-08 17:45:29 +01:00
6b702c4bd6 add ID property to Num and test Numbering methods 2017-03-08 17:45:29 +01:00
709ff25702 add #addAbstractNumbering and #addConcreteNumbering to Numbering 2017-03-08 17:45:29 +01:00
82998d4f6b record ID in AbstractNumbering 2017-03-08 17:45:29 +01:00
6e6a06eba4 fix numbering/num.ts linter warnings 2017-03-08 17:45:29 +01:00
ae70c2dfde fix numbering/indent.ts linter warnings 2017-03-08 17:45:29 +01:00
28e11a9b08 fix numbering/multi-level-type linter warnings 2017-03-08 17:45:29 +01:00
f5e81f1dfc fix numbering/level linter warnings 2017-03-08 17:45:29 +01:00
38138049fe fix abstract-number linter warnings 2017-03-08 17:45:29 +01:00
5511024ca6 fix run-fonts for new numbering test (and linter warnings) 2017-03-08 17:45:29 +01:00
ef1407e640 add a test for numbering 2017-03-08 17:45:29 +01:00
f822bbb26f fix typos in default numbering definition 2017-03-08 17:45:29 +01:00
52c4e3cabd allow NumberProperties to specify custom id/level
This change allows callers to create custom numbering styles and
attach them to paragraphs
2017-03-08 16:20:44 +01:00
9ced196678 Merge pull request #8 from felipeochoa/npm-fix
Npm fixes - prepublish and files
2017-03-08 15:11:58 +00:00
ef6e195e89 add an .npmignore file which does not exclude the build dir
Per https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package,
npm automatically uses .gitignore if there is no .npmignore, which may
have been keeping the build dir out of the package
2017-03-08 14:17:46 +01:00
a77d520f41 add the build files to the npm package 2017-03-08 12:05:47 +01:00
8eb11bca29 fix npm prepublish-on-install warnings 2017-03-08 12:05:47 +01:00
660a81633f removed copy and paste description 2017-03-07 23:15:26 +00:00
a917247b60 removed inverted comma 2017-03-07 23:13:04 +00:00
f492b3fe04 fixed pages bug 2017-03-07 23:12:08 +00:00
96a8942455 updated readme 2017-03-07 23:10:35 +00:00
bca478bb81 updated tslint and ignored some files 2017-03-07 23:05:09 +00:00
f5de5fef4d added tslint support 2017-03-07 22:56:59 +00:00
0e9301c0b5 clean up comment 2017-03-07 22:48:25 +00:00
b0869567c6 used more generic .vscode gitignore 2017-03-07 22:48:12 +00:00
0585a25a5a removed typescript 2017-03-07 22:37:40 +00:00
9804091f6a removed random semi colon 2017-03-07 22:35:20 +00:00
9c3023019f huge clean up of project. Now uses @types, and removed committed typings.
Formatted the imports too
2017-03-07 22:15:53 +00:00
148 changed files with 3969 additions and 25187 deletions

2
.gitignore vendored
View File

@ -37,4 +37,4 @@ build
build-tests build-tests
# vscode # vscode
ts/.vscode .vscode

43
.npmignore Normal file
View File

@ -0,0 +1,43 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# build
# build <-- we want this in the package
build-tests
# vscode
.vscode
# docs
docs

View File

@ -1,10 +1,15 @@
language: node_js language: node_js
node_js: node_js:
- "6" - "stable"
- "node"
install: install:
- npm install - npm install
script: script:
- npm test - npm test
after_failure: after_failure:
- "cat /home/travis/builds/dolanmiu/docx/npm-debug.log" - "cat /home/travis/builds/dolanmiu/docx/npm-debug.log"
after_success:
- bash ./deploy-docs.sh
env:
global:
- ENCRYPTION_LABEL: "ad385fa3b525"

403
README.md
View File

@ -1,50 +1,40 @@
# [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] <p align="center">
<img alt="clippy the assistant" src="http://i60.tinypic.com/339pvtt.png">
</p>
> A tool to create Word Documents (.docx) with JS or TS, written in TS. <p align="center">
Generate .docx files with JS/TS very easily, written in TS.
</p>
-----
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][gemnasium-image]][gemnasium-url] [![Known Vulnerabilities][snky-image]][snky-url] [![Chat on Gitter][gitter-image]][gitter-url]
[![NPM](https://nodei.co/npm/docx.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/docx/) [![NPM](https://nodei.co/npm/docx.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/docx/)
![Clippy in Microsoft Office](http://i60.tinypic.com/339pvtt.png "Clippy in Microsoft Office") # docx
# Table of Contents ## Install
- [Install](#)
- [Usage](#)
- [Create simple Word Document](#)
- [Create Paragraph](#)
- [Styles](#)
- [Heading1 - Heading5](#)
- [Title](#)
- [Text Alignment](#)
- [Example](#)
- [Thematic Break (Page Break)](#)
- [Text](#)
- [Typographical Emphasis](#)
- [Bold](#)
- [Italics](#)
- [Underline](#)
- [Break](#)
- [Chaining](#)
- [Bullet Points](#)
- [Tab Stops](#)
- [Left Tab Stop](#)
- [Center Tab Stop](#)
- [Right Tab Stop](#)
- [Max Right Tab Stop](#)
- [Example](#)
- [Exporting](#)
- [Express](#)
- [Standalone .docx file](#)
- [Examples](#)
- [License](#)
# Install
```sh ```sh
$ npm install --save docx $ npm install --save docx
``` ```
## Demo
# Usage ```sh
$ npm run demo
```
will run the demo selector app in the `demo` folder. It will prompt you to select a demo number, which will run a demo from that folder.
## Guide
Please refer to [the Wiki](https://github.com/dolanmiu/docx/wiki) for details on how to use this library, examples and much more!
Full documentation can be found here: [http://dolanmiu.github.io/docx](http://dolanmiu.github.io/docx)
## Simple Usage
```js ```js
// Used to create docx files // Used to create docx files
@ -53,330 +43,45 @@ var docx = require('docx');
// Create document // Create document
var doc = new docx.Document(); var doc = new docx.Document();
// Add some content in the document
var paragraph = new docx.Paragraph("Some cool text here.");
// Add more text into the paragraph if you wish
paragraph.addRun(new docx.TextRun('Lorem Ipsum Foo Bar'));
doc.addParagraph(paragraph);
// Used to export the file into a .docx file // Used to export the file into a .docx file
var exporter = new docx.LocalPacker(doc);
// Or use the express packer to make the file downloadable.
// res is express' Response object // res is express' Response object
var exporter = new docx.ExpressPacker(doc, res); var exporter = new docx.ExpressPacker(doc, res);
var exporter = new docx.LocalPacker(doc);
``` exporter.pack('My First Document');
## Create simple Word Document
```js // done! A file called 'My First Document.docx'
var doc = new docx.Document(); // will be in your file system if you used LocalPacker
// Or it will start downloading if you are using Express
var paragraph = new docx.Paragraph();
var text = new docx.TextRun('Hello World');
paragraph.addText(text);
doc.addParagraph(paragraph);
``` ```
### Document properties ## Examples
You can add properties to the Word document by specifying options, for example: Check [the Wiki](https://github.com/dolanmiu/docx/wiki/Examples) for examples.
```js
var doc = new docx.Document({
creator: 'Dolan Miu',
description: 'My extremely interesting document',
title: 'My Document'
});
```
#### Full list of options: -----
```
creator
description
title
subject
keywords
lastModifiedBy
revision
```
You can mix and match whatever properties you want, or provide no properties. Made with 💖
## Create Paragraph Huge thanks to [@felipeochoa](https://github.com/felipeochoa) for awesome contributions to this project
Every text block in OpenXML is organised in paragraphs. You can add more text to the paragraph by doing this:
```js
var paragraph = new docx.Paragraph(),
```
```js
var text = new docx.TextRun('Lorem Ipsum Foo Bar');
var paragraph = new docx.Paragraph();
paragraph.addText(text);
```
```js
var paragraph = new docx.Paragraph("Short hand notation for adding text.");
```
After you create the paragraph, you must add the paragraph into the `document`:
```js
doc.addParagraph(paragraph);
```
### Styles
Styles is a very important part of the look of a word document. At the moment, only headings and title is supported, but son the rest will be supported along with custom styles!
![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu")
#### Heading1 - Heading5
```js
paragraph.heading1();
paragraph.heading2();
paragraph.heading3();
paragraph.heading4();
paragraph.heading5();
```
#### Title
```js
paragraph.title();
```
### Text Alignment
To change the text alignment of a paragraph, for center, left, right or justified:
```js
paragraph.center();
```
```js
paragraph.left();
```
```js
paragraph.right();
```
```js
paragraph.justified();
```
#### Example
```js
paragraph.heading1().center();
```
The above will create a `heading 1` which is `centered`.
### Thematic Break
To add a break in the page, simply add `.thematicBreak()` on a paragraph:
```js
var paragraph = new docx.Paragraph("Amazing Heading").heading1().thematicBreak();
```
The above example will create a heading with a page break directly under it.
### Page Break
To move to a new page (insert a page break), simply add `.pageBreak()` on a paragraph:
```js
var paragraph = new docx.Paragraph("Amazing Heading").heading1().pageBreak();
```
The above example will create a heading and start a new page immediately afterwards.
## Text
Paragraphs need `text run` objects. To create text:
```js
var text = new docx.TextRun("My awesome text here for my university dissertation");
paragraph.addText(text);
```
Text objects have methods inside which changes the way the text is displayed.
### Typographical Emphasis
More info [here](https://english.stackexchange.com/questions/97081/what-is-the-typography-term-which-refers-to-the-usage-of-bold-italics-and-unde)
#### Bold
```js
text.bold();
```
#### Italics
```js
text.italic();
```
#### Underline
```js
text.underline();
```
#### Strike through
```js
text.strike();
```
#### Double strike through
```js
text.doubleStrike();
```
#### Superscript
```js
text.superScript();
```
#### Subscript
```js
text.subScript();
```
#### All Capitals
```js
text.allCaps();
```
#### Small Capitals
```js
text.smallCaps();
```
### Break
Sometimes you would want to put text underneath another line of text but inside the same paragraph.
```js
text.break();
```
### Chaining
What if you want to create a paragraph which is ***bold*** and ***italic***?
```js
paragraph.bold().italic();
```
## Bullet Points
To make a bullet point, simply make a paragraph into a bullet point:
```js
var text = new docx.TextRun("Bullet points");
var paragraph = new docx.Paragraph(text).bullet();
var text2 = new docx.TextRun("Are awesome");
var paragraph2 = new docx.Paragraph(text2).bullet();
doc.addParagraph(paragraph);
doc.addParagraph(paragraph2);
```
This will produce:
* Bullet points
* Are awesome
## Tab Stops
If you do not know why tab stops are useful, then I recommend you do a bit of research. It enables side by side text which is nicely laid out without the need for tables, or constantly pressing space bar.
**Note**: At the moment, the unit of measurement for a tab stop is counter intuitive for a human. It is using OpenXMLs own measuring system. For example, 2268 roughly translates to 3cm. Therefore in the future, I may consider changing it to percentages or even cm.
![Word 2013 Tabs](http://www.teachucomp.com/wp-content/uploads/blog-4-22-2015-UsingTabStopsInWord-1024x577.png "Word 2013 Tab Stops")
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.
### Left Tab Stop
```js
paragraph.leftTabStop(2268);
```
2268 is the distance from the left side.
### Center Tab Stop
```js
paragraph.centerTabStp(2268);
```
2268 is the distance from the left side.
### Right Tab Stop
```js
paragraph.rightTabStop(2268);
```
2268 is the distance from the left side.
### Max Right Tab Stop
```js
paragraph.maxRightTabStop();
```
This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line.
### Example
```js
var paragraph = new docx.Paragraph().maxRightTabStop();
var leftText = new docx.TextRun("Hey everyone").bold();
var rightText = new docx.TextRun("11th November 2015").tab();
paragraph.addText(leftText);
paragraph.addText(rightText);
```
The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. YUK!
```js
var paragraph = new docx.Paragraph();
paragraph.maxRightTabStop();
paragraph.leftTabStop(1000);
var text = new docx.TextRun("Second tab stop here I come!").tab().tab();
paragraph.addText(text);
```
The above shows the use of two tab stops, and how to select/use it.
# Exporting
I used the express exporter in my [website](http://www.dolan.bio). It's very useful, and is the preferred way if you want to make a downloadable file for a visitor. it is much better than generating a physical file on the server, and then passing a download link to that file.
## Express
Simply use the exporter, and pass in the necessary parameters:
```js
var docx = require('docx');
var doc = new docx.Document();
var exporter = new docx.ExpressPacker(doc, res);
exporter.pack('My Document');
```
where `res` is the response object obtained through the Express router. It is that simple. The file will begin downloading in the browser.
## Standalone .docx file
```js
var docx = require('docx');
var doc = new docx.Document();
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
```
# Examples
## In practice
I used this library in my personal portfolio/CV website. Click generate CV for a demonstration. [http://www.dolan.bio](http://www.dolan.bio)
## General
#### Simple paragraph
```js
var doc = new docx.Document();
var paragraph = new docx.Paragraph("Hello World");
var institutionText = new docx.TextRun("University College London").bold(),
var dateText = new docx.TextRun("5th Dec 2015").tab().bold();
paragraph.addText(institutionText);
paragraph.addText(dateText);
doc.addParagraph(paragraph);
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
```
Or:
```js
var doc = new docx.Document();
var paragraph = new docx.Paragraph("Hello World");
var institutionText = new docx.TextRun("University College London").bold(),
var dateText = new docx.TextRun("5th Dec 2015").tab().bold();
paragraph.addText(institutionText);
paragraph.addText(dateText);
var exporter = new docx.ExpressPacker(doc, res);
exporter.pack('My Document');
```
Would produce:
***University College London***
***5th Dec 2015***
Made with 💖 by Dolan Miu 🍆 💦 😝
# License
MIT © [Dolan Miu](http://www.dolan.bio)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[npm-image]: https://badge.fury.io/js/docx.svg [npm-image]: https://badge.fury.io/js/docx.svg
[npm-url]: https://npmjs.org/package/docx [npm-url]: https://npmjs.org/package/docx
[travis-image]: https://travis-ci.org/dolanmiu/docx.svg?branch=master [travis-image]: https://travis-ci.org/dolanmiu/docx.svg?branch=master
[travis-url]: https://travis-ci.org/dolanmiu/docx [travis-url]: https://travis-ci.org/dolanmiu/docx
[daviddm-image]: https://david-dm.org/dolanmiu/docx.svg?theme=shields.io [daviddm-image]: https://david-dm.org/dolanmiu/docx.svg?theme=shields.io
[daviddm-url]: https://david-dm.org/dolanmiu/docx [daviddm-url]: https://david-dm.org/dolanmiu/docx
[snky-image]: https://snyk.io/test/github/dolanmiu/docx/badge.svg
[snky-url]: https://snyk.io/test/github/dolanmiu/docx
[gitter-image]: https://badges.gitter.im/dolanmiu/docx.svg
[gitter-url]: https://gitter.im/docx-lib/Lobby
[gemnasium-image]: https://gemnasium.com/badges/github.com/dolanmiu/docx.svg
[gemnasium-url]: https://gemnasium.com/github.com/dolanmiu/docx

22
demo/demo1.js Normal file
View File

@ -0,0 +1,22 @@
const docx = require('../build');
var doc = new docx.Document();
var paragraph = new docx.Paragraph("Hello World");
var institutionText = new docx.TextRun("University College London").bold();
var dateText = new docx.TextRun("5th Dec 2015").tab().bold();
paragraph.addRun(institutionText);
paragraph.addRun(dateText);
doc.addParagraph(paragraph);
// Feature coming soon
// var media = new docx.Media();
// media.addMedia("happy-penguins", "./demo/penguins.jpg");
// var pictureRun = new docx.PictureRun(media.getMedia("happy-penguins"));
// var exporter = new docx.LocalPacker(doc);
var exporter = new docx.LocalPacker(doc);
exporter.pack('My Document');
console.log('Document created succesfully at project root!');

74
demo/demo2.js Normal file
View File

@ -0,0 +1,74 @@
const docx = require('../build');
const styles = new docx.Styles();
styles.createParagraphStyle('Heading1', 'Heading 1')
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(28)
.bold()
.italics()
.spacing({after: 120});
styles.createParagraphStyle('Heading2', 'Heading 2')
.basedOn("Normal")
.next("Normal")
.quickFormat()
.size(26)
.bold()
.underline('double', 'FF0000')
.spacing({before: 240, after: 120});
styles.createParagraphStyle('aside', 'Aside')
.basedOn('Normal')
.next('Normal')
.color('999999')
.italics()
.indent(720)
.spacing({line: 276});
styles.createParagraphStyle('wellSpaced', 'Well Spaced')
.basedOn('Normal')
.spacing({line: 276, before: 20 * 72 * .1, after: 20 * 72 * .05});
styles.createParagraphStyle('ListParagraph', 'List Paragraph')
.quickFormat()
.basedOn('Normal');
const numbering = new docx.Numbering();
const numberedAbstract = numbering.createAbstractNumbering();
numberedAbstract.createLevel(0, "lowerLetter", "%1)", "left");
const doc = new docx.Document({
creator: 'Clippy',
title: 'Sample Document',
description: 'A brief example of using docx',
});
doc.createParagraph('Test heading1, bold and italicized').heading1();
doc.createParagraph('Some simple content');
doc.createParagraph('Test heading2 with double red underline').heading2();
const letterNumbering = numbering.createConcreteNumbering(numberedAbstract);
const letterNumbering5 = numbering.createConcreteNumbering(numberedAbstract);
letterNumbering5.overrideLevel(0, 5);
doc.createParagraph('Option1').setNumbering(letterNumbering, 0);
doc.createParagraph('Option5 -- override 2 to 5').setNumbering(letterNumbering5, 0);
doc.createParagraph('Option3').setNumbering(letterNumbering, 0);
doc.createParagraph()
.createTextRun('Some monospaced content')
.font('Monospace');
doc.createParagraph('An aside, in light gray italics and indented').style('aside');
doc.createParagraph('This is normal, but well-spaced text').style('wellSpaced');
const para = doc.createParagraph();
para.createTextRun('This is a bold run,').bold();
para.createTextRun(' switching to normal ');
para.createTextRun('and then underlined ').underline();
para.createTextRun('and back to normal.');
const exporter = new docx.LocalPacker(doc, styles, undefined, numbering);
exporter.pack('test.docx');

29
demo/index.js Normal file
View File

@ -0,0 +1,29 @@
var prompt = require('prompt');
var shelljs = require('shelljs');
var fs = require('fs');
console.log('What demo do you wish to run? (Enter a number)');
var schema = {
properties: {
number: {
pattern: /^[0-9]+$/,
message: 'Please enter a number.',
required: true
}
}
};
prompt.start();
prompt.get(schema, function (err, result) {
var demoNumber = result.number;
var filePath = `./demo/demo${demoNumber}.js`;
if (!fs.existsSync(filePath)) {
console.error(`demo${demoNumber} does not exist: ${filePath}`);
return;
}
console.log(`Running demo ${demoNumber}`);
shelljs.exec(`node ${filePath}`);
});

BIN
demo/penguins.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

68
deploy-docs.sh Normal file
View File

@ -0,0 +1,68 @@
#!/bin/bash
set -e # Exit with nonzero exit code if anything fails
SOURCE_BRANCH="master"
TARGET_BRANCH="gh-pages"
function doCompile {
npm run typedoc
}
# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
echo "Skipping deploy; just doing a build."
doCompile
exit 0
fi
# Save some useful information
REPO=`git config remote.origin.url`
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
SHA=`git rev-parse --verify HEAD`
# Clone the existing gh-pages for this repo into docs/
# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
git clone $REPO docs
cd docs
git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
cd ..
# Clean out existing contents
# echo "Cleaning out existing contents."
# rm -rf docs/*
# Run our compile script
doCompile
# Now let's go have some fun with the cloned repo
cd docs
git config user.name "Travis CI"
git config user.email "dolan_miu@hotmail.com"
ls
# add .nojekyll file
touch .nojekyll
# If there are no changes to the compiled out (e.g. this is a README update) then just bail.
if [ -z `git diff --exit-code` ]; then
echo "No changes to the output on this push; exiting."
exit 0
fi
# Commit the "changes", i.e. the new version.
# The delta will show diffs between new and old versions.
git add .
git commit -m "Deploy to GitHub Pages: ${SHA}"
# Get the deploy key by using Travis's stored variables to decrypt deploy-key.enc
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy-key.enc -out deploy-key -d
chmod 600 deploy-key
eval `ssh-agent -s`
ssh-add deploy-key
# Now that we're all set up, we can push.
git push $SSH_REPO $TARGET_BRANCH

BIN
deploy-key.enc Normal file

Binary file not shown.

View File

@ -1,32 +1,44 @@
{ {
"name": "docx", "name": "docx",
"version": "1.0.1", "version": "2.1.0",
"description": "Generate .docx documents with JavaScript (formerly Office-Clippy)", "description": "Generate .docx documents with JavaScript (formerly Office-Clippy)",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {
"pretest": "rimraf ./build-tests && tsc -p ts/test-tsconfig.json", "pretest": "rimraf ./build-tests && tsc -p ts/test-tsconfig.json",
"test": "mocha ./build-tests --recursive", "test": "mocha ./build-tests --recursive",
"prepublish": "tsc -p ts" "prepublishOnly": "npm run build",
"lint": "tslint --project ./ts",
"build": "rimraf ./build && tsc -p ts",
"demo": "npm run build && node ./demo",
"typedoc": "typedoc --out docs/ ts/ --module commonjs --target ES6 --disableOutputCheck"
}, },
"files": [
"ts",
"build",
"template"
],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/dolanmiu/docx.git" "url": "git+https://github.com/dolanmiu/docx.git"
}, },
"keywords": [ "keywords": [
"office", "office",
"word",
"generate", "generate",
"creator",
"create",
"document", "document",
"doc" "doc",
"officegen",
"clippy"
], ],
"types": "./build/index.d.ts",
"dependencies": { "dependencies": {
"app-root-path": "^2.0.1", "@types/archiver": "^1.3.2",
"@types/express": "^4.0.35",
"archiver": "^1.3.0", "archiver": "^1.3.0",
"lodash": "^4.6.1",
"xml": "^1.0.1" "xml": "^1.0.1"
}, },
"typescript": {
"definition": "ts/typings/index.d.ts"
},
"author": "Dolan Miu", "author": "Dolan Miu",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
@ -34,9 +46,15 @@
}, },
"homepage": "https://github.com/dolanmiu/docx#readme", "homepage": "https://github.com/dolanmiu/docx#readme",
"devDependencies": { "devDependencies": {
"@types/chai": "^3.4.35",
"@types/mocha": "^2.2.39",
"chai": "^3.5.0", "chai": "^3.5.0",
"mocha": "^3.2.0", "mocha": "^3.2.0",
"prompt": "^1.0.0",
"rimraf": "^2.5.2", "rimraf": "^2.5.2",
"shelljs": "^0.7.7",
"tslint": "^5.1.0",
"typedoc": "^0.5.10",
"typescript": "^2.2.1" "typescript": "^2.2.1"
} }
} }

View File

@ -1,11 +1,11 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { Attributes, XmlComponent } from "../../xml-components";
export class Columns extends XmlComponent { export class Columns extends XmlComponent {
constructor() { constructor() {
super("w:cols"); super("w:cols");
this.root.push(new Attributes({ this.root.push(new Attributes({
space: "708" space: "708",
})); }));
} }
} }

View File

@ -1,11 +1,11 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { Attributes, XmlComponent } from "../../xml-components";
export class DocumentGrid extends XmlComponent { export class DocumentGrid extends XmlComponent {
constructor() { constructor() {
super("w:docGrid"); super("w:docGrid");
this.root.push(new Attributes({ this.root.push(new Attributes({
linePitch: "360" linePitch: "360",
})); }));
} }
} }

View File

@ -1,15 +1,12 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { XmlComponent } from "../../xml-components";
import {SectionProperties} from "./section-properties";
export class Body extends XmlComponent { export class Body extends XmlComponent {
constructor() { constructor() {
super("w:body"); super("w:body");
// this.root.push(new SectionProperties()); not actually needed
} }
push(component: XmlComponent) { public push(component: XmlComponent): void {
// this.root.splice(this.body.length - 1, 0, component);
this.root.push(component); this.root.push(component);
} }
} }

View File

@ -1,4 +1,4 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { Attributes, XmlComponent } from "../../xml-components";
export class PageMargin extends XmlComponent { export class PageMargin extends XmlComponent {
@ -11,7 +11,7 @@ export class PageMargin extends XmlComponent {
left: "1440", left: "1440",
header: "708", header: "708",
footer: "708", footer: "708",
gutter: "0" gutter: "0",
})); }));
} }
} }

View File

@ -1,4 +1,4 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { Attributes, XmlComponent } from "../../xml-components";
export class PageSize extends XmlComponent { export class PageSize extends XmlComponent {
@ -6,7 +6,7 @@ export class PageSize extends XmlComponent {
super("w:pgSz"); super("w:pgSz");
this.root.push(new Attributes({ this.root.push(new Attributes({
w: "11906", w: "11906",
h: "16838" h: "16838",
})); }));
} }
} }

View File

@ -1,8 +1,8 @@
import {XmlComponent, Attributes} from "../../xml-components"; import { Attributes, XmlComponent } from "../../xml-components";
import {PageSize} from "./page-size"; import { Columns } from "./columns";
import {PageMargin} from "./page-margin"; import { DocumentGrid } from "./doc-grid";
import {Columns} from "./columns"; import { PageMargin } from "./page-margin";
import {DocumentGrid} from "./doc-grid"; import { PageSize } from "./page-size";
export class SectionProperties extends XmlComponent { export class SectionProperties extends XmlComponent {
@ -11,11 +11,11 @@ export class SectionProperties extends XmlComponent {
this.root.push(new Attributes({ this.root.push(new Attributes({
rsidR: "00B64E8F", rsidR: "00B64E8F",
rsidRPr: "00D842E4", rsidRPr: "00D842E4",
rsidSect: "000A6AD0" rsidSect: "000A6AD0",
})); }));
this.root.push(new PageSize()); this.root.push(new PageSize());
this.root.push(new PageMargin()); this.root.push(new PageMargin());
this.root.push(new Columns()); this.root.push(new Columns());
this.root.push(new DocumentGrid()); this.root.push(new DocumentGrid());
} }
} }

View File

@ -1,6 +1,6 @@
import {XmlAttributeComponent} from "../xml-components"; import { XmlAttributeComponent } from "../xml-components";
interface DocumentAttributesProperties { export interface IDocumentAttributesProperties {
wpc?: string; wpc?: string;
mc?: string; mc?: string;
o?: string; o?: string;
@ -26,39 +26,30 @@ interface DocumentAttributesProperties {
type?: string; type?: string;
} }
export class DocumentAttributes extends XmlAttributeComponent { export class DocumentAttributes extends XmlAttributeComponent<IDocumentAttributesProperties> {
protected xmlKeys = {
constructor(properties?: DocumentAttributesProperties) { wpc: "xmlns:wpc",
super({ mc: "xmlns:mc",
wpc: "xmlns:wpc", o: "xmlns:o",
mc: "xmlns:mc", r: "xmlns:r",
o: "xmlns:o", m: "xmlns:m",
r: "xmlns:r", v: "xmlns:v",
m: "xmlns:m", wp14: "xmlns:wp14",
v: "xmlns:v", wp: "xmlns:wp",
wp14: "xmlns:wp14", w10: "xmlns:w10",
wp: "xmlns:wp", w: "xmlns:w",
w10: "xmlns:w10", w14: "xmlns:w14",
w: "xmlns:w", w15: "xmlns:w15",
w14: "xmlns:w14", wpg: "xmlns:wpg",
w15: "xmlns:w15", wpi: "xmlns:wpi",
wpg: "xmlns:wpg", wne: "xmlns:wne",
wpi: "xmlns:wpi", wps: "xmlns:wps",
wne: "xmlns:wne", Ignorable: "mc:Ignorable",
wps: "xmlns:wps", cp: "xmlns:cp",
Ignorable: "mc:Ignorable", dc: "xmlns:dc",
cp: "xmlns:cp", dcterms: "xmlns:dcterms",
dc: "xmlns:dc", dcmitype: "xmlns:dcmitype",
dcterms: "xmlns:dcterms", xsi: "xmlns:xsi",
dcmitype: "xmlns:dcmitype", type: "xsi:type",
xsi: "xmlns:xsi", };
type: "xsi:type" }
}, properties);
this.root = properties;
if (!properties) {
this.root = {};
}
}
}

View File

@ -1,7 +1,8 @@
import {XmlComponent} from "../xml-components"; import { Paragraph } from "../paragraph";
import {DocumentAttributes} from "./document-attributes"; import { Table } from "../table";
import {Body} from "./body"; import { XmlComponent } from "../xml-components";
import {Paragraph} from "../paragraph"; import { Body } from "./body";
import { DocumentAttributes } from "./document-attributes";
export class Document extends XmlComponent { export class Document extends XmlComponent {
private body: Body; private body: Body;
@ -25,18 +26,30 @@ export class Document extends XmlComponent {
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
wne: "http://schemas.microsoft.com/office/word/2006/wordml", wne: "http://schemas.microsoft.com/office/word/2006/wordml",
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
Ignorable: "w14 w15 wp14" Ignorable: "w14 w15 wp14",
})); }));
this.body = new Body(); this.body = new Body();
this.root.push(this.body); this.root.push(this.body);
} }
addParagraph(paragraph: Paragraph): void { public addParagraph(paragraph: Paragraph): void {
this.body.push(paragraph); this.body.push(paragraph);
} }
clearVariables(): void { public createParagraph(text?: string): Paragraph {
this.body.clearVariables(); const para = new Paragraph(text);
delete this.body; this.addParagraph(para);
return para;
} }
}
public addTable(table: Table): void {
this.body.push(table);
}
public createTable(rows: number, cols: number): Table {
const table = new Table(rows, cols);
this.addTable(table);
return table;
}
}

View File

@ -1,4 +1,7 @@
export {Document} from "./document"; export { Document } from "./document";
export {Paragraph} from "./paragraph"; export { Paragraph } from "./paragraph";
export {Run} from "./run" export { Run } from "./run";
export {TextRun} from "./run/text-run" export { TextRun } from "./run/text-run";
export { PictureRun } from "./run/picture-run";
export { Table } from "./table";
// Perhaps all run related stuff can be exported from run, instead of exporting Run, TextRun, PictureRun seperately.

View File

@ -0,0 +1,15 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
export type AlignmentOptions = "left" | "center" | "right" | "both";
export class AlignmentAttributes extends XmlAttributeComponent<{val: AlignmentOptions}> {
protected xmlKeys = {val: "w:val"};
}
export class Alignment extends XmlComponent {
constructor(type: AlignmentOptions) {
super("w:jc");
this.root.push(new AlignmentAttributes({val: type}));
}
}

View File

@ -1,4 +1,4 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
class Border extends XmlComponent { class Border extends XmlComponent {
@ -8,7 +8,7 @@ class Border extends XmlComponent {
color: "auto", color: "auto",
space: "1", space: "1",
val: "single", val: "single",
sz: "6" sz: "6",
})); }));
} }
} }
@ -19,4 +19,4 @@ export class ThematicBreak extends XmlComponent {
super("w:pBdr"); super("w:pBdr");
this.root.push(new Border()); this.root.push(new Border());
} }
} }

View File

@ -0,0 +1,10 @@
export { Alignment } from "./alignment";
export { ThematicBreak } from "./border";
export { Indent } from "./indent";
export { KeepLines, KeepNext } from "./keep";
export { PageBreak } from "./page-break";
export { ParagraphProperties } from "./properties";
export { ISpacingProperties, Spacing } from "./spacing";
export { Style } from "./style";
export { LeftTabStop, MaxRightTabStop } from "./tab-stop";
export { NumberProperties } from "./unordered-list";

View File

@ -0,0 +1,24 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
interface IIndentAttributesProperties {
left?: number;
hanging?: number;
}
class IndentAttributes extends XmlAttributeComponent<IIndentAttributesProperties> {
protected xmlKeys = {
left: "w:left",
hanging: "w:hanging",
};
}
export class Indent extends XmlComponent {
constructor(left: number, hanging?: number) {
super("w:ind");
this.root.push(new IndentAttributes({
left: left,
hanging: hanging,
}));
}
}

View File

@ -1,21 +1,20 @@
import {XmlComponent, Attributes} from "../xml-components"; import { IData } from "../../media/data";
import {ThematicBreak} from "./border"; import { Num } from "../../numbering/num";
import {PageBreak} from "./page-break"; import { Run } from "../run";
import {TextRun} from "../run/text-run"; import { PictureRun } from "../run/picture-run";
import {ParagraphProperties} from "./properties"; import { TextRun } from "../run/text-run";
import {MaxRightTabStop, LeftTabStop} from "./tab-stop"; import { XmlComponent } from "../xml-components";
import {Style} from "./style";
import {NumberProperties} from "./unordered-list";
class Alignment extends XmlComponent { import { Alignment } from "./alignment";
import { ThematicBreak } from "./border";
constructor(type: string) { import { Indent } from "./indent";
super("w:jc"); import { KeepLines, KeepNext } from "./keep";
this.root.push(new Attributes({ import { PageBreak } from "./page-break";
val: type import { ParagraphProperties } from "./properties";
})); import { ISpacingProperties, Spacing } from "./spacing";
} import { Style } from "./style";
} import { LeftTabStop, MaxRightTabStop } from "./tab-stop";
import { NumberProperties } from "./unordered-list";
export class Paragraph extends XmlComponent { export class Paragraph extends XmlComponent {
private properties: ParagraphProperties; private properties: ParagraphProperties;
@ -29,84 +28,127 @@ export class Paragraph extends XmlComponent {
} }
} }
addText(run: TextRun): Paragraph { public addRun(run: Run): Paragraph {
this.root.push(run); this.root.push(run);
return this; return this;
} }
heading1(): Paragraph { public createTextRun(text: string): TextRun {
const run = new TextRun(text);
this.addRun(run);
return run;
}
public createPictureRun(imageData: IData): PictureRun {
const run = new PictureRun(imageData);
this.addRun(run);
return run;
}
public heading1(): Paragraph {
this.properties.push(new Style("Heading1")); this.properties.push(new Style("Heading1"));
return this; return this;
} }
heading2(): Paragraph { public heading2(): Paragraph {
this.properties.push(new Style("Heading2")); this.properties.push(new Style("Heading2"));
return this; return this;
} }
heading3(): Paragraph { public heading3(): Paragraph {
this.properties.push(new Style("Heading3")); this.properties.push(new Style("Heading3"));
return this; return this;
} }
heading4(): Paragraph { public heading4(): Paragraph {
this.properties.push(new Style("Heading4")); this.properties.push(new Style("Heading4"));
return this; return this;
} }
heading5(): Paragraph { public heading5(): Paragraph {
this.properties.push(new Style("Heading5")); this.properties.push(new Style("Heading5"));
return this; return this;
} }
title(): Paragraph { public title(): Paragraph {
this.properties.push(new Style("Title")); this.properties.push(new Style("Title"));
return this; return this;
} }
center(): Paragraph { public center(): Paragraph {
this.properties.push(new Alignment("center")); this.properties.push(new Alignment("center"));
return this; return this;
} }
left(): Paragraph { public left(): Paragraph {
this.properties.push(new Alignment("left")); this.properties.push(new Alignment("left"));
return this; return this;
} }
right(): Paragraph { public right(): Paragraph {
this.properties.push(new Alignment("right")); this.properties.push(new Alignment("right"));
return this; return this;
} }
justified(): Paragraph { public justified(): Paragraph {
this.properties.push(new Alignment("both")); this.properties.push(new Alignment("both"));
return this; return this;
} }
thematicBreak(): Paragraph { public thematicBreak(): Paragraph {
this.properties.push(new ThematicBreak()); this.properties.push(new ThematicBreak());
return this; return this;
} }
pageBreak(): Paragraph { public pageBreak(): Paragraph {
this.properties.push(new PageBreak()); this.properties.push(new PageBreak());
return this; return this;
} }
maxRightTabStop(): Paragraph { public maxRightTabStop(): Paragraph {
this.properties.push(new MaxRightTabStop()); this.properties.push(new MaxRightTabStop());
return this; return this;
} }
leftTabStop(position: number): Paragraph { public leftTabStop(position: number): Paragraph {
this.properties.push(new LeftTabStop(position)); this.properties.push(new LeftTabStop(position));
return this; return this;
} }
bullet(): Paragraph { public bullet(): Paragraph {
this.properties.push(new Style("ListParagraph")); this.properties.push(new Style("ListParagraph"));
this.properties.push(new NumberProperties()); this.properties.push(new NumberProperties(1, 0));
return this; return this;
} }
}
public setNumbering(numbering: Num, indentLevel: number): Paragraph {
this.properties.push(new Style("ListParagraph"));
this.properties.push(new NumberProperties(numbering.id, indentLevel));
return this;
}
public style(styleId: string): Paragraph {
this.properties.push(new Style(styleId));
return this;
}
public indent(start: number, hanging?: number): Paragraph {
this.properties.push(new Indent(start, hanging));
return this;
}
public spacing(params: ISpacingProperties): Paragraph {
this.properties.push(new Spacing(params));
return this;
}
public keepNext(): Paragraph {
this.properties.push(new KeepNext());
return this;
}
public keepLines(): Paragraph {
this.properties.push(new KeepLines());
return this;
}
}

13
ts/docx/paragraph/keep.ts Normal file
View File

@ -0,0 +1,13 @@
import { XmlComponent } from "../xml-components";
export class KeepLines extends XmlComponent {
constructor() {
super("w:keepLines");
}
}
export class KeepNext extends XmlComponent {
constructor() {
super("w:keepNext");
}
}

View File

@ -1,12 +1,12 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Run } from "../run";
import {Run} from "../run"; import { Attributes, XmlComponent } from "../xml-components";
class Break extends XmlComponent { class Break extends XmlComponent {
constructor() { constructor() {
super("w:br"); super("w:br");
this.root.push(new Attributes({ this.root.push(new Attributes({
type: "page" type: "page",
})); }));
} }
} }
@ -17,4 +17,4 @@ export class PageBreak extends Run {
super(); super();
this.root.push(new Break()); this.root.push(new Break());
} }
} }

View File

@ -1,13 +1,12 @@
import {XmlComponent, Attributes} from "../xml-components"; import { XmlComponent } from "../xml-components";
export class ParagraphProperties extends XmlComponent { export class ParagraphProperties extends XmlComponent {
constructor() { constructor() {
super("w:pPr"); super("w:pPr");
this.root.push(new Attributes());
} }
push(item: XmlComponent): void { public push(item: XmlComponent): void {
this.root.push(item); this.root.push(item);
} }
} }

View File

@ -0,0 +1,22 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
export interface ISpacingProperties {
after?: number;
before?: number;
line?: number;
}
class SpacingAttributes extends XmlAttributeComponent<ISpacingProperties> {
protected xmlKeys = {
after: "w:after",
before: "w:before",
line: "w:line",
};
}
export class Spacing extends XmlComponent {
constructor(opts: ISpacingProperties) {
super("w:spacing");
this.root.push(new SpacingAttributes(opts));
}
}

View File

@ -1,11 +1,11 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
export class Style extends XmlComponent { export class Style extends XmlComponent {
constructor(type: string) { constructor(type: string) {
super("w:pStyle"); super("w:pStyle");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: type val: type,
})); }));
} }
} }

View File

@ -1,6 +1,6 @@
import {XmlComponent, Attributes} from "../xml-components"; import { XmlAttributeComponent, XmlComponent } from "../xml-components";
class TabStop extends XmlComponent { export class TabStop extends XmlComponent {
constructor(tab: Tab) { constructor(tab: Tab) {
super("w:tabs"); super("w:tabs");
@ -8,13 +8,19 @@ class TabStop extends XmlComponent {
} }
} }
class Tab extends XmlComponent { export type TabOptions = "left" | "right";
constructor(value: string, position: any) { export class TabAttributes extends XmlAttributeComponent<{val: TabOptions, pos: string | number}> {
protected xmlKeys = {val: "w:val", pos: "w:pos"};
}
export class Tab extends XmlComponent {
constructor(value: TabOptions, position: string | number) {
super("w:tab"); super("w:tab");
this.root.push(new Attributes({ this.root.push(new TabAttributes({
val: value, val: value,
pos: position pos: position,
})); }));
} }
} }

View File

@ -1,12 +1,11 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
import {Style} from "./style";
export class NumberProperties extends XmlComponent { export class NumberProperties extends XmlComponent {
constructor() { constructor(numberId: number, indentLevel: number) {
super("w:numPr"); super("w:numPr");
this.root.push(new IndentLevel(0)); this.root.push(new IndentLevel(indentLevel));
this.root.push(new NumberId(1)); this.root.push(new NumberId(numberId));
} }
} }
@ -15,7 +14,7 @@ class IndentLevel extends XmlComponent {
constructor(level: number) { constructor(level: number) {
super("w:ilvl"); super("w:ilvl");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: level val: level,
})); }));
} }
} }
@ -24,7 +23,7 @@ class NumberId extends XmlComponent {
constructor(id: number) { constructor(id: number) {
super("w:numId"); super("w:numId");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: id val: id,
})); }));
} }
} }

View File

@ -1,8 +1,8 @@
import {XmlComponent} from "../xml-components"; import { XmlComponent } from "../xml-components";
export class Break extends XmlComponent { export class Break extends XmlComponent {
constructor() { constructor() {
super("w:br"); super("w:br");
} }
} }

View File

@ -1,4 +1,4 @@
import {XmlComponent} from "../xml-components"; import { XmlComponent } from "../xml-components";
export class SmallCaps extends XmlComponent { export class SmallCaps extends XmlComponent {

View File

@ -1,11 +1,14 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
export { Underline } from "./underline";
export { SubScript, SuperScript } from "./script";
export { RunFonts } from "./run-fonts";
export class Bold extends XmlComponent { export class Bold extends XmlComponent {
constructor() { constructor() {
super("w:b"); super("w:b");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -15,7 +18,7 @@ export class Italics extends XmlComponent {
constructor() { constructor() {
super("w:i"); super("w:i");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -25,7 +28,7 @@ export class Caps extends XmlComponent {
constructor() { constructor() {
super("w:caps"); super("w:caps");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -35,7 +38,7 @@ export class Color extends XmlComponent {
constructor(color: string) { constructor(color: string) {
super("w:color"); super("w:color");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: color val: color,
})); }));
} }
} }
@ -45,7 +48,7 @@ export class DoubleStrike extends XmlComponent {
constructor() { constructor() {
super("w:dstrike"); super("w:dstrike");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -55,7 +58,7 @@ export class Emboss extends XmlComponent {
constructor() { constructor() {
super("w:emboss"); super("w:emboss");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -65,7 +68,7 @@ export class Imprint extends XmlComponent {
constructor() { constructor() {
super("w:imprint"); super("w:imprint");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -75,7 +78,7 @@ export class Shadow extends XmlComponent {
constructor() { constructor() {
super("w:shadow"); super("w:shadow");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -85,7 +88,7 @@ export class SmallCaps extends XmlComponent {
constructor() { constructor() {
super("w:smallCaps"); super("w:smallCaps");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -95,7 +98,7 @@ export class Strike extends XmlComponent {
constructor() { constructor() {
super("w:strike"); super("w:strike");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: true val: true,
})); }));
} }
} }
@ -105,7 +108,7 @@ export class Size extends XmlComponent {
constructor(size: number) { constructor(size: number) {
super("w:sz"); super("w:sz");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: size val: size,
})); }));
} }
} }

View File

@ -1,75 +1,96 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Break } from "./break";
import {RunProperties} from "./properties"; import { Caps, SmallCaps } from "./caps";
import {Bold, Italics} from "./formatting"; import { Bold, Color, DoubleStrike, Italics, Size, Strike } from "./formatting";
import {Tab} from "./tab"; import { RunProperties } from "./properties";
import {Break} from "./break"; import { RunFonts } from "./run-fonts";
import {SmallCaps, Caps} from "./caps"; import { SubScript, SuperScript } from "./script";
import {Strike, DoubleStrike} from "./strike"; import { Style } from "./style";
import {SubScript, SuperScript} from "./script"; import { Tab } from "./tab";
import {Underline} from "./underline" import { Underline } from "./underline";
import { XmlComponent } from "../xml-components";
export class Run extends XmlComponent { export class Run extends XmlComponent {
private properties: RunProperties; private properties: RunProperties;
constructor() { constructor() {
super("w:r"); super("w:r");
this.properties = new RunProperties(); this.properties = new RunProperties();
this.root.push(this.properties); this.root.push(this.properties);
} }
bold(): Run { public bold(): Run {
this.properties.push(new Bold()); this.properties.push(new Bold());
return this; return this;
} }
italic(): Run { public italic(): Run {
this.properties.push(new Italics()); this.properties.push(new Italics());
return this; return this;
} }
underline(): Run { public underline(underlineType?: string, color?: string): Run {
this.properties.push(new Underline()); this.properties.push(new Underline(underlineType, color));
return this; return this;
} }
break(): Run { public color(color: string): Run {
this.properties.push(new Color(color));
return this;
}
public size(size: number): Run {
this.properties.push(new Size(size));
return this;
}
public break(): Run {
this.root.splice(1, 0, new Break()); this.root.splice(1, 0, new Break());
return this; return this;
} }
tab(): Run { public tab(): Run {
this.root.splice(1, 0, new Tab()); this.root.splice(1, 0, new Tab());
return this; return this;
} }
smallCaps(): Run { public smallCaps(): Run {
this.properties.push(new SmallCaps()); this.properties.push(new SmallCaps());
return this; return this;
} }
allCaps(): Run { public allCaps(): Run {
this.properties.push(new Caps()); this.properties.push(new Caps());
return this; return this;
} }
strike(): Run { public strike(): Run {
this.properties.push(new Strike()); this.properties.push(new Strike());
return this; return this;
} }
doubleStrike(): Run { public doubleStrike(): Run {
this.properties.push(new DoubleStrike()); this.properties.push(new DoubleStrike());
return this; return this;
} }
subScript(): Run { public subScript(): Run {
this.properties.push(new SubScript()); this.properties.push(new SubScript());
return this; return this;
} }
superScript(): Run { public superScript(): Run {
this.properties.push(new SuperScript()); this.properties.push(new SuperScript());
return this; return this;
} }
}
public font(fontName: string): Run {
this.properties.push(new RunFonts(fontName));
return this;
}
public style(styleId: string): Run {
this.properties.push(new Style(styleId));
return this;
}
}

View File

@ -0,0 +1,16 @@
import { IData } from "../../media/data";
import { Run } from "../run";
import { Drawing } from "./run-components/drawing";
export class PictureRun extends Run {
constructor(imageData: IData) {
super();
if (imageData === undefined) {
throw new Error("imageData cannot be undefined");
}
this.root.push(new Drawing(imageData));
}
}

View File

@ -1,4 +1,4 @@
import {XmlComponent} from "../xml-components"; import { XmlComponent } from "../xml-components";
export class RunProperties extends XmlComponent { export class RunProperties extends XmlComponent {
@ -6,7 +6,7 @@ export class RunProperties extends XmlComponent {
super("w:rPr"); super("w:rPr");
} }
push(item: XmlComponent): void { public push(item: XmlComponent): void {
this.root.push(item); this.root.push(item);
} }
} }

View File

@ -0,0 +1,16 @@
import { IData } from "../../../../media/data";
import { XmlComponent } from "../../../xml-components";
import { Inline } from "./inline";
export class Drawing extends XmlComponent {
constructor(imageData: IData) {
super("w:drawing");
if (imageData === undefined) {
throw new Error("imageData cannot be undefined");
}
this.root.push(new Inline(imageData.referenceId));
}
}

View File

@ -0,0 +1,10 @@
import { XmlComponent } from "../../../../../../xml-components";
import { Pic } from "./pic";
export class GraphicData extends XmlComponent {
constructor(referenceId: number) {
super("a:graphicData");
this.root.push(new Pic(referenceId));
}
}

View File

@ -0,0 +1,14 @@
import { XmlComponent } from "../../../../../../../../xml-components";
import { Blip } from "./blip";
import { SourceRectangle } from "./source-rectangle";
import { Stretch } from "./stretch";
export class BlipFill extends XmlComponent {
constructor(referenceId: number) {
super("pic:blipFill");
this.root.push(new Blip(referenceId));
this.root.push(new SourceRectangle());
this.root.push(new Stretch());
}
}

View File

@ -0,0 +1,21 @@
import { XmlAttributeComponent, XmlComponent } from "../../../../../../../../xml-components";
interface IBlipProperties {
embed: string;
}
class BlipAttributes extends XmlAttributeComponent<IBlipProperties> {
protected xmlKeys = {
embed: "r:embed",
};
}
export class Blip extends XmlComponent {
constructor(referenceId: number) {
super("a:blip");
this.root.push(new BlipAttributes({
embed: `rId${referenceId}`,
}));
}
}

View File

@ -0,0 +1,8 @@
import { XmlComponent } from "../../../../../../../../xml-components";
export class SourceRectangle extends XmlComponent {
constructor() {
super("a:srcRect");
}
}

View File

@ -0,0 +1,16 @@
import { XmlComponent } from "../../../../../../../../xml-components";
class FillRectangle extends XmlComponent {
constructor() {
super("a:fillRect");
}
}
export class Stretch extends XmlComponent {
constructor() {
super("a:stretch");
this.root.push(new FillRectangle());
}
}

View File

@ -0,0 +1,10 @@
import { XmlComponent } from "../../../../../../../xml-components";
import { BlipFill } from "./blip/blip-fill";
export class Pic extends XmlComponent {
constructor(referenceId: number) {
super("pic:pic");
this.root.push(new BlipFill(referenceId));
}
}

View File

@ -0,0 +1,23 @@
import { XmlAttributeComponent, XmlComponent } from "../../../../../xml-components";
import { GraphicData } from "./graphic-data";
interface IGraphicProperties {
a: string;
}
class GraphicAttributes extends XmlAttributeComponent<IGraphicProperties> {
protected xmlKeys = {
a: "xmlns:a",
};
}
export class Graphic extends XmlComponent {
constructor(referenceId: number) {
super("a:graphic");
this.root.push(new GraphicAttributes({
a: "http://schemas.openxmlformats.org/drawingml/2006/main",
}));
this.root.push(new GraphicData(referenceId));
}
}

View File

@ -0,0 +1,10 @@
import { XmlComponent } from "../../../../xml-components";
import { Graphic } from "./graphic";
export class Inline extends XmlComponent {
constructor(referenceId: number) {
super("wp:inline");
this.root.push(new Graphic(referenceId));
}
}

View File

@ -0,0 +1,15 @@
import { XmlAttributeComponent, XmlComponent } from "../../xml-components";
class TextAttributes extends XmlAttributeComponent<{space: "default" | "preserve"}> {
protected xmlKeys = {space: "xml:space"};
}
export class Text extends XmlComponent {
constructor(text: string) {
super("w:t");
this.root.push(new TextAttributes({space: "preserve"}));
if (text) {
this.root.push(text);
}
}
}

27
ts/docx/run/run-fonts.ts Normal file
View File

@ -0,0 +1,27 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
interface IRunFontAttributesProperties {
ascii: string;
hAnsi: string;
hint?: string;
}
class RunFontAttributes extends XmlAttributeComponent<IRunFontAttributesProperties> {
protected xmlKeys = {
ascii: "w:ascii",
hAnsi: "w:hAnsi",
hint: "w:hint",
};
}
export class RunFonts extends XmlComponent {
constructor(ascii: string, hint?: string) {
super("w:rFonts");
this.root.push(new RunFontAttributes({
ascii: ascii,
hAnsi: ascii,
hint: hint,
}));
}
}

View File

@ -1,11 +1,11 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
abstract class VerticalAlign extends XmlComponent { export abstract class VerticalAlign extends XmlComponent {
constructor(type: string) { constructor(type: string) {
super("w:vertAlign"); super("w:vertAlign");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: type val: type,
})); }));
} }
} }
@ -22,4 +22,4 @@ export class SubScript extends VerticalAlign {
constructor() { constructor() {
super("subscript"); super("subscript");
} }
} }

View File

@ -1,15 +0,0 @@
import {XmlComponent} from "../xml-components";
export class Strike extends XmlComponent {
constructor() {
super("w:strike");
}
}
export class DoubleStrike extends XmlComponent {
constructor() {
super("w:dstrike");
}
}

13
ts/docx/run/style.ts Normal file
View File

@ -0,0 +1,13 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
class StyleAttributes extends XmlAttributeComponent<{val: string}> {
protected xmlKeys = {val: "w:val"};
}
export class Style extends XmlComponent {
constructor(styleId: string) {
super("w:rStyle");
this.root.push(new StyleAttributes({val: styleId}));
}
}

View File

@ -1,8 +1,8 @@
import {XmlComponent} from "../xml-components"; import { XmlComponent } from "../xml-components";
export class Tab extends XmlComponent { export class Tab extends XmlComponent {
constructor() { constructor() {
super("w:tab"); super("w:tab");
} }
} }

View File

@ -1,5 +1,5 @@
import {Text} from "./text"; import { Run } from "../run";
import {Run} from "../run"; import { Text } from "./run-components/text";
export class TextRun extends Run { export class TextRun extends Run {
@ -7,4 +7,4 @@ export class TextRun extends Run {
super(); super();
this.root.push(new Text(text)); this.root.push(new Text(text));
} }
} }

View File

@ -1,9 +0,0 @@
import {XmlUnitComponent} from "../xml-components"
export class Text extends XmlUnitComponent {
constructor(text: string) {
super("w:t");
this.root = text;
}
}

View File

@ -1,20 +1,20 @@
import {XmlComponent, Attributes} from "../xml-components"; import { Attributes, XmlComponent } from "../xml-components";
abstract class BaseUnderline extends XmlComponent { export abstract class BaseUnderline extends XmlComponent {
constructor(underlineType: string, color?: string) { constructor(underlineType: string, color?: string) {
super("w:u"); super("w:u");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: underlineType, val: underlineType,
color: color color: color,
})); }));
} }
} }
export class Underline extends BaseUnderline { export class Underline extends BaseUnderline {
constructor() { constructor(underlineType: string = "single", color?: string) {
super(""); super(underlineType, color);
} }
} }
@ -88,7 +88,6 @@ export class DoubleUnderline extends BaseUnderline {
} }
} }
export class SingleUnderline extends BaseUnderline { export class SingleUnderline extends BaseUnderline {
constructor() { constructor() {
@ -129,4 +128,4 @@ export class WordsUnderline extends BaseUnderline {
constructor() { constructor() {
super("words"); super("words");
} }
} }

View File

@ -1,3 +0,0 @@
export class Table {
}

21
ts/docx/table/grid.ts Normal file
View File

@ -0,0 +1,21 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
export class TableGrid extends XmlComponent {
constructor(cols: number[]) {
super("w:tblGrid");
cols.forEach((col) => this.root.push(new GridCol(col)));
}
}
class GridColAttributes extends XmlAttributeComponent<{w: number}> {
protected xmlKeys = {w: "w:w"};
}
export class GridCol extends XmlComponent {
constructor(width?: number) {
super("w:gridCol");
if (width !== undefined) {
this.root.push(new GridColAttributes({w: width}));
}
}
}

123
ts/docx/table/index.ts Normal file
View File

@ -0,0 +1,123 @@
import { Paragraph } from "../paragraph";
import { XmlComponent } from "../xml-components";
import { TableGrid } from "./grid";
import { TableProperties, WidthTypes } from "./properties";
export class Table extends XmlComponent {
private properties: TableProperties;
private rows: TableRow[];
private grid: TableGrid;
constructor(rows: number, cols: number) {
super("w:tbl");
this.properties = new TableProperties();
this.root.push(this.properties);
const gridCols: number[] = [];
for (let i = 0; i < cols; i++) {
/*
0-width columns don't get rendered correctly, so we need
to give them some value. A reasonable default would be
~6in / numCols, but if we do that it becomes very hard
to resize the table using setWidth, unless the layout
algorithm is set to 'fixed'. Instead, the approach here
means even in 'auto' layout, setting a width on the
table will make it look reasonable, as the layout
algorithm will expand columns to fit its content
*/
gridCols.push(1);
}
this.grid = new TableGrid(gridCols);
this.root.push(this.grid);
this.rows = [];
for (let i = 0; i < rows; i++) {
const cells: TableCell[] = [];
for (let j = 0; j < cols; j++) {
cells.push(new TableCell());
}
const row = new TableRow(cells);
this.rows.push(row);
this.root.push(row);
}
}
public getRow(ix: number): TableRow {
return this.rows[ix];
}
public getCell(row: number, col: number): TableCell {
return this.getRow(row).getCell(col);
}
public setWidth(type: WidthTypes, width: number | string): Table {
this.properties.setWidth(type, width);
return this;
}
public fixedWidthLayout(): Table {
this.properties.fixedWidthLayout();
return this;
}
}
export class TableRow extends XmlComponent {
private properties: TableRowProperties;
private cells: TableCell[];
constructor(cells: TableCell[]) {
super("w:tr");
this.properties = new TableRowProperties();
this.root.push(this.properties);
this.cells = cells;
cells.forEach((c) => this.root.push(c));
}
public getCell(ix: number): TableCell {
return this.cells[ix];
}
}
export class TableRowProperties extends XmlComponent {
constructor() {
super("w:trPr");
}
}
export class TableCell extends XmlComponent {
private properties: TableCellProperties;
constructor() {
super("w:tc");
this.properties = new TableCellProperties();
this.root.push(this.properties);
}
public addContent(content: Paragraph | Table): TableCell {
this.root.push(content);
return this;
}
public prepForXml(): XmlableObject {
// Cells must end with a paragraph
const retval = super.prepForXml();
const content = retval["w:tc"];
if (!content[content.length - 1]["w:p"]) {
content.push(new Paragraph().prepForXml());
}
return retval;
}
public createParagraph(text?: string): Paragraph {
const para = new Paragraph(text);
this.addContent(para);
return para;
}
}
export class TableCellProperties extends XmlComponent {
constructor() {
super("w:tcPr");
}
}

View File

@ -0,0 +1,48 @@
import { XmlAttributeComponent, XmlComponent } from "../xml-components";
export type WidthTypes = "dxa" | "pct" | "nil" | "auto";
export class TableProperties extends XmlComponent {
constructor() {
super("w:tblPr");
}
public setWidth(type: WidthTypes, w: number | string): TableProperties {
this.root.push(new PreferredTableWidth(type, w));
return this;
}
public fixedWidthLayout(): TableProperties {
this.root.push(new TableLayout("fixed"));
return this;
}
}
interface ITableWidth {
type: WidthTypes;
w: number | string;
}
class TableWidthAttributes extends XmlAttributeComponent<ITableWidth> {
protected xmlKeys = {type: "w:type", w: "w:w"};
}
class PreferredTableWidth extends XmlComponent {
constructor(type: WidthTypes, w: number | string) {
super("w:tblW");
this.root.push(new TableWidthAttributes({type, w}));
}
}
type TableLayoutOptions = "autofit" | "fixed";
class TableLayoutAttributes extends XmlAttributeComponent<{type: TableLayoutOptions}> {
protected xmlKeys = {type: "w:type"};
}
class TableLayout extends XmlComponent {
constructor(type: TableLayoutOptions) {
super("w:tblLayout");
this.root.push(new TableLayoutAttributes({type}));
}
}

View File

@ -1,7 +1,7 @@
import {XmlAttributeComponent} from "./default-attributes"; import { XmlAttributeComponent } from "./default-attributes";
interface AttributesProperties { export interface IAttributesProperties {
val?: any; val?: string | number | boolean;
color?: string; color?: string;
space?: string; space?: string;
sz?: string; sz?: string;
@ -19,32 +19,29 @@ interface AttributesProperties {
footer?: string; footer?: string;
gutter?: string; gutter?: string;
linePitch?: string; linePitch?: string;
pos?: string; pos?: string | number; // Little strange. Perhaps it is normal. Need to clarify in the spec.
} }
export class Attributes extends XmlAttributeComponent { export class Attributes extends XmlAttributeComponent<IAttributesProperties> {
protected xmlKeys = {
constructor(properties?: AttributesProperties) { val: "w:val",
super({ color: "w:color",
val: "w:val", space: "w:space",
color: "w:color", sz: "w:sz",
space: "w:space", type: "w:type",
sz: "w:sz", rsidR: "w:rsidR",
type: "w:type", rsidRPr: "w:rsidRPr",
rsidR: "w:rsidR", rsidSect: "w:rsidSect",
rsidRPr: "w:rsidRPr", w: "w:w",
rsidSect: "w:rsidSect", h: "w:h",
w: "w:w", top: "w:top",
h: "w:h", right: "w:right",
top: "w:top", bottom: "w:bottom",
right: "w:right", left: "w:left",
bottom: "w:bottom", header: "w:header",
left: "w:left", footer: "w:footer",
header: "w:header", gutter: "w:gutter",
footer: "w:footer", linePitch: "w:linePitch",
gutter: "w:gutter", pos: "w:pos",
linePitch: "w:linePitch", };
pos: "w:pos" }
}, properties);
}
}

View File

@ -5,7 +5,5 @@ export abstract class BaseXmlComponent {
this.rootKey = rootKey; this.rootKey = rootKey;
} }
abstract replaceKey(): void; public abstract prepForXml(): XmlableObject;
clearVariables(): void { }
};
}

View File

@ -1,30 +1,25 @@
import {BaseXmlComponent} from "./base"; import { BaseXmlComponent } from "./base";
import * as _ from "lodash";
export abstract class XmlAttributeComponent extends BaseXmlComponent { export type AttributeMap<T> = {[P in keyof T]: string};
protected root: Object;
private xmlKeys: Object;
constructor(xmlKeys: Object, properties: Object) { export abstract class XmlAttributeComponent<T> extends BaseXmlComponent {
protected root: T;
protected xmlKeys: AttributeMap<T>;
constructor(properties: T) {
super("_attr"); super("_attr");
this.xmlKeys = xmlKeys;
this.root = properties; this.root = properties;
if (!properties) {
this.root = {};
}
} }
replaceKey(): void { public prepForXml(): XmlableObject {
if (this.root !== undefined) { const attrs = {};
_.forOwn(this.root, (value, key) => { Object.keys(this.root).forEach((key) => {
let newKey = this.xmlKeys[key]; const value = this.root[key];
this.root[newKey] = value; if (value !== undefined) {
delete this.root[key]; const newKey = this.xmlKeys[key];
}); attrs[newKey] = value;
this[this.rootKey] = this.root; }
delete this.root; });
} return {_attr: attrs};
} }
} }

View File

@ -1,30 +1,26 @@
import * as _ from "lodash"; import { BaseXmlComponent } from "./base";
import {BaseXmlComponent} from "./base"; export { BaseXmlComponent };
export abstract class XmlComponent extends BaseXmlComponent { export abstract class XmlComponent extends BaseXmlComponent {
protected root: Array<BaseXmlComponent>; protected root: Array<BaseXmlComponent | string>;
constructor(rootKey: string) { constructor(rootKey: string) {
super(rootKey); super(rootKey);
this.root = new Array<BaseXmlComponent>(); this.root = new Array<BaseXmlComponent>();
} }
replaceKey(): void { public prepForXml(): XmlableObject {
// console.log(this.rootKey); const children = this.root.map((comp) => {
// console.log(this.root); if (comp instanceof BaseXmlComponent) {
if (this.root !== undefined) { return comp.prepForXml();
this.root.forEach(root => { }
if (root && root instanceof BaseXmlComponent) { return comp;
root.replaceKey(); }).filter((comp) => comp); // Exclude null, undefined, and empty strings
} return {
}); [this.rootKey]: children,
this[this.rootKey] = this.root; };
delete this.root;
}
} }
} }
export * from "./attributes" export * from "./attributes";
export * from "./default-attributes"; export * from "./default-attributes";
export * from "./unit";
export * from "./property";

View File

@ -1,57 +0,0 @@
import {XmlComponent} from "./";
import {ParagraphProperties} from "../paragraph/properties";
import {RunProperties} from "../run/properties";
export class ParagraphPropertyXmlComponent extends XmlComponent {
private paragraphProperties: ParagraphProperties;
constructor(rootKey) {
super(rootKey);
this.paragraphProperties = new ParagraphProperties();
this.root.push(this.paragraphProperties);
}
clearVariables(): void {
this.paragraphProperties.clearVariables();
delete this.paragraphProperties;
}
}
export class RunPropertyXmlComponent extends XmlComponent {
private runProperties: RunProperties;
constructor(rootKey) {
super(rootKey);
this.runProperties = new RunProperties();
this.root.push(this.runProperties);
}
clearVariables(): void {
this.runProperties.clearVariables();
delete this.runProperties;
}
}
export class MultiPropertyXmlComponent extends XmlComponent {
private runProperties: RunProperties;
private paragraphProperties: ParagraphProperties;
constructor(rootKey) {
super(rootKey);
this.runProperties = new RunProperties();
this.root.push(this.runProperties);
this.paragraphProperties = new ParagraphProperties();
this.root.push(this.paragraphProperties);
}
clearVariables(): void {
this.runProperties.clearVariables();
this.paragraphProperties.clearVariables();
delete this.runProperties;
delete this.paragraphProperties;
}
}

View File

@ -1,16 +0,0 @@
import {BaseXmlComponent} from "./base";
export abstract class XmlUnitComponent extends BaseXmlComponent {
protected root: string;
constructor(rootKey: string) {
super(rootKey);
}
replaceKey(): void {
if (this.root !== undefined) {
this[this.rootKey] = this.root;
delete this.root;
}
}
}

View File

@ -0,0 +1,3 @@
declare interface XmlableObject extends Object {
_attr?: { [key: string]: (string | number | boolean) }
}

View File

@ -1,52 +1,7 @@
import * as _ from "lodash"; import { BaseXmlComponent } from "../docx/xml-components";
import {XmlComponent} from "../docx/xml-components";
export class Formatter { export class Formatter {
public format(input: BaseXmlComponent): XmlableObject {
format(input: any): Object { return input.prepForXml();
input.clearVariables();
this.replaceKeys(input);
let newJson = this.clense(input);
// console.log(JSON.stringify(newJson, null, " "));
return newJson;
} }
}
private replaceKeys(input: XmlComponent): Object {
input.replaceKey();
return input;
}
private clense(input: any): Object {
let newJson = this.jsonify(input);
this.deepTraverseJson(newJson, (parent, value, key) => {
if (key === "properties") {
delete parent[key];
}
if (key === "xmlKeys") {
delete parent[key];
}
if (key === "rootKey") {
delete parent[key];
}
});
return newJson;
}
private jsonify(obj: Object): Object {
let stringifiedJson = JSON.stringify(obj);
return JSON.parse(stringifiedJson);
}
private deepTraverseJson(json: Object, lambda: (json: any, value: any, key: any) => void): void {
_.forOwn(json, (value, key) => {
if (_.isObject(value) && key !== "xmlKeys" && key !== "rootKey") {
this.deepTraverseJson(value, lambda);
}
lambda(json, value, key);
});
}
}

View File

@ -1,2 +1,3 @@
export {LocalPacker} from "./packer/local"; export { LocalPacker } from "./packer/local";
export {ExpressPacker} from "./packer/express"; export { ExpressPacker } from "./packer/express";
export { Packer } from "./packer/packer";

View File

@ -1,15 +1,16 @@
import {Packer} from "./packer";
import * as fs from "fs";
import * as express from "express"; import * as express from "express";
import {Document} from "../../docx/document"; import { Document } from "../../docx/document";
import {Properties} from "../../properties"; import { Media } from "../../media";
import {Numbering} from "../../numbering"; import { Numbering } from "../../numbering";
import { Properties } from "../../properties";
import { Styles } from "../../styles";
import { Packer } from "./packer";
export class ExpressPacker extends Packer { export class ExpressPacker extends Packer {
private res: express.Response; private res: express.Response;
constructor(document: Document, res: express.Response, styles?: any, properties?: Properties, numbering?: Numbering) { constructor(document: Document, res: express.Response, styles?: Styles, properties?: Properties, numbering?: Numbering, media?: Media) {
super(document, styles, properties, numbering); super(document, styles, properties, numbering, media);
this.res = res; this.res = res;
this.res.on("close", () => { this.res.on("close", () => {
@ -17,8 +18,8 @@ export class ExpressPacker extends Packer {
}); });
} }
pack(name: string): void { public pack(name: string): void {
this.res.attachment(name + ".docx"); this.res.attachment(`${name}.docx`);
super.pack(this.res); super.compile(this.res);
} }
} }

View File

@ -1,18 +1,21 @@
import {Packer} from "./packer";
import * as fs from "fs"; import * as fs from "fs";
import {Document} from "../../docx/document"; import { Document } from "../../docx/document";
import {Properties} from "../../properties"; import { Media } from "../../media";
import {Numbering} from "../../numbering"; import { Numbering } from "../../numbering";
import { Properties } from "../../properties";
import { Styles } from "../../styles";
import { Packer } from "./packer";
export class LocalPacker extends Packer { export class LocalPacker extends Packer {
private stream: fs.WriteStream; private stream: fs.WriteStream;
constructor(document: Document, styles?: any, properties?: Properties, numbering?: Numbering) { constructor(document: Document, styles?: Styles, properties?: Properties, numbering?: Numbering, media?: Media) {
super(document, styles, properties, numbering); super(document, styles, properties, numbering, media);
} }
pack(path: string): void { public pack(path: string): void {
this.stream = fs.createWriteStream(path); path = path.replace(/.docx$/, "");
super.pack(this.stream); this.stream = fs.createWriteStream(`${path}.docx`);
super.compile(this.stream);
} }
} }

View File

@ -1,96 +1,91 @@
import * as archiver from "archiver"; import * as archiver from "archiver";
import * as express from "express";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path";
import * as xml from "xml"; import * as xml from "xml";
import {Formatter} from "../formatter"; import { Document } from "../../docx";
import {Document} from "../../docx"; import { Media } from "../../media";
import {Styles} from "../../styles"; import { Numbering } from "../../numbering";
import {Properties} from "../../properties"; import { Properties } from "../../properties";
import {Numbering} from "../../numbering"; import { Styles } from "../../styles";
import {DefaultStylesFactory} from "../../styles/factory"; import { DefaultStylesFactory } from "../../styles/factory";
import { Formatter } from "../formatter";
let appRoot = require("app-root-path"); const TEMPLATE_PATH = path.resolve(__dirname, "../../../template");
export abstract class Packer { export abstract class Packer {
protected archive: any; protected archive: archiver.Archiver;
private formatter: Formatter; private formatter: Formatter;
protected document: Document;
private style: Styles; private style: Styles;
private properties: Properties;
private numbering: Numbering;
constructor(document: Document, style?: any, properties?: Properties, numbering?: Numbering) { constructor(
protected document: Document,
style?: Styles,
private properties: Properties = new Properties({
creator: "Un-named",
revision: "1",
lastModifiedBy: "Un-named",
}),
private numbering: Numbering = new Numbering(),
private media: Media = new Media(),
) {
this.formatter = new Formatter(); this.formatter = new Formatter();
this.document = document;
this.style = style;
this.properties = properties;
this.numbering = numbering;
this.archive = archiver.create("zip", {}); this.archive = archiver.create("zip", {});
if (!style) { if (style) {
let stylesFactory = new DefaultStylesFactory(); this.style = style;
} else {
const stylesFactory = new DefaultStylesFactory();
this.style = stylesFactory.newInstance(); this.style = stylesFactory.newInstance();
} }
if (!properties) {
this.properties = new Properties({
creator: "Un-named",
revision: "1",
lastModifiedBy: "Un-named"
});
}
if (!numbering) {
this.numbering = new Numbering();
}
this.archive.on("error", (err) => { this.archive.on("error", (err) => {
throw err; throw err;
}); });
} }
pack(output: any): void { protected compile(output: fs.WriteStream | express.Response): void {
this.archive.pipe(output); this.archive.pipe(output);
console.log(appRoot.path + "/template");
this.archive.glob("**", { this.archive.glob("**", {
expand: true, cwd: TEMPLATE_PATH,
cwd: appRoot.path + "/template",
}); });
this.archive.glob("**/.rels", { this.archive.glob("**/.rels", {
expand: true, cwd: TEMPLATE_PATH,
cwd: appRoot.path + "/template",
}); });
// this.archive.file(appRoot.path + "/template/[Content_Types].xml", { name: "[Content_Types].xml" }); const xmlDocument = xml(this.formatter.format(this.document));
// console.log(__dirname + "/packer.js"); const xmlStyles = xml(this.formatter.format(this.style));
// this.archive.file(__dirname + "/packer.js", { name: "/[Content_Types].xml" }); const xmlProperties = xml(this.formatter.format(this.properties), {
declaration: {
standalone: "yes",
encoding: "UTF-8",
},
});
const xmlNumbering = xml(this.formatter.format(this.numbering));
/*this.archive.directory(appRoot.path + "/template", {
name: "/root/g.txt",
prefix: "root"
});*/
let xmlDocument = xml(this.formatter.format(this.document));
let xmlStyles = xml(this.formatter.format(this.style));
let xmlProperties = xml(this.formatter.format(this.properties), { declaration: { standalone: "yes", encoding: "UTF-8" } });
let xmlNumbering = xml(this.formatter.format(this.numbering));
// console.log(JSON.stringify(this.numbering, null, " "));
console.log(xmlNumbering);
this.archive.append(xmlDocument, { this.archive.append(xmlDocument, {
name: "word/document.xml" name: "word/document.xml",
}); });
this.archive.append(xmlStyles, { this.archive.append(xmlStyles, {
name: "word/styles.xml" name: "word/styles.xml",
}); });
this.archive.append(xmlProperties, { this.archive.append(xmlProperties, {
name: "docProps/core.xml" name: "docProps/core.xml",
}); });
this.archive.append(xmlNumbering, { this.archive.append(xmlNumbering, {
name: "word/numbering.xml" name: "word/numbering.xml",
}); });
for (const data of this.media.array) {
this.archive.append(data.stream, {
name: `media/${data.fileName}`,
});
}
this.archive.finalize(); this.archive.finalize();
} }
} }

View File

@ -1,2 +1,6 @@
export * from "./docx"; export * from "./docx";
export * from "./export"; export * from "./export";
export { Numbering } from "./numbering";
export { Styles } from "./styles";
export { Media } from "./media";
export * from "./export";

8
ts/media/data.ts Normal file
View File

@ -0,0 +1,8 @@
import * as fs from "fs";
export interface IData {
referenceId: number;
stream: fs.ReadStream;
path: string;
fileName: string;
}

40
ts/media/index.ts Normal file
View File

@ -0,0 +1,40 @@
import * as fs from "fs";
import * as path from "path";
import { IData } from "./data";
export class Media {
private map: Map<string, IData>;
constructor() {
this.map = new Map<string, IData>();
}
public getMedia(key: string): IData {
const data = this.map.get(key);
if (data === undefined) {
throw new Error(`Cannot find image with the key ${key}`);
}
return data;
}
public addMedia(key: string, filePath: string): void {
this.map.set(key, {
referenceId: this.map.values.length,
stream: fs.createReadStream(filePath),
path: filePath,
fileName: path.basename(filePath),
});
}
public get array(): IData[] {
const array = new Array<IData>();
this.map.forEach((data) => {
array.push(data);
});
return array;
}
}

View File

@ -1,42 +1,39 @@
import {XmlComponent} from "../docx/xml-components"; import { XmlAttributeComponent, XmlComponent } from "../docx/xml-components";
import {XmlAttributeComponent} from "../docx/xml-components"; import { Level } from "./level";
import {Level} from "./level"; import { MultiLevelType } from "./multi-level-type";
import {MultiLevelType} from "./multi-level-type";
import * as _ from "lodash";
interface AbstractNumberingAttributesProperties { interface IAbstractNumberingAttributesProperties {
abstractNumId?: number; abstractNumId?: number;
restartNumberingAfterBreak?: number; restartNumberingAfterBreak?: number;
} }
class AbstractNumberingAttributes extends XmlAttributeComponent { class AbstractNumberingAttributes extends XmlAttributeComponent<IAbstractNumberingAttributesProperties> {
protected xmlKeys = {
constructor(properties: AbstractNumberingAttributesProperties) { abstractNumId: "w:abstractNumId",
super({ restartNumberingAfterBreak: "w15:restartNumberingAfterBreak",
abstractNumId: "w:abstractNumId", };
restartNumberingAfterBreak: "w15:restartNumberingAfterBreak"
}, properties);
}
} }
export class AbstractNumbering extends XmlComponent { export class AbstractNumbering extends XmlComponent {
public id: number;
constructor(id: number) { constructor(id: number) {
super("w:abstractNum"); super("w:abstractNum");
this.root.push(new AbstractNumberingAttributes({ this.root.push(new AbstractNumberingAttributes({
abstractNumId: id, abstractNumId: id,
restartNumberingAfterBreak: 0 restartNumberingAfterBreak: 0,
})); }));
this.root.push(new MultiLevelType("hybridMultilevel")); this.root.push(new MultiLevelType("hybridMultilevel"));
this.id = id;
} }
addLevel(level: Level): void { public addLevel(level: Level): void {
this.root.push(level); this.root.push(level);
} }
clearVariables() { public createLevel(num: number, format: string, text: string, align: string = "start"): Level {
_.forEach(this.root, element => { const level = new Level(num, format, text, align);
element.clearVariables(); this.addLevel(level);
}); return level;
} }
} }

View File

@ -1,27 +0,0 @@
import {XmlComponent, XmlAttributeComponent} from "../docx/xml-components";
interface IndentAttributesProperties {
left: number;
hanging: number;
}
class IndentAttributes extends XmlAttributeComponent {
constructor(properties: IndentAttributesProperties) {
super({
left: "w:left",
hanging: "w:hanging"
}, properties);
}
}
export class Indent extends XmlComponent {
constructor(left: number, hanging: number) {
super("w:ind");
this.root.push(new IndentAttributes({
left: left,
hanging: hanging
}));
}
}

View File

@ -1,13 +1,12 @@
import {MultiPropertyXmlComponent} from "../docx/xml-components"; import { DocumentAttributes } from "../docx/document/document-attributes";
import {DocumentAttributes} from "../docx/document/document-attributes"; import { Indent } from "../docx/paragraph/indent";
import {AbstractNumbering} from "./abstract-numbering"; import { RunFonts } from "../docx/run/run-fonts";
import {Level} from "./level"; import { XmlComponent } from "../docx/xml-components";
import {Indent} from "./indent"; import { AbstractNumbering } from "./abstract-numbering";
import {RunFonts} from "./run-fonts"; import { Num } from "./num";
import {Num} from "./num";
import * as _ from "lodash";
export class Numbering extends MultiPropertyXmlComponent { export class Numbering extends XmlComponent {
private nextId: number;
constructor() { constructor() {
super("w:numbering"); super("w:numbering");
@ -28,65 +27,61 @@ export class Numbering extends MultiPropertyXmlComponent {
wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
wne: "http://schemas.microsoft.com/office/word/2006/wordml", wne: "http://schemas.microsoft.com/office/word/2006/wordml",
wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
Ignorable: "w14 w15 wp14" Ignorable: "w14 w15 wp14",
})); }));
let abstractNumbering = new AbstractNumbering(0); this.nextId = 0;
let level0 = new Level(0, "bullet", "•", "left"); const abstractNumbering = this.createAbstractNumbering();
level0.addParagraphProperty(new Indent(720, 360));
level0.addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.addLevel(level0);
let level1 = new Level(1, "bullet", "o", "left"); abstractNumbering.createLevel(0, "bullet", "", "left")
level1.addParagraphProperty(new Indent(1440, 360)); .addParagraphProperty(new Indent(720, 360))
level1.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.addLevel(level1);
let level2 = new Level(2, "bullet", "", "left"); abstractNumbering.createLevel(1, "bullet", "o", "left")
level2.addParagraphProperty(new Indent(2160, 360)); .addParagraphProperty(new Indent(1440, 360))
level2.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.addLevel(level2);
let level3 = new Level(3, "bullet", "•", "left"); abstractNumbering.createLevel(2, "bullet", "•", "left")
level3.addParagraphProperty(new Indent(2880, 360)); .addParagraphProperty(new Indent(2160, 360))
level3.addRunProperty(new RunFonts("Symbol", "default")); .addRunProperty(new RunFonts("Wingdings", "default"));
abstractNumbering.addLevel(level3);
let level4 = new Level(4, "bullet", "o", "left"); abstractNumbering.createLevel(3, "bullet", "", "left")
level4.addParagraphProperty(new Indent(3600, 360)); .addParagraphProperty(new Indent(2880, 360))
level4.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.addLevel(level4);
let level5 = new Level(5, "bullet", "", "left"); abstractNumbering.createLevel(4, "bullet", "o", "left")
level5.addParagraphProperty(new Indent(4320, 360)); .addParagraphProperty(new Indent(3600, 360))
level5.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.addLevel(level5);
let level6 = new Level(6, "bullet", "•", "left"); abstractNumbering.createLevel(5, "bullet", "•", "left")
level6.addParagraphProperty(new Indent(5040, 360)); .addParagraphProperty(new Indent(4320, 360))
level6.addRunProperty(new RunFonts("Symbol", "default")); .addRunProperty(new RunFonts("Wingdings", "default"));
abstractNumbering.addLevel(level6);
let level7 = new Level(4, "bullet", "o", "left"); abstractNumbering.createLevel(6, "bullet", "", "left")
level7.addParagraphProperty(new Indent(5760, 360)); .addParagraphProperty(new Indent(5040, 360))
level7.addRunProperty(new RunFonts("Courier New", "default")); .addRunProperty(new RunFonts("Symbol", "default"));
abstractNumbering.addLevel(level7);
let level8 = new Level(5, "bullet", "", "left"); abstractNumbering.createLevel(7, "bullet", "o", "left")
level8.addParagraphProperty(new Indent(6480, 360)); .addParagraphProperty(new Indent(5760, 360))
level8.addRunProperty(new RunFonts("Wingdings", "default")); .addRunProperty(new RunFonts("Courier New", "default"));
abstractNumbering.addLevel(level8);
this.root.push(abstractNumbering); abstractNumbering.createLevel(8, "bullet", "•", "left")
this.root.push(new Num(1, 0)); .addParagraphProperty(new Indent(6480, 360))
.addRunProperty(new RunFonts("Wingdings", "default"));
this.createConcreteNumbering(abstractNumbering);
} }
clearVariables() { public createAbstractNumbering(): AbstractNumbering {
super.clearVariables(); const num = new AbstractNumbering(this.nextId++);
_.forEach(this.root, element => { this.root.push(num);
console.log(element); return num;
element.clearVariables();
});
} }
}
public createConcreteNumbering(abstractNumbering: AbstractNumbering): Num {
const num = new Num(this.nextId++, abstractNumbering.id);
this.root.push(num);
return num;
}
}

View File

@ -1,21 +1,19 @@
import {XmlComponent, Attributes, MultiPropertyXmlComponent} from "../docx/xml-components"; import * as paragraph from "../docx/paragraph/formatting";
import {XmlAttributeComponent} from "../docx/xml-components"; import { ParagraphProperties } from "../docx/paragraph/properties";
import {RunProperties} from "../docx/run/properties"; import * as formatting from "../docx/run/formatting";
import {ParagraphProperties} from "../docx/paragraph/properties"; import { RunProperties } from "../docx/run/properties";
import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components";
interface LevelAttributesProperties { interface ILevelAttributesProperties {
ilvl?: number; ilvl?: number;
tentative?: number; tentative?: number;
} }
class LevelAttributes extends XmlAttributeComponent { class LevelAttributes extends XmlAttributeComponent<ILevelAttributesProperties> {
protected xmlKeys = {
constructor(properties: LevelAttributesProperties) { ilvl: "w:ilvl",
super({ tentative: "w15:tentative",
ilvl: "w:ilvl", };
tentative: "w15:tentative"
}, properties);
}
} }
class Start extends XmlComponent { class Start extends XmlComponent {
@ -23,7 +21,7 @@ class Start extends XmlComponent {
constructor(value: number) { constructor(value: number) {
super("w:start"); super("w:start");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }
@ -33,7 +31,7 @@ class NumberFormat extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:numFmt"); super("w:numFmt");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }
@ -43,7 +41,7 @@ class LevelText extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:lvlText"); super("w:lvlText");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }
@ -53,26 +51,34 @@ class LevelJc extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:lvlJc"); super("w:lvlJc");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }
export class Level extends XmlComponent { export class LevelBase extends XmlComponent {
private paragraphProperties: ParagraphProperties; private paragraphProperties: ParagraphProperties;
private runProperties: RunProperties; private runProperties: RunProperties;
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) { constructor(level: number, start?: number, numberFormat?: string, levelText?: string, lvlJc?: string) {
super("w:lvl"); super("w:lvl");
this.root.push(new LevelAttributes({ this.root.push(new LevelAttributes({
ilvl: level, ilvl: level,
tentative: 1 tentative: 1,
})); }));
this.root.push(new Start(1)); if (start !== undefined) {
this.root.push(new NumberFormat(numberFormat)); this.root.push(new Start(start));
this.root.push(new LevelText(levelText)); }
this.root.push(new LevelJc(lvlJc)); if (numberFormat !== undefined) {
this.root.push(new NumberFormat(numberFormat));
}
if (levelText !== undefined) {
this.root.push(new LevelText(levelText));
}
if (lvlJc !== undefined) {
this.root.push(new LevelJc(lvlJc));
}
this.paragraphProperties = new ParagraphProperties(); this.paragraphProperties = new ParagraphProperties();
this.runProperties = new RunProperties(); this.runProperties = new RunProperties();
@ -81,19 +87,142 @@ export class Level extends XmlComponent {
this.root.push(this.runProperties); this.root.push(this.runProperties);
} }
clearVariables(): void { public addParagraphProperty(property: XmlComponent): Level {
this.paragraphProperties.clearVariables();
this.runProperties.clearVariables();
delete this.paragraphProperties;
delete this.runProperties;
}
addParagraphProperty(property: XmlComponent): void {
this.paragraphProperties.push(property); this.paragraphProperties.push(property);
return this;
} }
addRunProperty(property: XmlComponent): void { public addRunProperty(property: XmlComponent): Level {
this.runProperties.push(property); this.runProperties.push(property);
return this;
} }
}
// ---------- Run formatting ---------------------- //
public size(twips: number): Level {
this.addRunProperty(new formatting.Size(twips));
return this;
}
public bold(): Level {
this.addRunProperty(new formatting.Bold());
return this;
}
public italics(): Level {
this.addRunProperty(new formatting.Italics());
return this;
}
public smallCaps(): Level {
this.addRunProperty(new formatting.SmallCaps());
return this;
}
public allCaps(): Level {
this.addRunProperty(new formatting.Caps());
return this;
}
public strike(): Level {
this.addRunProperty(new formatting.Strike());
return this;
}
public doubleStrike(): Level {
this.addRunProperty(new formatting.DoubleStrike());
return this;
}
public subScript(): Level {
this.addRunProperty(new formatting.SubScript());
return this;
}
public superScript(): Level {
this.addRunProperty(new formatting.SuperScript());
return this;
}
public underline(underlineType?: string, color?: string): Level {
this.addRunProperty(new formatting.Underline(underlineType, color));
return this;
}
public color(color: string): Level {
this.addRunProperty(new formatting.Color(color));
return this;
}
public font(fontName: string): Level {
this.addRunProperty(new formatting.RunFonts(fontName));
return this;
}
// --------------------- Paragraph formatting ------------------------ //
public center(): Level {
this.addParagraphProperty(new paragraph.Alignment("center"));
return this;
}
public left(): Level {
this.addParagraphProperty(new paragraph.Alignment("left"));
return this;
}
public right(): Level {
this.addParagraphProperty(new paragraph.Alignment("right"));
return this;
}
public justified(): Level {
this.addParagraphProperty(new paragraph.Alignment("both"));
return this;
}
public thematicBreak(): Level {
this.addParagraphProperty(new paragraph.ThematicBreak());
return this;
}
public maxRightTabStop(): Level {
this.addParagraphProperty(new paragraph.MaxRightTabStop());
return this;
}
public leftTabStop(position: number): Level {
this.addParagraphProperty(new paragraph.LeftTabStop(position));
return this;
}
public indent(left: number, hanging?: number): Level {
this.addParagraphProperty(new paragraph.Indent(left, hanging));
return this;
}
public spacing(params: paragraph.ISpacingProperties): Level {
this.addParagraphProperty(new paragraph.Spacing(params));
return this;
}
public keepNext(): Level {
this.addParagraphProperty(new paragraph.KeepNext());
return this;
}
public keepLines(): Level {
this.addParagraphProperty(new paragraph.KeepLines());
return this;
}
}
export class Level extends LevelBase {
// This is the level that sits under abstractNum. We make a
// handful of properties required
constructor(level: number, numberFormat: string, levelText: string, lvlJc: string) {
super(level, 1, numberFormat, levelText, lvlJc);
}
}
export class LevelForOverride extends LevelBase {}

View File

@ -1,11 +1,11 @@
import {XmlComponent, Attributes} from "../docx/xml-components"; import { Attributes, XmlComponent } from "../docx/xml-components";
export class MultiLevelType extends XmlComponent { export class MultiLevelType extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:multiLevelType"); super("w:multiLevelType");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }

View File

@ -1,35 +1,80 @@
import {XmlComponent, Attributes, XmlAttributeComponent} from "../docx/xml-components"; import { Attributes, XmlAttributeComponent, XmlComponent } from "../docx/xml-components";
import { LevelForOverride } from "./level";
class AbstractNumId extends XmlComponent { class AbstractNumId extends XmlComponent {
constructor(value: number) { constructor(value: number) {
super("w:abstractNumId"); super("w:abstractNumId");
this.root.push(new Attributes({ this.root.push(new Attributes({
val: value val: value,
})); }));
} }
} }
interface NumAttributesProperties { interface INumAttributesProperties {
numId: number; numId: number;
} }
class NumAttributes extends XmlAttributeComponent { class NumAttributes extends XmlAttributeComponent<INumAttributesProperties> {
protected xmlKeys = {numId: "w:numId"};
constructor(properties: NumAttributesProperties) {
super({
numId: "w:numId"
}, properties);
}
} }
export class Num extends XmlComponent { export class Num extends XmlComponent {
public id: number;
constructor(numId: number, abstractNumId: number) { constructor(numId: number, abstractNumId: number) {
super("w:num"); super("w:num");
this.root.push(new NumAttributes({ this.root.push(new NumAttributes({
numId: numId numId: numId,
})); }));
this.root.push(new AbstractNumId(abstractNumId)); this.root.push(new AbstractNumId(abstractNumId));
this.id = numId;
} }
}
public overrideLevel(num: number, start?: number): LevelOverride {
const olvl = new LevelOverride(num, start);
this.root.push(olvl);
return olvl;
}
}
class LevelOverrideAttributes extends XmlAttributeComponent<{ilvl: number}> {
protected xmlKeys = {ilvl: "w:ilvl"};
}
export class LevelOverride extends XmlComponent {
private levelNum: number;
private lvl?: LevelForOverride;
constructor(levelNum: number, start?: number) {
super("w:lvlOverride");
this.root.push(new LevelOverrideAttributes({ilvl: levelNum}));
if (start !== undefined) {
this.root.push(new StartOverride(start));
}
this.levelNum = levelNum;
}
get level(): LevelForOverride {
let lvl: LevelForOverride;
if (!this.lvl) {
lvl = new LevelForOverride(this.levelNum);
this.root.push(lvl);
this.lvl = lvl;
} else {
lvl = this.lvl;
}
return lvl;
}
}
class StartOverrideAttributes extends XmlAttributeComponent<{val: number}> {
protected xmlKeys = {val: "w:val"};
}
class StartOverride extends XmlComponent {
constructor(start: number) {
super("w:startOverride");
this.root.push(new StartOverrideAttributes({val: start}));
}
}

View File

@ -1,29 +0,0 @@
import {XmlComponent, XmlAttributeComponent} from "../docx/xml-components";
interface RunFontAttributesProperties {
ascii: string;
hAnsi: string;
hint: string;
}
class RunFontAttributes extends XmlAttributeComponent {
constructor(properties: RunFontAttributesProperties) {
super({
left: "w:left",
hanging: "w:hanging"
}, properties);
}
}
export class RunFonts extends XmlComponent {
constructor(ascii: string, hint: string) {
super("w:ind");
this.root.push(new RunFontAttributes({
ascii: ascii,
hAnsi: ascii,
hint: hint
}));
}
}

View File

@ -1,73 +1,71 @@
import {XmlUnitComponent} from "../docx/xml-components"; import { DocumentAttributes } from "../docx/document/document-attributes";
import {XmlComponent} from "../docx/xml-components"; import { XmlComponent } from "../docx/xml-components";
import {DocumentAttributes} from "../docx/document/document-attributes";
export class Title extends XmlUnitComponent { export class Title extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("dc:title"); super("dc:title");
this.root = value; this.root.push(value);
} }
} }
export class Subject extends XmlUnitComponent { export class Subject extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("dc:subject"); super("dc:subject");
this.root = value; this.root.push(value);
} }
} }
export class Creator extends XmlUnitComponent { export class Creator extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("dc:creator"); super("dc:creator");
this.root = value; this.root.push(value);
} }
} }
export class Keywords extends XmlUnitComponent { export class Keywords extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("cp:keywords"); super("cp:keywords");
this.root = value; this.root.push(value);
} }
} }
export class Description extends XmlUnitComponent { export class Description extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("dc:description"); super("dc:description");
this.root = value; this.root.push(value);
} }
} }
export class LastModifiedBy extends XmlUnitComponent { export class LastModifiedBy extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("cp:lastModifiedBy"); super("cp:lastModifiedBy");
this.root = value; this.root.push(value);
} }
} }
export class Revision extends XmlUnitComponent { export class Revision extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("cp:revision"); super("cp:revision");
let revision = value; this.root.push(value);
this.root = value;
} }
} }
abstract class DateComponent extends XmlComponent { export abstract class DateComponent extends XmlComponent {
protected getCurrentDate(): any { protected getCurrentDate(): string {
let date = new Date(), const date = new Date();
year = date.getFullYear(), const year = date.getFullYear();
month = ("0" + (date.getMonth() + 1)).slice(-2), const month = ("0" + (date.getMonth() + 1)).slice(-2);
day = ("0" + date.getDate()).slice(-2), const day = ("0" + date.getDate()).slice(-2);
hours = ("0" + date.getHours()).slice(-2), const hours = ("0" + date.getHours()).slice(-2);
minutes = ("0" + date.getMinutes()).slice(-2), const minutes = ("0" + date.getMinutes()).slice(-2);
seconds = ("0" + date.getSeconds()).slice(-2); const seconds = ("0" + date.getSeconds()).slice(-2);
return year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z"; return year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z";
} }
@ -78,7 +76,7 @@ export class Created extends DateComponent {
constructor() { constructor() {
super("dcterms:created"); super("dcterms:created");
this.root.push(new DocumentAttributes({ this.root.push(new DocumentAttributes({
type: "dcterms:W3CDTF" type: "dcterms:W3CDTF",
})); }));
this.root.push(this.getCurrentDate()); this.root.push(this.getCurrentDate());
} }
@ -89,8 +87,8 @@ export class Modified extends DateComponent {
constructor() { constructor() {
super("dcterms:modified"); super("dcterms:modified");
this.root.push(new DocumentAttributes({ this.root.push(new DocumentAttributes({
type: "dcterms:W3CDTF" type: "dcterms:W3CDTF",
})); }));
this.root.push(this.getCurrentDate()); this.root.push(this.getCurrentDate());
} }
} }

View File

@ -1,8 +1,8 @@
import {XmlComponent} from "../docx/xml-components"; import { DocumentAttributes } from "../docx/document/document-attributes";
import {DocumentAttributes} from "../docx/document/document-attributes"; import { XmlComponent } from "../docx/xml-components";
import {Title, Subject, Creator, Keywords, Description, LastModifiedBy, Revision, Created, Modified} from "./components"; import { Created, Creator, Description, Keywords, LastModifiedBy, Modified, Revision, Subject, Title } from "./components";
interface PropertiesOptions { export interface IPropertiesOptions {
title?: string; title?: string;
subject?: string; subject?: string;
creator?: string; creator?: string;
@ -14,23 +14,37 @@ interface PropertiesOptions {
export class Properties extends XmlComponent { export class Properties extends XmlComponent {
constructor(options: PropertiesOptions) { constructor(options: IPropertiesOptions) {
super("cp:coreProperties"); super("cp:coreProperties");
this.root.push(new DocumentAttributes({ this.root.push(new DocumentAttributes({
cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
dc: "http://purl.org/dc/elements/1.1/", dc: "http://purl.org/dc/elements/1.1/",
dcterms: "http://purl.org/dc/terms/", dcterms: "http://purl.org/dc/terms/",
dcmitype: "http://purl.org/dc/dcmitype/", dcmitype: "http://purl.org/dc/dcmitype/",
xsi: "http://www.w3.org/2001/XMLSchema-instance" xsi: "http://www.w3.org/2001/XMLSchema-instance",
})); }));
this.root.push(new Title(options.title)); if (options.title) {
this.root.push(new Subject(options.subject)); this.root.push(new Title(options.title));
this.root.push(new Creator(options.creator)); }
this.root.push(new Keywords(options.keywords)); if (options.subject) {
this.root.push(new Description(options.description)); this.root.push(new Subject(options.subject));
this.root.push(new LastModifiedBy(options.lastModifiedBy)); }
this.root.push(new Revision(options.revision)); if (options.creator) {
this.root.push(new Creator(options.creator));
}
if (options.keywords) {
this.root.push(new Keywords(options.keywords));
}
if (options.description) {
this.root.push(new Description(options.description));
}
if (options.lastModifiedBy) {
this.root.push(new LastModifiedBy(options.lastModifiedBy));
}
if (options.revision) {
this.root.push(new Revision(options.revision));
}
this.root.push(new Created()); this.root.push(new Created());
this.root.push(new Modified()); this.root.push(new Modified());
} }
} }

View File

@ -0,0 +1,11 @@
import { XmlAttributeComponent } from "../docx/xml-components";
export interface IRelationshipsAttributesProperties {
xmlns: string;
}
export class RelationshipsAttributes extends XmlAttributeComponent<IRelationshipsAttributesProperties> {
protected xmlKeys = {
xmlns: "xmlns",
};
}

14
ts/relationships/index.ts Normal file
View File

@ -0,0 +1,14 @@
import { XmlComponent } from "../docx/xml-components";
import { RelationshipsAttributes } from "./attributes";
export class Relationships extends XmlComponent {
constructor() {
super("Relationships");
this.root.push(new RelationshipsAttributes({
xmlns: "http://schemas.openxmlformats.org/package/2006/relationships",
}));
// this.root.push(new Created());
}
}

View File

View File

@ -1,6 +1,6 @@
import {XmlComponent} from "../../docx/xml-components"; import { XmlComponent } from "../../docx/xml-components";
import {ParagraphPropertiesDefaults} from "./paragraph-properties"; import { ParagraphPropertiesDefaults } from "./paragraph-properties";
import {RunPropertiesDefaults} from "./run-properties"; import { RunPropertiesDefaults } from "./run-properties";
export class DocumentDefaults extends XmlComponent { export class DocumentDefaults extends XmlComponent {
@ -14,11 +14,4 @@ export class DocumentDefaults extends XmlComponent {
this.root.push(this.runPropertiesDefaults); this.root.push(this.runPropertiesDefaults);
this.root.push(this.paragraphPropertiesDefaults); this.root.push(this.paragraphPropertiesDefaults);
} }
}
clearVariables(): void {
this.runPropertiesDefaults.clearVariables();
this.paragraphPropertiesDefaults.clearVariables();
delete this.runPropertiesDefaults;
delete this.paragraphPropertiesDefaults;
}
}

View File

@ -1,5 +1,5 @@
import {XmlComponent} from "../../docx/xml-components"; import { ParagraphProperties } from "../../docx/paragraph/properties";
import {ParagraphProperties} from "../../docx/paragraph/properties"; import { XmlComponent } from "../../docx/xml-components";
export class ParagraphPropertiesDefaults extends XmlComponent { export class ParagraphPropertiesDefaults extends XmlComponent {
@ -7,4 +7,4 @@ export class ParagraphPropertiesDefaults extends XmlComponent {
super("w:pPrDefault"); super("w:pPrDefault");
this.root.push(new ParagraphProperties()); this.root.push(new ParagraphProperties());
} }
} }

View File

@ -1,5 +1,5 @@
import {XmlComponent} from "../../docx/xml-components"; import { RunProperties } from "../../docx/run/properties";
import {RunProperties} from "../../docx/run/properties"; import { XmlComponent } from "../../docx/xml-components";
export class RunPropertiesDefaults extends XmlComponent { export class RunPropertiesDefaults extends XmlComponent {
@ -7,4 +7,4 @@ export class RunPropertiesDefaults extends XmlComponent {
super("w:rPrDefault"); super("w:rPrDefault");
this.root.push(new RunProperties()); this.root.push(new RunProperties());
} }
} }

View File

@ -1,56 +1,54 @@
import {Styles} from "./"; import { Color, Italics, Size } from "../docx/run/formatting";
import {DocumentDefaults} from "./defaults";
import {ParagraphPropertiesDefaults} from "./defaults/paragraph-properties"; import { Styles } from "./";
import {RunPropertiesDefaults} from "./defaults/run-properties"; import { DocumentDefaults } from "./defaults";
import {Heading1Style, Heading2Style, TitleStyle, Heading3Style, Heading4Style, Heading5Style, Heading6Style, ListParagraph} from "./style"; import {
// import {StyleAttributes} from "./style/attributes"; Heading1Style, Heading2Style, Heading3Style, Heading4Style, Heading5Style, Heading6Style,
import {ParagraphProperties} from "../docx/paragraph/properties"; ListParagraph, TitleStyle,
import {RunProperties} from "../docx/run/properties"; } from "./style";
import {Color, Size, Italics} from "../docx/run/formatting";
export class DefaultStylesFactory { export class DefaultStylesFactory {
newInstance(): Styles { public newInstance(): Styles {
let styles = new Styles(); const styles = new Styles();
styles.push(new DocumentDefaults()); styles.push(new DocumentDefaults());
let titleStyle = new TitleStyle(); const titleStyle = new TitleStyle();
titleStyle.addRunProperty(new Size(56)); titleStyle.addRunProperty(new Size(56));
styles.push(titleStyle); styles.push(titleStyle);
let heading1Style = new Heading1Style(); const heading1Style = new Heading1Style();
heading1Style.addRunProperty(new Color("2E74B5")); heading1Style.addRunProperty(new Color("2E74B5"));
heading1Style.addRunProperty(new Size(32)); heading1Style.addRunProperty(new Size(32));
styles.push(heading1Style); styles.push(heading1Style);
let heading2Style = new Heading2Style(); const heading2Style = new Heading2Style();
heading2Style.addRunProperty(new Color("2E74B5")); heading2Style.addRunProperty(new Color("2E74B5"));
heading2Style.addRunProperty(new Size(26)); heading2Style.addRunProperty(new Size(26));
styles.push(heading2Style); styles.push(heading2Style);
let heading3Style = new Heading3Style(); const heading3Style = new Heading3Style();
heading3Style.addRunProperty(new Color("1F4D78")); heading3Style.addRunProperty(new Color("1F4D78"));
heading3Style.addRunProperty(new Size(24)); heading3Style.addRunProperty(new Size(24));
styles.push(heading3Style); styles.push(heading3Style);
let heading4Style = new Heading4Style(); const heading4Style = new Heading4Style();
heading4Style.addRunProperty(new Color("2E74B5")); heading4Style.addRunProperty(new Color("2E74B5"));
heading4Style.addRunProperty(new Italics()); heading4Style.addRunProperty(new Italics());
styles.push(heading4Style); styles.push(heading4Style);
let heading5Style = new Heading5Style(); const heading5Style = new Heading5Style();
heading5Style.addRunProperty(new Color("2E74B5")); heading5Style.addRunProperty(new Color("2E74B5"));
styles.push(heading5Style); styles.push(heading5Style);
let heading6Style = new Heading6Style(); const heading6Style = new Heading6Style();
heading6Style.addRunProperty(new Color("1F4D78")); heading6Style.addRunProperty(new Color("1F4D78"));
styles.push(heading6Style); styles.push(heading6Style);
let listParagraph = new ListParagraph(); const listParagraph = new ListParagraph();
// listParagraph.addParagraphProperty(); // listParagraph.addParagraphProperty();
styles.push(listParagraph); styles.push(listParagraph);
// console.log(JSON.stringify(styles, null, " "));
return styles; return styles;
} }
} }

View File

@ -1,9 +1,6 @@
import {XmlComponent} from "../docx/xml-components"; import { DocumentAttributes } from "../docx/document/document-attributes";
import {DocumentAttributes} from "../docx/document/document-attributes"; import { XmlComponent } from "../docx/xml-components";
import {DocumentDefaults} from "./defaults"; import { ParagraphStyle } from "./style";
import {LatentStyles} from "./latent-styles";
import {LatentStyleException} from "./latent-styles/exceptions";
import {LatentStyleExceptionAttributes} from "./latent-styles/exceptions/attributes";
export class Styles extends XmlComponent { export class Styles extends XmlComponent {
@ -15,7 +12,7 @@ export class Styles extends XmlComponent {
w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
w14: "http://schemas.microsoft.com/office/word/2010/wordml", w14: "http://schemas.microsoft.com/office/word/2010/wordml",
w15: "http://schemas.microsoft.com/office/word/2012/wordml", w15: "http://schemas.microsoft.com/office/word/2012/wordml",
Ignorable: "w14 w15" Ignorable: "w14 w15",
})); }));
// let latentStyles = new LatentStyles(); // let latentStyles = new LatentStyles();
// latentStyles.push(new LatentStyleException(new LatentStyleExceptionAttributes({ // latentStyles.push(new LatentStyleException(new LatentStyleExceptionAttributes({
@ -24,13 +21,14 @@ export class Styles extends XmlComponent {
// this.root.push(latentStyles); // this.root.push(latentStyles);
} }
push(style: XmlComponent): void { public push(style: XmlComponent): Styles {
this.root.push(style); this.root.push(style);
return this;
} }
clearVariables() { public createParagraphStyle(styleId: string, name?: string): ParagraphStyle {
this.root.forEach(element => { const para = new ParagraphStyle(styleId, name);
element.clearVariables(); this.push(para);
}); return para;
} }
} }

View File

@ -0,0 +1,27 @@
import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components";
export interface ILatentStyleExceptionAttributesProperties {
name?: string;
uiPriority?: string;
qFormat?: string;
semiHidden?: string;
unhideWhenUsed?: string;
}
export class LatentStyleExceptionAttributes extends XmlAttributeComponent<ILatentStyleExceptionAttributesProperties> {
protected xmlKeys = {
name: "w:name",
uiPriority: "w:uiPriority",
qFormat: "w:qFormat",
semiHidden: "w:semiHidden",
unhideWhenUsed: "w:unhideWhenUsed",
};
}
export class LatentStyleException extends XmlComponent {
constructor(attributes: ILatentStyleExceptionAttributesProperties) {
super("w:lsdException");
this.root.push(new LatentStyleExceptionAttributes(attributes));
}
}

View File

@ -1,31 +0,0 @@
import {XmlComponent} from "../../../docx/xml-components";
interface LatentStyleExceptionAttributesProperties {
name?: string;
uiPriority?: string;
qFormat?: string;
semiHidden?: string;
unhideWhenUsed?: string;
}
export class LatentStyleExceptionAttributes extends XmlComponent {
private _attr: Object;
xmlKeys = {
name: "w:name",
uiPriority: "w:uiPriority",
qFormat: "w:qFormat",
semiHidden: "w:semiHidden",
unhideWhenUsed: "w:unhideWhenUsed"
};
constructor(properties?: LatentStyleExceptionAttributesProperties) {
super("_attr");
this._attr = properties;
if (!properties) {
this._attr = {};
}
this._attr["xmlKeys"] = this.xmlKeys;
}
}

View File

@ -1,10 +0,0 @@
import {XmlComponent} from "../../../docx/xml-components";
import {LatentStyleExceptionAttributes} from "./attributes";
export class LatentStyleException extends XmlComponent {
constructor(attributes: LatentStyleExceptionAttributes) {
super("w:lsdException");
this.root.push(attributes);
}
}

View File

@ -1,5 +1,5 @@
import {XmlComponent} from "../../docx/xml-components"; import { XmlComponent } from "../../docx/xml-components";
import {LatentStyleException} from "./exceptions"; import { LatentStyleException } from "./exceptions";
export class LatentStyles extends XmlComponent { export class LatentStyles extends XmlComponent {
@ -7,7 +7,7 @@ export class LatentStyles extends XmlComponent {
super("w:latentStyles"); super("w:latentStyles");
} }
push(latentException: LatentStyleException): void { public push(latentException: LatentStyleException): void {
this.root.push(latentException); this.root.push(latentException);
} }
} }

View File

@ -1,3 +1,4 @@
/* tslint:disable */
function createLsdException(name, uiPriority, qFormat?, semiHidden?, unhideWhenUsed?) { function createLsdException(name, uiPriority, qFormat?, semiHidden?, unhideWhenUsed?) {
'use strict'; 'use strict';

View File

@ -1,24 +0,0 @@
import {XmlComponent} from "../../docx/xml-components";
import {XmlAttributeComponent} from "../../docx/xml-components";
interface StyleAttributesProperties {
type?: string;
styleId?: string;
default?: string;
customStyle?: string;
val?: string;
}
export class StyleAttributes extends XmlAttributeComponent {
private _attr: Object;
constructor(properties: StyleAttributesProperties) {
super({
type: "w:type",
styleId: "w:styleId",
default: "w:default",
customStyle: "w:customStyle",
val: "w:val"
}, properties);
}
}

View File

@ -1,13 +1,18 @@
import {XmlComponent} from "../../docx/xml-components"; import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components";
import {StyleAttributes} from "./attributes";
interface IComponentAttributes {
val: string;
}
class ComponentAttributes extends XmlAttributeComponent<IComponentAttributes> {
protected xmlKeys = {val: "w:val"};
}
export class Name extends XmlComponent { export class Name extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:name"); super("w:name");
this.root.push(new StyleAttributes({ this.root.push(new ComponentAttributes({val: value}));
val: value
}));
} }
} }
@ -15,9 +20,7 @@ export class BasedOn extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:basedOn"); super("w:basedOn");
this.root.push(new StyleAttributes({ this.root.push(new ComponentAttributes({val: value}));
val: value
}));
} }
} }
@ -25,10 +28,7 @@ export class Next extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:next"); super("w:next");
this.root.push(new StyleAttributes({ this.root.push(new ComponentAttributes({val: value}));
styleId: "1",
val: value
}));
} }
} }
@ -36,9 +36,7 @@ export class Link extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:link"); super("w:link");
this.root.push(new StyleAttributes({ this.root.push(new ComponentAttributes({val: value}));
val: value
}));
} }
} }
@ -46,9 +44,8 @@ export class UiPriority extends XmlComponent {
constructor(value: string) { constructor(value: string) {
super("w:uiPriority"); super("w:uiPriority");
this.root.push(new StyleAttributes({ // TODO: this value should be a ST_DecimalNumber
val: value this.root.push(new ComponentAttributes({val: value}));
}));
} }
} }
@ -73,4 +70,4 @@ export class RsId extends XmlComponent {
export class SemiHidden extends XmlComponent { export class SemiHidden extends XmlComponent {
} }

View File

@ -1,63 +1,204 @@
import {XmlComponent} from "../../docx/xml-components"; import * as paragraph from "../../docx/paragraph/formatting";
import {StyleAttributes} from "./attributes"; import * as formatting from "../../docx/run/formatting";
import {ParagraphProperties} from "../../docx/paragraph/properties"; import { RunProperties } from "../../docx/run/properties";
import {RunProperties} from "../../docx/run/properties"; import { XmlAttributeComponent, XmlComponent } from "../../docx/xml-components";
import {Name, BasedOn, Next, QuickFormat} from "./components";
import { BasedOn, Name, Next, QuickFormat } from "./components";
export interface IStyleAttributes {
type?: string;
styleId?: string;
default?: boolean;
customStyle?: string;
}
class StyleAttributes extends XmlAttributeComponent<IStyleAttributes> {
protected xmlKeys = {
type: "w:type",
styleId: "w:styleId",
default: "w:default",
customStyle: "w:customStyle",
};
}
export class Style extends XmlComponent { export class Style extends XmlComponent {
constructor(attributes: StyleAttributes) { constructor(attributes: IStyleAttributes, name?: string) {
super("w:style"); super("w:style");
this.root.push(attributes); this.root.push(new StyleAttributes(attributes));
if (name) {
this.root.push(new Name(name));
}
} }
push(styleSegment: XmlComponent): void { public push(styleSegment: XmlComponent): void {
this.root.push(styleSegment); this.root.push(styleSegment);
} }
} }
export class ParagraphStyle extends Style { export class ParagraphStyle extends Style {
private paragraphProperties: ParagraphProperties; private paragraphProperties: paragraph.ParagraphProperties;
private runProperties: RunProperties; private runProperties: RunProperties;
constructor(styleId: string) { constructor(styleId: string, name?: string) {
super({type: "paragraph", styleId: styleId}, name);
let attributes = new StyleAttributes({ this.paragraphProperties = new paragraph.ParagraphProperties();
type: "paragraph",
styleId: styleId
});
super(attributes);
this.paragraphProperties = new ParagraphProperties();
this.runProperties = new RunProperties(); this.runProperties = new RunProperties();
this.root.push(this.paragraphProperties); this.root.push(this.paragraphProperties);
this.root.push(this.runProperties); this.root.push(this.runProperties);
} }
clearVariables(): void { public addParagraphProperty(property: XmlComponent): void {
this.paragraphProperties.clearVariables();
this.runProperties.clearVariables();
delete this.paragraphProperties;
delete this.runProperties;
}
addParagraphProperty(property: XmlComponent): void {
this.paragraphProperties.push(property); this.paragraphProperties.push(property);
} }
addRunProperty(property: XmlComponent): void { public addRunProperty(property: XmlComponent): void {
this.runProperties.push(property); this.runProperties.push(property);
} }
public basedOn(parentId: string): ParagraphStyle {
this.root.push(new BasedOn(parentId));
return this;
}
public quickFormat(): ParagraphStyle {
this.root.push(new QuickFormat());
return this;
}
public next(nextId: string): ParagraphStyle {
this.root.push(new Next(nextId));
return this;
}
// ---------- Run formatting ---------------------- //
public size(twips: number): ParagraphStyle {
this.addRunProperty(new formatting.Size(twips));
return this;
}
public bold(): ParagraphStyle {
this.addRunProperty(new formatting.Bold());
return this;
}
public italics(): ParagraphStyle {
this.addRunProperty(new formatting.Italics());
return this;
}
public smallCaps(): ParagraphStyle {
this.addRunProperty(new formatting.SmallCaps());
return this;
}
public allCaps(): ParagraphStyle {
this.addRunProperty(new formatting.Caps());
return this;
}
public strike(): ParagraphStyle {
this.addRunProperty(new formatting.Strike());
return this;
}
public doubleStrike(): ParagraphStyle {
this.addRunProperty(new formatting.DoubleStrike());
return this;
}
public subScript(): ParagraphStyle {
this.addRunProperty(new formatting.SubScript());
return this;
}
public superScript(): ParagraphStyle {
this.addRunProperty(new formatting.SuperScript());
return this;
}
public underline(underlineType?: string, color?: string): ParagraphStyle {
this.addRunProperty(new formatting.Underline(underlineType, color));
return this;
}
public color(color: string): ParagraphStyle {
this.addRunProperty(new formatting.Color(color));
return this;
}
public font(fontName: string): ParagraphStyle {
this.addRunProperty(new formatting.RunFonts(fontName));
return this;
}
// --------------------- Paragraph formatting ------------------------ //
public center(): ParagraphStyle {
this.addParagraphProperty(new paragraph.Alignment("center"));
return this;
}
public left(): ParagraphStyle {
this.addParagraphProperty(new paragraph.Alignment("left"));
return this;
}
public right(): ParagraphStyle {
this.addParagraphProperty(new paragraph.Alignment("right"));
return this;
}
public justified(): ParagraphStyle {
this.addParagraphProperty(new paragraph.Alignment("both"));
return this;
}
public thematicBreak(): ParagraphStyle {
this.addParagraphProperty(new paragraph.ThematicBreak());
return this;
}
public maxRightTabStop(): ParagraphStyle {
this.addParagraphProperty(new paragraph.MaxRightTabStop());
return this;
}
public leftTabStop(position: number): ParagraphStyle {
this.addParagraphProperty(new paragraph.LeftTabStop(position));
return this;
}
public indent(left: number, hanging?: number): ParagraphStyle {
this.addParagraphProperty(new paragraph.Indent(left, hanging));
return this;
}
public spacing(params: paragraph.ISpacingProperties): ParagraphStyle {
this.addParagraphProperty(new paragraph.Spacing(params));
return this;
}
public keepNext(): ParagraphStyle {
this.addParagraphProperty(new paragraph.KeepNext());
return this;
}
public keepLines(): ParagraphStyle {
this.addParagraphProperty(new paragraph.KeepLines());
return this;
}
} }
export class HeadingStyle extends ParagraphStyle { export class HeadingStyle extends ParagraphStyle {
constructor(styleId: string, name: string) { constructor(styleId: string, name: string) {
super(styleId); super(styleId, name);
this.root.push(new Name(name)); this.basedOn("Normal");
this.root.push(new BasedOn("Normal")); this.next("Normal");
this.root.push(new Next("Normal")); this.quickFormat();
this.root.push(new QuickFormat());
} }
} }
@ -118,4 +259,4 @@ export class ListParagraph extends ParagraphStyle {
this.root.push(new BasedOn("Normal")); this.root.push(new BasedOn("Normal"));
this.root.push(new QuickFormat()); this.root.push(new QuickFormat());
} }
} }

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